From 821debcb855660ebd85a95bd85d18989793093cf Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 31 Dec 2013 18:18:39 -0700 Subject: [PATCH] Make Editor, DisplayBuffer, TokenizedBuffer to not use telepath This commit introduces dependency on a new npm called [reactionary](https://github.com/atom/reactionary). It will serve as a *much* lighter weight model framework to provide the reactive features of telepath without the replication logic. Specs are still failing for panes and workspace. I plan to just roll forward and remove the telepath dependency from them as well. --- package.json | 3 +- spec/editor-spec.coffee | 5 +--- spec/tokenized-buffer-spec.coffee | 2 +- src/display-buffer.coffee | 41 ++++++++++++++------------- src/editor.coffee | 47 +++++++++++++++---------------- src/tokenized-buffer.coffee | 37 +++++++++--------------- 6 files changed, 62 insertions(+), 73 deletions(-) diff --git a/package.json b/package.json index f6caaf9c5..76f589e7a 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,8 @@ "telepath": "0.80.0", "temp": "0.5.0", "text-buffer": "0.3.0", - "underscore-plus": "0.6.1" + "underscore-plus": "0.6.1", + "reactionary": "~0.1.0" }, "devDependencies": { "biscotto": "0.0.17", diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index 48116684d..30bcf8f36 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -28,10 +28,7 @@ describe "Editor", -> editor.foldBufferRow(4) expect(editor.isFoldedAtBufferRow(4)).toBeTruthy() - # Simulate serialization with replicate - editor2 = editor.testPersistence() - # FIXME: The created hook is called manually on deserialization because globals aren't ready otherwise - editor2.created() + editor2 = editor.testSerialization() expect(editor2.id).toBe editor.id expect(editor2.getBuffer().getPath()).toBe editor.getBuffer().getPath() diff --git a/spec/tokenized-buffer-spec.coffee b/spec/tokenized-buffer-spec.coffee index 654205c0e..087f1a03a 100644 --- a/spec/tokenized-buffer-spec.coffee +++ b/spec/tokenized-buffer-spec.coffee @@ -25,7 +25,7 @@ describe "TokenizedBuffer", -> startTokenizing(tokenizedBuffer) it "stops tokenization", -> - tokenizedBuffer.state.destroy() + tokenizedBuffer.destroy() spyOn(tokenizedBuffer, 'tokenizeNextChunk') advanceClock() expect(tokenizedBuffer.tokenizeNextChunk).not.toHaveBeenCalled() diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 3e7d64383..0c477db7f 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -1,7 +1,9 @@ _ = require 'underscore-plus' {Emitter, Subscriber} = require 'emissary' guid = require 'guid' -{Model, Point, Range} = require 'telepath' +Serializable = require 'nostalgia' +{Model} = require 'reactionary' +{Point, Range} = require 'text-buffer' TokenizedBuffer = require './tokenized-buffer' RowMap = require './row-map' Fold = require './fold' @@ -12,28 +14,18 @@ ConfigObserver = require './config-observer' # Private: module.exports = class DisplayBuffer extends Model + Serializable.includeInto(this) _.extend @prototype, ConfigObserver @properties - tokenizedBuffer: null - softWrap: -> atom.config.get('editor.softWrap') ? false + softWrap: null editorWidthInChars: null - constructor: -> + constructor: ({tabLength, @editorWidthInChars, @tokenizedBuffer, buffer}={}) -> super - @deserializing = @state? - - created: -> - if @deserializing - @deserializing = false - return - - if @tokenizedBuffer? - @tokenizedBuffer?.created() - else - @tokenizedBuffer = new TokenizedBuffer({@tabLength, @buffer, project: atom.project}) + @softWrap ?= atom.config.get('editor.softWrap') ? false + @tokenizedBuffer ?= new TokenizedBuffer({tabLength, buffer}) @buffer = @tokenizedBuffer.buffer - @markers = {} @foldsByMarkerId = {} @updateAllScreenLines() @@ -43,10 +35,9 @@ class DisplayBuffer extends Model @subscribe @buffer, 'markers-updated', @handleBufferMarkersUpdated @subscribe @buffer, 'marker-created', @handleBufferMarkerCreated - @subscribe @state, 'changed', ({newValues}) => - if newValues.softWrap? - @emit 'soft-wrap-changed', newValues.softWrap - @updateWrappedScreenLines() + @subscribe @$softWrap, 'value', (softWrap) => + @emit 'soft-wrap-changed', softWrap + @updateWrappedScreenLines() @observeConfig 'editor.preferredLineLength', callNow: false, => @updateWrappedScreenLines() if @softWrap and atom.config.get('editor.softWrapAtPreferredLineLength') @@ -54,6 +45,16 @@ class DisplayBuffer extends Model @observeConfig 'editor.softWrapAtPreferredLineLength', callNow: false, => @updateWrappedScreenLines() if @softWrap + serializeParams: -> + id: @id + softWrap: @softWrap + editorWidthInChars: @editorWidthInChars + tokenizedBuffer: @tokenizedBuffer.serialize() + + deserializeParams: (params) -> + params.tokenizedBuffer = TokenizedBuffer.deserialize(params.tokenizedBuffer) + params + copy: -> newDisplayBuffer = atom.create(new DisplayBuffer({@buffer, tabLength: @getTabLength()})) for marker in @findMarkers(displayBufferId: @id) diff --git a/src/editor.coffee b/src/editor.coffee index 3bc0ade3f..52c77d28a 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -1,6 +1,8 @@ _ = require 'underscore-plus' path = require 'path' -{Model, Point, Range} = require 'telepath' +Serializable = require 'nostalgia' +{Model} = require 'reactionary' +{Point, Range} = require 'text-buffer' LanguageMode = require './language-mode' DisplayBuffer = require './display-buffer' Cursor = require './cursor' @@ -29,10 +31,9 @@ TextMateScopeSelector = require('first-mate').ScopeSelector # ``` module.exports = class Editor extends Model + Serializable.includeInto(this) @properties - displayBuffer: null - softTabs: null scrollTop: 0 scrollLeft: 0 @@ -45,26 +46,15 @@ class Editor extends Model selections: null suppressSelectionMerging: false - constructor: -> + constructor: ({@softTabs, initialLine, tabLength, softWrap, @displayBuffer, buffer, registerEditor, suppressCursorCreation}) -> super - @deserializing = @state? - - created: -> - if @deserializing - @deserializing = false - @callDisplayBufferCreatedHook = true - @registerEditor = true - return @cursors = [] @selections = [] - unless @displayBuffer? - @displayBuffer = new DisplayBuffer({@buffer, @tabLength, @softWrap}) - @softTabs = @buffer.usesSoftTabs() ? @softTabs ? atom.config.get('editor.softTabs') ? true - - @displayBuffer.created() if @callDisplayBufferCreatedHook + @displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrap}) @buffer = @displayBuffer.buffer + @softTabs = @buffer.usesSoftTabs() ? @softTabs ? atom.config.get('editor.softTabs') ? true for marker in @findMarkers(@getSelectionMarkerAttributes()) marker.setAttributes(preserveFolds: true) @@ -73,9 +63,9 @@ class Editor extends Model @subscribeToBuffer() @subscribeToDisplayBuffer() - if @getCursors().length is 0 and not @suppressCursorCreation - if @initialLine - position = [@initialLine, 0] + if @getCursors().length is 0 and not suppressCursorCreation + if initialLine + position = [initialLine, 0] else position = [0, 0] @addCursorAtBufferPosition(position) @@ -85,10 +75,19 @@ class Editor extends Model @subscribe @$scrollTop, 'value', (scrollTop) => @emit 'scroll-top-changed', scrollTop @subscribe @$scrollLeft, 'value', (scrollLeft) => @emit 'scroll-left-changed', scrollLeft - atom.project.addEditor(this) if @registerEditor + atom.project.addEditor(this) if registerEditor - # Deprecated: The goal is a world where we don't call serialize explicitly - serialize: -> this + serializeParams: -> + id: @id + softTabs: @softTabs + scrollTop: @scrollTop + scrollLeft: @scrollLeft + displayBuffer: @displayBuffer.serialize() + + deserializeParams: (params) -> + params.displayBuffer = DisplayBuffer.deserialize(params.displayBuffer) + params.registerEditor = true + params # Private: subscribeToBuffer: -> @@ -134,7 +133,7 @@ class Editor extends Model tabLength = @getTabLength() displayBuffer = @displayBuffer.copy() softTabs = @getSoftTabs() - newEditor = @create(new Editor({@buffer, displayBuffer, tabLength, softTabs, suppressCursorCreation: true})) + newEditor = new Editor({@buffer, displayBuffer, tabLength, softTabs, suppressCursorCreation: true}) newEditor.setScrollTop(@getScrollTop()) newEditor.setScrollLeft(@getScrollLeft()) for marker in @findMarkers(editorId: @id) diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index ac3cf01b9..57d94e203 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -1,5 +1,7 @@ _ = require 'underscore-plus' -{Model, Point, Range} = require 'telepath' +{Model} = require 'reactionary' +{Point, Range} = require 'text-buffer' +Serializable = require 'nostalgia' TokenizedLine = require './tokenized-line' Token = require './token' @@ -7,10 +9,9 @@ Token = require './token' module.exports = class TokenizedBuffer extends Model - @properties - bufferPath: null - tabLength: -> atom.config.get('editor.tabLength') ? 2 - project: null + Serializable.includeInto(this) + + @property 'tabLength' grammar: null currentGrammarScore: null @@ -20,19 +21,8 @@ class TokenizedBuffer extends Model invalidRows: null visible: false - constructor: -> - super - @deserializing = @state? - - created: -> - if @deserializing - @deserializing = false - return - - if @buffer? and @buffer.isAlive() - @bufferPath = @buffer.getPath() - else - @buffer = @project.bufferForPathSync(@bufferPath) + constructor: ({@buffer, @tabLength}) -> + @tabLength ?= atom.config.get('editor.tabLength') ? 2 @subscribe atom.syntax, 'grammar-added grammar-updated', (grammar) => if grammar.injectionSelector? @@ -56,12 +46,13 @@ class TokenizedBuffer extends Model @reloadGrammar() - # TODO: Remove when everything is a telepath model - destroy: -> - @destroyed() + serializeParams: -> + bufferPath: @buffer.getPath() + tabLength: @tabLength - destroyed: -> - @unsubscribe() + deserializeParams: (params) -> + params.buffer = atom.project.bufferForPathSync(params.bufferPath) + params setGrammar: (grammar, score) -> return if grammar is @grammar