mirror of
https://github.com/junegunn/vim-easy-align.git
synced 2025-11-18 06:43:40 -05:00
Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aad5012615 | ||
|
|
0166077e16 | ||
|
|
3c4b7af9b5 | ||
|
|
5e6e60d620 | ||
|
|
712bab8c72 | ||
|
|
0546969c6b | ||
|
|
8805ec3834 | ||
|
|
96608ee5ef | ||
|
|
7d031956ab | ||
|
|
c4dbfece32 | ||
|
|
a2811dc253 | ||
|
|
5e4ec85956 | ||
|
|
b3281fb19a | ||
|
|
10a4176159 | ||
|
|
edba1827ed | ||
|
|
1cf343a271 | ||
|
|
c66f35ad39 | ||
|
|
2486b9c6df | ||
|
|
20124bc622 | ||
|
|
2a2625014b | ||
|
|
375da6858a | ||
|
|
06d5bcb911 | ||
|
|
badb701721 | ||
|
|
ea84b43062 | ||
|
|
bd8327499a | ||
|
|
057be51067 | ||
|
|
6d841110af | ||
|
|
ec456f82a6 | ||
|
|
61aeefb095 | ||
|
|
36697b4a72 | ||
|
|
9b20830c70 | ||
|
|
5f59570c9f | ||
|
|
5b48e997a1 | ||
|
|
67ac2f74e6 | ||
|
|
94524ec3d3 | ||
|
|
3e700c6ce4 | ||
|
|
3ee8cdfd9e | ||
|
|
a6e707b1b3 | ||
|
|
34a555c220 | ||
|
|
912bb949f7 | ||
|
|
81138d0e2c | ||
|
|
214efaad0c | ||
|
|
29078629f5 | ||
|
|
3ab67e2870 | ||
|
|
8dd2daaa9e | ||
|
|
e3f7352ab8 | ||
|
|
0fe7d17908 | ||
|
|
27b95b4ce0 | ||
|
|
5c870f60d9 | ||
|
|
cb71847a11 | ||
|
|
811ea63b11 | ||
|
|
9c9a16c759 | ||
|
|
1e627366e7 | ||
|
|
32224d88f2 |
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1,5 +1,6 @@
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
doc/tags export-ignore
|
||||
README.md export-ignore
|
||||
*.md export-ignore
|
||||
zip export-ignore
|
||||
test/* export-ignore
|
||||
|
||||
393
EXAMPLES.md
Normal file
393
EXAMPLES.md
Normal file
@@ -0,0 +1,393 @@
|
||||
vim-easy-align examples
|
||||
=======================
|
||||
|
||||
Open this document in your Vim and try it yourself.
|
||||
|
||||
This document assumes that you have defined the following mapping.
|
||||
|
||||
```vim
|
||||
vnoremap <silent> <Enter> :EasyAlign<cr>
|
||||
```
|
||||
|
||||
To enable syntax highlighting in the code blocks, define and call the following
|
||||
function.
|
||||
|
||||
```vim
|
||||
function! GFM()
|
||||
let langs = ['ruby', 'yaml', 'vim', 'c']
|
||||
|
||||
for lang in langs
|
||||
unlet b:current_syntax
|
||||
silent! exec printf("syntax include @%s syntax/%s.vim", lang, lang)
|
||||
exec printf("syntax region %sSnip matchgroup=Snip start='```%s' end='```' contains=@%s",
|
||||
\ lang, lang, lang)
|
||||
endfor
|
||||
let b:current_syntax='mkd'
|
||||
|
||||
syntax sync fromstart
|
||||
endfunction
|
||||
```
|
||||
|
||||
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
|
||||
George Harrison 1943
|
||||
Ringo Starr 1940
|
||||
Pete Best 1941
|
||||
|
||||
```
|
||||
|
||||
Formatting table
|
||||
----------------
|
||||
|
||||
Try these commands:
|
||||
- `<Enter>*|`
|
||||
- `<Enter>**|`
|
||||
- `<Enter><Enter>*|`
|
||||
- `<Enter><Enter>**|`
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
|
||||
| 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 |
|
||||
|
||||
```
|
||||
|
||||
|
||||
Alignment around =
|
||||
------------------
|
||||
|
||||
The default rule for delimiter key `=` aligns around a whole family of operators
|
||||
containing `=` character.
|
||||
|
||||
Try these commands:
|
||||
- `<Enter>=`
|
||||
- `<Enter>*=`
|
||||
- `<Enter>**=`
|
||||
- `<Enter><Enter>**=`
|
||||
|
||||
### Example
|
||||
|
||||
```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
|
||||
|
||||
```
|
||||
|
||||
Formatting YAML (or JSON)
|
||||
-------------------------
|
||||
|
||||
Try `<Enter>:` here, to align text around only the first occurrences of colons.
|
||||
In this case, you don't want to align around all the colons: `<Enter>*:`.
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
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()
|
||||
```
|
||||
|
||||
|
||||
Using blockwise-visual mode or negative field index
|
||||
---------------------------------------------------
|
||||
|
||||
You can try either:
|
||||
- select text around `=>` in blockwise-visual mode (`CTRL-V`) and `<Enter>=`
|
||||
- or `<Enter>-=`
|
||||
|
||||
```ruby
|
||||
options = { :caching => nil,
|
||||
:versions => 3,
|
||||
"cache=blocks" => false }.merge(options)
|
||||
```
|
||||
|
||||
Commas
|
||||
------
|
||||
|
||||
There is also a predefined rule for commas, try `<Enter>*,` on the following
|
||||
lines.
|
||||
|
||||
```
|
||||
aaa, bb,c
|
||||
d,eeeeeee
|
||||
fffff, gggggggggg,
|
||||
h, , ii
|
||||
j,,k
|
||||
```
|
||||
|
||||
Ignoring delimiters in comments or strings
|
||||
------------------------------------------
|
||||
|
||||
Delimiters highlighted as comments or strings are ignored by default, try
|
||||
`<Enter>*=` on the following lines.
|
||||
|
||||
```c
|
||||
|
||||
/* a */ b = c
|
||||
aa >= bb
|
||||
// aaa = bbb = cccc
|
||||
/* aaaa = */ bbbb === cccc " = dddd = " = eeee
|
||||
aaaaa /* bbbbb */ == ccccc /* != eeeee = */ === fffff
|
||||
|
||||
```
|
||||
|
||||
This only works when syntax highlighting is enabled.
|
||||
|
||||
Aligning in-line comments
|
||||
-------------------------
|
||||
|
||||
```ruby
|
||||
apple = 1 # comment not aligned
|
||||
banana = 'Gros Michel' # comment 2
|
||||
```
|
||||
|
||||
So, how do we align the trailing comments in the above lines?
|
||||
Simply try `<Enter>-<space>`. The spaces in the comments are ignored, so the
|
||||
trailing comment in each line is considered to be a single chunk.
|
||||
|
||||
But that doesn't work in the following case.
|
||||
|
||||
```ruby
|
||||
apple = 1 # comment not aligned
|
||||
apricot = 'DAD' + 'F#AD'
|
||||
banana = 'Gros Michel' # comment 2
|
||||
```
|
||||
|
||||
That is because the second line doesn't have trailing comment, and
|
||||
the last (`-`) space for that line is the one just before `'F#AD'`.
|
||||
|
||||
So, let's define a custom mapping for `#`.
|
||||
|
||||
```vim
|
||||
if !exists('g:easy_align_delimiters')
|
||||
let g:easy_align_delimiters = {}
|
||||
endif
|
||||
let g:easy_align_delimiters['#'] = { 'pattern': '#', 'ignores': ['String'] } }
|
||||
```
|
||||
|
||||
Notice that the rule overrides `ignores` attribute in order *not to ignore*
|
||||
delimiters highlighted as comments.
|
||||
|
||||
Then on `<Enter>#`, we get
|
||||
|
||||
```ruby
|
||||
apple = 1 # comment not aligned
|
||||
apricot = 'DAD' + 'F#AD'
|
||||
banana = 'string' # comment 2
|
||||
```
|
||||
|
||||
If you don't want to define the rule, you can do the same with the following
|
||||
command:
|
||||
|
||||
```vim
|
||||
" Using regular expression /#/
|
||||
" - "is" is fuzzy-matched to "*i*gnore*s*"
|
||||
:EasyAlign/#/{'is':['String']}
|
||||
```
|
||||
|
||||
In this case, the second line is ignored as it doesn't contain a `#`. (The one
|
||||
highlighted as String is ignored.) If you don't want the second line to be
|
||||
ignored, there are three options:
|
||||
|
||||
1. Set global `g:easy_align_ignore_unmatched` flag to 0
|
||||
2. Use `:EasyAlign` command with `ignore_unmatched` option
|
||||
3. Update the alignment rule with `ignore_unmatched` option
|
||||
|
||||
```vim
|
||||
" 1. Set global g:easy_align_ignore_unmatched to zero
|
||||
let g:easy_align_ignore_unmatched = 0
|
||||
|
||||
" 2. Using :EasyAlign command with ignore_unmatched option
|
||||
" 2-1. Using predefined rule with delimiter key #
|
||||
" - "iu" is fuzzy-matched to "*i*gnore_*u*nmatched"
|
||||
:EasyAlign#{'iu':0}
|
||||
|
||||
" 2-2. Using regular expression /#/
|
||||
:EasyAlign/#/{'is':['String'],'iu':0}
|
||||
|
||||
" 3. Update the alignment rule with ignore_unmatched option
|
||||
let g:easy_align_delimiters['#'] = {
|
||||
\ 'pattern': '#', 'ignores': ['String'], 'ignore_unmatched': 0 } }
|
||||
```
|
||||
|
||||
Then we get,
|
||||
|
||||
```ruby
|
||||
apple = 1 # comment not aligned
|
||||
apricot = 'DAD' + 'F#AD'
|
||||
banana = 'string' # comment 2
|
||||
```
|
||||
|
||||
Aligning C-style variable definition
|
||||
------------------------------------
|
||||
|
||||
Take the following example:
|
||||
|
||||
```c
|
||||
const char* str = "Hello";
|
||||
int64_t count = 1 + 2;
|
||||
static double pi = 3.14;
|
||||
```
|
||||
|
||||
We can align these lines with the predefined `=` rule. Select the lines and
|
||||
press `<Enter>=`
|
||||
|
||||
```c
|
||||
const char* str = "Hello";
|
||||
int64_t count = 1 + 2;
|
||||
static double pi = 3.14;
|
||||
```
|
||||
|
||||
Not bad. However, the names of the variables, `str`, `count`, and `pi` are not
|
||||
aligned with each other. Can we do better? We can clearly see that simple
|
||||
`<Enter><space>` won't properly align those names.
|
||||
So let's define an alignment rule than can handle this case.
|
||||
|
||||
```vim
|
||||
let g:easy_align_delimiters['d'] = {
|
||||
\ 'pattern': '\(const\|static\)\@<! ',
|
||||
\ 'left_margin': 0, 'right_margin': 0
|
||||
\ }
|
||||
```
|
||||
|
||||
This new rule aligns text around spaces that are *not* preceded by
|
||||
`const` or `static`. Let's try it with `<Enter>d`.
|
||||
|
||||
```c
|
||||
const char* str = "Hello";
|
||||
int64_t count = 1 + 2;
|
||||
static double pi = 3.14;
|
||||
```
|
||||
|
||||
Okay, the names are now aligned. We select the lines again with `gv`, and then
|
||||
press `<Enter>=` to finish our alignment.
|
||||
|
||||
```c
|
||||
const char* str = "Hello";
|
||||
int64_t count = 1 + 2;
|
||||
static double pi = 3.14;
|
||||
```
|
||||
|
||||
So far, so good. However, this rule is not sufficient to handle more complex
|
||||
cases involving C++ templates or Java generics. Take the following example:
|
||||
|
||||
```c
|
||||
const char* str = "Hello";
|
||||
int64_t count = 1 + 2;
|
||||
static double pi = 3.14;
|
||||
static std::map<std::string, float>* scores = pointer;
|
||||
```
|
||||
|
||||
We see that our rule above doesn't work anymore.
|
||||
|
||||
```c
|
||||
const char* str = "Hello";
|
||||
int64_t count = 1 + 2;
|
||||
static double pi = 3.14;
|
||||
static std::map<std::string, float>* scores = pointer;
|
||||
```
|
||||
|
||||
So what do we do? Let's try to improve our alignment rule.
|
||||
|
||||
```vim
|
||||
let g:easy_align_delimiters['d'] = {
|
||||
\ 'pattern': ' \(\S\+\s*[;=]\)\@=',
|
||||
\ 'left_margin': 0, 'right_margin': 0
|
||||
\ }
|
||||
```
|
||||
|
||||
Now the new rule has changed to align text around spaces that are followed
|
||||
by some non-whitespace characters and then an equals sign or a semi-colon.
|
||||
Try `<Enter>d`
|
||||
|
||||
```c
|
||||
const char* str = "Hello";
|
||||
int64_t count = 1 + 2;
|
||||
static double pi = 3.14;
|
||||
static std::map<std::string, float>* scores = pointer;
|
||||
```
|
||||
|
||||
We're right on track, now press `gv<Enter>=` and voila!
|
||||
|
||||
```c
|
||||
const char* str = "Hello";
|
||||
int64_t count = 1 + 2;
|
||||
static double pi = 3.14;
|
||||
static std::map<std::string, float>* scores = pointer;
|
||||
```
|
||||
|
||||
414
README.md
414
README.md
@@ -8,7 +8,17 @@ Demo
|
||||
|
||||

