Add proper selector for keybinding event in Atom editor


#1

I develop a package, which allows user to use Home button to toggle cursor position in soft-wrapped lines, as it is in Komodo Edit editor.

In my toggle() function I try to get active text editor from Atom Workspace using getActiveTextEditor function and then I do my logic.

atom.workspace.getActiveTextEditor()

I bind a Home key with a selector atom-text-editor.editor, and it mainly works fine until triggered inside Search&Replace pane or Command Palette.

"atom-text-editor.editor": {
  "home": "toggle-home:toggle"
}

In this case, getActiveTextEditor returns always a currently edited file’s text editor. It leads to a situation, when a cursor is moved inside an edited file’s pane, but not inside focused field. When I use a Home inside a text field in Settings pane, Atom throws an exception, as it can’t find any active text editor.

I did a research through Atom Docs, Atom API, even community packages, but all I found, was adding ‘mini’ to my event selector, to narrow event scope a bit.

"atom-text-editor.editor:not([mini])": {
  "home": "toggle-home:toggle"
}

Nevertheless it still causes exception or misbehaviour in text fields without ‘mini’ (ie. textarea of Git/GitHub package).

What I want to achieve is:

  1. to find a proper keybinding selector, that would fire only inside currently edited file pane;
    OR
  2. to find a method to get focused instance (Search&Replace, Command Palette or any other field) for further processing.

#2

Please see if this helps you:

   'atom-workspace atom-text-editor:not([mini])': {
      'home': 'toggle-home:toggle'
    }

#3

All of mentioned TextEditor fields are inside <atom-workspace/> tag, so adding this selector will not change anything, I guess, as <atom-workspace/> tag is a parent for all panes and panels.


#4

The inspiration came from observing what is listed in Settings -> Keybindings.
My test was done for Windows in the keymaps.cson file, which looked okay.

That does not mean it will work for you… as you are pointing out.


#5

It does not work for me. Changing selector this way does not change anything: event fires as before.


#6

Try this:

'atom-pane-container atom-text-editor:not([mini])': {
  'home': 'toggle-home:toggle'
}

You can see how the DOM is constructed by opening the developer tools (View -> Developer -> Toggle developer tools) and clicking on the Elements tab. All TextEditors are inside panes, which are all inside atom-pane-container. This won’t prevent you from unwanted interactions with packages that also inhabit the pane, however. If you want to really be sure, you have to set up your command like this:

atom.commands.add "atom-text-editor", "toggle-home:toggle", (evt) ->
  console.log evt

From there, you can look at evt.target to see if it is a proper TextEditor.


#7

I use Developer Tools fluently. And I found out (as I pointed in my question) that package GitHub/Git is also placed inside atom-pane-container. So certainly I can’t use this selector without conflicts, as You pointed in Your answer.

@DamnedScholar: I used Package Generator for my package, and init code is saved in JS file, not a coffee. How can I achieve capturing event, what You described, using pure JS?


#8

Oh, darn. I missed that. In that case, the selector atom-workspace-axis.vertical atom-pane-container atom-text-editor:not([mini]) will do it.

How can I achieve capturing event, what You described, using pure JS?

Sorry. For convenience, I tend to post code on here in a way that can be dropped into init.coffee. Here’s the JS form.

atom.commands.add("atom-text-editor", "toggle-home:toggle", (evt) => {
  console.log(evt)
})

You can convert CS to JS using the Try CoffeeScript tab at CoffeeScript.org (Atom uses version 1), and the preview package allows you to see converted code in Atom.


#9

When I first was looking at this name, I wasn’t sure if vertical can be switched to horizontal or anything else when splitting panes left/right or top/bottom, and I did not check this. My mistake. It looks like, it would work this way. I will give it a try and let You know if it works.

Thanks for the explanation about init in JS, and special thanks for coffee->js converter.


#10

My final command activation respecting event object would look like below

this.subscriptions.add(atom.commands.add('atom-text-editor', {
  'toggle-home:toggle': (evt) => this.toggle(evt)
}));

Then I can handle event object inside my toggle function.

Final thought
Proper selector for binding event only to currently focused file pane TextEditor is:

atom-workspace-axis.vertical atom-pane-container atom-text-editor.editor:not([mini])