Merge remote-tracking branch 'origin/master' into status-bar-buffer-modified-indicator

This commit is contained in:
Will Farrington
2012-10-07 09:13:08 -10:00
49 changed files with 755 additions and 563 deletions

View File

@@ -13,10 +13,10 @@ class CursorView extends View
hidden: false
initialize: (@cursor, @editor) ->
@cursor.on 'change-screen-position.cursor-view', (position, { bufferChange }) =>
@cursor.on 'change-screen-position.cursor-view', (screenPosition, { bufferChange }) =>
@updateAppearance()
@removeIdleClassTemporarily() unless bufferChange
@trigger 'cursor-move', bufferChange: bufferChange
@trigger 'cursor-move', {bufferChange}
@cursor.on 'destroy.cursor-view', => @remove()

View File

@@ -91,68 +91,68 @@ class Editor extends View
bindKeys: ->
editorBindings =
'move-right': @moveCursorRight
'move-left': @moveCursorLeft
'move-down': @moveCursorDown
'move-up': @moveCursorUp
'move-to-next-word': @moveCursorToNextWord
'move-to-previous-word': @moveCursorToPreviousWord
'select-right': @selectRight
'select-left': @selectLeft
'select-up': @selectUp
'select-down': @selectDown
'select-word': @selectWord
'newline': @insertNewline
'indent': @indent
'indent-selected-rows': @indentSelectedRows
'outdent-selected-rows': @outdentSelectedRows
'backspace': @backspace
'backspace-to-beginning-of-word': @backspaceToBeginningOfWord
'delete': @delete
'delete-to-end-of-word': @deleteToEndOfWord
'delete-line': @deleteLine
'cut-to-end-of-line': @cutToEndOfLine
'cut': @cutSelection
'copy': @copySelection
'paste': @paste
'undo': @undo
'redo': @redo
'move-to-top': @moveCursorToTop
'move-to-bottom': @moveCursorToBottom
'move-to-beginning-of-line': @moveCursorToBeginningOfLine
'move-to-end-of-line': @moveCursorToEndOfLine
'move-to-first-character-of-line': @moveCursorToFirstCharacterOfLine
'move-to-beginning-of-word': @moveCursorToBeginningOfWord
'move-to-end-of-word': @moveCursorToEndOfWord
'select-to-top': @selectToTop
'select-to-bottom': @selectToBottom
'select-to-end-of-line': @selectToEndOfLine
'select-to-beginning-of-line': @selectToBeginningOfLine
'select-to-end-of-word': @selectToEndOfWord
'select-to-beginning-of-word': @selectToBeginningOfWord
'select-all': @selectAll
'page-down': @pageDown
'page-up': @pageUp
'core:move-left': @moveCursorLeft
'core:move-right': @moveCursorRight
'core:move-to-top': @moveCursorToTop
'core:move-to-bottom': @moveCursorToBottom
'core:page-down': @pageDown
'core:page-up': @pageUp
'core:select-up': @selectUp
'core:select-down': @selectDown
'core:select-left': @selectLeft
'core:select-right': @selectRight
'core:select-to-top': @selectToTop
'core:select-to-bottom': @selectToBottom
'core:select-all': @selectAll
'core:backspace': @backspace
'core:delete': @delete
'core:undo': @undo
'core:redo': @redo
'core:cut': @cutSelection
'core:copy': @copySelection
'core:paste': @paste
'editor:move-to-next-word': @moveCursorToNextWord
'editor:move-to-previous-word': @moveCursorToPreviousWord
'editor:select-word': @selectWord
'editor:newline': @insertNewline
'editor:indent': @indent
'editor:indent-selected-rows': @indentSelectedRows
'editor:outdent-selected-rows': @outdentSelectedRows
'editor:backspace-to-beginning-of-word': @backspaceToBeginningOfWord
'editor:delete-to-end-of-word': @deleteToEndOfWord
'editor:delete-line': @deleteLine
'editor:cut-to-end-of-line': @cutToEndOfLine
'editor:move-to-beginning-of-line': @moveCursorToBeginningOfLine
'editor:move-to-end-of-line': @moveCursorToEndOfLine
'editor:move-to-first-character-of-line': @moveCursorToFirstCharacterOfLine
'editor:move-to-beginning-of-word': @moveCursorToBeginningOfWord
'editor:move-to-end-of-word': @moveCursorToEndOfWord
'editor:select-to-end-of-line': @selectToEndOfLine
'editor:select-to-beginning-of-line': @selectToBeginningOfLine
'editor:select-to-end-of-word': @selectToEndOfWord
'editor:select-to-beginning-of-word': @selectToBeginningOfWord
unless @mini
_.extend editorBindings,
'save': @save
'newline-below': @insertNewlineBelow
'toggle-soft-wrap': @toggleSoftWrap
'fold-all': @foldAll
'unfold-all': @unfoldAll
'fold-current-row': @foldCurrentRow
'unfold-current-row': @unfoldCurrentRow
'fold-selection': @foldSelection
'split-left': @splitLeft
'split-right': @splitRight
'split-up': @splitUp
'split-down': @splitDown
'close': @close
'show-next-buffer': @loadNextEditSession
'show-previous-buffer': @loadPreviousEditSession
'toggle-line-comments': @toggleLineCommentsInSelection
'log-cursor-scope': @logCursorScope
'core:move-up': @moveCursorUp
'core:move-down': @moveCursorDown
'core:close': @close
'editor:save': @save
'editor:newline-below': @insertNewlineBelow
'editor:toggle-soft-wrap': @toggleSoftWrap
'editor:fold-all': @foldAll
'editor:unfold-all': @unfoldAll
'editor:fold-current-row': @foldCurrentRow
'editor:unfold-current-row': @unfoldCurrentRow
'editor:fold-selection': @foldSelection
'editor:split-left': @splitLeft
'editor:split-right': @splitRight
'editor:split-up': @splitUp
'editor:split-down': @splitDown
'editor:show-next-buffer': @loadNextEditSession
'editor:show-previous-buffer': @loadPreviousEditSession
'editor:toggle-line-comments': @toggleLineCommentsInSelection
'editor:log-cursor-scope': @logCursorScope
for name, method of editorBindings
do (name, method) =>
@@ -343,6 +343,9 @@ class Editor extends View
else
@gutter.addClass('drop-shadow')
@on 'cursor-move', => @highlightCursorLine()
@on 'selection-change', => @highlightCursorLine()
selectOnMousemoveUntilMouseup: ->
moveHandler = (e) => @selectToScreenPosition(@screenPositionFromMouseEvent(e))
@on 'mousemove', moveHandler
@@ -415,6 +418,9 @@ class Editor extends View
@activeEditSession.on "buffer-path-change", =>
@trigger 'editor-path-change'
@activeEditSession.getSelection().on 'change-screen-range', =>
@trigger 'selection-change'
@trigger 'editor-path-change'
@renderWhenAttached()
@@ -640,7 +646,7 @@ class Editor extends View
addCursorView: (cursor) ->
cursorView = new CursorView(cursor, this)
@cursorViews.push(cursorView)
@renderedLines.append(cursorView)
@appendToLinesView(cursorView)
cursorView
removeCursorView: (cursorView) ->
@@ -664,7 +670,7 @@ class Editor extends View
addSelectionView: (selection) ->
selectionView = new SelectionView({editor: this, selection})
@selectionViews.push(selectionView)
@renderedLines.append(selectionView)
@appendToLinesView(selectionView)
selectionView
removeSelectionView: (selectionView) ->
@@ -674,9 +680,12 @@ class Editor extends View
cursorView.remove() for cursorView in @getCursorViews()
selectionView.remove() for selectionView in @getSelectionViews()
appendToLinesView: (view) ->
@renderedLines.append(view)
calculateDimensions: ->
fragment = $('<pre class="line" style="position: absolute; visibility: hidden;"><span>x</span></div>')
@renderedLines.append(fragment)
@appendToLinesView(fragment)
lineRect = fragment[0].getBoundingClientRect()
charRect = fragment.find('span')[0].getBoundingClientRect()
@@ -746,6 +755,7 @@ class Editor extends View
if renderedLines
@gutter.renderLineNumbers(renderFrom, renderTo)
@highlightCursorLine()
@updatePaddingOfRenderedLines()
updatePaddingOfRenderedLines: ->
@@ -809,11 +819,21 @@ class Editor extends View
charHeight = @charHeight
lines = @activeEditSession.linesForScreenRows(startRow, endRow)
activeEditSession = @activeEditSession
cursorScreenRow = @getCursorScreenPosition().row
mini = @mini
buildLineHtml = (line) => @buildLineHtml(line)
$$ -> @raw(buildLineHtml(line)) for line in lines
buildLineHtml = (line, lineClasses) => @buildLineHtml(line, lineClasses)
$$ ->
row = startRow
for line in lines
if mini or row isnt cursorScreenRow
lineClasses = null
else
lineClasses = ' cursor-line'
@raw(buildLineHtml(line, lineClasses))
row++
buildLineHtml: (screenLine) ->
buildLineHtml: (screenLine, lineClasses) ->
scopeStack = []
line = []
@@ -845,6 +865,8 @@ class Editor extends View
else
lineAttributes = { class: 'line' }
lineAttributes.class += lineClasses if lineClasses
attributePairs = []
attributePairs.push "#{attributeName}=\"#{value}\"" for attributeName, value of lineAttributes
line.push("<pre #{attributePairs.join(' ')}>")
@@ -932,3 +954,12 @@ class Editor extends View
@screenPositionFromPixelPosition
top: pageY - @scrollView.offset().top + @scrollTop()
left: pageX - @scrollView.offset().left + @scrollView.scrollLeft()
highlightCursorLine: ->
return if @mini
@cursorScreenRow = @getCursorScreenPosition().row
screenRow = @cursorScreenRow - @firstRenderedScreenRow
@find('pre.line.cursor-line').removeClass('cursor-line')
if @getSelection().isSingleScreenLine()
@find("pre.line:eq(#{screenRow})").addClass('cursor-line')

