diff --git a/spec/app/tokenized-buffer-spec.coffee b/spec/app/tokenized-buffer-spec.coffee
index f35dde3fe..40508e419 100644
--- a/spec/app/tokenized-buffer-spec.coffee
+++ b/spec/app/tokenized-buffer-spec.coffee
@@ -16,10 +16,18 @@ describe "TokenizedBuffer", ->
advanceClock() while tokenizedBuffer.firstInvalidRow()?
changeHandler?.reset()
+ describe "@deserialize(state)", ->
+ it "constructs a tokenized buffer with the same buffer and tabLength setting", ->
+ buffer = project.bufferForPath('sample.js')
+ tokenizedBuffer1 = new TokenizedBuffer(buffer: buffer, tabLength: 4)
+ tokenizedBuffer2 = deserialize(tokenizedBuffer1.serialize())
+ expect(tokenizedBuffer2.buffer).toBe tokenizedBuffer1.buffer
+ expect(tokenizedBuffer2.getTabLength()).toBe tokenizedBuffer1.getTabLength()
+
describe "when the buffer contains soft-tabs", ->
beforeEach ->
buffer = project.bufferForPath('sample.js')
- tokenizedBuffer = new TokenizedBuffer(buffer)
+ tokenizedBuffer = new TokenizedBuffer({buffer})
tokenizedBuffer.setVisible(true)
tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler')
@@ -299,7 +307,7 @@ describe "TokenizedBuffer", ->
beforeEach ->
atom.activatePackage('coffee-script-tmbundle', sync: true)
buffer = project.bufferForPath('sample-with-tabs.coffee')
- tokenizedBuffer = new TokenizedBuffer(buffer)
+ tokenizedBuffer = new TokenizedBuffer({buffer})
tokenizedBuffer.setVisible(true)
afterEach ->
@@ -311,7 +319,7 @@ describe "TokenizedBuffer", ->
fullyTokenize(tokenizedBuffer)
it "renders each tab as its own atomic token with a value of size tabLength", ->
- tabAsSpaces = _.multiplyString(' ', tokenizedBuffer.tabLength)
+ tabAsSpaces = _.multiplyString(' ', tokenizedBuffer.getTabLength())
screenLine0 = tokenizedBuffer.lineForScreenRow(0)
expect(screenLine0.text).toBe "# Econ 101#{tabAsSpaces}"
{ tokens } = screenLine0
@@ -332,7 +340,7 @@ describe "TokenizedBuffer", ->
'abc\uD835\uDF97def'
//\uD835\uDF97xyz
"""
- tokenizedBuffer = new TokenizedBuffer(buffer)
+ tokenizedBuffer = new TokenizedBuffer({buffer})
tokenizedBuffer.setVisible(true)
fullyTokenize(tokenizedBuffer)
@@ -369,7 +377,7 @@ describe "TokenizedBuffer", ->
atom.activatePackage('ruby-on-rails-tmbundle', sync: true)
buffer = project.bufferForPath(null, "
<%= User.find(2).full_name %>
")
- tokenizedBuffer = new TokenizedBuffer(buffer)
+ tokenizedBuffer = new TokenizedBuffer({buffer})
tokenizedBuffer.setGrammar(syntax.selectGrammar('test.erb'))
tokenizedBuffer.setVisible(true)
fullyTokenize(tokenizedBuffer)
@@ -389,7 +397,7 @@ describe "TokenizedBuffer", ->
it "returns the correct token (regression)", ->
buffer = project.bufferForPath('sample.js')
- tokenizedBuffer = new TokenizedBuffer(buffer)
+ tokenizedBuffer = new TokenizedBuffer({buffer})
tokenizedBuffer.setVisible(true)
fullyTokenize(tokenizedBuffer)
expect(tokenizedBuffer.tokenForPosition([1,0]).scopes).toEqual ["source.js"]
diff --git a/src/app/display-buffer.coffee b/src/app/display-buffer.coffee
index 1fb0c6adf..ffd3b60b7 100644
--- a/src/app/display-buffer.coffee
+++ b/src/app/display-buffer.coffee
@@ -22,7 +22,7 @@ class DisplayBuffer
constructor: (@buffer, options={}) ->
@id = guid.create().toString()
- @tokenizedBuffer = new TokenizedBuffer(@buffer, options)
+ @tokenizedBuffer = new TokenizedBuffer(_.defaults({@buffer}, options))
@softWrapColumn = options.softWrapColumn ? Infinity
@markers = {}
@foldsByMarkerId = {}
diff --git a/src/app/tokenized-buffer.coffee b/src/app/tokenized-buffer.coffee
index aebcd8d8e..e4e28a10a 100644
--- a/src/app/tokenized-buffer.coffee
+++ b/src/app/tokenized-buffer.coffee
@@ -3,17 +3,15 @@ TokenizedLine = require 'tokenized-line'
EventEmitter = require 'event-emitter'
Subscriber = require 'subscriber'
Token = require 'token'
-{Point, Range} = require 'telepath'
+telepath = require 'telepath'
+{Point, Range} = telepath
### Internal ###
module.exports =
class TokenizedBuffer
- @idCounter: 1
-
grammar: null
currentGrammarScore: null
- tabLength: null
buffer: null
aceAdaptor: null
tokenizedLines: null
@@ -21,9 +19,22 @@ class TokenizedBuffer
invalidRows: null
visible: false
- constructor: (@buffer, { @tabLength } = {}) ->
- @tabLength ?= 2
- @id = @constructor.idCounter++
+ @acceptsDocuments: true
+ registerDeserializer(this)
+
+ @deserialize: (state) ->
+ new this(state)
+
+ constructor: (optionsOrState) ->
+ if optionsOrState instanceof telepath.Document
+ @state = optionsOrState
+ @buffer = project.bufferForId(optionsOrState.get('bufferId'))
+ else
+ { @buffer, tabLength } = optionsOrState
+ @state = telepath.create
+ deserializer: @constructor.name
+ bufferId: @buffer.id
+ tabLength: tabLength ? 2
@subscribe syntax, 'grammar-added grammar-updated', (grammar) =>
if grammar.injectionSelector?
@@ -33,10 +44,13 @@ class TokenizedBuffer
@setGrammar(grammar, newScore) if newScore > @currentGrammarScore
@on 'grammar-changed grammar-updated', => @resetTokenizedLines()
- @subscribe @buffer, "changed.tokenized-buffer#{@id}", (e) => @handleBufferChange(e)
+ @subscribe @buffer, "changed", (e) => @handleBufferChange(e)
@reloadGrammar()
+ serialize: -> @state.clone()
+ getState: -> @state
+
setGrammar: (grammar, score) ->
return if grammar is @grammar
@unsubscribe(@grammar) if @grammar
@@ -70,12 +84,13 @@ class TokenizedBuffer
#
# Returns a {Number}.
getTabLength: ->
- @tabLength
+ @state.get('tabLength')
# Specifies the tab length.
#
# tabLength - A {Number} that defines the new tab length.
- setTabLength: (@tabLength) ->
+ setTabLength: (tabLength) ->
+ @state.set('tabLength', tabLength)
lastRow = @buffer.getLastRow()
@tokenizedLines = @buildPlaceholderTokenizedLinesForRows(0, lastRow)
@invalidateRow(0)
@@ -174,13 +189,15 @@ class TokenizedBuffer
buildPlaceholderTokenizedLineForRow: (row) ->
line = @buffer.lineForRow(row)
tokens = [new Token(value: line, scopes: [@grammar.scopeName])]
- new TokenizedLine({tokens, @tabLength})
+ tabLength = @getTabLength()
+ new TokenizedLine({tokens, tabLength})
buildTokenizedTokenizedLineForRow: (row, ruleStack) ->
line = @buffer.lineForRow(row)
lineEnding = @buffer.lineEndingForRow(row)
+ tabLength = @getTabLength()
{ tokens, ruleStack } = @grammar.tokenizeLine(line, ruleStack, row is 0)
- new TokenizedLine({tokens, ruleStack, @tabLength, lineEnding})
+ new TokenizedLine({tokens, ruleStack, tabLength, lineEnding})
lineForScreenRow: (row) ->
@linesForScreenRows(row, row)[0]
@@ -200,7 +217,6 @@ class TokenizedBuffer
destroy: ->
@unsubscribe()
- @buffer.off ".tokenized-buffer#{@id}"
iterateTokensInBufferRange: (bufferRange, iterator) ->
bufferRange = Range.fromObject(bufferRange)