65 Commits
2.1.0 ... 2.5.1

Author SHA1 Message Date
Junegunn Choi
e4f86274e3 Update install instructions 2013-09-22 23:04:20 +09:00
Junegunn Choi
2d575bcc25 Underscore between parens 2013-09-22 22:56:27 +09:00
Junegunn Choi
8a783c2125 Fix a failure in test due to change in interactive mode 2013-09-22 22:21:23 +09:00
Junegunn Choi
5230a2402f Disallow 0 as the first character of N-th 2013-09-22 21:58:31 +09:00
Junegunn Choi
94a750e03e Remove unnecessary prev output wipe 2013-09-22 21:48:14 +09:00
Junegunn Choi
afc95b5ed7 Forgiving interactive mode: Do not terminate on invalid input 2013-09-22 21:17:02 +09:00
Junegunn Choi
1d2c58c06a Field index -> N-th parameter 2013-09-22 03:52:36 +09:00
Junegunn Choi
4cdc450126 Update DEMO.md 2013-09-21 23:53:47 +09:00
Junegunn Choi
7e1be152dc Add DEMO.md 2013-09-21 15:46:40 +09:00
Junegunn Choi
c61a11d150 Update doc
- Field number -> Field index
2013-09-21 13:08:55 +09:00
Junegunn Choi
2797baca6c Disallow non-printable character input 2013-09-21 12:04:56 +09:00
Junegunn Choi
663264ed39 Fix center-alignment
= = eee   = eee = f
= = gg  &&= gg
= = fff

