Start basing Buffer's text on a replicable string

This commit is contained in:
Kevin Sawicki & Nathan Sobo 2013-07-01 17:00:59 -06:00 committed by Kevin Sawicki
parent 010c3435da
commit dd0f7a032f
4 changed files with 55 additions and 93 deletions

View File

@ -0,0 +1,21 @@
{createSite} = require 'telepath'
TextBuffer = require 'text-buffer'
describe "TextBuffer replication", ->
[buffer1, buffer2] = []
beforeEach ->
buffer1 = new TextBuffer(project.resolve('sample.js'))
buffer1.insert([0, 0], 'changed\n')
doc1 = buffer1.getState()
doc2 = doc1.clone(createSite(2))
doc1.connect(doc2)
buffer2 = deserialize(doc2)
afterEach ->
buffer1.destroy()
buffer2.destroy()
it "replicates the initial path and text of the buffer", ->
expect(buffer2.getPath()).toBe buffer1.getPath()
expect(buffer2.getText()).toBe buffer1.getText()

View File

@ -1,4 +1,4 @@
Range = require 'range'
{Range} = require 'telepath'
_ = require 'underscore'
### Internal ###
@ -22,7 +22,7 @@ class BufferChangeOperation
@markersToRestoreOnUndo = @invalidateMarkers(@oldRange)
if @oldRange?
@oldText = @buffer.getTextInRange(@oldRange)
@newRange = @calculateNewRange(@oldRange, @newText)
@newRange = Range.fromText(@oldRange.start, @newText)
newRange = @changeBuffer
oldRange: @oldRange
newRange: @newRange
@ -47,37 +47,9 @@ class BufferChangeOperation
@buffer.resumeEvents()
@resumeMarkerObservation()
splitLines: (text) ->
lines = text.split('\n')
lineEndings = []
for line, index in lines
if _.endsWith(line, '\r')
lines[index] = line[...-1]
lineEndings[index] = '\r\n'
else
lineEndings[index] = '\n'
{lines, lineEndings}
changeBuffer: ({ oldRange, newRange, newText, oldText }) ->
{ prefix, suffix } = @buffer.prefixAndSuffixForRange(oldRange)
{lines, lineEndings} = @splitLines(newText)
lastLineIndex = lines.length - 1
@buffer.text.change(oldRange, newText)
if lines.length == 1
lines = [prefix + newText + suffix]
else
lines[0] = prefix + lines[0]
lines[lastLineIndex] += suffix
startRow = oldRange.start.row
endRow = oldRange.end.row
normalizeLineEndings = @options.normalizeLineEndings ? true
if normalizeLineEndings and suggestedLineEnding = @buffer.suggestedLineEndingForRow(startRow)
lineEndings[index] = suggestedLineEnding for index in [0..lastLineIndex]
_.spliceWithArray(@buffer.lines, startRow, endRow - startRow + 1, lines)
_.spliceWithArray(@buffer.lineEndings, startRow, endRow - startRow + 1, lineEndings)
@buffer.cachedMemoryContents = null
@buffer.conflict = false if @buffer.conflict and !@buffer.isModified()
@ -88,17 +60,6 @@ class BufferChangeOperation
newRange
calculateNewRange: (oldRange, newText) ->
newRange = new Range(oldRange.start.copy(), oldRange.start.copy())
{lines} = @splitLines(newText)
if lines.length == 1
newRange.end.column += newText.length
else
lastLineIndex = lines.length - 1
newRange.end.row += lastLineIndex
newRange.end.column = lines[lastLineIndex].length
newRange
invalidateMarkers: (oldRange) ->
@buffer.getMarkers().map (marker) -> marker.tryToInvalidate(oldRange)

View File