|
||||
|
||||
[Screencast](https://vimeo.com/63506219)
|
||||
Features
|
||||
--------
|
||||
|
||||
- Makes the common case easy
|
||||
- Comes with a predefined set of alignment rules
|
||||
- Provides a fast and intuitive interface
|
||||
- Extensible
|
||||
- You can define your own rules
|
||||
- Supports arbitrary regular expressions
|
||||
- Optimized for code editing
|
||||
- Takes advantage of syntax highlighting feature to avoid unwanted alignments
|
||||
|
||||
Installation
|
||||
------------
|
||||
@@ -19,60 +29,130 @@ or [Pathogen](https://github.com/tpope/vim-pathogen).
|
||||
|
||||
### With Vundle
|
||||
|
||||
Add the following line to your .vimrc,
|
||||
|
||||
```vim
|
||||
Bundle 'junegunn/vim-easy-align'
|
||||
```
|
||||
|
||||
then execute `:BundleInstall` command.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
_vim-easy-align_ defines interactive `:EasyAlign` command in the visual mode.
|
||||
For convenience, it is advised that you define a mapping for triggering it in your `.vimrc`.
|
||||
_vim-easy-align_ defines `:EasyAlign` command (and the right-justification
|
||||
variant `:EasyAlign!`) 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 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`.
|
||||
|
||||
```vim
|
||||
vnoremap <silent> <Enter> :EasyAlign<cr>
|
||||
```
|
||||
|
||||
With the mapping, you can align selected lines with a few keystrokes.
|
||||
With the mapping, you can align selected lines of text with only a few keystrokes.
|
||||
|
||||
1. `<Enter>` key to start interactive EasyAlign command
|
||||
1. Optional Enter keys to toggle right-justification mode
|
||||
1. Optional field number (default: 1)
|
||||
- `1` Alignment around 1st delimiters
|
||||
- `2` Alignment around 2nd delimiters
|
||||
- `1` Around the 1st occurrences of delimiters
|
||||
- `2` Around the 2nd occurrences of delimiters
|
||||
- ...
|
||||
- `*` Alignment around all delimiters (recursive)
|
||||
1. Delimiter (`<space>`, `=`, `:`, `.`, `|`, `,`)
|
||||
- `*` Around all occurrences of delimiters
|
||||
- `**` Left-right alternating alignment around all delimiters
|
||||
- `-` Around the last occurrences of delimiters (`-1`)
|
||||
- `-2` Around the second to last occurrences of delimiters
|
||||
- ...
|
||||
1. Delimiter key (a single keystroke; `<space>`, `=`, `:`, `.`, `|`, `,`)
|
||||
|
||||
Alignment rules for the following delimiters have been crafted to meet the most needs.
|
||||
Alignment rules for the following delimiters have been defined to meet the most needs.
|
||||
|
||||
| Delimiter | Description/Use cases |
|
||||
| --------- | ---------------------------------------------------------- |
|
||||
| `<space>` | General alignment around spaces |
|
||||
| `=` | Operators containing equals sign (=, ==, !=, +=, &&=, ...) |
|
||||
| `:` | Suitable for formatting JSON or YAML |
|
||||
| `.` | Multi-line method chaining |
|
||||
| `,` | Multi-line method arguments |
|
||||
| | | Table markdown |
|
||||
| Delimiter key | Description/Use cases |
|
||||
| ------------- | -------------------------------------------------------------------- |
|
||||
| `<space>` | General alignment around whitespaces |
|
||||
| `=` | Operators containing equals sign (`=`, `==,` `!=`, `+=`, `&&=`, ...) |
|
||||
| `:` | Suitable for formatting JSON or YAML |
|
||||
| `.` | Multi-line method chaining |
|
||||
| `,` | Multi-line method arguments |
|
||||
| | | Table markdown |
|
||||
|
||||
### Example command sequences
|
||||
#### Example command sequences
|
||||
|
||||
| With visual map | Description | Equivalent command |
|
||||
| ----------------- | ------------------------------------------------- | ----------------------- |
|
||||
| `<Enter>=` | Alignment around 1st equals signs (and the likes) | `:'<,'>EasyAlign=` |
|
||||
| `<Enter>2=` | Alignment around 2nd equals signs (and the likes) | `:'<,'>EasyAlign2=` |
|
||||
| `<Enter>3=` | Alignment around 3rd equals signs (and the likes) | `:'<,'>EasyAlign3=` |
|
||||
| `<Enter>*=` | Alignment around all equals signs (and the likes) | `:'<,'>EasyAlign*=` |
|
||||
| `<Enter><Enter>=` | Right-justified alignment around 1st equals signs | `:'<,'>EasyAlignRight=` |
|
||||
| `<Enter><space>` | Alignment around 1st space | `:'<,'>EasyAlign\ ` |
|
||||
| `<Enter>2<space>` | Alignment around 2nd space | `:'<,'>EasyAlign2\ ` |
|
||||
| `<Enter>:` | Alignment around 1st colon | `:'<,'>EasyAlign:` |
|
||||
| ... | ... | |
|
||||
| With visual map | Description | Equivalent command |
|
||||
| ------------------- | -------------------------------------------------------- | --------------------- |
|
||||
| `<Enter><space>` | Alignment around 1st whitespaces | `:'<,'>EasyAlign\ ` |
|
||||
| `<Enter>2<space>` | Alignment around 2nd whitespaces | `:'<,'>EasyAlign2\ ` |
|
||||
| `<Enter>-<space>` | Alignment around the last whitespaces | `:'<,'>EasyAlign-\ ` |
|
||||
| `<Enter>:` | Alignment around 1st colon | `:'<,'>EasyAlign:` |
|
||||
| `<Enter>=` | Alignment around 1st equals signs (and the likes) | `:'<,'>EasyAlign=` |
|
||||
| `<Enter>2=` | Alignment around 2nd equals signs (and the likes) | `:'<,'>EasyAlign2=` |
|
||||
| `<Enter>3=` | Alignment around 3rd equals signs (and the likes) | `:'<,'>EasyAlign3=` |
|
||||
| `<Enter>*=` | Alignment around all equals signs (and the likes) | `:'<,'>EasyAlign*=` |
|
||||
| `<Enter>**=` | Left-right alternating alignment around all equals signs | `:'<,'>EasyAlign**=` |
|
||||
| `<Enter><Enter>=` | Right-justified alignment around 1st equals signs | `:'<,'>EasyAlign!=` |
|
||||
| `<Enter><Enter>**=` | Right-left alternating alignment around all equals signs | `:'<,'>EasyAlign!**=` |
|
||||
| ... | ... | |
|
||||
|
||||
### Non-interactive mode
|
||||
|
||||
Instead of going into the interactive mode, you can 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 in Vim dictionary
|
||||
format.
|
||||
|
||||
- `:EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'left_margin': '' }`
|
||||
|
||||
Then we get:
|
||||
|
||||
apple;: banana:: cake
|
||||
data;; exchange:; format
|
||||
|
||||
Options keys are fuzzy-matched, so you can write as follows:
|
||||
|
||||
- `:EasyAlign * /[:;]\+/ { 'stl': 1, 'l': 0 }`
|
||||
|
||||
You can even omit spaces between the arguments, so concisely (or cryptically):
|
||||
|
||||
- `:EasyAlign*/[:;]\+/{'s':1,'l':0}`
|
||||
|
||||
Available options will be shown later in the document.
|
||||
|
||||
### Partial alignment in blockwise-visual mode
|
||||
|
||||
In blockwise-visual mode (`CTRL-V`), EasyAlign command aligns only the selected
|
||||
parts, instead of the whole lines in the range.
|
||||
text in the block, instead of the whole lines in the range.
|
||||
|
||||
Consider the following case where you want to align text around `=>` operators.
|
||||
|
||||
@@ -82,9 +162,9 @@ my_hash = { :a => 1,
|
||||
:aaa => 3 }
|
||||
```
|
||||
|
||||
In non-blockwise visual mode (`v` / `V`), `<Enter>=` won't work since the assignment
|
||||
operator in the first line gets in the way.
|
||||
So we instead enter blockwise-visual mode (`CTRL-V`), and select the text *around*
|
||||
In non-blockwise visual mode (`v` / `V`), `<Enter>=` won't work since the
|
||||
assignment operator in the first line gets in the way. So we instead enter
|
||||
blockwise-visual mode (`CTRL-V`), and select the text *around*
|
||||
`=>` operators, then press `<Enter>=`.
|
||||
|
||||
```ruby
|
||||
@@ -93,75 +173,229 @@ my_hash = { :a => 1,
|
||||
:aaa => 3 }
|
||||
```
|
||||
|
||||
Defining custom alignment rules
|
||||
-------------------------------
|
||||
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>-=`
|
||||
|
||||
Alignment options
|
||||
-----------------
|
||||
|
||||
Options values can be 1) specified as global variables, 2) set on each alignment
|
||||
rule in `g:easy_align_delimiters`, 3) or given to every `:EasyAlign` command.
|
||||
|
||||
Command-line options have the highest precedence, and global variables have the
|
||||
lowest precedence.
|
||||
|
||||
### List of options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| ------------------ | ----------------- | ----------------------- | ------------------------------------------------------- |
|
||||
| `left_margin` | number | 0 | Number of spaces 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` | string | `''` | String to attach after delimiter |
|
||||
| `stick_to_left` | boolean | 0 | Whether to position delimiter on the left-side |
|
||||
| `ignore_unmatched` | boolean | 1 | Whether to ignore lines without matching delimiter |
|
||||
| `ignores` | array | `['String', 'Comment']` | Delimiters in these syntax highlight groups are ignored |
|
||||
| `delimiter_align` | string | `r` | Determines how to align delimiters of different lengths |
|
||||
|
||||
Some of the options can be specified using corresponding global variables.
|
||||
|
||||
| Option | Global variable |
|
||||
| ------------------ | ------------------------------- |
|
||||
| `ignore_unmatched` | `g:easy_align_ignore_unmatched` |
|
||||
| `ignores` | `g:easy_align_ignores` |
|
||||
| `delimiter_align` | `g:easy_align_delimiter_align` |
|
||||
|
||||
### Ignoring delimiters in comments or strings
|
||||
|
||||
EasyAlign can be configured to ignore delimiters in certain syntax highlight
|
||||
groups, such as code comments or strings. By default, delimiters that are
|
||||
highlighted as code comments or strings are ignored.
|
||||
|
||||
```vim
|
||||
" Default:
|
||||
" If a delimiter is in a highlight group whose name matches
|
||||
" any of the followings, it will be ignored.
|
||||
let g:easy_align_ignores = ['Comment', 'String']
|
||||
```
|
||||
|
||||
For example, the following paragraph
|
||||
|
||||
```ruby
|
||||
{
|
||||
# Quantity of apples: 1
|
||||
apple: 1,
|
||||
# Quantity of bananas: 2
|
||||
bananas: 2,
|
||||
# Quantity of grape:fruits: 3
|
||||
'grape:fruits': 3
|
||||
}
|
||||
```
|
||||
|
||||
becomes as follows on `<Enter>:` (or `:EasyAlign:`)
|
||||
|
||||
```ruby
|
||||
{
|
||||
# Quantity of apples: 1
|
||||
apple: 1,
|
||||
# Quantity of bananas: 2
|
||||
bananas: 2,
|
||||
# Quantity of grape:fruits: 3
|
||||
'grape:fruits': 3
|
||||
}
|
||||
```
|
||||
|
||||
Naturally, this feature only works when syntax highlighting is enabled.
|
||||
|
||||
You can change the default rule by using one of these 3 methods.
|
||||
|
||||
1. Define global `g:easy_align_ignores` list
|
||||
2. Define a custom alignment rule in `g:easy_align_delimiters` with `ignores` option
|
||||
3. Provide `ignores` option to `:EasyAlign` command. e.g. `:EasyAlign:{'is':[]}`
|
||||
|
||||
For example if you set `ignores` option to be an empty list, you get
|
||||
|
||||
```ruby
|
||||
{
|
||||
# Quantity of apples: 1
|
||||
apple: 1,
|
||||
# Quantity of bananas: 2
|
||||
bananas: 2,
|
||||
# Quantity of grape: fruits: 3
|
||||
'grape: fruits': 3
|
||||
}
|
||||
```
|
||||
|
||||
Satisfied? :satisfied:
|
||||
|
||||
### Ignoring unmatched lines
|
||||
|
||||
Lines without any matching delimiter are ignored as well (except in
|
||||
right-justification mode).
|
||||
|
||||
For example, when aligning the following code block around the colons,
|
||||
|
||||
```ruby
|
||||
{
|
||||
apple: proc {
|
||||
this_line_does_not_have_a_colon
|
||||
},
|
||||
bananas: 2,
|
||||
grapefruits: 3
|
||||
}
|
||||
```
|
||||
|
||||
this is usually what we want.
|
||||
|
||||
```ruby
|
||||
{
|
||||
apple: proc {
|
||||
this_line_does_not_have_a_colon
|
||||
},
|
||||
bananas: 2,
|
||||
grapefruits: 3
|
||||
}
|
||||
```
|
||||
|
||||
However, this default behavior is also configurable by using one of these 3
|
||||
methods.
|
||||
|
||||
1. Set the global `g:easy_align_ignore_unmatched` variable to 0
|
||||
2. Define a custom alignment rule with `ignore_unmatched` option set to 0
|
||||
3. Provide `ignore_unmatched` option to `:EasyAlign` command. e.g. `:EasyAlign:{'iu':0}`
|
||||
|
||||
Then we get,
|
||||
|
||||
```ruby
|
||||
{
|
||||
apple: proc {
|
||||
this_line_does_not_have_a_colon
|
||||
},
|
||||
bananas: 2,
|
||||
grapefruits: 3
|
||||
}
|
||||
```
|
||||
|
||||
### Aligning delimiters of different lengths
|
||||
|
||||
Global `g:easy_align_delimiter_align` option and rule-wise/command-wise
|
||||
`delimiter_align` option determines how matched delimiters of different lengths
|
||||
are aligned.
|
||||
|
||||
```ruby
|
||||
apple = 1
|
||||
banana += apple
|
||||
cake ||= banana
|
||||
```
|
||||
|
||||
By default, delimiters are right-aligned as follows.
|
||||
|
||||
```ruby
|
||||
apple = 1
|
||||
banana += apple
|
||||
cake ||= banana
|
||||
```
|
||||
|
||||
However, with `:EasyAlign={'da':l}`, delimiters are left-aligned.
|
||||
|
||||
```ruby
|
||||
apple = 1
|
||||
banana += apple
|
||||
cake ||= banana
|
||||
```
|
||||
|
||||
And on `:EasyAlign={'da':c}`, center-aligned.
|
||||
|
||||
```ruby
|
||||
apple = 1
|
||||
banana += apple
|
||||
cake ||= banana
|
||||
```
|
||||
|
||||
### Extending alignment rules
|
||||
|
||||
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`.
|
||||
|
||||
#### Example
|
||||
|
||||
```vim
|
||||
let g:easy_align_delimiters = {
|
||||
\ '>': { 'pattern': '>>\|=>\|>' },
|
||||
\ '/': { 'pattern': '//*' },
|
||||
\ 'x': {
|
||||
\ 'pattern': '[xX]',
|
||||
\ 'margin_left': ' <<<',
|
||||
\ 'margin_right': '>>> ',
|
||||
\ '/': { 'pattern': '//\+\|/\*\|\*/', 'ignores': ['String'] },
|
||||
\ '#': { 'pattern': '#\+', 'ignores': ['String'], 'delimiter_align': 'l' },
|
||||
\ ']': {
|
||||
\ 'pattern': '[\[\]]',
|
||||
\ 'left_margin': 0,
|
||||
\ 'right_margin': 0,
|
||||
\ 'stick_to_left': 0
|
||||
\ },
|
||||
\ ')': {
|
||||
\ 'pattern': '[()]',
|
||||
\ 'left_margin': 0,
|
||||
\ 'right_margin': 0,
|
||||
\ 'stick_to_left': 0
|
||||
\ },
|
||||
\ 'd': {
|
||||
\ 'pattern': ' \(\S\+\s*[;=]\)\@=',
|
||||
\ 'left_margin': 0,
|
||||
\ 'right_margin': 0
|
||||
\ }
|
||||
\ }
|
||||
```
|
||||
|
||||
Handling unmatched lines
|
||||
------------------------
|
||||
Advanced examples and use cases
|
||||
-------------------------------
|
||||
|
||||
EasyAlign by default ignores lines without the matching delimiters (except in right-justification mode).
|
||||
This is to ignore interleaved comments commonly found in code.
|
||||
|
||||
For example, when aligning the following code block,
|
||||
|
||||
```
|
||||
{
|
||||
# Quantity of apples
|
||||
apple: 1,
|
||||
# Quantity of bananas
|
||||
bananas: 2,
|
||||
# Quantity of grapefruits
|
||||
grapefruits: 3
|
||||
}
|
||||
```
|
||||
|
||||
we don't want the comment lines to affect the alignment,
|
||||
so this is usually what we want.
|
||||
|
||||
```
|
||||
{
|
||||
# Quantity of apples
|
||||
apple: 1,
|
||||
# Quantity of bananas
|
||||
bananas: 2,
|
||||
# Quantity of grapefruits
|
||||
grapefruits: 3
|
||||
}
|
||||
```
|
||||
|
||||
However, this default behavior is configurable.
|
||||
|
||||
```vim
|
||||
let g:easy_align_ignore_unmatched = 0
|
||||
```
|
||||
|
||||
Then we get,
|
||||
|
||||
```
|
||||
{
|
||||
# Quantity of apples
|
||||
apple: 1,
|
||||
# Quantity of bananas
|
||||
bananas: 2,
|
||||
# Quantity of grapefruits
|
||||
grapefruits: 3
|
||||
}
|
||||
```
|
||||
See [EXAMPLES.md](https://github.com/junegunn/vim-easy-align/blob/master/EXAMPLES.md)
|
||||
for more examples.
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
[Junegunn Choi](https://github.com/junegunn)
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT
|
||||
|
||||
@@ -1,95 +1,81 @@
|
||||
if exists("g:easy_align_loaded")
|
||||
" Copyright (c) 2013 Junegunn Choi
|
||||
"
|
||||
" MIT License
|
||||
"
|
||||
" Permission is hereby granted, free of charge, to any person obtaining
|
||||
" a copy of this software and associated documentation files (the
|
||||
" "Software"), to deal in the Software without restriction, including
|
||||
" without limitation the rights to use, copy, modify, merge, publish,
|
||||
" distribute, sublicense, and/or sell copies of the Software, and to
|
||||
" permit persons to whom the Software is furnished to do so, subject to
|
||||
" the following conditions:
|
||||
"
|
||||
" The above copyright notice and this permission notice shall be
|
||||
" included in all copies or substantial portions of the Software.
|
||||
"
|
||||
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
if exists("g:loaded_easy_align")
|
||||
finish
|
||||
endif
|
||||
let g:easy_align_loaded = 1
|
||||
let g:loaded_easy_align = 1
|
||||
|
||||
let s:easy_align_delimiters_default = {
|
||||
\ ' ': { 'pattern': ' ', 'margin_left': '', 'margin_right': '', '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 }
|
||||
\ ' ': { 'pattern': ' ', 'left_margin': '', 'right_margin': '', 'stick_to_left': 0 },
|
||||
\ '=': { 'pattern': '===\|<=>\|\(&&\|||\|<<\|>>\)=\|=\~\|=>\|[:+/*!%^=><&|-]\?=[#?]\?',
|
||||
\ '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': '(\@<!{',
|
||||
\ 'left_margin': ' ', 'right_margin': ' ', 'stick_to_left': 0 },
|
||||
\ '}': { 'pattern': '}', 'left_margin': ' ', 'right_margin': '', 'stick_to_left': 0 }
|
||||
\ }
|
||||
|
||||
let s:just = ['', '[R]']
|
||||
|
||||
function! s:do_align(just, fl, ll, fc, lc, pattern, nth, ml, mr, stick_to_left, recursive)
|
||||
let lines = {}
|
||||
let max_just_len = 0
|
||||
let max_delim_len = 0
|
||||
let max_tokens = 0
|
||||
let pattern = '\s*\(' .a:pattern. '\)\s*'
|
||||
for line in range(a:fl, a:ll)
|
||||
let tokens = split(a:lc ?
|
||||
\ strpart(getline(line), a:fc - 1, a:lc - a:fc + 1) :
|
||||
\ strpart(getline(line), a:fc - 1),
|
||||
\ pattern.'\zs')
|
||||
if empty(tokens)
|
||||
continue
|
||||
let s:known_options = {
|
||||
\ '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], 'delimiter_align': [1]
|
||||
\ }
|
||||
|
||||
if exists("*strwidth")
|
||||
function! s:strwidth(str)
|
||||
return strwidth(a:str)
|
||||
endfunction
|
||||
else
|
||||
function! s:strwidth(str)
|
||||
return len(split(a:str, '\zs'))
|
||||
endfunction
|
||||
endif
|
||||
|
||||
function! s:highlighted_as(line, col, groups)
|
||||
if empty(a:groups) | return 0 | endif
|
||||
let hl = synIDattr(synID(a:line, a:col, 0), 'name')
|
||||
for grp in a:groups
|
||||
if hl =~# grp
|
||||
return 1
|
||||
endif
|
||||
|
||||
" Preserve indentation
|
||||
if match(tokens[0], '^\s*$') != -1
|
||||
let tokens = extend([join(tokens[0:1], '')], tokens[2:-1])
|
||||
endif
|
||||
let max_tokens = max([len(tokens), max_tokens])
|
||||
|
||||
if len(tokens) < a:nth
|
||||
continue
|
||||
endif
|
||||
let nth = a:nth - 1 " 0-based
|
||||
|
||||
let last = tokens[nth]
|
||||
let prefix = (nth > 0 ? join(tokens[0 : nth - 1], '') : '')
|
||||
let token = substitute(last, pattern.'$', '', '')
|
||||
let suffix = join(tokens[nth + 1: -1], '')
|
||||
|
||||
if match(last, pattern.'$') == -1
|
||||
if a:just == 0 && (!exists("g:easy_align_ignore_unmatched") || g:easy_align_ignore_unmatched)
|
||||
continue
|
||||
else
|
||||
let delim = ''
|
||||
endif
|
||||
else
|
||||
let delim = matchlist(last, pattern)[1]
|
||||
endif
|
||||
|
||||
let max_just_len = max([len(token.prefix), max_just_len])
|
||||
let max_delim_len = max([len(delim), max_delim_len])
|
||||
let lines[line] = [prefix, token, delim, suffix]
|
||||
endfor
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
for [line, tokens] in items(lines)
|
||||
let [prefix, token, delim, suffix] = tokens
|
||||
|
||||
let pad = repeat(' ', max_just_len - len(prefix) - len(token))
|
||||
if a:just == 0
|
||||
if a:stick_to_left
|
||||
let suffix = pad . suffix
|
||||
else
|
||||
let token = token . pad
|
||||
endif
|
||||
elseif a:just == 1
|
||||
let token = pad . token
|
||||
endif
|
||||
|
||||
let delim = repeat(' ', max_delim_len - len(delim)). delim
|
||||
let cline = getline(line)
|
||||
let before = strpart(cline, 0, a:fc - 1)
|
||||
let after = a:lc ? strpart(cline, a:lc) : ''
|
||||
|
||||
let ml = empty(prefix . token) ? '' : a:ml
|
||||
let mr = (empty(suffix . after) || (empty(suffix) && stridx(after, a:mr) == 0)) ? '' : a:mr
|
||||
let aligned = join([prefix, token, ml, delim, mr, suffix], '')
|
||||
let aligned = empty(after) ? substitute(aligned, '\s*$', '', '') : aligned
|
||||
|
||||
call setline(line, before.aligned.after)
|
||||
endfor
|
||||
|
||||
if a:recursive && a:nth < max_tokens
|
||||
call s:do_align(a:just, a:fl, a:ll, a:fc, a:lc, a:pattern, a:nth + 1, a:ml, a:mr, a:stick_to_left, a:recursive)
|
||||
function! s:ignored_syntax()
|
||||
if has('syntax') && exists('g:syntax_on')
|
||||
" Backward-compatibility
|
||||
return get(g:, 'easy_align_ignores',
|
||||
\ (get(g:, 'easy_align_ignore_comment', 1) == 0) ?
|
||||
\ ['String'] : ['String', 'Comment'])
|
||||
else
|
||||
return []
|
||||
endif
|
||||
endfunction
|
||||
|
||||
@@ -98,79 +84,448 @@ function! s:echon(l, n, d)
|
||||
echon "\rEasyAlign". s:just[a:l] ." (" .a:n.a:d. ")"
|
||||
endfunction
|
||||
|
||||
function! easy_align#align(just, ...) range
|
||||
let just = a:just
|
||||
let recursive = 0
|
||||
let n = ''
|
||||
let ch = ''
|
||||
function! s:exit(msg)
|
||||
echon "\r". a:msg
|
||||
throw 'exit'
|
||||
endfunction
|
||||
|
||||
if a:0 == 0
|
||||
while 1
|
||||
call s:echon(just, n, '')
|
||||
function! s:ltrim(str)
|
||||
return substitute(a:str, '^\s*', '', '')
|
||||
endfunction
|
||||
|
||||
let c = getchar()
|
||||
let ch = nr2char(c)
|
||||
if c == 3 || c == 27
|
||||
return
|
||||
elseif c == 13
|
||||
let just = (just + 1) % len(s:just)
|
||||
elseif c >= 48 && c <= 57
|
||||
if n == '*'
|
||||
break
|
||||
else
|
||||
let n = n . nr2char(c)
|
||||
endif
|
||||
elseif ch == '*'
|
||||
if !empty(n)
|
||||
break
|
||||
else
|
||||
let n = '*'
|
||||
endif
|
||||
else
|
||||
break
|
||||
endif
|
||||
endwhile
|
||||
elseif a:0 == 1
|
||||
let tokens = matchlist(a:1, '^\([1-9][0-9]*\|\*\)\?\(.\)$')
|
||||
if empty(tokens)
|
||||
echo "Invalid arguments: ". a:1
|
||||
return
|
||||
endif
|
||||
let [n, ch] = tokens[1:2]
|
||||
elseif a:0 == 2
|
||||
let n = a:1
|
||||
let ch = a:2
|
||||
else
|
||||
echo "Invalid number of arguments: ". a:0 ." (expected 0, 1, or 2)"
|
||||
return
|
||||
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
|
||||
|
||||
if n == '*'
|
||||
let n = 1
|
||||
let recursive = 1
|
||||
elseif empty(n)
|
||||
let n = 1
|
||||
elseif n != string(str2nr(n))
|
||||
echon "\rInvalid field number: ". n
|
||||
return
|
||||
endif
|
||||
let regexp = '^' . substitute(substitute(a:key, '-', '_', 'g'), '\(.\)', '\1.*', 'g')
|
||||
let matches = filter(keys(s:known_options), 'v:val =~ regexp')
|
||||
|
||||
let delimiters = extend(copy(s:easy_align_delimiters_default),
|
||||
\ exists("g:easy_align_delimiters") ? g:easy_align_delimiters : {})
|
||||
|
||||
if has_key(delimiters, ch)
|
||||
let dict = delimiters[ch]
|
||||
call s:do_align(just, a:firstline, a:lastline,
|
||||
\ visualmode() == '' ? min([col("'<"), col("'>")]) : 1,
|
||||
\ visualmode() == '' ? max([col("'<"), col("'>")]) : 0,
|
||||
\ get(dict, 'pattern', ch),
|
||||
\ n,
|
||||
\ get(dict, 'margin_left', ' '),
|
||||
\ get(dict, 'margin_right', ' '),
|
||||
\ get(dict, 'stick_to_left', 0), recursive)
|
||||
call s:echon(just, (recursive ? '*' : n), ch)
|
||||
if empty(matches)
|
||||
call s:exit("Unknown option key: ". a:key)
|
||||
elseif len(matches) == 1
|
||||
return matches[0]
|
||||
else
|
||||
echon "\rUnknown delimiter: ". ch
|
||||
call s:exit("Ambiguous option key: ". a:key ." (" .join(matches, ', '). ")")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:normalize_options(opts)
|
||||
let ret = {}
|
||||
for k in keys(a:opts)
|
||||
let v = a:opts[k]
|
||||
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
|
||||
unlet v
|
||||
endfor
|
||||
return s:validate_options(ret)
|
||||
endfunction
|
||||
|
||||
function! s:validate_options(opts)
|
||||
for k in keys(a:opts)
|
||||
let v = a:opts[k]
|
||||
if index(s:known_options[k], type(v)) == -1
|
||||
call s:exit("Invalid type for option: ". k)
|
||||
endif
|
||||
unlet v
|
||||
endfor
|
||||
return a:opts
|
||||
endfunction
|
||||
|
||||
function! s:split_line(line, fc, lc, pattern, stick_to_left, ignore_unmatched, ignores)
|
||||
let left = a:lc ?
|
||||
\ strpart(getline(a:line), a:fc - 1, a:lc - a:fc + 1) :
|
||||
\ strpart(getline(a:line), a:fc - 1)
|
||||
let idx = 0
|
||||
" Do not allow \zs
|
||||
" 1: whole match
|
||||
" 2: token
|
||||
" 3: delimiter
|
||||
let pattern = '^\(\(.\{-}\s*\)\(' .a:pattern. '\)\s' . (a:stick_to_left ? '*' : '\{-}') . '\)'
|
||||
let tokens = []
|
||||
let delims = []
|
||||
|
||||
" Phase 1: split
|
||||
let ignorable = 0
|
||||
let token = ''
|
||||
while 1
|
||||
let matches = matchlist(left, pattern, idx)
|
||||
if empty(matches) | break | endif
|
||||
if empty(matches[1])
|
||||
let char = strpart(left, idx, 1)
|
||||
if empty(char) | break | endif
|
||||
let [match, part, delim] = [char, char, '']
|
||||
else
|
||||
let [match, part, delim] = matches[1 : 3]
|
||||
endif
|
||||
|
||||
let ignorable = s:highlighted_as(a:line, idx + len(part) + a:fc, a:ignores)
|
||||
if ignorable
|
||||
let token .= match
|
||||
else
|
||||
call add(tokens, token . match)
|
||||
call add(delims, delim)
|
||||
let token = ''
|
||||
endif
|
||||
|
||||
let idx += len(match)
|
||||
endwhile
|
||||
|
||||
let leftover = token . strpart(left, idx)
|
||||
if !empty(leftover)
|
||||
call add(tokens, leftover)
|
||||
call add(delims, '')
|
||||
endif
|
||||
|
||||
" Preserve indentation - merge first two tokens
|
||||
if len(tokens) > 1 && empty(s:rtrim(tokens[0]))
|
||||
let tokens[1] = tokens[0] . tokens[1]
|
||||
call remove(tokens, 0)
|
||||
call remove(delims, 0)
|
||||
endif
|
||||
|
||||
" Skip comment line
|
||||
if ignorable && len(tokens) == 1 && a:ignore_unmatched
|
||||
let tokens = []
|
||||
let delims = []
|
||||
endif
|
||||
|
||||
return [tokens, delims]
|
||||
endfunction
|
||||
|
||||
function! s:do_align(just, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth, ml, mr, da, stick_to_left, ignore_unmatched, ignores, recursive)
|
||||
let lines = {}
|
||||
let max_just_len = 0
|
||||
let max_delim_len = 0
|
||||
let max_tokens = 0
|
||||
let min_indent = -1
|
||||
|
||||
" Phase 1
|
||||
for line in range(a:fl, a:ll)
|
||||
if !has_key(a:all_tokens, line)
|
||||
" Split line into the tokens by the delimiters
|
||||
let [tokens, delims] = s:split_line(line, a:fc, a:lc, a:pattern, a:stick_to_left, a:ignore_unmatched, a:ignores)
|
||||
|
||||
" Remember tokens for subsequent recursive calls
|
||||
let a:all_tokens[line] = tokens
|
||||
let a:all_delims[line] = delims
|
||||
else
|
||||
let tokens = a:all_tokens[line]
|
||||
let delims = a:all_delims[line]
|
||||
endif
|
||||
|
||||
" Skip empty lines
|
||||
if empty(tokens)
|
||||
continue
|
||||
endif
|
||||
|
||||
" Calculate the maximum number of tokens for a line within the range
|
||||
let max_tokens = max([len(tokens), max_tokens])
|
||||
|
||||
if a:nth > 0 " Positive field number
|
||||
if len(tokens) < a:nth
|
||||
continue
|
||||
endif
|
||||
let nth = a:nth - 1 " make it 0-based
|
||||
else " Negative field number
|
||||
let nth = len(tokens) + a:nth
|
||||
if empty(delims[len(delims) - 1])
|
||||
let nth -= 1
|
||||
endif
|
||||
|
||||
if nth < 0 || nth == len(tokens)
|
||||
continue
|
||||
endif
|
||||
endif
|
||||
|
||||
let prefix = nth > 0 ? join(tokens[0 : nth - 1], '') : ''
|
||||
let delim = delims[nth]
|
||||
let token = s:rtrim( tokens[nth] )
|
||||
let token = s:rtrim( strpart(token, 0, len(token) - len(s:rtrim(delim))) )
|
||||
if empty(delim) && !exists('tokens[nth + 1]') && a:just == 0 && a:ignore_unmatched
|
||||
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]
|
||||
endfor
|
||||
|
||||
" Phase 2
|
||||
for [line, elems] in items(lines)
|
||||
let tokens = a:all_tokens[line]
|
||||
let delims = a:all_delims[line]
|
||||
let [nth, prefix, token, delim] = elems
|
||||
|
||||
" Remove the leading whitespaces of the next token
|
||||
if len(tokens) > nth + 1
|
||||
let tokens[nth + 1] = s:ltrim(tokens[nth + 1])
|
||||
endif
|
||||
|
||||
" Pad the token with spaces
|
||||
let pad = repeat(' ', max_just_len - s:strwidth(prefix) - s:strwidth(token))
|
||||
let rpad = ''
|
||||
if a:just == 0
|
||||
if a:stick_to_left
|
||||
let rpad = pad
|
||||
else
|
||||
let token = token . pad
|
||||
endif
|
||||
elseif a:just == 1
|
||||
let token = pad . token
|
||||
endif
|
||||
let tokens[nth] = token
|
||||
|
||||
" Pad the delimiter
|
||||
let dpadl = max_delim_len - s:strwidth(delim)
|
||||
if a:da ==? 'l'
|
||||
let [dl, dr] = ['', repeat(' ', dpadl)]
|
||||
elseif a:da ==? 'c'
|
||||
let dl = repeat(' ', dpadl / 2)
|
||||
let dr = repeat(' ', dpadl - dpadl / 2)
|
||||
elseif a:da ==? 'r'
|
||||
let [dl, dr] = [repeat(' ', dpadl), '']
|
||||
else
|
||||
call s:exit('Invalid delimiter_align: ' . a:da)
|
||||
endif
|
||||
|
||||
" Before and after the range (for blockwise visual mode)
|
||||
let cline = getline(line)
|
||||
let before = strpart(cline, 0, a:fc - 1)
|
||||
let after = a:lc ? strpart(cline, a:lc) : ''
|
||||
|
||||
" Determine the left and right margin around the delimiter
|
||||
let rest = join(tokens[nth + 1 : -1], '')
|
||||
let ml = empty(prefix . token) ? '' : a:ml
|
||||
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([lpad, token, ml, dl, delim, dr, mr, rpad], '')
|
||||
let tokens[nth] = aligned
|
||||
|
||||
" Update the line
|
||||
let newline = s:rtrim(before.join(tokens, '').after)
|
||||
call setline(line, newline)
|
||||
endfor
|
||||
|
||||
if a:recursive && a:nth < max_tokens
|
||||
let just = a:recursive == 2 ? !a:just : a:just
|
||||
call s:do_align(just, a:all_tokens, a:all_delims, a:fl, a:ll, a:fc, a:lc, a:pattern,
|
||||
\ a:nth + 1, a:ml, a:mr, a:da, a:stick_to_left, a:ignore_unmatched,
|
||||
\ a:ignores, a:recursive)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:interactive(just)
|
||||
let just = a:just
|
||||
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
|
||||
|
||||
function! s:parse_args(args)
|
||||
let n = ''
|
||||
let ch = ''
|
||||
let args = a:args
|
||||
let cand = ''
|
||||
let option = {}
|
||||
|
||||
" Poor man's option parser
|
||||
let idx = 0
|
||||
while 1
|
||||
let midx = match(args, '\s*{.*}\s*$', idx)
|
||||
if midx == -1 | break | endif
|
||||
|
||||
let cand = strpart(args, midx)
|
||||
try
|
||||
let [l, r, c] = ['l', 'r', 'c']
|
||||
let [L, R, C] = ['l', 'r', 'c']
|
||||
let o = eval(cand)
|
||||
if type(o) == 4
|
||||
let option = o
|
||||
if args[midx - 1 : midx] == '\ '
|
||||
let midx += 1
|
||||
endif
|
||||
let args = strpart(args, 0, midx)
|
||||
break
|
||||
endif
|
||||
catch
|
||||
" Ignore
|
||||
endtry
|
||||
let idx = midx + 1
|
||||
endwhile
|
||||
|
||||
" Invalid option dictionary
|
||||
if len(substitute(cand, '\s', '', 'g')) > 2 && empty(option)
|
||||
call s:exit("Invalid option: ". cand)
|
||||
endif
|
||||
|
||||
" Has /Regexp/?
|
||||
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
|
||||
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 empty(n) | let nth = 1
|
||||
elseif n == '0' || ( n != '-0' && n != string(str2nr(n)) )
|
||||
echon "\rInvalid field number: ". n
|
||||
return
|
||||
else
|
||||
let nth = n
|
||||
endif
|
||||
|
||||
let delimiters = s:easy_align_delimiters_default
|
||||
if exists('g:easy_align_delimiters')
|
||||
let delimiters = extend(copy(delimiters), g:easy_align_delimiters)
|
||||
endif
|
||||
|
||||
if regexp
|
||||
let dict = { 'pattern': ch }
|
||||
else
|
||||
" Resolving command-line ambiguity
|
||||
if !empty(a:expr)
|
||||
" '\ ' => ' '
|
||||
if ch =~ '^\\\s\+$'
|
||||
let ch = ' '
|
||||
" '\\' => '\'
|
||||
elseif ch =~ '^\\\\\s*$'
|
||||
let ch = '\'
|
||||
endif
|
||||
endif
|
||||
if !has_key(delimiters, ch)
|
||||
echon "\rUnknown delimiter key: ". ch
|
||||
return
|
||||
endif
|
||||
let dict = delimiters[ch]
|
||||
endif
|
||||
|
||||
try
|
||||
if !empty(option)
|
||||
let dict = extend(copy(dict), s:normalize_options(option))
|
||||
endif
|
||||
catch 'exit'
|
||||
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
|
||||
|
||||
let bvisual = visualmode() == ''
|
||||
|
||||
if recur && bvisual
|
||||
echon "\rRecursive alignment is currently not supported in blockwise-visual mode"
|
||||
return
|
||||
endif
|
||||
|
||||
try
|
||||
call s:do_align(just, {}, {}, a:firstline, a:lastline,
|
||||
\ bvisual ? min([col("'<"), col("'>")]) : 1,
|
||||
\ bvisual ? max([col("'<"), col("'>")]) : 0,
|
||||
\ get(dict, 'pattern', ch),
|
||||
\ nth,
|
||||
\ ml,
|
||||
\ mr,
|
||||
\ get(dict, 'delimiter_align', get(g:, 'easy_align_delimiter_align', 'r')),
|
||||
\ 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)
|
||||
catch 'exit'
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
*easy_align.txt* A simple, easy-to-use Vim alignment plugin
|
||||
|
||||
vim-easy-align *vim-easy-align* *easy-align*
|
||||
=========================================================================
|
||||
|
||||
@@ -7,26 +9,41 @@ A simple, easy-to-use Vim alignment plugin without too much ambition.
|
||||
Source: https://github.com/junegunn/vim-easy-align
|
||||
|
||||
|
||||
EasyAlign *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.
|
||||
(:EasyAlign! is the right-justification version.)
|
||||
|
||||
For convenience, it is advised that you define a mapping for triggering it
|
||||
in your `.vimrc`.
|
||||
| Mode | Command |
|
||||
| ------------------------- | ------------------------------------------- |
|
||||
| Interactive mode | :EasyAlign |
|
||||
| Using predefined rules | :EasyAlign [FIELD#] DELIMITER_KEY [OPTIONS] |
|
||||
| Using regular expressions | :EasyAlign [FIELD#] /REGEXP/ [OPTIONS] |
|
||||
|
||||
|
||||
Interactive mode
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
The command will go into the interactive mode when no argument is given.
|
||||
For convenience, it is advised that you define a mapping for triggering it in
|
||||
your `.vimrc`.
|
||||
|
||||
vnoremap <silent> <Enter> :EasyAlign<cr>
|
||||
|
||||
With this mapping, you can align selected lines with a few keystrokes.
|
||||
With this mapping, you can align selected lines of text with a few keystrokes.
|
||||
|
||||
1. <Enter> key to start interactive EasyAlign command
|
||||
2. Optional Enter keys to switch justficiation mode (default: left)
|
||||
3. Optional field number (default: 1)
|
||||
1 Alignment around 1st delimiters
|
||||
2 Alignment around 2nd delimiters
|
||||
1 Around the 1st occurrences of delimiters
|
||||
2 Around the 2nd occurrences of delimiters
|
||||
* Around all occurrences of delimiters
|
||||
** Left-right alternating alignment around all delimiters
|
||||
- Around the last occurrences of delimiters (`-1`)
|
||||
-2 Around the second to last occurrences of delimiters
|
||||
...
|
||||
* Alignment around all delimiters (recursive)
|
||||
4. Delimiter
|
||||
4. Delimiter key (a single keystroke)
|
||||
<space> General alignment around whitespaces
|
||||
= Operators containing equals sign (=, ==, !=, +=, &&=, ...)
|
||||
: Suitable for formatting JSON or YAML
|
||||
@@ -38,85 +55,242 @@ During the key sequence, <Enter> key will toggle right-justification mode.
|
||||
|
||||
Examples:
|
||||
|
||||
<Enter>= Alignment around 1st equals signs (and the likes)
|
||||
<Enter>2= Alignment around 2nd equals signs (and the likes)
|
||||
<Enter>3= Alignment around 3rd equals signs (and the likes)
|
||||
<Enter>*= Alignment around all equals signs (and the likes)
|
||||
<Enter><Enter>= Right-justified alignment around 1st equals signs
|
||||
<Enter><space> Alignment around 1st whitespace
|
||||
<Enter>2<space> Alignment around 2nd whitespace
|
||||
<Enter>: Alignment around 1st colon
|
||||
<Enter><space> Alignment around 1st whitespaces
|
||||
<Enter>2<space> Alignment around 2nd whitespaces
|
||||
<Enter>-<space> Alignment around the last whitespaces
|
||||
<Enter>: Alignment around 1st colon
|
||||
<Enter>= Alignment around 1st equals signs (and the likes)
|
||||
<Enter>2= Alignment around 2nd equals signs (and the likes)
|
||||
<Enter>3= Alignment around 3rd equals signs (and the likes)
|
||||
<Enter>*= Alignment around all equals signs (and the likes)
|
||||
<Enter>**= Left-right alternating alignment around all equals signs
|
||||
<Enter><Enter>= Right-justified alignment around 1st equals signs
|
||||
<Enter><Enter>**= Right-left alternating alignment around all equals signs
|
||||
|
||||
|
||||
EasyAlignRight *EasyAlignRight*
|
||||
Non-interactive mode
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
EasyAlignRight is the right-justified version of EasyAlign command.
|
||||
Instead of going into the interactive mode, you can 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 in Vim dictionary
|
||||
format.
|
||||
|
||||
- :EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'left_margin': '' }
|
||||
|
||||
Then we get:
|
||||
|
||||
apple;: banana:: cake
|
||||
data;; exchange:; format
|
||||
|
||||
Options keys are fuzzy-matched, so you can write as follows:
|
||||
|
||||
- :EasyAlign * /[:;]\+/ { 'stl': 1, 'l': '' }
|
||||
|
||||
You can even omit spaces between the arguments, so concisely (or cryptically):
|
||||
|
||||
- :EasyAlign*/[:;]\+/{'s':1,'l':''}
|
||||
|
||||
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 |
|
||||
| delimiter_align | string | 'r' |
|
||||
| ignore_unmatched | boolean | 1 |
|
||||
| ignores | array | `['String', 'Comment']` |
|
||||
|
||||
|
||||
Partial alignment in blockwise-visual mode
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
In blockwise-visual mode (`CTRL-V`), EasyAlign command aligns only
|
||||
the selected parts, instead of the whole lines in the range.
|
||||
the selected text in the block, instead of the whole lines in the range.
|
||||
|
||||
|
||||
|
||||
Defining custom alignment rules *g:easy_align_delimiters*
|
||||
Ignoring delimiters in comments or strings *g:easy_align_ignores*
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
let g:easy_align_delimiters = {
|
||||
\ '/': { 'pattern': '//*' },
|
||||
\ 'x': {
|
||||
\ 'pattern': '[xX]',
|
||||
\ 'margin_left': ' <<<',
|
||||
\ 'margin_right': '>>> ',
|
||||
\ 'stick_to_left': 0
|
||||
\ }
|
||||
\ }
|
||||
EasyAlign can be configured to ignore delimiters in certain syntax
|
||||
highlight groups, such as code comments or strings. By default, delimiters
|
||||
that are highlighted as code comments or strings are ignored.
|
||||
|
||||
" Default:
|
||||
" If a delimiter is in a highlight group whose name matches
|
||||
" any of the followings, it will be ignored.
|
||||
let g:easy_align_ignores = ['Comment', 'String']
|
||||
|
||||
Handling unmatched lines *g:easy_align_ignore_unmatched*
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
EasyAlign by default ignores lines without the matching delimiters
|
||||
(except in right-justification mode).
|
||||
This is to ignore interleaved comments commonly found in code.
|
||||
|
||||
For example, when aligning the following code,
|
||||
For example, the following paragraph
|
||||
|
||||
{
|
||||
# Quantity of apples
|
||||
# Quantity of apples: 1
|
||||
apple: 1,
|
||||
# Quantity of bananas
|
||||
# Quantity of bananas: 2
|
||||
bananas: 2,
|
||||
# Quantity of grape:fruits: 3
|
||||
'grape:fruits': 3
|
||||
}
|
||||
|
||||
becomes as follows on `<Enter>:`
|
||||
|
||||
{
|
||||
# Quantity of apples: 1
|
||||
apple: 1,
|
||||
# Quantity of bananas: 2
|
||||
bananas: 2,
|
||||
# Quantity of grape:fruits: 3
|
||||
'grape:fruits': 3
|
||||
}
|
||||
|
||||
Naturally, this feature only works when syntax highlighting is enabled.
|
||||
|
||||
You can change the default rule by either defining global `g:easy_align_ignores`
|
||||
array,
|
||||
|
||||
" Ignore nothing!
|
||||
let g:easy_align_ignores = []
|
||||
|
||||
or providing `ignores` option directly to :EasyAlign command
|
||||
|
||||
:EasyAlign:{'is':[]}
|
||||
|
||||
Then you get,
|
||||
|
||||
{
|
||||
# Quantity of apples: 1
|
||||
apple: 1,
|
||||
# Quantity of bananas: 2
|
||||
bananas: 2,
|
||||
# Quantity of grape: fruits: 3
|
||||
'grape: fruits': 3
|
||||
}
|
||||
|
||||
|
||||
Ignoring unmatched lines *g:easy_align_ignore_unmatched*
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
Lines without any matching delimiter are ignored as well (except in
|
||||
right-justification mode).
|
||||
|
||||
For example, when aligning the following code block around the colons,
|
||||
|
||||
{
|
||||
apple: proc {
|
||||
this_line_does_not_have_a_colon
|
||||
},
|
||||
bananas: 2,
|
||||
# Quantity of grapefruits
|
||||
grapefruits: 3
|
||||
}
|
||||
|
||||
this is usually what we want.
|
||||
|
||||
{
|
||||
# Quantity of apples
|
||||
apple: 1,
|
||||
# Quantity of bananas
|
||||
apple: proc {
|
||||
this_line_does_not_have_a_colon
|
||||
},
|
||||
bananas: 2,
|
||||
# Quantity of grapefruits
|
||||
grapefruits: 3
|
||||
}
|
||||
|
||||
However, this default behavior is configurable.
|
||||
However, this default behavior is also configurable.
|
||||
|
||||
One way is to set the global `g:easy_align_ignore_unmatched` variable to 0.
|
||||
|
||||
let g:easy_align_ignore_unmatched = 0
|
||||
|
||||
Or in non-interactive mode, you can provide `ignore_unmatched` option to
|
||||
`:EasyAlign` command as follows.
|
||||
|
||||
:EasyAlign:{'iu':0}
|
||||
|
||||
|
||||
Then we get,
|
||||
|
||||
{
|
||||
# Quantity of apples
|
||||
apple: 1,
|
||||
# Quantity of bananas
|
||||
bananas: 2,
|
||||
# Quantity of grapefruits
|
||||
grapefruits: 3
|
||||
apple: proc {
|
||||
this_line_does_not_have_a_colon
|
||||
},
|
||||
bananas: 2,
|
||||
grapefruits: 3
|
||||
}
|
||||
|
||||
|
||||
|
||||
Aligning delimiters of different lengths *g:easy_align_delimiter_align*
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
Global `g:easy_align_delimiter_align` option and rule-wise/command-wise
|
||||
`delimiter_align` option determines how matched delimiters of different
|
||||
lengths are aligned.
|
||||
|
||||
apple = 1
|
||||
banana += apple
|
||||
cake ||= banana
|
||||
|
||||
By default, delimiters are right-aligned as follows.
|
||||
|
||||
apple = 1
|
||||
banana += apple
|
||||
cake ||= banana
|
||||
|
||||
However, with `:EasyAlign={'da':l}`, delimiters are left-aligned.
|
||||
|
||||
apple = 1
|
||||
banana += apple
|
||||
cake ||= banana
|
||||
|
||||
And on `:EasyAlign={'da':c}`, center-aligned.
|
||||
|
||||
apple = 1
|
||||
banana += apple
|
||||
cake ||= banana
|
||||
|
||||
Extending alignment rules *g:easy_align_delimiters*
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
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`.
|
||||
|
||||
let g:easy_align_delimiters = {
|
||||
\ '>': { 'pattern': '>>\|=>\|>' },
|
||||
\ '/': { 'pattern': '//\+\|/\*\|\*/', 'ignores': ['String'] },
|
||||
\ '#': { 'pattern': '#\+', 'ignores': ['String'] },
|
||||
\ ']': {
|
||||
\ 'pattern': '[\[\]]',
|
||||
\ 'left_margin': 0,
|
||||
\ 'right_margin': 0,
|
||||
\ 'stick_to_left': 0
|
||||
\ },
|
||||
\ ')': {
|
||||
\ 'pattern': '[()]',
|
||||
\ 'left_margin': 0,
|
||||
\ 'right_margin': 0,
|
||||
\ 'stick_to_left': 0
|
||||
\ }
|
||||
\ }
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,29 @@
|
||||
if exists("g:easy_align_plugin_loaded")
|
||||
" Copyright (c) 2013 Junegunn Choi
|
||||
"
|
||||
" MIT License
|
||||
"
|
||||
" Permission is hereby granted, free of charge, to any person obtaining
|
||||
" a copy of this software and associated documentation files (the
|
||||
" "Software"), to deal in the Software without restriction, including
|
||||
" without limitation the rights to use, copy, modify, merge, publish,
|
||||
" distribute, sublicense, and/or sell copies of the Software, and to
|
||||
" permit persons to whom the Software is furnished to do so, subject to
|
||||
" the following conditions:
|
||||
"
|
||||
" The above copyright notice and this permission notice shall be
|
||||
" included in all copies or substantial portions of the Software.
|
||||
"
|
||||
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
if exists("g:loaded_easy_align_plugin")
|
||||
finish
|
||||
endif
|
||||
let g:easy_align_plugin_loaded = 1
|
||||
let g:loaded_easy_align_plugin = 1
|
||||
|
||||
command! -nargs=* -range EasyAlign <line1>,<line2>call easy_align#align(0, <f-args>)
|
||||
command! -nargs=* -range EasyAlignRight <line1>,<line2>call easy_align#align(1, <f-args>)
|
||||
command! -nargs=* -range -bang EasyAlign <line1>,<line2>call easy_align#align('<bang>' == '!', <q-args>)
|
||||
|
||||
506
test/basic.expected
Normal file
506
test/basic.expected
Normal file
@@ -0,0 +1,506 @@
|
||||
" :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
|
||||
|
||||
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
|
||||
|
||||
```
|
||||
|
||||
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 <|
|
||||
|
||||
```c
|
||||
|
||||
const char* str = "Hello";
|
||||
int64_t count = 1 + 2;
|
||||
static double pi = 3.14;
|
||||
static std::map<std::string, float>* scores = pointer;
|
||||
|
||||
```
|
||||
|
||||
Paul<<< McCartney{{{ 1942
|
||||
George<<< Harrison {{{ 1943
|
||||
Ringo<<< Starr {{{ 1940
|
||||
Pete<<< Best {{{ 1941
|
||||
|
||||
Paul McCartney 1942
|
||||
George Harrison 1943
|
||||
Ringo Starr 1940
|
||||
Pete Best 1941
|
||||
|
||||
... - . -----
|
||||
.. -- .. ----
|
||||
. --- ... ---
|
||||
---- .... --
|
||||
. --- ..... -
|
||||
.. -- ......
|
||||
... - ..... -
|
||||
|
||||
... - . -----
|
||||
.. -- .. ----
|
||||
. --- ... ---
|
||||
---- .... --
|
||||
. --- ..... -
|
||||
.. -- ......
|
||||
... - ..... -
|
||||
|
||||
... - . -----
|
||||
.. -- .. ----
|
||||
. --- ... ---
|
||||
---- .... --
|
||||
. --- ..... -
|
||||
.. -- ......
|
||||
... - ..... -
|
||||
|
||||
... - . -----
|
||||
.. -- .. ----
|
||||
. --- ... ---
|
||||
---- .... --
|
||||
. --- ..... -
|
||||
.. -- ......
|
||||
... - ..... -
|
||||
|
||||
... - .-----
|
||||
.. -- ..----
|
||||
. --- ...---
|
||||
---- ....--
|
||||
. --- .....-
|
||||
.. -- ......
|
||||
... - .....-
|
||||
|
||||
... - . -----
|
||||
.. -- .. ----
|
||||
. --- ... ---
|
||||
---- .... --
|
||||
. --- ..... -
|
||||
.. -- ......
|
||||
... - ..... -
|
||||
|
||||
... - .-----
|
||||
.. -- ..----
|
||||
. --- ...---
|
||||
---- ....--
|
||||
. --- .....-
|
||||
.. -- ......
|
||||
... - .....-
|
||||
|
||||
... - .-----
|
||||
.. -- ..----
|
||||
. --- ...---
|
||||
---- ....--
|
||||
. --- .....-
|
||||
.. -- ......
|
||||
... - .....-
|
||||
|
||||
...-.-----
|
||||
..--..----
|
||||
.---...---
|
||||
----....--
|
||||
.---.....-
|
||||
..--......
|
||||
...-.....-
|
||||
|
||||
... - . -----
|
||||
.. -- .. ----
|
||||
. --- ... ---
|
||||
---- .... --
|
||||
. --- ..... -
|
||||
.. -- ......
|
||||
... - ..... -
|
||||
|
||||
... - .-----
|
||||
.. -- ..----
|
||||
. --- ...---
|
||||
---- ....--
|
||||
. --- .....-
|
||||
.. -- ......
|
||||
... - .....-
|
||||
|
||||
... - . -----
|
||||
.. -- .. ----
|
||||
. --- ... ---
|
||||
---- .... --
|
||||
. --- ..... -
|
||||
.. -- ......
|
||||
... - ..... -
|
||||
|
||||
... - . -----
|
||||
.. -- .. ----
|
||||
. --- ... ---
|
||||
---- .... --
|
||||
. --- ..... -
|
||||
.. -- ......
|
||||
... - ..... -
|
||||
|
||||
...-. -----
|
||||
..--.. ----
|
||||
.---... ---
|
||||
----.... --
|
||||
.---..... -
|
||||
..--......
|
||||
...-..... -
|
||||
|
||||
... - .-----
|
||||
.. -- ..----
|
||||
. --- ...---
|
||||
---- ....--
|
||||
. --- .....-
|
||||
.. -- ......
|
||||
... - .....-
|
||||
|
||||
132
test/basic.md
Normal file
132
test/basic.md
Normal file
@@ -0,0 +1,132 @@
|
||||
" :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
|
||||
|
||||
```
|
||||
|
||||
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 |
|
||||
|
||||
|
||||
```c
|
||||
|
||||
const char* str = "Hello";
|
||||
int64_t count = 1 + 2;
|
||||
static double pi = 3.14;
|
||||
static std::map<std::string, float>* scores = pointer;
|
||||
|
||||
```
|
||||
|
||||
Paul McCartney 1942
|
||||
George Harrison 1943
|
||||
Ringo Starr 1940
|
||||
Pete Best 1941
|
||||
|
||||
...-.-----
|
||||
..--..----
|
||||
.---...---
|
||||
----....--
|
||||
.---.....-
|
||||
..--......
|
||||
...-.....-
|
||||
|
||||
1
test/basic.script
Normal file
1
test/basic.script
Normal file
@@ -0,0 +1 @@
|
||||
4Gvipjyvip
|
||||
44
test/include.vim
Normal file
44
test/include.vim
Normal file
@@ -0,0 +1,44 @@
|
||||
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'
|
||||
|
||||
syntax sync fromstart
|
||||
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()
|
||||
|
||||
96
test/regexp.expected
Normal file
96
test/regexp.expected
Normal file
@@ -0,0 +1,96 @@
|
||||
" :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
|
||||
|
||||
```ruby
|
||||
apple = 1 # comment not aligned
|
||||
apricot = 'DAD' + 'F#AD'
|
||||
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
|
||||
|
||||
12
test/regexp.md
Normal file
12
test/regexp.md
Normal file
@@ -0,0 +1,12 @@
|
||||
" :source run.vim
|
||||
" @a
|
||||
|
||||
apple;:banana::cake
|
||||
data;;exchange:;format
|
||||
|
||||
```ruby
|
||||
apple = 1 # comment not aligned
|
||||
apricot = 'DAD' + 'F#AD'
|
||||
banana = 'Gros Michel' # comment 2
|
||||
```
|
||||
|
||||
1
test/regexp.script
Normal file
1
test/regexp.script
Normal file
@@ -0,0 +1 @@
|
||||
4Gvipjyvip:EasyAlign:
|
||||
7
test/run.vim
Normal file
7
test/run.vim
Normal file
@@ -0,0 +1,7 @@
|
||||
e!
|
||||
execute 'source '. expand('%:p:h') . '/include.vim'
|
||||
|
||||
normal gg
|
||||
let @b=system('cat '. expand('%:p:r') . '.script')
|
||||
let @a='@b:vert diffsplit ' . expand('%:p:r') . '.expected
|
||||
'
|
||||
Reference in New Issue
Block a user