mirror of
https://github.com/atom/atom.git
synced 2026-02-07 05:05:02 -05:00
This removes all internal native oniguruma sources and starts using the node module directly to create onig scanners and regexes.
164 lines
6.9 KiB
CoffeeScript
164 lines
6.9 KiB
CoffeeScript
Range = require 'range'
|
|
_ = require 'underscore'
|
|
require 'underscore-extensions'
|
|
{OnigRegExp} = nodeRequire 'oniguruma'
|
|
|
|
module.exports =
|
|
class LanguageMode
|
|
buffer = null
|
|
grammar = null
|
|
editSession = null
|
|
|
|
constructor: (@editSession) ->
|
|
@buffer = @editSession.buffer
|
|
@reloadGrammar()
|
|
|
|
reloadGrammar: ->
|
|
path = @buffer.getPath()
|
|
pathContents = @buffer.cachedDiskContents
|
|
previousGrammar = @grammar
|
|
if @buffer.project?
|
|
@grammar = @buffer.project.grammarForFilePath(path, pathContents)
|
|
else
|
|
@grammar = syntax.grammarForFilePath(path, pathContents)
|
|
throw new Error("No grammar found for path: #{path}") unless @grammar
|
|
previousGrammar isnt @grammar
|
|
|
|
toggleLineCommentsForBufferRows: (start, end) ->
|
|
scopes = @editSession.scopesForBufferPosition([start, 0])
|
|
return unless commentStartString = syntax.getProperty(scopes, "editor.commentStart")
|
|
|
|
buffer = @editSession.buffer
|
|
commentStartRegexString = _.escapeRegExp(commentStartString).replace(/(\s+)$/, '($1)?')
|
|
commentStartRegex = new OnigRegExp("^(\\s*)(#{commentStartRegexString})")
|
|
shouldUncomment = commentStartRegex.test(buffer.lineForRow(start))
|
|
|
|
if commentEndString = syntax.getProperty(scopes, "editor.commentEnd")
|
|
if shouldUncomment
|
|
commentEndRegexString = _.escapeRegExp(commentEndString).replace(/^(\s+)/, '($1)?')
|
|
commentEndRegex = new OnigRegExp("(#{commentEndRegexString})(\\s*)$")
|
|
startMatch = commentStartRegex.search(buffer.lineForRow(start))
|
|
endMatch = commentEndRegex.search(buffer.lineForRow(end))
|
|
if startMatch and endMatch
|
|
buffer.transact ->
|
|
columnStart = startMatch[1].length
|
|
columnEnd = columnStart + startMatch[2].length
|
|
buffer.change([[start, columnStart], [start, columnEnd]], "")
|
|
|
|
endLength = buffer.lineLengthForRow(end) - endMatch[2].length
|
|
endColumn = endLength - endMatch[1].length
|
|
buffer.change([[end, endColumn], [end, endLength]], "")
|
|
else
|
|
buffer.transact ->
|
|
buffer.insert([start, 0], commentStartString)
|
|
buffer.insert([end, buffer.lineLengthForRow(end)], commentEndString)
|
|
else
|
|
if shouldUncomment
|
|
for row in [start..end]
|
|
if match = commentStartRegex.search(buffer.lineForRow(row))
|
|
columnStart = match[1].length
|
|
columnEnd = columnStart + match[2].length
|
|
buffer.change([[row, columnStart], [row, columnEnd]], "")
|
|
else
|
|
for row in [start..end]
|
|
buffer.insert([row, 0], commentStartString)
|
|
|
|
doesBufferRowStartFold: (bufferRow) ->
|
|
return false if @editSession.isBufferRowBlank(bufferRow)
|
|
nextNonEmptyRow = @editSession.nextNonBlankBufferRow(bufferRow)
|
|
return false unless nextNonEmptyRow?
|
|
@editSession.indentationForBufferRow(nextNonEmptyRow) > @editSession.indentationForBufferRow(bufferRow)
|
|
|
|
rowRangeForFoldAtBufferRow: (bufferRow) ->
|
|
return null unless @doesBufferRowStartFold(bufferRow)
|
|
|
|
startIndentLevel = @editSession.indentationForBufferRow(bufferRow)
|
|
scopes = @editSession.scopesForBufferPosition([bufferRow, 0])
|
|
for row in [(bufferRow + 1)..@editSession.getLastBufferRow()]
|
|
continue if @editSession.isBufferRowBlank(row)
|
|
indentation = @editSession.indentationForBufferRow(row)
|
|
if indentation <= startIndentLevel
|
|
includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes)?.search(@editSession.lineForBufferRow(row))
|
|
foldEndRow = row if includeRowInFold
|
|
break
|
|
|
|
foldEndRow = row
|
|
|
|
[bufferRow, foldEndRow]
|
|
|
|
suggestedIndentForBufferRow: (bufferRow) ->
|
|
currentIndentLevel = @editSession.indentationForBufferRow(bufferRow)
|
|
scopes = @editSession.scopesForBufferPosition([bufferRow, 0])
|
|
return currentIndentLevel unless increaseIndentRegex = @increaseIndentRegexForScopes(scopes)
|
|
|
|
currentLine = @buffer.lineForRow(bufferRow)
|
|
precedingRow = @buffer.previousNonBlankRow(bufferRow)
|
|
return currentIndentLevel unless precedingRow?
|
|
|
|
precedingLine = @buffer.lineForRow(precedingRow)
|
|
|
|
desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow)
|
|
desiredIndentLevel += 1 if increaseIndentRegex.test(precedingLine)
|
|
|
|
return desiredIndentLevel unless decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes)
|
|
desiredIndentLevel -= 1 if decreaseIndentRegex.test(currentLine)
|
|
|
|
Math.max(desiredIndentLevel, currentIndentLevel)
|
|
|
|
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 = @editSession.scopesForBufferPosition([precedingRow, Infinity])
|
|
increaseIndentRegex = @increaseIndentRegexForScopes(scopes)
|
|
return unless increaseIndentRegex
|
|
|
|
currentIndentLevel = @editSession.indentationForBufferRow(bufferRow)
|
|
desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow)
|
|
desiredIndentLevel += 1 if increaseIndentRegex.test(precedingLine)
|
|
if desiredIndentLevel > currentIndentLevel
|
|
@editSession.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
|
|
|
|
autoDecreaseIndentForBufferRow: (bufferRow) ->
|
|
scopes = @editSession.scopesForBufferPosition([bufferRow, 0])
|
|
increaseIndentRegex = @increaseIndentRegexForScopes(scopes)
|
|
decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes)
|
|
return unless increaseIndentRegex and decreaseIndentRegex
|
|
|
|
line = @buffer.lineForRow(bufferRow)
|
|
return unless decreaseIndentRegex.test(line)
|
|
|
|
currentIndentLevel = @editSession.indentationForBufferRow(bufferRow)
|
|
return if currentIndentLevel is 0
|
|
precedingRow = @buffer.previousNonBlankRow(bufferRow)
|
|
return unless precedingRow?
|
|
precedingLine = @buffer.lineForRow(precedingRow)
|
|
|
|
desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow)
|
|
desiredIndentLevel -= 1 unless increaseIndentRegex.test(precedingLine)
|
|
if desiredIndentLevel >= 0 and desiredIndentLevel < currentIndentLevel
|
|
@editSession.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
|
|
|
|
tokenizeLine: (line, stack, firstLine) ->
|
|
{tokens, stack} = @grammar.tokenizeLine(line, stack, firstLine)
|
|
|
|
increaseIndentRegexForScopes: (scopes) ->
|
|
if increaseIndentPattern = syntax.getProperty(scopes, 'editor.increaseIndentPattern')
|
|
new OnigRegExp(increaseIndentPattern)
|
|
|
|
decreaseIndentRegexForScopes: (scopes) ->
|
|
if decreaseIndentPattern = syntax.getProperty(scopes, 'editor.decreaseIndentPattern')
|
|
new OnigRegExp(decreaseIndentPattern)
|
|
|
|
foldEndRegexForScopes: (scopes) ->
|
|
if foldEndPattern = syntax.getProperty(scopes, 'editor.foldEndPattern')
|
|
new OnigRegExp(foldEndPattern)
|