Subscribe after Grammar tokenize event


#1

Hi all!
I’m developing a package relaying on grammar scopes to highlight dynamically some words. I can correctly execute my script every time something change in the TextEditor subscribing to onDidStopChanging() events, but I can’t figure out how to execute it when I open a new file or I open Atom with a Texteditor tab already open.
I know that I could use some WorkSpace events like onDidOpen() or onDidAddPaneItem(), but it seems that when the callback is executed, the Grammar has not yet tokenized the content of the TextEditor, resulting in no syntax scopes available to be used by my script.

Does anyone know the correct way to do this?


#2

atom.workspace.observeTextEditors() will fire every time a new TextEditor is created, and once for every current TextEditor that exists when that function is run.


#3

Ok, I didn’t think to put the call to my script in atom.workspace.observeTextEditors().
Sadly this doesn’t work, I still can’t get access to syntax scopes.
This is what I tried:

this.subscriptions.add(atom.workspace.observeTextEditors(
  (editor) => {
    this.MYSCRIPT(editor) // <-- this is what I added
    editor.onDidStopChanging(this.MYSCRIPT)
  }
))

Just to be extra-clear, in my script I use editor.scopeDescriptorForBufferPosition(range).getScopesArray() for some ranges. When a onDidStopChanging() event get fired, it all works, I get the right results. But in the call I added the scopes array is always composed of one element, the main grammar scope (like source.js, source.python, ecc…).


#4

Okay, I don’t think this is part of the published API because it gets a little into Atom’s internal functionality. I haven’t worked on any of this code, but I’ve used Atom for years as a fairly advanced user, so I’ve discovered a few things about how it works behind the scenes. Each TextEditor has a buffer object which contains the internal side of the data and API (where the TextEditor API is more front-facing and deals with visual information most commonly used by packages). By looking at the Atom code, in src/text-editor.js, I can look for emitters or events that reference tokenizing. Atom uses Node’s event system to communicate with itself about everything it does, and since that’s all open-source and JavaScript, any package can essentially plug into any part of Atom whether or not it’s part of the published API. And by looking at that code, it seems to me that TextEditor.onDidTokenize() will allow for a callback to trigger on that event. Give that a test.


#6

Just tried TextEditor.onDidTokenize(), and it is exactly what I needed!
It seems that the callback triggers only after the first tokenize of the buffer, but this is enough for me.
Thank you for the help, especially for suggesting me a good method to answer my future questions!

EDIT: For anybody that wants to see how this problem was approached and resolved, here’s the link to my package: https://atom.io/packages/language-matlab-plus.