View File

@@ -1,4 +1,4 @@
{View, $$$} = require 'space-pen'
{View, $$, $$$} = require 'space-pen'
$ = require 'jquery'
_ = require 'underscore'
@@ -9,47 +9,64 @@ class Gutter extends View
@div class: 'gutter', =>
@div outlet: 'lineNumbers', class: 'line-numbers'
cursorBufferRow: -1
firstScreenRow: -1
highestNumberWidth: null
afterAttach: (onDom) ->
@editor()?.on 'cursor-move', => @highlightCursorLine()
return if @attached or not onDom
@attached = true
editor = @editor()
highlightCursorLine = => @highlightCursorLine()
editor.on 'cursor-move', highlightCursorLine
editor.on 'selection-change', highlightCursorLine
@calculateWidth()
editor: ->
@parentView
calculateLineNumberPadding: ->
widthTesterElement = $$ -> @div {class: 'line-number'}, ""
widthTesterElement.width(0)
@append(widthTesterElement)
lineNumberPadding = widthTesterElement.outerWidth()
widthTesterElement.remove()
lineNumberPadding
renderLineNumbers: (startScreenRow, endScreenRow) ->
@firstScreenRow = startScreenRow
lastScreenRow = -1
currentCursorBufferRow = @cursorBufferRow
rows = @editor().bufferRowsForScreenRows(startScreenRow, endScreenRow)
cursorScreenRow = @editor().getCursorScreenPosition().row
@lineNumbers[0].innerHTML = $$$ ->
for row in rows
rowClass = null
if row isnt currentCursorBufferRow
rowClass = 'line-number'
if row == lastScreenRow
rowValue = ''
else
rowClass = 'line-number cursor-line-number'
@div {class: rowClass}, if row == lastScreenRow then '' else row + 1
rowValue = row + 1
@div {class: 'line-number'}, rowValue
lastScreenRow = row
@calculateWidth()
@highlightCursorLine()
calculateWidth: ->
width = @editor().getLineCount().toString().length * @editor().charWidth
if width != @cachedWidth
@cachedWidth = width
@lineNumbers.width(width)
highestNumberWidth = @editor().getLineCount().toString().length * @editor().charWidth
if highestNumberWidth != @highestNumberWidth
@highestNumberWidth = highestNumberWidth
@lineNumbers.width(highestNumberWidth + @calculateLineNumberPadding())
@widthChanged?(@outerWidth())
highlightCursorLine: ->
return if @firstScreenRow < 0
cursorScreenRow = @editor().getCursorScreenPosition().row
screenRowIndex = cursorScreenRow - @firstScreenRow
newCursorBufferRow = @editor().getCursorBufferPosition().row
if newCursorBufferRow isnt @cursorBufferRow
@cursorBufferRow = newCursorBufferRow
screenRow = @cursorBufferRow - @firstScreenRow
@find('.line-number.cursor-line-number').removeClass('cursor-line-number')
@find(".line-number:eq(#{screenRow})").addClass('cursor-line-number')
currentLineNumberRow = @find(".line-number.cursor-line-number")
currentLineNumberRow.removeClass('cursor-line-number')
currentLineNumberRow.removeClass('cursor-line-number-background')
newLineNumberRow = @find(".line-number:eq(#{screenRowIndex})")
newLineNumberRow.addClass('cursor-line-number')
if @editor().getSelection().isSingleScreenLine()
newLineNumberRow.addClass('cursor-line-number-background')

View File

@@ -1,15 +1,17 @@
window.keymap.bindKeys 'body'
'meta-up': 'core:move-to-top'
'meta-down': 'core:move-to-bottom'
'meta-shift-up': 'core:select-to-top'
'meta-shift-down': 'core:select-to-bottom'
window.keymap.bindKeys '.editor'
'meta-up': 'move-to-top'
'meta-down': 'move-to-bottom'
'meta-right': 'move-to-end-of-line'
'meta-left': 'move-to-beginning-of-line'
'alt-left': 'move-to-beginning-of-word'
'alt-right': 'move-to-end-of-word'
'meta-shift-up': 'select-to-top'
'meta-shift-down': 'select-to-bottom'
'meta-shift-left': 'select-to-beginning-of-line'
'meta-shift-right': 'select-to-end-of-line'
'alt-shift-left': 'select-to-beginning-of-word'
'alt-shift-right': 'select-to-end-of-word'
'alt-backspace': 'backspace-to-beginning-of-word'
'alt-delete': 'delete-to-end-of-word'
'meta-right': 'editor:move-to-end-of-line'
'meta-left': 'editor:move-to-beginning-of-line'
'alt-left': 'editor:move-to-beginning-of-word'
'alt-right': 'editor:move-to-end-of-word'
'meta-shift-left': 'editor:select-to-beginning-of-line'
'meta-shift-right': 'editor:select-to-end-of-line'
'alt-shift-left': 'editor:select-to-beginning-of-word'
'alt-shift-right': 'editor:select-to-end-of-word'
'alt-backspace': 'editor:backspace-to-beginning-of-word'
'alt-delete': 'editor:delete-to-end-of-word'

