How do I add tooltips that pop up whenever your cursor goes over a defined regex?


#1

Hi,

I’m trying to get my language-archlinux package to provide information about each variable and function you put your line cursor over (i.e., the one defined by the Less style atom-text-editor::shadow .cursor). I do not know how to do this though. Anyone know how to? Please keep it nice and simple, preferably in CoffeeScript as I understand it a little (not an awful lot, but every little helps) better than JavaScript.

Thanks for your time,
Brenton


#2

I think you would want to set up your code to monitor the scope of the cursor and when it has the correct scope, to match the word surrounding the cursor against your list.


#3

OK will pos=cursor.getScreenPosition() get the position of the cursor that I can then use in my Coffee code?


#4

It would, but using getPreviousWordBoundaryBufferPosition would get the position of the first letter of the word, and then your popover wouldn’t slide back and forth with the cursor. The TextEditor docs have details about buffer vs screen coordinates as well as methods to convert them.


#5

I have this so far:

{$, TextEditorView, View} = require 'atom-space-pen-views'
path                      = require "path"
{exec}                    = require "child_process"
name                      = atom.config.get 'language-archlinux.username'
email                     = atom.config.get 'language-archlinux.email'
activeEditor              = atom.workspace.getActiveTextEditor()
notifications             = atom.notifications
LoadingView               = null
loadingView               = null

if cursor.isInsideWord('pkgver')
  class tooltips extends View
        detaching: false
        @content: ->
          @div class: 'info', 'pkgver is the version of the package you are building.'

Is this along the lines of what you think will do the trick? Because I am rather confused as to exactly what I should do.


#6

I’ve changed this to:

{$, TextEditorView, View} = require 'atom-space-pen-views'
path                      = require "path"
{exec}                    = require "child_process"
name                      = atom.config.get 'language-archlinux.username'
email                     = atom.config.get 'language-archlinux.email'
activeEditor              = atom.workspace.getActiveTextEditor()
cursor                    = atom.workspace.cursor()
notifications             = atom.notifications
LoadingView               = null
loadingView               = null

module.exports =
  pkgver:
    if cursor.isInsideWord('pkgver')
      class tooltips extends View
          detaching: false
          @content: ->
            @div class: 'info', 'pkgver is the version of the package you are building.'

naming this file tooltips.coffee and added this to my main.coffee file:

{pkgver} = require "./tooltips"

I’m trying to do this myself, in case you’re thinking I’m trying to get you to do all the work for me, it’s just I don’t know what I need to do.


#7

I don’t know what you need to do either. I’m just navigating the docs and looking for methods.


#8

OK. Well you wouldn’t know how to access cursor.isInsideWord() in my code? My code doesn’t seem to be accessing it. I keep getting errors that cursor is not a method.


#9

I have found how to define cursor myself that does not seem to return a nonexistent value with:

activeEditor              = atom.workspace.getActiveTextEditor()
cursor                    = activeEditor.getCursors()

but cursor.isInsideWord() is still not a valid function.


#10

Because getCursors() returns an array of cursors. What you want is getLastCursor(), which will return a Cursor object pointing at the most recent cursor.


#11

Thanks. Now the package isn’t complaining of errors. The problem is that I don’t know how to activate my tooltips.coffee file properly in my main.coffee. I know how to activate commands defined in coffee files upon saving a file, closing a file or upon some other action performed by the user (e.g., pressing a keyboard shortcut) but I do not know how to execute it so that runs whenever your cursor goes over a keyword. Do you per chance?


#12

You can also listen for when the cursor changes position, which will also give you a Cursor object.


#13

So adding something like:

        {cursor,pkgver} = require "./tooltips"
        pkgver if cursor.onDidChangePosition(callback[.cursor]) 

to my main.coffee would do the trick? Where tooltips.coffee is now:

{$, TextEditorView, View} = require 'atom-space-pen-views'
path                      = require "path"
{exec}                    = require "child_process"
name                      = atom.config.get 'language-archlinux.username'
email                     = atom.config.get 'language-archlinux.email'
activeEditor              = atom.workspace.getActiveTextEditor()
notifications             = atom.notifications
cursor                    = activeEditor.getLastCursor()

if activeEditor
    filePath              = activeEditor.getPath().split(" ").join("\\ ")
    preferredPath         = atom.config.get('language-archlinux.preferredPath')
    if preferredPath
      fileDirectory       = preferredPath
    else
      fileDirectory       = String(filePath).split('/')
      fileName            = fileDirectory[fileDirectory.length - 1]
      fileDirectory.pop()
      fileDirectory       = fileDirectory.join("/")

