retrovim 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.conda/retrovim.yaml +259 -0
- package/.conda/terax.icns +0 -0
- package/.conda/terax.ico +0 -0
- package/.conda/terax.png +0 -0
- package/.github/workflows/release.yml +95 -0
- package/.gitmodules +3 -0
- package/.npm/kanata_touchcursor.js +28 -0
- package/.npm/nvim.js +26 -0
- package/.npm/yazi.js +26 -0
- package/.npm/zsh.js +17 -0
- package/.pip/kanata_touchcursor/__init__.py +28 -0
- package/.pip/nvim/__init__.py +31 -0
- package/.pip/yazi/__init__.py +31 -0
- package/.pip/zsh/__init__.py +22 -0
- package/CHANGELOG.md +26 -0
- package/LICENSE +674 -0
- package/README.md +336 -0
- package/kanata/touchcursor.kbd +164 -0
- package/nvim/init.lua +813 -0
- package/nvim/plugins/mini.nvim/.github/DISCUSSION_TEMPLATE/q-a.yml +72 -0
- package/nvim/plugins/mini.nvim/.github/ISSUE_TEMPLATE/bug-report.yml +136 -0
- package/nvim/plugins/mini.nvim/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/nvim/plugins/mini.nvim/.github/ISSUE_TEMPLATE/feature-request.yml +75 -0
- package/nvim/plugins/mini.nvim/.github/PULL_REQUEST_TEMPLATE.md +2 -0
- package/nvim/plugins/mini.nvim/.github/workflows/quality-control.yml +150 -0
- package/nvim/plugins/mini.nvim/.pre-commit-config.yaml +20 -0
- package/nvim/plugins/mini.nvim/.stylua.toml +7 -0
- package/nvim/plugins/mini.nvim/.styluaignore +1 -0
- package/nvim/plugins/mini.nvim/CHANGELOG.md +1894 -0
- package/nvim/plugins/mini.nvim/CODE_OF_CONDUCT.md +132 -0
- package/nvim/plugins/mini.nvim/CONTRIBUTING.md +331 -0
- package/nvim/plugins/mini.nvim/LICENSE +21 -0
- package/nvim/plugins/mini.nvim/MAINTAINING.md +330 -0
- package/nvim/plugins/mini.nvim/Makefile +51 -0
- package/nvim/plugins/mini.nvim/README.md +261 -0
- package/nvim/plugins/mini.nvim/TESTING.md +1011 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/README.md +35 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/benchmark.sh +56 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/init-files/init_dashboard-alpha.lua +21 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/init-files/init_dashboard-original.lua +17 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/init-files/init_dashboard-starter.lua +18 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/init-files/init_empty.lua +4 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/init-files/init_starter-default.lua +7 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/init-files/init_startify-alpha.lua +10 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/init-files/init_startify-original.lua +7 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/init-files/init_startify-starter.lua +20 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/install.sh +10 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/make_summary.py +68 -0
- package/nvim/plugins/mini.nvim/benchmarks/starter/startup-summary.md +10 -0
- package/nvim/plugins/mini.nvim/colors/miniautumn.lua +55 -0
- package/nvim/plugins/mini.nvim/colors/minicyan.lua +95 -0
- package/nvim/plugins/mini.nvim/colors/minischeme.lua +95 -0
- package/nvim/plugins/mini.nvim/colors/minispring.lua +53 -0
- package/nvim/plugins/mini.nvim/colors/minisummer.lua +49 -0
- package/nvim/plugins/mini.nvim/colors/miniwinter.lua +51 -0
- package/nvim/plugins/mini.nvim/colors/randomhue.lua +16 -0
- package/nvim/plugins/mini.nvim/doc/mini-ai.txt +889 -0
- package/nvim/plugins/mini.nvim/doc/mini-align.txt +923 -0
- package/nvim/plugins/mini.nvim/doc/mini-animate.txt +937 -0
- package/nvim/plugins/mini.nvim/doc/mini-base16.txt +285 -0
- package/nvim/plugins/mini.nvim/doc/mini-basics.txt +359 -0
- package/nvim/plugins/mini.nvim/doc/mini-bracketed.txt +622 -0
- package/nvim/plugins/mini.nvim/doc/mini-bufremove.txt +123 -0
- package/nvim/plugins/mini.nvim/doc/mini-clue.txt +760 -0
- package/nvim/plugins/mini.nvim/doc/mini-cmdline.txt +392 -0
- package/nvim/plugins/mini.nvim/doc/mini-colors.txt +880 -0
- package/nvim/plugins/mini.nvim/doc/mini-comment.txt +230 -0
- package/nvim/plugins/mini.nvim/doc/mini-completion.txt +477 -0
- package/nvim/plugins/mini.nvim/doc/mini-cursorword.txt +105 -0
- package/nvim/plugins/mini.nvim/doc/mini-deps.txt +590 -0
- package/nvim/plugins/mini.nvim/doc/mini-diff.txt +661 -0
- package/nvim/plugins/mini.nvim/doc/mini-doc.txt +434 -0
- package/nvim/plugins/mini.nvim/doc/mini-extra.txt +856 -0
- package/nvim/plugins/mini.nvim/doc/mini-files.txt +1018 -0
- package/nvim/plugins/mini.nvim/doc/mini-fuzzy.txt +160 -0
- package/nvim/plugins/mini.nvim/doc/mini-git.txt +425 -0
- package/nvim/plugins/mini.nvim/doc/mini-hipatterns.txt +489 -0
- package/nvim/plugins/mini.nvim/doc/mini-hues.txt +420 -0
- package/nvim/plugins/mini.nvim/doc/mini-icons.txt +508 -0
- package/nvim/plugins/mini.nvim/doc/mini-indentscope.txt +485 -0
- package/nvim/plugins/mini.nvim/doc/mini-input.txt +932 -0
- package/nvim/plugins/mini.nvim/doc/mini-jump.txt +202 -0
- package/nvim/plugins/mini.nvim/doc/mini-jump2d.txt +525 -0
- package/nvim/plugins/mini.nvim/doc/mini-keymap.txt +449 -0
- package/nvim/plugins/mini.nvim/doc/mini-map.txt +717 -0
- package/nvim/plugins/mini.nvim/doc/mini-misc.txt +431 -0
- package/nvim/plugins/mini.nvim/doc/mini-move.txt +181 -0
- package/nvim/plugins/mini.nvim/doc/mini-notify.txt +434 -0
- package/nvim/plugins/mini.nvim/doc/mini-nvim.txt +431 -0
- package/nvim/plugins/mini.nvim/doc/mini-operators.txt +472 -0
- package/nvim/plugins/mini.nvim/doc/mini-pairs.txt +346 -0
- package/nvim/plugins/mini.nvim/doc/mini-pick.txt +1535 -0
- package/nvim/plugins/mini.nvim/doc/mini-sessions.txt +239 -0
- package/nvim/plugins/mini.nvim/doc/mini-snippets.txt +1291 -0
- package/nvim/plugins/mini.nvim/doc/mini-splitjoin.txt +536 -0
- package/nvim/plugins/mini.nvim/doc/mini-starter.txt +618 -0
- package/nvim/plugins/mini.nvim/doc/mini-statusline.txt +361 -0
- package/nvim/plugins/mini.nvim/doc/mini-surround.txt +863 -0
- package/nvim/plugins/mini.nvim/doc/mini-tabline.txt +151 -0
- package/nvim/plugins/mini.nvim/doc/mini-test.txt +966 -0
- package/nvim/plugins/mini.nvim/doc/mini-trailspace.txt +91 -0
- package/nvim/plugins/mini.nvim/doc/mini-visits.txt +937 -0
- package/nvim/plugins/mini.nvim/logo.png +0 -0
- package/nvim/plugins/mini.nvim/lua/mini/ai.lua +2244 -0
- package/nvim/plugins/mini.nvim/lua/mini/align.lua +2076 -0
- package/nvim/plugins/mini.nvim/lua/mini/animate.lua +2127 -0
- package/nvim/plugins/mini.nvim/lua/mini/base16.lua +1752 -0
- package/nvim/plugins/mini.nvim/lua/mini/basics.lua +772 -0
- package/nvim/plugins/mini.nvim/lua/mini/bracketed.lua +2013 -0
- package/nvim/plugins/mini.nvim/lua/mini/bufremove.lua +283 -0
- package/nvim/plugins/mini.nvim/lua/mini/clue.lua +2096 -0
- package/nvim/plugins/mini.nvim/lua/mini/cmdline.lua +1182 -0
- package/nvim/plugins/mini.nvim/lua/mini/colors.lua +2483 -0
- package/nvim/plugins/mini.nvim/lua/mini/comment.lua +586 -0
- package/nvim/plugins/mini.nvim/lua/mini/completion.lua +2094 -0
- package/nvim/plugins/mini.nvim/lua/mini/cursorword.lua +311 -0
- package/nvim/plugins/mini.nvim/lua/mini/deps.lua +1660 -0
- package/nvim/plugins/mini.nvim/lua/mini/diff.lua +1938 -0
- package/nvim/plugins/mini.nvim/lua/mini/doc.lua +1371 -0
- package/nvim/plugins/mini.nvim/lua/mini/extra.lua +2290 -0
- package/nvim/plugins/mini.nvim/lua/mini/files.lua +3145 -0
- package/nvim/plugins/mini.nvim/lua/mini/fuzzy.lua +356 -0
- package/nvim/plugins/mini.nvim/lua/mini/git.lua +1737 -0
- package/nvim/plugins/mini.nvim/lua/mini/hipatterns.lua +1042 -0
- package/nvim/plugins/mini.nvim/lua/mini/hues.lua +2088 -0
- package/nvim/plugins/mini.nvim/lua/mini/icons.lua +2254 -0
- package/nvim/plugins/mini.nvim/lua/mini/indentscope.lua +1158 -0
- package/nvim/plugins/mini.nvim/lua/mini/init.lua +427 -0
- package/nvim/plugins/mini.nvim/lua/mini/input.lua +2183 -0
- package/nvim/plugins/mini.nvim/lua/mini/jump.lua +609 -0
- package/nvim/plugins/mini.nvim/lua/mini/jump2d.lua +1244 -0
- package/nvim/plugins/mini.nvim/lua/mini/keymap.lua +880 -0
- package/nvim/plugins/mini.nvim/lua/mini/map.lua +1709 -0
- package/nvim/plugins/mini.nvim/lua/mini/misc.lua +969 -0
- package/nvim/plugins/mini.nvim/lua/mini/move.lua +509 -0
- package/nvim/plugins/mini.nvim/lua/mini/notify.lua +938 -0
- package/nvim/plugins/mini.nvim/lua/mini/operators.lua +1349 -0
- package/nvim/plugins/mini.nvim/lua/mini/pairs.lua +657 -0
- package/nvim/plugins/mini.nvim/lua/mini/pick.lua +3876 -0
- package/nvim/plugins/mini.nvim/lua/mini/sessions.lua +689 -0
- package/nvim/plugins/mini.nvim/lua/mini/snippets.lua +2828 -0
- package/nvim/plugins/mini.nvim/lua/mini/splitjoin.lua +1132 -0
- package/nvim/plugins/mini.nvim/lua/mini/starter.lua +1599 -0
- package/nvim/plugins/mini.nvim/lua/mini/statusline.lua +686 -0
- package/nvim/plugins/mini.nvim/lua/mini/surround.lua +2388 -0
- package/nvim/plugins/mini.nvim/lua/mini/tabline.lua +564 -0
- package/nvim/plugins/mini.nvim/lua/mini/test.lua +2516 -0
- package/nvim/plugins/mini.nvim/lua/mini/trailspace.lua +215 -0
- package/nvim/plugins/mini.nvim/lua/mini/visits.lua +1577 -0
- package/nvim/plugins/mini.nvim/readmes/mini-ai.md +190 -0
- package/nvim/plugins/mini.nvim/readmes/mini-align.md +203 -0
- package/nvim/plugins/mini.nvim/readmes/mini-animate.md +214 -0
- package/nvim/plugins/mini.nvim/readmes/mini-base16.md +198 -0
- package/nvim/plugins/mini.nvim/readmes/mini-basics.md +184 -0
- package/nvim/plugins/mini.nvim/readmes/mini-bracketed.md +193 -0
- package/nvim/plugins/mini.nvim/readmes/mini-bufremove.md +139 -0
- package/nvim/plugins/mini.nvim/readmes/mini-clue.md +260 -0
- package/nvim/plugins/mini.nvim/readmes/mini-cmdline.md +183 -0
- package/nvim/plugins/mini.nvim/readmes/mini-colors.md +169 -0
- package/nvim/plugins/mini.nvim/readmes/mini-comment.md +183 -0
- package/nvim/plugins/mini.nvim/readmes/mini-completion.md +217 -0
- package/nvim/plugins/mini.nvim/readmes/mini-cursorword.md +137 -0
- package/nvim/plugins/mini.nvim/readmes/mini-deps.md +271 -0
- package/nvim/plugins/mini.nvim/readmes/mini-diff.md +289 -0
- package/nvim/plugins/mini.nvim/readmes/mini-doc.md +198 -0
- package/nvim/plugins/mini.nvim/readmes/mini-extra.md +158 -0
- package/nvim/plugins/mini.nvim/readmes/mini-files.md +247 -0
- package/nvim/plugins/mini.nvim/readmes/mini-fuzzy.md +134 -0
- package/nvim/plugins/mini.nvim/readmes/mini-git.md +168 -0
- package/nvim/plugins/mini.nvim/readmes/mini-hipatterns.md +176 -0
- package/nvim/plugins/mini.nvim/readmes/mini-hues.md +285 -0
- package/nvim/plugins/mini.nvim/readmes/mini-icons.md +183 -0
- package/nvim/plugins/mini.nvim/readmes/mini-indentscope.md +191 -0
- package/nvim/plugins/mini.nvim/readmes/mini-input.md +163 -0
- package/nvim/plugins/mini.nvim/readmes/mini-jump.md +161 -0
- package/nvim/plugins/mini.nvim/readmes/mini-jump2d.md +197 -0
- package/nvim/plugins/mini.nvim/readmes/mini-keymap.md +205 -0
- package/nvim/plugins/mini.nvim/readmes/mini-map.md +191 -0
- package/nvim/plugins/mini.nvim/readmes/mini-misc.md +145 -0
- package/nvim/plugins/mini.nvim/readmes/mini-move.md +163 -0
- package/nvim/plugins/mini.nvim/readmes/mini-notify.md +175 -0
- package/nvim/plugins/mini.nvim/readmes/mini-operators.md +193 -0
- package/nvim/plugins/mini.nvim/readmes/mini-pairs.md +158 -0
- package/nvim/plugins/mini.nvim/readmes/mini-pick.md +340 -0
- package/nvim/plugins/mini.nvim/readmes/mini-sessions.md +164 -0
- package/nvim/plugins/mini.nvim/readmes/mini-snippets.md +373 -0
- package/nvim/plugins/mini.nvim/readmes/mini-splitjoin.md +194 -0
- package/nvim/plugins/mini.nvim/readmes/mini-starter.md +176 -0
- package/nvim/plugins/mini.nvim/readmes/mini-statusline.md +155 -0
- package/nvim/plugins/mini.nvim/readmes/mini-surround.md +190 -0
- package/nvim/plugins/mini.nvim/readmes/mini-tabline.md +156 -0
- package/nvim/plugins/mini.nvim/readmes/mini-test.md +175 -0
- package/nvim/plugins/mini.nvim/readmes/mini-trailspace.md +137 -0
- package/nvim/plugins/mini.nvim/readmes/mini-visits.md +243 -0
- package/nvim/plugins/mini.nvim/scripts/dual_log.sh +13 -0
- package/nvim/plugins/mini.nvim/scripts/dual_push.sh +15 -0
- package/nvim/plugins/mini.nvim/scripts/dual_release.sh +102 -0
- package/nvim/plugins/mini.nvim/scripts/dual_sync.sh +115 -0
- package/nvim/plugins/mini.nvim/scripts/init-deps-example.lua +59 -0
- package/nvim/plugins/mini.nvim/scripts/lint-filename-length.sh +16 -0
- package/nvim/plugins/mini.nvim/scripts/lintcommit-ci.sh +18 -0
- package/nvim/plugins/mini.nvim/scripts/lintcommit.lua +393 -0
- package/nvim/plugins/mini.nvim/scripts/minidoc.lua +57 -0
- package/nvim/plugins/mini.nvim/scripts/minimal_init.lua +28 -0
- package/nvim/plugins/mini.nvim/scripts/minitest.lua +4 -0
- package/package.json +16 -0
- package/pyproject.toml +43 -0
- package/yazi/init.lua +12 -0
- package/yazi/keymap.toml +114 -0
- package/yazi/lesskey +5 -0
- package/yazi/plugins/bookmarks.yazi/main.lua +86 -0
- package/yazi/plugins/cd-git-root.yazi/main.lua +31 -0
- package/yazi/plugins/smart-enter.yazi/main.lua +11 -0
- package/yazi/theme.toml +26 -0
- package/yazi/yazi.toml +15 -0
- package/zsh/.zshrc +145 -0
- package/zsh/starship.toml +20 -0
- package/zsh/zsh-patina.toml +2 -0
|
@@ -0,0 +1,2013 @@
|
|
|
1
|
+
--- *mini.bracketed* Go forward/backward with square brackets
|
|
2
|
+
---
|
|
3
|
+
--- MIT License Copyright (c) 2023 Evgeni Chasnovski
|
|
4
|
+
|
|
5
|
+
--- Features:
|
|
6
|
+
--- - Configurable Lua functions to go forward/backward to a certain target.
|
|
7
|
+
--- Each function can be customized with:
|
|
8
|
+
--- - Direction. One of "forward", "backward", "first" (forward starting
|
|
9
|
+
--- from first one), "last" (backward starting from last one).
|
|
10
|
+
--- - Number of times to go.
|
|
11
|
+
--- - Whether to wrap on edges (going forward on last one goes to first).
|
|
12
|
+
--- - Some other target specific options.
|
|
13
|
+
---
|
|
14
|
+
--- - Mappings using square brackets. They are created using configurable
|
|
15
|
+
--- target suffix and can be selectively disabled.
|
|
16
|
+
---
|
|
17
|
+
--- Each mapping supports |[count]|. Mappings are created in Normal mode; for
|
|
18
|
+
--- targets which move cursor in current buffer also Visual and
|
|
19
|
+
--- Operator-pending (with dot-repeat) modes are supported.
|
|
20
|
+
---
|
|
21
|
+
--- Using `lower-suffix` and `upper-suffix` (lower and upper case suffix) for
|
|
22
|
+
--- a single target the following mappings are created:
|
|
23
|
+
--- - `[` + `upper-suffix` : go first.
|
|
24
|
+
--- - `[` + `lower-suffix` : go backward.
|
|
25
|
+
--- - `]` + `lower-suffix` : go forward.
|
|
26
|
+
--- - `]` + `upper-suffix` : go last.
|
|
27
|
+
---
|
|
28
|
+
--- - Supported targets (for more information see help for corresponding Lua
|
|
29
|
+
--- function):
|
|
30
|
+
---
|
|
31
|
+
--- `Target` `Mappings` `Lua function`
|
|
32
|
+
--- Buffer ......................... `[B` `[b` `]b` `]B` .... |MiniBracketed.buffer()|
|
|
33
|
+
--- Comment block .................. `[C` `[c` `]c` `]C` .... |MiniBracketed.comment()|
|
|
34
|
+
--- Conflict marker ................ `[X` `[x` `]x` `]X` .... |MiniBracketed.conflict()|
|
|
35
|
+
--- Diagnostic ..................... `[D` `[d` `]d` `]D` .... |MiniBracketed.diagnostic()|
|
|
36
|
+
--- File on disk ................... `[F` `[f` `]f` `]F` .... |MiniBracketed.file()|
|
|
37
|
+
--- Indent change .................. `[I` `[i` `]i` `]I` .... |MiniBracketed.indent()|
|
|
38
|
+
--- Jump inside current buffer ..... `[J` `[j` `]j` `]J` .... |MiniBracketed.jump()|
|
|
39
|
+
--- Location from |location-list| .... `[L` `[l` `]l` `]L` .... |MiniBracketed.location()|
|
|
40
|
+
--- Old files ...................... `[O` `[o` `]o` `]O` .... |MiniBracketed.oldfile()|
|
|
41
|
+
--- Quickfix entry from |Quickfix| ... `[Q` `[q` `]q` `]Q` .... |MiniBracketed.quickfix()|
|
|
42
|
+
--- Tree-sitter node and parents ... `[T` `[t` `]t` `]T` .... |MiniBracketed.treesitter()|
|
|
43
|
+
--- Undo from linear history ....... `[U` `[u` `]u` `]U` .... |MiniBracketed.undo()|
|
|
44
|
+
--- Window in current tab .......... `[W` `[w` `]w` `]W` .... |MiniBracketed.window()|
|
|
45
|
+
--- Yank entry over put region ..... `[Y` `[y` `]y` `]Y` .... |MiniBracketed.yank()|
|
|
46
|
+
---
|
|
47
|
+
--- Notes:
|
|
48
|
+
--- - The `undo` target remaps |u| and |CTRL-R| keys to register undo state
|
|
49
|
+
--- after undo and redo respectively. If this conflicts with your setup,
|
|
50
|
+
--- either disable `undo` target or make your remaps after calling
|
|
51
|
+
--- |MiniBracketed.setup()|. To use `undo` target, remap your undo/redo keys
|
|
52
|
+
--- to call |MiniBracketed.register_undo_state()| after the action.
|
|
53
|
+
---
|
|
54
|
+
--- # Setup ~
|
|
55
|
+
---
|
|
56
|
+
--- This module needs a setup with `require('mini.bracketed').setup({})` (replace
|
|
57
|
+
--- `{}` with your `config` table). It will create global Lua table `MiniBracketed`
|
|
58
|
+
--- which you can use for scripting or manually (with `:lua MiniBracketed.*`).
|
|
59
|
+
---
|
|
60
|
+
--- See |MiniBracketed.config| for available config settings.
|
|
61
|
+
---
|
|
62
|
+
--- You can override runtime config settings (like target options) locally
|
|
63
|
+
--- to buffer inside `vim.b.minibracketed_config` which should have same structure
|
|
64
|
+
--- as `MiniBracketed.config`. See |mini.nvim-buffer-local-config| for more details.
|
|
65
|
+
---
|
|
66
|
+
--- # Comparisons ~
|
|
67
|
+
---
|
|
68
|
+
--- - [tpope/vim-unimpaired](https://github.com/tpope/vim-unimpaired):
|
|
69
|
+
--- - Supports buffer, conflict, file, location, and quickfix targets mostly
|
|
70
|
+
--- via built-in commands (like |:bprevious|, etc.) without configuration.
|
|
71
|
+
--- - Supports files from argument list and tags. This module does not.
|
|
72
|
+
--- - Doesn't support most other this module's targets (comment, indent, ...).
|
|
73
|
+
--- - |mini.indentscope|:
|
|
74
|
+
--- - Target |MiniBracketed.indent()| target can go to "first" and "last"
|
|
75
|
+
--- indent change. It also can go not only to line with smaller indent,
|
|
76
|
+
--- but also bigger or different one.
|
|
77
|
+
--- - Mappings from |mini.indentscope| have more flexibility in computation of
|
|
78
|
+
--- indent scope, like how to treat empty lines near border or whether to
|
|
79
|
+
--- compute indent at cursor.
|
|
80
|
+
---
|
|
81
|
+
--- # Disabling ~
|
|
82
|
+
---
|
|
83
|
+
--- To disable, set `vim.g.minibracketed_disable` (globally) or
|
|
84
|
+
--- `vim.b.minibracketed_disable` (for a buffer) to `true`. Considering high
|
|
85
|
+
--- number of different scenarios and customization intentions, writing exact
|
|
86
|
+
--- rules for disabling module's functionality is left to user. See
|
|
87
|
+
--- |mini.nvim-disabling-recipes| for common recipes.
|
|
88
|
+
---@tag MiniBracketed
|
|
89
|
+
|
|
90
|
+
---@diagnostic disable:luadoc-miss-type-name
|
|
91
|
+
---@alias __bracketed_direction string One of "first", "backward", "forward", "last".
|
|
92
|
+
---@alias __bracketed_add_to_jumplist - <add_to_jumplist> (`boolean`) - Whether to add current position to jumplist.
|
|
93
|
+
--- Default: `false`.
|
|
94
|
+
---@alias __bracketed_opts table|nil Options. A table with fields:
|
|
95
|
+
--- - <n_times> `(number)` - Number of times to advance. Default: |v:count1|.
|
|
96
|
+
--- - <wrap> `(boolean)` - Whether to wrap around edges. Default: `true`.
|
|
97
|
+
|
|
98
|
+
---@diagnostic disable:undefined-field
|
|
99
|
+
|
|
100
|
+
-- Module definition ==========================================================
|
|
101
|
+
local MiniBracketed = {}
|
|
102
|
+
local H = {}
|
|
103
|
+
|
|
104
|
+
--- Module setup
|
|
105
|
+
---
|
|
106
|
+
---@param config table|nil Module config table. See |MiniBracketed.config|.
|
|
107
|
+
---
|
|
108
|
+
---@usage >lua
|
|
109
|
+
--- require('mini.bracketed').setup() -- use default config
|
|
110
|
+
--- -- OR
|
|
111
|
+
--- require('mini.bracketed').setup({}) -- replace {} with your config table
|
|
112
|
+
--- <
|
|
113
|
+
MiniBracketed.setup = function(config)
|
|
114
|
+
-- TODO: Remove after Neovim=0.9 support is dropped
|
|
115
|
+
if vim.fn.has('nvim-0.10') == 0 then
|
|
116
|
+
vim.notify(
|
|
117
|
+
'(mini.bracketed) Neovim<0.10 is soft deprecated (module works but is not supported).'
|
|
118
|
+
.. " It will be deprecated after the next 'mini.nvim' release (module might not work)."
|
|
119
|
+
.. ' Please update your Neovim version.'
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
-- Export module
|
|
124
|
+
_G.MiniBracketed = MiniBracketed
|
|
125
|
+
|
|
126
|
+
-- Setup config
|
|
127
|
+
config = H.setup_config(config)
|
|
128
|
+
|
|
129
|
+
-- Apply config
|
|
130
|
+
H.apply_config(config)
|
|
131
|
+
|
|
132
|
+
-- Define behavior
|
|
133
|
+
H.create_autocommands()
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
--stylua: ignore
|
|
137
|
+
--- Defaults ~
|
|
138
|
+
---@eval return MiniDoc.afterlines_to_code(MiniDoc.current.eval_section)
|
|
139
|
+
---@text Options ~
|
|
140
|
+
---
|
|
141
|
+
--- Each entry configures target with the same name and can have data configuring
|
|
142
|
+
--- mapping suffix and target options.
|
|
143
|
+
---
|
|
144
|
+
--- Example of configuration: >lua
|
|
145
|
+
---
|
|
146
|
+
--- require('mini.bracketed').setup({
|
|
147
|
+
--- -- Map [N, [n, ]n, ]N for conflict marker like in 'tpope/vim-unimpaired'
|
|
148
|
+
--- conflict = { suffix = 'n' },
|
|
149
|
+
---
|
|
150
|
+
--- -- Make diagnostic advance only by errors
|
|
151
|
+
--- diagnostic = { options = { severity = vim.diagnostic.severity.ERROR } },
|
|
152
|
+
---
|
|
153
|
+
--- -- Disable creation of mappings for `indent` target (for example,
|
|
154
|
+
--- -- in favor of ones from |mini.indentscope|)
|
|
155
|
+
--- indent = { suffix = '' },
|
|
156
|
+
---
|
|
157
|
+
--- -- Disable mappings for `window` target in favor of custom ones
|
|
158
|
+
--- window = { suffix = '' },
|
|
159
|
+
--- })
|
|
160
|
+
---
|
|
161
|
+
--- -- Create custom `window` mappings
|
|
162
|
+
--- local map = vim.keymap.set
|
|
163
|
+
--- map('n', '<Leader>wH', "<Cmd>lua MiniBracketed.window('first')<CR>")
|
|
164
|
+
--- map('n', '<Leader>wh', "<Cmd>lua MiniBracketed.window('backward')<CR>")
|
|
165
|
+
--- map('n', '<Leader>wl', "<Cmd>lua MiniBracketed.window('forward')<CR>")
|
|
166
|
+
--- map('n', '<Leader>wL', "<Cmd>lua MiniBracketed.window('last')<CR>")
|
|
167
|
+
--- <
|
|
168
|
+
--- ## Suffix ~
|
|
169
|
+
---
|
|
170
|
+
--- The `suffix` key is used to create target mappings.
|
|
171
|
+
---
|
|
172
|
+
--- Supply empty string to disable mapping creation for that particular target.
|
|
173
|
+
--- To create a completely different mapping (like with |<Leader>|) use target
|
|
174
|
+
--- function manually.
|
|
175
|
+
---
|
|
176
|
+
--- Using `lower-suffix` and `upper-suffix` (lower and upper case suffix) for
|
|
177
|
+
--- a single target the following mappings are created:
|
|
178
|
+
--- - `[` + `upper-suffix` : go first.
|
|
179
|
+
--- - `[` + `lower-suffix` : go backward.
|
|
180
|
+
--- - `]` + `lower-suffix` : go forward.
|
|
181
|
+
--- - `]` + `upper-suffix` : go last.
|
|
182
|
+
---
|
|
183
|
+
--- When supplied with a non-letter, only forward/backward mappings are created.
|
|
184
|
+
---
|
|
185
|
+
--- ## Options ~
|
|
186
|
+
---
|
|
187
|
+
--- The `options` key is directly forwarded as `opts` to corresponding Lua function.
|
|
188
|
+
MiniBracketed.config = {
|
|
189
|
+
-- First-level elements are tables describing behavior of a target:
|
|
190
|
+
--
|
|
191
|
+
-- - <suffix> - single character suffix. Used after `[` / `]` in mappings.
|
|
192
|
+
-- For example, with `b` creates `[B`, `[b`, `]b`, `]B` mappings.
|
|
193
|
+
-- Supply empty string `''` to not create mappings.
|
|
194
|
+
--
|
|
195
|
+
-- - <options> - table overriding target options.
|
|
196
|
+
--
|
|
197
|
+
-- See `:h MiniBracketed.config` for more info.
|
|
198
|
+
|
|
199
|
+
buffer = { suffix = 'b', options = {} },
|
|
200
|
+
comment = { suffix = 'c', options = {} },
|
|
201
|
+
conflict = { suffix = 'x', options = {} },
|
|
202
|
+
diagnostic = { suffix = 'd', options = {} },
|
|
203
|
+
file = { suffix = 'f', options = {} },
|
|
204
|
+
indent = { suffix = 'i', options = {} },
|
|
205
|
+
jump = { suffix = 'j', options = {} },
|
|
206
|
+
location = { suffix = 'l', options = {} },
|
|
207
|
+
oldfile = { suffix = 'o', options = {} },
|
|
208
|
+
quickfix = { suffix = 'q', options = {} },
|
|
209
|
+
treesitter = { suffix = 't', options = {} },
|
|
210
|
+
undo = { suffix = 'u', options = {} },
|
|
211
|
+
window = { suffix = 'w', options = {} },
|
|
212
|
+
yank = { suffix = 'y', options = {} },
|
|
213
|
+
}
|
|
214
|
+
--minidoc_afterlines_end
|
|
215
|
+
|
|
216
|
+
--- Listed buffer
|
|
217
|
+
---
|
|
218
|
+
--- Go to next/previous listed buffer. Order by their number (see |bufnr()|).
|
|
219
|
+
---
|
|
220
|
+
--- Direction "forward" increases number, "backward" - decreases.
|
|
221
|
+
---
|
|
222
|
+
---@param direction __bracketed_direction
|
|
223
|
+
---@param opts __bracketed_opts
|
|
224
|
+
MiniBracketed.buffer = function(direction, opts)
|
|
225
|
+
if H.is_disabled() then return end
|
|
226
|
+
|
|
227
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'buffer')
|
|
228
|
+
opts =
|
|
229
|
+
vim.tbl_deep_extend('force', { n_times = vim.v.count1, wrap = true }, H.get_config().buffer.options, opts or {})
|
|
230
|
+
|
|
231
|
+
-- Define iterator that traverses all valid listed buffers
|
|
232
|
+
-- (should be same as `:bnext` / `:bprev`)
|
|
233
|
+
local buf_list = vim.api.nvim_list_bufs()
|
|
234
|
+
local is_listed = function(buf_id) return vim.api.nvim_buf_is_valid(buf_id) and vim.bo[buf_id].buflisted end
|
|
235
|
+
|
|
236
|
+
local iterator = {}
|
|
237
|
+
|
|
238
|
+
iterator.next = function(buf_id)
|
|
239
|
+
for id = buf_id + 1, buf_list[#buf_list] do
|
|
240
|
+
if is_listed(id) then return id end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
iterator.prev = function(buf_id)
|
|
245
|
+
for id = buf_id - 1, buf_list[1], -1 do
|
|
246
|
+
if is_listed(id) then return id end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
iterator.state = vim.api.nvim_get_current_buf()
|
|
251
|
+
iterator.start_edge = buf_list[1] - 1
|
|
252
|
+
iterator.end_edge = buf_list[#buf_list] + 1
|
|
253
|
+
|
|
254
|
+
-- Iterate
|
|
255
|
+
local res_buf_id = MiniBracketed.advance(iterator, direction, opts)
|
|
256
|
+
if res_buf_id == iterator.state then return end
|
|
257
|
+
|
|
258
|
+
-- Apply
|
|
259
|
+
vim.api.nvim_set_current_buf(res_buf_id)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
--- Comment block
|
|
263
|
+
---
|
|
264
|
+
--- Go to next/previous comment block. Only linewise comments using
|
|
265
|
+
--- |'commentstring'| are recognized.
|
|
266
|
+
---
|
|
267
|
+
--- Direction "forward" increases line number, "backward" - decreases.
|
|
268
|
+
---
|
|
269
|
+
---@param direction __bracketed_direction
|
|
270
|
+
---@param opts __bracketed_opts
|
|
271
|
+
--- __bracketed_add_to_jumplist
|
|
272
|
+
--- - <block_side> `(string)` - which side of comment block to use. One of
|
|
273
|
+
--- "near" (default; use nearest side), "start" (use first line), "end"
|
|
274
|
+
--- (use last line), "both" (use both first and last lines).
|
|
275
|
+
MiniBracketed.comment = function(direction, opts)
|
|
276
|
+
if H.is_disabled() then return end
|
|
277
|
+
|
|
278
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'comment')
|
|
279
|
+
opts = vim.tbl_deep_extend(
|
|
280
|
+
'force',
|
|
281
|
+
{ add_to_jumplist = false, block_side = 'near', n_times = vim.v.count1, wrap = true },
|
|
282
|
+
H.get_config().comment.options,
|
|
283
|
+
opts or {}
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
-- Compute loop data to traverse target commented lines in current buffer
|
|
287
|
+
local is_commented = H.make_comment_checker()
|
|
288
|
+
if is_commented == nil then return end
|
|
289
|
+
|
|
290
|
+
local predicate = ({
|
|
291
|
+
near = function(_, cur, _, recent) return cur and not recent end,
|
|
292
|
+
start = function(above, cur, _, _) return cur and not above end,
|
|
293
|
+
['end'] = function(_, cur, below, _) return cur and not below end,
|
|
294
|
+
both = function(above, cur, below, _) return cur and not (above and below) end,
|
|
295
|
+
})[opts.block_side]
|
|
296
|
+
if predicate == nil then return end
|
|
297
|
+
|
|
298
|
+
-- Define iterator
|
|
299
|
+
local iterator = {}
|
|
300
|
+
|
|
301
|
+
local n_lines = vim.api.nvim_buf_line_count(0)
|
|
302
|
+
iterator.next = function(line_num)
|
|
303
|
+
local above, cur = is_commented(line_num), is_commented(line_num + 1)
|
|
304
|
+
for lnum = line_num + 1, n_lines do
|
|
305
|
+
local below = is_commented(lnum + 1)
|
|
306
|
+
if predicate(above, cur, below, above) then return lnum end
|
|
307
|
+
above, cur = cur, below
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
iterator.prev = function(line_num)
|
|
312
|
+
local cur, below = is_commented(line_num - 1), is_commented(line_num)
|
|
313
|
+
for lnum = line_num - 1, 1, -1 do
|
|
314
|
+
local above = is_commented(lnum - 1)
|
|
315
|
+
if predicate(above, cur, below, below) then return lnum end
|
|
316
|
+
below, cur = cur, above
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
iterator.state = vim.fn.line('.')
|
|
321
|
+
iterator.start_edge = 0
|
|
322
|
+
iterator.end_edge = n_lines + 1
|
|
323
|
+
|
|
324
|
+
-- Iterate
|
|
325
|
+
local res_line_num = MiniBracketed.advance(iterator, direction, opts)
|
|
326
|
+
local is_outside = res_line_num <= 0 or n_lines < res_line_num
|
|
327
|
+
if res_line_num == nil or res_line_num == iterator.state or is_outside then return end
|
|
328
|
+
|
|
329
|
+
-- Possibly add current position to jumplist
|
|
330
|
+
if opts.add_to_jumplist then H.add_to_jumplist() end
|
|
331
|
+
|
|
332
|
+
-- Apply. Open just enough folds and put cursor on first non-blank.
|
|
333
|
+
H.set_cursor(res_line_num, 0)
|
|
334
|
+
vim.cmd('normal! zv^')
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
--- Git conflict marker
|
|
338
|
+
---
|
|
339
|
+
--- Go to next/previous lines containing Git conflict marker. That is, if it
|
|
340
|
+
--- starts with "<<<<<<< ", ">>>>>>> ", or is "=======".
|
|
341
|
+
---
|
|
342
|
+
--- Direction "forward" increases line number, "backward" - decreases.
|
|
343
|
+
---
|
|
344
|
+
--- Notes:
|
|
345
|
+
--- - Using this target in Operator-pending mode allows the following approach
|
|
346
|
+
--- at resolving merge conflicts:
|
|
347
|
+
--- - Place cursor on `=======` line.
|
|
348
|
+
--- - Execute one of these: `d]x[xdd` (choose upper part) or
|
|
349
|
+
--- `d[x]xdd` (choose lower part).
|
|
350
|
+
---
|
|
351
|
+
---@param direction __bracketed_direction
|
|
352
|
+
---@param opts __bracketed_opts
|
|
353
|
+
--- __bracketed_add_to_jumplist
|
|
354
|
+
MiniBracketed.conflict = function(direction, opts)
|
|
355
|
+
if H.is_disabled() then return end
|
|
356
|
+
|
|
357
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'conflict')
|
|
358
|
+
opts = vim.tbl_deep_extend(
|
|
359
|
+
'force',
|
|
360
|
+
{ add_to_jumplist = false, n_times = vim.v.count1, wrap = true },
|
|
361
|
+
H.get_config().conflict.options,
|
|
362
|
+
opts or {}
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
-- Define iterator that traverses all conflict markers in current buffer
|
|
366
|
+
local n_lines = vim.api.nvim_buf_line_count(0)
|
|
367
|
+
|
|
368
|
+
local iterator = {}
|
|
369
|
+
|
|
370
|
+
iterator.next = function(line_num)
|
|
371
|
+
for lnum = line_num + 1, n_lines do
|
|
372
|
+
if H.is_conflict_mark(lnum) then return lnum end
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
iterator.prev = function(line_num)
|
|
377
|
+
for lnum = line_num - 1, 1, -1 do
|
|
378
|
+
if H.is_conflict_mark(lnum) then return lnum end
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
iterator.state = vim.fn.line('.')
|
|
383
|
+
iterator.start_edge = 0
|
|
384
|
+
iterator.end_edge = n_lines + 1
|
|
385
|
+
|
|
386
|
+
-- Iterate
|
|
387
|
+
local res_line_num = MiniBracketed.advance(iterator, direction, opts)
|
|
388
|
+
local is_outside = res_line_num <= 0 or n_lines < res_line_num
|
|
389
|
+
if res_line_num == nil or res_line_num == iterator.state or is_outside then return end
|
|
390
|
+
|
|
391
|
+
-- Possibly add current position to jumplist
|
|
392
|
+
if opts.add_to_jumplist then H.add_to_jumplist() end
|
|
393
|
+
|
|
394
|
+
-- Apply. Open just enough folds and put cursor on first non-blank.
|
|
395
|
+
H.set_cursor(res_line_num, 0)
|
|
396
|
+
vim.cmd('normal! zv^')
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
--- Diagnostic
|
|
400
|
+
---
|
|
401
|
+
--- Go to next/previous diagnostic. This is mostly similar to built-in
|
|
402
|
+
--- |vim.diagnostic.jump()| (on Neovim<0.11 it is |vim.diagnostic.goto_next()| and
|
|
403
|
+
--- |vim.diagnostic.goto_prev()|) which has an interface and behavior
|
|
404
|
+
--- consistent with other methods of the module.
|
|
405
|
+
---
|
|
406
|
+
--- Direction "forward" increases line number, "backward" - decreases.
|
|
407
|
+
---
|
|
408
|
+
--- Notes:
|
|
409
|
+
--- - Using `severity` option, this target can be used in mappings like "go to
|
|
410
|
+
--- next/previous error" (), etc. Using code similar to this: >lua
|
|
411
|
+
---
|
|
412
|
+
--- local severity_error = vim.diagnostic.severity.ERROR
|
|
413
|
+
--- -- Use these inside custom mappings
|
|
414
|
+
--- MiniBracketed.diagnostic('forward', { severity = severity_error })
|
|
415
|
+
--- MiniBracketed.diagnostic('backward', { severity = severity_error })
|
|
416
|
+
--- <
|
|
417
|
+
---@param direction __bracketed_direction
|
|
418
|
+
---@param opts __bracketed_opts
|
|
419
|
+
--- - <float> `(boolean|table)` - control floating window after movement.
|
|
420
|
+
--- For available values see |vim.diagnostic.goto_next()|.
|
|
421
|
+
--- - <severity> `(string|table)` - which severity to use.
|
|
422
|
+
--- For available values see |diagnostic-severity|.
|
|
423
|
+
MiniBracketed.diagnostic = function(direction, opts)
|
|
424
|
+
if H.is_disabled() then return end
|
|
425
|
+
|
|
426
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'diagnostic')
|
|
427
|
+
local default_opts = { float = vim.diagnostic.config().float, n_times = vim.v.count1, severity = nil, wrap = true }
|
|
428
|
+
local buf_id = vim.api.nvim_get_current_buf()
|
|
429
|
+
if vim.is_callable(default_opts.float) then default_opts.float = default_opts.float(nil, buf_id) end
|
|
430
|
+
opts = vim.tbl_extend('force', default_opts, H.get_config().diagnostic.options, opts or {})
|
|
431
|
+
|
|
432
|
+
-- Define iterator that traverses all diagnostic entries in current buffer
|
|
433
|
+
local to_cursor_pos = function(pos) return { pos[1] + 1, pos[2] } end
|
|
434
|
+
local pos_field = vim.fn.has('nvim-0.11') == 1 and 'pos' or 'cursor_position'
|
|
435
|
+
local iterator = {}
|
|
436
|
+
|
|
437
|
+
iterator.next = function(position)
|
|
438
|
+
local next_opts = { [pos_field] = to_cursor_pos(position), severity = opts.severity, wrap = false }
|
|
439
|
+
local next = vim.diagnostic.get_next(next_opts)
|
|
440
|
+
if next == nil then return end
|
|
441
|
+
return { next.lnum, next.col }
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
iterator.prev = function(position)
|
|
445
|
+
local prev_opts = { [pos_field] = to_cursor_pos(position), severity = opts.severity, wrap = false }
|
|
446
|
+
local prev = vim.diagnostic.get_prev(prev_opts)
|
|
447
|
+
if prev == nil then return end
|
|
448
|
+
return { prev.lnum, prev.col }
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
-- - Define states with zero-based indexing as used in `vim.diagnostic`.
|
|
452
|
+
-- - Go outside of proper buffer position for `start_edge` and `end_edge` to
|
|
453
|
+
-- correctly spot diagnostic entry right and start and end of buffer.
|
|
454
|
+
local cursor_pos = vim.api.nvim_win_get_cursor(0)
|
|
455
|
+
iterator.state = { cursor_pos[1] - 1, cursor_pos[2] }
|
|
456
|
+
|
|
457
|
+
iterator.start_edge = { 0, -1 }
|
|
458
|
+
|
|
459
|
+
local last_line = vim.api.nvim_buf_line_count(0)
|
|
460
|
+
iterator.end_edge = { last_line - 1, vim.fn.col({ last_line, '$' }) - 1 }
|
|
461
|
+
|
|
462
|
+
-- Iterate
|
|
463
|
+
local res_pos = MiniBracketed.advance(iterator, direction, opts)
|
|
464
|
+
if res_pos == nil or res_pos == iterator.state then return end
|
|
465
|
+
|
|
466
|
+
-- Apply. Use built-in jump with offsetted cursor position to make it respect
|
|
467
|
+
-- `vim.diagnostic.config()`.
|
|
468
|
+
H.diagnostic_jump({ res_pos[1] + 1, res_pos[2] - 1 }, opts.float, opts.severity)
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
--- File on disk
|
|
472
|
+
---
|
|
473
|
+
--- Go to next/previous file on disk alphabetically. Files are taken from
|
|
474
|
+
--- directory of file in current buffer (or current working directory if buffer
|
|
475
|
+
--- doesn't contain a readable file). Only first-level files are used, i.e. it
|
|
476
|
+
--- doesn't go inside subdirectories.
|
|
477
|
+
---
|
|
478
|
+
--- Direction "forward" goes forward alphabetically, "backward" - backward.
|
|
479
|
+
---
|
|
480
|
+
---@param direction __bracketed_direction
|
|
481
|
+
---@param opts __bracketed_opts
|
|
482
|
+
MiniBracketed.file = function(direction, opts)
|
|
483
|
+
if H.is_disabled() then return end
|
|
484
|
+
|
|
485
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'file')
|
|
486
|
+
opts = vim.tbl_deep_extend('force', { n_times = vim.v.count1, wrap = true }, H.get_config().file.options, opts or {})
|
|
487
|
+
|
|
488
|
+
-- Get file data
|
|
489
|
+
local file_data = H.get_file_data()
|
|
490
|
+
if file_data == nil then return end
|
|
491
|
+
local file_basenames, directory = file_data.file_basenames, file_data.directory
|
|
492
|
+
|
|
493
|
+
-- Define iterator that traverses all found files
|
|
494
|
+
local iterator = {}
|
|
495
|
+
local n_files = #file_basenames
|
|
496
|
+
|
|
497
|
+
iterator.next = function(ind)
|
|
498
|
+
-- Allow advance in untrackable current buffer
|
|
499
|
+
if ind == nil then return 1 end
|
|
500
|
+
if n_files <= ind then return end
|
|
501
|
+
return ind + 1
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
iterator.prev = function(ind)
|
|
505
|
+
-- Allow advance in untrackable current buffer
|
|
506
|
+
if ind == nil then return n_files end
|
|
507
|
+
if ind <= 1 then return end
|
|
508
|
+
return ind - 1
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
-- - Find filename array index of current buffer
|
|
512
|
+
local cur_basename = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(0), ':t')
|
|
513
|
+
local cur_basename_ind
|
|
514
|
+
if cur_basename ~= '' then
|
|
515
|
+
for i, f in ipairs(file_basenames) do
|
|
516
|
+
if cur_basename == f then
|
|
517
|
+
cur_basename_ind = i
|
|
518
|
+
break
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
iterator.state = cur_basename_ind
|
|
524
|
+
iterator.start_edge = 0
|
|
525
|
+
iterator.end_edge = n_files + 1
|
|
526
|
+
|
|
527
|
+
-- Iterate
|
|
528
|
+
local res_ind = MiniBracketed.advance(iterator, direction, opts)
|
|
529
|
+
if res_ind == iterator.state then return end
|
|
530
|
+
|
|
531
|
+
-- Apply. Open target_path.
|
|
532
|
+
local path_sep = package.config:sub(1, 1)
|
|
533
|
+
local target_path = directory .. path_sep .. file_basenames[res_ind]
|
|
534
|
+
H.edit(target_path)
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
--- Indent change
|
|
538
|
+
---
|
|
539
|
+
--- Go to next/previous line with different indent (see |indent()|).
|
|
540
|
+
--- Can be used to go to lines with smaller, bigger, or different indent.
|
|
541
|
+
---
|
|
542
|
+
--- Notes:
|
|
543
|
+
--- - Directions "first" and "last" work differently from most other targets
|
|
544
|
+
--- for performance reasons. They are essentially "backward" and "forward"
|
|
545
|
+
--- with very big `n_times` option.
|
|
546
|
+
--- - For similar reasons, `wrap` is not supported.
|
|
547
|
+
--- - Blank line inherit indent from near non-blank line in direction of movement.
|
|
548
|
+
---
|
|
549
|
+
--- Direction "forward" increases line number, "backward" - decreases.
|
|
550
|
+
---
|
|
551
|
+
---@param direction __bracketed_direction
|
|
552
|
+
---@param opts table|nil Options. A table with fields:
|
|
553
|
+
--- - <n_times> `(number)` - Number of times to advance. Default: |v:count1|.
|
|
554
|
+
--- __bracketed_add_to_jumplist
|
|
555
|
+
--- - <change_type> `(string)` - which type of indent change to use.
|
|
556
|
+
--- One of "less" (default; smaller indent), "more" (bigger indent),
|
|
557
|
+
--- "diff" (different indent).
|
|
558
|
+
MiniBracketed.indent = function(direction, opts)
|
|
559
|
+
if H.is_disabled() then return end
|
|
560
|
+
|
|
561
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'indent')
|
|
562
|
+
opts = vim.tbl_deep_extend(
|
|
563
|
+
'force',
|
|
564
|
+
{ add_to_jumplist = false, change_type = 'less', n_times = vim.v.count1 },
|
|
565
|
+
H.get_config().indent.options,
|
|
566
|
+
opts or {}
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
opts.wrap = false
|
|
570
|
+
|
|
571
|
+
if direction == 'first' then
|
|
572
|
+
-- For some reason using `n_times = math.huge` leads to infinite loop
|
|
573
|
+
direction, opts.n_times = 'backward', vim.api.nvim_buf_line_count(0) + 1
|
|
574
|
+
end
|
|
575
|
+
if direction == 'last' then
|
|
576
|
+
direction, opts.n_times = 'forward', vim.api.nvim_buf_line_count(0) + 1
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
-- Compute loop data to traverse target commented lines in current buffer
|
|
580
|
+
local predicate = ({
|
|
581
|
+
less = function(new, cur) return new < cur or cur == 0 end,
|
|
582
|
+
more = function(new, cur) return new > cur end,
|
|
583
|
+
diff = function(new, cur) return new ~= cur end,
|
|
584
|
+
})[opts.change_type]
|
|
585
|
+
if predicate == nil then return end
|
|
586
|
+
|
|
587
|
+
-- Define iterator
|
|
588
|
+
local iterator = {}
|
|
589
|
+
|
|
590
|
+
iterator.next = function(cur_lnum)
|
|
591
|
+
-- Correctly process empty current line
|
|
592
|
+
cur_lnum = vim.fn.nextnonblank(cur_lnum)
|
|
593
|
+
local cur_indent = vim.fn.indent(cur_lnum)
|
|
594
|
+
|
|
595
|
+
local new_lnum, new_indent = cur_lnum, cur_indent
|
|
596
|
+
-- Check with `new_lnum > 0` because `nextnonblank()` returns -1 if line is
|
|
597
|
+
-- outside of line range
|
|
598
|
+
while new_lnum > 0 do
|
|
599
|
+
new_indent = vim.fn.indent(new_lnum)
|
|
600
|
+
if predicate(new_indent, cur_indent) then return new_lnum end
|
|
601
|
+
new_lnum = vim.fn.nextnonblank(new_lnum + 1)
|
|
602
|
+
end
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
iterator.prev = function(cur_lnum)
|
|
606
|
+
cur_lnum = vim.fn.prevnonblank(cur_lnum)
|
|
607
|
+
local cur_indent = vim.fn.indent(cur_lnum)
|
|
608
|
+
|
|
609
|
+
local new_lnum, new_indent = cur_lnum, cur_indent
|
|
610
|
+
while new_lnum > 0 do
|
|
611
|
+
new_indent = vim.fn.indent(new_lnum)
|
|
612
|
+
if predicate(new_indent, cur_indent) then return new_lnum end
|
|
613
|
+
new_lnum = vim.fn.prevnonblank(new_lnum - 1)
|
|
614
|
+
end
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
-- - Don't add first and last states as there is no wrapping around edges
|
|
618
|
+
iterator.state = vim.fn.line('.')
|
|
619
|
+
|
|
620
|
+
-- Iterate
|
|
621
|
+
local res_line_num = MiniBracketed.advance(iterator, direction, opts)
|
|
622
|
+
if res_line_num == nil or res_line_num == iterator.state then return end
|
|
623
|
+
|
|
624
|
+
-- Possibly add current position to jumplist
|
|
625
|
+
if opts.add_to_jumplist then H.add_to_jumplist() end
|
|
626
|
+
|
|
627
|
+
-- Apply. Open just enough folds and put cursor on first non-blank.
|
|
628
|
+
H.set_cursor(res_line_num, 0)
|
|
629
|
+
vim.cmd('normal! zv^')
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
--- Jump inside current buffer
|
|
633
|
+
---
|
|
634
|
+
--- Go to next/previous jump from |jumplist| which is inside current buffer.
|
|
635
|
+
---
|
|
636
|
+
--- Notes:
|
|
637
|
+
--- - There are no Visual mode mappings due to implementation problems.
|
|
638
|
+
---
|
|
639
|
+
--- Direction "forward" increases jump number, "backward" - decreases.
|
|
640
|
+
---
|
|
641
|
+
---@param direction __bracketed_direction
|
|
642
|
+
---@param opts __bracketed_opts
|
|
643
|
+
MiniBracketed.jump = function(direction, opts)
|
|
644
|
+
if H.is_disabled() then return end
|
|
645
|
+
|
|
646
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'jump')
|
|
647
|
+
opts = vim.tbl_deep_extend('force', { n_times = vim.v.count1, wrap = true }, H.get_config().jump.options, opts or {})
|
|
648
|
+
|
|
649
|
+
-- Define iterator that traverses all jumplist entries inside current buffer
|
|
650
|
+
local cur_buf_id = vim.api.nvim_get_current_buf()
|
|
651
|
+
local jump_list, cur_jump_num = unpack(vim.fn.getjumplist())
|
|
652
|
+
local n_list = #jump_list
|
|
653
|
+
if n_list == 0 then return end
|
|
654
|
+
-- - Correct for zero-based indexing
|
|
655
|
+
cur_jump_num = cur_jump_num + 1
|
|
656
|
+
|
|
657
|
+
local iterator = {}
|
|
658
|
+
|
|
659
|
+
local is_jump_num_from_current_buffer = function(jump_num)
|
|
660
|
+
local jump_entry = jump_list[jump_num]
|
|
661
|
+
if jump_entry == nil then return end
|
|
662
|
+
return jump_entry.bufnr == cur_buf_id
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
iterator.next = function(jump_num)
|
|
666
|
+
for num = jump_num + 1, n_list do
|
|
667
|
+
if is_jump_num_from_current_buffer(num) then return num end
|
|
668
|
+
end
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
iterator.prev = function(jump_num)
|
|
672
|
+
for num = jump_num - 1, 1, -1 do
|
|
673
|
+
if is_jump_num_from_current_buffer(num) then return num end
|
|
674
|
+
end
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
iterator.state = cur_jump_num
|
|
678
|
+
iterator.start_edge = 0
|
|
679
|
+
iterator.end_edge = n_list + 1
|
|
680
|
+
|
|
681
|
+
-- Iterate
|
|
682
|
+
local res_jump_num = MiniBracketed.advance(iterator, direction, opts)
|
|
683
|
+
if res_jump_num == nil or jump_list[res_jump_num] == nil then return end
|
|
684
|
+
|
|
685
|
+
-- Apply. Make jump. Allow jumping to current jump entry as it might be
|
|
686
|
+
-- different from current cursor position.
|
|
687
|
+
H.make_jump(jump_list, cur_jump_num, res_jump_num)
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
--- Location from location list
|
|
691
|
+
---
|
|
692
|
+
--- Go to next/previous location from |location-list|. This is similar to
|
|
693
|
+
--- |:lfirst|, |:lprevious|, |:lnext|, and |:llast| but with support of
|
|
694
|
+
--- wrapping around edges and |[count]| for "first"/"last" direction.
|
|
695
|
+
---
|
|
696
|
+
--- Direction "forward" increases location number, "backward" - decreases.
|
|
697
|
+
---
|
|
698
|
+
---@param direction __bracketed_direction
|
|
699
|
+
---@param opts __bracketed_opts
|
|
700
|
+
MiniBracketed.location = function(direction, opts)
|
|
701
|
+
if H.is_disabled() then return end
|
|
702
|
+
|
|
703
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'location')
|
|
704
|
+
opts =
|
|
705
|
+
vim.tbl_deep_extend('force', { n_times = vim.v.count1, wrap = true }, H.get_config().location.options, opts or {})
|
|
706
|
+
|
|
707
|
+
H.qf_loc_implementation('location', direction, opts)
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
--- Old files from previous and current sessions
|
|
711
|
+
---
|
|
712
|
+
--- Go to older/newer readable file either from previous session (see |v:oldfiles|)
|
|
713
|
+
--- or the current one (updated automatically after |MiniBracketed.setup()| call).
|
|
714
|
+
---
|
|
715
|
+
--- Direction "forward" goes to more recent files, "backward" - to older.
|
|
716
|
+
---
|
|
717
|
+
--- Notes:
|
|
718
|
+
--- - In current session it tracks only normal buffers (see |'buftype'|) for
|
|
719
|
+
--- some readable file.
|
|
720
|
+
--- - No new file is tracked when advancing this target. Only after buffer
|
|
721
|
+
--- change is done not through this target (like with |MiniBracketed.buffer()|),
|
|
722
|
+
--- it updates recency of last advanced and new buffers.
|
|
723
|
+
---
|
|
724
|
+
---@param direction __bracketed_direction
|
|
725
|
+
---@param opts __bracketed_opts
|
|
726
|
+
MiniBracketed.oldfile = function(direction, opts)
|
|
727
|
+
if H.is_disabled() then return end
|
|
728
|
+
|
|
729
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'oldfile')
|
|
730
|
+
opts =
|
|
731
|
+
vim.tbl_deep_extend('force', { n_times = vim.v.count1, wrap = true }, H.get_config().oldfile.options, opts or {})
|
|
732
|
+
|
|
733
|
+
-- Define iterator that traverses all old files
|
|
734
|
+
local cur_path = vim.api.nvim_buf_get_name(0)
|
|
735
|
+
|
|
736
|
+
H.oldfile_normalize()
|
|
737
|
+
local oldfile_arr = H.oldfile_get_array()
|
|
738
|
+
local n_oldfiles = #oldfile_arr
|
|
739
|
+
|
|
740
|
+
local iterator = {}
|
|
741
|
+
|
|
742
|
+
iterator.next = function(ind)
|
|
743
|
+
-- Allow advance in untrackable current buffer
|
|
744
|
+
if ind == nil then return 1 end
|
|
745
|
+
if n_oldfiles <= ind then return end
|
|
746
|
+
return ind + 1
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
iterator.prev = function(ind)
|
|
750
|
+
-- Allow advance in untrackable current buffer
|
|
751
|
+
if ind == nil then return n_oldfiles end
|
|
752
|
+
if ind <= 1 then return end
|
|
753
|
+
return ind - 1
|
|
754
|
+
end
|
|
755
|
+
|
|
756
|
+
iterator.state = H.cache.oldfile.recency[cur_path]
|
|
757
|
+
iterator.start_edge = 0
|
|
758
|
+
iterator.end_edge = n_oldfiles + 1
|
|
759
|
+
|
|
760
|
+
-- Iterate
|
|
761
|
+
local res_arr_ind = MiniBracketed.advance(iterator, direction, opts)
|
|
762
|
+
if res_arr_ind == nil or res_arr_ind == iterator.state then return end
|
|
763
|
+
|
|
764
|
+
-- Apply. Edit file at path while marking it not for tracking.
|
|
765
|
+
H.cache.oldfile.is_advancing = true
|
|
766
|
+
H.edit(oldfile_arr[res_arr_ind])
|
|
767
|
+
end
|
|
768
|
+
|
|
769
|
+
--- Quickfix from quickfix list
|
|
770
|
+
---
|
|
771
|
+
--- Go to next/previous entry from |quickfix| list. This is similar to
|
|
772
|
+
--- |:cfirst|, |:cprevious|, |:cnext|, and |:clast| but with support of
|
|
773
|
+
--- wrapping around edges and |[count]| for "first"/"last" direction.
|
|
774
|
+
---
|
|
775
|
+
--- Direction "forward" increases location number, "backward" - decreases.
|
|
776
|
+
---
|
|
777
|
+
---@param direction __bracketed_direction
|
|
778
|
+
---@param opts __bracketed_opts
|
|
779
|
+
MiniBracketed.quickfix = function(direction, opts)
|
|
780
|
+
if H.is_disabled() then return end
|
|
781
|
+
|
|
782
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'quickfix')
|
|
783
|
+
opts =
|
|
784
|
+
vim.tbl_deep_extend('force', { n_times = vim.v.count1, wrap = true }, H.get_config().quickfix.options, opts or {})
|
|
785
|
+
|
|
786
|
+
H.qf_loc_implementation('quickfix', direction, opts)
|
|
787
|
+
end
|
|
788
|
+
|
|
789
|
+
--- Tree-sitter node
|
|
790
|
+
---
|
|
791
|
+
--- Go to end/start of current tree-sitter node and its parents (except root).
|
|
792
|
+
---
|
|
793
|
+
--- Notes:
|
|
794
|
+
--- - Requires loaded tree-sitter parser in the current buffer.
|
|
795
|
+
--- - Directions "first" and "last" work differently from most other targets
|
|
796
|
+
--- for performance reasons. They are essentially "backward" and "forward"
|
|
797
|
+
--- with very big `n_times` option.
|
|
798
|
+
--- - For similar reasons, `wrap` is not supported.
|
|
799
|
+
---
|
|
800
|
+
--- Direction "forward" moves cursor forward to node's end, "backward" - backward
|
|
801
|
+
--- to node's start.
|
|
802
|
+
---
|
|
803
|
+
---@param direction __bracketed_direction
|
|
804
|
+
---@param opts table|nil Options. A table with fields:
|
|
805
|
+
--- - <n_times> `(number)` - Number of times to advance. Default: |v:count1|.
|
|
806
|
+
--- __bracketed_add_to_jumplist
|
|
807
|
+
MiniBracketed.treesitter = function(direction, opts)
|
|
808
|
+
if H.is_disabled() then return end
|
|
809
|
+
|
|
810
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'treesitter')
|
|
811
|
+
opts = vim.tbl_deep_extend(
|
|
812
|
+
'force',
|
|
813
|
+
{ add_to_jumplist = false, n_times = vim.v.count1 },
|
|
814
|
+
H.get_config().treesitter.options,
|
|
815
|
+
opts or {}
|
|
816
|
+
)
|
|
817
|
+
|
|
818
|
+
opts.wrap = false
|
|
819
|
+
|
|
820
|
+
if direction == 'first' then
|
|
821
|
+
direction, opts.n_times = 'backward', math.huge
|
|
822
|
+
end
|
|
823
|
+
if direction == 'last' then
|
|
824
|
+
direction, opts.n_times = 'forward', math.huge
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
-- Define iterator that traverses current node and its parents (except root)
|
|
828
|
+
local is_bad_node = function(node) return node == nil or node:parent() == nil end
|
|
829
|
+
local is_after = function(row_new, col_new, row_ref, col_ref)
|
|
830
|
+
return row_ref < row_new or (row_ref == row_new and col_ref < col_new)
|
|
831
|
+
end
|
|
832
|
+
local is_before = function(row_new, col_new, row_ref, col_ref) return is_after(row_ref, col_ref, row_new, col_new) end
|
|
833
|
+
|
|
834
|
+
local iterator = {}
|
|
835
|
+
|
|
836
|
+
-- Traverse node and parents until node's end is after current position
|
|
837
|
+
iterator.next = function(node_pos)
|
|
838
|
+
local node = node_pos.node
|
|
839
|
+
if is_bad_node(node) then return nil end
|
|
840
|
+
|
|
841
|
+
local init_row, init_col = node_pos.pos[1], node_pos.pos[2]
|
|
842
|
+
local cur_row, cur_col, cur_node = init_row, init_col, node
|
|
843
|
+
|
|
844
|
+
repeat
|
|
845
|
+
if is_bad_node(cur_node) then break end
|
|
846
|
+
|
|
847
|
+
cur_row, cur_col = cur_node:end_()
|
|
848
|
+
-- Correct for end-exclusiveness
|
|
849
|
+
cur_col = cur_col - 1
|
|
850
|
+
cur_node = cur_node:parent()
|
|
851
|
+
until is_after(cur_row, cur_col, init_row, init_col)
|
|
852
|
+
|
|
853
|
+
if not is_after(cur_row, cur_col, init_row, init_col) then return end
|
|
854
|
+
|
|
855
|
+
return { node = cur_node, pos = { cur_row, cur_col } }
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
-- Traverse node and parents until node's start is before current position
|
|
859
|
+
iterator.prev = function(node_pos)
|
|
860
|
+
local node = node_pos.node
|
|
861
|
+
if is_bad_node(node) then return nil end
|
|
862
|
+
|
|
863
|
+
local init_row, init_col = node_pos.pos[1], node_pos.pos[2]
|
|
864
|
+
local cur_row, cur_col, cur_node = init_row, init_col, node
|
|
865
|
+
|
|
866
|
+
repeat
|
|
867
|
+
if is_bad_node(cur_node) then break end
|
|
868
|
+
|
|
869
|
+
cur_row, cur_col = cur_node:start()
|
|
870
|
+
cur_node = cur_node:parent()
|
|
871
|
+
until is_before(cur_row, cur_col, init_row, init_col)
|
|
872
|
+
|
|
873
|
+
if not is_before(cur_row, cur_col, init_row, init_col) then return end
|
|
874
|
+
|
|
875
|
+
return { node = cur_node, pos = { cur_row, cur_col } }
|
|
876
|
+
end
|
|
877
|
+
|
|
878
|
+
local cur_pos = vim.api.nvim_win_get_cursor(0)
|
|
879
|
+
local ok, node = pcall(H.get_treesitter_node, cur_pos[1] - 1, cur_pos[2])
|
|
880
|
+
if not ok then
|
|
881
|
+
H.error(
|
|
882
|
+
'In `treesitter()` target can not find tree-sitter node under cursor.'
|
|
883
|
+
.. ' Do you have tree-sitter enabled in current buffer?'
|
|
884
|
+
)
|
|
885
|
+
end
|
|
886
|
+
iterator.state = { pos = { cur_pos[1] - 1, cur_pos[2] }, node = node }
|
|
887
|
+
|
|
888
|
+
-- Iterate
|
|
889
|
+
local res_node_pos = MiniBracketed.advance(iterator, direction, opts)
|
|
890
|
+
if res_node_pos == nil then return end
|
|
891
|
+
|
|
892
|
+
-- Possibly add current position to jumplist
|
|
893
|
+
if opts.add_to_jumplist then H.add_to_jumplist() end
|
|
894
|
+
|
|
895
|
+
-- Apply
|
|
896
|
+
H.set_cursor(res_node_pos.pos[1] + 1, res_node_pos.pos[2])
|
|
897
|
+
end
|
|
898
|
+
|
|
899
|
+
--- Undo along a tracked linear history
|
|
900
|
+
---
|
|
901
|
+
--- In a nutshell:
|
|
902
|
+
--- - Keys |u| and |CTRL-R| (although remapped) can be used as usual, but every
|
|
903
|
+
--- their execution new state is recorded in this module's linear undo history.
|
|
904
|
+
--- - Advancing this target goes along linear undo history revealing undo states
|
|
905
|
+
--- IN ORDER THEY ACTUALLY APPEARED.
|
|
906
|
+
--- - One big difference with built-in methods is that tracked linear history
|
|
907
|
+
--- can repeat undo states (not consecutively, though).
|
|
908
|
+
---
|
|
909
|
+
--- Neovim's default way of managing undo history is through branches (see
|
|
910
|
+
--- |undo-branches|). Basically it means that if you undo several changes and then
|
|
911
|
+
--- make new ones, it creates new undo branch while usually (see |'undolevels'|)
|
|
912
|
+
--- saving previous buffer states in another branch. While there are commands
|
|
913
|
+
--- to navigate by time of undo state creation (like |:earlier| and |:later|),
|
|
914
|
+
--- there is no intuitive way to cycle through them. Existing |g-| and |g+|
|
|
915
|
+
--- cycle through undo states BASED ON THEIR CREATION TIME, which often
|
|
916
|
+
--- gets confusing really guickly in extensively edited buffer.
|
|
917
|
+
---
|
|
918
|
+
--- This `undo()` target provides a way to cycle through linear undo history
|
|
919
|
+
--- IN ORDER STATES ACTUALLY APPEARED. It does so by registering any new undo
|
|
920
|
+
--- states plus every time |MiniBracketed.register_undo_state()| is called. To have
|
|
921
|
+
--- more "out of the box" experience, |u| and |CTRL-R| are remapped to call it after
|
|
922
|
+
--- they perform their undo/redo.
|
|
923
|
+
---
|
|
924
|
+
--- Example:
|
|
925
|
+
---
|
|
926
|
+
--- To show more clearly the difference between advancing this target and using
|
|
927
|
+
--- built-in functionality, here is an example:
|
|
928
|
+
---
|
|
929
|
+
--- - Create undo history in a new buffer (|:new|):
|
|
930
|
+
--- - Enter `one two three` text.
|
|
931
|
+
--- - Delete first word with `daw` and undo the change with `u`.
|
|
932
|
+
--- - Delete second word with `daw` and undo the change with `u`.
|
|
933
|
+
--- - Delete third word with `daw` and undo the change with `u`.
|
|
934
|
+
---
|
|
935
|
+
--- - Now try one of the following (each one after performing previous steps in
|
|
936
|
+
--- separate new buffer):
|
|
937
|
+
--- - Press `u`. It goes back to empty buffer. Press `<C-R>` twice and it
|
|
938
|
+
--- goes to the latest change (`one two`). No way to get to other states
|
|
939
|
+
--- (like `two three` or `one three`) with these two keys.
|
|
940
|
+
---
|
|
941
|
+
--- - Press `g-`. It goes to an empty buffer. Press `g+` 4 times. It cycles
|
|
942
|
+
--- through all available undo states IN ORDER THEY WERE CREATED.
|
|
943
|
+
---
|
|
944
|
+
--- - Finally, press `[u`. It goes back to `one two` - state which was
|
|
945
|
+
--- PREVIOUSLY VISITED by the user. Another `[u` restores `one two three`.
|
|
946
|
+
--- Use `]U` to go to latest visited undo state.
|
|
947
|
+
---
|
|
948
|
+
---@param direction __bracketed_direction
|
|
949
|
+
---@param opts __bracketed_opts
|
|
950
|
+
MiniBracketed.undo = function(direction, opts)
|
|
951
|
+
if H.is_disabled() then return end
|
|
952
|
+
|
|
953
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'undo')
|
|
954
|
+
opts = vim.tbl_deep_extend('force', { n_times = vim.v.count1, wrap = true }, H.get_config().undo.options, opts or {})
|
|
955
|
+
|
|
956
|
+
-- Define iterator that traverses undo states in order they appeared
|
|
957
|
+
local buf_id = vim.api.nvim_get_current_buf()
|
|
958
|
+
H.undo_sync(buf_id, vim.fn.undotree())
|
|
959
|
+
|
|
960
|
+
local iterator = {}
|
|
961
|
+
local buf_history = H.cache.undo[buf_id]
|
|
962
|
+
local n = #buf_history
|
|
963
|
+
|
|
964
|
+
iterator.next = function(id)
|
|
965
|
+
if id == nil or n <= id then return end
|
|
966
|
+
return id + 1
|
|
967
|
+
end
|
|
968
|
+
|
|
969
|
+
iterator.prev = function(id)
|
|
970
|
+
if id == nil or id <= 1 then return end
|
|
971
|
+
return id - 1
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
iterator.state = buf_history.current_id
|
|
975
|
+
iterator.start_edge = 0
|
|
976
|
+
iterator.end_edge = n + 1
|
|
977
|
+
|
|
978
|
+
-- Iterate
|
|
979
|
+
local res_id = MiniBracketed.advance(iterator, direction, opts)
|
|
980
|
+
if res_id == nil or res_id == iterator.state then return end
|
|
981
|
+
|
|
982
|
+
-- Apply. Move to undo state by number while recording current history id
|
|
983
|
+
buf_history.is_advancing = true
|
|
984
|
+
vim.cmd('undo ' .. buf_history[res_id])
|
|
985
|
+
|
|
986
|
+
buf_history.current_id = res_id
|
|
987
|
+
end
|
|
988
|
+
|
|
989
|
+
--- Register state for undo target
|
|
990
|
+
---
|
|
991
|
+
--- Use this function to add current undo state to this module's linear undo
|
|
992
|
+
--- history. It is used in |MiniBracketed.setup()| to remap |u| and |CTRL-R| keys
|
|
993
|
+
--- to add their new state to linear undo history.
|
|
994
|
+
MiniBracketed.register_undo_state = function()
|
|
995
|
+
local buf_id = vim.api.nvim_get_current_buf()
|
|
996
|
+
local tree = vim.fn.undotree()
|
|
997
|
+
|
|
998
|
+
-- Synchronize undo history and stop advancing
|
|
999
|
+
H.undo_sync(buf_id, tree, false)
|
|
1000
|
+
|
|
1001
|
+
-- Append new undo state to linear history
|
|
1002
|
+
local buf_history = H.cache.undo[buf_id]
|
|
1003
|
+
H.undo_append_state(buf_history, tree.seq_cur)
|
|
1004
|
+
buf_history.current_id = #buf_history
|
|
1005
|
+
end
|
|
1006
|
+
|
|
1007
|
+
--- Normal window
|
|
1008
|
+
---
|
|
1009
|
+
--- Go to next/previous normal window. Order by their number (see |winnr()|).
|
|
1010
|
+
---
|
|
1011
|
+
--- Direction "forward" increases window number, "backward" - decreases.
|
|
1012
|
+
---
|
|
1013
|
+
--- Only normal (non-floating) windows are used.
|
|
1014
|
+
---
|
|
1015
|
+
---@param direction __bracketed_direction
|
|
1016
|
+
---@param opts __bracketed_opts
|
|
1017
|
+
MiniBracketed.window = function(direction, opts)
|
|
1018
|
+
if H.is_disabled() then return end
|
|
1019
|
+
|
|
1020
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'window')
|
|
1021
|
+
opts =
|
|
1022
|
+
vim.tbl_deep_extend('force', { n_times = vim.v.count1, wrap = true }, H.get_config().window.options, opts or {})
|
|
1023
|
+
|
|
1024
|
+
-- Define iterator that traverses all normal windows in "natural" order
|
|
1025
|
+
local is_normal = function(win_nr)
|
|
1026
|
+
local win_id = vim.fn.win_getid(win_nr)
|
|
1027
|
+
return vim.api.nvim_win_get_config(win_id).relative == ''
|
|
1028
|
+
end
|
|
1029
|
+
|
|
1030
|
+
local iterator = {}
|
|
1031
|
+
|
|
1032
|
+
iterator.next = function(win_nr)
|
|
1033
|
+
for nr = win_nr + 1, vim.fn.winnr('$') do
|
|
1034
|
+
if is_normal(nr) then return nr end
|
|
1035
|
+
end
|
|
1036
|
+
end
|
|
1037
|
+
|
|
1038
|
+
iterator.prev = function(win_nr)
|
|
1039
|
+
for nr = win_nr - 1, 1, -1 do
|
|
1040
|
+
if is_normal(nr) then return nr end
|
|
1041
|
+
end
|
|
1042
|
+
end
|
|
1043
|
+
|
|
1044
|
+
iterator.state = vim.fn.winnr()
|
|
1045
|
+
iterator.start_edge = 0
|
|
1046
|
+
iterator.end_edge = vim.fn.winnr('$') + 1
|
|
1047
|
+
|
|
1048
|
+
-- Iterate
|
|
1049
|
+
local res_win_nr = MiniBracketed.advance(iterator, direction, opts)
|
|
1050
|
+
if res_win_nr == iterator.state then return end
|
|
1051
|
+
|
|
1052
|
+
-- Apply
|
|
1053
|
+
vim.api.nvim_set_current_win(vim.fn.win_getid(res_win_nr))
|
|
1054
|
+
end
|
|
1055
|
+
|
|
1056
|
+
--- Replace "latest put region" with yank history entry
|
|
1057
|
+
---
|
|
1058
|
+
--- After |MiniBracketed.setup()| is called, on every yank/delete/change operation
|
|
1059
|
+
--- (technically, every trigger of |TextYankPost| event) the object of operation
|
|
1060
|
+
--- is added to yank history. Advancing this target will replace the region of
|
|
1061
|
+
--- latest put operation with entry from yank history.
|
|
1062
|
+
---
|
|
1063
|
+
--- By default works best if called RIGHT AFTER text paste (like with |p| or |P|).
|
|
1064
|
+
---
|
|
1065
|
+
--- To better detect "latest put region", use |MiniBracketed.register_put_region()|
|
|
1066
|
+
--- as described later.
|
|
1067
|
+
---
|
|
1068
|
+
--- Direction "forward" goes to newer yank history entry, "backward" - to older.
|
|
1069
|
+
---
|
|
1070
|
+
--- Example:
|
|
1071
|
+
---
|
|
1072
|
+
--- - Type `one two three`.
|
|
1073
|
+
--- - Yank each word with `yiw`.
|
|
1074
|
+
--- - Create new line and press `p`. This should paste `three`.
|
|
1075
|
+
--- - Type `[y`. This should replace latest `three` with `two`.
|
|
1076
|
+
---
|
|
1077
|
+
--- # Latest put region ~
|
|
1078
|
+
---
|
|
1079
|
+
--- "Latest put region" is (in order of decreasing priority):
|
|
1080
|
+
--- - The one from latest advance of this target.
|
|
1081
|
+
--- - The one registered by user with |MiniBracketed.register_put_region()|.
|
|
1082
|
+
--- - The one taken from |'[| and |']| marks.
|
|
1083
|
+
---
|
|
1084
|
+
--- For users there are these approaches to manage which region will be used:
|
|
1085
|
+
--- - Do nothing. In this case region between `[` / `]` marks will always be used
|
|
1086
|
+
--- for first `yank` advance.
|
|
1087
|
+
--- Although doable, this has several drawbacks: it will use latest yanked or
|
|
1088
|
+
--- changed region or the entire buffer if marks are not set.
|
|
1089
|
+
--- If remember to advance this target only after recent put operation, this
|
|
1090
|
+
--- should work as expected.
|
|
1091
|
+
---
|
|
1092
|
+
--- - Remap common put operations to use |MiniBracketed.register_put_region()|.
|
|
1093
|
+
--- After that, only regions from mapped put operations will be used for first
|
|
1094
|
+
--- advance. Example of custom mappings (note use of |:map-expression|): >lua
|
|
1095
|
+
---
|
|
1096
|
+
--- local put_keys = { 'p', 'P' }
|
|
1097
|
+
--- for _, lhs in ipairs(put_keys) do
|
|
1098
|
+
--- local rhs = 'v:lua.MiniBracketed.register_put_region("' .. lhs .. '")'
|
|
1099
|
+
--- vim.keymap.set({ 'n', 'x' }, lhs, rhs, { expr = true })
|
|
1100
|
+
--- end
|
|
1101
|
+
--- <
|
|
1102
|
+
---@param direction __bracketed_direction
|
|
1103
|
+
---@param opts __bracketed_opts
|
|
1104
|
+
--- - <operators> `(table)` - array of operator names ("c", "d", or "y") for
|
|
1105
|
+
--- which yank entry should be used to advance. For example, use `{ "y" }`
|
|
1106
|
+
--- to advance only by entries actually resulted from yank operation with |y|.
|
|
1107
|
+
--- Default: `{ 'c', 'd', 'y' }`.
|
|
1108
|
+
MiniBracketed.yank = function(direction, opts)
|
|
1109
|
+
if H.is_disabled() then return end
|
|
1110
|
+
|
|
1111
|
+
H.validate_direction(direction, { 'first', 'backward', 'forward', 'last' }, 'yank')
|
|
1112
|
+
-- NOTE: Don't use `tbl_deep_extend` to prefer full input `operators` array
|
|
1113
|
+
local default_opts = { n_times = vim.v.count1, operators = { 'c', 'd', 'y' }, wrap = true }
|
|
1114
|
+
opts = vim.tbl_extend('force', default_opts, H.get_config().yank.options, opts or {})
|
|
1115
|
+
|
|
1116
|
+
-- Update yank history data
|
|
1117
|
+
local cache_yank, history = H.cache.yank, H.cache.yank.history
|
|
1118
|
+
local n_history = #history
|
|
1119
|
+
local cur_state = H.get_yank_state()
|
|
1120
|
+
if not vim.deep_equal(cur_state, cache_yank.state) then H.yank_stop_advancing() end
|
|
1121
|
+
|
|
1122
|
+
-- Define iterator that traverses yank history for entry with proper operator
|
|
1123
|
+
local iterator = {}
|
|
1124
|
+
|
|
1125
|
+
iterator.next = function(id)
|
|
1126
|
+
for i = id + 1, n_history do
|
|
1127
|
+
if vim.tbl_contains(opts.operators, history[i].operator) then return i end
|
|
1128
|
+
end
|
|
1129
|
+
end
|
|
1130
|
+
|
|
1131
|
+
iterator.prev = function(id)
|
|
1132
|
+
for i = id - 1, 1, -1 do
|
|
1133
|
+
if vim.tbl_contains(opts.operators, history[i].operator) then return i end
|
|
1134
|
+
end
|
|
1135
|
+
end
|
|
1136
|
+
|
|
1137
|
+
iterator.state = cache_yank.current_id
|
|
1138
|
+
iterator.start_edge = 0
|
|
1139
|
+
iterator.end_edge = n_history + 1
|
|
1140
|
+
|
|
1141
|
+
-- Iterate
|
|
1142
|
+
local res_id = MiniBracketed.advance(iterator, direction, opts)
|
|
1143
|
+
if res_id == nil then return end
|
|
1144
|
+
|
|
1145
|
+
-- Apply. Replace latest put region with yank history entry
|
|
1146
|
+
-- - Account for possible errors when latest region became out of bounds
|
|
1147
|
+
local ok, _ = pcall(H.replace_latest_put_region, cache_yank.history[res_id])
|
|
1148
|
+
if not ok then return end
|
|
1149
|
+
|
|
1150
|
+
cache_yank.current_id = res_id
|
|
1151
|
+
cache_yank.is_advancing = true
|
|
1152
|
+
cache_yank.state = H.get_yank_state()
|
|
1153
|
+
end
|
|
1154
|
+
|
|
1155
|
+
--- Register "latest put region"
|
|
1156
|
+
---
|
|
1157
|
+
--- This function should be called after put register becomes relevant
|
|
1158
|
+
--- (|v:register| is appropriately set) but before put operation takes place
|
|
1159
|
+
--- (|'[| and |']| marks become relevant).
|
|
1160
|
+
---
|
|
1161
|
+
--- Designed to be used in a user-facing expression mapping (see |:map-expression|).
|
|
1162
|
+
--- For mapping examples see |MiniBracketed.yank()|.
|
|
1163
|
+
---
|
|
1164
|
+
---@param put_key string Put keys to be remapped.
|
|
1165
|
+
---
|
|
1166
|
+
---@return string Returns `put_key` for a better usage inside expression mappings.
|
|
1167
|
+
MiniBracketed.register_put_region = function(put_key)
|
|
1168
|
+
local buf_id = vim.api.nvim_get_current_buf()
|
|
1169
|
+
|
|
1170
|
+
-- Compute mode of register **before** putting (while it is still relevant)
|
|
1171
|
+
local mode = H.get_register_mode(vim.v.register)
|
|
1172
|
+
|
|
1173
|
+
-- Register latest put region **after** it is done (when it becomes relevant)
|
|
1174
|
+
vim.schedule(function() H.cache.yank.user_put_regions[buf_id] = H.get_latest_region(mode) end)
|
|
1175
|
+
|
|
1176
|
+
return put_key
|
|
1177
|
+
end
|
|
1178
|
+
|
|
1179
|
+
--- Advance iterator
|
|
1180
|
+
---
|
|
1181
|
+
--- This is the main function which performs any forward/backward/first/last
|
|
1182
|
+
--- advance in this module. Its basic idea is to take iterator (object containing
|
|
1183
|
+
--- information about current state and how to go to next/previous one) and go
|
|
1184
|
+
--- in certain direction until needed/allowed.
|
|
1185
|
+
---
|
|
1186
|
+
--- Notes:
|
|
1187
|
+
--- - Directions "first" and "last" are convenience wrappers for "forward" and
|
|
1188
|
+
--- "backward" with pre-setting initial state to `start_edge` and `end_edge`.
|
|
1189
|
+
--- - Iterators `next()` and `prev()` methods should be able to handle `nil` as input.
|
|
1190
|
+
--- - This function only returns new state and doesn't modify `iterator.state`.
|
|
1191
|
+
---
|
|
1192
|
+
---@param iterator table Table:
|
|
1193
|
+
--- - Methods:
|
|
1194
|
+
--- - <next> - given state, return state in forward direction (no wrap).
|
|
1195
|
+
--- - <prev> - given state, return state in backward direction (no wrap).
|
|
1196
|
+
--- - Fields:
|
|
1197
|
+
--- - <state> - object describing current state.
|
|
1198
|
+
--- - <start_edge> (optional) - object with `forward(start_edge)` describing
|
|
1199
|
+
--- first state. If `nil`, can't wrap forward or use direction "first".
|
|
1200
|
+
--- - <end_edge> (optional) - object with `backward(end_edge)` describing
|
|
1201
|
+
--- last state. If `nil`, can't wrap backward or use direction "last".
|
|
1202
|
+
---@param direction string Direction. One of "first", "backward", "forward", "last".
|
|
1203
|
+
---@param opts table|nil Options with the following keys:
|
|
1204
|
+
--- - <n_times> `(number)` - number of times to go in input direction.
|
|
1205
|
+
--- Default: `v:count1`.
|
|
1206
|
+
--- - <wrap> `(boolean)` - whether to wrap around edges when `next()` or
|
|
1207
|
+
--- `prev()` return `nil`. Default: `true`.
|
|
1208
|
+
---
|
|
1209
|
+
---@return any Result state. If `nil`, could not reach any valid result state.
|
|
1210
|
+
MiniBracketed.advance = function(iterator, direction, opts)
|
|
1211
|
+
opts = vim.tbl_deep_extend('force', { n_times = vim.v.count1, wrap = true }, opts or {})
|
|
1212
|
+
|
|
1213
|
+
-- Use two states: "result" will be used as result, "current" will be used
|
|
1214
|
+
-- for iteration. Separation is needed at least for two reasons:
|
|
1215
|
+
-- - Allow partial reach of `n_times`.
|
|
1216
|
+
-- - Don't allow `start_edge` and `end_edge` be the output.
|
|
1217
|
+
local res_state = iterator.state
|
|
1218
|
+
|
|
1219
|
+
-- Compute loop data
|
|
1220
|
+
local iter_method = 'next'
|
|
1221
|
+
local cur_state = res_state
|
|
1222
|
+
|
|
1223
|
+
if direction == 'backward' then iter_method = 'prev' end
|
|
1224
|
+
|
|
1225
|
+
if direction == 'first' then
|
|
1226
|
+
cur_state, iter_method = iterator.start_edge, 'next'
|
|
1227
|
+
end
|
|
1228
|
+
|
|
1229
|
+
if direction == 'last' then
|
|
1230
|
+
cur_state, iter_method = iterator.end_edge, 'prev'
|
|
1231
|
+
end
|
|
1232
|
+
|
|
1233
|
+
-- Loop
|
|
1234
|
+
local iter = iterator[iter_method]
|
|
1235
|
+
for _ = 1, opts.n_times do
|
|
1236
|
+
-- Advance
|
|
1237
|
+
cur_state = iter(cur_state)
|
|
1238
|
+
|
|
1239
|
+
if cur_state == nil then
|
|
1240
|
+
-- Stop if can't wrap around edges
|
|
1241
|
+
if not opts.wrap then break end
|
|
1242
|
+
|
|
1243
|
+
-- Wrap around edge
|
|
1244
|
+
local edge = iterator.start_edge
|
|
1245
|
+
if iter_method == 'prev' then edge = iterator.end_edge end
|
|
1246
|
+
if edge == nil then break end
|
|
1247
|
+
|
|
1248
|
+
cur_state = iter(edge)
|
|
1249
|
+
|
|
1250
|
+
-- Ensure non-nil new state (can happen when there are no targets)
|
|
1251
|
+
if cur_state == nil then break end
|
|
1252
|
+
end
|
|
1253
|
+
|
|
1254
|
+
-- Allow only partial reach of `n_times`
|
|
1255
|
+
res_state = cur_state
|
|
1256
|
+
end
|
|
1257
|
+
|
|
1258
|
+
return res_state
|
|
1259
|
+
end
|
|
1260
|
+
|
|
1261
|
+
-- Helper data ================================================================
|
|
1262
|
+
-- Module default config
|
|
1263
|
+
H.default_config = vim.deepcopy(MiniBracketed.config)
|
|
1264
|
+
|
|
1265
|
+
H.cache = {
|
|
1266
|
+
-- Tracking of old files for `oldfile()` (this data structure is designed to be
|
|
1267
|
+
-- fast to add new file; initially `nil` to postpone initialization from
|
|
1268
|
+
-- `v:oldfiles` up until it is actually needed):
|
|
1269
|
+
-- - `recency` is a table with file paths as fields and numerical values
|
|
1270
|
+
-- indicating how recent file was accessed (higher - more recent).
|
|
1271
|
+
-- - `max_recency` is a maximum currently used `recency`. Used to add new file.
|
|
1272
|
+
-- - `is_advancing` is an indicator that buffer change was done inside
|
|
1273
|
+
-- `oldfile()` function. It is a key to enabling moving along old files
|
|
1274
|
+
-- (and not just going back and forth between two files because they swap
|
|
1275
|
+
-- places as two most recent files).
|
|
1276
|
+
-- - `last_advanced_bufname` - name of last advanced buffer. Used to update
|
|
1277
|
+
-- recency of only the last buffer entered during advancing.
|
|
1278
|
+
oldfile = nil,
|
|
1279
|
+
|
|
1280
|
+
-- Per buffer history of visited undo states. A table for each buffer id:
|
|
1281
|
+
-- - Numerical fields indicate actual history of visited undo states (from
|
|
1282
|
+
-- oldest to latest).
|
|
1283
|
+
-- - <current_id> - identifier of current history entry (used for iteration).
|
|
1284
|
+
-- - <seq_last> - latest recorded state (`seq_last` from `undotree()`).
|
|
1285
|
+
-- - <is_advancing> - whether currently advancing. Used to allow consecutive
|
|
1286
|
+
-- advances along tracked undo history.
|
|
1287
|
+
undo = {},
|
|
1288
|
+
|
|
1289
|
+
-- Cache for `yank` targets
|
|
1290
|
+
yank = {
|
|
1291
|
+
-- Per-buffer region of latest advance. Used to correctly determine range
|
|
1292
|
+
-- and mode of latest advanced region.
|
|
1293
|
+
advance_put_regions = {},
|
|
1294
|
+
-- Current id of yank entry in yank history
|
|
1295
|
+
current_id = 0,
|
|
1296
|
+
-- Yank history. Each element contains data necessary to replace latest put
|
|
1297
|
+
-- region with yanked one. See `track_yank()`.
|
|
1298
|
+
history = {},
|
|
1299
|
+
-- Whether currently advancing
|
|
1300
|
+
is_advancing = false,
|
|
1301
|
+
-- State of latest yank advancement to determine of currently advancing
|
|
1302
|
+
state = {},
|
|
1303
|
+
-- Per-buffer region registered by user as "latest put region". Used to
|
|
1304
|
+
-- overcome limitations of automatic detection of latest put region (like
|
|
1305
|
+
-- not reliable mode detection when pasting from register; respecting not
|
|
1306
|
+
-- only regions of put operations, but also yank and change).
|
|
1307
|
+
user_put_regions = {},
|
|
1308
|
+
},
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
-- Helper functionality =======================================================
|
|
1312
|
+
-- Settings -------------------------------------------------------------------
|
|
1313
|
+
H.setup_config = function(config)
|
|
1314
|
+
H.check_type('config', config, 'table', true)
|
|
1315
|
+
config = vim.tbl_deep_extend('force', vim.deepcopy(H.default_config), config or {})
|
|
1316
|
+
|
|
1317
|
+
H.check_type('buffer', config.buffer, 'table')
|
|
1318
|
+
H.check_type('buffer.suffix', config.buffer.suffix, 'string')
|
|
1319
|
+
H.check_type('buffer.options', config.buffer.options, 'table')
|
|
1320
|
+
|
|
1321
|
+
H.check_type('comment', config.comment, 'table')
|
|
1322
|
+
H.check_type('comment.suffix', config.comment.suffix, 'string')
|
|
1323
|
+
H.check_type('comment.options', config.comment.options, 'table')
|
|
1324
|
+
|
|
1325
|
+
H.check_type('conflict', config.conflict, 'table')
|
|
1326
|
+
H.check_type('conflict.suffix', config.conflict.suffix, 'string')
|
|
1327
|
+
H.check_type('conflict.options', config.conflict.options, 'table')
|
|
1328
|
+
|
|
1329
|
+
H.check_type('diagnostic', config.diagnostic, 'table')
|
|
1330
|
+
H.check_type('diagnostic.suffix', config.diagnostic.suffix, 'string')
|
|
1331
|
+
H.check_type('diagnostic.options', config.diagnostic.options, 'table')
|
|
1332
|
+
|
|
1333
|
+
H.check_type('file', config.file, 'table')
|
|
1334
|
+
H.check_type('file.suffix', config.file.suffix, 'string')
|
|
1335
|
+
H.check_type('file.options', config.file.options, 'table')
|
|
1336
|
+
|
|
1337
|
+
H.check_type('indent', config.indent, 'table')
|
|
1338
|
+
H.check_type('indent.suffix', config.indent.suffix, 'string')
|
|
1339
|
+
H.check_type('indent.options', config.indent.options, 'table')
|
|
1340
|
+
|
|
1341
|
+
H.check_type('jump', config.jump, 'table')
|
|
1342
|
+
H.check_type('jump.suffix', config.jump.suffix, 'string')
|
|
1343
|
+
H.check_type('jump.options', config.jump.options, 'table')
|
|
1344
|
+
|
|
1345
|
+
H.check_type('location', config.location, 'table')
|
|
1346
|
+
H.check_type('location.suffix', config.location.suffix, 'string')
|
|
1347
|
+
H.check_type('location.options', config.location.options, 'table')
|
|
1348
|
+
|
|
1349
|
+
H.check_type('oldfile', config.oldfile, 'table')
|
|
1350
|
+
H.check_type('oldfile.suffix', config.oldfile.suffix, 'string')
|
|
1351
|
+
H.check_type('oldfile.options', config.oldfile.options, 'table')
|
|
1352
|
+
|
|
1353
|
+
H.check_type('quickfix', config.quickfix, 'table')
|
|
1354
|
+
H.check_type('quickfix.suffix', config.quickfix.suffix, 'string')
|
|
1355
|
+
H.check_type('quickfix.options', config.quickfix.options, 'table')
|
|
1356
|
+
|
|
1357
|
+
H.check_type('treesitter', config.treesitter, 'table')
|
|
1358
|
+
H.check_type('treesitter.suffix', config.treesitter.suffix, 'string')
|
|
1359
|
+
H.check_type('treesitter.options', config.treesitter.options, 'table')
|
|
1360
|
+
|
|
1361
|
+
H.check_type('undo', config.undo, 'table')
|
|
1362
|
+
H.check_type('undo.suffix', config.undo.suffix, 'string')
|
|
1363
|
+
H.check_type('undo.options', config.undo.options, 'table')
|
|
1364
|
+
|
|
1365
|
+
H.check_type('window', config.window, 'table')
|
|
1366
|
+
H.check_type('window.suffix', config.window.suffix, 'string')
|
|
1367
|
+
H.check_type('window.options', config.window.options, 'table')
|
|
1368
|
+
|
|
1369
|
+
H.check_type('yank', config.yank, 'table')
|
|
1370
|
+
H.check_type('yank.suffix', config.yank.suffix, 'string')
|
|
1371
|
+
H.check_type('yank.options', config.yank.options, 'table')
|
|
1372
|
+
|
|
1373
|
+
return config
|
|
1374
|
+
end
|
|
1375
|
+
|
|
1376
|
+
--stylua: ignore
|
|
1377
|
+
H.apply_config = function(config)
|
|
1378
|
+
MiniBracketed.config = config
|
|
1379
|
+
|
|
1380
|
+
-- Make mappings. NOTE: make 'forward'/'backward' *after* 'first'/'last' to
|
|
1381
|
+
-- allow non-letter suffixes define 'forward'/'backward'.
|
|
1382
|
+
if config.buffer.suffix ~= '' then
|
|
1383
|
+
local low, up = H.get_suffix_variants(config.buffer.suffix)
|
|
1384
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.buffer('first')<CR>", { desc = 'Buffer first' })
|
|
1385
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.buffer('last')<CR>", { desc = 'Buffer last' })
|
|
1386
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.buffer('backward')<CR>", { desc = 'Buffer backward' })
|
|
1387
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.buffer('forward')<CR>", { desc = 'Buffer forward' })
|
|
1388
|
+
end
|
|
1389
|
+
|
|
1390
|
+
if config.comment.suffix ~= '' then
|
|
1391
|
+
local low, up = H.get_suffix_variants(config.comment.suffix)
|
|
1392
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.comment('first')<CR>", { desc = 'Comment first' })
|
|
1393
|
+
H.map('x', '[' .. up, "<Cmd>lua MiniBracketed.comment('first')<CR>", { desc = 'Comment first' })
|
|
1394
|
+
H.map('o', '[' .. up, "V<Cmd>lua MiniBracketed.comment('first')<CR>", { desc = 'Comment first' })
|
|
1395
|
+
|
|
1396
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.comment('last')<CR>", { desc = 'Comment last' })
|
|
1397
|
+
H.map('x', ']' .. up, "<Cmd>lua MiniBracketed.comment('last')<CR>", { desc = 'Comment last' })
|
|
1398
|
+
H.map('o', ']' .. up, "V<Cmd>lua MiniBracketed.comment('last')<CR>", { desc = 'Comment last' })
|
|
1399
|
+
|
|
1400
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.comment('backward')<CR>", { desc = 'Comment backward' })
|
|
1401
|
+
H.map('x', '[' .. low, "<Cmd>lua MiniBracketed.comment('backward')<CR>", { desc = 'Comment backward' })
|
|
1402
|
+
H.map('o', '[' .. low, "V<Cmd>lua MiniBracketed.comment('backward')<CR>", { desc = 'Comment backward' })
|
|
1403
|
+
|
|
1404
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.comment('forward')<CR>", { desc = 'Comment forward' })
|
|
1405
|
+
H.map('x', ']' .. low, "<Cmd>lua MiniBracketed.comment('forward')<CR>", { desc = 'Comment forward' })
|
|
1406
|
+
H.map('o', ']' .. low, "V<Cmd>lua MiniBracketed.comment('forward')<CR>", { desc = 'Comment forward' })
|
|
1407
|
+
end
|
|
1408
|
+
|
|
1409
|
+
if config.conflict.suffix ~= '' then
|
|
1410
|
+
local low, up = H.get_suffix_variants(config.conflict.suffix)
|
|
1411
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.conflict('first')<CR>", { desc = 'Conflict first' })
|
|
1412
|
+
H.map('x', '[' .. up, "<Cmd>lua MiniBracketed.conflict('first')<CR>", { desc = 'Conflict first' })
|
|
1413
|
+
H.map('o', '[' .. up, "V<Cmd>lua MiniBracketed.conflict('first')<CR>", { desc = 'Conflict first' })
|
|
1414
|
+
|
|
1415
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.conflict('last')<CR>", { desc = 'Conflict last' })
|
|
1416
|
+
H.map('x', ']' .. up, "<Cmd>lua MiniBracketed.conflict('last')<CR>", { desc = 'Conflict last' })
|
|
1417
|
+
H.map('o', ']' .. up, "V<Cmd>lua MiniBracketed.conflict('last')<CR>", { desc = 'Conflict last' })
|
|
1418
|
+
|
|
1419
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.conflict('backward')<CR>", { desc = 'Conflict backward' })
|
|
1420
|
+
H.map('x', '[' .. low, "<Cmd>lua MiniBracketed.conflict('backward')<CR>", { desc = 'Conflict backward' })
|
|
1421
|
+
H.map('o', '[' .. low, "V<Cmd>lua MiniBracketed.conflict('backward')<CR>", { desc = 'Conflict backward' })
|
|
1422
|
+
|
|
1423
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.conflict('forward')<CR>", { desc = 'Conflict forward' })
|
|
1424
|
+
H.map('x', ']' .. low, "<Cmd>lua MiniBracketed.conflict('forward')<CR>", { desc = 'Conflict forward' })
|
|
1425
|
+
H.map('o', ']' .. low, "V<Cmd>lua MiniBracketed.conflict('forward')<CR>", { desc = 'Conflict forward' })
|
|
1426
|
+
end
|
|
1427
|
+
|
|
1428
|
+
if config.diagnostic.suffix ~= '' then
|
|
1429
|
+
local low, up = H.get_suffix_variants(config.diagnostic.suffix)
|
|
1430
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.diagnostic('first')<CR>", { desc = 'Diagnostic first' })
|
|
1431
|
+
H.map('x', '[' .. up, "<Cmd>lua MiniBracketed.diagnostic('first')<CR>", { desc = 'Diagnostic first' })
|
|
1432
|
+
H.map('o', '[' .. up, "v<Cmd>lua MiniBracketed.diagnostic('first')<CR>", { desc = 'Diagnostic first' })
|
|
1433
|
+
|
|
1434
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.diagnostic('last')<CR>", { desc = 'Diagnostic last' })
|
|
1435
|
+
H.map('x', ']' .. up, "<Cmd>lua MiniBracketed.diagnostic('last')<CR>", { desc = 'Diagnostic last' })
|
|
1436
|
+
H.map('o', ']' .. up, "v<Cmd>lua MiniBracketed.diagnostic('last')<CR>", { desc = 'Diagnostic last' })
|
|
1437
|
+
|
|
1438
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.diagnostic('backward')<CR>", { desc = 'Diagnostic backward' })
|
|
1439
|
+
H.map('x', '[' .. low, "<Cmd>lua MiniBracketed.diagnostic('backward')<CR>", { desc = 'Diagnostic backward' })
|
|
1440
|
+
H.map('o', '[' .. low, "v<Cmd>lua MiniBracketed.diagnostic('backward')<CR>", { desc = 'Diagnostic backward' })
|
|
1441
|
+
|
|
1442
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.diagnostic('forward')<CR>", { desc = 'Diagnostic forward' })
|
|
1443
|
+
H.map('x', ']' .. low, "<Cmd>lua MiniBracketed.diagnostic('forward')<CR>", { desc = 'Diagnostic forward' })
|
|
1444
|
+
H.map('o', ']' .. low, "v<Cmd>lua MiniBracketed.diagnostic('forward')<CR>", { desc = 'Diagnostic forward' })
|
|
1445
|
+
end
|
|
1446
|
+
|
|
1447
|
+
if config.file.suffix ~= '' then
|
|
1448
|
+
local low, up = H.get_suffix_variants(config.file.suffix)
|
|
1449
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.file('first')<CR>", { desc = 'File first' })
|
|
1450
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.file('last')<CR>", { desc = 'File last' })
|
|
1451
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.file('backward')<CR>", { desc = 'File backward' })
|
|
1452
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.file('forward')<CR>", { desc = 'File forward' })
|
|
1453
|
+
end
|
|
1454
|
+
|
|
1455
|
+
if config.indent.suffix ~= '' then
|
|
1456
|
+
local low, up = H.get_suffix_variants(config.indent.suffix)
|
|
1457
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.indent('first')<CR>", { desc = 'Indent first' })
|
|
1458
|
+
H.map('x', '[' .. up, "<Cmd>lua MiniBracketed.indent('first')<CR>", { desc = 'Indent first' })
|
|
1459
|
+
H.map('o', '[' .. up, "V<Cmd>lua MiniBracketed.indent('first')<CR>", { desc = 'Indent first' })
|
|
1460
|
+
|
|
1461
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.indent('last')<CR>", { desc = 'Indent last' })
|
|
1462
|
+
H.map('x', ']' .. up, "<Cmd>lua MiniBracketed.indent('last')<CR>", { desc = 'Indent last' })
|
|
1463
|
+
H.map('o', ']' .. up, "V<Cmd>lua MiniBracketed.indent('last')<CR>", { desc = 'Indent last' })
|
|
1464
|
+
|
|
1465
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.indent('backward')<CR>", { desc = 'Indent backward' })
|
|
1466
|
+
H.map('x', '[' .. low, "<Cmd>lua MiniBracketed.indent('backward')<CR>", { desc = 'Indent backward' })
|
|
1467
|
+
H.map('o', '[' .. low, "V<Cmd>lua MiniBracketed.indent('backward')<CR>", { desc = 'Indent backward' })
|
|
1468
|
+
|
|
1469
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.indent('forward')<CR>", { desc = 'Indent forward' })
|
|
1470
|
+
H.map('x', ']' .. low, "<Cmd>lua MiniBracketed.indent('forward')<CR>", { desc = 'Indent forward' })
|
|
1471
|
+
H.map('o', ']' .. low, "V<Cmd>lua MiniBracketed.indent('forward')<CR>", { desc = 'Indent forward' })
|
|
1472
|
+
end
|
|
1473
|
+
|
|
1474
|
+
if config.jump.suffix ~= '' then
|
|
1475
|
+
-- No Visual mode mappings due to implementation problems ()
|
|
1476
|
+
local low, up = H.get_suffix_variants(config.jump.suffix)
|
|
1477
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.jump('first')<CR>", { desc = 'Jump first' })
|
|
1478
|
+
H.map('o', '[' .. up, "v<Cmd>lua MiniBracketed.jump('first')<CR>", { desc = 'Jump first' })
|
|
1479
|
+
|
|
1480
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.jump('last')<CR>", { desc = 'Jump last' })
|
|
1481
|
+
H.map('o', ']' .. up, "v<Cmd>lua MiniBracketed.jump('last')<CR>", { desc = 'Jump last' })
|
|
1482
|
+
|
|
1483
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.jump('backward')<CR>", { desc = 'Jump backward' })
|
|
1484
|
+
H.map('o', '[' .. low, "v<Cmd>lua MiniBracketed.jump('backward')<CR>", { desc = 'Jump backward' })
|
|
1485
|
+
|
|
1486
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.jump('forward')<CR>", { desc = 'Jump forward' })
|
|
1487
|
+
H.map('o', ']' .. low, "v<Cmd>lua MiniBracketed.jump('forward')<CR>", { desc = 'Jump forward' })
|
|
1488
|
+
end
|
|
1489
|
+
|
|
1490
|
+
if config.oldfile.suffix ~= '' then
|
|
1491
|
+
local low, up = H.get_suffix_variants(config.oldfile.suffix)
|
|
1492
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.oldfile('first')<CR>", { desc = 'Oldfile first' })
|
|
1493
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.oldfile('last')<CR>", { desc = 'Oldfile last' })
|
|
1494
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.oldfile('backward')<CR>", { desc = 'Oldfile backward' })
|
|
1495
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.oldfile('forward')<CR>", { desc = 'Oldfile forward' })
|
|
1496
|
+
end
|
|
1497
|
+
|
|
1498
|
+
if config.location.suffix ~= '' then
|
|
1499
|
+
local low, up = H.get_suffix_variants(config.location.suffix)
|
|
1500
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.location('first')<CR>", { desc = 'Location first' })
|
|
1501
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.location('last')<CR>", { desc = 'Location last' })
|
|
1502
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.location('backward')<CR>", { desc = 'Location backward' })
|
|
1503
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.location('forward')<CR>", { desc = 'Location forward' })
|
|
1504
|
+
end
|
|
1505
|
+
|
|
1506
|
+
if config.quickfix.suffix ~= '' then
|
|
1507
|
+
local low, up = H.get_suffix_variants(config.quickfix.suffix)
|
|
1508
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.quickfix('first')<CR>", { desc = 'Quickfix first' })
|
|
1509
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.quickfix('last')<CR>", { desc = 'Quickfix last' })
|
|
1510
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.quickfix('backward')<CR>", { desc = 'Quickfix backward' })
|
|
1511
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.quickfix('forward')<CR>", { desc = 'Quickfix forward' })
|
|
1512
|
+
end
|
|
1513
|
+
|
|
1514
|
+
if config.treesitter.suffix ~= '' then
|
|
1515
|
+
local low, up = H.get_suffix_variants(config.treesitter.suffix)
|
|
1516
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.treesitter('first')<CR>", { desc = 'Treesitter first' })
|
|
1517
|
+
H.map('x', '[' .. up, "<Cmd>lua MiniBracketed.treesitter('first')<CR>", { desc = 'Treesitter first' })
|
|
1518
|
+
H.map('o', '[' .. up, "v<Cmd>lua MiniBracketed.treesitter('first')<CR>", { desc = 'Treesitter first' })
|
|
1519
|
+
|
|
1520
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.treesitter('last')<CR>", { desc = 'Treesitter last' })
|
|
1521
|
+
H.map('x', ']' .. up, "<Cmd>lua MiniBracketed.treesitter('last')<CR>", { desc = 'Treesitter last' })
|
|
1522
|
+
H.map('o', ']' .. up, "v<Cmd>lua MiniBracketed.treesitter('last')<CR>", { desc = 'Treesitter last' })
|
|
1523
|
+
|
|
1524
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.treesitter('backward')<CR>", { desc = 'Treesitter backward' })
|
|
1525
|
+
H.map('x', '[' .. low, "<Cmd>lua MiniBracketed.treesitter('backward')<CR>", { desc = 'Treesitter backward' })
|
|
1526
|
+
H.map('o', '[' .. low, "v<Cmd>lua MiniBracketed.treesitter('backward')<CR>", { desc = 'Treesitter backward' })
|
|
1527
|
+
|
|
1528
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.treesitter('forward')<CR>", { desc = 'Treesitter forward' })
|
|
1529
|
+
H.map('x', ']' .. low, "<Cmd>lua MiniBracketed.treesitter('forward')<CR>", { desc = 'Treesitter forward' })
|
|
1530
|
+
H.map('o', ']' .. low, "v<Cmd>lua MiniBracketed.treesitter('forward')<CR>", { desc = 'Treesitter forward' })
|
|
1531
|
+
end
|
|
1532
|
+
|
|
1533
|
+
if config.undo.suffix ~= '' then
|
|
1534
|
+
local low, up = H.get_suffix_variants(config.undo.suffix)
|
|
1535
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.undo('first')<CR>", { desc = 'Undo first' })
|
|
1536
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.undo('last')<CR>", { desc = 'Undo last' })
|
|
1537
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.undo('backward')<CR>", { desc = 'Undo backward' })
|
|
1538
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.undo('forward')<CR>", { desc = 'Undo forward' })
|
|
1539
|
+
|
|
1540
|
+
H.map('n', 'u', 'u<Cmd>lua MiniBracketed.register_undo_state()<CR>')
|
|
1541
|
+
H.map('n', '<C-R>', '<C-R><Cmd>lua MiniBracketed.register_undo_state()<CR>')
|
|
1542
|
+
end
|
|
1543
|
+
|
|
1544
|
+
if config.window.suffix ~= '' then
|
|
1545
|
+
local low, up = H.get_suffix_variants(config.window.suffix)
|
|
1546
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.window('first')<CR>", { desc = 'Window first' })
|
|
1547
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.window('last')<CR>", { desc = 'Window last' })
|
|
1548
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.window('backward')<CR>", { desc = 'Window backward' })
|
|
1549
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.window('forward')<CR>", { desc = 'Window forward' })
|
|
1550
|
+
end
|
|
1551
|
+
|
|
1552
|
+
if config.yank.suffix ~= '' then
|
|
1553
|
+
local low, up = H.get_suffix_variants(config.yank.suffix)
|
|
1554
|
+
H.map('n', '[' .. up, "<Cmd>lua MiniBracketed.yank('first')<CR>", { desc = 'Yank first' })
|
|
1555
|
+
H.map('n', ']' .. up, "<Cmd>lua MiniBracketed.yank('last')<CR>", { desc = 'Yank last' })
|
|
1556
|
+
H.map('n', '[' .. low, "<Cmd>lua MiniBracketed.yank('backward')<CR>", { desc = 'Yank backward' })
|
|
1557
|
+
H.map('n', ']' .. low, "<Cmd>lua MiniBracketed.yank('forward')<CR>", { desc = 'Yank forward' })
|
|
1558
|
+
end
|
|
1559
|
+
end
|
|
1560
|
+
|
|
1561
|
+
H.get_suffix_variants = function(char) return char:lower(), char:upper() end
|
|
1562
|
+
|
|
1563
|
+
H.create_autocommands = function()
|
|
1564
|
+
local gr = vim.api.nvim_create_augroup('MiniBracketed', {})
|
|
1565
|
+
|
|
1566
|
+
local au = function(event, pattern, callback, desc)
|
|
1567
|
+
vim.api.nvim_create_autocmd(event, { group = gr, pattern = pattern, callback = callback, desc = desc })
|
|
1568
|
+
end
|
|
1569
|
+
|
|
1570
|
+
au('BufEnter', '*', H.track_oldfile, 'Track oldfile')
|
|
1571
|
+
au('TextYankPost', '*', H.track_yank, 'Track yank')
|
|
1572
|
+
end
|
|
1573
|
+
|
|
1574
|
+
H.is_disabled = function() return vim.g.minibracketed_disable == true or vim.b.minibracketed_disable == true end
|
|
1575
|
+
|
|
1576
|
+
H.get_config = function(config)
|
|
1577
|
+
return vim.tbl_deep_extend('force', MiniBracketed.config, vim.b.minibracketed_config or {}, config or {})
|
|
1578
|
+
end
|
|
1579
|
+
|
|
1580
|
+
-- Autocommands ---------------------------------------------------------------
|
|
1581
|
+
H.track_oldfile = function()
|
|
1582
|
+
if H.is_disabled() then return end
|
|
1583
|
+
|
|
1584
|
+
-- Ensure tracking data is initialized
|
|
1585
|
+
H.oldfile_ensure_initialized()
|
|
1586
|
+
|
|
1587
|
+
-- Reset tracking indicator to allow proper tracking of next buffer
|
|
1588
|
+
local is_advancing = H.cache.oldfile.is_advancing
|
|
1589
|
+
H.cache.oldfile.is_advancing = false
|
|
1590
|
+
|
|
1591
|
+
-- Track only appropriate buffers (normal buffers with path)
|
|
1592
|
+
local path = vim.api.nvim_buf_get_name(0)
|
|
1593
|
+
local is_proper_buffer = path ~= '' and vim.bo.buftype == ''
|
|
1594
|
+
if not is_proper_buffer then return end
|
|
1595
|
+
|
|
1596
|
+
-- If advancing, don't touch tracking data to be able to consecutively move
|
|
1597
|
+
-- along recent files. Cache advanced buffer name to later update recency of
|
|
1598
|
+
-- the last one (just before buffer switching outside of `oldfile()`)
|
|
1599
|
+
local cache_oldfile = H.cache.oldfile
|
|
1600
|
+
|
|
1601
|
+
if is_advancing then
|
|
1602
|
+
cache_oldfile.last_advanced_bufname = path
|
|
1603
|
+
return
|
|
1604
|
+
end
|
|
1605
|
+
|
|
1606
|
+
-- If not advancing, update recency of a single latest advanced buffer (if
|
|
1607
|
+
-- present) and then update recency of current buffer
|
|
1608
|
+
if cache_oldfile.last_advanced_bufname ~= nil then
|
|
1609
|
+
H.oldfile_update_recency(cache_oldfile.last_advanced_bufname)
|
|
1610
|
+
cache_oldfile.last_advanced_bufname = nil
|
|
1611
|
+
end
|
|
1612
|
+
|
|
1613
|
+
H.oldfile_update_recency(path)
|
|
1614
|
+
end
|
|
1615
|
+
|
|
1616
|
+
H.track_yank = function()
|
|
1617
|
+
-- Don't track if asked not to. Allows other functionality to disable
|
|
1618
|
+
-- tracking (like in 'mini.move').
|
|
1619
|
+
if H.is_disabled() then return end
|
|
1620
|
+
|
|
1621
|
+
-- Track all `TextYankPost` events without exceptions. This leads to a better
|
|
1622
|
+
-- handling of charwise/linewise/blockwise selection detection.
|
|
1623
|
+
local event = vim.v.event
|
|
1624
|
+
table.insert(
|
|
1625
|
+
H.cache.yank.history,
|
|
1626
|
+
{ operator = event.operator, regcontents = event.regcontents, regtype = event.regtype }
|
|
1627
|
+
)
|
|
1628
|
+
|
|
1629
|
+
H.yank_stop_advancing()
|
|
1630
|
+
end
|
|
1631
|
+
|
|
1632
|
+
-- Comments -------------------------------------------------------------------
|
|
1633
|
+
H.make_comment_checker = function()
|
|
1634
|
+
local left, right = unpack(vim.fn.split(vim.bo.commentstring, '%s'))
|
|
1635
|
+
left, right = left or '', right or ''
|
|
1636
|
+
if left == '' and right == '' then return nil end
|
|
1637
|
+
|
|
1638
|
+
-- String is commented if it has structure:
|
|
1639
|
+
-- <space> <left> <anything> <right> <space>
|
|
1640
|
+
local regex = string.format('^%%s-%s.*%s%%s-$', vim.pesc(vim.trim(left)), vim.pesc(vim.trim(right)))
|
|
1641
|
+
|
|
1642
|
+
-- Check if line with number `line_num` is a comment. NOTE: `getline()`
|
|
1643
|
+
-- return empty string for invalid line number, which makes them *not
|
|
1644
|
+
-- commented*.
|
|
1645
|
+
return function(line_num) return vim.fn.getline(line_num):find(regex) ~= nil end
|
|
1646
|
+
end
|
|
1647
|
+
|
|
1648
|
+
-- Conflicts ------------------------------------------------------------------
|
|
1649
|
+
H.is_conflict_mark = function(line_num)
|
|
1650
|
+
local l_start = vim.fn.getline(line_num):sub(1, 8)
|
|
1651
|
+
return l_start == '<<<<<<< ' or l_start == '=======' or l_start == '>>>>>>> '
|
|
1652
|
+
end
|
|
1653
|
+
|
|
1654
|
+
-- Diagnostic -----------------------------------------------------------------
|
|
1655
|
+
H.diagnostic_jump = function(pos, float, severity)
|
|
1656
|
+
vim.diagnostic.jump({ count = 1, pos = pos, float = float, severity = severity })
|
|
1657
|
+
end
|
|
1658
|
+
if vim.fn.has('nvim-0.11') == 0 then
|
|
1659
|
+
H.diagnostic_jump = function(pos, float, severity)
|
|
1660
|
+
vim.diagnostic.goto_next({ cursor_position = pos, float = float, severity = severity })
|
|
1661
|
+
end
|
|
1662
|
+
end
|
|
1663
|
+
|
|
1664
|
+
-- Files ----------------------------------------------------------------------
|
|
1665
|
+
H.get_file_data = function()
|
|
1666
|
+
-- Compute target directory
|
|
1667
|
+
local cur_buf_path = vim.api.nvim_buf_get_name(0)
|
|
1668
|
+
local dir_path = cur_buf_path ~= '' and vim.fn.fnamemodify(cur_buf_path, ':p:h') or vim.fn.getcwd()
|
|
1669
|
+
|
|
1670
|
+
-- Compute sorted array of all files in target directory
|
|
1671
|
+
local dir_handle = vim.loop.fs_scandir(dir_path)
|
|
1672
|
+
local files_stream = function() return vim.loop.fs_scandir_next(dir_handle) end
|
|
1673
|
+
|
|
1674
|
+
local files = {}
|
|
1675
|
+
for basename, fs_type in files_stream do
|
|
1676
|
+
if fs_type == 'file' then table.insert(files, basename) end
|
|
1677
|
+
end
|
|
1678
|
+
|
|
1679
|
+
-- - Sort files ignoring case
|
|
1680
|
+
table.sort(files, function(x, y) return x:lower() < y:lower() end)
|
|
1681
|
+
|
|
1682
|
+
if #files == 0 then return end
|
|
1683
|
+
return { directory = dir_path, file_basenames = files }
|
|
1684
|
+
end
|
|
1685
|
+
|
|
1686
|
+
-- Jumps ----------------------------------------------------------------------
|
|
1687
|
+
H.make_jump = function(jump_list, cur_jump_num, new_jump_num)
|
|
1688
|
+
local num_diff = new_jump_num - cur_jump_num
|
|
1689
|
+
|
|
1690
|
+
if num_diff == 0 then
|
|
1691
|
+
-- Perform jump manually to always jump. Example: move to last jump and
|
|
1692
|
+
-- move manually; then jump with "last" direction should move to last jump.
|
|
1693
|
+
local jump_entry = jump_list[new_jump_num]
|
|
1694
|
+
pcall(vim.fn.cursor, { jump_entry.lnum, jump_entry.col + 1, jump_entry.coladd })
|
|
1695
|
+
else
|
|
1696
|
+
-- Use builtin mappings to also update current jump entry
|
|
1697
|
+
local key = num_diff > 0 and '\t' or '\15'
|
|
1698
|
+
vim.cmd('normal! ' .. math.abs(num_diff) .. key)
|
|
1699
|
+
end
|
|
1700
|
+
|
|
1701
|
+
-- Open just enough folds
|
|
1702
|
+
vim.cmd('normal! zv')
|
|
1703
|
+
end
|
|
1704
|
+
|
|
1705
|
+
-- Oldfile --------------------------------------------------------------------
|
|
1706
|
+
H.oldfile_normalize = function()
|
|
1707
|
+
-- Ensure that tracking data is initialized
|
|
1708
|
+
H.oldfile_ensure_initialized()
|
|
1709
|
+
|
|
1710
|
+
-- Order currently readable paths in increasing order of recency
|
|
1711
|
+
local recency_pairs = {}
|
|
1712
|
+
for path, rec in pairs(H.cache.oldfile.recency) do
|
|
1713
|
+
if vim.fn.filereadable(path) == 1 then table.insert(recency_pairs, { path, rec }) end
|
|
1714
|
+
end
|
|
1715
|
+
table.sort(recency_pairs, function(x, y) return x[2] < y[2] end)
|
|
1716
|
+
|
|
1717
|
+
-- Construct new tracking data with recency from 1 to number of entries
|
|
1718
|
+
local new_recency = {}
|
|
1719
|
+
for i, pair in ipairs(recency_pairs) do
|
|
1720
|
+
new_recency[pair[1]] = i
|
|
1721
|
+
end
|
|
1722
|
+
|
|
1723
|
+
H.cache.oldfile = { recency = new_recency, max_recency = #recency_pairs, is_advancing = H.cache.oldfile.is_advancing }
|
|
1724
|
+
end
|
|
1725
|
+
|
|
1726
|
+
H.oldfile_ensure_initialized = function()
|
|
1727
|
+
if H.cache.oldfile ~= nil or vim.v.oldfiles == nil then return end
|
|
1728
|
+
|
|
1729
|
+
local n = #vim.v.oldfiles
|
|
1730
|
+
local recency = {}
|
|
1731
|
+
for i, path in ipairs(vim.v.oldfiles) do
|
|
1732
|
+
recency[path] = n - i + 1
|
|
1733
|
+
end
|
|
1734
|
+
|
|
1735
|
+
H.cache.oldfile = { recency = recency, max_recency = n, is_advancing = false }
|
|
1736
|
+
end
|
|
1737
|
+
|
|
1738
|
+
H.oldfile_get_array = function()
|
|
1739
|
+
local res = {}
|
|
1740
|
+
for path, i in pairs(H.cache.oldfile.recency) do
|
|
1741
|
+
res[i] = path
|
|
1742
|
+
end
|
|
1743
|
+
return res
|
|
1744
|
+
end
|
|
1745
|
+
|
|
1746
|
+
H.oldfile_update_recency = function(path)
|
|
1747
|
+
local n = H.cache.oldfile.max_recency + 1
|
|
1748
|
+
H.cache.oldfile.recency[path] = n
|
|
1749
|
+
H.cache.oldfile.max_recency = n
|
|
1750
|
+
end
|
|
1751
|
+
|
|
1752
|
+
-- Quickfix/Location lists ----------------------------------------------------
|
|
1753
|
+
H.qf_loc_implementation = function(list_type, direction, opts)
|
|
1754
|
+
local get_list, goto_command = vim.fn.getqflist, 'cc'
|
|
1755
|
+
if list_type == 'location' then
|
|
1756
|
+
get_list, goto_command = function(...) return vim.fn.getloclist(0, ...) end, 'll'
|
|
1757
|
+
end
|
|
1758
|
+
|
|
1759
|
+
-- Define iterator that traverses quickfix/location list entries
|
|
1760
|
+
local list = get_list()
|
|
1761
|
+
local n_list = #list
|
|
1762
|
+
if n_list == 0 then return end
|
|
1763
|
+
|
|
1764
|
+
local iterator = {}
|
|
1765
|
+
|
|
1766
|
+
iterator.next = function(ind)
|
|
1767
|
+
if ind == nil or n_list <= ind then return end
|
|
1768
|
+
return ind + 1
|
|
1769
|
+
end
|
|
1770
|
+
|
|
1771
|
+
iterator.prev = function(ind)
|
|
1772
|
+
if ind == nil or ind <= 1 then return end
|
|
1773
|
+
return ind - 1
|
|
1774
|
+
end
|
|
1775
|
+
|
|
1776
|
+
iterator.state = get_list({ idx = 0 }).idx
|
|
1777
|
+
iterator.start_edge = 0
|
|
1778
|
+
iterator.end_edge = n_list + 1
|
|
1779
|
+
|
|
1780
|
+
-- Iterate
|
|
1781
|
+
local res_ind = MiniBracketed.advance(iterator, direction, opts)
|
|
1782
|
+
|
|
1783
|
+
-- Apply. Focus target entry, open enough folds and center. Allow jumping to
|
|
1784
|
+
-- current quickfix/loclist entry as it might be different from current
|
|
1785
|
+
-- cursor position.
|
|
1786
|
+
vim.cmd(goto_command .. ' ' .. res_ind)
|
|
1787
|
+
vim.cmd('normal! zvzz')
|
|
1788
|
+
end
|
|
1789
|
+
|
|
1790
|
+
-- Treesitter -----------------------------------------------------------------
|
|
1791
|
+
H.get_treesitter_node = function(row, col) return vim.treesitter.get_node({ pos = { row, col } }) end
|
|
1792
|
+
|
|
1793
|
+
-- Undo -----------------------------------------------------------------------
|
|
1794
|
+
H.undo_sync = function(buf_id, tree, is_advancing)
|
|
1795
|
+
-- Get or initialize buffer history of visited undo states
|
|
1796
|
+
local prev_buf_history = H.cache.undo[buf_id] or H.undo_init(tree)
|
|
1797
|
+
if is_advancing == nil then is_advancing = prev_buf_history.is_advancing end
|
|
1798
|
+
|
|
1799
|
+
-- Prune current buffer history to contain only allowed state numbers. This
|
|
1800
|
+
-- assumes that once undo state is not allowed, it will always be not
|
|
1801
|
+
-- allowed. This step is needed because allowed undo state numbers can:
|
|
1802
|
+
-- - Not start from 1 due to 'undolevels'.
|
|
1803
|
+
-- - Contain range of missing state numbers due to `:undo!`.
|
|
1804
|
+
--
|
|
1805
|
+
-- Do this even if advancing because `:undo!` can be executed at any time.
|
|
1806
|
+
local allowed_states = H.undo_get_allowed_state_numbers(tree)
|
|
1807
|
+
|
|
1808
|
+
local buf_history = {}
|
|
1809
|
+
for i, state_num in ipairs(prev_buf_history) do
|
|
1810
|
+
-- Use only allowed states
|
|
1811
|
+
if allowed_states[state_num] then H.undo_append_state(buf_history, state_num) end
|
|
1812
|
+
|
|
1813
|
+
-- Correctly track current id when advancing
|
|
1814
|
+
if i == prev_buf_history.current_id then buf_history.current_id = #buf_history end
|
|
1815
|
+
end
|
|
1816
|
+
buf_history.current_id = buf_history.current_id or #buf_history
|
|
1817
|
+
buf_history.is_advancing = prev_buf_history.is_advancing
|
|
1818
|
+
buf_history.seq_last = prev_buf_history.seq_last
|
|
1819
|
+
|
|
1820
|
+
H.cache.undo[buf_id] = buf_history
|
|
1821
|
+
|
|
1822
|
+
-- Continue only if not actually advancing: either if set so manually *or* if
|
|
1823
|
+
-- there were additions to undo history *or* some states became not allowed
|
|
1824
|
+
-- (due to `:undo!`).
|
|
1825
|
+
if is_advancing and tree.seq_last <= buf_history.seq_last and #buf_history == #prev_buf_history then return end
|
|
1826
|
+
|
|
1827
|
+
-- Register current undo state (if not equal to last).
|
|
1828
|
+
-- Usually it is a result of advance but also can be due to `:undo`/`:undo!`.
|
|
1829
|
+
H.undo_append_state(buf_history, tree.seq_cur)
|
|
1830
|
+
|
|
1831
|
+
-- Add all new *allowed* undo states created since last sync
|
|
1832
|
+
for new_state = buf_history.seq_last + 1, tree.seq_last do
|
|
1833
|
+
if allowed_states[new_state] then H.undo_append_state(buf_history, new_state) end
|
|
1834
|
+
end
|
|
1835
|
+
|
|
1836
|
+
-- Update data to be most recent
|
|
1837
|
+
buf_history.current_id = #buf_history
|
|
1838
|
+
buf_history.is_advancing = false
|
|
1839
|
+
buf_history.seq_last = tree.seq_last
|
|
1840
|
+
end
|
|
1841
|
+
|
|
1842
|
+
H.undo_append_state = function(buf_history, state_num)
|
|
1843
|
+
-- Ensure that there are no two consecutive equal states
|
|
1844
|
+
if state_num == nil or buf_history[#buf_history] == state_num then return end
|
|
1845
|
+
|
|
1846
|
+
table.insert(buf_history, state_num)
|
|
1847
|
+
end
|
|
1848
|
+
|
|
1849
|
+
H.undo_init = function(tree)
|
|
1850
|
+
-- Assume all previous states are allowed
|
|
1851
|
+
local res = {}
|
|
1852
|
+
for i = 0, tree.seq_last do
|
|
1853
|
+
res[i + 1] = i
|
|
1854
|
+
end
|
|
1855
|
+
res.current_id = #res
|
|
1856
|
+
res.is_advancing = false
|
|
1857
|
+
res.seq_last = tree.seq_last
|
|
1858
|
+
|
|
1859
|
+
return res
|
|
1860
|
+
end
|
|
1861
|
+
|
|
1862
|
+
H.undo_get_allowed_state_numbers = function(tree)
|
|
1863
|
+
-- `:undo 0` is always possible (goes to *before* the first allowed state).
|
|
1864
|
+
local res = { [0] = true }
|
|
1865
|
+
local traverse
|
|
1866
|
+
traverse = function(entries)
|
|
1867
|
+
for _, e in ipairs(entries) do
|
|
1868
|
+
if e.alt ~= nil then traverse(e.alt) end
|
|
1869
|
+
res[e.seq] = true
|
|
1870
|
+
end
|
|
1871
|
+
end
|
|
1872
|
+
|
|
1873
|
+
traverse(tree.entries)
|
|
1874
|
+
return res
|
|
1875
|
+
end
|
|
1876
|
+
|
|
1877
|
+
-- Yank -----------------------------------------------------------------------
|
|
1878
|
+
H.yank_stop_advancing = function()
|
|
1879
|
+
H.cache.yank.current_id = #H.cache.yank.history
|
|
1880
|
+
H.cache.yank.is_advancing = false
|
|
1881
|
+
H.cache.yank.advance_put_regions[vim.api.nvim_get_current_buf()] = nil
|
|
1882
|
+
end
|
|
1883
|
+
|
|
1884
|
+
H.get_yank_state = function() return { buf_id = vim.api.nvim_get_current_buf(), changedtick = vim.b.changedtick } end
|
|
1885
|
+
|
|
1886
|
+
H.replace_latest_put_region = function(yank_data)
|
|
1887
|
+
-- Squash all yank advancing in a single undo block
|
|
1888
|
+
local normal_command = (H.cache.yank.is_advancing and 'undojoin | ' or '') .. 'silent normal! '
|
|
1889
|
+
local normal_fun = function(x) vim.cmd(normal_command .. x) end
|
|
1890
|
+
|
|
1891
|
+
-- Compute latest put region: from latest `yank` advance; or from user's
|
|
1892
|
+
-- latest put; or from `[`/`]` marks
|
|
1893
|
+
local cache_yank = H.cache.yank
|
|
1894
|
+
local buf_id = vim.api.nvim_get_current_buf()
|
|
1895
|
+
local latest_region = cache_yank.advance_put_regions[buf_id]
|
|
1896
|
+
or cache_yank.user_put_regions[buf_id]
|
|
1897
|
+
or H.get_latest_region()
|
|
1898
|
+
|
|
1899
|
+
-- Compute modes for replaced and new regions.
|
|
1900
|
+
local latest_mode = latest_region.mode
|
|
1901
|
+
local new_mode = yank_data.regtype:sub(1, 1)
|
|
1902
|
+
|
|
1903
|
+
-- Compute later put key based on replaced and new regions.
|
|
1904
|
+
-- Prefer `P` but use `p` in cases replaced region was on the edge: last line
|
|
1905
|
+
-- for linewise-linewise replace or last column for nonlinewise-nonlinewise.
|
|
1906
|
+
local is_linewise = (latest_mode == 'V' and new_mode == 'V')
|
|
1907
|
+
local is_edge_line = is_linewise and latest_region.to.line == vim.fn.line('$')
|
|
1908
|
+
|
|
1909
|
+
local is_charblockwise = (latest_mode ~= 'V' and new_mode ~= 'V')
|
|
1910
|
+
local is_edge_col = is_charblockwise and latest_region.to.col == vim.fn.getline(latest_region.to.line):len()
|
|
1911
|
+
|
|
1912
|
+
local is_edge = is_edge_line or is_edge_col
|
|
1913
|
+
local put_key = is_edge and 'p' or 'P'
|
|
1914
|
+
|
|
1915
|
+
-- Delete latest region
|
|
1916
|
+
H.region_delete(latest_region, normal_fun)
|
|
1917
|
+
|
|
1918
|
+
-- Paste yank data using temporary register
|
|
1919
|
+
local cache_z_reg = vim.fn.getreg('z')
|
|
1920
|
+
vim.fn.setreg('z', yank_data.regcontents, yank_data.regtype)
|
|
1921
|
+
|
|
1922
|
+
normal_fun('"z' .. put_key)
|
|
1923
|
+
|
|
1924
|
+
vim.fn.setreg('z', cache_z_reg)
|
|
1925
|
+
|
|
1926
|
+
-- Register newly put region for correct further advancing
|
|
1927
|
+
cache_yank.advance_put_regions[buf_id] = H.get_latest_region(new_mode)
|
|
1928
|
+
end
|
|
1929
|
+
|
|
1930
|
+
H.get_latest_region = function(mode)
|
|
1931
|
+
local left, right = vim.fn.getpos("'["), vim.fn.getpos("']")
|
|
1932
|
+
return {
|
|
1933
|
+
from = { line = left[2], col = left[3] },
|
|
1934
|
+
to = { line = right[2], col = right[3] },
|
|
1935
|
+
-- Mode should be one of 'v', 'V', or '\22' ('<C-v>')
|
|
1936
|
+
-- By default use mode of current or unnamed register
|
|
1937
|
+
-- NOTE: this breaks if latest paste was not from unnamed register.
|
|
1938
|
+
-- To account for that, use `register_put_region()`.
|
|
1939
|
+
mode = mode or H.get_register_mode(vim.v.register),
|
|
1940
|
+
}
|
|
1941
|
+
end
|
|
1942
|
+
|
|
1943
|
+
H.region_delete = function(region, normal_fun)
|
|
1944
|
+
-- Start with `to` to have cursor positioned on region start after deletion
|
|
1945
|
+
H.set_cursor(region.to.line, region.to.col - 1)
|
|
1946
|
+
|
|
1947
|
+
-- Do nothing more if region is empty (or leads to unnecessary line deletion)
|
|
1948
|
+
local is_empty = region.from.line == region.to.line
|
|
1949
|
+
and region.from.col == region.to.col
|
|
1950
|
+
and vim.fn.getline(region.from.line) == ''
|
|
1951
|
+
|
|
1952
|
+
if is_empty then return end
|
|
1953
|
+
|
|
1954
|
+
-- Select region in correct Visual mode
|
|
1955
|
+
normal_fun(region.mode)
|
|
1956
|
+
H.set_cursor(region.from.line, region.from.col - 1)
|
|
1957
|
+
|
|
1958
|
+
-- Delete region in "black hole" register
|
|
1959
|
+
-- - NOTE: it doesn't affect history as `"_` doesn't trigger `TextYankPost`
|
|
1960
|
+
normal_fun('"_d')
|
|
1961
|
+
end
|
|
1962
|
+
|
|
1963
|
+
H.get_register_mode = function(register)
|
|
1964
|
+
-- Use only first character to correctly get '\22' in blockwise mode
|
|
1965
|
+
return vim.fn.getregtype(register):sub(1, 1)
|
|
1966
|
+
end
|
|
1967
|
+
|
|
1968
|
+
-- Utilities ------------------------------------------------------------------
|
|
1969
|
+
H.error = function(msg) error('(mini.bracketed) ' .. msg, 0) end
|
|
1970
|
+
|
|
1971
|
+
H.check_type = function(name, val, ref, allow_nil)
|
|
1972
|
+
if type(val) == ref or (ref == 'callable' and vim.is_callable(val)) or (allow_nil and val == nil) then return end
|
|
1973
|
+
H.error(string.format('`%s` should be %s, not %s', name, ref, type(val)))
|
|
1974
|
+
end
|
|
1975
|
+
|
|
1976
|
+
H.validate_direction = function(direction, choices, fun_name)
|
|
1977
|
+
if not vim.tbl_contains(choices, direction) then
|
|
1978
|
+
local choices_string = "'" .. table.concat(choices, "', '") .. "'"
|
|
1979
|
+
local error_text = string.format('In `%s()` argument `direction` should be one of %s.', fun_name, choices_string)
|
|
1980
|
+
H.error(error_text)
|
|
1981
|
+
end
|
|
1982
|
+
end
|
|
1983
|
+
|
|
1984
|
+
H.map = function(mode, lhs, rhs, opts)
|
|
1985
|
+
if lhs == '' then return end
|
|
1986
|
+
opts = vim.tbl_deep_extend('force', { silent = true }, opts or {})
|
|
1987
|
+
vim.keymap.set(mode, lhs, rhs, opts)
|
|
1988
|
+
end
|
|
1989
|
+
|
|
1990
|
+
H.edit = function(path, win_id)
|
|
1991
|
+
if type(path) ~= 'string' then return end
|
|
1992
|
+
local b = vim.api.nvim_win_get_buf(win_id or 0)
|
|
1993
|
+
local try_mimic_buf_reuse = (vim.fn.bufname(b) == '' and vim.bo[b].buftype ~= 'quickfix' and not vim.bo[b].modified)
|
|
1994
|
+
and (#vim.fn.win_findbuf(b) == 1 and vim.deep_equal(vim.fn.getbufline(b, 1, '$'), { '' }))
|
|
1995
|
+
local buf_id = vim.fn.bufadd(vim.fn.fnamemodify(path, ':.'))
|
|
1996
|
+
-- Showing in window also loads. Use `pcall` to not error with swap messages.
|
|
1997
|
+
pcall(vim.api.nvim_win_set_buf, win_id or 0, buf_id)
|
|
1998
|
+
vim.bo[buf_id].buflisted = true
|
|
1999
|
+
if try_mimic_buf_reuse then pcall(vim.api.nvim_buf_delete, b, { unload = false }) end
|
|
2000
|
+
return buf_id
|
|
2001
|
+
end
|
|
2002
|
+
|
|
2003
|
+
H.add_to_jumplist = function() vim.cmd([[normal! m']]) end
|
|
2004
|
+
|
|
2005
|
+
H.set_cursor = function(row, col)
|
|
2006
|
+
if row <= 0 then return vim.api.nvim_win_set_cursor(0, { 1, 0 }) end
|
|
2007
|
+
local n_lines = vim.api.nvim_buf_line_count(0)
|
|
2008
|
+
if n_lines < row then return vim.api.nvim_win_set_cursor(0, { n_lines, vim.fn.getline(n_lines):len() - 1 }) end
|
|
2009
|
+
col = math.min(math.max(col, 0), vim.fn.getline(row):len())
|
|
2010
|
+
return vim.api.nvim_win_set_cursor(0, { row, col })
|
|
2011
|
+
end
|
|
2012
|
+
|
|
2013
|
+
return MiniBracketed
|