When project.showInvisibles is true; spaces, tabs and newlines are visible

This commit is contained in:
Corey Johnson 2012-10-11 11:47:55 -07:00 committed by Corey Johnson & Nathan Sobo
parent e2a917fcf3
commit 4478bbca9a
4 changed files with 40 additions and 18 deletions

View File

@ -214,7 +214,7 @@ describe "Editor", ->
expect(editor.lineElementForScreenRow(0).text()).toBe 'abc'
editor.edit(otherEditSession)
expect(editor.lineElementForScreenRow(0).html()).toBe ' '
expect(editor.lineElementForScreenRow(0).html()).toBe '<span class="text plain">&nbsp;</span>'
editor.insertText("def\n")
expect(editor.lineElementForScreenRow(0).text()).toBe 'def'
@ -992,7 +992,7 @@ describe "Editor", ->
# renders empty lines with a non breaking space
expect(buffer.lineForRow(10)).toBe ''
expect(editor.renderedLines.find('.line:eq(10)').html()).toBe '&nbsp;'
expect(editor.renderedLines.find('.line:eq(10) span').html()).toBe '&nbsp;'
it "syntax highlights code based on the file type", ->
line0 = editor.renderedLines.find('.line:first')
@ -1198,7 +1198,7 @@ describe "Editor", ->
editor.scrollTop(editor.lineHeight * 3.5) # first visible row will be 3, last will be 8
expect(editor.renderedLines.find('.line').length).toBe 10
expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(1)
expect(editor.renderedLines.find('.line:last').html()).toBe '&nbsp;' # line 10 is blank
expect(editor.renderedLines.find('.line:last span').html()).toBe '&nbsp;' # line 10 is blank
expect(editor.gutter.find('.line-number:first').text()).toBe '2'
expect(editor.gutter.find('.line-number:last').text()).toBe '11'
@ -1206,7 +1206,7 @@ describe "Editor", ->
editor.scrollTop(editor.lineHeight * 5.5) # first visible row will be 5, last will be 10
expect(editor.renderedLines.find('.line').length).toBe 10
expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(1)
expect(editor.renderedLines.find('.line:last').html()).toBe '&nbsp;' # line 10 is blank
expect(editor.renderedLines.find('.line:last span').html()).toBe '&nbsp;' # line 10 is blank
expect(editor.gutter.find('.line-number:first').text()).toBe '2'
expect(editor.gutter.find('.line-number:last').text()).toBe '11'
@ -1218,7 +1218,7 @@ describe "Editor", ->
editor.scrollTop(editor.lineHeight * 3.5) # first visible row will be 3, last will be 8
expect(editor.renderedLines.find('.line').length).toBe 10
expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(1)
expect(editor.renderedLines.find('.line:last').html()).toBe '&nbsp;' # line 10 is blank
expect(editor.renderedLines.find('.line:last span').html()).toBe '&nbsp;' # line 10 is blank
editor.scrollTop(0)
expect(editor.renderedLines.find('.line').length).toBe 8
@ -1827,3 +1827,12 @@ describe "Editor", ->
editor.pageUp()
expect(editor.getCursor().getScreenPosition().row).toBe(0)
expect(editor.getFirstVisibleScreenRow()).toBe(0)
describe "when showInvisibles is enabled on the editSession", ->
beforeEach ->
editor.activeEditSession.showInvisibles = true
editor.attachToDom(5)
it "displays spaces as •, tabs as ▸ and newlines as ¬", ->
editor.setText " a line with tabs\tand spaces "
expect(editor.find('.line').text()).toBe "•a•line•with•tabs▸ and•spaces•¬"

View File

@ -35,11 +35,12 @@ class EditSession
cursors: null
selections: null
autoIndent: false # TODO: re-enabled auto-indent after fixing the rest of tokenization
tabLength: null
softTabs: true
softWrap: false
tabLength: null
showInvisibles: false
constructor: ({@project, @buffer, @tabLength, @autoIndent, @softTabs, @softWrap}) ->
constructor: ({@project, @buffer, @tabLength, @autoIndent, @softTabs, @softWrap, @showInvisibles}) ->
@id = @constructor.idCounter++
@softTabs ?= true
@languageMode = new LanguageMode(this, @buffer.getExtension())

View File

@ -873,12 +873,13 @@ class Editor extends View
attributePairs.push "#{attributeName}=\"#{value}\"" for attributeName, value of lineAttributes
line.push("<pre #{attributePairs.join(' ')}>")
if screenLine.text == ''
line.push('&nbsp;')
else
for token in screenLine.tokens
updateScopeStack(token.scopes)
line.push(token.escapeValue())
for token in screenLine.tokens
updateScopeStack(token.scopes)
line.push(token.escapeValue(@activeEditSession.showInvisibles))
if @activeEditSession.showInvisibles
line.push("<pre class='invisible'>¬</pre>")
line.push('</pre>')
line.join('')

View File

@ -5,8 +5,9 @@ class Token
value: null
scopes: null
isAtomic: null
isTab: null
constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @fold}) ->
constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @fold, @isTab}) ->
@screenDelta = @value.length
@bufferDelta ?= @screenDelta
@ -24,20 +25,30 @@ class Token
breakOutTabCharacters: (tabLength) ->
return [this] unless /\t/.test(@value)
tabText = new Array(tabLength + 1).join(" ")
for substring in @value.match(/([^\t]+|\t)/g)
if substring == '\t'
@buildTabToken(tabLength)
new Token(value: tabText, scopes: @scopes, bufferDelta: 1, isAtomic: true, isTab: true)
else
new Token(value: substring, scopes: @scopes)
buildTabToken: (tabLength) ->
tabText = new Array(tabLength + 1).join(" ")
new Token(value: tabText, scopes: @scopes, bufferDelta: 1, isAtomic: true)
escapeValue: ->
@value
escapeValue: (showInvisibles)->
return "&nbsp;" if @value == ""
value = @value
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
if showInvisibles
if @isTab
value = "" + value[1..]
else
value = value.replace(/[ ]+/g, "")
value