Merge pull request #160 from jazzpi/visual-marks
Basic support for visual marks ('<,'>)
This commit is contained in:
commit
6c22b3b701
5 changed files with 167 additions and 107 deletions
|
|
@ -5,7 +5,8 @@ CommandError = require './command-error'
|
||||||
|
|
||||||
class Command
|
class Command
|
||||||
constructor: (@editor, @exState) ->
|
constructor: (@editor, @exState) ->
|
||||||
@viewModel = new ExViewModel(@)
|
@selections = @exState.getSelections()
|
||||||
|
@viewModel = new ExViewModel(@, Object.keys(@selections).length > 0)
|
||||||
|
|
||||||
parseAddr: (str, curPos) ->
|
parseAddr: (str, curPos) ->
|
||||||
if str is '.'
|
if str is '.'
|
||||||
|
|
@ -97,6 +98,13 @@ class Command
|
||||||
|
|
||||||
curPos = @editor.getCursorBufferPosition()
|
curPos = @editor.getCursorBufferPosition()
|
||||||
|
|
||||||
|
# Special case: run command on selection. This can't be handled by simply
|
||||||
|
# parsing the mark since vim-mode doesn't set it (and it would be fairly
|
||||||
|
# useless with multiple selections)
|
||||||
|
if addr1 is "'<" and addr2 is "'>"
|
||||||
|
runOverSelections = true
|
||||||
|
else
|
||||||
|
runOverSelections = false
|
||||||
if addr1?
|
if addr1?
|
||||||
address1 = @parseAddr(addr1, curPos)
|
address1 = @parseAddr(addr1, curPos)
|
||||||
else
|
else
|
||||||
|
|
@ -149,9 +157,7 @@ class Command
|
||||||
[m, command, args] = cl.match(/^(\w+)(.*)/)
|
[m, command, args] = cl.match(/^(\w+)(.*)/)
|
||||||
|
|
||||||
# If the command matches an existing one exactly, execute that one
|
# If the command matches an existing one exactly, execute that one
|
||||||
if (func = Ex.singleton()[command])?
|
unless (func = Ex.singleton()[command])?
|
||||||
func({ range, args, @vimState, @exState, @editor })
|
|
||||||
else
|
|
||||||
# Step 8: Match command against existing commands
|
# Step 8: Match command against existing commands
|
||||||
matching = (name for name, val of Ex.singleton() when \
|
matching = (name for name, val of Ex.singleton() when \
|
||||||
name.indexOf(command) is 0)
|
name.indexOf(command) is 0)
|
||||||
|
|
@ -161,7 +167,14 @@ class Command
|
||||||
command = matching[0]
|
command = matching[0]
|
||||||
|
|
||||||
func = Ex.singleton()[command]
|
func = Ex.singleton()[command]
|
||||||
|
|
||||||
if func?
|
if func?
|
||||||
|
if runOverSelections
|
||||||
|
for id, selection of @selections
|
||||||
|
bufferRange = selection.getBufferRange()
|
||||||
|
range = [bufferRange.start.row, bufferRange.end.row]
|
||||||
|
func({ range, args, @vimState, @exState, @editor })
|
||||||
|
else
|
||||||
func({ range, args, @vimState, @exState, @editor })
|
func({ range, args, @vimState, @exState, @editor })
|
||||||
else
|
else
|
||||||
throw new CommandError("Not an editor command: #{input.characters}")
|
throw new CommandError("Not an editor command: #{input.characters}")
|
||||||
|
|
|
||||||
|
|
@ -60,4 +60,13 @@ class ExState
|
||||||
@clearOpStack()
|
@clearOpStack()
|
||||||
@emitter.emit('processed-op-stack')
|
@emitter.emit('processed-op-stack')
|
||||||
|
|
||||||
|
# Returns all non-empty selections
|
||||||
|
getSelections: ->
|
||||||
|
filtered = {}
|
||||||
|
for id, selection of @editor.getSelections()
|
||||||
|
unless selection.isEmpty()
|
||||||
|
filtered[id] = selection
|
||||||
|
|
||||||
|
return filtered
|
||||||
|
|
||||||
module.exports = ExState
|
module.exports = ExState
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,13 @@ Ex = require './ex'
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
class ExViewModel extends ViewModel
|
class ExViewModel extends ViewModel
|
||||||
constructor: (@exCommand) ->
|
constructor: (@exCommand, withSelection) ->
|
||||||
super(@exCommand, class: 'command')
|
super(@exCommand, class: 'command')
|
||||||
@historyIndex = -1
|
@historyIndex = -1
|
||||||
|
|
||||||
|
if withSelection
|
||||||
|
@view.editorElement.getModel().setText("'<,'>")
|
||||||
|
|
||||||
@view.editorElement.addEventListener('keydown', @tabAutocomplete)
|
@view.editorElement.addEventListener('keydown', @tabAutocomplete)
|
||||||
atom.commands.add(@view.editorElement, 'core:move-up', @increaseHistoryEx)
|
atom.commands.add(@view.editorElement, 'core:move-up', @increaseHistoryEx)
|
||||||
atom.commands.add(@view.editorElement, 'core:move-down', @decreaseHistoryEx)
|
atom.commands.add(@view.editorElement, 'core:move-down', @decreaseHistoryEx)
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ describe "the commands", ->
|
||||||
|
|
||||||
helpers.getEditorElement (element) ->
|
helpers.getEditorElement (element) ->
|
||||||
atom.commands.dispatch(element, "ex-mode:open")
|
atom.commands.dispatch(element, "ex-mode:open")
|
||||||
keydown('escape')
|
atom.commands.dispatch(element.getModel().normalModeInputView.editorElement,
|
||||||
|
"core:cancel")
|
||||||
editorElement = element
|
editorElement = element
|
||||||
editor = editorElement.getModel()
|
editor = editorElement.getModel()
|
||||||
vimState = vimMode.mainModule.getEditorState(editor)
|
vimState = vimMode.mainModule.getEditorState(editor)
|
||||||
|
|
@ -61,6 +62,9 @@ describe "the commands", ->
|
||||||
commandEditor.getModel().setText(text)
|
commandEditor.getModel().setText(text)
|
||||||
atom.commands.dispatch(commandEditor, "core:confirm")
|
atom.commands.dispatch(commandEditor, "core:confirm")
|
||||||
|
|
||||||
|
openEx = ->
|
||||||
|
atom.commands.dispatch(editorElement, "ex-mode:open")
|
||||||
|
|
||||||
describe ":write", ->
|
describe ":write", ->
|
||||||
describe "when editing a new file", ->
|
describe "when editing a new file", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
|
|
@ -68,14 +72,14 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "opens the save dialog", ->
|
it "opens the save dialog", ->
|
||||||
spyOn(atom, 'showSaveDialogSync')
|
spyOn(atom, 'showSaveDialogSync')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('write')
|
submitNormalModeInputText('write')
|
||||||
expect(atom.showSaveDialogSync).toHaveBeenCalled()
|
expect(atom.showSaveDialogSync).toHaveBeenCalled()
|
||||||
|
|
||||||
it "saves when a path is specified in the save dialog", ->
|
it "saves when a path is specified in the save dialog", ->
|
||||||
filePath = projectPath('write-from-save-dialog')
|
filePath = projectPath('write-from-save-dialog')
|
||||||
spyOn(atom, 'showSaveDialogSync').andReturn(filePath)
|
spyOn(atom, 'showSaveDialogSync').andReturn(filePath)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('write')
|
submitNormalModeInputText('write')
|
||||||
expect(fs.existsSync(filePath)).toBe(true)
|
expect(fs.existsSync(filePath)).toBe(true)
|
||||||
expect(fs.readFileSync(filePath, 'utf-8')).toEqual('abc\ndef')
|
expect(fs.readFileSync(filePath, 'utf-8')).toEqual('abc\ndef')
|
||||||
|
|
@ -84,7 +88,7 @@ describe "the commands", ->
|
||||||
it "saves when a path is specified in the save dialog", ->
|
it "saves when a path is specified in the save dialog", ->
|
||||||
spyOn(atom, 'showSaveDialogSync').andReturn(undefined)
|
spyOn(atom, 'showSaveDialogSync').andReturn(undefined)
|
||||||
spyOn(fs, 'writeFileSync')
|
spyOn(fs, 'writeFileSync')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('write')
|
submitNormalModeInputText('write')
|
||||||
expect(fs.writeFileSync.calls.length).toBe(0)
|
expect(fs.writeFileSync.calls.length).toBe(0)
|
||||||
|
|
||||||
|
|
@ -100,7 +104,7 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "saves the file", ->
|
it "saves the file", ->
|
||||||
editor.setText('abc')
|
editor.setText('abc')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('write')
|
submitNormalModeInputText('write')
|
||||||
expect(fs.readFileSync(filePath, 'utf-8')).toEqual('abc')
|
expect(fs.readFileSync(filePath, 'utf-8')).toEqual('abc')
|
||||||
expect(editor.isModified()).toBe(false)
|
expect(editor.isModified()).toBe(false)
|
||||||
|
|
@ -111,7 +115,7 @@ describe "the commands", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
newPath = path.relative(dir, "#{filePath}.new")
|
newPath = path.relative(dir, "#{filePath}.new")
|
||||||
editor.getBuffer().setText('abc')
|
editor.getBuffer().setText('abc')
|
||||||
keydown(':')
|
openEx()
|
||||||
|
|
||||||
afterEach ->
|
afterEach ->
|
||||||
submitNormalModeInputText("write #{newPath}")
|
submitNormalModeInputText("write #{newPath}")
|
||||||
|
|
@ -133,7 +137,7 @@ describe "the commands", ->
|
||||||
newPath = path.join('~', newPath)
|
newPath = path.join('~', newPath)
|
||||||
|
|
||||||
it "throws an error with more than one path", ->
|
it "throws an error with more than one path", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('write path1 path2')
|
submitNormalModeInputText('write path1 path2')
|
||||||
expect(atom.notifications.notifications[0].message).toEqual(
|
expect(atom.notifications.notifications[0].message).toEqual(
|
||||||
'Command error: Only one file name allowed'
|
'Command error: Only one file name allowed'
|
||||||
|
|
@ -150,7 +154,7 @@ describe "the commands", ->
|
||||||
fs.removeSync(existsPath)
|
fs.removeSync(existsPath)
|
||||||
|
|
||||||
it "throws an error if the file already exists", ->
|
it "throws an error if the file already exists", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText("write #{existsPath}")
|
submitNormalModeInputText("write #{existsPath}")
|
||||||
expect(atom.notifications.notifications[0].message).toEqual(
|
expect(atom.notifications.notifications[0].message).toEqual(
|
||||||
'Command error: File exists (add ! to override)'
|
'Command error: File exists (add ! to override)'
|
||||||
|
|
@ -158,7 +162,7 @@ describe "the commands", ->
|
||||||
expect(fs.readFileSync(existsPath, 'utf-8')).toEqual('abc')
|
expect(fs.readFileSync(existsPath, 'utf-8')).toEqual('abc')
|
||||||
|
|
||||||
it "writes if forced with :write!", ->
|
it "writes if forced with :write!", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText("write! #{existsPath}")
|
submitNormalModeInputText("write! #{existsPath}")
|
||||||
expect(atom.notifications.notifications).toEqual([])
|
expect(atom.notifications.notifications).toEqual([])
|
||||||
expect(fs.readFileSync(existsPath, 'utf-8')).toEqual('abc\ndef')
|
expect(fs.readFileSync(existsPath, 'utf-8')).toEqual('abc\ndef')
|
||||||
|
|
@ -166,7 +170,7 @@ describe "the commands", ->
|
||||||
describe ":wall", ->
|
describe ":wall", ->
|
||||||
it "saves all", ->
|
it "saves all", ->
|
||||||
spyOn(atom.workspace, 'saveAll')
|
spyOn(atom.workspace, 'saveAll')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('wall')
|
submitNormalModeInputText('wall')
|
||||||
expect(atom.workspace.saveAll).toHaveBeenCalled()
|
expect(atom.workspace.saveAll).toHaveBeenCalled()
|
||||||
|
|
||||||
|
|
@ -177,14 +181,14 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "opens the save dialog", ->
|
it "opens the save dialog", ->
|
||||||
spyOn(atom, 'showSaveDialogSync')
|
spyOn(atom, 'showSaveDialogSync')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('saveas')
|
submitNormalModeInputText('saveas')
|
||||||
expect(atom.showSaveDialogSync).toHaveBeenCalled()
|
expect(atom.showSaveDialogSync).toHaveBeenCalled()
|
||||||
|
|
||||||
it "saves when a path is specified in the save dialog", ->
|
it "saves when a path is specified in the save dialog", ->
|
||||||
filePath = projectPath('saveas-from-save-dialog')
|
filePath = projectPath('saveas-from-save-dialog')
|
||||||
spyOn(atom, 'showSaveDialogSync').andReturn(filePath)
|
spyOn(atom, 'showSaveDialogSync').andReturn(filePath)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('saveas')
|
submitNormalModeInputText('saveas')
|
||||||
expect(fs.existsSync(filePath)).toBe(true)
|
expect(fs.existsSync(filePath)).toBe(true)
|
||||||
expect(fs.readFileSync(filePath, 'utf-8')).toEqual('abc\ndef')
|
expect(fs.readFileSync(filePath, 'utf-8')).toEqual('abc\ndef')
|
||||||
|
|
@ -192,7 +196,7 @@ describe "the commands", ->
|
||||||
it "saves when a path is specified in the save dialog", ->
|
it "saves when a path is specified in the save dialog", ->
|
||||||
spyOn(atom, 'showSaveDialogSync').andReturn(undefined)
|
spyOn(atom, 'showSaveDialogSync').andReturn(undefined)
|
||||||
spyOn(fs, 'writeFileSync')
|
spyOn(fs, 'writeFileSync')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('saveas')
|
submitNormalModeInputText('saveas')
|
||||||
expect(fs.writeFileSync.calls.length).toBe(0)
|
expect(fs.writeFileSync.calls.length).toBe(0)
|
||||||
|
|
||||||
|
|
@ -208,7 +212,7 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "complains if no path given", ->
|
it "complains if no path given", ->
|
||||||
editor.setText('abc')
|
editor.setText('abc')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('saveas')
|
submitNormalModeInputText('saveas')
|
||||||
expect(atom.notifications.notifications[0].message).toEqual(
|
expect(atom.notifications.notifications[0].message).toEqual(
|
||||||
'Command error: Argument required'
|
'Command error: Argument required'
|
||||||
|
|
@ -220,7 +224,7 @@ describe "the commands", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
newPath = path.relative(dir, "#{filePath}.new")
|
newPath = path.relative(dir, "#{filePath}.new")
|
||||||
editor.getBuffer().setText('abc')
|
editor.getBuffer().setText('abc')
|
||||||
keydown(':')
|
openEx()
|
||||||
|
|
||||||
afterEach ->
|
afterEach ->
|
||||||
submitNormalModeInputText("saveas #{newPath}")
|
submitNormalModeInputText("saveas #{newPath}")
|
||||||
|
|
@ -242,7 +246,7 @@ describe "the commands", ->
|
||||||
newPath = path.join('~', newPath)
|
newPath = path.join('~', newPath)
|
||||||
|
|
||||||
it "throws an error with more than one path", ->
|
it "throws an error with more than one path", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('saveas path1 path2')
|
submitNormalModeInputText('saveas path1 path2')
|
||||||
expect(atom.notifications.notifications[0].message).toEqual(
|
expect(atom.notifications.notifications[0].message).toEqual(
|
||||||
'Command error: Only one file name allowed'
|
'Command error: Only one file name allowed'
|
||||||
|
|
@ -259,7 +263,7 @@ describe "the commands", ->
|
||||||
fs.removeSync(existsPath)
|
fs.removeSync(existsPath)
|
||||||
|
|
||||||
it "throws an error if the file already exists", ->
|
it "throws an error if the file already exists", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText("saveas #{existsPath}")
|
submitNormalModeInputText("saveas #{existsPath}")
|
||||||
expect(atom.notifications.notifications[0].message).toEqual(
|
expect(atom.notifications.notifications[0].message).toEqual(
|
||||||
'Command error: File exists (add ! to override)'
|
'Command error: File exists (add ! to override)'
|
||||||
|
|
@ -267,7 +271,7 @@ describe "the commands", ->
|
||||||
expect(fs.readFileSync(existsPath, 'utf-8')).toEqual('abc')
|
expect(fs.readFileSync(existsPath, 'utf-8')).toEqual('abc')
|
||||||
|
|
||||||
it "writes if forced with :saveas!", ->
|
it "writes if forced with :saveas!", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText("saveas! #{existsPath}")
|
submitNormalModeInputText("saveas! #{existsPath}")
|
||||||
expect(atom.notifications.notifications).toEqual([])
|
expect(atom.notifications.notifications).toEqual([])
|
||||||
expect(fs.readFileSync(existsPath, 'utf-8')).toEqual('abc\ndef')
|
expect(fs.readFileSync(existsPath, 'utf-8')).toEqual('abc\ndef')
|
||||||
|
|
@ -281,7 +285,7 @@ describe "the commands", ->
|
||||||
atom.workspace.open()
|
atom.workspace.open()
|
||||||
|
|
||||||
it "closes the active pane item if not modified", ->
|
it "closes the active pane item if not modified", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('quit')
|
submitNormalModeInputText('quit')
|
||||||
expect(pane.destroyActiveItem).toHaveBeenCalled()
|
expect(pane.destroyActiveItem).toHaveBeenCalled()
|
||||||
expect(pane.getItems().length).toBe(1)
|
expect(pane.getItems().length).toBe(1)
|
||||||
|
|
@ -292,14 +296,14 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "opens the prompt to save", ->
|
it "opens the prompt to save", ->
|
||||||
spyOn(pane, 'promptToSaveItem')
|
spyOn(pane, 'promptToSaveItem')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('quit')
|
submitNormalModeInputText('quit')
|
||||||
expect(pane.promptToSaveItem).toHaveBeenCalled()
|
expect(pane.promptToSaveItem).toHaveBeenCalled()
|
||||||
|
|
||||||
describe ":quitall", ->
|
describe ":quitall", ->
|
||||||
it "closes Atom", ->
|
it "closes Atom", ->
|
||||||
spyOn(atom, 'close')
|
spyOn(atom, 'close')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('quitall')
|
submitNormalModeInputText('quitall')
|
||||||
expect(atom.close).toHaveBeenCalled()
|
expect(atom.close).toHaveBeenCalled()
|
||||||
|
|
||||||
|
|
@ -307,7 +311,7 @@ describe "the commands", ->
|
||||||
it "acts as an alias to :quit", ->
|
it "acts as an alias to :quit", ->
|
||||||
spyOn(Ex, 'tabclose').andCallThrough()
|
spyOn(Ex, 'tabclose').andCallThrough()
|
||||||
spyOn(Ex, 'quit').andCallThrough()
|
spyOn(Ex, 'quit').andCallThrough()
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('tabclose')
|
submitNormalModeInputText('tabclose')
|
||||||
expect(Ex.quit).toHaveBeenCalledWith(Ex.tabclose.calls[0].args...)
|
expect(Ex.quit).toHaveBeenCalledWith(Ex.tabclose.calls[0].args...)
|
||||||
|
|
||||||
|
|
@ -321,13 +325,13 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "switches to the next tab", ->
|
it "switches to the next tab", ->
|
||||||
pane.activateItemAtIndex(1)
|
pane.activateItemAtIndex(1)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('tabnext')
|
submitNormalModeInputText('tabnext')
|
||||||
expect(pane.getActiveItemIndex()).toBe(2)
|
expect(pane.getActiveItemIndex()).toBe(2)
|
||||||
|
|
||||||
it "wraps around", ->
|
it "wraps around", ->
|
||||||
pane.activateItemAtIndex(pane.getItems().length - 1)
|
pane.activateItemAtIndex(pane.getItems().length - 1)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('tabnext')
|
submitNormalModeInputText('tabnext')
|
||||||
expect(pane.getActiveItemIndex()).toBe(0)
|
expect(pane.getActiveItemIndex()).toBe(0)
|
||||||
|
|
||||||
|
|
@ -341,13 +345,13 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "switches to the previous tab", ->
|
it "switches to the previous tab", ->
|
||||||
pane.activateItemAtIndex(1)
|
pane.activateItemAtIndex(1)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('tabprevious')
|
submitNormalModeInputText('tabprevious')
|
||||||
expect(pane.getActiveItemIndex()).toBe(0)
|
expect(pane.getActiveItemIndex()).toBe(0)
|
||||||
|
|
||||||
it "wraps around", ->
|
it "wraps around", ->
|
||||||
pane.activateItemAtIndex(0)
|
pane.activateItemAtIndex(0)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('tabprevious')
|
submitNormalModeInputText('tabprevious')
|
||||||
expect(pane.getActiveItemIndex()).toBe(pane.getItems().length - 1)
|
expect(pane.getActiveItemIndex()).toBe(pane.getItems().length - 1)
|
||||||
|
|
||||||
|
|
@ -358,7 +362,7 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "writes the file, then quits", ->
|
it "writes the file, then quits", ->
|
||||||
spyOn(atom, 'showSaveDialogSync').andReturn(projectPath('wq-1'))
|
spyOn(atom, 'showSaveDialogSync').andReturn(projectPath('wq-1'))
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('wq')
|
submitNormalModeInputText('wq')
|
||||||
expect(Ex.write).toHaveBeenCalled()
|
expect(Ex.write).toHaveBeenCalled()
|
||||||
# Since `:wq` only calls `:quit` after `:write` is finished, we need to
|
# Since `:wq` only calls `:quit` after `:write` is finished, we need to
|
||||||
|
|
@ -367,7 +371,7 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "doesn't quit when the file is new and no path is specified in the save dialog", ->
|
it "doesn't quit when the file is new and no path is specified in the save dialog", ->
|
||||||
spyOn(atom, 'showSaveDialogSync').andReturn(undefined)
|
spyOn(atom, 'showSaveDialogSync').andReturn(undefined)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('wq')
|
submitNormalModeInputText('wq')
|
||||||
expect(Ex.write).toHaveBeenCalled()
|
expect(Ex.write).toHaveBeenCalled()
|
||||||
wasNotCalled = false
|
wasNotCalled = false
|
||||||
|
|
@ -377,7 +381,7 @@ describe "the commands", ->
|
||||||
waitsFor((-> wasNotCalled), 100)
|
waitsFor((-> wasNotCalled), 100)
|
||||||
|
|
||||||
it "passes the file name", ->
|
it "passes the file name", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('wq wq-2')
|
submitNormalModeInputText('wq wq-2')
|
||||||
expect(Ex.write)
|
expect(Ex.write)
|
||||||
.toHaveBeenCalled()
|
.toHaveBeenCalled()
|
||||||
|
|
@ -387,7 +391,7 @@ describe "the commands", ->
|
||||||
describe ":xit", ->
|
describe ":xit", ->
|
||||||
it "acts as an alias to :wq", ->
|
it "acts as an alias to :wq", ->
|
||||||
spyOn(Ex, 'wq')
|
spyOn(Ex, 'wq')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('xit')
|
submitNormalModeInputText('xit')
|
||||||
expect(Ex.wq).toHaveBeenCalled()
|
expect(Ex.wq).toHaveBeenCalled()
|
||||||
|
|
||||||
|
|
@ -395,7 +399,7 @@ describe "the commands", ->
|
||||||
it "calls :wall, then :quitall", ->
|
it "calls :wall, then :quitall", ->
|
||||||
spyOn(Ex, 'wall')
|
spyOn(Ex, 'wall')
|
||||||
spyOn(Ex, 'quitall')
|
spyOn(Ex, 'quitall')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('wqall')
|
submitNormalModeInputText('wqall')
|
||||||
expect(Ex.wall).toHaveBeenCalled()
|
expect(Ex.wall).toHaveBeenCalled()
|
||||||
expect(Ex.quitall).toHaveBeenCalled()
|
expect(Ex.quitall).toHaveBeenCalled()
|
||||||
|
|
@ -407,7 +411,7 @@ describe "the commands", ->
|
||||||
editor.getBuffer().setText('abc')
|
editor.getBuffer().setText('abc')
|
||||||
editor.saveAs(filePath)
|
editor.saveAs(filePath)
|
||||||
fs.writeFileSync(filePath, 'def')
|
fs.writeFileSync(filePath, 'def')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('edit')
|
submitNormalModeInputText('edit')
|
||||||
# Reloading takes a bit
|
# Reloading takes a bit
|
||||||
waitsFor((-> editor.getText() is 'def'),
|
waitsFor((-> editor.getText() is 'def'),
|
||||||
|
|
@ -419,7 +423,7 @@ describe "the commands", ->
|
||||||
editor.saveAs(filePath)
|
editor.saveAs(filePath)
|
||||||
editor.getBuffer().setText('abcd')
|
editor.getBuffer().setText('abcd')
|
||||||
fs.writeFileSync(filePath, 'def')
|
fs.writeFileSync(filePath, 'def')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('edit')
|
submitNormalModeInputText('edit')
|
||||||
expect(atom.notifications.notifications[0].message).toEqual(
|
expect(atom.notifications.notifications[0].message).toEqual(
|
||||||
'Command error: No write since last change (add ! to override)')
|
'Command error: No write since last change (add ! to override)')
|
||||||
|
|
@ -433,7 +437,7 @@ describe "the commands", ->
|
||||||
editor.saveAs(filePath)
|
editor.saveAs(filePath)
|
||||||
editor.getBuffer().setText('abcd')
|
editor.getBuffer().setText('abcd')
|
||||||
fs.writeFileSync(filePath, 'def')
|
fs.writeFileSync(filePath, 'def')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('edit!')
|
submitNormalModeInputText('edit!')
|
||||||
expect(atom.notifications.notifications.length).toBe(0)
|
expect(atom.notifications.notifications.length).toBe(0)
|
||||||
waitsFor((-> editor.getText() is 'def')
|
waitsFor((-> editor.getText() is 'def')
|
||||||
|
|
@ -441,7 +445,7 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "throws an error when editing a new file", ->
|
it "throws an error when editing a new file", ->
|
||||||
editor.getBuffer().reload()
|
editor.getBuffer().reload()
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('edit')
|
submitNormalModeInputText('edit')
|
||||||
expect(atom.notifications.notifications[0].message).toEqual(
|
expect(atom.notifications.notifications[0].message).toEqual(
|
||||||
'Command error: No file name')
|
'Command error: No file name')
|
||||||
|
|
@ -457,18 +461,18 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "opens the specified path", ->
|
it "opens the specified path", ->
|
||||||
filePath = projectPath('edit-new-test')
|
filePath = projectPath('edit-new-test')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText("edit #{filePath}")
|
submitNormalModeInputText("edit #{filePath}")
|
||||||
expect(atom.workspace.open).toHaveBeenCalledWith(filePath)
|
expect(atom.workspace.open).toHaveBeenCalledWith(filePath)
|
||||||
|
|
||||||
it "opens a relative path", ->
|
it "opens a relative path", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('edit edit-relative-test')
|
submitNormalModeInputText('edit edit-relative-test')
|
||||||
expect(atom.workspace.open).toHaveBeenCalledWith(
|
expect(atom.workspace.open).toHaveBeenCalledWith(
|
||||||
projectPath('edit-relative-test'))
|
projectPath('edit-relative-test'))
|
||||||
|
|
||||||
it "throws an error if trying to open more than one file", ->
|
it "throws an error if trying to open more than one file", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('edit edit-new-test-1 edit-new-test-2')
|
submitNormalModeInputText('edit edit-new-test-1 edit-new-test-2')
|
||||||
expect(atom.workspace.open.callCount).toBe(0)
|
expect(atom.workspace.open.callCount).toBe(0)
|
||||||
expect(atom.notifications.notifications[0].message).toEqual(
|
expect(atom.notifications.notifications[0].message).toEqual(
|
||||||
|
|
@ -478,14 +482,14 @@ describe "the commands", ->
|
||||||
it "acts as an alias to :edit if supplied with a path", ->
|
it "acts as an alias to :edit if supplied with a path", ->
|
||||||
spyOn(Ex, 'tabedit').andCallThrough()
|
spyOn(Ex, 'tabedit').andCallThrough()
|
||||||
spyOn(Ex, 'edit')
|
spyOn(Ex, 'edit')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('tabedit tabedit-test')
|
submitNormalModeInputText('tabedit tabedit-test')
|
||||||
expect(Ex.edit).toHaveBeenCalledWith(Ex.tabedit.calls[0].args...)
|
expect(Ex.edit).toHaveBeenCalledWith(Ex.tabedit.calls[0].args...)
|
||||||
|
|
||||||
it "acts as an alias to :tabnew if not supplied with a path", ->
|
it "acts as an alias to :tabnew if not supplied with a path", ->
|
||||||
spyOn(Ex, 'tabedit').andCallThrough()
|
spyOn(Ex, 'tabedit').andCallThrough()
|
||||||
spyOn(Ex, 'tabnew')
|
spyOn(Ex, 'tabnew')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('tabedit ')
|
submitNormalModeInputText('tabedit ')
|
||||||
expect(Ex.tabnew)
|
expect(Ex.tabnew)
|
||||||
.toHaveBeenCalledWith(Ex.tabedit.calls[0].args...)
|
.toHaveBeenCalledWith(Ex.tabedit.calls[0].args...)
|
||||||
|
|
@ -493,14 +497,14 @@ describe "the commands", ->
|
||||||
describe ":tabnew", ->
|
describe ":tabnew", ->
|
||||||
it "opens a new tab", ->
|
it "opens a new tab", ->
|
||||||
spyOn(atom.workspace, 'open')
|
spyOn(atom.workspace, 'open')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('tabnew')
|
submitNormalModeInputText('tabnew')
|
||||||
expect(atom.workspace.open).toHaveBeenCalled()
|
expect(atom.workspace.open).toHaveBeenCalled()
|
||||||
|
|
||||||
it "opens a new tab for editing when provided an argument", ->
|
it "opens a new tab for editing when provided an argument", ->
|
||||||
spyOn(Ex, 'tabnew').andCallThrough()
|
spyOn(Ex, 'tabnew').andCallThrough()
|
||||||
spyOn(Ex, 'tabedit')
|
spyOn(Ex, 'tabedit')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('tabnew tabnew-test')
|
submitNormalModeInputText('tabnew tabnew-test')
|
||||||
expect(Ex.tabedit)
|
expect(Ex.tabedit)
|
||||||
.toHaveBeenCalledWith(Ex.tabnew.calls[0].args...)
|
.toHaveBeenCalledWith(Ex.tabnew.calls[0].args...)
|
||||||
|
|
@ -512,14 +516,14 @@ describe "the commands", ->
|
||||||
spyOn(pane, 'splitDown').andCallThrough()
|
spyOn(pane, 'splitDown').andCallThrough()
|
||||||
filePath = projectPath('split')
|
filePath = projectPath('split')
|
||||||
editor.saveAs(filePath)
|
editor.saveAs(filePath)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('split')
|
submitNormalModeInputText('split')
|
||||||
expect(pane.splitDown).toHaveBeenCalled()
|
expect(pane.splitDown).toHaveBeenCalled()
|
||||||
else
|
else
|
||||||
spyOn(pane, 'splitUp').andCallThrough()
|
spyOn(pane, 'splitUp').andCallThrough()
|
||||||
filePath = projectPath('split')
|
filePath = projectPath('split')
|
||||||
editor.saveAs(filePath)
|
editor.saveAs(filePath)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('split')
|
submitNormalModeInputText('split')
|
||||||
expect(pane.splitUp).toHaveBeenCalled()
|
expect(pane.splitUp).toHaveBeenCalled()
|
||||||
# FIXME: Should test whether the new pane contains a TextEditor
|
# FIXME: Should test whether the new pane contains a TextEditor
|
||||||
|
|
@ -532,7 +536,7 @@ describe "the commands", ->
|
||||||
spyOn(pane, 'splitRight').andCallThrough()
|
spyOn(pane, 'splitRight').andCallThrough()
|
||||||
filePath = projectPath('vsplit')
|
filePath = projectPath('vsplit')
|
||||||
editor.saveAs(filePath)
|
editor.saveAs(filePath)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('vsplit')
|
submitNormalModeInputText('vsplit')
|
||||||
expect(pane.splitLeft).toHaveBeenCalled()
|
expect(pane.splitLeft).toHaveBeenCalled()
|
||||||
else
|
else
|
||||||
|
|
@ -540,7 +544,7 @@ describe "the commands", ->
|
||||||
spyOn(pane, 'splitLeft').andCallThrough()
|
spyOn(pane, 'splitLeft').andCallThrough()
|
||||||
filePath = projectPath('vsplit')
|
filePath = projectPath('vsplit')
|
||||||
editor.saveAs(filePath)
|
editor.saveAs(filePath)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('vsplit')
|
submitNormalModeInputText('vsplit')
|
||||||
expect(pane.splitLeft).toHaveBeenCalled()
|
expect(pane.splitLeft).toHaveBeenCalled()
|
||||||
# FIXME: Should test whether the new pane contains a TextEditor
|
# FIXME: Should test whether the new pane contains a TextEditor
|
||||||
|
|
@ -552,19 +556,19 @@ describe "the commands", ->
|
||||||
editor.setCursorBufferPosition([2, 0])
|
editor.setCursorBufferPosition([2, 0])
|
||||||
|
|
||||||
it "deletes the current line", ->
|
it "deletes the current line", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('delete')
|
submitNormalModeInputText('delete')
|
||||||
expect(editor.getText()).toEqual('abc\ndef\njkl')
|
expect(editor.getText()).toEqual('abc\ndef\njkl')
|
||||||
|
|
||||||
it "copies the deleted text", ->
|
it "copies the deleted text", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('delete')
|
submitNormalModeInputText('delete')
|
||||||
expect(atom.clipboard.read()).toEqual('ghi\n')
|
expect(atom.clipboard.read()).toEqual('ghi\n')
|
||||||
|
|
||||||
it "deletes the lines in the given range", ->
|
it "deletes the lines in the given range", ->
|
||||||
processedOpStack = false
|
processedOpStack = false
|
||||||
exState.onDidProcessOpStack -> processedOpStack = true
|
exState.onDidProcessOpStack -> processedOpStack = true
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('1,2delete')
|
submitNormalModeInputText('1,2delete')
|
||||||
expect(editor.getText()).toEqual('ghi\njkl')
|
expect(editor.getText()).toEqual('ghi\njkl')
|
||||||
|
|
||||||
|
|
@ -577,7 +581,7 @@ describe "the commands", ->
|
||||||
expect(editor.getText()).toEqual('abc\n')
|
expect(editor.getText()).toEqual('abc\n')
|
||||||
|
|
||||||
it "undos deleting several lines at once", ->
|
it "undos deleting several lines at once", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('-1,.delete')
|
submitNormalModeInputText('-1,.delete')
|
||||||
expect(editor.getText()).toEqual('abc\njkl')
|
expect(editor.getText()).toEqual('abc\njkl')
|
||||||
atom.commands.dispatch(editorElement, 'core:undo')
|
atom.commands.dispatch(editorElement, 'core:undo')
|
||||||
|
|
@ -589,17 +593,17 @@ describe "the commands", ->
|
||||||
editor.setCursorBufferPosition([0, 0])
|
editor.setCursorBufferPosition([0, 0])
|
||||||
|
|
||||||
it "replaces a character on the current line", ->
|
it "replaces a character on the current line", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute /a/x')
|
submitNormalModeInputText(':substitute /a/x')
|
||||||
expect(editor.getText()).toEqual('xbcaABC\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('xbcaABC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "doesn't need a space before the arguments", ->
|
it "doesn't need a space before the arguments", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/a/x')
|
submitNormalModeInputText(':substitute/a/x')
|
||||||
expect(editor.getText()).toEqual('xbcaABC\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('xbcaABC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "respects modifiers passed to it", ->
|
it "respects modifiers passed to it", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/a/x/g')
|
submitNormalModeInputText(':substitute/a/x/g')
|
||||||
expect(editor.getText()).toEqual('xbcxABC\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('xbcxABC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
|
|
@ -608,7 +612,7 @@ describe "the commands", ->
|
||||||
expect(editor.getText()).toEqual('xbcxxBC\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('xbcxxBC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "replaces on multiple lines", ->
|
it "replaces on multiple lines", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':%substitute/abc/ghi')
|
submitNormalModeInputText(':%substitute/abc/ghi')
|
||||||
expect(editor.getText()).toEqual('ghiaABC\ndefdDEF\nghiaABC')
|
expect(editor.getText()).toEqual('ghiaABC\ndefdDEF\nghiaABC')
|
||||||
|
|
||||||
|
|
@ -622,18 +626,18 @@ describe "the commands", ->
|
||||||
editor.setCursorBufferPosition([2, 0])
|
editor.setCursorBufferPosition([2, 0])
|
||||||
|
|
||||||
it "yanks the current line", ->
|
it "yanks the current line", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('yank')
|
submitNormalModeInputText('yank')
|
||||||
expect(atom.clipboard.read()).toEqual('ghi\n')
|
expect(atom.clipboard.read()).toEqual('ghi\n')
|
||||||
|
|
||||||
it "yanks the lines in the given range", ->
|
it "yanks the lines in the given range", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('1,2yank')
|
submitNormalModeInputText('1,2yank')
|
||||||
expect(atom.clipboard.read()).toEqual('abc\ndef\n')
|
expect(atom.clipboard.read()).toEqual('abc\ndef\n')
|
||||||
|
|
||||||
describe "illegal delimiters", ->
|
describe "illegal delimiters", ->
|
||||||
test = (delim) ->
|
test = (delim) ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(":substitute #{delim}a#{delim}x#{delim}gi")
|
submitNormalModeInputText(":substitute #{delim}a#{delim}x#{delim}gi")
|
||||||
expect(atom.notifications.notifications[0].message).toEqual(
|
expect(atom.notifications.notifications[0].message).toEqual(
|
||||||
"Command error: Regular expressions can't be delimited by alphanumeric characters, '\\', '\"' or '|'")
|
"Command error: Regular expressions can't be delimited by alphanumeric characters, '\\', '\"' or '|'")
|
||||||
|
|
@ -650,12 +654,12 @@ describe "the commands", ->
|
||||||
editor.setText('abcabc\nabcabc')
|
editor.setText('abcabc\nabcabc')
|
||||||
|
|
||||||
it "removes the pattern without modifiers", ->
|
it "removes the pattern without modifiers", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(":substitute/abc//")
|
submitNormalModeInputText(":substitute/abc//")
|
||||||
expect(editor.getText()).toEqual('abc\nabcabc')
|
expect(editor.getText()).toEqual('abc\nabcabc')
|
||||||
|
|
||||||
it "removes the pattern with modifiers", ->
|
it "removes the pattern with modifiers", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(":substitute/abc//g")
|
submitNormalModeInputText(":substitute/abc//g")
|
||||||
expect(editor.getText()).toEqual('\nabcabc')
|
expect(editor.getText()).toEqual('\nabcabc')
|
||||||
|
|
||||||
|
|
@ -664,7 +668,7 @@ describe "the commands", ->
|
||||||
editor.setText('abc,def,ghi')
|
editor.setText('abc,def,ghi')
|
||||||
|
|
||||||
test = (escapeChar, escaped) ->
|
test = (escapeChar, escaped) ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(":substitute/,/\\#{escapeChar}/g")
|
submitNormalModeInputText(":substitute/,/\\#{escapeChar}/g")
|
||||||
expect(editor.getText()).toEqual("abc#{escaped}def#{escaped}ghi")
|
expect(editor.getText()).toEqual("abc#{escaped}def#{escaped}ghi")
|
||||||
|
|
||||||
|
|
@ -679,26 +683,26 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "uses case sensitive search if smartcase is off and the pattern is lowercase", ->
|
it "uses case sensitive search if smartcase is off and the pattern is lowercase", ->
|
||||||
atom.config.set('vim-mode.useSmartcaseForSearch', false)
|
atom.config.set('vim-mode.useSmartcaseForSearch', false)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/abc/ghi/g')
|
submitNormalModeInputText(':substitute/abc/ghi/g')
|
||||||
expect(editor.getText()).toEqual('ghiaABC\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('ghiaABC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "uses case sensitive search if smartcase is off and the pattern is uppercase", ->
|
it "uses case sensitive search if smartcase is off and the pattern is uppercase", ->
|
||||||
editor.setText('abcaABC\ndefdDEF\nabcaABC')
|
editor.setText('abcaABC\ndefdDEF\nabcaABC')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/ABC/ghi/g')
|
submitNormalModeInputText(':substitute/ABC/ghi/g')
|
||||||
expect(editor.getText()).toEqual('abcaghi\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('abcaghi\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "uses case insensitive search if smartcase is on and the pattern is lowercase", ->
|
it "uses case insensitive search if smartcase is on and the pattern is lowercase", ->
|
||||||
editor.setText('abcaABC\ndefdDEF\nabcaABC')
|
editor.setText('abcaABC\ndefdDEF\nabcaABC')
|
||||||
atom.config.set('vim-mode.useSmartcaseForSearch', true)
|
atom.config.set('vim-mode.useSmartcaseForSearch', true)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/abc/ghi/g')
|
submitNormalModeInputText(':substitute/abc/ghi/g')
|
||||||
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "uses case sensitive search if smartcase is on and the pattern is uppercase", ->
|
it "uses case sensitive search if smartcase is on and the pattern is uppercase", ->
|
||||||
editor.setText('abcaABC\ndefdDEF\nabcaABC')
|
editor.setText('abcaABC\ndefdDEF\nabcaABC')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/ABC/ghi/g')
|
submitNormalModeInputText(':substitute/ABC/ghi/g')
|
||||||
expect(editor.getText()).toEqual('abcaghi\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('abcaghi\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
|
|
@ -708,37 +712,37 @@ describe "the commands", ->
|
||||||
|
|
||||||
it "uses case insensitive search if smartcase is off and \c is in the pattern", ->
|
it "uses case insensitive search if smartcase is off and \c is in the pattern", ->
|
||||||
atom.config.set('vim-mode.useSmartcaseForSearch', false)
|
atom.config.set('vim-mode.useSmartcaseForSearch', false)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/abc\\c/ghi/g')
|
submitNormalModeInputText(':substitute/abc\\c/ghi/g')
|
||||||
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "doesn't matter where in the pattern \\c is", ->
|
it "doesn't matter where in the pattern \\c is", ->
|
||||||
atom.config.set('vim-mode.useSmartcaseForSearch', false)
|
atom.config.set('vim-mode.useSmartcaseForSearch', false)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/a\\cbc/ghi/g')
|
submitNormalModeInputText(':substitute/a\\cbc/ghi/g')
|
||||||
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "uses case sensitive search if smartcase is on, \\C is in the pattern and the pattern is lowercase", ->
|
it "uses case sensitive search if smartcase is on, \\C is in the pattern and the pattern is lowercase", ->
|
||||||
atom.config.set('vim-mode.useSmartcaseForSearch', true)
|
atom.config.set('vim-mode.useSmartcaseForSearch', true)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/a\\Cbc/ghi/g')
|
submitNormalModeInputText(':substitute/a\\Cbc/ghi/g')
|
||||||
expect(editor.getText()).toEqual('ghiaABC\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('ghiaABC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "overrides \\C with \\c if \\C comes first", ->
|
it "overrides \\C with \\c if \\C comes first", ->
|
||||||
atom.config.set('vim-mode.useSmartcaseForSearch', true)
|
atom.config.set('vim-mode.useSmartcaseForSearch', true)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/a\\Cb\\cc/ghi/g')
|
submitNormalModeInputText(':substitute/a\\Cb\\cc/ghi/g')
|
||||||
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "overrides \\C with \\c if \\c comes first", ->
|
it "overrides \\C with \\c if \\c comes first", ->
|
||||||
atom.config.set('vim-mode.useSmartcaseForSearch', true)
|
atom.config.set('vim-mode.useSmartcaseForSearch', true)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/a\\cb\\Cc/ghi/g')
|
submitNormalModeInputText(':substitute/a\\cb\\Cc/ghi/g')
|
||||||
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "overrides an appended /i flag with \\C", ->
|
it "overrides an appended /i flag with \\C", ->
|
||||||
atom.config.set('vim-mode.useSmartcaseForSearch', true)
|
atom.config.set('vim-mode.useSmartcaseForSearch', true)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/ab\\Cc/ghi/gi')
|
submitNormalModeInputText(':substitute/ab\\Cc/ghi/gi')
|
||||||
expect(editor.getText()).toEqual('ghiaABC\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('ghiaABC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
|
|
@ -747,23 +751,23 @@ describe "the commands", ->
|
||||||
editor.setText('abcaABC\ndefdDEF\nabcaABC')
|
editor.setText('abcaABC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "replaces \\1 with the first group", ->
|
it "replaces \\1 with the first group", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/bc(.{2})/X\\1X')
|
submitNormalModeInputText(':substitute/bc(.{2})/X\\1X')
|
||||||
expect(editor.getText()).toEqual('aXaAXBC\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('aXaAXBC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "replaces multiple groups", ->
|
it "replaces multiple groups", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/a([a-z]*)aA([A-Z]*)/X\\1XY\\2Y')
|
submitNormalModeInputText(':substitute/a([a-z]*)aA([A-Z]*)/X\\1XY\\2Y')
|
||||||
expect(editor.getText()).toEqual('XbcXYBCY\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('XbcXYBCY\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
it "replaces \\0 with the entire match", ->
|
it "replaces \\0 with the entire match", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':substitute/ab(ca)AB/X\\0X')
|
submitNormalModeInputText(':substitute/ab(ca)AB/X\\0X')
|
||||||
expect(editor.getText()).toEqual('XabcaABXC\ndefdDEF\nabcaABC')
|
expect(editor.getText()).toEqual('XabcaABXC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
describe ":set", ->
|
describe ":set", ->
|
||||||
it "throws an error without a specified option", ->
|
it "throws an error without a specified option", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':set')
|
submitNormalModeInputText(':set')
|
||||||
expect(atom.notifications.notifications[0].message).toEqual(
|
expect(atom.notifications.notifications[0].message).toEqual(
|
||||||
'Command error: No option specified')
|
'Command error: No option specified')
|
||||||
|
|
@ -771,7 +775,7 @@ describe "the commands", ->
|
||||||
it "sets multiple options at once", ->
|
it "sets multiple options at once", ->
|
||||||
atom.config.set('editor.showInvisibles', false)
|
atom.config.set('editor.showInvisibles', false)
|
||||||
atom.config.set('editor.showLineNumbers', false)
|
atom.config.set('editor.showLineNumbers', false)
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':set list number')
|
submitNormalModeInputText(':set list number')
|
||||||
expect(atom.config.get('editor.showInvisibles')).toBe(true)
|
expect(atom.config.get('editor.showInvisibles')).toBe(true)
|
||||||
expect(atom.config.get('editor.showLineNumbers')).toBe(true)
|
expect(atom.config.get('editor.showLineNumbers')).toBe(true)
|
||||||
|
|
@ -782,7 +786,7 @@ describe "the commands", ->
|
||||||
atom.config.set('editor.showLineNumbers', false)
|
atom.config.set('editor.showLineNumbers', false)
|
||||||
|
|
||||||
it "sets (no)list", ->
|
it "sets (no)list", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':set list')
|
submitNormalModeInputText(':set list')
|
||||||
expect(atom.config.get('editor.showInvisibles')).toBe(true)
|
expect(atom.config.get('editor.showInvisibles')).toBe(true)
|
||||||
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
||||||
|
|
@ -790,7 +794,7 @@ describe "the commands", ->
|
||||||
expect(atom.config.get('editor.showInvisibles')).toBe(false)
|
expect(atom.config.get('editor.showInvisibles')).toBe(false)
|
||||||
|
|
||||||
it "sets (no)nu(mber)", ->
|
it "sets (no)nu(mber)", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':set nu')
|
submitNormalModeInputText(':set nu')
|
||||||
expect(atom.config.get('editor.showLineNumbers')).toBe(true)
|
expect(atom.config.get('editor.showLineNumbers')).toBe(true)
|
||||||
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
||||||
|
|
@ -804,7 +808,7 @@ describe "the commands", ->
|
||||||
expect(atom.config.get('editor.showLineNumbers')).toBe(false)
|
expect(atom.config.get('editor.showLineNumbers')).toBe(false)
|
||||||
|
|
||||||
it "sets (no)sp(lit)r(ight)", ->
|
it "sets (no)sp(lit)r(ight)", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':set spr')
|
submitNormalModeInputText(':set spr')
|
||||||
expect(atom.config.get('ex-mode.splitright')).toBe(true)
|
expect(atom.config.get('ex-mode.splitright')).toBe(true)
|
||||||
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
||||||
|
|
@ -818,7 +822,7 @@ describe "the commands", ->
|
||||||
expect(atom.config.get('ex-mode.splitright')).toBe(false)
|
expect(atom.config.get('ex-mode.splitright')).toBe(false)
|
||||||
|
|
||||||
it "sets (no)s(plit)b(elow)", ->
|
it "sets (no)s(plit)b(elow)", ->
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText(':set sb')
|
submitNormalModeInputText(':set sb')
|
||||||
expect(atom.config.get('ex-mode.splitbelow')).toBe(true)
|
expect(atom.config.get('ex-mode.splitbelow')).toBe(true)
|
||||||
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
||||||
|
|
@ -835,7 +839,7 @@ describe "the commands", ->
|
||||||
it "calls the aliased function without arguments", ->
|
it "calls the aliased function without arguments", ->
|
||||||
ExClass.registerAlias('W', 'w')
|
ExClass.registerAlias('W', 'w')
|
||||||
spyOn(Ex, 'write')
|
spyOn(Ex, 'write')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('W')
|
submitNormalModeInputText('W')
|
||||||
expect(Ex.write).toHaveBeenCalled()
|
expect(Ex.write).toHaveBeenCalled()
|
||||||
|
|
||||||
|
|
@ -843,8 +847,30 @@ describe "the commands", ->
|
||||||
ExClass.registerAlias('W', 'write')
|
ExClass.registerAlias('W', 'write')
|
||||||
spyOn(Ex, 'W').andCallThrough()
|
spyOn(Ex, 'W').andCallThrough()
|
||||||
spyOn(Ex, 'write')
|
spyOn(Ex, 'write')
|
||||||
keydown(':')
|
openEx()
|
||||||
submitNormalModeInputText('W')
|
submitNormalModeInputText('W')
|
||||||
WArgs = Ex.W.calls[0].args[0]
|
WArgs = Ex.W.calls[0].args[0]
|
||||||
writeArgs = Ex.write.calls[0].args[0]
|
writeArgs = Ex.write.calls[0].args[0]
|
||||||
expect(WArgs).toBe writeArgs
|
expect(WArgs).toBe writeArgs
|
||||||
|
|
||||||
|
describe "with selections", ->
|
||||||
|
it "executes on the selected range", ->
|
||||||
|
spyOn(Ex, 's')
|
||||||
|
editor.setCursorBufferPosition([0, 0])
|
||||||
|
editor.selectToBufferPosition([2, 1])
|
||||||
|
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
||||||
|
submitNormalModeInputText("'<,'>s/abc/def")
|
||||||
|
expect(Ex.s.calls[0].args[0].range).toEqual [0, 2]
|
||||||
|
|
||||||
|
it "calls the functions multiple times if there are multiple selections", ->
|
||||||
|
spyOn(Ex, 's')
|
||||||
|
editor.setCursorBufferPosition([0, 0])
|
||||||
|
editor.selectToBufferPosition([2, 1])
|
||||||
|
editor.addCursorAtBufferPosition([3, 0])
|
||||||
|
editor.selectToBufferPosition([3, 2])
|
||||||
|
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
||||||
|
submitNormalModeInputText("'<,'>s/abc/def")
|
||||||
|
calls = Ex.s.calls
|
||||||
|
expect(calls.length).toEqual 2
|
||||||
|
expect(calls[0].args[0].range).toEqual [0, 2]
|
||||||
|
expect(calls[1].args[0].range).toEqual [3, 3]
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ describe "the input element", ->
|
||||||
expect(getVisibility()).toBe true
|
expect(getVisibility()).toBe true
|
||||||
commandEditor = getCommandEditor()
|
commandEditor = getCommandEditor()
|
||||||
model = commandEditor.getModel()
|
model = commandEditor.getModel()
|
||||||
|
expect(model.getText()).toBe ''
|
||||||
model.setText('abc')
|
model.setText('abc')
|
||||||
atom.commands.dispatch(commandEditor, "core:backspace")
|
atom.commands.dispatch(commandEditor, "core:backspace")
|
||||||
expect(getVisibility()).toBe true
|
expect(getVisibility()).toBe true
|
||||||
|
|
@ -82,3 +83,11 @@ describe "the input element", ->
|
||||||
expect(model.getText()).toBe ''
|
expect(model.getText()).toBe ''
|
||||||
atom.commands.dispatch(commandEditor, "core:backspace")
|
atom.commands.dispatch(commandEditor, "core:backspace")
|
||||||
expect(getVisibility()).toBe false
|
expect(getVisibility()).toBe false
|
||||||
|
|
||||||
|
it "contains '<,'> when opened while there are selections", ->
|
||||||
|
editor.setCursorBufferPosition([0, 0])
|
||||||
|
editor.selectToBufferPosition([0, 1])
|
||||||
|
editor.addCursorAtBufferPosition([2, 0])
|
||||||
|
editor.selectToBufferPosition([2, 1])
|
||||||
|
atom.commands.dispatch(editorElement, "ex-mode:open")
|
||||||
|
expect(getCommandEditor().getModel().getText()).toBe "'<,'>"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue