Add support for arbitrary regular expressions

This commit is contained in:
Junegunn Choi
2013-08-04 11:22:40 +09:00
parent 057be51067
commit bd8327499a
14 changed files with 884 additions and 103 deletions

1
.gitattributes vendored
View File

@@ -3,3 +3,4 @@
doc/tags export-ignore doc/tags export-ignore
*.md export-ignore *.md export-ignore
zip export-ignore zip export-ignore
test export-ignore

View File

@@ -1,6 +1,12 @@
vim-easy-align examples vim-easy-align examples
======================= =======================
The description in this document assumes that you have defined this mapping.
```vim
vnoremap <silent> <Enter> :EasyAlign<cr>
```
To enable syntax highlighting in the code blocks, define and call the following To enable syntax highlighting in the code blocks, define and call the following
function. function.
@@ -26,6 +32,19 @@ endfunction
Alignment around whitespaces Alignment around whitespaces
---------------------------- ----------------------------
You can align text around whitespaces with `<space>` delimiter key.
Try these commands:
- `<Enter><space>`
- `<Enter>2<space>`
- `<Enter>*<space>`
- `<Enter>-<space>`
- `<Enter>-2<space>`
- `<Enter><Enter><space>`
- `<Enter><Enter>*<space>`
### Example
``` ```
Paul McCartney 1942 Paul McCartney 1942
@@ -38,7 +57,13 @@ Pete Best 1941
Formatting table Formatting table
---------------- ----------------
Try `<Enter>*|` Try these commands:
- `<Enter>*|`
- `<Enter>**|`
- `<Enter><Enter>*|`
- `<Enter><Enter>**|`
### Example
``` ```
@@ -58,15 +83,17 @@ Try `<Enter>*|`
Alignment around = Alignment around =
------------------ ------------------
The default rule for delimiter key `=` aligns around the most of the operators The default rule for delimiter key `=` aligns around a whole family of operators
containing `=` character. containing `=` character.
Try: Try these commands:
- `<Enter>=` - `<Enter>=`
- `<Enter>*=` - `<Enter>*=`
- `<Enter>**=` - `<Enter>**=`
- `<Enter><Enter>**=` - `<Enter><Enter>**=`
### Example
```ruby ```ruby
a = a =
@@ -106,17 +133,21 @@ In this case, you don't want to align around all the colons: `<Enter>*:`.
mysql: mysql:
# JDBC driver for MySQL database: # JDBC driver for MySQL database:
driver: com.mysql.jdbc.Driver driver: com.mysql.jdbc.Driver
# JDBC URL for the connection (jdbc:mysql://HOSTNAME/DATABASE) # JDBC URL for the connection (jdbc:mysql://HOSTNAME/DATABASE)
url: jdbc:mysql://localhost/test url: jdbc:mysql://localhost/test
database: test database: test
"user:pass": r00t:pa55 "user:pass":r00t:pa55
``` ```
Partial alignment in block-visual mode / Negative field index Partial alignment in block-visual mode / Negative field index
------------------------------------------------------------- -------------------------------------------------------------
You can try one of these:
- Select text around `=>` in block-wise visual mode (`<Ctrl>-V`) and `<Enter>=`
- `<Enter>-=`
```ruby ```ruby
options = { :caching => nil, options = { :caching => nil,
@@ -145,7 +176,7 @@ Ignoring delimiters in comments and strings
------------------------------------------- -------------------------------------------
Delimiters highlighted as comments or strings are ignored by default, try Delimiters highlighted as comments or strings are ignored by default, try
`<Enter>*=` for the following lines. `<Enter>*=` on the following lines.
```c ```c
@@ -162,7 +193,7 @@ Aligning in-line comments
```ruby ```ruby
apple = 1 # comment not aligned apple = 1 # comment not aligned
banana = "string" # comment 2 banana = 'Gros Michel' # comment 2
``` ```
So, how do we align the trailing comments in the above lines? So, how do we align the trailing comments in the above lines?
@@ -173,12 +204,14 @@ But this doesn't work in the following case.
```ruby ```ruby
apple = 1 # comment not aligned apple = 1 # comment not aligned
apricot = 'A#B' apricot = 'DAD' + 'F#AD'
banana = 'string' # comment 2 banana = 'Gros Michel' # comment 2
``` ```
The second line doesn't have trailing comment, and *the last space* is the one That is because the second line doesn't have trailing comment, and
before `'A#B'`. So we define a custom mapping for `#` the last space (`-`) for that line is the one just before `'F#AD'`.
So, let's define a custom mapping for `#`.
```vim ```vim
if !exists('g:easy_align_delimiters') if !exists('g:easy_align_delimiters')
@@ -187,8 +220,10 @@ endif
let g:easy_align_delimiters['#'] = { 'pattern': '#\+', 'ignores': ['String'] } } let g:easy_align_delimiters['#'] = { 'pattern': '#\+', 'ignores': ['String'] } }
``` ```
Notice that the rule overrides `ignores` attribute in order *not* to ignore Notice that the rule overrides `ignores` attribute in order *not to ignore*
delimiters highlighted as comments. Then we try `<Enter>#`, to get delimiters highlighted as comments.
Then on `<Enter>#`, we get
```ruby ```ruby
apple = 1 # comment not aligned apple = 1 # comment not aligned

