<Plug>(EasyAlign) / <Plug>(LiveEasyAlign) for vim-repeat integration

This commit is contained in:
Junegunn Choi
2013-12-01 22:53:39 +09:00
parent 8d4d5b7941
commit da284f908e
5 changed files with 169 additions and 64 deletions

View File

@@ -49,11 +49,27 @@ and extract in ~/.vim or
1. Add `Plug 'junegunn/vim-easy-align'` to .vimrc 1. Add `Plug 'junegunn/vim-easy-align'` to .vimrc
2. Run `:PlugInstall` 2. Run `:PlugInstall`
TL;DR
-----
Define the following mappings in your .vimrc.
(Of course, you are free to change the mapping keys)
```vim
" Interactive mode
vmap <Enter> <Plug>(EasyAlign)
nmap <leader>a <Plug>(EasyAlign)
" Live interactive mode (optional)
vmap <leader><Enter> <Plug>(LiveEasyAlign)
nmap <leader>A <Plug>(LiveEasyAlign)
```
Usage Usage
----- -----
_vim-easy-align_ defines `:EasyAlign` command (and the right-align _vim-easy-align_ defines `:EasyAlign` command (and the right-align
variant `:EasyAlign!`) for visual mode. variant `:EasyAlign!`).
| Mode | Command | | Mode | Command |
| ------------------------- | ------------------------------------------------ | | ------------------------- | ------------------------------------------------ |
@@ -74,18 +90,23 @@ several options, you can just type in a single character.
### Interactive mode ### Interactive mode
The command will go into the interactive mode when no argument is given. The command will go into the interactive mode when no argument is given.
For convenience, it is advised that you define a mapping for triggering it in For convenience, it is advised that you define mappings for triggering it in
your `.vimrc`. your `.vimrc`.
```vim ```vim
vnoremap <silent> <Enter> :EasyAlign<Enter> " For visual mode (e.g. vip<Enter>)
vmap <Enter> <Plug>(EasyAlign)
" For normal mode, with Vim movement (e.g. <Leader>aip)
nmap <Leader>a <Plug>(EasyAlign)
``` ```
(Of course you can use any key combination as the trigger. e.g. `<Leader>a`) (Of course you can use any key combination as the trigger.)
With the mapping, you can align selected lines of text with only a few keystrokes. With the mapping, you can align selected lines of text with only a few keystrokes.
1. `<Enter>` key to start interactive EasyAlign command 1. `<Enter>` key (or `<Leader>a` followed by a Vim movement) to start
interactive EasyAlign command
1. Optional: Enter keys to select alignment mode (left, right, or center) 1. Optional: Enter keys to select alignment mode (left, right, or center)
1. Optional: N-th delimiter (default: 1) 1. Optional: N-th delimiter (default: 1)
- `1` Around the 1st occurrences of delimiters - `1` Around the 1st occurrences of delimiters
@@ -170,6 +191,20 @@ repeatable, non-interactive command recorded in `g:easy_align_last_command`.
:<C-R>=g:easy_align_last_command<Enter><Enter> :<C-R>=g:easy_align_last_command<Enter><Enter>
``` ```
### EasyAlign as Vim operator
With normal-mode map to `<Plug>(EasyAlign)`, EasyAlign command becomes a Vim
operator that can be used with any Vim movement.
```vim
nmap <leader>a <Plug>(EasyAlign)
```
Now without going into visual mode, you can align the lines in the paragraph
with `<Leader>aip=`, `<Leader>aip*|`, or `<Leader>aip:`. And if you have
installed [vim-repeat](https://github.com/tpope/vim-repeat) by Tim Pope, the
exact alignment can be repeated with `.` key.
### Live interactive mode ### Live interactive mode
If you're performing a complex alignment where multiple options should be If you're performing a complex alignment where multiple options should be
@@ -177,11 +212,12 @@ carefully adjusted, try "live interactive mode" where you can preview the result
of the alignment on-the-fly as you type in. of the alignment on-the-fly as you type in.
Live interactive mode can be started with `:LiveEasyAlign` command which takes Live interactive mode can be started with `:LiveEasyAlign` command which takes
the same parameters as `:EasyAlign`. I suggest you define a mapping such as the same parameters as `:EasyAlign`. I suggest you define mappings such as
follows in addition to the one for `:EasyAlign` command. follows in addition to the ones for `:EasyAlign` command.
```vim ```vim
vnoremap <silent> <Leader><Enter> :LiveEasyAlign<Enter> vmap <leader><Enter> <Plug>(LiveEasyAlign)
nmap <leader>A <Plug>(LiveEasyAlign)
``` ```
In live interactive mode, you have to type in the same delimiter (or `CTRL-X` on In live interactive mode, you have to type in the same delimiter (or `CTRL-X` on
@@ -289,32 +325,6 @@ my_hash = { :a => 1,
However, in this case, we don't really need blockwise visual mode However, in this case, we don't really need blockwise visual mode
since the same can be easily done using the negative N-th parameter: `<Enter>-=` since the same can be easily done using the negative N-th parameter: `<Enter>-=`
### EasyAlign as Vim operator
With `<Plug>(EasyAlignOperator)` map, EasyAlign command becomes a Vim operator
that can be used with any Vim movement.
```vim
nmap <leader>a <Plug>(EasyAlignOperator)
```
Now without going into visual mode, you can align the lines in the paragraph
with `<Leader>aip=`, `<Leader>aip*|`, or `<Leader>aip:`.
Or you can be more specific by defining custom operator functions as follows, so
you can do `<Leader>=ip` or `<Leader>:ip`.
```vim
function! s:easy_align_1st_eq(type, ...)
'[,']EasyAlign=
endfunction
nnoremap <Leader>= :set opfunc=<SID>easy_align_1st_eq<Enter>g@
function! s:easy_align_1st_colon(type, ...)
'[,']EasyAlign:
endfunction
nnoremap <Leader>: :set opfunc=<SID>easy_align_1st_colon<Enter>g@
```
Alignment options Alignment options
----------------- -----------------

View File

@@ -1041,10 +1041,16 @@ function s:summarize(opts, recur, mode_sequence)
return copts return copts
endfunction endfunction
function! s:align(bang, live, first_line, last_line, expr) function! s:align(bang, live, visualmode, first_line, last_line, expr)
" Heuristically determine if the user was in visual mode " Heuristically determine if the user was in visual mode
let vis = a:first_line == line("'<") && a:last_line == line("'>") if empty(a:visualmode)
let bvis = vis && char2nr(visualmode()) == 22 " ^V let vis = a:first_line == line("'<") && a:last_line == line("'>")
let bvis = vis && char2nr(visualmode()) == 22 " ^V
" Visual-mode explicitly given
else
let vis = 1
let bvis = a:visualmode == "\<C-V>"
end
let range = [a:first_line, a:last_line] let range = [a:first_line, a:last_line]
let modes = s:interactive_modes(a:bang) let modes = s:interactive_modes(a:bang)
let mode = modes[0] let mode = modes[0]
@@ -1080,9 +1086,9 @@ function! s:align(bang, live, first_line, last_line, expr)
endtry endtry
endfunction endfunction
function! easy_align#align(bang, live, expr) range function! easy_align#align(bang, live, visualmode, expr) range
try try
call s:align(a:bang, a:live, a:firstline, a:lastline, a:expr) call s:align(a:bang, a:live, a:visualmode, a:firstline, a:lastline, a:expr)
catch 'exit' catch 'exit'
endtry endtry
endfunction endfunction

View File

@@ -27,14 +27,19 @@ Interactive mode
------------------------------------------------------------------------- -------------------------------------------------------------------------
The command will go into the interactive mode when no argument is given. The command will go into the interactive mode when no argument is given.
For convenience, it is advised that you define a mapping for triggering it in For convenience, it is advised that you define mappings for triggering it in
your `.vimrc`. your `.vimrc`.
vnoremap <silent> <Enter> :EasyAlign<Enter> " For visual mode (e.g. vip<Enter>)
vmap <Enter> <Plug>(EasyAlign)
" For normal mode, with Vim movement (e.g. <Leader>aip)
nmap <Leader>a <Plug>(EasyAlign)
With this mapping, you can align selected lines of text with a few keystrokes. With this mapping, you can align selected lines of text with a few keystrokes.
1. <Enter> key to start interactive EasyAlign command 1. <Enter> key (or <Leader>a followed by a Vim movement) to start interactive
EasyAlign command
2. Optional: Enter keys to select alignment mode (left, right, or center) 2. Optional: Enter keys to select alignment mode (left, right, or center)
3. Optional: N-th delimiter (default: 1) 3. Optional: N-th delimiter (default: 1)
1 Around the 1st occurrences of delimiters 1 Around the 1st occurrences of delimiters
@@ -108,6 +113,20 @@ repeatable, non-interactive command recorded in `g:easy_align_last_command`.
:<C-R>=g:easy_align_last_command<Enter><Enter> :<C-R>=g:easy_align_last_command<Enter><Enter>
EasyAlign as Vim operator *<Plug>(EasyAlign)*
-------------------------------------------------------------------------
With normal-mode map to `<Plug>(EasyAlign)`, EasyAlign command becomes
a Vim operator that can be used with any Vim movement.
nmap <leader>a <Plug>(EasyAlign)
Now without going into visual mode, you can align the lines in the
paragraph with "<Leader>aip=", "<Leader>aip*|", or "<Leader>aip:".
And if you have installed vim-repeat by Tim Pope, the exact alignment
can be repeated with "." key.
Live interactive mode *:LiveEasyAlign* *:LiveEasyAlign!* Live interactive mode *:LiveEasyAlign* *:LiveEasyAlign!*
------------------------------------------------------------------------- -------------------------------------------------------------------------
@@ -115,11 +134,12 @@ If you're performing a complex alignment where multiple options should be
carefully adjusted, try "live interactive mode" which aligns the text carefully adjusted, try "live interactive mode" which aligns the text
on-the-fly as you type in. on-the-fly as you type in.
Live interactive mode can be started with `:LiveEasyAlign` command which Live interactive mode can be started with `:LiveEasyAlign` command which takes
takes the same parameters as `:EasyAlign`. I suggest you define the the same parameters as `:EasyAlign`. I suggest you define mappings such as
following mapping in addition to the one for `:EasyAlign` command. follows in addition to the ones for `:EasyAlign` command.
vnoremap <silent> <Leader><Enter> :LiveEasyAlign<Enter> vmap <Leader><Enter> <Plug>(LiveEasyAlign)
nmap <leader>A <Plug>(LiveEasyAlign)
In live interactive mode, you have to type in the same delimiter (or In live interactive mode, you have to type in the same delimiter (or
`CTRL-X` on regular expression) again to finalize the alignment. This `CTRL-X` on regular expression) again to finalize the alignment. This
@@ -228,18 +248,6 @@ In blockwise-visual mode (CTRL-V), EasyAlign command aligns only
the selected text in the block, instead of the whole lines in the range. the selected text in the block, instead of the whole lines in the range.
EasyAlign as Vim operator *<Plug>(EasyAlignOperator)*
-------------------------------------------------------------------------
With `<Plug>(EasyAlignOperator)` map, EasyAlign command becomes a Vim
operator that can be used with any Vim movement.
nmap <leader>a <Plug>(EasyAlignOperator)
Now without going into visual mode, you can align the lines in the
paragraph with "<Leader>aip=", "<Leader>aip*|", or "<Leader>aip:".
Alignment options Alignment options
------------------------------------------------------------------------- -------------------------------------------------------------------------

View File

@@ -26,11 +26,57 @@ if exists("g:loaded_easy_align_plugin")
endif endif
let g:loaded_easy_align_plugin = 1 let g:loaded_easy_align_plugin = 1
command! -nargs=* -range -bang EasyAlign <line1>,<line2>call easy_align#align('<bang>' == '!', 0, <q-args>) command! -nargs=* -range -bang EasyAlign <line1>,<line2>call easy_align#align('<bang>' == '!', 0, '', <q-args>)
command! -nargs=* -range -bang LiveEasyAlign <line1>,<line2>call easy_align#align('<bang>' == '!', 1, <q-args>) command! -nargs=* -range -bang LiveEasyAlign <line1>,<line2>call easy_align#align('<bang>' == '!', 1, '', <q-args>)
function! s:generic_easy_align_op(type, vmode, live)
let sel_save = &selection
let &selection = "inclusive"
if a:vmode
let vmode = a:type
else
let tail = "\<C-c>"
if a:type == 'line'
silent execute "normal! '[V']".tail
elseif a:type == 'block'
silent execute "normal! `[\<C-V>`]".tail
else
silent execute "normal! `[v`]".tail
endif
let vmode = ''
endif
try
if get(g:, 'easy_align_need_repeat', 0)
execute "'<,'>". g:easy_align_last_command
else
'<,'>call easy_align#align('<bang>' == '!', a:live, vmode, '')
end
silent! call repeat#set("\<Plug>(EasyAlignRepeat)")
finally
unlet! g:easy_align_need_repeat
let &selection = sel_save
endtry
endfunction
function! s:easy_align_op(type, ...) function! s:easy_align_op(type, ...)
'[,']EasyAlign call s:generic_easy_align_op(a:type, a:0, 0)
endfunction endfunction
function! s:live_easy_align_op(type, ...)
call s:generic_easy_align_op(a:type, a:0, 1)
endfunction
nnoremap <silent> <Plug>(EasyAlign) :set opfunc=<SID>easy_align_op<Enter>g@
vnoremap <silent> <Plug>(EasyAlign) :<C-U>call <SID>easy_align_op(visualmode(), 1)<Enter>
nnoremap <silent> <Plug>(LiveEasyAlign) :set opfunc=<SID>live_easy_align_op<Enter>g@
vnoremap <silent> <Plug>(LiveEasyAlign) :<C-U>call <SID>live_easy_align_op(visualmode(), 1)<Enter>
" vim-repeat support
nnoremap <silent> <Plug>(EasyAlignRepeat) :let g:easy_align_need_repeat = 1<Enter>.
vnoremap <silent> <Plug>(EasyAlignRepeat) :<C-U>let g:easy_align_need_repeat = 1<Enter>gv.
" Backward-compatibility (deprecated)
nnoremap <silent> <Plug>(EasyAlignOperator) :set opfunc=<SID>easy_align_op<Enter>g@ nnoremap <silent> <Plug>(EasyAlignOperator) :set opfunc=<SID>easy_align_op<Enter>g@

View File

@@ -15,11 +15,17 @@ Execute (Clean up test environment):
let g:easy_align_delimiters = {} let g:easy_align_delimiters = {}
let mapleader = ' ' let mapleader = ' '
vnoremap <silent> <Enter> :EasyAlign<Enter>
vnoremap <silent> r<Enter> :EasyAlign!<Enter> vnoremap <silent> r<Enter> :EasyAlign!<Enter>
vnoremap <silent> <Leader><Enter> :LiveEasyAlign<Enter>
vnoremap <silent> <Leader>r<Enter> :LiveEasyAlign!<Enter> vnoremap <silent> <Leader>r<Enter> :LiveEasyAlign!<Enter>
nmap <leader>A <Plug>(EasyAlignOperator)
" " Legacy
" vnoremap <silent> <Enter> :EasyAlign<Enter>
" vnoremap <silent> <Leader><Enter> :LiveEasyAlign<Enter>
" nmap <leader>A <Plug>(EasyAlignOperator)
vmap <Enter> <Plug>(EasyAlign)
vmap <leader><Enter> <Plug>(LiveEasyAlign)
nmap <leader>A <Plug>(EasyAlign)
########################################################### ###########################################################
@@ -1510,6 +1516,35 @@ Expect:
'type': 'global', 'type': 'global',
'url': 'http://localhost:8090/display/TEST'} 'url': 'http://localhost:8090/display/TEST'}
###########################################################
Given (Two paragraphs (requires vim-repeat)):
a = 1
bb = 2
ccc = 3
dddd = 4
d = 1
cc = 2
bbb = 3
aaaa = 4
Do (Align and repeat):
\<Space>Aip\<Enter>=
6G
.
Expect:
a = 1
bb = 2
ccc = 3
dddd = 4
d = 1
cc = 2
bbb = 3
aaaa = 4
########################################################### ###########################################################
Execute: Execute:
Restore Restore