View File

@@ -1,10 +1,27 @@
window.keymap.bindKeys '*'
'meta-w': 'close'
window.keymap.bindKeys 'body'
'alt-meta-i': 'toggle-dev-tools'
right: 'move-right'
left: 'move-left'
down: 'move-down'
up: 'move-up'
pagedown: 'page-down'
pageup: 'page-up'
'meta-S': 'save-all'
'meta-w': 'core:close'
up: 'core:move-up'
down: 'core:move-down'
left: 'core:move-left'
right: 'core:move-right'
'shift-up': 'core:select-up'
'shift-down': 'core:select-down'
'shift-left': 'core:select-left'
'shift-right': 'core:select-right'
'meta-a': 'core:select-all'
'backspace': 'core:backspace'
'shift-backspace': 'core:backspace'
'delete': 'core:delete'
'meta-z': 'core:undo'
'meta-Z': 'core:redo'
'meta-x': 'core:cut'
'meta-c': 'core:copy'
'meta-v': 'core:paste'
pageup: 'core:page-up'
pagedown: 'core:page-down'
'meta-S': 'root-view:save-all'
'meta-+': 'root-view:increase-font-size'
'meta--': 'root-view:decrease-font-size'
'ctrl-w w': 'root-view:focus-next-pane'

View File

@@ -1,40 +1,25 @@
window.keymap.bindKeys '.editor',
'meta-s': 'save'
'shift-right': 'select-right'
'shift-left': 'select-left'
'shift-up': 'select-up'
'shift-down': 'select-down'
'meta-a': 'select-all'
'enter': 'newline'
'meta-enter': 'newline-below'
'tab': 'indent'
'backspace': 'backspace'
'shift-backspace': 'backspace'
'delete': 'delete'
'meta-d': 'delete-line'
'meta-x': 'cut'
'meta-c': 'copy'
'meta-v': 'paste'
'meta-z': 'undo'
'meta-Z': 'redo'
'alt-meta-w': 'toggle-soft-wrap'
'ctrl-[': 'fold-current-row'
'ctrl-]': 'unfold-current-row'
'ctrl-{': 'fold-all'
'ctrl-}': 'unfold-all'
'alt-meta-ctrl-f': 'fold-selection'
'alt-meta-left': 'split-left'
'alt-meta-right': 'split-right'
'alt-meta-up': 'split-up'
'alt-meta-down': 'split-down'
'shift-tab': 'outdent-selected-rows'
'meta-[': 'outdent-selected-rows'
'meta-]': 'indent-selected-rows'
'meta-{': 'show-previous-buffer'
'meta-}': 'show-next-buffer'
'meta-+': 'increase-font-size'
'meta--': 'decrease-font-size'
'meta-/': 'toggle-line-comments'
'ctrl-w w': 'focus-next-pane'
'ctrl-W': 'select-word'
'meta-alt-p': 'log-cursor-scope'
'meta-s': 'editor:save'
'enter': 'editor:newline'
'meta-enter': 'editor:newline-below'
'tab': 'editor:indent'
'meta-d': 'editor:delete-line'
'alt-meta-w': 'editor:toggle-soft-wrap'
'ctrl-[': 'editor:fold-current-row'
'ctrl-]': 'editor:unfold-current-row'
'ctrl-{': 'editor:fold-all'
'ctrl-}': 'editor:unfold-all'
'alt-meta-ctrl-f': 'editor:fold-selection'
'alt-meta-left': 'editor:split-left'
'alt-meta-right': 'editor:split-right'
'alt-meta-up': 'editor:split-up'
'alt-meta-down': 'editor:split-down'
'shift-tab': 'editor:outdent-selected-rows'
'meta-[': 'editor:outdent-selected-rows'
'meta-]': 'editor:indent-selected-rows'
'meta-{': 'editor:show-previous-buffer'
'meta-}': 'editor:show-next-buffer'
'meta-/': 'editor:toggle-line-comments'
'ctrl-W': 'editor:select-word'
'meta-alt-p': 'editor:log-cursor-scope'

