mirror of
https://github.com/atom/atom.git
synced 2026-02-14 08:35:11 -05:00
Add indent guide to editor
The guide displays a continuous vertical line across lines with the same indent levels. Closes #50
This commit is contained in:
@@ -15,6 +15,7 @@ class Editor extends View
|
||||
@configDefaults:
|
||||
fontSize: 20
|
||||
showInvisibles: false
|
||||
showIndentGuide: false
|
||||
autosave: false
|
||||
autoIndent: true
|
||||
autoIndentOnPaste: false
|
||||
@@ -191,6 +192,7 @@ class Editor extends View
|
||||
'editor:move-line-down': @moveLineDown
|
||||
'editor:duplicate-line': @duplicateLine
|
||||
'editor:undo-close-session': @undoDestroySession
|
||||
'editor:toggle-indent-guide': => config.set('editor.showIndentGuide', !config.get('editor.showIndentGuide'))
|
||||
|
||||
documentation = {}
|
||||
for name, method of editorBindings
|
||||
@@ -330,6 +332,11 @@ class Editor extends View
|
||||
cr: '\u00a4'
|
||||
@resetDisplay()
|
||||
|
||||
setShowIndentGuide: (showIndentGuide) ->
|
||||
return if showIndentGuide == @showIndentGuide
|
||||
@showIndentGuide = showIndentGuide
|
||||
@resetDisplay()
|
||||
|
||||
checkoutHead: -> @getBuffer().checkoutHead()
|
||||
setText: (text) -> @getBuffer().setText(text)
|
||||
getText: -> @getBuffer().getText()
|
||||
@@ -346,6 +353,7 @@ class Editor extends View
|
||||
|
||||
configure: ->
|
||||
@observeConfig 'editor.showInvisibles', (showInvisibles) => @setShowInvisibles(showInvisibles)
|
||||
@observeConfig 'editor.showIndentGuide', (showIndentGuide) => @setShowIndentGuide(showIndentGuide)
|
||||
@observeConfig 'editor.invisibles', (invisibles) => @setInvisibles(invisibles)
|
||||
@observeConfig 'editor.fontSize', (fontSize) => @setFontSize(fontSize)
|
||||
@observeConfig 'editor.fontFamily', (fontFamily) => @setFontFamily(fontFamily)
|
||||
@@ -1110,13 +1118,34 @@ class Editor extends View
|
||||
|
||||
buildLineElementsForScreenRows: (startRow, endRow) ->
|
||||
div = document.createElement('div')
|
||||
div.innerHTML = @buildLinesHtml(@activeEditSession.linesForScreenRows(startRow, endRow))
|
||||
div.innerHTML = @buildLinesHtml(startRow, endRow)
|
||||
new Array(div.children...)
|
||||
|
||||
buildLinesHtml: (screenLines) ->
|
||||
screenLines.map((line) => @buildLineHtml(line)).join('\n\n')
|
||||
buildLinesHtml: (startRow, endRow) ->
|
||||
lines = @activeEditSession.linesForScreenRows(startRow, endRow)
|
||||
htmlLines = []
|
||||
screenRow = startRow
|
||||
for line in @activeEditSession.linesForScreenRows(startRow, endRow)
|
||||
htmlLines.push(@buildLineHtml(line, screenRow++))
|
||||
htmlLines.join('\n\n')
|
||||
|
||||
buildLineHtml: (screenLine) ->
|
||||
buildEmptyLineHtml: (screenRow) ->
|
||||
if not @mini and @showIndentGuide
|
||||
indentation = 0
|
||||
while --screenRow >= 0
|
||||
bufferRow = @activeEditSession.bufferPositionForScreenPosition([screenRow]).row
|
||||
bufferLine = @activeEditSession.lineForBufferRow(bufferRow)
|
||||
unless bufferLine is ''
|
||||
indentation = Math.ceil(@activeEditSession.indentLevelForLine(bufferLine))
|
||||
break
|
||||
|
||||
if indentation > 0
|
||||
indentationHtml = "<span class='indent-guide'>#{_.multiplyString(' ', @activeEditSession.getTabLength())}</span>"
|
||||
return _.multiplyString(indentationHtml, indentation)
|
||||
|
||||
return ' ' unless @showInvisibles
|
||||
|
||||
buildLineHtml: (screenLine, screenRow) ->
|
||||
scopeStack = []
|
||||
line = []
|
||||
|
||||
@@ -1153,7 +1182,8 @@ class Editor extends View
|
||||
invisibles = @invisibles if @showInvisibles
|
||||
|
||||
if screenLine.text == ''
|
||||
line.push(" ") unless @showInvisibles
|
||||
html = @buildEmptyLineHtml(screenRow)
|
||||
line.push(html) if html
|
||||
else
|
||||
firstNonWhitespacePosition = screenLine.text.search(/\S/)
|
||||
firstTrailingWhitespacePosition = screenLine.text.search(/\s*$/)
|
||||
@@ -1164,6 +1194,7 @@ class Editor extends View
|
||||
invisibles: invisibles
|
||||
hasLeadingWhitespace: position < firstNonWhitespacePosition
|
||||
hasTrailingWhitespace: position + token.value.length > firstTrailingWhitespacePosition
|
||||
hasIndentGuide: @showIndentGuide
|
||||
))
|
||||
|
||||
position += token.value.length
|
||||
|
||||
@@ -62,7 +62,8 @@ class Token
|
||||
isOnlyWhitespace: ->
|
||||
not /\S/.test(@value)
|
||||
|
||||
getValueAsHtml: ({invisibles, hasLeadingWhitespace, hasTrailingWhitespace})->
|
||||
getValueAsHtml: ({invisibles, hasLeadingWhitespace, hasTrailingWhitespace, hasIndentGuide})->
|
||||
invisibles ?= {}
|
||||
html = @value
|
||||
.replace(/&/g, '&')
|
||||
.replace(/"/g, '"')
|
||||
@@ -70,26 +71,29 @@ class Token
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
|
||||
if invisibles
|
||||
if @isHardTab and invisibles.tab
|
||||
html = html.replace(/^./, "<span class='invisible hard-tab'>#{invisibles.tab}</span>")
|
||||
else if invisibles.space
|
||||
if hasLeadingWhitespace
|
||||
html = html.replace /^[ ]+/, (match) ->
|
||||
"<span class='invisible leading-whitespace'>#{match.replace(/./g, invisibles.space)}</span>"
|
||||
if hasTrailingWhitespace
|
||||
html = html.replace /[ ]+$/, (match) ->
|
||||
"<span class='invisible trailing-whitespace'>#{match.replace(/./g, invisibles.space)}</span>"
|
||||
if @isHardTab
|
||||
html = html.replace /^./, (match) ->
|
||||
classes = []
|
||||
classes.push('invisible') if invisibles.tab
|
||||
classes.push('indent-guide') if hasIndentGuide
|
||||
classes.push('hard-tab')
|
||||
match = invisibles.tab ? match
|
||||
"<span class='#{classes.join(' ')}'>#{match}</span>"
|
||||
else
|
||||
if @isHardTab
|
||||
html = html.replace /^./, (match) ->
|
||||
"<span class='hard-tab'>#{match}</span>"
|
||||
else
|
||||
if hasLeadingWhitespace
|
||||
html = html.replace /^[ ]+/, (match) ->
|
||||
"<span class='leading-whitespace'>#{match}</span>"
|
||||
if hasTrailingWhitespace
|
||||
html = html.replace /[ ]+$/, (match) ->
|
||||
"<span class='trailing-whitespace'>#{match}</span>"
|
||||
if hasLeadingWhitespace
|
||||
html = html.replace /^[ ]+/, (match) ->
|
||||
classes = []
|
||||
classes.push('invisible') if invisibles.space
|
||||
classes.push('indent-guide') if hasIndentGuide
|
||||
classes.push('leading-whitespace')
|
||||
match = match.replace(/./g, invisibles.space) if invisibles.space
|
||||
"<span class='#{classes.join(' ')}'>#{match}</span>"
|
||||
if hasTrailingWhitespace
|
||||
html = html.replace /[ ]+$/, (match) ->
|
||||
classes = []
|
||||
classes.push('invisible') if invisibles.space
|
||||
classes.push('trailing-whitespace')
|
||||
match = match.replace(/./g, invisibles.space) if invisibles.space
|
||||
"<span class='#{classes.join(' ')}'>#{match}</span>"
|
||||
|
||||
html
|
||||
|
||||
Reference in New Issue
Block a user