Add indentBasis option to insertText

We will use this to normalize indentation on paste even when we didn't copy all the leading whitespace on the first line.
This commit is contained in:
Corey Johnson & Nathan Sobo
2012-10-24 18:29:09 -06:00
parent 9fc439b30d
commit 6f353fda62
2 changed files with 90 additions and 43 deletions

View File

@@ -723,55 +723,102 @@ describe "EditSession", ->
" bar();"
].join('\n')
removeLeadingWhitespace = (text) -> text.replace(/^\s*/, '')
describe "when the cursor is preceded only by whitespace", ->
describe "when auto-indent is enabled", ->
beforeEach ->
editSession.setAutoIndent(true)
describe "when the cursor's current column is less than the suggested indent level", ->
it "indents all lines relative to the suggested indent", ->
editSession.insertText('\n xx')
editSession.setCursorBufferPosition([3, 1])
editSession.insertText(text, normalizeIndent: true)
describe "when the indentBasis is inferred from the first line", ->
it "indents all lines relative to the suggested indent", ->
editSession.insertText('\n xx')
editSession.setCursorBufferPosition([3, 1])
editSession.insertText(text, normalizeIndent: true)
expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
expect(editSession.lineForBufferRow(4)).toBe " foo();"
expect(editSession.lineForBufferRow(5)).toBe " }"
expect(editSession.lineForBufferRow(6)).toBe " bar();xx"
expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
expect(editSession.lineForBufferRow(4)).toBe " foo();"
expect(editSession.lineForBufferRow(5)).toBe " }"
expect(editSession.lineForBufferRow(6)).toBe " bar();xx"
describe "when an indentBasis is provided", ->
it "indents all lines relative to the suggested indent", ->
editSession.insertText('\n xx')
editSession.setCursorBufferPosition([3, 1])
editSession.insertText(removeLeadingWhitespace(text), normalizeIndent: true, indentBasis: 4)
expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
expect(editSession.lineForBufferRow(4)).toBe " foo();"
expect(editSession.lineForBufferRow(5)).toBe " }"
expect(editSession.lineForBufferRow(6)).toBe " bar();xx"
describe "when the cursor's current column is greater than the suggested indent level", ->
it "preserves the current indent level, indenting all lines relative to it", ->
editSession.insertText('\n ')
editSession.insertText(text, normalizeIndent: true)
describe "when the indentBasis is inferred from the first line", ->
it "preserves the current indent level, indenting all lines relative to it", ->
editSession.insertText('\n ')
editSession.insertText(text, normalizeIndent: true)
expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
expect(editSession.lineForBufferRow(4)).toBe " foo();"
expect(editSession.lineForBufferRow(5)).toBe " }"
expect(editSession.lineForBufferRow(6)).toBe " bar();"
expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
expect(editSession.lineForBufferRow(4)).toBe " foo();"
expect(editSession.lineForBufferRow(5)).toBe " }"
expect(editSession.lineForBufferRow(6)).toBe " bar();"
describe "when an indentBasis is provided", ->
it "preserves the current indent level, indenting all lines relative to it", ->
editSession.insertText('\n ')
editSession.insertText(removeLeadingWhitespace(text), normalizeIndent: true, indentBasis: 4)
expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
expect(editSession.lineForBufferRow(4)).toBe " foo();"
expect(editSession.lineForBufferRow(5)).toBe " }"
expect(editSession.lineForBufferRow(6)).toBe " bar();"
describe "if auto-indent is disabled", ->
beforeEach ->
expect(editSession.autoIndent).toBeFalsy()
it "always normalizes indented lines to the cursor's current indentation level", ->
editSession.insertText('\n ')
editSession.insertText(text, normalizeIndent: true)
describe "when the indentBasis is inferred from the first line", ->
it "always normalizes indented lines to the cursor's current indentation level", ->
editSession.insertText('\n ')
editSession.insertText(text, normalizeIndent: true)
expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
expect(editSession.lineForBufferRow(4)).toBe " foo();"
expect(editSession.lineForBufferRow(5)).toBe " }"
expect(editSession.lineForBufferRow(6)).toBe "bar();"
expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
expect(editSession.lineForBufferRow(4)).toBe " foo();"
expect(editSession.lineForBufferRow(5)).toBe " }"
expect(editSession.lineForBufferRow(6)).toBe "bar();"
describe "when an indentBasis is provided", ->
it "always normalizes indented lines to the cursor's current indentation level", ->
editSession.insertText('\n ')
editSession.insertText(removeLeadingWhitespace(text), normalizeIndent: true, indentBasis: 4)
expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
expect(editSession.lineForBufferRow(4)).toBe " foo();"
expect(editSession.lineForBufferRow(5)).toBe " }"
describe "when the cursor is preceded by non-whitespace characters", ->
it "normalizes the indentation level of all lines based on the level of the existing first line", ->
editSession.setAutoIndent(true)
editSession.buffer.delete([[2, 0], [2, 2]])
editSession.insertText(text, normalizeIndent:true)
describe "when the indentBasis is inferred from the first line", ->
it "normalizes the indentation level of all lines based on the level of the existing first line", ->
editSession.setAutoIndent(true)
editSession.buffer.delete([[2, 0], [2, 2]])
editSession.insertText(text, normalizeIndent:true)
expect(editSession.lineForBufferRow(2)).toBe " if (items.length <= 1) return items;while (true) {"
expect(editSession.lineForBufferRow(3)).toBe " foo();"
expect(editSession.lineForBufferRow(4)).toBe " }"
expect(editSession.lineForBufferRow(5)).toBe "bar();"
expect(editSession.lineForBufferRow(2)).toBe " if (items.length <= 1) return items;while (true) {"
expect(editSession.lineForBufferRow(3)).toBe " foo();"
expect(editSession.lineForBufferRow(4)).toBe " }"
expect(editSession.lineForBufferRow(5)).toBe "bar();"
describe "when an indentBasis is provided", ->
it "normalizes the indentation level of all lines based on the level of the existing first line", ->
editSession.setAutoIndent(true)
editSession.buffer.delete([[2, 0], [2, 2]])
editSession.insertText(removeLeadingWhitespace(text), normalizeIndent:true, indentBasis: 4)
expect(editSession.lineForBufferRow(2)).toBe " if (items.length <= 1) return items;while (true) {"
expect(editSession.lineForBufferRow(3)).toBe " foo();"
expect(editSession.lineForBufferRow(4)).toBe " }"
expect(editSession.lineForBufferRow(5)).toBe "bar();"
describe ".insertNewline()", ->
describe "when there is a single cursor", ->

