mirror of
https://github.com/junegunn/vim-easy-align.git
synced 2025-11-10 10:53:49 -05:00
Implement special keys to switch option values in interactive mode
With this commit, we can now change option values in interactive mode with the
folowing special keys
- CTRL-L left_margin
- CTRL-R right_margin
- CTRL-D delimiter_align
- CTRL-I indentation
- CTRL-U ignore_unmatched
- CTRL-G ignore_groups
('ignores' option has been renamed to 'ignore_groups', but backward-compatible)
This commit is contained in:
@@ -240,10 +240,10 @@ So, let's define a custom mapping for `#`.
|
|||||||
if !exists('g:easy_align_delimiters')
|
if !exists('g:easy_align_delimiters')
|
||||||
let g:easy_align_delimiters = {}
|
let g:easy_align_delimiters = {}
|
||||||
endif
|
endif
|
||||||
let g:easy_align_delimiters['#'] = { 'pattern': '#', 'ignores': ['String'] }
|
let g:easy_align_delimiters['#'] = { 'pattern': '#', 'ignore_groups': ['String'] }
|
||||||
```
|
```
|
||||||
|
|
||||||
Notice that the rule overrides `ignores` attribute in order *not to ignore*
|
Notice that the rule overrides `ignore_groups` attribute in order *not to ignore*
|
||||||
delimiters highlighted as comments.
|
delimiters highlighted as comments.
|
||||||
|
|
||||||
Then on `<Enter>#`, we get
|
Then on `<Enter>#`, we get
|
||||||
@@ -285,7 +285,7 @@ let g:easy_align_ignore_unmatched = 0
|
|||||||
|
|
||||||
" 3. Update the alignment rule with ignore_unmatched option
|
" 3. Update the alignment rule with ignore_unmatched option
|
||||||
let g:easy_align_delimiters['#'] = {
|
let g:easy_align_delimiters['#'] = {
|
||||||
\ 'pattern': '#', 'ignores': ['String'], 'ignore_unmatched': 0 }
|
\ 'pattern': '#', 'ignore_groups': ['String'], 'ignore_unmatched': 0 }
|
||||||
```
|
```
|
||||||
|
|
||||||
Then we get,
|
Then we get,
|
||||||
|
|||||||
69
README.md
69
README.md
@@ -194,28 +194,40 @@ lowest precedence.
|
|||||||
|
|
||||||
### List of options
|
### List of options
|
||||||
|
|
||||||
| Option | Type | Default | Description |
|
| Option | Type | Default | Description |
|
||||||
| ------------------ | ----------------- | --------------------- | ------------------------------------------------------- |
|
| ------------------ | ------- | --------------------- | ------------------------------------------------------- |
|
||||||
| `left_margin` | number | 0 | Number of spaces to attach before delimiter |
|
| `left_margin` | number | 0 | Number of spaces to attach before delimiter |
|
||||||
| `left_margin` | string | `''` | String to attach before delimiter |
|
| `left_margin` | string | `''` | String to attach before delimiter |
|
||||||
| `right_margin` | number | 0 | Number of spaces to attach after delimiter |
|
| `right_margin` | number | 0 | Number of spaces to attach after delimiter |
|
||||||
| `right_margin` | string | `''` | String to attach after delimiter |
|
| `right_margin` | string | `''` | String to attach after delimiter |
|
||||||
| `stick_to_left` | boolean | 0 | Whether to position delimiter on the left-side |
|
| `stick_to_left` | boolean | 0 | Whether to position delimiter on the left-side |
|
||||||
| `ignore_unmatched` | boolean | 1 | Whether to ignore lines without matching delimiter |
|
| `ignore_groups` | list | ['String', 'Comment'] | Delimiters in these syntax highlight groups are ignored |
|
||||||
| `ignores` | list | ['String', 'Comment'] | Delimiters in these syntax highlight groups are ignored |
|
| `ignore_unmatched` | boolean | 1 | Whether to ignore lines without matching delimiter |
|
||||||
| `indentation` | string | `k` | Indentation method (*k*eep, *d*eep, *s*hallow, *n*one) |
|
| `indentation` | string | `k` | Indentation method (*k*eep, *d*eep, *s*hallow, *n*one) |
|
||||||
| `delimiter_align` | string | `r` | Determines how to align delimiters of different lengths |
|
| `delimiter_align` | string | `r` | Determines how to align delimiters of different lengths |
|
||||||
| `mode_sequence` | string | | Alignment modes for multiple occurrences of delimiters |
|
| `mode_sequence` | string | | Alignment modes for multiple occurrences of delimiters |
|
||||||
|
|
||||||
Some of the options can be specified using corresponding global variables.
|
Some of the options can be specified using corresponding global variables.
|
||||||
|
|
||||||
| Option | Global variable |
|
| Option | Global variable |
|
||||||
| ------------------ | ------------------------------- |
|
| ------------------ | ------------------------------- |
|
||||||
|
| `ignore_groups` | `g:easy_align_ignore_groups` |
|
||||||
| `ignore_unmatched` | `g:easy_align_ignore_unmatched` |
|
| `ignore_unmatched` | `g:easy_align_ignore_unmatched` |
|
||||||
| `ignores` | `g:easy_align_ignores` |
|
|
||||||
| `delimiter_align` | `g:easy_align_delimiter_align` |
|
| `delimiter_align` | `g:easy_align_delimiter_align` |
|
||||||
| `indentation` | `g:easy_align_indentation` |
|
| `indentation` | `g:easy_align_indentation` |
|
||||||
|
|
||||||
|
In interactive mode, you can switch some of the alignment options using special
|
||||||
|
keys listed below.
|
||||||
|
|
||||||
|
| Key | Option | Values |
|
||||||
|
| -------- | ------------------ | -------------------------------------------------- |
|
||||||
|
| `CTRL-I` | `indentation` | shallow, deep, none, keep |
|
||||||
|
| `CTRL-L` | `left_margin` | Input number or string |
|
||||||
|
| `CTRL-R` | `right_margin` | Input number or string |
|
||||||
|
| `CTRL-D` | `delimiter_align` | left, center, right |
|
||||||
|
| `CTRL-U` | `ignore_unmatched` | 0, 1 |
|
||||||
|
| `CTRL-G` | `ignore_groups` | [], ['String'], ['Comment'], ['String', 'Comment'] |
|
||||||
|
|
||||||
### Ignoring delimiters in comments or strings
|
### Ignoring delimiters in comments or strings
|
||||||
|
|
||||||
EasyAlign can be configured to ignore delimiters in certain syntax highlight
|
EasyAlign can be configured to ignore delimiters in certain syntax highlight
|
||||||
@@ -226,7 +238,7 @@ highlighted as code comments or strings are ignored.
|
|||||||
" Default:
|
" Default:
|
||||||
" If a delimiter is in a highlight group whose name matches
|
" If a delimiter is in a highlight group whose name matches
|
||||||
" any of the followings, it will be ignored.
|
" any of the followings, it will be ignored.
|
||||||
let g:easy_align_ignores = ['Comment', 'String']
|
let g:easy_align_ignore_groups = ['Comment', 'String']
|
||||||
```
|
```
|
||||||
|
|
||||||
For example, the following paragraph
|
For example, the following paragraph
|
||||||
@@ -257,13 +269,15 @@ becomes as follows on `<Enter>:` (or `:EasyAlign:`)
|
|||||||
|
|
||||||
Naturally, this feature only works when syntax highlighting is enabled.
|
Naturally, this feature only works when syntax highlighting is enabled.
|
||||||
|
|
||||||
You can change the default rule by using one of these 3 methods.
|
You can change the default rule by using one of these 4 methods.
|
||||||
|
|
||||||
1. Define global `g:easy_align_ignores` list
|
1. Press `CTRL-G` in interactive mode to switch groups
|
||||||
2. Define a custom alignment rule in `g:easy_align_delimiters` with `ignores` option
|
2. Define global `g:easy_align_ignore_groups` list
|
||||||
3. Provide `ignores` option to `:EasyAlign` command. e.g. `:EasyAlign:{'is':[]}`
|
3. Define a custom rule in `g:easy_align_delimiters` with `ignore_groups` option
|
||||||
|
4. Provide `ignore_groups` option to `:EasyAlign` command.
|
||||||
|
e.g. `:EasyAlign:{'ig':[]}`
|
||||||
|
|
||||||
For example if you set `ignores` option to be an empty list, you get
|
For example if you set `ignore_groups` option to be an empty list, you get
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
{
|
{
|
||||||
@@ -307,12 +321,13 @@ this is usually what we want.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
However, this default behavior is also configurable by using one of these 3
|
However, this default behavior is also configurable by using one of these 4
|
||||||
methods.
|
methods.
|
||||||
|
|
||||||
1. Set the global `g:easy_align_ignore_unmatched` variable to 0
|
1. Press `CTRL-U` in interactive mode to toggle `ignore_unmatched` option
|
||||||
2. Define a custom alignment rule with `ignore_unmatched` option set to 0
|
2. Set the global `g:easy_align_ignore_unmatched` variable to 0
|
||||||
3. Provide `ignore_unmatched` option to `:EasyAlign` command. e.g. `:EasyAlign:{'iu':0}`
|
3. Define a custom alignment rule with `ignore_unmatched` option set to 0
|
||||||
|
4. Provide `ignore_unmatched` option to `:EasyAlign` command. e.g. `:EasyAlign:{'iu':0}`
|
||||||
|
|
||||||
Then we get,
|
Then we get,
|
||||||
|
|
||||||
@@ -362,6 +377,8 @@ banana += apple
|
|||||||
cake ||= banana
|
cake ||= banana
|
||||||
```
|
```
|
||||||
|
|
||||||
|
In interactive mode, you can change the option value with `CTRL-D` key.
|
||||||
|
|
||||||
### Adjusting indentation
|
### Adjusting indentation
|
||||||
|
|
||||||
By default :EasyAlign command keeps the original indentation of the lines. But
|
By default :EasyAlign command keeps the original indentation of the lines. But
|
||||||
@@ -410,6 +427,8 @@ eggplant = 5
|
|||||||
|
|
||||||
Notice that `idt` is fuzzy-matched to `indentation`.
|
Notice that `idt` is fuzzy-matched to `indentation`.
|
||||||
|
|
||||||
|
In interactive mode, you can change the option value with `CTRL-I` key.
|
||||||
|
|
||||||
### Left/right/center mode switch in interactive mode
|
### Left/right/center mode switch in interactive mode
|
||||||
|
|
||||||
In interactive mode, you can choose the alignment mode you want by pressing
|
In interactive mode, you can choose the alignment mode you want by pressing
|
||||||
@@ -489,8 +508,8 @@ you can extend the rules by setting a dictionary named `g:easy_align_delimiters`
|
|||||||
```vim
|
```vim
|
||||||
let g:easy_align_delimiters = {
|
let g:easy_align_delimiters = {
|
||||||
\ '>': { 'pattern': '>>\|=>\|>' },
|
\ '>': { 'pattern': '>>\|=>\|>' },
|
||||||
\ '/': { 'pattern': '//\+\|/\*\|\*/', 'ignores': ['String'] },
|
\ '/': { 'pattern': '//\+\|/\*\|\*/', 'ignore_groups': ['String'] },
|
||||||
\ '#': { 'pattern': '#\+', 'ignores': ['String'], 'delimiter_align': 'l' },
|
\ '#': { 'pattern': '#\+', 'ignore_groups': ['String'], 'delimiter_align': 'l' },
|
||||||
\ ']': {
|
\ ']': {
|
||||||
\ 'pattern': '[[\]]',
|
\ 'pattern': '[[\]]',
|
||||||
\ 'left_margin': 0,
|
\ 'left_margin': 0,
|
||||||
|
|||||||
@@ -44,8 +44,15 @@ let s:mode_labels = { 'l': '', 'r': '[R]', 'c': '[C]' }
|
|||||||
let s:known_options = {
|
let s:known_options = {
|
||||||
\ 'margin_left': [0, 1], 'margin_right': [0, 1], 'stick_to_left': [0],
|
\ 'margin_left': [0, 1], 'margin_right': [0, 1], 'stick_to_left': [0],
|
||||||
\ 'left_margin': [0, 1], 'right_margin': [0, 1], 'indentation': [1],
|
\ 'left_margin': [0, 1], 'right_margin': [0, 1], 'indentation': [1],
|
||||||
\ 'ignores': [3 ], 'ignore_unmatched': [0 ], 'delimiter_align': [1],
|
\ 'ignore_groups': [3 ], 'ignore_unmatched': [0 ], 'delimiter_align': [1],
|
||||||
\ 'mode_sequence': [1 ]
|
\ 'mode_sequence': [1 ], 'ignores': [3]
|
||||||
|
\ }
|
||||||
|
|
||||||
|
let s:option_values = {
|
||||||
|
\ 'indentation': ['shallow', 'deep', 'none', 'keep'],
|
||||||
|
\ 'delimiter_align': ['left', 'center', 'right'],
|
||||||
|
\ 'ignore_unmatched': [0, 1],
|
||||||
|
\ 'ignore_groups': [[], ['String'], ['Comment'], ['String', 'Comment']]
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
if exists("*strwidth")
|
if exists("*strwidth")
|
||||||
@@ -72,17 +79,19 @@ endfunction
|
|||||||
function! s:ignored_syntax()
|
function! s:ignored_syntax()
|
||||||
if has('syntax') && exists('g:syntax_on')
|
if has('syntax') && exists('g:syntax_on')
|
||||||
" Backward-compatibility
|
" Backward-compatibility
|
||||||
return get(g:, 'easy_align_ignores',
|
return get(g:, 'easy_align_ignore_groups',
|
||||||
\ (get(g:, 'easy_align_ignore_comment', 1) == 0) ?
|
\ get(g:, 'easy_align_ignores',
|
||||||
\ ['String'] : ['String', 'Comment'])
|
\ (get(g:, 'easy_align_ignore_comment', 1) == 0) ?
|
||||||
|
\ ['String'] : ['String', 'Comment']))
|
||||||
else
|
else
|
||||||
return []
|
return []
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:echon(l, n, d)
|
function! s:echon(l, n, d, o)
|
||||||
echon "\r"
|
echon "\r"
|
||||||
echon "\rEasyAlign". s:mode_labels[a:l] ." (" .a:n.a:d. ")"
|
echon "\rEasyAlign". s:mode_labels[a:l] ." (" .a:n.a:d. ")"
|
||||||
|
\ . (empty(a:o) ? '' : ' '.string(a:o))
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:exit(msg)
|
function! s:exit(msg)
|
||||||
@@ -106,9 +115,18 @@ function! s:fuzzy_lu(key)
|
|||||||
if has_key(s:known_options, a:key)
|
if has_key(s:known_options, a:key)
|
||||||
return a:key
|
return a:key
|
||||||
endif
|
endif
|
||||||
|
let key = tolower(a:key)
|
||||||
|
|
||||||
let regexp = '^' . substitute(substitute(a:key, '-', '_', 'g'), '\(.\)', '\1.*', 'g')
|
" stl -> ^s.*_t.*_l.*
|
||||||
let matches = filter(keys(s:known_options), 'v:val =~ regexp')
|
let regexp1 = '^' .key[0]. '.*' .substitute(key[1 : -1], '\(.\)', '_\1.*', 'g')
|
||||||
|
let matches = filter(keys(s:known_options), 'v:val =~ regexp1')
|
||||||
|
if len(matches) == 1
|
||||||
|
return matches[0]
|
||||||
|
endif
|
||||||
|
|
||||||
|
" stl -> ^s.*t.*l.*
|
||||||
|
let regexp2 = '^' . substitute(substitute(key, '-', '_', 'g'), '\(.\)', '\1.*', 'g')
|
||||||
|
let matches = filter(keys(s:known_options), 'v:val =~ regexp2')
|
||||||
|
|
||||||
if empty(matches)
|
if empty(matches)
|
||||||
call s:exit("Unknown option key: ". a:key)
|
call s:exit("Unknown option key: ". a:key)
|
||||||
@@ -116,9 +134,12 @@ function! s:fuzzy_lu(key)
|
|||||||
return matches[0]
|
return matches[0]
|
||||||
else
|
else
|
||||||
" Avoid ambiguity introduced by deprecated margin_left and margin_right
|
" Avoid ambiguity introduced by deprecated margin_left and margin_right
|
||||||
if index(matches, 'mode_sequence') != -1
|
if sort(matches) == ['margin_left', 'margin_right', 'mode_sequence']
|
||||||
return 'mode_sequence'
|
return 'mode_sequence'
|
||||||
endif
|
endif
|
||||||
|
if sort(matches) == ['ignore_groups', 'ignores']
|
||||||
|
return 'ignore_groups'
|
||||||
|
endif
|
||||||
call s:exit("Ambiguous option key: ". a:key ." (" .join(matches, ', '). ")")
|
call s:exit("Ambiguous option key: ". a:key ." (" .join(matches, ', '). ")")
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
@@ -156,7 +177,7 @@ function! s:validate_options(opts)
|
|||||||
return a:opts
|
return a:opts
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:split_line(line, nth, modes, cycle, fc, lc, pattern, stick_to_left, ignore_unmatched, ignores)
|
function! s:split_line(line, nth, modes, cycle, fc, lc, pattern, stick_to_left, ignore_unmatched, ignore_groups)
|
||||||
let mode = ''
|
let mode = ''
|
||||||
|
|
||||||
let string = a:lc ?
|
let string = a:lc ?
|
||||||
@@ -189,7 +210,7 @@ function! s:split_line(line, nth, modes, cycle, fc, lc, pattern, stick_to_left,
|
|||||||
let [match, part, delim] = matches[1 : 3]
|
let [match, part, delim] = matches[1 : 3]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let ignorable = s:highlighted_as(a:line, idx + len(part) + a:fc, a:ignores)
|
let ignorable = s:highlighted_as(a:line, idx + len(part) + a:fc, a:ignore_groups)
|
||||||
if ignorable
|
if ignorable
|
||||||
let token .= match
|
let token .= match
|
||||||
else
|
else
|
||||||
@@ -212,7 +233,7 @@ function! s:split_line(line, nth, modes, cycle, fc, lc, pattern, stick_to_left,
|
|||||||
|
|
||||||
let leftover = token . strpart(string, idx)
|
let leftover = token . strpart(string, idx)
|
||||||
if !empty(leftover)
|
if !empty(leftover)
|
||||||
let ignorable = s:highlighted_as(a:line, len(string) + a:fc - 1, a:ignores)
|
let ignorable = s:highlighted_as(a:line, len(string) + a:fc - 1, a:ignore_groups)
|
||||||
call add(tokens, leftover)
|
call add(tokens, leftover)
|
||||||
call add(delims, '')
|
call add(delims, '')
|
||||||
endif
|
endif
|
||||||
@@ -249,7 +270,7 @@ function! s:max(old, new)
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:do_align(modes, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth,
|
function! s:do_align(modes, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth,
|
||||||
\ ml, mr, da, indentation, stick_to_left, ignore_unmatched, ignores, recur)
|
\ ml, mr, da, indentation, stick_to_left, ignore_unmatched, ignore_groups, recur)
|
||||||
let mode = a:modes[0]
|
let mode = a:modes[0]
|
||||||
let lines = {}
|
let lines = {}
|
||||||
let min_indent = -1
|
let min_indent = -1
|
||||||
@@ -263,7 +284,7 @@ function! s:do_align(modes, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth
|
|||||||
let [tokens, delims] = s:split_line(
|
let [tokens, delims] = s:split_line(
|
||||||
\ line, a:nth, copy(a:modes), a:recur == 2,
|
\ line, a:nth, copy(a:modes), a:recur == 2,
|
||||||
\ a:fc, a:lc, a:pattern,
|
\ a:fc, a:lc, a:pattern,
|
||||||
\ a:stick_to_left, a:ignore_unmatched, a:ignores)
|
\ a:stick_to_left, a:ignore_unmatched, a:ignore_groups)
|
||||||
|
|
||||||
" Remember tokens for subsequent recursive calls
|
" Remember tokens for subsequent recursive calls
|
||||||
let a:all_tokens[line] = tokens
|
let a:all_tokens[line] = tokens
|
||||||
@@ -434,17 +455,31 @@ function! s:do_align(modes, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth
|
|||||||
\ a:modes, a:all_tokens, a:all_delims,
|
\ a:modes, a:all_tokens, a:all_delims,
|
||||||
\ a:fl, a:ll, a:fc, a:lc, a:pattern,
|
\ a:fl, a:ll, a:fc, a:lc, a:pattern,
|
||||||
\ a:nth + 1, a:ml, a:mr, a:da, a:indentation, a:stick_to_left,
|
\ a:nth + 1, a:ml, a:mr, a:da, a:indentation, a:stick_to_left,
|
||||||
\ a:ignore_unmatched, a:ignores, a:recur)
|
\ a:ignore_unmatched, a:ignore_groups, a:recur)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! s:input(str)
|
||||||
|
redraw
|
||||||
|
call inputsave()
|
||||||
|
let got = input(a:str)
|
||||||
|
call inputrestore()
|
||||||
|
try
|
||||||
|
return eval(got)
|
||||||
|
catch
|
||||||
|
return got
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! s:interactive(modes)
|
function! s:interactive(modes)
|
||||||
let mode = s:shift(a:modes, 1)
|
let mode = s:shift(a:modes, 1)
|
||||||
let n = ''
|
let n = ''
|
||||||
let ch = ''
|
let ch = ''
|
||||||
|
let opts = {}
|
||||||
|
let vals = deepcopy(s:option_values)
|
||||||
|
|
||||||
while 1
|
while 1
|
||||||
call s:echon(mode, n, '')
|
call s:echon(mode, n, '', opts)
|
||||||
|
|
||||||
let c = getchar()
|
let c = getchar()
|
||||||
let ch = nr2char(c)
|
let ch = nr2char(c)
|
||||||
@@ -471,11 +506,23 @@ function! s:interactive(modes)
|
|||||||
if n[0] == '*' | break
|
if n[0] == '*' | break
|
||||||
else | let n = n . ch
|
else | let n = n . ch
|
||||||
end
|
end
|
||||||
|
elseif ch == "\<C-D>"
|
||||||
|
let opts['da'] = s:shift(vals['delimiter_align'], 1)
|
||||||
|
elseif ch == "\<C-I>"
|
||||||
|
let opts['idt'] = s:shift(vals['indentation'], 1)
|
||||||
|
elseif ch == "\<C-L>"
|
||||||
|
let opts['lm'] = s:input("Left margin: ")
|
||||||
|
elseif ch == "\<C-R>"
|
||||||
|
let opts['rm'] = s:input("Right margin: ")
|
||||||
|
elseif ch == "\<C-U>"
|
||||||
|
let opts['iu'] = s:shift(vals['ignore_unmatched'], 1)
|
||||||
|
elseif ch == "\<C-G>"
|
||||||
|
let opts['ig'] = s:shift(vals['ignore_groups'], 1)
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
endif
|
endif
|
||||||
endwhile
|
endwhile
|
||||||
return [mode, n, ch]
|
return [mode, n, ch, s:normalize_options(opts)]
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:parse_args(args)
|
function! s:parse_args(args)
|
||||||
@@ -483,7 +530,7 @@ function! s:parse_args(args)
|
|||||||
let ch = ''
|
let ch = ''
|
||||||
let args = a:args
|
let args = a:args
|
||||||
let cand = ''
|
let cand = ''
|
||||||
let option = {}
|
let opts = {}
|
||||||
|
|
||||||
" Poor man's option parser
|
" Poor man's option parser
|
||||||
let idx = 0
|
let idx = 0
|
||||||
@@ -497,7 +544,7 @@ function! s:parse_args(args)
|
|||||||
let [L, R, C, K, S, D, N] = ['l', 'r', 'c', 'k', 's', 'd', 'n']
|
let [L, R, C, K, S, D, N] = ['l', 'r', 'c', 'k', 's', 'd', 'n']
|
||||||
let o = eval(cand)
|
let o = eval(cand)
|
||||||
if type(o) == 4
|
if type(o) == 4
|
||||||
let option = o
|
let opts = o
|
||||||
if args[midx - 1 : midx] == '\ '
|
if args[midx - 1 : midx] == '\ '
|
||||||
let midx += 1
|
let midx += 1
|
||||||
endif
|
endif
|
||||||
@@ -511,8 +558,10 @@ function! s:parse_args(args)
|
|||||||
endwhile
|
endwhile
|
||||||
|
|
||||||
" Invalid option dictionary
|
" Invalid option dictionary
|
||||||
if len(substitute(cand, '\s', '', 'g')) > 2 && empty(option)
|
if len(substitute(cand, '\s', '', 'g')) > 2 && empty(opts)
|
||||||
call s:exit("Invalid option: ". cand)
|
call s:exit("Invalid option: ". cand)
|
||||||
|
else
|
||||||
|
let opts = s:normalize_options(opts)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Has /Regexp/?
|
" Has /Regexp/?
|
||||||
@@ -525,10 +574,10 @@ function! s:parse_args(args)
|
|||||||
try | call matchlist('', regexp)
|
try | call matchlist('', regexp)
|
||||||
catch | call s:exit("Invalid regular expression: ". regexp)
|
catch | call s:exit("Invalid regular expression: ". regexp)
|
||||||
endtry
|
endtry
|
||||||
return [matches[1], regexp, option, 1]
|
return [matches[1], regexp, opts, 1]
|
||||||
else
|
else
|
||||||
let tokens = matchlist(args, '^\([1-9][0-9]*\|-[0-9]*\|\*\*\?\)\?\s*\(.\{-}\)\?$')
|
let tokens = matchlist(args, '^\([1-9][0-9]*\|-[0-9]*\|\*\*\?\)\?\s*\(.\{-}\)\?$')
|
||||||
return [tokens[1], tokens[2], option, 0]
|
return [tokens[1], tokens[2], opts, 0]
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -540,16 +589,17 @@ function! easy_align#align(bang, expr) range
|
|||||||
let recur = 0
|
let recur = 0
|
||||||
let n = ''
|
let n = ''
|
||||||
let ch = ''
|
let ch = ''
|
||||||
let option = {}
|
let opts = {}
|
||||||
|
let iopts = {}
|
||||||
let regexp = 0
|
let regexp = 0
|
||||||
|
|
||||||
try
|
try
|
||||||
if empty(a:expr)
|
if empty(a:expr)
|
||||||
let [mode, n, ch] = s:interactive(copy(modes))
|
let [mode, n, ch, iopts] = s:interactive(copy(modes))
|
||||||
else
|
else
|
||||||
let [n, ch, option, regexp] = s:parse_args(a:expr)
|
let [n, ch, opts, regexp] = s:parse_args(a:expr)
|
||||||
if empty(n) && empty(ch)
|
if empty(n) && empty(ch)
|
||||||
let [mode, n, ch] = s:interactive(copy(modes))
|
let [mode, n, ch, iopts] = s:interactive(copy(modes))
|
||||||
elseif empty(ch)
|
elseif empty(ch)
|
||||||
" Try swapping n and ch
|
" Try swapping n and ch
|
||||||
let [n, ch] = ['', n]
|
let [n, ch] = ['', n]
|
||||||
@@ -595,13 +645,11 @@ function! easy_align#align(bang, expr) range
|
|||||||
let dict = delimiters[ch]
|
let dict = delimiters[ch]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
try
|
for opt in [opts, iopts]
|
||||||
if !empty(option)
|
if !empty(opt)
|
||||||
let dict = extend(copy(dict), s:normalize_options(option))
|
let dict = extend(copy(dict), opt)
|
||||||
endif
|
endif
|
||||||
catch 'exit'
|
endfor
|
||||||
return
|
|
||||||
endtry
|
|
||||||
|
|
||||||
let ml = get(dict, 'left_margin', ' ')
|
let ml = get(dict, 'left_margin', ' ')
|
||||||
let mr = get(dict, 'right_margin', ' ')
|
let mr = get(dict, 'right_margin', ' ')
|
||||||
@@ -628,13 +676,13 @@ function! easy_align#align(bang, expr) range
|
|||||||
\ nth,
|
\ nth,
|
||||||
\ ml,
|
\ ml,
|
||||||
\ mr,
|
\ mr,
|
||||||
\ get(dict, 'delimiter_align', get(g:, 'easy_align_delimiter_align', 'r')),
|
\ get(dict, 'delimiter_align', get(g:, 'easy_align_delimiter_align', 'r'))[0],
|
||||||
\ get(dict, 'indentation', get(g:, 'easy_align_indentation', 'k')),
|
\ get(dict, 'indentation', get(g:, 'easy_align_indentation', 'k'))[0],
|
||||||
\ get(dict, 'stick_to_left', 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', 1)),
|
||||||
\ get(dict, 'ignores', s:ignored_syntax()),
|
\ get(dict, 'ignore_groups', get(dict, 'ignores', s:ignored_syntax())),
|
||||||
\ recur)
|
\ recur)
|
||||||
call s:echon(mode, n, regexp ? '/'.ch.'/' : ch)
|
call s:echon(mode, n, regexp ? '/'.ch.'/' : ch, iopts)
|
||||||
catch 'exit'
|
catch 'exit'
|
||||||
endtry
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
|||||||
@@ -116,21 +116,7 @@ You can even omit spaces between the arguments, so concisely (or cryptically):
|
|||||||
|
|
||||||
- :EasyAlign*/[:;]\+/{'s':1,'l':''}
|
- :EasyAlign*/[:;]\+/{'s':1,'l':''}
|
||||||
|
|
||||||
Available options are as follows.
|
Available options will be shown later in the document.
|
||||||
|
|
||||||
| Atrribute | Type | Default |
|
|
||||||
| ---------------- | ---------------- | ----------------------------- |
|
|
||||||
| left_margin | number or string | 0 |
|
|
||||||
| right_margin | number or string | 0 |
|
|
||||||
| stick_to_left | boolean | 0 |
|
|
||||||
| ignore_unmatched | boolean | 1 |
|
|
||||||
| ignores | array | ['String', 'Comment'] |
|
|
||||||
| delimiter_align | string | 'r' |
|
|
||||||
| | | (right, left, center) |
|
|
||||||
| indentation | string | 'k' |
|
|
||||||
| | | (keep, shallow, deep, none) |
|
|
||||||
| mode_sequence | string | (Depends on field number and |
|
|
||||||
| | | selected alignment mode) |
|
|
||||||
|
|
||||||
|
|
||||||
Partial alignment in blockwise-visual mode
|
Partial alignment in blockwise-visual mode
|
||||||
@@ -140,7 +126,50 @@ 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.
|
||||||
|
|
||||||
|
|
||||||
Ignoring delimiters in comments or strings *g:easy_align_ignores*
|
Alignment options
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Available options are as follows.
|
||||||
|
|
||||||
|
| Atrribute | Type | Default |
|
||||||
|
| ---------------- | ---------------- | ----------------------------- |
|
||||||
|
| left_margin | number or string | 0 |
|
||||||
|
| right_margin | number or string | 0 |
|
||||||
|
| stick_to_left | boolean | 0 |
|
||||||
|
| ignore_unmatched | boolean | 1 |
|
||||||
|
| ignore_groups | array | ['String', 'Comment'] |
|
||||||
|
| delimiter_align | string | 'r' |
|
||||||
|
| | | (right, left, center) |
|
||||||
|
| indentation | string | 'k' |
|
||||||
|
| | | (keep, shallow, deep, none) |
|
||||||
|
| mode_sequence | string | (Depends on field number and |
|
||||||
|
| | | selected alignment mode) |
|
||||||
|
|
||||||
|
|
||||||
|
Some of the options can be specified using corresponding global variables.
|
||||||
|
|
||||||
|
| Option | Global variable |
|
||||||
|
| ------------------ | ------------------------------- |
|
||||||
|
| ignore_groups | `g:easy_align_ignore_groups` |
|
||||||
|
| ignore_unmatched | `g:easy_align_ignore_unmatched` |
|
||||||
|
| delimiter_align | `g:easy_align_delimiter_align` |
|
||||||
|
| indentation | `g:easy_align_indentation` |
|
||||||
|
|
||||||
|
|
||||||
|
In interactive mode, you can switch some of the alignment options using special
|
||||||
|
keys listed below.
|
||||||
|
|
||||||
|
| Key | Option | Values |
|
||||||
|
| ------ | ---------------- | -------------------------------------------------- |
|
||||||
|
| CTRL-I | indentation | shallow, deep, none, keep |
|
||||||
|
| CTRL-L | left_margin | Input number or string |
|
||||||
|
| CTRL-R | right_margin | Input number or string |
|
||||||
|
| CTRL-D | delimiter_align | left, center, right |
|
||||||
|
| CTRL-U | ignore_unmatched | 0, 1 |
|
||||||
|
| CTRL-G | ignore_groups | [], ['String'], ['Comment'], ['String', 'Comment'] |
|
||||||
|
|
||||||
|
|
||||||
|
Ignoring delimiters in comments or strings *g:easy_align_ignore_groups*
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
|
|
||||||
EasyAlign can be configured to ignore delimiters in certain syntax
|
EasyAlign can be configured to ignore delimiters in certain syntax
|
||||||
@@ -150,7 +179,7 @@ that are highlighted as code comments or strings are ignored.
|
|||||||
" Default:
|
" Default:
|
||||||
" If a delimiter is in a highlight group whose name matches
|
" If a delimiter is in a highlight group whose name matches
|
||||||
" any of the followings, it will be ignored.
|
" any of the followings, it will be ignored.
|
||||||
let g:easy_align_ignores = ['Comment', 'String']
|
let g:easy_align_ignore_groups = ['Comment', 'String']
|
||||||
|
|
||||||
For example, the following paragraph
|
For example, the following paragraph
|
||||||
|
|
||||||
@@ -176,13 +205,15 @@ becomes as follows on '<Enter>:' (or `:EasyAlign:`)
|
|||||||
|
|
||||||
Naturally, this feature only works when syntax highlighting is enabled.
|
Naturally, this feature only works when syntax highlighting is enabled.
|
||||||
|
|
||||||
You can change the default rule by using one of these 3 methods.
|
You can change the default rule by using one of these 4 methods.
|
||||||
|
|
||||||
1. Define global `g:easy_align_ignores` list
|
1. Press CTRL-G in interactive mode to switch groups
|
||||||
2. Define a custom rule in `g:easy_align_delimiters` with 'ignores' option
|
2. Define global `g:easy_align_ignore_groups` list
|
||||||
3. Provide 'ignores' option to `:EasyAlign` command. e.g. :EasyAlign:{'is':[]}
|
3. Define a custom rule in `g:easy_align_delimiters` with 'ignore_groups' option
|
||||||
|
4. Provide 'ignore_groups' option to `:EasyAlign` command.
|
||||||
|
e.g. :EasyAlign:{'is':[]}
|
||||||
|
|
||||||
For example if you set 'ignores' option to be an empty list, you get
|
For example if you set 'ignore_groups' option to be an empty list, you get
|
||||||
|
|
||||||
{
|
{
|
||||||
# Quantity of apples: 1
|
# Quantity of apples: 1
|
||||||
@@ -220,12 +251,13 @@ this is usually what we want.
|
|||||||
grapefruits: 3
|
grapefruits: 3
|
||||||
}
|
}
|
||||||
|
|
||||||
However, this default behavior is also configurable by using one of these 3
|
However, this default behavior is also configurable by using one of these 4
|
||||||
methods.
|
methods.
|
||||||
|
|
||||||
1. Set the global `g:easy_align_ignore_unmatched` variable to 0
|
1. Press CTRL-U in interactive mode to toggle 'ignore_unmatched' option
|
||||||
2. Define a custom alignment rule with 'ignore_unmatched' option set to 0
|
2. Set the global `g:easy_align_ignore_unmatched` variable to 0
|
||||||
3. Provide 'ignore_unmatched' option to `:EasyAlign` command.
|
3. Define a custom alignment rule with 'ignore_unmatched' option set to 0
|
||||||
|
4. Provide 'ignore_unmatched' option to `:EasyAlign` command.
|
||||||
e.g. :EasyAlign:{'iu':0}
|
e.g. :EasyAlign:{'iu':0}
|
||||||
|
|
||||||
Then we get,
|
Then we get,
|
||||||
@@ -268,6 +300,8 @@ And on ':EasyAlign={'da':c}', center-aligned.
|
|||||||
banana += apple
|
banana += apple
|
||||||
cake ||= banana
|
cake ||= banana
|
||||||
|
|
||||||
|
In interactive mode, you can change the option value with `CTRL-D` key.
|
||||||
|
|
||||||
|
|
||||||
Adjusting indentation *g:easy_align_indentation*
|
Adjusting indentation *g:easy_align_indentation*
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
@@ -317,6 +351,8 @@ But then again we have 'indentation' option. See the following example.
|
|||||||
|
|
||||||
Notice that 'idt' is fuzzy-matched to 'indentation'.
|
Notice that 'idt' is fuzzy-matched to 'indentation'.
|
||||||
|
|
||||||
|
In interactive mode, you can change the option value with `CTRL-I` key.
|
||||||
|
|
||||||
|
|
||||||
Left/right/center mode switch in interactive mode
|
Left/right/center mode switch in interactive mode
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
@@ -396,8 +432,8 @@ you can extend the rules by setting a dictionary named
|
|||||||
|
|
||||||
let g:easy_align_delimiters = {
|
let g:easy_align_delimiters = {
|
||||||
\ '>': { 'pattern': '>>\|=>\|>' },
|
\ '>': { 'pattern': '>>\|=>\|>' },
|
||||||
\ '/': { 'pattern': '//\+\|/\*\|\*/', 'ignores': ['String'] },
|
\ '/': { 'pattern': '//\+\|/\*\|\*/', 'ignore_groups': ['String'] },
|
||||||
\ '#': { 'pattern': '#\+', 'ignores': ['String'] },
|
\ '#': { 'pattern': '#\+', 'ignore_groups': ['String'] },
|
||||||
\ ']': {
|
\ ']': {
|
||||||
\ 'pattern': '[[\]]',
|
\ 'pattern': '[[\]]',
|
||||||
\ 'left_margin': 0,
|
\ 'left_margin': 0,
|
||||||
|
|||||||
@@ -104,6 +104,56 @@ j, , k
|
|||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
|
|
||||||
|
a =
|
||||||
|
a = 1
|
||||||
|
bbbb = 2
|
||||||
|
ccccccc = 3
|
||||||
|
ccccccccccccccc
|
||||||
|
ddd = #
|
||||||
|
eeee === eee = eee = eee = f
|
||||||
|
fff = ggg += gg &&= gg
|
||||||
|
g != hhhhhhhh == # 8
|
||||||
|
i := 5
|
||||||
|
i %= 5
|
||||||
|
i *= 5
|
||||||
|
j =~ 5
|
||||||
|
j >= 5
|
||||||
|
aa => 123
|
||||||
|
aa <<= 123
|
||||||
|
aa >>= 123
|
||||||
|
bbb => 123
|
||||||
|
c => 1233123
|
||||||
|
d => 123
|
||||||
|
dddddd &&= 123
|
||||||
|
dddddd ||= 123
|
||||||
|
dddddd /= 123
|
||||||
|
gg <=> ee
|
||||||
|
|
||||||
|
a =
|
||||||
|
a = 1
|
||||||
|
bbbb = 2
|
||||||
|
ccccccc = 3
|
||||||
|
ccccccccccccccc
|
||||||
|
ddd = #
|
||||||
|
eeee === eee = eee = eee = f
|
||||||
|
fff = ggg += gg &&= gg
|
||||||
|
g != hhhhhhhh == # 8
|
||||||
|
i := 5
|
||||||
|
i %= 5
|
||||||
|
i *= 5
|
||||||
|
j =~ 5
|
||||||
|
j >= 5
|
||||||
|
aa => 123
|
||||||
|
aa <<= 123
|
||||||
|
aa >>= 123
|
||||||
|
bbb => 123
|
||||||
|
c => 1233123
|
||||||
|
d => 123
|
||||||
|
dddddd &&= 123
|
||||||
|
dddddd ||= 123
|
||||||
|
dddddd /= 123
|
||||||
|
gg <=> ee
|
||||||
|
|
||||||
a =
|
a =
|
||||||
a = 1
|
a = 1
|
||||||
bbbb = 2
|
bbbb = 2
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
4Gvipjyvip
|
4Gvipjyvip
|
||||||
|
|||||||
Reference in New Issue
Block a user