@ -1,4 +1,5 @@
_ = require 'underscore'
telepath = require 'telepath'
fsUtils = require 'fs-utils'
File = require 'file'
Point = require 'point'
@ -14,16 +15,19 @@ BufferMarker = require 'buffer-marker'
# the case, as a `Buffer` could be an unsaved chunk of text.
module.exports =
class TextBuffer
@acceptsDocuments: true
@idCounter = 1
registerDeserializer(this)
@deserialize: (state) ->
new TextBuffer(state)
stoppedChangingDelay: 300
stoppedChangingTimeout: null
undoManager: null
cachedDiskContents: null
cachedMemoryContents: null
conflict: false
lines: null
lineEndings: null
file: null
validMarkers: null
invalidMarkers: null
@ -33,13 +37,20 @@ class TextBuffer
#
# path - A {String} representing the file path
# initialText - A {String} setting the starting text
constructor: (path, initialText) ->
constructor: (args...) ->
@id = @constructor.idCounter++
@nextMarkerId = 1
@validMarkers = {}
@invalidMarkers = {}
@lines = ['']
@lineEndings = []
if args[0] instanceof telepath.Document
@state = args[0]
@text = @state.get('text')
path = @state.get('path')
else
[path, initialText] = args
@text = telepath.Document.create('', shareStrings: true)
@state = telepath.Document.create(deserializer: @constructor.name, text: @text)
if path
@setPath(path)
@ -72,15 +83,8 @@ class TextBuffer
@destroy() if @refcount <= 0
this
serialize: ->
deserializer: 'TextBuffer'
path: @getPath()
text: @getText() if @isModified()
getState: -> @serialize()
@deserialize: ({path, text}) ->
new TextBuffer(path, text)
serialize: -> @state
getState: -> @state
subscribeToFile: ->
@file.on "contents-changed", =>
@ -146,6 +150,8 @@ class TextBuffer
@file.read() if @file.exists()
@subscribeToFile()
@state.set('path', path)
@trigger "path-changed", this
# Retrieves the current buffer's file extension.
@ -181,25 +187,13 @@ class TextBuffer
#
# Returns a {String} of the combined lines.
getTextInRange: (range) ->
range = @clipRange(range)
if range.start.row == range.end.row
return @lineForRow(range.start.row)[range.start.column...range.end.column]
multipleLines = []
multipleLines.push @lineForRow(range.start.row)[range.start.column..] # first line
multipleLines.push @lineEndingForRow(range.start.row)
for row in [range.start.row + 1...range.end.row]
multipleLines.push @lineForRow(row) # middle lines
multipleLines.push @lineEndingForRow(row)
multipleLines.push @lineForRow(range.end.row)[0...range.end.column] # last line
return multipleLines.join ''
@text.getTextInRange(@clipRange(range))
# Gets all the lines in a file.
#
# Returns an {Array} of {String}s.
getLines: ->
@lines
@text.getLines()
# Given a row, returns the line of text.
#
@ -207,7 +201,7 @@ class TextBuffer
#
# Returns a {String}.
lineForRow: (row) ->
@lines[row]
@text.lineForRow(row)
# Given a row, returns its line ending.
#
@ -215,7 +209,7 @@ class TextBuffer
#
# Returns a {String}, or `undefined` if `row` is the final row.
lineEndingForRow: (row) ->
@lineEndings[row] unless row is @getLastRow()
@text.lineEndingForRow(row)
suggestedLineEndingForRow: (row) ->
@lineEndingForRow(row) ? @lineEndingForRow(row - 1)
@ -226,7 +220,7 @@ class TextBuffer
#
# Returns a {Number}.
lineLengthForRow: (row) ->
@lines[row].length
@text.lineLengthForRow(row)
# Given a row, returns the length of the line ending
#
@ -253,13 +247,13 @@ class TextBuffer
#
# Returns a {Number}.
getLineCount: ->
@getLines().length
@text.getLineCount()
# Gets the row number of the last line.
#
# Returns a {Number}.
getLastRow: ->
@getLines().length - 1
@getLineCount() - 1
# Finds the last line in the current buffer.
#
@ -275,20 +269,10 @@ class TextBuffer
new Point(lastRow, @lineLengthForRow(lastRow))
characterIndexForPosition: (position) ->
position = @clipPosition(position)
index = 0
for row in [0...position.row]
index += @lineLengthForRow(row) + Math.max(@lineEndingLengthForRow(row), 1)
index + position.column
@text.indexForPoint(position)
positionForCharacterIndex: (index) ->
row = 0
while index >= (lineLength = @lineLengthForRow(row) + Math.max(@lineEndingLengthForRow(row), 1))
index -= lineLength
row++
new Point(row, index)
@text.pointForIndex(index)
# Given a row, this deletes it from the buffer.
#
@ -365,10 +349,6 @@ class TextBuffer
range = Range.fromObject(range)
new Range(@clipPosition(range.start), @clipPosition(range.end))
prefixAndSuffixForRange: (range) ->
prefix: @lines[range.start.row][0...range.start.column]
suffix: @lines[range.end.row][range.end.column..]
# Undos the last operation.
#
# editSession - The {EditSession} associated with the buffer.
@ -413,7 +393,7 @@ class TextBuffer
# Identifies if a buffer is empty.
#
# Returns a {Boolean}.
isEmpty: -> @lines.length is 1 and @lines[0].length is 0
isEmpty: -> @text.isEmpty()
# Returns all valid {BufferMarker}s on the buffer.
getMarkers: ({includeInvalid} = {}) ->

2
vendor/telepath vendored

@ -1 +1 @@
Subproject commit 3b465ef7e08c188621e3a30817650fbea38d3656
Subproject commit 6e7b122559024b32156e11cf8bb53cf810228a19