mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
Add TokenizedBuffer.bufferRangeForScopeAtPosition(selector, position)
You can call this method with a selector and a position and get the range of any matching scope containing the given position, or a falsy value if the scope does not match at that position.
This commit is contained in:
@@ -396,3 +396,21 @@ describe "TokenizedBuffer", ->
|
||||
expect(tokenizedBuffer.tokenForPosition([1,0]).scopes).toEqual ["source.js"]
|
||||
expect(tokenizedBuffer.tokenForPosition([1,1]).scopes).toEqual ["source.js"]
|
||||
expect(tokenizedBuffer.tokenForPosition([1,2]).scopes).toEqual ["source.js", "storage.modifier.js"]
|
||||
|
||||
describe ".bufferRangeForScopeAtPosition(selector, position)", ->
|
||||
beforeEach ->
|
||||
buffer = project.bufferForPath('sample.js')
|
||||
tokenizedBuffer = new TokenizedBuffer(buffer)
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
describe "when the selector does not match the token at the position", ->
|
||||
it "returns a falsy value", ->
|
||||
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.bogus', [0, 1])).toBeFalsy()
|
||||
|
||||
describe "when the selector matches a single token at the position", ->
|
||||
it "returns the range covered by the token", ->
|
||||
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.storage.modifier.js', [0, 1])).toEqual [[0, 0], [0, 3]]
|
||||
|
||||
describe "when the selector matches a run of multiple tokens at the position", ->
|
||||
it "returns the range covered by all contigous tokens (within a single line)", ->
|
||||
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.function', [1, 18])).toEqual [[1, 6], [1, 28]]
|
||||
|
||||
@@ -109,6 +109,12 @@ class Token
|
||||
isOnlyWhitespace: ->
|
||||
not /\S/.test(@value)
|
||||
|
||||
matchesScopeSelector: (selector) ->
|
||||
targetClasses = selector.replace(/^\.?/, '').split('.')
|
||||
_.any @scopes, (scope) ->
|
||||
scopeClasses = scope.split('.')
|
||||
_.isSubset(targetClasses, scopeClasses)
|
||||
|
||||
getValueAsHtml: ({invisibles, hasLeadingWhitespace, hasTrailingWhitespace, hasIndentGuide})->
|
||||
invisibles ?= {}
|
||||
html = @value
|
||||
|
||||
@@ -200,8 +200,34 @@ class TokenizedBuffer
|
||||
@tokenForPosition(position).scopes
|
||||
|
||||
tokenForPosition: (position) ->
|
||||
{row, column} = Point.fromObject(position)
|
||||
@tokenizedLines[row].tokenAtBufferColumn(column)
|
||||
|
||||
tokenStartPositionForPosition: (position) ->
|
||||
{row, column} = Point.fromObject(position)
|
||||
column = @tokenizedLines[row].tokenStartColumnForBufferColumn(column)
|
||||
new Point(row, column)
|
||||
|
||||
bufferRangeForScopeAtPosition: (selector, position) ->
|
||||
position = Point.fromObject(position)
|
||||
@tokenizedLines[position.row].tokenAtBufferColumn(position.column)
|
||||
tokenizedLine = @tokenizedLines[position.row]
|
||||
startIndex = tokenizedLine.tokenIndexAtBufferColumn(position.column)
|
||||
|
||||
for index in [startIndex..0]
|
||||
token = tokenizedLine.tokenAtIndex(index)
|
||||
break unless token.matchesScopeSelector(selector)
|
||||
firstToken = token
|
||||
|
||||
for index in [startIndex...tokenizedLine.getTokenCount()]
|
||||
token = tokenizedLine.tokenAtIndex(index)
|
||||
break unless token.matchesScopeSelector(selector)
|
||||
lastToken = token
|
||||
|
||||
return unless firstToken? and lastToken?
|
||||
|
||||
startColumn = tokenizedLine.bufferColumnForToken(firstToken)
|
||||
endColumn = tokenizedLine.bufferColumnForToken(lastToken) + lastToken.bufferDelta
|
||||
new Range([position.row, startColumn], [position.row, endColumn])
|
||||
|
||||
destroy: ->
|
||||
@unsubscribe()
|
||||
|
||||
@@ -90,11 +90,22 @@ class TokenizedLine
|
||||
@lineEnding is null
|
||||
|
||||
tokenAtBufferColumn: (bufferColumn) ->
|
||||
@tokens[@tokenIndexAtBufferColumn(bufferColumn)]
|
||||
|
||||
tokenIndexAtBufferColumn: (bufferColumn) ->
|
||||
delta = 0
|
||||
for token, index in @tokens
|
||||
delta += token.bufferDelta
|
||||
return index if delta > bufferColumn
|
||||
index - 1
|
||||
|
||||
tokenStartColumnForBufferColumn: (bufferColumn) ->
|
||||
delta = 0
|
||||
for token in @tokens
|
||||
delta += token.bufferDelta
|
||||
return token if delta > bufferColumn
|
||||
token
|
||||
nextDelta = delta + token.bufferDelta
|
||||
break if nextDelta > bufferColumn
|
||||
delta = nextDelta
|
||||
delta
|
||||
|
||||
breakOutAtomicTokens: (inputTokens, tabLength) ->
|
||||
outputTokens = []
|
||||
@@ -112,3 +123,15 @@ class TokenizedLine
|
||||
return true if _.contains(scope.split('.'), 'comment')
|
||||
break
|
||||
false
|
||||
|
||||
tokenAtIndex: (index) ->
|
||||
@tokens[index]
|
||||
|
||||
getTokenCount: ->
|
||||
@tokens.length
|
||||
|
||||
bufferColumnForToken: (targetToken) ->
|
||||
column = 0
|
||||
for token in @tokens
|
||||
return column if token is targetToken
|
||||
column += token.bufferDelta
|
||||
|
||||
Reference in New Issue
Block a user