Getting changes in TextBuffer


#1

I can subscribe to changes quite easily

editor.onDidStopChanging(() => {

However how can I know what exacty changed. Currently I am forced to do editor.getText() which is not great for performance.

editor.onDidStopChanging(() => {
   var newText = editor.getText();

Is there a better way.


#2

What is it you’re trying to make happen?


#3

I just ran into this yesterday. You have to use the immediate onDidChange to get the diffs. This kind of makes sense since after the 300 ms delay a lot could have happened and it wasn’t saved.

I used onDidChange but did my own timeout to save performance. I can show the code if you wish.


#4

That would be great!


#5

Wow that was a fast reply. It seemed like 15 seconds. I’ll get the code here by tomorrow morning.


#6

FWIW, here’s the minimap code that deals with the editor changes:

https://github.com/fundon/atom-minimap/blob/next/v4/lib/mixins/canvas-drawer.coffee#L302-L344

The pendingChanges array contains the changes object as received in the onDidChange event.
In our case we need to compute which parts of the minimap canvas can be reused and which parts needs a redraw.


#7

Here is my replacement for TextEditor::onDidStopChanging. I extracted it from my code and simplified/optimized it. It hasn’t been tested.

myOnDidStopChanging = (editor, callback) ->
  disposed = no
  diffs = []
  sub = editor.onDidChange (diff) ->
    diffs.push diff
    clearTimeout changeTimeout if changeTimeout
    changeTimeout = setTimeout ->
      callback diffs if not disposed
      diffs = []
      changeTimeout = null
    , 300
  dispose: ->
    disposed = yes
    sub.dispose()

Note that myOnDidStopChanging returns a normal disposable.

Maybe I should submit this as a PR to core.


#8

You could monkey-patch TextEditor by using this version …

TextEditor::onDidStopChangingWithDiffs = (callback) ->
  diffs = []
  disposed = no
  sub = @onDidChange (diff) ->
    diffs.push diff
    clearTimeout changeTimeout if changeTimeout
    changeTimeout = setTimeout ->
      changeTimeout = null
      callback diffs if not disposed
      diffs = []
    , 300
  dispose: ->
    disposed = yes
    sub.dispose()
    

Then you could use onDidStopChangingWithDiffs anywhere after the patch.


#9

Just wanted to say thank you. I’ll just be using onDidChange and updating my code to not do any analysis for that in the UI thread.