Render end-of-line invisibles based on state of TokenizedLine

This commit is contained in:
Nathan Sobo
2014-08-12 11:20:12 -06:00
parent 742ec6df0d
commit 63f2ab3088
2 changed files with 20 additions and 28 deletions

View File

@@ -211,7 +211,7 @@ describe "EditorComponent", ->
atom.config.set("editor.invisibles", invisibles)
it "re-renders the lines when the showInvisibles config option changes", ->
editor.setText " a line with tabs\tand spaces "
editor.setText " a line with tabs\tand spaces \n"
nextAnimationFrame()
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab}and spaces#{invisibles.space}#{invisibles.eol}"
@@ -222,7 +222,7 @@ describe "EditorComponent", ->
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab}and spaces#{invisibles.space}#{invisibles.eol}"
it "displays leading/trailing spaces, tabs, and newlines as visible characters", ->
editor.setText " a line with tabs\tand spaces "
editor.setText " a line with tabs\tand spaces \n"
nextAnimationFrame()
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab}and spaces#{invisibles.space}#{invisibles.eol}"
@@ -231,7 +231,7 @@ describe "EditorComponent", ->
expect(leafNodes[leafNodes.length - 1].classList.contains('invisible-character')).toBe true
it "displays newlines as their own token outside of the other tokens' scopes", ->
editor.setText "var"
editor.setText "var\n"
nextAnimationFrame()
expect(component.lineNodeForScreenRow(0).innerHTML).toBe "<span class=\"source js\"><span class=\"storage modifier js\">var</span></span><span class=\"invisible-character\">#{invisibles.eol}</span>"
@@ -272,7 +272,7 @@ describe "EditorComponent", ->
describe "when soft wrapping is enabled", ->
beforeEach ->
editor.setText "a line that wraps "
editor.setText "a line that wraps \n"
editor.setSoftWrap(true)
nextAnimationFrame()
componentNode.style.width = 16 * charWidth + editor.getVerticalScrollbarWidth() + 'px'

View File

@@ -60,7 +60,7 @@ LinesComponent = React.createClass
shouldComponentUpdate: (newProps) ->
return true unless isEqualForProperties(newProps, @props,
'renderedRowRange', 'lineDecorations', 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth',
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'invisibles', 'visible',
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'visible',
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount', 'lineWidth', 'useHardwareAcceleration',
'placeholderText', 'performedInitialMeasurement', 'backgroundColor', 'cursorPixelRects'
)
@@ -82,7 +82,7 @@ LinesComponent = React.createClass
return unless performedInitialMeasurement
@clearScreenRowCaches() unless prevProps.lineHeightInPixels is @props.lineHeightInPixels
@removeLineNodes() unless isEqualForProperties(prevProps, @props, 'showIndentGuide', 'invisibles')
@removeLineNodes() unless isEqualForProperties(prevProps, @props, 'showIndentGuide')
@updateLines(@props.lineWidth isnt prevProps.lineWidth)
@measureCharactersInNewLines() if visible and not scrollingVertically
@@ -170,34 +170,30 @@ LinesComponent = React.createClass
lineHTML
buildEmptyLineInnerHTML: (line) ->
{showIndentGuide, invisibles} = @props
{cr, eol} = invisibles
{indentLevel, tabLength} = line
{showIndentGuide} = @props
{indentLevel, tabLength, endOfLineInvisibles} = line
if showIndentGuide and indentLevel > 0
invisiblesToRender = []
invisiblesToRender.push(cr) if cr? and line.lineEnding is '\r\n'
invisiblesToRender.push(eol) if eol?
invisibleIndex = 0
lineHTML = ''
for i in [0...indentLevel]
lineHTML += "<span class='indent-guide'>"
for j in [0...tabLength]
if invisible = invisiblesToRender.shift()
if invisible = endOfLineInvisibles?[invisibleIndex++]
lineHTML += "<span class='invisible-character'>#{invisible}</span>"
else
lineHTML += ' '
lineHTML += "</span>"
while invisiblesToRender.length
lineHTML += "<span class='invisible-character'>#{invisiblesToRender.shift()}</span>"
while invisibleIndex < endOfLineInvisibles?.length
lineHTML += "<span class='invisible-character'>#{line.endOfLineInvisibles[invisibleIndex++]}</span>"
lineHTML
else
@buildEndOfLineHTML(line, @props.invisibles) or '&nbsp;'
@buildEndOfLineHTML(line) or '&nbsp;'
buildLineInnerHTML: (line) ->
{invisibles, mini, showIndentGuide, invisibles} = @props
{mini, showIndentGuide, invisibles} = @props
{tokens, text} = line
innerHTML = ""
@@ -210,20 +206,16 @@ LinesComponent = React.createClass
innerHTML += token.getValueAsHtml({invisibles, hasIndentGuide})
innerHTML += @popScope(scopeStack) while scopeStack.length > 0
innerHTML += @buildEndOfLineHTML(line, invisibles)
innerHTML += @buildEndOfLineHTML(line)
innerHTML
buildEndOfLineHTML: (line, invisibles) ->
return '' if @props.mini or line.isSoftWrapped()
buildEndOfLineHTML: (line) ->
{endOfLineInvisibles} = line
html = ''
# Note the lack of '?' in the character checks. A user can set the chars
# to an empty string which we will interpret as not-set
if invisibles.cr and line.lineEnding is '\r\n'
html += "<span class='invisible-character'>#{invisibles.cr}</span>"
if invisibles.eol
html += "<span class='invisible-character'>#{invisibles.eol}</span>"
if endOfLineInvisibles?
for invisible in endOfLineInvisibles
html += "<span class='invisible-character'>#{invisible}</span>"
html
updateScopeStack: (scopeStack, desiredScopes) ->