mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
Normalize pasted text when there is an indent basis
This commit is contained in:
@@ -1011,145 +1011,6 @@ describe "EditSession", ->
|
||||
editSession.insertText('holy cow')
|
||||
expect(editSession.lineForScreenRow(2).fold).toBeUndefined()
|
||||
|
||||
xdescribe "when the `normalizeIndent` option is true", ->
|
||||
describe "when the inserted text contains no newlines", ->
|
||||
it "does not adjust the indentation level of the text", ->
|
||||
editSession.setCursorBufferPosition([5, 2])
|
||||
editSession.insertText("foo", normalizeIndent: true)
|
||||
expect(editSession.lineForBufferRow(5)).toBe " foo current = items.shift();"
|
||||
|
||||
describe "when the inserted text contains newlines", ->
|
||||
text = null
|
||||
beforeEach ->
|
||||
editSession.setCursorBufferPosition([2, Infinity])
|
||||
text = [
|
||||
" while (true) {"
|
||||
" foo();"
|
||||
" }"
|
||||
" bar();"
|
||||
].join('\n')
|
||||
|
||||
removeLeadingWhitespace = (text) -> text.replace(/^\s*/, '')
|
||||
|
||||
describe "when the cursor is preceded only by whitespace", ->
|
||||
describe "when auto-indent is enabled", ->
|
||||
describe "when the cursor's current column is less than the suggested indent level", ->
|
||||
describe "when the indentBasis is inferred from the first line", ->
|
||||
it "indents all lines relative to the suggested indent", ->
|
||||
editSession.insertText('\n xx', autoIndent: true)
|
||||
editSession.setCursorBufferPosition([3, 1])
|
||||
editSession.insertText(text, normalizeIndent: true, autoIndent: 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"
|
||||
|
||||
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: 2, autoIndent: 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"
|
||||
|
||||
describe "when inserting on a line that has mixed tabs and whitespace in hard tabs mode (regression)", ->
|
||||
it "correctly indents the inserted text", ->
|
||||
editSession.softTabs = false
|
||||
buffer.setText """
|
||||
not indented
|
||||
\tmixed indented
|
||||
"""
|
||||
|
||||
editSession.setCursorBufferPosition([1, 0])
|
||||
editSession.insertText(text, normalizeIndent: true, autoIndent: true)
|
||||
|
||||
expect(editSession.lineForBufferRow(1)).toBe "\t\t\twhile (true) {"
|
||||
expect(editSession.lineForBufferRow(2)).toBe "\t\t\t\tfoo();"
|
||||
expect(editSession.lineForBufferRow(3)).toBe "\t\t\t}"
|
||||
expect(editSession.lineForBufferRow(4)).toBe "\t\tbar(); \tmixed indented"
|
||||
|
||||
describe "when inserting on a fractionally-indented line in hard tabs mode (regression)", ->
|
||||
it "correctly indents the inserted text", ->
|
||||
editSession.softTabs = false
|
||||
buffer.setText """
|
||||
not indented
|
||||
fractional indentation
|
||||
"""
|
||||
|
||||
editSession.setCursorBufferPosition([1, 0])
|
||||
editSession.insertText(text, normalizeIndent: true, autoIndent: true)
|
||||
|
||||
expect(editSession.lineForBufferRow(1)).toBe "\t\twhile (true) {"
|
||||
expect(editSession.lineForBufferRow(2)).toBe "\t\t\tfoo();"
|
||||
expect(editSession.lineForBufferRow(3)).toBe "\t\t}"
|
||||
expect(editSession.lineForBufferRow(4)).toBe "\tbar(); fractional indentation"
|
||||
|
||||
describe "when the cursor's current column is greater than the suggested indent level", ->
|
||||
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();"
|
||||
|
||||
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: 2)
|
||||
|
||||
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", ->
|
||||
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();"
|
||||
|
||||
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: 2)
|
||||
|
||||
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", ->
|
||||
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.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();"
|
||||
|
||||
describe "when an indentBasis is provided", ->
|
||||
it "normalizes the indentation level of all lines based on the level of the existing first line", ->
|
||||
editSession.buffer.delete([[2, 0], [2, 2]])
|
||||
editSession.insertText(removeLeadingWhitespace(text), normalizeIndent:true, indentBasis: 2)
|
||||
|
||||
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", ->
|
||||
describe "when the cursor is at the beginning of a line", ->
|
||||
@@ -2332,11 +2193,13 @@ describe "EditSession", ->
|
||||
expect(editSession.lineForScreenRow(0).tokens.length).toBeGreaterThan 1
|
||||
|
||||
describe "auto-indent", ->
|
||||
copyText = (text) ->
|
||||
copyText = (text, {startColumn}={}) ->
|
||||
startColumn ?= 0
|
||||
editSession.setCursorBufferPosition([0, 0])
|
||||
editSession.insertText(text)
|
||||
numberOfNewlines = text.match(/\n/g)?.length
|
||||
editSession.getSelection().setBufferRange([[0,0], [numberOfNewlines,0]])
|
||||
endColumn = text.match(/[^\n]*$/)[0]?.length
|
||||
editSession.getSelection().setBufferRange([[0,startColumn], [numberOfNewlines,endColumn]])
|
||||
editSession.cutSelectedText()
|
||||
|
||||
describe "editor.autoIndent", ->
|
||||
@@ -2393,7 +2256,7 @@ describe "EditSession", ->
|
||||
editSession.setCursorBufferPosition([1, Infinity])
|
||||
editSession.insertText('\n ')
|
||||
expect(editSession.indentationForBufferRow(2)).toBe editSession.indentationForBufferRow(1) + 1
|
||||
editSession.insertText('}', autoDecreaseIndent: true)
|
||||
editSession.insertText('}')
|
||||
expect(editSession.indentationForBufferRow(2)).toBe editSession.indentationForBufferRow(1)
|
||||
|
||||
describe "when the preceding line doesn't match an increase indent pattern", ->
|
||||
@@ -2401,12 +2264,12 @@ describe "EditSession", ->
|
||||
editSession.setCursorBufferPosition([3, Infinity])
|
||||
editSession.insertText('\n ')
|
||||
expect(editSession.indentationForBufferRow(4)).toBe editSession.indentationForBufferRow(3)
|
||||
editSession.insertText('}', autoDecreaseIndent: true)
|
||||
editSession.insertText('}')
|
||||
expect(editSession.indentationForBufferRow(4)).toBe editSession.indentationForBufferRow(3) - 1
|
||||
|
||||
it "doesn't break when decreasing the indentation on a row that has no indentation", ->
|
||||
editSession.setCursorBufferPosition([12, Infinity])
|
||||
editSession.insertText("\n}; # too many closing brackets!", autoDecreaseIndent: true)
|
||||
editSession.insertText("\n}; # too many closing brackets!")
|
||||
expect(editSession.lineForBufferRow(13)).toBe "}; # too many closing brackets!"
|
||||
|
||||
describe "when inserted text does not match a decrease indent pattern", ->
|
||||
@@ -2414,14 +2277,14 @@ describe "EditSession", ->
|
||||
editSession.setCursorBufferPosition([12, 0])
|
||||
editSession.insertText(' ')
|
||||
expect(editSession.lineForBufferRow(12)).toBe ' };'
|
||||
editSession.insertText('\t\t', autoDecreaseIndent: true)
|
||||
editSession.insertText('\t\t')
|
||||
expect(editSession.lineForBufferRow(12)).toBe ' \t\t};'
|
||||
|
||||
describe "when the current line does not match a decrease indent pattern", ->
|
||||
it "leaves the line unchanged", ->
|
||||
editSession.setCursorBufferPosition([2, 4])
|
||||
expect(editSession.indentationForBufferRow(2)).toBe editSession.indentationForBufferRow(1) + 1
|
||||
editSession.insertText('foo', autoIndent: true)
|
||||
editSession.insertText('foo')
|
||||
expect(editSession.indentationForBufferRow(2)).toBe editSession.indentationForBufferRow(1) + 1
|
||||
|
||||
describe "editor.autoIndentOnPaste", ->
|
||||
@@ -2460,6 +2323,57 @@ describe "EditSession", ->
|
||||
editSession.pasteText()
|
||||
expect(editSession.lineForBufferRow(10)).toBe " var number"
|
||||
|
||||
describe "editor.normalizePastedText", ->
|
||||
describe "when the inserted text contains no newlines", ->
|
||||
it "does not adjust the indentation level of the text", ->
|
||||
editSession.setCursorBufferPosition([5, 2])
|
||||
editSession.insertText("foo", indentBasis: 5)
|
||||
expect(editSession.lineForBufferRow(5)).toBe " foo current = items.shift();"
|
||||
|
||||
describe "when the inserted text contains newlines", ->
|
||||
it "does not normalize the indentation level of the text when editor.autoIndentOnPaste is true", ->
|
||||
copyText(" function() {\nvar cool = 1;\n }\n")
|
||||
config.set('editor.autoIndentOnPaste', true)
|
||||
editSession.setCursorBufferPosition([5, 2])
|
||||
editSession.pasteText()
|
||||
expect(editSession.lineForBufferRow(5)).toBe " function() {"
|
||||
expect(editSession.lineForBufferRow(6)).toBe " var cool = 1;"
|
||||
expect(editSession.lineForBufferRow(7)).toBe " }"
|
||||
|
||||
describe "when copied text includes whitespace on first line", ->
|
||||
describe "when cursor is preceded whitespace and followed non-whitespace", ->
|
||||
it "normalizes indented lines to the cursor's current indentation level", ->
|
||||
copyText(" while (true) {\n foo();\n }\n", {startColumn: 4})
|
||||
editSession.setCursorBufferPosition([3, 4])
|
||||
editSession.pasteText()
|
||||
|
||||
expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
|
||||
expect(editSession.lineForBufferRow(4)).toBe " foo();"
|
||||
expect(editSession.lineForBufferRow(5)).toBe " }"
|
||||
expect(editSession.lineForBufferRow(6)).toBe "var pivot = items.shift(), current, left = [], right = [];"
|
||||
|
||||
describe "when cursor is preceded whitespace and followed by whitespace", ->
|
||||
it "normalizes indented lines to the cursor's current indentation level", ->
|
||||
copyText(" while (true) {\n foo();\n }\n", {startColumn: 0})
|
||||
editSession.setCursorBufferPosition([3, 4])
|
||||
editSession.pasteText()
|
||||
|
||||
expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
|
||||
expect(editSession.lineForBufferRow(4)).toBe " foo();"
|
||||
expect(editSession.lineForBufferRow(5)).toBe " }"
|
||||
expect(editSession.lineForBufferRow(6)).toBe "var pivot = items.shift(), current, left = [], right = [];"
|
||||
|
||||
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", ->
|
||||
copyText(" while (true) {\n foo();\n }\n", {startColumn: 0})
|
||||
editSession.setCursorBufferPosition([1, Infinity])
|
||||
editSession.pasteText()
|
||||
|
||||
expect(editSession.lineForBufferRow(1)).toBe " var sort = function(items) { while (true) {"
|
||||
expect(editSession.lineForBufferRow(2)).toBe " foo();"
|
||||
expect(editSession.lineForBufferRow(3)).toBe " }"
|
||||
expect(editSession.lineForBufferRow(4)).toBe ""
|
||||
|
||||
it "autoIndentSelectedRows auto-indents the selection", ->
|
||||
editSession.setCursorBufferPosition([2, 0])
|
||||
editSession.insertText("function() {\ninside=true\n}\n i=1\n")
|
||||
|
||||
@@ -263,10 +263,12 @@ class Selection
|
||||
oldBufferRange = @getBufferRange()
|
||||
@editSession.destroyFoldsContainingBufferRow(oldBufferRange.end.row)
|
||||
wasReversed = @isReversed()
|
||||
|
||||
@clear()
|
||||
@cursor.needsAutoscroll = @cursor.isLastCursor()
|
||||
|
||||
if options.indentBasis? and not options.autoIndent
|
||||
text = @normalizeIndents(text, options.indentBasis)
|
||||
|
||||
newBufferRange = @editSession.buffer.change(oldBufferRange, text)
|
||||
if options.select
|
||||
@setBufferRange(newBufferRange, reverse: wasReversed)
|
||||
@@ -282,6 +284,32 @@ class Selection
|
||||
|
||||
newBufferRange
|
||||
|
||||
normalizeIndents: (text, indentBasis) ->
|
||||
textPrecedingCursor = @cursor.getCurrentBufferLine()[0...@cursor.getBufferColumn()]
|
||||
isCursorInsideExistingLine = /\S/.test(textPrecedingCursor)
|
||||
|
||||
lines = text.split('\n')
|
||||
firstLineIndentLevel = @editSession.indentLevelForLine(lines[0])
|
||||
if isCursorInsideExistingLine
|
||||
minimumIndentLevel = @editSession.indentationForBufferRow(@cursor.getBufferRow())
|
||||
else
|
||||
minimumIndentLevel = @cursor.getIndentLevel() + firstLineIndentLevel
|
||||
normalizedLines = []
|
||||
|
||||
for line, i in lines
|
||||
if i == 0
|
||||
indentLevel = firstLineIndentLevel
|
||||
else if /$^/.test line # remove all indentation from empty lines
|
||||
indentLevel = 0
|
||||
else
|
||||
lineIndentLevel = @editSession.indentLevelForLine(lines[i])
|
||||
indentLevel = minimumIndentLevel + (lineIndentLevel - indentBasis)
|
||||
|
||||
normalizedLines.push(@setIndentationForLine(line, indentLevel))
|
||||
|
||||
console.log normalizedLines
|
||||
normalizedLines.join('\n')
|
||||
|
||||
# Indents the selection.
|
||||
#
|
||||
# options - A hash with one key, `autoIndent`. If `true`, the indentation is
|
||||
@@ -307,9 +335,8 @@ class Selection
|
||||
for row in [start..end]
|
||||
@editSession.buffer.insert([row, 0], @editSession.getTabText()) unless @editSession.buffer.lineLengthForRow(row) == 0
|
||||
|
||||
adjustIndentationForLine: (line, delta) ->
|
||||
currentIndentLevel = @editSession.indentLevelForLine(line)
|
||||
desiredIndentLevel = Math.max(0, currentIndentLevel + delta)
|
||||
setIndentationForLine: (line, indentLevel) ->
|
||||
desiredIndentLevel = Math.max(0, indentLevel)
|
||||
desiredIndentString = @editSession.buildIndentString(desiredIndentLevel)
|
||||
line.replace(/^[\t ]*/, desiredIndentString)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user