Merge pull request #6010 from atom/as-soft-wrap-hanging-indent

Soft wrap hanging indentation spaces
This commit is contained in:
Nathan Sobo
2015-03-18 11:39:27 -06:00
4 changed files with 60 additions and 22 deletions

View File

@@ -124,9 +124,42 @@ describe "DisplayBuffer", ->
expect(displayBuffer.tokenizedLineForScreenRow(3).tokens[1].isHardTab).toBeTruthy()
describe "when a line is wrapped", ->
it "correctly tokenizes soft wrap indentation tokens", ->
expect(displayBuffer.tokenizedLineForScreenRow(4).tokens[0].isSoftWrapIndentation).toBeTruthy()
expect(displayBuffer.tokenizedLineForScreenRow(4).tokens[1].isSoftWrapIndentation).toBeTruthy()
it "breaks soft-wrap indentation into a token for each indentation level to support indent guides", ->
tokenizedLine = displayBuffer.tokenizedLineForScreenRow(4)
expect(tokenizedLine.tokens[0].value).toBe(" ")
expect(tokenizedLine.tokens[0].isSoftWrapIndentation).toBeTruthy()
expect(tokenizedLine.tokens[1].value).toBe(" ")
expect(tokenizedLine.tokens[1].isSoftWrapIndentation).toBeTruthy()
expect(tokenizedLine.tokens[2].isSoftWrapIndentation).toBeFalsy()
describe "when editor.softWrapHangingIndent is set", ->
beforeEach ->
atom.config.set('editor.softWrapHangingIndent', 3)
it "further indents wrapped lines", ->
expect(displayBuffer.tokenizedLineForScreenRow(10).text).toBe " return "
expect(displayBuffer.tokenizedLineForScreenRow(11).text).toBe " sort(left).concat(pivot).concat(sort(right)"
expect(displayBuffer.tokenizedLineForScreenRow(12).text).toBe " );"
it "includes hanging indent when breaking soft-wrap indentation into tokens", ->
tokenizedLine = displayBuffer.tokenizedLineForScreenRow(4)
expect(tokenizedLine.tokens[0].value).toBe(" ")
expect(tokenizedLine.tokens[0].isSoftWrapIndentation).toBeTruthy()
expect(tokenizedLine.tokens[1].value).toBe(" ")
expect(tokenizedLine.tokens[1].isSoftWrapIndentation).toBeTruthy()
expect(tokenizedLine.tokens[2].value).toBe(" ") # hanging indent
expect(tokenizedLine.tokens[2].isSoftWrapIndentation).toBeTruthy()
expect(tokenizedLine.tokens[3].value).toBe(" ") # odd space
expect(tokenizedLine.tokens[3].isSoftWrapIndentation).toBeTruthy()
expect(tokenizedLine.tokens[4].isSoftWrapIndentation).toBeFalsy()
describe "when the buffer changes", ->
describe "when buffer lines are updated", ->

View File

@@ -149,6 +149,10 @@ module.exports =
softWrapAtPreferredLineLength:
type: 'boolean'
default: false
softWrapHangingIndent:
type: 'integer'
default: 0
minimum: 0
scrollSensitivity:
type: 'integer'
default: 40

View File

@@ -69,12 +69,17 @@ class DisplayBuffer extends Model
scrollPastEnd: atom.config.get('editor.scrollPastEnd', scope: scopeDescriptor)
softWrap: atom.config.get('editor.softWrap', scope: scopeDescriptor)
softWrapAtPreferredLineLength: atom.config.get('editor.softWrapAtPreferredLineLength', scope: scopeDescriptor)
softWrapHangingIndent: atom.config.get('editor.softWrapHangingIndent', scope: scopeDescriptor)
preferredLineLength: atom.config.get('editor.preferredLineLength', scope: scopeDescriptor)
subscriptions.add atom.config.onDidChange 'editor.softWrap', scope: scopeDescriptor, ({newValue}) =>
@configSettings.softWrap = newValue
@updateWrappedScreenLines()
subscriptions.add atom.config.onDidChange 'editor.softWrapHangingIndent', scope: scopeDescriptor, ({newValue}) =>
@configSettings.softWrapHangingIndent = newValue
@updateWrappedScreenLines()
subscriptions.add atom.config.onDidChange 'editor.softWrapAtPreferredLineLength', scope: scopeDescriptor, ({newValue}) =>
@configSettings.softWrapAtPreferredLineLength = newValue
@updateWrappedScreenLines() if @isSoftWrapped()
@@ -1157,7 +1162,10 @@ class DisplayBuffer extends Model
softWraps = 0
if @isSoftWrapped()
while wrapScreenColumn = tokenizedLine.findWrapColumn(@getSoftWrapColumn())
[wrappedLine, tokenizedLine] = tokenizedLine.softWrapAt(wrapScreenColumn)
[wrappedLine, tokenizedLine] = tokenizedLine.softWrapAt(
wrapScreenColumn,
@configSettings.softWrapHangingIndent
)
break if wrappedLine.hasOnlySoftWrapIndentation()
screenLines.push(wrappedLine)
softWraps++

View File

@@ -111,25 +111,18 @@ class TokenizedLine
return maxColumn
# Calculates how many trailing spaces in this line's indentation cannot fit in a single tab.
#
# Returns a {Number} representing the odd indentation spaces in this line.
getOddIndentationSpaces: ->
oddIndentLevel = @indentLevel - Math.floor(@indentLevel)
Math.round(@tabLength * oddIndentLevel)
buildSoftWrapIndentationTokens: (token, hangingIndent) ->
totalIndentSpaces = (@indentLevel * @tabLength) + hangingIndent
indentTokens = []
while totalIndentSpaces > 0
tokenLength = Math.min(@tabLength, totalIndentSpaces)
indentToken = token.buildSoftWrapIndentationToken(tokenLength)
indentTokens.push(indentToken)
totalIndentSpaces -= tokenLength
buildSoftWrapIndentationTokens: (token) ->
indentTokens = [0...Math.floor(@indentLevel)].map =>
token.buildSoftWrapIndentationToken(@tabLength)
indentTokens
if @getOddIndentationSpaces()
indentTokens.concat(
token.buildSoftWrapIndentationToken @getOddIndentationSpaces()
)
else
indentTokens
softWrapAt: (column) ->
softWrapAt: (column, hangingIndent) ->
return [new TokenizedLine([], '', [0, 0], [0, 0]), this] if column == 0
rightTokens = new Array(@tokens...)
@@ -142,7 +135,7 @@ class TokenizedLine
leftTextLength += nextToken.value.length
leftTokens.push nextToken
indentationTokens = @buildSoftWrapIndentationTokens(leftTokens[0])
indentationTokens = @buildSoftWrapIndentationTokens(leftTokens[0], hangingIndent)
leftFragment = new TokenizedLine(
tokens: leftTokens