mini.splitjoin documentation
Generated from the main
branch of ‘mini.nvim’
mini.splitjoin Split and join arguments
MIT License Copyright (c) 2023 Evgeni Chasnovski
Module
Features:
Mappings and Lua functions that modify arguments (regions inside brackets between allowed separators) under cursor.
Supported actions:
Toggle - split if arguments are on single line, join otherwise. Main supported function of the module. See MiniSplitjoin.toggle().
Split - make every argument separator be on end of separate line. See MiniSplitjoin.split().
Join - make all arguments be on single line. See MiniSplitjoin.join().
Mappings are dot-repeatable in Normal mode and work in Visual mode.
Customizable argument detection (see MiniSplitjoin.config.detect):
Which brackets can contain arguments.
Which strings can separate arguments.
Which regions are excluded when looking for separators (like inside nested brackets or quotes).
Customizable pre and post hooks for both split and join. See
split
andjoin
in MiniSplitjoin.config. There are several built-in ones in MiniSplitjoin.gen_hook.Works inside comments by using modified notion of indent. See MiniSplitjoin.get_indent_part().
Provides low-level Lua functions for split and join at positions. See MiniSplitjoin.split_at() and MiniSplitjoin.join_at().
Notes:
Search for arguments is done using Lua patterns (regex-like approach). Certain amount of false positives is to be expected.
This module is mostly designed around MiniSplitjoin.toggle(). If target split positions are on different lines, join first and then split.
Actions can be done on Visual mode selection, which mostly present as a safety route in case of incorrect detection of initial region. It uses MiniSplitjoin.get_visual_region() which treats selection as full brackets (include brackets in selection).
Setup
This module needs a setup with require('mini.splitjoin').setup({})
(replace {}
with your config
table). It will create global Lua table MiniSplitjoin
which you can use for scripting or manually (with :lua MiniSplitjoin.*
).
See MiniSplitjoin.config for available config settings.
You can override runtime config settings (like action hooks) locally to buffer inside vim.b.minisplitjoin_config
which should have same structure as MiniSplitjoin.config
. See mini.nvim-buffer-local-config for more details.
Comparisons
-
Mostly has the same design as this module.
Doesn’t work inside comments, while this module does.
Has more built-in ways to control split and join, while this module intentionally provides only handful.
-
- More oriented towards language-depended transformations, while this module intntionally deals with more generic text-related functionality.
-
Operates based on tree-sitter nodes. This is more accurate in some edge cases, but requires tree-sitter parser.
Doesn’t work inside comments or strings.
Disabling
To disable, set g:minisplitjoin_disable
(globally) or b:minisplitjoin_disable
(for a buffer) to v: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.
Glossary
POSITION
Table with fields <line> and <col> containing line and column numbers respectively. Both are 1-indexed. Example: { line = 2, col = 1 }
.
REGION
Table representing region in a buffer. Fields: <from> and <to> for inclusive start and end positions. Example:
{ from = { line = 1, col = 1 }, to = { line = 2, col = 1 } }
setup()
MiniSplitjoin.setup
({config})
Module setup
Parameters
{config} (table|nil)
Module config table. See MiniSplitjoin.config.
Usage
require('mini.splitjoin').setup() -- use default config
-- OR
require('mini.splitjoin').setup({}) -- replace {} with your config table
config
MiniSplitjoin.config
Defaults
MiniSplitjoin.config = {
-- Module mappings. Use `''` (empty string) to disable one.
-- Created for both Normal and Visual modes.
mappings = {
toggle = 'gS',
split = '',
join = '',
},
-- Detection options: where split/join should be done
detect = {
-- Array of Lua patterns to detect region with arguments.
-- Default: { '%b()', '%b[]', '%b{}' }
brackets = nil,
-- String Lua pattern defining argument separator
separator = ',',
-- Array of Lua patterns for sub-regions to exclude separators from.
-- Enables correct detection in presence of nested brackets and quotes.
-- Default: { '%b()', '%b[]', '%b{}', '%b""', "%b''" }
exclude_regions = nil,
},
-- Split options
split = {
hooks_pre = {},
hooks_post = {},
},
-- Join options
join = {
hooks_pre = {},
hooks_post = {},
},
}
Detection
The table at config.detect
controls how arguments are detected using Lua patterns. General idea is to convert whole buffer into a single line, perform string search, and convert results back into 2d positions.
Example configuration:
require('mini.splitjoin').setup({
detect = {
-- Detect only inside balanced parenthesis
brackets = { '%b()' },
-- Allow both `,` and `;` to separate arguments
separator = '[,;]',
-- Make any separator define an argument
exclude_regions = {},
},
})
Outer brackets
detect.brackets
is an array of Lua patterns used to find enclosing region. It is done by traversing whole buffer to find the smallest region matching any supplied pattern.
Default: nil
, inferred as { '%b()', '%b[]', '%b{}' }
. So an argument can be inside a balanced ()
, []
, or {}
.
Example: brackets = { '%b()' }
will search for arguments only inside balanced ()
.
Separator
detect.separator
is a single Lua pattern defining which strings should be treated as argument separators.
Empty string in detect.separator
will result in only surrounding brackets used as separators.
Only end of pattern match will be used as split/join positions.
Default: ','
. So an argument can be separated only with comma.
Example: separator = { '[,;]' }
will treat both ,
and ;
as separators.
Excluded regions
detect.exclude_regions
is an array of Lua patterns for sub-regions from which to exclude separators. Enables correct detection in case of nested brackets and quotes.
Default: nil
; inferred as { '%b()', '%b[]', '%b{}', '%b""', "%b''" }
. So a separator can not be inside a balanced ()
, []
, {}
(representing nested argument regions) or ""
, ''
(representing strings).
Example: exclude_regions = {}
will not exclude any regions. So in case of f(a, { b, c })
it will detect both commas as argument separators.
Hooks
split.hooks_pre
, split.hooks_post
, join.hooks_pre
, and join.hooks_post
are arrays of hook functions. If empty (default) no hook is applied.
Hooks should take and return array of positions. See MiniSplitjoin-glossary.
They can be used to tweak actions:
Pre-hooks are called before action. Each is applied on the output of previous one. Input of first hook are detected split/join positions. Output of last one is actually used to perform split/join.
Post-hooks are called after action. Each is applied on the output of previous one. Input of first hook are split/join positions from actual action plus its region’s right end as last position (for easier hook code). Output of last one is used as action return value.
For more specific details see MiniSplitjoin.split() and MiniSplitjoin.join().
See MiniSplitjoin.gen_hook for generating common hooks with examples.
toggle()
MiniSplitjoin.toggle
({opts})
Toggle arguments
Overview:
Detect region at input position: either by using supplied
opts.region
or by finding smallest bracketed region surrounding position. See MiniSplitjoin.config.detect for more details.If region spans single line, use MiniSplitjoin.split() with found region. Otherwise use MiniSplitjoin.join().
Parameters
{opts} (table|nil)
Options. Has structure from MiniSplitjoin.config inheriting its default values.
Following extra optional fields are allowed:
<position>
(table)
- position at which to find smallest bracket region. See MiniSplitjoin-glossary for the structure. Default: cursor position.<region>
(table)
- region at which to perform action. Assumes inclusive both start at left bracket and end at right bracket. See MiniSplitjoin-glossary for the structure. Default:nil
to automatically detect region.
Return
(any)
Output of chosen split()
or join()
action.
split()
MiniSplitjoin.split
({opts})
Split arguments
Overview:
Detect region: either by using supplied
opts.region
or by finding smallest bracketed region surrounding input position (cursor position by default). See MiniSplitjoin.config.detect for more details.Find separator positions using
separator
andexclude_regions
fromopts
. Both brackets are treated as separators. See MiniSplitjoin.config.detect for more details. Note: stop if no separator positions are found.Modify separator positions to represent split positions. Last split position (which is inferred from right bracket) is moved one column to left so that right bracket would move on new line.
Apply all hooks from
opts.split.hooks_pre
. Each is applied on the output of previous one. Input of first hook is split positions from previous step. Output of last one is used as split positions in next step.Split and update split positions with MiniSplitjoin.split_at().
Apply all hooks from
opts.split.hooks_post
. Each is applied on the output of previous one. Input of first hook is split positions from previous step plus region’s right end (for easier hook code). Output of last one is used as function return value.
Note:
- By design, it doesn’t detect if argument should be split, so application on arguments spanning multiple lines can lead to undesirable result.
Parameters
{opts} (table|nil)
Options. Has structure from MiniSplitjoin.config inheriting its default values.
Following extra optional fields are allowed:
<position>
(table)
- position at which to find smallest bracket region. See MiniSplitjoin-glossary for the structure. Default: cursor position.<region>
(table)
- region at which to perform action. Assumes inclusive both start at left bracket and end at right bracket. See MiniSplitjoin-glossary for the structure. Default:nil
to automatically detect region.
Return
(any)
Output of last opts.split.hooks_post
or nil
if no split positions found. Default: return value of MiniSplitjoin.split_at() application.
join()
MiniSplitjoin.join
({opts})
Join arguments
Overview:
Detect region: either by using supplied
opts.region
or by finding smallest bracketed region surrounding input position (cursor position by default). See MiniSplitjoin.config.detect for more details.Compute join positions to be line ends of all but last region lines. Note: stop if no join positions are found.
Apply all hooks from
opts.join.hooks_pre
. Each is applied on the output of previous one. Input of first hook is join positions from previous step. Output of last one is used as join positions in next step.Join and update join positions with MiniSplitjoin.join_at().
Apply all hooks from
opts.join.hooks_post
. Each is applied on the output of previous one. Input of first hook is join positions from previous step plus region’s right end for easier hook code. Output of last one is used as function return value.
Parameters
{opts} (table|nil)
Options. Has structure from MiniSplitjoin.config inheriting its default values.
Following extra optional fields are allowed:
<position>
(table)
- position at which to find smallest bracket region. See MiniSplitjoin-glossary for the structure. Default: cursor position.<region>
(table)
- region at which to perform action. Assumes inclusive both start at left bracket and end at right bracket. See MiniSplitjoin-glossary for the structure. Default:nil
to automatically detect region.
Return
(any)
Output of last opts.split.hooks_post
or nil
of no join positions found. Default: return value of MiniSplitjoin.join_at() application.
gen_hook
MiniSplitjoin.gen_hook
Generate common hooks
This is a table with function elements. Call to actually get hook.
All generated post-hooks return updated versions of their input reflecting changes done inside hook.
Example for lua
filetype (place it in ‘lua.lua’ filetype plugin, ftplugin):
local gen_hook = MiniSplitjoin.gen_hook
local curly = { brackets = { '%b{}' } }
-- Add trailing comma when splitting inside curly brackets
local add_comma_curly = gen_hook.add_trailing_separator(curly)
-- Delete trailing comma when joining inside curly brackets
local del_comma_curly = gen_hook.del_trailing_separator(curly)
-- Pad curly brackets with single space after join
local pad_curly = gen_hook.pad_brackets(curly)
-- Create buffer-local config
vim.b.minisplitjoin_config = {
split = { hooks_post = { add_comma_curly } },
join = { hooks_post = { del_comma_curly, pad_curly } },
}
gen_hook.pad_brackets()
MiniSplitjoin.gen_hook.pad_brackets
({opts})
Generate hook to pad brackets
This is a join post-hook. Use in join.hooks_post
of MiniSplitjoin.config.
Parameters
{opts} (table|nil)
Options. Possible fields:
<pad>
(string)
- pad to add after first and before last join positions. Default:' '
(single space).<brackets>
(table)
- array of bracket patterns indicating on which brackets action should be made. Has same structure asbrackets
in MiniSplitjoin.config.detect. Default:MiniSplitjoin.config.detect.brackets
.
Return
(function)
A hook which adds inner pad to first and last join positions and returns updated input join positions.
gen_hook.add_trailing_separator()
MiniSplitjoin.gen_hook.add_trailing_separator
({opts})
Generate hook to add trailing separator
This is a split post-hook. Use in split.hooks_post
of MiniSplitjoin.config.
Parameters
{opts} (table|nil)
Options. Possible fields:
<sep>
(string)
- separator to add before last split position. Default:','
.<brackets>
(table)
- array of bracket patterns indicating on which brackets action should be made. Has same structure asbrackets
in MiniSplitjoin.config.detect. Default:MiniSplitjoin.config.detect.brackets
.
Return
(function)
A hook which adds separator before last split position and returns updated input split positions.
gen_hook.del_trailing_separator()
MiniSplitjoin.gen_hook.del_trailing_separator
({opts})
Generate hook to delete trailing separator
This is a join post-hook. Use in join.hooks_post
of MiniSplitjoin.config.
Parameters
{opts} (table|nil)
Options. Possible fields:
<sep>
(string)
- separator to remove before last join position. Default:','
.<brackets>
(table)
- array of bracket patterns indicating on which brackets action should be made. Has same structure asbrackets
in MiniSplitjoin.config.detect. Default:MiniSplitjoin.config.detect.brackets
.
Return
(function)
A hook which adds separator before last split position and returns updated input split positions.
split_at()
MiniSplitjoin.split_at
({positions})
Split at positions
Overview:
For each position move all characters after it to next line and make it have same indent as current one (see MiniSplitjoin.get_indent_part()). Also remove trailing whitespace at position line.
Increase indent of inner lines by a single pad: tab in case of ‘noexpandtab’ or shiftwidth() number of spaces otherwise.
Notes:
Cursor is adjusted to follow text updates.
Use output of this function to keep track of input positions.
Parameters
{positions} (table)
Array of positions at which to perform split. See MiniSplitjoin-glossary for their structure. Note: they don’t have to be ordered, but first and last ones will be used to infer lines for which indent will be increased.
Return
(table)
Array of new positions to where input positions
were moved.
join_at()
MiniSplitjoin.join_at
({positions})
Join at positions
Overview:
- For each position join its line with the next line. Joining is done by replacing trailing whitespace of the line and indent of its next line (see MiniSplitjoin.get_indent_part()) with a pad string (single space except empty string for first and last positions). To adjust this, use hooks (for example, see MiniSplitjoin.gen_hook.pad_brackets()).
Notes:
Cursor is adjusted to follow text updates.
Use output of this function to keep track of input positions.
Parameters
{positions} (table)
Array of positions at which to perform join. See MiniSplitjoin-glossary for their structure. Note: they don’t have to be ordered, but first and last ones will have different pad string.
Return
(table)
Array of new positions to where input positions
were moved.
get_visual_region()
MiniSplitjoin.get_visual_region
()
Get previous visual region
Get previous visual selection using ’< and ’> marks in the format of region (see MiniSplitjoin-glossary). Used in Visual mode mappings.
Note:
Both marks are included in region.
In linewise mode start is at column 1 and end is at line’s last character.
Return
(table)
A region. See MiniSplitjoin-glossary for exact structure.
get_indent_part()
MiniSplitjoin.get_indent_part
({line}, {respect_comments})
Get string’s indent part
Parameters
{line} (string)
String for which to compute indent.
{respect_comments} (boolean|nil)
Whether to respect comments as indent part. Default: true
.
Return
(string)
Part of input representing line’s indent. Can be empty string. Use string.len()
to compute indent in bytes.
operator()
MiniSplitjoin.operator
({task})
Operator for Normal mode mappings
Main function to be used in expression mappings. No need to use it directly, everything is setup in MiniSplitjoin.setup().
Parameters
{task} (string)
Name of task.