WIP: Reworking auto-indent/outdent logic

This commit is contained in:
Corey Johnson & Nathan Sobo
2012-08-09 12:57:47 -06:00
parent ad4b3db439
commit e8aaec43f7
6 changed files with 135 additions and 74 deletions

View File

@@ -329,17 +329,27 @@ class Buffer
isRowBlank: (row) ->
not /\S/.test @lineForRow(row)
nextNonBlankRow: (row) ->
lastRow = @getLastRow()
if row < lastRow
for row in [(row + 1)..lastRow]
return row unless @isRowBlank(row)
previousNonBlankRow: (startRow) ->
startRow = Math.min(startRow, @getLastRow())
for row in [(startRow - 1)..0]
return row unless @isRowBlank(row)
null
nextNonBlankRow: (startRow) ->
lastRow = @getLastRow()
if startRow < lastRow
for row in [(startRow + 1)..lastRow]
return row unless @isRowBlank(row)
null
indentationForRow: (row) ->
@lineForRow(row).match(/^\s*/)?[0].length
setIndentationForRow: (bufferRow, newLevel) ->
currentLevel = @indentationForRow(bufferRow)
indentString = [0...newLevel].map(-> ' ').join('')
@change([[bufferRow, 0], [bufferRow, currentLevel]], indentString)
logLines: (start=0, end=@getLastRow())->
for row in [start..end]
line = @lineForRow(row)

View File

@@ -247,17 +247,17 @@ class EditSession
largestFoldStartingAtScreenRow: (screenRow) ->
@displayBuffer.largestFoldStartingAtScreenRow(screenRow)
indentationForRow: (row) ->
@languageMode.indentationForRow(row)
autoIndentBufferRows: (startRow, endRow) ->
@languageMode.autoIndentBufferRows(startRow, endRow)
autoIndentRows: (startRow, endRow) ->
@autoIndentRow(row) for row in [startRow..endRow]
autoIndentBufferRow: (bufferRow) ->
@languageMode.autoIndentBufferRow(bufferRow)
autoIndentRow: (row) ->
actualIndentation = @lineForBufferRow(row).match(/^\s*/)[0]
desiredIndentation = @indentationForRow(row)
if actualIndentation != desiredIndentation
@buffer.change([[row, 0], [row, actualIndentation.length]], desiredIndentation)
autoIncreaseIndentForBufferRow: (bufferRow) ->
@languageMode.autoIncreaseIndentForBufferRow(bufferRow)
autoDecreaseIndentForRow: (bufferRow) ->
@languageMode.autoDecreaseIndentForBufferRow(bufferRow)
toggleLineCommentsInRange: (range) ->
@languageMode.toggleLineCommentsInRange(range)

View File

@@ -13,7 +13,8 @@ class LanguageMode
"'": "'"
constructor: (@editSession) ->
@grammar = TextMateBundle.grammarForFileName(@editSession.buffer.getBaseName())
@buffer = @editSession.buffer
@grammar = TextMateBundle.grammarForFileName(@buffer.getBaseName())
_.adviseBefore @editSession, 'insertText', (text) =>
return true if @editSession.hasMultipleCursors()
@@ -84,25 +85,43 @@ class LanguageMode
[bufferRow, foldEndRow]
indentationForRow: (row) ->
for precedingRow in [row - 1..-1]
return if precedingRow < 0
precedingLine = @editSession.buffer.lineForRow(precedingRow)
break if /\S/.test(precedingLine)
autoIndentBufferRows: (startRow, endRow) ->
@autoIndentBufferRow(row) for row in [startRow..endRow]
autoIndentBufferRow: (bufferRow) ->
@autoIncreaseIndentForBufferRow(bufferRow)
@autoDecreaseIndentForBufferRow(bufferRow)
autoIncreaseIndentForBufferRow: (bufferRow) ->
precedingRow = @buffer.previousNonBlankRow(bufferRow)
return unless precedingRow?
precedingLine = @editSession.lineForBufferRow(precedingRow)
scopes = @tokenizedBuffer.scopesForPosition([precedingRow, Infinity])
indentation = precedingLine.match(/^\s*/)[0]
increaseIndentPattern = TextMateBundle.getPreferenceInScope(scopes[0], 'increaseIndentPattern')
decreaseIndentPattern = TextMateBundle.getPreferenceInScope(scopes[0], 'decreaseIndentPattern')
increaseIndentPattern = new OnigRegExp(TextMateBundle.getPreferenceInScope(scopes[0], 'increaseIndentPattern'))
if new OnigRegExp(increaseIndentPattern).search(precedingLine)
indentation += @editSession.tabText
currentIndentation = @buffer.indentationForRow(bufferRow)
desiredIndentation = @buffer.indentationForRow(precedingRow)
desiredIndentation += @editSession.tabText.length if increaseIndentPattern.test(precedingLine)
if desiredIndentation > currentIndentation
@buffer.setIndentationForRow(bufferRow, desiredIndentation)
line = @editSession.buffer.lineForRow(row)
if new OnigRegExp(decreaseIndentPattern).search(line)
indentation = indentation.replace(@editSession.tabText, "")
autoDecreaseIndentForBufferRow: (bufferRow) ->
scopes = @tokenizedBuffer.scopesForPosition([bufferRow, 0])
increaseIndentPattern = new OnigRegExp(TextMateBundle.getPreferenceInScope(scopes[0], 'increaseIndentPattern'))
decreaseIndentPattern = new OnigRegExp(TextMateBundle.getPreferenceInScope(scopes[0], 'decreaseIndentPattern'))
line = @buffer.lineForRow(bufferRow)
return unless decreaseIndentPattern.test(line)
indentation
currentIndentation = @buffer.indentationForRow(bufferRow)
precedingRow = @buffer.previousNonBlankRow(bufferRow)
precedingLine = @buffer.lineForRow(precedingRow)
desiredIndentation = @buffer.indentationForRow(precedingRow)
desiredIndentation -= @editSession.tabText.length unless increaseIndentPattern.test(precedingLine)
if desiredIndentation < currentIndentation
@buffer.setIndentationForRow(bufferRow, desiredIndentation)
getLineTokens: (line, stack) ->
{tokens, stack} = @grammar.getLineTokens(line, stack)

View File

@@ -74,3 +74,6 @@ class Range
else
columns = @end.column
new Point(rows, columns)
getRowCount: ->
@end.row - @start.row + 1

View File

@@ -134,7 +134,18 @@ class Selection
@cursor.setBufferPosition(newBufferRange.end, skipAtomicTokens: true) if wasReversed
if @editSession.autoIndent
@editSession.autoIndentRows(newBufferRange.start.row, newBufferRange.end.row)
if /\n/.test(text)
firstLinePrefix = @editSession.getTextInBufferRange([[newBufferRange.start.row, 0], newBufferRange.start])
if /^\s*$/.test(firstLinePrefix)
@editSession.autoIncreaseIndentForBufferRow(newBufferRange.start.row)
if newBufferRange.getRowCount() > 1
@editSession.autoIndentBufferRows(newBufferRange.start.row + 1, newBufferRange.end.row)
else
@editSession.autoIncreaseIndentForBufferRow(newBufferRange.start.row + 1)
if newBufferRange.getRowCount() > 2
@editSession.autoIndentBufferRows(newBufferRange.start.row + 2, newBufferRange.end.row)
else
@editSession.autoDecreaseIndentForRow(newBufferRange.start.row)
backspace: ->
if @isEmpty() and not @editSession.isFoldedAtScreenRow(@cursor.getScreenRow())