Merge pull request #124 from github/auto-indent-config

Auto-indent config
This commit is contained in:
Corey Johnson 2013-01-10 11:02:54 -08:00
commit c3a2b99b69
7 changed files with 107 additions and 57 deletions

View File

@ -675,10 +675,7 @@ describe "EditSession", ->
editSession.insertText('holy cow') editSession.insertText('holy cow')
expect(editSession.lineForScreenRow(2).fold).toBeUndefined() expect(editSession.lineForScreenRow(2).fold).toBeUndefined()
describe "when auto-indent is enabled and the `autoIndent` option is true", -> describe "when auto-indent is enabled", ->
beforeEach ->
editSession.setAutoIndent(true)
describe "when a single newline is inserted", -> describe "when a single newline is inserted", ->
describe "when the newline is inserted on a line that starts a new level of indentation", -> describe "when the newline is inserted on a line that starts a new level of indentation", ->
it "auto-indents the new line to one additional level of indentation beyond the preceding line", -> it "auto-indents the new line to one additional level of indentation beyond the preceding line", ->
@ -739,16 +736,13 @@ describe "EditSession", ->
removeLeadingWhitespace = (text) -> text.replace(/^\s*/, '') removeLeadingWhitespace = (text) -> text.replace(/^\s*/, '')
describe "when the cursor is preceded only by whitespace", -> describe "when the cursor is preceded only by whitespace", ->
describe "when auto-indent is enabled", -> describe "when auto-indent is enabled", ->
beforeEach ->
editSession.setAutoIndent(true)
describe "when the cursor's current column is less than the suggested indent level", -> describe "when the cursor's current column is less than the suggested indent level", ->
describe "when the indentBasis is inferred from the first line", -> describe "when the indentBasis is inferred from the first line", ->
it "indents all lines relative to the suggested indent", -> it "indents all lines relative to the suggested indent", ->
editSession.insertText('\n xx') editSession.insertText('\n xx', autoIndent: true)
editSession.setCursorBufferPosition([3, 1]) editSession.setCursorBufferPosition([3, 1])
editSession.insertText(text, normalizeIndent: true) editSession.insertText(text, normalizeIndent: true, autoIndent: true)
expect(editSession.lineForBufferRow(3)).toBe " while (true) {" expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
expect(editSession.lineForBufferRow(4)).toBe " foo();" expect(editSession.lineForBufferRow(4)).toBe " foo();"
@ -759,7 +753,7 @@ describe "EditSession", ->
it "indents all lines relative to the suggested indent", -> it "indents all lines relative to the suggested indent", ->
editSession.insertText('\n xx') editSession.insertText('\n xx')
editSession.setCursorBufferPosition([3, 1]) editSession.setCursorBufferPosition([3, 1])
editSession.insertText(removeLeadingWhitespace(text), normalizeIndent: true, indentBasis: 2) editSession.insertText(removeLeadingWhitespace(text), normalizeIndent: true, indentBasis: 2, autoIndent: true)
expect(editSession.lineForBufferRow(3)).toBe " while (true) {" expect(editSession.lineForBufferRow(3)).toBe " while (true) {"
expect(editSession.lineForBufferRow(4)).toBe " foo();" expect(editSession.lineForBufferRow(4)).toBe " foo();"
@ -775,7 +769,7 @@ describe "EditSession", ->
""" """
editSession.setCursorBufferPosition([1, 0]) editSession.setCursorBufferPosition([1, 0])
editSession.insertText(text, normalizeIndent: true) editSession.insertText(text, normalizeIndent: true, autoIndent: true)
expect(editSession.lineForBufferRow(1)).toBe "\t\t\twhile (true) {" expect(editSession.lineForBufferRow(1)).toBe "\t\t\twhile (true) {"
expect(editSession.lineForBufferRow(2)).toBe "\t\t\t\tfoo();" expect(editSession.lineForBufferRow(2)).toBe "\t\t\t\tfoo();"
@ -791,7 +785,7 @@ describe "EditSession", ->
""" """
editSession.setCursorBufferPosition([1, 0]) editSession.setCursorBufferPosition([1, 0])
editSession.insertText(text, normalizeIndent: true) editSession.insertText(text, normalizeIndent: true, autoIndent: true)
expect(editSession.lineForBufferRow(1)).toBe "\t\twhile (true) {" expect(editSession.lineForBufferRow(1)).toBe "\t\twhile (true) {"
expect(editSession.lineForBufferRow(2)).toBe "\t\t\tfoo();" expect(editSession.lineForBufferRow(2)).toBe "\t\t\tfoo();"
@ -820,9 +814,6 @@ describe "EditSession", ->
expect(editSession.lineForBufferRow(6)).toBe " bar();" expect(editSession.lineForBufferRow(6)).toBe " bar();"
describe "if auto-indent is disabled", -> describe "if auto-indent is disabled", ->
beforeEach ->
expect(editSession.autoIndent).toBeFalsy()
describe "when the indentBasis is inferred from the first line", -> describe "when the indentBasis is inferred from the first line", ->
it "always normalizes indented lines to the cursor's current indentation level", -> it "always normalizes indented lines to the cursor's current indentation level", ->
editSession.insertText('\n ') editSession.insertText('\n ')
@ -845,7 +836,6 @@ describe "EditSession", ->
describe "when the cursor is preceded by non-whitespace characters", -> describe "when the cursor is preceded by non-whitespace characters", ->
describe "when the indentBasis is inferred from the first line", -> 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", -> 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.buffer.delete([[2, 0], [2, 2]])
editSession.insertText(text, normalizeIndent:true) editSession.insertText(text, normalizeIndent:true)
@ -856,7 +846,6 @@ describe "EditSession", ->
describe "when an indentBasis is provided", -> describe "when an indentBasis is provided", ->
it "normalizes the indentation level of all lines based on the level of the existing 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.buffer.delete([[2, 0], [2, 2]])
editSession.insertText(removeLeadingWhitespace(text), normalizeIndent:true, indentBasis: 2) editSession.insertText(removeLeadingWhitespace(text), normalizeIndent:true, indentBasis: 2)
@ -1311,8 +1300,7 @@ describe "EditSession", ->
it "moves the cursor to the end of the leading whitespace and inserts enough whitespace to bring the line to the suggested level of indentaion", -> it "moves the cursor to the end of the leading whitespace and inserts enough whitespace to bring the line to the suggested level of indentaion", ->
buffer.insert([5, 0], " \n") buffer.insert([5, 0], " \n")
editSession.setCursorBufferPosition [5, 0] editSession.setCursorBufferPosition [5, 0]
editSession.setAutoIndent(true) editSession.indent(autoIndent: true)
editSession.indent()
expect(buffer.lineForRow(5)).toMatch /^\s+$/ expect(buffer.lineForRow(5)).toMatch /^\s+$/
expect(buffer.lineForRow(5).length).toBe 6 expect(buffer.lineForRow(5).length).toBe 6
expect(editSession.getCursorBufferPosition()).toEqual [5, 6] expect(editSession.getCursorBufferPosition()).toEqual [5, 6]
@ -1323,8 +1311,7 @@ describe "EditSession", ->
editSession.softTabs = false editSession.softTabs = false
buffer.insert([5, 0], "\t\n") buffer.insert([5, 0], "\t\n")
editSession.setCursorBufferPosition [5, 0] editSession.setCursorBufferPosition [5, 0]
editSession.setAutoIndent(true) editSession.indent(autoIndent: true)
editSession.indent()
expect(buffer.lineForRow(5)).toMatch /^\t\t\t$/ expect(buffer.lineForRow(5)).toMatch /^\t\t\t$/
expect(editSession.getCursorBufferPosition()).toEqual [5, 3] expect(editSession.getCursorBufferPosition()).toEqual [5, 3]
@ -1333,8 +1320,7 @@ describe "EditSession", ->
it "moves the cursor to the end of the leading whitespace and inserts 'tabLength' spaces into the buffer", -> it "moves the cursor to the end of the leading whitespace and inserts 'tabLength' spaces into the buffer", ->
buffer.insert([7, 0], " \n") buffer.insert([7, 0], " \n")
editSession.setCursorBufferPosition [7, 2] editSession.setCursorBufferPosition [7, 2]
editSession.setAutoIndent(true) editSession.indent(autoIndent: true)
editSession.indent()
expect(buffer.lineForRow(7)).toMatch /^\s+$/ expect(buffer.lineForRow(7)).toMatch /^\s+$/
expect(buffer.lineForRow(7).length).toBe 8 expect(buffer.lineForRow(7).length).toBe 8
expect(editSession.getCursorBufferPosition()).toEqual [7, 8] expect(editSession.getCursorBufferPosition()).toEqual [7, 8]
@ -1345,8 +1331,7 @@ describe "EditSession", ->
editSession.softTabs = false editSession.softTabs = false
buffer.insert([7, 0], "\t\t\t\n") buffer.insert([7, 0], "\t\t\t\n")
editSession.setCursorBufferPosition [7, 1] editSession.setCursorBufferPosition [7, 1]
editSession.setAutoIndent(true) editSession.indent(autoIndent: true)
editSession.indent()
expect(buffer.lineForRow(7)).toMatch /^\t\t\t\t$/ expect(buffer.lineForRow(7)).toMatch /^\t\t\t\t$/
expect(editSession.getCursorBufferPosition()).toEqual [7, 4] expect(editSession.getCursorBufferPosition()).toEqual [7, 4]
@ -1421,17 +1406,16 @@ describe "EditSession", ->
expect(editSession.buffer.lineForRow(0)).toBe "var first = function () {" expect(editSession.buffer.lineForRow(0)).toBe "var first = function () {"
expect(buffer.lineForRow(1)).toBe " var first = function(items) {" expect(buffer.lineForRow(1)).toBe " var first = function(items) {"
it "preserves the indent level when copying and pasting multiple lines", -> it "preserves the indent level when copying and pasting multiple lines", ->
editSession.setAutoIndent(true) editSession.setSelectedBufferRange([[4, 4], [7, 5]])
editSession.setSelectedBufferRange([[4, 4], [7, 5]]) editSession.copySelectedText()
editSession.copySelectedText() editSession.setCursorBufferPosition([10, 0])
editSession.setCursorBufferPosition([10, 0]) editSession.pasteText(autoIndent: true)
editSession.pasteText()
expect(editSession.lineForBufferRow(10)).toBe " while(items.length > 0) {" expect(editSession.lineForBufferRow(10)).toBe " while(items.length > 0) {"
expect(editSession.lineForBufferRow(11)).toBe " current = items.shift();" expect(editSession.lineForBufferRow(11)).toBe " current = items.shift();"
expect(editSession.lineForBufferRow(12)).toBe " current < pivot ? left.push(current) : right.push(current);" expect(editSession.lineForBufferRow(12)).toBe " current < pivot ? left.push(current) : right.push(current);"
expect(editSession.lineForBufferRow(13)).toBe " }" expect(editSession.lineForBufferRow(13)).toBe " }"
describe ".indentSelectedRows()", -> describe ".indentSelectedRows()", ->
describe "when nothing is selected", -> describe "when nothing is selected", ->
@ -1931,3 +1915,57 @@ describe "EditSession", ->
editSession.setCursorScreenPosition([0, 1]) editSession.setCursorScreenPosition([0, 1])
editSession.buffer.reload() editSession.buffer.reload()
expect(editSession.getCursorScreenPosition()).toEqual [0,1] expect(editSession.getCursorScreenPosition()).toEqual [0,1]
describe "auto-indent", ->
describe "editor.autoIndent", ->
it "auto-indents newlines if editor.autoIndent is true", ->
config.set("editor.autoIndent", undefined)
editSession.setCursorBufferPosition([1, 30])
editSession.insertText("\n")
expect(editSession.lineForBufferRow(2)).toBe " "
it "does not auto-indent newlines if editor.autoIndent is false", ->
config.set("editor.autoIndent", false)
editSession.setCursorBufferPosition([1, 30])
editSession.insertText("\n")
expect(editSession.lineForBufferRow(2)).toBe ""
it "auto-indents calls to `indent` if editor.autoIndent is true", ->
config.set("editor.autoIndent", true)
editSession.setCursorBufferPosition([1, 30])
editSession.insertText("\n ")
expect(editSession.lineForBufferRow(2)).toBe " "
editSession.indent()
expect(editSession.lineForBufferRow(2)).toBe " "
it "does not auto-indents calls to `indent` if editor.autoIndent is false", ->
config.set("editor.autoIndent", false)
editSession.setCursorBufferPosition([1, 30])
editSession.insertText("\n ")
expect(editSession.lineForBufferRow(2)).toBe " "
editSession.indent()
expect(editSession.lineForBufferRow(2)).toBe " "
describe "editor.autoIndentOnPaste", ->
it "does not auto-indent pasted text by default", ->
editSession.setCursorBufferPosition([2, 0])
editSession.insertText("0\n 2\n 4\n")
editSession.getSelection().setBufferRange([[2,0], [5,0]])
editSession.cutSelectedText()
editSession.pasteText()
expect(editSession.lineForBufferRow(2)).toBe "0"
expect(editSession.lineForBufferRow(3)).toBe " 2"
expect(editSession.lineForBufferRow(4)).toBe " 4"
it "auto-indents pasted text when editor.autoIndentOnPaste is true", ->
config.set("editor.autoIndentOnPaste", true)
editSession.setCursorBufferPosition([2, 0])
editSession.insertText("0\n 2\n 4\n")
editSession.getSelection().setBufferRange([[2,0], [5,0]])
editSession.cutSelectedText()
editSession.pasteText()
expect(editSession.lineForBufferRow(2)).toBe " 0"
expect(editSession.lineForBufferRow(3)).toBe " 2"
expect(editSession.lineForBufferRow(4)).toBe " 4"

