Compare commits
27 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30ad82671b | ||
|
|
59cafd6b99 | ||
|
|
ef4bb8a6ac | ||
|
|
744ec7351e | ||
|
|
23dde8c7ee | ||
|
|
a887128b9f | ||
|
|
a33959f829 | ||
|
|
b9b3ba3e9f | ||
|
|
15038d7b0c | ||
|
|
2b7e6346a5 | ||
|
|
4f1ebf8a1a | ||
|
|
653d62ec15 | ||
|
|
93d0af041f | ||
|
|
146d832e14 | ||
|
|
14f0c83261 | ||
|
|
c75395174f | ||
|
|
d0059a7bb2 | ||
|
|
1a515fcb05 | ||
|
|
964813a0b0 | ||
|
|
2fa4584eb4 | ||
|
|
23be6cc862 | ||
|
|
195396b47e | ||
|
|
791c62a3ba | ||
|
|
d76940dabc | ||
|
|
4312777508 | ||
|
|
15296ff369 | ||
|
|
117d7439ad |
8 changed files with 141 additions and 27 deletions
|
|
@ -1,3 +1,12 @@
|
||||||
|
## (unpublished)
|
||||||
|
|
||||||
|
* Fix `:enew` not working ([#215](https://github.com/lloeki/ex-mode/pull/215))
|
||||||
|
|
||||||
|
## 0.18.0
|
||||||
|
|
||||||
|
* Add Gdefault support ([#191](https://github.com/lloeki/ex-mode/pull/191))
|
||||||
|
* Add :sort command ([#190](https://github.com/lloeki/ex-mode/pull/190))
|
||||||
|
|
||||||
## 0.17.0
|
## 0.17.0
|
||||||
|
|
||||||
* Add support for Atom 1.19 ([#185](https://github.com/lloeki/ex-mode/pull/185))
|
* Add support for Atom 1.19 ([#185](https://github.com/lloeki/ex-mode/pull/185))
|
||||||
|
|
|
||||||
29
README.md
Normal file → Executable file
29
README.md
Normal file → Executable file
|
|
@ -30,7 +30,34 @@ atom.packages.onDidActivatePackage (pack) ->
|
||||||
Ex.registerAlias 'Wq', 'wq'
|
Ex.registerAlias 'Wq', 'wq'
|
||||||
```
|
```
|
||||||
|
|
||||||
See `lib/ex.coffee` for some examples commands. Contributions are very welcome!
|
## Existing commands
|
||||||
|
|
||||||
|
This is the baseline list of commands supported in `ex-mode`.
|
||||||
|
|
||||||
|
| Command | Operation |
|
||||||
|
| --------------------------------------- | ---------------------------------- |
|
||||||
|
| `q/quit/tabc/tabclose` | Close active tab |
|
||||||
|
| `qall/quitall` | Close all tabs |
|
||||||
|
| `tabe/tabedit/tabnew` | Open new tab |
|
||||||
|
| `e/edit/tabe/tabedit/tabnew <file>` | Edit given file |
|
||||||
|
| `tabn/tabnext` | Go to next tab |
|
||||||
|
| `tabp/tabprevious` | Go to previous tab |
|
||||||
|
| `tabo/tabonly` | Close other tabs |
|
||||||
|
| `w/write` | Save active tab |
|
||||||
|
| `w/write/saveas <file>` | Save as |
|
||||||
|
| `wall/wa` | Save all tabs |
|
||||||
|
| `sp/split` | Split window |
|
||||||
|
| `sp/split <file>` | Open file in split window |
|
||||||
|
| `s/substitute` | Substitute regular expression in active line |
|
||||||
|
| `vsp/vsplit` | Vertical split window |
|
||||||
|
| `vsp/vsplit <file>` | Open file in vertical split window |
|
||||||
|
| `delete` | Cut active line |
|
||||||
|
| `yank` | Copy active line |
|
||||||
|
| `set <options>` | Set options |
|
||||||
|
| `sort` | Sort all lines in file |
|
||||||
|
| `sort <line range>` | Sort lines in line range |
|
||||||
|
|
||||||
|
See `lib/ex.coffee` for the implementations of these commands. Contributions are very welcome!
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,6 @@
|
||||||
':': 'ex-mode:open'
|
':': 'ex-mode:open'
|
||||||
'atom-text-editor.ex-mode-editor':
|
'atom-text-editor.ex-mode-editor':
|
||||||
'ctrl-c': 'ex-mode:close'
|
'ctrl-c': 'ex-mode:close'
|
||||||
|
'ctrl-[': 'ex-mode:close'
|
||||||
'atom-text-editor.vim-mode:not(.insert-mode)':
|
'atom-text-editor.vim-mode:not(.insert-mode)':
|
||||||
':': 'ex-mode:open'
|
':': 'ex-mode:open'
|
||||||
|
|
|
||||||
|
|
@ -50,3 +50,13 @@ module.exports = ExMode =
|
||||||
description: 'when splitting, split from right'
|
description: 'when splitting, split from right'
|
||||||
type: 'boolean'
|
type: 'boolean'
|
||||||
default: 'false'
|
default: 'false'
|
||||||
|
gdefault:
|
||||||
|
title: 'Gdefault'
|
||||||
|
description: 'When on, the ":substitute" flag \'g\' is default on'
|
||||||
|
type: 'boolean'
|
||||||
|
default: 'false'
|
||||||
|
onlyCloseBuffers:
|
||||||
|
title: 'Only close buffers'
|
||||||
|
description: 'When on, quitall only closes all buffers, not entire Atom instance'
|
||||||
|
type: 'boolean'
|
||||||
|
default: 'false'
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ CommandError = require './command-error'
|
||||||
fs = require 'fs-plus'
|
fs = require 'fs-plus'
|
||||||
VimOption = require './vim-option'
|
VimOption = require './vim-option'
|
||||||
_ = require 'underscore-plus'
|
_ = require 'underscore-plus'
|
||||||
|
atom
|
||||||
|
|
||||||
defer = () ->
|
defer = () ->
|
||||||
deferred = {}
|
deferred = {}
|
||||||
|
|
@ -132,7 +133,11 @@ class Ex
|
||||||
atom.workspace.getActivePane().destroyActiveItem()
|
atom.workspace.getActivePane().destroyActiveItem()
|
||||||
|
|
||||||
quitall: ->
|
quitall: ->
|
||||||
atom.close()
|
if !atom.config.get('ex-mode.onlyCloseBuffers')
|
||||||
|
atom.close()
|
||||||
|
else
|
||||||
|
atom.workspace.getTextEditors().forEach (editor) ->
|
||||||
|
editor.destroy()
|
||||||
|
|
||||||
q: => @quit()
|
q: => @quit()
|
||||||
|
|
||||||
|
|
@ -206,9 +211,7 @@ class Ex
|
||||||
e: (args) => @edit(args)
|
e: (args) => @edit(args)
|
||||||
|
|
||||||
enew: ->
|
enew: ->
|
||||||
buffer = atom.workspace.getActiveTextEditor().buffer
|
atom.workspace.open()
|
||||||
buffer.setPath(undefined)
|
|
||||||
buffer.load()
|
|
||||||
|
|
||||||
write: ({ range, args, editor, saveas }) ->
|
write: ({ range, args, editor, saveas }) ->
|
||||||
saveas ?= false
|
saveas ?= false
|
||||||
|
|
@ -226,29 +229,30 @@ class Ex
|
||||||
deferred = defer()
|
deferred = defer()
|
||||||
|
|
||||||
editor = atom.workspace.getActiveTextEditor()
|
editor = atom.workspace.getActiveTextEditor()
|
||||||
saved = false
|
|
||||||
|
# Case 1; path is provided
|
||||||
if filePath.length isnt 0
|
if filePath.length isnt 0
|
||||||
fullPath = getFullPath(filePath)
|
fullPath = getFullPath filePath
|
||||||
if editor.getPath()? and (not fullPath? or editor.getPath() == fullPath)
|
|
||||||
if saveas
|
|
||||||
throw new CommandError("Argument required")
|
|
||||||
else
|
|
||||||
# Use editor.save when no path is given or the path to the file is given
|
|
||||||
trySave(-> editor.save()).then(deferred.resolve)
|
|
||||||
saved = true
|
|
||||||
else if not fullPath?
|
|
||||||
fullPath = atom.showSaveDialogSync()
|
|
||||||
|
|
||||||
if not saved and fullPath?
|
# Only write when it does not exist or we have a force flag set.
|
||||||
if not force and fs.existsSync(fullPath)
|
if force or not fs.existsSync(fullPath)
|
||||||
throw new CommandError("File exists (add ! to override)")
|
editor.saveAs(fullPath)
|
||||||
if saveas or editor.getFileName() == null
|
return deferred.promise
|
||||||
editor = atom.workspace.getActiveTextEditor()
|
|
||||||
trySave(-> editor.saveAs(fullPath, editor)).then(deferred.resolve)
|
|
||||||
else
|
|
||||||
trySave(-> saveAs(fullPath, editor)).then(deferred.resolve)
|
|
||||||
|
|
||||||
deferred.promise
|
throw new CommandError("File exists (add ! to override)")
|
||||||
|
|
||||||
|
# Case 2; no path provided, call editor save.
|
||||||
|
editor = atom.workspace.getActiveTextEditor()
|
||||||
|
|
||||||
|
# Does the current buffer exist?
|
||||||
|
if editor.getPath()? and fs.existsSync(editor.getPath())
|
||||||
|
trySave(-> editor.save()).then(deferred.promise)
|
||||||
|
else
|
||||||
|
# Cant see what the better API is but Pane.saveActiveItemAs() is the only call
|
||||||
|
# I could find that states it will ask the user.
|
||||||
|
trySave(-> atom.workspace.getActivePane().saveActiveItemAs()).then(deferred.promise)
|
||||||
|
|
||||||
|
return deferred.promise
|
||||||
|
|
||||||
wall: ->
|
wall: ->
|
||||||
atom.workspace.saveAll()
|
atom.workspace.saveAll()
|
||||||
|
|
@ -361,6 +365,9 @@ class Ex
|
||||||
try
|
try
|
||||||
flagsObj = {}
|
flagsObj = {}
|
||||||
flags.split('').forEach((flag) -> flagsObj[flag] = true)
|
flags.split('').forEach((flag) -> flagsObj[flag] = true)
|
||||||
|
# gdefault option
|
||||||
|
if atom.config.get('ex-mode.gdefault')
|
||||||
|
flagsObj.g = !flagsObj.g
|
||||||
patternRE = getSearchTerm(pattern, flagsObj)
|
patternRE = getSearchTerm(pattern, flagsObj)
|
||||||
catch e
|
catch e
|
||||||
if e.message.indexOf('Invalid flags supplied to RegExp constructor') is 0
|
if e.message.indexOf('Invalid flags supplied to RegExp constructor') is 0
|
||||||
|
|
@ -442,4 +449,24 @@ class Ex
|
||||||
throw new CommandError("No such option: #{option}")
|
throw new CommandError("No such option: #{option}")
|
||||||
optionProcessor()
|
optionProcessor()
|
||||||
|
|
||||||
|
sort: ({ range }) =>
|
||||||
|
editor = atom.workspace.getActiveTextEditor()
|
||||||
|
sortingRange = [[]]
|
||||||
|
|
||||||
|
# If no range is provided, the entire file should be sorted.
|
||||||
|
isMultiLine = range[1] - range[0] > 1
|
||||||
|
if isMultiLine
|
||||||
|
sortingRange = [[range[0], 0], [range[1] + 1, 0]]
|
||||||
|
else
|
||||||
|
sortingRange = [[0, 0], [editor.getLastBufferRow(), 0]]
|
||||||
|
|
||||||
|
# Store every bufferedRow string in an array.
|
||||||
|
textLines = []
|
||||||
|
for lineIndex in [sortingRange[0][0]..sortingRange[1][0] - 1]
|
||||||
|
textLines.push(editor.lineTextForBufferRow(lineIndex))
|
||||||
|
|
||||||
|
# Sort the array and join them together with newlines for writing back to the file.
|
||||||
|
sortedText = _.sortBy(textLines).join('\n') + '\n'
|
||||||
|
editor.buffer.setTextInRange(sortingRange, sortedText)
|
||||||
|
|
||||||
module.exports = Ex
|
module.exports = Ex
|
||||||
|
|
|
||||||
|
|
@ -56,4 +56,10 @@ class VimOption
|
||||||
noscs: =>
|
noscs: =>
|
||||||
@nosmartcase()
|
@nosmartcase()
|
||||||
|
|
||||||
|
gdefault: =>
|
||||||
|
atom.config.set("ex-mode.gdefault", true)
|
||||||
|
|
||||||
|
nogdefault: =>
|
||||||
|
atom.config.set("ex-mode.gdefault", false)
|
||||||
|
|
||||||
module.exports = VimOption
|
module.exports = VimOption
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "ex-mode",
|
"name": "ex-mode",
|
||||||
"main": "./lib/ex-mode",
|
"main": "./lib/ex-mode",
|
||||||
"version": "0.17.0",
|
"version": "0.18.0",
|
||||||
"description": "Ex for Atom's vim-mode",
|
"description": "Ex for Atom's vim-mode",
|
||||||
"activationCommands": {
|
"activationCommands": {
|
||||||
"atom-workspace": "ex-mode:open"
|
"atom-workspace": "ex-mode:open"
|
||||||
|
|
|
||||||
|
|
@ -715,6 +715,17 @@ describe "the commands", ->
|
||||||
submitNormalModeInputText(':%substitute/abc/ghi/ig')
|
submitNormalModeInputText(':%substitute/abc/ghi/ig')
|
||||||
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nghiaghi')
|
expect(editor.getText()).toEqual('ghiaghi\ndefdDEF\nghiaghi')
|
||||||
|
|
||||||
|
it "set gdefault option", ->
|
||||||
|
openEx()
|
||||||
|
atom.config.set('ex-mode.gdefault', true)
|
||||||
|
submitNormalModeInputText(':substitute/a/x')
|
||||||
|
expect(editor.getText()).toEqual('xbcxABC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
|
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
||||||
|
atom.config.set('ex-mode.gdefault', true)
|
||||||
|
submitNormalModeInputText(':substitute/a/x/g')
|
||||||
|
expect(editor.getText()).toEqual('xbcaABC\ndefdDEF\nabcaABC')
|
||||||
|
|
||||||
describe ":yank", ->
|
describe ":yank", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
editor.setText('abc\ndef\nghi\njkl')
|
editor.setText('abc\ndef\nghi\njkl')
|
||||||
|
|
@ -944,6 +955,14 @@ describe "the commands", ->
|
||||||
submitNormalModeInputText(':set nosmartcase')
|
submitNormalModeInputText(':set nosmartcase')
|
||||||
expect(atom.config.get('vim-mode.useSmartcaseForSearch')).toBe(false)
|
expect(atom.config.get('vim-mode.useSmartcaseForSearch')).toBe(false)
|
||||||
|
|
||||||
|
it "sets (no)gdefault", ->
|
||||||
|
openEx()
|
||||||
|
submitNormalModeInputText(':set gdefault')
|
||||||
|
expect(atom.config.get('ex-mode.gdefault')).toBe(true)
|
||||||
|
atom.commands.dispatch(editorElement, 'ex-mode:open')
|
||||||
|
submitNormalModeInputText(':set nogdefault')
|
||||||
|
expect(atom.config.get('ex-mode.gdefault')).toBe(false)
|
||||||
|
|
||||||
describe "aliases", ->
|
describe "aliases", ->
|
||||||
it "calls the aliased function without arguments", ->
|
it "calls the aliased function without arguments", ->
|
||||||
ExClass.registerAlias('W', 'w')
|
ExClass.registerAlias('W', 'w')
|
||||||
|
|
@ -983,3 +1002,18 @@ describe "the commands", ->
|
||||||
expect(calls.length).toEqual 2
|
expect(calls.length).toEqual 2
|
||||||
expect(calls[0].args[0].range).toEqual [0, 2]
|
expect(calls[0].args[0].range).toEqual [0, 2]
|
||||||
expect(calls[1].args[0].range).toEqual [3, 3]
|
expect(calls[1].args[0].range).toEqual [3, 3]
|
||||||
|
|
||||||
|
describe ':sort', ->
|
||||||
|
beforeEach ->
|
||||||
|
editor.setText('ghi\nabc\njkl\ndef\n142\nzzz\n91xfds9\n')
|
||||||
|
editor.setCursorBufferPosition([0, 0])
|
||||||
|
|
||||||
|
it "sorts entire file if range is not multi-line", ->
|
||||||
|
openEx()
|
||||||
|
submitNormalModeInputText('sort')
|
||||||
|
expect(editor.getText()).toEqual('142\n91xfds9\nabc\ndef\nghi\njkl\nzzz\n')
|
||||||
|
|
||||||
|
it "sorts specific range if range is multi-line", ->
|
||||||
|
openEx()
|
||||||
|
submitNormalModeInputText('2,4sort')
|
||||||
|
expect(editor.getText()).toEqual('ghi\nabc\ndef\njkl\n142\nzzz\n91xfds9\n')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue