mirror of
https://github.com/junegunn/vim-easy-align.git
synced 2025-11-09 18:33:49 -05:00
Usability improvements
- Preserve indentation when a line starts with a delimiter
- Useful for aligning multi-line method chains
- Renamed `margin_{left,right}` to `{left,right}_margin
- Makes it easier to type in (`l`, `r`)
- `margin_{left,right}` is still supported
- Margins can be specified as the number of spaces, or as an arbitrary string
This commit is contained in:
25
EXAMPLES.md
25
EXAMPLES.md
@@ -141,6 +141,31 @@ mysql:
|
||||
|
||||
```
|
||||
|
||||
Formatting multi-line method chaining
|
||||
-------------------------------------
|
||||
|
||||
Try `<Enter>.` or `<Enter>*.` on the following lines.
|
||||
|
||||
```ruby
|
||||
my_object
|
||||
.method1().chain()
|
||||
.second_method().call()
|
||||
.third().call()
|
||||
.method_4().execute()
|
||||
```
|
||||
|
||||
Notice that the indentation is adjusted to match the shortest one among those of
|
||||
the lines starting with the delimiter.
|
||||
|
||||
```ruby
|
||||
my_object
|
||||
.method1() .chain()
|
||||
.second_method().call()
|
||||
.third() .call()
|
||||
.method_4() .execute()
|
||||
```
|
||||
|
||||
|
||||
Partial alignment in block-visual mode / Negative field index
|
||||
-------------------------------------------------------------
|
||||
|
||||
|
||||
28
README.md
28
README.md
@@ -127,7 +127,7 @@ 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, 'margin_left': '' }`
|
||||
- `:EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'left_margin': '' }`
|
||||
|
||||
Then we get:
|
||||
|
||||
@@ -136,21 +136,21 @@ Then we get:
|
||||
|
||||
Options keys are fuzzy-matched, so you can write as follows:
|
||||
|
||||
- `:EasyAlign * /[:;]\+/ { 'stl': 1, 'ml': '' }`
|
||||
- `:EasyAlign * /[:;]\+/ { 'stl': 1, 'l': 0 }`
|
||||
|
||||
You can even omit spaces between the arguments, so concisely (or cryptically):
|
||||
|
||||
- `:EasyAlign*/[:;]\+/{'stl':1,'ml':''}`
|
||||
- `:EasyAlign*/[:;]\+/{'s':1,'l':0}`
|
||||
|
||||
Available options for each alignment are as follows.
|
||||
|
||||
| Atrribute | Type | Default |
|
||||
| ---------------- | ------- | ----------------------- |
|
||||
| margin_left | string | `' '` |
|
||||
| margin_right | string | `' '` |
|
||||
| stick_to_left | boolean | 0 |
|
||||
| ignore_unmatched | boolean | 1 |
|
||||
| ignores | array | `['String', 'Comment']` |
|
||||
| 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']` |
|
||||
|
||||
(The last two options will be described shortly in the following sections.)
|
||||
|
||||
@@ -331,14 +331,14 @@ let g:easy_align_delimiters = {
|
||||
\ '#': { 'pattern': '#\+', 'ignores': ['String'] },
|
||||
\ ']': {
|
||||
\ 'pattern': '[\[\]]',
|
||||
\ 'margin_left': '',
|
||||
\ 'margin_right': '',
|
||||
\ 'left_margin': 0,
|
||||
\ 'right_margin': 0,
|
||||
\ 'stick_to_left': 0
|
||||
\ },
|
||||
\ ')': {
|
||||
\ 'pattern': '[()]',
|
||||
\ 'margin_left': '',
|
||||
\ 'margin_right': '',
|
||||
\ 'left_margin': 0,
|
||||
\ 'right_margin': 0,
|
||||
\ 'stick_to_left': 0
|
||||
\ }
|
||||
\ }
|
||||
|
||||
@@ -27,23 +27,24 @@ endif
|
||||
let g:loaded_easy_align = 1
|
||||
|
||||
let s:easy_align_delimiters_default = {
|
||||
\ ' ': { 'pattern': ' ', 'margin_left': '', 'margin_right': '', 'stick_to_left': 0 },
|
||||
\ ' ': { 'pattern': ' ', 'left_margin': '', 'right_margin': '', 'stick_to_left': 0 },
|
||||
\ '=': { 'pattern': '===\|<=>\|\(&&\|||\|<<\|>>\)=\|=\~\|=>\|[:+/*!%^=><&|-]\?=[#?]\?',
|
||||
\ 'margin_left': ' ', 'margin_right': ' ', 'stick_to_left': 0 },
|
||||
\ ':': { 'pattern': ':', 'margin_left': '', 'margin_right': ' ', 'stick_to_left': 1 },
|
||||
\ ',': { 'pattern': ',', 'margin_left': '', 'margin_right': ' ', 'stick_to_left': 1 },
|
||||
\ '|': { 'pattern': '|', 'margin_left': ' ', 'margin_right': ' ', 'stick_to_left': 0 },
|
||||
\ '.': { 'pattern': '\.', 'margin_left': '', 'margin_right': '', 'stick_to_left': 0 },
|
||||
\ 'left_margin': ' ', 'right_margin': ' ', 'stick_to_left': 0 },
|
||||
\ ':': { 'pattern': ':', 'left_margin': '', 'right_margin': ' ', 'stick_to_left': 1 },
|
||||
\ ',': { 'pattern': ',', 'left_margin': '', 'right_margin': ' ', 'stick_to_left': 1 },
|
||||
\ '|': { 'pattern': '|', 'left_margin': ' ', 'right_margin': ' ', 'stick_to_left': 0 },
|
||||
\ '.': { 'pattern': '\.', 'left_margin': '', 'right_margin': '', 'stick_to_left': 0 },
|
||||
\ '{': { 'pattern': '(\@<!{',
|
||||
\ 'margin_left': ' ', 'margin_right': ' ', 'stick_to_left': 0 },
|
||||
\ '}': { 'pattern': '}', 'margin_left': ' ', 'margin_right': '', 'stick_to_left': 0 }
|
||||
\ 'left_margin': ' ', 'right_margin': ' ', 'stick_to_left': 0 },
|
||||
\ '}': { 'pattern': '}', 'left_margin': ' ', 'right_margin': '', 'stick_to_left': 0 }
|
||||
\ }
|
||||
|
||||
let s:just = ['', '[R]']
|
||||
|
||||
let s:known_options = {
|
||||
\ 'pattern': 1, 'margin_left': 1, 'margin_right': 1, 'stick_to_left': 0,
|
||||
\ 'ignores': 3, 'ignore_unmatched': 0
|
||||
\ 'pattern': [1], 'margin_left': [0, 1], 'margin_right': [0, 1], 'stick_to_left': [0],
|
||||
\ 'left_margin': [0, 1], 'right_margin': [0, 1],
|
||||
\ 'ignores': [3], 'ignore_unmatched': [0]
|
||||
\ }
|
||||
|
||||
if exists("*strwidth")
|
||||
@@ -101,7 +102,7 @@ function! s:fuzzy_lu(key)
|
||||
return a:key
|
||||
endif
|
||||
|
||||
let regexp = '^' . substitute(a:key, '\(.\)', '\1.*', 'g')
|
||||
let regexp = '^' . substitute(substitute(a:key, '-', '_', 'g'), '\(.\)', '\1.*', 'g')
|
||||
let matches = filter(keys(s:known_options), 'v:val =~ regexp')
|
||||
|
||||
if empty(matches)
|
||||
@@ -116,14 +117,18 @@ endfunction
|
||||
function! s:normalize_options(opts)
|
||||
let ret = {}
|
||||
for [k, v] in items(a:opts)
|
||||
let ret[s:fuzzy_lu(k)] = v
|
||||
let k = s:fuzzy_lu(k)
|
||||
" Backward-compatibility
|
||||
if k == 'margin_left' | let k = 'left_margin' | endif
|
||||
if k == 'margin_right' | let k = 'right_margin' | endif
|
||||
let ret[k] = v
|
||||
endfor
|
||||
return s:validate_options(ret)
|
||||
endfunction
|
||||
|
||||
function! s:validate_options(opts)
|
||||
for [k, v] in items(a:opts)
|
||||
if type(v) != s:known_options[k]
|
||||
if index(s:known_options[k], type(v)) == -1
|
||||
call s:exit("Invalid type for option: ". k)
|
||||
endif
|
||||
endfor
|
||||
@@ -135,6 +140,7 @@ function! s:do_align(just, all_tokens, fl, ll, fc, lc, pattern, nth, ml, mr, sti
|
||||
let max_just_len = 0
|
||||
let max_delim_len = 0
|
||||
let max_tokens = 0
|
||||
let min_indent = -1
|
||||
let pattern = '\s*\(' .a:pattern. '\)\s' . (a:stick_to_left ? '*' : '\{-}')
|
||||
|
||||
" Phase 1
|
||||
@@ -212,6 +218,10 @@ function! s:do_align(just, all_tokens, fl, ll, fc, lc, pattern, nth, ml, mr, sti
|
||||
continue
|
||||
endif
|
||||
|
||||
let indent = len(matchstr(tokens[0], '^\s\+'))
|
||||
if min_indent < 0 || indent < min_indent
|
||||
let min_indent = indent
|
||||
endif
|
||||
let max_just_len = max([s:strwidth(prefix.token), max_just_len])
|
||||
let max_delim_len = max([s:strwidth(delim), max_delim_len])
|
||||
let lines[line] = [nth, prefix, token, delim]
|
||||
@@ -260,8 +270,19 @@ function! s:do_align(just, all_tokens, fl, ll, fc, lc, pattern, nth, ml, mr, sti
|
||||
let mr = (empty(rest) ||
|
||||
\ (empty(rest) && stridx(after, a:mr) == 0)) ? '' : a:mr
|
||||
|
||||
" Adjust indentation of the lines starting with a delimiter
|
||||
let lpad = ''
|
||||
if nth == 0
|
||||
let ipad = repeat(' ', min_indent - len(strpart(before.token, '^\s\+').ml))
|
||||
if a:just == 0
|
||||
let token = ipad . token
|
||||
else
|
||||
let lpad = ipad
|
||||
endif
|
||||
endif
|
||||
|
||||
" Align the token
|
||||
let aligned = join([token, ml, delim, mr, rpad], '')
|
||||
let aligned = join([lpad, token, ml, delim, mr, rpad], '')
|
||||
let tokens[nth] = aligned
|
||||
|
||||
" Update the line
|
||||
@@ -431,13 +452,18 @@ function! easy_align#align(just, expr) range
|
||||
return
|
||||
endtry
|
||||
|
||||
let ml = get(dict, 'left_margin', ' ')
|
||||
let mr = get(dict, 'right_margin', ' ')
|
||||
if type(ml) == 0 | let ml = repeat(' ', ml) | endif
|
||||
if type(mr) == 0 | let mr = repeat(' ', mr) | endif
|
||||
|
||||
call s:do_align(just, {}, a:firstline, a:lastline,
|
||||
\ visualmode() == '' ? min([col("'<"), col("'>")]) : 1,
|
||||
\ visualmode() == '' ? max([col("'<"), col("'>")]) : 0,
|
||||
\ get(dict, 'pattern', ch),
|
||||
\ nth,
|
||||
\ get(dict, 'margin_left', ' '),
|
||||
\ get(dict, 'margin_right', ' '),
|
||||
\ ml,
|
||||
\ mr,
|
||||
\ get(dict, 'stick_to_left', 0),
|
||||
\ get(dict, 'ignore_unmatched', get(g:, 'easy_align_ignore_unmatched', 1)),
|
||||
\ get(dict, 'ignores', s:ignored_syntax()),
|
||||
|
||||
@@ -95,7 +95,7 @@ try these commands:
|
||||
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.
|
||||
|
||||
- :EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'margin_left': '' }
|
||||
- :EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'left_margin': '' }
|
||||
|
||||
Then we get:
|
||||
|
||||
@@ -104,21 +104,21 @@ Then we get:
|
||||
|
||||
Options keys are fuzzy-matched, so you can write as follows:
|
||||
|
||||
- :EasyAlign * /[:;]\+/ { 'stl': 1, 'ml': '' }
|
||||
- :EasyAlign * /[:;]\+/ { 'stl': 1, 'l': '' }
|
||||
|
||||
You can even omit spaces between the arguments, so concisely (or cryptically):
|
||||
|
||||
- :EasyAlign*/[:;]\+/{'stl':1,'ml':''}
|
||||
- :EasyAlign*/[:;]\+/{'s':1,'l':''}
|
||||
|
||||
Available options for each alignment are as follows.
|
||||
|
||||
| Atrribute | Type | Default |
|
||||
| ---------------- | ------- | ----------------------- |
|
||||
| margin_left | string | `' '` |
|
||||
| margin_right | string | `' '` |
|
||||
| stick_to_left | boolean | 0 |
|
||||
| ignore_unmatched | boolean | 1 |
|
||||
| ignores | array | `['String', 'Comment']` |
|
||||
| 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']` |
|
||||
|
||||
|
||||
Partial alignment in blockwise-visual mode
|
||||
@@ -231,14 +231,14 @@ Extending alignment rules *g:easy_align_delimiters*
|
||||
\ '#': { 'pattern': '#\+' },
|
||||
\ ']': {
|
||||
\ 'pattern': '[\[\]]',
|
||||
\ 'margin_left': '',
|
||||
\ 'margin_right': '',
|
||||
\ 'left_margin': 0,
|
||||
\ 'right_margin': 0,
|
||||
\ 'stick_to_left': 0
|
||||
\ },
|
||||
\ ')': {
|
||||
\ 'pattern': '[()]',
|
||||
\ 'margin_left': '',
|
||||
\ 'margin_right': '',
|
||||
\ 'left_margin': 0,
|
||||
\ 'right_margin': 0,
|
||||
\ 'stick_to_left': 0
|
||||
\ }
|
||||
\ }
|
||||
|
||||
@@ -257,3 +257,102 @@ aa >= bb
|
||||
aaaaa /* bbbbb */ == ccccc /* != eeeee = */ === fffff
|
||||
|
||||
```
|
||||
|
||||
my_object
|
||||
.method1 .chain
|
||||
.second_method.call
|
||||
.third .call
|
||||
.method_4 .execute
|
||||
|
||||
my_object
|
||||
.method1 . chain
|
||||
.second_method. call
|
||||
.third . call
|
||||
.method_4 .execute
|
||||
|
||||
my_object
|
||||
. method1.chain
|
||||
.second_method.call
|
||||
. third.call
|
||||
. method_4.execute
|
||||
|
||||
my_object
|
||||
. method1.chain
|
||||
.second_method.call
|
||||
. third.call
|
||||
. method_4.execute
|
||||
|
||||
my_object
|
||||
. method1. chain
|
||||
.second_method. call
|
||||
. third. call
|
||||
. method_4.execute
|
||||
|
||||
my_object
|
||||
.method1 .chain
|
||||
.second_method.call
|
||||
.third .call
|
||||
.method_4 .execute
|
||||
|
||||
my_object
|
||||
.method1.chain
|
||||
.second_method.call
|
||||
.third.call
|
||||
.method_4.execute
|
||||
|
||||
my_object .
|
||||
method1 .chain.
|
||||
second_method.call.
|
||||
third .call.
|
||||
method_4 .execute
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| -- | -- | -- | -- |
|
||||
| threads | Fixnum | 1 | number of threads in the thread pool |
|
||||
| queues | Fixnum | 1 | number of concurrent queues |
|
||||
| queue_size | Fixnum | 1000 | size of each queue |
|
||||
| interval | Numeric | 0 | dispatcher interval for batch processing |
|
||||
| batch | Boolean | false | enables batch processing mode |
|
||||
| batch_size | Fixnum | nil | number of maximum items to be assigned at once |
|
||||
| logger | Logger | nil | logger instance for debug logs |
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| -- | -- | -- | -- |
|
||||
| threads | Fixnum | 1 | number of threads in the thread pool |
|
||||
| queues | Fixnum | 1 | number of concurrent queues |
|
||||
| queue_size | Fixnum | 1000 | size of each queue |
|
||||
| interval | Numeric | 0 | dispatcher interval for batch processing |
|
||||
| batch | Boolean | false | enables batch processing mode |
|
||||
| batch_size | Fixnum | nil | number of maximum items to be assigned at once |
|
||||
| logger | Logger | nil | logger instance for debug logs |
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| -- | -- | -- | -- |
|
||||
| threads | Fixnum | 1 | number of threads in the thread pool |
|
||||
| queues | Fixnum | 1 | number of concurrent queues |
|
||||
| queue_size | Fixnum | 1000 | size of each queue |
|
||||
| interval | Numeric | 0 | dispatcher interval for batch processing |
|
||||
| batch | Boolean | false | enables batch processing mode |
|
||||
| batch_size | Fixnum | nil | number of maximum items to be assigned at once |
|
||||
| logger | Logger | nil | logger instance for debug logs |
|
||||
|
||||
|Option |Type |Default |Description |
|
||||
|-- |-- |-- |-- |
|
||||
|threads |Fixnum |1 |number of threads in the thread pool |
|
||||
|queues |Fixnum |1 |number of concurrent queues |
|
||||
|queue_size |Fixnum |1000 |size of each queue |
|
||||
|interval |Numeric |0 |dispatcher interval for batch processing |
|
||||
|batch |Boolean |false |enables batch processing mode |
|
||||
|batch_size |Fixnum |nil |number of maximum items to be assigned at once |
|
||||
|logger |Logger |nil |logger instance for debug logs |
|
||||
|
||||
| Option <| Type <| Default<| Description <|
|
||||
| -- <| -- <| -- <| -- <|
|
||||
| threads <| Fixnum <| 1 <| number of threads in the thread pool <|
|
||||
| queues <| Fixnum <| 1 <| number of concurrent queues <|
|
||||
| queue_size<| Fixnum <| 1000 <| size of each queue <|
|
||||
| interval <| Numeric<| 0 <| dispatcher interval for batch processing <|
|
||||
| batch <| Boolean<| false <| enables batch processing mode <|
|
||||
| batch_size<| Fixnum <| nil <| number of maximum items to be assigned at once<|
|
||||
| logger <| Logger <| nil <| logger instance for debug logs <|
|
||||
|
||||
|
||||
@@ -84,3 +84,26 @@ aa >= bb
|
||||
aaaaa /* bbbbb */ == ccccc /* != eeeee = */ === fffff
|
||||
|
||||
```
|
||||
|
||||
my_object
|
||||
.method1.chain
|
||||
.second_method.call
|
||||
.third.call
|
||||
.method_4.execute
|
||||
|
||||
my_object.
|
||||
method1.chain.
|
||||
second_method.call.
|
||||
third.call.
|
||||
method_4.execute
|
||||
|
||||
| Option| Type | Default | Description |
|
||||
|--|--|--|--|
|
||||
| threads | Fixnum | 1 | number of threads in the thread pool |
|
||||
|queues |Fixnum | 1 | number of concurrent queues |
|
||||
|queue_size | Fixnum | 1000 | size of each queue |
|
||||
| interval | Numeric | 0 | dispatcher interval for batch processing |
|
||||
|batch | Boolean | false | enables batch processing mode |
|
||||
|batch_size | Fixnum | nil | number of maximum items to be assigned at once |
|
||||
|logger | Logger | nil | logger instance for debug logs |
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
4Gvipjyvip
|
||||
4Gvipjyvip
|
||||
|
||||
@@ -1 +1 @@
|
||||
4Gvipjyvip:EasyAlign:
|
||||
4Gvipjyvip:EasyAlign:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
source include.vim
|
||||
e!
|
||||
execute 'source '. expand('%:p:h') . '/include.vim'
|
||||
|
||||
while line('.') < line('$')
|
||||
normal 30j
|
||||
@@ -6,7 +7,7 @@ while line('.') < line('$')
|
||||
endwhile
|
||||
|
||||
normal gg
|
||||
let @b=system('cat '. expand('%:r') . '.script')
|
||||
let @a='@b:vert diffsplit ' . expand('%:r') . '.expected
|
||||
let @b=system('cat '. expand('%:p:r') . '.script')
|
||||
let @a='@b:vert diffsplit ' . expand('%:p:r') . '.expected
|
||||
'
|
||||
" Syntax highlighting doesn't work
|
||||
|
||||
Reference in New Issue
Block a user