_ = require 'underscore'
module.exports =
class Token
value: null
scopes: null
isAtomic: null
isHardTab: null
### Internal ###
constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @isHardTab}) ->
@screenDelta = @value.length
@bufferDelta ?= @screenDelta
### Public ###
isEqual: (other) ->
@value == other.value and _.isEqual(@scopes, other.scopes) and !!@isAtomic == !!other.isAtomic
isBracket: ->
/^meta\.brace\b/.test(_.last(@scopes))
splitAt: (splitIndex) ->
value1 = @value.substring(0, splitIndex)
value2 = @value.substring(splitIndex)
[new Token(value: value1, scopes: @scopes), new Token(value: value2, scopes: @scopes)]
breakOutAtomicTokens: (tabLength, breakOutLeadingWhitespace) ->
if breakOutLeadingWhitespace
return [this] unless /^[ ]|\t/.test(@value)
else
return [this] unless /\t/.test(@value)
outputTokens = []
regex = new RegExp("([ ]{#{tabLength}})|(\t)|([^\t]+)", "g")
while match = regex.exec(@value)
[fullMatch, softTab, hardTab] = match
if softTab and breakOutLeadingWhitespace
outputTokens.push(@buildSoftTabToken(tabLength, false))
else if hardTab
breakOutLeadingWhitespace = false
outputTokens.push(@buildHardTabToken(tabLength, true))
else
breakOutLeadingWhitespace = false
outputTokens.push(new Token(value: match[0], scopes: @scopes))
outputTokens
buildHardTabToken: (tabLength) ->
@buildTabToken(tabLength, true)
buildSoftTabToken: (tabLength) ->
@buildTabToken(tabLength, false)
buildTabToken: (tabLength, isHardTab) ->
new Token(
value: _.multiplyString(" ", tabLength)
scopes: @scopes
bufferDelta: if isHardTab then 1 else tabLength
isAtomic: true
isHardTab: isHardTab
)
isOnlyWhitespace: ->
not /\S/.test(@value)
getValueAsHtml: ({invisibles, hasLeadingWhitespace, hasTrailingWhitespace, hasIndentGuide})->
invisibles ?= {}
html = @value
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(//g, '>')
if @isHardTab
classes = []
classes.push('indent-guide') if hasIndentGuide
classes.push('invisible-character') if invisibles.tab
classes.push('hard-tab')
classes = classes.join(' ')
html = html.replace /^./, (match) ->
match = invisibles.tab ? match
"#{match}"
else
if hasLeadingWhitespace
classes = []
classes.push('indent-guide') if hasIndentGuide
classes.push('invisible-character') if invisibles.space
classes.push('leading-whitespace')
classes = classes.join(' ')
html = html.replace /^[ ]+/, (match) ->
match = match.replace(/./g, invisibles.space) if invisibles.space
"#{match}"
if hasTrailingWhitespace
classes = []
classes.push('indent-guide') if hasIndentGuide and not hasLeadingWhitespace
classes.push('invisible-character') if invisibles.space
classes.push('trailing-whitespace')
classes = classes.join(' ')
html = html.replace /[ ]+$/, (match) ->
match = match.replace(/./g, invisibles.space) if invisibles.space
"#{match}"
html