mirror of
https://github.com/atom/atom.git
synced 2026-02-08 21:55:05 -05:00
Merge remote-tracking branch 'origin/folding' into chrome
This commit is contained in:
@@ -13,11 +13,11 @@ class Cursor extends View
|
||||
@one 'attach', => @updateAppearance()
|
||||
|
||||
bufferChanged: (e) ->
|
||||
@setScreenPosition(e.newRange.end)
|
||||
@setBufferPosition(e.newRange.end)
|
||||
|
||||
setScreenPosition: (point) ->
|
||||
point = Point.fromObject(point)
|
||||
@$position = @editor.clipPosition(point)
|
||||
setScreenPosition: (position) ->
|
||||
position = Point.fromObject(position)
|
||||
@screenPosition = @editor.clipScreenPosition(position)
|
||||
@goalColumn = null
|
||||
@updateAppearance()
|
||||
@trigger 'cursor:position-changed'
|
||||
@@ -26,7 +26,13 @@ class Cursor extends View
|
||||
window.clearTimeout(@idleTimeout) if @idleTimeout
|
||||
@idleTimeout = window.setTimeout (=> @addClass 'idle'), 200
|
||||
|
||||
getScreenPosition: -> _.clone(@$position)
|
||||
setBufferPosition: (bufferPosition) ->
|
||||
@setScreenPosition(@editor.screenPositionForBufferPosition(bufferPosition))
|
||||
|
||||
getBufferPosition: ->
|
||||
@editor.bufferPositionForScreenPosition(@getScreenPosition())
|
||||
|
||||
getScreenPosition: -> _.clone(@screenPosition)
|
||||
|
||||
getColumn: ->
|
||||
@getScreenPosition().column
|
||||
@@ -44,21 +50,13 @@ class Cursor extends View
|
||||
moveUp: ->
|
||||
{ row, column } = @getScreenPosition()
|
||||
column = @goalColumn if @goalColumn?
|
||||
if row > 0
|
||||
@setScreenPosition({row: row - 1, column: column})
|
||||
else
|
||||
@moveToLineStart()
|
||||
|
||||
@setScreenPosition({row: row - 1, column: column})
|
||||
@goalColumn = column
|
||||
|
||||
moveDown: ->
|
||||
{ row, column } = @getScreenPosition()
|
||||
column = @goalColumn if @goalColumn?
|
||||
if row < @editor.buffer.numLines() - 1
|
||||
@setScreenPosition({row: row + 1, column: column})
|
||||
else
|
||||
@moveToLineEnd()
|
||||
|
||||
@setScreenPosition({row: row + 1, column: column})
|
||||
@goalColumn = column
|
||||
|
||||
moveToLineEnd: ->
|
||||
@@ -71,20 +69,16 @@ class Cursor extends View
|
||||
|
||||
moveRight: ->
|
||||
{ row, column } = @getScreenPosition()
|
||||
if column < @editor.buffer.getLine(row).length
|
||||
column++
|
||||
else if row < @editor.buffer.numLines() - 1
|
||||
row++
|
||||
column = 0
|
||||
@setScreenPosition({row, column})
|
||||
@setScreenPosition(@editor.clipScreenPosition([row, column + 1], skipAtomicTokens: true, wrapBeyondNewlines: true, wrapAtSoftNewlines: true))
|
||||
|
||||
moveLeft: ->
|
||||
{ row, column } = @getScreenPosition()
|
||||
|
||||
if column > 0
|
||||
column--
|
||||
else if row > 0
|
||||
else
|
||||
row--
|
||||
column = @editor.buffer.getLine(row).length
|
||||
column = Infinity
|
||||
|
||||
@setScreenPosition({row, column})
|
||||
|
||||
@@ -111,7 +105,7 @@ class Cursor extends View
|
||||
@setScreenPosition [row, column + offset]
|
||||
|
||||
updateAppearance: ->
|
||||
position = @editor.pixelPositionFromPoint(@getScreenPosition())
|
||||
position = @editor.pixelPositionForScreenPosition(@getScreenPosition())
|
||||
@css(position)
|
||||
@autoScrollVertically(position)
|
||||
@autoScrollHorizontally(position)
|
||||
|
||||
@@ -95,7 +95,7 @@ class Editor extends View
|
||||
clickCount = e.originalEvent.detail
|
||||
|
||||
if clickCount == 1
|
||||
@setCursorScreenPosition @pointFromMouseEvent(e)
|
||||
@setCursorScreenPosition @screenPositionFromMouseEvent(e)
|
||||
else if clickCount == 2
|
||||
@selection.selectWord()
|
||||
else if clickCount >= 3
|
||||
@@ -107,7 +107,7 @@ class Editor extends View
|
||||
@insertText(e.originalEvent.data)
|
||||
|
||||
@on 'cursor:position-changed', =>
|
||||
@hiddenInput.css(@pixelPositionFromPoint(@cursor.getScreenPosition()))
|
||||
@hiddenInput.css(@pixelPositionForScreenPosition(@cursor.getScreenPosition()))
|
||||
|
||||
@one 'attach', =>
|
||||
@calculateDimensions()
|
||||
@@ -116,7 +116,7 @@ class Editor extends View
|
||||
@focus()
|
||||
|
||||
selectTextOnMouseMovement: ->
|
||||
moveHandler = (e) => @selectToPosition(@pointFromMouseEvent(e))
|
||||
moveHandler = (e) => @selectToScreenPosition(@screenPositionFromMouseEvent(e))
|
||||
@on 'mousemove', moveHandler
|
||||
$(document).one 'mouseup', => @off 'mousemove', moveHandler
|
||||
|
||||
@@ -132,9 +132,21 @@ class Editor extends View
|
||||
|
||||
renderLines: ->
|
||||
@lines.empty()
|
||||
for screenLine in @lineWrapper.getLines()
|
||||
for screenLine in @getScreenLines()
|
||||
@lines.append @buildLineElement(screenLine)
|
||||
|
||||
getScreenLines: ->
|
||||
@lineWrapper.getLines()
|
||||
|
||||
linesForScreenRows: (start, end) ->
|
||||
@lineWrapper.linesForScreenRows(start, end)
|
||||
|
||||
screenLineCount: ->
|
||||
@lineWrapper.lineCount()
|
||||
|
||||
lastScreenRow: ->
|
||||
@screenLineCount() - 1
|
||||
|
||||
setBuffer: (@buffer) ->
|
||||
@highlighter = new Highlighter(@buffer)
|
||||
@lineFolder = new LineFolder(@highlighter)
|
||||
@@ -146,9 +158,12 @@ class Editor extends View
|
||||
@buffer.on 'change', (e) =>
|
||||
@cursor.bufferChanged(e)
|
||||
|
||||
@lineFolder.on 'fold', (range) =>
|
||||
@setCursorBufferPosition(range.end)
|
||||
|
||||
@lineWrapper.on 'change', (e) =>
|
||||
{ oldRange, newRange } = e
|
||||
screenLines = @lineWrapper.linesForScreenRows(newRange.start.row, newRange.end.row)
|
||||
screenLines = @linesForScreenRows(newRange.start.row, newRange.end.row)
|
||||
if newRange.end.row > oldRange.end.row
|
||||
# update, then insert elements
|
||||
for row in [newRange.start.row..newRange.end.row]
|
||||
@@ -202,27 +217,30 @@ class Editor extends View
|
||||
else
|
||||
$(window).off 'resize', @_setMaxLineLength
|
||||
|
||||
clipPosition: ({row, column}) ->
|
||||
if row > @buffer.lastRow()
|
||||
row = @buffer.lastRow()
|
||||
column = @buffer.getLine(row).length
|
||||
else
|
||||
row = Math.min(Math.max(0, row), @buffer.numLines() - 1)
|
||||
column = Math.min(Math.max(0, column), @buffer.getLine(row).length)
|
||||
clipScreenPosition: (screenPosition, eagerWrap=false) ->
|
||||
@lineWrapper.clipScreenPosition(screenPosition, eagerWrap)
|
||||
|
||||
new Point(row, column)
|
||||
|
||||
pixelPositionFromPoint: (position) ->
|
||||
{ row, column } = @lineWrapper.screenPositionForBufferPosition(position)
|
||||
pixelPositionForScreenPosition: ({row, column}) ->
|
||||
{ top: row * @lineHeight, left: column * @charWidth }
|
||||
|
||||
pointFromPixelPosition: ({top, left}) ->
|
||||
screenPositionFromPixelPosition: ({top, left}) ->
|
||||
screenPosition = new Point(Math.floor(top / @lineHeight), Math.floor(left / @charWidth))
|
||||
@lineWrapper.bufferPositionForScreenPosition screenPosition
|
||||
|
||||
pointFromMouseEvent: (e) ->
|
||||
screenPositionForBufferPosition: (position) ->
|
||||
@lineWrapper.screenPositionForBufferPosition(position)
|
||||
|
||||
bufferPositionForScreenPosition: (position) ->
|
||||
@lineWrapper.bufferPositionForScreenPosition(position)
|
||||
|
||||
screenRangeForBufferRange: (range) ->
|
||||
@lineWrapper.screenRangeForBufferRange(range)
|
||||
|
||||
bufferRangeForScreenRange: (range) ->
|
||||
@lineWrapper.bufferRangeForScreenRange(range)
|
||||
|
||||
screenPositionFromMouseEvent: (e) ->
|
||||
{ pageX, pageY } = e
|
||||
@pointFromPixelPosition
|
||||
@screenPositionFromPixelPosition
|
||||
top: pageY - @lines.offset().top
|
||||
left: pageX - @lines.offset().left
|
||||
|
||||
@@ -254,8 +272,10 @@ class Editor extends View
|
||||
moveCursorDown: -> @cursor.moveDown()
|
||||
moveCursorRight: -> @cursor.moveRight()
|
||||
moveCursorLeft: -> @cursor.moveLeft()
|
||||
setCursorScreenPosition: (point) -> @cursor.setScreenPosition(point)
|
||||
setCursorScreenPosition: (position) -> @cursor.setScreenPosition(position)
|
||||
getCursorScreenPosition: -> @cursor.getScreenPosition()
|
||||
setCursorBufferPosition: (position) -> @cursor.setBufferPosition(position)
|
||||
getCursorBufferPosition: -> @cursor.getBufferPosition()
|
||||
setCursorRow: (row) -> @cursor.setRow(row)
|
||||
getCursorRow: -> @cursor.getRow()
|
||||
setCursorColumn: (column) -> @cursor.setColumn(column)
|
||||
@@ -265,8 +285,10 @@ class Editor extends View
|
||||
selectLeft: -> @selection.selectLeft()
|
||||
selectUp: -> @selection.selectUp()
|
||||
selectDown: -> @selection.selectDown()
|
||||
selectToPosition: (position) ->
|
||||
@selection.selectToPosition(position)
|
||||
selectToScreenPosition: (position) ->
|
||||
@selection.selectToScreenPosition(position)
|
||||
selectToBufferPosition: (position) ->
|
||||
@selection.selectToBufferPosition(position)
|
||||
|
||||
insertText: (text) -> @selection.insertText(text)
|
||||
insertNewline: -> @selection.insertNewline()
|
||||
|
||||
@@ -21,9 +21,7 @@ class LineFolder
|
||||
@lineMap.insertAtBufferRow(0, @highlighter.screenLines)
|
||||
|
||||
logLines: (start=0, end=@lastRow())->
|
||||
for row in [start..end]
|
||||
line = @lineForScreenRow(row).text
|
||||
console.log row, line, line.length
|
||||
@lineMap.logLines(start, end)
|
||||
|
||||
createFold: (bufferRange) ->
|
||||
fold = new Fold(this, bufferRange)
|
||||
@@ -116,7 +114,7 @@ class LineFolder
|
||||
@lineMap.lineForScreenRow(screenRow)
|
||||
|
||||
getLines: ->
|
||||
@lineMap.getScreenLines()
|
||||
@lineMap.screenLinesForRows(0, @lastRow())
|
||||
|
||||
lineCount: ->
|
||||
@lineMap.screenLineCount()
|
||||
@@ -136,12 +134,15 @@ class LineFolder
|
||||
bufferPositionForScreenPosition: (screenPosition) ->
|
||||
@lineMap.bufferPositionForScreenPosition(screenPosition)
|
||||
|
||||
clipScreenPosition: (screenPosition) ->
|
||||
@lineMap.clipScreenPosition(screenPosition)
|
||||
clipScreenPosition: (screenPosition, options={}) ->
|
||||
@lineMap.clipScreenPosition(screenPosition, options)
|
||||
|
||||
screenRangeForBufferRange: (bufferRange) ->
|
||||
@lineMap.screenRangeForBufferRange(bufferRange)
|
||||
|
||||
bufferRangeForScreenRange: (screenRange) ->
|
||||
@lineMap.bufferRangeForScreenRange(screenRange)
|
||||
|
||||
expandScreenRangeToLineEnds: (screenRange) ->
|
||||
{ start, end } = screenRange
|
||||
new Range([start.row, 0], [end.row, @lineMap.lineForScreenRow(end.row).text.length])
|
||||
|
||||
@@ -50,14 +50,10 @@ class LineMap
|
||||
replaceScreenRows: (start, end, screenLines) ->
|
||||
@spliceAtScreenRow(start, end - start + 1, screenLines)
|
||||
|
||||
getScreenLines: ->
|
||||
return @screenLines
|
||||
|
||||
lineForScreenRow: (row) ->
|
||||
@linesForScreenRows(row, row)[0]
|
||||
|
||||
linesForScreenRows: (startRow, endRow) ->
|
||||
lastLine = null
|
||||
lines = []
|
||||
delta = new Point
|
||||
|
||||
@@ -67,11 +63,13 @@ class LineMap
|
||||
if pendingFragment
|
||||
pendingFragment = pendingFragment.concat(fragment)
|
||||
else
|
||||
pendingFragment = fragment
|
||||
pendingFragment = _.clone(fragment)
|
||||
if pendingFragment.screenDelta.row > 0
|
||||
pendingFragment.bufferDelta = new Point(1, 0)
|
||||
lines.push pendingFragment
|
||||
pendingFragment = null
|
||||
delta = delta.add(fragment.screenDelta)
|
||||
|
||||
lines
|
||||
|
||||
lineForBufferRow: (row) ->
|
||||
@@ -99,6 +97,9 @@ class LineMap
|
||||
delta = delta.add(screenLine.screenDelta)
|
||||
delta.row
|
||||
|
||||
lastScreenRow: ->
|
||||
@screenLineCount() - 1
|
||||
|
||||
screenPositionForBufferPosition: (bufferPosition, eagerWrap=true) ->
|
||||
bufferPosition = Point.fromObject(bufferPosition)
|
||||
bufferDelta = new Point
|
||||
@@ -135,18 +136,52 @@ class LineMap
|
||||
end = @screenPositionForBufferPosition(bufferRange.end)
|
||||
new Range(start, end)
|
||||
|
||||
clipScreenPosition: (screenPosition) ->
|
||||
bufferRangeForScreenRange: (screenRange) ->
|
||||
start = @bufferPositionForScreenPosition(screenRange.start)
|
||||
end = @bufferPositionForScreenPosition(screenRange.end)
|
||||
new Range(start, end)
|
||||
|
||||
clipScreenPosition: (screenPosition, options) ->
|
||||
wrapBeyondNewlines = options.wrapBeyondNewlines ? false
|
||||
wrapAtSoftNewlines = options.wrapAtSoftNewlines ? false
|
||||
skipAtomicTokens = options.skipAtomicTokens ? false
|
||||
screenPosition = Point.fromObject(screenPosition)
|
||||
screenPosition = new Point(Math.max(0, screenPosition.row), Math.max(0, screenPosition.column))
|
||||
|
||||
screenPosition.column = Math.max(0, screenPosition.column)
|
||||
|
||||
if screenPosition.row < 0
|
||||
screenPosition.row = 0
|
||||
screenPosition.column = 0
|
||||
|
||||
if screenPosition.row > @lastScreenRow()
|
||||
screenPosition.row = @lastScreenRow()
|
||||
screenPosition.column = Infinity
|
||||
|
||||
screenDelta = new Point
|
||||
for screenLine in @screenLines
|
||||
nextDelta = screenDelta.add(screenLine.screenDelta)
|
||||
for lineFragment in @screenLines
|
||||
nextDelta = screenDelta.add(lineFragment.screenDelta)
|
||||
break if nextDelta.isGreaterThan(screenPosition)
|
||||
screenDelta = nextDelta
|
||||
|
||||
maxColumn = screenDelta.column + screenLine.lengthForClipping()
|
||||
screenDelta.column = Math.min(maxColumn, screenPosition.column)
|
||||
if lineFragment.isAtomic
|
||||
if skipAtomicTokens and screenPosition.column > screenDelta.column
|
||||
return new Point(screenDelta.row, screenDelta.column + lineFragment.text.length)
|
||||
else
|
||||
return screenDelta
|
||||
|
||||
screenDelta
|
||||
maxColumn = screenDelta.column + lineFragment.text.length
|
||||
if lineFragment.isSoftWrapped() and screenPosition.column >= maxColumn
|
||||
if wrapAtSoftNewlines
|
||||
return new Point(screenDelta.row + 1, 0)
|
||||
else
|
||||
return new Point(screenDelta.row, maxColumn - 1)
|
||||
|
||||
if screenPosition.column > maxColumn and wrapBeyondNewlines
|
||||
return new Point(screenDelta.row + 1, 0)
|
||||
|
||||
new Point(screenDelta.row, Math.min(maxColumn, screenPosition.column))
|
||||
|
||||
logLines: (start=0, end=@screenLineCount() - 1)->
|
||||
for row in [start..end]
|
||||
line = @lineForScreenRow(row).text
|
||||
console.log row, line, line.length
|
||||
|
||||
@@ -76,9 +76,6 @@ class LineWrapper
|
||||
return column + 1 if /\s/.test(line[column])
|
||||
return @maxLength
|
||||
|
||||
screenRangeForBufferRange: (bufferRange) ->
|
||||
@lineMap.screenRangeForBufferRange(bufferRange)
|
||||
|
||||
screenPositionForBufferPosition: (bufferPosition, eagerWrap=true) ->
|
||||
@lineMap.screenPositionForBufferPosition(
|
||||
@lineFolder.screenPositionForBufferPosition(bufferPosition),
|
||||
@@ -88,6 +85,22 @@ class LineWrapper
|
||||
@lineFolder.bufferPositionForScreenPosition(
|
||||
@lineMap.bufferPositionForScreenPosition(screenPosition))
|
||||
|
||||
screenRangeForBufferRange: (bufferRange) ->
|
||||
@lineMap.screenRangeForBufferRange(
|
||||
@lineFolder.screenRangeForBufferRange(bufferRange))
|
||||
|
||||
bufferRangeForScreenRange: (screenRange) ->
|
||||
@lineFolder.bufferRangeForScreenRange(
|
||||
@lineMap.bufferRangeForScreenRange(screenRange))
|
||||
|
||||
clipScreenPosition: (screenPosition, options={}) ->
|
||||
@lineMap.screenPositionForBufferPosition(
|
||||
@lineFolder.clipScreenPosition(
|
||||
@lineMap.bufferPositionForScreenPosition(@lineMap.clipScreenPosition(screenPosition, options)),
|
||||
options
|
||||
)
|
||||
)
|
||||
|
||||
lineForScreenRow: (screenRow) ->
|
||||
@linesForScreenRows(screenRow, screenRow)[0]
|
||||
|
||||
@@ -95,9 +108,15 @@ class LineWrapper
|
||||
@lineMap.linesForScreenRows(startRow, endRow)
|
||||
|
||||
getLines: ->
|
||||
@linesForScreenRows(0, @lineCount() - 1)
|
||||
@linesForScreenRows(0, @lastRow())
|
||||
|
||||
lineCount: ->
|
||||
@lineMap.screenLineCount()
|
||||
|
||||
lastRow: ->
|
||||
@lineCount() - 1
|
||||
|
||||
logLines: (start=0, end=@lineCount() - 1)->
|
||||
@lineMap.logLines(start, end)
|
||||
|
||||
_.extend(LineWrapper.prototype, EventEmitter)
|
||||
|
||||
@@ -52,5 +52,8 @@ class ScreenLineFragment
|
||||
else
|
||||
@text.length
|
||||
|
||||
isSoftWrapped: ->
|
||||
@screenDelta.row == 1 and @bufferDelta.row == 0
|
||||
|
||||
isEqual: (other) ->
|
||||
_.isEqual(@tokens, other.tokens) and @screenDelta.isEqual(other.screenDelta) and @bufferDelta.isEqual(other.bufferDelta)
|
||||
|
||||
@@ -60,35 +60,38 @@ class Selection extends View
|
||||
region.remove() for region in @regions
|
||||
@regions = []
|
||||
|
||||
getRange: ->
|
||||
getScreenRange: ->
|
||||
if @anchor
|
||||
new Range(@anchor.getScreenPosition(), @cursor.getScreenPosition())
|
||||
else
|
||||
new Range(@cursor.getScreenPosition(), @cursor.getScreenPosition())
|
||||
|
||||
setRange: (range) ->
|
||||
setScreenRange: (range) ->
|
||||
@cursor.setScreenPosition(range.start)
|
||||
@modifySelection =>
|
||||
@cursor.setScreenPosition(range.end)
|
||||
|
||||
getScreenRange: ->
|
||||
@editor.lineWrapper.screenRangeForBufferRange(@getRange())
|
||||
getBufferRange: ->
|
||||
@editor.bufferRangeForScreenRange(@getScreenRange())
|
||||
|
||||
setBufferRange: (bufferRange) ->
|
||||
@setScreenRange(@editor.screenRangeForBufferRange(bufferRange))
|
||||
|
||||
getText: ->
|
||||
@editor.buffer.getTextInRange @getRange()
|
||||
@editor.buffer.getTextInRange @getBufferRange()
|
||||
|
||||
insertText: (text) ->
|
||||
@editor.buffer.change(@getRange(), text)
|
||||
@editor.buffer.change(@getBufferRange(), text)
|
||||
|
||||
insertNewline: ->
|
||||
@insertText('\n')
|
||||
|
||||
delete: ->
|
||||
range = @getRange()
|
||||
range = @getBufferRange()
|
||||
@editor.buffer.change(range, '') unless range.isEmpty()
|
||||
|
||||
isEmpty: ->
|
||||
@getRange().isEmpty()
|
||||
@getBufferRange().isEmpty()
|
||||
|
||||
modifySelection: (fn) ->
|
||||
@placeAnchor()
|
||||
@@ -114,11 +117,11 @@ class Selection extends View
|
||||
endOffset = regex.exec(rightSide)?[0]?.length or 0
|
||||
|
||||
range = new Range([row, column + startOffset], [row, column + endOffset])
|
||||
@setRange range
|
||||
@setBufferRange range
|
||||
|
||||
selectLine: (row) ->
|
||||
rowLength = @editor.buffer.getLine(row).length
|
||||
@setRange new Range([row, 0], [row, rowLength])
|
||||
@setBufferRange new Range([row, 0], [row, rowLength])
|
||||
|
||||
selectRight: ->
|
||||
@modifySelection =>
|
||||
@@ -140,10 +143,14 @@ class Selection extends View
|
||||
@modifySelection =>
|
||||
@cursor.moveLeftUntilMatch(regex)
|
||||
|
||||
selectToPosition: (position) ->
|
||||
selectToScreenPosition: (position) ->
|
||||
@modifySelection =>
|
||||
@cursor.setScreenPosition(position)
|
||||
|
||||
selectToBufferPosition: (position) ->
|
||||
@modifySelection =>
|
||||
@cursor.setBufferPosition(position)
|
||||
|
||||
moveCursorToLineEnd: ->
|
||||
@cursor.moveToLineEnd()
|
||||
|
||||
@@ -156,8 +163,8 @@ class Selection extends View
|
||||
|
||||
copy: ->
|
||||
return if @isEmpty()
|
||||
text = @editor.buffer.getTextInRange @getRange()
|
||||
text = @editor.buffer.getTextInRange(@getBufferRange())
|
||||
atom.native.writeToPasteboard text
|
||||
|
||||
fold: ->
|
||||
@editor.lineFolder.createFold(@getRange())
|
||||
@editor.lineFolder.createFold(@getBufferRange())
|
||||
|
||||
@@ -13,7 +13,7 @@ class MoveLeft extends Motion
|
||||
select: ->
|
||||
position = @editor.getCursorScreenPosition()
|
||||
position.column-- if position.column > 0
|
||||
@editor.selectToPosition position
|
||||
@editor.selectToBufferPosition(position)
|
||||
|
||||
class MoveRight extends Motion
|
||||
execute: ->
|
||||
@@ -42,7 +42,7 @@ class MoveToNextWord extends Motion
|
||||
@editor.setCursorScreenPosition(@nextWordPosition())
|
||||
|
||||
select: ->
|
||||
@editor.selectToPosition(@nextWordPosition())
|
||||
@editor.selectToBufferPosition(@nextWordPosition())
|
||||
|
||||
nextWordPosition: ->
|
||||
regex = getWordRegex()
|
||||
|
||||
Reference in New Issue
Block a user