From 35cf96e15fde93386e19f3f3dc9490307512fced Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 1 May 2013 20:54:09 -0700 Subject: [PATCH] Render empty line invisibles at correct position End of line invisibles are not rendered at the correct position for empty lines instead of always after the last indent guide span. Closes #456 --- spec/app/editor-spec.coffee | 16 ++++++++++++ src/app/editor.coffee | 50 ++++++++++++++++++++++++++++-------- static/editor.less | 2 -- themes/atom-dark-syntax.css | 5 ++++ themes/atom-light-syntax.css | 5 ++++ 5 files changed, 65 insertions(+), 13 deletions(-) diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 7419ef4ee..7a9f98d07 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -1551,6 +1551,22 @@ describe "Editor", -> expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2 expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' ' + describe "when the line is empty and end of show invisibles are enabled", -> + it "renders the indent guides interleaved the end of line invisibles", -> + editor.attachToDom() + config.set("editor.showIndentGuide", true) + config.set("editor.showInvisibles", true) + eol = editor.invisibles?.eol + + expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 1 + expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe "#{eol} " + + editor.setCursorBufferPosition([9]) + editor.indent() + + expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2 + expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe "#{eol} " + describe "when soft-wrap is enabled", -> beforeEach -> editor.attachToDom() diff --git a/src/app/editor.coffee b/src/app/editor.coffee index abfdafc72..44037d13a 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -1546,7 +1546,22 @@ class Editor extends View htmlLines.push(@buildLineHtml(line, screenRow++)) htmlLines.join('\n\n') - buildEmptyLineHtml: (screenRow) -> + buildEndOfLineInvisibles: (screenLine) -> + invisibles = [] + for invisible in @getEndOfLineInvisibles(screenLine) + invisibles.push("#{invisible}") + invisibles.join('') + + getEndOfLineInvisibles: (screenLine) -> + return [] unless @showInvisibles and @invisibles + return [] if @mini or screenLine.isSoftWrapped() + + invisibles = [] + invisibles.push(@invisibles.cr) if @invisibles.cr and screenLine.lineEnding is '\r\n' + invisibles.push(@invisibles.eol) if @invisibles.eol + invisibles + + buildEmptyLineHtml: (screenLine, screenRow) -> if not @mini and @showIndentGuide indentation = 0 while --screenRow >= 0 @@ -1557,10 +1572,28 @@ class Editor extends View break if indentation > 0 - indentationHtml = "#{_.multiplyString(' ', @activeEditSession.getTabLength())}" - return _.multiplyString(indentationHtml, indentation) + tabLength = @activeEditSession.getTabLength() + invisibles = @getEndOfLineInvisibles(screenLine) + indentGuideHtml = [] + for level in [0...indentation] + indentLevelHtml = [""] + for characterPosition in [0...tabLength] + if invisible = invisibles.shift() + indentLevelHtml.push("#{invisible}") + else + indentLevelHtml.push(' ') + indentLevelHtml.push("") + indentGuideHtml.push(indentLevelHtml.join('')) - return ' ' unless @showInvisibles + for invisible in invisibles + indentGuideHtml.push("#{invisible}") + return indentGuideHtml.join('') + + invisibles = @buildEndOfLineInvisibles(screenLine) + if invisibles.length > 0 + invisibles + else + ' ' buildLineHtml: (screenLine, screenRow) -> scopeStack = [] @@ -1599,7 +1632,7 @@ class Editor extends View invisibles = @invisibles if @showInvisibles if screenLine.text == '' - html = @buildEmptyLineHtml(screenRow) + html = @buildEmptyLineHtml(screenLine, screenRow) line.push(html) if html else firstNonWhitespacePosition = screenLine.text.search(/\S/) @@ -1615,12 +1648,7 @@ class Editor extends View position += token.value.length popScope() while scopeStack.length > 0 - if invisibles and not @mini and not screenLine.isSoftWrapped() - if invisibles.cr and screenLine.lineEnding is '\r\n' - line.push("#{invisibles.cr}") - if invisibles.eol - line.push("#{invisibles.eol}") - + line.push(@buildEndOfLineInvisibles(screenLine)) unless screenLine.text == '' line.push("") if fold line.push('') diff --git a/static/editor.less b/static/editor.less index 699ffe3bc..cf3a4eb87 100644 --- a/static/editor.less +++ b/static/editor.less @@ -81,13 +81,11 @@ } .editor .invisible-character { - opacity: 0.2; font-weight: normal !important; font-style: normal !important; } .editor .indent-guide { - opacity: 0.2; display: inline-block; box-shadow: inset 1px 0px; } diff --git a/themes/atom-dark-syntax.css b/themes/atom-dark-syntax.css index e14796b22..a095d3018 100644 --- a/themes/atom-dark-syntax.css +++ b/themes/atom-dark-syntax.css @@ -3,6 +3,11 @@ color: #c5c8c6; } +.editor .invisible-character, +.editor .indent-guide { + color: rgba(197, 200, 198, .2); +} + .editor .gutter .line-number.fold, .editor .gutter .line-number:after, .editor .fold-marker:after { diff --git a/themes/atom-light-syntax.css b/themes/atom-light-syntax.css index 248630da8..774a3c561 100644 --- a/themes/atom-light-syntax.css +++ b/themes/atom-light-syntax.css @@ -3,6 +3,11 @@ color: #555; } +.editor .invisible-character, +.editor .indent-guide { + color: rgba(85, 85, 85, .2); +} + .editor .gutter .line-number.fold, .editor .gutter .line-number:after, .editor .fold-marker:after {