mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
Merge branch 'master' into batch-updates
This commit is contained in:
@@ -8,6 +8,7 @@ crypto = require 'crypto'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
babel = null # Defer until used
|
||||
Grim = null # Defer until used
|
||||
|
||||
stats =
|
||||
hits: 0
|
||||
@@ -132,10 +133,30 @@ transpile = (sourceCode, filePath, cachePath) ->
|
||||
# either generated on the fly or pulled from cache.
|
||||
loadFile = (module, filePath) ->
|
||||
sourceCode = fs.readFileSync(filePath, 'utf8')
|
||||
return module._compile(sourceCode, filePath) unless sourceCode.startsWith('"use 6to5"') or
|
||||
sourceCode.startsWith("'use 6to5'") or
|
||||
sourceCode.startsWith('"use babel"') or
|
||||
sourceCode.startsWith("'use babel'")
|
||||
if sourceCode.startsWith('"use babel"') or sourceCode.startsWith("'use babel'")
|
||||
# Continue.
|
||||
else if sourceCode.startsWith('"use 6to5"') or sourceCode.startsWith("'use 6to5'")
|
||||
# Create a manual deprecation since the stack is too deep to use Grim
|
||||
# which limits the depth to 3
|
||||
Grim ?= require 'grim'
|
||||
stack = [
|
||||
{
|
||||
fileName: __filename
|
||||
functionName: 'loadFile'
|
||||
location: "#{__filename}:161:5"
|
||||
}
|
||||
{
|
||||
fileName: filePath
|
||||
functionName: '<unknown>'
|
||||
location: "#{filePath}:1:1"
|
||||
}
|
||||
]
|
||||
deprecation =
|
||||
message: "Use the 'use babel' pragma instead of 'use 6to5'"
|
||||
stacks: [stack]
|
||||
Grim.addSerializedDeprecation(deprecation)
|
||||
else
|
||||
return module._compile(sourceCode, filePath)
|
||||
|
||||
cachePath = getCachePath(sourceCode)
|
||||
js = getCachedJavaScript(cachePath) ? transpile(sourceCode, filePath, cachePath)
|
||||
|
||||
@@ -271,7 +271,7 @@ class Cursor extends Model
|
||||
{ row, column } = @getScreenPosition()
|
||||
|
||||
column = @goalColumn if @goalColumn?
|
||||
@setScreenPosition({row: row - rowCount, column: column})
|
||||
@setScreenPosition({row: row - rowCount, column: column}, skipSoftWrapIndentation: true)
|
||||
@goalColumn = column
|
||||
|
||||
# Public: Moves the cursor down one screen row.
|
||||
@@ -288,7 +288,7 @@ class Cursor extends Model
|
||||
{ row, column } = @getScreenPosition()
|
||||
|
||||
column = @goalColumn if @goalColumn?
|
||||
@setScreenPosition({row: row + rowCount, column: column})
|
||||
@setScreenPosition({row: row + rowCount, column: column}, skipSoftWrapIndentation: true)
|
||||
@goalColumn = column
|
||||
|
||||
# Public: Moves the cursor left one screen column.
|
||||
@@ -359,19 +359,21 @@ class Cursor extends Model
|
||||
# line.
|
||||
moveToFirstCharacterOfLine: ->
|
||||
screenRow = @getScreenRow()
|
||||
lineBufferRange = @editor.bufferRangeForScreenRange([[screenRow, 0], [screenRow, Infinity]])
|
||||
screenLineStart = @editor.clipScreenPosition([screenRow, 0], skipSoftWrapIndentation: true)
|
||||
screenLineEnd = [screenRow, Infinity]
|
||||
screenLineBufferRange = @editor.bufferRangeForScreenRange([screenLineStart, screenLineEnd])
|
||||
|
||||
firstCharacterColumn = null
|
||||
@editor.scanInBufferRange /\S/, lineBufferRange, ({range, stop}) ->
|
||||
@editor.scanInBufferRange /\S/, screenLineBufferRange, ({range, stop}) ->
|
||||
firstCharacterColumn = range.start.column
|
||||
stop()
|
||||
|
||||
if firstCharacterColumn? and firstCharacterColumn isnt @getBufferColumn()
|
||||
targetBufferColumn = firstCharacterColumn
|
||||
else
|
||||
targetBufferColumn = lineBufferRange.start.column
|
||||
targetBufferColumn = screenLineBufferRange.start.column
|
||||
|
||||
@setBufferPosition([lineBufferRange.start.row, targetBufferColumn])
|
||||
@setBufferPosition([screenLineBufferRange.start.row, targetBufferColumn])
|
||||
|
||||
# Public: Moves the cursor to the end of the line.
|
||||
moveToEndOfScreenLine: ->
|
||||
|
||||
@@ -819,11 +819,12 @@ class DisplayBuffer extends Model
|
||||
# options - A hash with the following values:
|
||||
# wrapBeyondNewlines: if `true`, continues wrapping past newlines
|
||||
# wrapAtSoftNewlines: if `true`, continues wrapping past soft newlines
|
||||
# skipSoftWrapIndentation: if `true`, skips soft wrap indentation without wrapping to the previous line
|
||||
# screenLine: if `true`, indicates that you're using a line number, not a row number
|
||||
#
|
||||
# Returns the new, clipped {Point}. Note that this could be the same as `position` if no clipping was performed.
|
||||
clipScreenPosition: (screenPosition, options={}) ->
|
||||
{ wrapBeyondNewlines, wrapAtSoftNewlines } = options
|
||||
{ wrapBeyondNewlines, wrapAtSoftNewlines, skipSoftWrapIndentation } = options
|
||||
{ row, column } = Point.fromObject(screenPosition)
|
||||
|
||||
if row < 0
|
||||
@@ -841,9 +842,15 @@ class DisplayBuffer extends Model
|
||||
if screenLine.isSoftWrapped() and column >= maxScreenColumn
|
||||
if wrapAtSoftNewlines
|
||||
row++
|
||||
column = 0
|
||||
column = @screenLines[row].clipScreenColumn(0)
|
||||
else
|
||||
column = screenLine.clipScreenColumn(maxScreenColumn - 1)
|
||||
else if screenLine.isColumnInsideSoftWrapIndentation(column)
|
||||
if skipSoftWrapIndentation
|
||||
column = screenLine.clipScreenColumn(0)
|
||||
else
|
||||
row--
|
||||
column = @screenLines[row].getMaxScreenColumn() - 1
|
||||
else if wrapBeyondNewlines and column > maxScreenColumn and row < @getLastRow()
|
||||
row++
|
||||
column = 0
|
||||
@@ -851,28 +858,6 @@ class DisplayBuffer extends Model
|
||||
column = screenLine.clipScreenColumn(column, options)
|
||||
new Point(row, column)
|
||||
|
||||
# Given a line, finds the point where it would wrap.
|
||||
#
|
||||
# line - The {String} to check
|
||||
# softWrapColumn - The {Number} where you want soft wrapping to occur
|
||||
#
|
||||
# Returns a {Number} representing the `line` position where the wrap would take place.
|
||||
# Returns `null` if a wrap wouldn't occur.
|
||||
findWrapColumn: (line, softWrapColumn=@getSoftWrapColumn()) ->
|
||||
return unless @isSoftWrapped()
|
||||
return unless line.length > softWrapColumn
|
||||
|
||||
if /\s/.test(line[softWrapColumn])
|
||||
# search forward for the start of a word past the boundary
|
||||
for column in [softWrapColumn..line.length]
|
||||
return column if /\S/.test(line[column])
|
||||
return line.length
|
||||
else
|
||||
# search backward for the start of the word on the boundary
|
||||
for column in [softWrapColumn..0]
|
||||
return column + 1 if /\s/.test(line[column])
|
||||
return softWrapColumn
|
||||
|
||||
# Calculates a {Range} representing the start of the {TextBuffer} until the end.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
@@ -1157,10 +1142,12 @@ class DisplayBuffer extends Model
|
||||
bufferRow += foldedRowCount
|
||||
else
|
||||
softWraps = 0
|
||||
while wrapScreenColumn = @findWrapColumn(tokenizedLine.text)
|
||||
[wrappedLine, tokenizedLine] = tokenizedLine.softWrapAt(wrapScreenColumn)
|
||||
screenLines.push(wrappedLine)
|
||||
softWraps++
|
||||
if @isSoftWrapped()
|
||||
while wrapScreenColumn = tokenizedLine.findWrapColumn(@getSoftWrapColumn())
|
||||
[wrappedLine, tokenizedLine] = tokenizedLine.softWrapAt(wrapScreenColumn)
|
||||
break if wrappedLine.hasOnlySoftWrapIndentation()
|
||||
screenLines.push(wrappedLine)
|
||||
softWraps++
|
||||
screenLines.push(tokenizedLine)
|
||||
|
||||
if softWraps > 0
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
RegionStyleProperties = ['top', 'left', 'right', 'width', 'height']
|
||||
SpaceRegex = /\s+/
|
||||
|
||||
module.exports =
|
||||
class HighlightsComponent
|
||||
@@ -44,8 +45,17 @@ class HighlightsComponent
|
||||
|
||||
# update class
|
||||
if newHighlightState.class isnt oldHighlightState.class
|
||||
highlightNode.classList.remove(oldHighlightState.class) if oldHighlightState.class?
|
||||
highlightNode.classList.add(newHighlightState.class)
|
||||
if oldHighlightState.class?
|
||||
if SpaceRegex.test(oldHighlightState.class)
|
||||
highlightNode.classList.remove(oldHighlightState.class.split(SpaceRegex)...)
|
||||
else
|
||||
highlightNode.classList.remove(oldHighlightState.class)
|
||||
|
||||
if SpaceRegex.test(newHighlightState.class)
|
||||
highlightNode.classList.add(newHighlightState.class.split(SpaceRegex)...)
|
||||
else
|
||||
highlightNode.classList.add(newHighlightState.class)
|
||||
|
||||
oldHighlightState.class = newHighlightState.class
|
||||
|
||||
@updateHighlightRegions(id, newHighlightState)
|
||||
|
||||
@@ -157,7 +157,7 @@ class Package
|
||||
@activateConfig()
|
||||
@activateStylesheets()
|
||||
if @requireMainModule()
|
||||
@mainModule.activate(atom.packages.getPackageState(@name) ? {})
|
||||
@mainModule.activate?(atom.packages.getPackageState(@name) ? {})
|
||||
@mainActivated = true
|
||||
@activateServices()
|
||||
catch e
|
||||
|
||||
@@ -1817,13 +1817,13 @@ class TextEditor extends Model
|
||||
|
||||
# Merge cursors that have the same screen position
|
||||
mergeCursors: ->
|
||||
positions = []
|
||||
positions = {}
|
||||
for cursor in @getCursors()
|
||||
position = cursor.getBufferPosition().toString()
|
||||
if position in positions
|
||||
if positions.hasOwnProperty(position)
|
||||
cursor.destroy()
|
||||
else
|
||||
positions.push(position)
|
||||
positions[position] = true
|
||||
|
||||
preserveCursorPositionOnBufferReload: ->
|
||||
cursorPosition = null
|
||||
|
||||
@@ -21,7 +21,7 @@ class Token
|
||||
firstTrailingWhitespaceIndex: null
|
||||
hasInvisibleCharacters: false
|
||||
|
||||
constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @isHardTab, @hasPairedCharacter}) ->
|
||||
constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @isHardTab, @hasPairedCharacter, @isSoftWrapIndentation}) ->
|
||||
@screenDelta = @value.length
|
||||
@bufferDelta ?= @screenDelta
|
||||
@hasPairedCharacter ?= textUtils.hasPairedCharacter(@value)
|
||||
@@ -144,6 +144,15 @@ class Token
|
||||
isHardTab: isHardTab
|
||||
)
|
||||
|
||||
buildSoftWrapIndentationToken: (length) ->
|
||||
new Token(
|
||||
value: _.multiplyString(" ", length),
|
||||
scopes: @scopes,
|
||||
bufferDelta: 0,
|
||||
isAtomic: true,
|
||||
isSoftWrapIndentation: true
|
||||
)
|
||||
|
||||
isOnlyWhitespace: ->
|
||||
not WhitespaceRegex.test(@value)
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ class TokenizedLine
|
||||
@tokens = @breakOutAtomicTokens(tokens)
|
||||
@text = @buildText()
|
||||
@bufferDelta = @buildBufferDelta()
|
||||
@softWrapIndentationTokens = @getSoftWrapIndentationTokens()
|
||||
@softWrapIndentationDelta = @buildSoftWrapIndentationDelta()
|
||||
|
||||
@id = idCounter++
|
||||
@markLeadingAndTrailingWhitespaceTokens()
|
||||
@@ -49,7 +51,9 @@ class TokenizedLine
|
||||
break if tokenStartColumn + token.screenDelta > column
|
||||
tokenStartColumn += token.screenDelta
|
||||
|
||||
if token.isAtomic and tokenStartColumn < column
|
||||
if @isColumnInsideSoftWrapIndentation(tokenStartColumn)
|
||||
@softWrapIndentationDelta
|
||||
else if token.isAtomic and tokenStartColumn < column
|
||||
if skipAtomicTokens
|
||||
tokenStartColumn + token.screenDelta
|
||||
else
|
||||
@@ -85,6 +89,46 @@ class TokenizedLine
|
||||
getMaxBufferColumn: ->
|
||||
@startBufferColumn + @bufferDelta
|
||||
|
||||
# Given a boundary column, finds the point where this line would wrap.
|
||||
#
|
||||
# maxColumn - The {Number} where you want soft wrapping to occur
|
||||
#
|
||||
# Returns a {Number} representing the `line` position where the wrap would take place.
|
||||
# Returns `null` if a wrap wouldn't occur.
|
||||
findWrapColumn: (maxColumn) ->
|
||||
return unless @text.length > maxColumn
|
||||
|
||||
if /\s/.test(@text[maxColumn])
|
||||
# search forward for the start of a word past the boundary
|
||||
for column in [maxColumn..@text.length]
|
||||
return column if /\S/.test(@text[column])
|
||||
|
||||
return @text.length
|
||||
else
|
||||
# search backward for the start of the word on the boundary
|
||||
for column in [maxColumn..0] when @isColumnOutsideSoftWrapIndentation(column)
|
||||
return column + 1 if /\s/.test(@text[column])
|
||||
|
||||
return maxColumn
|
||||
|
||||
# Calculates how many trailing spaces in this line's indentation cannot fit in a single tab.
|
||||
#
|
||||
# Returns a {Number} representing the odd indentation spaces in this line.
|
||||
getOddIndentationSpaces: ->
|
||||
oddIndentLevel = @indentLevel - Math.floor(@indentLevel)
|
||||
Math.round(@tabLength * oddIndentLevel)
|
||||
|
||||
buildSoftWrapIndentationTokens: (token) ->
|
||||
indentTokens = [0...Math.floor(@indentLevel)].map =>
|
||||
token.buildSoftWrapIndentationToken(@tabLength)
|
||||
|
||||
if @getOddIndentationSpaces()
|
||||
indentTokens.concat(
|
||||
token.buildSoftWrapIndentationToken @getOddIndentationSpaces()
|
||||
)
|
||||
else
|
||||
indentTokens
|
||||
|
||||
softWrapAt: (column) ->
|
||||
return [new TokenizedLine([], '', [0, 0], [0, 0]), this] if column == 0
|
||||
|
||||
@@ -98,25 +142,50 @@ class TokenizedLine
|
||||
leftTextLength += nextToken.value.length
|
||||
leftTokens.push nextToken
|
||||
|
||||
indentationTokens = @buildSoftWrapIndentationTokens(leftTokens[0])
|
||||
|
||||
leftFragment = new TokenizedLine(
|
||||
tokens: leftTokens
|
||||
startBufferColumn: @startBufferColumn
|
||||
ruleStack: @ruleStack
|
||||
invisibles: @invisibles
|
||||
lineEnding: null
|
||||
lineEnding: null,
|
||||
indentLevel: @indentLevel,
|
||||
tabLength: @tabLength
|
||||
)
|
||||
rightFragment = new TokenizedLine(
|
||||
tokens: rightTokens
|
||||
tokens: indentationTokens.concat(rightTokens)
|
||||
startBufferColumn: @bufferColumnForScreenColumn(column)
|
||||
ruleStack: @ruleStack
|
||||
invisibles: @invisibles
|
||||
lineEnding: @lineEnding
|
||||
lineEnding: @lineEnding,
|
||||
indentLevel: @indentLevel,
|
||||
tabLength: @tabLength
|
||||
)
|
||||
[leftFragment, rightFragment]
|
||||
|
||||
isSoftWrapped: ->
|
||||
@lineEnding is null
|
||||
|
||||
isColumnOutsideSoftWrapIndentation: (column) ->
|
||||
return true if @softWrapIndentationTokens.length == 0
|
||||
|
||||
column > @softWrapIndentationDelta
|
||||
|
||||
isColumnInsideSoftWrapIndentation: (column) ->
|
||||
return false if @softWrapIndentationTokens.length == 0
|
||||
|
||||
column < @softWrapIndentationDelta
|
||||
|
||||
getSoftWrapIndentationTokens: ->
|
||||
_.select(@tokens, (token) -> token.isSoftWrapIndentation)
|
||||
|
||||
buildSoftWrapIndentationDelta: ->
|
||||
_.reduce @softWrapIndentationTokens, ((acc, token) -> acc + token.screenDelta), 0
|
||||
|
||||
hasOnlySoftWrapIndentation: ->
|
||||
@tokens.length == @softWrapIndentationTokens.length
|
||||
|
||||
tokenAtBufferColumn: (bufferColumn) ->
|
||||
@tokens[@tokenIndexAtBufferColumn(bufferColumn)]
|
||||
|
||||
@@ -173,7 +242,7 @@ class TokenizedLine
|
||||
changedText = true
|
||||
else
|
||||
if invisibles.space
|
||||
if token.hasLeadingWhitespace()
|
||||
if token.hasLeadingWhitespace() and not token.isSoftWrapIndentation
|
||||
token.value = token.value.replace LeadingWhitespaceRegex, (leadingWhitespace) ->
|
||||
leadingWhitespace.replace RepeatedSpaceRegex, invisibles.space
|
||||
token.hasInvisibleCharacters = true
|
||||
|
||||
Reference in New Issue
Block a user