module_export =
  cursor:
    cursor
  pkgver:
    if activeEditor
      if cursor.isInsideWord('^pkgver=')
        class tooltips extends View
          detaching: false
          @content: ->
              @div class: 'command-palette', "pkgver is the package version."

?


#14

Can I suggest an event listener? Not tested, but something like this
Edit: added process.nextTick, removed camel casing in tooltip

module.exports =
  activate: ->
    atom.workspace.observeTextEditors (editor) =>
      process.nextTick =>
        editor?.getElement()?.addEventListener 'mousemove', @displayTooltip.bind(@)

  displayTooltip: ({target}) ->
    @tooltip?.dispose()
    text = target.textContent
    @tooltip = atom.tooltips.add(target, {title: "something something #{text}"})

#15

@refkotay I am willing to try anything. Where do I put this? In main.coffee or tooltips.coffee? Guessing tooltips.coffee.


#16

That should be your entire package


#17

My language-archlinux package does a lot more than just showing this tooltip. The target variable is provided how? Like there’s quite a few different tooltips I’d like to provide, each of which depend on the target regex (e.g., I want the ^pkgver= regex to have the tooltip “The package version”, likewise I’d like the regex ^pkgname= to have the tooltip “The package name. Must be lower case”). So I’m guessing the regex and tooltips would be best provided by a CSON or JSON data file.


#18

event.target is the top level dom node that the mouse has moved onto. The event argument is passed automatically to the eventListener callback. There was was not any psuedo code in the post, it should work.
Here’s the structure I recommend starting with:
arch-tips '- lib/arch-tips.coffee '- package.json
And here is what they would look like
package.json:

{
  "name": "arch-tips",
  "main": "./lib/arch-tips",
  "engines": {
    "atom": ">=1.0.0 <2.0.0"
  }
}

lib/arch-tips.coffee

#require things here

module.exports = ArchTips
  activate: ->

    atom.workspace.observeTextEditors (editor) =>
      process.nextTick =>
        editor?.getElement()?.addEventListener 'mousemove', @displayTooltip.bind(@)

    # set variables here, like filepath, etc..

  displayTooltip: ({target}) ->
    @tooltip?.dispose()
    text = target.textContent
    @tooltip = atom.tooltips.add(target, {title: "something something #{text}"})

Again, just to start with, until you can get this working. That would be my suggestion

Edit: added process.nextTick. Added lib/ to package.json. Removed camel casing in tooltip


#19

OK sorry I don’t get much of the programming lingo you used. How do I specify the regexes and text? Please give me an example because I just implemented your code (I don’t know what I need to require either, unfortunately) and I got the error:

Cannot read property 'bind' of undefined
Hide Stack Trace
TypeError: Cannot read property 'bind' of undefined
  at /home/fusion809/GitHub/mine/atom/pkgbuild-tips/lib/main.coffee:5:75
  at Workspace.module.exports.Workspace.observeTextEditors (/usr/lib/atom-bleeding/src/workspace.js:307:9)
  at Object.activate (/home/fusion809/GitHub/mine/atom/pkgbuild-tips/lib/main.coffee:4:20)
  at Package.module.exports.Package.activateNow (/usr/lib/atom-bleeding/src/package.js:183:20)
  at /usr/lib/atom-bleeding/src/package.js:156:32
  at Package.module.exports.Package.measure (/usr/lib/atom-bleeding/src/package.js:92:15)
  at /usr/lib/atom-bleeding/src/package.js:149:26
  at Package.module.exports.Package.activate (/usr/lib/atom-bleeding/src/package.js:146:34)
  at PackageManager.module.exports.PackageManager.activatePackage (/usr/lib/atom-bleeding/src/package-manager.js:530:21)
  at /usr/lib/atom-bleeding/src/package-manager.js:511:29
  at Config.module.exports.Config.transactAsync (/usr/lib/atom-bleeding/src/config.js:337:18)
  at PackageManager.module.exports.PackageManager.activatePackages (/usr/lib/atom-bleeding/src/package-manager.js:506:19)
  at PackageManager.module.exports.PackageManager.activate (/usr/lib/atom-bleeding/src/package-manager.js:489:46)
  at /usr/lib/atom-bleeding/src/atom-environment.js:754:28

#20

Your last edit got rid of my previously reported error. But the package is doing nothing still, as I have no data (i.e., regexes and tooltips) provided to it.