diff --git a/README.md b/README.md index d4d8e33..0be804a 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,27 @@ and extract in ~/.vim or 1. Add `Plug 'junegunn/vim-easy-align'` to .vimrc 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 (EasyAlign) +nmap a (EasyAlign) + +" Live interactive mode (optional) +vmap (LiveEasyAlign) +nmap A (LiveEasyAlign) +``` + Usage ----- _vim-easy-align_ defines `:EasyAlign` command (and the right-align -variant `:EasyAlign!`) for visual mode. +variant `:EasyAlign!`). | Mode | Command | | ------------------------- | ------------------------------------------------ | @@ -74,18 +90,23 @@ several options, you can just type in a single character. ### Interactive mode 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`. ```vim -vnoremap :EasyAlign +" For visual mode (e.g. vip) +vmap (EasyAlign) + +" For normal mode, with Vim movement (e.g. aip) +nmap a (EasyAlign) ``` -(Of course you can use any key combination as the trigger. e.g. `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. -1. `` key to start interactive EasyAlign command +1. `` key (or `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: N-th delimiter (default: 1) - `1` Around the 1st occurrences of delimiters @@ -170,6 +191,20 @@ repeatable, non-interactive command recorded in `g:easy_align_last_command`. :=g:easy_align_last_command ``` +### EasyAlign as Vim operator + +With normal-mode map to `(EasyAlign)`, EasyAlign command becomes a Vim +operator that can be used with any Vim movement. + +```vim +nmap a (EasyAlign) +``` + +Now without going into visual mode, you can align the lines in the paragraph +with `aip=`, `aip*|`, or `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 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. Live interactive mode can be started with `:LiveEasyAlign` command which takes -the same parameters as `:EasyAlign`. I suggest you define a mapping such as -follows in addition to the one for `:EasyAlign` command. +the same parameters as `:EasyAlign`. I suggest you define mappings such as +follows in addition to the ones for `:EasyAlign` command. ```vim -vnoremap :LiveEasyAlign +vmap (LiveEasyAlign) +nmap A (LiveEasyAlign) ``` 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 since the same can be easily done using the negative N-th parameter: `-=` -### EasyAlign as Vim operator - -With `(EasyAlignOperator)` map, EasyAlign command becomes a Vim operator -that can be used with any Vim movement. - -```vim -nmap a (EasyAlignOperator) -``` - -Now without going into visual mode, you can align the lines in the paragraph -with `aip=`, `aip*|`, or `aip:`. - -Or you can be more specific by defining custom operator functions as follows, so -you can do `=ip` or `:ip`. - -```vim -function! s:easy_align_1st_eq(type, ...) - '[,']EasyAlign= -endfunction -nnoremap = :set opfunc=easy_align_1st_eqg@ - -function! s:easy_align_1st_colon(type, ...) - '[,']EasyAlign: -endfunction -nnoremap : :set opfunc=easy_align_1st_colong@ -``` Alignment options ----------------- diff --git a/autoload/easy_align.vim b/autoload/easy_align.vim index afd3a9f..2028ffb 100644 --- a/autoload/easy_align.vim +++ b/autoload/easy_align.vim @@ -1041,10 +1041,16 @@ function s:summarize(opts, recur, mode_sequence) return copts 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 - let vis = a:first_line == line("'<") && a:last_line == line("'>") - let bvis = vis && char2nr(visualmode()) == 22 " ^V + if empty(a:visualmode) + 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 == "\" + end let range = [a:first_line, a:last_line] let modes = s:interactive_modes(a:bang) let mode = modes[0] @@ -1080,9 +1086,9 @@ function! s:align(bang, live, first_line, last_line, expr) endtry endfunction -function! easy_align#align(bang, live, expr) range +function! easy_align#align(bang, live, visualmode, expr) range 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' endtry endfunction diff --git a/doc/easy_align.txt b/doc/easy_align.txt index b05d503..b89a1dc 100644 --- a/doc/easy_align.txt +++ b/doc/easy_align.txt @@ -27,14 +27,19 @@ Interactive mode ------------------------------------------------------------------------- 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`. - vnoremap :EasyAlign + " For visual mode (e.g. vip) + vmap (EasyAlign) + + " For normal mode, with Vim movement (e.g. aip) + nmap a (EasyAlign) With this mapping, you can align selected lines of text with a few keystrokes. -1. key to start interactive EasyAlign command +1. key (or a followed by a Vim movement) to start interactive + EasyAlign command 2. Optional: Enter keys to select alignment mode (left, right, or center) 3. Optional: N-th delimiter (default: 1) 1 Around the 1st occurrences of delimiters @@ -108,6 +113,20 @@ repeatable, non-interactive command recorded in `g:easy_align_last_command`. :=g:easy_align_last_command +EasyAlign as Vim operator *(EasyAlign)* +------------------------------------------------------------------------- + +With normal-mode map to `(EasyAlign)`, EasyAlign command becomes +a Vim operator that can be used with any Vim movement. + + nmap a (EasyAlign) + +Now without going into visual mode, you can align the lines in the +paragraph with "aip=", "aip*|", or "aip:". +And if you have installed vim-repeat by Tim Pope, the exact alignment +can be repeated with "." key. + + 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 on-the-fly as you type in. -Live interactive mode can be started with `:LiveEasyAlign` command which -takes the same parameters as `:EasyAlign`. I suggest you define the -following mapping in addition to the one for `:EasyAlign` command. +Live interactive mode can be started with `:LiveEasyAlign` command which takes +the same parameters as `:EasyAlign`. I suggest you define mappings such as +follows in addition to the ones for `:EasyAlign` command. - vnoremap :LiveEasyAlign + vmap (LiveEasyAlign) + nmap A (LiveEasyAlign) In live interactive mode, you have to type in the same delimiter (or `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. -EasyAlign as Vim operator *(EasyAlignOperator)* -------------------------------------------------------------------------- - -With `(EasyAlignOperator)` map, EasyAlign command becomes a Vim -operator that can be used with any Vim movement. - - nmap a (EasyAlignOperator) - -Now without going into visual mode, you can align the lines in the -paragraph with "aip=", "aip*|", or "aip:". - - Alignment options ------------------------------------------------------------------------- diff --git a/plugin/easy_align.vim b/plugin/easy_align.vim index 66156d3..a25dd21 100644 --- a/plugin/easy_align.vim +++ b/plugin/easy_align.vim @@ -26,11 +26,57 @@ if exists("g:loaded_easy_align_plugin") endif let g:loaded_easy_align_plugin = 1 -command! -nargs=* -range -bang EasyAlign ,call easy_align#align('' == '!', 0, ) -command! -nargs=* -range -bang LiveEasyAlign ,call easy_align#align('' == '!', 1, ) +command! -nargs=* -range -bang EasyAlign ,call easy_align#align('' == '!', 0, '', ) +command! -nargs=* -range -bang LiveEasyAlign ,call easy_align#align('' == '!', 1, '', ) + +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 = "\" + if a:type == 'line' + silent execute "normal! '[V']".tail + elseif a:type == 'block' + silent execute "normal! `[\`]".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('' == '!', a:live, vmode, '') + end + silent! call repeat#set("\(EasyAlignRepeat)") + finally + unlet! g:easy_align_need_repeat + let &selection = sel_save + endtry +endfunction function! s:easy_align_op(type, ...) - '[,']EasyAlign + call s:generic_easy_align_op(a:type, a:0, 0) endfunction + +function! s:live_easy_align_op(type, ...) + call s:generic_easy_align_op(a:type, a:0, 1) +endfunction + +nnoremap (EasyAlign) :set opfunc=easy_align_opg@ +vnoremap (EasyAlign) :call easy_align_op(visualmode(), 1) +nnoremap (LiveEasyAlign) :set opfunc=live_easy_align_opg@ +vnoremap (LiveEasyAlign) :call live_easy_align_op(visualmode(), 1) + +" vim-repeat support +nnoremap (EasyAlignRepeat) :let g:easy_align_need_repeat = 1. +vnoremap (EasyAlignRepeat) :let g:easy_align_need_repeat = 1gv. + +" Backward-compatibility (deprecated) nnoremap (EasyAlignOperator) :set opfunc=easy_align_opg@ diff --git a/test/interactive.vader b/test/interactive.vader index 4394e58..737d354 100644 --- a/test/interactive.vader +++ b/test/interactive.vader @@ -15,11 +15,17 @@ Execute (Clean up test environment): let g:easy_align_delimiters = {} let mapleader = ' ' - vnoremap :EasyAlign vnoremap r :EasyAlign! - vnoremap :LiveEasyAlign vnoremap r :LiveEasyAlign! - nmap A (EasyAlignOperator) + + " " Legacy + " vnoremap :EasyAlign + " vnoremap :LiveEasyAlign + " nmap A (EasyAlignOperator) + + vmap (EasyAlign) + vmap (LiveEasyAlign) + nmap A (EasyAlign) ########################################################### @@ -1510,6 +1516,35 @@ Expect: 'type': 'global', '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): + \Aip\= + 6G + . + +Expect: + a = 1 + bb = 2 + ccc = 3 + dddd = 4 + + d = 1 + cc = 2 + bbb = 3 + aaaa = 4 + ########################################################### Execute: Restore