*mini.surround* Surround actions
*MiniSurround*
MIT License Copyright (c) 2021 Evgeni Chasnovski
==============================================================================
Fast and feature-rich surrounding. Can be configured to have experience
similar to 'tpope/vim-surround' (see |MiniSurround-vim-surround-config|).
Features:
- Actions (all of them are dot-repeatable out of the box and respect
|[count]|) with configurable keymappings:
- Add surrounding with `sa` (in visual mode or on motion).
- Delete surrounding with `sd`.
- Replace surrounding with `sr`.
- Find surrounding with `sf` or `sF` (move cursor right or left).
- Highlight surrounding with `sh`.
- Change number of neighbor lines with `sn` (see |MiniSurround-algorithm|).
- Surrounding is identified by a single character as both "input" (in
`delete` and `replace` start, `find`, and `highlight`) and "output" (in
`add` and `replace` end):
- 'f' - function call (string of alphanumeric symbols or '_' or '.'
followed by balanced '()'). In "input" finds function call, in
"output" prompts user to enter function name.
- 't' - tag. In "input" finds tag with same identifier, in "output"
prompts user to enter tag name with possible attributes.
- All symbols in brackets '()', '[]', '{}', '<>". In "input' represents
balanced brackets (open - with whitespace pad, close - without), in
"output" - left and right parts of brackets.
- '?' - interactive. Prompts user to enter left and right parts.
- All other alphanumeric, punctuation, or space characters represent
surrounding with identical left and right parts.
- Configurable search methods to find not only covering but possibly next,
previous, or nearest surrounding. See more in |MiniSurround.config|.
- All actions involving finding surrounding (delete, replace, find,
highlight) can be used with suffix that changes search method to find
previous/last. See more in |MiniSurround.config|.
Known issues which won't be resolved:
- Search for surrounding is done using Lua patterns (regex-like approach).
So certain amount of false positives should be expected.
- When searching for "input" surrounding, there is no distinction if it is
inside string or comment. So in this case there will be not proper match
for a function call: 'f(a = ")", b = 1)'.
- Tags are searched using regex-like methods, so issues are inevitable.
Overall it is pretty good, but certain cases won't work. Like self-nested
tags won't match correctly on both ends: ''.
# Setup ~
This module needs a setup with `require('mini.surround').setup({})`
(replace `{}` with your `config` table). It will create global Lua table
`MiniSurround` which you can use for scripting or manually (with
`:lua MiniSurround.*`).
See |MiniSurround.config| for `config` structure and default values.
You can override runtime config settings locally to buffer inside
`vim.b.minisurround_config` which should have same structure as
`MiniSurround.config`. See |mini.nvim-buffer-local-config| for more details.
To stop module from showing non-error feedback, set `config.silent = true`.
# Example usage ~
Regular mappings:
- `saiw)` - add (`sa`) for inner word (`iw`) parenthesis (`)`).
- `saiw?[[]]` - add (`sa`) for inner word (`iw`) interactive
surrounding (`?`): `[[` for left and `]]` for right.
- `2sdf` - delete (`sd`) second (`2`) surrounding function call (`f`).
- `sr)tdiv` - replace (`sr`) surrounding parenthesis (`)`) with tag
(`t`) with identifier 'div' (`div` in command line prompt).
- `sff` - find right (`sf`) part of surrounding function call (`f`).
- `sh}` - highlight (`sh`) for a brief period of time surrounding curly
brackets (`}`).
Extended mappings (temporary force "prev"/"next" search methods):
- `sdnf` - delete (`sd`) next (`n`) function call (`f`).
- `srlf(` - replace (`sr`) last (`l`) function call (`f`) with padded
bracket (`(`).
- `2sfnt` - find (`sf`) second (`2`) next (`n`) tag (`t`).
- `2shl}` - highlight (`sh`) last (`l`) second (`2`) curly bracket (`}`).
# Comparisons ~
- 'tpope/vim-surround':
- 'vim-surround' has completely different, with other focus set of
default mappings, while 'mini.surround' has a more coherent set.
- 'mini.surround' supports dot-repeat, customized search path (see
|MiniSurround.config|), customized specifications (see
|MiniSurround-surround-specification|) allowing usage of tree-sitter
queries (see |MiniSurround.gen_spec.input.treesitter()|),
highlighting and finding surrounding, "last"/"next" extended
mappings. While 'vim-surround' does not.
- 'machakann/vim-sandwich':
- Both have same keybindings for common actions (add, delete, replace).
- Otherwise same differences as with 'tpop/vim-surround' (except
dot-repeat because 'vim-sandwich' supports it).
- 'kylechui/nvim-surround':
- 'nvim-surround' is designed after 'tpope/vim-surround' with same
default mappings and logic, while 'mini.surround' has mappings
similar to 'machakann/vim-sandwich'.
- 'mini.surround' has more flexible customization of input surrounding
(with composed patterns, region pair(s), search methods).
- 'mini.surround' supports |[count]| in both input and output
surrounding (see |MiniSurround-count|) while 'nvim-surround' doesn't.
- 'mini.surround' supports "last"/"next" extended mappings.
- |mini.ai|:
- Both use similar logic for finding target: textobject in 'mini.ai'
and surrounding pair in 'mini.surround'. While 'mini.ai' uses
extraction pattern for separate `a` and `i` textobjects,
'mini.surround' uses it to select left and right surroundings
(basically a difference between `a` and `i` textobjects).
- Some builtin specifications are slightly different:
- Quotes in 'mini.ai' are balanced, in 'mini.surround' they are not.
- The 'mini.surround' doesn't have argument surrounding.
- Default behavior in 'mini.ai' selects one of the edges into `a`
textobject, while 'mini.surround' - both.
# Highlight groups ~
* `MiniSurround` - highlighting of requested surrounding.
To change any highlight group, modify it directly with |:highlight|.
# Disabling ~
To disable, set `vim.g.minisurround_disable` (globally) or
`vim.b.minisurround_disable` (for a buffer) to `true`. Considering high
number of different scenarios and customization intentions, writing exact
rules for disabling module's functionality is left to user. See
|mini.nvim-disabling-recipes| for common recipes.
------------------------------------------------------------------------------
*MiniSurround-surround-builtin*
Builtin surroundings ~
This table describes all builtin surroundings along with what they
represent. Explanation:
- `Key` represents the surrounding identifier: single character which should
be typed after action mappings (see |MiniSurround.config.mappings|).
- `Name` is a description of surrounding.
- `Example line` contains a string for which examples are constructed. The
`*` denotes the cursor position over `a` character.
- `Delete` shows the result of typing `sd` followed by surrounding identifier.
It aims to demonstrate "input" surrounding which is also used in replace
with `sr` (surrounding id is typed first), highlight with `sh`, find with
`sf` and `sF`.
- `Replace` shows the result of typing `sr!` followed by surrounding
identifier (with possible follow up from user). It aims to demonstrate
"output" surrounding which is also used in adding with `sa` (followed by
textobject/motion or in Visual mode).
Example: typing `sd)` with cursor on `*` (covers `a` character) changes line
`!( *a (bb) )!` into `! aa (bb) !`. Typing `sr!)` changes same initial line
into `(( aa (bb) ))`.
>
|Key| Name | Example line | Delete | Replace |
|---|---------------|---------------|-------------|-----------------|
| ( | Balanced () | !( *a (bb) )! | !aa (bb)! | ( ( aa (bb) ) ) |
| [ | Balanced [] | ![ *a [bb] ]! | !aa [bb]! | [ [ aa [bb] ] ] |
| { | Balanced {} | !{ *a {bb} }! | !aa {bb}! | { { aa {bb} } } |
| < | Balanced <> | !< *a >! | !aa ! | < < aa > > |
|---|---------------|---------------|-------------|-----------------|
| ) | Balanced () | !( *a (bb) )! | ! aa (bb) ! | (( aa (bb) )) |
| ] | Balanced [] | ![ *a [bb] ]! | ! aa [bb] ! | [[ aa [bb] ]] |
| } | Balanced {} | !{ *a {bb} }! | ! aa {bb} ! | {{ aa {bb} }} |
| > | Balanced <> | !< *a >! | ! aa ! | << aa >> |
| b | Alias for | !( *a {bb} )! | ! aa {bb} ! | (( aa {bb} )) |
| | ), ], or } | | | |
|---|---------------|---------------|-------------|-----------------|
| q | Alias for | !'aa'*a'aa'! | !'aaaaaa'! | "'aa'aa'aa'" |
| | ", ', or ` | | | |
|---|---------------|---------------|-------------|-----------------|
| ? | User prompt | !e * o! | ! a ! | ee a oo |
| |(typed e and o)| | | |
|---|---------------|---------------|-------------|-----------------|
| t | Tag | !*! | !a! | a |
| | | | | (typed y) |
|---|---------------|---------------|-------------|-----------------|
| f | Function call | !f(*a, bb)! | !aa, bb! | g(f(*a, bb)) |
| | | | | (typed g) |
|---|---------------|---------------|-------------|-----------------|
| | Default | !_a*a_! | !aaa! | __aaa__ |
| | (typed _) | | | |
|---|---------------|---------------|-------------|-----------------|
<
Notes:
- All examples assume default `config.search_method`.
- Open brackets differ from close brackets by how they treat inner edge
whitespace: open includes it left and right parts, close does not.
- Output value of `b` alias is same as `)`. For `q` alias - same as `"`.
- Default surrounding is activated for all characters which are not
configured surrounding identifiers. Notes:
- Due to special handling of underlying `x.-x` Lua pattern
(see |MiniSurround-search-algorithm|), it doesn't really support
non-trivial `[count]` for "cover" search method.
- When cursor is exactly on the identifier character while there are
two matching candidates on both left and right, the one resulting in
region with smaller width is preferred.
------------------------------------------------------------------------------
*MiniSurround-glossary*
Note: this is similar to |MiniAi-glossary|.
- REGION - table representing region in a buffer. Fields: and
for inclusive start and end positions ( might be `nil` to
describe empty region). Each position is also a table with line
and column
(both start at 1). Examples: >lua
{ from = { line = 1, col = 1 }, to = { line = 2, col = 1 } }
-- Empty region
{ from = { line = 10, col = 10 } }
<
- REGION PAIR - table representing regions for left and right surroundings.
Fields: and with regions. Examples: >lua
{
left = { from = { line = 1, col = 1 }, to = { line = 1, col = 1 } },
right = { from = { line = 1, col = 3 } },
}
<
- PATTERN - string describing Lua pattern.
- SPAN - interval inside a string (end-exclusive). Like [1, 5). Equal
`from` and `to` edges describe empty span at that point.
- SPAN `A = [a1, a2)` COVERS `B = [b1, b2)` if every element of
`B` is within `A` (`a1 <= b < a2`).
It also is described as B IS NESTED INSIDE A.
- NESTED PATTERN - array of patterns aimed to describe nested spans.
- SPAN MATCHES NESTED PATTERN if there is a sequence of consecutively
nested spans each matching corresponding pattern within substring of
previous span (or input string for first span). Example: >lua
-- Nested patterns for balanced `()` with inner space
{ '%b()', '^. .* .$' }
-- Example input string (with columns underneath for easier reading):
"( ( () ( ) ) )"
-- 12345678901234
<
Here are all matching spans [1, 15) and [3, 13). Both [5, 7) and [8, 10)
match first pattern but not second. All other combinations of `(` and `)`
don't match first pattern (not balanced).
- COMPOSED PATTERN: array with each element describing possible pattern
(or array of them) at that place. Composed pattern basically defines all
possible combinations of nested pattern (their cartesian product).
Examples:
1. Either balanced `()` or balanced `[]` but both with inner edge space: >lua
-- Composed pattern
{ { '%b()', '%b[]' }, '^. .* .$' }
-- Composed pattern expanded into equivalent array of nested patterns
{ '%b()', '^. .* .$' } -- and
{ '%b[]', '^. .* .$' }
<
2. Either "balanced `()` with inner edge space" or "balanced `[]` with
no inner edge space", both with 5 or more characters: >lua
-- Composed pattern
{ { { '%b()', '^. .* .$' }, { '%b[]', '^.[^ ].*[^ ].$' } }, '.....' }
-- Composed pattern expanded into equivalent array of nested patterns
{ '%b()', '^. .* .$', '.....' } -- and
{ '%b[]', '^.[^ ].*[^ ].$', '.....' }
<
- SPAN MATCHES COMPOSED PATTERN if it matches at least one nested pattern
from expanded composed pattern.
------------------------------------------------------------------------------
*MiniSurround-surround-specification*
Surround specification is a table with keys:
- - defines how to find and extract surrounding for "input"
operations (like `delete`). See more in "Input surrounding" section.
-