View File

@@ -1,22 +1,22 @@
window.keymap.bindKeys '*',
'ctrl-f': 'move-right'
'ctrl-b': 'move-left'
'ctrl-p': 'move-up'
'ctrl-n': 'move-down'
window.keymap.bindKeys 'body',
'ctrl-p': 'core:move-up'
'ctrl-n': 'core:move-down'
'ctrl-b': 'core:move-left'
'ctrl-f': 'core:move-right'
'ctrl-P': 'core:select-up'
'ctrl-N': 'core:select-down'
'ctrl-F': 'core:select-right'
'ctrl-B': 'core:select-left'
'ctrl-h': 'core:backspace'
'ctrl-d': 'core:delete'
window.keymap.bindKeys '.editor',
'ctrl-F': 'select-right'
'ctrl-B': 'select-left'
'ctrl-P': 'select-up'
'ctrl-N': 'select-down'
'alt-f': 'move-to-end-of-word'
'alt-F': 'select-to-end-of-word'
'alt-b': 'move-to-beginning-of-word'
'alt-B': 'select-to-beginning-of-word'
'ctrl-a': 'move-to-first-character-of-line'
'ctrl-e': 'move-to-end-of-line'
'ctrl-h': 'backspace'
'ctrl-d': 'delete'
'alt-h': 'backspace-to-beginning-of-word'
'alt-d': 'delete-to-end-of-word'
'ctrl-k': 'cut-to-end-of-line'
'alt-f': 'editor:move-to-end-of-word'
'alt-F': 'editor:select-to-end-of-word'
'alt-b': 'editor:move-to-beginning-of-word'
'alt-B': 'editor:select-to-beginning-of-word'
'ctrl-a': 'editor:move-to-first-character-of-line'
'ctrl-e': 'editor:move-to-end-of-line'
'alt-h': 'editor:backspace-to-beginning-of-word'
'alt-d': 'editor:delete-to-end-of-word'
'ctrl-k': 'editor:cut-to-end-of-line'

View File

@@ -49,7 +49,9 @@ class LanguageMode
scopes = @tokenizedBuffer.scopesForPosition(range.start)
return unless commentString = TextMateBundle.lineCommentStringForScope(scopes[0])
commentRegex = new OnigRegExp("^\s*" + _.escapeRegExp(commentString))
commentRegexString = _.escapeRegExp(commentString)
commentRegexString = commentRegexString.replace(/(\s+)$/, '($1)?')
commentRegex = new OnigRegExp("^\s*#{commentRegexString}")
shouldUncomment = commentRegex.test(@editSession.lineForBufferRow(range.start.row))

View File

@@ -73,10 +73,10 @@ class RootView extends View
@project.setPath(path) unless @project.getRootDirectory()
@setTitle(path)
@on 'increase-font-size', => @setFontSize(@getFontSize() + 1)
@on 'decrease-font-size', => @setFontSize(@getFontSize() - 1)
@on 'focus-next-pane', => @focusNextPane()
@on 'save-all', => @saveAll()
@on 'root-view:increase-font-size', => @setFontSize(@getFontSize() + 1)
@on 'root-view:decrease-font-size', => @setFontSize(@getFontSize() - 1)
@on 'root-view:focus-next-pane', => @focusNextPane()
@on 'root-view:save-all', => @saveAll()
afterAttach: (onDom) ->
@focus() if onDom

View File

@@ -31,6 +31,9 @@ class Selection
isReversed: ->
not @isEmpty() and @cursor.getBufferPosition().isLessThan(@anchor.getBufferPosition())
isSingleScreenLine: ->
@getScreenRange().isSingleLine()
getScreenRange: ->
if @anchor
new Range(@anchor.getScreenPosition(), @cursor.getScreenPosition())