For this to work, I needed to make the updating of anchors transactional. Now, all anchors are updated and *then* they emit their events. That way when the cursor moves based on the user typing, the tab stop they're in has a chance to expand before we handle the move event. This prevents spurious cancellation of the snippet when typing on a tab stop.
Path watching resumes once the file is saved again. This commit allows files to be created for as-yet nonexistent paths. We won't call `$native.watchPath` until we have at least 1 subscription to the file in JS and the file exists on disk.
Also, we moved execution of the path watcher callbacks until after the callbacks data structure is updated in order to avoid confusing behavior in specs.
This will be used by the status bar and other expensive code that needs to respond to the buffer changing, but that we don't want running on every single keystroke when the user is typing quickly.
Computing the signature was really slow for large files. Keeping a cached copy of the disk contents and comparing directly costs less in the benchmark. We'll have to turn on the status bar in benchmarks to see if the comparison is too expensive.
Now, we maintain md5 signatures for the on-disk and in-memory contents of the buffer. Whenever either contents change, we recompute the signature and store it on the buffer. We can tell if the buffer is modified by comparing these signatures. When the disk contents change, we compare the memory and disk signatures *before* recomputing the disk signature to determine whether to update the buffer or mark it as a conflict.
Previously if a file was a single line
it couldn't be deleted using the delete
line command because the start row would
index one row back which would be -1 and
therefore not be able to report a length
for use in the delete range.
This is still in progress. You can't *redo* snippet expansion and restore tab stops. Also, this commit performs all changes associated with snippet expansion in a transaction.
The `do`, `undo`, and `redo` methods on operations take an optional editSession argument, which can be used to determine the context in which they are being run. We restore selections on that edit session instead of the session where the operations originally occurred.