View File

@@ -137,7 +137,7 @@ class Selection
oldBufferRange = @getBufferRange()
@editSession.destroyFoldsContainingBufferRow(oldBufferRange.end.row)
wasReversed = @isReversed()
text = @normalizeIndent(text) if options.normalizeIndent
text = @normalizeIndent(text, options) if options.normalizeIndent
@clear()
newBufferRange = @editSession.buffer.change(oldBufferRange, text)
@cursor.setBufferPosition(newBufferRange.end, skipAtomicTokens: true) if wasReversed
@@ -148,37 +148,37 @@ class Selection
else
@editSession.autoDecreaseIndentForRow(newBufferRange.start.row)
normalizeIndent: (text) ->
normalizeIndent: (text, options) ->
return text unless /\n/.test(text)
currentBufferRow = @cursor.getBufferRow()
currentBufferColumn = @cursor.getBufferColumn()
lines = text.split('\n')
currentBasis = options.indentBasis ? lines[0].match(/\s*/)[0].length
lines[0] = lines[0].replace(/^\s*/, '') # strip leading space from first line
normalizedLines = []
textPrecedingCursor = @editSession.buffer.getTextInRange([[currentBufferRow, 0], [currentBufferRow, currentBufferColumn]])
insideExistingLine = textPrecedingCursor.match(/\S/)
if insideExistingLine
desiredBase = @editSession.indentationForBufferRow(currentBufferRow)
desiredBasis = @editSession.indentationForBufferRow(currentBufferRow)
else if @editSession.autoIndent
desiredBase = @editSession.suggestedIndentForBufferRow(currentBufferRow)
desiredBasis = @editSession.suggestedIndentForBufferRow(currentBufferRow)
else
desiredBase = currentBufferColumn
currentBase = lines[0].match(/\s*/)[0].length
delta = desiredBase - currentBase
desiredBasis = currentBufferColumn
for line, i in lines
if i == 0
if insideExistingLine
firstLineDelta = -line.length # remove all leading whitespace
delta = 0
else
firstLineDelta = delta - currentBufferColumn
normalizedLines.push(@adjustIndentationForLine(line, firstLineDelta))
delta = desiredBasis - currentBufferColumn
else
normalizedLines.push(@adjustIndentationForLine(line, delta))
delta = desiredBasis - currentBasis
normalizedLines.push(@adjustIndentationForLine(line, delta))
normalizedLines.join('\n')