View File

@@ -14,6 +14,7 @@ Features
- Optimized for code editing - Optimized for code editing
- Designed to require minimal keystrokes - Designed to require minimal keystrokes
- Extensible alignment rules - Extensible alignment rules
- Supports arbitrary regular expressions
- Aligns text around either _all or n-th_ occurrence(s) of the delimiter - Aligns text around either _all or n-th_ occurrence(s) of the delimiter
- Ignores delimiters in certain syntax highlight groups (e.g. comments, strings) - Ignores delimiters in certain syntax highlight groups (e.g. comments, strings)
- Ignores lines without a matching delimiter - Ignores lines without a matching delimiter
@@ -34,7 +35,18 @@ Bundle 'junegunn/vim-easy-align'
Usage Usage
----- -----
_vim-easy-align_ defines interactive `:EasyAlign` command in the visual mode. _vim-easy-align_ defines `:EasyAlign` and `:EasyAlignRight` commands in the
visual mode.
| Mode | Command |
| ------------------------- | --------------------------------------------- |
| Interactive mode | `:EasyAlign` |
| Using predefined rules | `:EasyAlign [FIELD#] DELIMITER_KEY [OPTIONS]` |
| Using regular expressions | `:EasyAlign [FIELD#] /REGEXP/ [OPTIONS]` |
### Interactive mode
The commands will go into 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 a mapping for triggering it in
your `.vimrc`. your `.vimrc`.
@@ -68,7 +80,7 @@ Alignment rules for the following delimiters have been defined to meet the most
| `,` | Multi-line method arguments | | `,` | Multi-line method arguments |
| &#124; | Table markdown | | &#124; | Table markdown |
### Example command sequences #### Example command sequences
| With visual map | Description | Equivalent command | | With visual map | Description | Equivalent command |
| ------------------- | -------------------------------------------------------- | ------------------------- | | ------------------- | -------------------------------------------------------- | ------------------------- |
@@ -85,6 +97,62 @@ Alignment rules for the following delimiters have been defined to meet the most
| `<Enter><Enter>**=` | Right-left alternating alignment around all equals signs | `:'<,'>EasyAlignRight**=` | | `<Enter><Enter>**=` | Right-left alternating alignment around all equals signs | `:'<,'>EasyAlignRight**=` |
| ... | ... | | | ... | ... | |
### Non-interactive mode
Instead of going into the interactive mode, you can instead type in arguments to
`:EasyAlign` command. In non-interactive mode, you can even use arbitrary
regular expressions.
```vim
" Using predefined alignment rules
:EasyAlign [FIELD#] DELIMITER_KEY [OPTIONS]
" Using arbitrary regular expressions
:EasyAlign [FIELD#] /REGEXP/ [OPTIONS]
```
For example, when aligning the following lines around colons and semi-colons,
apple;:banana::cake
data;;exchange:;format
try these commands:
- `: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.
- `:EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'margin_left': '' }`
Then we get:
apple;: banana:: cake
data;; exchange:; format
Options keys are fuzzy-matched, so you can write as follows:
- `:EasyAlign * /[:;]\+/ { 'stl': 1, 'ml': '' }`
You can even omit spaces between the arguments, so concisely (or cryptically):
- `:EasyAlign*/[:;]\+/{'stl':1,'ml':''}`
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']` |
(The last two options will be described shortly in the following sections.)
### Partial alignment in blockwise-visual mode ### Partial alignment in blockwise-visual mode
In blockwise-visual mode (`CTRL-V`), EasyAlign command aligns only the selected In blockwise-visual mode (`CTRL-V`), EasyAlign command aligns only the selected
@@ -112,8 +180,8 @@ 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 field number: `<Enter>-=` since the same can be easily done using the negative field number: `<Enter>-=`
Options Global options
------- --------------
| Option | Type | Default | Description | | Option | Type | Default | Description |
| ----------------------------- | ---------- | --------------------- | -------------------------------------------------- | | ----------------------------- | ---------- | --------------------- | -------------------------------------------------- |
@@ -147,7 +215,7 @@ For example, the following paragraph
} }
``` ```
becomes as follows on `<Enter>:` becomes as follows on `<Enter>:` (or `:EasyAlign:`)
```ruby ```ruby
{ {
@@ -233,18 +301,8 @@ Then we get,
### Extending alignment rules ### Extending alignment rules
Although the default predefined rules should cover the most of the use cases, Although the default rules should cover the most of the use cases,
you can extend the rules by setting a dictionary named `g:easy_align_delimiters`. you can extend the rules by setting a dictionary named `g:easy_align_delimiters`.
Each entry in the dictionary can have the following attributes.
| Atrribute | Type | Default |
| ---------------- | ------- | --------------------- |
| pattern | regexp | |
| margin_left | string | `' '` |
| margin_right | string | `' '` |
| stick_to_left | boolean | 0 |
| ignore_unmatched | boolean | 1 |
| ignores | array | ['String', 'Comment'] |
#### Example #### Example

View File

@@ -41,6 +41,11 @@ let s:easy_align_delimiters_default = {
let s:just = ['', '[R]'] 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
\ }
if exists("*strwidth") if exists("*strwidth")
function! s:strwidth(str) function! s:strwidth(str)
return strwidth(a:str) return strwidth(a:str)
@@ -73,6 +78,58 @@ function! s:ignored_syntax()
endif endif
endfunction endfunction
function! s:echon(l, n, d)
echon "\r"
echon "\rEasyAlign". s:just[a:l] ." (" .a:n.a:d. ")"
endfunction
function! s:exit(msg)
echon "\r". a:msg
throw 'exit'
endfunction
function! s:ltrim(str)
return substitute(a:str, '^\s*', '', '')
endfunction
function! s:rtrim(str)
return substitute(a:str, '\s*$', '', '')
endfunction
function! s:fuzzy_lu(key)
if has_key(s:known_options, a:key)
return a:key
endif
let regexp = '^' . substitute(a:key, '\(.\)', '\1.*', 'g')
let matches = filter(keys(s:known_options), 'v:val =~ regexp')
if empty(matches)
call s:exit("Unknown option key: ". a:key)
elseif len(matches) == 1
return matches[0]
else
call s:exit("Ambiguous option key: ". a:key ." (" .join(matches, ', '). ")")
endif
endfunction
function! s:normalize_options(opts)
let ret = {}
for [k, v] in items(a:opts)
let ret[s:fuzzy_lu(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]
call s:exit("Invalid type for option: ". k)
endif
endfor
return a:opts
endfunction
function! s:do_align(just, all_tokens, fl, ll, fc, lc, pattern, nth, ml, mr, stick_to_left, ignore_unmatched, ignores, recursive) function! s:do_align(just, all_tokens, fl, ll, fc, lc, pattern, nth, ml, mr, stick_to_left, ignore_unmatched, ignores, recursive)
let lines = {} let lines = {}
let max_just_len = 0 let max_just_len = 0
@@ -167,7 +224,7 @@ function! s:do_align(just, all_tokens, fl, ll, fc, lc, pattern, nth, ml, mr, sti
" Remove the leading whitespaces of the next token " Remove the leading whitespaces of the next token
if len(tokens) > nth + 1 if len(tokens) > nth + 1
let tokens[nth + 1] = substitute(tokens[nth + 1], '^\s*', '', '') let tokens[nth + 1] = s:ltrim(tokens[nth + 1])
endif endif
" Pad the token with spaces " Pad the token with spaces
@@ -208,7 +265,7 @@ function! s:do_align(just, all_tokens, fl, ll, fc, lc, pattern, nth, ml, mr, sti
let tokens[nth] = aligned let tokens[nth] = aligned
" Update the line " Update the line
let newline = substitute(before.join(tokens, '').after, '\s*$', '', '') let newline = s:rtrim(before.join(tokens, '').after)
call setline(line, newline) call setline(line, newline)
endfor endfor
@@ -220,66 +277,123 @@ function! s:do_align(just, all_tokens, fl, ll, fc, lc, pattern, nth, ml, mr, sti
endif endif
endfunction endfunction
function! s:echon(l, n, d) function! s:interactive(just)
echon "\r" let just = a:just
echon "\rEasyAlign". s:just[a:l] ." (" .a:n.a:d. ")" let n = ''
let ch = ''
while 1
call s:echon(just, n, '')
let c = getchar()
let ch = nr2char(c)
if c == 3 || c == 27 " CTRL-C / ESC
throw 'exit'
elseif c == '<27>kb' " Backspace
if len(n) > 0
let n = strpart(n, 0, len(n) - 1)
endif
elseif c == 13 " Enter key
let just = (just + 1) % len(s:just)
elseif ch == '-'
if empty(n) | let n = '-'
elseif n == '-' | let n = ''
else | break
endif
elseif ch == '*'
if empty(n) | let n = '*'
elseif n == '*' | let n = '**'
elseif n == '**' | let n = ''
else | break
endif
elseif c >= 48 && c <= 57 " Numbers
if n[0] == '*' | break
else | let n = n . ch
end
else
break
endif
endwhile
return [just, n, ch]
endfunction endfunction
function! easy_align#align(just, ...) range function! s:parse_args(args)
let just = a:just let n = ''
let recursive = 0 let ch = ''
let n = '' let args = a:args
let ch = '' let cand = ''
let option = {}
if a:0 == 0 " Poor man's option parser
while 1 let idx = 0
call s:echon(just, n, '') while 1
let midx = match(args, '{.*}\s*$', idx)
if midx == -1 | break | endif
let c = getchar() let cand = strpart(args, midx)
let ch = nr2char(c) try
if c == 3 || c == 27 " CTRL-C / ESC let o = eval(cand)
return if type(o) == 4
elseif c == '<27>kb' " Backspace let option = o
if len(n) > 0 let args = strpart(args, 0, midx)
let n = strpart(n, 0, len(n) - 1)
endif
elseif c == 13 " Enter key
let just = (just + 1) % len(s:just)
elseif ch == '-'
if empty(n) | let n = '-'
elseif n == '-' | let n = ''
else | break
endif
elseif ch == '*'
if empty(n) | let n = '*'
elseif n == '*' | let n = '**'
elseif n == '**' | let n = ''
else | break
endif
elseif c >= 48 && c <= 57 " Numbers
if n[0] == '*' | break
else | let n = n . ch
end
else
break break
endif endif
endwhile catch
elseif a:0 == 1 " Ignore
let tokens = matchlist(a:1, '^\([1-9][0-9]*\|-[0-9]*\|\*\*\?\)\?\(.\)$') endtry
if empty(tokens) let idx = midx + 1
echo "Invalid arguments: ". a:1 endwhile
return
endif " Invalid option dictionary
let [n, ch] = tokens[1:2] if len(cand) > 2 && empty(option)
elseif a:0 == 2 call s:exit("Invalid option: ". cand)
let [n, ch] = a:000
else
echo "Invalid number of arguments: ". a:0 ." (expected 0, 1, or 2)"
return
endif endif
if n == '*' | let [nth, recursive] = [1, 1] " Has /Regexp/?
elseif n == '**' | let [nth, recursive] = [1, 2] let matches = matchlist(args, '^\(.\{-}\)\s*/\(.*\)/\s*$')
" Found regexp
if !empty(matches)
let regexp = matches[2]
" Test regexp
try | call matchlist('', regexp)
catch | call s:exit("Invalid regular expression: ". regexp)
endtry
" Unsupported regular expression
if match(regexp, '\\zs') != -1
call s:exit("Using \\zs is not allowed. Use stick_to_left option instead.")
endif
return [matches[1], regexp, option, 1]
else
let tokens = matchlist(args, '^\([1-9][0-9]*\|-[0-9]*\|\*\*\?\)\?\s*\(.\{-}\)\?$')
return [tokens[1], tokens[2], option, 0]
endif
endfunction
function! easy_align#align(just, expr) range
let just = a:just
let recur = 0
let n = ''
let ch = ''
let option = {}
let regexp = 0
try
if empty(a:expr)
let [just, n, ch] = s:interactive(just)
else
let [n, ch, option, regexp] = s:parse_args(a:expr)
if empty(ch)
" Try swapping n and ch
let [n, ch] = ['', n]
endif
endif
catch 'exit'
return
endtry
if n == '*' | let [nth, recur] = [1, 1]
elseif n == '**' | let [nth, recur] = [1, 2]
elseif n == '-' | let nth = -1 elseif n == '-' | let nth = -1
elseif empty(n) | let nth = 1 elseif empty(n) | let nth = 1
elseif n == '0' || ( n != '-0' && n != string(str2nr(n)) ) elseif n == '0' || ( n != '-0' && n != string(str2nr(n)) )
@@ -294,22 +408,40 @@ function! easy_align#align(just, ...) range
let delimiters = extend(copy(delimiters), g:easy_align_delimiters) let delimiters = extend(copy(delimiters), g:easy_align_delimiters)
endif endif
if has_key(delimiters, ch) if regexp
let dict = delimiters[ch] let dict = { 'pattern': ch }
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', ' '),
\ get(dict, 'stick_to_left', 0),
\ get(dict, 'ignore_unmatched', get(g:, 'easy_align_ignore_unmatched', 1)),
\ get(dict, 'ignores', s:ignored_syntax()),
\ recursive)
call s:echon(just, n, ch)
else else
echon "\rUnknown delimiter: ". ch if ch =~ '^\\\s\+$'
let ch = ' '
elseif ch =~ '^\\\\\s\+$'
let ch = '\'
endif
if !has_key(delimiters, ch)
echon "\rUnknown delimiter key: ". ch
return
endif
let dict = delimiters[ch]
endif endif
try
if !empty(option)
let dict = extend(copy(dict), s:normalize_options(option))
endif
catch 'exit'
return
endtry
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', ' '),
\ get(dict, 'stick_to_left', 0),
\ get(dict, 'ignore_unmatched', get(g:, 'easy_align_ignore_unmatched', 1)),
\ get(dict, 'ignores', s:ignored_syntax()),
\ recur)
call s:echon(just, n, regexp ? '/'.ch.'/' : ch)
endfunction endfunction

View File

@@ -10,8 +10,15 @@ A simple, easy-to-use Vim alignment plugin without too much ambition.
EasyAlign *EasyAlign* EasyAlign *EasyAlign*
------------------------------------------------------------------------- -------------------------------------------------------------------------
vim-easy-align defines interactive `:EasyAlign` command in the visual mode. vim-easy-align defines `:EasyAlign` command in the visual mode.
| Mode | Command |
| ------------------------- | ------------------------------------------- |
| Interactive mode | :EasyAlign |
| Using predefined rules | :EasyAlign [FIELD#] DELIMITER_KEY [OPTIONS] |
| Using regular expressions | :EasyAlign [FIELD#] /REGEXP/ [OPTIONS] |
The commands will go into interactive mode when no argument is given.
For convenience, it is advised that you define a mapping for triggering it For convenience, it is advised that you define a mapping for triggering it
in your `.vimrc`. in your `.vimrc`.
@@ -60,6 +67,60 @@ EasyAlignRight *EasyAlignRight*
EasyAlignRight is the right-justified version of EasyAlign command. EasyAlignRight is the right-justified version of EasyAlign command.
Non-interactive mode
--------------------
Instead of going into the interactive mode, you can instead type in arguments to
`:EasyAlign` command. In non-interactive mode, you can even use arbitrary
regular expressions.
" Using predefined alignment rules
:EasyAlign [FIELD#] DELIMITER_KEY [OPTIONS]
" Using arbitrary regular expressions
:EasyAlign [FIELD#] /REGEXP/ [OPTIONS]
For example, when aligning the following lines around colons and semi-colons,
apple;:banana::cake
data;;exchange:;format
try these commands:
- :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.
- :EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'margin_left': '' }
Then we get:
apple;: banana:: cake
data;; exchange:; format
Options keys are fuzzy-matched, so you can write as follows:
- :EasyAlign * /[:;]\+/ { 'stl': 1, 'ml': '' }
You can even omit spaces between the arguments, so concisely (or cryptically):
- :EasyAlign*/[:;]\+/{'stl':1,'ml':''}
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']` |
Partial alignment in blockwise-visual mode Partial alignment in blockwise-visual mode
------------------------------------------------------------------------- -------------------------------------------------------------------------

View File

@@ -26,5 +26,5 @@ 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 EasyAlign <line1>,<line2>call easy_align#align(0, <f-args>) command! -nargs=* -range EasyAlign <line1>,<line2>call easy_align#align(0, <q-args>)
command! -nargs=* -range EasyAlignRight <line1>,<line2>call easy_align#align(1, <f-args>) command! -nargs=* -range EasyAlignRight <line1>,<line2>call easy_align#align(1, <q-args>)

259
test/basic.expected Normal file
View File

@@ -0,0 +1,259 @@
" :source run.vim
" @a
Pa ul Mc Ca rt ne y{ {1 }} 94 2
Ge or ge Ha rr is on {{ 1} }9 43
Ri ng o St ar r {{ 1} }9 40
Pe te Be st {{ 1} }9 41
Paul McCartney{{1}}942
George Harrison {{1}}943
Ringo Starr {{1}}940
Pete Best {{1}}941
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
| 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 |
aaa, bb, c
d, eeeeeee
fffff, gggggggggg,
h, , ii
j, , k
```ruby
a =
a = 1
bbbb = 2
ccccccc = 3
ccccccccccccccc
ddd = 4
eeee === eee = eee = eee=f
fff = ggg += gg &&= gg
g != hhhhhhhh == 888
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 = 4
eeee === eee = eee = eee = f
fff = ggg += gg &&= gg
g != hhhhhhhh == 888
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 = 4
eeee === eee = eee = eee = f
fff = ggg += gg &&= gg
g != hhhhhhhh == 888
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 = 4
eeee === eee = eee = eee=f
fff = ggg += gg &&= gg
g != hhhhhhhh == 888
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
options = { :caching => nil,
:versions => 3,
"cache=blocks" => false }.merge(options)
options = { :caching => nil,
:versions => 3,
"cache=blocks" => false }.merge(options)
options = { :caching => nil,
:versions => 3,
"cache=blocks" => false }.merge(options)
apple = 1 # comment not aligned
banana = 'Gros Michel' # comment 2
# let g:easy_align_delimiters = { '#': { 'pattern': '#\+', 'ignores': ['String'] } }
apple = 1 # comment not aligned
apricot = 'DAD' + 'F#AD'
banana = 'Gros Michel' # comment 2
apple = 1 # comment not aligned
apricot = 'DAD' + 'F#AD'
banana = 'Gros Michel' # comment 2
```
```yaml
mysql:
# JDBC driver for MySQL database:
driver: com.mysql.jdbc.Driver
# JDBC URL for the connection (jdbc:mysql://HOSTNAME/DATABASE)
url: jdbc:mysql://localhost/test
database: test
"user:pass": r00t:pa55
```
```c
/* a */ b = c
aa >= bb
// aaa = bbb = cccc
/* aaaa = */ bbbb === cccc " = dddd = " = eeee
aaaaa /* bbbbb */ == ccccc /* != eeeee = */ === fffff
/* a */ b = c
aa >= bb
// aaa = bbb = cccc
/* aaaa = */ bbbb === cccc " = dddd = " = eeee
aaaaa /* bbbbb */ == ccccc /* != eeeee = */ === fffff
```

86
test/basic.md Normal file
View File

@@ -0,0 +1,86 @@
" :source run.vim
" @a
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
| 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 |
aaa, bb,c
d,eeeeeee
fffff, gggggggggg,
h, , ii
j,,k
```ruby
a =
a = 1
bbbb = 2
ccccccc = 3
ccccccccccccccc
ddd = 4
eeee === eee = eee = eee=f
fff = ggg += gg &&= gg
g != hhhhhhhh == 888
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
options = { :caching => nil,
:versions => 3,
"cache=blocks" => false }.merge(options)
apple = 1 # comment not aligned
banana = 'Gros Michel' # comment 2
# let g:easy_align_delimiters = { '#': { 'pattern': '#\+', 'ignores': ['String'] } }
apple = 1 # comment not aligned
apricot = 'DAD' + 'F#AD'
banana = 'Gros Michel' # comment 2
```
```yaml
mysql:
# JDBC driver for MySQL database:
driver: com.mysql.jdbc.Driver
# JDBC URL for the connection (jdbc:mysql://HOSTNAME/DATABASE)
url: jdbc:mysql://localhost/test
database: test
"user:pass":r00t:pa55
```
```c
/* a */ b = c
aa >= bb
// aaa = bbb = cccc
/* aaaa = */ bbbb === cccc " = dddd = " = eeee
aaaaa /* bbbbb */ == ccccc /* != eeeee = */ === fffff
```

1
test/basic.script Normal file
View File

@@ -0,0 +1 @@
4Gvipjyvip

42
test/include.vim Normal file
View File

@@ -0,0 +1,42 @@
function! GFM()
let syntaxes = {
\ 'ruby': 'syntax/ruby.vim',
\ 'yaml': 'syntax/yaml.vim',
\ 'vim': 'syntax/vim.vim',
\ 'sh': 'syntax/sh.vim',
\ 'python': 'syntax/python.vim',
\ 'java': 'syntax/java.vim',
\ 'c': 'syntax/c.vim'
\ }
for [lang, syn] in items(syntaxes)
unlet b:current_syntax
silent! exec printf("syntax include @%s %s", lang, syn)
exec printf("syntax region %sSnip matchgroup=Snip start='```%s' end='```' contains=@%s",
\ lang, lang, lang)
endfor
let b:current_syntax='mkd'
endfunction
silent! unlet g:easy_align_delimiters
silent! unlet g:easy_align_ignore_unmatched
silent! unlet g:easy_align_ignores
vnoremap <silent> <Enter> :EasyAlign<cr>
noremap <silent> <C-k> <nop>
noremap <silent> <C-j> <nop>
noremap <silent> <C-h> <nop>
noremap <silent> <C-l> <nop>
vnoremap <silent> <C-k> <nop>
vnoremap <silent> <C-j> <nop>
vnoremap <silent> <C-h> <nop>
vnoremap <silent> <C-l> <nop>
set nolazyredraw
set buftype=nofile
silent! ScrollPositionHide
call GFM()

87
test/regexp.expected Normal file
View File

@@ -0,0 +1,87 @@
" :source run.vim
" @a
apple;:banana :: cake
data;;exchange :; format
apple ;: banana :: cake
data ;; exchange :; format
apple ;: banana :: cake
data ;; exchange :; format
apple ;:____banana::cake
data ;;____exchange:;format
apple ; : banana : : cake
data ; ; exchange : ; format
ap pl e; :b an an a: :c ak e
da ta ;; ex ch an ge :; fo rm at
ap ple;:banana::cake
da ta;;exchange:;format
apple???;:~~~banana???::~~~ cake
data???;;~~~ exchange???:;~~~format
apple;: banana::cake
data;; exchange:;format
apple<<<;:>>>banana::cake
data <<<;;>>>exchange:;format
apple ;: banana::cake
data ;; exchange:;format
apple;:banana :: cake
data;;exchange :; format
apple ;: banana :: cake
data ;; exchange :; format
apple ;: banana :: cake
data ;; exchange :; format
apple ;: banana :: cake
data ;; exchange :; format
apple ;: banana :: cake
data ;; exchange :; format
apple ;: banana::cake
data ;; exchange:;format
apple ; :banana::cake
data ; ; exchange: ; format
apple ; :banana::cake
data ; ;exchange:;format
apple ; :banana::cake
data ; ;exchange:;format
apple;:banana::cake
data;;exchange:;format
apple;: banana: : cake
data;;exchange: ;format
apple;:banana: :cake
data;;exchange:;format
apple;:banana: :cake
data;;exchange:;format
apple;: banana: : cake
data;;exchange: ;format
apple;:banana:: cake
data;;exchange: ;format
apple;: banana: : cake
data;;exchange: ;format
apple;: banana::cake
data;;exchange: ;format

6
test/regexp.md Normal file
View File

@@ -0,0 +1,6 @@
" :source run.vim
" @a
apple;:banana::cake
data;;exchange:;format

1
test/regexp.script Normal file
View File

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

12
test/run.vim Normal file
View File

@@ -0,0 +1,12 @@
source include.vim
while line('.') < line('$')
normal 30j
redraw
endwhile
normal gg
let @b=system('cat '. expand('%:r') . '.script')
let @a='@b:vert diffsplit ' . expand('%:r') . '.expected
'
" Syntax highlighting doesn't work