9 Commits
2.5.1 ... 2.6.0

Author SHA1 Message Date
Junegunn Choi
bab23a1917 Update documentation 2013-10-05 15:55:22 +09:00
Junegunn Choi
fa26fd7b42 Remove option value after every cycle 2013-10-05 15:27:50 +09:00
Junegunn Choi
a4a1e27395 Apply ignore_unmatched option on R/C mode if explicitly set
By default, unmatched trailing token from each line is also aligned in
right and center alignment modes unlike in left alignment mode. If
ignore_unmatched option is explicitly set to 1 by user, they will be ignored
even in right/center modes.
2013-10-05 12:23:44 +09:00
Junegunn Choi
98bd9fe6f0 Shorthand notation for ignore_groups/ignore_unmatched
e.g. ig['String']iu0
2013-10-04 02:29:24 +09:00
Junegunn Choi
f944f5bf29 Set g:easy_align_last_command 2013-10-04 02:07:35 +09:00
Junegunn Choi
484b4ba5ec Update doc 2013-10-04 01:50:43 +09:00
Junegunn Choi
9d3afa6206 Merge option values in dictionary and shortcut expression 2013-10-04 01:36:55 +09:00
Junegunn Choi
4c6a8c174d Implement shortcut expression for options 2013-10-03 21:59:51 +09:00
Junegunn Choi
3304f4e95a Make <Down> set both left and right margin to zero
(Undocumented) <Up> will clear *UP* left_margin, right_margin, and stick_to_left
2013-10-03 16:06:23 +09:00
7 changed files with 195 additions and 57 deletions

View File

@@ -77,7 +77,7 @@ For convenience, it is advised that you define a mapping for triggering it in
your `.vimrc`.
```vim
vnoremap <silent> <Enter> :EasyAlign<cr>
vnoremap <silent> <Enter> :EasyAlign<Enter>
```
(Of course you can use any key combination as the trigger. e.g. `<Leader>a`)
@@ -158,6 +158,14 @@ keys listed below. The meaning of each option will be described in
| `CTRL-O` | `mode_sequence` | Input string of `/[lrc]+\*{0,2}/` |
| `<Left>` | `stick_to_left` | `{ 'stick_to_left': 1, 'left_margin': 0 }` |
| `<Right>` | `stick_to_left` | `{ 'stick_to_left': 0, 'left_margin': 1 }` |
| `<Down>` | `*_margin` | `{ 'left_margin': 0, 'right_margin': 0 }` |
After a successful alignment, you can repeat the same operation using the
repeatable, non-interactive command recorded in `g:easy_align_last_command`.
```vim
:<C-R>=g:easy_align_last_command<Enter><Enter>
```
---
@@ -171,7 +179,7 @@ Go try out vim-easy-align right now, and come back later when you feel like it.
---
### Non-interactive mode
### Non-interactive mode (command line)
Instead of going into the interactive mode, you can type in arguments to
`:EasyAlign` command.
@@ -215,8 +223,26 @@ You can even omit spaces between the arguments, so concisely (or cryptically):
- `:EasyAlign*/[:;]\+/{'s':1,'l':0}`
The same thing can be done in the interactive mode as well with the following
key combination.
Nice. But let's make it even shorter. When you use write regular expression in
command line, option values can be written in shorthand notation.
- `:EasyAlign*/[:;]\+/s1l0`
The following table summarizes the shorthand notation.
| Option | Expression |
| ---------------- | ---------- |
| left_margin | `l[0-9]+` |
| right_margin | `r[0-9]+` |
| stick_to_left | `s[01]` |
| ignore_unmatched | `iu[01]` |
| ignore_groups | `ig\[.*\]` |
| delimiter_align | `d[lrc]` |
| mode_sequence | `m[lrc*]*` |
| indentation | `i[ksdn]` |
For your information, the same thing can be done in the interactive mode as well
with the following key combination.
- `<Enter>`
- `*`
@@ -273,19 +299,19 @@ There are 4 ways to set alignment options (from lowest precedence to highest):
1. Some option values can be set with corresponding global variables
2. Option values can be specified in the definition of each alignment rule
3. Option values can be given as a dictionary argument to `:EasyAlign` command
3. Option values can be given as arguments to `:EasyAlign` command
4. Option values can be set in interactive mode using special shortcut keys
| Option | Shortcut key | Global variable |
| ------------------ | ------------------- | ------------------------------- |
| `left_margin` | `CTRL-L` | |
| `right_margin` | `CTRL-R` | |
| `stick_to_left` | `<Left>`, `<Right>` | |
| `ignore_groups` | `CTRL-G` | `g:easy_align_ignore_groups` |
| `ignore_unmatched` | `CTRL-U` | `g:easy_align_ignore_unmatched` |
| `indentation` | `CTRL-I` | `g:easy_align_indentation` |
| `delimiter_align` | `CTRL-D` | `g:easy_align_delimiter_align` |
| `mode_sequence` | `CTRL-O` | |
| Option name | Shortcut key | Abbreviated | Global variable |
| ------------------ | ------------------- | ----------- | ------------------------------- |
| `left_margin` | `CTRL-L` | `l[0-9]+` | |
| `right_margin` | `CTRL-R` | `r[0-9]+` | |
| `stick_to_left` | `<Left>`, `<Right>` | `s[01]` | |
| `ignore_groups` | `CTRL-G` | `ig\[.*\]` | `g:easy_align_ignore_groups` |
| `ignore_unmatched` | `CTRL-U` | `iu[01]` | `g:easy_align_ignore_unmatched` |
| `indentation` | `CTRL-I` | `i[ksdn]` | `g:easy_align_indentation` |
| `delimiter_align` | `CTRL-D` | `d[lrc]` | `g:easy_align_delimiter_align` |
| `mode_sequence` | `CTRL-O` | `m[lrc*]*` | |
### Ignoring delimiters in comments or strings

