Adding new stuff

This commit is contained in:
ViktorBarzin 2017-07-09 02:00:02 +03:00
parent 1f2c9e448a
commit 44142239cd
40 changed files with 16241 additions and 11 deletions

28
.vimrc
View file

@ -43,6 +43,11 @@ let g:xptemplate_minimal_prefix = 1
let g:xptemplate_vars="$author=viktor.barzin"
let g:xptemplate_vars="$email=viktor.barzin@samitor.com"
" Rebind <Leader> key
" I like to have it here becuase it is easier to reach than the default and
" it is next to ``m`` and ``n`` which I use for navigating between tabs.
let mapleader = ","
" Swap lines
nnoremap <Leader>k :-1,-1m+0<CR>k
nnoremap <Leader>j :+0,+0m+1<CR>
@ -98,6 +103,7 @@ set wildmenu
set pastetoggle=<F2>
set clipboard=unnamed
" Mouse and backspace
set mouse=a " on OSX press ALT and click
set bs=2 " make backspace behave like normal again
@ -110,10 +116,6 @@ endif
" Set comment string for commentary.vim for python
set commentstring=#%s
" Rebind <Leader> key
" I like to have it here becuase it is easier to reach than the default and
" it is next to ``m`` and ``n`` which I use for navigating between tabs.
let mapleader = ","
@ -145,8 +147,8 @@ if has('win32') || has ('win64')
" Bind nohl
" Removes highlight of your last search
" ``<C>`` stands for ``CTRL`` and therefore ``<C-n>`` stands for ``CTRL+n``
noremap <C-n> :nohl<CR>
vnoremap <C-n> :nohl<CR>
noremap <F3> :nohl<CR>
vnoremap <F3> :nohl<CR>
"inoremap <C-n> :nohl<CR>
" Tab switching
@ -418,11 +420,11 @@ set synmaxcol=200
set autoread
" Autosave
" augroup autoSaveAndRead
" autocmd!
" autocmd TextChanged,InsertLeave,FocusLost * silent! wall
" autocmd CursorHold * silent! checktime
" augroup END
augroup autoSaveAndRead
autocmd!
autocmd TextChanged,InsertLeave,FocusLost * silent! wall
autocmd CursorHold * silent! checktime
augroup END
" Lion alignment operator config (see https://github.com/tommcdo/vim-lion)
let b:lion_squeeze_spaces = 1
@ -430,3 +432,7 @@ let b:lion_squeeze_spaces = 1
set showmatch
set matchtime=3
" Recompute syntax highlighting
nnoremap <silent> <F4> :syntax sync fromstart<CR>
autocmd FileType markdown syntax sync fromstart

View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2014 Christian Wellenbrock
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.

View file

