From cbe07b49aa22df3b26ee3e51c19aeb48fb26068e Mon Sep 17 00:00:00 2001 From: probablycorey Date: Mon, 19 May 2014 16:20:51 -0700 Subject: [PATCH 01/18] Add basic invisible specs --- spec/editor-component-spec.coffee | 26 ++++++++++++++++++++++++++ src/lines-component.coffee | 7 +++++++ 2 files changed, 33 insertions(+) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 28f740531..e150baf49 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -88,6 +88,32 @@ describe "EditorComponent", -> expect(component.lineNodeForScreenRow(3).offsetTop).toBe 3 * lineHeightInPixels expect(component.lineNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels + describe "when showInvisibles is enabled", -> + beforeEach -> + atom.config.set("editor.showInvisibles", true) + + it "displays spaces, tabs, and newlines as visible charachters", -> + editor.setText " a line with tabs\tand spaces " + eol = '\u00ac' + space = '\u00b7' + tab = '\u00bb' + cr = '\u00a4' + expect(component.lineNodeForScreenRow(0).textContent).toBe "#{space}a line with tabs#{tab} and spaces#{space}#{eol}" + + it "displays newlines as their own token outside of the other tokens scope", -> + + it "allows invisible glyphs to be customized via the editor.invisibles config", -> + + it "displays trailing carriage return using a visible non-empty value", -> + + describe "when soft wrapping is enabled", -> + beforeEach -> + editor.setSoftWrap(true) + + it "doesn't show the end of line invisible at the end of lines broken due to wrapping", -> + + it "displays trailing carriage return using a visible non-empty value", -> + describe "when indent guides are enabled", -> beforeEach -> component.setShowIndentGuide(true) diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 1cae8b8fb..72b1ca730 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -140,6 +140,12 @@ LinesComponent = React.createClass innerHTML = "" scopeStack = [] + invisibles = + eol: '\u00ac' + space: '\u00b7' + tab: '\u00bb' + cr: '\u00a4' + firstTrailingWhitespacePosition = text.search(/\s*$/) lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0 for token in tokens @@ -147,6 +153,7 @@ LinesComponent = React.createClass hasIndentGuide = not mini and showIndentGuide and token.hasLeadingWhitespace or (token.hasTrailingWhitespace and lineIsWhitespaceOnly) innerHTML += token.getValueAsHtml({invisibles, hasIndentGuide}) innerHTML += @popScope(scopeStack) while scopeStack.length > 0 + innerHTML += invisibles.eol innerHTML updateScopeStack: (scopeStack, desiredScopes) -> From 09e4c585aa4b5f45f273c7c9d889801efc89f421 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Mon, 19 May 2014 16:56:17 -0700 Subject: [PATCH 02/18] Add setInvisibles method --- src/editor-component.coffee | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 9a30ab6ca..ecaf68870 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -1,6 +1,6 @@ React = require 'react' {div, span} = require 'reactionary' -{debounce} = require 'underscore-plus' +{debounce, defaults} = require 'underscore-plus' scrollbarStyle = require 'scrollbar-style' GutterComponent = require './gutter-component' @@ -268,6 +268,7 @@ EditorComponent = React.createClass @subscribe atom.config.observe 'editor.fontFamily', @setFontFamily @subscribe atom.config.observe 'editor.fontSize', @setFontSize @subscribe atom.config.observe 'editor.showIndentGuide', @setShowIndentGuide + @subscribe atom.config.observe 'editor.invisibles', @setInvisibles measureScrollbars: -> @measuringScrollbars = false @@ -291,6 +292,22 @@ EditorComponent = React.createClass setShowIndentGuide: (showIndentGuide) -> @setState({showIndentGuide}) + # Public: Defines which characters are invisible. + # + # invisibles - An {Object} defining the invisible characters: + # :eol - The end of line invisible {String} (default: `\u00ac`). + # :space - The space invisible {String} (default: `\u00b7`). + # :tab - The tab invisible {String} (default: `\u00bb`). + # :cr - The carriage return invisible {String} (default: `\u00a4`). + setInvisibles: (invisibles={}) -> + defaults invisibles, + eol: '\u00ac' + space: '\u00b7' + tab: '\u00bb' + cr: '\u00a4' + + @setState({invisibles}) + onFocus: -> @refs.scrollView.focus() From 73ce81d59725c849dfdcea2159315bb4db4dc06a Mon Sep 17 00:00:00 2001 From: probablycorey Date: Mon, 19 May 2014 16:56:53 -0700 Subject: [PATCH 03/18] Pass invisibles down to lines component --- spec/editor-component-spec.coffee | 15 ++++++++++----- src/editor-component.coffee | 4 ++-- src/editor-scroll-view-component.coffee | 4 ++-- src/lines-component.coffee | 8 +------- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index e150baf49..3d9056498 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -89,16 +89,21 @@ describe "EditorComponent", -> expect(component.lineNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels describe "when showInvisibles is enabled", -> + invisibles = null + beforeEach -> atom.config.set("editor.showInvisibles", true) + invisibles = + eol: 'E' + space: 'S' + tab: 'T' + cr: 'C' + + component.setInvisibles(invisibles) it "displays spaces, tabs, and newlines as visible charachters", -> editor.setText " a line with tabs\tand spaces " - eol = '\u00ac' - space = '\u00b7' - tab = '\u00bb' - cr = '\u00a4' - expect(component.lineNodeForScreenRow(0).textContent).toBe "#{space}a line with tabs#{tab} and spaces#{space}#{eol}" + expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}" it "displays newlines as their own token outside of the other tokens scope", -> diff --git a/src/editor-component.coffee b/src/editor-component.coffee index ecaf68870..28c045a95 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -31,7 +31,7 @@ EditorComponent = React.createClass mouseWheelScreenRow: null render: -> - {focused, fontSize, lineHeight, fontFamily, showIndentGuide} = @state + {focused, fontSize, lineHeight, fontFamily, showIndentGuide, invisibles} = @state {editor, cursorBlinkResumeDelay} = @props maxLineNumberDigits = editor.getScreenLineCount().toString().length @@ -62,7 +62,7 @@ EditorComponent = React.createClass lineHeight: lineHeightInPixels, renderedRowRange, @pendingChanges, scrollTop, scrollLeft, scrollHeight, scrollWidth, @scrollingVertically, @cursorsMoved, @selectionChanged, @selectionAdded, cursorBlinkResumeDelay, - @onInputFocused, @onInputBlurred, @mouseWheelScreenRow + @onInputFocused, @onInputBlurred, @mouseWheelScreenRow, invisibles } ScrollbarComponent diff --git a/src/editor-scroll-view-component.coffee b/src/editor-scroll-view-component.coffee index 1363c5e67..eee2a1fe3 100644 --- a/src/editor-scroll-view-component.coffee +++ b/src/editor-scroll-view-component.coffee @@ -16,7 +16,7 @@ EditorScrollViewComponent = React.createClass overflowChangedWhilePaused: false render: -> - {editor, fontSize, fontFamily, lineHeight, showIndentGuide} = @props + {editor, fontSize, fontFamily, lineHeight, showIndentGuide, invisibles} = @props {renderedRowRange, pendingChanges, scrollTop, scrollLeft, scrollHeight, scrollWidth, scrollingVertically, mouseWheelScreenRow} = @props {selectionChanged, selectionAdded, cursorBlinkResumeDelay, cursorsMoved, onInputFocused, onInputBlurred} = @props @@ -37,7 +37,7 @@ EditorScrollViewComponent = React.createClass LinesComponent { ref: 'lines', editor, fontSize, fontFamily, lineHeight, showIndentGuide, renderedRowRange, pendingChanges, scrollTop, scrollLeft, scrollingVertically, - selectionChanged, scrollHeight, scrollWidth, mouseWheelScreenRow + selectionChanged, scrollHeight, scrollWidth, mouseWheelScreenRow, invisibles } componentDidMount: -> diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 72b1ca730..1f48ce003 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -135,17 +135,11 @@ LinesComponent = React.createClass " " buildLineInnerHTML: (line) -> - {invisibles, mini, showIndentGuide} = @props + {invisibles, mini, showIndentGuide, invisibles} = @props {tokens, text} = line innerHTML = "" scopeStack = [] - invisibles = - eol: '\u00ac' - space: '\u00b7' - tab: '\u00bb' - cr: '\u00a4' - firstTrailingWhitespacePosition = text.search(/\s*$/) lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0 for token in tokens From 8b4cff474f6c48d57dee3e4507640cf25f9d1c67 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Mon, 19 May 2014 17:10:04 -0700 Subject: [PATCH 04/18] Spec :lipstick: --- spec/editor-component-spec.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 3d9056498..8a7d22421 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -92,14 +92,14 @@ describe "EditorComponent", -> invisibles = null beforeEach -> - atom.config.set("editor.showInvisibles", true) invisibles = eol: 'E' space: 'S' tab: 'T' cr: 'C' - component.setInvisibles(invisibles) + atom.config.set("editor.showInvisibles", true) + atom.config.set("editor.invisibles", invisibles) it "displays spaces, tabs, and newlines as visible charachters", -> editor.setText " a line with tabs\tand spaces " From 4d642b91ef30569bd93ffd7130d066755b2bdef2 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Mon, 19 May 2014 17:10:36 -0700 Subject: [PATCH 05/18] Only pass invisibles through to the line component if needed --- src/editor-component.coffee | 7 ++++++- src/lines-component.coffee | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 28c045a95..dc07b9613 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -31,9 +31,10 @@ EditorComponent = React.createClass mouseWheelScreenRow: null render: -> - {focused, fontSize, lineHeight, fontFamily, showIndentGuide, invisibles} = @state + {focused, fontSize, lineHeight, fontFamily, showIndentGuide, showInvisibles} = @state {editor, cursorBlinkResumeDelay} = @props maxLineNumberDigits = editor.getScreenLineCount().toString().length + invisibles = if showInvisibles then @state.invisibles else {} if @isMounted() renderedRowRange = @getRenderedRowRange() @@ -269,6 +270,7 @@ EditorComponent = React.createClass @subscribe atom.config.observe 'editor.fontSize', @setFontSize @subscribe atom.config.observe 'editor.showIndentGuide', @setShowIndentGuide @subscribe atom.config.observe 'editor.invisibles', @setInvisibles + @subscribe atom.config.observe 'editor.showInvisibles', @setShowInvisibles measureScrollbars: -> @measuringScrollbars = false @@ -308,6 +310,9 @@ EditorComponent = React.createClass @setState({invisibles}) + setShowInvisibles: (showInvisibles) -> + @setState({showInvisibles}) + onFocus: -> @refs.scrollView.focus() diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 1f48ce003..27a3c0660 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -147,7 +147,7 @@ LinesComponent = React.createClass hasIndentGuide = not mini and showIndentGuide and token.hasLeadingWhitespace or (token.hasTrailingWhitespace and lineIsWhitespaceOnly) innerHTML += token.getValueAsHtml({invisibles, hasIndentGuide}) innerHTML += @popScope(scopeStack) while scopeStack.length > 0 - innerHTML += invisibles.eol + innerHTML += invisibles.eol if invisibles.eol? innerHTML updateScopeStack: (scopeStack, desiredScopes) -> From 9b5593d020089aba457cae0afccbc6da244afe2f Mon Sep 17 00:00:00 2001 From: probablycorey Date: Mon, 19 May 2014 17:27:59 -0700 Subject: [PATCH 06/18] Put EOL invisibles into their own scope --- spec/editor-component-spec.coffee | 2 ++ src/lines-component.coffee | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 8a7d22421..c9ccab8bd 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -106,6 +106,8 @@ describe "EditorComponent", -> expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}" it "displays newlines as their own token outside of the other tokens scope", -> + editor.setText "var" + expect(component.lineNodeForScreenRow(0).innerHTML).toBe "var#{invisibles.eol}" it "allows invisible glyphs to be customized via the editor.invisibles config", -> diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 27a3c0660..8de0963ee 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -146,8 +146,9 @@ LinesComponent = React.createClass innerHTML += @updateScopeStack(scopeStack, token.scopes) hasIndentGuide = not mini and showIndentGuide and token.hasLeadingWhitespace or (token.hasTrailingWhitespace and lineIsWhitespaceOnly) innerHTML += token.getValueAsHtml({invisibles, hasIndentGuide}) + innerHTML += @popScope(scopeStack) while scopeStack.length > 0 - innerHTML += invisibles.eol if invisibles.eol? + innerHTML += "#{invisibles.eol}" innerHTML updateScopeStack: (scopeStack, desiredScopes) -> From 273203e4c9aef40277d82aab80a4d4e8ffa84106 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 20 May 2014 10:37:02 -0700 Subject: [PATCH 07/18] Fix typo --- spec/editor-component-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index c9ccab8bd..0bfafa006 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -101,7 +101,7 @@ describe "EditorComponent", -> atom.config.set("editor.showInvisibles", true) atom.config.set("editor.invisibles", invisibles) - it "displays spaces, tabs, and newlines as visible charachters", -> + it "displays spaces, tabs, and newlines as visible characters", -> editor.setText " a line with tabs\tand spaces " expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}" From 2bbf5c7800db49eefb64ece508787e7e55944ebe Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 20 May 2014 10:37:24 -0700 Subject: [PATCH 08/18] Remove unnecessary spec --- spec/editor-component-spec.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 0bfafa006..df2c2345a 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -109,8 +109,6 @@ describe "EditorComponent", -> editor.setText "var" expect(component.lineNodeForScreenRow(0).innerHTML).toBe "var#{invisibles.eol}" - it "allows invisible glyphs to be customized via the editor.invisibles config", -> - it "displays trailing carriage return using a visible non-empty value", -> describe "when soft wrapping is enabled", -> From c999a6e0e4c543ac149425a50d06e1d8bc1ec9fd Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 20 May 2014 10:38:01 -0700 Subject: [PATCH 09/18] Show carriage return invisibles --- spec/editor-component-spec.coffee | 2 ++ src/lines-component.coffee | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index df2c2345a..2b255fb44 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -110,6 +110,8 @@ describe "EditorComponent", -> expect(component.lineNodeForScreenRow(0).innerHTML).toBe "var#{invisibles.eol}" it "displays trailing carriage return using a visible non-empty value", -> + editor.setText "a line that ends with a carriage return\r\n" + expect(component.lineNodeForScreenRow(0).textContent).toBe "a line that ends with a carriage return#{invisibles.cr}#{invisibles.eol}" describe "when soft wrapping is enabled", -> beforeEach -> diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 8de0963ee..e88b65c56 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -148,9 +148,19 @@ LinesComponent = React.createClass innerHTML += token.getValueAsHtml({invisibles, hasIndentGuide}) innerHTML += @popScope(scopeStack) while scopeStack.length > 0 - innerHTML += "#{invisibles.eol}" + innerHTML += @buildEndOfLineHTML(line, invisibles) innerHTML + buildEndOfLineHTML: (line, invisibles) -> + return '' if @props.mini + + eolInvisibles = [] + eolInvisibles.push(invisibles.cr) if invisibles.cr? and line.lineEnding is '\r\n' + eolInvisibles.push(invisibles.eol) if invisibles.eol? + eolInvisibles + .map((eolInvisible) -> "#{eolInvisible}") + .join("") + updateScopeStack: (scopeStack, desiredScopes) -> html = "" From 1e6e804ebbb0ffd9c15d4835afba965cc4e7befc Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 20 May 2014 11:37:32 -0700 Subject: [PATCH 10/18] Use screen line count to determine renderedEndRow --- src/editor-component.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor-component.coffee b/src/editor-component.coffee index dc07b9613..37cffac49 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -102,7 +102,7 @@ EditorComponent = React.createClass {editor, lineOverdrawMargin} = @props [visibleStartRow, visibleEndRow] = editor.getVisibleRowRange() renderedStartRow = Math.max(0, visibleStartRow - lineOverdrawMargin) - renderedEndRow = Math.min(editor.getLineCount(), visibleEndRow + lineOverdrawMargin) + renderedEndRow = Math.min(editor.getScreenLineCount(), visibleEndRow + lineOverdrawMargin) [renderedStartRow, renderedEndRow] getInitialState: -> {} From 6880368a795251f3d0fff9330a1f58728d434261 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 20 May 2014 11:44:55 -0700 Subject: [PATCH 11/18] Add soft wrap support to invisibles --- spec/editor-component-spec.coffee | 7 ++++++- src/lines-component.coffee | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 2b255fb44..b50a18b8e 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -115,9 +115,14 @@ describe "EditorComponent", -> describe "when soft wrapping is enabled", -> beforeEach -> + editor.setText "a line that wraps " editor.setSoftWrap(true) + node.style.width = 15 * charWidth + 'px' + component.measureHeightAndWidth() - it "doesn't show the end of line invisible at the end of lines broken due to wrapping", -> + it "doesn't show end of line invisibles at the end of wrapped lines", -> + expect(component.lineNodeForScreenRow(0).textContent).toBe "a line that " + expect(component.lineNodeForScreenRow(1).textContent).toBe "wraps#{invisibles.space}#{invisibles.eol}" it "displays trailing carriage return using a visible non-empty value", -> diff --git a/src/lines-component.coffee b/src/lines-component.coffee index e88b65c56..771b9325f 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -152,7 +152,7 @@ LinesComponent = React.createClass innerHTML buildEndOfLineHTML: (line, invisibles) -> - return '' if @props.mini + return '' if @props.mini or line.isSoftWrapped() eolInvisibles = [] eolInvisibles.push(invisibles.cr) if invisibles.cr? and line.lineEnding is '\r\n' From f962888b35d57d5bdfb0e1b636730207740f2f3c Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 20 May 2014 11:49:40 -0700 Subject: [PATCH 12/18] Remove unnecessary spec --- spec/editor-component-spec.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index b50a18b8e..d7c43afc0 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -124,8 +124,6 @@ describe "EditorComponent", -> expect(component.lineNodeForScreenRow(0).textContent).toBe "a line that " expect(component.lineNodeForScreenRow(1).textContent).toBe "wraps#{invisibles.space}#{invisibles.eol}" - it "displays trailing carriage return using a visible non-empty value", -> - describe "when indent guides are enabled", -> beforeEach -> component.setShowIndentGuide(true) From 2f038cbe667820d6ba59c23c5298dc9c32bca4dd Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 20 May 2014 12:34:18 -0700 Subject: [PATCH 13/18] Update lines component when invisibles changes --- src/lines-component.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 771b9325f..ce9e29234 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -35,7 +35,7 @@ LinesComponent = React.createClass shouldComponentUpdate: (newProps) -> return true if newProps.selectionChanged - return true unless isEqualForProperties(newProps, @props, 'renderedRowRange', 'fontSize', 'fontFamily', 'lineHeight', 'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically') + return true unless isEqualForProperties(newProps, @props, 'renderedRowRange', 'fontSize', 'fontFamily', 'lineHeight', 'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'invisibles') {renderedRowRange, pendingChanges} = newProps for change in pendingChanges From ff36781c988b06a8263ebd4c9d30a63e161a1f28 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 20 May 2014 12:34:43 -0700 Subject: [PATCH 14/18] Add failing spec for toggling showInvisibles config option --- spec/editor-component-spec.coffee | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index d7c43afc0..36f528fdd 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -101,8 +101,16 @@ describe "EditorComponent", -> atom.config.set("editor.showInvisibles", true) atom.config.set("editor.invisibles", invisibles) - it "displays spaces, tabs, and newlines as visible characters", -> + it "re-renders the editor when the showInvisibles config option changes", -> editor.setText " a line with tabs\tand spaces " + + expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}" + atom.config.set("editor.showInvisibles", false) + expect(component.lineNodeForScreenRow(0).textContent).toBe " a line with tabs\t and spaces " + atom.config.set("editor.showInvisibles", true) + expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}" + + it "displays spaces, tabs, and newlines as visible characters", -> expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}" it "displays newlines as their own token outside of the other tokens scope", -> From 25e3ae03259172c590e4b123c724de2c0c59915c Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 20 May 2014 13:58:22 -0700 Subject: [PATCH 15/18] Re-render the lines when the showInvisible config option is triggered --- spec/editor-component-spec.coffee | 2 +- src/lines-component.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 36f528fdd..32673e869 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -106,7 +106,7 @@ describe "EditorComponent", -> expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}" atom.config.set("editor.showInvisibles", false) - expect(component.lineNodeForScreenRow(0).textContent).toBe " a line with tabs\t and spaces " + expect(component.lineNodeForScreenRow(0).textContent).toBe " a line with tabs and spaces " atom.config.set("editor.showInvisibles", true) expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}" diff --git a/src/lines-component.coffee b/src/lines-component.coffee index ce9e29234..4bc351ed4 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -46,7 +46,7 @@ LinesComponent = React.createClass componentDidUpdate: (prevProps) -> @measureLineHeightAndCharWidth() unless isEqualForProperties(prevProps, @props, 'fontSize', 'fontFamily', 'lineHeight') @clearScreenRowCaches() unless prevProps.lineHeight is @props.lineHeight - @removeLineNodes() unless prevProps.showIndentGuide is @props.showIndentGuide + @removeLineNodes() unless isEqualForProperties(prevProps, @props, 'showIndentGuide', 'invisibles') @updateLines() @clearScopedCharWidths() unless isEqualForProperties(prevProps, @props, 'fontSize', 'fontFamily') @measureCharactersInNewLines() unless @props.scrollingVertically From a722d1aa368c066c02e08557ff1649e07b52de03 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 20 May 2014 14:07:36 -0700 Subject: [PATCH 16/18] Make editor component spec pass --- spec/editor-component-spec.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 32673e869..bb3e3a7d9 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -111,6 +111,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 spaces, tabs, and newlines as visible characters", -> + editor.setText " a line with tabs\tand spaces " expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}" it "displays newlines as their own token outside of the other tokens scope", -> From 48b33ed07df28752318a0651808b30185c55afd3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 20 May 2014 15:17:19 -0600 Subject: [PATCH 17/18] :lipstick: --- spec/editor-component-spec.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index bb3e3a7d9..7b2885aa1 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -101,7 +101,7 @@ describe "EditorComponent", -> atom.config.set("editor.showInvisibles", true) atom.config.set("editor.invisibles", invisibles) - it "re-renders the editor when the showInvisibles config option changes", -> + it "re-renders the lines when the showInvisibles config option changes", -> editor.setText " a line with tabs\tand spaces " expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}" @@ -114,11 +114,11 @@ describe "EditorComponent", -> editor.setText " a line with tabs\tand spaces " expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab} and spaces#{invisibles.space}#{invisibles.eol}" - it "displays newlines as their own token outside of the other tokens scope", -> + it "displays newlines as their own token outside of the other tokens' scopes", -> editor.setText "var" expect(component.lineNodeForScreenRow(0).innerHTML).toBe "var#{invisibles.eol}" - it "displays trailing carriage return using a visible non-empty value", -> + it "displays trailing carriage returns using a visible, non-empty value", -> editor.setText "a line that ends with a carriage return\r\n" expect(component.lineNodeForScreenRow(0).textContent).toBe "a line that ends with a carriage return#{invisibles.cr}#{invisibles.eol}" From ece868c9de8e8c183ed9d6e732ef83328d66bb20 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Tue, 20 May 2014 15:16:07 -0700 Subject: [PATCH 18/18] Concat strings instead of joining an Array --- src/lines-component.coffee | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 4bc351ed4..10f9c5060 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -154,12 +154,13 @@ LinesComponent = React.createClass buildEndOfLineHTML: (line, invisibles) -> return '' if @props.mini or line.isSoftWrapped() - eolInvisibles = [] - eolInvisibles.push(invisibles.cr) if invisibles.cr? and line.lineEnding is '\r\n' - eolInvisibles.push(invisibles.eol) if invisibles.eol? - eolInvisibles - .map((eolInvisible) -> "#{eolInvisible}") - .join("") + html = '' + if invisibles.cr? and line.lineEnding is '\r\n' + html += "#{invisibles.cr}" + if invisibles.eol? + html += "#{invisibles.eol}" + + html updateScopeStack: (scopeStack, desiredScopes) -> html = ""