mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Apply text to buffer via diff on reload
Previously, it would blindly read from disk on reload, and set the text into the editor. This was problematic as it would mess with markers and folds. No longer. Fixes #1285 and fixes atom/bookmarks#3
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
"clear-cut": "0.2.0",
|
||||
"coffee-script": "1.6.3",
|
||||
"coffeestack": "0.6.0",
|
||||
"diff": "git://github.com/benogle/jsdiff.git",
|
||||
"emissary": "0.19.0",
|
||||
"first-mate": "0.5.0",
|
||||
"fs-plus": "0.11.0",
|
||||
|
||||
@@ -113,10 +113,17 @@ describe 'TextBuffer', ->
|
||||
|
||||
runs ->
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
expect(event.oldRange).toEqual [[0, 0], [0, 5]]
|
||||
expect(event.oldRange).toEqual [[0, 0], [0, 0]]
|
||||
expect(event.newRange).toEqual [[0, 0], [0, 6]]
|
||||
expect(event.oldText).toBe "first"
|
||||
expect(event.oldText).toBe ""
|
||||
expect(event.newText).toBe "second"
|
||||
|
||||
[event] = changeHandler.argsForCall[1]
|
||||
expect(event.oldRange).toEqual [[0, 6], [0, 11]]
|
||||
expect(event.newRange).toEqual [[0, 6], [0, 6]]
|
||||
expect(event.oldText).toBe "first"
|
||||
expect(event.newText).toBe ""
|
||||
|
||||
expect(buffer.isModified()).toBeFalsy()
|
||||
|
||||
describe "when the buffer's memory contents differ from the *previous* disk contents", ->
|
||||
@@ -454,6 +461,67 @@ describe 'TextBuffer', ->
|
||||
expect(event.oldRange).toEqual expectedPreRange
|
||||
expect(event.newRange).toEqual [[0, 0], [1, 14]]
|
||||
|
||||
describe ".setTextViaDiff(text)", ->
|
||||
it "changes the entire contents of the buffer with smaller content with no newline at the end", ->
|
||||
newText = "I know you are.\nBut what am I?"
|
||||
buffer.setTextViaDiff(newText)
|
||||
expect(buffer.getText()).toBe newText
|
||||
|
||||
it "changes the entire contents of the buffer with smaller content with newline at the end", ->
|
||||
newText = "I know you are.\nBut what am I?\n"
|
||||
buffer.setTextViaDiff(newText)
|
||||
expect(buffer.getText()).toBe newText
|
||||
|
||||
it "changes a few lines at the beginning in the buffer", ->
|
||||
newText = buffer.getText().replace(/function/g, 'omgwow')
|
||||
buffer.setTextViaDiff(newText)
|
||||
expect(buffer.getText()).toBe newText
|
||||
|
||||
it "changes a few lines in the middle of the buffer", ->
|
||||
newText = buffer.getText().replace(/shift/g, 'omgwow')
|
||||
buffer.setTextViaDiff(newText)
|
||||
expect(buffer.getText()).toBe newText
|
||||
|
||||
it "adds a newline at the end", ->
|
||||
newText = buffer.getText() + '\n'
|
||||
buffer.setTextViaDiff(newText)
|
||||
expect(buffer.getText()).toBe newText
|
||||
|
||||
it "changes all with no newlines", ->
|
||||
buffer.setText('BUFFER CHANGE')
|
||||
newText = 'DISK CHANGE'
|
||||
buffer.setTextViaDiff(newText)
|
||||
expect(buffer.getText()).toBe newText
|
||||
|
||||
describe "with windows newlines", ->
|
||||
beforeEach ->
|
||||
buffer.setText(buffer.getText().replace(/\n/g, '\r\n'))
|
||||
|
||||
it "adds a newline at the end", ->
|
||||
newText = buffer.getText() + '\r\n'
|
||||
buffer.setTextViaDiff(newText)
|
||||
expect(buffer.getText()).toBe newText
|
||||
|
||||
it "changes the entire contents of the buffer with smaller content with no newline at the end", ->
|
||||
newText = "I know you are.\r\nBut what am I?"
|
||||
buffer.setTextViaDiff(newText)
|
||||
expect(buffer.getText()).toBe newText
|
||||
|
||||
it "changes the entire contents of the buffer with smaller content with newline at the end", ->
|
||||
newText = "I know you are.\r\nBut what am I?\r\n"
|
||||
buffer.setTextViaDiff(newText)
|
||||
expect(buffer.getText()).toBe newText
|
||||
|
||||
it "changes a few lines at the beginning in the buffer", ->
|
||||
newText = buffer.getText().replace(/function/g, 'omgwow')
|
||||
buffer.setTextViaDiff(newText)
|
||||
expect(buffer.getText()).toBe newText
|
||||
|
||||
it "changes a few lines in the middle of the buffer", ->
|
||||
newText = buffer.getText().replace(/shift/g, 'omgwow')
|
||||
buffer.setTextViaDiff(newText)
|
||||
expect(buffer.getText()).toBe newText
|
||||
|
||||
describe ".save()", ->
|
||||
saveBuffer = null
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
_ = require 'underscore-plus'
|
||||
diff = require 'diff'
|
||||
Q = require 'q'
|
||||
{P} = require 'scandal'
|
||||
telepath = require 'telepath'
|
||||
@@ -133,7 +134,7 @@ class TextBuffer extends telepath.Model
|
||||
# Sets the buffer's content to the cached disk contents
|
||||
reload: ->
|
||||
@emit 'will-reload'
|
||||
@setText(@cachedDiskContents)
|
||||
@setTextViaDiff(@cachedDiskContents)
|
||||
@emitModifiedStatusChanged(false)
|
||||
@emit 'reloaded'
|
||||
|
||||
@@ -198,6 +199,12 @@ class TextBuffer extends telepath.Model
|
||||
setText: (text) ->
|
||||
@change(@getRange(), text, normalizeLineEndings: false)
|
||||
|
||||
# Replaces the current buffer contents. Only apply the differences.
|
||||
#
|
||||
# text - A {String} containing the new buffer contents.
|
||||
setTextViaDiff: (text) ->
|
||||
@applyDifferences(text)
|
||||
|
||||
# Gets the range of the buffer contents.
|
||||
#
|
||||
# Returns a new {Range}, from `[0, 0]` to the end of the buffer.
|
||||
@@ -667,3 +674,49 @@ class TextBuffer extends telepath.Model
|
||||
for row in [start..end]
|
||||
line = @lineForRow(row)
|
||||
console.log row, line, line.length
|
||||
|
||||
applyDifferences: (newText) ->
|
||||
currentText = @getText()
|
||||
return if currentText == newText
|
||||
|
||||
endsWithNewline = (str) ->
|
||||
/[\r\n]+$/g.test(str)
|
||||
|
||||
computeBufferColumn = (str) ->
|
||||
newlineIndex = Math.max(str.lastIndexOf('\n'), str.lastIndexOf('\r'))
|
||||
if endsWithNewline(str)
|
||||
0
|
||||
else if newlineIndex == -1
|
||||
str.length
|
||||
else
|
||||
str.length - newlineIndex - 1
|
||||
|
||||
@transact =>
|
||||
bufferRow = 0
|
||||
bufferColumn = 0
|
||||
startPosition = [0, 0]
|
||||
|
||||
lineDiff = diff.diffLines(currentText, newText)
|
||||
changeOptions = normalizeLineEndings: false
|
||||
|
||||
for change in lineDiff
|
||||
numberLines = change.value.match(/\n/g)?.length ? 0
|
||||
startPosition[0] = bufferRow
|
||||
startPosition[1] = bufferColumn
|
||||
|
||||
if change.added
|
||||
@change([startPosition, startPosition], change.value, changeOptions)
|
||||
bufferRow += numberLines
|
||||
bufferColumn = computeBufferColumn(change.value)
|
||||
|
||||
else if change.removed
|
||||
endBufferRow = bufferRow + numberLines
|
||||
endBufferColumn = bufferColumn + computeBufferColumn(change.value)
|
||||
@change([startPosition, [endBufferRow, endBufferColumn]], '', changeOptions)
|
||||
|
||||
else
|
||||
bufferRow += numberLines
|
||||
bufferColumn = computeBufferColumn(change.value)
|
||||
|
||||
# console.log 'after', bufferRow, bufferColumn, change
|
||||
# console.log @getText()
|
||||
|
||||
Reference in New Issue
Block a user