= = eee   = eee = f
= = gg  &&= gg
= = f f
2013-09-21 03:31:34 +09:00
Junegunn Choi
df75520f72 Colored, replayable output 2013-09-21 03:11:20 +09:00
Junegunn Choi
a2d52611ee Fix invalid type conversion 2013-09-20 23:19:32 +09:00
Junegunn Choi
fce0a103ff Use try-finally for reverting the setup 2013-09-19 17:27:26 +09:00
Junegunn Choi
1752bf567b Improve message output
- Error message highlighting
- Wipe previous message if needed
- No line wrap on narrow terminal
2013-09-19 17:10:00 +09:00
Junegunn Choi
003194a47f Update example command sequences 2013-09-18 16:18:03 +09:00
Junegunn Choi
c1c6f32e8c Update example command sequence 2013-09-18 15:50:19 +09:00
Junegunn Choi
71edb17182 Update help file 2013-09-17 23:36:58 +09:00
Junegunn Choi
8951e13cf8 Update documentation 2013-09-17 23:32:41 +09:00
Junegunn Choi
a998aee45d Update README.md 2013-09-17 15:57:41 +09:00
Junegunn Choi
912bf6ca93 Update README.md 2013-09-17 15:54:33 +09:00
Junegunn Choi
9cf4fde00c Use number as margins (same effect, but easier to read) 2013-09-17 03:12:30 +09:00
Junegunn Choi
5f5cd49e95 Update README.md 2013-09-17 03:05:43 +09:00
Junegunn Choi
639ade715b Wording 2013-09-15 19:59:36 +09:00
Junegunn Choi
a1f2a697a5 Update README 2013-09-15 19:49:26 +09:00
Junegunn Choi
0fb127cee6 Update doc 2013-09-15 01:28:42 +09:00
Junegunn Choi
d3803b927d Heuristically determine if the user was in visual mode 2013-09-14 23:15:03 +09:00
Junegunn Choi
40a06e3d36 Left arrow key will also set left_margin to zero
- Right arrow key will set left_margin to one
- Up and Down arrow will clear the values of stick_to_left and left_margin
2013-09-14 17:30:51 +09:00
Junegunn Choi
11e0623959 DASH, not LI 2013-09-14 17:23:08 +09:00
Junegunn Choi
e9b6418280 Concept of alignment rule 2013-09-14 17:20:14 +09:00
Junegunn Choi
9f9d18ca71 Fix #8, #9, and #10.
- <Left> and <Right> key to toggle stick_to_left option
- <CTRL-X> in addition to <CTRL-/> to take regular expression
- Retain visual selection display on <CTRL-O/L/R/X>
2013-09-14 12:31:01 +09:00
Junegunn Choi
301bdbcfc7 Regular expression in interactive mode (#8) 2013-09-14 00:40:16 +09:00
Junegunn Choi
56e498a57d Implement mode_sequence expansion (#7) 2013-09-14 00:05:08 +09:00
Junegunn Choi
c0a500728c Update README 2013-09-13 10:34:16 +09:00
Junegunn Choi
2e0f9a73cd Update README.md 2013-09-13 10:26:38 +09:00
Junegunn Choi
6cac16dc3d Include =~# and =~? in = rule (Vimscript) 2013-08-25 23:03:30 +09:00
Junegunn Choi
6b275b8a46 Revert C-style variable definition example 2013-08-23 17:55:35 +09:00
Junegunn Choi
25fec2e955 Implement stick_to_left in center-alignment mode 2013-08-23 17:47:03 +09:00
Junegunn Choi
01337b9c4e Include .= operator in = rule 2013-08-23 17:40:13 +09:00
Junegunn Choi
0f70b20fdb Add related work section (#6) 2013-08-23 13:14:03 +09:00
Junegunn Choi
61be5b3abf Update doc 2013-08-23 01:37:50 +09:00
Junegunn Choi
2ad49b24f0 Add CTRL-O special key for mode_sequence option 2013-08-23 00:09:21 +09:00
Junegunn Choi
5058de6f4c Retain lm and rm values on CTRL-L and CTRL-R 2013-08-22 23:47:25 +09:00
Junegunn Choi
4c5d6d9e82 Improve center-alignment: ignore leading whitespaces 2013-08-22 23:41:21 +09:00
Junegunn Choi
12c319a8ac Implement special keys to switch option values in interactive mode
With this commit, we can now change option values in interactive mode with the
folowing special keys

- CTRL-L  left_margin
- CTRL-R  right_margin
- CTRL-D  delimiter_align
- CTRL-I  indentation
- CTRL-U  ignore_unmatched
- CTRL-G  ignore_groups

('ignores' option has been renamed to 'ignore_groups', but backward-compatible)
2013-08-20 01:38:20 +09:00
Junegunn Choi
62314afcaf Fix typo 2013-08-19 15:16:19 +09:00
Junegunn Choi
cef26cdef9 Update EXAMPLES 2013-08-19 14:59:35 +09:00
Junegunn Choi
659e2ff513 Update README 2013-08-19 10:57:21 +09:00
Junegunn Choi
481a88f601 Update README 2013-08-19 04:21:02 +09:00
Junegunn Choi
6fb4f57b5a Add test cases for center-alignment 2013-08-19 04:14:56 +09:00
Junegunn Choi
beb986ebc3 Update documentation 2013-08-19 04:06:36 +09:00
Junegunn Choi
5222db47cf Rename align_mode to mode_sequence 2013-08-19 02:37:46 +09:00
Junegunn Choi
74003c0297 Allow interactive mode with options 2013-08-19 02:25:38 +09:00
Junegunn Choi
999e1ff68e Implement center-align mode and align_modes option 2013-08-19 02:09:34 +09:00
Junegunn Choi
11a74c4176 Fix right-justification for lines with different indentation 2013-08-16 23:47:01 +09:00
Junegunn Choi
e7e7a80afb Update doc 2013-08-16 17:58:05 +09:00
Junegunn Choi
29e5cd1d19 Add the link to slower GIF 2013-08-16 15:03:57 +09:00
Junegunn Choi
5c6558bd1b Improve right-justification mode
With this commit you can right-align the last token with * or ** field number.
For example, the following lines
    a = 1
    bb = 22
    ccc = 333
are aligned as follows on `:EasyAlign**=`
    a   =   1
    bb  =  22
    ccc = 333
And even if we don't have the second =, we can do `:EasyAlign!2=` to get
    a =     1
    bb =   22
    ccc = 333
2013-08-16 13:58:28 +09:00
Junegunn Choi
b6625f6d2b Fix: Unmatched token incorrectly ignored in right-justification mode 2013-08-16 09:37:04 +09:00
Junegunn Choi
d4277a0298 Fix a typo 2013-08-16 03:12:36 +09:00
Junegunn Choi
d31e6ed257 Update README 2013-08-16 02:37:24 +09:00
Junegunn Choi
1e2af43a64 Ignore unmatched line on right-justification mode
Unmatched line is NOT ignored on right-justification mode. However this
commit makes such a line ignored when the end of the line is highlighted
as one of the ignored syntax groups (e.g. Comments or Strings)
2013-08-16 02:23:00 +09:00
Junegunn Choi
0fb997d5ab Add g:easy_align_indentation. Add n indentation option. 2013-08-16 01:38:50 +09:00
Junegunn Choi
90a5487974 Add indentation option 2013-08-16 00:15:57 +09:00
12 changed files with 1957 additions and 347 deletions

91
DEMO.md Normal file
View File

@@ -0,0 +1,91 @@
# vim: set buftype=nofile colorcolumn= scrolloff=0 noshowcmd:
vim-easy-align
==============
Where's Lennon?
---------------
Paul McCartney 1942
George Harrison 1943
Ringo Starr 1940
Pete Best 1941
Formatting table
----------------
```
| 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 processing |
|batch | Boolean | false | enables batch processing mode |
|batch_size | Fixnum | nil | maximum number of items in batch|
|logger | Logger | nil | logger instance for debug logs |
```
Operators with = sign
---------------------
```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)
-------------------------
```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
```
Using blockwise-visual mode or negative N-th parameter
------------------------------------------------------
```ruby
options = { :caching => nil,
:versions => 3,
"cache=blocks" => false }.merge(options)
```
Commas
------
aaa, bb,c
d,eeeeeee
fffff, gggggggggg,
h, , ii
j,,k

View File

@@ -41,6 +41,7 @@ Try these commands:
- `<Enter>-2<space>`
- `<Enter><Enter><space>`
- `<Enter><Enter>*<space>`
- `<Enter><Enter><Enter>*<space>`
### Example
@@ -61,6 +62,7 @@ Try these commands:
- `<Enter>**|`
- `<Enter><Enter>*|`
- `<Enter><Enter>**|`
- `<Enter><Enter><Enter>*|`
### Example
@@ -90,6 +92,7 @@ Try these commands:
- `<Enter>*=`
- `<Enter>**=`
- `<Enter><Enter>**=`
- `<Enter><Enter><Enter>*=`
### Example
@@ -163,8 +166,8 @@ my_object
```
Using blockwise-visual mode or negative field index
---------------------------------------------------
Using blockwise-visual mode or negative N-th parameter
------------------------------------------------------
You can try either:
- select text around `=>` in blockwise-visual mode (`CTRL-V`) and `<Enter>=`
@@ -237,10 +240,10 @@ So, let's define a custom mapping for `#`.
if !exists('g:easy_align_delimiters')
let g:easy_align_delimiters = {}
endif
let g:easy_align_delimiters['#'] = { 'pattern': '#', 'ignores': ['String'] } }
let g:easy_align_delimiters['#'] = { 'pattern': '#', 'ignore_groups': ['String'] }
```
Notice that the rule overrides `ignores` attribute in order *not to ignore*
Notice that the rule overrides `ignore_groups` attribute in order *not to ignore*
delimiters highlighted as comments.
Then on `<Enter>#`, we get
@@ -282,7 +285,7 @@ let g:easy_align_ignore_unmatched = 0
" 3. Update the alignment rule with ignore_unmatched option
let g:easy_align_delimiters['#'] = {
\ 'pattern': '#', 'ignores': ['String'], 'ignore_unmatched': 0 } }
\ 'pattern': '#', 'ignore_groups': ['String'], 'ignore_unmatched': 0 }
```
Then we get,

449
README.md
View File

@@ -1,17 +1,19 @@
vim-easy-align
==============
A simple, easy-to-use Vim alignment plugin without too much ambition.
A simple, easy-to-use Vim alignment plugin.
Demo
----
![Screencast](https://raw.github.com/junegunn/vim-easy-align/gif/vim-easy-align.gif)
(Too fast? Slower GIF is [here](https://raw.github.com/junegunn/vim-easy-align/gif/vim-easy-align-slow.gif))
Features
--------
- Makes the common case easy
- Easy to use
- Comes with a predefined set of alignment rules
- Provides a fast and intuitive interface
- Extensible
@@ -20,34 +22,53 @@ Features
- Optimized for code editing
- Takes advantage of syntax highlighting feature to avoid unwanted alignments
### _"I already have a similar one. Should I switch?"_
Maybe or maybe not. See [related work](https://github.com/junegunn/vim-easy-align#related-work) section.
Installation
------------
Either [download zip file](http://www.vim.org/scripts/script.php?script_id=4520)
and extract in ~/.vim or use [Vundle](https://github.com/gmarik/vundle) (recommended)
or [Pathogen](https://github.com/tpope/vim-pathogen).
and extract in ~/.vim or
[use](https://github.com/tpope/vim-pathogen)
[your](https://github.com/gmarik/vundle)
[favorite](https://github.com/junegunn/vim-plug)
[plugin](https://github.com/Shougo/neobundle.vim)
[manager](https://github.com/MarcWeber/vim-addon-manager).
### With Vundle
Add the following line to your .vimrc,
```vim
Bundle 'junegunn/vim-easy-align'
```
then execute `:BundleInstall` command.
- [Pathogen](https://github.com/tpope/vim-pathogen)
- `git clone https://github.com/junegunn/vim-easy-align.git ~/.vim/bundle/vim-easy-align`
- [Vundle](https://github.com/gmarik/vundle)
1. Add `Bundle 'junegunn/vim-easy-align'` to .vimrc
2. Run `:BundleInstall`
- [NeoBundle](https://github.com/Shougo/neobundle.vim)
1. Add `NeoBundle 'junegunn/vim-easy-align'` to .vimrc
2. Run `:NeoBundleInstall`
- [vim-plug](https://github.com/junegunn/vim-plug)
1. Add `Plug 'junegunn/vim-easy-align'` to .vimrc
2. Run `:PlugInstall`
Usage
-----
_vim-easy-align_ defines `:EasyAlign` command (and the right-justification
variant `:EasyAlign!`) in the visual mode.
_vim-easy-align_ defines `:EasyAlign` command (and the right-align
variant `:EasyAlign!`) for visual mode.
| Mode | Command |
| ------------------------- | --------------------------------------------- |
| Interactive mode | `:EasyAlign` |
| Using predefined rules | `:EasyAlign [FIELD#] DELIMITER_KEY [OPTIONS]` |
| Using regular expressions | `:EasyAlign [FIELD#] /REGEXP/ [OPTIONS]` |
| Mode | Command |
| ------------------------- | ------------------------------------------------ |
| Interactive mode | `:EasyAlign[!] [OPTIONS]` |
| Using predefined rules | `:EasyAlign[!] [N-th] DELIMITER_KEY [OPTIONS]` |
| Using regular expressions | `:EasyAlign[!] [N-th] /REGEXP/ [OPTIONS]` |
### Concept of _alignment rule_
An *alignment rule* is a predefined set of options for common alignment tasks,
which is identified by a single character, *DELIMITER KEY*, such as `<space>`,
`=`, `:`, `.`, `|`, and `,`.
Think of it as a shortcut. Instead of writing regular expression and setting
several options, you can just type in a single character.
### Interactive mode
@@ -59,11 +80,13 @@ your `.vimrc`.
vnoremap <silent> <Enter> :EasyAlign<cr>
```
(Of course you can use any key combination as the trigger. e.g. `<Leader>a`)
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. Optional: Enter keys to select alignment mode (left, right, or center)
1. Optional: N-th delimiter (default: 1)
- `1` Around the 1st occurrences of delimiters
- `2` Around the 2nd occurrences of delimiters
- ...
@@ -85,35 +108,80 @@ Alignment rules for the following delimiters have been defined to meet the most
| `,` | Multi-line method arguments |
| &#124; | Table markdown |
You can override these default rules or define your own rules with
`g:easy_align_delimiters`, which will be described in
[the later section](https://github.com/junegunn/vim-easy-align#extending-alignment-rules).
#### Example command sequences
| 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!**=` |
| ... | ... | |
| 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>-2<space>` | Alignment around the 2nd to last whitespaces | `:'<,'>EasyAlign-2\ ` |
| `<Enter>:` | Alignment around 1st colon (`key: value`) | `:'<,'>EasyAlign:` |
| `<Enter><Right>:` | Alignment around 1st colon (`key : value`) | `:'<,'>EasyAlign:{'s':0,'l':1}` |
| `<Enter>=` | Alignment around 1st operators with = | `:'<,'>EasyAlign=` |
| `<Enter>2=` | Alignment around 2nd operators with = | `:'<,'>EasyAlign2=` |
| `<Enter>3=` | Alignment around 3rd operators with = | `:'<,'>EasyAlign3=` |
| `<Enter>*=` | Alignment around all operators with = | `:'<,'>EasyAlign*=` |
| `<Enter>**=` | Left-right alternating alignment around all = operators | `:'<,'>EasyAlign**=` |
| `<Enter><Enter>=` | Right alignment around 1st equals signs | `:'<,'>EasyAlign!=` |
| `<Enter><Enter>**=` | Right-left alternating alignment around all = operators | `:'<,'>EasyAlign!**=` |
#### Using regular expressions
Instead of finishing the command with a predefined delimiter key, you can type
in a regular expression after `<CTRL-/>` or `<CTRL-X>` key.
For example, if you want to align text around all occurrences of numbers:
- `<Enter>`
- `*`
- `<CTRL-/>` (or `<CTRL-X>` on GVim)
- `[0-9]\+`
#### Alignment options in interactive mode
While in interactive mode, you can set alignment options using special shortcut
keys listed below. The meaning of each option will be described in
[the following sections](https://github.com/junegunn/vim-easy-align#alignment-options).
| Key | Option | Values |
| -------- | ------------------ | -------------------------------------------------- |
| `CTRL-I` | `indentation` | shallow, deep, none, keep |
| `CTRL-L` | `left_margin` | Input number or string |
| `CTRL-R` | `right_margin` | Input number or string |
| `CTRL-D` | `delimiter_align` | left, center, right |
| `CTRL-U` | `ignore_unmatched` | 0, 1 |
| `CTRL-G` | `ignore_groups` | [], ['String'], ['Comment'], ['String', 'Comment'] |
| `CTRL-O` | `mode_sequence` | Input string of `/[lrc]+\*{0,2}/` |
| `<Left>` | `stick_to_left` | `{ 'stick_to_left': 1, 'left_margin': 0 }` |
| `<Right>` | `stick_to_left` | `{ 'stick_to_left': 0, 'left_margin': 1 }` |
---
### *Intermission*
You can stop reading here. Trust me. All the fancy features described in the
following sections are really powerful but you won't be needing them in most
of the cases.
Go try out vim-easy-align right now, and come back later when you feel like it.
---
### 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.
`:EasyAlign` command.
```vim
" Using predefined alignment rules
:EasyAlign[!] [FIELD#] DELIMITER_KEY [OPTIONS]
:EasyAlign[!] [N-th] DELIMITER_KEY [OPTIONS]
" Using arbitrary regular expressions
:EasyAlign[!] [FIELD#] /REGEXP/ [OPTIONS]
:EasyAlign[!] [N-th] /REGEXP/ [OPTIONS]
```
For example, when aligning the following lines around colons and semi-colons,
@@ -132,14 +200,14 @@ 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': '' }`
- `:EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'left_margin': 0 }`
Then we get:
apple;: banana:: cake
data;; exchange:; format
Options keys are fuzzy-matched, so you can write as follows:
Option names are fuzzy-matched, so you can write as follows:
- `:EasyAlign * /[:;]\+/ { 'stl': 1, 'l': 0 }`
@@ -147,7 +215,14 @@ 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.
The same thing can be done in the interactive mode as well with the following
key combination.
- `<Enter>`
- `*`
- `<Left>`
- `<CTRL-/>` (or `<CTRL-X>` on GVim)
- `[:;]\+`
### Partial alignment in blockwise-visual mode
@@ -174,37 +249,43 @@ my_hash = { :a => 1,
```
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 N-th parameter: `<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 |
| Option | Type | Default | Description |
| ------------------ | ------- | --------------------- | ------------------------------------------------------- |
| `left_margin` | number | 1 | Number of spaces to attach before delimiter |
| `left_margin` | string | `' '` | String to attach before delimiter |
| `right_margin` | number | 1 | 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_groups` | list | ['String', 'Comment'] | Delimiters in these syntax highlight groups are ignored |
| `ignore_unmatched` | boolean | 1 | Whether to ignore lines without matching delimiter |
| `indentation` | string | `k` | Indentation method (*k*eep, *d*eep, *s*hallow, *n*one) |
| `delimiter_align` | string | `r` | Determines how to align delimiters of different lengths |
| `mode_sequence` | string | | Alignment modes for multiple occurrences of delimiters |
Some of the options can be specified using corresponding global variables.
There are 4 ways to set alignment options (from lowest precedence to highest):
| Option | Global variable |
| ------------------ | ------------------------------- |
| `ignore_unmatched` | `g:easy_align_ignore_unmatched` |
| `ignores` | `g:easy_align_ignores` |
| `delimiter_align` | `g:easy_align_delimiter_align` |
1. Some option values can be set with corresponding global variables
2. Option values can be specified in the definition of each alignment rule
3. Option values can be given as a dictionary argument to `:EasyAlign` command
4. Option values can be set in interactive mode using special shortcut keys
| Option | Shortcut key | Global variable |
| ------------------ | ------------------- | ------------------------------- |
| `left_margin` | `CTRL-L` | |
| `right_margin` | `CTRL-R` | |
| `stick_to_left` | `<Left>`, `<Right>` | |
| `ignore_groups` | `CTRL-G` | `g:easy_align_ignore_groups` |
| `ignore_unmatched` | `CTRL-U` | `g:easy_align_ignore_unmatched` |
| `indentation` | `CTRL-I` | `g:easy_align_indentation` |
| `delimiter_align` | `CTRL-D` | `g:easy_align_delimiter_align` |
| `mode_sequence` | `CTRL-O` | |
### Ignoring delimiters in comments or strings
@@ -216,7 +297,7 @@ 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']
let g:easy_align_ignore_groups = ['Comment', 'String']
```
For example, the following paragraph
@@ -247,13 +328,15 @@ becomes as follows on `<Enter>:` (or `:EasyAlign:`)
Naturally, this feature only works when syntax highlighting is enabled.
You can change the default rule by using one of these 3 methods.
You can change the default rule by using one of these 4 methods.
1. Define global `g:easy_align_ignores` list
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':[]}`
1. Press `CTRL-G` in interactive mode to switch groups
2. Define global `g:easy_align_ignore_groups` list
3. Define a custom rule in `g:easy_align_delimiters` with `ignore_groups` option
4. Provide `ignore_groups` option to `:EasyAlign` command.
e.g. `:EasyAlign:{'ig':[]}`
For example if you set `ignores` option to be an empty list, you get
For example if you set `ignore_groups` option to be an empty list, you get
```ruby
{
@@ -271,7 +354,7 @@ Satisfied? :satisfied:
### Ignoring unmatched lines
Lines without any matching delimiter are ignored as well (except in
right-justification mode).
right-align mode).
For example, when aligning the following code block around the colons,
@@ -297,12 +380,13 @@ this is usually what we want.
}
```
However, this default behavior is also configurable by using one of these 3
However, this default behavior is also configurable by using one of these 4
methods.
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}`
1. Press `CTRL-U` in interactive mode to toggle `ignore_unmatched` option
2. Set the global `g:easy_align_ignore_unmatched` variable to 0
3. Define a custom alignment rule with `ignore_unmatched` option set to 0
4. Provide `ignore_unmatched` option to `:EasyAlign` command. e.g. `:EasyAlign:{'iu':0}`
Then we get,
@@ -352,6 +436,136 @@ banana += apple
cake ||= banana
```
In interactive mode, you can change the option value with `CTRL-D` key.
### Adjusting indentation
By default :EasyAlign command keeps the original indentation of the lines. But
then again we have `indentation` option. See the following example.
```ruby
# Lines with different indentation
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Default: _k_eep the original indentation
# :EasyAlign=
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Use the _s_hallowest indentation among the lines
# :EasyAlign={'idt':s}
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Use the _d_eepest indentation among the lines
# :EasyAlign={'idt':d}
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Indentation: _n_one
# :EasyAlign={'idt':n}
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
```
Notice that `idt` is fuzzy-matched to `indentation`.
In interactive mode, you can change the option value with `CTRL-I` key.
### Left/right/center mode switch in interactive mode
In interactive mode, you can choose the alignment mode you want by pressing
enter keys. The non-bang command, `:EasyAlign` starts in left-alignment mode
and changes to right and center mode as you press enter keys, while the bang
version first starts in right-alignment mode.
- `:EasyAlign`
- Left, Right, Center
- `:EasyAlign!`
- Right, Left, Center
If you do not prefer this default mode transition, you can define your own
settings as follows.
```vim
let g:easy_align_interactive_modes = ['l', 'r']
let g:easy_align_bang_interactive_modes = ['c', 'r']
```
### Alignments over multiple occurrences of delimiters
As stated above, "N-th" parameter is used to target specific occurrences of
the delimiter when it appears multiple times in each line.
To recap:
```vim
" Left-alignment around the FIRST occurrences of delimiters
:EasyAlign =
" Left-alignment around the SECOND occurrences of delimiters
:EasyAlign 2=
" Left-alignment around the LAST occurrences of delimiters
:EasyAlign -=
" Left-alignment around ALL occurrences of delimiters
:EasyAlign *=
" Left-right ALTERNATING alignment around all occurrences of delimiters
:EasyAlign **=
" Right-left ALTERNATING alignment around all occurrences of delimiters
:EasyAlign! **=
```
In addition to these, you can fine-tune alignments over multiple occurrences of
the delimiters with 'mode_sequence' option. (The option can also be set
in interactive mode with the special key `CTRL-O`)
```vim
" Left alignment over the first two occurrences of delimiters
:EasyAlign = { 'mode_sequence': 'll' }
" Right, left, center alignment over the 1st to 3rd occurrences of delimiters
:EasyAlign = { 'm': 'rlc' }
" Right, left, center alignment over the 2nd to 4th occurrences of delimiters
:EasyAlign 2={ 'm': 'rlc' }
" (*) Repeating alignments (default: l, r, or c)
" Right, left, center, center, center, center, ...
:EasyAlign *={ 'm': 'rlc' }
" (**) Alternating alignments (default: lr or rl)
" Right, left, center, right, left, center, ...
:EasyAlign **={ 'm': 'rlc' }
" Right, left, center, center, center, ... repeating alignment
" over the 3rd to the last occurrences of delimiters
:EasyAlign 3={ 'm': 'rlc*' }
" Right, left, center, right, left, center, ... alternating alignment
" over the 3rd to the last occurrences of delimiters
:EasyAlign 3={ 'm': 'rlc**' }
```
### Extending alignment rules
Although the default rules should cover the most of the use cases,
@@ -362,10 +576,10 @@ you can extend the rules by setting a dictionary named `g:easy_align_delimiters`
```vim
let g:easy_align_delimiters = {
\ '>': { 'pattern': '>>\|=>\|>' },
\ '/': { 'pattern': '//\+\|/\*\|\*/', 'ignores': ['String'] },
\ '#': { 'pattern': '#\+', 'ignores': ['String'], 'delimiter_align': 'l' },
\ '/': { 'pattern': '//\+\|/\*\|\*/', 'ignore_groups': ['String'] },
\ '#': { 'pattern': '#\+', 'ignore_groups': ['String'], 'delimiter_align': 'l' },
\ ']': {
\ 'pattern': '[\[\]]',
\ 'pattern': '[[\]]',
\ 'left_margin': 0,
\ 'right_margin': 0,
\ 'stick_to_left': 0
@@ -390,6 +604,81 @@ Advanced examples and use cases
See [EXAMPLES.md](https://github.com/junegunn/vim-easy-align/blob/master/EXAMPLES.md)
for more examples.
Related work
------------
There are two well-known plugins with the same goal as that of vim-easy-align.
- [DrChip's Alignment Tool for Vim](http://www.drchip.org/astronaut/vim/align.html) (herein will be referred to as "Align")
- [Tabular](https://github.com/godlygeek/tabular)
Both are great plugins with very large user bases. I actually had been a Tabular
user for a couple of years before I finally made up my mind to roll out my own.
So why would someone choose vim-easy-align over those two?
Feature-by-feature comparison I believe is not quite useful, since a typical
user will end up using only a small subset of the features.
So I will mention just a few core benefits of vim-easy-align.
### Ease of use
As the name implies, vim-easy-align is *easier* to use. Its interactive mode
allows you to achieve what you want with just a few keystrokes.
The key sequence is mnemonic, so it's easy to remember and execute.
It even feels like a native Vim command!
- *Right-align*: `<Enter><Enter>`
- around the *second* occurrences: `2`
- of *whitespaces*: `<space>`
For the simplest cases, Tabular and Align are also easy to use. But sooner or
later, you will find yourself scratching your head, trying to come up with some
complex regular expressions.
_"How am I going to align the third to the last word in each line to the right
without affecting the ones before it?"_
### Clean
vim-easy-align doesn't clutter your workspace with mappings and global
variables. All you would need is a single mapping to the interactive EasyAlign
command, and even that is totally up to you.
### Optimized for code editing
vim-easy-align by default performs syntax-aware alignment, which is invaluable
when editing codes.
Try to come up with a regular expression to correctly format the following code
snippet. With vim-easy-align under default configuration and a mapping, it can
be done with just two keystrokes: `<Enter>:`
```javascript
var jdbc = {
// 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"
};
```
(To be fair, Align also can be configured to consider syntax highlighting with
`g:AlignSkip` function reference which should point to a custom function that
looks up the syntax group of a character on a certain position)
### "Okay. So should I switch?"
Maybe, but I can't really say. I have no ambition to make vim-easy-align
an absolute superior to the others. For some cases, vim-easy-align works better
than the others, but for some other cases, Tabular or Align.vim might be a
better choice.
So try it yourself and see if it works for you!
Author
------

View File

@@ -27,24 +27,39 @@ endif
let g:loaded_easy_align = 1
let s:easy_align_delimiters_default = {
\ ' ': { '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': 0, 'right_margin': 0, 'stick_to_left': 0 },
\ '=': { 'pattern': '===\|<=>\|\(&&\|||\|<<\|>>\)=\|=\~[#?]\?\|=>\|[:+/*!%^=><&|.-]\?=[#?]\?',
\ 'left_margin': 1, 'right_margin': 1, 'stick_to_left': 0 },
\ ':': { 'pattern': ':', 'left_margin': 0, 'right_margin': 1, 'stick_to_left': 1 },
\ ',': { 'pattern': ',', 'left_margin': 0, 'right_margin': 1, 'stick_to_left': 1 },
\ '|': { 'pattern': '|', 'left_margin': 1, 'right_margin': 1, 'stick_to_left': 0 },
\ '.': { 'pattern': '\.', 'left_margin': 0, 'right_margin': 0, 'stick_to_left': 0 },
\ '{': { 'pattern': '(\@<!{',
\ 'left_margin': ' ', 'right_margin': ' ', 'stick_to_left': 0 },
\ '}': { 'pattern': '}', 'left_margin': ' ', 'right_margin': '', 'stick_to_left': 0 }
\ 'left_margin': 1, 'right_margin': 1, 'stick_to_left': 0 },
\ '}': { 'pattern': '}', 'left_margin': 1, 'right_margin': 0, 'stick_to_left': 0 }
\ }
let s:just = ['', '[R]']
let s:mode_labels = { 'l': '', 'r': '[R]', 'c': '[C]' }
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]
\ 'margin_left': [0, 1], 'margin_right': [0, 1], 'stick_to_left': [0],
\ 'left_margin': [0, 1], 'right_margin': [0, 1], 'indentation': [1],
\ 'ignore_groups': [3 ], 'ignore_unmatched': [0 ], 'delimiter_align': [1],
\ 'mode_sequence': [1 ], 'ignores': [3]
\ }
let s:option_values = {
\ 'indentation': ['shallow', 'deep', 'none', 'keep'],
\ 'delimiter_align': ['left', 'center', 'right'],
\ 'ignore_unmatched': [0, 1],
\ 'ignore_groups': [[], ['String'], ['Comment'], ['String', 'Comment']]
\ }
let s:shorthand = {
\ 'margin_left': 'lm', 'margin_right': 'rm', 'stick_to_left': 'stl',
\ 'left_margin': 'lm', 'right_margin': 'rm', 'indentation': 'idt',
\ 'ignore_groups': 'ig', 'ignore_unmatched': 'iu', 'delimiter_align': 'da',
\ 'mode_sequence': 'm', 'ignores': 'ig'
\ }
if exists("*strwidth")
@@ -71,21 +86,66 @@ endfunction
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'])
return get(g:, 'easy_align_ignore_groups',
\ get(g:, 'easy_align_ignores',
\ (get(g:, 'easy_align_ignore_comment', 1) == 0) ?
\ ['String'] : ['String', 'Comment']))
else
return []
endif
endfunction
function! s:echon(l, n, d)
echon "\r"
echon "\rEasyAlign". s:just[a:l] ." (" .a:n.a:d. ")"
function! s:echon_(tokens)
" http://vim.wikia.com/wiki/How_to_print_full_screen_width_messages
let xy = [&ruler, &showcmd]
try
set noruler noshowcmd
let winlen = winwidth(winnr()) - 2
let len = len(join(map(copy(a:tokens), 'v:val[1]'), ''))
let ellipsis = len > winlen ? '..' : ''
echon "\r"
let yet = 0
for [hl, msg] in a:tokens
if empty(msg) | continue | endif
execute "echohl ". hl
let yet += len(msg)
if yet > winlen - len(ellipsis)
echon msg[ 0 : (winlen - len(ellipsis) - yet - 1) ] . ellipsis
break
else
echon msg
endif
endfor
finally
echohl None
let [&ruler, &showcmd] = xy
endtry
endfunction
function! s:echon(l, n, r, d, o, warn)
let tokens = [
\ ['Function', ':EasyAlign'],
\ ['ModeMsg', get(s:mode_labels, a:l, a:l)],
\ ['None', ' ']]
if a:r == -1 | call add(tokens, ['Comment', '(']) | endif
call add(tokens, [a:n =~ '*' ? 'Repeat' : 'Number', a:n])
call extend(tokens, a:r == 1 ?
\ [['Delimiter', '/'], ['String', a:d], ['Delimiter', '/']] :
\ [['Identifier', a:d == ' ' ? '\ ' : (a:d == '\' ? '\\' : a:d)]])
if a:r == -1 | call extend(tokens, [['Normal', '_'], ['Comment', ')']]) | endif
call add(tokens, ['Statement', empty(a:o) ? '' : ' '.string(a:o)])
if !empty(a:warn)
call add(tokens, ['WarningMsg', ' ('.a:warn.')'])
endif
call s:echon_(tokens)
endfunction
function! s:exit(msg)
echon "\r". a:msg
call s:echon_([['ErrorMsg', a:msg]])
throw 'exit'
endfunction
@@ -97,23 +157,51 @@ function! s:rtrim(str)
return substitute(a:str, '\s*$', '', '')
endfunction
function! s:trim(str)
return substitute(a:str, '^\s*\(.\{-}\)\s*$', '\1', '')
endfunction
function! s:fuzzy_lu(key)
if has_key(s:known_options, a:key)
return a:key
endif
let key = tolower(a:key)
let regexp = '^' . substitute(substitute(a:key, '-', '_', 'g'), '\(.\)', '\1.*', 'g')
let matches = filter(keys(s:known_options), 'v:val =~ regexp')
" stl -> ^s.*_t.*_l.*
let regexp1 = '^' .key[0]. '.*' .substitute(key[1 : -1], '\(.\)', '_\1.*', 'g')
let matches = filter(keys(s:known_options), 'v:val =~ regexp1')
if len(matches) == 1
return matches[0]
endif
" stl -> ^s.*t.*l.*
let regexp2 = '^' . substitute(substitute(key, '-', '_', 'g'), '\(.\)', '\1.*', 'g')
let matches = filter(keys(s:known_options), 'v:val =~ regexp2')
if empty(matches)
call s:exit("Unknown option key: ". a:key)
elseif len(matches) == 1
return matches[0]
else
" Avoid ambiguity introduced by deprecated margin_left and margin_right
if sort(matches) == ['margin_left', 'margin_right', 'mode_sequence']
return 'mode_sequence'
endif
if sort(matches) == ['ignore_groups', 'ignores']
return 'ignore_groups'
endif
call s:exit("Ambiguous option key: ". a:key ." (" .join(matches, ', '). ")")
endif
endfunction
function! s:shift(modes, cycle)
let item = remove(a:modes, 0)
if a:cycle || empty(a:modes)
call add(a:modes, item)
endif
return item
endfunction
function! s:normalize_options(opts)
let ret = {}
for k in keys(a:opts)
@@ -128,6 +216,14 @@ function! s:normalize_options(opts)
return s:validate_options(ret)
endfunction
function! s:compact_options(opts)
let ret = {}
for k in keys(a:opts)
let ret[s:shorthand[k]] = a:opts[k]
endfor
return ret
endfunction
function! s:validate_options(opts)
for k in keys(a:opts)
let v = a:opts[k]
@@ -139,8 +235,10 @@ function! s:validate_options(opts)
return a:opts
endfunction
function! s:split_line(line, fc, lc, pattern, stick_to_left, ignore_unmatched, ignores)
let left = a:lc ?
function! s:split_line(line, nth, modes, cycle, fc, lc, pattern, stick_to_left, ignore_unmatched, ignore_groups)
let mode = ''
let string = a:lc ?
\ strpart(getline(a:line), a:fc - 1, a:lc - a:fc + 1) :
\ strpart(getline(a:line), a:fc - 1)
let idx = 0
@@ -156,62 +254,95 @@ function! s:split_line(line, fc, lc, pattern, stick_to_left, ignore_unmatched, i
let ignorable = 0
let token = ''
while 1
let matches = matchlist(left, pattern, idx)
let matches = matchlist(string, pattern, idx)
" No match
if empty(matches) | break | endif
" Match, but empty delimiter
if empty(matches[1])
let char = strpart(left, idx, 1)
let char = strpart(string, idx, 1)
if empty(char) | break | endif
let [match, part, delim] = [char, char, '']
" Match
else
let [match, part, delim] = matches[1 : 3]
endif
let ignorable = s:highlighted_as(a:line, idx + len(part) + a:fc, a:ignores)
let ignorable = s:highlighted_as(a:line, idx + len(part) + a:fc, a:ignore_groups)
if ignorable
let token .= match
else
let [pmode, mode] = [mode, s:shift(a:modes, a:cycle)]
call add(tokens, token . match)
call add(delims, delim)
let token = ''
endif
let idx += len(match)
" If the string is non-empty and ends with the delimiter,
" append an empty token to the list
if idx == len(string)
call add(tokens, '')
call add(delims, '')
break
endif
endwhile
let leftover = token . strpart(left, idx)
let leftover = token . strpart(string, idx)
if !empty(leftover)
let ignorable = s:highlighted_as(a:line, len(string) + a:fc - 1, a:ignore_groups)
call add(tokens, leftover)
call add(delims, '')
endif
let [pmode, mode] = [mode, s:shift(a:modes, a:cycle)]
" 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)
let mode = pmode
endif
" Skip comment line
if ignorable && len(tokens) == 1 && a:ignore_unmatched
let tokens = []
let delims = []
" Append an empty item to enable right/center alignment of the last token
" - if the last token is not ignorable or ignorable but not the only token
elseif (mode ==? 'r' || mode ==? 'c') && (!ignorable || len(tokens) > 1) && a:nth >= 0 " includes -0
call add(tokens, '')
call add(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
function! s:max(old, new)
for k in keys(a:new)
if a:new[k] > a:old[k]
let a:old[k] = a:new[k] " max() doesn't work with Floats
endif
endfor
endfunction
function! s:do_align(modes, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth,
\ ml, mr, da, indentation, stick_to_left, ignore_unmatched, ignore_groups, recur)
let mode = a:modes[0]
let lines = {}
let min_indent = -1
let max = { 'pivot_len': 0.0, 'token_len': 0, 'just_len': 0, 'delim_len': 0,
\ 'indent': 0, 'tokens': 0, 'strip_len': 0 }
" 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)
let [tokens, delims] = s:split_line(
\ line, a:nth, copy(a:modes), a:recur == 2,
\ a:fc, a:lc, a:pattern,
\ a:stick_to_left, a:ignore_unmatched, a:ignore_groups)
" Remember tokens for subsequent recursive calls
let a:all_tokens[line] = tokens
@@ -227,15 +358,19 @@ function! s:do_align(just, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth,
endif
" Calculate the maximum number of tokens for a line within the range
let max_tokens = max([len(tokens), max_tokens])
call s:max(max, { 'tokens': len(tokens) })
if a:nth > 0 " Positive field number
if a:nth > 0 " Positive N-th
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
else " -0 or Negative N-th
if a:nth == 0 && mode !=? 'l'
let nth = len(tokens) - 1
else
let nth = len(tokens) + a:nth
endif
if empty(delims[len(delims) - 1])
let nth -= 1
endif
@@ -249,7 +384,7 @@ function! s:do_align(just, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth,
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
if empty(delim) && !exists('tokens[nth + 1]') && a:ignore_unmatched
continue
endif
@@ -257,11 +392,52 @@ function! s:do_align(just, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth,
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])
if mode ==? 'c' | let token .= matchstr(token, '^\s*') | endif
let [pw, tw] = [s:strwidth(prefix), s:strwidth(token)]
call s:max(max, { 'indent': indent, 'token_len': tw, 'just_len': pw + tw,
\ 'delim_len': s:strwidth(delim) })
if mode ==? 'c'
call s:max(max, { 'pivot_len': pw + tw / 2.0,
\ 'strip_len': s:strwidth(s:trim(token)) })
endif
let lines[line] = [nth, prefix, token, delim]
endfor
" Phase 1-5: indentation handling (only on a:nth == 1)
if a:nth == 1
if a:indentation ==? 'd'
let indent = repeat(' ', max.indent)
elseif a:indentation ==? 's'
let indent = repeat(' ', min_indent)
elseif a:indentation ==? 'n'
let indent = ''
elseif a:indentation !=? 'k'
call s:exit('Invalid indentation: ' . a:indentation)
end
if a:indentation !=? 'k'
let max.just_len = 0
let max.token_len = 0
let max.pivot_len = 0
for [line, elems] in items(lines)
let [nth, prefix, token, delim] = elems
let token = substitute(token, '^\s*', indent, '')
if mode ==? 'c'
let token = substitute(token, '\s*$', indent, '')
endif
let [pw, tw] = [s:strwidth(prefix), s:strwidth(token)]
call s:max(max, { 'token_len': tw, 'just_len': pw + tw })
if mode ==? 'c'
call s:max(max, { 'pivot_len': pw + tw / 2.0 })
endif
let lines[line][2] = token
endfor
endif
endif
" Phase 2
for [line, elems] in items(lines)
let tokens = a:all_tokens[line]
@@ -274,21 +450,42 @@ function! s:do_align(just, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth,
endif
" Pad the token with spaces
let pad = repeat(' ', max_just_len - s:strwidth(prefix) - s:strwidth(token))
let [pw, tw] = [s:strwidth(prefix), s:strwidth(token)]
let rpad = ''
if a:just == 0
if mode ==? 'l'
let pad = repeat(' ', max.just_len - pw - tw)
if a:stick_to_left
let rpad = pad
else
let token = token . pad
endif
elseif a:just == 1
elseif mode ==? 'r'
let pad = repeat(' ', max.just_len - pw - tw)
let token = pad . token
elseif mode ==? 'c'
let p1 = max.pivot_len - (pw + tw / 2.0)
let p2 = (max.token_len - tw) / 2.0
let pf1 = floor(p1)
if pf1 < p1 | let p2 = ceil(p2)
else | let p2 = floor(p2)
endif
let strip = float2nr(ceil((max.token_len - max.strip_len) / 2.0))
let token = repeat(' ', float2nr(pf1)) .token. repeat(' ', float2nr(p2))
let token = substitute(token, repeat(' ', strip) . '$', '', '')
if a:stick_to_left
if empty(s:rtrim(token))
let center = len(token) / 2
let [token, rpad] = [strpart(token, 0, center), strpart(token, center)]
else
let [token, rpad] = [s:rtrim(token), matchstr(token, '\s*$')]
endif
endif
endif
let tokens[nth] = token
" Pad the delimiter
let dpadl = max_delim_len - s:strwidth(delim)
let dpadl = max.delim_len - s:strwidth(delim)
if a:da ==? 'l'
let [dl, dr] = ['', repeat(' ', dpadl)]
elseif a:da ==? 'c'
@@ -314,8 +511,8 @@ function! s:do_align(just, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth,
" 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 ipad = repeat(' ', min_indent - len(token.ml))
if mode ==? 'l'
let token = ipad . token
else
let lpad = ipad
@@ -331,60 +528,168 @@ function! s:do_align(just, all_tokens, all_delims, fl, ll, fc, lc, pattern, nth,
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)
if a:nth < max.tokens && (a:recur || len(a:modes) > 1)
call s:shift(a:modes, a:recur == 2)
call s:do_align(
\ a:modes, 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:indentation, a:stick_to_left,
\ a:ignore_unmatched, a:ignore_groups, a:recur)
endif
endfunction
function! s:interactive(just)
let just = a:just
function! s:input(str, default, vis)
if a:vis
normal! gv
redraw
execute "normal! \<esc>"
else
" EasyAlign command can be called without visual selection
redraw
endif
call inputsave()
let got = input(a:str, a:default)
call inputrestore()
return got
endfunction
function! s:atoi(str)
return (a:str =~ '^[0-9]\+$') ? str2nr(a:str) : a:str
endfunction
function! s:interactive(modes, vis, opts, delims)
let mode = s:shift(a:modes, 1)
let n = ''
let ch = ''
let opts = s:compact_options(a:opts)
let vals = deepcopy(s:option_values)
let regx = 0
let warn = ''
while 1
call s:echon(just, n, '')
call s:echon(mode, n, -1, '', opts, warn)
let check = 0
let warn = ''
let c = getchar()
let ch = nr2char(c)
if c == 3 || c == 27 " CTRL-C / ESC
throw 'exit'
elseif c == '<27>kb' " Backspace
elseif c == "\<bs>"
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)
let mode = s:shift(a:modes, 1)
if has_key(opts, 'm')
let opts.m = mode . strpart(opts.m, 1)
endif
elseif ch == '-'
if empty(n) | let n = '-'
elseif n == '-' | let n = ''
else | break
else | let check = 1
endif
elseif ch == '*'
if empty(n) | let n = '*'
elseif n == '*' | let n = '**'
elseif n == '**' | let n = ''
else | break
else | let check = 1
endif
elseif c >= 48 && c <= 57 " Numbers
if n[0] == '*' | break
elseif (c == 48 && len(n) > 0) || c > 48 && c <= 57 " Numbers
if n[0] == '*' | let check = 1
else | let n = n . ch
end
elseif ch == "\<C-D>"
let opts['da'] = s:shift(vals['delimiter_align'], 1)
elseif ch == "\<C-I>"
let opts['idt'] = s:shift(vals['indentation'], 1)
elseif ch == "\<C-L>"
let lm = s:input("Left margin: ", get(opts, 'lm', ''), a:vis)
if empty(lm)
let warn = 'Set to default. Input 0 to remove it'
silent! call remove(opts, 'lm')
else
let opts['lm'] = s:atoi(lm)
endif
elseif ch == "\<C-R>"
let rm = s:input("Right margin: ", get(opts, 'rm', ''), a:vis)
if empty(rm)
let warn = 'Set to default. Input 0 to remove it'
silent! call remove(opts, 'rm')
else
let opts['rm'] = s:atoi(rm)
endif
elseif ch == "\<C-U>"
let opts['iu'] = s:shift(vals['ignore_unmatched'], 1)
elseif ch == "\<C-G>"
let opts['ig'] = s:shift(vals['ignore_groups'], 1)
elseif c == "\<Left>"
let opts['stl'] = 1
let opts['lm'] = 0
elseif c == "\<Right>"
let opts['stl'] = 0
let opts['lm'] = 1
elseif c == "\<Up>" || c == "\<Down>"
silent! call remove(opts, 'stl')
silent! call remove(opts, 'lm')
elseif ch == "\<C-O>"
let modes = tolower(s:input("Mode sequence: ", get(opts, 'm', mode), a:vis))
if match(modes, '^[lrc]\+\*\{0,2}$') != -1
let opts['m'] = modes
let mode = modes[0]
while mode != s:shift(a:modes, 1)
endwhile
else
silent! call remove(opts, 'm')
endif
elseif ch == "\<C-_>" || ch == "\<C-X>"
let prompt = 'Regular expression: '
let ch = s:input(prompt, '', a:vis)
if !empty(ch) && s:valid_regexp(ch)
let regx = 1
break
else
let warn = 'Invalid regular expression: '.ch
endif
elseif ch =~ '[[:print:]]'
let check = 1
else
break
let warn = 'Invalid character'
endif
if check
if has_key(a:delims, ch)
break
else
let warn = 'Unknown delimiter key: '.ch
endif
endif
endwhile
return [just, n, ch]
return [mode, n, ch, s:normalize_options(opts), regx]
endfunction
function! s:valid_regexp(regexp)
try
call matchlist('', a:regexp)
catch
return 0
endtry
return 1
endfunction
function! s:test_regexp(regexp)
if !s:valid_regexp(a:regexp)
call s:exit('Invalid regular expression: '. a:regexp)
endif
return a:regexp
endfunction
function! s:parse_args(args)
let n = ''
let ch = ''
let args = a:args
let cand = ''
let option = {}
let n = ''
let ch = ''
let args = a:args
let cand = ''
let opts = {}
" Poor man's option parser
let idx = 0
@@ -394,11 +699,11 @@ function! s:parse_args(args)
let cand = strpart(args, midx)
try
let [l, r, c] = ['l', 'r', 'c']
let [L, R, C] = ['l', 'r', 'c']
let [l, r, c, k, s, d, n] = ['l', 'r', 'c', 'k', 's', 'd', 'n']
let [L, R, C, K, S, D, N] = ['l', 'r', 'c', 'k', 's', 'd', 'n']
let o = eval(cand)
if type(o) == 4
let option = o
let opts = o
if args[midx - 1 : midx] == '\ '
let midx += 1
endif
@@ -412,8 +717,10 @@ function! s:parse_args(args)
endwhile
" Invalid option dictionary
if len(substitute(cand, '\s', '', 'g')) > 2 && empty(option)
if len(substitute(cand, '\s', '', 'g')) > 2 && empty(opts)
call s:exit("Invalid option: ". cand)
else
let opts = s:normalize_options(opts)
endif
" Has /Regexp/?
@@ -421,63 +728,76 @@ function! s:parse_args(args)
" 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]
return [matches[1], s:test_regexp(matches[2]), opts, 1]
else
let tokens = matchlist(args, '^\([1-9][0-9]*\|-[0-9]*\|\*\*\?\)\?\s*\(.\{-}\)\?$')
return [tokens[1], tokens[2], option, 0]
return [tokens[1], tokens[2], opts, 0]
endif
endfunction
function! easy_align#align(just, expr) range
let just = a:just
function! s:modes(bang)
return get(g:,
\ (a:bang ? 'easy_align_bang_interactive_modes' : 'easy_align_interactive_modes'),
\ (a:bang ? ['r', 'l', 'c'] : ['l', 'r', 'c']))
endfunction
function! s:alternating_modes(mode)
return a:mode ==? 'r' ? ['r', 'l'] : ['l', 'r']
endfunction
function! easy_align#align(bang, expr) range
try
call s:align(a:bang, a:firstline, a:lastline, a:expr)
catch 'exit'
endtry
endfunction
function! s:align(bang, first_line, last_line, expr)
let modes = s:modes(a:bang)
let mode = modes[0]
let recur = 0
let n = ''
let ch = ''
let option = {}
let opts = {}
let regexp = 0
" Heuristically determine if the user was in visual mode
let vis = a:first_line == line("'<") && a:last_line == line("'>")
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
let delimiters = s:easy_align_delimiters_default
if exists('g:easy_align_delimiters')
let delimiters = extend(copy(delimiters), g:easy_align_delimiters)
endif
if empty(a:expr)
let [mode, n, ch, opts, regexp] = s:interactive(copy(modes), vis, opts, delimiters)
else
let [n, ch, opts, regexp] = s:parse_args(a:expr)
if empty(n) && empty(ch)
let [mode, n, ch, opts, regexp] = s:interactive(copy(modes), vis, opts, delimiters)
elseif empty(ch)
" Try swapping n and ch
let [n, ch] = ['', n]
endif
catch 'exit'
return
endtry
endif
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
call s:exit('Invalid N-th parameter: '. n)
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\+$'
" '\' => ' '
if ch =~ '^\\\s*$'
let ch = ' '
" '\\' => '\'
elseif ch =~ '^\\\\\s*$'
@@ -485,47 +805,61 @@ function! easy_align#align(just, expr) range
endif
endif
if !has_key(delimiters, ch)
echon "\rUnknown delimiter key: ". ch
return
call s:exit('Unknown delimiter key: '. ch)
endif
let dict = delimiters[ch]
let dict = copy(delimiters[ch])
endif
try
if !empty(option)
let dict = extend(copy(dict), s:normalize_options(option))
endif
catch 'exit'
return
endtry
call extend(dict, opts)
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() == ''
let bvisual = vis && char2nr(visualmode()) == 22 " ^V
if recur && bvisual
echon "\rRecursive alignment is currently not supported in blockwise-visual mode"
return
call s:exit('Recursive alignment is not supported in blockwise-visual mode')
endif
try
call s:do_align(just, {}, {}, a:firstline, a:lastline,
let aseq = get(dict, 'mode_sequence',
\ recur == 2 ? s:alternating_modes(mode) : [mode])
let mode_expansion = matchstr(aseq, '\*\+$')
if mode_expansion == '*'
let aseq = aseq[0 : -2]
let recur = 1
elseif mode_expansion == '**'
let aseq = aseq[0 : -3]
let recur = 2
endif
let aseq_list = type(aseq) == 1 ? split(tolower(aseq), '\s*') : map(copy(aseq), 'tolower(v:val)')
let aseq_str = join(aseq_list, '')
call s:do_align(
\ aseq_list,
\ {}, {}, a:first_line, a:last_line,
\ 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, 'delimiter_align', get(g:, 'easy_align_delimiter_align', 'r'))[0],
\ get(dict, 'indentation', get(g:, 'easy_align_indentation', 'k'))[0],
\ get(dict, 'stick_to_left', 0),
\ get(dict, 'ignore_unmatched', get(g:, 'easy_align_ignore_unmatched', 1)),
\ get(dict, 'ignores', s:ignored_syntax()),
\ get(dict, 'ignore_groups', get(dict, 'ignores', s:ignored_syntax())),
\ recur)
call s:echon(just, n, regexp ? '/'.ch.'/' : ch)
catch 'exit'
endtry
let copts = s:compact_options(opts)
let nbmode = s:modes(0)[0]
if !has_key(copts, 'm') && (
\ (recur == 2 && join(s:alternating_modes(nbmode), '') != aseq_str) ||
\ (recur != 2 && (aseq_str[0] != nbmode || len(aseq_str) > 1))
\ )
call extend(copts, { 'm': aseq_str })
endif
call s:echon('', n, regexp, ch, copts, '')
endfunction

View File

@@ -3,23 +3,24 @@
vim-easy-align *vim-easy-align* *easy-align*
=========================================================================
A simple, easy-to-use Vim alignment plugin without too much ambition.
A simple, easy-to-use Vim alignment plugin.
Author: Junegunn Choi
Source: https://github.com/junegunn/vim-easy-align
Author: Junegunn Choi
Source: https://github.com/junegunn/vim-easy-align
License: MIT
EasyAlign *:EasyAlign* *:EasyAlign!*
-------------------------------------------------------------------------
vim-easy-align defines `:EasyAlign` command in the visual mode.
(:EasyAlign! is the right-justification version.)
(:EasyAlign! is the right-align version.)
| Mode | Command |
| ------------------------- | ------------------------------------------- |
| Interactive mode | :EasyAlign |
| Using predefined rules | :EasyAlign [FIELD#] DELIMITER_KEY [OPTIONS] |
| Using regular expressions | :EasyAlign [FIELD#] /REGEXP/ [OPTIONS] |
| Mode | Command |
| ------------------------- | -------------------------------------------- |
| Interactive mode | :EasyAlign[!] [OPTIONS] |
| Using predefined rules | :EasyAlign[!] [N-th] DELIMITER_KEY [OPTIONS] |
| Using regular expressions | :EasyAlign[!] [N-th] /REGEXP/ [OPTIONS] |
Interactive mode
@@ -34,16 +35,16 @@ your `.vimrc`.
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)
2. Optional: Enter keys to select alignment mode (left, right, or center)
3. Optional: N-th delimiter (default: 1)
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`)
- Around the last occurrences of delimiters (-1)
-2 Around the second to last occurrences of delimiters
...
4. Delimiter key (a single keystroke)
4. Delimiter key for the predefined rules (a single keystroke)
<space> General alignment around whitespaces
= Operators containing equals sign (=, ==, !=, +=, &&=, ...)
: Suitable for formatting JSON or YAML
@@ -51,7 +52,10 @@ With this mapping, you can align selected lines of text with a few keystrokes.
, Multi-line method arguments. CSV.
| Table markdown
During the key sequence, <Enter> key will toggle right-justification mode.
(You can override these default rules or define your own rules with
`g:easy_align_delimiters`, which will be described in the later section.)
During the key sequence, <Enter> key will toggle right-align mode.
Examples:
@@ -64,22 +68,48 @@ Examples:
<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-alignment around 1st equals signs
<Enter><Enter>**= Right-left alternating alignment around all equals signs
Instead of finishing the command with a predefined delimiter key, you can type
in a regular expression after `<CTRL-/>` or `<CTRL-X>` key.
For example, if you want to align text around all occurrences of numbers:
- <Enter>
- *
- <CTRL-/> (or <CTRL-X> on Gvim)
- [0-9]\+
While in interactive mode, you can adjust some of the alignment options using
special shortcut keys listed below. The meanings of the options will be
described in the following sections.
| Key | Option | Values |
| ------- | ---------------- | -------------------------------------------- |
| CTRL-I | indentation | shallow, deep, none, keep |
| CTRL-L | left_margin | Input number or string |
| CTRL-R | right_margin | Input number or string |
| CTRL-D | delimiter_align | left, center, right |
| CTRL-U | ignore_unmatched | 0, 1 |
| CTRL-G | ignore_groups | [], [String], [Comment], [String, Comment] |
| CTRL-O | mode_sequence | Input string of /[lrc]+\*{0,2}/ |
| <Left> | stick_to_left | { 'stick_to_left': 1, 'left_margin': 0 } |
| <Right> | stick_to_left | { 'stick_to_left': 0, 'left_margin': 1 } |
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.
`:EasyAlign` command.
" Using predefined alignment rules
:EasyAlign[!] [FIELD#] DELIMITER_KEY [OPTIONS]
:EasyAlign[!] [N-th] DELIMITER_KEY [OPTIONS]
" Using arbitrary regular expressions
:EasyAlign[!] [FIELD#] /REGEXP/ [OPTIONS]
:EasyAlign[!] [N-th] /REGEXP/ [OPTIONS]
For example, when aligning the following lines around colons and semi-colons,
@@ -93,18 +123,18 @@ try these commands:
- :EasyAlign */[:;]\+/
- :EasyAlign **/[:;]\+/
Notice that you can't append `\zs` to your regular expression to put delimiters
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': '' }
- :EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'left_margin': 0 }
Then we get:
apple;: banana:: cake
data;; exchange:; format
Options keys are fuzzy-matched, so you can write as follows:
Option names are fuzzy-matched, so you can write as follows:
- :EasyAlign * /[:;]\+/ { 'stl': 1, 'l': '' }
@@ -112,26 +142,62 @@ You can even omit spaces between the arguments, so concisely (or cryptically):
- :EasyAlign*/[:;]\+/{'s':1,'l':''}
Available options are as follows.
The same thing can be done in the interactive mode as well with the following
key combination.
| 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']` |
- <Enter>
- *
- <Left>
- <CTRL-/> (or <CTRL-X> on GVim)
- [:;]\+
Partial alignment in blockwise-visual mode
-------------------------------------------------------------------------
In blockwise-visual mode (`CTRL-V`), EasyAlign command aligns only
In blockwise-visual mode (CTRL-V), EasyAlign command aligns only
the selected text in the block, instead of the whole lines in the range.
Ignoring delimiters in comments or strings *g:easy_align_ignores*
Alignment options
-------------------------------------------------------------------------
Available options are as follows.
| Atrribute | Type | Default |
| ---------------- | ---------------- | ----------------------------- |
| left_margin | number or string | 1 |
| right_margin | number or string | 1 |
| stick_to_left | boolean | 0 |
| ignore_unmatched | boolean | 1 |
| ignore_groups | array | ['String', 'Comment'] |
| delimiter_align | string | 'r' |
| | | (right, left, center) |
| indentation | string | 'k' |
| | | (keep, shallow, deep, none) |
| mode_sequence | string | (Depends on N-th param and |
| | | selected alignment mode) |
There are 4 ways to set alignment options (from lowest precedence to highest):
1. Some option values can be set with corresponding global variables
2. Option values can be specified in the definition of each alignment rule
3. Option values can be given as a dictionary argument to :EasyAlign command
4. Option values can be set in interactive mode using special shortcut keys
| Option | Shortcut key | Global variable |
| ---------------- | ------------------- | ------------------------------- |
| left_margin | CTRL-L | |
| right_margin | CTRL-R | |
| stick_to_left | <Left>, <Right> | |
| ignore_groups | CTRL-G | `g:easy_align_ignore_groups` |
| ignore_unmatched | CTRL-U | `g:easy_align_ignore_unmatched` |
| indentation | CTRL-I | `g:easy_align_indentation` |
| delimiter_align | CTRL-D | `g:easy_align_delimiter_align` |
| mode_sequence | CTRL-O | |
Ignoring delimiters in comments or strings *g:easy_align_ignore_groups*
-------------------------------------------------------------------------
EasyAlign can be configured to ignore delimiters in certain syntax
@@ -141,7 +207,7 @@ 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']
let g:easy_align_ignore_groups = ['Comment', 'String']
For example, the following paragraph
@@ -154,7 +220,7 @@ For example, the following paragraph
'grape:fruits': 3
}
becomes as follows on `<Enter>:`
becomes as follows on '<Enter>:' (or `:EasyAlign:`)
{
# Quantity of apples: 1
@@ -167,17 +233,15 @@ becomes as follows on `<Enter>:`
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,
You can change the default rule by using one of these 4 methods.
" Ignore nothing!
let g:easy_align_ignores = []
1. Press CTRL-G in interactive mode to switch groups
2. Define global `g:easy_align_ignore_groups` list
3. Define a custom rule in `g:easy_align_delimiters` with 'ignore_groups' option
4. Provide 'ignore_groups' option to `:EasyAlign` command.
e.g. :EasyAlign:{'is':[]}
or providing `ignores` option directly to :EasyAlign command
:EasyAlign:{'is':[]}
Then you get,
For example if you set 'ignore_groups' option to be an empty list, you get
{
# Quantity of apples: 1
@@ -193,7 +257,7 @@ Ignoring unmatched lines *g:easy_align_ignore_unmatched*
-------------------------------------------------------------------------
Lines without any matching delimiter are ignored as well (except in
right-justification mode).
right-align mode).
For example, when aligning the following code block around the colons,
@@ -215,17 +279,14 @@ this is usually what we want.
grapefruits: 3
}
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}
However, this default behavior is also configurable by using one of these 4
methods.
1. Press CTRL-U in interactive mode to toggle 'ignore_unmatched' option
2. Set the global `g:easy_align_ignore_unmatched` variable to 0
3. Define a custom alignment rule with 'ignore_unmatched' option set to 0
4. Provide 'ignore_unmatched' option to `:EasyAlign` command.
e.g. :EasyAlign:{'iu':0}
Then we get,
@@ -238,12 +299,11 @@ Then we get,
}
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
'delimiter_align' option determines how matched delimiters of different
lengths are aligned.
apple = 1
@@ -256,18 +316,150 @@ By default, delimiters are right-aligned as follows.
banana += apple
cake ||= banana
However, with `:EasyAlign={'da':l}`, delimiters are left-aligned.
However, with ':EasyAlign={'da':l}', delimiters are left-aligned.
apple = 1
banana += apple
cake ||= banana
And on `:EasyAlign={'da':c}`, center-aligned.
And on ':EasyAlign={'da':c}', center-aligned.
apple = 1
banana += apple
cake ||= banana
In interactive mode, you can change the option value with `CTRL-D` key.
Adjusting indentation *g:easy_align_indentation*
-------------------------------------------------------------------------
By default :EasyAlign command keeps the original indentation of the lines.
But then again we have 'indentation' option. See the following example.
# Lines with different indentation
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Default: _k_eep the original indentation
# :EasyAlign=
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Use the _s_hallowest indentation among the lines
# :EasyAlign={'idt':s}
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Use the _d_eepest indentation among the lines
# :EasyAlign={'idt':d}
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Indentation: _n_one
# :EasyAlign={'idt':n}
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
Notice that 'idt' is fuzzy-matched to 'indentation'.
In interactive mode, you can change the option value with `CTRL-I` key.
Left/right/center mode switch in interactive mode
-------------------------------------------------------------------------
*g:easy_align_interactive_modes*
*g:easy_align_bang_interactive_modes*
In interactive mode, you can choose the alignment mode you want by pressing
enter keys. The non-bang command, `:EasyAlign` starts in left-alignment mode
and changes to right and center mode as you press enter keys, while the bang
version first starts in right-alignment mode.
- `:EasyAlign`
- Left, Right, Center
- `:EasyAlign!`
- Right, Left, Center
If you do not prefer this default mode transition, you can define your own
settings as follows.
let g:easy_align_interactive_modes = ['l', 'r']
let g:easy_align_bang_interactive_modes = ['c', 'r']
Alignments over multiple occurrences of delimiters
-------------------------------------------------------------------------
As stated above, "N-th" parameter is used to target specific occurrences of
the delimiter when it appears multiple times in each line.
To recap:
" Left-alignment around the FIRST occurrences of delimiters
:EasyAlign =
" Left-alignment around the SECOND occurrences of delimiters
:EasyAlign 2=
" Left-alignment around the LAST occurrences of delimiters
:EasyAlign -=
" Left-alignment around ALL occurrences of delimiters
:EasyAlign *=
" Left-right ALTERNATING alignment around all occurrences of delimiters
:EasyAlign **=
" Right-left ALTERNATING alignment around all occurrences of delimiters
:EasyAlign! **=
In addition to these, you can fine-tune alignments over multiple occurrences of
the delimiters with 'mode_sequence' option. (The option can also be set
in interactive mode with the special key CTRL-O)
" Left alignment over the first two occurrences of delimiters
:EasyAlign = { 'mode_sequence': 'll' }
" Right, left, center alignment over the 1st to 3rd occurrences of delimiters
:EasyAlign = { 'm': 'rlc' }
" Right, left, center alignment over the 2nd to 4th occurrences of delimiters
:EasyAlign 2={ 'm': 'rlc' }
" (*) Repeating alignments (default: l, r, or c)
" Right, left, center, center, center, center, ...
:EasyAlign *={ 'm': 'rlc' }
" (**) Alternating alignments (default: lr or rl)
" Right, left, center, right, left, center, ...
:EasyAlign **={ 'm': 'rlc' }
" Right, left, center, center, center, ... repeating alignment
" over the 3rd to the last occurrences of delimiters
:EasyAlign 3={ 'm': 'rlc*' }
" Right, left, center, right, left, center, ... alternating alignment
" over the 3rd to the last occurrences of delimiters
:EasyAlign 3={ 'm': 'rlc**' }
Extending alignment rules *g:easy_align_delimiters*
-------------------------------------------------------------------------
@@ -277,10 +469,10 @@ you can extend the rules by setting a dictionary named
let g:easy_align_delimiters = {
\ '>': { 'pattern': '>>\|=>\|>' },
\ '/': { 'pattern': '//\+\|/\*\|\*/', 'ignores': ['String'] },
\ '#': { 'pattern': '#\+', 'ignores': ['String'] },
\ '/': { 'pattern': '//\+\|/\*\|\*/', 'ignore_groups': ['String'] },
\ '#': { 'pattern': '#\+', 'ignore_groups': ['String'] },
\ ']': {
\ 'pattern': '[\[\]]',
\ 'pattern': '[[\]]',
\ 'left_margin': 0,
\ 'right_margin': 0,
\ 'stick_to_left': 0

View File

@@ -104,15 +104,65 @@ j, , k
```ruby
a =
a = 1
bbbb .= 2
ccccccc = 3
ccccccccccccccc
ddd = #
eeee === eee = eee = eee = f
fff = ggg += gg &&= gg
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
j =~ 5
j >= 5
aa => 123
aa <<= 123
aa >>= 123
bbb => 123
c => 1233123
d => 123
dddddd &&= 123
dddddd ||= 123
dddddd /= 123
gg <=> ee
a =
a = 1
bbbb .= 2
ccccccc = 3
ccccccccccccccc
ddd = #
eeee === eee = eee = eee = f
fff = ggg += gg &&= gg
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
j =~ 5
j >= 5
aa => 123
aa <<= 123
aa >>= 123
bbb => 123
c => 1233123
d => 123
dddddd &&= 123
dddddd ||= 123
dddddd /= 123
gg <=> ee
a =
a = 1
bbbb = 2
bbbb .= 2
ccccccc = 3
ccccccccccccccc
ddd = 4
ddd = #
eeee === eee = eee = eee=f
fff = ggg += gg &&= gg
g != hhhhhhhh == 888
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
@@ -131,13 +181,13 @@ ccccccccccccccc
a =
a = 1
bbbb = 2
bbbb .= 2
ccccccc = 3
ccccccccccccccc
ddd = 4
ddd = #
eeee === eee = eee = eee = f
fff = ggg += gg &&= gg
g != hhhhhhhh == 888
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
@@ -156,13 +206,13 @@ gg <=> ee
a =
a = 1
bbbb = 2
bbbb .= 2
ccccccc = 3
ccccccccccccccc
ddd = 4
ddd = #
eeee === eee = eee = eee = f
fff = ggg += gg &&= gg
g != hhhhhhhh == 888
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
@@ -181,13 +231,13 @@ gg <=> ee
a =
a = 1
bbbb = 2
bbbb .= 2
ccccccc = 3
ccccccccccccccc
ddd = 4
ddd = #
eeee === eee = eee = eee=f
fff = ggg += gg &&= gg
g != hhhhhhhh == 888
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
@@ -355,15 +405,15 @@ my_object .
|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
@@ -374,10 +424,10 @@ 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
Paul McCartney 1942
George Harrison 1943
@@ -504,3 +554,513 @@ George Harrison 1943
.. -- ......
... - .....-
apple = 1 = 2
banana = 2 = 2
cake = 3 = 2
daisy = 4 = 2
eggplant = 5 = 2
apple = 1 = 2
banana = 2 = 2
cake = 3 = 2
daisy = 4 = 2
eggplant = 5 = 2
apple = 1 = 2
banana = 2 = 2
cake = 3 = 2
daisy = 4 = 2
eggplant = 5 = 2
apple = 1 = 2
banana = 2 = 2
cake = 3 = 2
daisy = 4 = 2
eggplant = 5 = 2
apple = 1 = 2
banana = 2 = 2
cake = 3 = 2
daisy = 4 = 2
eggplant = 5 = 2
apple = 1 = 2
banana = 2 = 2
cake = 3 = 2
daisy = 4 = 2
eggplant = 5 = 2
1 apple = 1 = 2
1 banana = 2 = 2
1 cake = 3 = 2
1 daisy = 4 = 2
1 eggplant = 5 = 2
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
a pple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
apple = 1 = 2
banana = 2 = 2
cake = 3 = 2
daisy = 4 = 2
eggplant = 5 = 2
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
```c
int a = 1;
long b = 2;
float c = 3;
string d = 4;
// this line should not get aligned
long int e = 5;
std::map f;
std::map g; /* this? */
short h /* how about this? */ = 6;
string i = "asdf";
int a = 1;
long b = 2;
float c = 3;
string d = 4;
// this line should not get aligned
long int e = 5;
std::map f;
std::map g; /* this? */
short h /* how about this? */ = 6;
string i = "asdf";
```
```ruby
a =
a = 1
bbbb .= 2
ccccccc = 3
ccccccccccccccc
# eeeeeeeeeeeeeeee
e # asdf
ddd = #
eeee === eee = eee = eee=f
fff = ggg += gg &&= gg
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
j =~ 5
j >= 5
aa => 123
aa <<= 123
aa >>= 123
bbb => 123
c => 1233123
d => 123
dddddd &&= 123
dddddd ||= 123
dddddd /= 123
gg <=> ee
a =
a = 1
bbbb .= 2
ccccccc = 3
ccccccccccccccc
# eeeeeeeeeeeeeeee
e # asdf
ddd = #
eeee === eee = eee = eee = f
fff = ggg += gg &&= gg
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
j =~ 5
j >= 5
aa => 123
aa <<= 123
aa >>= 123
bbb => 123
c => 1233123
d => 123
dddddd &&= 123
dddddd ||= 123
dddddd /= 123
gg <=> ee
a =
a = 1
bbbb .= 2
ccccccc = 3
ccccccccccccccc
# eeeeeeeeeeeeeeee
e # asdf
ddd = #
eeee === eee = eee = eee = f
fff = ggg += gg &&= gg
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
j =~ 5
j >= 5
aa => 123
aa <<= 123
aa >>= 123
bbb => 123
c => 1233123
d => 123
dddddd &&= 123
dddddd ||= 123
dddddd /= 123
gg <=> ee
a =
a = 1
bbbb .= 2
ccccccc = 3
ccccccccccccccc
# eeeeeeeeeeeeeeee
e # asdf
ddd = #
eeee === eee = eee = eee = f
fff = ggg += gg &&= gg
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
j =~ 5
j >= 5
aa => 123
aa <<= 123
aa >>= 123
bbb => 123
c => 1233123
d => 123
dddddd &&= 123
dddddd ||= 123
dddddd /= 123
gg <=> ee
a =
a = 1
bbbb .= 2
ccccccc = 3
ccccccccccccccc
# eeeeeeeeeeeeeeee
e # asdf
ddd = #
eeee === eee = eee = eee = f
fff = ggg += gg &&= gg
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
j =~ 5
j >= 5
aa => 123
aa <<= 123
aa >>= 123
bbb => 123
c => 1233123
d => 123
dddddd &&= 123
dddddd ||= 123
dddddd /= 123
gg <=> ee
a =
a = 1
bbbb .= 2
ccccccc = 3
ccccccccccccccc
# eeeeeeeeeeeeeeee
e # asdf
ddd = #
eeee === eee = eee = eee=f
fff = ggg += gg &&= gg
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
j =~ 5
j >= 5
aa => 123
aa <<= 123
aa >>= 123
bbb => 123
c => 1233123
d => 123
dddddd &&= 123
dddddd ||= 123
dddddd /= 123
gg <=> ee
a = 1
bb = 22
ccc = 333
dddd = "asdf"
a = 1
bb = 22
ccc = 333
dddd = "asdf"
a = 1
bb = 22
ccc = 333
dddd = "asdf"
a = 1
bb = 22
ccc = 333
dddd = "asdf"
a = 1
bb = 22
ccc = 333
dddd = "asdf"
a = 1
bb = 22
ccc = 333
dddd = "asdf"
a = 1
bb = 22
ccc = 333
dddd = "asdf"
```
a a a a a
bbb bbb bbb bbb bbb
ccccc ccccc ccccc ccccc ccccc
d ddd dddd ddd d
aaaaa = 123456778901234567890 =
bbbbbbbbbb = 12345 =
aaaaa = 123456778901234567890 =
cccccccccccccccccc = 123 =
aaaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
aaaaa = 12345 =
bbbbbbbbbb = 123456778901234567890 =
aaaaa = 12345
bbbbbbbbbb = 123456778901234567890
123456 789
1234567890 1
1234 56
123456 7890
aaaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
| 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 |
```
aaaaa = 123456778901234567890 =
cccccccccccccccccc =12345678 =
aaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
aaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
aaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
aaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
aaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
aaaaaaaaaaaaa = 123456778901234567890 =
cc = 12345678 =
aaaaaaaaaaa = 123
a = 123
aaaaaaaaaaaa = 123
a = 123
aaaaaaaaaaaa = 123
aaaaaaaaaaa = 123
aaaaaaaaaa = 123
aaa = 123
aa = 123
a = 123
aaaaaaaaaaaa = 123
aaaaaaaaaaa = 123
aaaaaaaaaa = 123
aaa = 123
aa = 123
a = 123
aaaaaaaaaaaa = 123
aaaaaaaaaaa = 123
aaaaaaaaaa = 123
aaa = 123
aa = 123
a = 123
aaaa = 123456778901234567890 =
cccccccccccccc = 12345678 =
aaaa = 123456778901234567890 =
bbbbbb = 4
cccccccccccccccccc = 12345678 =
aaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
aaaaa = 123456778901234567890 =
cc = 12345678 =
= aaaaa = 123456778901234567890 =
= cccccccccccccccccc = 12345678 =
=aaaaa = 123456778901234567890 =
= cccccccccccccccccc = 12345678 =
```
a, , bbb
aa, , bb
aaa, , b
aaaa, ,
aaa, b,
aa, bb,
a, bbb,
1 22222 33 444 555 6666 7 888
11 222 3333 4 55 6666 77 888
111 22 333 444 55555 6666 7 88888
1111 2 33 444 555 66 777 8
1 22222 33 444 555 6666 7 888
11 222 3333 4 55 6666 77 888
111 22 333 444 55555 6666 7 88888
1111 2 33 444 555 66 777 8
1 22222 33 444 555 6666 7 888
11 222 3333 4 55 6666 77 888
111 22 333 444 55555 6666 7 88888
1111 2 33 444 555 66 777 8

View File

@@ -26,13 +26,13 @@ j,,k
a =
a = 1
bbbb = 2
bbbb .= 2
ccccccc = 3
ccccccccccccccc
ddd = 4
ddd = #
eeee === eee = eee = eee=f
fff = ggg += gg &&= gg
g != hhhhhhhh == 888
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
@@ -130,3 +130,144 @@ Pete Best 1941
..--......
...-.....-
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
```c
int a = 1;
long b = 2;
float c = 3;
string d = 4;
// this line should not get aligned
long int e = 5;
std::map f;
std::map g; /* this? */
short h /* how about this? */ = 6;
string i = "asdf";
```
```ruby
a =
a = 1
bbbb .= 2
ccccccc = 3
ccccccccccccccc
# eeeeeeeeeeeeeeee
e # asdf
ddd = #
eeee === eee = eee = eee=f
fff = ggg += gg &&= gg
g != hhhhhhhh == # 8
i := 5
i %= 5
i *= 5
j =~ 5
j >= 5
aa => 123
aa <<= 123
aa >>= 123
bbb => 123
c => 1233123
d => 123
dddddd &&= 123
dddddd ||= 123
dddddd /= 123
gg <=> ee
a = 1
bb = 22
ccc = 333
dddd = "asdf"
```
a a a a a
bbb bbb bbb bbb bbb
ccccc ccccc ccccc ccccc ccccc
d ddd dddd ddd d
aaaaa = 123456778901234567890 =
bbbbbbbbbb = 12345 =
aaaaa = 123456778901234567890 =
cccccccccccccccccc = 123 =
aaaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
aaaaa = 12345 =
bbbbbbbbbb = 123456778901234567890 =
aaaaa = 12345
bbbbbbbbbb = 123456778901234567890
123456 789
1234567890 1
1234 56
123456 7890
aaaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
```
aaaaa = 123456778901234567890 =
cccccccccccccccccc =12345678 =
aaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
aaaaaaaaaaaaa = 123456778901234567890 =
cc = 12345678 =
aaaaaaaaaaa= 123
a = 123
aaaaaaaaaaaa= 123
a = 123
aaaaaaaaaaaa = 123
aaaaaaaaaaa = 123
aaaaaaaaaa = 123
aaa = 123
aa = 123
a = 123
aaaa = 123456778901234567890 =
cccccccccccccc = 12345678 =
aaaa = 123456778901234567890 =
bbbbbb = 4
cccccccccccccccccc = 12345678 =
aaaa = 123456778901234567890 =
cccccccccccccccccc = 12345678 =
aaaaa = 123456778901234567890 =
cc = 12345678 =
=aaaaa = 123456778901234567890 =
= cccccccccccccccccc = 12345678 =
```
a,,bbb
aa,,bb
aaa,,b
aaaa,,
aaa,b,
aa,bb,
a,bbb,
1 22222 33 444 555 6666 7 888
11 222 3333 4 55 6666 77 888
111 22 333 444 55555 6666 7 88888
1111 2 33 444 555 66 777 8

View File

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

View File

@@ -1,44 +0,0 @@
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()

View File

@@ -91,6 +91,6 @@ 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
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(

View File

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

View File

@@ -1,5 +1,49 @@
e!
execute 'source '. expand('%:p:h') . '/include.vim'
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
set colorcolumn=
silent! ScrollPositionHide
call GFM()
normal gg
let @b=system('cat '. expand('%:p:r') . '.script')