From 8ce3c6ca9db0ecfa0d05dbf1f729d4ddef0d0ed8 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Thu, 9 Feb 2012 15:17:59 -0800 Subject: [PATCH] Emit correct change events when replaced spans multiple screen lines --- spec/atom/line-wrapper-spec.coffee | 47 ++++++++++++++++++++++++++---- src/atom/line-wrapper.coffee | 10 +++---- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/spec/atom/line-wrapper-spec.coffee b/spec/atom/line-wrapper-spec.coffee index b7dce318f..3f797bc5c 100644 --- a/spec/atom/line-wrapper-spec.coffee +++ b/spec/atom/line-wrapper-spec.coffee @@ -4,7 +4,7 @@ Highlighter = require 'highlighter' Range = require 'range' _ = require 'underscore' -fdescribe "LineWrapper", -> +describe "LineWrapper", -> [wrapper, buffer] = [] beforeEach -> @@ -32,6 +32,8 @@ fdescribe "LineWrapper", -> describe "when the buffer changes", -> changeHandler = null longText = '0123456789ABCDEF' + text10 = '0123456789' + text60 = '0123456789 123456789 123456789 123456789 123456789 123456789' beforeEach -> changeHandler = jasmine.createSpy('changeHandler') @@ -84,13 +86,48 @@ fdescribe "LineWrapper", -> expect(event.newRange).toEqual(new Range([2, 4], [4, 33])) describe "when a wrapped line is updated", -> - describe "when the update does not cause the line to un-wrap", -> + describe "when the old text spans multiple screen lines", -> + describe "when the new text spans fewer screen lines than the old text", -> + fit "updates tokens for the corresponding screen lines and emits a change event", -> + wrapper.setMaxLength(15) - describe "when the update causes the line to no longer be wrapped", -> + range = new Range([3, 8], [3, 47]) + buffer.change(range, "a") + expect(tokensText(wrapper.tokensForScreenRow(9))).toBe ' var a [], ' + expect(tokensText(wrapper.tokensForScreenRow(10))).toBe 'right = [];' + expect(tokensText(wrapper.tokensForScreenRow(11))).toBe ' ' - describe "when the update causes a line that was wrapped twice to be only wrapped once", -> + expect(changeHandler).toHaveBeenCalled() + [event] = changeHandler.argsForCall[0] + expect(event.oldRange).toEqual [[9, 8], [11, 16]] + expect(event.newRange).toEqual [[9, 8], [9, 9]] - describe "when the update causes the line to wrap a second time", -> + describe "when the new text spans as many screen lines than the old text", -> + it "updates tokens for the corresponding screen lines and emits a change event", -> + range = new Range([3, 40], [3, 57]) + buffer.change(range, text10) + expect(tokensText(wrapper.tokensForScreenRow(3))).toBe ' var pivot = items.shift(), current, ' + expect(tokensText(wrapper.tokensForScreenRow(4))).toBe '0123456789= [];' + expect(tokensText(wrapper.tokensForScreenRow(5))).toBe ' while(items.length > 0) {' + + expect(changeHandler).toHaveBeenCalled() + [event] = changeHandler.argsForCall[0] + expect(event.oldRange).toEqual [[3, 40], [4, 6]] + expect(event.newRange).toEqual [[3, 40], [4, 10]] + + describe "when the new text spans more screen lines than the old text", -> + it "updates tokens for the corresponding screen lines and emits a change event", -> + range = new Range([3, 40], [3, 57]) + buffer.change(range, text60) + expect(tokensText(wrapper.tokensForScreenRow(3))).toBe ' var pivot = items.shift(), current, 0123456789 ' + expect(tokensText(wrapper.tokensForScreenRow(4))).toBe '123456789 123456789 123456789 123456789 123456789= ' + expect(tokensText(wrapper.tokensForScreenRow(5))).toBe '[];' + expect(tokensText(wrapper.tokensForScreenRow(6))).toBe ' while(items.length > 0) {' + + expect(changeHandler).toHaveBeenCalled() + [event] = changeHandler.argsForCall[0] + expect(event.oldRange).toEqual [[3, 40], [4, 6]] + expect(event.newRange).toEqual [[3, 40], [5, 3]] describe "when a line is inserted", -> describe "when the line is wrapped", -> diff --git a/src/atom/line-wrapper.coffee b/src/atom/line-wrapper.coffee index a56f9f540..97ec33338 100644 --- a/src/atom/line-wrapper.coffee +++ b/src/atom/line-wrapper.coffee @@ -9,15 +9,15 @@ class LineWrapper @buffer = @highlighter.buffer @buildWrappedLines() @highlighter.on 'change', (e) => + oldRange = @screenRangeFromBufferRange(e.oldRange) oldCount = @wrappedLines[e.oldRange.start.row].screenLines.length @wrappedLines[e.oldRange.start.row] = @buildWrappedLineForBufferRow(e.newRange.start.row) newCount = @wrappedLines[e.oldRange.start.row].screenLines.length - oldRange = @screenRangeFromBufferRange(e.oldRange) newRange = @screenRangeFromBufferRange(e.newRange) if newCount > oldCount - newRange.end.row += newCount - oldCount + newRange.end.row = newRange.start.row + (newCount - 1) newRange.end.column = @tokensForScreenRow(newRange.end.row).textLength @trigger 'change', { oldRange, newRange } @@ -84,11 +84,9 @@ class LineWrapper value2 = value.substring(splitIndex) [{value: value1, type }, {value: value2, type}] - - screenRangeFromBufferRange: (bufferRange) -> - start = @screenPositionFromBufferPosition(bufferRange.start) - end = @screenPositionFromBufferPosition(bufferRange.end) + start = @screenPositionFromBufferPosition(bufferRange.start, true) + end = @screenPositionFromBufferPosition(bufferRange.end, true) new Range(start,end) screenPositionFromBufferPosition: (bufferPosition, allowEOL=false) ->