@ -0,0 +1,743 @@
## Introduction
**Targets.vim** is a Vim plugin that adds various [text objects][textobjects]
to give you more targets to [operate][operator] on. It expands on the idea of
simple commands like `di'` (delete inside the single quotes around the cursor)
to give you more opportunities to craft powerful commands that can be
[repeated][repeat] reliably. One major goal is to handle all corner cases
correctly.
## Examples
The following examples are displayed as three lines each. The top line denotes
cursor positions from where the presented command works. The middle line shows
the contents of the example line that we're working on. The last line shows the
part of the line that the command will operate on.
To change the text in the next pair of parentheses, use the `cin)` command
```
cursor position │ .....................
buffer line │ This is example text (with a pair of parentheses).
selection │ └───────── cin) ─────────┘
```
To delete the item in a comma separated list under the cursor, use `da,`
```
cursor position │ .........
buffer line │ Shopping list: oranges, apples, bananas, tomatoes
selection │ └─ da, ─┘
```
Notice how the selection includes exactly one of the surrounding commas to
leave a proper comma separated list behind.
## Overview
We distinguish between four kinds of text objects that behave slightly
differently:
- Pair text objects
- Quote text objects
- Separator text objects
- Argument text objects
## Pair Text Objects
These text objects are similar to the built in text objects such as `i)`.
Supported trigger characters:
- `(` `)` `b` (work on parentheses)
- `{` `}` `B` (work on curly braces)
- `[` `]` (work on square brackets)
- `<` `>` (work on angle brackets)
- `t` (work on tags)
Pair text objects work over multiple lines and support seeking. See below for
details about seeking.
The following examples will use parentheses, but they all work for each listed
trigger character accordingly.
#### In Pair
`i( i) ib i{ i} iB i[ i] i< i> it`
- Select inside of pair characters.
- This overrides Vim's default text object to allow seeking for the next pair
in the current line to the right or left when the cursor is not inside a
pair. This behavior is similar to Vim's seeking behavior of `di'` when not
inside of quotes, but it works both ways.
- Accepts a count to select multiple blocks.
```
............
a ( b ( cccccccc ) d ) e
│ └── i) ──┘ │
└───── 2i) ──────┘
```
#### A Pair
`a( a) ab a{ a} aB a[ a] a< a> at`
- Select a pair including pair characters.
- Overrides Vim's default text object to allow seeking.
- Accepts a count.
```
............
a ( b ( cccccccc ) d ) e
│ └─── a) ───┘ │
└────── 2a) ───────┘
```
#### Inside Pair
`I( I) Ib I{ I} IB I[ I] I< I> It`
- Select contents of pair characters.
- Like inside of parentheses, but exclude whitespace at both ends. Useful for
changing contents while preserving spacing.
- Accepts a count.
```
............
a ( b ( cccccccc ) d ) e
│ └─ I) ─┘ │
└──── 2I) ─────┘
```
#### Around Pair
`A( A) Ab A{ A} AB A[ A] A< A> At`
- Select around pair characters.
- Like a pair, but include whitespace at one side of the pair. Prefers to
select trailing whitespace, falls back to select leading whitespace.
- Accepts a count.
```
............
a ( b ( cccccccc ) d ) e
│ └─── A) ────┘ │
└────── 2A) ────────┘
```
### Next and Last Pair
`in( an( In( An( il( al( Il( Al( ...`
Work directly on distant pairs without moving there separately.
All the above pair text objects can be shifted to the next pair by
including the letter `n`. The command `in)` selects inside of the next
pair. Use the letter `l` instead to work on the previous (last) pair. Uses
a count to skip multiple pairs. Skipping works over multiple lines.
See our [Cheat Sheet][cheatsheet] for two charts summarizing all pair mappings.
### Pair Seek
If any of the normal pair commands (not containing `n` or `l`) is executed when
the cursor is not positioned inside a pair, it seeks for pairs before or after
the cursor by searching for the appropriate delimiter on the current line. This
is similar to using the explicit version containing `n` or `l`, but in only
seeks on the current line.
## Quote Text Objects
These text objects are similar to the built in text objects such as `i'`.
Supported trigger characters:
- `'` (work on single quotes)
- `"` (work on double quotes)
- `` ` `` (work on back ticks)
These quote text objects try to be smarter than the default ones. They count
the quotation marks from the beginning of the line to decide which of these are
the beginning of a quote and which ones are the end.
If you type `ci"` on the `,` in the example below, it will automatically skip
and change `world` instead of changing `,` between `hello` and `world`.
```
buffer │ join("hello", "world")
proper │ └─────┘ └─────┘
false │ └──┘
```
Quote text objects work over multiple lines and support seeking. See below for
details about seeking.
The following examples will use single quotes, but they all work for each
mentioned separator character accordingly.
#### In Quote
`` i' i" i` ``
- Select inside quote.
- This overrides Vim's default text object to allow seeking in both directions.
```
............
a ' bbbbbbbb ' c ' d ' e
└── i' ──┘
```
#### A Quote
``a' a" a` ``
- Select a quote.
- This overrides Vim's default text object to support seeking.
- Unlike Vim's quote text objects, this incudes no surrounding whitespace.
```
............
a ' bbbbbbbb ' c ' d ' e
└─── a' ───┘
```
#### Inside Quote
``I' I" I` ``
- Select contents of a quote.
- Like inside quote, but exclude whitespace at both ends. Useful for changing
contents while preserving spacing.
```
............
a ' bbbbbbbb ' c ' d ' e
└─ I' ─┘
```
#### Around Quote
``A' A" A` ``
- Select around a quote.
- Like a quote, but include whitespace in one direction. Prefers to select
trailing whitespace, falls back to select leading whitespace.
```
............
a ' bbbbbbbb ' c ' d ' e
└─── A' ────┘
```
### Next and Last Quote
`in' In' An' il' Il' Al' iN' IN' AN' iL' IL' AL' ...`
Work directly on distant quotes without moving there separately.
All the above pair text objects can be shifted to the next quote by
including the letter `n`. The command `in'` selects inside of the next
single quotes. Use the letter `l` instead to work on the previous (last)
quote. Uses a count to skip multiple quotation characters.
Use uppercase `N` and `L` to jump from within one quote into the next
proper quote, instead of into the pseudo quote in between. (Using `N`
instead of `n` is actually just doubling the count to achieve this.)
See our [Cheat Sheet][cheatsheet] for a chart summarizing all quote mappings.
### Quote Seek
If any of the normal quote commands (not containing `n`, `l`, `N` or `L`) is
executed when the cursor is not positioned inside a quote, it seeks for quotes
before or after the cursor by searching for the appropriate delimiter on the
current line. This is similar to using the explicit version containing `n` or
`l`.
## Separator Text Objects
These text objects are based on single separator characters like the comma in
one of our examples above. The text between two instances of the separator
character can be operated on with these targets.
Supported separators:
```
, . ; : + - = ~ _ * # / | \ & $
```
Separator text objects work over multiple lines and support seeking.
The following examples will use commas, but they all work for each listed
separator character accordingly.
#### In Separator
`i, i. i; i: i+ i- i= i~ i_ i* i# i/ i| i\ i& i$`
- Select inside separators. Similar to in quote.
```
...........
a , b , cccccccc , d , e
└── i, ──┘
```
#### A Separator
`a, a. a; a: a+ a- a= a~ a_ a* a# a/ a| a\ a& a$`
- Select an item in a list separated by the separator character.
- Includes the leading separator, but excludes the trailing one. This leaves
a proper list separated by the separator character after deletion. See the
examples above.
```
...........
a , b , cccccccc , d , e
└─── a, ──┘
```
#### Inside Separator
`I, I. I; I: I+ I- I= I~ I_ I* I# I/ I| I\ I& I$`
- Select contents between separators.
- Like inside separators, but exclude whitespace at both ends. Useful for
changing contents while preserving spacing.
```
...........
a , b , cccccccc , d , e
└─ I, ─┘
```
#### Around Separator
`A, A. A; A: A+ A- A= A~ A_ A* A# A/ A| A\ A& A$`
- Select around a pair of separators.
- Includes both separators and a surrounding whitespace, similar to `a'` and
`A(`.
```
...........
a , b , cccccccc , d , e
└─── A, ────┘
```
### Next and Last Separator
`in, an, In, An, il, al, Il, Al, iN, aN, IN, AN, iL, aL, IL, AL, ...`
Work directly on distant separators without moving there separately.
All the above separator text objects can be shifted to the next separator by
including the letter `n`. The command `in,` selects inside of the next commas.
Use the letter `l` instead to work on the previous (last) separators. Uses the
count to skip multiple separator characters.
Use uppercase `N` and `L` to jump from within one pair of separators into
the next distinct pair, instead of into the adjacent one. (Using `N`
instead of `n` is actually just doubling the count to achieve this.)
See our [Cheat Sheet][cheatsheet] for a chart summarizing all separator mappings.
### Separator Seek
Like quote seeking. If any of the normal separator commands (not
containing `n` or `l`) is executed when the cursor is not positioned inside a
pair of separators, it seeks for the separator before or after the cursor.
This is similar to using the explicit version containing `n` or `l`.
## Argument Text Objects
These text objects are similar to separator text objects, but are specialized
for arguments surrounded by braces and commas. They also take matching braces
into account to capture only valid arguments.
Argument text objects work over multiple lines and support seeking.
#### In Argument
`ia`
- Select inside arguments. Similar to in quote.
- Accepts a count.
```
...........
a , b ( cccccccc , d ) e
└── ia ──┘
```
#### An Argument
`aa`
- Select an argument in a list of arguments.
- Includes a separator if preset, but excludes surrounding braces. This leaves
a proper argument list after deletion.
- Accepts a count.
```
...........
a , b ( cccccccc , d ) e
└─── aa ──┘
```
#### Inside Argument
`Ia`
- Select content of an argument.
- Like inside separators, but exclude whitespace at both ends. Useful for
changing contents while preserving spacing.
- Accepts a count.
```
...........
a , b ( cccccccc , d ) e
└─ Ia ─┘
```
#### Around Argument
`Aa`
- Select around an argument.
- Includes both delimiters and a surrounding whitespace, similar to `a'` and
`A(`.
- Accepts a count.
```
...........
a , b ( cccccccc , d ) e
└─── Aa ────┘
```
### Next and Last Argument
`ina ana Ina Ana ila ala Ila Ala`
Work directly on distant arguments without moving there separately.
All the above argument text objects can be shifted to the next argument by
including the letter `n`. The command `ina` selects inside of the next
argument. Use the letter `l` instead to work on the previous (last) argument.
Uses a [count] to skip multiple argument characters. The order is determined by
the nearest surrounding argument delimiter.
See our [Cheat Sheet][cheatsheet] for a chart summarizing all argument mappings.
### Argument Seek
Like separator seeking. If any of the normal argument commands (not containing
`n` or `l`) is executed when the cursor is not positioned inside an argument,
it seeks for the argument before or after the cursor. This is similar to using
the explicit version containing `n` or `l`.
## Installation
Use your favorite plugin manager.
- [NeoBundle][neobundle]
```vim
NeoBundle 'wellle/targets.vim'
```
- [Vundle][vundle]
```vim
Bundle 'wellle/targets.vim'
```
- [Vim-plug][vim-plug]
```vim
Plug 'wellle/targets.vim'
```
- [Pathogen][pathogen]
```sh
git clone git://github.com/wellle/targets.vim.git ~/.vim/bundle/targets.vim
```
## Settings
Put these variables into your vimrc to customize the mappings described above.
The provided examples also indicate the default values.
Available options:
```vim
g:targets_aiAI
g:targets_nlNL
g:targets_pairs
g:targets_quotes
g:targets_separators
g:targets_tagTrigger
g:targets_argTrigger
g:targets_argOpening
g:targets_argClosing
g:targets_argSeparator
g:targets_seekRanges
g:targets_jumpRanges
```
### g:targets_aiAI
Default:
```vim
let g:targets_aiAI = 'aiAI'
```
Controls the normal mode operator mode maps that get created for In Pair (`i`),
A Pair (`a`), Inside Pair (`I`), and Around Pair (`A`). Required to be a 4
character long list. Use a space to deactivate a mode.
### g:targets_nlNL
Default:
```vim
let g:targets_nlNL = 'nlNL'
```
Controls the keys used in maps for seeking next and last text objects. For
example, if you don't wish to use the `N` and `L` seeks, and instead wish for
`n` to always search for the next object and `N` to search for the last, you
could set:
```vim
let g:targets_nlNL = 'nN '
```
Note that two extra spaces are still required on the end, indicating you wish
to disable the default functionality of `N` and `L`. Required to be a 4
character long list.
### g:targets_pairs
Default:
```vim
let g:targets_pairs = '()b {}B [] <>'
```
Defines the space separated list of pair objects you wish to use, along with
optional one letter aliases for them.
### g:targets_quotes
Default:
```vim
let g:targets_quotes = '" '' `'
```
Defines the space separated list of quoting objects you wish to use. Note that
you have to escape the single quote by doubling it. Quote objects can
optionally be followed by a single one letter alias. For example, to set `d`
as an alias for double quotes, allowing such commands as `cid` to be
equivalent to `ci"`, you could define:
```vim
let g:targets_quotes = '"d '' `'
```
### g:targets_separators
Default:
```vim
let g:targets_separators = ', . ; : + - = ~ _ * # / | \ & $'
```
Defines the space separated list of separator objects you wish to use. Like
quote objects, separator objects can optionally be followed by a single one
letter alias. To set `c` as an alias for comma, allowing such commands as
`dic` to be equivalent to `di,`, you could define:
```vim
let g:targets_separators = ',c . ; : + - = ~ _ * # / | \ & $'
```
### g:targets_tagTrigger
Default:
```vim
let g:targets_tagTrigger = 't'
```
Defines the key you need to press to operate on tag text objects.
### g:targets_argTrigger
Default:
```vim
let g:targets_argTrigger = 'a'
```
Defines the key you need to press to operate on arguments. To use `,` as
argument trigger, allowing commands as `da,` to act like `daa`, use this:
```vim
let g:targets_argTrigger = ','
```
### g:targets_argOpening and g:targets_argClosing
Default:
```vim
let g:targets_argOpening = '[([]'
let g:targets_argClosing = '[])]'
```
Defines regular expressions that match the beginning and closing delimiter of
an argument list respectively. If you also want to find arguments delimited by
curly braces, try this:
```vim
let g:targets_argOpening = '[({[]'
let g:targets_argClosing = '[]})]'
```
### g:targets_argSeparator
Default:
```vim
let g:targets_argSeparator = ','
```
Defines a regular expression matching separators in an argument list. If you
also want to find arguments separated by semicolon, use this:
```vim
let g:targets_argSeparator = '[,;]'
```
### g:targets_seekRanges
Default:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr ll lb ar ab lB Ar aB Ab AB rb al rB Al bb aa bB Aa BB AA'
```
Defines a priority ordered, space separated list of range types which can be
used to customize seeking behavior.
The default setting generally prefers targets around the cursor, with one
exception: If the target around the cursor is not contained in the current
cursor line, but the next or last target are, then prefer those. Targets
beginning or ending on the cursor are preferred over everything else.
Some other useful example settings:
Prefer multiline targets around cursor over distant targets within cursor line:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr lb ar ab lB Ar aB Ab AB rr ll rb al rB Al bb aa bB Aa BB AA'
```
Never seek backwards:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr lb ar ab lB Ar aB Ab AB rb rB bb bB BB'
```
Only seek if next/last targets touch current line:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr ll lb ar ab lB Ar aB Ab AB rb rB al Al'
```
Only consider targets fully visible on screen:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr lb ar ab rr rb bb ll al aa'
```
Only consider targets around cursor:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr lb ar ab lB Ar aB Ab AB'
```
Only consider targets fully contained in current line:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr ll'
```
If you want to build your own, or are just curious what those cryptic letters
mean, check out the full documentation in our [Cheat Sheet][cheatsheet].
### g:targets_jumpRanges
Default:
```vim
let g:targets_jumpRanges = 'bb bB BB aa Aa AA' ~
```
Defines an unordered, space separated list of range types which can be used to
customize the jumplist behavior (see documentation on seek ranges). It
controls whether or not to add the cursor position prior to selecting the text
object to the jumplist.
The default setting adds the previous cursor position to the jumplist if the
target that was operated on doesn't intersect the cursor line. That means it
adds a jumplist entry if the target ends above the cursor line or starts below
the cursor line.
Some other useful example settings (or build your own!):
Never add cursor position to jumplist:
```vim
let g:targets_jumpRanges = '' ~
```
Always add cursor position to jumplist:
```vim
let g:targets_jumpRanges = 'cr cb cB lc ac Ac lr rr ll lb ar ab lB Ar aB Ab AB rb al rB Al bb aa bB Aa BB AA' ~
```
Only add to jumplist if cursor was not inside the target:
```vim
let g:targets_jumpRanges = 'rr rb rB bb bB BB ll al Al aa Aa AA' ~
```
## Notes
- [Repeating an operator-pending mapping forgets its last count.][repeatcount]
Works since Vim 7.4.160
## Issues
- [Empty matches can't be selected because it is not possible to visually select
zero-character ranges.][emptyrange]
- Forcing motion to work linewise by inserting `V` in `dVan(` doesn't work
for operator-pending mappings. [See `:h o_v`][o_v].
- Report issues or submit pull requests to
[github.com/wellle/targets.vim][targets].
## Todos
Create more mappings to support commands like `danw` or `danp` to delete the
next word or paragraph.
[cheatsheet]: cheatsheet.md
[textobjects]: http://vimdoc.sourceforge.net/htmldoc/motion.html#text-objects
[operator]: http://vimdoc.sourceforge.net/htmldoc/motion.html#operator
[repeat]: http://vimdoc.sourceforge.net/htmldoc/repeat.html#single-repeat
[neobundle]: https://github.com/Shougo/neobundle.vim
[vundle]: https://github.com/gmarik/vundle
[vim-plug]: https://github.com/junegunn/vim-plug
[pathogen]: https://github.com/tpope/vim-pathogen
[repeatcount]: https://groups.google.com/forum/?fromgroups#!topic/vim_dev/G4SSgcRVN7g
[emptyrange]: https://groups.google.com/forum/#!topic/vim_use/qialxUwdcMc
[targets]: https://github.com/wellle/targets.vim
[o_v]: http://vimdoc.sourceforge.net/htmldoc/motion.html#o_v

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,54 @@
let s:invalid = 0
let s:empty = 1
let s:nonempty = 2
function! targets#state#new(state)
return {
\ 'state': a:state,
\
\ 'isInvalid': function('targets#state#isInvalid'),
\ 'isEmpty': function('targets#state#isEmpty'),
\ 'isNonempty': function('targets#state#isNonempty'),
\ 'isValid': function('targets#state#isValid'),
\ 'isInvalidOrEmpty': function('targets#state#isInvalidOrEmpty'),
\ }
endfunction
" constructors
function! targets#state#invalid()
return targets#state#new(s:invalid)
endfunction
function! targets#state#nonempty()
return targets#state#new(s:nonempty)
endfunction
function! targets#state#empty()
return targets#state#new(s:empty)
endfunction
" raw attributes
function! targets#state#isInvalid() dict
return self.state == s:invalid
endfunction
function! targets#state#isEmpty() dict
return self.state == s:empty
endfunction
function! targets#state#isNonempty() dict
return self.state == s:nonempty
endfunction
" derived attributes
" empty or nonempty
function! targets#state#isValid() dict
return self.state != s:invalid
endfunction
function! targets#state#isInvalidOrEmpty() dict
return self.state != s:nonempty
endfunction

View file

@ -0,0 +1,186 @@
function! targets#target#new(sl, sc, el, ec, error)
return {
\ 'error': a:error,
\ 'sl': a:sl,
\ 'sc': a:sc,
\ 'el': a:el,
\ 'ec': a:ec,
\ 'linewise': 0,
\
\ 'copy': function('targets#target#copy'),
\ 'setS': function('targets#target#setS'),
\ 'setE': function('targets#target#setE'),
\ 's': function('targets#target#s'),
\ 'e': function('targets#target#e'),
\ 'searchposS': function('targets#target#searchposS'),
\ 'searchposE': function('targets#target#searchposE'),
\ 'getcharS': function('targets#target#getcharS'),
\ 'getcharE': function('targets#target#getcharE'),
\ 'getposS': function('targets#target#getposS'),
\ 'getposE': function('targets#target#getposE'),
\ 'cursorS': function('targets#target#cursorS'),
\ 'cursorE': function('targets#target#cursorE'),
\ 'state': function('targets#target#state'),
\ 'range': function('targets#target#range'),
\ 'select': function('targets#target#select'),
\ 'string': function('targets#target#string')
\ }
endfunction
function! targets#target#fromValues(sl, sc, el, ec)
if a:sl == 0 || a:sc == 0 || a:el == 0 || a:ec == 0
return targets#target#withError("zero found")
endif
return targets#target#new(a:sl, a:sc, a:el, a:ec, '')
endfunction
function! targets#target#fromVisualSelection()
let [sl, sc] = getpos("'<")[1:2]
let [el, ec] = getpos("'>")[1:2]
return targets#target#fromValues(sl, sc, el, ec)
endfunction
function! targets#target#withError(error)
return targets#target#new(0, 0, 0, 0, a:error)
endfunction
function! targets#target#copy() dict
return targets#target#fromValues(self.sl, self.sc, self.el, self.ec)
endfunction
function! targets#target#setS(line, column) dict
let [self.sl, self.sc] = [a:line, a:column]
endfunction
function! targets#target#setE(line, column) dict
let [self.el, self.ec] = [a:line, a:column]
endfunction
function! targets#target#s() dict
return [self.sl, self.sc]
endfunction
function! targets#target#e() dict
return [self.el, self.ec]
endfunction
function! targets#target#searchposS(...) dict
let pattern = a:1
let flags = a:0 > 1 ? a:2 : ''
let stopline = a:0 > 2 ? a:3 : 0
let [self.sl, self.sc] = searchpos(pattern, flags, stopline)
endfunction
function! targets#target#searchposE(...) dict
let pattern = a:1
let flags = a:0 > 1 ? a:2 : ''
let stopline = a:0 > 2 ? a:3 : 0
let [self.el, self.ec] = searchpos(pattern, flags, stopline)
endfunction
function! targets#target#getcharS() dict
return getline(self.sl)[self.sc-1]
endfunction
function! targets#target#getcharE() dict
return getline(self.el)[self.ec-1]
endfunction
" args (mark = '.')
function! targets#target#getposS(...) dict
let mark = a:0 > 0 ? a:1 : '.'
let [self.sl, self.sc] = getpos(mark)[1:2]
endfunction
" args (mark = '.')
function! targets#target#getposE(...) dict
let mark = a:0 > 0 ? a:1 : '.'
let [self.el, self.ec] = getpos(mark)[1:2]
endfunction
function! targets#target#cursorS() dict
call cursor(self.s())
endfunction
function! targets#target#cursorE() dict
call cursor(self.e())
endfunction
function! targets#target#state() dict
if self.error != ''
return targets#state#invalid()
endif
if self.sl == 0 || self.el == 0
return targets#state#invalid()
elseif self.sl < self.el
return targets#state#nonempty()
elseif self.sl > self.el
return targets#state#invalid()
elseif self.sc == self.ec + 1
return targets#state#empty()
elseif self.sc > self.ec
return targets#state#invalid()
else
return targets#state#nonempty()
endif
endfunction
function! targets#target#range(cursor, min, max) dict
if self.error != ''
return ''
endif
let positionS = s:position(self.sl, self.sc, a:cursor, a:min, a:max, 'c')
let positionE = s:position(self.el, self.ec, a:cursor, a:min, a:max, 'c')
return positionS . positionE
endfunction
function! s:position(line, column, cursor, min, max, tie)
let cursorLine = a:cursor[1]
if a:line == cursorLine " cursor line
let cursorColumn = a:cursor[2]
if a:column == cursorColumn " same column
return a:tie
elseif a:column < cursorColumn " left of cursor
return 'l'
else " a:column > cursorColumn " right of cursor
return 'r'
endif
elseif a:line < cursorLine
if a:line >= a:min " above on screen
return 'a'
else " above off screen
return 'A'
endif
else " a:line > cursorLine
if a:line <= a:max " below on screen
return 'b'
else " below off screen
return 'B'
endif
endif
endfunction
" visually select the target
function! targets#target#select() dict
call cursor(self.s())
if self.linewise
silent! normal! V
else
silent! normal! v
endif
call cursor(self.e())
endfunction
function! targets#target#string() dict
if self.error != ''
return '[err:' . self.error . ']'
endif
return '[' . self.sl . ' ' . self.sc . '; ' . self.el . ' ' . self.ec . ']'
endfunction

View file

@ -0,0 +1,273 @@
## Pair mappings
Available mappings
i( i) ib i{ i} iB i[ i] ir i< i> ia it
a( a) ab a{ a} aB a[ a] ar a< a> aa at
I( I) Ib I{ I} IB I[ I] Ir I< I> Ia It
A( A) Ab A{ A} AB A[ A] Ar A< A> Aa At
in( in) inb in{ in} inB in[ in] inr in< in> ina int
an( an) anb an{ an} anB an[ an] anr an< an> ana ant
In( In) Inb In{ In} InB In[ In] Inr In< In> Ina Int
An( An) Anb An{ An} AnB An[ An] Anr An< An> Ana Ant
il( il) ilb il{ il} ilB il[ il] ilr il< il> ila ilt
al( al) alb al{ al} alB al[ al] alr al< al> ala alt
Il( Il) Ilb Il{ Il} IlB Il[ Il] Ilr Il< Il> Ila Ilt
Al( Al) Alb Al{ Al} AlB Al[ Al] Alr Al< Al> Ala Alt
Chart for a list of pairs
```
..........
a ( bbbbbbbb ) ( ccccccc ) ( dddddd ) ( eeeeeee ) ( ffffffff ) g
││└ 2Il) ┘│││││└ Il) ┘│││││└ I) ┘│││││└ In) ┘│││││└ 2In) ┘│││
│└─ 2il) ─┘│││└─ il) ─┘│││└─ i) ─┘│││└─ in) ─┘│││└─ 2in) ─┘││
├── 2al) ──┘│├── al) ──┘│├── a) ──┘│├── an) ──┘│├── 2an) ──┘│
└── 2Al) ───┘└── Al) ───┘└── A) ───┘└── An) ───┘└── 2An) ───┘
```
Chart for nested pairs
```
..........
a ( b ( cccccccc ) d ) ( e ( ffffff ) g ) ( h ( iiiiiiii ) j ) k
│││ ││└ 2Il) ┘││││││││││ ││└ I) ┘││││││││││ ││└ 2In) ┘│││││││
│││ │└─ 2il) ─┘│││││││││ │└─ i) ─┘│││││││││ │└─ 2in) ─┘││││││
│││ ├── 2al) ──┘││││││││ ├── a) ──┘││││││││ ├── 2an) ──┘│││││
│││ └── 2Al) ───┘│││││││ └── A) ───┘│││││││ └── 2An) ───┘││││
││└───── Il) ────┘│││││└─── 2I) ────┘│││││└───── In) ────┘│││
│└────── il) ─────┘│││└──── 2i) ─────┘│││└────── in) ─────┘││
├─────── al) ──────┘│├───── 2a) ──────┘│├─────── an) ──────┘│
└─────── Al) ───────┘└───── 2A) ───────┘└─────── An) ───────┘
```
## Quote mappings
Available mappings
```
i' i" i` in' in" in` il' il" il` iL' iL" iL`
a' a" a` an' an" an` al' al" al` aL' aL" aL`
I' I" I` In' In" In` Il' Il" Il` IL' IL" IL`
A' A" A` An' An" An` Al' Al" Al` AL' AL" AL`
```
Chart for a list of quotes
```
.............
a ' bbbbbbb ' c ' dddddd ' e ' fffffff ' g
││└ Il' ┘│││ ││└ I' ┘│││ ││└ In' ┘│││
│└─ il' ─┘││ │└─ i' ─┘││ │└─ in' ─┘││
├── al' ──┘│ ├── a' ──┘│ ├── an' ──┘│
└── Al' ───┘ └── A' ───┘ └── An' ───┘
```
## Separator mappings
Available mappings
```
i, i. i; i: i+ i- i= i~ i_ i* i# i/ i| i\ i& i$
a, a. a; a: a+ a- a= a~ a_ a* a# a/ a| a\ a& a$
I, I. I; I: I+ I- I= I~ I_ I* I# I/ I| I\ I& I$
A, A. A; A: A+ A- A= A~ A_ A* A# A/ A| A\ A& A$
in, in. in; in: in+ in- in= in~ in_ in* in# in/ in| in\ in& in$
an, an. an; an: an+ an- an= an~ an_ an* an# an/ an| an\ an& an$
In, In. In; In: In+ In- In= In~ In_ In* In# In/ In| In\ In& In$
An, An. An; An: An+ An- An= An~ An_ An* An# An/ An| An\ An& An$
il, il. il; il: il+ il- il= il~ il_ il* il# il/ il| il\ il& il$
al, al. al; al: al+ al- al= al~ al_ al* al# al/ al| al\ al& al$
Il, Il. Il; Il: Il+ Il- Il= Il~ Il_ Il* Il# Il/ Il| Il\ Il& Il$
Al, Al. Al; Al: Al+ Al- Al= Al~ Al_ Al* Al# Al/ Al| Al\ Al& Al$
iN, iN. iN; iN: iN+ iN- iN= iN~ iN_ iN* iN# iN/ iN| iN\ iN& iN$
aN, aN. aN; aN: aN+ aN- aN= aN~ aN_ aN* aN# aN/ aN| aN\ aN& aN$
IN, IN. IN; IN: IN+ IN- IN= IN~ IN_ IN* IN# IN/ IN| IN\ IN& IN$
AN, AN. AN; AN: AN+ AN- AN= AN~ AN_ AN* AN# AN/ AN| AN\ AN& AN$
iL, iL. iL; iL: iL+ iL- iL= iL~ iL_ iL* iL# iL/ iL| iL\ iL& iL$
aL, aL. aL; aL: aL+ aL- aL= aL~ aL_ aL* aL# aL/ aL| aL\ aL& aL$
IL, IL. IL; IL: IL+ IL- IL= IL~ IL_ IL* IL# IL/ IL| IL\ IL& IL$
AL, AL. AL; AL: AL+ AL- AL= AL~ AL_ AL* AL# AL/ AL| AL\ AL& AL$
```
Chart for a list of separators
```
.........
a , bbbbbbb , ccccccc , dddddd , eeeeeee , fffffff , g
││└ IL, ┘│││└ Il, ┘│││└ I, ┘│││└ In, ┘│││└ IN, ┘│ │
│└─ iL, ─┤│├─ il, ─┤│├─ i, ─┤│├─ in, ─┤│├─ iN, ─┤ │
├── aL, ─┘├┼─ al, ─┘├┼─ a, ─┘├┼─ an, ─┘├┼─ aN, ─┘ │
└── AL, ──┼┘ └┼─ A, ──┼┘ └┼─ AN, ───┘
└─ Al, ──┘ └─ An, ──┘
```
## Argument mappings
Available mappings
```
ia aa Ia Aa
ina ana Ina Ana
ila ala Ila Ala
```
Chart for arguments
```
.........
a ( bbbbbb , ccccccc , d ( eeeeee , fffffff ) , gggggg ) h
││├2Ila┘│││└─Ila─┘││││ ││├─Ia─┘│││└─Ina─┘│││││└2Ina┘│ │
│└┼2ila─┘│├──ila──┤│││ │└┼─ia──┘│├──ina──┤│││├─2ina─┤ │
│ └2ala──┼┤ ││││ │ └─aa───┼┤ │││├┼─2ana─┘ │
└──2Ala──┼┘ ││││ └───Aa───┼┘ │││└┼─2Ana───┘
├───ala──┘│││ ├───ana──┘││ │
└───Ala───┼┤│ └───Ana───┼┤ │
││└─────2Ia────────────┘│ │
│└──────2ia─────────────┤ │
├───────2aa─────────────┘ │
└───────2Aa───────────────┘
```
## Customize seeking
Seeking is controlled by the setting `g:targets_seekRanges`. Default value:
```vim
let g:targets_seekRanges = 'lr rr ll lb ar ab lB Ar aB Ab AB rb al rB Al bb aa bB Aa BB AA'
```
When using a command like `cib` to change inside a block, targets.vim considers
the three targets:
- smallest target around cursor
- next target after cursor
- last target before cursor
For each of those that were found, we detect what range type it has. A range
type depends on the relative position of the start and end of the target,
relative to the current cursor position and the currently visible lines.
The possibly relative positions are:
- `c`: on cursor position
- `l`: left of cursor in current line
- `r`: right of cursor in current line
- `a`: above cursor on screen
- `b`: below cursor on screen
- `A`: above cursor off screen
- `B`: below cursor off screen
All possibly ranges are listed below, denoted by two characters: one for the
relative start and one for the relative end position of the target. For
example, `lr` means "from left of cursor to right of cursor in cursor line".
Next to each range type is a pictogram of an example. They are made of these
symbols:
- `.`: current cursor position
- `(`: start of target
- `)`: end of target
- `/`: line break before and after cursor line
- `|`: screen edge between hidden and visible lines
#### Ranges on cursor:
```
cr | / () / | starting on cursor, current line
cb | / ( /) | starting on cursor, multiline down, on screen
cB | / ( / |) starting on cursor, multiline down, partially off screen
lc | / () / | ending on cursor, current line
ac | (/ ) / | ending on cursor, multiline up, on screen
Ac (| / ) / | ending on cursor, multiline up, partially off screen
```
#### Ranges around cursor:
```
lr | / (.) / | around cursor, current line
lb | / (. /) | around cursor, multiline down, on screen
ar | (/ .) / | around cursor, multiline up, on screen
ab | (/ . /) | around cursor, multiline both, on screen
lB | / (. / |) around cursor, multiline down, partially off screen
Ar (| / .) / | around cursor, multiline up, partially off screen
aB | (/ . / |) around cursor, multiline both, partially off screen bottom
Ab (| / . /) | around cursor, multiline both, partially off screen top
AB (| / . / |) around cursor, multiline both, partially off screen both
```
#### Ranges after (right of/below) cursor
```
rr | / .()/ | after cursor, current line
rb | / .( /) | after cursor, multiline, on screen
rB | / .( / |) after cursor, multiline, partially off screen
bb | / . /()| after cursor below, on screen
bB | / . /( |) after cursor below, partially off screen
BB | / . / |() after cursor below, off screen
```
#### Ranges before (left of/above) cursor
```
ll | /(). / | before cursor, current line
al | (/ ). / | before cursor, multiline, on screen
Al (| / ). / | before cursor, multiline, partially off screen
aa |()/ . / | before cursor above, on screen
Aa (| )/ . / | before cursor above, partially off screen
AA ()| / . / | before cursor above, off screen
```
Pictogram legend:
```
A a l r b B relative positions
└───────────┘ visible screen
└─────┘ current line
```
Given the range types of our targets, we then pick the one that appears first
in `g:targets_seekRanges`. If none is found, the selection fails.
The default setting generally prefers targets around the cursor, with one
exception: If the target around the cursor is not contained in the current
cursor line, but the next or last target are, then prefer those. Targets
beginning or ending on the cursor are preferred over everything else.
Some other useful example settings:
Prefer multiline targets around cursor over distant targets within cursor line:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr lb ar ab lB Ar aB Ab AB rr ll rb al rB Al bb aa bB Aa BB AA'
```
Never seek backwards:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr lb ar ab lB Ar aB Ab AB rb rB bb bB BB'
```
Only seek if next/last targets touch current line:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr ll lb ar ab lB Ar aB Ab AB rb rB al Al'
```
Only consider targets fully visible on screen:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr lb ar ab rr rb bb ll al aa'
```
Only consider targets around cursor:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr lb ar ab lB Ar aB Ab AB'
```
Only consider targets fully contained in current line:
```vim
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr ll'
```

View file

@ -0,0 +1,772 @@
*targets.txt* Provide additional text objects
Author: Christian Wellenbrock <christian.wellenbrock@gmail.com>
License: MIT license
____
\___\_.::::::::::.____
/___/ '::::::::::'
==============================================================================
INTRODUCTION *targets-introduction*
Targets.vim adds various |text-objects| to give you more targets to operate
on. It expands on the idea of simple commands like `di'` (delete inside the
single quotes around the cursor) to give you more opportunities to craft
powerful commands that can be repeated reliably. Another major goal is to
handle all corner cases correctly.
==============================================================================
EXAMPLES *targets-examples*
The following examples are displayed as three lines each. The top line denotes
cursor positions from where the presented command works. The middle line shows
the contents of the example line that we're working on. The last line shows
the part of the line that the command will operate on.
To change the text in the next pair of parentheses, use the `cin)` command
.....................
This is example text (with a pair of parentheses) ~
└───────── cin) ─────────┘
To delete the item in a comma separated list under the cursor, use `da,`
.........
Shopping list: oranges, apples, bananas, tomatoes ~
└─ da, ─┘
Notice how the selection includes exactly one of the surrounding commas to
leave a proper comma separated list behind.
==============================================================================
OVERVIEW *targets-overview*
We distinguish between four kinds of text objects that behave slightly
differently:
Pair text objects |targets-pair-text-objects|
Quote text objects |targets-quote-text-objects|
Separator text objects |targets-separator-text-objects|
Argument text objects |targets-argument-text-objects|
==============================================================================
PAIR TEXT OBJECTS *targets-pair-text-objects*
These text objects are similar to the built in text objects such as |i)|.
Supported trigger characters:
( ) b (work on parentheses)
{ } B (work on curly braces)
[ ] (work on square brackets)
< > (work on angle brackets)
t (work on tags)
Pair text objects work over multiple lines and support |targets-pair-seek|.
We borrowed the aliases `r` and `a` from the |surround| plugin by Tim Pope.
The following examples will use parentheses, but they all work for each listed
trigger character accordingly.
i( i) ib i[ i] it *it_t* *i(_t* *i)_t* *ib_t* *i[_t* *i]_t*
i{ i} iB i< i> *i{_t* *i}_t* *iB_t* *i<_t* *i>_t*
Select inside of pair characters. This overrides Vim's default text object
to allow seeking for the next pair in the current line to the right or
left when the cursor is not inside a pair. This behavior is similar to
Vim's seeking behavior of `di'` when not inside of quotes, but it works
both ways. Accepts a [count] to select multiple
blocks.
............
a ( b ( cccccccc ) d ) e ~
│ └── i) ──┘ │
└───── 2i) ──────┘
a( a) ab a[ a] at *at_t* *a(_t* *a)_t* *ab_t* *a[_t* *a]_t*
a{ a} aB a< a> *a{_t* *a}_t* *aB_t* *a<_t* *a>_t*
Select a pair. Overrides Vim's default text object to allow seeking.
Accepts [count].
............
a ( b ( cccccccc ) d ) e ~
│ └─── a) ───┘ │
└────── 2a) ───────┘
I( I) Ib I[ I] It *It* *I(* *I)* *Ib* *I[* *I]*
I{ I} IB I< I> *I{* *I}* *IB* *I<* *I>*
Select contents of pair characters. Like inside of parentheses, but
exclude whitespace at both ends. Useful for changing contents while
preserving spacing. Accepts [count].
............
a ( b ( cccccccc ) d ) e ~
│ └─ I) ─┘ │
└──── 2I) ─────┘
A( A) Ab A[ A] At *At* *A(* *A)* *Ab* *A[* *A]*
A{ A} AB A< A> *A{* *A}* *AB* *A<* *A>*
Select around pair characters. Like a pair, but include whitespace at one
side of the pair. Prefers to select trailing whitespace, falls back to
select leading whitespace. Accepts [count].
............
a ( b ( cccccccc ) d ) e ~
│ └─── A) ────┘ │
└────── 2A) ────────┘
------------------------------------------------------------------------------
NEXT AND LAST PAIR *targets-next-last-pair*
Work directly on distant pairs without moving there separately.
in( in) inb in[ in] int *int* *in(* *in)* *inb* *in[* *in]*
in{ in} inB in< in> *in{* *in}* *inB* *in<* *in>*
an( an) anb an[ an] ant *ant* *an(* *an)* *anb* *an[* *an]*
an{ an} anB an< an> *an{* *an}* *anB* *an<* *an>*
In( In) Inb In[ In] Int *Int* *In(* *In)* *Inb* *In[* *In]*
In{ In} InB In< In> *In{* *In}* *InB* *In<* *In>*
An( An) Anb An[ An] Ant *Ant* *An(* *An)* *Anb* *An[* *An]*
An{ An} AnB An< An> *An{* *An}* *AnB* *An<* *An>*
il( il) ilb il[ il] ilt *ilt* *il(* *il)* *ilb* *il[* *il]*
il{ il} ilB il< il> *il{* *il}* *ilB* *il<* *il>*
al( al) alb al[ al] alt *alt* *al(* *al)* *alb* *al[* *al]*
al{ al} alB al< al> *al{* *al}* *alB* *al<* *al>*
Il( Il) Ilb Il[ Il] Ilt *Ilt* *Il(* *Il)* *Ilb* *Il[* *Il]*
Il{ Il} IlB Il< Il> *Il{* *Il}* *IlB* *Il<* *Il>*
Al( Al) Alb Al[ Al] Alt *Alt* *Al(* *Al)* *Alb* *Al[* *Al]*
Al{ Al} AlB Al< Al> *Al{* *Al}* *AlB* *Al<* *Al>*
All the above pair text objects can be shifted to the next pair by
including the letter `n`. The command `in)` selects inside of the next
pair. Use the letter `l` instead to work on the previous (last) pair. Uses
a [count] to skip multiple pairs. Skipping works over multiple lines.
*targets-pair-charts*
The following charts summarizes all pair mappings for a list of pairs and
nested pairs:
..........
a ( bbbbbbbb ) ( ccccccc ) ( dddddd ) ( eeeeeee ) ( ffffffff ) g ~
││└ 2Il) ┘│││││└ Il) ┘│││││└ I) ┘│││││└ In) ┘│││││└ 2In) ┘│││
│└─ 2il) ─┘│││└─ il) ─┘│││└─ i) ─┘│││└─ in) ─┘│││└─ 2in) ─┘││
├── 2al) ──┘│├── al) ──┘│├── a) ──┘│├── an) ──┘│├── 2an) ──┘│
└── 2Al) ───┘└── Al) ───┘└── A) ───┘└── An) ───┘└── 2An) ───┘
..........
a ( b ( cccccccc ) d ) ( e ( ffffff ) g ) ( h ( iiiiiiii ) j ) k ~
│││ ││└ 2Il) ┘││││││││││ ││└ I) ┘││││││││││ ││└ 2In) ┘│││││││
│││ │└─ 2il) ─┘│││││││││ │└─ i) ─┘│││││││││ │└─ 2in) ─┘││││││
│││ ├── 2al) ──┘││││││││ ├── a) ──┘││││││││ ├── 2an) ──┘│││││
│││ └── 2Al) ───┘│││││││ └── A) ───┘│││││││ └── 2An) ───┘││││
││└───── Il) ────┘│││││└─── 2I) ────┘│││││└───── In) ────┘│││
│└────── il) ─────┘│││└──── 2i) ─────┘│││└────── in) ─────┘││
├─────── al) ──────┘│├───── 2a) ──────┘│├─────── an) ──────┘│
└─────── Al) ───────┘└───── 2A) ───────┘└─────── An) ───────┘
------------------------------------------------------------------------------
PAIR SEEK *targets-pair-seek*
If any of the normal pair commands (not containing `n` or `l`) is executed
when the cursor is not positioned inside a pair, it seeks for pairs before or
after the cursor by searching for the appropriate delimiter on the current
line. This is similar to using the explicit version containing `n` or `l`, but
in only seeks on the current line.
==============================================================================
QUOTE TEXT OBJECTS *targets-quote-text-objects*
These text objects are similar to the built in text objects such as |i'|.
Supported trigger characters:
' (work on single quotes)
" (work on double quotes)
` (work on back ticks)
These quote text objects try to be smarter than the default ones. They count
the quotation marks from the beginning of the line to decide which of these
are the beginning of a quote and which ones are the end.
If you type `ci"` on the `,` in the example below, it will automatically skip
and change `world` instead of changing `,` between `hello` and `world`.
join("hello", "world") ~
└─────┘ └─────┘ proper quotes
└──┘ false quotes
Quote text objects work over multiple lines and support |targets-quote-seek|.
The following examples will use single quotes, but they all work for each
listed quoting character accordingly.
i' i" i` *i`_t* *i'_t* *iquote_t*
Select inside quote. This overrides Vim's default text object to allow
seeking in both directions.
............
a ' bbbbbbbb ' c ' d ' e~
└── i' ──┘
a' a" a` *a`_t* *a'_t* *aquote_t*
Select a quote. This overrides Vim's default text object to support
|targets-quote-seek|. Unlike Vim's quote text objects, this incudes no
surrounding whitespace.
............
a ' bbbbbbbb ' c ' d ' e~
└─── a' ───┘
I' I" I` *I`* *I'* *Iquote*
Select contents of a quote. Like inside quote, but exclude whitespace at
both ends. Useful for changing contents while preserving spacing.
............
a ' bbbbbbbb ' c ' d ' e~
└─ I' ─┘
A' A" A` *A`* *A'* *Aquote*
Select around a quote. Like a quote, but include whitespace in one
direction. Prefers to select trailing whitespace, falls back to select
leading whitespace.
............
a ' bbbbbbbb ' c ' d ' e~
└─── A' ────┘
------------------------------------------------------------------------------
NEXT AND LAST QUOTE *targets-next-last-quote*
Work directly on distant quotes without moving there separately.
in' in" in` il' il" il` *in`* *in'* *inquote* *il`* *il'* *ilquote*
an' an" an` al' al" al` *an`* *an'* *anquote* *al`* *al'* *alquote*
In' In" In` Il' Il" Il` *In`* *In'* *Inquote* *Il`* *Il'* *Ilquote*
iN' iN" iN` iL' iL" iL` *iN`* *iN'* *iNquote* *iL`* *iL'* *iLquote*
aN' aN" aN` aL' aL" aL` *aN`* *aN'* *aNquote* *aL`* *aL'* *aLquote*
IN' IN" IN` IL' IL" IL` *IN`* *IN'* *INquote* *IL`* *IL'* *ILquote*
All the above pair text objects can be shifted to the next quote by
including the letter `n`. The command `in'` selects inside of the next
single quotes. Use the letter `l` instead to work on the previous (last)
quote. Uses a [count] to skip multiple quotation characters.
Use uppercase `N` and `L` to jump from within one quote into the next
proper quote, instead of into the pseudo quote in between. (Using `N`
instead of `n` is actually just doubling the count to achieve this.)
*targets-quote-chart*
The following chart summarizes all quote mappings:
.............
a ' bbbbbbb ' c ' dddddd ' e ' fffffff ' g ~
││└ Il' ┘│││ ││└ I' ┘│││ ││└ In' ┘│││
│└─ il' ─┘││ │└─ i' ─┘││ │└─ in' ─┘││
├── al' ──┘│ ├── a' ──┘│ ├── an' ──┘│
└── Al' ───┘ └── A' ───┘ └── An' ───┘
------------------------------------------------------------------------------
QUOTE SEEK *targets-quote-seek*
If any of the normal quote commands (not containing `n`, `l`, `N` or `L`) is
executed when the cursor is not positioned inside a quote, it seeks for quotes
before or after the cursor by searching for the appropriate delimiter on the
current line. Similar to using the explicit version containing `n` or `l`.
==============================================================================
SEPARATOR TEXT OBJECTS *targets-separator-text-objects*
These text objects are based on single separator characters like the comma in
one of our |targets-examples|. The text between two instances of the separator
character can be operated on with these targets.
Supported separators:
, . ; : + - = ~ _ * # / | \ & $ ~
Separator text objects work over multiple lines and support
|targets-separator-seek|.
The following examples will use commas, but they all work for each listed
separator character accordingly.
i, i. i; i: i+ i- i= i~ *i,* *i.* *i;* *i:* *i+* *i-* *i=* *i~*
i_ i/ i| i\ i& i$ i# i* *i_* *i/* *i|* *i\* *i&* *i$* *i#* *istar*
Select inside separators.
...........
a , b , cccccccc , d , e ~
└── i, ──┘
a, a. a; a: a+ a- a= a~ *a,* *a.* *a;* *a:* *a+* *a-* *a=* *a~*
a_ a/ a| a\ a& a$ a# a* *a_* *a/* *a|* *a\* *a&* *a$* *a#* *astar*
Select an item in a list separated by the separator character. This
includes the leading separator, but excludes the trailing one. This leaves
a proper list separated by the separator character after deletion. See
|targets-examples|.
...........
a , b , cccccccc , d , e ~
└─── a, ──┘
I, I. I; I: I+ I- I= I~ *I,* *I.* *I;* *I:* *I+* *I-* *I=* *I~*
I_ I/ I| I\ I& I$ I# I* *I_* *I/* *I|* *I\* *I&* *I$* *I#* *Istar*
Select contents between separators. Like inside separators, but exclude
whitespace at both ends. Useful for changing contents while preserving
spacing.
...........
a , b , cccccccc , d , e ~
└─ I, ─┘
A, A. A; A: A+ A- A= A~ *A,* *A.* *A;* *A:* *A+* *A-* *A=* *A~*
A_ A/ A| A\ A& A$ A# A* *A_* *A/* *A|* *A\* *A&* *A$* *A#* *Astar*
Select around a pair of separators. This includes both separators and a
surrounding whitespace, similar to `a'` and `A(`.
...........
a , b , cccccccc , d , e ~
└─── A, ────┘
------------------------------------------------------------------------------
NEXT AND LAST SEPARATOR *targets-next-last-separator*
Work directly on distant separators without moving there separately.
*in,* *in.* *in;* *in:* *in+* *in-* *in=* *in~*
*an,* *an.* *an;* *an:* *an+* *an-* *an=* *an~*
*In,* *In.* *In;* *In:* *In+* *In-* *In=* *In~*
*An,* *An.* *An;* *An:* *An+* *An-* *An=* *An~*
*il,* *il.* *il;* *il:* *il+* *il-* *il=* *il~*
*al,* *al.* *al;* *al:* *al+* *al-* *al=* *al~*
*Il,* *Il.* *Il;* *Il:* *Il+* *Il-* *Il=* *Il~*
*Al,* *Al.* *Al;* *Al:* *Al+* *Al-* *Al=* *Al~*
*iN,* *iN.* *iN;* *iN:* *iN+* *iN-* *iN=* *iN~*
*aN,* *aN.* *aN;* *aN:* *aN+* *aN-* *aN=* *aN~*
*IN,* *IN.* *IN;* *IN:* *IN+* *IN-* *IN=* *IN~*
*AN,* *AN.* *AN;* *AN:* *AN+* *AN-* *AN=* *AN~*
*iL,* *iL.* *iL;* *iL:* *iL+* *iL-* *iL=* *iL~*
*aL,* *aL.* *aL;* *aL:* *aL+* *aL-* *aL=* *aL~*
*IL,* *IL.* *IL;* *IL:* *IL+* *IL-* *IL=* *IL~*
*AL,* *AL.* *AL;* *AL:* *AL+* *AL-* *AL=* *AL~*
*in_* *in/* *in|* *in\* *in&* *in$* *in#* *instar*
*an_* *an/* *an|* *an\* *an&* *an$* *an#* *anstar*
*In_* *In/* *In|* *In\* *In&* *In$* *In#* *Instar*
*An_* *An/* *An|* *An\* *An&* *An$* *An#* *Anstar*
*il_* *il/* *il|* *il\* *il&* *il$* *il#* *ilstar*
*al_* *al/* *al|* *al\* *al&* *al$* *al#* *alstar*
*Il_* *Il/* *Il|* *Il\* *Il&* *Il$* *Il#* *Ilstar*
*Al_* *Al/* *Al|* *Al\* *Al&* *Al$* *Al#* *Alstar*
*iN_* *iN/* *iN|* *iN\* *iN&* *iN$* *iN#* *iNstar*
*aN_* *aN/* *aN|* *aN\* *aN&* *aN$* *aN#* *aNstar*
*IN_* *IN/* *IN|* *IN\* *IN&* *IN$* *IN#* *INstar*
*AN_* *AN/* *AN|* *AN\* *AN&* *AN$* *AN#* *ANstar*
*iL_* *iL/* *iL|* *iL\* *iL&* *iL$* *iL#* *iLstar*
*aL_* *aL/* *aL|* *aL\* *aL&* *aL$* *aL#* *aLstar*
*IL_* *IL/* *IL|* *IL\* *IL&* *IL$* *IL#* *ILstar*
*AL_* *AL/* *AL|* *AL\* *AL&* *AL$* *AL#* *ALstar*
in, in. in; in: in+ in- in= in~ in_ in/ in| in\ in& in$ in# in*
an, an. an; an: an+ an- an= an~ an_ an/ an| an\ an& an$ an# an*
In, In. In; In: In+ In- In= In~ In_ In/ In| In\ In& In$ In# In*
An, An. An; An: An+ An- An= An~ An_ An/ An| An\ An& An$ An# An*
il, il. il; il: il+ il- il= il~ il_ il/ il| il\ il& il$ il# il*
al, al. al; al: al+ al- al= al~ al_ al/ al| al\ al& al$ al# al*
Il, Il. Il; Il: Il+ Il- Il= Il~ Il_ Il/ Il| Il\ Il& Il$ Il# Il*
Al, Al. Al; Al: Al+ Al- Al= Al~ Al_ Al/ Al| Al\ Al& Al$ Al# Al*
iN, iN. iN; iN: iN+ iN- iN= iN~ iN_ iN/ iN| iN\ iN& iN$ iN# iN*
aN, aN. aN; aN: aN+ aN- aN= aN~ aN_ aN/ aN| aN\ aN& aN$ aN# aN*
IN, IN. IN; IN: IN+ IN- IN= IN~ IN_ IN/ IN| IN\ IN& IN$ IN# IN*
AN, AN. AN; AN: AN+ AN- AN= AN~ AN_ AN/ AN| AN\ AN& AN$ AN# AN*
iL, iL. iL; iL: iL+ iL- iL= iL~ iL_ iL/ iL| iL\ iL& iL$ iL# iL*
aL, aL. aL; aL: aL+ aL- aL= aL~ aL_ aL/ aL| aL\ aL& aL$ aL# aL*
IL, IL. IL; IL: IL+ IL- IL= IL~ IL_ IL/ IL| IL\ IL& IL$ IL# IL*
AL, AL. AL; AL: AL+ AL- AL= AL~ AL_ AL/ AL| AL\ AL& AL$ AL# AL*
All the above separator text objects can be shifted to the next separator
by including the letter `n`. The command `in,` selects inside of the next
commas. Use the letter `l` instead to work on the previous (last)
separators. Uses a [count] to skip multiple separator characters.
Use uppercase `N` and `L` to jump from within one pair of separators into
the next distinct pair, instead of into the adjacent one. (Using `N`
instead of `n` is actually just doubling the count to achieve this.)
*targets-separator-chart*
The following chart summarizes all separator mappings:
.........
a , bbbbbbb , ccccccc , dddddd , eeeeeee , fffffff , g ~
││└ IL, ┘│││└ Il, ┘│││└ I, ┘│││└ In, ┘│││└ IN, ┘│ │
│└─ iL, ─┤│├─ il, ─┤│├─ i, ─┤│├─ in, ─┤│├─ iN, ─┤ │
├── aL, ─┘├┼─ al, ─┘├┼─ a, ─┘├┼─ an, ─┘├┼─ aN, ─┘ │
└── AL, ──┼┘ └┼─ A, ──┼┘ └┼─ AN, ───┘
└─ Al, ──┘ └─ An, ──┘
------------------------------------------------------------------------------
SEPARATOR SEEK *targets-separator-seek*
Like |targets-quote-seek|. If any of the normal separator commands (not
containing `n` or `l`) is executed when the cursor is not positioned inside a
pair of separators, it seeks for the separator before or after the cursor.
This is similar to using the explicit version containing `n` or `l`.
==============================================================================
ARGUMENT TEXT OBJECTS *targets-argument-text-objects*
These text objects are similar to separator text objects, but are specialized
for arguments surrounded by braces and commas. They also take matching braces
into account to capture only valid arguments.
Argument text objects work over multiple lines and support
|targets-argument-seek|.
ia *ia*
Select inside argument. Accepts a
[count] to select bigger nested arguments.
...........
a , b ( cccccccc , d ) e ~
└── ia ──┘
aa *aa*
Select an argument in a list of arguments. This includes a separator if
present, but excludes surrounding braces. This leaves a proper of
arguments after deletion. Accepts a
[count] to select bigger nested arguments.
...........
a , b ( cccccccc , d ) e ~
└─── aa ──┘
Ia *Ia*
Select contents of an argument. Like inside argument, but exclude
whitespace at both ends. Useful for changing contents while preserving
spacing. Accepts a [count] to select
bigger nested arguments.
...........
a , b ( cccccccc , d ) e ~
└─ Ia ─┘
Aa *Aa*
Select around an argument. This includes both delimiters and a surrounding
whitespace, similar to `a'` and `A(`. Accepts a [count] to select bigger
nested arguments.
...........
a , b ( cccccccc , d ) e ~
└─── Aa ────┘
------------------------------------------------------------------------------
NEXT AND LAST ARGUMENT *targets-next-last-argument*
Work directly on distant arguments without moving there separately.
ina ana Ina Ana *ina* *ana* *Ina* *Ana*
ila ala Ila Ala *ila* *ala* *Ila* *Ala*
All the above argument text objects can be shifted to the next argument
by including the letter `n`. The command `ina` selects inside of the next
argument. Use the letter `l` instead to work on the previous (last)
argument. Uses a [count] to skip multiple argument characters. The order
is determined by the nearest surrounding argument delimiter.
*targets-argument-chart*
The following chart summarizes all argument mappings:
.........
a ( bbbbbb , ccccccc , d ( eeeeee , fffffff ) , gggggg ) h ~
││├2Ila┘│││└─Ila─┘││││ ││├─Ia─┘│││└─Ina─┘│││││└2Ina┘│ │
│└┼2ila─┘│├──ila──┤│││ │└┼─ia──┘│├──ina──┤│││├─2ina─┤ │
│ └2ala──┼┤ ││││ │ └─aa───┼┤ │││├┼─2ana─┘ │
└──2Ala──┼┘ ││││ └───Aa───┼┘ │││└┼─2Ana───┘
├───ala──┘│││ ├───ana──┘││ │
└───Ala───┼┤│ └───Ana───┼┤ │
││└─────2Ia────────────┘│ │
│└──────2ia─────────────┤ │
├───────2aa─────────────┘ │
└───────2Aa───────────────┘
------------------------------------------------------------------------------
ARGUMENT SEEK *targets-argument-seek*
Like |targets-separator-seek|. If any of the normal argument commands (not
containing `n` or `l`) is executed when the cursor is not positioned inside an
argument, it seeks for the argument before or after the cursor. This is
similar to using the explicit version containing `n` or `l`.
==============================================================================
SETTINGS *targets-settings*
Put these variables into your vimrc to customize the mappings described above.
The provided examples also indicate the default values.
Available options: ~
|g:targets_aiAI|
|g:targets_nlNL|
|g:targets_pairs|
|g:targets_quotes|
|g:targets_separators|
|g:targets_tagTrigger|
|g:targets_argTrigger|
|g:targets_argOpening|
|g:targets_argClosing|
|g:targets_argSeparator|
|g:targets_seekRanges|
|g:targets_jumpRanges|
------------------------------------------------------------------------------
*g:targets_aiAI*
Default:
let g:targets_aiAI = 'aiAI' ~
Controls the normal mode operator mode maps that get created for In Pair (i),
A Pair (a), Inside Pair (I), and Around Pair (A). Required to be a 4 character
long list. Use a space to deactivate a mode.
*g:targets_nlNL*
Default:
let g:targets_nlNL = 'nlNL' ~
Controls the keys used in maps for seeking next and last text objects. For
example, if you don't wish to use the N and L seeks, and instead wish for 'n'
to always search for the next object and `N` to search for the last, you could
set:
let g:targets_nlNL = 'nN ' ~
Note that two extra spaces are still required on the end, indicating you wish
to disable the default functionality of N and L. Required to be a 4 character
long list.
*g:targets_pairs*
Default:
let g:targets_pairs = '()b {}B [] <>' ~
Defines the space separated list of pair objects you wish to use, along with
optional one letter aliases for them.
*g:targets_quotes*
Default:
let g:targets_quotes = '" '' `' ~
Defines the space separated list of quoting objects you wish to use. Note that
you have to escape the single quote by doubling it. Quote objects can
optionally be followed by a single one letter alias. For example, to set `d`
as an alias for double quotes, allowing such commands as `cid` to be
equivalent to `ci"`, you could define:
let g:targets_quotes = '"d '' `' ~
*g:targets_separators*
Default:
let g:targets_separators = ', . ; : + - = ~ _ * # / | \ & $' ~
Defines the space separated list of separator objects you wish to use. Like
quote objects, separator objects can optionally be followed by a single one
letter alias. To set `c` as an alias for comma, allowing such commands as
`dic` to be equivalent to `di,`, you could define:
let g:targets_separators = ',c . ; : + - = ~ _ * # / | \ & $' ~
*g:targets_tagTrigger*
Default:
let g:targets_tagTrigger = 't' ~
Defines the key you need to press to operate on tag text objects.
*g:targets_argTrigger*
Default:
let g:targets_argTrigger = 'a' ~
Defines the key you need to press to operate on arguments. To use `,` as
argument trigger, allowing commands as `da,` to act like `daa`, use this:
let g:targets_argTrigger = ',' ~
*g:targets_argOpening*
*g:targets_argClosing*
Default:
let g:targets_argOpening = '[([]' ~
let g:targets_argClosing = '[])]' ~
Defines regular expressions that match the beginning and closing delimiter of
an argument list respectively. If you also want to find arguments delimited by
curly braces, try this:
let g:targets_argOpening = '[({[]' ~
let g:targets_argClosing = '[]})]' ~
*g:targets_argSeparator*
Default:
let g:targets_argSeparator = ',' ~
Defines a regular expression matching separators in an argument list. If you
also want to find arguments separated by semicolon, use this:
let g:targets_argSeparator = '[,;]' ~
*g:targets_seekRanges*
Default:
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr ll lb ar ab lB Ar aB Ab AB rb al rB Al bb aa bB Aa BB AA' ~
Defines a priority ordered, space separated list of range types which can be
used to customize seeking behavior. When using a command like `cib` to change
inside a block, targets.vim considers the three targets:
smallest target around cursor
next target after cursor
last target before cursor
For each of those that were found, we detect what range type it has. A range
type depends on the relative position of the start and end of the target,
relative to the current cursor position and the currently visible lines.
The possibly relative positions are:
c on cursor position ~
l left of cursor in current line ~
r right of cursor in current line ~
a above cursor on screen ~
b below cursor on screen ~
A above cursor off screen ~
B below cursor off screen ~
All possibly ranges are listed below, denoted by two characters: one for the
relative start and one for the relative end position of the target. For
example, `lr` means "from left of cursor to right of cursor in cursor line".
Next to each range type is a pictogram of an example. They are made of these
symbols:
. current cursor position ~
( ) start and end of target ~
/ line break before and after cursor line ~
| screen edge between hidden and visible lines ~
Ranges on cursor:
cr | / () / | starting on cursor, current line ~
cb | / ( /) | starting on cursor, multiline down, on screen ~
cB | / ( / |) starting on cursor, multiline down, partially off screen ~
lc | / () / | ending on cursor, current line ~
ac | (/ ) / | ending on cursor, multiline up, on screen ~
Ac (| / ) / | ending on cursor, multiline up, partially off screen ~
Ranges around cursor:
lr | / (.) / | around cursor, current line ~
lb | / (. /) | around cursor, multiline down, on screen ~
ar | (/ .) / | around cursor, multiline up, on screen ~
ab | (/ . /) | around cursor, multiline both, on screen ~
lB | / (. / |) around cursor, multiline down, partially off screen ~
Ar (| / .) / | around cursor, multiline up, partially off screen ~
aB | (/ . / |) around cursor, multiline both, partially off screen bottom ~
Ab (| / . /) | around cursor, multiline both, partially off screen top ~
AB (| / . / |) around cursor, multiline both, partially off screen both ~
Ranges after (right of/below) cursor
rr | / .()/ | after cursor, current line ~
rb | / .( /) | after cursor, multiline, on screen ~
rB | / .( / |) after cursor, multiline, partially off screen ~
bb | / . /()| after cursor below, on screen ~
bB | / . /( |) after cursor below, partially off screen ~
BB | / . / |() after cursor below, off screen ~
Ranges before (left of/above) cursor
ll | /(). / | before cursor, current line ~
al | (/ ). / | before cursor, multiline, on screen ~
Al (| / ). / | before cursor, multiline, partially off screen ~
aa |()/ . / | before cursor above, on screen ~
Aa (| )/ . / | before cursor above, partially off screen ~
AA ()| / . / | before cursor above, off screen ~
A a l r b B relative positions
└───────────┘ visible screen
└─────┘ current line
Given the range types of our targets, we then pick the one that appears first
in `g:targets_seekRanges`. If none is found, the selection fails.
The default setting generally prefers targets around the cursor, with one
exception: If the target around the cursor is not contained in the current
cursor line, but the next or last target are, then prefer those. Targets
beginning or ending on the cursor are preferred over everything else.
Some other useful example settings (or build your own!):
Prefer multiline targets around cursor over distant targets within cursor line:
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr lb ar ab lB Ar aB Ab AB rr ll rb al rB Al bb aa bB Aa BB AA' ~
Never seek backwards:
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr lb ar ab lB Ar aB Ab AB rb rB bb bB BB' ~
Only seek if next/last targets touch current line:
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr ll lb ar ab lB Ar aB Ab AB rb rB al Al' ~
Only consider targets fully visible on screen:
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr lb ar ab rr rb bb ll al aa' ~
Only consider targets around cursor:
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr lb ar ab lB Ar aB Ab AB' ~
Only consider targets fully contained in current line:
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr ll' ~
*g:targets_jumpRanges*
Default:
let g:targets_jumpRanges = 'bb bB BB aa Aa AA' ~
Defines an unordered, space separated list of range types which can be used to
customize the jumplist behavior (see documentation on seek ranges). It
controls whether or not to add the cursor position prior to selecting the text
object to the jumplist.
The default setting adds the previous cursor position to the jumplist if the
target that was operated on doesn't intersect the cursor line. That means it
adds a jumplist entry if the target ends above the cursor line or starts below
the cursor line.
Some other useful example settings (or build your own!):
Never add cursor position to jumplist:
let g:targets_jumpRanges = '' ~
Always add cursor position to jumplist:
let g:targets_jumpRanges = 'cr cb cB lc ac Ac lr rr ll lb ar ab lB Ar aB Ab AB rb al rB Al bb aa bB Aa BB AA' ~
Only add to jumplist if cursor was not inside the target:
let g:targets_jumpRanges = 'rr rb rB bb bB BB ll al Al aa Aa AA' ~
==============================================================================
NOTES *targets-notes*
Repeating an operator-pending mapping forgets its last count.
https://groups.google.com/forum/?fromgroups#!topic/vim_dev/G4SSgcRVN7g
Works since Vim 7.4.160
==============================================================================
ISSUES *targets-issues*
Empty matches can't be selected because it is not possible to visually select
zero-character ranges.
Forcing motion to work linewise by inserting `V` in `dVan(` doesn't work
for operator-pending mappings. See |o_V|.
Report issues or submit pull requests to:
https://github.com/wellle/vim-targets
==============================================================================
TODOS *targets-todos*
Create more mappings to support commands like `danw` or `danp` to delete the
next word or paragraph.
==============================================================================
vim:tw=78:ts=8:ft=help:norl:

View file

@ -0,0 +1,268 @@
" targets.vim Provides additional text objects
" Author: Christian Wellenbrock <christian.wellenbrock@gmail.com>
" License: MIT license
if exists("g:loaded_targets") || &cp || v:version < 700
finish
endif
let g:loaded_targets = '0.4.5' " version number
let s:save_cpoptions = &cpoptions
set cpo&vim
function! s:addMapping1(mapType, mapping, aiAI)
if a:aiAI !=# ' '
silent! execute a:mapType . 'noremap <silent> <unique>' . a:aiAI . a:mapping
endif
endfunction
function! s:addMapping2(mapType, mapping, aiAI, nlNL)
if a:aiAI !=# ' ' && a:nlNL !=# ' '
silent! execute a:mapType . 'noremap <silent> <unique>' . a:aiAI . a:nlNL . a:mapping
endif
endfunction
" pair text objects (multi line objects with single line seek)
" cursor │ .........
" line │ a ( bbbbbb ) ( ccccc ) ( ddddd ) ( eeeee ) ( ffffff ) g
" command │ ││└2Il)┘│││││└Il)┘│││││└─I)┘│││││└In)┘│││││└2In)┘│││
" │ │└─2il)─┘│││└─il)─┘│││└──i)─┘│││└─in)─┘│││└─2in)─┘││
" │ ├──2al)──┘│├──al)──┘│├───a)──┘│├──an)──┘│├──2an)──┘│
" │ └──2Al)───┘└──Al)───┘└───A)───┘└──An)───┘└──2An)───┘
" cursor │ .........
" line │ a ( b ( cccccc ) d ) ( e ( fffff ) g ) ( h ( iiiiii ) j ) k
" command │ │││ ││└2Il)┘││││││││││ ││└─I)┘││││││││││ ││└2In)┘│││││││
" │ │││ │└─2il)─┘│││││││││ │└──i)─┘│││││││││ │└─2in)─┘││││││
" │ │││ ├──2al)──┘││││││││ ├───a)──┘││││││││ ├──2an)──┘│││││
" │ │││ └──2Al)───┘│││││││ └───A)───┘│││││││ └──2An)───┘││││
" │ ││└─────Il)────┘│││││└────2I)────┘│││││└─────In)────┘│││
" │ │└──────il)─────┘│││└─────2i)─────┘│││└──────in)─────┘││
" │ ├───────al)──────┘│├──────2a)──────┘│├───────an)──────┘│
" │ └───────Al)───────┘└──────2A)───────┘└───────An)───────┘
function! s:createPairTextObjects(mapType)
for trigger in split(g:targets_pairs, '\zs')
if trigger ==# ' '
continue
endif
let triggerMap = trigger . " :<C-U>call targets#" . a:mapType . "('" . trigger
call s:addMapping1(a:mapType, triggerMap . "ci', v:count1)<CR>", s:i)
call s:addMapping1(a:mapType, triggerMap . "ca', v:count1)<CR>", s:a)
call s:addMapping1(a:mapType, triggerMap . "cI', v:count1)<CR>", s:I)
call s:addMapping1(a:mapType, triggerMap . "cA', v:count1)<CR>", s:A)
call s:addMapping2(a:mapType, triggerMap . "ni', v:count1)<CR>", s:i, s:n)
call s:addMapping2(a:mapType, triggerMap . "na', v:count1)<CR>", s:a, s:n)
call s:addMapping2(a:mapType, triggerMap . "nI', v:count1)<CR>", s:I, s:n)
call s:addMapping2(a:mapType, triggerMap . "nA', v:count1)<CR>", s:A, s:n)
call s:addMapping2(a:mapType, triggerMap . "li', v:count1)<CR>", s:i, s:l)
call s:addMapping2(a:mapType, triggerMap . "la', v:count1)<CR>", s:a, s:l)
call s:addMapping2(a:mapType, triggerMap . "lI', v:count1)<CR>", s:I, s:l)
call s:addMapping2(a:mapType, triggerMap . "lA', v:count1)<CR>", s:A, s:l)
endfor
endfunction
" tag text objects work on tags (similar to pair text objects)
function! s:createTagTextObjects(mapType)
let trigger = g:targets_tagTrigger
let triggerMap = trigger . " :<C-U>call targets#" . a:mapType . "('" . trigger
call s:addMapping1(a:mapType, triggerMap . "ci', v:count1)<CR>", s:i)
call s:addMapping1(a:mapType, triggerMap . "ca', v:count1)<CR>", s:a)
call s:addMapping1(a:mapType, triggerMap . "cI', v:count1)<CR>", s:I)
call s:addMapping1(a:mapType, triggerMap . "cA', v:count1)<CR>", s:A)
call s:addMapping2(a:mapType, triggerMap . "ni', v:count1)<CR>", s:i, s:n)
call s:addMapping2(a:mapType, triggerMap . "na', v:count1)<CR>", s:a, s:n)
call s:addMapping2(a:mapType, triggerMap . "nI', v:count1)<CR>", s:I, s:n)
call s:addMapping2(a:mapType, triggerMap . "nA', v:count1)<CR>", s:A, s:n)
call s:addMapping2(a:mapType, triggerMap . "li', v:count1)<CR>", s:i, s:l)
call s:addMapping2(a:mapType, triggerMap . "la', v:count1)<CR>", s:a, s:l)
call s:addMapping2(a:mapType, triggerMap . "lI', v:count1)<CR>", s:I, s:l)
call s:addMapping2(a:mapType, triggerMap . "lA', v:count1)<CR>", s:A, s:l)
endfunction
" quote text objects expand into quote (by counting quote signs)
" `aN'` is a shortcut for `2an'` to jump from within one quote into the
" next one, instead of the quote in between
" cursor │ ........
" line │ a ' bbbbb ' ccccc ' dddd ' eeeee ' fffff ' g
" command │ ││└IL'┘│││└Il'┘│││└I'┘│││└In'┘│││└IN'┘│││
" │ │└─iL'─┘│├─il'─┘│├─i'─┘│├─in'─┘│├─iN'─┘││
" │ ├──aL'──┤│ ├┼─a'──┤│ ├┼─aN'──┘│
" │ └──AL'──┼┘ ├┼─A'──┼┘ ├┼─AN'───┘
" │ ├──al'──┘│ ├──an'──┘│
" │ └──Al'───┘ └──An'───┘
" cursor │ .......... │ ...... │ ..........
" line │ a ' bbbb ' c '' │ ' a ' bbbb ' c ' │ '' b ' cccc ' d
" command │ ││└I'┘│││ │ ││└I'┘│││ │ ││└I'┘│││
" │ │└─i'─┘││ │ │└─i'─┘││ │ │└─i'─┘││
" │ ├──a'──┘│ │ ├──a'──┘│ │ ├──a'──┘│
" │ └──A'───┘ │ └──A'───┘ │ └──A'───┘
function! s:createQuoteTextObjects(mapType)
" quote text objects
for trigger in split(g:targets_quotes, '\zs')
if trigger ==# " "
continue
elseif trigger ==# "'"
let triggerMap = "' :<C-U>call targets#" . a:mapType . "('''"
else
let triggerMap = trigger . " :<C-U>call targets#" . a:mapType . "('" . trigger
endif
call s:addMapping1(a:mapType, triggerMap . "ci', v:count1)<CR>", s:i)
call s:addMapping1(a:mapType, triggerMap . "ca', v:count1)<CR>", s:a)
call s:addMapping1(a:mapType, triggerMap . "cI', v:count1)<CR>", s:I)
call s:addMapping1(a:mapType, triggerMap . "cA', v:count1)<CR>", s:A)
call s:addMapping2(a:mapType, triggerMap . "ni', v:count1)<CR>", s:i, s:n)
call s:addMapping2(a:mapType, triggerMap . "na', v:count1)<CR>", s:a, s:n)
call s:addMapping2(a:mapType, triggerMap . "nI', v:count1)<CR>", s:I, s:n)
call s:addMapping2(a:mapType, triggerMap . "nA', v:count1)<CR>", s:A, s:n)
call s:addMapping2(a:mapType, triggerMap . "li', v:count1)<CR>", s:i, s:l)
call s:addMapping2(a:mapType, triggerMap . "la', v:count1)<CR>", s:a, s:l)
call s:addMapping2(a:mapType, triggerMap . "lI', v:count1)<CR>", s:I, s:l)
call s:addMapping2(a:mapType, triggerMap . "lA', v:count1)<CR>", s:A, s:l)
endfor
endfunction
" separator text objects expand to the right
" cursor │ .............
" line │ a ' bbbbbbb ' c ' dddddd ' e ' fffffff ' g ~
" command │ ││└ Il' ┘│││ ││└ I' ┘│││ ││└ In' ┘│││
" │ │└─ il' ─┘││ │└─ i' ─┘││ │└─ in' ─┘││
" │ ├── al' ──┘│ ├── a' ──┘│ ├── an' ──┘│
" │ └── Al' ───┘ └── A' ───┘ └── An' ───┘
" cursor │ ......... │ ..........
" line │ a , bbbb , c , d │ a , b , cccc , d
" command │ ││└I,┘│ │ │ ││└I,┘│ │
" │ │└─i,─┤ │ │ │└─i,─┤ │
" │ ├──a,─┘ │ │ ├──a,─┘ │
" │ └──A,───┘ │ └──A,───┘
function! s:createSeparatorTextObjects(mapType)
" separator text objects
for trigger in split(g:targets_separators, '\zs')
if trigger ==# ' '
continue
elseif trigger ==# '|'
let trigger = '\|'
endif
let triggerMap = trigger . " :<C-U>call targets#" . a:mapType . "('" . trigger
call s:addMapping1(a:mapType, triggerMap . "ci', v:count1)<CR>", s:i)
call s:addMapping1(a:mapType, triggerMap . "ca', v:count1)<CR>", s:a)
call s:addMapping1(a:mapType, triggerMap . "cI', v:count1)<CR>", s:I)
call s:addMapping1(a:mapType, triggerMap . "cA', v:count1)<CR>", s:A)
call s:addMapping2(a:mapType, triggerMap . "ni', v:count1)<CR>", s:i, s:n)
call s:addMapping2(a:mapType, triggerMap . "na', v:count1)<CR>", s:a, s:n)
call s:addMapping2(a:mapType, triggerMap . "nI', v:count1)<CR>", s:I, s:n)
call s:addMapping2(a:mapType, triggerMap . "nA', v:count1)<CR>", s:A, s:n)
call s:addMapping2(a:mapType, triggerMap . "li', v:count1)<CR>", s:i, s:l)
call s:addMapping2(a:mapType, triggerMap . "la', v:count1)<CR>", s:a, s:l)
call s:addMapping2(a:mapType, triggerMap . "lI', v:count1)<CR>", s:I, s:l)
call s:addMapping2(a:mapType, triggerMap . "lA', v:count1)<CR>", s:A, s:l)
call s:addMapping2(a:mapType, triggerMap . "Ni', v:count1)<CR>", s:i, s:N)
call s:addMapping2(a:mapType, triggerMap . "Na', v:count1)<CR>", s:a, s:N)
call s:addMapping2(a:mapType, triggerMap . "NI', v:count1)<CR>", s:I, s:N)
call s:addMapping2(a:mapType, triggerMap . "NA', v:count1)<CR>", s:A, s:N)
call s:addMapping2(a:mapType, triggerMap . "Li', v:count1)<CR>", s:i, s:L)
call s:addMapping2(a:mapType, triggerMap . "La', v:count1)<CR>", s:a, s:L)
call s:addMapping2(a:mapType, triggerMap . "LI', v:count1)<CR>", s:I, s:L)
call s:addMapping2(a:mapType, triggerMap . "LA', v:count1)<CR>", s:A, s:L)
endfor
endfunction
" argument text objects expand to the right
" cursor │ .........
" line │ a ( bbbbbb , ccccccc , d ( eeeeee , fffffff ) , gggggg ) h
" command │ ││├2Ila┘│││└─Ila─┘││││ ││├─Ia─┘│││└─Ina─┘│││││└2Ina┘│ │
" │ │└┼2ila─┘│├──ila──┤│││ │└┼─ia──┘│├──ina──┤│││├─2ina─┤ │
" │ │ └2ala──┼┤ ││││ │ └─aa───┼┤ │││├┼─2ana─┘ │
" │ └──2Ala──┼┘ ││││ └───Aa───┼┘ │││└┼─2Ana───┘
" │ ├───ala──┘│││ ├───ana──┘││ │
" │ └───Ala───┼┤│ └───Ana───┼┤ │
" │ ││└─────2Ia────────────┘│ │
" │ │└──────2ia─────────────┤ │
" │ ├───────2aa─────────────┘ │
" │ └───────2Aa───────────────┘
function! s:createArgTextObjects(mapType)
let trigger = g:targets_argTrigger
let triggerMap = trigger . " :<C-U>call targets#" . a:mapType . "('" . trigger
call s:addMapping1(a:mapType, triggerMap . "ci', v:count1)<CR>", s:i)
call s:addMapping1(a:mapType, triggerMap . "ca', v:count1)<CR>", s:a)
call s:addMapping1(a:mapType, triggerMap . "cI', v:count1)<CR>", s:I)
call s:addMapping1(a:mapType, triggerMap . "cA', v:count1)<CR>", s:A)
call s:addMapping2(a:mapType, triggerMap . "ni', v:count1)<CR>", s:i, s:n)
call s:addMapping2(a:mapType, triggerMap . "na', v:count1)<CR>", s:a, s:n)
call s:addMapping2(a:mapType, triggerMap . "nI', v:count1)<CR>", s:I, s:n)
call s:addMapping2(a:mapType, triggerMap . "nA', v:count1)<CR>", s:A, s:n)
call s:addMapping2(a:mapType, triggerMap . "li', v:count1)<CR>", s:i, s:l)
call s:addMapping2(a:mapType, triggerMap . "la', v:count1)<CR>", s:a, s:l)
call s:addMapping2(a:mapType, triggerMap . "lI', v:count1)<CR>", s:I, s:l)
call s:addMapping2(a:mapType, triggerMap . "lA', v:count1)<CR>", s:A, s:l)
endfunction
" add expression mappings for `A` and `I` in visual mode #23 unless
" deactivated #49. Manually make mappings for older verions of vim #117.
function! s:addVisualMappings()
if v:version >= 704 || (v:version == 703 && has('patch338'))
silent! execute 'xnoremap <expr> <silent> <unique> ' . s:i . " targets#e('i')"
silent! execute 'xnoremap <expr> <silent> <unique> ' . s:a . " targets#e('a')"
silent! execute 'xnoremap <expr> <silent> <unique> ' . s:I . " targets#e('I')"
silent! execute 'xnoremap <expr> <silent> <unique> ' . s:A . " targets#e('A')"
else
call s:createPairTextObjects('x')
call s:createTagTextObjects('x')
call s:createQuoteTextObjects('x')
call s:createSeparatorTextObjects('x')
call s:createArgTextObjects('x')
endif
endfunction
function! s:loadSettings()
if !exists('g:targets_aiAI')
let g:targets_aiAI = 'aiAI'
endif
if !exists('g:targets_nlNL')
let g:targets_nlNL = 'nlNL'
endif
if !exists('g:targets_pairs')
let g:targets_pairs = '()b {}B [] <>'
endif
if !exists('g:targets_quotes')
let g:targets_quotes = '" '' `'
endif
if !exists('g:targets_separators')
let g:targets_separators = ', . ; : + - = ~ _ * # / \ | & $'
endif
if !exists('g:targets_tagTrigger')
let g:targets_tagTrigger = 't'
endif
if !exists('g:targets_argTrigger')
let g:targets_argTrigger = 'a'
endif
if !exists('g:targets_argOpening')
let g:targets_argOpening = '[([]'
endif
if !exists('g:targets_argClosing')
let g:targets_argClosing = '[])]'
endif
if !exists('g:targets_argSeparator')
let g:targets_argSeparator = ','
endif
if !exists('g:targets_seekRanges')
let g:targets_seekRanges = 'cr cb cB lc ac Ac lr rr ll lb ar ab lB Ar aB Ab AB rb al rB Al bb aa bB Aa BB AA'
endif
if !exists('g:targets_jumpRanges')
let g:targets_jumpRanges = 'bb bB BB aa Aa AA'
endif
let [s:a, s:i, s:A, s:I] = split(g:targets_aiAI, '\zs')
let [s:n, s:l, s:N, s:L] = split(g:targets_nlNL, '\zs')
endfunction
call s:loadSettings()
" create the text objects (current total count: 544)
" more specific ones first for #145
call s:createTagTextObjects('o')
call s:createArgTextObjects('o')
call s:createPairTextObjects('o')
call s:createQuoteTextObjects('o')
call s:createSeparatorTextObjects('o')
call s:addVisualMappings()
let &cpoptions = s:save_cpoptions
unlet s:save_cpoptions

View file

@ -0,0 +1,10 @@
all:
@rm -f *.out
@vim -N -u NONE --noplugin -S test.vim
@git diff --no-index test1.ok test1.out && echo "test1 OK" || echo "test1 failed"
@git diff --no-index test2.ok test2.out && echo "test2 OK" || echo "test2 failed"
@git diff --no-index test3.ok test3.out && echo "test3 OK" || echo "test3 failed"
@git diff --no-index test4.ok test4.out && echo "test4 OK" || echo "test4 failed"
@git diff --no-index test5.ok test5.out && echo "test5 OK" || echo "test5 failed"
@git diff --no-index test6.ok test6.out && echo "test6 OK" || echo "test6 failed"
@git diff --no-index test7.ok test7.out && echo "test7 OK" || echo "test7 failed"

View file

@ -0,0 +1,253 @@
" targets.vim Provides additional text objects
" Author: Christian Wellenbrock <christian.wellenbrock@gmail.com>
" License: MIT license
set runtimepath+=../
set softtabstop=16 expandtab
source ../plugin/targets.vim
function! s:execute(operation, motions)
if a:operation == 'c'
execute "normal " . a:operation . a:motions . "_"
elseif a:operation == 'v'
execute "normal " . a:operation . a:motions
normal r_
else
execute "normal " . a:operation . a:motions
endif
if a:operation == 'y'
execute "normal A\<Tab>'\<C-R>\"'"
endif
execute "normal I" . a:operation . a:motions . "\<Tab>\<Esc>"
endfunction
function! s:testBasic()
edit test1.in
normal gg0
for delset in [
\ [ '(', ')', 'b' ],
\ [ '{', '}', 'B' ],
\ [ '[', ']' ],
\ [ '<', '>' ],
\ [ 't' ]
\ ]
normal "lyy
for op in [ 'c', 'd', 'y', 'v' ]
for cnt in [ '', '1', '2' ]
for ln in [ 'l', '', 'n' ]
for iaIA in [ 'I', 'i', 'a', 'A' ]
for del in delset
execute "normal \"lpfx"
call s:execute(op, cnt . iaIA . ln . del)
endfor
endfor
endfor
endfor
endfor
normal +
endfor
normal +
for del in [ "'", '"', '`' ]
normal "lyy
for op in [ 'c', 'd', 'y', 'v' ]
for cnt in [ '', '1', '2' ]
for LlnN in [ 'l', '', 'n' ]
for iaIA in [ 'I', 'i', 'a', 'A' ]
execute "normal \"lpfx"
call s:execute(op, cnt . iaIA . LlnN . del)
endfor
endfor
endfor
endfor
normal +
endfor
normal +
for del in [ ',', '.', ';', ':', '+', '-', '=', '~', '_', '*', '#', '/', '|', '\', '&', '$' ]
normal "lyy
for op in [ 'c', 'd', 'y', 'v' ]
for cnt in [ '', '1', '2' ]
for LlnN in [ 'L', 'l', '', 'n', 'N' ]
for iaIA in [ 'I', 'i', 'a', 'A' ]
execute "normal \"lpfx"
call s:execute(op, cnt . iaIA . LlnN . del)
endfor
endfor
endfor
endfor
normal +
endfor
normal +
normal "lyy
for op in [ 'c', 'd', 'y', 'v' ]
for cnt in [ '', '1', '2' ]
for ln in [ 'l', '', 'n' ]
for iaIA in [ 'I', 'i', 'a', 'A' ]
execute "normal \"lpfx"
call s:execute(op, cnt . iaIA . ln . 'a')
endfor
endfor
endfor
endfor
write! test1.out
endfunction
function! s:testMultiline()
edit! test2.in
normal gg0
execute "normal /comment 1\<CR>"
set autoindent
execute "normal cin{foo\<Esc>"
set autoindent&
execute "normal /comment 2\<CR>"
execute "normal din{"
execute "normal /comment 3\<CR>"
execute "normal cin;foo\<Esc>"
execute "normal /comment 4\<CR>"
execute "normal cin`foo\<Esc>"
execute "normal /comment 5\<CR>"
execute "normal cI{foo\<Esc>"
write! test2.out
endfunction
function s:testSeeking()
edit! test3.in
normal gg0
for c in split('ABCDEFGHI', '\zs')
execute "normal /" . c . "\<CR>"
execute "normal ci)" . c . "\<Esc>"
endfor
for c in split('JKLMNO', '\zs')
execute "normal /" . c . "\<CR>"
execute "normal ci'" . c . "\<Esc>"
endfor
write! test3.out
endfunction
function s:testVisual()
edit! test4.in
normal gg0
for delset in [
\ [ '(', ')', 'b' ],
\ [ '{', '}', 'B' ],
\ [ '[', ']' ],
\ [ '<', '>' ],
\ [ 't' ]
\ ]
normal "lyy
for ia in [ 'i', 'a' ]
for del in delset
normal "lpfx
execute "normal v" . ia . del . ia . del . "r_"
endfor
endfor
normal +
endfor
write! test4.out
endfunction
function s:testModifiers()
edit! test5.in
normal gg0
normal fxvItr_
write! test5.out
endfunction
function s:testEmpty()
edit! test6.in
normal gg0
normal ci"foo
normal +
normal ci(foo
normal +
normal ci,foo
write! test6.out
endfunction
function s:testQuotes()
edit! test7.in
normal gg0
normal ci"A
normal +
normal cin"A
normal +
normal c2in"B
normal +fx
normal ci"D
normal +fx
normal cin"D
normal +fx
normal c2in"E
normal +fx
normal cil"C
normal +fx
normal c2il"B
normal +fx
normal ci"X
normal +fx
normal cin"D
normal +fx
normal c2in"E
normal +fx
normal cil"C
normal +fx
normal c2il"B
normal +fx
normal ci"C
normal +fx
normal cil"C
normal +fx
normal c2il"B
write! test7.out
endfunction
call s:testBasic()
call s:testMultiline()
call s:testSeeking()
call s:testVisual()
call s:testModifiers()
call s:testEmpty()
call s:testQuotes()
quit!

View file

@ -0,0 +1,28 @@
a ( b ) ( c ) ( ( x ) ) ( e ) ( f ) g
a { b } { c } { { x } } { e } { f } g
a [ b ] [ c ] [ [ x ] ] [ e ] [ f ] g
a < b > < c > < < x > > < e > < f > g
a <a> b </a> <b> c </b> <c> <d> x </d> </c> <e> e </e> <f> f </f> g
a ' b ' c ' d ' e ' x ' g ' h ' i ' k ' l
a " b " c " d " e " x " g " h " i " k " l
a ` b ` c ` d ` e ` x ` g ` h ` i ` k ` l
a , b , c , d , e , x , g , h , i , k , l
a . b . c . d . e . x . g . h . i . k . l
a ; b ; c ; d ; e ; x ; g ; h ; i ; k ; l
a : b : c : d : e : x : g : h : i : k : l
a + b + c + d + e + x + g + h + i + k + l
a - b - c - d - e - x - g - h - i - k - l
a = b = c = d = e = x = g = h = i = k = l
a ~ b ~ c ~ d ~ e ~ x ~ g ~ h ~ i ~ k ~ l
a _ b _ c _ d _ e _ x _ g _ h _ i _ k _ l
a * b * c * d * e * x * g * h * i * k * l
a # b # c # d # e # x # g # h # i # k # l
a / b / c / d / e / x / g / h / i / k / l
a | b | c | d | e | x | g | h | i | k | l
a \ b \ c \ d \ e \ x \ g \ h \ i \ k \ l
a & b & c & d & e & x & g & h & i & k & l
a $ b $ c $ d $ e $ x $ g $ h $ i $ k $ l
a ( b , c ( d ) , d ( x , e ) , f ) g

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,25 @@
// comment 1
function f() {
return 4;
}
// comment 2
function f() {
return 4;
}
// comment 3
int a = 5;
int b = a > 0
? 1
: 2;
// comment 4
string x = `line 1
line 2
line 3`;
// comment 5
function f() {
return 4;
}

View file

@ -0,0 +1,20 @@
// comment 1
function f() {
foo
}
// comment 2
function f() {
}
// comment 3
int a = 5;
foo;
// comment 4
string x = `foo`;
// comment 5
function f() {
foo
}

View file

@ -0,0 +1,20 @@
// comment 1
function f() {
foo
}
// comment 2
function f() {
}
// comment 3
int a = 5;
foo;
// comment 4
string x = `foo`;
// comment 5
function f() {
foo
}

View file

@ -0,0 +1,42 @@
A
a ( b ) c
B ( a ) b
a ( b ) C
D ( a
b ) c
a ( b
c ) E
a ( b
F ( ) c
d ) e
a ( b
c ( ) G
d ) e
a ( b ) H ( c ) d
a ( b ) c
I " this must be the last pair test
J
a 'b' c
K 'a' b
a 'b' L
a ' b
M ' c
d ' e
a ' b
c ' N
d ' e
a ' b ' c
O " this must be the last quote test

View file

@ -0,0 +1,38 @@
A
a (A) c
B (B) b
a (C) C
D (D) c
a (E) E
a ( b
F (F) c
d ) e
a ( b
c (G) G
d ) e
a ( b ) H (H) d
a (I) c
I " this must be the last pair test
J
a 'J' c
K 'K' b
a 'L' L
a 'M' c
d ' e
a ' b
c 'N' e
a 'O' c
O " this must be the last quote test

View file

@ -0,0 +1,38 @@
A
a (A) c
B (B) b
a (C) C
D (D) c
a (E) E
a ( b
F (F) c
d ) e
a ( b
c (G) G
d ) e
a ( b ) H (H) d
a (I) c
I " this must be the last pair test
J
a 'J' c
K 'K' b
a 'L' L
a 'M' c
d ' e
a ' b
c 'N' e
a 'O' c
O " this must be the last quote test

View file

@ -0,0 +1,6 @@
a ( b ( x ) c ) d
a { b { x } c } d
a [ b [ x ] c ] d
a < b < x > c > d
a <a> b <b> x </b> c </a> d

View file

@ -0,0 +1,28 @@
a ( b ( x ) c ) d
a (___________) d
a (___________) d
a (___________) d
a _____________ d
a _____________ d
a _____________ d
a { b { x } c } d
a {___________} d
a {___________} d
a {___________} d
a _____________ d
a _____________ d
a _____________ d
a [ b [ x ] c ] d
a [___________] d
a [___________] d
a _____________ d
a _____________ d
a < b < x > c > d
a <___________> d
a <___________> d
a _____________ d
a _____________ d
a <a> b <b> x </b> c </a> d
a <a>________________</a> d
a _______________________ d

View file

@ -0,0 +1,28 @@
a ( b ( x ) c ) d
a (___________) d
a (___________) d
a (___________) d
a _____________ d
a _____________ d
a _____________ d
a { b { x } c } d
a {___________} d
a {___________} d
a {___________} d
a _____________ d
a _____________ d
a _____________ d
a [ b [ x ] c ] d
a [___________] d
a [___________] d
a _____________ d
a _____________ d
a < b < x > c > d
a <___________> d
a <___________> d
a _____________ d
a _____________ d
a <a> b <b> x </b> c </a> d
a <a>________________</a> d
a _______________________ d

View file

@ -0,0 +1 @@
<a>axb</a>

View file

@ -0,0 +1 @@
<a>___</a>

View file

@ -0,0 +1 @@
<a>___</a>

View file

@ -0,0 +1,3 @@
a "" b
a () b
a ,, b

View file

@ -0,0 +1,3 @@
a "foo" b
a (foo) b
a ,foo, b

View file

@ -0,0 +1,3 @@
a "foo" b
a (foo) b
a ,foo, b

View file

@ -0,0 +1,16 @@
x "a" "b" c
x "a" "b" c
x "a" "b" c
a "b" "c" x "d" "e" f
a "b" "c" x "d" "e" f
a "b" "c" x "d" "e" f
a "b" "c" x "d" "e" f
a "b" "c" x "d" "e" f
a "b" "c" "x" "d" "e" f
a "b" "c" "x" "d" "e" f
a "b" "c" "x" "d" "e" f
a "b" "c" "x" "d" "e" f
a "b" "c" "x" "d" "e" f
a "b" "c" x
a "b" "c" x
a "b" "c" x

View file

@ -0,0 +1,16 @@
x "A" "b" c
x "A" "b" c
x "a" "B" c
a "b" "c" x "D" "e" f
a "b" "c" x "D" "e" f
a "b" "c" x "d" "E" f
a "b" "C" x "d" "e" f
a "B" "c" x "d" "e" f
a "b" "c" "X" "d" "e" f
a "b" "c" "x" "D" "e" f
a "b" "c" "x" "d" "E" f
a "b" "C" "x" "d" "e" f
a "B" "c" "x" "d" "e" f
a "b" "C" x
a "b" "C" x
a "B" "c" x

View file

@ -0,0 +1,16 @@
x "A" "b" c
x "A" "b" c
x "a" "B" c
a "b" "c" x "D" "e" f
a "b" "c" x "D" "e" f
a "b" "c" x "d" "E" f
a "b" "C" x "d" "e" f
a "B" "c" x "d" "e" f
a "b" "c" "X" "d" "e" f
a "b" "c" "x" "D" "e" f
a "b" "c" "x" "d" "E" f
a "b" "C" "x" "d" "e" f
a "B" "c" "x" "d" "e" f
a "b" "C" x
a "b" "C" x
a "B" "c" x

Binary file not shown.

Binary file not shown.