View File

@ -34,6 +34,7 @@ beforeEach ->
spyOn(config, 'load') spyOn(config, 'load')
spyOn(config, 'save') spyOn(config, 'save')
config.set "editor.fontSize", 16 config.set "editor.fontSize", 16
config.set "editor.autoIndent", false
# make editor display updates synchronous # make editor display updates synchronous
spyOn(Editor.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay() spyOn(Editor.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay()

View File

@ -33,11 +33,10 @@ class EditSession
anchorRanges: null anchorRanges: null
cursors: null cursors: null
selections: null selections: null
autoIndent: false # TODO: re-enabled auto-indent after fixing the rest of tokenization
softTabs: true softTabs: true
softWrap: false softWrap: false
constructor: ({@project, @buffer, tabLength, @autoIndent, softTabs, @softWrap }) -> constructor: ({@project, @buffer, tabLength, softTabs, @softWrap }) ->
@softTabs = @buffer.usesSoftTabs() ? softTabs ? true @softTabs = @buffer.usesSoftTabs() ? softTabs ? true
@languageMode = new LanguageMode(this, @buffer.getExtension()) @languageMode = new LanguageMode(this, @buffer.getExtension())
@displayBuffer = new DisplayBuffer(@buffer, { @languageMode, tabLength }) @displayBuffer = new DisplayBuffer(@buffer, { @languageMode, tabLength })
@ -93,7 +92,6 @@ class EditSession
getScrollLeft: -> @scrollLeft getScrollLeft: -> @scrollLeft
setSoftWrapColumn: (@softWrapColumn) -> @displayBuffer.setSoftWrapColumn(@softWrapColumn) setSoftWrapColumn: (@softWrapColumn) -> @displayBuffer.setSoftWrapColumn(@softWrapColumn)
setAutoIndent: (@autoIndent) ->
setSoftTabs: (@softTabs) -> setSoftTabs: (@softTabs) ->
getSoftWrap: -> @softWrap getSoftWrap: -> @softWrap
@ -159,18 +157,26 @@ class EditSession
getCursorScopes: -> @getCursor().getScopes() getCursorScopes: -> @getCursor().getScopes()
logScreenLines: (start, end) -> @displayBuffer.logLines(start, end) logScreenLines: (start, end) -> @displayBuffer.logLines(start, end)
insertText: (text, options) -> shouldAutoIndent: ->
config.get("editor.autoIndent")
shouldAutoIndentPastedText: ->
config.get("editor.autoIndentOnPaste")
insertText: (text, options={}) ->
options.autoIndent ?= @shouldAutoIndent()
@mutateSelectedText (selection) -> selection.insertText(text, options) @mutateSelectedText (selection) -> selection.insertText(text, options)
insertNewline: -> insertNewline: ->
@insertText('\n', autoIndent: true) @insertText('\n')
insertNewlineBelow: -> insertNewlineBelow: ->
@moveCursorToEndOfLine() @moveCursorToEndOfLine()
@insertNewline() @insertNewline()
indent: -> indent: (options={})->
@mutateSelectedText (selection) -> selection.indent() options.autoIndent ?= @shouldAutoIndent()
@mutateSelectedText (selection) -> selection.indent(options)
backspace: -> backspace: ->
@mutateSelectedText (selection) -> selection.backspace() @mutateSelectedText (selection) -> selection.backspace()
@ -217,9 +223,14 @@ class EditSession
selection.copy(maintainPasteboard) selection.copy(maintainPasteboard)
maintainPasteboard = true maintainPasteboard = true
pasteText: -> pasteText: (options={}) ->
options.normalizeIndent ?= true
options.autoIndent ?= @shouldAutoIndentPastedText()
[text, metadata] = pasteboard.read() [text, metadata] = pasteboard.read()
@insertText(text, _.extend(metadata ? {}, normalizeIndent: true)) _.extend(options, metadata) if metadata
@insertText(text, options)
undo: -> undo: ->
@buffer.undo(this) @buffer.undo(this)

View File

@ -17,6 +17,8 @@ class Editor extends View
fontSize: 20 fontSize: 20
showInvisibles: false showInvisibles: false
autosave: false autosave: false
autoIndent: true
autoIndentOnPaste: false
@content: (params) -> @content: (params) ->
@div class: @classes(params), tabindex: -1, => @div class: @classes(params), tabindex: -1, =>
@ -80,7 +82,6 @@ class Editor extends View
buffer: new Buffer() buffer: new Buffer()
softWrap: false softWrap: false
tabLength: 2 tabLength: 2
autoIndent: false
softTabs: true softTabs: true
@editSessions.push editSession @editSessions.push editSession
@ -244,7 +245,7 @@ class Editor extends View
insertText: (text, options) -> @activeEditSession.insertText(text, options) insertText: (text, options) -> @activeEditSession.insertText(text, options)
insertNewline: -> @activeEditSession.insertNewline() insertNewline: -> @activeEditSession.insertNewline()
insertNewlineBelow: -> @activeEditSession.insertNewlineBelow() insertNewlineBelow: -> @activeEditSession.insertNewlineBelow()
indent: -> @activeEditSession.indent() indent: (options) -> @activeEditSession.indent(options)
indentSelectedRows: -> @activeEditSession.indentSelectedRows() indentSelectedRows: -> @activeEditSession.indentSelectedRows()
outdentSelectedRows: -> @activeEditSession.outdentSelectedRows() outdentSelectedRows: -> @activeEditSession.outdentSelectedRows()
cutSelection: -> @activeEditSession.cutSelectedText() cutSelection: -> @activeEditSession.cutSelectedText()
@ -381,7 +382,7 @@ class Editor extends View
@selectOnMousemoveUntilMouseup() @selectOnMousemoveUntilMouseup()
@on "textInput", (e) => @on "textInput", (e) =>
@insertText(e.originalEvent.data, autoIndent: true) @insertText(e.originalEvent.data)
false false
@scrollView.on 'mousewheel', (e) => @scrollView.on 'mousewheel', (e) =>

View File

@ -16,7 +16,6 @@ class Project
new Project(state.path, state.grammarOverridesByPath) new Project(state.path, state.grammarOverridesByPath)
tabLength: 2 tabLength: 2
autoIndent: true
softTabs: true softTabs: true
softWrap: false softWrap: false
rootDirectory: null rootDirectory: null
@ -93,9 +92,6 @@ class Project
relativize: (fullPath) -> relativize: (fullPath) ->
fullPath.replace(@getPath(), "").replace(/^\//, '') fullPath.replace(@getPath(), "").replace(/^\//, '')
getAutoIndent: -> @autoIndent
setAutoIndent: (@autoIndent) ->
getSoftTabs: -> @softTabs getSoftTabs: -> @softTabs
setSoftTabs: (@softTabs) -> setSoftTabs: (@softTabs) ->
@ -116,7 +112,6 @@ class Project
defaultEditSessionOptions: -> defaultEditSessionOptions: ->
tabLength: @tabLength tabLength: @tabLength
autoIndent: @getAutoIndent()
softTabs: @getSoftTabs() softTabs: @getSoftTabs()
softWrap: @getSoftWrap() softWrap: @getSoftWrap()

View File

@ -101,6 +101,10 @@ class RootView extends View
config.set("editor.showInvisibles", !config.get("editor.showInvisibles")) config.set("editor.showInvisibles", !config.get("editor.showInvisibles"))
@command 'window:toggle-ignored-files', => @command 'window:toggle-ignored-files', =>
config.set("core.hideGitIgnoredFiles", not config.core.hideGitIgnoredFiles) config.set("core.hideGitIgnoredFiles", not config.core.hideGitIgnoredFiles)
@command 'window:toggle-auto-indent', =>
config.set("editor.autoIndent", !config.get("editor.autoIndent"))
@command 'window:toggle-auto-indent-on-paste', =>
config.set("editor.autoIndentOnPaste", !config.get("editor.autoIndentOnPaste"))
afterAttach: (onDom) -> afterAttach: (onDom) ->
@focus() if onDom @focus() if onDom

View File

@ -179,13 +179,13 @@ class Selection
else else
@cursor.setBufferPosition(newBufferRange.end, skipAtomicTokens: true) if wasReversed @cursor.setBufferPosition(newBufferRange.end, skipAtomicTokens: true) if wasReversed
if @editSession.autoIndent and options.autoIndent if options.autoIndent
if text == '\n' if text == '\n'
@editSession.autoIndentBufferRow(newBufferRange.end.row) @editSession.autoIndentBufferRow(newBufferRange.end.row)
else else
@editSession.autoDecreaseIndentForRow(newBufferRange.start.row) @editSession.autoDecreaseIndentForRow(newBufferRange.start.row)
indent: -> indent: ({ autoIndent }={})->
{ row, column } = @cursor.getBufferPosition() { row, column } = @cursor.getBufferPosition()
if @isEmpty() if @isEmpty()
@ -193,7 +193,7 @@ class Selection
desiredIndent = @editSession.suggestedIndentForBufferRow(row) desiredIndent = @editSession.suggestedIndentForBufferRow(row)
delta = desiredIndent - @cursor.getIndentLevel() delta = desiredIndent - @cursor.getIndentLevel()
if @editSession.autoIndent and delta > 0 if autoIndent and delta > 0
@insertText(@editSession.buildIndentString(delta)) @insertText(@editSession.buildIndentString(delta))
else else
@insertText(@editSession.getTabText()) @insertText(@editSession.getTabText())
@ -221,7 +221,7 @@ class Selection
if insideExistingLine if insideExistingLine
desiredBasis = @editSession.indentationForBufferRow(currentBufferRow) desiredBasis = @editSession.indentationForBufferRow(currentBufferRow)
else if @editSession.autoIndent else if options.autoIndent
desiredBasis = @editSession.suggestedIndentForBufferRow(currentBufferRow) desiredBasis = @editSession.suggestedIndentForBufferRow(currentBufferRow)
else else
desiredBasis = @cursor.getIndentLevel() desiredBasis = @cursor.getIndentLevel()