mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Merge remote-tracking branch 'origin/master'
Conflicts: src/atom/cursor.coffee src/atom/editor.coffee src/atom/selection.coffee
This commit is contained in:
@@ -291,9 +291,36 @@ describe "Editor", ->
|
||||
expect(editor.getCursorPosition()).toEqual(row: 0, column: 0)
|
||||
[pageX, pageY] = window.pixelPositionForPoint(editor, [0, 8])
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 1}})
|
||||
$(document).trigger 'mouseup'
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 2}})
|
||||
expect(editor.getSelectedText()).toBe "quicksort"
|
||||
|
||||
describe "when it is clicked more then twice (tripple, quadruple, etc...)", ->
|
||||
it "selects the line under the cursor", ->
|
||||
expect(editor.getCursorPosition()).toEqual(row: 0, column: 0)
|
||||
|
||||
# Triple click
|
||||
[pageX, pageY] = window.pixelPositionForPoint(editor, [1, 8])
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 1}})
|
||||
$(document).trigger 'mouseup'
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 2}})
|
||||
$(document).trigger 'mouseup'
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 3}})
|
||||
expect(editor.getSelectedText()).toBe " var sort = function(items) {"
|
||||
$(document).trigger 'mouseup'
|
||||
|
||||
# Quad click
|
||||
[pageX, pageY] = window.pixelPositionForPoint(editor, [2, 3])
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 1}})
|
||||
$(document).trigger 'mouseup'
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 2}})
|
||||
$(document).trigger 'mouseup'
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 3}})
|
||||
$(document).trigger 'mouseup'
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 4}})
|
||||
expect(editor.getSelectedText()).toBe " if (items.length <= 1) return items;"
|
||||
$(document).trigger 'mouseup'
|
||||
|
||||
describe "selection", ->
|
||||
selection = null
|
||||
|
||||
@@ -385,12 +412,12 @@ describe "Editor", ->
|
||||
expect(range.end).toEqual({row: 5, column: 27})
|
||||
expect(editor.getCursorPosition()).toEqual(row: 5, column: 27)
|
||||
|
||||
it "creates a selection from the initial double click to mouse cursor's location ", ->
|
||||
it "creates a selection from word underneath double click to mouse cursor's location ", ->
|
||||
editor.attachToDom()
|
||||
editor.css(position: 'absolute', top: 10, left: 10)
|
||||
|
||||
# double click
|
||||
[pageX, pageY] = window.pixelPositionForPoint(editor, [4, 10])
|
||||
[pageX, pageY] = window.pixelPositionForPoint(editor, [4, 7])
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 1}})
|
||||
$(document).trigger 'mouseup'
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 2}})
|
||||
@@ -400,7 +427,7 @@ describe "Editor", ->
|
||||
editor.lines.trigger mousemoveEvent({pageX, pageY})
|
||||
|
||||
range = editor.selection.getRange()
|
||||
expect(range.start).toEqual({row: 4, column: 10})
|
||||
expect(range.start).toEqual({row: 4, column: 4})
|
||||
expect(range.end).toEqual({row: 5, column: 27})
|
||||
expect(editor.getCursorPosition()).toEqual(row: 5, column: 27)
|
||||
|
||||
@@ -412,7 +439,41 @@ describe "Editor", ->
|
||||
editor.lines.trigger mousemoveEvent({pageX, pageY})
|
||||
|
||||
range = editor.selection.getRange()
|
||||
expect(range.start).toEqual({row: 4, column: 10})
|
||||
expect(range.start).toEqual({row: 4, column: 4})
|
||||
expect(range.end).toEqual({row: 5, column: 27})
|
||||
expect(editor.getCursorPosition()).toEqual(row: 5, column: 27)
|
||||
|
||||
|
||||
it "creates a selection from line underneath triple click to mouse cursor's location ", ->
|
||||
editor.attachToDom()
|
||||
editor.css(position: 'absolute', top: 10, left: 10)
|
||||
|
||||
# double click
|
||||
[pageX, pageY] = window.pixelPositionForPoint(editor, [4, 7])
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 1}})
|
||||
$(document).trigger 'mouseup'
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 2}})
|
||||
$(document).trigger 'mouseup'
|
||||
editor.lines.trigger mousedownEvent({pageX, pageY, originalEvent: {detail: 3}})
|
||||
|
||||
# moving changes selection
|
||||
[pageX, pageY] = window.pixelPositionForPoint(editor, [5, 27])
|
||||
editor.lines.trigger mousemoveEvent({pageX, pageY})
|
||||
|
||||
range = editor.selection.getRange()
|
||||
expect(range.start).toEqual({row: 4, column: 0})
|
||||
expect(range.end).toEqual({row: 5, column: 27})
|
||||
expect(editor.getCursorPosition()).toEqual(row: 5, column: 27)
|
||||
|
||||
# mouse up may occur outside of editor, but still need to halt selection
|
||||
$(document).trigger 'mouseup'
|
||||
|
||||
# moving after mouse up should not change selection
|
||||
[pageX, pageY] = window.pixelPositionForPoint(editor, [8, 8])
|
||||
editor.lines.trigger mousemoveEvent({pageX, pageY})
|
||||
|
||||
range = editor.selection.getRange()
|
||||
expect(range.start).toEqual({row: 4, column: 0})
|
||||
expect(range.end).toEqual({row: 5, column: 27})
|
||||
expect(editor.getCursorPosition()).toEqual(row: 5, column: 27)
|
||||
|
||||
@@ -571,7 +632,7 @@ describe "Editor", ->
|
||||
|
||||
describe ".clipPosition(point)", ->
|
||||
it "selects the nearest valid position to the given point", ->
|
||||
expect(editor.clipPosition(row: 1000, column: 0)).toEqual(row: buffer.numLines() - 1, column: 0)
|
||||
expect(editor.clipPosition(row: 1000, column: 0)).toEqual(row: buffer.lastRow(), column: buffer.getLine(buffer.lastRow()).length)
|
||||
expect(editor.clipPosition(row: -5, column: 0)).toEqual(row: 0, column: 0)
|
||||
expect(editor.clipPosition(row: 1, column: 10000)).toEqual(row: 1, column: buffer.getLine(1).length)
|
||||
expect(editor.clipPosition(row: 1, column: -5)).toEqual(row: 1, column: 0)
|
||||
|
||||
@@ -184,7 +184,8 @@ describe "Selection", ->
|
||||
selection.selectWord()
|
||||
expect(selection.getText()).toBe ''
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
describe ".selectLine(row)", ->
|
||||
it "selects the entire line at given row", ->
|
||||
editor.setCursorPosition [0,2]
|
||||
selection.selectLine(1)
|
||||
expect(selection.getText()).toBe " var sort = function(items) {"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Editor = require 'editor'
|
||||
VimMode = require 'vim-mode'
|
||||
|
||||
describe "VimMode", ->
|
||||
fdescribe "VimMode", ->
|
||||
editor = null
|
||||
|
||||
beforeEach ->
|
||||
@@ -37,13 +37,20 @@ describe "VimMode", ->
|
||||
|
||||
describe "the x keybinding", ->
|
||||
it "deletes a charachter", ->
|
||||
editor.buffer.setText("12345")
|
||||
editor.setCursorPosition([0, 1])
|
||||
editor.buffer.setText("012345")
|
||||
editor.setCursorPosition([0, 4])
|
||||
|
||||
editor.trigger keydownEvent('x')
|
||||
expect(editor.buffer.getText()).toBe '01235'
|
||||
expect(editor.getCursorPosition()).toEqual([0, 4])
|
||||
|
||||
expect(editor.buffer.getText()).toBe '1345'
|
||||
expect(editor.getCursorPosition()).toEqual([0, 1])
|
||||
editor.trigger keydownEvent('x')
|
||||
expect(editor.buffer.getText()).toBe '0123'
|
||||
expect(editor.getCursorPosition()).toEqual([0, 3])
|
||||
|
||||
editor.trigger keydownEvent('x')
|
||||
expect(editor.buffer.getText()).toBe '012'
|
||||
expect(editor.getCursorPosition()).toEqual([0, 2])
|
||||
|
||||
describe "the d keybinding", ->
|
||||
describe "when followed by a d", ->
|
||||
@@ -53,11 +60,18 @@ describe "VimMode", ->
|
||||
|
||||
editor.trigger keydownEvent('d')
|
||||
editor.trigger keydownEvent('d')
|
||||
|
||||
expect(editor.buffer.getText()).toBe "12345\nABCDE"
|
||||
expect(editor.getCursorPosition()).toEqual([1,0])
|
||||
|
||||
describe "when the second d is prefixed by a count", ->
|
||||
it "deletes the last line", ->
|
||||
editor.buffer.setText("12345\nabcde\nABCDE")
|
||||
editor.setCursorPosition([2,1])
|
||||
editor.trigger keydownEvent('d')
|
||||
editor.trigger keydownEvent('d')
|
||||
expect(editor.buffer.getText()).toBe "12345\nabcde"
|
||||
expect(editor.getCursorPosition()).toEqual([1,0])
|
||||
|
||||
xdescribe "when the second d is prefixed by a count", ->
|
||||
it "deletes n lines, starting from the current", ->
|
||||
editor.buffer.setText("12345\nabcde\nABCDE\nQWERT")
|
||||
editor.setCursorPosition([1,1])
|
||||
@@ -135,11 +149,11 @@ describe "VimMode", ->
|
||||
|
||||
describe "the l keybinding", ->
|
||||
it "moves the cursor right, but not to the next line", ->
|
||||
editor.setCursorPosition([1,4])
|
||||
editor.setCursorPosition([1,3])
|
||||
editor.trigger keydownEvent('l')
|
||||
expect(editor.getCursorPosition()).toEqual([1,5])
|
||||
expect(editor.getCursorPosition()).toEqual([1,4])
|
||||
editor.trigger keydownEvent('l')
|
||||
expect(editor.getCursorPosition()).toEqual([1,5])
|
||||
expect(editor.getCursorPosition()).toEqual([1,4])
|
||||
|
||||
describe "the w keybinding", ->
|
||||
it "moves the cursor to the beginning of the next word", ->
|
||||
|
||||
@@ -22,8 +22,8 @@ jasmine.Env.prototype.equals_ = _.isEqual
|
||||
|
||||
emitObject = jasmine.StringPrettyPrinter.prototype.emitObject
|
||||
jasmine.StringPrettyPrinter.prototype.emitObject = (obj) ->
|
||||
if obj.toString
|
||||
@append obj.toString()
|
||||
if obj.inspect
|
||||
@append obj.inspect()
|
||||
else
|
||||
emitObject.call(this, obj)
|
||||
|
||||
|
||||
@@ -41,6 +41,9 @@ class Buffer
|
||||
getLine: (row) ->
|
||||
@lines[row]
|
||||
|
||||
getLineLength: (row) ->
|
||||
@lines[row].length
|
||||
|
||||
numLines: ->
|
||||
@getLines().length
|
||||
|
||||
@@ -50,6 +53,15 @@ class Buffer
|
||||
lastLine: ->
|
||||
@getLine(@lastRow())
|
||||
|
||||
deleteRow: (row) ->
|
||||
range = null
|
||||
if row == @lastRow()
|
||||
range = new Range([row - 1, @getLineLength(row - 1)], [row, @getLineLength(row)])
|
||||
else
|
||||
range = new Range([row, 0], [row + 1, 0])
|
||||
|
||||
@change(range, '')
|
||||
|
||||
insert: (point, text) ->
|
||||
@change(new Range(point, point), text)
|
||||
|
||||
|
||||
@@ -28,13 +28,13 @@ class Cursor extends View
|
||||
|
||||
getPosition: -> _.clone(@point)
|
||||
|
||||
getColumn: ->
|
||||
@getPosition().column
|
||||
|
||||
setColumn: (column) ->
|
||||
{ row } = @getPosition()
|
||||
@setPosition {row, column}
|
||||
|
||||
getColumn: ->
|
||||
@getPosition().column
|
||||
|
||||
getRow: ->
|
||||
@getPosition().row
|
||||
|
||||
|
||||
@@ -44,8 +44,8 @@ class Editor extends View
|
||||
'shift-up': 'select-up'
|
||||
'shift-down': 'select-down'
|
||||
enter: 'newline'
|
||||
backspace: 'delete-left'
|
||||
delete: 'delete-right'
|
||||
backspace: 'backspace'
|
||||
delete: 'delete'
|
||||
'meta-x': 'cut'
|
||||
'meta-c': 'copy'
|
||||
'meta-v': 'paste'
|
||||
@@ -59,8 +59,8 @@ class Editor extends View
|
||||
@on 'select-up', => @selectUp()
|
||||
@on 'select-down', => @selectDown()
|
||||
@on 'newline', => @insertNewline()
|
||||
@on 'delete-left', => @deleteLeft()
|
||||
@on 'delete-right', => @deleteRight()
|
||||
@on 'backspace', => @backspace()
|
||||
@on 'delete', => @delete()
|
||||
@on 'cut', => @cutSelection()
|
||||
@on 'copy', => @copySelection()
|
||||
@on 'paste', => @paste()
|
||||
@@ -82,10 +82,12 @@ class Editor extends View
|
||||
|
||||
if clickCount == 1
|
||||
@setCursorPosition @pointFromMouseEvent(e)
|
||||
@selectTextOnMouseMovement()
|
||||
else if clickCount == 2
|
||||
@selection.selectWord()
|
||||
@selectTextOnMouseMovement()
|
||||
else if clickCount >= 3
|
||||
@selection.selectLine(@getCursorRow())
|
||||
|
||||
@selectTextOnMouseMovement()
|
||||
|
||||
@hiddenInput.on "textInput", (e) =>
|
||||
@insertText(e.originalEvent.data)
|
||||
@@ -158,8 +160,13 @@ class Editor extends View
|
||||
@lines.find("pre.line:eq(#{row})")
|
||||
|
||||
clipPosition: ({row, column}) ->
|
||||
row = Math.min(Math.max(0, row), @buffer.numLines() - 1)
|
||||
column = Math.min(Math.max(0, column), @buffer.getLine(row).length)
|
||||
if row > @buffer.lastRow()
|
||||
row = @buffer.lastRow()
|
||||
column = @buffer.getLine(row).length
|
||||
else
|
||||
row = Math.min(Math.max(0, row), @buffer.numLines() - 1)
|
||||
column = Math.min(Math.max(0, column), @buffer.getLine(row).length)
|
||||
|
||||
new Point(row, column)
|
||||
|
||||
pixelPositionFromPoint: ({row, column}) ->
|
||||
@@ -223,11 +230,11 @@ class Editor extends View
|
||||
copySelection: -> @selection.copy()
|
||||
paste: -> @selection.insertText(atom.native.readFromPasteboard())
|
||||
|
||||
deleteLeft: ->
|
||||
backspace: ->
|
||||
@selectLeft() if @selection.isEmpty()
|
||||
@selection.delete()
|
||||
|
||||
deleteRight: ->
|
||||
delete: ->
|
||||
@selectRight() if @selection.isEmpty()
|
||||
@selection.delete()
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class Point
|
||||
else
|
||||
@row == other.row and @column == other.column
|
||||
|
||||
toString: ->
|
||||
inspect: ->
|
||||
"(#{@row}, #{@column})"
|
||||
|
||||
compare: (other) ->
|
||||
|
||||
@@ -17,7 +17,7 @@ class Range
|
||||
copy: (range) ->
|
||||
new Range(_.clone(@start), _.clone(@end))
|
||||
|
||||
toString: ->
|
||||
inpsect: ->
|
||||
"[#{@start.toString()} - #{@end.toString()}]"
|
||||
|
||||
isEmpty: ->
|
||||
|
||||
@@ -113,6 +113,10 @@ class Selection extends View
|
||||
range = new Range([row, column + startOffset], [row, column + endOffset])
|
||||
@setRange range
|
||||
|
||||
selectLine: (row) ->
|
||||
rowLength = @editor.buffer.getLine(row).length
|
||||
@setRange new Range([row, 0], [row, rowLength])
|
||||
|
||||
selectRight: ->
|
||||
@modifySelection =>
|
||||
@cursor.moveRight()
|
||||
|
||||
@@ -10,6 +10,8 @@ class VimMode
|
||||
opStack: null
|
||||
|
||||
constructor: (@editor) ->
|
||||
requireStylesheet 'vim-mode.css'
|
||||
|
||||
@opStack = []
|
||||
@editor.addClass('command-mode')
|
||||
|
||||
@@ -76,14 +78,15 @@ class VimMode
|
||||
@pushOperator(new operators.NumericPrefix(num))
|
||||
|
||||
delete: () ->
|
||||
if @isDeletePending()
|
||||
@pushOperator(new motions.SelectLines(@editor))
|
||||
if deleteOperation = @isDeletePending()
|
||||
deleteOperation.complete = true
|
||||
@processOpStack()
|
||||
else
|
||||
@pushOperator(new operators.Delete(@editor))
|
||||
|
||||
isDeletePending: () ->
|
||||
for op in @opStack
|
||||
return true if op instanceof operators.Delete
|
||||
return op if op instanceof operators.Delete
|
||||
false
|
||||
|
||||
pushOperator: (op) ->
|
||||
|
||||
@@ -4,7 +4,10 @@ class Command
|
||||
|
||||
class DeleteRight extends Command
|
||||
execute: ->
|
||||
@editor.deleteRight()
|
||||
@editor.delete()
|
||||
isOnEOL = @editor.getCursorColumn() == @editor.getCurrentLine().length
|
||||
if isOnEOL
|
||||
@editor.setCursorColumn(@editor.getCursorColumn() - 1)
|
||||
|
||||
module.exports = { DeleteRight }
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ class MoveLeft extends Motion
|
||||
class MoveRight extends Motion
|
||||
execute: ->
|
||||
{column, row} = @editor.getCursorPosition()
|
||||
currentLineLength = @editor.buffer.getLine(row).length
|
||||
@editor.moveCursorRight() if column < currentLineLength
|
||||
isOnLastCharachter = @editor.getCursorColumn() == @editor.getCurrentLine().length - 1
|
||||
@editor.moveCursorRight() unless isOnLastCharachter
|
||||
|
||||
class MoveUp extends Motion
|
||||
execute: ->
|
||||
@@ -55,16 +55,4 @@ class MoveToNextWord extends Motion
|
||||
column = nextLineMatch?.index or 0
|
||||
{ row, column }
|
||||
|
||||
class SelectLines extends Motion
|
||||
count: null
|
||||
|
||||
constructor: (@editor) ->
|
||||
@count = 1
|
||||
|
||||
setCount: (@count) ->
|
||||
|
||||
select: ->
|
||||
@editor.setCursorPosition(column: 0, row: @editor.getCursorRow())
|
||||
@editor.selectToPosition(column: 0, row: @editor.getCursorRow() + @count)
|
||||
|
||||
module.exports = { MoveLeft, MoveRight, MoveUp, MoveDown, MoveToNextWord, SelectLines }
|
||||
module.exports = { MoveLeft, MoveRight, MoveUp, MoveDown, MoveToNextWord }
|
||||
|
||||
@@ -39,7 +39,8 @@ class Delete
|
||||
@motion.select()
|
||||
@editor.getSelection().delete()
|
||||
else
|
||||
@editor.deleteLine()
|
||||
@editor.buffer.deleteRow(@editor.getCursorRow())
|
||||
@editor.setCursorPosition([@editor.getCursorRow(), 0])
|
||||
|
||||
compose: (motion) ->
|
||||
@motion = motion
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
overflow-y: scroll;
|
||||
overflow-x: auto;
|
||||
cursor: default;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.editor pre {
|
||||
|
||||
4
static/vim-mode.css
Normal file
4
static/vim-mode.css
Normal file
@@ -0,0 +1,4 @@
|
||||
.editor.command-mode .cursor {
|
||||
border-left: 0;
|
||||
background-color: #9dff9d;
|
||||
}
|
||||
Reference in New Issue
Block a user