From 3df3f474830db247f2142e52e7bba480f91c7de0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 17 Feb 2012 18:07:51 -0700 Subject: [PATCH] WIP: LineWrapper maintains a LineMap in parallel w/ SpanIndex. Planning to convert method at a time to use the LineMap instead of the SpanIndex. --- spec/atom/line-wrapper-spec.coffee | 11 ++++++++--- src/atom/line-wrapper.coffee | 28 +++++++++++++++++++++------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/spec/atom/line-wrapper-spec.coffee b/spec/atom/line-wrapper-spec.coffee index e5de73434..7f8e52300 100644 --- a/spec/atom/line-wrapper-spec.coffee +++ b/spec/atom/line-wrapper-spec.coffee @@ -2,7 +2,7 @@ Buffer = require 'buffer' LineWrapper = require 'line-wrapper' Highlighter = require 'highlighter' Range = require 'range' -ScreenLine = require 'screen-line' +ScreenLineFragment = require 'screen-line-fragment' _ = require 'underscore' describe "LineWrapper", -> @@ -142,7 +142,7 @@ describe "LineWrapper", -> makeScreenLine = (tokenValues...) -> tokens = makeTokens(tokenValues...) text = tokenValues.join('') - new ScreenLine(tokens, text) + new ScreenLineFragment(tokens, text, [1, 0], [1, 0]) beforeEach -> wrapper.setMaxLength(10) @@ -157,12 +157,17 @@ describe "LineWrapper", -> expect(line1.startColumn).toBe 0 expect(line1.endColumn).toBe 6 expect(line1.text.length).toBe 6 + expect(line1.screenDelta).toEqual [1, 0] + expect(line1.bufferDelta).toEqual [1, 0] describe "when the buffer line is empty", -> it "returns a single empty screen line", -> screenLines = wrapper.wrapScreenLine(makeScreenLine()) expect(screenLines.length).toBe 1 - expect(screenLines[0].tokens).toEqual [] + [screenLine] = screenLines + expect(screenLine.tokens).toEqual [] + expect(screenLine.screenDelta).toEqual [1, 0] + expect(screenLine.bufferDelta).toEqual [1, 0] describe "when there is a non-whitespace character at the max-length boundary", -> describe "when there is whitespace before the max-length boundary", -> diff --git a/src/atom/line-wrapper.coffee b/src/atom/line-wrapper.coffee index 176d42fee..fd8401cc9 100644 --- a/src/atom/line-wrapper.coffee +++ b/src/atom/line-wrapper.coffee @@ -1,6 +1,7 @@ _ = require 'underscore' EventEmitter = require 'event-emitter' SpanIndex = require 'span-index' +LineMap = require 'line-map' Point = require 'point' Range = require 'range' @@ -24,10 +25,15 @@ class LineWrapper getSpans: (wrappedLines) -> wrappedLines.map (line) -> line.screenLines.length + unpackWrappedLines: (wrappedLines) -> + _.flatten(_.pluck(wrappedLines, 'screenLines')) + buildWrappedLines: -> @index = new SpanIndex + @lineMap = new LineMap wrappedLines = @buildWrappedLinesForBufferRows(0, @buffer.lastRow()) @index.insert 0, @getSpans(wrappedLines), wrappedLines + @lineMap.insertAtBufferRow 0, @unpackWrappedLines(wrappedLines) handleChange: (e) -> oldRange = new Range @@ -40,6 +46,7 @@ class LineWrapper { start, end } = e.oldRange wrappedLines = @buildWrappedLinesForBufferRows(e.newRange.start.row, e.newRange.end.row) @index.splice start.row, end.row, @getSpans(wrappedLines), wrappedLines + @lineMap.replaceBufferRows start.row, end.row, @unpackWrappedLines(wrappedLines) newRange = oldRange.copy() newRange.end.row = @lastScreenRowForBufferRow(e.newRange.end.row) @@ -59,16 +66,23 @@ class LineWrapper @buildWrappedLineForBufferRow(row) buildWrappedLineForBufferRow: (bufferRow) -> - { screenLines: @wrapScreenLine(@highlighter.screenLineForRow(bufferRow)) } + { screenLines: @wrapScreenLine(@highlighter.lineFragmentForRow(bufferRow)) } wrapScreenLine: (screenLine, startColumn=0) -> - [leftHalf, rightHalf] = screenLine.splitAt(@findSplitColumn(screenLine.text)) - endColumn = startColumn + leftHalf.text.length - _.extend(leftHalf, {startColumn, endColumn}) - if rightHalf - [leftHalf].concat @wrapScreenLine(rightHalf, endColumn) + screenLines = [] + splitColumn = @findSplitColumn(screenLine.text) + + if splitColumn == 0 or splitColumn == screenLine.text.length + screenLines.push screenLine + endColumn = startColumn + screenLine.text.length else - [leftHalf] + [leftHalf, rightHalf] = screenLine.splitAt(splitColumn) + screenLines.push leftHalf + endColumn = startColumn + leftHalf.text.length + screenLines.push @wrapScreenLine(rightHalf, endColumn)... + + _.extend(screenLines[0], {startColumn, endColumn}) + screenLines findSplitColumn: (line) -> return line.length unless line.length > @maxLength