View File

@@ -49,10 +49,10 @@ let s:known_options = {
\ }
let s:option_values = {
\ 'indentation': ['shallow', 'deep', 'none', 'keep'],
\ 'delimiter_align': ['left', 'center', 'right'],
\ 'ignore_unmatched': [0, 1],
\ 'ignore_groups': [[], ['String'], ['Comment'], ['String', 'Comment']]
\ 'indentation': ['shallow', 'deep', 'none', 'keep', -1],
\ 'delimiter_align': ['left', 'center', 'right', -1],
\ 'ignore_unmatched': [0, 1, -1],
\ 'ignore_groups': [[], ['String'], ['Comment'], ['String', 'Comment'], -1]
\ }
let s:shorthand = {
@@ -142,6 +142,7 @@ function! s:echon(l, n, r, d, o, warn)
endif
call s:echon_(tokens)
return join(map(tokens, 'v:val[1]'), '')
endfunction
function! s:exit(msg)
@@ -311,7 +312,10 @@ function! s:split_line(line, nth, modes, cycle, fc, lc, pattern, stick_to_left,
let delims = []
" Append an empty item to enable right/center alignment of the last token
" - if the last token is not ignorable or ignorable but not the only token
elseif (mode ==? 'r' || mode ==? 'c') && (!ignorable || len(tokens) > 1) && a:nth >= 0 " includes -0
elseif a:ignore_unmatched != 1 &&
\ (mode ==? 'r' || mode ==? 'c') &&
\ (!ignorable || len(tokens) > 1) &&
\ a:nth >= 0 " includes -0
call add(tokens, '')
call add(delims, '')
endif
@@ -557,6 +561,15 @@ function! s:atoi(str)
return (a:str =~ '^[0-9]\+$') ? str2nr(a:str) : a:str
endfunction
function! s:shift_opts(opts, key, vals)
let val = s:shift(a:vals, 1)
if type(val) == 0 && val == -1
call remove(a:opts, a:key)
else
let a:opts[a:key] = val
endif
endfunction
function! s:interactive(modes, vis, opts, delims)
let mode = s:shift(a:modes, 1)
let n = ''
@@ -600,9 +613,9 @@ function! s:interactive(modes, vis, opts, delims)
else | let n = n . ch
end
elseif ch == "\<C-D>"
let opts['da'] = s:shift(vals['delimiter_align'], 1)
call s:shift_opts(opts, 'da', vals['delimiter_align'])
elseif ch == "\<C-I>"
let opts['idt'] = s:shift(vals['indentation'], 1)
call s:shift_opts(opts, 'idt', vals['indentation'])
elseif ch == "\<C-L>"
let lm = s:input("Left margin: ", get(opts, 'lm', ''), a:vis)
if empty(lm)
@@ -620,18 +633,22 @@ function! s:interactive(modes, vis, opts, delims)
let opts['rm'] = s:atoi(rm)
endif
elseif ch == "\<C-U>"
let opts['iu'] = s:shift(vals['ignore_unmatched'], 1)
call s:shift_opts(opts, 'iu', vals['ignore_unmatched'])
elseif ch == "\<C-G>"
let opts['ig'] = s:shift(vals['ignore_groups'], 1)
call s:shift_opts(opts, 'ig', vals['ignore_groups'])
elseif c == "\<Left>"
let opts['stl'] = 1
let opts['lm'] = 0
elseif c == "\<Right>"
let opts['stl'] = 0
let opts['lm'] = 1
elseif c == "\<Up>" || c == "\<Down>"
elseif c == "\<Down>"
let opts['lm'] = 0
let opts['rm'] = 0
elseif c == "\<Up>"
silent! call remove(opts, 'stl')
silent! call remove(opts, 'lm')
silent! call remove(opts, 'rm')
elseif ch == "\<C-O>"
let modes = tolower(s:input("Mode sequence: ", get(opts, 'm', mode), a:vis))
if match(modes, '^[lrc]\+\*\{0,2}$') != -1
@@ -684,6 +701,51 @@ function! s:test_regexp(regexp)
return a:regexp
endfunction
function! s:parse_shortcut_opts(expr)
let opts = {}
let expr = substitute(a:expr, '\s', '', 'g')
let regex =
\ '^\('
\ .'\(l[0-9]\+\)\|\(r[0-9]\+\)\|\(iu[01]\)\|\(s[01]\)\|'
\ .'\(d[clr]\)\|\(m[lrc*]\+\)\|\(i[kdsn]\)\|\(ig\[.*\]\)'
\ .'\)\+$'
if empty(expr)
return opts
elseif expr !~ regex
call s:exit("Invalid expression: ". a:expr)
else
let match = matchlist(expr, regex)
if empty(match) | break | endif
for m in filter(match[ 2 : -1 ], '!empty(v:val)')
let k = tolower(m[0])
let kk = tolower(m[0 : 1])
let rest = m[1 : -1]
if index(['l', 'r', 's'], k) >= 0
let opts[k] = str2nr(rest)
elseif kk == 'iu'
let opts['iu'] = str2nr(m[2 : -1])
elseif kk == 'ig'
try
let arr = eval(m[2 : -1])
if type(arr) == 3
let opts['ig'] = arr
else
throw 'Not an array'
endif
catch
call s:exit("Invalid ignore_groups: ". a:expr)
endtry
elseif k == 'i'
let opts['idt'] = rest
else
let opts[k] = rest
endif
endfor
endif
return s:normalize_options(opts)
endfunction
function! s:parse_args(args)
let n = ''
let ch = ''
@@ -724,10 +786,13 @@ function! s:parse_args(args)
endif
" Has /Regexp/?
let matches = matchlist(args, '^\(.\{-}\)\s*/\(.*\)/\s*$')
let matches = matchlist(args, '^\(.\{-}\)\s*/\(.*\)/\(.\{-}\)$')
" Found regexp
if !empty(matches)
if !empty(matches[3])
let opts = extend(s:parse_shortcut_opts(matches[3]), opts)
endif
return [matches[1], s:test_regexp(matches[2]), opts, 1]
else
let tokens = matchlist(args, '^\([1-9][0-9]*\|-[0-9]*\|\*\*\?\)\?\s*\(.\{-}\)\?$')
@@ -848,7 +913,7 @@ function! s:align(bang, first_line, last_line, expr)
\ get(dict, 'delimiter_align', get(g:, 'easy_align_delimiter_align', 'r'))[0],
\ get(dict, 'indentation', get(g:, 'easy_align_indentation', 'k'))[0],
\ get(dict, 'stick_to_left', 0),
\ get(dict, 'ignore_unmatched', get(g:, 'easy_align_ignore_unmatched', 1)),
\ get(dict, 'ignore_unmatched', get(g:, 'easy_align_ignore_unmatched', 2)),
\ get(dict, 'ignore_groups', get(dict, 'ignores', s:ignored_syntax())),
\ recur)
@@ -860,6 +925,6 @@ function! s:align(bang, first_line, last_line, expr)
\ )
call extend(copts, { 'm': aseq_str })
endif
call s:echon('', n, regexp, ch, copts, '')
let g:easy_align_last_command = s:echon('', n, regexp, ch, copts, '')
endfunction

