From ed773585158e3aec4fc8ec4638be11aad59f3f34 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 20 Feb 2015 09:29:37 +0100 Subject: [PATCH] Show guide on soft wrapped lines with indentation * Rename phantomToken to softWrapIndent and use it consistently * Build multiple softWrapIndent tokens in order to show guides * Memoize softWrapIndentTokens and softWrapIndentDelta --- spec/display-buffer-spec.coffee | 6 +++--- src/display-buffer.coffee | 4 ++-- src/token.coffee | 6 +++--- src/tokenized-line.coffee | 37 ++++++++++++++++++++------------- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 75c256aec..14ee31176 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -116,9 +116,9 @@ describe "DisplayBuffer", -> expect(displayBuffer.tokenizedLineForScreenRow(3).tokens[1].isHardTab).toBeTruthy() describe "when a line is wrapped", -> - it "correctly tokenizes the phantom tokens", -> - expect(displayBuffer.tokenizedLineForScreenRow(4).tokens[0].isPhantom).toBeTruthy() - expect(displayBuffer.tokenizedLineForScreenRow(4).tokens[0].hasLeadingWhitespace()).toBeFalsy() + it "correctly tokenizes soft wrap indent tokens", -> + expect(displayBuffer.tokenizedLineForScreenRow(4).tokens[0].isSoftWrapIndent).toBeTruthy() + expect(displayBuffer.tokenizedLineForScreenRow(4).tokens[1].isSoftWrapIndent).toBeTruthy() describe "when the buffer changes", -> describe "when buffer lines are updated", -> diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index f5b6145a0..1b4db0f71 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -844,7 +844,7 @@ class DisplayBuffer extends Model column = @screenLines[row].clipScreenColumn(0) else column = screenLine.clipScreenColumn(maxScreenColumn - 1) - else if screenLine.isColumnInsidePhantomToken(column) + else if screenLine.isColumnInsideSoftWrapIndentation(column) if wrapAtSoftNewlines column = screenLine.clipScreenColumn(0) else @@ -1144,7 +1144,7 @@ class DisplayBuffer extends Model if @isSoftWrapped() while wrapScreenColumn = tokenizedLine.findWrapColumn(@getSoftWrapColumn()) [wrappedLine, tokenizedLine] = tokenizedLine.softWrapAt(wrapScreenColumn) - break if wrappedLine.hasOnlyPhantomTokens() + break if wrappedLine.hasOnlySoftWrapIndentation() screenLines.push(wrappedLine) softWraps++ screenLines.push(tokenizedLine) diff --git a/src/token.coffee b/src/token.coffee index 4f17bb658..a088acac7 100644 --- a/src/token.coffee +++ b/src/token.coffee @@ -21,7 +21,7 @@ class Token firstTrailingWhitespaceIndex: null hasInvisibleCharacters: false - constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @isHardTab, @hasPairedCharacter, @isPhantom}) -> + constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @isHardTab, @hasPairedCharacter, @isSoftWrapIndent}) -> @screenDelta = @value.length @bufferDelta ?= @screenDelta @hasPairedCharacter ?= textUtils.hasPairedCharacter(@value) @@ -150,7 +150,7 @@ class Token scopes: @scopes, bufferDelta: 0, isAtomic: true, - isPhantom: true + isSoftWrapIndent: true ) isOnlyWhitespace: -> @@ -229,7 +229,7 @@ class Token else match hasLeadingWhitespace: -> - !@isPhantom and @firstNonWhitespaceIndex? and @firstNonWhitespaceIndex > 0 + @firstNonWhitespaceIndex? and @firstNonWhitespaceIndex > 0 hasTrailingWhitespace: -> @firstTrailingWhitespaceIndex? and @firstTrailingWhitespaceIndex < @value.length diff --git a/src/tokenized-line.coffee b/src/tokenized-line.coffee index 932b15cd1..d9a45241e 100644 --- a/src/tokenized-line.coffee +++ b/src/tokenized-line.coffee @@ -17,6 +17,8 @@ class TokenizedLine @tokens = @breakOutAtomicTokens(tokens) @text = @buildText() @bufferDelta = @buildBufferDelta() + @softWrapIndentTokens = @getSoftWrapIndentTokens() + @softWrapIndentDelta = @buildSoftWrapIndentDelta() @id = idCounter++ @markLeadingAndTrailingWhitespaceTokens() @@ -48,8 +50,8 @@ class TokenizedLine break if tokenStartColumn + token.screenDelta > column tokenStartColumn += token.screenDelta - if token.isPhantom and tokenStartColumn <= column - tokenStartColumn + token.screenDelta + if @isColumnInsideSoftWrapIndentation(tokenStartColumn) + @softWrapIndentDelta else if token.isAtomic and tokenStartColumn < column if skipAtomicTokens tokenStartColumn + token.screenDelta @@ -103,7 +105,7 @@ class TokenizedLine return @text.length else # search backward for the start of the word on the boundary - for column in [maxColumn..0] when @isColumnOutsidePhantomToken(column) + for column in [maxColumn..0] when @isColumnOutsideSoftWrapIndentation(column) return column + 1 if /\s/.test(@text[column]) return maxColumn @@ -121,7 +123,8 @@ class TokenizedLine leftTextLength += nextToken.value.length leftTokens.push nextToken - indentToken = leftTokens[0].buildSoftWrapIndentToken(@indentLevel * @tabLength) + indentTokens = [0...@indentLevel].map => + leftTokens[0].buildSoftWrapIndentToken(@tabLength) leftFragment = new TokenizedLine( tokens: leftTokens @@ -133,7 +136,7 @@ class TokenizedLine tabLength: @tabLength ) rightFragment = new TokenizedLine( - tokens: [indentToken].concat(rightTokens) + tokens: indentTokens.concat(rightTokens) startBufferColumn: @bufferColumnForScreenColumn(column) ruleStack: @ruleStack invisibles: @invisibles @@ -146,18 +149,24 @@ class TokenizedLine isSoftWrapped: -> @lineEnding is null - isColumnOutsidePhantomToken: (column) -> - return true unless @tokens[0].isPhantom + isColumnOutsideSoftWrapIndentation: (column) -> + return true if @softWrapIndentTokens.length == 0 - column > @tokens[0].screenDelta + column > @softWrapIndentDelta - isColumnInsidePhantomToken: (column) -> - return false unless @tokens[0].isPhantom + isColumnInsideSoftWrapIndentation: (column) -> + return false if @softWrapIndentTokens.length == 0 - column < @tokens[0].screenDelta + column < @softWrapIndentDelta - hasOnlyPhantomTokens: -> - @tokens.length == 1 && @tokens[0].isPhantom + getSoftWrapIndentTokens: -> + _.select(@tokens, (token) -> token.isSoftWrapIndent) + + buildSoftWrapIndentDelta: -> + _.reduce @softWrapIndentTokens, ((acc, token) -> acc + token.screenDelta), 0 + + hasOnlySoftWrapIndentation: -> + @tokens.length == @softWrapIndentTokens.length tokenAtBufferColumn: (bufferColumn) -> @tokens[@tokenIndexAtBufferColumn(bufferColumn)] @@ -213,7 +222,7 @@ class TokenizedLine changedText = true else if invisibles.space - if token.hasLeadingWhitespace() + if token.hasLeadingWhitespace() and not token.isSoftWrapIndent token.value = token.value.replace LeadingWhitespaceRegex, (leadingWhitespace) -> leadingWhitespace.replace RepeatedSpaceRegex, invisibles.space token.hasInvisibleCharacters = true