View File

@@ -30,7 +30,7 @@ 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
your `.vimrc`.
vnoremap <silent> <Enter> :EasyAlign<cr>
vnoremap <silent> <Enter> :EasyAlign<Enter>
With this mapping, you can align selected lines of text with a few keystrokes.
@@ -97,9 +97,17 @@ described in the following sections.
| CTRL-O | mode_sequence | Input string of /[lrc]+\*{0,2}/ |
| <Left> | stick_to_left | { 'stick_to_left': 1, 'left_margin': 0 } |
| <Right> | stick_to_left | { 'stick_to_left': 0, 'left_margin': 1 } |
| <Down> | *_margin | { 'left_margin': 0, 'right_margin': 0 } |
*g:easy_align_last_command*
After a successful alignment, you can repeat the same operation using the
repeatable, non-interactive command recorded in `g:easy_align_last_command`.
:<C-R>=g:easy_align_last_command<Enter><Enter>
Non-interactive mode
Non-interactive mode (command line)
-------------------------------------------------------------------------
Instead of going into the interactive mode, you can type in arguments to
@@ -118,16 +126,16 @@ For example, when aligning the following lines around colons and semi-colons,
try these commands:
- :EasyAlign /[:;]\+/
- :EasyAlign 2/[:;]\+/
- :EasyAlign */[:;]\+/
- :EasyAlign **/[:;]\+/
:EasyAlign /[:;]\+/
:EasyAlign 2/[:;]\+/
:EasyAlign */[:;]\+/
:EasyAlign **/[:;]\+/
Notice that you can't append '\zs' to your regular expression to put delimiters
on the left. It can be done by providing additional options in Vim dictionary
format.
- :EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'left_margin': 0 }
:EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'left_margin': 0 }
Then we get:
@@ -136,20 +144,38 @@ Then we get:
Option names are fuzzy-matched, so you can write as follows:
- :EasyAlign * /[:;]\+/ { 'stl': 1, 'l': '' }
:EasyAlign * /[:;]\+/ { 'stl': 1, 'l': '' }
You can even omit spaces between the arguments, so concisely (or cryptically):
- :EasyAlign*/[:;]\+/{'s':1,'l':''}
:EasyAlign*/[:;]\+/{'s':1,'l':''}
The same thing can be done in the interactive mode as well with the following
key combination.
Nice. But let's make it even shorter. When you use write regular expression in
command line, option values can be written in shorthand notation.
- <Enter>
- *
- <Left>
- <CTRL-/> (or <CTRL-X> on GVim)
- [:;]\+
:EasyAlign*/[:;]\+/s1l0
The following table summarizes the shorthand notation.
| Option | Expression |
| -------------- | ---------- |
| left_margin | l[0-9]+ |
| right_margin | r[0-9]+ |
| stick_to_left | s[01] |
| ignore_unmatched | iu[01] |
| ignore_groups | ig\[.*\] |
| delimiter_align | d[lrc] |
| mode_sequence | m[lrc*]+ |
| indentation | i[ksdn] |
For your information, the same thing can be done in the interactive mode as well
with the following key combination.
- <Enter>
- *
- <Left>
- <CTRL-/> (or <CTRL-X> on GVim)
- [:;]\+
Partial alignment in blockwise-visual mode
@@ -182,19 +208,19 @@ There are 4 ways to set alignment options (from lowest precedence to highest):
1. Some option values can be set with corresponding global variables
2. Option values can be specified in the definition of each alignment rule
3. Option values can be given as a dictionary argument to :EasyAlign command
3. Option values can be given as arguments to :EasyAlign command
4. Option values can be set in interactive mode using special shortcut keys
| Option | Shortcut key | Global variable |
| ---------------- | ------------------- | ------------------------------- |
| left_margin | CTRL-L | |
| right_margin | CTRL-R | |
| stick_to_left | <Left>, <Right> | |
| ignore_groups | CTRL-G | `g:easy_align_ignore_groups` |
| ignore_unmatched | CTRL-U | `g:easy_align_ignore_unmatched` |
| indentation | CTRL-I | `g:easy_align_indentation` |
| delimiter_align | CTRL-D | `g:easy_align_delimiter_align` |
| mode_sequence | CTRL-O | |
| Option | Shortcut key | Abbreviated | Global variable |
| ---------------- | --------------- | ----------- | ----------------------------- |
| left_margin | CTRL-L | l[0-9]+ | |
| right_margin | CTRL-R | r[0-9]+ | |
| stick_to_left | <Left>, <Right> | s[01] | |
| ignore_groups | CTRL-G | ig\[.*\] | `g:easy_align_ignore_groups` |
| ignore_unmatched | CTRL-U | iu[01] | `g:easy_align_ignore_unmatched` |
| indentation | CTRL-I | i[ksdn] | `g:easy_align_indentation` |
| delimiter_align | CTRL-D | d[lrc] | `g:easy_align_delimiter_align` |
| mode_sequence | CTRL-O | m[lrc*]+ | |
Ignoring delimiters in comments or strings *g:easy_align_ignore_groups*

View File

@@ -1064,3 +1064,12 @@ aaa, b,
111 22 333 444 55555 6666 7 88888
1111 2 33 444 555 66 777 8
a = 1
bb = 2
ccccc
ddd = 3
a = 1
bb = 2
ccccc
ddd = 3

View File

@@ -1 +1 @@
4Gvipjyvip
4Gvipjyvip

View File

@@ -94,3 +94,15 @@ banana = 'Gros Michel' # comment 2
a()p()p()l()e();():()b()a()n()a()n()a():():()c()a()k()e(
d()a()t()a();();()e()x()c()h()a()n()g()e():();()f()o()r()m()a()t(
apple ;: banana :: cake
data ;;exchange :;format
apple ;: banana :: cake
data ;; exchange :; format
apple;:banana ::cake
data ;;exchange:;format
apple ;: banana :: cake
data ;; exchange :; format

View File

@@ -1 +1 @@
4Gvipjyvip:EasyAlign:
4Gvipjyvip:EasyAlign: