Repository: nvim-mini/mini.nvim Branch: main Commit: 59f09943573c Files: 2783 Total size: 9.8 MB Directory structure: gitextract_29gci10c/ ├── .github/ │ ├── DISCUSSION_TEMPLATE/ │ │ └── q-a.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug-report.yml │ │ ├── config.yml │ │ └── feature-request.yml │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows/ │ └── quality-control.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .stylua.toml ├── .styluaignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── MAINTAINING.md ├── Makefile ├── README.md ├── TESTING.md ├── benchmarks/ │ └── starter/ │ ├── .gitignore │ ├── README.md │ ├── benchmark.sh │ ├── init-files/ │ │ ├── init_dashboard-alpha.lua │ │ ├── init_dashboard-original.lua │ │ ├── init_dashboard-starter.lua │ │ ├── init_empty.lua │ │ ├── init_starter-default.lua │ │ ├── init_startify-alpha.lua │ │ ├── init_startify-original.lua │ │ └── init_startify-starter.lua │ ├── install.sh │ ├── make_summary.py │ └── startup-summary.md ├── colors/ │ ├── miniautumn.lua │ ├── minicyan.lua │ ├── minischeme.lua │ ├── minispring.lua │ ├── minisummer.lua │ ├── miniwinter.lua │ └── randomhue.lua ├── doc/ │ ├── mini-ai.txt │ ├── mini-align.txt │ ├── mini-animate.txt │ ├── mini-base16.txt │ ├── mini-basics.txt │ ├── mini-bracketed.txt │ ├── mini-bufremove.txt │ ├── mini-clue.txt │ ├── mini-cmdline.txt │ ├── mini-colors.txt │ ├── mini-comment.txt │ ├── mini-completion.txt │ ├── mini-cursorword.txt │ ├── mini-deps.txt │ ├── mini-diff.txt │ ├── mini-doc.txt │ ├── mini-extra.txt │ ├── mini-files.txt │ ├── mini-fuzzy.txt │ ├── mini-git.txt │ ├── mini-hipatterns.txt │ ├── mini-hues.txt │ ├── mini-icons.txt │ ├── mini-indentscope.txt │ ├── mini-jump.txt │ ├── mini-jump2d.txt │ ├── mini-keymap.txt │ ├── mini-map.txt │ ├── mini-misc.txt │ ├── mini-move.txt │ ├── mini-notify.txt │ ├── mini-nvim.txt │ ├── mini-operators.txt │ ├── mini-pairs.txt │ ├── mini-pick.txt │ ├── mini-sessions.txt │ ├── mini-snippets.txt │ ├── mini-splitjoin.txt │ ├── mini-starter.txt │ ├── mini-statusline.txt │ ├── mini-surround.txt │ ├── mini-tabline.txt │ ├── mini-test.txt │ ├── mini-trailspace.txt │ └── mini-visits.txt ├── lua/ │ └── mini/ │ ├── ai.lua │ ├── align.lua │ ├── animate.lua │ ├── base16.lua │ ├── basics.lua │ ├── bracketed.lua │ ├── bufremove.lua │ ├── clue.lua │ ├── cmdline.lua │ ├── colors.lua │ ├── comment.lua │ ├── completion.lua │ ├── cursorword.lua │ ├── deps.lua │ ├── diff.lua │ ├── doc.lua │ ├── extra.lua │ ├── files.lua │ ├── fuzzy.lua │ ├── git.lua │ ├── hipatterns.lua │ ├── hues.lua │ ├── icons.lua │ ├── indentscope.lua │ ├── init.lua │ ├── jump.lua │ ├── jump2d.lua │ ├── keymap.lua │ ├── map.lua │ ├── misc.lua │ ├── move.lua │ ├── notify.lua │ ├── operators.lua │ ├── pairs.lua │ ├── pick.lua │ ├── sessions.lua │ ├── snippets.lua │ ├── splitjoin.lua │ ├── starter.lua │ ├── statusline.lua │ ├── surround.lua │ ├── tabline.lua │ ├── test.lua │ ├── trailspace.lua │ └── visits.lua ├── readmes/ │ ├── mini-ai.md │ ├── mini-align.md │ ├── mini-animate.md │ ├── mini-base16.md │ ├── mini-basics.md │ ├── mini-bracketed.md │ ├── mini-bufremove.md │ ├── mini-clue.md │ ├── mini-cmdline.md │ ├── mini-colors.md │ ├── mini-comment.md │ ├── mini-completion.md │ ├── mini-cursorword.md │ ├── mini-deps.md │ ├── mini-diff.md │ ├── mini-doc.md │ ├── mini-extra.md │ ├── mini-files.md │ ├── mini-fuzzy.md │ ├── mini-git.md │ ├── mini-hipatterns.md │ ├── mini-hues.md │ ├── mini-icons.md │ ├── mini-indentscope.md │ ├── mini-jump.md │ ├── mini-jump2d.md │ ├── mini-keymap.md │ ├── mini-map.md │ ├── mini-misc.md │ ├── mini-move.md │ ├── mini-notify.md │ ├── mini-operators.md │ ├── mini-pairs.md │ ├── mini-pick.md │ ├── mini-sessions.md │ ├── mini-snippets.md │ ├── mini-splitjoin.md │ ├── mini-starter.md │ ├── mini-statusline.md │ ├── mini-surround.md │ ├── mini-tabline.md │ ├── mini-test.md │ ├── mini-trailspace.md │ └── mini-visits.md ├── scripts/ │ ├── dual_log.sh │ ├── dual_push.sh │ ├── dual_release.sh │ ├── dual_sync.sh │ ├── init-deps-example.lua │ ├── lint-filename-length.sh │ ├── lintcommit-ci.sh │ ├── lintcommit.lua │ ├── minidoc.lua │ ├── minimal_init.lua │ └── minitest.lua └── tests/ ├── dir-ai/ │ └── mock-nvim-treesitter/ │ └── lua/ │ └── nvim-treesitter/ │ ├── init.lua │ └── query.lua ├── dir-bracketed/ │ ├── dir-a/ │ │ └── file-aa │ ├── file-a │ ├── file-b │ ├── file-c │ ├── file-d │ ├── file-e │ └── mock/ │ ├── diagnostic.lua │ └── treesitter.lua ├── dir-cmdline/ │ ├── compiler/ │ │ └── testcompiler.vim │ ├── fileA │ ├── fileB │ ├── keymap/ │ │ └── testkeymap.vim │ └── pack/ │ └── test/ │ └── opt/ │ └── testplugin/ │ └── plugin/ │ └── testplugin.vim ├── dir-colors/ │ └── mock_cs/ │ └── colors/ │ └── mock_cs.lua ├── dir-deps/ │ ├── mocks/ │ │ └── spawn.lua │ ├── pack/ │ │ └── deps/ │ │ └── opt/ │ │ ├── plu-gin_0.nvim/ │ │ │ └── lua/ │ │ │ └── plug_0.lua │ │ ├── plugin_1/ │ │ │ ├── after/ │ │ │ │ └── plugin/ │ │ │ │ ├── plug_1.lua │ │ │ │ ├── plug_1.nonlua │ │ │ │ ├── plug_1.vim │ │ │ │ └── subdir/ │ │ │ │ └── plug_1_sub.lua │ │ │ ├── doc/ │ │ │ │ └── help_1.txt │ │ │ ├── lua/ │ │ │ │ └── plug_1.lua │ │ │ └── plugin/ │ │ │ ├── plug_1.lua │ │ │ ├── plug_1.vim │ │ │ └── subdir/ │ │ │ └── plug_1_sub.lua │ │ ├── plugin_2/ │ │ │ ├── after/ │ │ │ │ └── plugin/ │ │ │ │ └── plug_2.lua │ │ │ ├── doc/ │ │ │ │ └── help_2.txt │ │ │ ├── lua/ │ │ │ │ └── plug_2.lua │ │ │ └── plugin/ │ │ │ └── plug_2.lua │ │ └── plugin_3/ │ │ └── lua/ │ │ └── plug_3.lua │ ├── snapshots/ │ │ ├── not-proper-1 │ │ ├── not-proper-2 │ │ └── snap │ └── test-log ├── dir-diff/ │ ├── file │ ├── file-bom │ ├── git-repo/ │ │ ├── .git-dir/ │ │ │ └── index │ │ └── dir-in-git/ │ │ └── file-in-git │ └── mocks/ │ └── spawn.lua ├── dir-doc/ │ ├── .gitignore │ ├── .styluaignore │ ├── arguments/ │ │ ├── file.lua │ │ ├── file_ignore.lua │ │ └── output_reference.txt │ ├── buffer-local_script.lua │ ├── custom-script/ │ │ ├── gendoc/ │ │ │ └── gendoc-script.lua │ │ ├── init.lua │ │ └── output_reference.txt │ ├── default-collation/ │ │ ├── after/ │ │ │ ├── file01.lua │ │ │ ├── file02.lua │ │ │ └── init.lua │ │ ├── colors/ │ │ │ ├── file01.lua │ │ │ ├── file02.lua │ │ │ └── init.lua │ │ ├── default-collation_reference.txt │ │ ├── file01.lua │ │ ├── file02.lua │ │ ├── init.lua │ │ └── lua/ │ │ ├── aaa/ │ │ │ └── init.lua │ │ ├── file01.lua │ │ ├── file02.lua │ │ └── init.lua │ ├── helpers.lua │ ├── inference/ │ │ ├── inference_reference.txt │ │ └── init.lua │ ├── sections/ │ │ ├── .styluaignore │ │ ├── alias.lua │ │ ├── eval.lua │ │ ├── init.lua │ │ ├── param.lua │ │ ├── return.lua │ │ ├── sections_reference.txt │ │ └── toc.lua │ └── structure/ │ ├── file1.lua │ └── file2.lua ├── dir-extra/ │ ├── colorschemes/ │ │ └── colors/ │ │ └── miniforcebg.lua │ ├── explorer/ │ │ ├── Dir2/ │ │ │ └── file2-1 │ │ ├── File2 │ │ ├── dir1/ │ │ │ ├── file1-1 │ │ │ └── subdir/ │ │ │ └── file1-1-1 │ │ ├── dir3/ │ │ │ └── file3-1 │ │ ├── file1 │ │ └── file3 │ ├── git-files/ │ │ ├── git-file-1 │ │ └── git-file-2 │ ├── lua/ │ │ └── nvim-web-devicons.lua │ ├── mocks/ │ │ ├── diagnostic-file-1 │ │ ├── diagnostic-file-2 │ │ ├── diagnostic.lua │ │ ├── git-commit │ │ ├── git-diff │ │ ├── git-diff-edge-cases │ │ ├── git-diff-unified-0 │ │ ├── git-diff-unified-20 │ │ ├── keymaps.lua │ │ └── spawn.lua │ └── real-files/ │ ├── LICENSE │ ├── Makefile │ ├── a.lua │ └── b.txt ├── dir-files/ │ ├── common/ │ │ ├── .a-dir/ │ │ │ ├── aa-file │ │ │ └── ab-file │ │ ├── .a-file │ │ ├── A-file-2 │ │ ├── a-dir/ │ │ │ ├── aa-dir/ │ │ │ │ └── aaa-file │ │ │ ├── aa-file │ │ │ └── ab-file │ │ ├── a-file │ │ ├── b-dir/ │ │ │ └── ba-file │ │ └── b-file │ ├── init-default-explorer.lua │ ├── lua/ │ │ └── nvim-web-devicons.lua │ ├── mock-win-functions.lua │ ├── nested/ │ │ └── dir-1/ │ │ ├── dir-11/ │ │ │ └── dir-111/ │ │ │ └── dir-1111/ │ │ │ └── dir-11111/ │ │ │ └── file-111111 │ │ └── dir-12/ │ │ └── file-121 │ └── real/ │ ├── LICENSE │ ├── Makefile │ ├── a.lua │ ├── b.txt │ └── top-secret ├── dir-git/ │ ├── File2 │ ├── deps-confirm │ ├── diff-output │ ├── file │ ├── file1 │ ├── file3 │ ├── git-repo/ │ │ ├── .git-dir/ │ │ │ ├── COMMIT_EDITMSG │ │ │ ├── HEAD │ │ │ ├── index │ │ │ └── refs/ │ │ │ └── heads/ │ │ │ └── tmp │ │ ├── dir-in-git/ │ │ │ └── file-in-dir-in-git │ │ ├── file-in-git │ │ └── file-in-git_symlink-source │ ├── help-output │ ├── log-output │ └── mocks/ │ └── spawn.lua ├── dir-keymap/ │ ├── mock-plugins/ │ │ ├── blink.cmp/ │ │ │ └── lua/ │ │ │ └── blink/ │ │ │ └── cmp/ │ │ │ └── init.lua │ │ ├── luasnip/ │ │ │ └── lua/ │ │ │ └── luasnip/ │ │ │ └── init.lua │ │ ├── nvim-autopairs/ │ │ │ └── lua/ │ │ │ └── nvim-autopairs/ │ │ │ └── init.lua │ │ └── nvim-cmp/ │ │ └── lua/ │ │ └── cmp/ │ │ └── init.lua │ └── tree-sitter-tests.lua ├── dir-map/ │ ├── lua/ │ │ └── gitsigns.lua │ ├── mock-diagnostic.lua │ ├── resolution_1x2 │ ├── resolution_2x1 │ ├── resolution_2x2 │ ├── resolution_3x2 │ ├── resolution_4x2 │ └── src-test-integration.lua ├── dir-misc/ │ ├── Makefile │ ├── aaa.lua │ ├── dir/ │ │ ├── lang.aaa │ │ ├── subdir/ │ │ │ └── lang.aaa │ │ └── subdir-2/ │ │ └── lang.aaa │ ├── init-restore-cursor.lua │ ├── lang.aaa │ ├── mocked-git-repo/ │ │ └── bbb.lua │ ├── pack/ │ │ └── bundle/ │ │ └── opt/ │ │ └── mocked-lang-plugin/ │ │ ├── ftdetect/ │ │ │ └── aaa.lua │ │ └── ftplugin/ │ │ ├── aaa.lua │ │ └── lang-aaa.lua │ └── restore-cursor.lua ├── dir-pick/ │ ├── builtin-tests/ │ │ ├── dir1/ │ │ │ ├── file1-1 │ │ │ └── file1-2 │ │ ├── dir2/ │ │ │ └── file2-1 │ │ └── file │ ├── file │ ├── lua/ │ │ └── nvim-web-devicons.lua │ ├── mocks/ │ │ └── spawn.lua │ └── real-files/ │ ├── LICENSE │ ├── Makefile │ ├── a.lua │ └── b.txt ├── dir-sessions/ │ ├── global/ │ │ ├── .session │ │ ├── session1 │ │ ├── session2.vim │ │ ├── session3.lua │ │ ├── session_cd_global │ │ ├── session_cd_local │ │ └── session_cd_local_2 │ ├── init-files/ │ │ ├── autoread.lua │ │ └── autowrite.lua │ └── local/ │ └── alternative-local-session ├── dir-snippets/ │ ├── .styluaignore │ ├── bad-file-cant-decode.json │ ├── bad-file-cant-execute.lua │ ├── bad-file-not-dict-object.json │ ├── bad-file-not-table-return.lua │ ├── file-array.code-snippets │ ├── file-array.json │ ├── file-array.lua │ ├── file-dict.code-snippets │ ├── file-dict.json │ ├── file-dict.lua │ ├── file-dynamic-snippets.lua │ ├── file.many.dots.lua │ ├── file.notsupported │ ├── snippets/ │ │ ├── lua.json │ │ ├── lua.lua │ │ └── nested/ │ │ ├── lua.json │ │ └── lua.lua │ └── subdir/ │ └── snippets/ │ ├── lua/ │ │ ├── deeper/ │ │ │ └── another.json │ │ ├── file.json │ │ └── snips.lua │ ├── lua.code-snippets │ └── lua.json ├── dir-starter/ │ ├── dir/ │ │ ├── file1 │ │ ├── file3 │ │ └── subdir/ │ │ └── file2 │ ├── directory/ │ │ └── file │ ├── init-files/ │ │ └── test-init.lua │ └── sessions/ │ └── session_global.lua ├── dir-statusline/ │ ├── lua/ │ │ └── nvim-web-devicons.lua │ └── mock-diagnostics.lua ├── dir-surround/ │ └── mock-nvim-treesitter/ │ └── lua/ │ └── nvim-treesitter/ │ ├── init.lua │ ├── parsers.lua │ └── query.lua ├── dir-tabline/ │ ├── bad%new.dir/ │ │ └── aaa.lua │ ├── dir1/ │ │ ├── aaa │ │ ├── bad%new.file.lua │ │ └── dir_nested/ │ │ └── aaa │ ├── dir2/ │ │ ├── aaa │ │ └── dir_nested/ │ │ └── aaa │ └── lua/ │ └── nvim-web-devicons.lua ├── dir-test/ │ ├── init_stdout-reporter_works.lua │ ├── intermediate-screenshot │ ├── reference-screenshot │ ├── testref_case-helpers.lua │ ├── testref_collect-busted.lua │ ├── testref_custom-script.lua │ ├── testref_general.lua │ ├── testref_new-set.lua │ ├── testref_reporters.lua │ ├── testref_run-data.lua │ ├── testref_run-hooks.lua │ ├── testref_run-n_retry-stop_on_error.lua │ ├── testref_run-n_retry.lua │ ├── testref_run-parametrize-error.lua │ ├── testref_run-parametrize.lua │ ├── testref_run.lua │ ├── tests-test_test.lua---expect---reference_screenshot()---respects-`opts.directory` │ └── tests-test_test.lua---expect---reference_screenshot()---respects-`opts.directory`-002 ├── dir-trailspace/ │ └── file ├── dir-visits/ │ ├── dir_1/ │ │ ├── file_1-1 │ │ ├── file_1-2 │ │ ├── file_1-3 │ │ └── subdir/ │ │ └── file_1-1-1 │ ├── dir_2/ │ │ └── file_2-1 │ └── file ├── helpers.lua ├── mock-lsp/ │ ├── extra.lua │ ├── fruits.lua │ └── months.lua ├── mock-system/ │ └── vim-system.lua ├── mock-treesitter/ │ ├── lua-file.lua │ └── queries/ │ └── lua/ │ └── textobjects.scm ├── screenshots/ │ ├── tests-dir-test-testref_run-n_retry.lua---screenshot-number---test │ ├── tests-test_ai.lua---Builtin---User-prompt---colors-its-prompts │ ├── tests-test_ai.lua---Builtin---User-prompt---colors-its-prompts-002 │ ├── tests-test_ai.lua---Builtin---User-prompt---colors-its-prompts-003 │ ├── tests-test_ai.lua---Textobject---respects-`config.silent` │ ├── tests-test_ai.lua---Textobject---shows-reminder-after-one-idle-second---test-+-args-{-'a'-} │ ├── tests-test_ai.lua---Textobject---shows-reminder-after-one-idle-second---test-+-args-{-'a'-}-002 │ ├── tests-test_ai.lua---Textobject---shows-reminder-after-one-idle-second---test-+-args-{-'i'-} │ ├── tests-test_ai.lua---Textobject---shows-reminder-after-one-idle-second---test-+-args-{-'i'-}-002 │ ├── tests-test_align.lua---Align---cleans-command-line-only-if-state-was-shown │ ├── tests-test_align.lua---Align---respects-`config.silent` │ ├── tests-test_align.lua---Align---showing-state-does-not-cause-hit-enter-prompt │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Normal'-} │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Normal'-}-002 │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Normal'-}-003 │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Normal'-}-004 │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Normal'-}-005 │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Normal'-}-006 │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Visual'-} │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Visual'-}-002 │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Visual'-}-003 │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Visual'-}-004 │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Visual'-}-005 │ ├── tests-test_align.lua---Align---shows-state-after-one-idle-second---test-+-args-{-'Visual'-}-006 │ ├── tests-test_align.lua---Align-with-preview---correctly-restores-visual-selection---test-+-args-{-'Visual-block'-} │ ├── tests-test_align.lua---Align-with-preview---correctly-restores-visual-selection---test-+-args-{-'Visual-block'-}-002 │ ├── tests-test_align.lua---Align-with-preview---correctly-restores-visual-selection---test-+-args-{-'Visual-char'-} │ ├── tests-test_align.lua---Align-with-preview---correctly-restores-visual-selection---test-+-args-{-'Visual-char'-}-002 │ ├── tests-test_align.lua---Align-with-preview---correctly-restores-visual-selection---test-+-args-{-'Visual-line'-} │ ├── tests-test_align.lua---Align-with-preview---correctly-restores-visual-selection---test-+-args-{-'Visual-line'-}-002 │ ├── tests-test_align.lua---Align-with-preview---correctly-shows-all-steps-in-status │ ├── tests-test_align.lua---Align-with-preview---respects-`config.silent` │ ├── tests-test_align.lua---Align-with-preview---uses-option-names-for-main-steps │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-block'-} │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-block'-}-002 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-block'-}-003 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-block'-}-004 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-block'-}-005 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-char'-} │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-char'-}-002 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-char'-}-003 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-char'-}-004 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-char'-}-005 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-line'-} │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-line'-}-002 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-line'-}-003 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-line'-}-004 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Normal-line'-}-005 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-block'-} │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-block'-}-002 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-block'-}-003 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-block'-}-004 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-block'-}-005 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-char'-} │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-char'-}-002 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-char'-}-003 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-char'-}-004 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-char'-}-005 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-line'-} │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-line'-}-002 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-line'-}-003 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-line'-}-004 │ ├── tests-test_align.lua---Align-with-preview---works---test-+-args-{-'Visual-line'-}-005 │ ├── tests-test_align.lua---Modifiers----BS----does-nothing-if-no-pre-steps │ ├── tests-test_align.lua---Modifiers----BS----does-nothing-if-no-pre-steps-002 │ ├── tests-test_align.lua---Modifiers----BS----prompts-to-choose-if-ambiguous │ ├── tests-test_align.lua---Modifiers----BS----prompts-to-choose-if-ambiguous-002 │ ├── tests-test_align.lua---Modifiers----BS----prompts-to-choose-if-ambiguous-003 │ ├── tests-test_align.lua---Modifiers----BS----prompts-to-choose-if-ambiguous-004 │ ├── tests-test_align.lua---Modifiers----BS----prompts-to-choose-if-ambiguous-005 │ ├── tests-test_align.lua---Modifiers----BS----works---test-+-args-{-'pre_justify'-} │ ├── tests-test_align.lua---Modifiers----BS----works---test-+-args-{-'pre_justify'-}-002 │ ├── tests-test_align.lua---Modifiers----BS----works---test-+-args-{-'pre_merge'-} │ ├── tests-test_align.lua---Modifiers----BS----works---test-+-args-{-'pre_merge'-}-002 │ ├── tests-test_align.lua---Modifiers----BS----works---test-+-args-{-'pre_split'-} │ ├── tests-test_align.lua---Modifiers----BS----works---test-+-args-{-'pre_split'-}-002 │ ├── tests-test_align.lua---Modifiers----bar- │ ├── tests-test_align.lua---Modifiers----bar--002 │ ├── tests-test_align.lua---Modifiers----comma- │ ├── tests-test_align.lua---Modifiers----comma--002 │ ├── tests-test_align.lua---Modifiers----equal-sign- │ ├── tests-test_align.lua---Modifiers----equal-sign--002 │ ├── tests-test_align.lua---Modifiers----space-bar- │ ├── tests-test_align.lua---Modifiers----space-bar--002 │ ├── tests-test_align.lua---Modifiers---f---allows-empty-input │ ├── tests-test_align.lua---Modifiers---f---works │ ├── tests-test_align.lua---Modifiers---i---works │ ├── tests-test_align.lua---Modifiers---i---works-002 │ ├── tests-test_align.lua---Modifiers---j---works---test-+-args-{-'c'-} │ ├── tests-test_align.lua---Modifiers---j---works---test-+-args-{-'c'-}-002 │ ├── tests-test_align.lua---Modifiers---j---works---test-+-args-{-'l'-} │ ├── tests-test_align.lua---Modifiers---j---works---test-+-args-{-'l'-}-002 │ ├── tests-test_align.lua---Modifiers---j---works---test-+-args-{-'n'-} │ ├── tests-test_align.lua---Modifiers---j---works---test-+-args-{-'n'-}-002 │ ├── tests-test_align.lua---Modifiers---j---works---test-+-args-{-'r'-} │ ├── tests-test_align.lua---Modifiers---j---works---test-+-args-{-'r'-}-002 │ ├── tests-test_align.lua---Modifiers---j---works---test-+-args-{-'u'-} │ ├── tests-test_align.lua---Modifiers---j---works---test-+-args-{-'u'-}-002 │ ├── tests-test_align.lua---Modifiers---m---works │ ├── tests-test_align.lua---Modifiers---m---works-002 │ ├── tests-test_align.lua---Modifiers---p---works │ ├── tests-test_align.lua---Modifiers---s---works │ ├── tests-test_align.lua---Modifiers---s---works-002 │ ├── tests-test_align.lua---Modifiers---t---works │ ├── tests-test_animate.lua---Cursor---can-have-only-one-animation-active │ ├── tests-test_animate.lua---Cursor---can-have-only-one-animation-active-002 │ ├── tests-test_animate.lua---Cursor---can-have-only-one-animation-active-003 │ ├── tests-test_animate.lua---Cursor---can-have-only-one-animation-active-004 │ ├── tests-test_animate.lua---Cursor---does-not-stop-if-mark-should-be-placed-outside-of-range │ ├── tests-test_animate.lua---Cursor---does-not-stop-if-mark-should-be-placed-outside-of-range-002 │ ├── tests-test_animate.lua---Cursor---does-not-stop-if-mark-should-be-placed-outside-of-range-003 │ ├── tests-test_animate.lua---Cursor---does-not-stop-if-mark-should-be-placed-outside-of-range-004 │ ├── tests-test_animate.lua---Cursor---does-not-stop-if-mark-should-be-placed-outside-of-range-005 │ ├── tests-test_animate.lua---Cursor---does-not-stop-if-mark-should-be-placed-outside-of-range-006 │ ├── tests-test_animate.lua---Cursor---is-not-animated-if-`path`-output-is-empty-or-`nil` │ ├── tests-test_animate.lua---Cursor---is-not-animated-if-`path`-output-is-empty-or-`nil`-002 │ ├── tests-test_animate.lua---Cursor---respects-`enable`-config-setting │ ├── tests-test_animate.lua---Cursor---respects-`vim.{g,b}.minianimate_disable`---test-+-args-{-'b'-} │ ├── tests-test_animate.lua---Cursor---respects-`vim.{g,b}.minianimate_disable`---test-+-args-{-'b'-}-002 │ ├── tests-test_animate.lua---Cursor---respects-`vim.{g,b}.minianimate_disable`---test-+-args-{-'g'-} │ ├── tests-test_animate.lua---Cursor---respects-`vim.{g,b}.minianimate_disable`---test-+-args-{-'g'-}-002 │ ├── tests-test_animate.lua---Cursor---respects-buffer-local-config │ ├── tests-test_animate.lua---Cursor---stops-on-buffer-change │ ├── tests-test_animate.lua---Cursor---stops-on-buffer-change-002 │ ├── tests-test_animate.lua---Cursor---stops-on-buffer-change-003 │ ├── tests-test_animate.lua---Cursor---stops-on-buffer-change-004 │ ├── tests-test_animate.lua---Cursor---stops-on-buffer-change-005 │ ├── tests-test_animate.lua---Cursor---works │ ├── tests-test_animate.lua---Cursor---works-002 │ ├── tests-test_animate.lua---Cursor---works-003 │ ├── tests-test_animate.lua---Cursor---works-004 │ ├── tests-test_animate.lua---Cursor---works-005 │ ├── tests-test_animate.lua---Cursor---works-when-cursor-and-or-marks-are-outside-of-line │ ├── tests-test_animate.lua---Cursor---works-when-cursor-and-or-marks-are-outside-of-line-002 │ ├── tests-test_animate.lua---Cursor---works-when-cursor-and-or-marks-are-outside-of-line-003 │ ├── tests-test_animate.lua---Cursor---works-when-cursor-and-or-marks-are-outside-of-line-004 │ ├── tests-test_animate.lua---Cursor---works-when-cursor-and-or-marks-are-outside-of-line-005 │ ├── tests-test_animate.lua---Cursor---works-when-cursor-and-or-marks-are-outside-of-line-006 │ ├── tests-test_animate.lua---Cursor---works-when-cursor-and-or-marks-are-outside-of-line-007 │ ├── tests-test_animate.lua---Cursor---works-when-cursor-and-or-marks-are-outside-of-line-008 │ ├── tests-test_animate.lua---Cursor---works-when-cursor-and-or-marks-are-outside-of-line-009 │ ├── tests-test_animate.lua---Cursor---works-when-movement-is-triggered-by-outside-command │ ├── tests-test_animate.lua---Cursor---works-when-movement-is-triggered-by-outside-command-002 │ ├── tests-test_animate.lua---Cursor---works-when-movement-is-triggered-by-outside-command-003 │ ├── tests-test_animate.lua---Cursor---works-when-movement-is-triggered-by-outside-command-004 │ ├── tests-test_animate.lua---Cursor---works-when-movement-is-triggered-by-outside-command-005 │ ├── tests-test_animate.lua---Cursor---works-with-horizontally-scrolled-window-view │ ├── tests-test_animate.lua---Cursor---works-with-horizontally-scrolled-window-view-002 │ ├── tests-test_animate.lua---Cursor---works-with-horizontally-scrolled-window-view-003 │ ├── tests-test_animate.lua---Cursor---works-with-horizontally-scrolled-window-view-004 │ ├── tests-test_animate.lua---Cursor---works-with-horizontally-scrolled-window-view-005 │ ├── tests-test_animate.lua---Cursor---works-with-multibyte-characters │ ├── tests-test_animate.lua---Cursor---works-with-multibyte-characters-002 │ ├── tests-test_animate.lua---Cursor---works-with-multibyte-characters-003 │ ├── tests-test_animate.lua---Cursor---works-with-multibyte-characters-004 │ ├── tests-test_animate.lua---Cursor---works-with-multibyte-characters-005 │ ├── tests-test_animate.lua---Cursor---works-with-multibyte-characters-006 │ ├── tests-test_animate.lua---Cursor---works-with-multibyte-characters-007 │ ├── tests-test_animate.lua---Cursor---works-with-multibyte-characters-008 │ ├── tests-test_animate.lua---Cursor---works-with-tabs │ ├── tests-test_animate.lua---Cursor---works-with-tabs-002 │ ├── tests-test_animate.lua---Cursor---works-with-tabs-003 │ ├── tests-test_animate.lua---Cursor---works-with-tabs-004 │ ├── tests-test_animate.lua---Cursor---works-with-tabs-005 │ ├── tests-test_animate.lua---Cursor---works-with-tabs-006 │ ├── tests-test_animate.lua---Resize---allows-immediate-another-resize-animation │ ├── tests-test_animate.lua---Resize---allows-immediate-another-resize-animation-002 │ ├── tests-test_animate.lua---Resize---allows-immediate-another-resize-animation-003 │ ├── tests-test_animate.lua---Resize---allows-immediate-another-resize-animation-004 │ ├── tests-test_animate.lua---Resize---allows-immediate-another-resize-animation-005 │ ├── tests-test_animate.lua---Resize---allows-immediate-another-resize-animation-006 │ ├── tests-test_animate.lua---Resize---allows-immediate-another-resize-animation-007 │ ├── tests-test_animate.lua---Resize---allows-immediate-another-resize-animation-008 │ ├── tests-test_animate.lua---Resize---allows-immediate-another-resize-animation-009 │ ├── tests-test_animate.lua---Resize---animates-only-for-equal-layouts │ ├── tests-test_animate.lua---Resize---animates-only-for-equal-layouts-002 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-002 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-003 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-004 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-005 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-006 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-in-current-window │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-in-current-window-002 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-in-current-window-003 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-in-current-window-004 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-in-current-window-005 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-in-current-window-006 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-in-current-window-007 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-in-current-window-008 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-in-current-window-009 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-in-current-window-010 │ ├── tests-test_animate.lua---Resize---does-not-flicker-due-to-high-cursor-column-in-current-window-011 │ ├── tests-test_animate.lua---Resize---is-not-animated-if-`subresize`-output-is-empty-or-`nil` │ ├── tests-test_animate.lua---Resize---is-not-animated-if-`subresize`-output-is-empty-or-`nil`-002 │ ├── tests-test_animate.lua---Resize---respects-`enable`-config-setting │ ├── tests-test_animate.lua---Resize---respects-`vim.{g,b}.minianimate_disable`---test-+-args-{-'b'-} │ ├── tests-test_animate.lua---Resize---respects-`vim.{g,b}.minianimate_disable`---test-+-args-{-'b'-}-002 │ ├── tests-test_animate.lua---Resize---respects-`vim.{g,b}.minianimate_disable`---test-+-args-{-'b'-}-003 │ ├── tests-test_animate.lua---Resize---respects-`vim.{g,b}.minianimate_disable`---test-+-args-{-'g'-} │ ├── tests-test_animate.lua---Resize---respects-`vim.{g,b}.minianimate_disable`---test-+-args-{-'g'-}-002 │ ├── tests-test_animate.lua---Resize---respects-`vim.{g,b}.minianimate_disable`---test-+-args-{-'g'-}-003 │ ├── tests-test_animate.lua---Resize---respects-buffer-local-config │ ├── tests-test_animate.lua---Resize---works │ ├── tests-test_animate.lua---Resize---works-002 │ ├── tests-test_animate.lua---Resize---works-003 │ ├── tests-test_animate.lua---Resize---works-004 │ ├── tests-test_animate.lua---Resize---works-005 │ ├── tests-test_animate.lua---Resize---works-006 │ ├── tests-test_animate.lua---Resize---works-007 │ ├── tests-test_animate.lua---Resize---works-008 │ ├── tests-test_animate.lua---Resize---works-009 │ ├── tests-test_animate.lua---Resize---works-010 │ ├── tests-test_animate.lua---Resize---works-011 │ ├── tests-test_animate.lua---Resize---works-012 │ ├── tests-test_animate.lua---Resize---works-013 │ ├── tests-test_animate.lua---Resize---works-014 │ ├── tests-test_animate.lua---Resize---works-015 │ ├── tests-test_animate.lua---Resize---works-016 │ ├── tests-test_animate.lua---Resize---works-017 │ ├── tests-test_animate.lua---Resize---works-when-resize-is-triggered-by-outside-command │ ├── tests-test_animate.lua---Resize---works-when-resize-is-triggered-by-outside-command-002 │ ├── tests-test_animate.lua---Resize---works-when-resize-is-triggered-by-outside-command-003 │ ├── tests-test_animate.lua---Resize---works-when-resize-is-triggered-by-outside-command-004 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth` │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-002 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-003 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-004 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-005 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-006 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-007 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-008 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-009 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-010 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-011 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-012 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-013 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-014 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-015 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-016 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-017 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-018 │ ├── tests-test_animate.lua---Resize---works-with-`winheight`-`winwidth`-019 │ ├── tests-test_animate.lua---Scroll---allows-immediate-another-scroll-animation │ ├── tests-test_animate.lua---Scroll---allows-immediate-another-scroll-animation-002 │ ├── tests-test_animate.lua---Scroll---allows-immediate-another-scroll-animation-003 │ ├── tests-test_animate.lua---Scroll---allows-immediate-another-scroll-animation-004 │ ├── tests-test_animate.lua---Scroll---allows-immediate-another-scroll-animation-005 │ ├── tests-test_animate.lua---Scroll---allows-immediate-another-scroll-animation-006 │ ├── tests-test_animate.lua---Scroll---does-not-animate-in-Select-mode │ ├── tests-test_animate.lua---Scroll---does-not-automatically-animate-after-buffer-change │ ├── tests-test_animate.lua---Scroll---does-not-automatically-animate-after-buffer-change-002 │ ├── tests-test_animate.lua---Scroll---does-not-automatically-animate-result-of-'incsearch' │ ├── tests-test_animate.lua---Scroll---does-not-automatically-animate-result-of-'incsearch'-002 │ ├── tests-test_animate.lua---Scroll---does-not-automatically-animate-result-of-'incsearch'-003 │ ├── tests-test_animate.lua---Scroll---does-not-automatically-animate-result-of-'incsearch'-004 │ ├── tests-test_animate.lua---Scroll---handles-mappings-with--Cmd--CR- │ ├── tests-test_animate.lua---Scroll---handles-mappings-with--Cmd--CR--002 │ ├── tests-test_animate.lua---Scroll---respects-'scrolloff'-in-presence-of-folds │ ├── tests-test_animate.lua---Scroll---respects-'scrolloff'-in-presence-of-folds-002 │ ├── tests-test_animate.lua---Scroll---respects-'scrolloff'-in-presence-of-folds-003 │ ├── tests-test_animate.lua---Scroll---respects-'scrolloff'-in-presence-of-folds-004 │ ├── tests-test_animate.lua---Scroll---respects-'scrolloff'-in-presence-of-folds-005 │ ├── tests-test_animate.lua---Scroll---respects-folds │ ├── tests-test_animate.lua---Scroll---respects-folds-002 │ ├── tests-test_animate.lua---Scroll---respects-folds-003 │ ├── tests-test_animate.lua---Scroll---respects-folds-004 │ ├── tests-test_animate.lua---Scroll---respects-folds-005 │ ├── tests-test_animate.lua---Scroll---respects-global-'scrolloff' │ ├── tests-test_animate.lua---Scroll---respects-global-'scrolloff'-002 │ ├── tests-test_animate.lua---Scroll---respects-global-'scrolloff'-003 │ ├── tests-test_animate.lua---Scroll---respects-global-'scrolloff'-004 │ ├── tests-test_animate.lua---Scroll---respects-global-'scrolloff'-005 │ ├── tests-test_animate.lua---Scroll---respects-window-local-'scrolloff' │ ├── tests-test_animate.lua---Scroll---respects-window-local-'scrolloff'-002 │ ├── tests-test_animate.lua---Scroll---respects-window-local-'scrolloff'-003 │ ├── tests-test_animate.lua---Scroll---respects-window-local-'scrolloff'-004 │ ├── tests-test_animate.lua---Scroll---respects-window-local-'scrolloff'-005 │ ├── tests-test_animate.lua---Scroll---stops-on-buffer-change │ ├── tests-test_animate.lua---Scroll---stops-on-buffer-change-002 │ ├── tests-test_animate.lua---Scroll---stops-on-buffer-change-003 │ ├── tests-test_animate.lua---Scroll---stops-on-buffer-change-004 │ ├── tests-test_animate.lua---Scroll---stops-on-window-change │ ├── tests-test_animate.lua---Scroll---stops-on-window-change-002 │ ├── tests-test_animate.lua---Scroll---stops-on-window-change-003 │ ├── tests-test_animate.lua---Scroll---stops-on-window-change-004 │ ├── tests-test_animate.lua---Scroll---works │ ├── tests-test_animate.lua---Scroll---works-002 │ ├── tests-test_animate.lua---Scroll---works-003 │ ├── tests-test_animate.lua---Scroll---works-004 │ ├── tests-test_animate.lua---Scroll---works-005 │ ├── tests-test_animate.lua---Scroll---works-006 │ ├── tests-test_animate.lua---Scroll---works-007 │ ├── tests-test_animate.lua---Scroll---works-008 │ ├── tests-test_animate.lua---Scroll---works-009 │ ├── tests-test_animate.lua---Scroll---works-010 │ ├── tests-test_animate.lua---Scroll---works-properly-just-after-buffer-change │ ├── tests-test_animate.lua---Scroll---works-properly-just-after-buffer-change-002 │ ├── tests-test_animate.lua---Scroll---works-properly-just-after-window-change │ ├── tests-test_animate.lua---Scroll---works-properly-just-after-window-change-002 │ ├── tests-test_animate.lua---Scroll---works-when-movement-is-triggered-by-outside-command │ ├── tests-test_animate.lua---Scroll---works-when-movement-is-triggered-by-outside-command-002 │ ├── tests-test_animate.lua---Scroll---works-when-movement-is-triggered-by-outside-command-003 │ ├── tests-test_animate.lua---Scroll---works-when-movement-is-triggered-by-outside-command-004 │ ├── tests-test_animate.lua---Scroll---works-when-movement-is-triggered-by-outside-command-005 │ ├── tests-test_basics.lua---Mappings---Toggle-options---respects-`config.silent` │ ├── tests-test_basics.lua---Mappings---Toggle-options---shows-feedback-about-new-value │ ├── tests-test_clue.lua---'mini.nvim'-compatibility---mini.align │ ├── tests-test_clue.lua---'mini.nvim'-compatibility---mini.align-002 │ ├── tests-test_clue.lua---Clues---are-properly-sorted │ ├── tests-test_clue.lua---Clues---can-be-configured-after-load │ ├── tests-test_clue.lua---Clues---can-be-overridden-in-later-entries │ ├── tests-test_clue.lua---Clues---can-have-callable-description │ ├── tests-test_clue.lua---Clues---can-have-callables │ ├── tests-test_clue.lua---Clues---can-have-callables-002 │ ├── tests-test_clue.lua---Clues---can-have-callables-003 │ ├── tests-test_clue.lua---Clues---can-have-callables-004 │ ├── tests-test_clue.lua---Clues---can-have-nested-subarrays │ ├── tests-test_clue.lua---Clues---handles-an-array-of-modes │ ├── tests-test_clue.lua---Clues---handles-an-array-of-modes-002 │ ├── tests-test_clue.lua---Clues---handles-no-description │ ├── tests-test_clue.lua---Clues---handles-showing-group-clues-after-executing-key-with-postkeys │ ├── tests-test_clue.lua---Clues---handles-showing-group-clues-after-executing-key-with-postkeys-002 │ ├── tests-test_clue.lua---Clues---has-proper-precedence │ ├── tests-test_clue.lua---Clues---respects-`vim.b.miniclue_config` │ ├── tests-test_clue.lua---Clues---shows-as-group-a-single-non-exact-clue │ ├── tests-test_clue.lua---Clues---shows-as-group-a-single-non-exact-clue-002 │ ├── tests-test_clue.lua---Clues---shows-as-group-a-single-non-exact-clue-003 │ ├── tests-test_clue.lua---Clues---silently-ignores-non-valid-clues │ ├── tests-test_clue.lua---Clues---uses-human-readable-names-for-special-keys │ ├── tests-test_clue.lua---Postkeys---closes-window-if-postkeys-do-not-end-up-key-querying │ ├── tests-test_clue.lua---Postkeys---persists-window-if-action-changes-tabpage │ ├── tests-test_clue.lua---Postkeys---persists-window-if-action-changes-tabpage-002 │ ├── tests-test_clue.lua---Postkeys---shows-window-immediately │ ├── tests-test_clue.lua---Postkeys---works │ ├── tests-test_clue.lua---Postkeys---works-002 │ ├── tests-test_clue.lua---Postkeys---works-003 │ ├── tests-test_clue.lua---Postkeys---works-in-edge-cases │ ├── tests-test_clue.lua---Postkeys---works-in-edge-cases-002 │ ├── tests-test_clue.lua---Postkeys---works-in-edge-cases-003 │ ├── tests-test_clue.lua---Querying-keys---does-not-entirely-block-redraws │ ├── tests-test_clue.lua---Querying-keys---does-not-entirely-block-redraws-002 │ ├── tests-test_clue.lua---Querying-keys---takes-into-account-user-supplied-clues │ ├── tests-test_clue.lua---Querying-keys---takes-into-account-user-supplied-clues-002 │ ├── tests-test_clue.lua---Showing-keys---allows-zero-delay │ ├── tests-test_clue.lua---Showing-keys---can-have-'auto'-for-`row`-and-`col`-in-window-config │ ├── tests-test_clue.lua---Showing-keys---can-have-'auto'-for-`row`-and-`col`-in-window-config-002 │ ├── tests-test_clue.lua---Showing-keys---can-have-'auto'-for-`row`-and-`col`-in-window-config-003 │ ├── tests-test_clue.lua---Showing-keys---can-have-'auto'-for-`row`-and-`col`-in-window-config-004 │ ├── tests-test_clue.lua---Showing-keys---can-have-`config.window.config.width='auto'` │ ├── tests-test_clue.lua---Showing-keys---can-have-callable-`config.window.config` │ ├── tests-test_clue.lua---Showing-keys---can-work-with-small-instance-dimensions │ ├── tests-test_clue.lua---Showing-keys---does-not-trigger-unnecessary-events │ ├── tests-test_clue.lua---Showing-keys---highlights-group-descriptions-differently │ ├── tests-test_clue.lua---Showing-keys---highlights-next-key-with-postkeys-differently │ ├── tests-test_clue.lua---Showing-keys---indicates-that-description-is-truncated │ ├── tests-test_clue.lua---Showing-keys---properly-translates-special-keys │ ├── tests-test_clue.lua---Showing-keys---properly-translates-special-keys-002 │ ├── tests-test_clue.lua---Showing-keys---properly-translates-special-keys-003 │ ├── tests-test_clue.lua---Showing-keys---properly-translates-special-keys-004 │ ├── tests-test_clue.lua---Showing-keys---reacts-to-`VimResized` │ ├── tests-test_clue.lua---Showing-keys---reacts-to-`VimResized`-002 │ ├── tests-test_clue.lua---Showing-keys---respects-'winborder'-option │ ├── tests-test_clue.lua---Showing-keys---respects-'winborder'-option-002 │ ├── tests-test_clue.lua---Showing-keys---respects-'winborder'-option-003 │ ├── tests-test_clue.lua---Showing-keys---respects-`config.window.config` │ ├── tests-test_clue.lua---Showing-keys---respects-`config.window.config`-002 │ ├── tests-test_clue.lua---Showing-keys---respects-`config.window.delay` │ ├── tests-test_clue.lua---Showing-keys---respects-`config.window.delay`-002 │ ├── tests-test_clue.lua---Showing-keys---respects-`config.window.delay`-003 │ ├── tests-test_clue.lua---Showing-keys---respects-`scroll_down`-and-`scroll_up`-in-`config.window` │ ├── tests-test_clue.lua---Showing-keys---respects-`scroll_down`-and-`scroll_up`-in-`config.window`-002 │ ├── tests-test_clue.lua---Showing-keys---respects-`scroll_down`-and-`scroll_up`-in-`config.window`-003 │ ├── tests-test_clue.lua---Showing-keys---respects-`scroll_down`-and-`scroll_up`-in-`config.window`-004 │ ├── tests-test_clue.lua---Showing-keys---respects-`scroll_down`-and-`scroll_up`-in-`config.window`-005 │ ├── tests-test_clue.lua---Showing-keys---respects-`scroll_down`-and-`scroll_up`-in-`config.window`-006 │ ├── tests-test_clue.lua---Showing-keys---respects-`scroll_down`-and-`scroll_up`-in-`config.window`-007 │ ├── tests-test_clue.lua---Showing-keys---respects-`scroll_down`-and-`scroll_up`-in-`config.window`-008 │ ├── tests-test_clue.lua---Showing-keys---respects-`scroll_down`-and-`scroll_up`-in-`config.window`-009 │ ├── tests-test_clue.lua---Showing-keys---respects-`scroll_down`-and-`scroll_up`-in-`config.window`-010 │ ├── tests-test_clue.lua---Showing-keys---respects-`vim.b.miniclue_config` │ ├── tests-test_clue.lua---Showing-keys---respects-tabline,-statusline,-cmdheight │ ├── tests-test_clue.lua---Showing-keys---respects-tabline,-statusline,-cmdheight-002 │ ├── tests-test_clue.lua---Showing-keys---respects-tabline,-statusline,-cmdheight-003 │ ├── tests-test_clue.lua---Showing-keys---respects-tabline,-statusline,-cmdheight-004 │ ├── tests-test_clue.lua---Showing-keys---scroll-is-not-persistent │ ├── tests-test_clue.lua---Showing-keys---scroll-is-not-persistent-002 │ ├── tests-test_clue.lua---Showing-keys---scroll-is-not-persistent-003 │ ├── tests-test_clue.lua---Showing-keys---uses-query-clue-as-title │ ├── tests-test_clue.lua---Showing-keys---uses-query-clue-as-title-002 │ ├── tests-test_clue.lua---Showing-keys---uses-query-clue-as-title-003 │ ├── tests-test_clue.lua---Showing-keys---uses-query-clue-as-title-004 │ ├── tests-test_clue.lua---Showing-keys---uses-query-clue-as-title-005 │ ├── tests-test_clue.lua---Showing-keys---uses-query-clue-as-title-006 │ ├── tests-test_clue.lua---Showing-keys---uses-query-clue-as-title-007 │ ├── tests-test_clue.lua---Showing-keys---uses-query-clue-as-title-008 │ ├── tests-test_clue.lua---Showing-keys---works │ ├── tests-test_clue.lua---Showing-keys---works-002 │ ├── tests-test_clue.lua---Showing-keys---works-003 │ ├── tests-test_clue.lua---Showing-keys---works-in-Command-line-window │ ├── tests-test_clue.lua---Showing-keys---works-in-Command-line-window-002 │ ├── tests-test_clue.lua---Showing-keys---works-with-multibyte-characters │ ├── tests-test_clue.lua---Showing-keys---works-with-multibyte-characters-002 │ ├── tests-test_clue.lua---Showing-keys---works-with-small-available-dimensions │ ├── tests-test_clue.lua---ensure_all_triggers()---works │ ├── tests-test_clue.lua---ensure_all_triggers()---works-002 │ ├── tests-test_clue.lua---ensure_buf_triggers()---works │ ├── tests-test_clue.lua---gen_clues---builtin_completion()---works │ ├── tests-test_clue.lua---gen_clues---g()---works │ ├── tests-test_clue.lua---gen_clues---g()---works-002 │ ├── tests-test_clue.lua---gen_clues---marks()---works │ ├── tests-test_clue.lua---gen_clues---marks()---works-002 │ ├── tests-test_clue.lua---gen_clues---marks()---works-003 │ ├── tests-test_clue.lua---gen_clues---marks()---works-004 │ ├── tests-test_clue.lua---gen_clues---marks()---works-005 │ ├── tests-test_clue.lua---gen_clues---marks()---works-006 │ ├── tests-test_clue.lua---gen_clues---marks()---works-007 │ ├── tests-test_clue.lua---gen_clues---marks()---works-008 │ ├── tests-test_clue.lua---gen_clues---registers()---respects-`opts.show_contents` │ ├── tests-test_clue.lua---gen_clues---registers()---works │ ├── tests-test_clue.lua---gen_clues---registers()---works-002 │ ├── tests-test_clue.lua---gen_clues---registers()---works-003 │ ├── tests-test_clue.lua---gen_clues---registers()---works-004 │ ├── tests-test_clue.lua---gen_clues---registers()---works-005 │ ├── tests-test_clue.lua---gen_clues---registers()---works-006 │ ├── tests-test_clue.lua---gen_clues---registers()---works-007 │ ├── tests-test_clue.lua---gen_clues---registers()---works-008 │ ├── tests-test_clue.lua---gen_clues---registers()---works-009 │ ├── tests-test_clue.lua---gen_clues---square_brackets()---works │ ├── tests-test_clue.lua---gen_clues---square_brackets()---works-002 │ ├── tests-test_clue.lua---gen_clues---windows()---works │ ├── tests-test_clue.lua---gen_clues---windows()---works-002 │ ├── tests-test_clue.lua---gen_clues---z()---works │ ├── tests-test_clue.lua---gen_clues---z()---works-002 │ ├── tests-test_clue.lua---setup()---ensures-valid-triggers-on-`LspAttach`-event │ ├── tests-test_cmdline.lua---Autocomplete---is-not-triggered-when-wildmenu-is-visible │ ├── tests-test_cmdline.lua---Autocomplete---works │ ├── tests-test_cmdline.lua---Autocomplete---works-002 │ ├── tests-test_cmdline.lua---Autocomplete---works-003 │ ├── tests-test_cmdline.lua---Autocomplete---works-004 │ ├── tests-test_cmdline.lua---Autocomplete---works-005 │ ├── tests-test_cmdline.lua---Autocomplete---works-in-different-command-types │ ├── tests-test_cmdline.lua---Autocomplete---works-in-different-command-types-002 │ ├── tests-test_cmdline.lua---Autocomplete---works-in-different-command-types-003 │ ├── tests-test_cmdline.lua---Autocomplete---works-in-different-command-types-004 │ ├── tests-test_cmdline.lua---Autocomplete---works-in-edge-cases │ ├── tests-test_cmdline.lua---Autocomplete---works-in-edge-cases-002 │ ├── tests-test_cmdline.lua---Autocomplete---works-in-edge-cases-003 │ ├── tests-test_cmdline.lua---Autocomplete---works-with-different-completion-types │ ├── tests-test_cmdline.lua---Autocomplete---works-with-different-completion-types-002 │ ├── tests-test_cmdline.lua---Autocomplete---works-with-different-completion-types-003 │ ├── tests-test_cmdline.lua---Autopeek---correctly-computes-lines-to-show │ ├── tests-test_cmdline.lua---Autopeek---correctly-computes-lines-to-show-002 │ ├── tests-test_cmdline.lua---Autopeek---correctly-computes-lines-to-show-003 │ ├── tests-test_cmdline.lua---Autopeek---correctly-computes-lines-to-show-004 │ ├── tests-test_cmdline.lua---Autopeek---correctly-computes-lines-to-show-005 │ ├── tests-test_cmdline.lua---Autopeek---correctly-computes-lines-to-show-006 │ ├── tests-test_cmdline.lua---Autopeek---correctly-computes-lines-to-show-007 │ ├── tests-test_cmdline.lua---Autopeek---correctly-computes-lines-to-show-008 │ ├── tests-test_cmdline.lua---Autopeek---correctly-computes-lines-to-show-009 │ ├── tests-test_cmdline.lua---Autopeek---correctly-computes-lines-to-show-010 │ ├── tests-test_cmdline.lua---Autopeek---correctly-shows-window-without-border │ ├── tests-test_cmdline.lua---Autopeek---correctly-shows-window-without-border-002 │ ├── tests-test_cmdline.lua---Autopeek---correctly-shows-window-without-border-003 │ ├── tests-test_cmdline.lua---Autopeek---correctly-shows-window-without-border-004 │ ├── tests-test_cmdline.lua---Autopeek---correctly-shows-window-without-border-005 │ ├── tests-test_cmdline.lua---Autopeek---correctly-shows-window-without-border-006 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-002 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-003 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-004 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-005 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-006 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-007 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-008 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-009 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-010 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-011 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-012 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-013 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-014 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-015 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-016 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-017 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-018 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-019 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-020 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-021 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-022 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-023 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-024 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-025 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-026 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-027 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-028 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-029 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-030 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-031 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-032 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-033 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-034 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-035 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-036 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-037 │ ├── tests-test_cmdline.lua---Autopeek---fits-into-available-height-038 │ ├── tests-test_cmdline.lua---Autopeek---hides-visual-selection │ ├── tests-test_cmdline.lua---Autopeek---hides-visual-selection-002 │ ├── tests-test_cmdline.lua---Autopeek---ignores-'wrap' │ ├── tests-test_cmdline.lua---Autopeek---ignores-'wrap'-002 │ ├── tests-test_cmdline.lua---Autopeek---ignores-'wrap'-003 │ ├── tests-test_cmdline.lua---Autopeek---ignores-'wrap'-004 │ ├── tests-test_cmdline.lua---Autopeek---is-shown-below-pmenu-and--C-d--output │ ├── tests-test_cmdline.lua---Autopeek---persists-for-the-entirety-of-command-typing │ ├── tests-test_cmdline.lua---Autopeek---persists-for-the-entirety-of-command-typing-002 │ ├── tests-test_cmdline.lua---Autopeek---persists-for-the-entirety-of-command-typing-003 │ ├── tests-test_cmdline.lua---Autopeek---reacts-to-`VimResized` │ ├── tests-test_cmdline.lua---Autopeek---reacts-to-`VimResized`-002 │ ├── tests-test_cmdline.lua---Autopeek---reacts-to-`VimResized`-003 │ ├── tests-test_cmdline.lua---Autopeek---reacts-to-`VimResized`-004 │ ├── tests-test_cmdline.lua---Autopeek---reacts-to-command-line-height-change-during-typing │ ├── tests-test_cmdline.lua---Autopeek---reacts-to-command-line-height-change-during-typing-002 │ ├── tests-test_cmdline.lua---Autopeek---reacts-to-command-line-height-change-during-typing-003 │ ├── tests-test_cmdline.lua---Autopeek---respects-'winborder' │ ├── tests-test_cmdline.lua---Autopeek---respects-'winborder'-002 │ ├── tests-test_cmdline.lua---Autopeek---respects-'winborder'-003 │ ├── tests-test_cmdline.lua---Autopeek---respects-`config.autopeek.n_context` │ ├── tests-test_cmdline.lua---Autopeek---respects-`config.autopeek.n_context`-002 │ ├── tests-test_cmdline.lua---Autopeek---respects-`config.autopeek.n_context`-003 │ ├── tests-test_cmdline.lua---Autopeek---respects-`config.autopeek.n_context`-004 │ ├── tests-test_cmdline.lua---Autopeek---respects-`config.autopeek.n_context`-005 │ ├── tests-test_cmdline.lua---Autopeek---respects-`config.autopeek.n_context`-006 │ ├── tests-test_cmdline.lua---Autopeek---respects-`config.autopeek.n_context`-007 │ ├── tests-test_cmdline.lua---Autopeek---respects-`config.autopeek.window.config` │ ├── tests-test_cmdline.lua---Autopeek---respects-`config.autopeek.window.config`-002 │ ├── tests-test_cmdline.lua---Autopeek---respects-`config.autopeek.window.config`-003 │ ├── tests-test_cmdline.lua---Autopeek---respects-`config.autopeek.window.statuscolumn` │ ├── tests-test_cmdline.lua---Autopeek---respects-mappings │ ├── tests-test_cmdline.lua---Autopeek---updates-when-navigating-through-history │ ├── tests-test_cmdline.lua---Autopeek---updates-when-navigating-through-history-002 │ ├── tests-test_cmdline.lua---Autopeek---updates-when-navigating-through-history-003 │ ├── tests-test_cmdline.lua---Autopeek---updates-when-navigating-through-history-004 │ ├── tests-test_cmdline.lua---Autopeek---works │ ├── tests-test_cmdline.lua---Autopeek---works-002 │ ├── tests-test_cmdline.lua---Autopeek---works-003 │ ├── tests-test_cmdline.lua---Autopeek---works-004 │ ├── tests-test_cmdline.lua---Autopeek---works-005 │ ├── tests-test_cmdline.lua---Autopeek---works-006 │ ├── tests-test_cmdline.lua---Autopeek---works-007 │ ├── tests-test_cmdline.lua---Autopeek---works-008 │ ├── tests-test_cmdline.lua---Autopeek---works-009 │ ├── tests-test_cmdline.lua---Autopeek---works-if-range-is-present-immediately │ ├── tests-test_cmdline.lua---Autopeek---works-when-regular-command-line-parsing-fails │ ├── tests-test_cmdline.lua---Autopeek---works-when-regular-command-line-parsing-fails-002 │ ├── tests-test_cmdline.lua---Autopeek---works-when-regular-command-line-parsing-fails-003 │ ├── tests-test_cmdline.lua---Autopeek---works-when-regular-command-line-parsing-fails-004 │ ├── tests-test_cmdline.lua---Autopeek---works-when-regular-command-line-parsing-fails-005 │ ├── tests-test_cmdline.lua---Autopeek---works-when-regular-command-line-parsing-fails-006 │ ├── tests-test_cmdline.lua---Autopeek---works-when-regular-command-line-parsing-fails-007 │ ├── tests-test_cmdline.lua---Autopeek---works-when-regular-command-line-parsing-fails-008 │ ├── tests-test_cmdline.lua---Autopeek---works-when-regular-command-line-parsing-fails-009 │ ├── tests-test_cmdline.lua---Autopeek---works-when-using-command-line-expression-register │ ├── tests-test_cmdline.lua---Autopeek---works-when-using-command-line-expression-register-002 │ ├── tests-test_cmdline.lua---Autopeek---works-with-'inccommand' │ ├── tests-test_cmdline.lua---Autopeek---works-with-'inccommand'-002 │ ├── tests-test_cmdline.lua---Autopeek---works-with-'inccommand'-003 │ ├── tests-test_cmdline.lua---Autopeek---works-with-'inccommand'-004 │ ├── tests-test_cmdline.lua---Autopeek---works-with-'inccommand'-005 │ ├── tests-test_cmdline.lua---Autopeek---works-with-'inccommand'-006 │ ├── tests-test_cmdline.lua---Autopeek---works-with-different-'cmdheight' │ ├── tests-test_cmdline.lua---Autopeek---works-with-different-'cmdheight'-002 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-002 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-003 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-004 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-005 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-006 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-007 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-008 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-009 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-010 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-011 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-012 │ ├── tests-test_cmdline.lua---Autopeek---works-with-every-kind-of-line-range-013 │ ├── tests-test_cmdline.lua---Autopeek---works-with-inverted-range │ ├── tests-test_cmdline.lua---Autopeek---works-with-inverted-range-002 │ ├── tests-test_cmdline.lua---Autopeek---works-with-inverted-range-003 │ ├── tests-test_cmdline.lua---Autopeek---works-with-inverted-range-004 │ ├── tests-test_cmdline.lua---Autopeek---works-with-inverted-range-005 │ ├── tests-test_cmdline.lua---Autopeek---works-with-inverted-range-006 │ ├── tests-test_cmdline.lua---Autopeek---works-with-inverted-range-007 │ ├── tests-test_cmdline.lua---Autopeek---works-with-inverted-range-008 │ ├── tests-test_cmdline.lua---Autopeek---works-with-inverted-range-009 │ ├── tests-test_cmdline.lua---Autopeek---works-with-virtual-lines │ ├── tests-test_cmdline.lua---Autopeek---works-with-virtual-lines-002 │ ├── tests-test_cmdline.lua---Autopeek---works-with-virtual-lines-003 │ ├── tests-test_cmdline.lua---Autopeek---works-with-virtual-lines-004 │ ├── tests-test_cmdline.lua---Autopeek---works-with-virtual-lines-005 │ ├── tests-test_cmdline.lua---Autopeek---works-with-virtual-lines-006 │ ├── tests-test_cmdline.lua---default_autopeek_statuscolumn()---respects-`opts` │ ├── tests-test_cmdline.lua---default_autopeek_statuscolumn()---respects-`opts`-002 │ ├── tests-test_cmdline.lua---default_autopeek_statuscolumn()---respects-`opts`-003 │ ├── tests-test_cmdline.lua---default_autopeek_statuscolumn()---respects-`opts`-004 │ ├── tests-test_cmdline.lua---default_autopeek_statuscolumn()---works │ ├── tests-test_cmdline.lua---default_autopeek_statuscolumn()---works-002 │ ├── tests-test_cmdline.lua---default_autopeek_statuscolumn()---works-003 │ ├── tests-test_cmdline.lua---default_autopeek_statuscolumn()---works-004 │ ├── tests-test_cmdline.lua---default_autopeek_statuscolumn()---works-005 │ ├── tests-test_cmdline.lua---default_autopeek_statuscolumn()---works-006 │ ├── tests-test_cmdline.lua---default_autopeek_statuscolumn()---works-with-wrapped-and-virtual-lines │ ├── tests-test_colors.lua---interactive()---works │ ├── tests-test_colors.lua---interactive()---works-002 │ ├── tests-test_completion.lua---Autocompletion---forces-new-LSP-completion-at-LSP-trigger---test-+-args-{-'completefunc'-} │ ├── tests-test_completion.lua---Autocompletion---forces-new-LSP-completion-at-LSP-trigger---test-+-args-{-'completefunc'-}-002 │ ├── tests-test_completion.lua---Autocompletion---forces-new-LSP-completion-at-LSP-trigger---test-+-args-{-'omnifunc'-} │ ├── tests-test_completion.lua---Autocompletion---forces-new-LSP-completion-at-LSP-trigger---test-+-args-{-'omnifunc'-}-002 │ ├── tests-test_completion.lua---Autocompletion---forces-new-LSP-completion-for-`isIncomplete`-even-if-canceled │ ├── tests-test_completion.lua---Autocompletion---forces-new-LSP-completion-in-case-of-`isIncomplete` │ ├── tests-test_completion.lua---Autocompletion---forces-new-LSP-completion-in-case-of-`isIncomplete`-002 │ ├── tests-test_completion.lua---Autocompletion---forces-new-LSP-completion-in-case-of-`isIncomplete`-003 │ ├── tests-test_completion.lua---Autocompletion---respects-string-`config.fallback_action` │ ├── tests-test_completion.lua---Autocompletion---respects-string-`config.fallback_action`-002 │ ├── tests-test_completion.lua---Autocompletion---works-with-LSP-client │ ├── tests-test_completion.lua---Autocompletion---works-with-`-BS-` │ ├── tests-test_completion.lua---Autocompletion---works-with-`-BS-`-002 │ ├── tests-test_completion.lua---Autocompletion---works-with-`-BS-`-003 │ ├── tests-test_completion.lua---Autocompletion---works-without-LSP-clients │ ├── tests-test_completion.lua---Information-window---accounts-for-border-when-picking-side │ ├── tests-test_completion.lua---Information-window---adjusts-for-top-bottom-code-block-delimiters │ ├── tests-test_completion.lua---Information-window---adjusts-for-top-bottom-code-block-delimiters-002 │ ├── tests-test_completion.lua---Information-window---adjusts-title │ ├── tests-test_completion.lua---Information-window---adjusts-title-002 │ ├── tests-test_completion.lua---Information-window---adjusts-window-width │ ├── tests-test_completion.lua---Information-window---can-be-adjusted-in-event │ ├── tests-test_completion.lua---Information-window---has-minimal-dimensions-for-small-text │ ├── tests-test_completion.lua---Information-window---ignores-data-from-first-response-if-server-can-resolve-completion-item │ ├── tests-test_completion.lua---Information-window---respects-'pumborder'-option │ ├── tests-test_completion.lua---Information-window---respects-'pumborder'-option-002 │ ├── tests-test_completion.lua---Information-window---respects-'pumborder'-option-003 │ ├── tests-test_completion.lua---Information-window---respects-'pumborder'-option-004 │ ├── tests-test_completion.lua---Information-window---respects-'pumborder'-option-005 │ ├── tests-test_completion.lua---Information-window---respects-'pumborder'-option-006 │ ├── tests-test_completion.lua---Information-window---respects-'pumborder'-option-007 │ ├── tests-test_completion.lua---Information-window---respects-'pumborder'-option-008 │ ├── tests-test_completion.lua---Information-window---respects-'pumborder'-option-009 │ ├── tests-test_completion.lua---Information-window---respects-`config.window.info` │ ├── tests-test_completion.lua---Information-window---respects-`config.window.info`-002 │ ├── tests-test_completion.lua---Information-window---stylizes-markdown-with-concealed-characters │ ├── tests-test_completion.lua---Information-window---uses-`detail`-to-construct-content │ ├── tests-test_completion.lua---Information-window---uses-`detail`-to-construct-content-002 │ ├── tests-test_completion.lua---Information-window---uses-`info`-field-from-not-LSP-source │ ├── tests-test_completion.lua---Information-window---works │ ├── tests-test_completion.lua---Information-window---works-without-attached-LSP-server │ ├── tests-test_completion.lua---Information-window---works-without-attached-LSP-server-002 │ ├── tests-test_completion.lua---Manual-completion---respects-`abbr_hlgroup`-as-item-field │ ├── tests-test_completion.lua---Manual-completion---respects-`filterText`-during-built-in-filtering │ ├── tests-test_completion.lua---Manual-completion---respects-`filterText`-during-built-in-filtering-002 │ ├── tests-test_completion.lua---Manual-completion---respects-`kind_hlgroup`-as-item-field │ ├── tests-test_completion.lua---Manual-completion---respects-`labelDetails`-from-LSP-response │ ├── tests-test_completion.lua---Manual-completion---uses-`vim.lsp.protocol.CompletionItemKind`-in-LSP-step │ ├── tests-test_completion.lua---Scroll---can-be-done-in-both-windows │ ├── tests-test_completion.lua---Scroll---can-be-done-in-both-windows-002 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-both-windows-003 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-both-windows-004 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-info-window │ ├── tests-test_completion.lua---Scroll---can-be-done-in-info-window-002 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-info-window-003 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-info-window-004 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-info-window-005 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-info-window-006 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-info-window-007 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-signature-window │ ├── tests-test_completion.lua---Scroll---can-be-done-in-signature-window-002 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-signature-window-003 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-signature-window-004 │ ├── tests-test_completion.lua---Scroll---can-be-done-in-signature-window-005 │ ├── tests-test_completion.lua---Scroll---respects-`config.mappings` │ ├── tests-test_completion.lua---Scroll---respects-`config.mappings`-002 │ ├── tests-test_completion.lua---Scroll---respects-`config.mappings`-003 │ ├── tests-test_completion.lua---Signature-help---accounts-for-border-when-picking-side │ ├── tests-test_completion.lua---Signature-help---adjusts-title │ ├── tests-test_completion.lua---Signature-help---adjusts-title-002 │ ├── tests-test_completion.lua---Signature-help---adjusts-window-height │ ├── tests-test_completion.lua---Signature-help---can-be-adjusted-in-event │ ├── tests-test_completion.lua---Signature-help---handles-multiline-text │ ├── tests-test_completion.lua---Signature-help---has-minimal-dimensions-for-small-text │ ├── tests-test_completion.lua---Signature-help---respects-`config.window.signature` │ ├── tests-test_completion.lua---Signature-help---respects-`config.window.signature`-002 │ ├── tests-test_completion.lua---Signature-help---stylizes-markdown-with-concealed-characters │ ├── tests-test_completion.lua---Signature-help---updates-highlighting-of-active-parameter │ ├── tests-test_completion.lua---Signature-help---updates-highlighting-of-active-parameter-002 │ ├── tests-test_completion.lua---Signature-help---updates-highlighting-of-active-parameter-003 │ ├── tests-test_completion.lua---Signature-help---updates-highlighting-of-active-parameter-004 │ ├── tests-test_completion.lua---Signature-help---updates-highlighting-of-active-parameter-005 │ ├── tests-test_completion.lua---Signature-help---updates-highlighting-of-active-parameter-006 │ ├── tests-test_completion.lua---Signature-help---updates-without-delay-with-different-window │ ├── tests-test_completion.lua---Signature-help---updates-without-delay-with-different-window-002 │ ├── tests-test_completion.lua---Signature-help---works │ ├── tests-test_completion.lua---Snippets---LSP-server-from-'mini.snippets'---works │ ├── tests-test_completion.lua---Snippets---LSP-server-from-'mini.snippets'---works-with-in-server-matching │ ├── tests-test_completion.lua---Snippets---are-not-inserted-if-have-no-tabstops-or-variables │ ├── tests-test_completion.lua---Snippets---properly-show-special-symbol-in-popup │ ├── tests-test_completion.lua---Snippets---respect-'mini.snippets'-config │ ├── tests-test_completion.lua---Snippets---show-full-snippet-text-as-info │ ├── tests-test_completion.lua---Snippets---show-full-snippet-text-as-info-002 │ ├── tests-test_completion.lua---Snippets---work │ ├── tests-test_cursorword.lua---Highlighting---can-stop │ ├── tests-test_cursorword.lua---Highlighting---respects-MiniCursorwordCurrent-highlight-group │ ├── tests-test_cursorword.lua---Highlighting---works │ ├── tests-test_cursorword.lua---Highlighting---works-on-multibyte-character │ ├── tests-test_cursorword.lua---Highlighting---works-on-multibyte-character-002 │ ├── tests-test_cursorword.lua---Highlighting---works-with-multiple-windows │ ├── tests-test_deps.lua---Commands----DepsAdd-works │ ├── tests-test_deps.lua---Commands----DepsShowLog-works │ ├── tests-test_deps.lua---Commands----DepsUpdate-works │ ├── tests-test_deps.lua---Commands----DepsUpdateOffline-works │ ├── tests-test_deps.lua---clean()---works │ ├── tests-test_deps.lua---clean()---works-002 │ ├── tests-test_deps.lua---update()---can-fold-in-confirm-buffer │ ├── tests-test_deps.lua---update()---can-highlight-breaking-changes │ ├── tests-test_deps.lua---update()---can-work-with-non-default-branches │ ├── tests-test_deps.lua---update()---shows-empty-monitor-log │ ├── tests-test_deps.lua---update()---works │ ├── tests-test_diff.lua---Diff---`MiniDiffUpdated`-event-can-be-used-to-override-`minidiff_summary_string`-variable │ ├── tests-test_diff.lua---Diff---redraws-statusline-when-diff-is-updated │ ├── tests-test_diff.lua---Diff---redraws-statusline-when-diff-is-updated-002 │ ├── tests-test_diff.lua---Overlay---always-highlights-whole-lines │ ├── tests-test_diff.lua---Overlay---scrolls-along-with-buffer-lines │ ├── tests-test_diff.lua---Overlay---scrolls-along-with-buffer-lines-002 │ ├── tests-test_diff.lua---Overlay---word-diff---has-non-zero-interhunk-context │ ├── tests-test_diff.lua---Overlay---word-diff---works │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-BOM-bytes │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-multibyte-characters │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-multibyte-characters-002 │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-multibyte-characters-003 │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-multibyte-characters-004 │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-multibyte-characters-005 │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-multibyte-characters-006 │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-multibyte-characters-007 │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-multibyte-characters-008 │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-multibyte-characters-009 │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-multibyte-characters-010 │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-one-of-lines-being-empty │ ├── tests-test_diff.lua---Overlay---word-diff---works-with-one-of-lines-being-empty-002 │ ├── tests-test_diff.lua---Overlay---works │ ├── tests-test_diff.lua---Overlay---works-002 │ ├── tests-test_diff.lua---Overlay---works-003 │ ├── tests-test_diff.lua---Overlay---works-at-edge-lines │ ├── tests-test_diff.lua---Overlay---works-at-edge-lines-002 │ ├── tests-test_diff.lua---Overlay---works-at-edge-lines-003 │ ├── tests-test_diff.lua---Overlay---works-when-'change'-overlaps-with-'delete' │ ├── tests-test_diff.lua---Overlay---works-with-'add'-hunks │ ├── tests-test_diff.lua---Overlay---works-with-'change'-hunks │ ├── tests-test_diff.lua---Overlay---works-with-'change'-hunks-002 │ ├── tests-test_diff.lua---Overlay---works-with-'delete'-hunks │ ├── tests-test_diff.lua---Visualization---can-be-visually-disabled │ ├── tests-test_diff.lua---Visualization---does-not-appear-if-there-is-no-gutter │ ├── tests-test_diff.lua---Visualization---forces-redraw-when-it-is-needed │ ├── tests-test_diff.lua---Visualization---forces-redraw-when-it-is-needed-002 │ ├── tests-test_diff.lua---Visualization---reacts-to-hunk-lines-delete-move │ ├── tests-test_diff.lua---Visualization---reacts-to-hunk-lines-delete-move-002 │ ├── tests-test_diff.lua---Visualization---respects-`view.signs` │ ├── tests-test_diff.lua---Visualization---respects-`view.style` │ ├── tests-test_diff.lua---Visualization---respects-`view.style`-002 │ ├── tests-test_diff.lua---Visualization---shows-signcolumn-even-if-hunks-are-outside-of-view │ ├── tests-test_diff.lua---Visualization---shows-signcolumn-even-if-hunks-are-outside-of-view-002 │ ├── tests-test_diff.lua---Visualization---works │ ├── tests-test_diff.lua---Visualization---works-with-'add'-hunks │ ├── tests-test_diff.lua---Visualization---works-with-'add'-hunks-002 │ ├── tests-test_diff.lua---Visualization---works-with-'change'-hunks │ ├── tests-test_diff.lua---Visualization---works-with-'change'-hunks-002 │ ├── tests-test_diff.lua---Visualization---works-with-'delete'-hunks │ ├── tests-test_diff.lua---Visualization---works-with-'delete'-hunks-002 │ ├── tests-test_diff.lua---Visualization---works-with-'delete'-hunks-003 │ ├── tests-test_diff.lua---disable()---works │ ├── tests-test_diff.lua---set_ref_text()---immediately-updates-diff-data-and-visualization │ ├── tests-test_diff.lua---set_ref_text()---removing-reference-text-removes-visualization │ ├── tests-test_diff.lua---set_ref_text()---removing-reference-text-removes-visualization-002 │ ├── tests-test_diff.lua---toggle_overlay()---works │ ├── tests-test_diff.lua---toggle_overlay()---works-002 │ ├── tests-test_diff.lua---toggle_overlay()---works-003 │ ├── tests-test_diff.lua---toggle_overlay()---works-004 │ ├── tests-test_diff.lua---toggle_overlay()---works-005 │ ├── tests-test_extra.lua---pickers---buf_lines()---can-not-show-icons │ ├── tests-test_extra.lua---pickers---buf_lines()---respects-`local_opts.scope` │ ├── tests-test_extra.lua---pickers---buf_lines()---works │ ├── tests-test_extra.lua---pickers---colorschemes()---respects-`local_opts.preview_hl_groups` │ ├── tests-test_extra.lua---pickers---colorschemes()---works │ ├── tests-test_extra.lua---pickers---colorschemes()---works-002 │ ├── tests-test_extra.lua---pickers---colorschemes()---works-with-preview │ ├── tests-test_extra.lua---pickers---colorschemes()---works-with-preview-002 │ ├── tests-test_extra.lua---pickers---colorschemes()---works-with-preview-003 │ ├── tests-test_extra.lua---pickers---commands()---respects-user-commands │ ├── tests-test_extra.lua---pickers---commands()---respects-user-commands-002 │ ├── tests-test_extra.lua---pickers---commands()---works │ ├── tests-test_extra.lua---pickers---commands()---works-002 │ ├── tests-test_extra.lua---pickers---diagnostic()---works │ ├── tests-test_extra.lua---pickers---diagnostic()---works-002 │ ├── tests-test_extra.lua---pickers---explorer()---can-be-resumed │ ├── tests-test_extra.lua---pickers---explorer()---can-be-resumed-002 │ ├── tests-test_extra.lua---pickers---explorer()---can-not-show-icons │ ├── tests-test_extra.lua---pickers---explorer()---can-not-show-icons-002 │ ├── tests-test_extra.lua---pickers---explorer()---respects-`local_opts.filter` │ ├── tests-test_extra.lua---pickers---explorer()---respects-`local_opts.filter`-002 │ ├── tests-test_extra.lua---pickers---explorer()---respects-`local_opts.sort` │ ├── tests-test_extra.lua---pickers---explorer()---respects-`local_opts.sort`-002 │ ├── tests-test_extra.lua---pickers---explorer()---works │ ├── tests-test_extra.lua---pickers---explorer()---works-002 │ ├── tests-test_extra.lua---pickers---explorer()---works-003 │ ├── tests-test_extra.lua---pickers---explorer()---works-004 │ ├── tests-test_extra.lua---pickers---explorer()---works-005 │ ├── tests-test_extra.lua---pickers---explorer()---works-006 │ ├── tests-test_extra.lua---pickers---git_branches()---works │ ├── tests-test_extra.lua---pickers---git_branches()---works-002 │ ├── tests-test_extra.lua---pickers---git_commits()---works │ ├── tests-test_extra.lua---pickers---git_commits()---works-002 │ ├── tests-test_extra.lua---pickers---git_files()---can-not-show-icons │ ├── tests-test_extra.lua---pickers---git_files()---works │ ├── tests-test_extra.lua---pickers---git_files()---works-002 │ ├── tests-test_extra.lua---pickers---git_hunks()---respects-`local_opts.n_context`---test-+-args-{-0-} │ ├── tests-test_extra.lua---pickers---git_hunks()---respects-`local_opts.n_context`---test-+-args-{-0-}-002 │ ├── tests-test_extra.lua---pickers---git_hunks()---respects-`local_opts.n_context`---test-+-args-{-0-}-003 │ ├── tests-test_extra.lua---pickers---git_hunks()---respects-`local_opts.n_context`---test-+-args-{-20-} │ ├── tests-test_extra.lua---pickers---git_hunks()---respects-`local_opts.n_context`---test-+-args-{-20-}-002 │ ├── tests-test_extra.lua---pickers---git_hunks()---respects-`local_opts.n_context`---test-+-args-{-20-}-003 │ ├── tests-test_extra.lua---pickers---git_hunks()---works │ ├── tests-test_extra.lua---pickers---git_hunks()---works-002 │ ├── tests-test_extra.lua---pickers---git_hunks()---works-003 │ ├── tests-test_extra.lua---pickers---git_hunks()---works-004 │ ├── tests-test_extra.lua---pickers---git_hunks()---works-005 │ ├── tests-test_extra.lua---pickers---git_hunks()---works-006 │ ├── tests-test_extra.lua---pickers---hipatterns()---respects-`local_opts.highlighters` │ ├── tests-test_extra.lua---pickers---hipatterns()---respects-`local_opts.scope` │ ├── tests-test_extra.lua---pickers---hipatterns()---works │ ├── tests-test_extra.lua---pickers---hipatterns()---works-002 │ ├── tests-test_extra.lua---pickers---history()---works │ ├── tests-test_extra.lua---pickers---history()---works-002 │ ├── tests-test_extra.lua---pickers---hl_groups()---respects-non-default-linked-highlight-groups │ ├── tests-test_extra.lua---pickers---hl_groups()---works │ ├── tests-test_extra.lua---pickers---hl_groups()---works-002 │ ├── tests-test_extra.lua---pickers---keymaps()---shows-source-of-Lua-callback-in-preview │ ├── tests-test_extra.lua---pickers---keymaps()---shows-source-of-Lua-callback-in-preview-002 │ ├── tests-test_extra.lua---pickers---keymaps()---shows-source-of-Lua-callback-in-preview-003 │ ├── tests-test_extra.lua---pickers---keymaps()---works │ ├── tests-test_extra.lua---pickers---keymaps()---works-002 │ ├── tests-test_extra.lua---pickers---list()---works-for-`change` │ ├── tests-test_extra.lua---pickers---list()---works-for-`change`-002 │ ├── tests-test_extra.lua---pickers---list()---works-for-`jump` │ ├── tests-test_extra.lua---pickers---list()---works-for-`jump`-002 │ ├── tests-test_extra.lua---pickers---list()---works-for-`location` │ ├── tests-test_extra.lua---pickers---list()---works-for-`location`-002 │ ├── tests-test_extra.lua---pickers---list()---works-for-`location`-003 │ ├── tests-test_extra.lua---pickers---list()---works-for-`location`-004 │ ├── tests-test_extra.lua---pickers---list()---works-for-`quickfix` │ ├── tests-test_extra.lua---pickers---list()---works-for-`quickfix`-002 │ ├── tests-test_extra.lua---pickers---list()---works-for-`quickfix`-003 │ ├── tests-test_extra.lua---pickers---list()---works-for-`quickfix`-004 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`declaration` │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`declaration`-002 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`definition` │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`definition`-002 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`document_symbol` │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`document_symbol`-002 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`document_symbol`-after-`MiniIcons.tweak_lsp_kind()` │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`document_symbol`-after-`MiniIcons.tweak_lsp_kind()`-002 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`document_symbol`-after-`MiniIcons.tweak_lsp_kind()`-003 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`document_symbol`-with-'mini.icons'-set-up │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`document_symbol`-with-'mini.icons'-set-up-002 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`implementation` │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`implementation`-002 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`references` │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`references`-002 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`type_definition` │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`type_definition`-002 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`workspace_symbol` │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`workspace_symbol`-002 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`workspace_symbol`-after-`MiniIcons.tweak_lsp_kind()` │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`workspace_symbol`-after-`MiniIcons.tweak_lsp_kind()`-002 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`workspace_symbol`-after-`MiniIcons.tweak_lsp_kind()`-003 │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`workspace_symbol`-with-'mini.icons'-set-up │ ├── tests-test_extra.lua---pickers---lsp()---works-for-`workspace_symbol`-with-'mini.icons'-set-up-002 │ ├── tests-test_extra.lua---pickers---manpages()---can-choose-in-split │ ├── tests-test_extra.lua---pickers---manpages()---works │ ├── tests-test_extra.lua---pickers---manpages()---works-002 │ ├── tests-test_extra.lua---pickers---manpages()---works-003 │ ├── tests-test_extra.lua---pickers---marks()---respects-`local_opts.scope` │ ├── tests-test_extra.lua---pickers---marks()---respects-`local_opts.scope`-002 │ ├── tests-test_extra.lua---pickers---marks()---respects-`local_opts.scope`-003 │ ├── tests-test_extra.lua---pickers---marks()---works │ ├── tests-test_extra.lua---pickers---marks()---works-002 │ ├── tests-test_extra.lua---pickers---marks()---works-003 │ ├── tests-test_extra.lua---pickers---marks()---works-004 │ ├── tests-test_extra.lua---pickers---oldfiles()---can-not-show-icons │ ├── tests-test_extra.lua---pickers---oldfiles()---works │ ├── tests-test_extra.lua---pickers---options()---correctly-previews-deprecated-options │ ├── tests-test_extra.lua---pickers---options()---respects-set-options │ ├── tests-test_extra.lua---pickers---options()---respects-set-options-002 │ ├── tests-test_extra.lua---pickers---options()---respects-set-options-003 │ ├── tests-test_extra.lua---pickers---options()---works │ ├── tests-test_extra.lua---pickers---options()---works-002 │ ├── tests-test_extra.lua---pickers---registers()---works │ ├── tests-test_extra.lua---pickers---registers()---works-002 │ ├── tests-test_extra.lua---pickers---spellsuggest()---works │ ├── tests-test_extra.lua---pickers---spellsuggest()---works-002 │ ├── tests-test_extra.lua---pickers---treesitter()---works │ ├── tests-test_extra.lua---pickers---treesitter()---works-002 │ ├── tests-test_extra.lua---pickers---treesitter()---works-003 │ ├── tests-test_extra.lua---pickers---visit_labels()---can-not-show-icons-after-choosing │ ├── tests-test_extra.lua---pickers---visit_labels()---respects-`local_opts.sort` │ ├── tests-test_extra.lua---pickers---visit_labels()---works │ ├── tests-test_extra.lua---pickers---visit_labels()---works-002 │ ├── tests-test_extra.lua---pickers---visit_labels()---works-003 │ ├── tests-test_extra.lua---pickers---visit_paths()---can-not-show-icons │ ├── tests-test_extra.lua---pickers---visit_paths()---works │ ├── tests-test_extra.lua---pickers---visit_paths()---works-002 │ ├── tests-test_files.lua---Cursors---handle-`content.prefix`-returning-different-lengths │ ├── tests-test_files.lua---Cursors---shows-whole-line-after-horizontal-scroll │ ├── tests-test_files.lua---Cursors---shows-whole-line-after-horizontal-scroll-002 │ ├── tests-test_files.lua---Default-explorer---works-in-`-edit-.` │ ├── tests-test_files.lua---Default-explorer---works-in-`-tabfind-.` │ ├── tests-test_files.lua---Default-explorer---works-in-`-tabfind-.`-002 │ ├── tests-test_files.lua---Default-explorer---works-in-`-vsplit-.` │ ├── tests-test_files.lua---Default-explorer---works-in-`-vsplit-.`-002 │ ├── tests-test_files.lua---Default-explorer---works-on-startup │ ├── tests-test_files.lua---Events---`MiniFilesWindowOpen`-can-be-used-to-tweak-window-config │ ├── tests-test_files.lua---Events---`MiniFilesWindowOpen`-can-be-used-to-tweak-window-config-002 │ ├── tests-test_files.lua---Events---`MiniFilesWindowOpen`-can-be-used-to-tweak-window-config-003 │ ├── tests-test_files.lua---Events---`MiniFilesWindowUpdate`-can-customize-internally-set-window-config-parts │ ├── tests-test_files.lua---Events---`MiniFilesWindowUpdate`-can-customize-internally-set-window-config-parts-002 │ ├── tests-test_files.lua---Events---`MiniFilesWindowUpdate`-can-customize-internally-set-window-config-parts-003 │ ├── tests-test_files.lua---Events---`MiniFilesWindowUpdate`-can-customize-internally-set-window-config-parts-004 │ ├── tests-test_files.lua---Events---`MiniFilesWindowUpdate`-can-customize-internally-set-window-config-parts-005 │ ├── tests-test_files.lua---File-manipulation---can-be-not-confirmed │ ├── tests-test_files.lua---File-manipulation---can-be-not-confirmed-002 │ ├── tests-test_files.lua---File-manipulation---can-be-not-confirmed-with-preview │ ├── tests-test_files.lua---File-manipulation---can-be-not-confirmed-with-preview-002 │ ├── tests-test_files.lua---File-manipulation---can-convert-file-into-directory │ ├── tests-test_files.lua---File-manipulation---can-convert-file-into-directory-002 │ ├── tests-test_files.lua---File-manipulation---can-copy-directory │ ├── tests-test_files.lua---File-manipulation---can-copy-directory-002 │ ├── tests-test_files.lua---File-manipulation---can-copy-directory-inside-itself │ ├── tests-test_files.lua---File-manipulation---can-copy-directory-inside-itself-002 │ ├── tests-test_files.lua---File-manipulation---can-copy-directory-inside-new-directory │ ├── tests-test_files.lua---File-manipulation---can-copy-directory-inside-new-directory-002 │ ├── tests-test_files.lua---File-manipulation---can-copy-file │ ├── tests-test_files.lua---File-manipulation---can-copy-file-002 │ ├── tests-test_files.lua---File-manipulation---can-copy-file-inside-new-directory │ ├── tests-test_files.lua---File-manipulation---can-copy-file-inside-new-directory-002 │ ├── tests-test_files.lua---File-manipulation---can-create │ ├── tests-test_files.lua---File-manipulation---can-create-002 │ ├── tests-test_files.lua---File-manipulation---can-delete │ ├── tests-test_files.lua---File-manipulation---can-delete-002 │ ├── tests-test_files.lua---File-manipulation---can-move-directory │ ├── tests-test_files.lua---File-manipulation---can-move-directory-002 │ ├── tests-test_files.lua---File-manipulation---can-move-file │ ├── tests-test_files.lua---File-manipulation---can-move-file-002 │ ├── tests-test_files.lua---File-manipulation---can-move-inside-new-directory │ ├── tests-test_files.lua---File-manipulation---can-move-inside-new-directory-002 │ ├── tests-test_files.lua---File-manipulation---can-move-while-changing-basename │ ├── tests-test_files.lua---File-manipulation---can-move-while-changing-basename-002 │ ├── tests-test_files.lua---File-manipulation---can-rename │ ├── tests-test_files.lua---File-manipulation---can-rename-002 │ ├── tests-test_files.lua---File-manipulation---copy-does-not-override-existing-entry │ ├── tests-test_files.lua---File-manipulation---copy-does-not-override-existing-entry-002 │ ├── tests-test_files.lua---File-manipulation---copy-does-not-override-existing-entry-003 │ ├── tests-test_files.lua---File-manipulation---create-does-not-override-existing-entry │ ├── tests-test_files.lua---File-manipulation---create-does-not-override-existing-entry-002 │ ├── tests-test_files.lua---File-manipulation---creates-files-in-nested-directories │ ├── tests-test_files.lua---File-manipulation---creates-files-in-nested-directories-002 │ ├── tests-test_files.lua---File-manipulation---creates-nested-directories │ ├── tests-test_files.lua---File-manipulation---creates-nested-directories-002 │ ├── tests-test_files.lua---File-manipulation---handles-backslash-on-Unix │ ├── tests-test_files.lua---File-manipulation---handles-backslash-on-Unix-002 │ ├── tests-test_files.lua---File-manipulation---handles-move-directory-inside-itself │ ├── tests-test_files.lua---File-manipulation---handles-move-directory-inside-itself-002 │ ├── tests-test_files.lua---File-manipulation---ignores-blank-lines │ ├── tests-test_files.lua---File-manipulation---ignores-blank-lines-002 │ ├── tests-test_files.lua---File-manipulation---ignores-identical-user-copied-entries │ ├── tests-test_files.lua---File-manipulation---ignores-identical-user-copied-entries-002 │ ├── tests-test_files.lua---File-manipulation---move-does-not-override-existing-entry │ ├── tests-test_files.lua---File-manipulation---move-does-not-override-existing-entry-002 │ ├── tests-test_files.lua---File-manipulation---move-does-not-override-existing-entry-003 │ ├── tests-test_files.lua---File-manipulation---move-works-again-after-undo │ ├── tests-test_files.lua---File-manipulation---move-works-again-after-undo-002 │ ├── tests-test_files.lua---File-manipulation---rename-does-not-override-existing-entry │ ├── tests-test_files.lua---File-manipulation---rename-does-not-override-existing-entry-002 │ ├── tests-test_files.lua---File-manipulation---rename-does-not-override-existing-entry-003 │ ├── tests-test_files.lua---File-manipulation---rename-works-again-after-undo │ ├── tests-test_files.lua---File-manipulation---rename-works-again-after-undo-002 │ ├── tests-test_files.lua---File-manipulation---respects-modified-hidden-buffers │ ├── tests-test_files.lua---File-manipulation---works-with-problematic-names │ ├── tests-test_files.lua---File-manipulation---works-with-problematic-names-002 │ ├── tests-test_files.lua---Mappings---`go_in_plus`-supports--count- │ ├── tests-test_files.lua---Mappings---`go_in_plus`-supports--count--002 │ ├── tests-test_files.lua---Mappings---`go_in_plus`-works │ ├── tests-test_files.lua---Mappings---`go_in`-supports--count- │ ├── tests-test_files.lua---Mappings---`go_in`-supports--count--002 │ ├── tests-test_files.lua---Mappings---`go_in`-works │ ├── tests-test_files.lua---Mappings---`go_in`-works-in-linewise-Visual-mode │ ├── tests-test_files.lua---Mappings---`go_in`-works-in-linewise-Visual-mode-002 │ ├── tests-test_files.lua---Mappings---`go_in`-works-in-linewise-Visual-mode-003 │ ├── tests-test_files.lua---Mappings---`go_out_plus`-supports--count- │ ├── tests-test_files.lua---Mappings---`go_out_plus`-supports--count--002 │ ├── tests-test_files.lua---Mappings---`go_out_plus`-supports--count--003 │ ├── tests-test_files.lua---Mappings---`go_out_plus`-works │ ├── tests-test_files.lua---Mappings---`go_out_plus`-works-002 │ ├── tests-test_files.lua---Mappings---`go_out_plus`-works-003 │ ├── tests-test_files.lua---Mappings---`go_out`-supports--count- │ ├── tests-test_files.lua---Mappings---`go_out`-supports--count--002 │ ├── tests-test_files.lua---Mappings---`go_out`-supports--count--003 │ ├── tests-test_files.lua---Mappings---`go_out`-works │ ├── tests-test_files.lua---Mappings---`reset`-works │ ├── tests-test_files.lua---Mappings---`reset`-works-002 │ ├── tests-test_files.lua---Mappings---`reset`-works-003 │ ├── tests-test_files.lua---Mappings---`reveal_cwd`-works │ ├── tests-test_files.lua---Mappings---`reveal_cwd`-works-002 │ ├── tests-test_files.lua---Mappings---`reveal_cwd`-works-003 │ ├── tests-test_files.lua---Mappings---`show_help`-works │ ├── tests-test_files.lua---Mappings---`show_help`-works-002 │ ├── tests-test_files.lua---Mappings---`show_help`-works-003 │ ├── tests-test_files.lua---Mappings---`synchronize`-works │ ├── tests-test_files.lua---Mappings---`synchronize`-works-002 │ ├── tests-test_files.lua---Mappings---`synchronize`-works-003 │ ├── tests-test_files.lua---Mappings---`synchronize`-works-004 │ ├── tests-test_files.lua---Mappings---`synchronize`-works-005 │ ├── tests-test_files.lua---Mappings---`synchronize`-works-006 │ ├── tests-test_files.lua---Mappings---`trim_left`-works │ ├── tests-test_files.lua---Mappings---`trim_right`-works │ ├── tests-test_files.lua---Preview---always-updates-with-cursor │ ├── tests-test_files.lua---Preview---can-work-after-renaming-with-small-overall-width │ ├── tests-test_files.lua---Preview---can-work-after-renaming-with-small-overall-width-002 │ ├── tests-test_files.lua---Preview---does-not-highlight-big-files │ ├── tests-test_files.lua---Preview---is-not-removed-when-going-out │ ├── tests-test_files.lua---Preview---is-not-removed-when-going-out-002 │ ├── tests-test_files.lua---Preview---is-not-shown-if-not-enough-space │ ├── tests-test_files.lua---Preview---previews-only-one-level-deep │ ├── tests-test_files.lua---Preview---respects-global-value-of-'list'-and-'listchars'-option │ ├── tests-test_files.lua---Preview---respects-global-value-of-'list'-and-'listchars'-option-002 │ ├── tests-test_files.lua---Preview---respects-global-value-of-'list'-and-'listchars'-option-003 │ ├── tests-test_files.lua---Preview---respects-global-value-of-'list'-and-'listchars'-option-004 │ ├── tests-test_files.lua---Preview---works-after-`trim_left()` │ ├── tests-test_files.lua---Preview---works-for-directories │ ├── tests-test_files.lua---Preview---works-for-directories-002 │ ├── tests-test_files.lua---Preview---works-for-directories-003 │ ├── tests-test_files.lua---Preview---works-for-files │ ├── tests-test_files.lua---Preview---works-for-files-002 │ ├── tests-test_files.lua---Preview---works-for-files-003 │ ├── tests-test_files.lua---Preview---works-for-files-004 │ ├── tests-test_files.lua---Preview---works-for-files-005 │ ├── tests-test_files.lua---Preview---works-for-files-006 │ ├── tests-test_files.lua---Preview---works-with-imaginary-paths │ ├── tests-test_files.lua---Preview---works-with-imaginary-paths-002 │ ├── tests-test_files.lua---Preview---works-with-imaginary-paths-003 │ ├── tests-test_files.lua---Preview---works-with-imaginary-paths-004 │ ├── tests-test_files.lua---Preview---works-with-imaginary-paths-005 │ ├── tests-test_files.lua---Preview---works-with-imaginary-paths-006 │ ├── tests-test_files.lua---Preview---works-with-imaginary-paths-007 │ ├── tests-test_files.lua---Preview---works-with-imaginary-paths-008 │ ├── tests-test_files.lua---Windows---always-show-cursor-line-in-directories │ ├── tests-test_files.lua---Windows---always-show-cursor-line-in-directories-002 │ ├── tests-test_files.lua---Windows---correctly-computes-part-of-branch-to-show │ ├── tests-test_files.lua---Windows---correctly-computes-part-of-branch-to-show-002 │ ├── tests-test_files.lua---Windows---correctly-computes-part-of-branch-to-show-003 │ ├── tests-test_files.lua---Windows---correctly-computes-part-of-branch-to-show-004 │ ├── tests-test_files.lua---Windows---correctly-computes-part-of-branch-to-show-005 │ ├── tests-test_files.lua---Windows---correctly-computes-part-of-branch-to-show-006 │ ├── tests-test_files.lua---Windows---correctly-computes-part-of-branch-to-show-with-preview │ ├── tests-test_files.lua---Windows---correctly-highlight-content-during-editing │ ├── tests-test_files.lua---Windows---does-not-wrap-content │ ├── tests-test_files.lua---Windows---is-in-sync-with-cursor │ ├── tests-test_files.lua---Windows---is-in-sync-with-cursor-002 │ ├── tests-test_files.lua---Windows---is-in-sync-with-cursor-003 │ ├── tests-test_files.lua---Windows---is-in-sync-with-cursor-004 │ ├── tests-test_files.lua---Windows---is-in-sync-with-cursor-005 │ ├── tests-test_files.lua---Windows---never-shows-past-end-of-buffer │ ├── tests-test_files.lua---Windows---never-shows-past-end-of-buffer-002 │ ├── tests-test_files.lua---Windows---never-shows-past-end-of-buffer-003 │ ├── tests-test_files.lua---Windows---reacts-on-`VimResized` │ ├── tests-test_files.lua---Windows---reacts-on-`VimResized`-002 │ ├── tests-test_files.lua---Windows---reacts-on-`VimResized`-003 │ ├── tests-test_files.lua---Windows---reacts-on-`VimResized`-004 │ ├── tests-test_files.lua---Windows---respect-'winborder'-option │ ├── tests-test_files.lua---Windows---respect-'winborder'-option-002 │ ├── tests-test_files.lua---Windows---respect-'winborder'-option-003 │ ├── tests-test_files.lua---Windows---respects-tabline-and-statusline-when-computing-height │ ├── tests-test_files.lua---Windows---respects-tabline-and-statusline-when-computing-height-002 │ ├── tests-test_files.lua---Windows---respects-tabline-and-statusline-when-computing-height-003 │ ├── tests-test_files.lua---Windows---respects-tabline-and-statusline-when-computing-height-004 │ ├── tests-test_files.lua---Windows---respects-tabline-when-computing-position │ ├── tests-test_files.lua---Windows---works-with-too-small-dimensions │ ├── tests-test_files.lua---close()---checks-for-pending-file-system-actions │ ├── tests-test_files.lua---close()---checks-for-pending-file-system-actions-002 │ ├── tests-test_files.lua---close()---checks-for-pending-file-system-actions-003 │ ├── tests-test_files.lua---close()---handles-invalid-target-window │ ├── tests-test_files.lua---close()---handles-invalid-target-window-002 │ ├── tests-test_files.lua---close()---works │ ├── tests-test_files.lua---close()---works-002 │ ├── tests-test_files.lua---close()---works-per-tabpage │ ├── tests-test_files.lua---go_in()---warns-about-paths-not-present-on-disk │ ├── tests-test_files.lua---go_in()---works-on-directory │ ├── tests-test_files.lua---go_in()---works-on-directory-002 │ ├── tests-test_files.lua---go_out()---root-update-reuses-buffers-without-their-update │ ├── tests-test_files.lua---go_out()---works-on-branch-root │ ├── tests-test_files.lua---go_out()---works-on-not-branch-root │ ├── tests-test_files.lua---open()---`content.prefix`-can-be-used-to-not-show-prefix │ ├── tests-test_files.lua---open()---`content.prefix`-can-return-`nil` │ ├── tests-test_files.lua---open()---`content.prefix`-can-return-`nil`-002 │ ├── tests-test_files.lua---open()---`content.prefix`-can-return-`nil`-003 │ ├── tests-test_files.lua---open()---`content.sort`-can-be-used-to-also-filter-items │ ├── tests-test_files.lua---open()---can-display-entries-with-newline-character │ ├── tests-test_files.lua---open()---can-display-entries-with-newline-character-002 │ ├── tests-test_files.lua---open()---focuses-on-file-entry-when-opened-from-history │ ├── tests-test_files.lua---open()---focuses-on-file-entry-when-opened-from-history-002 │ ├── tests-test_files.lua---open()---focuses-on-file-entry-when-opened-from-history-003 │ ├── tests-test_files.lua---open()---focuses-on-file-entry-when-opened-from-history-004 │ ├── tests-test_files.lua---open()---handles-backslash-on-Unix │ ├── tests-test_files.lua---open()---handles-problematic-entry-names │ ├── tests-test_files.lua---open()---history---handles-external-changes-between-calls │ ├── tests-test_files.lua---open()---history---handles-external-changes-between-calls-002 │ ├── tests-test_files.lua---open()---history---is-shared-across-tabpages │ ├── tests-test_files.lua---open()---history---is-shared-across-tabpages-002 │ ├── tests-test_files.lua---open()---history---is-shared-across-tabpages-003 │ ├── tests-test_files.lua---open()---history---opens-from-history-by-default │ ├── tests-test_files.lua---open()---history---opens-from-history-by-default-002 │ ├── tests-test_files.lua---open()---history---prefers-global-config-before-taking-from-history │ ├── tests-test_files.lua---open()---history---prefers-global-config-before-taking-from-history-002 │ ├── tests-test_files.lua---open()---history---respects-`use_latest` │ ├── tests-test_files.lua---open()---history---respects-`use_latest`-002 │ ├── tests-test_files.lua---open()---history---stores-whole-branch-and-not-only-visible-windows │ ├── tests-test_files.lua---open()---history---stores-whole-branch-and-not-only-visible-windows-002 │ ├── tests-test_files.lua---open()---normalizes-before-first-refresh-when-focused-on-directory-with-`windows.preview` │ ├── tests-test_files.lua---open()---normalizes-before-first-refresh-when-focused-on-file │ ├── tests-test_files.lua---open()---properly-closes-currently-opened-explorer │ ├── tests-test_files.lua---open()---respects-`content.filter` │ ├── tests-test_files.lua---open()---respects-`content.filter`-002 │ ├── tests-test_files.lua---open()---respects-`content.highlight` │ ├── tests-test_files.lua---open()---respects-`content.highlight`-002 │ ├── tests-test_files.lua---open()---respects-`content.prefix` │ ├── tests-test_files.lua---open()---respects-`content.prefix`-002 │ ├── tests-test_files.lua---open()---respects-`content.sort` │ ├── tests-test_files.lua---open()---respects-`content.sort`-002 │ ├── tests-test_files.lua---open()---respects-`mappings` │ ├── tests-test_files.lua---open()---respects-`mappings`-002 │ ├── tests-test_files.lua---open()---respects-`vim.b.minifiles_config` │ ├── tests-test_files.lua---open()---respects-`windows.max_number` │ ├── tests-test_files.lua---open()---respects-`windows.max_number`-002 │ ├── tests-test_files.lua---open()---respects-`windows.preview` │ ├── tests-test_files.lua---open()---respects-`windows.preview`-002 │ ├── tests-test_files.lua---open()---respects-`windows.width_focus`-and-`windows.width_nofocus` │ ├── tests-test_files.lua---open()---respects-`windows.width_focus`-and-`windows.width_nofocus`-002 │ ├── tests-test_files.lua---open()---respects-`windows.width_preview` │ ├── tests-test_files.lua---open()---respects-`windows.width_preview`-002 │ ├── tests-test_files.lua---open()---respects-`windows.width_preview`-003 │ ├── tests-test_files.lua---open()---respects-`windows.width_preview`-004 │ ├── tests-test_files.lua---open()---respects-`windows.width_preview`-005 │ ├── tests-test_files.lua---open()---respects-`windows.width_preview`-006 │ ├── tests-test_files.lua---open()---uses-`MiniIcons.get()`-with-full-path │ ├── tests-test_files.lua---open()---uses-icon-provider │ ├── tests-test_files.lua---open()---uses-icon-provider-002 │ ├── tests-test_files.lua---open()---uses-icon-provider-003 │ ├── tests-test_files.lua---open()---works-per-tabpage │ ├── tests-test_files.lua---open()---works-per-tabpage-002 │ ├── tests-test_files.lua---open()---works-per-tabpage-003 │ ├── tests-test_files.lua---open()---works-with-directory-path │ ├── tests-test_files.lua---open()---works-with-directory-path-002 │ ├── tests-test_files.lua---open()---works-with-directory-path-003 │ ├── tests-test_files.lua---open()---works-with-file-path │ ├── tests-test_files.lua---open()---works-with-file-path-002 │ ├── tests-test_files.lua---refresh()---does-not-update-buffers-with-`nil`-`filter`-and-`sort` │ ├── tests-test_files.lua---refresh()---does-not-update-buffers-with-`nil`-`filter`-and-`sort`-002 │ ├── tests-test_files.lua---refresh()---handles-presence-of-pending-file-system-actions │ ├── tests-test_files.lua---refresh()---handles-presence-of-pending-file-system-actions-002 │ ├── tests-test_files.lua---refresh()---handles-presence-of-pending-file-system-actions-003 │ ├── tests-test_files.lua---refresh()---handles-presence-of-pending-file-system-actions-004 │ ├── tests-test_files.lua---refresh()---preserves-explorer-options │ ├── tests-test_files.lua---refresh()---preserves-explorer-options-002 │ ├── tests-test_files.lua---refresh()---updates-buffers-with-non-empty-`content` │ ├── tests-test_files.lua---refresh()---updates-buffers-with-non-empty-`content`-002 │ ├── tests-test_files.lua---refresh()---updates-buffers-with-non-empty-`content`-003 │ ├── tests-test_files.lua---refresh()---updates-buffers-with-non-empty-`content`-004 │ ├── tests-test_files.lua---refresh()---works │ ├── tests-test_files.lua---reset()---resets-all-cursors │ ├── tests-test_files.lua---reset()---resets-all-cursors-002 │ ├── tests-test_files.lua---reset()---works │ ├── tests-test_files.lua---reset()---works-002 │ ├── tests-test_files.lua---reset()---works-when-anchor-is-not-in-branch │ ├── tests-test_files.lua---reset()---works-when-anchor-is-not-in-branch-002 │ ├── tests-test_files.lua---reveal_cwd()---properly-places-cursors │ ├── tests-test_files.lua---reveal_cwd()---properly-places-cursors-002 │ ├── tests-test_files.lua---reveal_cwd()---works │ ├── tests-test_files.lua---reveal_cwd()---works-002 │ ├── tests-test_files.lua---reveal_cwd()---works-when-not-inside-cwd │ ├── tests-test_files.lua---reveal_cwd()---works-when-not-inside-cwd-002 │ ├── tests-test_files.lua---reveal_cwd()---works-when-root-is-already-cwd │ ├── tests-test_files.lua---reveal_cwd()---works-when-root-is-already-cwd-002 │ ├── tests-test_files.lua---reveal_cwd()---works-with-preview │ ├── tests-test_files.lua---reveal_cwd()---works-with-preview-002 │ ├── tests-test_files.lua---set_branch()---works │ ├── tests-test_files.lua---set_branch()---works-002 │ ├── tests-test_files.lua---set_branch()---works-003 │ ├── tests-test_files.lua---set_branch()---works-with-file-path-in-branch │ ├── tests-test_files.lua---set_branch()---works-with-file-path-in-branch-002 │ ├── tests-test_files.lua---set_branch()---works-with-preview │ ├── tests-test_files.lua---show_help()---adjusts-window-width │ ├── tests-test_files.lua---show_help()---handles-bookmarks │ ├── tests-test_files.lua---show_help()---handles-mappings-without-description │ ├── tests-test_files.lua---show_help()---handles-non-default-mappings │ ├── tests-test_files.lua---show_help()---opens-relatively-current-window │ ├── tests-test_files.lua---show_help()---respects-'winborder'-option │ ├── tests-test_files.lua---show_help()---respects-'winborder'-option-002 │ ├── tests-test_files.lua---show_help()---respects-'winborder'-option-003 │ ├── tests-test_files.lua---show_help()---works │ ├── tests-test_files.lua---show_help()---works-002 │ ├── tests-test_files.lua---synchronize()---can-update-external-file-system-changes │ ├── tests-test_files.lua---trim_left()---works │ ├── tests-test_files.lua---trim_left()---works-002 │ ├── tests-test_files.lua---trim_left()---works-when-in-the-middle-of-the-branch │ ├── tests-test_files.lua---trim_left()---works-when-in-the-middle-of-the-branch-002 │ ├── tests-test_files.lua---trim_right()---works │ ├── tests-test_files.lua---trim_right()---works-002 │ ├── tests-test_files.lua---trim_right()---works-when-in-the-middle-of-the-branch │ ├── tests-test_files.lua---trim_right()---works-when-in-the-middle-of-the-branch-002 │ ├── tests-test_git.lua----Git---completion---uses-correct-working-directory-for-paths │ ├── tests-test_git.lua----Git---completion---works-with-explicit-paths │ ├── tests-test_git.lua----Git---completion---works-with-explicit-paths-002 │ ├── tests-test_git.lua----Git---completion---works-with-explicit-paths-003 │ ├── tests-test_git.lua----Git---completion---works-with-explicit-paths-004 │ ├── tests-test_git.lua----Git---completion---works-with-explicit-paths-005 │ ├── tests-test_git.lua----Git---completion---works-with-not-supported-command │ ├── tests-test_git.lua----Git---completion---works-with-not-supported-command-002 │ ├── tests-test_git.lua----Git---completion---works-with-not-supported-command-003 │ ├── tests-test_git.lua----Git---completion---works-with-options │ ├── tests-test_git.lua----Git---completion---works-with-options-002 │ ├── tests-test_git.lua----Git---completion---works-with-options-003 │ ├── tests-test_git.lua----Git---completion---works-with-options-004 │ ├── tests-test_git.lua----Git---completion---works-with-options-005 │ ├── tests-test_git.lua----Git---completion---works-with-options-006 │ ├── tests-test_git.lua----Git---completion---works-with-options-007 │ ├── tests-test_git.lua----Git---completion---works-with-present-command-modifiers │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-002 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-003 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-004 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-005 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-006 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-007 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-008 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-009 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-010 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-011 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-012 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-013 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-014 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-015 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-016 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-017 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-018 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-019 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-020 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-021 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-022 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-023 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-024 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-025 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-026 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-027 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-028 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-029 │ ├── tests-test_git.lua----Git---completion---works-with-subcommand-targets-030 │ ├── tests-test_git.lua----Git---completion---works-with-subcommands │ ├── tests-test_git.lua----Git---completion---works-with-subcommands-002 │ ├── tests-test_git.lua----Git---completion---works-with-subcommands-003 │ ├── tests-test_git.lua----Git---completion---works-with-subcommands-004 │ ├── tests-test_git.lua----Git---completion---works-with-subcommands-005 │ ├── tests-test_git.lua----Git---completion---works-with-subcommands-006 │ ├── tests-test_git.lua---Tracking---redraws-statusline-when-summary-is-updated │ ├── tests-test_git.lua---Tracking---redraws-statusline-when-summary-is-updated-002 │ ├── tests-test_git.lua---Tracking---redraws-statusline-when-summary-is-updated-003 │ ├── tests-test_git.lua---Tracking---redraws-statusline-when-summary-is-updated-004 │ ├── tests-test_git.lua---Tracking---redraws-statusline-when-summary-is-updated-005 │ ├── tests-test_git.lua---diff_foldexpr()---works-in-`git-log`-output │ ├── tests-test_git.lua---diff_foldexpr()---works-in-`git-log`-output-002 │ ├── tests-test_git.lua---diff_foldexpr()---works-in-`git-log`-output-003 │ ├── tests-test_git.lua---diff_foldexpr()---works-in-`git-log`-output-004 │ ├── tests-test_git.lua---diff_foldexpr()---works-in-diff-patch │ ├── tests-test_git.lua---diff_foldexpr()---works-in-diff-patch-002 │ ├── tests-test_git.lua---diff_foldexpr()---works-in-diff-patch-003 │ ├── tests-test_git.lua---diff_foldexpr()---works-in-diff-patch-004 │ ├── tests-test_hipatterns.lua---Auto-enable---does-not-enable-in-not-proper-buffers │ ├── tests-test_hipatterns.lua---Auto-enable---makes-`-edit`-work │ ├── tests-test_hipatterns.lua---Auto-enable---makes-`-edit`-work-002 │ ├── tests-test_hipatterns.lua---Auto-enable---works │ ├── tests-test_hipatterns.lua---Autocommands---resets-on-color-scheme-change │ ├── tests-test_hipatterns.lua---Autocommands---resets-on-color-scheme-change-002 │ ├── tests-test_hipatterns.lua---Autocommands---resets-on-color-scheme-change-003 │ ├── tests-test_hipatterns.lua---Highlighters---allows-array-`pattern` │ ├── tests-test_hipatterns.lua---Highlighters---allows-array-`pattern`-002 │ ├── tests-test_hipatterns.lua---Highlighters---allows-callable-`group` │ ├── tests-test_hipatterns.lua---Highlighters---allows-callable-`pattern` │ ├── tests-test_hipatterns.lua---Highlighters---allows-frontier-pattern-in-`pattern` │ ├── tests-test_hipatterns.lua---Highlighters---allows-return-`nil`-`group`-to-not-highlight │ ├── tests-test_hipatterns.lua---Highlighters---allows-return-`nil`-`pattern`-to-not-highlight │ ├── tests-test_hipatterns.lua---Highlighters---allows-return-`nil`-`pattern`-to-not-highlight-002 │ ├── tests-test_hipatterns.lua---Highlighters---allows-submatch-in-`pattern` │ ├── tests-test_hipatterns.lua---Highlighters---allows-submatch-in-`pattern`-002 │ ├── tests-test_hipatterns.lua---Highlighters---allows-submatch-in-`pattern`-003 │ ├── tests-test_hipatterns.lua---Highlighters---allows-submatch-in-`pattern`-004 │ ├── tests-test_hipatterns.lua---Highlighters---allows-submatch-in-`pattern`-005 │ ├── tests-test_hipatterns.lua---Highlighters---respects-`extmark_opts.priority` │ ├── tests-test_hipatterns.lua---Highlighters---respects-`extmark_opts.priority`-002 │ ├── tests-test_hipatterns.lua---Highlighters---respects-`extmark_opts.priority`-003 │ ├── tests-test_hipatterns.lua---Highlighters---respects-`extmark_opts` │ ├── tests-test_hipatterns.lua---Highlighters---silently-skips-wrong-entries │ ├── tests-test_hipatterns.lua---disable()---works │ ├── tests-test_hipatterns.lua---disable()---works-002 │ ├── tests-test_hipatterns.lua---disable()---works-in-not-current-buffer │ ├── tests-test_hipatterns.lua---disable()---works-in-not-current-buffer-002 │ ├── tests-test_hipatterns.lua---enable()---does-not-flicker-during-text-insert │ ├── tests-test_hipatterns.lua---enable()---does-not-flicker-during-text-insert-002 │ ├── tests-test_hipatterns.lua---enable()---does-not-flicker-during-text-insert-003 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-buffer-enter │ ├── tests-test_hipatterns.lua---enable()---reacts-to-buffer-enter-002 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-delete-of-line-with-match │ ├── tests-test_hipatterns.lua---enable()---reacts-to-delete-of-line-with-match-002 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-delete-of-line-with-match-003 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-delete-of-line-with-match-004 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-filetype-change │ ├── tests-test_hipatterns.lua---enable()---reacts-to-filetype-change-002 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-filetype-change-003 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-text-change │ ├── tests-test_hipatterns.lua---enable()---reacts-to-text-change-002 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-text-change-003 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-text-change-004 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-text-change-005 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-window-scroll │ ├── tests-test_hipatterns.lua---enable()---reacts-to-window-scroll-002 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-window-scroll-003 │ ├── tests-test_hipatterns.lua---enable()---reacts-to-window-scroll-004 │ ├── tests-test_hipatterns.lua---enable()---respects-`vim.b.minihipatterns_config` │ ├── tests-test_hipatterns.lua---enable()---respects-`vim.b.minihipatterns_config`-002 │ ├── tests-test_hipatterns.lua---enable()---respects-`vim.b.minihipatterns_config`-003 │ ├── tests-test_hipatterns.lua---enable()---respects-`vim.{g,b}.minihipatterns_disable`---test-+-args-{-'b'-} │ ├── tests-test_hipatterns.lua---enable()---respects-`vim.{g,b}.minihipatterns_disable`---test-+-args-{-'g'-} │ ├── tests-test_hipatterns.lua---enable()---respects-global-config-after-`setup()` │ ├── tests-test_hipatterns.lua---enable()---works │ ├── tests-test_hipatterns.lua---enable()---works-in-not-current-buffer │ ├── tests-test_hipatterns.lua---enable()---works-in-not-normal-buffer │ ├── tests-test_hipatterns.lua---enable()---works-with-defaults │ ├── tests-test_hipatterns.lua---gen_highlighter---hex_color()---respects-`opts.filter` │ ├── tests-test_hipatterns.lua---gen_highlighter---hex_color()---respects-`opts.filter`-002 │ ├── tests-test_hipatterns.lua---gen_highlighter---hex_color()---respects-`opts.priority` │ ├── tests-test_hipatterns.lua---gen_highlighter---hex_color()---respects-`opts.priority`-002 │ ├── tests-test_hipatterns.lua---gen_highlighter---hex_color()---respects-`opts.priority`-003 │ ├── tests-test_hipatterns.lua---gen_highlighter---hex_color()---works │ ├── tests-test_hipatterns.lua---gen_highlighter---hex_color()---works-with-style-'#' │ ├── tests-test_hipatterns.lua---gen_highlighter---hex_color()---works-with-style-'inline' │ ├── tests-test_hipatterns.lua---gen_highlighter---hex_color()---works-with-style-'line' │ ├── tests-test_hipatterns.lua---setup()---auto-enables-in-all-visible-buffers │ ├── tests-test_hipatterns.lua---setup()---auto-enables-in-all-visible-buffers-002 │ ├── tests-test_hipatterns.lua---toggle()---works │ ├── tests-test_hipatterns.lua---toggle()---works-002 │ ├── tests-test_hipatterns.lua---update()---works │ ├── tests-test_hipatterns.lua---update()---works-002 │ ├── tests-test_hipatterns.lua---update()---works-003 │ ├── tests-test_hipatterns.lua---update()---works-004 │ ├── tests-test_hipatterns.lua---update()---works-005 │ ├── tests-test_hipatterns.lua---update()---works-006 │ ├── tests-test_indentscope.lua---Auto-drawing---by-default-is-not-done-for-incomplete-scope │ ├── tests-test_indentscope.lua---Auto-drawing---by-default-is-not-done-for-incomplete-scope-002 │ ├── tests-test_indentscope.lua---Auto-drawing---by-default-is-not-done-for-incomplete-scope-003 │ ├── tests-test_indentscope.lua---Auto-drawing---by-default-is-not-done-for-incomplete-scope-004 │ ├── tests-test_indentscope.lua---Auto-drawing---by-default-is-not-done-for-incomplete-scope-005 │ ├── tests-test_indentscope.lua---Auto-drawing---implements-debounce-style-delay │ ├── tests-test_indentscope.lua---Auto-drawing---implements-debounce-style-delay-002 │ ├── tests-test_indentscope.lua---Auto-drawing---respects-ModeChanged-event │ ├── tests-test_indentscope.lua---Auto-drawing---respects-ModeChanged-event-002 │ ├── tests-test_indentscope.lua---Auto-drawing---respects-ModeChanged-event-003 │ ├── tests-test_indentscope.lua---Auto-drawing---respects-`config.draw.delay` │ ├── tests-test_indentscope.lua---Auto-drawing---respects-`config.draw.delay`-002 │ ├── tests-test_indentscope.lua---Auto-drawing---respects-`config.draw.predicate` │ ├── tests-test_indentscope.lua---Auto-drawing---respects-`config.draw.predicate`-002 │ ├── tests-test_indentscope.lua---Auto-drawing---respects-`config.draw.predicate`-003 │ ├── tests-test_indentscope.lua---Auto-drawing---respects-`vim.{g,b}.miniindentscope_disable`---test-+-args-{-'b'-} │ ├── tests-test_indentscope.lua---Auto-drawing---respects-`vim.{g,b}.miniindentscope_disable`---test-+-args-{-'b'-}-002 │ ├── tests-test_indentscope.lua---Auto-drawing---respects-`vim.{g,b}.miniindentscope_disable`---test-+-args-{-'g'-} │ ├── tests-test_indentscope.lua---Auto-drawing---respects-`vim.{g,b}.miniindentscope_disable`---test-+-args-{-'g'-}-002 │ ├── tests-test_indentscope.lua---Auto-drawing---respects-common-events---test-+-args-{-'CursorMoved'-} │ ├── tests-test_indentscope.lua---Auto-drawing---respects-common-events---test-+-args-{-'CursorMovedI'-} │ ├── tests-test_indentscope.lua---Auto-drawing---respects-common-events---test-+-args-{-'TextChanged'-} │ ├── tests-test_indentscope.lua---Auto-drawing---respects-common-events---test-+-args-{-'TextChangedI'-} │ ├── tests-test_indentscope.lua---Auto-drawing---respects-common-events---test-+-args-{-'TextChangedP'-} │ ├── tests-test_indentscope.lua---Auto-drawing---updates-immediately-when-scopes-intersect │ ├── tests-test_indentscope.lua---Auto-drawing---updates-immediately-when-scopes-intersect-002 │ ├── tests-test_indentscope.lua---Auto-drawing---works-in-Insert-mode │ ├── tests-test_indentscope.lua---Auto-drawing---works-in-Insert-mode-002 │ ├── tests-test_indentscope.lua---Auto-drawing---works-in-Insert-mode-003 │ ├── tests-test_indentscope.lua---Auto-drawing---works-in-Normal-mode │ ├── tests-test_indentscope.lua---Auto-drawing---works-in-Normal-mode-002 │ ├── tests-test_indentscope.lua---Auto-drawing---works-in-Normal-mode-003 │ ├── tests-test_indentscope.lua---draw()---does-not-overshadow-'listchars' │ ├── tests-test_indentscope.lua---draw()---does-not-round-time-of-every-animation-step │ ├── tests-test_indentscope.lua---draw()---respects-`config.draw.animation` │ ├── tests-test_indentscope.lua---draw()---respects-`config.draw.animation`-002 │ ├── tests-test_indentscope.lua---draw()---respects-`config.draw.animation`-003 │ ├── tests-test_indentscope.lua---draw()---respects-`config.draw.animation`-004 │ ├── tests-test_indentscope.lua---draw()---respects-`config.draw.priority` │ ├── tests-test_indentscope.lua---draw()---respects-`config.draw.priority`-002 │ ├── tests-test_indentscope.lua---draw()---respects-`config.symbol` │ ├── tests-test_indentscope.lua---draw()---respects-`config.symbol`-002 │ ├── tests-test_indentscope.lua---draw()---shows-symbols-on-wrapped-lines-without-overlapping │ ├── tests-test_indentscope.lua---draw()---shows-symbols-on-wrapped-lines-without-overlapping-002 │ ├── tests-test_indentscope.lua---draw()---shows-symbols-on-wrapped-lines-without-overlapping-003 │ ├── tests-test_indentscope.lua---draw()---works │ ├── tests-test_indentscope.lua---draw()---works-002 │ ├── tests-test_indentscope.lua---draw()---works-003 │ ├── tests-test_indentscope.lua---draw()---works-004 │ ├── tests-test_indentscope.lua---undraw()---works │ ├── tests-test_indentscope.lua---undraw()---works-002 │ ├── tests-test_jump.lua---Delayed-highlighting---done-only-if-actually-jumping │ ├── tests-test_jump.lua---Delayed-highlighting---implements-debounce-style-delay │ ├── tests-test_jump.lua---Delayed-highlighting---implements-debounce-style-delay-002 │ ├── tests-test_jump.lua---Delayed-highlighting---implements-debounce-style-delay-003 │ ├── tests-test_jump.lua---Delayed-highlighting---never-highlights-in-Insert-mode │ ├── tests-test_jump.lua---Delayed-highlighting---never-highlights-in-Insert-mode-002 │ ├── tests-test_jump.lua---Delayed-highlighting---respects-'ignorecase' │ ├── tests-test_jump.lua---Delayed-highlighting---respects-'smartcase' │ ├── tests-test_jump.lua---Delayed-highlighting---respects-`config.delay.highlight`---test-+-args-{-'backward'-} │ ├── tests-test_jump.lua---Delayed-highlighting---respects-`config.delay.highlight`---test-+-args-{-'backward'-}-002 │ ├── tests-test_jump.lua---Delayed-highlighting---respects-`config.delay.highlight`---test-+-args-{-'backward_till'-} │ ├── tests-test_jump.lua---Delayed-highlighting---respects-`config.delay.highlight`---test-+-args-{-'backward_till'-}-002 │ ├── tests-test_jump.lua---Delayed-highlighting---respects-`config.delay.highlight`---test-+-args-{-'forward'-} │ ├── tests-test_jump.lua---Delayed-highlighting---respects-`config.delay.highlight`---test-+-args-{-'forward'-}-002 │ ├── tests-test_jump.lua---Delayed-highlighting---respects-`config.delay.highlight`---test-+-args-{-'forward_till'-} │ ├── tests-test_jump.lua---Delayed-highlighting---respects-`config.delay.highlight`---test-+-args-{-'forward_till'-}-002 │ ├── tests-test_jump.lua---Delayed-highlighting---respects-`vim.b.minijump_config` │ ├── tests-test_jump.lua---Delayed-highlighting---respects-`vim.b.minijump_config`-002 │ ├── tests-test_jump.lua---Delayed-highlighting---stops-immediately-when-not-jumping │ ├── tests-test_jump.lua---Delayed-highlighting---stops-immediately-when-not-jumping-002 │ ├── tests-test_jump.lua---Delayed-highlighting---updates-immediately-within-same-jumping │ ├── tests-test_jump.lua---Delayed-highlighting---updates-immediately-within-same-jumping-002 │ ├── tests-test_jump.lua---Delayed-highlighting---updates-immediately-within-same-jumping-003 │ ├── tests-test_jump.lua---Delayed-highlighting---works---test-+-args-{-'backward'-} │ ├── tests-test_jump.lua---Delayed-highlighting---works---test-+-args-{-'backward'-}-002 │ ├── tests-test_jump.lua---Delayed-highlighting---works---test-+-args-{-'backward_till'-} │ ├── tests-test_jump.lua---Delayed-highlighting---works---test-+-args-{-'backward_till'-}-002 │ ├── tests-test_jump.lua---Delayed-highlighting---works---test-+-args-{-'forward'-} │ ├── tests-test_jump.lua---Delayed-highlighting---works---test-+-args-{-'forward'-}-002 │ ├── tests-test_jump.lua---Delayed-highlighting---works---test-+-args-{-'forward_till'-} │ ├── tests-test_jump.lua---Delayed-highlighting---works---test-+-args-{-'forward_till'-}-002 │ ├── tests-test_jump.lua---Jumping-with-f-t-F-T---respects-`config.silent` │ ├── tests-test_jump.lua---Jumping-with-f-t-F-T---shows-reminder-after-one-idle-second │ ├── tests-test_jump.lua---Jumping-with-f-t-F-T---shows-reminder-after-one-idle-second-002 │ ├── tests-test_jump.lua---Stop-jumping-after-idle---works │ ├── tests-test_jump.lua---Stop-jumping-after-idle---works-002 │ ├── tests-test_jump.lua---Stop-jumping-after-idle---works-if-should-be-done-before-target-highlighting │ ├── tests-test_jump2d.lua---builtin_opts.line_start---works │ ├── tests-test_jump2d.lua---builtin_opts.single_character---shows-reminder-after-one-idle-second │ ├── tests-test_jump2d.lua---builtin_opts.word_start---works │ ├── tests-test_jump2d.lua---builtin_opts.word_start---works-002 │ ├── tests-test_jump2d.lua---builtin_opts.word_start---works-with-multibyte-characters │ ├── tests-test_jump2d.lua---default_spotter()---correctly-merges-'overlapping'-spots │ ├── tests-test_jump2d.lua---default_spotter()---spots-before-and-after-punctuation │ ├── tests-test_jump2d.lua---default_spotter()---spots-first-capital-letter │ ├── tests-test_jump2d.lua---default_spotter()---spots-start-and-end-of-words │ ├── tests-test_jump2d.lua---default_spotter()---works │ ├── tests-test_jump2d.lua---default_spotter()---works-(almost)-with-multibyte-character │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---handles-patterns-with-'^'-and-'$'---test-+-args-{-'.()..$',-'none'-} │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---handles-patterns-with-'^'-and-'$'---test-+-args-{-'...$',-'end'-} │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---handles-patterns-with-'^'-and-'$'---test-+-args-{-'...$',-'start'-} │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---handles-patterns-with-'^'-and-'$'---test-+-args-{-'^.()..',-'none'-} │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---handles-patterns-with-'^'-and-'$'---test-+-args-{-'^...',-'end'-} │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---handles-patterns-with-'^'-and-'$'---test-+-args-{-'^...',-'start'-} │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---respects-`pattern`-argument │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---respects-`side`-argument---test-+-args-{-'%S+',-'end'-} │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---respects-`side`-argument---test-+-args-{-'%S+',-'start'-} │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---respects-`side`-argument---test-+-args-{-'.().',-'none'-} │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---works │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---works-in-edge-cases │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---works-with-multibyte-characters │ ├── tests-test_jump2d.lua---gen_spotter---pattern()---works-with-multibyte-characters-002 │ ├── tests-test_jump2d.lua---gen_spotter---union()---works │ ├── tests-test_jump2d.lua---gen_spotter---vimpattern---respects-`pattern`-argument │ ├── tests-test_jump2d.lua---gen_spotter---vimpattern---works │ ├── tests-test_jump2d.lua---gen_spotter---vimpattern---works-002 │ ├── tests-test_jump2d.lua---gen_spotter---vimpattern---works-with-anchored-patterns │ ├── tests-test_jump2d.lua---gen_spotter---vimpattern---works-with-anchored-patterns-002 │ ├── tests-test_jump2d.lua---gen_spotter---vimpattern---works-with-anchored-patterns-003 │ ├── tests-test_jump2d.lua---gen_spotter---vimpattern---works-with-anchored-patterns-004 │ ├── tests-test_jump2d.lua---gen_spotter---vimpattern---works-with-multibyte-characters │ ├── tests-test_jump2d.lua---setup()---applies-`config.mappings` │ ├── tests-test_jump2d.lua---start()---allows-`hook.before_start`-to-modify-spotter │ ├── tests-test_jump2d.lua---start()---handles-overlapping-multi-step-labels │ ├── tests-test_jump2d.lua---start()---handles-overlapping-multi-step-labels-002 │ ├── tests-test_jump2d.lua---start()---handles-overlapping-multi-step-labels-003 │ ├── tests-test_jump2d.lua---start()---handles-overlapping-multi-step-labels-004 │ ├── tests-test_jump2d.lua---start()---handles-very-big-`view.n_steps_ahead` │ ├── tests-test_jump2d.lua---start()---handles-very-big-`view.n_steps_ahead`-002 │ ├── tests-test_jump2d.lua---start()---highlights-unique-labels-with-different-highlight-group │ ├── tests-test_jump2d.lua---start()---ignores-current-window-during-label-computation---test-+-args-{-'bottomleft'-} │ ├── tests-test_jump2d.lua---start()---ignores-current-window-during-label-computation---test-+-args-{-'topright'-} │ ├── tests-test_jump2d.lua---start()---ignores-cursor-position-during-label-computation---test-+-args-{-1,-1-} │ ├── tests-test_jump2d.lua---start()---ignores-cursor-position-during-label-computation---test-+-args-{-2,-0-} │ ├── tests-test_jump2d.lua---start()---ignores-cursor-position-during-label-computation---test-+-args-{-3,-0-} │ ├── tests-test_jump2d.lua---start()---ignores-cursor-position-during-label-computation---test-+-args-{-3,-3-} │ ├── tests-test_jump2d.lua---start()---ignores-not-focusable-windows │ ├── tests-test_jump2d.lua---start()---jumps-immediately-to-single-spot │ ├── tests-test_jump2d.lua---start()---overrides-`config`-from-`opts`-argument │ ├── tests-test_jump2d.lua---start()---respects-`allowed_lines.blank` │ ├── tests-test_jump2d.lua---start()---respects-`allowed_lines.blank`-002 │ ├── tests-test_jump2d.lua---start()---respects-`allowed_lines.cursor_-`---test-+-args-{-'cursor_after'-} │ ├── tests-test_jump2d.lua---start()---respects-`allowed_lines.cursor_-`---test-+-args-{-'cursor_after'-}-002 │ ├── tests-test_jump2d.lua---start()---respects-`allowed_lines.cursor_-`---test-+-args-{-'cursor_at'-} │ ├── tests-test_jump2d.lua---start()---respects-`allowed_lines.cursor_-`---test-+-args-{-'cursor_at'-}-002 │ ├── tests-test_jump2d.lua---start()---respects-`allowed_lines.cursor_-`---test-+-args-{-'cursor_before'-} │ ├── tests-test_jump2d.lua---start()---respects-`allowed_lines.cursor_-`---test-+-args-{-'cursor_before'-}-002 │ ├── tests-test_jump2d.lua---start()---respects-`allowed_lines.fold` │ ├── tests-test_jump2d.lua---start()---respects-`allowed_lines.fold`-002 │ ├── tests-test_jump2d.lua---start()---respects-`allowed_windows`---test-+-args-{-{current-=-false,not_current-=-false}-} │ ├── tests-test_jump2d.lua---start()---respects-`allowed_windows`---test-+-args-{-{current-=-false,not_current-=-false}-}-002 │ ├── tests-test_jump2d.lua---start()---respects-`allowed_windows`---test-+-args-{-{current-=-false}-} │ ├── tests-test_jump2d.lua---start()---respects-`allowed_windows`---test-+-args-{-{current-=-false}-}-002 │ ├── tests-test_jump2d.lua---start()---respects-`allowed_windows`---test-+-args-{-{not_current-=-false}-} │ ├── tests-test_jump2d.lua---start()---respects-`allowed_windows`---test-+-args-{-{not_current-=-false}-}-002 │ ├── tests-test_jump2d.lua---start()---respects-`config.silent` │ ├── tests-test_jump2d.lua---start()---respects-`labels` │ ├── tests-test_jump2d.lua---start()---respects-`labels`-002 │ ├── tests-test_jump2d.lua---start()---respects-`opts.hl_group_dim` │ ├── tests-test_jump2d.lua---start()---respects-`spotter` │ ├── tests-test_jump2d.lua---start()---respects-`spotter`-002 │ ├── tests-test_jump2d.lua---start()---respects-`view.dim` │ ├── tests-test_jump2d.lua---start()---respects-`view.dim`-002 │ ├── tests-test_jump2d.lua---start()---respects-`view.dim`-003 │ ├── tests-test_jump2d.lua---start()---respects-`view.n_steps_ahead` │ ├── tests-test_jump2d.lua---start()---respects-`view.n_steps_ahead`-002 │ ├── tests-test_jump2d.lua---start()---respects-`view.n_steps_ahead`-003 │ ├── tests-test_jump2d.lua---start()---respects-`view.n_steps_ahead`-004 │ ├── tests-test_jump2d.lua---start()---respects-`view.n_steps_ahead`-005 │ ├── tests-test_jump2d.lua---start()---respects-`vim.{g,b}.minijump2d_disable`---test-+-args-{-'b'-} │ ├── tests-test_jump2d.lua---start()---respects-`vim.{g,b}.minijump2d_disable`---test-+-args-{-'g'-} │ ├── tests-test_jump2d.lua---start()---respects-folds │ ├── tests-test_jump2d.lua---start()---respects-folds-002 │ ├── tests-test_jump2d.lua---start()---shows-reminder-after-one-idle-second │ ├── tests-test_jump2d.lua---start()---shows-reminder-after-one-idle-second-002 │ ├── tests-test_jump2d.lua---start()---shows-reminder-after-one-idle-second-003 │ ├── tests-test_jump2d.lua---start()---stops-jumping-if-not-label-was-typed---test-+-args-{-'-C-c-'-} │ ├── tests-test_jump2d.lua---start()---stops-jumping-if-not-label-was-typed---test-+-args-{-'-Down-'-} │ ├── tests-test_jump2d.lua---start()---stops-jumping-if-not-label-was-typed---test-+-args-{-'-Esc-'-} │ ├── tests-test_jump2d.lua---start()---traverses-floating-windows-at-the-end │ ├── tests-test_jump2d.lua---start()---traverses-visible-'regular'-windows-based-on-their-layout │ ├── tests-test_jump2d.lua---start()---uses-`-CR-`-to-jump-to-first-available-spot │ ├── tests-test_jump2d.lua---start()---uses-`spotter`-with-correct-arguments │ ├── tests-test_jump2d.lua---start()---uses-only-all-visible-windows-by-default │ ├── tests-test_jump2d.lua---start()---uses-only-visible-lines │ ├── tests-test_jump2d.lua---start()---uses-only-visible-lines-002 │ ├── tests-test_jump2d.lua---start()---works │ ├── tests-test_jump2d.lua---start()---works-002 │ ├── tests-test_jump2d.lua---start()---works-in-Operator-pending-mode │ ├── tests-test_jump2d.lua---start()---works-in-Operator-pending-mode-002 │ ├── tests-test_jump2d.lua---start()---works-in-Operator-pending-mode-003 │ ├── tests-test_jump2d.lua---start()---works-in-Operator-pending-mode-004 │ ├── tests-test_jump2d.lua---start()---works-in-Visual-mode │ ├── tests-test_jump2d.lua---start()---works-in-Visual-mode-002 │ ├── tests-test_jump2d.lua---stop()---clears-all-highlighting │ ├── tests-test_jump2d.lua---stop()---clears-all-highlighting-002 │ ├── tests-test_jump2d.lua---stop()---works │ ├── tests-test_jump2d.lua---stop()---works-002 │ ├── tests-test_map.lua---Cursor-in-map-window---opens-enough-folds-in-source-window │ ├── tests-test_map.lua---Cursor-in-map-window---opens-enough-folds-in-source-window-002 │ ├── tests-test_map.lua---Pure-scrollbar---is-active-when-width-is-lower-than-offset │ ├── tests-test_map.lua---Pure-scrollbar---is-active-when-width-is-lower-than-offset-002 │ ├── tests-test_map.lua---Pure-scrollbar---is-active-when-width-is-lower-than-offset-003 │ ├── tests-test_map.lua---Pure-scrollbar---works │ ├── tests-test_map.lua---Pure-scrollbar---works-002 │ ├── tests-test_map.lua---Scrollbar---updates-on-cursor-movement │ ├── tests-test_map.lua---Scrollbar---updates-on-cursor-movement-002 │ ├── tests-test_map.lua---Scrollbar---updates-on-cursor-movement-003 │ ├── tests-test_map.lua---Scrollbar---updates-on-cursor-movement-004 │ ├── tests-test_map.lua---Scrollbar---updates-on-source-window-scrolling │ ├── tests-test_map.lua---Scrollbar---updates-on-source-window-scrolling-002 │ ├── tests-test_map.lua---Window---does-not-account-for-folds │ ├── tests-test_map.lua---Window---does-not-account-for-folds-002 │ ├── tests-test_map.lua---Window---does-not-account-for-folds-003 │ ├── tests-test_map.lua---Window---does-not-respect-'winborder'-option │ ├── tests-test_map.lua---Window---fully-updates-on-buffer-enter │ ├── tests-test_map.lua---Window---fully-updates-on-buffer-enter-002 │ ├── tests-test_map.lua---Window---fully-updates-on-buffer-write │ ├── tests-test_map.lua---Window---fully-updates-on-buffer-write-002 │ ├── tests-test_map.lua---Window---fully-updates-on-mode-change-to-Normal │ ├── tests-test_map.lua---Window---fully-updates-on-mode-change-to-Normal-002 │ ├── tests-test_map.lua---Window---fully-updates-on-text-change-in-Normal-mode │ ├── tests-test_map.lua---Window---fully-updates-on-text-change-in-Normal-mode-002 │ ├── tests-test_map.lua---Window---fully-updates-on-vim-resize │ ├── tests-test_map.lua---Window---fully-updates-on-vim-resize-002 │ ├── tests-test_map.lua---gen_encode_symbols---can-be-used-as-`MiniMap.config.symbols.encode` │ ├── tests-test_map.lua---gen_encode_symbols---can-be-used-as-part-of-`opts.symbols.encode` │ ├── tests-test_map.lua---gen_integration---builtin_search()---respects-documented-keymaps │ ├── tests-test_map.lua---gen_integration---builtin_search()---respects-documented-keymaps-002 │ ├── tests-test_map.lua---gen_integration---builtin_search()---respects-documented-keymaps-003 │ ├── tests-test_map.lua---gen_integration---builtin_search()---respects-documented-keymaps-004 │ ├── tests-test_map.lua---gen_integration---builtin_search()---updates-when-appropriate │ ├── tests-test_map.lua---gen_integration---builtin_search()---updates-when-appropriate-002 │ ├── tests-test_map.lua---gen_integration---builtin_search()---updates-when-appropriate-003 │ ├── tests-test_map.lua---gen_integration---builtin_search()---updates-when-appropriate-004 │ ├── tests-test_map.lua---gen_integration---builtin_search()---updates-when-appropriate-005 │ ├── tests-test_map.lua---gen_integration---builtin_search()---works │ ├── tests-test_map.lua---gen_integration---builtin_search()---works-002 │ ├── tests-test_map.lua---gen_integration---diagnostic()---respects-`hl_groups`-argument │ ├── tests-test_map.lua---gen_integration---diagnostic()---respects-`hl_groups`-argument-002 │ ├── tests-test_map.lua---gen_integration---diagnostic()---respects-`hl_groups`-argument-003 │ ├── tests-test_map.lua---gen_integration---diagnostic()---respects-`hl_groups`-argument-004 │ ├── tests-test_map.lua---gen_integration---diagnostic()---updates-when-appropriate │ ├── tests-test_map.lua---gen_integration---diagnostic()---updates-when-appropriate-002 │ ├── tests-test_map.lua---gen_integration---diagnostic()---works │ ├── tests-test_map.lua---gen_integration---diff()---works │ ├── tests-test_map.lua---gen_integration---gitsigns()---respects-`hl_groups`-argument │ ├── tests-test_map.lua---gen_integration---gitsigns()---updates-when-appropriate │ ├── tests-test_map.lua---gen_integration---gitsigns()---updates-when-appropriate-002 │ ├── tests-test_map.lua---gen_integration---gitsigns()---works │ ├── tests-test_map.lua---open()---allows-more-than-single-character-in-scroll-symbols │ ├── tests-test_map.lua---open()---can-open-pure-scrollbar │ ├── tests-test_map.lua---open()---respects-`MiniMapNormal`-highlight-group │ ├── tests-test_map.lua---open()---respects-`opts.integrations`-argument │ ├── tests-test_map.lua---open()---respects-`opts.symbols`-argument │ ├── tests-test_map.lua---open()---respects-`opts.symbols`-argument-002 │ ├── tests-test_map.lua---open()---respects-`opts.window`-argument │ ├── tests-test_map.lua---open()---shows-appropriate-integration-counts │ ├── tests-test_map.lua---open()---works │ ├── tests-test_map.lua---refresh()---respects-`opts.integrations`-argument │ ├── tests-test_map.lua---refresh()---respects-`opts.symbols`-argument │ ├── tests-test_map.lua---refresh()---respects-`opts.window`-argument │ ├── tests-test_map.lua---refresh()---respects-`parts`-argument │ ├── tests-test_map.lua---refresh()---respects-`parts`-argument-002 │ ├── tests-test_map.lua---refresh()---respects-`parts`-argument-003 │ ├── tests-test_map.lua---refresh()---respects-`parts`-argument-004 │ ├── tests-test_map.lua---refresh()---respects-`parts`-argument-005 │ ├── tests-test_map.lua---refresh()---respects-`vim.{g,b}.minimap_disable`---test-+-args-{-'b'-} │ ├── tests-test_map.lua---refresh()---respects-`vim.{g,b}.minimap_disable`---test-+-args-{-'g'-} │ ├── tests-test_map.lua---refresh()---works │ ├── tests-test_map.lua---refresh()---works-002 │ ├── tests-test_misc.lua---zoom()---respects-'winborder'-option │ ├── tests-test_misc.lua---zoom()---respects-'winborder'-option-002 │ ├── tests-test_misc.lua---zoom()---respects-'winborder'-option-003 │ ├── tests-test_misc.lua---zoom()---respects-`config`-argument │ ├── tests-test_misc.lua---zoom()---respects-`config`-argument-002 │ ├── tests-test_misc.lua---zoom()---respects-`config`-argument-003 │ ├── tests-test_misc.lua---zoom()---respects-`config`-argument-004 │ ├── tests-test_misc.lua---zoom()---respects-`config`-argument-005 │ ├── tests-test_misc.lua---zoom()---respects-`config`-argument-006 │ ├── tests-test_misc.lua---zoom()---respects-`config`-argument-007 │ ├── tests-test_misc.lua---zoom()---respects-`config`-argument-008 │ ├── tests-test_misc.lua---zoom()---respects-`config`-argument-009 │ ├── tests-test_misc.lua---zoom()---works │ ├── tests-test_notify.lua---LSP-progress---handles-not-present-data │ ├── tests-test_notify.lua---LSP-progress---handles-not-present-data-002 │ ├── tests-test_notify.lua---LSP-progress---handles-not-present-data-003 │ ├── tests-test_notify.lua---LSP-progress---respects-`lsp_progress.duration_last` │ ├── tests-test_notify.lua---LSP-progress---respects-`lsp_progress.duration_last`-002 │ ├── tests-test_notify.lua---LSP-progress---works │ ├── tests-test_notify.lua---LSP-progress---works-002 │ ├── tests-test_notify.lua---LSP-progress---works-003 │ ├── tests-test_notify.lua---LSP-progress---works-004 │ ├── tests-test_notify.lua---LSP-progress---works-005 │ ├── tests-test_notify.lua---Window---computes-default-dimensions-based-on-buffer-content │ ├── tests-test_notify.lua---Window---computes-default-dimensions-based-on-buffer-content-002 │ ├── tests-test_notify.lua---Window---fully-updates-on-vim-resize │ ├── tests-test_notify.lua---Window---fully-updates-on-vim-resize-002 │ ├── tests-test_notify.lua---Window---fully-updates-on-vim-resize-003 │ ├── tests-test_notify.lua---Window---fully-updates-on-vim-resize-004 │ ├── tests-test_notify.lua---Window---handles-width-computation-for-empty-lines-inside-notification-buffer │ ├── tests-test_notify.lua---Window---respects-'winborder'-option │ ├── tests-test_notify.lua---Window---respects-'winborder'-option-002 │ ├── tests-test_notify.lua---Window---respects-'winborder'-option-003 │ ├── tests-test_notify.lua---Window---respects-`content.format` │ ├── tests-test_notify.lua---Window---respects-`content.sort` │ ├── tests-test_notify.lua---Window---respects-`window.config` │ ├── tests-test_notify.lua---Window---respects-`window.config`-002 │ ├── tests-test_notify.lua---Window---respects-`window.config`-003 │ ├── tests-test_notify.lua---Window---respects-`window.max_width_share` │ ├── tests-test_notify.lua---Window---respects-`window.max_width_share`-002 │ ├── tests-test_notify.lua---Window---respects-`window.max_width_share`-003 │ ├── tests-test_notify.lua---Window---respects-`window.max_width_share`-004 │ ├── tests-test_notify.lua---Window---respects-tabline-statusline-cmdline │ ├── tests-test_notify.lua---Window---respects-tabline-statusline-cmdline-002 │ ├── tests-test_notify.lua---Window---respects-tabline-statusline-cmdline-003 │ ├── tests-test_notify.lua---Window---respects-tabline-statusline-cmdline-004 │ ├── tests-test_notify.lua---Window---respects-tabline-statusline-cmdline-005 │ ├── tests-test_notify.lua---Window---respects-tabline-statusline-cmdline-006 │ ├── tests-test_notify.lua---Window---respects-tabline-statusline-cmdline-007 │ ├── tests-test_notify.lua---Window---respects-tabline-statusline-cmdline-008 │ ├── tests-test_notify.lua---Window---respects-tabline-statusline-cmdline-009 │ ├── tests-test_notify.lua---Window---respects-tabline-statusline-cmdline-010 │ ├── tests-test_notify.lua---Window---shows-start-of-buffer-if-it-does-not-fit-whole │ ├── tests-test_notify.lua---Window---works-with-multiline-messages │ ├── tests-test_notify.lua---Window---wraps-text │ ├── tests-test_notify.lua---Window---wraps-text-002 │ ├── tests-test_notify.lua---add()---allows-empty-string-message │ ├── tests-test_notify.lua---add()---works │ ├── tests-test_notify.lua---clear()---works │ ├── tests-test_notify.lua---clear()---works-002 │ ├── tests-test_notify.lua---make_notify()---works │ ├── tests-test_notify.lua---refresh()---respects-`vim.{g,b}.mininotify_disable`---test-+-args-{-'b'-} │ ├── tests-test_notify.lua---refresh()---respects-`vim.{g,b}.mininotify_disable`---test-+-args-{-'b'-}-002 │ ├── tests-test_notify.lua---refresh()---respects-`vim.{g,b}.mininotify_disable`---test-+-args-{-'b'-}-003 │ ├── tests-test_notify.lua---refresh()---respects-`vim.{g,b}.mininotify_disable`---test-+-args-{-'g'-} │ ├── tests-test_notify.lua---refresh()---respects-`vim.{g,b}.mininotify_disable`---test-+-args-{-'g'-}-002 │ ├── tests-test_notify.lua---refresh()---respects-`vim.{g,b}.mininotify_disable`---test-+-args-{-'g'-}-003 │ ├── tests-test_notify.lua---remove()---works │ ├── tests-test_notify.lua---remove()---works-002 │ ├── tests-test_notify.lua---remove()---works-with-several-active-notifications │ ├── tests-test_notify.lua---remove()---works-with-several-active-notifications-002 │ ├── tests-test_notify.lua---show_history()---respects-`content.format` │ ├── tests-test_notify.lua---show_history()---reuses-history-buffer │ ├── tests-test_notify.lua---show_history()---shows-all-notifications │ ├── tests-test_notify.lua---show_history()---sorts-by-update-time │ ├── tests-test_notify.lua---show_history()---works │ ├── tests-test_notify.lua---update()---works │ ├── tests-test_notify.lua---update()---works-002 │ ├── tests-test_operators.lua---Exchange---can-be-canceled │ ├── tests-test_operators.lua---Exchange---can-be-canceled-002 │ ├── tests-test_operators.lua---Exchange---correctly-highlights-first-step-with-'selection=exclusive' │ ├── tests-test_operators.lua---Exchange---highlights-first-step---test-+-args-{-'blockwise'-} │ ├── tests-test_operators.lua---Exchange---highlights-first-step---test-+-args-{-'charwise'-} │ ├── tests-test_operators.lua---Exchange---highlights-first-step---test-+-args-{-'linewise'-} │ ├── tests-test_operators.lua---Exchange---works-with-multibyte-characters │ ├── tests-test_operators.lua---Exchange---works-with-multibyte-characters-002 │ ├── tests-test_operators.lua---Exchange---works-with-multibyte-characters-003 │ ├── tests-test_operators.lua---Exchange---works-with-multibyte-characters-004 │ ├── tests-test_operators.lua---Exchange---works-with-multibyte-characters-005 │ ├── tests-test_operators.lua---Multiply---works-with-`cmdheight=0` │ ├── tests-test_operators.lua---Multiply---works-with-`cmdheight=0`-002 │ ├── tests-test_operators.lua---Replace---works-with-`cmdheight=0` │ ├── tests-test_operators.lua---Replace---works-with-`cmdheight=0`-002 │ ├── tests-test_pairs.lua----BS--action---works │ ├── tests-test_pick.lua----Pick---has-proper-complete │ ├── tests-test_pick.lua----Pick---has-proper-complete-002 │ ├── tests-test_pick.lua----Pick---has-proper-complete-003 │ ├── tests-test_pick.lua----Pick---works │ ├── tests-test_pick.lua----Pick---works-002 │ ├── tests-test_pick.lua---Caret---moves-by-query-parts │ ├── tests-test_pick.lua---Caret---moves-by-query-parts-002 │ ├── tests-test_pick.lua---Caret---moves-by-query-parts-003 │ ├── tests-test_pick.lua---Caret---works │ ├── tests-test_pick.lua---Caret---works-002 │ ├── tests-test_pick.lua---Caret---works-003 │ ├── tests-test_pick.lua---Choose---works-for-split-tab-variations │ ├── tests-test_pick.lua---Choose---works-for-split-tab-variations-002 │ ├── tests-test_pick.lua---Choose---works-for-split-tab-variations-003 │ ├── tests-test_pick.lua---Info-view---is-updated-after-moving-marking-current-item │ ├── tests-test_pick.lua---Info-view---is-updated-after-moving-marking-current-item-002 │ ├── tests-test_pick.lua---Info-view---is-updated-after-moving-marking-current-item-003 │ ├── tests-test_pick.lua---Info-view---is-updated-after-moving-marking-current-item-004 │ ├── tests-test_pick.lua---Info-view---respects-custom-mappings │ ├── tests-test_pick.lua---Info-view---supports-vertical-and-horizontal-scroll │ ├── tests-test_pick.lua---Info-view---supports-vertical-and-horizontal-scroll-002 │ ├── tests-test_pick.lua---Info-view---supports-vertical-and-horizontal-scroll-003 │ ├── tests-test_pick.lua---Info-view---supports-vertical-and-horizontal-scroll-004 │ ├── tests-test_pick.lua---Info-view---works │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-002 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-003 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-004 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-005 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-006 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-007 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-008 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-009 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-010 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-011 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-012 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-013 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-014 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-015 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-016 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-017 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-018 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-019 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-020 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-021 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-022 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-023 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-024 │ ├── tests-test_pick.lua---Main-view---properly-computes-items-range-to-show-025 │ ├── tests-test_pick.lua---Main-view---shows-marked-items-across-queries │ ├── tests-test_pick.lua---Main-view---shows-marked-items-across-queries-002 │ ├── tests-test_pick.lua---Main-view---supports-horizontal-scroll │ ├── tests-test_pick.lua---Main-view---supports-horizontal-scroll-002 │ ├── tests-test_pick.lua---Main-view---supports-horizontal-scroll-003 │ ├── tests-test_pick.lua---Main-view---supports-horizontal-scroll-004 │ ├── tests-test_pick.lua---Main-view---supports-horizontal-scroll-005 │ ├── tests-test_pick.lua---Main-view---supports-horizontal-scroll-006 │ ├── tests-test_pick.lua---Main-view---works-with-`content_from_bottom`=true │ ├── tests-test_pick.lua---Main-view---works-with-`content_from_bottom`=true-002 │ ├── tests-test_pick.lua---Main-view---works-with-`content_from_bottom`=true-003 │ ├── tests-test_pick.lua---Main-view---works-with-`content_from_bottom`=true-004 │ ├── tests-test_pick.lua---Main-view---works-with-`content_from_bottom`=true-005 │ ├── tests-test_pick.lua---Main-view---works-with-`content_from_bottom`=true-006 │ ├── tests-test_pick.lua---Main-view---works-with-`content_from_bottom`=true-007 │ ├── tests-test_pick.lua---Main-view---works-with-`content_from_bottom`=true-008 │ ├── tests-test_pick.lua---Main-view---works-with-`content_from_bottom`=true-009 │ ├── tests-test_pick.lua---Main-view---works-with-`content_from_bottom`=true-010 │ ├── tests-test_pick.lua---Mark---works-without-items-set │ ├── tests-test_pick.lua---Matching---dedicated-event-can-update-window-config │ ├── tests-test_pick.lua---Matching---dedicated-event-can-update-window-config-002 │ ├── tests-test_pick.lua---Matching---dedicated-event-can-update-window-config-003 │ ├── tests-test_pick.lua---Matching---dedicated-event-can-update-window-config-004 │ ├── tests-test_pick.lua---Move---works-when-no-items-are-set │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-002 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-003 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-004 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-005 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-006 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-007 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-008 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-009 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-010 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-011 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-012 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-013 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-014 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-015 │ ├── tests-test_pick.lua---Overall-view---adjusts-dimensions-respecting-border-016 │ ├── tests-test_pick.lua---Overall-view---allows-'none'-as-border │ ├── tests-test_pick.lua---Overall-view---allows-very-large-dimensions │ ├── tests-test_pick.lua---Overall-view---correctly-infers-footer-empty-space │ ├── tests-test_pick.lua---Overall-view---correctly-infers-footer-empty-space-002 │ ├── tests-test_pick.lua---Overall-view---correctly-infers-footer-empty-space-003 │ ├── tests-test_pick.lua---Overall-view---correctly-infers-footer-empty-space-004 │ ├── tests-test_pick.lua---Overall-view---does-not-show-footer-if-items-are-not-set │ ├── tests-test_pick.lua---Overall-view---is-shown-over-number-and-sign-columns │ ├── tests-test_pick.lua---Overall-view---respects-'winborder'-option │ ├── tests-test_pick.lua---Overall-view---respects-'winborder'-option-002 │ ├── tests-test_pick.lua---Overall-view---respects-'winborder'-option-003 │ ├── tests-test_pick.lua---Overall-view---respects-'winborder'-option-004 │ ├── tests-test_pick.lua---Overall-view---respects-`options.content_from_bottom`-with-footer │ ├── tests-test_pick.lua---Overall-view---respects-tabline,-statusline,-'cmdheight' │ ├── tests-test_pick.lua---Overall-view---respects-tabline,-statusline,-'cmdheight'-002 │ ├── tests-test_pick.lua---Overall-view---respects-tabline,-statusline,-'cmdheight'-003 │ ├── tests-test_pick.lua---Overall-view---respects-tabline,-statusline,-'cmdheight'-004 │ ├── tests-test_pick.lua---Overall-view---respects-tabline,-statusline,-'cmdheight'-005 │ ├── tests-test_pick.lua---Overall-view---respects-tabline,-statusline,-'cmdheight'-006 │ ├── tests-test_pick.lua---Overall-view---sanitizes-picker-name │ ├── tests-test_pick.lua---Overall-view---sanitizes-picker-name-002 │ ├── tests-test_pick.lua---Overall-view---shows-prompt │ ├── tests-test_pick.lua---Overall-view---shows-prompt-002 │ ├── tests-test_pick.lua---Overall-view---shows-prompt-003 │ ├── tests-test_pick.lua---Overall-view---shows-prompt-004 │ ├── tests-test_pick.lua---Overall-view---shows-prompt-005 │ ├── tests-test_pick.lua---Overall-view---truncates-footer │ ├── tests-test_pick.lua---Overall-view---truncates-footer-002 │ ├── tests-test_pick.lua---Overall-view---truncates-footer-003 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-002 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-003 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-004 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-005 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-006 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-007 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-008 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-009 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-010 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-011 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-012 │ ├── tests-test_pick.lua---Overall-view---truncates-prompt-013 │ ├── tests-test_pick.lua---Overall-view---uses-footer-for-extra-info │ ├── tests-test_pick.lua---Overall-view---uses-footer-for-extra-info-002 │ ├── tests-test_pick.lua---Overall-view---uses-footer-for-extra-info-003 │ ├── tests-test_pick.lua---Overall-view---uses-footer-for-extra-info-004 │ ├── tests-test_pick.lua---Overall-view---uses-footer-for-extra-info-005 │ ├── tests-test_pick.lua---Overall-view---uses-footer-for-extra-info-006 │ ├── tests-test_pick.lua---Overall-view---works-with-small-available-dimensions │ ├── tests-test_pick.lua---Paste---works │ ├── tests-test_pick.lua---Paste---works-002 │ ├── tests-test_pick.lua---Paste---works-003 │ ├── tests-test_pick.lua---Preview---does-explicit-redraw-several-times │ ├── tests-test_pick.lua---Preview---does-explicit-redraw-several-times-002 │ ├── tests-test_pick.lua---Preview---is-updated-after-moving-current-item │ ├── tests-test_pick.lua---Preview---is-updated-after-moving-current-item-002 │ ├── tests-test_pick.lua---Preview---respects-global-value-of-'list'-and-'listchars'-option │ ├── tests-test_pick.lua---Preview---respects-global-value-of-'list'-and-'listchars'-option-002 │ ├── tests-test_pick.lua---Preview---respects-global-value-of-'list'-and-'listchars'-option-003 │ ├── tests-test_pick.lua---Preview---respects-global-value-of-'list'-and-'listchars'-option-004 │ ├── tests-test_pick.lua---Preview---supports-vertical-and-horizontal-scroll │ ├── tests-test_pick.lua---Preview---supports-vertical-and-horizontal-scroll-002 │ ├── tests-test_pick.lua---Preview---supports-vertical-and-horizontal-scroll-003 │ ├── tests-test_pick.lua---Preview---supports-vertical-and-horizontal-scroll-004 │ ├── tests-test_pick.lua---Preview---works │ ├── tests-test_pick.lua---Refine---works │ ├── tests-test_pick.lua---Refine---works-002 │ ├── tests-test_pick.lua---Refine---works-003 │ ├── tests-test_pick.lua---Refine---works-when-no-items-are-set │ ├── tests-test_pick.lua---builtin.buffers()---respects-`local_opts.include_current` │ ├── tests-test_pick.lua---builtin.buffers()---respects-`local_opts.include_unlisted` │ ├── tests-test_pick.lua---builtin.buffers()---respects-`source.show`-from-config │ ├── tests-test_pick.lua---builtin.buffers()---works │ ├── tests-test_pick.lua---builtin.files()---respects-`source.show`-from-config │ ├── tests-test_pick.lua---builtin.files()---works │ ├── tests-test_pick.lua---builtin.grep()---respects-`source.show`-from-config │ ├── tests-test_pick.lua---builtin.grep()---works │ ├── tests-test_pick.lua---builtin.grep()---works-002 │ ├── tests-test_pick.lua---builtin.grep_live()---has-custom-'add-glob'-mapping │ ├── tests-test_pick.lua---builtin.grep_live()---respects-`source.show`-from-config │ ├── tests-test_pick.lua---builtin.grep_live()---works │ ├── tests-test_pick.lua---builtin.help()---handles-consecutive-applications │ ├── tests-test_pick.lua---builtin.help()---has-proper-preview │ ├── tests-test_pick.lua---builtin.help()---works │ ├── tests-test_pick.lua---builtin.help()---works-002 │ ├── tests-test_pick.lua---builtin.help()---works-for-help-tags-with-special-characters │ ├── tests-test_pick.lua---builtin.help()---works-when-help-window-is-already-opened │ ├── tests-test_pick.lua---builtin.help()---works-with-`builtin.resume()` │ ├── tests-test_pick.lua---builtin.help()---works-with-`builtin.resume()`-002 │ ├── tests-test_pick.lua---builtin.resume()---works │ ├── tests-test_pick.lua---default_match()---works-with-active-picker │ ├── tests-test_pick.lua---default_match()---works-with-active-picker-002 │ ├── tests-test_pick.lua---default_preview()---can-be-used-in-outside-preview-window │ ├── tests-test_pick.lua---default_preview()---does-not-highlight-big-files │ ├── tests-test_pick.lua---default_preview()---does-not-highlight-big-files-002 │ ├── tests-test_pick.lua---default_preview()---has-fallback │ ├── tests-test_pick.lua---default_preview()---has-fallback-002 │ ├── tests-test_pick.lua---default_preview()---has-syntax-highlighting-in-buffer │ ├── tests-test_pick.lua---default_preview()---has-syntax-highlighting-in-buffer-002 │ ├── tests-test_pick.lua---default_preview()---has-syntax-highlighting-in-file-path │ ├── tests-test_pick.lua---default_preview()---has-syntax-highlighting-in-file-path-002 │ ├── tests-test_pick.lua---default_preview()---loads-context-in-buffer │ ├── tests-test_pick.lua---default_preview()---loads-context-in-buffer-002 │ ├── tests-test_pick.lua---default_preview()---loads-context-in-buffer-003 │ ├── tests-test_pick.lua---default_preview()---loads-context-in-file-path │ ├── tests-test_pick.lua---default_preview()---loads-context-in-file-path-002 │ ├── tests-test_pick.lua---default_preview()---loads-context-in-file-path-003 │ ├── tests-test_pick.lua---default_preview()---respects-`opts.line_position`---1-+-args-{-'bottom'-} │ ├── tests-test_pick.lua---default_preview()---respects-`opts.line_position`---1-+-args-{-'bottom'-}-002 │ ├── tests-test_pick.lua---default_preview()---respects-`opts.line_position`---1-+-args-{-'center'-} │ ├── tests-test_pick.lua---default_preview()---respects-`opts.line_position`---1-+-args-{-'center'-}-002 │ ├── tests-test_pick.lua---default_preview()---respects-`opts.line_position`---1-+-args-{-'top'-} │ ├── tests-test_pick.lua---default_preview()---respects-`opts.line_position`---1-+-args-{-'top'-}-002 │ ├── tests-test_pick.lua---default_preview()---respects-`opts.n_context_lines` │ ├── tests-test_pick.lua---default_preview()---respects-`opts.n_context_lines`-002 │ ├── tests-test_pick.lua---default_preview()---respects-`source.cwd` │ ├── tests-test_pick.lua---default_preview()---shows-line-in-buffer │ ├── tests-test_pick.lua---default_preview()---shows-line-in-file-path │ ├── tests-test_pick.lua---default_preview()---shows-line-in-file-path-002 │ ├── tests-test_pick.lua---default_preview()---shows-position-in-buffer │ ├── tests-test_pick.lua---default_preview()---shows-position-in-file-path │ ├── tests-test_pick.lua---default_preview()---shows-position-in-file-path-002 │ ├── tests-test_pick.lua---default_preview()---shows-region-in-buffer │ ├── tests-test_pick.lua---default_preview()---shows-region-in-buffer-002 │ ├── tests-test_pick.lua---default_preview()---shows-region-in-file-path │ ├── tests-test_pick.lua---default_preview()---shows-region-in-file-path-002 │ ├── tests-test_pick.lua---default_preview()---works │ ├── tests-test_pick.lua---default_preview()---works-for-URI-path │ ├── tests-test_pick.lua---default_preview()---works-for-buffer │ ├── tests-test_pick.lua---default_preview()---works-for-buffer-002 │ ├── tests-test_pick.lua---default_preview()---works-for-buffer-003 │ ├── tests-test_pick.lua---default_preview()---works-for-buffer-004 │ ├── tests-test_pick.lua---default_preview()---works-for-buffer-005 │ ├── tests-test_pick.lua---default_preview()---works-for-directory-path │ ├── tests-test_pick.lua---default_preview()---works-for-directory-path-002 │ ├── tests-test_pick.lua---default_preview()---works-for-file-path │ ├── tests-test_pick.lua---default_preview()---works-for-file-path-002 │ ├── tests-test_pick.lua---default_preview()---works-for-file-path-003 │ ├── tests-test_pick.lua---default_preview()---works-for-file-path-004 │ ├── tests-test_pick.lua---default_preview()---works-for-file-path-with-tilde │ ├── tests-test_pick.lua---default_preview()---works-for-relative-file-path │ ├── tests-test_pick.lua---default_preview()---works-for-relative-file-path-002 │ ├── tests-test_pick.lua---default_preview()---works-without-active-picker │ ├── tests-test_pick.lua---default_preview()---works-without-active-picker-002 │ ├── tests-test_pick.lua---default_show()---handles-edge-cases │ ├── tests-test_pick.lua---default_show()---handles-query-similar-to-`default_match` │ ├── tests-test_pick.lua---default_show()---handles-query-similar-to-`default_match`-002 │ ├── tests-test_pick.lua---default_show()---handles-query-similar-to-`default_match`-003 │ ├── tests-test_pick.lua---default_show()---handles-query-similar-to-`default_match`-004 │ ├── tests-test_pick.lua---default_show()---handles-query-similar-to-`default_match`-005 │ ├── tests-test_pick.lua---default_show()---handles-stritems-with-non-trivial-whitespace │ ├── tests-test_pick.lua---default_show()---respects-'ignorecase'-'smartcase' │ ├── tests-test_pick.lua---default_show()---respects-'ignorecase'-'smartcase'-002 │ ├── tests-test_pick.lua---default_show()---respects-'ignorecase'-'smartcase'-003 │ ├── tests-test_pick.lua---default_show()---respects-'ignorecase'-'smartcase'-004 │ ├── tests-test_pick.lua---default_show()---respects-'ignorecase'-'smartcase'-005 │ ├── tests-test_pick.lua---default_show()---respects-'ignorecase'-'smartcase'-006 │ ├── tests-test_pick.lua---default_show()---respects-`opts.icons` │ ├── tests-test_pick.lua---default_show()---respects-`opts.icons`-002 │ ├── tests-test_pick.lua---default_show()---respects-`opts.icons`-003 │ ├── tests-test_pick.lua---default_show()---respects-`opts.show_icons` │ ├── tests-test_pick.lua---default_show()---respects-`opts.show_icons`-002 │ ├── tests-test_pick.lua---default_show()---respects-`opts.show_icons`-003 │ ├── tests-test_pick.lua---default_show()---respects-`opts.show_icons`-004 │ ├── tests-test_pick.lua---default_show()---shows-best-match │ ├── tests-test_pick.lua---default_show()---shows-best-match-002 │ ├── tests-test_pick.lua---default_show()---works │ ├── tests-test_pick.lua---default_show()---works-with-multibyte-characters │ ├── tests-test_pick.lua---default_show()---works-with-multibyte-characters-002 │ ├── tests-test_pick.lua---default_show()---works-with-non-single-char-entries-queries │ ├── tests-test_pick.lua---default_show()---works-with-non-single-char-entries-queries-002 │ ├── tests-test_pick.lua---default_show()---works-with-non-single-char-entries-queries-003 │ ├── tests-test_pick.lua---default_show()---works-without-active-picker │ ├── tests-test_pick.lua---default_show()---works-without-active-picker-002 │ ├── tests-test_pick.lua---refresh()---is-called-on-`VimResized` │ ├── tests-test_pick.lua---refresh()---is-called-on-`VimResized`-002 │ ├── tests-test_pick.lua---refresh()---recomputes-window-config │ ├── tests-test_pick.lua---refresh()---recomputes-window-config-002 │ ├── tests-test_pick.lua---refresh()---works │ ├── tests-test_pick.lua---refresh()---works-002 │ ├── tests-test_pick.lua---set_picker_items()---recomputes-visible-range │ ├── tests-test_pick.lua---set_picker_match_inds()---can-set-current-match-index │ ├── tests-test_pick.lua---set_picker_match_inds()---can-set-marked-match-indexes │ ├── tests-test_pick.lua---set_picker_match_inds()---can-set-marked-match-indexes-002 │ ├── tests-test_pick.lua---set_picker_match_inds()---works │ ├── tests-test_pick.lua---set_picker_opts()---works │ ├── tests-test_pick.lua---set_picker_opts()---works-002 │ ├── tests-test_pick.lua---set_picker_opts()---works-003 │ ├── tests-test_pick.lua---set_picker_query()---works │ ├── tests-test_pick.lua---start()---can-be-started-without-explicit-items │ ├── tests-test_pick.lua---start()---correctly-computes-stritems │ ├── tests-test_pick.lua---start()---respects-`options.content_from_bottom` │ ├── tests-test_pick.lua---start()---respects-`source.items` │ ├── tests-test_pick.lua---start()---respects-`source.items`-002 │ ├── tests-test_pick.lua---start()---respects-`source.items`-003 │ ├── tests-test_pick.lua---start()---respects-`source.items`-004 │ ├── tests-test_pick.lua---start()---respects-`source.match` │ ├── tests-test_pick.lua---start()---respects-`source.name` │ ├── tests-test_pick.lua---start()---respects-`source.preview` │ ├── tests-test_pick.lua---start()---respects-`source.preview`-002 │ ├── tests-test_pick.lua---start()---respects-`source.show` │ ├── tests-test_pick.lua---start()---respects-`source.show`-002 │ ├── tests-test_pick.lua---start()---respects-`vim.b.minipick_config` │ ├── tests-test_pick.lua---start()---respects-`window.config` │ ├── tests-test_pick.lua---start()---respects-`window.config`-002 │ ├── tests-test_pick.lua---start()---respects-`window.prompt_caret` │ ├── tests-test_pick.lua---start()---respects-`window.prompt_caret`-002 │ ├── tests-test_pick.lua---start()---respects-`window.prompt_prefix` │ ├── tests-test_pick.lua---start()---respects-`window.prompt_prefix`-002 │ ├── tests-test_pick.lua---start()---respects-`window.prompt_prefix`-003 │ ├── tests-test_pick.lua---start()---respects-`window.prompt_prefix`-004 │ ├── tests-test_pick.lua---start()---respects-global-config │ ├── tests-test_pick.lua---start()---stops-currently-active-picker │ ├── tests-test_pick.lua---start()---stops-improperly-aborted-previous-picker │ ├── tests-test_pick.lua---start()---stops-improperly-aborted-previous-picker-002 │ ├── tests-test_pick.lua---start()---tracks-lost-focus │ ├── tests-test_pick.lua---start()---tracks-lost-focus-002 │ ├── tests-test_pick.lua---start()---tracks-lost-focus-003 │ ├── tests-test_pick.lua---start()---works │ ├── tests-test_pick.lua---start()---works-002 │ ├── tests-test_pick.lua---start()---works-on-Neovim-0.9 │ ├── tests-test_pick.lua---start()---works-on-Neovim-0.9-002 │ ├── tests-test_pick.lua---start()---works-with-window-footer │ ├── tests-test_pick.lua---start()---works-with-window-footer-002 │ ├── tests-test_pick.lua---stop()---works │ ├── tests-test_pick.lua---stop()---works-002 │ ├── tests-test_pick.lua---ui_select()---respects-`opts.preview_item` │ ├── tests-test_pick.lua---ui_select()---respects-`start_opts` │ ├── tests-test_pick.lua---ui_select()---shows-only-original-item-in-preview │ ├── tests-test_pick.lua---ui_select()---works │ ├── tests-test_snippets.lua---Interaction-with-built-in-completion---no-affect-of-'exausted'-popup-during-jump │ ├── tests-test_snippets.lua---Interaction-with-built-in-completion---squashed-tabstops │ ├── tests-test_snippets.lua---Interaction-with-built-in-completion---squashed-tabstops-002 │ ├── tests-test_snippets.lua---Session---autostop---is-not-triggered-if-final-tabstop-is-not-current │ ├── tests-test_snippets.lua---Session---choices---are-always-shown-all-at-once │ ├── tests-test_snippets.lua---Session---choices---are-always-shown-all-at-once-002 │ ├── tests-test_snippets.lua---Session---choices---are-always-shown-all-at-once-003 │ ├── tests-test_snippets.lua---Session---choices---work-with-default-'completeopt' │ ├── tests-test_snippets.lua---Session---choices---work-with-default-'completeopt'-002 │ ├── tests-test_snippets.lua---Session---choices---works │ ├── tests-test_snippets.lua---Session---choices---works-002 │ ├── tests-test_snippets.lua---Session---does-not-show-'Pattern-not-found'-message │ ├── tests-test_snippets.lua---Session---highlighting---uses-same-highlighting-for-whole-placeholder-for-current-tabstop │ ├── tests-test_snippets.lua---Session---highlighting---uses-same-highlighting-for-whole-placeholder-for-current-tabstop-002 │ ├── tests-test_snippets.lua---Session---highlighting---uses-same-highlighting-for-whole-placeholder-for-current-tabstop-003 │ ├── tests-test_snippets.lua---Session---linked-tabstops---are-updated-immediately-when-typing │ ├── tests-test_snippets.lua---Session---linked-tabstops---are-updated-immediately-when-typing-002 │ ├── tests-test_snippets.lua---Session---linked-tabstops---are-updated-immediately-when-typing-003 │ ├── tests-test_snippets.lua---Session---linked-tabstops---jumps-to-the-first-node │ ├── tests-test_snippets.lua---Session---linked-tabstops---jumps-to-the-first-node-002 │ ├── tests-test_snippets.lua---Session---linked-tabstops---jumps-to-the-first-node-003 │ ├── tests-test_snippets.lua---Session---linked-tabstops---validates-that-session-data-is-valid │ ├── tests-test_snippets.lua---Session---linked-tabstops---validates-that-session-data-is-valid-002 │ ├── tests-test_snippets.lua---Session---nesting---can-be-done-outside-of-current-session-region │ ├── tests-test_snippets.lua---Session---nesting---does-not-nest-if-no-tabstops-in-new-session │ ├── tests-test_snippets.lua---Session---nesting---works-and-triggers-events │ ├── tests-test_snippets.lua---Session---nesting---works-and-triggers-events-002 │ ├── tests-test_snippets.lua---Session---nesting---works-and-triggers-events-003 │ ├── tests-test_snippets.lua---Session---nesting---works-and-triggers-events-004 │ ├── tests-test_snippets.lua---Session---nesting---works-and-triggers-events-005 │ ├── tests-test_snippets.lua---Session---persists-after-`-edit` │ ├── tests-test_snippets.lua---Session---preserves-order-of-'squashed'-empty-tabstops │ ├── tests-test_snippets.lua---Session---preserves-order-of-'squashed'-empty-tabstops-002 │ ├── tests-test_snippets.lua---Session---preserves-order-of-'squashed'-empty-tabstops-003 │ ├── tests-test_snippets.lua---Session---preserves-order-of-'squashed'-empty-tabstops-004 │ ├── tests-test_snippets.lua---Session---preserves-order-of-'squashed'-empty-tabstops-005 │ ├── tests-test_snippets.lua---Tricky-snippets---intertwined-nested-tabstops │ ├── tests-test_snippets.lua---Tricky-snippets---intertwined-nested-tabstops-002 │ ├── tests-test_snippets.lua---Tricky-snippets---intertwined-nested-tabstops-003 │ ├── tests-test_snippets.lua---Tricky-snippets---intertwined-nested-tabstops-004 │ ├── tests-test_snippets.lua---Tricky-snippets---intertwined-nested-tabstops-005 │ ├── tests-test_snippets.lua---Tricky-snippets---intertwined-nested-tabstops-006 │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops,-another │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops,-another-002 │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops,-another-003 │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops,-another-004 │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops,-another-005 │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops,-another-006 │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops-002 │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops-003 │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops-004 │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops-005 │ ├── tests-test_snippets.lua---Tricky-snippets---nested-empty-tabstops-006 │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-empty-consecutive-tabstops │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-empty-consecutive-tabstops-002 │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-empty-consecutive-tabstops-003 │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-empty-consecutive-tabstops-004 │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-empty-consecutive-tabstops-005 │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-empty-interleaving-tabstops │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-empty-interleaving-tabstops-002 │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-empty-interleaving-tabstops-003 │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-empty-interleaving-tabstops-004 │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-empty-interleaving-tabstops-005 │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-tabstops-with-placeholders │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-tabstops-with-placeholders-002 │ ├── tests-test_snippets.lua---Tricky-snippets---squashed-linked-tabstops-with-placeholders-003 │ ├── tests-test_snippets.lua---Various-snippets---placeholders │ ├── tests-test_snippets.lua---Various-snippets---placeholders-002 │ ├── tests-test_snippets.lua---Various-snippets---placeholders-003 │ ├── tests-test_snippets.lua---Various-snippets---placeholders-004 │ ├── tests-test_snippets.lua---Various-snippets---placeholders-005 │ ├── tests-test_snippets.lua---Various-snippets---placeholders-006 │ ├── tests-test_snippets.lua---Various-snippets---placeholders-007 │ ├── tests-test_snippets.lua---Various-snippets---tabstop │ ├── tests-test_snippets.lua---Various-snippets---tabstop-002 │ ├── tests-test_snippets.lua---default_insert()---respects-`opts.empty_tabstop`-and-`opts.empty_tabstop_final` │ ├── tests-test_snippets.lua---default_insert()---respects-`opts.lookup` │ ├── tests-test_snippets.lua---session.stop()---ensures-next-nested-session-is-valid │ ├── tests-test_snippets.lua---session.stop()---works │ ├── tests-test_snippets.lua---session.stop()---works-002 │ ├── tests-test_snippets.lua---session.stop()---works-003 │ ├── tests-test_starter.lua---Default-content---'Recent-files'-section---displays-only-readable-files │ ├── tests-test_starter.lua---Default-content---'Recent-files'-section---present-even-if-no-recent-files │ ├── tests-test_starter.lua---Default-content---'Sessions'-section---present-even-if-no-sessions-detected │ ├── tests-test_starter.lua---Default-content---'Sessions'-section---works │ ├── tests-test_starter.lua---Default-content---computes-`header`-depending-on-time-of-day---test-+-args-{-'00'-} │ ├── tests-test_starter.lua---Default-content---computes-`header`-depending-on-time-of-day---test-+-args-{-'04'-} │ ├── tests-test_starter.lua---Default-content---computes-`header`-depending-on-time-of-day---test-+-args-{-'08'-} │ ├── tests-test_starter.lua---Default-content---computes-`header`-depending-on-time-of-day---test-+-args-{-'12'-} │ ├── tests-test_starter.lua---Default-content---computes-`header`-depending-on-time-of-day---test-+-args-{-'16'-} │ ├── tests-test_starter.lua---Default-content---computes-`header`-depending-on-time-of-day---test-+-args-{-'20'-} │ ├── tests-test_starter.lua---Default-content---works │ ├── tests-test_starter.lua---Highlighting---uses-`MiniStarterItemBullet` │ ├── tests-test_starter.lua---Highlighting---uses-`MiniStarterItemBullet`-002 │ ├── tests-test_starter.lua---Highlighting---works-for-current-item │ ├── tests-test_starter.lua---Highlighting---works-for-current-item-002 │ ├── tests-test_starter.lua---Highlighting---works-for-querying │ ├── tests-test_starter.lua---Highlighting---works-for-querying-002 │ ├── tests-test_starter.lua---Highlighting---works-for-querying-003 │ ├── tests-test_starter.lua---Querying---works-with-`cmdheight=0` │ ├── tests-test_starter.lua---Resize---updates-Starter-buffer │ ├── tests-test_starter.lua---gen_hook---adding_bullet()---respects-`bullet`-argument │ ├── tests-test_starter.lua---gen_hook---adding_bullet()---works │ ├── tests-test_starter.lua---gen_hook---aligning()---handles-small-windows │ ├── tests-test_starter.lua---gen_hook---aligning()---has-output-respecting-`buf_id`-argument │ ├── tests-test_starter.lua---gen_hook---aligning()---has-output-respecting-`buf_id`-argument-002 │ ├── tests-test_starter.lua---gen_hook---aligning()---respects-arguments---test-+-args-{-''center',-'bottom''-} │ ├── tests-test_starter.lua---gen_hook---aligning()---respects-arguments---test-+-args-{-''center',-'center''-} │ ├── tests-test_starter.lua---gen_hook---aligning()---respects-arguments---test-+-args-{-''center',-'top''-} │ ├── tests-test_starter.lua---gen_hook---aligning()---respects-arguments---test-+-args-{-''left',-'bottom''-} │ ├── tests-test_starter.lua---gen_hook---aligning()---respects-arguments---test-+-args-{-''left',-'center''-} │ ├── tests-test_starter.lua---gen_hook---aligning()---respects-arguments---test-+-args-{-''left',-'top''-} │ ├── tests-test_starter.lua---gen_hook---aligning()---respects-arguments---test-+-args-{-''right',-'bottom''-} │ ├── tests-test_starter.lua---gen_hook---aligning()---respects-arguments---test-+-args-{-''right',-'center''-} │ ├── tests-test_starter.lua---gen_hook---aligning()---respects-arguments---test-+-args-{-''right',-'top''-} │ ├── tests-test_starter.lua---gen_hook---aligning()---works │ ├── tests-test_starter.lua---gen_hook---indexing()---respects-arguments---test-+-args-{-''all',-nil'-} │ ├── tests-test_starter.lua---gen_hook---indexing()---respects-arguments---test-+-args-{-''section',-nil'-} │ ├── tests-test_starter.lua---gen_hook---indexing()---respects-arguments---test-+-args-{-'nil,-{-'AAA'-}'-} │ ├── tests-test_starter.lua---gen_hook---indexing()---respects-arguments---test-+-args-{-'nil,-{}'-} │ ├── tests-test_starter.lua---gen_hook---indexing()---works │ ├── tests-test_starter.lua---gen_hook---padding()---respects-arguments---test-+-args-{-'0,-2'-} │ ├── tests-test_starter.lua---gen_hook---padding()---respects-arguments---test-+-args-{-'2,-0'-} │ ├── tests-test_starter.lua---gen_hook---padding()---respects-arguments---test-+-args-{-'2,-2'-} │ ├── tests-test_starter.lua---gen_hook---padding()---works │ ├── tests-test_starter.lua---get_content()---works │ ├── tests-test_starter.lua---open()---respects-`vim.b.ministarter_config` │ ├── tests-test_starter.lua---refresh()---respects-`config.silent` │ ├── tests-test_starter.lua---refresh()---respects-`config.silent`-002 │ ├── tests-test_starter.lua---refresh()---respects-`vim.b.ministarter_config` │ ├── tests-test_starter.lua---refresh()---respects-`vim.b.ministarter_config`-002 │ ├── tests-test_starter.lua---sections---recent_files()---correctly-identifies-files-from-current-directory │ ├── tests-test_starter.lua---sections---recent_files()---respects-`show_path` │ ├── tests-test_starter.lua---sections---recent_files()---respects-files-in-subdirectories │ ├── tests-test_starter.lua---sections---works │ ├── tests-test_statusline.lua---Default-content---active---test-+-args-{-120-} │ ├── tests-test_statusline.lua---Default-content---active---test-+-args-{-39-} │ ├── tests-test_statusline.lua---Default-content---active---test-+-args-{-40-} │ ├── tests-test_statusline.lua---Default-content---active---test-+-args-{-75-} │ ├── tests-test_statusline.lua---Default-content---inactive-is-evaluated-in-the-context-of-its-window │ ├── tests-test_surround.lua---Add-surrounding---respects-`config.silent` │ ├── tests-test_surround.lua---Add-surrounding---shows-reminder-after-one-idle-second │ ├── tests-test_surround.lua---Add-surrounding---shows-reminder-after-one-idle-second-002 │ ├── tests-test_surround.lua---Add-surrounding---works-with-`cmdheight=0` │ ├── tests-test_surround.lua---Add-surrounding---works-with-`cmdheight=0`-002 │ ├── tests-test_surround.lua---Add-surrounding---works-with-`cmdheight=0`-003 │ ├── tests-test_surround.lua---Builtin---Function-call---colors-its-prompts │ ├── tests-test_surround.lua---Builtin---Function-call---colors-its-prompts-002 │ ├── tests-test_surround.lua---Builtin---Tag---colors-its-prompts │ ├── tests-test_surround.lua---Builtin---Tag---colors-its-prompts-002 │ ├── tests-test_surround.lua---Builtin---User-prompt---colors-its-prompts │ ├── tests-test_surround.lua---Builtin---User-prompt---colors-its-prompts-002 │ ├── tests-test_surround.lua---Builtin---User-prompt---colors-its-prompts-003 │ ├── tests-test_surround.lua---Delete-surrounding---respects-`config.silent` │ ├── tests-test_surround.lua---Delete-surrounding---respects-`config.silent`-002 │ ├── tests-test_surround.lua---Delete-surrounding---shows-reminder-after-one-idle-second │ ├── tests-test_surround.lua---Delete-surrounding---shows-reminder-after-one-idle-second-002 │ ├── tests-test_surround.lua---Find-surrounding---shows-reminder-after-one-idle-second │ ├── tests-test_surround.lua---Find-surrounding---shows-reminder-after-one-idle-second-002 │ ├── tests-test_surround.lua---Highlight-surrounding---removes-highlighting-in-correct-buffer │ ├── tests-test_surround.lua---Highlight-surrounding---removes-highlighting-in-correct-buffer-002 │ ├── tests-test_surround.lua---Highlight-surrounding---removes-highlighting-per-line │ ├── tests-test_surround.lua---Highlight-surrounding---removes-highlighting-per-line-002 │ ├── tests-test_surround.lua---Highlight-surrounding---removes-highlighting-per-line-003 │ ├── tests-test_surround.lua---Highlight-surrounding---respects-`config.n_lines` │ ├── tests-test_surround.lua---Highlight-surrounding---respects-`v-count`-for-input-surrounding │ ├── tests-test_surround.lua---Highlight-surrounding---respects-`vim.b.minisurround_config` │ ├── tests-test_surround.lua---Highlight-surrounding---respects-`vim.b.minisurround_config`-002 │ ├── tests-test_surround.lua---Highlight-surrounding---respects-`vim.{g,b}.minisurround_disable`---test-+-args-{-'b'-} │ ├── tests-test_surround.lua---Highlight-surrounding---respects-`vim.{g,b}.minisurround_disable`---test-+-args-{-'g'-} │ ├── tests-test_surround.lua---Highlight-surrounding---works-in-extended-mappings │ ├── tests-test_surround.lua---Highlight-surrounding---works-in-extended-mappings-002 │ ├── tests-test_surround.lua---Highlight-surrounding---works-in-extended-mappings-003 │ ├── tests-test_surround.lua---Highlight-surrounding---works-with-multiline-input-surroundings │ ├── tests-test_surround.lua---Highlight-surrounding---works-with-multiline-input-surroundings-002 │ ├── tests-test_surround.lua---Highlight-surrounding---works-with-multiline-input-surroundings-003 │ ├── tests-test_surround.lua---Highlight-surrounding---works-with-multiline-input-surroundings-004 │ ├── tests-test_surround.lua---Highlight-surrounding---works-without-dot-repeat │ ├── tests-test_surround.lua---Highlight-surrounding---works-without-dot-repeat-002 │ ├── tests-test_surround.lua---Highlight-surrounding---works-without-dot-repeat-003 │ ├── tests-test_surround.lua---Highlight-surrounding---works-without-dot-repeat-004 │ ├── tests-test_surround.lua---Replace-surrounding---respects-`config.silent` │ ├── tests-test_surround.lua---Replace-surrounding---respects-`config.silent`-002 │ ├── tests-test_surround.lua---Replace-surrounding---shows-reminder-after-one-idle-second │ ├── tests-test_surround.lua---Replace-surrounding---shows-reminder-after-one-idle-second-002 │ ├── tests-test_surround.lua---Replace-surrounding---shows-reminder-after-one-idle-second-003 │ ├── tests-test_surround.lua---gen_spec---input---treesitter()---works-with-empty-region │ ├── tests-test_tabline.lua---Screen---works │ ├── tests-test_tabline.lua---Screen---works-002 │ ├── tests-test_tabline.lua---Screen---works-003 │ ├── tests-test_tabline.lua---Screen---works-004 │ ├── tests-test_tabline.lua---Screen---works-005 │ ├── tests-test_test.lua---expect---reference_screenshot()---correctly-infers-reference-path │ ├── tests-test_test.lua---expect---reference_screenshot()---correctly-infers-reference-path-002 │ ├── tests-test_test.lua---expect---reference_screenshot()---correctly-infers-reference-path-004 │ ├── tests-test_test.lua---expect---reference_screenshot()---correctly-sanitizes-path-for-Windows- │ ├── tests-test_test.lua---expect---reference_screenshot()---correctly-sanitizes-path-for-Windows-#2- │ ├── tests-test_test.lua---expect---reference_screenshot()---works-with-multibyte-characters │ ├── tests-test_test.lua---gen_reporter---buffer---test-+-args-{-''-} │ ├── tests-test_test.lua---gen_reporter---buffer---test-+-args-{-'group_depth=2'-} │ ├── tests-test_test.lua---gen_reporter---buffer---test-+-args-{-'window={border='double',title=('a')-rep(200)}'-} │ ├── tests-test_test.lua---gen_reporter---buffer---test-+-args-{-'window={width=0.9-vim.o.columns,col=0.05-vim.o.columns}'-} │ ├── tests-test_test.lua---gen_reporter---buffer---test-+-args-{-'window={width=0.9-vim.o.columns,col=0.05-vim.o.columns}'-}-002 │ ├── tests-test_test.lua---gen_reporter---stdout---test-+-args-{-''-} │ ├── tests-test_test.lua---gen_reporter---stdout---test-+-args-{-'TEST_GROUP_DEPTH=2'-} │ ├── tests-test_test.lua---gen_reporter---stdout---test-+-args-{-'TEST_QUIT_ON_FINISH=false'-} │ ├── tests-test_trailspace.lua---Trailspace-autohighlighting---respects-BufEnter-BufLeave │ ├── tests-test_trailspace.lua---Trailspace-autohighlighting---respects-BufEnter-BufLeave-002 │ ├── tests-test_trailspace.lua---Trailspace-autohighlighting---respects-BufEnter-BufLeave-003 │ ├── tests-test_trailspace.lua---Trailspace-autohighlighting---respects-InsertEnter-InsertLeave │ ├── tests-test_trailspace.lua---Trailspace-autohighlighting---respects-InsertEnter-InsertLeave-002 │ ├── tests-test_trailspace.lua---Trailspace-autohighlighting---respects-InsertEnter-InsertLeave-003 │ ├── tests-test_trailspace.lua---Trailspace-autohighlighting---respects-OptionSet │ ├── tests-test_trailspace.lua---Trailspace-autohighlighting---respects-OptionSet-002 │ ├── tests-test_trailspace.lua---Trailspace-autohighlighting---respects-WinEnter-WinLeave │ ├── tests-test_trailspace.lua---Trailspace-autohighlighting---respects-WinEnter-WinLeave-002 │ ├── tests-test_trailspace.lua---Trailspace-autohighlighting---respects-WinEnter-WinLeave-003 │ ├── tests-test_trailspace.lua---Trailspace-highlighting-on-startup---works │ ├── tests-test_trailspace.lua---highlight()---respects-`config.only_in_normal_buffers`---test-+-args-{-false,-''-} │ ├── tests-test_trailspace.lua---highlight()---respects-`config.only_in_normal_buffers`---test-+-args-{-false,-'help'-} │ ├── tests-test_trailspace.lua---highlight()---respects-`config.only_in_normal_buffers`---test-+-args-{-false,-'nofile'-} │ ├── tests-test_trailspace.lua---highlight()---respects-`config.only_in_normal_buffers`---test-+-args-{-true,-''-} │ ├── tests-test_trailspace.lua---highlight()---respects-`config.only_in_normal_buffers`---test-+-args-{-true,-'help'-} │ ├── tests-test_trailspace.lua---highlight()---respects-`config.only_in_normal_buffers`---test-+-args-{-true,-'nofile'-} │ ├── tests-test_trailspace.lua---highlight()---respects-`vim.b.minitrailspace_config` │ ├── tests-test_trailspace.lua---highlight()---respects-`vim.{g,b}.minitrailspace_disable`---test-+-args-{-'b'-} │ ├── tests-test_trailspace.lua---highlight()---respects-`vim.{g,b}.minitrailspace_disable`---test-+-args-{-'g'-} │ ├── tests-test_trailspace.lua---highlight()---works │ ├── tests-test_trailspace.lua---highlight()---works-002 │ ├── tests-test_trailspace.lua---highlight()---works-after-`clearmatches()` │ ├── tests-test_trailspace.lua---highlight()---works-after-`clearmatches()`-002 │ ├── tests-test_trailspace.lua---highlight()---works-only-in-Normal-mode---test-+-args-{-'-'-} │ ├── tests-test_trailspace.lua---highlight()---works-only-in-Normal-mode---test-+-args-{-'R'-} │ ├── tests-test_trailspace.lua---highlight()---works-only-in-Normal-mode---test-+-args-{-'i'-} │ ├── tests-test_trailspace.lua---highlight()---works-only-in-Normal-mode---test-+-args-{-'v'-} │ ├── tests-test_trailspace.lua---unhighlight()---works │ ├── tests-test_trailspace.lua---unhighlight()---works-002 │ ├── tests-test_trailspace.lua---unhighlight()---works-after-`clearmatches()` │ ├── tests-test_visits.lua---add_label()---asks-user-for-label-if-it-is-not-supplied │ ├── tests-test_visits.lua---add_label()---asks-user-for-label-if-it-is-not-supplied-002 │ ├── tests-test_visits.lua---add_label()---asks-user-for-label-if-it-is-not-supplied-003 │ ├── tests-test_visits.lua---add_label()---works │ ├── tests-test_visits.lua---remove_label()---asks-user-for-label-if-it-is-not-supplied │ ├── tests-test_visits.lua---remove_label()---asks-user-for-label-if-it-is-not-supplied-002 │ ├── tests-test_visits.lua---remove_label()---asks-user-for-label-if-it-is-not-supplied-003 │ └── tests-test_visits.lua---remove_label()---works ├── test_ai.lua ├── test_align.lua ├── test_animate.lua ├── test_base16.lua ├── test_basics.lua ├── test_bracketed.lua ├── test_bufremove.lua ├── test_clue.lua ├── test_cmdline.lua ├── test_colors.lua ├── test_comment.lua ├── test_completion.lua ├── test_cursorword.lua ├── test_deps.lua ├── test_diff.lua ├── test_doc.lua ├── test_extra.lua ├── test_files.lua ├── test_fuzzy.lua ├── test_git.lua ├── test_hipatterns.lua ├── test_hues.lua ├── test_icons.lua ├── test_indentscope.lua ├── test_jump.lua ├── test_jump2d.lua ├── test_keymap.lua ├── test_map.lua ├── test_misc.lua ├── test_move.lua ├── test_notify.lua ├── test_operators.lua ├── test_pairs.lua ├── test_pick.lua ├── test_sessions.lua ├── test_snippets.lua ├── test_splitjoin.lua ├── test_starter.lua ├── test_statusline.lua ├── test_surround.lua ├── test_tabline.lua ├── test_test.lua ├── test_trailspace.lua └── test_visits.lua ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/DISCUSSION_TEMPLATE/q-a.yml ================================================ labels: [question] body: - type: checkboxes id: guidelines attributes: label: Contributing guidelines options: - label: I have read [CODE_OF_CONDUCT.md](https://github.com/nvim-mini/mini.nvim/blob/main/CODE_OF_CONDUCT.md) required: true - type: dropdown id: module attributes: label: "Module(s)" description: "Choose one or several modules this question is related to" multiple: true options: - mini.ai - mini.align - mini.animate - mini.base16 - mini.basics - mini.bracketed - mini.bufremove - mini.clue - mini.cmdline - mini.colors - mini.comment - mini.completion - mini.cursorword - mini.deps - mini.diff - mini.doc - mini.extra - mini.files - mini.fuzzy - mini.git - mini.hipatterns - mini.hues - mini.icons - mini.indentscope - mini.jump - mini.jump2d - mini.keymap - mini.map - mini.misc - mini.move - mini.notify - mini.operators - mini.pairs - mini.pick - mini.sessions - mini.snippets - mini.splitjoin - mini.starter - mini.statusline - mini.surround - mini.tabline - mini.test - mini.trailspace - mini.visits - none of the above - all of the above validations: required: true - type: textarea id: description attributes: label: "Question" validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/bug-report.yml ================================================ name: Bug report description: Report a problem with the existing module(s) labels: [bug] body: - type: checkboxes id: guidelines attributes: label: Contributing guidelines options: - label: I have read [CONTRIBUTING.md](https://github.com/nvim-mini/mini.nvim/blob/main/CONTRIBUTING.md) required: true - label: I have read [CODE_OF_CONDUCT.md](https://github.com/nvim-mini/mini.nvim/blob/main/CODE_OF_CONDUCT.md) required: true - label: I have updated 'mini.nvim' to latest version of the `main` branch required: true - type: dropdown id: module attributes: label: "Module(s)" description: "Choose one or several modules the problem is related to" multiple: true options: - mini.ai - mini.align - mini.animate - mini.base16 - mini.basics - mini.bracketed - mini.bufremove - mini.clue - mini.cmdline - mini.colors - mini.comment - mini.completion - mini.cursorword - mini.deps - mini.diff - mini.doc - mini.extra - mini.files - mini.fuzzy - mini.git - mini.hipatterns - mini.hues - mini.icons - mini.indentscope - mini.jump - mini.jump2d - mini.keymap - mini.map - mini.misc - mini.move - mini.notify - mini.operators - mini.pairs - mini.pick - mini.sessions - mini.snippets - mini.splitjoin - mini.starter - mini.statusline - mini.surround - mini.tabline - mini.test - mini.trailspace - mini.visits validations: required: true - type: dropdown id: nvim-version attributes: label: "Neovim version" description: "Choose the latest Neovim version on which you can reproduce the problem" multiple: false options: - 0.9.x - 0.10.x - 0.11.x - 0.12 (!at least latest Nightly build!) default: 2 validations: required: true - type: textarea id: description attributes: label: "Description" description: "A short description of a problem; include expected behavior" validations: required: true - type: textarea id: reproduction attributes: label: "Reproduction" description: "Steps to reproduce the issue. Suggested steps involve creating an independent config from scratch. If can not reproduce like this, please ask a usage question first." value: | 1. Create separate 'nvim-repro' config directory: - '~/.config/nvim-repro/' on Unix - '~/AppData/Local/nvim-repro/' on Windows 2. Inside 'nvim-repro' directory create a file named 'init.lua'. Populate it with the following content: ```lua -- Clone latest 'mini.nvim' (requires Git CLI installed) vim.cmd('echo "Installing `mini.nvim`" | redraw') local mini_path = vim.fn.stdpath('data') .. '/site/pack/deps/start/mini.nvim' local clone_cmd = { 'git', 'clone', '--depth=1', 'https://github.com/nvim-mini/mini.nvim', mini_path } vim.fn.system(clone_cmd) vim.cmd('echo "`mini.nvim` is installed" | redraw') -- Make sure 'mini.nvim' is available vim.cmd('packadd mini.nvim') require('mini.deps').setup() -- Add extra setup steps needed to reproduce the behavior -- Use `MiniDeps.add('user/repo')` to install another plugin from GitHub ``` 3. Run `NVIM_APPNAME=nvim-repro nvim` (i.e. execute `nvim` with `NVIM_APPNAME` environment variable set to "nvim-repro"). Wait for all dependencies to install. 4. Replace this with description of interactive reproduction steps along with the behavior you observe. Feel free to include images/videos/etc, this helps a lot.
What to do after reporting an issue After reporting the issue, it is safe (and even recommended for cleaner possible future bug reports) to remove 'nvim-repro' config from the system: - Delete config directory ('~/.config/nvim-repro' on Unix). - Delete data directory ('~/.local/share/nvim-repro' on Unix). - Delete state directory ('~/.local/state/nvim-repro' on Unix).
validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: Question url: https://github.com/nvim-mini/mini.nvim/discussions/new?category=q-a about: Ask about configuration and usage of 'mini.nvim' ================================================ FILE: .github/ISSUE_TEMPLATE/feature-request.yml ================================================ name: Feature request description: Describe a new feature you would like to see labels: [feature-request] body: - type: checkboxes id: guidelines attributes: label: Contributing guidelines options: - label: I have read [CONTRIBUTING.md](https://github.com/nvim-mini/mini.nvim/blob/main/CONTRIBUTING.md) required: true - label: I have read [CODE_OF_CONDUCT.md](https://github.com/nvim-mini/mini.nvim/blob/main/CODE_OF_CONDUCT.md) required: true - type: dropdown id: module attributes: label: "Module(s)" description: "Choose one or several modules this feature is related to. Choose 'new' for a new module suggestion." multiple: true options: - mini.ai - mini.align - mini.animate - mini.base16 - mini.basics - mini.bracketed - mini.bufremove - mini.clue - mini.cmdline - mini.colors - mini.comment - mini.completion - mini.cursorword - mini.deps - mini.diff - mini.doc - mini.extra - mini.files - mini.fuzzy - mini.git - mini.hipatterns - mini.hues - mini.icons - mini.indentscope - mini.jump - mini.jump2d - mini.keymap - mini.map - mini.misc - mini.move - mini.notify - mini.operators - mini.pairs - mini.pick - mini.sessions - mini.snippets - mini.splitjoin - mini.starter - mini.statusline - mini.surround - mini.tabline - mini.test - mini.trailspace - mini.visits - new validations: required: true - type: textarea id: description attributes: label: "Description" description: "A concise and justified description of a feature" validations: required: true ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ - [ ] I have read [CONTRIBUTING.md](https://github.com/nvim-mini/mini.nvim/blob/main/CONTRIBUTING.md) - [ ] I have read [CODE_OF_CONDUCT.md](https://github.com/nvim-mini/mini.nvim/blob/main/CODE_OF_CONDUCT.md) ================================================ FILE: .github/workflows/quality-control.yml ================================================ name: Quality Control on: push: branches-ignore: [ sync, stable ] pull_request: branches-ignore: [ sync, stable ] concurrency: group: ${{ github.workflow }}-${{ github.ref }}-${{ github.actor }} cancel-in-progress: true jobs: detect-changes: name: Detect changes runs-on: ubuntu-latest outputs: code: ${{ steps.filter.outputs.code }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 id: filter with: filters: | code: - 'colors/**' - 'lua/**' - 'tests/**' - 'scripts/minimal_init.lua' - '.github/workflows/**' test: name: Test # Run only if testable code has changed (to save time and resources) needs: detect-changes if: ${{ needs.detect-changes.outputs.code == 'true' }} timeout-minutes: 15 strategy: fail-fast: false matrix: os: [ ubuntu-latest ] neovim_version: [ 'v0.9.5', 'v0.10.4', 'v0.11.5', 'nightly' ] include: - os: macos-latest neovim_version: v0.11.5 - os: windows-latest neovim_version: v0.11.5 runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - name: Setup neovim uses: rhysd/action-setup-vim@v1 with: neovim: true version: ${{ matrix.neovim_version }} - name: Run tests run: make test lint-gendoc: name: Lint document generation runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Neovim uses: rhysd/action-setup-vim@v1 with: neovim: true version: v0.11.5 - name: Generate documentation run: make --silent documentation - name: Check for changes run: if [[ -n $(git status -s) ]]; then exit 1; fi lint-formatting: name: Lint formatting runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: JohnnyMorganz/stylua-action@v4 with: token: ${{ secrets.GITHUB_TOKEN }} version: v2.1.0 # CLI arguments args: --color always --respect-ignores --check . lint-commit: name: Lint new commits runs-on: ubuntu-latest env: LINTCOMMIT_STRICT: true steps: - uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha || github.ref }} - name: Install Neovim uses: rhysd/action-setup-vim@v1 with: neovim: true version: v0.11.5 - name: Lint new commits run: make --silent lintcommit-ci lint-filename: name: Lint filenames runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Check filename legnths run: make --silent lint-filename-length-ci - name: Check case sensitivity uses: credfeto/action-case-checker@v1.2.1 check-workflow-status: name: Check workflow status runs-on: ubuntu-latest needs: [ test, lint-gendoc, lint-formatting, lint-commit, lint-filename ] if: always() steps: - name: Check workflow status run: | exit_on_result() { if [[ "$2" == "failure" || "$2" == "cancelled" ]]; then echo "Job '$1' failed or was cancelled." exit 1 fi } exit_on_result "test" "${{ needs.test.result }}" exit_on_result "lint-gendoc" "${{ needs.lint-gendoc.result }}" exit_on_result "lint-formatting" "${{ needs.lint-formatting.result }}" exit_on_result "lint-commit" "${{ needs.lint-commit.result }}" exit_on_result "lint-filename" "${{ needs.lint-filename.result }}" ================================================ FILE: .gitignore ================================================ doc/tags dual .nvim.lua Session.vim ================================================ FILE: .pre-commit-config.yaml ================================================ repos: - repo: local hooks: - id: stylua name: StyLua language: system entry: stylua args: [--respect-ignores] types: [lua] - id: gendocs name: Gendocs language: system entry: make --silent documentation types: [lua] - id: lintcommit name: LintCommit language: system entry: nvim args: ['--headless', '--noplugin', '-u', 'scripts/lintcommit.lua', '--'] stages: ['commit-msg'] ================================================ FILE: .stylua.toml ================================================ column_width = 120 line_endings = "Unix" indent_type = "Spaces" indent_width = 2 quote_style = "AutoPreferSingle" call_parentheses = "Always" collapse_simple_statement = "Always" ================================================ FILE: .styluaignore ================================================ dual ================================================ FILE: CHANGELOG.md ================================================ This is the log of changes for past and current development versions. It lists changes in user-facing functionality per module (or all modules) and type. There are following change types: - `Evolve` - change in previously intended functionality *while* adding a new one. - `Refine` - change in previously intended functionality *without* adding new one. This is usually described as a "breaking change", but used here in a sense that it might break user's expectations about existing functionality. - `Expand` - adding new functionality without affecting existing ones. This is essentially new features. # Version 0.18.0-dev ## mini.base16 ### Expand - Add new plugin integrations: - 'folke/snacks.nvim' ## mini.clue ### Expand - Allow mode arrays for clues and triggers for parity with `modes` parameter of `vim.keymap.set`. By @pkazmier, PR #2202. ## mini.extra ### Expand - Add `pickers.manpages` picker. ## mini.hues ### Expand - Add new plugin integrations: - 'folke/snacks.nvim' ## mini.jump ### Evolve - Make dot-repeat behave exactly as in clean Neovim, i.e. make it less interfere with regular jumping. This allows doing something like `dte` -> `fx` -> `.` to perform `dte` again and not `dfx` (which is the latest regular jumping state). By @abeldekat, PR #2284. ## mini.misc ### Evolve - Update `setup_termbg_sync()` to use OSC 111 control sequence to reset terminal emulator's background color. This provides a more robust behavior across platforms (like `tmux`). The previous "reset by explicitly setting initial background color" behavior is available by setting the new `opts.explicit_reset` option to `true`. ### Expand - Add `safely()` to execute a function reporting its possible error as warning. It can also postpone execution until certain condition (like event, fixed delay, etc.). It is intended to be a future replacement for `MiniDeps.now()` and `MiniDeps.later()`. ## mini.pairs ### Refine - Update neighborhood patterns for default mappings to work better with multibyte characters. Their meaning is the same, just the form is adjusted to be more versatile. ## mini.pick ### Expand - Allow `source.preview` to directly set another buffer into picker's main window. The recommended way is still to adjust the provided `buf_id` buffer, but there is now a workaround if this is not reasonably possible. ### Refine - Stop forcing redraw every `config.delay.async` milliseconds while the picker is active. It added visible CPU usage and code/test lines for its benefit (mostly to show "background" changes/notifications). One side effect of this is that previews with an asynchronous highlighting (like after `vim.treesitter.start()`) might require extra care. There are built-in several (but limited) number of explicit `:redraw` with `config.delay.async` milliseconds apart. If that is not enough, make sure to explicitly redraw when needed. ## mini.surround ### Expand - Create Visual and Operator-pending mode mappings for `find` and `find_left` actions. ## mini.test ### Refine - Update `expect.error` and `expect.no_error` to not accept extra arguments for tested function. It will mostly work until the next 'mini.nvim' release, but not after that. Use them explicitly inside anonymous function: `expect.error(f, "", 1, 2)` -> `expect.error(function() f(1, 2) end, "")` and `expect.no_error(f, 1, 2)` -> `expect.no_error(function() f(1, 2) end)`. Sorry for the inconvenience. - Update all built-in reporters (`gen_reporter.buffer` and `gen_reporter.stdout`) to first show all fails followed by all notes. This makes it easier to find failed cases when there are many notes (like from `MiniTest.skip()`). ### Expand - Update all `MiniTest.expect` expectations to allow customization of failure reason instead of default "Failed expectation for ...". This also consistently introduces `opts` last argument. - Update `MiniTest.expect.equality` to show more detailed cause of failed equality. Like which character is different in two string or which values are different in two tables and at what key branch. # Version 0.17.0 ## All ### Evolve - Move repository hosting from personal 'echasnovski' GitHub account to the 'nvim-mini' organization. All `git pull` and `git clone` should be automatically redirected from previous to new locations without breaking user configurations. Yet updating source links to point to new locations (like `'echasnovski/mini.nvim'` -> `'nvim-mini/mini.nvim'` and standalone repos) is recommended. This change is made to improve long term project stability. See more details [here](https://github.com/nvim-mini/mini.nvim/discussions/1970). - Start setting custom Neovim method implementation during `setup()` (if module provides one). This is usually the expected behavior for majority of use cases and should improve "out of the box" experience. Modules should still export a function to manually adjust the implementation. It is a breaking change only if the implementation was not explicitly used. Can still be done if set or restored *after* calling module's `setup()`. Affected modules: - 'mini.notify' sets `vim.notify`. - 'mini.pick' sets `vim.ui.select`. ### Refine - Stop official support of Neovim 0.8. ### Expand - Add new bundled color schemes based on 'mini.hues': - `miniwinter`: "icy winter" palette with azure background. - `minispring`: "blooming spring" palette with green background. - `minisummer`: "hot summer" palette with brown/yellow background. - `miniautumn`: "cooling autumn" palette with purple background. ## mini.ai ### Refine - Update `gen_spec.treesitter()` to have `use_nvim_treesitter = false` as default option value (instead of `true`). It used to implement more advanced behavior, but as built-in `vim.treesitter` is capable enough, there is no need in extra dependency. The option will be removed after the release. ### Expand - Add `gen_spec.user_prompt` that acts the same as `?` built-in textobject. It can be used for using this textobject under another identifier. ## mini.basics ### Refine - Change default value of `options.win_border` to be `'auto'`. ### Expand - Update `options.win_border` to allow value `'auto'` which infers target 'fillchars' values from 'winborder' option. ## mini.colors - Update `add_transparency()` color scheme method to adjust more groups: - `XxxMsg` groups in case of `opts.general = true`. - `DiagnosticSignXxx` groups in case of `opts.statuscolumn = true`. ## mini.completion ### Evolve - Update `setup()` to remove "t" flag from 'complete' option (if not previously set and fallback action is default) as it leads to visible lags. ### Expand - Add `MiniCompletionWindowOpen` and `MiniCompletionWindowUpdate` events. - Add support for highlighting LSP item label via setting `abbr_hlgroup` field as part of an LSP item (like inside `config.lsp_completion.process_items`). ## mini.clue ### Evolve - Use current query clue (if not immediately after trigger) as a window title instead of showing keys verbatim. This shows extra context when navigating through mappings. ### Expand - Add `gen_clues.square_brackets` to generate clues for `[` and `]` keys. By @TheLeoP, PR #1937. - Ensure triggers for 'mini.starter' buffers, but not override its query updaters (like for "g" and "z" triggers). ## mini.cmdline - Introduction of a new module. ## mini.diff ### Expand - Add support for working with files containing BOM bytes. ## mini.doc ### Refine - Update default `write_pre` hook to remove `===` and `---` delimiters from the top of the file to better comply with `:h local-additions`. ## mini.extra ### Expand - Add `pickers.colorschemes` picker. By @pkazmier, PR #1789. - Add `workspace_symbol_live` scope to `pickers.lsp` picker. It allows searching for LSP symbols in the workspace with live feedback. Relates to `workspace_symbol` scope similarly to how `MiniPick.builtin.grep_live()` relates to `MiniPick.builtin.grep()`. - Add `` mapping for `pickers.history` picker to edit commands or searches in cmdline. By @TheLeoP, PR #1960. ## mini.files ### Evolve - Allow appending `/` to a file name to mean "delete file" + "create directory". This is useful when initial intention was to create a directory but there was no `/` at the end. ### Refine - Ensure preview window is never hidden, even if cursor is on the line for a not (yet) existing file system entry. This reduces flickering of preview window when creating new files in Insert mode. ### Expand - Add `config.content.highlight` to customize how file system entry is highlighted. Defaults to a new `default_highlight()` function. ## mini.hues ### Evolve - Add auto adjusting of highlight groups based on certain events. It can be disabled via new `autoadjust` config setting or `opts.autoadjust` in `apply_palette()`. Affected groups: - `MsgSeparator` depends on `msgsep` flag of 'fillchars' option. - `Pmenu` depends on 'pumborder' option value (on Neovim>=0.12). ### Refine - Make black (0 and 8) and white (7 and 15) colors for built-in terminal different from regular background and foreground. This improves color coverage and does not affect default uncolored text (it is highlighted as `Normal`). ### Expand - Add `get_palette()` function. ## mini.jump ### Expand - Trigger dedicated events during steps of jumping life cycle. See `:h MiniJump-events`. ## mini.jump2d ### Evolve - Update `builtin_opts.word_start` to use built-in notion of "keyword" (see `:h 'iskeyword'`) when computing word start. ### Refine - Move `gen_xxx_spotter` into separate `gen_spotter` table for consistency with other modules: - `gen_pattern_spotter` -> `gen_spotter.pattern` - `gen_union_spotter` -> `gen_spotter.union` The `gen_xxx_spotter` functions will work (with warning) until at least next release. - Not focusable windows are now ignored when computing jump spots. ### Expand - Add `gen_spotter.vimpattern()` that can generate spotter based on Vimscript (not Lua) pattern. ## mini.map ### Expand - Update `gen_integration.builtin_search()` to react to change of `v:hlsearch`. ## mini.misc ### Expand - Update `zoom()` to return whether current buffer is zoomed in. By @loichyan, PR #1954. - Add `log_add()` and related functions (`log_get()`, `log_show()`, `log_clear()`) to work with a special in-memory log array. Useful when debugging Lua code (instead of `print()`). ## mini.pick ### Evolve - Pickers `grep` and `grep_live` with `rg` tool now respect Neovim's `'ignorecase'` and `'smartcase'` options. This forces corresponding case matching flag (thus overriding global configuration) in favor of a more consistent user experience. ### Expand - "Paste" action now supports special registers: `` (word at cursor), `` (WORD at cursor), `` (line at cursor), `` (filename at cursor). - Key query process now respects most language mappings. By @yehorb, PR #2026. ## mini.sessions ### Refine - Update `read()` to write currently read session only if `MiniSessions.config.autowrite` is set to `true`. ## mini.surround ### Evolve - Stop creating `update_n_lines` mapping: it occupies "mapping real estate" while being rarely needed and straightforward to create manually using `MiniSurround.update_n_lines()`. - Automatically map `s` key to `` if the key is not already mapped and any of created mappings starts with it. This prevents accidental trigger of built-in `s` if there is a long delay between pressing "s" and the next key. ### Refine - Update `gen_spec.inpuf.treesitter()` to have `use_nvim_treesitter = false` as default option value (instead of `true`). It used to implement more advanced behavior, but as built-in `vim.treesitter` is capable enough, there is no need in extra dependency. The option will be removed after the release. ## mini.test ### Refine - Soft deprecate `ignore_lines` option in `expect.reference_screenshot()` in favor of more capable `ignore_text` and `ignore_attr` options. For example, `ignore_lines = { 1 }` is the same as supplying both `ignore_text = { 1 }` and `ignore_attr = { 1 }`. It will work at least until the next release, after which its support will be removed. Sorry for the inconvenience. ### Expand - Update `expect.reference_screenshot()` to support separate ignoring of text and attribute screenshot data via new `ignore_text` and `ignore_attr` options. # Version 0.16.0 ## All ### Evolve - Unify behavior of floating windows: - Truncate title/footer from left if it is too wide. - Set default title if window is allowed to have border. - Use single space padding for default title/footer. - Use 'single' as default window border in modules where it can be configured. On Neovim>=0.11 also respect non-empty 'winborder' option with lower precedence than explicitly configured value for the module. - Unify how module-related buffers are named: `mini:///`. This structure allows creating identifiable, reasonably unique, and useful buffer names. This is a user facing change because in some cases the shown buffer's name will change (like in statusline of opened 'mini.starter' buffer or output of `:buffers!`). - Stop forcing recommended option values behind `set_vim_settings` config setting. Instead set them automatically in `setup()`. If it is not essential, do so only if it was not set by user/plugin beforehand (no matter the value). Document this as a new general principle to be followed in the future. Affected modules: - 'mini.bufremove' (do nothing as recommended 'hidden' is on by default) - 'mini.completion' (conditionally set 'completeopt=menuone,noselect' and flags "c" in 'shortmess') - 'mini.statusline' (do nothing as recommended 'laststatus=2' is default) - 'mini.tabline' (unconditionally set 'showtabline=2', as it is essential to module's functinonality) ### Refine - Soft deprecate support for Neovim 0.8. It will be fully stopped in next release. ## mini.ai ### Refine - Visual textobject selection now puts the cursor on the right edge instead of left. This better aligns with the (undocumented) behavior of how built-in `a` / `i` textobjects work in Visual mode, as opposed to the (documented in `:h operator-resulting-pos`) behavior of how it is done after applying the operator. ### Expand - Textobject identifier can now be any single character supported by `:h getcharstr()`. This also makes it possible to use characters outside of Latin alphanumeric and punctuation sets as `custom_textobjects` keys. Default textobject is extended to be anything but Latin letters (to fall back to `:h text-objects`). - Update `gen_spec.treesitter()` to respect capture ranges specified by query directives (like `(#offset! @table.inner 0 1 0 -1)`). ## mini.base16 ### Refine - Update 'mini.pick' highlight groups to show prompt text with same colors as match ranges, as they are connected. ### Expand - Add support for colored markdown headings. - Add new plugin integrations: - 'ibhagwan/fzf-lua' - 'MeanderingProgrammer/render-markdown.nvim' - 'OXY2DEV/helpview.nvim' - 'OXY2DEV/markview.nvim' ## mini.colors ### Expand - Update `convert()` to have `adjust_lightness` option which can be used to disable lightness adjustment (which is enabled by default for a more uniform progression from 0 to 100). This can be useful for output to be more consistent with other Oklab/Oklch implementations. ## mini.comment ### Expand - Update textobject to respect `ignore_blank_line` option. Blank lines between commented lines are treated as part of a textobject. ## mini.completion ### Evolve - Add snippet support. By default uses 'mini.snippets' to manage snippet session (if enabled, **highly recommended), falls back to `vim.snippet` on Neovim>=0.10. See "Snippets" section in `:h MiniCompletion` for more details. This affect existing functionality because items with `Snippet` kind are no longer filtered out by default. - Rework how LSP completion items are converted to Neovim's completion items: - Show `detail` highlighted as buffer's language at the start of info window, but only if `detail` provides information not already present in `documentation`. It was previously used as extra text in the popup menu (via `menu` field), but this doesn't quite follow LSP specification: `detail` and `documentation` fields can be delayed up until `completionItem/resolve` request which implies they should be treated similarly. - Show `labelDetails` as a part of the popup menu via `menu` completion item field. - Rework how information window is shown with the goal to reduce flickering during fast up/down navigation through completion candidates: - Do not close the window immediately after the move. Instead highlight border with `MiniCompletionInfoBorderOutdated` immediately while update window when its content is ready. Close the window only if no candidate is selected. - Show content of already visited/resolved candidate without delay. - Show default `-No-info-` text if there is no extra information about the candidate. - Update behavior and capabilities of `default_process_items()`: - Add `filtersort` option to control how items are filtered and/or sorted. Its new default value has changed behavior: do fuzzy matching if 'completeopt' option contains "fuzzy" entry; same as before otherwise. - Add `kind_priority` option to allow arranging items by completion item kind (like "Variable", "Snippet", "Text", etc.) after applying `filtersort`. This allows finer filter and/or sort based on kind, like "put Variable on top, Snippet on bottom, remove Text". - Use `filterText` and `label` item fields during matching (instead of `textEdit.newText`, `insertText`, and `label` as before). This is more aligned with LSP specification. ### Refine - Prefer in some cases to use `nil` as default config value with explicit fallback. This should not have any user facing effects and marked as breaking only because a structure of a default config has changed. Affected fields: - `lsp_completion.process_items` (use `default_process_items` as fallback) and `fallback_action` (use `''` as fallback). This makes it more aligned with other modules that usually avoid using function values in default config. - `window.info.border` and `window.signature.border` (use non-empty 'winborder' and `'single'` as fallback). - Change default value of `MiniCompletionActiveParameter` highlight group to link to `LspSignatureActiveParameter` (instead of forcing underline). - Call `lsp_completion.process_items` with an array of items from all buffer servers at once (and not for each server separately). This can be used for more elaborate filter/sort strategies. ### Expand - Add scrolling in info and signature window. By default can be done with `` / `` when target window is shown. Can be configured via `mappings.scroll_down` and `mappings.scroll_up` config options. - Respect `isIncomplete` in LSP completion response and immediately force new completion request on the next key press. - Add support for context in 'textDocument/completion' request. - Both info and signature help windows now use tree-sitter highlighting: - Info window uses "markdown" parser (works best on Neovim>=0.10 as its parser is built-in). Special markdown characters are concealed (i.e. hidden) which might result into seemingly unnecessary whitespace as dimensions are computed not accounting for that. - Signature help uses same parser as in current filetype. - Update signature help without delay if it is already shown. This helps to keep signature help up to date after cursor jumps in Insert mode (like during snippet session). - Add support for item defaults in `CompletionList` response. - Add `get_lsp_capabilities()` that returns data about which part of LSP specification is supported in 'mini.completion'. - Input items for `lsp_completion.process_items` now have `client_id` field with the identifier of the server that item came from. Use `vim.lsp.get_client_by_id()` to get an actual data about the server. ## mini.diff ### Expand - The `config.source` can now be array of sources, which will be attempted to attach in order. Important for source's `attach` to either return `false` or call `MiniDiff.fail_attach()` (even not immediately) to signal that source has failed to attach to a particular buffer. - Overlay virtual lines now scroll horizontally along with buffer lines. Requires Neovim>=0.11 and disabled 'wrap' option. - Highlighting of buffer parts of change hunks can now be customized with these new highlight groups: - `MiniDiffOverChangeBuf` - changed buffer text. Previously used `MiniDiffOverChange` (for changed reference text); links to it by default. - `MiniDiffOverContextBuf` - context of a change shown in buffer overlay. Previously not highlighted, default highlight group is not created. ## mini.doc ### Expand - FEATURE: improve detection and formatting for types in `@param`, `@return`, and similar. ## mini.fuzzy ### Refine - Update `process_lsp_items()` to only use `filterText` and `label` item fields during fuzzy matching (instead of `textEdit.newText`, `insertText`, and `label` as before). This is more aligned with LSP specification. - Treat empty `word` as matching any candidate (matched positions is empty array and score is -1). This behavior is usually more useful in practice. ## mini.hues ### Evolve ### Refine - Update 'mini.pick' highlight groups to show prompt text with same colors as match ranges, as they are connected. ### Expand - Add support for colored markdown headings. - Add new plugin integrations: - 'ibhagwan/fzf-lua' - 'MeanderingProgrammer/render-markdown.nvim' - 'OXY2DEV/helpview.nvim' - 'OXY2DEV/markview.nvim' ## mini.keymap ### Expand - Introduction of a new module. ## mini.notify ### Expand - Add `lsp_progress.level` option to control level of LSP progress notifications. - Add `MiniNotifyLspProgress` highlight group to be used for LSP progress notifications. - Add `data` field to notification specification and as a new argument to `MiniNotify.add()`. It can be used to store any data relevant to the notification. For example, notifications from `make_notify()` output set `source` field to `'vim.notify'`, while notifications from LSP progress set `source` to `'lsp_progress'`. ## mini.operators ### Expand - Update `setup()` to remap built-in `gx` Normal/Visual mode mappings (for opening an URI under cursor) to `gX` (if that is not already taken). ## mini.pairs ### Expand - Update all actions to work with pairs containing multibyte characters (like "¿?", "「」", and similar). ## mini.pick ### Refine - Rename `prompt_cursor` in `config.window` to `prompt_caret` for better naming consistency. It works for now, but will stop in the next release. Sorry for the inconvenience. ### Expand - Add `MiniPickPromptCaret` and `MiniPickPromptPrefix` highlight groups to allow finer customization of picker's prompt. - Update `get_picker_matches()` to return data (items and indexes) about currently shown items. - Update `set_picker_match_inds()` to be able to set current match and marked items indexes. ## mini.snippets ### Expand - Add `start_lsp_server()` to start specialized in-process LSP server to show loaded snippets inside (auto)completion engines (like 'mini.completion'). ## mini.statusline ### Refine - Function `section_fileinfo()` got several updates: - File size is now computed based on the current buffer text and not for file's saved version. - File info is now shown even for buffers with empty 'filetype'. It previously was treated as a sign of a "temporary buffer", but it might be a result of an unsuccessful filetype matching. ## mini.surround ### Expand - Surrounding identifier can now be any single character supported by `:h getcharstr()`. This also makes it possible to use characters outside of Latin alphanumeric and punctuation sets as `custom_surroundings` keys. - Update `gen_spec.input.treesitter()` to respect capture ranges specified by query directives (like `(#offset! @table.inner 0 1 0 -1)`). ## mini.tabline ### Expand - Add support for showing special (truncation) characters at left and/or right if there are more tabs to the left and/or right. They are shown with the new `MiniTablineTrunc` highlight group in case 'list' option is enabled (i.e. user deliberately enabled similar functionality for windows). Exact characters are taken from 'listchars' option: `precedes` and `extends` fields. - Labels for quickfix and location lists are now different. # Version 0.15.0 ## mini.align ### Expand - Add built-in modifier for "|" character with aligning Markdown-like tables in mind. ## mini.animate ### Evolve - Add `max_output_steps` option to `gen_path.line()` and `gen_path.angle()` to limit the number of steps the return. Default is 1000 to improve performance on large cursor jumps which also is set for `config.cursor.path`. ## mini.files ### Expand - Closing and refreshing explorer now requires confirmation only if there are pending file system actions (and not in case of at least one modified buffer present). - Confirming file system actions in `synchronize()` now can cancel synchronization (by pressing `c`) while keeping buffer contents the same. `synchronize()` also returns a boolean representing whether synchronization was done. ## mini.git ### Expand - Git data is computed after resolving symlinks. This allows working with files symlinked into outside of Git repo. This behavior is the same as in 'mini.diff'. ## mini.hipatterns ### Refine - Make `MiniHipatterns{Fixme,Hack,Todo,Note}` highlight groups by default be reverse and bold variant of `Diagnostic{Error,Warn,Info,Hint}` group instead of directly link to them. This ensures better visibility for color schemes which don't have explicit 'mini.hipatterns' support. ## mini.hues ### Expand - Add `'lowmedium'` and `'mediumhigh'` saturation levels. ## mini.icons ### Expand - Add distinctive glyphs and highlighting for special Neovim directories (from `:h 'runtimepath'`). ## mini.indentscope ### Evolve - Add `options.n_lines` option to limit the scope computation (for better performance). It's default value is 10000 while previous behavior behavior had no restriction (as with `n_lines = math.huge`) which should matter only in very big scopes. - Add `draw.predicate` configuration to customize whether the scope should be autodrawn. It's default value does not draw scope with incomplete computation (i.e. interrupted due to `options.n_lines` value), which should matter only in very big scopes. ## mini.notify - FEATURE: `setup()` now also can be used to clean history (for example, like `MiniNotify.setup(MiniNotify.config)`). ## mini.pick ### Evolve - Picker window now has local current directory set to source's `cwd`. This allows easier code for "in window" functions (callable items, choose, preview, etc.) as relative paths will be properly resolved. It also results in some changes: - Calling `set_picker_items_from_cli()` with active picker now resolves explicitly set to relative path `spawn_opts.cwd` against picker's `cwd` (and not against global current directory as was done previously). ### Expand - Update `grep` and `grep_live` pickers to allow `globs` local option which restricts search to files that match any of its glob patterns (for example, `{ '*.lua', 'lua/**' }` will only search in Lua files and files in 'lua' directory). The `grep_live` picker also has custom `` mapping to add globs interactively after picker is opened. - Update `help` picker to have `default_split` local option which customizes split direction of `choose` action (`` by default). - Update `ui_select()` to allow fourth argument `start_opts` to customize `MiniPick.start()` call. - Add `MiniPickMatch` event triggered after updating query matches or setting items. Can be used, for example, to adjust window height based on current matches. ## mini.snippets ### Expand - Introduction of a new module. ## mini.surround ### Refine - Created mappings for `find`, `find_left`, and `highlight` are now *not* dot-repeatable. Dot-repeat should repeat last text change but neither of those actions change text. Having them dot-repeatable breaks the common "move cursor -> press dot" workflow. Initially making them dot-repeatable was a "you can but you should not" type of mistake. ## mini.test ### Evolve - Now calling `skip()` in set's `pre_case` hook results in skipping all test cases in a set. Calling in other hooks has no effect. This enables a more structured skipping of all test cases inside a set. To skip inside hooks, use `add_note()` followed by `return`. ### Expand - Add `n_retry` test set property. When set, each case will be tried that at most that many times until first success (if any). - Add `hooks.pre_source` and `hooks.post_source` fields to collected cases. They can be either `'once'` or `'case'` and allow a more granular control over case execution. - Function `finally()` now can be called several times inside a single function with callbacks executed in order of how they were registered. - Update `expect.reference_screenshot()` to allow `directory` option pointing to a directory where automatically constructed reference path is located. # Version 0.14.0 ## All ### Evolve - Update help files to use code blocks with language annotation, as it results in a better code highlighting. Implies enabled tree-sitter highlighting in 'help' filetype: - It is default in Neovim>=0.10. - Tree-sitter parser is built-in in Neovim 0.9.x, needs manual enabling via `vim.treesitter.start()`. - Has visual regressions on Neovim 0.8.0 and 0.8.1 without enabled tree-sitter (code blocks are highlighted as normal text). Use 0.8.2 or newer. - Universally prefer 'mini.icons' module over 'nvim-tree/nvim-web-devicons'. ### Refine - Stop official support of Neovim 0.7. ### Expand - Start automated testing on Windows and MacOS. - Universally ensure that all plugin's highlight groups are defined after any color scheme takes effect. ## mini.base16 ### Expand - Add 'kevinhwang91/nvim-bqf' plugin integration. ## mini.completion ### Expand - Add highlighting of LSP kind (like "Function", "Keyword", etc.). Works only on Neovim>=0.11. Requires enabled 'mini.icons' to work out of the box. ## mini.doc ### Evolve - Update `afterlines_to_code()` to result into Lua code block in help file by using `>lua` at the start instead of `>`. NOTE: users need enabled `help` tree-sitter parser (which is default on Neovim>=0.9) for code blocks to have proper highlighting. ## mini.extra ### Refine - Use "│" as line/position separator instead of ":". This aligns with changes in 'mini.pick' and makes line/position more easily visible. ### Expand - Update `oldfiles` picker to have `current_dir` option which if `true` shows files only from picker's working directory. By @abeldekat, PR #997. - Update `git_hunks`, `list`, and `lsp` pickers to show icons. Scopes `document_symbol` and `workspace_symbol` in `lsp` picker show icon based on LSP kind (requires set up 'mini.icons'), others - based on path data. - Update `buf_lines` and `oldfiles` pickers to have `preserve_order` local option, similar to `visit_paths` picker. Other possible candidates for this option are intentionally not updated to not increase maintenance (manually override `match` source method to call `MiniPick.default_match()` with `{ preserve_order = true }` options). - Update `buf_lines` picker to pad line numbers to achieve more aligned look. ## mini.git ### Expand - Update `show_at_cursor()` to include commit's statistics when showing commit. - Update `show_at_cursor()` to show relevant at cursor commit data inside 'mini.deps' confirmation buffer. ## mini.hipatterns ### Evolve - Update `compute_hex_color_group()` to compute based on combination of `hex_color` and `style`, opposed to just `hex_color`. This allows simultaneous usage of several styles in user's custom highlighters. ## mini.hues ### Expand - Implement `apply_palette()` (to compliment `make_palette()`) providing a way to tweak applied palette before applying it. - Add 'kevinhwang91/nvim-bqf' plugin integration. ## mini.files ### Evolve ### Refine - Update how confirmation lines are computed: - Show create actions in the group directory where text manipulation took place. This matters during creating nested entries and is usually a more intuitive representation. - For delete show its type after the file name ("permanently" or "to trash") as an additional visual indication of delete type. - For create, copy and move prefer showing its "to" path relative to group directory. - Separate action name and paths with "│" (instead of ":") for better visual separation. - Don't enclose paths in quotes. Initially it was done to reliably show possible whitespace in paths, but inferring it from overall line structure should be good enough. - Soft deprecate `get_target_window()` in favor of `get_explorer_state().target_window`. Will be completely removed after the next release. ### Expand - Prefer using 'mini.icons' as icon provider. - Implement bookmarks. With default config: - Type `m` followed by a single character `` to set directory path of focused window as a bookmark with id ``. - Type `'` followed by a bookmark id to make bookmark's path focused in explorer. - Use `MiniFiles.set_bookmark()` inside `MiniFilesExplorerOpen` event to set custom bookmarks. - Make data for `MiniFilesActionDelete` contain `to` field in case of not permanent delete. - Make file manipulation work better for special complex/overlapping cases (like delete 'file-a' and copy 'file-b' as 'file-a'). It is **still** a better idea to split overlapping manipulations into smaller and not related steps, as there *are* cases which won't work. - Add `get_explorer_state()` to allow more reliable user customizations. - Add `set_branch()` to allow to set what paths should be displayed and focused. ## mini.icons ### Expand - Introduction of a new module. ## mini.misc ### Expand - Implement `setup_termbg_sync()` to set up terminal background synchronization (removes possible "frame" around current Neovim instance). Works only on Neovim>=0.10. ## mini.pick ### Evolve ### Refine - Update `default_match()` to have table `opts` as fourth argument (instead of boolean `do_sync`). Use `{ sync = true }` to run synchronously. The new design is more aligned with other functions and is more forward compatible. - Encoding line or position in string items has changed: - Use "\0" (null character; use "\000" form if it is in a string before digit) instead of ":" as delimiter. This makes it work with files similar to ":" position encoding (like "time_12:34:56"). This only matters for custom sources which provide line or position in string items. - Update `default_show()` to display "│" character instead of "\0" in item's string representation (previously was ":"). In particular, this changes how line/position is displayed in `grep` and `grep_live` built-in pickers. This change was done because "│" is more visible as separator. ### Expand - Prefer using 'mini.icons' as icon provider. - Add `preserve_order` option to `default_match()` to allow asynchronous matching which preserves order (i.e. doesn't do sort step of fuzzy matching). - Explicitly hide cursor when picker is active (instead of putting it in command line). ## mini.starter ### Refine - Change filetype of Starter buffer from 'starter' to 'ministarter'. This is a more robust value and more aligned with other modules. ## mini.statusline ### Refine - Update `section_fileinfo()` to show non-empty filetype even in not normal buffers (like plugin's scratch buffers, help, quickfix, etc.). Previously it showed nothing, which was a mistake as filetype can be a valuable information. - The default `set_vim_settings` config value now does not affect `laststatus = 3` (aka global statusline). ### Expand - Prefer using 'mini.icons' as icon provider for `section_fileinfo()`. ## mini.surround ### Refine - Adding surrounding in linewise mode now also ignores trailing whitespace on the last line (same as it ignores indent on the first line). ## mini.tabline ### Expand - Prefer using 'mini.icons' as icon provider. ## mini.test ### Expand - Make it work on Windows. By @cameronr, PR #1101. # Version 0.13.0 ## mini.comment ### Refine - Blank lines are now completely ignored when deciding the toggling action. In practice this means that if target block consists only from commented and/or blank lines, it will be uncommented rather than commented. - Whitespace in comment parts is now treated more explicitly. In particular: - Default `options.pad_comment_parts = true` now more explicitly means that any value of 'commentstring' is transformed so that comment parts have exactly single space inner padding. Example: any `/*%s*/`, ` /* %s */ `, or `/* %s */` is equivalent to having `/* %s */`. - Detection of whether consecutive lines are commented or not does not depend on whitespace in comment parts. Uncommenting is first attempted with exact comment parts and falls back on trying its trimmed parts. Example of toggling comment on single line with `/* %s */` 'commentstring' value: - `/* this is commented */` -> `this is commented`. - `/*this is also commented */` -> `this is also commented ` (notice trailing space). - Commenting blank lines is done with trimmed comments parts, while uncommenting explicitly results into empty lines. ### Expand - Support dot-repeat after initial commenting is done for visual selection; repeating is done for same relative range. ## mini.deps ### Expand - Add `MiniDepsMsgBreaking` highlight group for messages indicating a breaking change in a conventional commit style. ## mini.diff ### Expand - Introduction of a new module. ## mini.files ### Expand - Add new `MiniFilesExplorerOpen` and `MiniFilesExplorerClose` events. ## mini.git ### Expand - Introduction of a new module. ## mini.hues ### Refine - Update some highlight groups for better usability: - `DiffChange` and `DiffText` - make changed diff lines have colored background. - `Folded` - make folds differ from `CursorLine`. - `QuickFixLine` - make current quickfix item differ from `CursorLine`. ## mini.map ### Expand - Add `gen_integration.diff()` which highlights general diff hunks from 'mini.diff'. ## mini.pick ### Evolve ### Refine - Stop trying to parse path for special format ("path:row" and "path:row:col") if supplied inside a table item. This made impossible working with paths containing ":". - Update `builtin.files()` to use table items when string item might be ambiguous. ### Expand - Respect general URI format for paths inside table items. ## mini.starter ### Refine - Explicitly block all events in `open()` during startup for a better performance. ## mini.statusline ### Evolve - Update `section_git()` to prefer using data from 'mini.git' with fallback on pure HEAD data from 'lewis6991/gistigns.nvim'. - Update default active content: - Add `section_diff()` (shows diff data near  icon) following refactor of `section_git()`. - Add `section_lsp()` (shows number of attached LSP servers near 󰰎 icon) following refactor of `section_diagnostics()`. ### Refine - Update `section_diagnostics()` to depend only on defined diagnostic. This means: - Something is shown **only** if there is any diagnostic actually present in the buffer. No diagnostic entries - nothing is shown. Previously it did not show if there was no LSP servers attached (as initially diagnostics came only from LSP) or buffer was not normal. - Fallback icon is "Diag" instead of "LSP". ### Expand - Update `section_diagnostics()` to support `signs` table option to customize signs for severity levels. - Add `section_diff()` to show data from 'mini.diff' with fallback on diff data from 'lewis6991/gistigns.nvim'. - Add `section_lsp()` to show indicator of LSP servers attached to the buffer. ## mini.tabline ### Expand - Implement `config.format` for custom label formatting. ## mini.test ### Refine - Child process is now created with extra `--headless --cmd "set lines=24 columns=80"` arguments making it headless but still reasonably similar to fully functioning Neovim during interactive usage. This change should generally not break a lot of things, while enabling a faster and more robust test execution. # Version 0.12.0 ## mini.basics ### Refine - Remove `` mapping, as it is more useful in most terminal emulators for suspending Neovim process (to later resume with `fg` command). To correct latest misspelled word, use mappings like this: ```lua vim.keymap.set('n', '', '[s1z=', { desc = 'Correct latest misspelled word' }) vim.keymap.set('i', '', 'u[s1z=`]au', { desc = 'Correct latest misspelled word' }) ``` ### Expand - Add `tab:> ` to 'listchars' option when `options.extra_ui` is set. This prevents showing `^I` instead of a tab and actual value comes from Neovim's default. - Set `termguicolors` only on Neovim<0.10, as later versions should have it on by default (if terminal emulator supports it). ## mini.comment ### Expand - Hooks are now called with data about commenting action. ## mini.deps ### Expand - Introduction of a new module. ## mini.doc ### Refine - Stop using `:echo` to display messages and warnings in favor of `vim.notify()`. - Update default `write_post` hook to not display current time in success message. - Update to include space before `~` in generated section headings. ## mini.files ### Expand - Update `go_in()` to have `close_on_file` option. - Show warning if action is set to override existing path. ## mini.hues ### Refine - Update verbatim text (`@text.literal` and `@markup.raw`) color to be distinctive instead of dimmed. ### Expand - Add support for new standard tree-sitter captures on Neovim>=0.10 (see https://github.com/neovim/neovim/pull/27067). ## mini.misc ### Refine - Update `bench_time()` to use `vim.loop.hrtime()` (as better designed for benchmarking) instead of `vim.loop.gettimeofday()`. ## mini.notify ### Expand - Introduction of a new module. ## mini.pick ### Expand - Implement `window.prompt_cursor` and `window.prompt_prefix` config options. - Update `builtin.help()` to use tree-sitter highlighting (if there is any). ## mini.sessions ### Refine - Update `read()` to first `write()` current session (if there is any). ## mini.starter ### Expand - Add `sections.pick()` with 'mini.pick' pickers. ## mini.statusline ### Evolve - Add `search_count` section to default active content. ## mini.visits ### Expand - Introduction of a new module. # Version 0.11.0 ## mini.base16 ### Refine - Stop supporting deprecated 'HiPhish/nvim-ts-rainbow2'. ## mini.bufremove ### Evolve - Applying `delete()` and `wipeout()` without `force` in a modified buffer now asks for confirmation instead of declining and showing message. ## mini.clue ### Expand - Value of `config.window.config` now can be callable returning window config. ## mini.comment ### Expand - Implement `config.mappings.comment_visual` to configure mapped keys in Visual mode. ## mini.completion ### Evolve - Start adding `C` flag to `shortmess` option on Neovim>=0.9. By @yamin-shihab, PR #554. ## mini.extra ### Expand - Introduction of a new module. ## mini.files ### Refine - Opening file which is present in unlisted buffer now makes the buffer listed. - Highlight in preview now is not enabled if file is sufficiently large. ### Expand - Explorer now tracks if focus is lost and properly closes on detection. - Implement `MiniFilesCursorLine` highlight group. ## mini.hipatterns ### Refine - Field `priority` in highlighter definitions is soft deprecated in favor of `extmark_opts = { priority = }`. ### Expand - Allow `pattern` in highlighter definitions to be an array to highlight several patterns under the same highlighter name. - Implement `extmark_opts` in highlighter definitions for a more control over extmarks placed at matches. - Update `compute_hex_color_group()` to allow `style = 'fg'`. - Update `gen_highlighter.hex_color()` to allow `style = 'inline'` (requires Neovim>=0.10 with support of inline extmarks). - Implement `get_matches()` to get buffer matches. ## mini.hues ### Refine - Stop supporting deprecated 'HiPhish/nvim-ts-rainbow2'. ## mini.map ### Expand - Implement `config.window.zindex` to configure z-index of map window. ## mini.misc ### Expand - Update `setup_auto_root()` and `find_root()` to now have `fallback` argument to be applied when no root is found with `vim.fn.find()`. ## mini.pick ### Expand - Introduction of a new module. ## mini.starter ### Expand - Value of `show_path` in `sections.recent_files()` can now be callable for more control on how full path is displayed. ## mini.test ### Evolve - Update `child.get_screenshot()` to now by default call `:redraw` prior to computing screenshot. Can be disabled by new `opts.redraw` argument. ### Refine - Error in any "pre" hook now leads to test case not being executed (with note). ### Expand - New method `child.lua_func()` can execute simple functions inside child process and return the result (stasjok, #437). - Update `expect.reference_screenshot()` to now have `ignore_lines` option allowing to ignore specified lines during screenshot compare. # Version 0.10.0 ## mini.ai ### Expand - Allow `vis_mode` field in custom texobject region to force Visual mode with which textobject is selected. ## mini.animate ### Expand - Add `MiniAnimateNormalFloat` highlight group to tweak highlighting of `open` and `close` animations. ## mini.base16 ### Expand - Add 'HiPhish/rainbow-delimiters.nvim' integration. ## mini.basics ### Refine - Remove `` mapping in Terminal mode, as it is more useful inside terminal emulator itself. ## mini.bracketed ### Expand - Add `add_to_jumplist` option to relevant targets (which move cursor and don't already add to jumplist). ## mini.bufremove ### Refine - Create normal buffer instead of scratch when there is no reasonable target to focus (#394). ## mini.clue ### Expand - Introduction of a new module. ## mini.files ### Expand - Introduction of a new module. ## mini.hues ### Expand - Add 'HiPhish/rainbow-delimiters.nvim' integration. ## mini.jump2d ### Expand - Add `gen_union_spotter()` to allow combining separate spotters into one. ## mini.operators ### Expand - Introduction of a new module. ## mini.pairs ### Expand - Allow `false` in `config.mappings` to not map the key. ## mini.surround ### Expand - Update `add` (`sa`) with ability to replicate left and right parts by respecting `[count]`. In Normal mode two kinds of `[count]` is respected: one for operator (replicates left and right parts) and one for textobject/motion. In Visual mode `[count]` replicates parts. # Version 0.9.0 ## All ### Evolve - Use Lua API to create autocommands. Stop exporting functions only related to autocommands. - Use `vim.keymap` to deal with mappings. Stop exporting functions only related to mappings. ### Refine - Stop official support of Neovim 0.6. ### Expand - Add 'randomhue' color scheme. ## mini.base16 ### Evolve - Stop supporting archived 'p00f/nvim-ts-rainbow' in favor of 'HiPhish/nvim-ts-rainbow2'. ### Expand - Add new integrations: - Lsp semantic tokens. - 'folke/lazy.nvim'. - 'folke/noice.nvim'. - 'kevinhwang91/nvim-ufo'. ## mini.basics ### Expand - Add dot-repeat support for adding empty lines (`go` and `gO` mappings). ## mini.colors ### Expand - Introduction of a new module. ## mini.comment ### Expand - Use tree-sitter information about locally active language to infer 'commentstring' option value. - Add `options.custom_commentstring` option for a more granular customization of comment structure. - Add `get_commentstring()` function representing built-in logic of computing relevant 'commentstring'. ## mini.hipatterns ### Expand - Introduction of a new module. ## mini.hues ### Expand - Introduction of a new module. # Version 0.8.0 ## All ### Expand - Add and implement design principle for silencing module by setting `config.silent = true`. It is now present in modules capable of showing non-error feedback: - mini.ai - mini.align - mini.basics - mini.bufremove - mini.doc - mini.jump - mini.jump2d - mini.starter - mini.surround - mini.test ## mini.bracketed ### Expand - Introduction of a new module. ## mini.comment ### Expand - Add `options.start_of_line` option which controls whether to recognize as comment only lines without indent. - Add `options.ignore_blank_line` option which controls whether to ignore blank lines. - Add `options.pad_comment_parts` option which controls whether to ensure single space pad for comment leaders. ## mini.doc ### Expand - Add `config.hooks.write_pre` hook to be executed before writing to a file. ## mini.indentscope ### Expand - Add `MiniIndentscopeSymbolOff` highlight group to be used if scope's indent is not multiple of 'shiftwidth'. - Add `draw.priority` option to control priority of scope line draw. ## mini.jump2d ### Expand - Add `view.n_steps_ahead` option which controls how many steps ahead to show. Appearance is controlled by new `MiniJump2dSpotAhead` highlight group. - Add `view.dim` option which controls whether to dim lines with at least one jump spot. Appearance is controlled by new `MiniJump2dDim` highlight group. - Add `MiniJump2dSpotUnique` highlight group to be used for spots with unique label for next step. ## mini.pairs ### Expand - Both `MiniPairs.br()` and `MiniPairs.cr()` can now take a key which will be used instead of default `` and ``. ## mini.sessions ### Expand - Update `setup()` to now create global directory at path `config.directory` if it doesn't exist. - All actions now keep list of detected sessions up to date. ## mini.splitjoin ### Expand - Introduction of a new module. ## mini.surround ### Expand - Add `respect_selection_type` option which, when enabled, makes adding and deleting surrounding respect selection type: - Linewise adding places surrounding parts on separate lines while indenting surrounded lines once. - Deleting surrounding which looks like a result of linewise adding will act to revert it: delete lines with surrounding parts and dedent surrounded lines once. - Blockwise adding places surrounding parts on whole edges, not only start and end of selection. # Version 0.7.0 ## All ### Expand - Start dual distribution. Every module is now distributed both as part of 'mini.nvim' library and as standalone plugin (in separate git repository). ## mini.ai ### Refine - In `MiniAi.gen_spec.argument()` option `separators` (plural; array of characters) is soft deprecated in favor of `separator` (singular; Lua pattern) option. ## mini.animate ### Expand - Introduction of a new module. ## mini.basics ### Expand - Introduction of a new module. ## mini.completion ### Refine - Rename `MiniCompletion.config.window_dimensions` to `MiniCompletion.config.window` to be able to handle more general configuration. ### Expand - Add `MiniCompletion.config.window.info.border` and `MiniCompletion.config.window.signature.border` which can be used to define border of info and signature floating windows respectively. ## mini.indentscope ### Refine - Stop using (deprecate) `MiniIndentscopePrefix` highlight groups. It was initially introduced as a way to properly show scope indicator on empty lines. It had a drawback of overshadowing 'listchars' symbols (see #125) and vertical guides from 'lukas-reineke/indent-blankline.nvim'. As the other implementation approach was found by @mivort (see #161), `MiniIndentscopePrefix` is no longer needed and no overshadowing is done. - Update `MiniIndentscope.gen_animation` to now be a table (for consistency with other `gen_*` functions in 'mini.nvim'). See "Migrate from function type" section of `:h MiniIndentscope.gen_animation`. Calling it as function will be available until next release. ## mini.misc ### Expand - Add `MiniMisc.setup_auto_root()` and `MiniMisc.find_root()` for root finding functionality. NOTE: requires Neovim>=0.8. - Add `MiniMisc.setup_restore_cursor()` for automatically restoring latest cursor position on file reopen. By @cryptomilk, PR #198. ## mini.move ### Expand - Introduction of a new module. # Version 0.6.0 ## All ### Refine - Stop official support of Neovim 0.5. ### Expand - Make all messages use colors and not cause hit-enter-prompt. ## mini.align ### Expand - Introduction of a new module. ## mini.base16 ### Refine - Change some 'mini.nvim' highlights: - `MiniCompletionActiveParameter` now highlights with background instead of underline. - `MiniJump2dSpot` now explicitly defined to use plugin's palette. - `MiniStarterItemPrefix` and `MiniStarterQuery` are now bold for better visibility. - Update highlight for changed git diff to be more visible and to comply more with general guidelines. ### Expand - Add support for many plugin integrations. - Implement `MiniBase16.config.plugins` for configuring plugin integrations. ## mini.jump ### Refine - Allow cursor to be positioned past the end of previous/current line (#113). ## mini.map ### Expand - Introduction of a new module. ## mini.starter ### Refine - Item evaluation is now prepended with query reset, as it is rarely needed any more (#105). - All hooks are now called with `(content, buf_id)` signature allowing them properly use current window layout. ## mini.surround ### Evolve - Update 'mini.surround' to share as much with 'mini.ai' as possible. This provides more integrated experience while enabling more useful features. Details: - Custom surrounding specification for input action has changed. Instead of `{ find = , extract = }` it is now `{ }`. Previous format will work until the next release. See more in help file. - Algorithm for finding surrounding is now more powerful. It allows searching for more complex surroundings (via composed patterns or array of region pairs) and respects `v:count`. - Multiline input and output surroundings are now supported. - Opening brackets (`(`, `[`, `{`, `<`) now include whitespace in surrounding: input surrounding selects all inner edge whitespace, output surrounding is padded with single space. - Surrounding identifier `i` ("interactive") is soft deprecated in favor of `?` ("user prompt"). - New surrounding aliases: - `b` for "brackets". Input - any of balanced `()`, `[]` `{}`. Output - `()`. - `q` for "quotes". Input - any of `"`, `'`, `` ` ``. Output - `""`. - Three new search methods `'prev'`, `'next'`, and `'nearest'` for finding non-covering previous and next surrounding. - Implement "last"/"next" extended mappings which force `'prev'` or `'next'` search method. Controlled with `config.mappings.suffix_last` and `config.mappings.suffix_next`respectively. This also means that custom surroundings with identifier equal to "last"/"next" mappings suffixes (defaults to 'l' and 'n') will work only with long enough delay after typing action mapping. ### Expand - Implement `MiniSurround.gen_spec` with generators of common surrounding specifications (like `MiniSurround.gen_spec.input.treesitter` for tree-sitter based input surrounding). # Version 0.5.0 ## All ### Refine - Update all tests to use new 'mini.test' module. ### Expand - Implement buffer local configuration. This is done with `vim.b.mini*_config` buffer variables. - Add new `minicyan` color scheme. ## mini.ai - Introduction of a new module. ## mini.comment ### Expand - Now hooks can be used to terminate further actions by returning `false` (#108). ## mini.indentscope ### Refine - Soft deprecate `vim.b.miniindentscope_options` in favor of using `options` field of `miniindentscope_config`. ## mini.sessions ### Expand - Hooks are now called with active session data as argument. ## mini.starter ### Evolve ### Refine - Deprecate `MiniStarter.content` in favor of `MiniStarter.get_content()`. ### Expand - Make it possible to open multiple Starter buffers at the same time (#82). - All functions dealing with Starter buffer now have `buf_id` as argument. ## mini.statusline ### Expand - Implement `config.use_icons` which controls whether to use icons by default. ## mini.test - Introduction of a new module. ## mini.trailspace ### Expand - Implement `MiniTrailspace.trim_last_lines()`. # Version 0.4.0 ## All ### Expand - Update all modules to supply mapping description for Neovim>=0.7. - Cover all modules with extensive tests. ## mini.comment ### Expand - Implement `config.hooks` with `pre` and `post` hooks (executed before and after successful commenting). Fixes #50, #59. ## mini.completion ### Expand - Implement support for `additionalTextEdits` (issue #61). ## mini.jump ### Refine - Soft deprecate `config.highlight_delay` in favor of `config.delay.highlight`. ### Expand - Implement idle timeout to stop jumping automatically (@annenpolka, #56). - Implement `MiniJump.state`: table with useful model-related information. - Update process of querying target symbol: show help message after delay, allow `` to stop selecting target. ## mini.jump2d - Introduction of a new module. ## mini.pairs ### Refine - Create mappings for `` and `` in certain mode only after some pair is registered in that mode. ## mini.sessions ### Refine - All feedback about incorrect behavior is now an error instead of message notifications. ### Expand - Implement `MiniSessions.select()` to select session interactively and perform action on it. - Implement `config.hooks` to execute hook functions before and after successful action. ## mini.starter ### Expand - Allow `config.header` and `config.footer` be any value, which will be converted to string via `tostring()`. - Update query logic to not allow queries which result into no items. - Add `` and `` to default mappings. ## mini.statusline ### Refine - Change default icon for `MiniStatusline.section_diagnostics()` from ﯭ to  due to former having issues in some terminal emulators. ## mini.surround ### Evolve ### Refine - Deprecate `config.funname_pattern` option in favor of manually modifying `f` surrounding. - Always move cursor to the right of left surrounding in `add()`, `delete()`, and `replace()` (instead of moving only if it was on the same line as left surrounding). ### Expand - Implement `config.search_method`. - Implement custom surroundings via `config.custom_surroundings`. - Implement `MiniSurround.user_input()`. - Update process of getting user input: allow `` to cancel and make empty string a valid input. ## mini.tabline ### Refine - Show listed buffers also in case of multiple tabpages (instead of using builtin behavior). ### Expand - Implement `config.tabpage_section`. - Show quickfix/loclist buffers with special `*quickfix*` label. # Version 0.3.0 ## All ### Expand - Update all modules to have annotations formatted for 'mini.doc'. ## mini.cursorword ### Expand - Current word under cursor now can be highlighted differently. ## mini.doc ### Expand - Introduction of a new module. ## mini.indentscope ### Expand - Introduction of a new module. ## mini.starter ### Expand - Implement `MiniStarter.set_query()` and make `` mapping for resetting query. # Version 0.2.0 ## mini.base16 ### Expand - Use new `Diagnostic*` highlight groups in Neovim 0.6.0. ## mini.comment ### Expand - Respect tab indentation (#20). ## mini.jump ### Expand - Introduction of a new module. ## mini.pairs ### Expand - Implement pair registration with custom mapping functions: - Implement `MiniPairs.map()`, `MiniPairs.map_buf()`, `MiniPairs.unmap()`, `MiniPairs.unmap_buf()` to (un)make mappings for pairs which automatically register them for `` and ``. Note, that this has a minor break of previous behavior: now `MiniPairs.bs()` and `MiniPairs.cr()` don't have any input argument. But default behavior didn't change. - Allow setting global pair mappings inside `config` of `MiniPairs.setup()`. ## mini.sessions ### Expand - Introduction of a new module. ## mini.starter ### Expand - Introduction of a new module. ## mini.statusline ### Expand - Implement new section `MiniStatusline.section_searchcount()`. - Update `section_diagnostics` to use `vim.diagnostic` in Neovim 0.6.0. # Version 0.1.0 ## All ### Expand - Initial stable version. ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at `evgeni chasnovski |at| gmail >dot< com` . All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations]. [homepage]: https://www.contributor-covenant.org [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing Thank you for your willingness to contribute to 'mini.nvim'. It means a lot! You can make contributions in the following ways: - **Mention it** somehow to help reach broader audience. This helps a lot. - **Create a GitHub issue**. It can be one of the following types: - **Bug report**. Describe your actions in a reproducible way along with their effect and what you expected should happen. Before making one, please make your best efforts to: - Make sure that it is not an intended behavior, i.e. not described in documentation as such. - Make sure that it was not reported before, i.e. there is no bug report already created (no matter open or closed). - **Feature request**. A concise and justified description of what one or several modules should be able to do. Before making one, please make your best efforts to make sure that it is not a feature that won't get implemented (these should be described in documentation; for example: block comments in 'mini.comment'). - **Create a pull request (PR)**. It can be one of the following types: - **Code related**. For example, fix a bug or implement a feature. **Before even starting one, please make sure that it is aligned with project vision and goals**. The best way to do so is to receive positive feedback from maintainer on your initiative in one of the GitHub issues (existing or created by you). Please, make sure to regenerate latest help file and that all tests pass (see later sections). - **Documentation related**. For example, fix typo/wording in 'README.md', code comments or annotations (which are used to generate Neovim documentation; see later section). Feel free to make these without creating a GitHub issue. - **Add plugin integration to 'mini.base16' and 'mini.hues' modules**. - **Add explicit support to other colorschemes**. Every 'mini.nvim' module supports any colorscheme right out of the box. This is done by making most highlight groups be linked to a semantically similar builtin highlight group. Other groups are hard-coded based on personal preference. However, these choices might be out of tune with a particular colorscheme. Updating as many colorschemes as possible to have explicit 'mini.nvim' support is highly appreciated. For your convenience, there is a list of all highlight groups in later section of this file. - **Participate in [discussions](https://github.com/nvim-mini/mini.nvim/discussions)**. All well-intentioned, polite, and respectful contributions are always welcome! Thanks for reading this! ## Commit messages - Try to make commit message as concise as possible while giving enough information about nature of a change. Think about whether it will be easy to understand in one year time when browsing through commit history. - Single commit should change either zero or one module, or affect all modules (i.e. enforcing some universal rule but not necessarily change files). Changes for two or more modules should be split in several module-specific commits. - Use [Conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) style: - Messages should have the following structure: ``` [optional scope][!]: [optional body] [optional footer(s)] ``` - `` is **mandatory** and can be one of: - `ci` - change in how automation (GitHub actions, dual distribution scripts, etc.) is done. - `docs` - change in user facing documentation (help, README, CONTRIBUTING, etc.). - `feat` - adding new user facing feature. - `fix` - resolving user facing issue. - `refactor` - change in code or documentation that should not affect users. - `style` - change in convention of how something should be done (formatting, wording, etc.) and its effects. - `test` - change in tests. For temporary commits which later should be squashed (when working on PR, for example), use `fixup` type. - `[optional scope]`, if present, should be done in parenthesis `()`. If commit changes single module (as it usually should), using scope with module name is **mandatory**. If commit enforces something for all modules, use `ALL` scope. - Breaking change, if present, should be expressed with `!` before `:`. - `` is a change overview in imperative, present tense ("change" not "changed" nor "changes"). Should result into first line under 72 characters. Should start with not capitalized word and NOT end with sentence ending punctuation (i.e. one of `.,?!;`). - `[optional body]`, if present, should contain details and motivation about the change in plain language. Should be formatted to have maximum 80 characters in line. - `[optional footer(s)]`, if present, should be instruction(s) to Git or Github. Use "Resolve #xxx" on separate line if this commit resolves issue or PR. - Use module's function and field names without module's name. Like `add()` and not `MiniSurround.add()`. Examples: ``` feat(deps): add folds in update confirmation buffer ``` ``` fix(jump): make operator not delete one character if target is not found One main goal is to do that in a dot-repeatable way, because this is very likely to be repeated after an unfortunate first try. Resolve #688 ``` ``` refactor(bracketed): do not source 'vim.treesitter' on `require()` Although less explicit, this considerably reduces startup footprint of 'mini.bracketed' in isolation. ``` ``` feat(hues)!: update verbatim text to be distinctive ``` ``` test(ALL): update screenshots to work on Nightly ``` ### Automated commit linting - To lint messages of already done commits, execute `scripts/lintcommit-ci.sh `. For example, to lint currently latest commit use `scripts/lintcommit-ci.sh HEAD~..HEAD`. - To lint commit message before doing commit, install [`pre-commit`](https://pre-commit.com/#install) and enable it with `pre-commit install --hook-type commit-msg` (from the root directory). NOTE: requires `nvim` executable. If it throws (usually descriptive) error - recommit with proper message. ## Generating help file If your contribution updates annotations used to generate help file, please regenerate it. You can make this with one of the following (assuming current directory being project root): - From command line execute `make documentation`. - Inside Neovim instance run `:luafile scripts/minidoc.lua` or `:lua require('mini.doc').generate()`. ## Testing If your contribution updates code, please make sure that it doesn't break existing tests. If it adds new functionality or fixes a recognized bug, add new test case(s). There are two ways of running tests: - From command line: - Execute `make test` to run all tests (with `nvim` as executable). - Execute `make test_xxx` to run tests only from file `tests/test_xxx.lua` (with `nvim` as executable). For example, `make test_ai`. - If you have multiple Neovim executables (say, `nvim_07`, `nvim_08`, `nvim_09`, `nvim_010`), you can use `NVIM_EXEC` variable to tests against multiple versions like this: `NVIM_EXEC="nvim_07 nvim_08 nvim_09 nvim_010" make test` or `NVIM_EXEC="nvim_07 nvim_08 nvim_09 nvim_010" make test_xxx`. - Inside Neovim instance execute `:lua require('mini.test').setup(); MiniTest.run()` to run all tests or `:lua require('mini.test').setup(); MiniTest.run_file()` to run tests only from current buffer. This plugin uses 'mini.test' to manage its tests. For a more hands-on introduction, see [TESTING.md](TESTING.md). **Notes**: - If new functionality relies on an external dependency (`git` CLI tool, LSP server, etc.), use mocking (writing Lua code which emulates dependency usage as close as reasonably possible). For examples, take a look at tests for 'mini.pick', 'mini.completion', and 'mini.statusline'. - There is a certain number of tests that are flaky (i.e. will sometimes report an error due to other reasons than actual functionality being broke). It is usually the ones which test time related functionality (i.e. that certain action was done after specific amount of delay). A commonly used way to know if the test is flaky is that it fails on non-nightly Neovim version yet there were no changes to its tested module after it had passed in the past. For example, some 'mini.animate' test is shown to break but there were no changes to it since test passed in CI couple of days before. This issue is addressed by having test cases being executed several times in case of failure (with more retries in slow context). See ["Retry" section in 'TESTING.md'](TESTING.md#Retry). In case there is some test breaking which reasonably should not, rerun that test (or the whole file) at least several times. - Advice for writing more robust tests: - To test asynchronous or slow execution, use common `sleep()` test helper. For a more robust testing code, **never** directly use numbers to compute sleep time. Use precomputed time delay constants, which should always take into account different testing OSs (like be bigger on Windows, etc.). If module testing requires its extensive use and tests can not be made robust enough (examples are 'mini.animate', 'mini.jump', etc.), consider using it with argument that skips entire test case if `sleep()` is called in slow context. - Take into account that Windows uses "\" as default path separator instead of Unix "/". This should be accounted either in module's code (preferably) or in test files (for example, by computing path separator and relying on it). ## Formatting This project uses [StyLua](https://github.com/JohnnyMorganz/StyLua) version 2.1.0 for formatting Lua code. Before making changes to code, please: - [Install StyLua](https://github.com/JohnnyMorganz/StyLua#installation). NOTE: use `v2.1.0`. - Format with it. Currently there are two ways to do this: - Manually run `stylua .` from the root directory of this project. - Install [`pre-commit`](https://pre-commit.com/#install) and enable it with `pre-commit install` (from the root directory). This will auto-format relevant code before making commits. ## List of highlight groups Here is a list of all highlight groups defined inside 'mini.nvim' modules. See documentation in 'doc' directory to find out what they are used for. - 'mini.animate': - `MiniAnimateCursor` - `MiniAnimateNormalFloat` - 'mini.clue': - `MiniClueBorder` - `MiniClueDescGroup` - `MiniClueDescSingle` - `MiniClueNextKey` - `MiniClueNextKeyWithPostkeys` - `MiniClueSeparator` - `MiniClueTitle` - 'mini.cmdline': - `MiniCmdlinePeekBorder` - `MiniCmdlinePeekLineNr` - `MiniCmdlinePeekNormal` - `MiniCmdlinePeekSep` - `MiniCmdlinePeekSign` - `MiniCmdlinePeekTitle` - 'mini.completion': - `MiniCompletionActiveParameter` - `MiniCompletionDeprecated` - `MiniCompletionInfoBorderOutdated` - 'mini.cursorword': - `MiniCursorword` - `MiniCursorwordCurrent` - 'mini.deps': - `MiniDepsChangeAdded` - `MiniDepsChangeRemoved` - `MiniDepsHint` - `MiniDepsInfo` - `MiniDepsMsgBreaking` - `MiniDepsPlaceholder` - `MiniDepsTitle` - `MiniDepsTitleError` - `MiniDepsTitleSame` - `MiniDepsTitleUpdate` - 'mini.diff': - `MiniDiffSignAdd` - `MiniDiffSignChange` - `MiniDiffSignDelete` - `MiniDiffOverAdd` - `MiniDiffOverChange` - `MiniDiffOverChangeBuf` - `MiniDiffOverContext` - `MiniDiffOverContextBuf` - `MiniDiffOverDelete` - 'mini.files': - `MiniFilesBorder` - `MiniFilesBorderModified` - `MiniFilesCursorLine` - `MiniFilesDirectory` - `MiniFilesFile` - `MiniFilesNormal` - `MiniFilesTitle` - `MiniFilesTitleFocused` - 'mini.hipatterns': - `MiniHipatternsFixme` - `MiniHipatternsHack` - `MiniHipatternsNote` - `MiniHipatternsTodo` - 'mini.icons': - `MiniIconsAzure` - `MiniIconsBlue` - `MiniIconsCyan` - `MiniIconsGreen` - `MiniIconsGrey` - `MiniIconsOrange` - `MiniIconsPurple` - `MiniIconsRed` - `MiniIconsYellow` - 'mini.indentscope': - `MiniIndentscopeSymbol` - `MiniIndentscopeSymbolOff` - 'mini.jump': - `MiniJump` - 'mini.jump2d': - `MiniJump2dDim` - `MiniJump2dSpot` - `MiniJump2dSpotAhead` - `MiniJump2dSpotUnique` - 'mini.map': - `MiniMapNormal` - `MiniMapSymbolCount` - `MiniMapSymbolLine` - `MiniMapSymbolView` - 'mini.notify': - `MiniNotifyBorder` - `MiniNotifyLspProgress` - `MiniNotifyNormal` - `MiniNotifyTitle` - 'mini.operators': - `MiniOperatorsExchangeFrom` - 'mini.pick': - `MiniPickBorder` - `MiniPickBorderBusy` - `MiniPickBorderText` - `MiniPickCursor` - `MiniPickIconDirectory` - `MiniPickIconFile` - `MiniPickHeader` - `MiniPickMatchCurrent` - `MiniPickMatchMarked` - `MiniPickMatchRanges` - `MiniPickNormal` - `MiniPickPreviewLine` - `MiniPickPreviewRegion` - `MiniPickPrompt` - `MiniPickPromptCaret` - `MiniPickPromptPrefix` - 'mini.snippets': - `MiniSnippetsCurrent` - `MiniSnippetsCurrentReplace` - `MiniSnippetsFinal` - `MiniSnippetsUnvisited` - `MiniSnippetsVisited` - 'mini.starter': - `MiniStarterCurrent` - `MiniStarterFooter` - `MiniStarterHeader` - `MiniStarterInactive` - `MiniStarterItem` - `MiniStarterItemBullet` - `MiniStarterItemPrefix` - `MiniStarterSection` - `MiniStarterQuery` - 'mini.statusline': - `MiniStatuslineDevinfo` - `MiniStatuslineFileinfo` - `MiniStatuslineFilename` - `MiniStatuslineInactive` - `MiniStatuslineModeCommand` - `MiniStatuslineModeInsert` - `MiniStatuslineModeNormal` - `MiniStatuslineModeOther` - `MiniStatuslineModeReplace` - `MiniStatuslineModeVisual` - 'mini.surround': - `MiniSurround` - 'mini.tabline': - `MiniTablineCurrent` - `MiniTablineFill` - `MiniTablineHidden` - `MiniTablineModifiedCurrent` - `MiniTablineModifiedHidden` - `MiniTablineModifiedVisible` - `MiniTablineTabpagesection` - `MiniTablineTrunc` - `MiniTablineVisible` - 'mini.test': - `MiniTestEmphasis` - `MiniTestFail` - `MiniTestPass` - 'mini.trailspace': - `MiniTrailspace` ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2021 Evgeni Chasnovski Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: MAINTAINING.md ================================================ # Maintaining This document contains knowledge about specifically maintaining 'mini.nvim'. It assumes general knowledge about how Open Source and GitHub issues/PRs work. See [CONTRIBUTING.md](CONTRIBUTING.md) for how to generate help files, run tests, and format. ## General advice - Follow common boilerplate code as much as possible when creating new module, as it makes easier to use "search and replace" in the long term. This includes: - Documentation at the beginning: describing module, its setup, highlight groups, similar plugins, disabling, `setup()`, and `config`. - Create and use `H` helper table at the beginning to allow having exported code written before helpers (severely improves readability). - Structure of `setup()` function with its helper functions: `H.setup_config()`, `H.apply_config()`, `H.create_autocommands()`, `H.create_default_hl()`, `H.create_user_commands()`. - Use module's `H.get_config()` and `H.is_disabled()` helpers. They both should respect buffer local configuration. - From time to time some test cases will break on Neovim Nightly. This is usually due to the following reasons: - There was an intended change in Neovim Nightly to which affected module(s) should adapt. Update module and/or tests. - There was a change in Neovim Nightly disrupting only tests (usually screenshots due to changed way of how highlight attributes are computed). Update test: ideally so that it passes on all versions (by adjusting test logic or by selectively ignoring attributes / text of not matching lines with `ignore_text` / `ignore_attr` *behind narrowest Neovim version check*), but testing some parts only on Nightly is allowed if needed (regenerate screenshot on Nightly and verify it only on versions starting from it). - There was an unintended change in Neovim Nightly which breaks functionality it should not break. Create an issue in ['neovim/neovim' repo](https://github.com/neovim/neovim). If the issue is not resolved for a long-ish time (i.e. more than a week) try to make tests pass and/or adapt the code to new behavior. - Write help annotations in a way that after help generation they are usable in both built-in `:help`and on nvim-mini.org site. In particular: - Prefer using `# Section ~` and `## Subsection ~` explicit sections. This allows more structured table of contents and adds anchors for all of them. - Prefer using "naturally sounding" help tags for an entire section because they are transformed into a title. So like `---@tag MiniAi-builtin-textobjects` and not `---@tag MiniAi-textobjects-builtin`. - As a consequence, don't add "# Title ~" title at the beginning of the section. This is a role for the tag (in both help file and site). - Do not use explicit right aligned tags, as they result into a separate high level heading on the site. This usually breaks hierarchical structure of the page (like if added as part of a `MiniXxx.config` section, it ends the `config` section and starts its own). Prefer to "naturally" incorporate a tag into a text in first line of its info or add it directly below a dedicated section. Examples: ``` --- # Important topic ~ --- *MiniXxx-important-topic* --- --- A text about important topic of 'mini.xxx' module. --- --- # Another topic ~ --- --- *MiniXxx-another-topic* is also important. --- --- *MiniXxx-last-resort* --- As last resort just add left aligned tag before first line --- or at line start. ``` ## Maintainer setup Mandatory: - Have `nvim` executable for latest stable release. - Install [`git`](https://www.git-scm.com). - Install [`StyLua`](https://github.com/JohnnyMorganz/StyLua) with version described in [CONTRIBUTING.md](CONTRIBUTING.md). - Install [`make`](https://www.gnu.org/software/make/). Recommended: - Have executables for all supported Neovim versions. For example, `nvim_07`, `nvim_08`, `nvim_09`, `nvim_010`. This is useful for running tests on multiple versions. - Install [`lua-language-server`](https://github.com/LuaLS/lua-language-server). - Install [`pre-commit`](https://pre-commit.com/#install) and enable it with `pre-commit install` and `pre-commit install --hook-type commit-msg` (run from repository's root). - Set up 'mini.doc' and 'mini.test' and make mappings for the following frequently used commands: - `'lua MiniDoc.generate()'` - to generate documentation. - `'lua MiniTest.run_at_location()'` - to run test under cursor. - `'lua MiniTest.run_file()'` - to run current test file. ## Supported Neovim versions Aim for supporting 4 latest minor Neovim releases: current stable, current Nightly, and two latest stable releases. For example, if 0.9.x is current stable, then all latest patch versions of 0.7, 0.8, 0.9 should be supported plus Nightly (0.10.0). NOTE: some modules can have less supported versions during their release **only** if it is absolutely necessary for the core functionality. ## Dual distribution Modules of 'mini.nvim' are distributed both as part of 'mini.nvim' repository and each one in its standalone repository. All development takes place in 'mini.nvim' while being synced to standalone ones. This is done by having special `sync` branch which points to the latest commit which was synced to standalone repositories. Usual workflow involves performing these steps after every commit in 'mini.nvim': - Check out to `main` branch. - Ensure there are no immediate defects. Usually it means to wait until all CI checks passed. - Run `make dual_sync`. This should: - Create 'dual' directory if doesn't exist yet. - Pull standalone repositories in 'dual/repos'. - Create patches in 'dual/patches' and apply them for standalone repositories. See 'scripts/dual_sync.sh' for more details. - Run `make dual_log` to make sure that all and correct patches were applied. If some commit touches files from several modules, it results into commits for every affected standalone repository. - Run `make dual_push`. This should: - Push updates for affected standalone repositories. - Clean up 'dual/patches'. - Update `sync` branch to point to latest commit and push it to `origin`. ## Typical workflow for adding change - Solve the problem. - If change is in code, write test which breaks before problem is solved and passes after. - If change introduces new config setting, consult with [dedicated checklist](#adding-new-config-settings). - If change is worth to be seen by users (notable/breaking feature/fix), update 'CHANGELOG.md' following formatting from previous versions. - Make sure that all tests in affected module(s) pass in all supported versions. See [Maintainer setup](#maintainer-setup) and ['Testing' section in CONTRIBUTING.md](CONTRIBUTING.md#testing). - Stage and commit changes into a separate Git branch. Push the branch. - Make sure that all CI pass. - Merge branch into `main` branch. Push `main`. - Make sure that all CI pass (again). - Synchronize dual distribution: - `make dual_sync` to sync. - `make dual_log` and look at changes which are about to be applied to standalone repositories. Make sure that they are what you'd expect. - `make dual_push` to push changes to standalone repositories. ## Typical workflow for processing a GitHub issue - Add label with module name issue is about (if any). If issue is worded politely and/or with much details, thank user for opening an issue. - Make sure the underlying problem is valid, i.e. it can be reproduced and the root cause is in this project. If it can not be reproduced, politely explain that and ask for more reproduction details. If the cause is not related to the project, politely explain that, close an issue, and direct towards the real root cause. - Check already existing issues for possible duplicates. If there is at least one, review its reasoning before making decision about the current issue. - Decide whether and how an issue should be resolved. Use ["General principles"](README.md#general-principles), module's help and code documentation while making the decision. - If decision is to not resolve, politely explain that and close an issue (possibly mentioning similar reasoning in the past). - If decision is to resolve, resolve the issue while putting `Resolve #xxx` at the bottom of commit message. ## Typical workflow for processing GitHub pull request - Add label with module name pull request (PR) is about (if any). If PR is worded politely, thank user for doing that. - Make sure the PR is valid, i.e. resolves an issue or adds a feature any of which aligns with the project. Ideally, it should have been agreed in the prior created issue (as per [CONTRIBUTING.md](CONTRIBUTING.md)). - Review PR code and iterate towards making it have enough code quality. Use first steps of ["Typical workflow for adding change"](#typical-workflow-for-adding-change) as reference. **Note**: if what is left to do requires some overly specific project knowledge (i.e. can be done _much_ quicker if you know how, but requires non-trivial amount of reading/discovering first time), consider merging PR in a new separate branch and finish it manually (usually with preserving original commit authorship). - When change is of enough quality, merge it and proceed treating it as regular change. ## Stopping support for old Neovim version Begin the process of stopping official support for outdated Neovim version shortly after (week or two) the release of the new stable one. Usually it is stopping support for Neovim 0.x (say, 0.8) shortly after the release of 0.(x+3).0 (say, 0.11.0). The deprecation should be done in two stages: - Stage 1, soft deprecation (to notify old version users about upcoming support drop): - Add version of the following code snippet at the beginning of `setup()` function body in **every** module: ```lua -- TODO: Remove after Neovim=0.8 support is dropped if vim.fn.has('nvim-0.9') == 0 then vim.notify( '(mini.ai) Neovim<0.9 is soft deprecated (module works but not supported).' .. ' It will be deprecated after next "mini.nvim" release (module might not work).' .. ' Please update your Neovim version.' ) end ``` - Modify CI to not test on old Neovim version. - Update issue template to not include old Neovim version. - Update README and repo description to indicate new oldest supported Neovim version. - Wait for a considerable amount of time (at least about a month) *and* a new 'mini.nvim' stable release (so that there is no actual deprecation in the stable release). - Stage 2, deprecation: - Remove all notification snippets added in Stage 1. - Adjust code that is conditioned on `vim.fn.has('nvim-0.x')` and `vim.fn.exists('+option')` (if the option is present in all currently supported Neovim versions). - Adjust code/comments/documentation that contains any combination of `Neovim{<,<=,=,>=,>}{0.x,0.(x+1)}` (like `Neovim<0.x`, `Neovim>=0.(x+1)`, etc.). - Add entry "Stop official support of Neovim 0.x." in 'CHANGELOG.md' at the start of current development version block. ## Reacting to new minor Neovim version - Modify CI to test on new Neovim version. - Update issue template to mention new Neovim version as released one, make it default choice, and bump Nightly version. ## Reacting to failing tests after Neovim Nightly changes As Neovim is in active development, from time to time there will be test failures only on Neovim Nightly (and not on earlier versions). Adjusting tests to pass on all supported versions is important. The sooner the better, as it will allow for an easier deduction of what Neovim change is responsible here. For examples of how this was done in the past, search `git log --oneline` output for "Nightly". This is probably the best way to learn about different approaches. Here is a rough outline of how to act (with some Git commit hashes for illustration): - Investigate if the change actually affects plugin functionality or is it only due to how the test is set up. Trying to manually reproduce the tested behavior on Nightly version is usually helpful for this decision. Common examples of code related changes on Nightly: - Changing how certain functions work: different arguments or a breaking change. Like in `848c5e8f428faf843051768e0d56104cd02aea1f`. - Deprecating functions. Like in `0f85c464605cab5ba922644d3f2508c6d62f258e`. However, usually it is about how a test is set up. Some common examples: - Screenshot testing fails in areas that are not relevant to what is being tested. For example, highlighting attributes of the command line are different (like in `bac6c8bb77fe0a872719ea43c39e35c7c695f05e`) or the number of picker items in 'mini.pick' has changed (like in `b409fd1d8b9ea7ec7c0923eb2562b52ed5d1ab0a`) - New option/mapping/command/etc. is added that broke assumptions about testing environment. Like in `0a8a1072137d916406507c941698a4bfa9dbbe7a`. - Mocking (like LSP or system interaction) is not precise enough for the actually behavior anymore. Like in `c889667a9d73b106bd303a043eb37a91da4a41a2`. - If the change affects the code: - Adjust the code to work on all supported versions. This should always be the priority. - If you think the Nightly change is unintended, open an issue upstream. Usually requires narrowing down to a reproducible example that does not involve this plugin at all (this is hard!). - If needed, also adjust the tests to pass on all versions. - If needed, prioritize version support in order: current release, Nightly, previous releases. Like if there is a question of different performance trade-offs. - If the change only affects the test: - First try to adjust the test to pass on all supported Neovim versions. Like adding different code paths for Neovim>=0.xx and Neovim<0.xx. This is usually not the case for failing screenshot testing. If feasible and can be done concisely, replace failing screenshot testing with other means of equivalent testing. Like in `68955a915c45ae7c988c539abe6e89f0971a9a2d`. - If the previous path is not possible or is significantly complex, make an educated decision of whether test fail is related to the actually tested functionality or not. If it tests something crucial, make the best effort to test on the widest *forward-compatible* set of Neovim versions. I.e. it should test on Neovim>=0.yy and not Neovim<=0.yy. Usually it is good enough for non-crucial part of the test to make only a forward-compatible test that starts on current Nightly (as long as that version is being tested in CI). Like in `3f5d06a6f710966cb93baaadc4897eeb6d6210e5` or `be6979dddb339c4a548d2f1dac5c290b5bf73306`. - Make adjustments and commit. Use commit message with title that contains "Nightly" and (preferably) with body describing the culprit for the change. This helps when searching the Git history for similar cases. ## Adding new config settings - Add code which uses new setting. - Add default value to `Mini*.config` definition. - Update module's `H.setup_config()` with type check of new setting. - Update tests to test default config value and its type check. - Regenerate help file. - Update module's README in 'readmes' directory. - Possibly update demo for it to be aligned with current config values. - Update 'CHANGELOG.md'. In module's section of current version add line starting with `- FEATURE: Implement ...`. ## Adding new color scheme plugin integration - Update color scheme module file in a way similar to other already added plugins: - Add definitions for highlight groups. - Add plugin entry in a list of supported plugins in help annotations. - Add plugin entry in a module's README. - Regenerate documentation (see [corresponding section in CONTRIBUTING.md](CONTRIBUTING.md#generating-help-file)). ## Adding new module ### Preparation - Create new module-related assets in https://github.com/nvim-mini/assets: - Logo files. See 'logo-2/generate.lua' in the repo for more details. - Demo video. Preferably under 1 minute screencast showcasing main features. Usually should also display module's config. Use config as close to bare MiniMax as possible. See other demos for reference. - Write release blog post for nvim-mini.org. Copy file naming and structure from previous release posts. Mention future beta-testing issue with a placeholder link. ### Initial - Add Lua source code in 'lua' directory. - Add tests in 'tests' directory. Use 'tests/dir-xxx' name for module-specific non-test helpers. - Update 'lua/init.lua' to mention new module: both in initial table of contents and list of modules. - Add new module to the following files: - 'scripts/minidoc.lua' to generate separate help file. - 'scripts/dual_sync.sh' to include new module. - 'scripts/dual_release.sh' to include new module. - '.github/ISSUE_TEMPLATE/bug-report.yml' to be included in a dropdown menu. - '.github/ISSUE_TEMPLATE/feature-request.yml' to be included in a dropdown menu. - '.github/DISCUSSION_TEMPLATE/q-a.yml' to be included in a dropdown menu. - Generate help files. - Add README to 'readmes' directory following the structure of some of already existing README (preferably one of the latest). NOTE: comment out mentions of `stable` branch, as it won't work during beta-testing. - Update main README: - Mention new module in table of contents. - Remove the module from "Planned modules" section (if present). - Update 'CHANGELOG.md' to mention introduction of new module. - Update 'CONTRIBUTING.md' to mention new highlight groups (if there are any). - Create separate release branch and commit changes with message 'feat(xxx): add NEW MODULE'. NOTE: it is cleaner to synchronize standalone repositories prior to this commit. - If there are new highlight groups, follow up with adding explicit support in color scheme modules. - Push release branch. Make sure CI is green. ### Site integration - Checkout to module release branch. - Verify that nvim-mini.org handles new module. For that: - Modify 'mini.nvim' dependency to checkout into release branch. - `make sync`. - Add release blog post. - `quarto preview`. - Verify that new content looks as expected. ### Release - Make standalone plugin: - Create new empty GitHub repository. Disable Issues, limit PRs. - Clone the repo manually. Copy 'LICENSE' file to it, stage, and commit ("docs: add license"). Push. - Add the following GitHub tags: "lua", "neovim", "neovim-plugin", "mini-nvim". - Merge release branch into `main`. Push `main` and sync dual distribution. - Check that standalone repo doesn't have some known issues: - Make sure that all tracked files are synchronized. For list of tracked files see 'scripts/dual_sync.sh'. Initially they are 'doc/mini-xxx.txt', 'lua/mini/xxx.lua', 'LICENSE', and 'readmes/mini-xxx.md' (copied to be 'README.md' in standalone repository). - Make sure that 'README.md' in standalone repository has appropriate relative links (see patch script). - If there are issues, manually adjust in the repo, amend to latest commit, and force push. - Create a beta-testing issue and pin it. - Update nvim-mini.org: - `make sync` on `main` branch. - Add release blog post. NOTE: update it with proper beta-testing issue link. - Push. ### Post release - Wait for at least several weeks of beta-testing before including new module to MiniMax. ## Making stable release ### When There is no clear guidelines for when a stable (minor) release should be made. Mostly "when if feels right" but "not too often". If it has to be put in words, it is something like "After 3 new modules have finished beta-testing or 4 months, whichever is sooner". No patch releases have been made yet. ### Preparation - Write release blog post for nvim-mini.org. Copy file naming and structure from previous version release posts. ### Initial - Check for `TODO`s about actions to be done *before* release. - Checkout `release-0.xx` branch. - Update READMEs of new modules to mention `stable` branch. Commit. - Bump version in 'CHANGELOG.md'. Commit. - Make a dummy change in 'lua/mini/init.lua' file to trigger code CI. Commit. - Push to check on CI. **Proceed only if it is successful**. - Remove dummy change commit. ### Release - Merge `release-0.xx` to `main` and push it. Check that CI has passed. - Synchronize standalone repositories. - Make annotated tag: `git tag -a v0.xx.0 -m 'Version 0.xx.0'`. Push it. - Make GitHub release. Get description from copying entries of version's 'CHANGELOG.md' section. - Move `stable` branch to point at new tag (`git branch --force stable` when on latest tag's commit). Push it. - Release standalone repositories. It should be enough to use 'scripts/dual_release.sh' like so: ``` # REPLACE `xx` with your version number TAG_NAME="v0.xx.0" TAG_MESSAGE="Version 0.xx.0" make dual_release ``` - Check that standalone repositories actually got updates (tag + `stable`): manually visit some of them (at least new modules) on GitHub. ### After release - Synchronize nvim-mini.org. Merge blog post. Push. Post on Reddit and other social media. - Finish beta-testing new modules: - Close beta-testing issues. - Add them to MiniMax. - Use development version in 'CHANGELOG.md' ('0.(xx+1).0-dev'). Commit. - Check for `TODO`s about actions to be done *after* release. ================================================ FILE: Makefile ================================================ NVIM_EXEC ?= nvim all: test documentation # Use `make test` to run tests for all modules test: for nvim_exec in $(NVIM_EXEC); do \ printf "\n======\n\n" ; \ $$nvim_exec --version | head -n 1 && echo '' ; \ $$nvim_exec --headless --noplugin -u ./scripts/minimal_init.lua \ -c "lua require('mini.test').setup()" \ -c "lua MiniTest.run()" ; \ done # Use `make test_xxx` to run tests for module 'mini.xxx' TEST_MODULES = $(basename $(notdir $(wildcard tests/test_*.lua))) $(TEST_MODULES): for nvim_exec in $(NVIM_EXEC); do \ printf "\n======\n\n" ; \ $$nvim_exec --version | head -n 1 && echo '' ; \ $$nvim_exec --headless --noplugin -u ./scripts/minimal_init.lua \ -c "lua require('mini.test').setup()" \ -c "lua MiniTest.run_file('tests/$@.lua')" ; \ done documentation: $(NVIM_EXEC) --headless --noplugin -u ./scripts/minimal_init.lua -c "lua require('mini.doc').generate()" -c "qa!" lintcommit-ci: export LINTCOMMIT_STRICT=true && chmod u+x scripts/lintcommit-ci.sh && scripts/lintcommit-ci.sh lint-filename-length-ci: chmod u+x scripts/lint-filename-length.sh && scripts/lint-filename-length.sh dual_sync: chmod u+x scripts/dual_sync.sh && scripts/dual_sync.sh dual_log: chmod u+x scripts/dual_log.sh && scripts/dual_log.sh dual_push: chmod u+x scripts/dual_push.sh && scripts/dual_push.sh printf "\n\033[1mAdjusting `sync` branch\033[0m\n" git branch --force sync git push origin sync printf "\n\033[1mRemoving local patches\033[0m\n" rm -r dual/patches dual_release: chmod u+x scripts/dual_release.sh && scripts/dual_release.sh "$(TAG_NAME)" "$(TAG_MESSAGE)" ================================================ FILE: README.md ================================================

mini.nvim

### All-in-one plugin Library of 40+ independent Lua modules improving overall [Neovim](https://github.com/neovim/neovim) (version 0.9 and higher) experience with minimal effort. They all share same configuration approaches and general design principles. Think about this project as "Swiss Army knife" among Neovim plugins: it has many different independent tools (modules) suitable for most common tasks. Each module can be used separately without any startup and usage overhead. If you want to help this project grow but don't know where to start: - Leave a Github star for 'mini.nvim' and/or any other [MINI projects](https://nvim-mini.org). - Check out [contributing guides](CONTRIBUTING.md). See [change log](CHANGELOG.md) for a history of changes, including current development version. See [MiniMax](https://nvim-mini.org/MiniMax) for a full config example based on 'mini.nvim'. > [!NOTE] > This was previously hosted at `echasnovski/mini.nvim`. It was transferred to a dedicated organization to improve long term project stability. See more details [here](https://github.com/nvim-mini/mini.nvim/discussions/1970). ## Table of contents - [Installation](#installation) - [Modules](#modules) - [General principles](#general-principles) - [Plugin color schemes](#plugin-color-schemes) - [Planned modules](#planned-modules) ## Installation There are two branches to install from: - `main` (default, **recommended**) will have latest development version of plugin. All changes since last stable release should be perceived as being in beta testing phase (meaning they already passed alpha-testing and are moderately settled). - `stable` will be updated only upon releases with code tested during public beta-testing phase in `main` branch. Here are code snippets for some common installation methods: - Manually with `git clone` (compatible with [mini.deps](https://nvim-mini.org/mini.nvim/readmes/mini-deps)): ```lua -- Put this at the top of 'init.lua' local path_package = vim.fn.stdpath('data') .. '/site' local mini_path = path_package .. '/pack/deps/start/mini.nvim' if not vim.loop.fs_stat(mini_path) then vim.cmd('echo "Installing `mini.nvim`" | redraw') local clone_cmd = { 'git', 'clone', '--filter=blob:none', -- Uncomment next line to use 'stable' branch -- '--branch', 'stable', 'https://github.com/nvim-mini/mini.nvim', mini_path } vim.fn.system(clone_cmd) vim.cmd('packadd mini.nvim | helptags ALL') vim.cmd('echo "Installed `mini.nvim`" | redraw') end ``` - With [folke/lazy.nvim](https://github.com/folke/lazy.nvim): | Branch | Code snippet | |--------|-----------------------------------------------| | Main | `{ 'nvim-mini/mini.nvim', version = false },` | | Stable | `{ 'nvim-mini/mini.nvim', version = '*' },` | - With [junegunn/vim-plug](https://github.com/junegunn/vim-plug): | Branch | Code snippet | |--------|------------------------------------------------------| | Main | `Plug 'nvim-mini/mini.nvim'` | | Stable | `Plug 'nvim-mini/mini.nvim', { 'branch': 'stable' }` | - Every module is also distributed as a standalone Git repository. Check out module's information for more details. **Important**: don't forget to call module's `setup()` (if required) to enable its functionality. **Note**: if you are on Windows, there might be problems with too long file paths (like `error: unable to create file : Filename too long`). Try doing one of the following: - Enable corresponding git global config value: `git config --system core.longpaths true`. Then try to reinstall. - Install plugin in other place with shorter path. ## Modules 'mini.nvim' contains many modules which is slightly daunting at first. All of them can be used independently, one at a time. For easier exploration, here they are presented in groups based on module's primary functionality (although some modules can fit in several groups). See more detailed listing [here](doc/mini-nvim.txt). ### Text editing These modules improve your text editing experience. Start with 'mini.ai', 'mini.operators', and 'mini.surround'. | Module | Description | Overview | Details | |-----------------|---------------------------------------|--------------------------------------|------------------------------------------| | mini.ai | Extend and create `a`/`i` textobjects | [README](readmes/mini-ai.md) | [Documentation](doc/mini-ai.txt) | | mini.align | Align text interactively | [README](readmes/mini-align.md) | [Documentation](doc/mini-align.txt) | | mini.comment | Comment lines | [README](readmes/mini-comment.md) | [Documentation](doc/mini-comment.txt) | | mini.completion | Completion and signature help | [README](readmes/mini-completion.md) | [Documentation](doc/mini-completion.txt) | | mini.keymap | Special key mappings | [README](readmes/mini-keymap.md) | [Documentation](doc/mini-keymap.txt) | | mini.move | Move any selection in any direction | [README](readmes/mini-move.md) | [Documentation](doc/mini-move.txt) | | mini.operators | Text edit operators | [README](readmes/mini-operators.md) | [Documentation](doc/mini-operators.txt) | | mini.pairs | Autopairs | [README](readmes/mini-pairs.md) | [Documentation](doc/mini-pairs.txt) | | mini.snippets | Manage and expand snippets | [README](readmes/mini-snippets.md) | [Documentation](doc/mini-snippets.txt) | | mini.splitjoin | Split and join arguments | [README](readmes/mini-splitjoin.md) | [Documentation](doc/mini-splitjoin.txt) | | mini.surround | Surround actions | [README](readmes/mini-surround.md) | [Documentation](doc/mini-surround.txt) | ### General workflow These modules improve your general workflow. Start with 'mini.bracketed', 'mini.files', and 'mini.pick'. | Module | Description | Overview | Details | |----------------|------------------------------------------|-------------------------------------|-----------------------------------------| | mini.basics | Common configuration presets | [README](readmes/mini-basics.md) | [Documentation](doc/mini-basics.txt) | | mini.bracketed | Go forward/backward with square brackets | [README](readmes/mini-bracketed.md) | [Documentation](doc/mini-bracketed.txt) | | mini.bufremove | Remove buffers | [README](readmes/mini-bufremove.md) | [Documentation](doc/mini-bufremove.txt) | | mini.clue | Show next key clues | [README](readmes/mini-clue.md) | [Documentation](doc/mini-clue.txt) | | mini.cmdline | Command line tweaks | [README](readmes/mini-cmdline.md) | [Documentation](doc/mini-cmdline.txt) | | mini.deps | Plugin manager | [README](readmes/mini-deps.md) | [Documentation](doc/mini-deps.txt) | | mini.diff | Work with diff hunks | [README](readmes/mini-diff.md) | [Documentation](doc/mini-diff.txt) | | mini.extra | Extra 'mini.nvim' functionality | [README](readmes/mini-extra.md) | [Documentation](doc/mini-extra.txt) | | mini.files | Navigate and manipulate file system | [README](readmes/mini-files.md) | [Documentation](doc/mini-files.txt) | | mini.git | Git integration | [README](readmes/mini-git.md) | [Documentation](doc/mini-git.txt) | | mini.jump | Jump to next/previous single character | [README](readmes/mini-jump.md) | [Documentation](doc/mini-jump.txt) | | mini.jump2d | Jump within visible lines | [README](readmes/mini-jump2d.md) | [Documentation](doc/mini-jump2d.txt) | | mini.misc | Miscellaneous functions | [README](readmes/mini-misc.md) | [Documentation](doc/mini-misc.txt) | | mini.pick | Pick anything | [README](readmes/mini-pick.md) | [Documentation](doc/mini-pick.txt) | | mini.sessions | Session management | [README](readmes/mini-sessions.md) | [Documentation](doc/mini-sessions.txt) | | mini.visits | Track and reuse file system visits | [README](readmes/mini-visits.md) | [Documentation](doc/mini-visits.txt) | ### Appearance These modules improve your Neovim appearance. Start with 'mini.hues', 'mini.icons', and 'mini.statusline'. | Module | Description | Overview | Details | |------------------|--------------------------------------|---------------------------------------|-------------------------------------------| | mini.animate | Animate common Neovim actions | [README](readmes/mini-animate.md) | [Documentation](doc/mini-animate.txt) | | mini.base16 | Base16 colorscheme creation | [README](readmes/mini-base16.md) | [Documentation](doc/mini-base16.txt) | | mini.colors | Tweak and save any color scheme | [README](readmes/mini-colors.md) | [Documentation](doc/mini-colors.txt) | | mini.cursorword | Autohighlight word under cursor | [README](readmes/mini-cursorword.md) | [Documentation](doc/mini-cursorword.txt) | | mini.hipatterns | Highlight patterns in text | [README](readmes/mini-hipatterns.md) | [Documentation](doc/mini-hipatterns.txt) | | mini.hues | Generate configurable color scheme | [README](readmes/mini-hues.md) | [Documentation](doc/mini-hues.txt) | | mini.icons | Icon provider | [README](readmes/mini-icons.md) | [Documentation](doc/mini-icons.txt) | | mini.indentscope | Visualize and work with indent scope | [README](readmes/mini-indentscope.md) | [Documentation](doc/mini-indentscope.txt) | | mini.map | Window with buffer text overview | [README](readmes/mini-map.md) | [Documentation](doc/mini-map.txt) | | mini.notify | Show notifications | [README](readmes/mini-notify.md) | [Documentation](doc/mini-notify.txt) | | mini.starter | Start screen | [README](readmes/mini-starter.md) | [Documentation](doc/mini-starter.txt) | | mini.statusline | Statusline | [README](readmes/mini-statusline.md) | [Documentation](doc/mini-statusline.txt) | | mini.tabline | Tabline | [README](readmes/mini-tabline.md) | [Documentation](doc/mini-tabline.txt) | | mini.trailspace | Trailspace (highlight and remove) | [README](readmes/mini-trailspace.md) | [Documentation](doc/mini-trailspace.txt) | ### Other These modules don't quite fit in any of the previous categories. | Module | Description | Overview | Details | |------------|----------------------------|---------------------------------|-------------------------------------| | mini.doc | Generate Neovim help files | [README](readmes/mini-doc.md) | [Documentation](doc/mini-doc.txt) | | mini.fuzzy | Fuzzy matching | [README](readmes/mini-fuzzy.md) | [Documentation](doc/mini-fuzzy.txt) | | mini.test | Test Neovim plugins | [README](readmes/mini-test.md) | [Documentation](doc/mini-test.txt) | ## General principles ### Design Each module is designed to solve a particular problem targeting balance between feature-richness (handling as many edge-cases as possible) and simplicity of implementation/support. Granted, not all of them ended up with the same balance, but it is the goal nevertheless. ### Independence Modules are independent of each other and can be run without external dependencies. Although some of them may need dependencies for full experience. ### Structure Each module is a submodule for a placeholder "mini" module. So, for example, "surround" module should be referred to as "mini.surround". As later will be explained, this plugin can also be referred to as "MiniSurround". ### Setup - Each module you want to use should be enabled separately with `require().setup({})`. Possibly replace `{}` with your config table or omit altogether to use defaults. You can supply only parts of config, the rest will be inferred from defaults. - Call to module's `setup()` always creates a global Lua object with coherent camel-case name: `require('mini.surround').setup()` creates `_G.MiniSurround`. This allows for a simpler usage of plugin functionality: instead of `require('mini.surround')` use `MiniSurround` (or manually `:lua MiniSurround.*` in command line); available from `v:lua` like `v:lua.MiniSurround`. Considering this, "module" and "Lua object" names can be used interchangeably: 'mini.surround' and 'MiniSurround' will mean the same thing. - Each supplied `config` table is stored in `config` field of global object. Like `MiniSurround.config`. - Values of `config` which affect runtime activity can be changed on the fly to have effect. For example, `MiniSurround.config.n_lines` can be changed during runtime; but changing `MiniSurround.config.mappings` won't have any effect (as mappings are created once during `setup()`). - If module works best with some specific non-default option value, it is set during `setup()`. If the value is not essential to module's functionality, it is done only if user or another plugin hasn't set it beforehand (no matter the value). ### Buffer local configuration Each module can be additionally configured to use certain runtime config settings locally to buffer. See `mini.nvim-buffer-local-config` section in help file for more information. ### Buffer names All module-related buffers are named according to the following format: `mini:///` (forward slashes are used on any platform; `` may be empty). This structure allows creating identifiable, reasonably unique, and useful buffer names. For example, 'mini.files' buffers are created per displayed directory/file with names like `minifiles://10/path/to/displayed/directory`. ### Disabling Each module's core functionality can be disabled globally or locally to buffer. See "Disabling" section in module's help page for more details. See `mini.nvim-disabling-recipes` section in main help file for common recipes. ### Silencing Each module providing non-error feedback (like a reminder to press a key after some idle time in 'mini.ai', 'mini.jump2d', 'mini.surround') can be configured to not do that by setting `config.silent = true` (either inside `setup()` call or on the fly). ### Highlighting Appearance of module's output is controlled by certain set of highlight groups (see `:h highlight-groups`). By default they usually link to some semantically close built-in highlight group and are ensured to be defined after any color scheme takes effect. Use `:highlight` command or `vim.api.nvim_set_hl()` Lua function to customize highlighting. To see a more calibrated look, use 'mini.hues', 'mini.base16', or plugin's color scheme. ### Stability Each module upon release is considered to be relatively stable: both in terms of setup and functionality. Any non-bugfix backward-incompatible change will be released gradually as much as possible. ### Not filetype and language specific Including functionality which needs several filetype/language specific implementations is an explicit no-goal of this project. This is mostly due to the potential increase in maintenance to keep implementation up to date. However, any part which might need filetype/language specific tuning should be designed to allow it by letting user set proper buffer options and/or local configuration. ## Plugin color schemes This plugin comes with several color schemes (all have both dark and light variants). Activate any of them as a regular `colorscheme` (like `:colorscheme miniwinter` or `vim.cmd.colorscheme('miniwinter')`). - Based on ['mini.hues'](readmes/mini-hues.md) (recommended): - `miniwinter`: "icy winter" palette with azure background. - `minispring`: "blooming spring" palette with green background. - `minisummer`: "hot summer" palette with brown/yellow background. - `miniautumn`: "cooling autumn" palette with purple background. - `randomhue`: random background and foreground of the same hue with medium saturation. You can see how they look in ['mini.hues' README](readmes/mini-hues.md#bundled-color-schemes). - Based on ['mini.base16'](readmes/mini-base16.md): - `minicyan`: cyan and grey main colors with medium contrast and saturation palette. - `minischeme`: blue and yellow main colors with high contrast and saturation palette. You can see how they look in ['mini.base16' README](readmes/mini-base16.md#demo). ## Planned modules This is the list of modules I currently intend to implement eventually (as my free time and dedication will allow), in alphabetical order: - 'mini.abbrev' - helper to manage/setup Insert mode abbreviations. - 'mini.cycle' - cycle through alternatives with pre-defined rules. Something like [monaqa/dial.nvim](https://github.com/monaqa/dial.nvim) and [AndrewRadev/switch.vim](https://github.com/AndrewRadev/switch.vim) - 'mini.folds' - more capable and user-friendly folds. - 'mini.repl' - extendable wrapper for REPLs with built-in support for R, Python, Julia, and maybe (just maybe) some AI tools. - 'mini.sendtext' - send text between buffers. In particular between regular and built-in terminal buffers. - 'mini.statuscolumn' - customizable 'statuscolumn'. - 'mini.terminals' - coherently manage interactive terminal buffers. Something like [kassio/neoterm](https://github.com/kassio/neoterm). Might also incorporate functionality to asynchronously run code in shell with post-processed results. - 'mini.quickfix' - more capable and user-friendly quickfix list. Possibly with preview and inline editing for search-and-replace workflow. - 'mini.windows' - window manager. Interactive picker, layout organizer, and maybe more. ================================================ FILE: TESTING.md ================================================ # How to test with 'mini.test' Writing tests for Neovim Lua plugin is hard. Writing good tests for Neovim Lua plugin is even harder. The 'mini.test' module is designed to make it reasonably easier while still allowing lots of flexibility. It deliberately favors a more verbose and program-like style of writing tests, opposite to "human readable, DSL like" approach of [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) ("busted-style testing" from [Olivine-Labs/busted](https://github.com/Olivine-Labs/busted)). Although the latter is also possible. This file is intended as a hands-on introduction to 'mini.test' with examples. For more details, see [its documentation](doc/mini-test.txt) and tests of this plugin's modules. General approach of writing test files: - Organize tests in separate Lua files. - Each file should be associated with a test set table (output of `MiniTest.new_set()`). Recommended approach is to create it manually in each test file and then return it. - Each test action should be defined in separate function assign to an entry of test set. - It is strongly encouraged to use custom Neovim processes to do actual testing inside test action. See [Using child process](#using-child-process). **NOTES**: - All commands are assumed to be executed with current working directory being a root of your Neovim plugin project. That is both for shell and Neovim commands. - All paths are assumed to be relative to current working directory. ## Example plugin In this file we will be testing 'hello_lines' plugin (once some basic concepts are introduced). It will have functionality to add prefix 'Hello ' to lines implemented in a single file 'lua/hello_lines/init.lua':
'lua/hello_lines/init.lua' ```lua local M = {} --- Prepend 'Hello ' to every element ---@param lines table Array. Default: { 'world' }. ---@return table Array of strings. M.compute = function(lines) lines = lines or { 'world' } return vim.tbl_map(function(x) return 'Hello ' .. tostring(x) end, lines) end local ns_id = vim.api.nvim_create_namespace('hello_lines') --- Set lines with highlighted 'Hello ' prefix ---@param buf_id number Buffer handle where lines should be set. Default: 0. ---@param lines table Array. Default: { 'world' }. M.set_lines = function(buf_id, lines) buf_id = buf_id or 0 lines = lines or { 'world' } vim.api.nvim_buf_clear_namespace(buf_id, ns_id, 0, -1) vim.api.nvim_buf_set_lines(buf_id or 0, 0, -1, true, M.compute(lines)) for i = 1, #lines do local extmark_opts = { end_row = i - 1, end_col = 5, hl_group = 'Special' } vim.api.nvim_buf_set_extmark(buf_id, ns_id, i - 1, 0, extmark_opts) end end return M ```
## Quick demo Here is a quick demo of how tests with 'mini.test' look like:
'tests/test_hello_lines.lua' ```lua -- Define helper aliases local new_set = MiniTest.new_set local expect, eq = MiniTest.expect, MiniTest.expect.equality -- Create (but not start) child Neovim object local child = MiniTest.new_child_neovim() -- Define main test set of this file local T = new_set({ -- Register hooks hooks = { -- This will be executed before every (even nested) case pre_case = function() -- Restart child process with custom 'init.lua' script child.restart({ '-u', 'scripts/minimal_init.lua' }) -- Load tested plugin child.lua([[M = require('hello_lines')]]) end, -- This will be executed one after all tests from this set are finished post_once = child.stop, }, }) -- Test set fields define nested structure T['compute()'] = new_set() -- Define test action as callable field of test set. -- If it produces error - test fails. T['compute()']['works'] = function() -- Execute Lua code inside child process, get its result and compare with -- expected result eq(child.lua_get([[M.compute({'a', 'b'})]]), { 'Hello a', 'Hello b' }) end T['compute()']['uses correct defaults'] = function() eq(child.lua_get([[M.compute()]]), { 'Hello world' }) end -- Make parametrized tests. This will create three copies of each case T['set_lines()'] = new_set({ parametrize = { {}, { 0, { 'a' } }, { 0, { 1, 2, 3 } } } }) -- Use arguments from test parametrization T['set_lines()']['works'] = function(buf_id, lines) -- Directly modify some options to make better test child.o.lines, child.o.columns = 10, 20 child.bo.readonly = false -- Execute Lua code without returning value child.lua('M.set_lines(...)', { buf_id, lines }) -- Test screen state. On first run it will automatically create reference -- screenshots with text and look information in predefined location. On -- later runs it will compare current screenshot with reference. Will throw -- informative error with helpful information if they don't match exactly. expect.reference_screenshot(child.get_screenshot()) end -- Return test set which will be collected and execute inside `MiniTest.run()` return T ```
## File organization It might be a bit overwhelming. It actually is for most of the people. However, it should be done once and then you rarely need to touch it. Overview of full file structure used in for testing 'hello_lines' plugin: ``` . ├── deps │ └── mini.nvim # Mandatory ├── lua │ └── hello_lines │ └── init.lua # Mandatory ├── Makefile # Recommended ├── scripts │ ├── minimal_init.lua # Mandatory │ └── minitest.lua # Recommended └── tests └── test_hello_lines.lua # Mandatory ``` To write tests, you'll need these files: Mandatory: - **Your Lua plugin in 'lua' directory**. Here we will be testing 'hello_lines' plugin. - **Test files**. By default they should be Lua files located in 'tests/' directory and named with 'test_' prefix. For example, we will write everything in 'test_hello_lines.lua'. It is usually a good idea to follow this template (will be assumed for the rest of this file):
Template for test files ```lua local new_set = MiniTest.new_set local expect, eq = MiniTest.expect, MiniTest.expect.equality local T = new_set() -- Actual tests definitions will go here return T ```
- **'mini.nvim' dependency**. It is needed to use its 'mini.test' module. Proposed way to store it is in 'deps/mini.nvim' directory. Create it with `git`: ```bash mkdir -p deps git clone --filter=blob:none https://github.com/nvim-mini/mini.nvim deps/mini.nvim ``` - **Manual Neovim startup file** (a.k.a 'init.lua') with proposed path 'scripts/minimal_init.lua'. It will be used to ensure that Neovim processes can recognize your tested plugin and 'mini.nvim' dependency. Proposed minimal content:
'scripts/minimal_init.lua' ```lua -- Add current directory to 'runtimepath' to be able to use 'lua' files vim.cmd([[let &rtp.=','.getcwd()]]) -- Set up 'mini.test' only when calling headless Neovim (like with `make test`) if #vim.api.nvim_list_uis() == 0 then -- Add 'mini.nvim' to 'runtimepath' to be able to use 'mini.test' -- Assumed that 'mini.nvim' is stored in 'deps/mini.nvim' vim.cmd('set rtp+=deps/mini.nvim') -- Set up 'mini.test' require('mini.test').setup() end ```
Recommended: - **Makefile**. In order to simplify running tests from shell and inside Continuous Integration services (like Github Actions), it is recommended to define Makefile. It will define steps for running tests. Proposed template:
Template for Makefile ``` # Run all test files test: deps/mini.nvim nvim --headless --noplugin -u ./scripts/minimal_init.lua -c "lua MiniTest.run()" # Run test from file at `$FILE` environment variable test_file: deps/mini.nvim nvim --headless --noplugin -u ./scripts/minimal_init.lua -c "lua MiniTest.run_file('$(FILE)')" # Download 'mini.nvim' to use its 'mini.test' testing module deps/mini.nvim: @mkdir -p deps git clone --filter=blob:none https://github.com/nvim-mini/mini.nvim $@ ```
- **'mini.test' script** at 'scripts/minitest.lua'. Use it to customize what is tested (which files, etc.) and how. Usually not needed, but otherwise should have some variant of a call to `MiniTest.run()`. ## Running tests The 'mini.test' module out of the box supports two major ways of running tests: - **Interactive**. All test files will be run directly inside current Neovim session. This proved to be very useful for debugging while writing tests. To run tests, simply execute `:lua MiniTest.run()` / `:lua MiniTest.run_file()` / `:lua MiniTest.run_at_location()` (assuming, you already have 'mini.test' set up with `require('mini.test').setup()`). With default configuration this will result into floating window with information about results of test execution. Press `q` to close it. **Note**: Be careful though, as it might affect your current setup. To avoid this, [use child processes](#using-child-process) inside tests. - **Headless** (from shell). Start headless Neovim process with proper startup file and execute `lua MiniTest.run()`. Assuming full file organization from previous section, this can be achieved with `make test`. This will show information about results of test execution directly in shell. ## Basics These sections will show some basic capabilities of 'mini.test' and how to use them. In all examples code blocks represent some whole test file (like 'tests/test_basics.lua'). ### First test A test is defined as function assigned to a field of test set. If it throws error, test has failed. Test file should return single test set. Here is an example: ```lua local T = MiniTest.new_set() T['works'] = function() local x = 1 + 1 if x ~= 2 then error('`x` is not equal to 2') end end return T ``` Writing `if .. error() .. end` is too tiresome. That is why 'mini.test' comes with very minimal but usually quite enough set of *expectations*: `MiniTest.expect`. They display the intended expectation between objects and will throw error with informative message if it doesn't hold. Here is a rewritten previous example: ```lua local T = MiniTest.new_set() T['works'] = function() local x = 1 + 1 MiniTest.expect.equality(x, 2) end return T ``` Test sets can be nested. This will be useful in combination with [hooks](#hooks) and [parametrization](#test-parametrization): ```lua local T = MiniTest.new_set() T['big scope'] = new_set() T['big scope']['works'] = function() local x = 1 + 1 MiniTest.expect.equality(x, 2) end T['big scope']['also works'] = function() local x = 2 + 2 MiniTest.expect.equality(x, 4) end T['out of scope'] = function() local x = 3 + 3 MiniTest.expect.equality(x, 6) end return T ``` **NOTE**: 'mini.test' supports emulation of busted-style testing by default. So previous example can be written like this: ```lua describe('big scope', function() it('works', function() local x = 1 + 1 MiniTest.expect.equality(x, 2) end) it('also works', function() local x = 2 + 2 MiniTest.expect.equality(x, 4) end) end) it('out of scope', function() local x = 3 + 3 MiniTest.expect.equality(x, 6) end) -- NOTE: when using this style, no test set should be returned ``` Although this is possible, the rest of this file will use a recommended test set approach. ### Builtin expectations These four builtin expectations are the ones used most commonly: ```lua local T = MiniTest.new_set() local expect, eq = MiniTest.expect, MiniTest.expect.equality local x = 1 + 1 -- This is so frequently used that having short alias proved useful T['expect.equality'] = function() eq(x, 2) end T['expect.no_equality'] = function() expect.no_equality(x, 1) end T['expect.error'] = function() -- This expectation will pass because function will throw an error expect.error(function() if x == 2 then error('Deliberate error') end end) end T['expect.no_error'] = function() -- This expectation will pass because function will *not* throw an error expect.no_error(function() if x ~= 2 then error('This should not be thrown') end end) end return T ``` ### Writing custom expectation Although you can use `if ... error() ... end` approach, there is `MiniTest.new_expectation()` to simplify this process for some repetitive expectation. Here is an example used in this plugin: ```lua local T = MiniTest.new_set() local expect_match = MiniTest.new_expectation( -- Expectation subject 'string matching', -- Predicate function(str, pattern) return str:find(pattern) ~= nil end, -- Fail context function(str, pattern) return string.format('Pattern: %s\nObserved string: %s', vim.inspect(pattern), str) end ) T['string matching'] = function() local x = 'abcd' -- This will pass expect_match(x, '^a') -- This will fail expect_match(x, 'x') end return T ``` Executing this content from file 'tests/test_basics.lua' will fail with the following message: ``` FAIL in "tests/test_basics.lua | string matching": Failed expectation for string matching. Pattern: "x" Observed string: abcd Traceback: tests/test_basics.lua:20 ``` ### Hooks Hooks are functions that will be called without arguments at predefined stages of test execution. They are defined for a test set. There are four types of hooks: - **pre_once** - executed before first (filtered) node. - **pre_case** - executed before each case (even nested). - **post_case** - executed after each case (even nested). - **post_once** - executed after last (filtered) node. Example: ```lua local new_set = MiniTest.new_set local expect, eq = MiniTest.expect, MiniTest.expect.equality local T = new_set() local n = 0 local increase_n = function() n = n + 1 end T['hooks'] = new_set({ hooks = { pre_once = increase_n, pre_case = increase_n, post_case = increase_n, post_once = increase_n }, }) T['hooks']['work'] = function() -- `n` will be increased twice: in `pre_once` and `pre_case` eq(n, 2) end T['hooks']['work again'] = function() -- `n` will be increased twice: in `post_case` from previous case and -- `pre_case` before this one eq(n, 4) end T['after hooks set'] = function() -- `n` will be again increased twice: in `post_case` from previous case and -- `post_once` after last case in T['hooks'] test set eq(n, 6) end return T ``` ### Test parametrization One of the distinctive features of 'mini.test' is ability to leverage test parametrization. As hooks, it is a feature of test set. Example of simple parametrization: ```lua local new_set = MiniTest.new_set local eq = MiniTest.expect.equality local T = new_set() -- Each parameter should be an array to allow parametrizing multiple arguments T['parametrize'] = new_set({ parametrize = { { 1 }, { 2 } } }) -- This will result into two cases. First will fail. T['parametrize']['works'] = function(x) eq(x, 2) end -- Parametrization can be nested. Cases are "multiplied" with every combination -- of parameters. T['parametrize']['nested'] = new_set({ parametrize = { { '1' }, { '2' } } }) -- This will result into four cases. Two of them will fail. T['parametrize']['nested']['works'] = function(x, y) eq(tostring(x), y) end -- Parametrizing multiple arguments T['parametrize multiple arguments'] = new_set({ parametrize = { { 1, 1 }, { 2, 2 } } }) -- This will result into two cases. Both will pass. T['parametrize multiple arguments']['works'] = function(x, y) eq(x, y) end return T ``` ### Retry Some tests can be inherently flaky (can randomly fail even if its tested feature is correct). For example, testing that sequence of events is executed with correct delay between each other. Such tests can work reliably on fast machines, but can spuriously fail on slow ones (like during Continuous Integrations checks) while underlying feature is correct. To reduce flakiness, there is a feature of test set called `n_retry`: a maximum number of times to retry each its test case until success. Example of how it can be used: ```lua local new_set = MiniTest.new_set local T = new_set() -- Each case will be attempted until first success at most 5 times T['n_retry'] = new_set({ n_retry = 5 }) -- With default `n_retry = 1` this case will fail 1 out of 2 runs. -- With `n_retry = 5` this case will fail 1 out of 32 runs. T['n_retry']['case'] = function() math.randomseed(vim.loop.hrtime()) assert(math.random() < 0.5) end return T ``` ### Runtime access to current cases There is `MiniTest.current` table containing information about "current" test cases. It has `all_cases` and `case` fields with all currently executed tests and *the* current case. Test case is a single unit of sequential test execution. It contains all information needed to execute test case along with data about its execution. Example: ```lua local new_set = MiniTest.new_set local eq = MiniTest.expect.equality local T = new_set() T['MiniTest.current.all_cases'] = function() -- A useful hack: show runtime data with expecting it to be something else eq(MiniTest.current.all_cases, 0) end T['MiniTest.current.case'] = function() eq(MiniTest.current.case, 0) end return T ``` This will result into following lengthy fails:
Fail information ``` FAIL in "tests/test_basics.lua | MiniTest.current.all_cases": Failed expectation for equality. Left: { { args = {}, data = {}, desc = { "tests/test_basics.lua", "MiniTest.current.all_cases" }, exec = { fails = {}, notes = {}, state = "Executing test" }, hooks = { post = {}, pre = {} }, test = }, { args = {}, data = {}, desc = { "tests/test_basics.lua", "MiniTest.current.case" }, hooks = { post = {}, pre = {} }, test = } } Right: 0 Traceback: tests/test_basics.lua:8 FAIL in "tests/test_basics.lua | MiniTest.current.case": Failed expectation for equality. Left: { args = {}, data = {}, desc = { "tests/test_basics.lua", "MiniTest.current.case" }, exec = { fails = {}, notes = {}, state = "Executing test" }, hooks = { post = {}, pre = {} }, test = } Right: 0 Traceback: tests/test_basics.lua:12 ```
### Case helpers There are some functions intended to help writing more robust cases: `skip()`, `finally()`, and `add_note()`. The `MiniTest.current` table contains useful information about the current state of tests execution. Example: ```lua local T = MiniTest.new_set() -- `MiniTest.skip()` allows skipping rest of test execution while giving an -- informative note. This test will pass with notes. T['skip()'] = function() if 1 + 1 == 2 then MiniTest.skip('Apparently, 1 + 1 is 2') end error('1 + 1 is not 2') end -- `MiniTest.add_note()` allows adding notes. Final state will have -- "with notes" suffix. T['add_note()'] = function() MiniTest.add_note('This test is not important.') error('Custom error.') end -- `MiniTest.finally()` allows registering some function to be executed after -- this case is finished executing (with or without an error). T['finally()'] = function() -- Add note only if test fails MiniTest.finally(function() if #MiniTest.current.case.exec.fails > 0 then MiniTest.add_note('This test is flaky.') end end) error('Expected error from time to time') end return T ``` This will result into following messages: ``` NOTE in "tests/test_basics.lua | skip()": Apparently, 1 + 1 is 2 FAIL in "tests/test_basics.lua | add_note()": tests/test_basics.lua:16: Custom error. NOTE in "tests/test_basics.lua | add_note()": This test is not important. FAIL in "tests/test_basics.lua | finally()": tests/test_basics.lua:28: Expected error from time to time NOTE in "tests/test_basics.lua | finally()": This test is flaky. ``` ## Customizing test run Test run consists from two stages: - **Collection**. It will source each appropriate file (customizable), combine all test sets into single test set, convert it from hierarchical to sequential form (array of test cases), and filter cases based on customizable predicate. - **Execution**. It will safely execute array of test cases (with each pre-hooks, test action, post-hooks) one after another in scheduled asynchronous fashion while collecting information about how it went and calling customizable reporter methods. All configuration goes into `opts` argument of `MiniTest.run()`. ### Collection: custom files and filter You can customize which files will be sourced and which cases will be later executed. Example: ```lua local new_set = MiniTest.new_set local T = new_set() -- Use `data` field to pass custom information for easier test management T['fast'] = new_set({ data = { type = 'fast' } }) T['fast']['first test'] = function() end T['fast']['second test'] = function() end T['slow'] = new_set({ data = { type = 'slow' } }) T['slow']['first test'] = function() vim.loop.sleep(1000) end T['slow']['second test'] = function() vim.loop.sleep(1000) end return T ``` You can run only this file ('tests/test_basics.lua') and only "fast" cases with this call: ```lua MiniTest.run({ collect = { find_files = function() return { 'tests/test_basics.lua' } end, filter_cases = function(case) return case.data.type == 'fast' end, } }) ``` ### Execution: custom reporter and stop on first error You can customize execution of test cases with custom reporter (how test results are displayed in real time) and whether to stop execution after the first test case fail/error. Execution doesn't result into any output, instead it updates `MiniTest.current.all_cases` in place: each case gets an `exec` field with information about how its execution went. Example of showing status summary table in the command line after everything is finished: ```lua local reporter = { -- Other used methods are `start(cases)` and `update(case_num)` finish = function() local summary = {} for _, c in ipairs(MiniTest.current.all_cases) do local state = c.exec.state summary[state] = (summary[state] or 0) + 1 end print(vim.inspect(summary, { newline = ' ', indent = '' })) end, } MiniTest.run({ execute = { reporter = reporter } }) ``` ## Using child process Main feature of 'mini.test' which makes it different from other Lua testing frameworks is its design towards **custom usage of child Neovim process inside tests**. Ultimately, each test should be done with fresh Neovim process initialized with bare minimum setup (like allowing to load your plugin). To make this easier, there is a dedicated function `MiniTest.new_child_neovim()`. It returns an object with many useful helper methods, like for start/stop/restart, redirected execution (write code in current process, it gets executed in child one), emulating typing keys, **testing screen state**, etc. ### Start/stop/restart You can start/stop/restart child process associated with this child Neovim object. Current (from which testing is initiated) and child Neovim processes can "talk" to each through RPC messages (see `:h RPC`). It means you can programmatically execute code inside child process, get its output inside current process, and test if it meets your expectation. Child process is headless but fully functioning process which allows you to test things such as extmarks, floating windows, etc. Although this approach proved to be useful and efficient, it is not ideal. Here are some limitations: - Due to current RPC protocol implementation functions and userdata can't be used in both input and output with child process. Indicator of this issue is a `Cannot convert given lua type` error. Usual solution is to move some logic on the side of child process, like create and use global functions (note that they will be "forgotten" after next restart). - Sometimes hanging process will occur: it stops executing without any output. Most of the time it is because Neovim process is "blocked", i.e. it waits for user input and won't return from other call. Common causes are active hit-enter-prompt (solution: increase prompt height to a bigger value) or Operator-pending mode (solution: exit it). To mitigate this experience, most helper methods will throw an error if they can deduce that immediate execution will lead to hanging state. Here is recommended setup for managing child processes. It will make fresh Neovim process before every test case: ```lua local child = MiniTest.new_child_neovim() local T = MiniTest.new_set({ hooks = { pre_case = function() -- Restart child process with custom 'init.lua' script child.restart({ '-u', 'scripts/minimal_init.lua' }) -- Load tested plugin child.lua([[M = require('hello_lines')]]) end, -- Stop once all test cases are finished post_once = child.stop, }, }) -- Define some tests here return T ``` ### Executing Lua code Previous section already demonstrated that there is a `child.lua()` method. It will execute arbitrary Lua code in the form of a single string. This is basically a wrapper for `vim.api.nvim_exec_lua()`. There is also a convenience wrapper `child.lua_get()` which is essentially a `child.lua('return ' .. s, ...)`. Examples: ```lua local eq = MiniTest.expect.equality local child = MiniTest.new_child_neovim() local T = MiniTest.new_set({ hooks = { pre_case = function() child.restart({ '-u', 'scripts/minimal_init.lua' }) child.lua([[M = require('hello_lines')]]) end, post_once = child.stop, }, }) T['lua()'] = MiniTest.new_set() T['lua()']['works'] = function() child.lua('_G.n = 0; _G.n = _G.n + 1') eq(child.lua('return _G.n'), 1) end T['lua()']['can use tested plugin'] = function() eq(child.lua('return M.compute()'), { 'Hello world' }) eq(child.lua([[return M.compute({'a', 'b'})]]), { 'Hello a', 'Hello b' }) end T['lua_get()'] = function() child.lua('_G.n = 0') eq(child.lua_get('_G.n'), child.lua('return _G.n')) end return T ``` ### Managing Neovim options and state Although ability to execute arbitrary Lua code is technically enough to write any tests, it gets cumbersome very quickly due it using only string input. That is why there are many convenience helpers with the same idea: write code inside current Neovim process that will be automatically executed same way in child process. Here is the showcase: ```lua local new_set = MiniTest.new_set local eq = MiniTest.expect.equality local child = MiniTest.new_child_neovim() local T = MiniTest.new_set({ hooks = { pre_case = function() child.restart({ '-u', 'scripts/minimal_init.lua' }) child.lua([[M = require('hello_lines')]]) end, post_once = child.stop, }, }) -- These methods will "redirect" execution to child through `vim.rpcrequest()` -- and `vim.rpcnotify()` respectively. Any call `child.api.xxx(...)` returns -- the output of `vim.api.xxx(...)` executed inside child process. T['api()/api_notify()'] = function() -- Set option. For some reason, first buffer is 'readonly' which leads to -- high delay in test execution child.api.nvim_set_option_value('readonly', false, { buf = 0 }) -- Set all lines child.api.nvim_buf_set_lines(0, 0, -1, true, { 'aaa' }) -- Get all lines and test with expected ones eq(child.api.nvim_buf_get_lines(0, 0, -1, true), { 'aaa' }) end -- Execute Vimscript with or without capturing its output T['cmd()/cmd()'] = function() child.cmd('hi Comment guifg=#aaaaaa') eq(child.cmd_capture('hi Comment'), 'Comment xxx guifg=#aaaaaa') end -- There are redirection tables for most of the main Neovim functionality T['various redirection tables with methods'] = function() eq(child.fn.fnamemodify('hello_lines.lua', ':t:r'), 'hello_lines') eq(child.loop.hrtime() > 0, true) eq(child.lsp.get_clients(), {}) -- And more end -- There are redirection tables for scoped (buffer, window, etc.) variables -- You can use them to both set and get values T['redirection tables for variables'] = function() child.b.aaa = true eq(child.b.aaa, true) eq(child.b.aaa, child.lua_get('vim.b.aaa')) end -- There are redirection tables for scoped (buffer, window, etc.) options -- You can use them to both set and get values T['redirection tables for options'] = function() child.o.lines, child.o.columns = 5, 12 eq(child.o.lines, 5) eq({ child.o.lines, child.o.columns }, child.lua_get('{ vim.o.lines, vim.o.columns }')) end return T ``` ### Emulate typing keys Very important part of testing is emulating user typing keys. There is a special `child.type_keys()` helper method for that. Examples: ```lua local eq = MiniTest.expect.equality local child = MiniTest.new_child_neovim() local T = MiniTest.new_set({ hooks = { pre_case = function() child.restart({ '-u', 'scripts/minimal_init.lua' }) child.bo.readonly = false child.lua([[M = require('hello_lines')]]) end, post_once = child.stop, }, }) local get_lines = function() return child.api.nvim_buf_get_lines(0, 0, -1, true) end T['type_keys()'] = MiniTest.new_set() T['type_keys()']['works'] = function() -- It can take one string child.type_keys('iabcde') eq(get_lines(), { 'abcde' }) eq(child.fn.mode(), 'n') -- Or several strings which improves readability child.type_keys('cc', 'fghij', '') eq(get_lines(), { 'fghij' }) -- Or tables of strings (possibly nested) child.type_keys({ 'cc', { 'j', 'k', 'l', 'm', 'n' } }) eq(get_lines(), { 'jklmn' }) end T['type_keys()']['allows custom delay'] = function() -- This adds delay of 500 ms after each supplied string (three times here) child.type_keys(500, 'i', 'abcde', '') eq(get_lines(), { 'abcde' }) end return T ``` ### Test screen state with screenshots One of the main difficulties in testing Neovim plugins is verifying that something is actually displayed in the way you intend. Like general highlighting, statusline, tabline, sign column, extmarks, etc. Testing screen state with screenshots makes this a lot easier. There is a `child.get_screenshot()` method which basically calls `screenstring()` (`:h screenstring()`) and `screenattr()` (`:h screenattr()`) for every visible cell (row from 1 to 'lines' option, column from 1 to 'columns' option). It then returns screenshot with two layers: - `text` - "2d array" (row-column) of single characters displayed at particular cells. - `attr` - "2d array" (row-column) of symbols representing how text is displayed (basically, "coded" appearance/highlighting). They should be used only in relation to each other: same/different symbols for two cells mean same/different visual appearance. Note: there will be false positives if there are more than 94 different attribute values. To make output more portable and visually useful, outputs of `screenattr()` are coded with single character symbols. Couple of caveats: - As is apparent from use of `screenattr()`, these screenshots **can't tell how exactly cell is highlighted**, only **if two cells are highlighted the same**. This is due to the currently lacking functionality in Neovim itself. This might change in the future. To help manage testing screen state, there is a special `MiniTest.expect.reference_screenshot(screenshot, path, opts)` method. It takes screenshot table along with optional path of where to save this screenshot (if not supplied, inferred from test case description and put in 'tests/screenshots' directory). On first run it will automatically create reference screenshot at `path`. On later runs it will compare current screenshot with reference. Will throw informative error with helpful information if they don't match exactly. Example: ```lua local expect = MiniTest.expect local child = MiniTest.new_child_neovim() local T = MiniTest.new_set({ hooks = { pre_case = function() child.restart({ '-u', 'scripts/minimal_init.lua' }) child.bo.readonly = false child.lua([[M = require('hello_lines')]]) end, post_once = child.stop, }, }) T['set_lines()'] = MiniTest.new_set({ parametrize = { {}, { 0, { 'a' } }, { 0, { 1, 2, 3 } } } }) T['set_lines()']['works'] = function(buf_id, lines) child.o.lines, child.o.columns = 10, 15 child.lua('M.set_lines(...)', { buf_id, lines }) expect.reference_screenshot(child.get_screenshot()) end return T ``` This will result into three files in 'tests/screenshots' with names containing test case description along with supplied arguments. Here is example reference screenshot for `{ 0, { 1, 2, 3 } }` arguments (line numbers and ruler for columns is added as file specification to make it easier to find differences between two screenshots): ``` --|---------|----- 01|Hello 1 02|Hello 2 03|Hello 3 04|~ 05|~ 06|~ 07|~ 08|~ 09|`) corresponding to benchmarked setup. Configuration files are created in three different groups: - 'init_starter-default.lua' and 'init_empty.lua' represent default 'mini.starter' setup and corresponding 'init.lua' without 'mini.starter'. - 'init_startify-starter', 'init_startify-original', and 'init_startify-alpha' have comparable output imitating default 'vim-startify' with empty header. - 'init_dashboard-starter', 'init_dashboard-original', and 'init_dashboard-alpha' have comparable output imitating default 'dashboard-nvim' enabled keybindings. Summary of startup-times for various 'init' files from 'init-files/' directory can be seen in 'startup-summary.md'. Current benchmark was done with Neovim 0.5.1 on Ubuntu 18.04 (i3-6100). Exact states of plugins used: - [nvim-mini/mini.nvim](https://github.com/nvim-mini/mini.nvim/tree/cfa108eeaead1abd8854a1f1cfb02e72482641ce) - [mhinz/vim-startify](https://github.com/mhinz/vim-startify/tree/81e36c352a8deea54df5ec1e2f4348685569bed2) - [glepnir/dashboard-nvim](https://github.com/glepnir/dashboard-nvim/tree/ba98ab86487b8eda3b0934b5423759944b5f7ebd) - [goolord/alpha-nvim](https://github.com/goolord/alpha-nvim/tree/7a49086bf9197f573b396d4ac46262c02dfb9aec) To rerun locally execute these commands (preferably without anything else running in the background and monitor always on): ```bash chmod +x install.sh ./install.sh # This will create file 'startup-times.csv' and update 'startup-summary.md' # WARNING: this will lead to screen flicker chmod +x benchmark.sh ./benchmark.sh ``` Structure: - 'init-files/' - directory with all configuration files being benchmarked. NOTE: all of them contain auto-closing command at the end (`defer_fn(...)`) to most accurately measure startup time. To view its output, remove this command. - 'benchmark.sh' - script for performing benchmark which is as close to real-world usage as reasonably possible and computing its summary. Its outputs are 'startup-times.csv' and 'startup-summary.md'. All configuration files are benchmarked in alternate fashion: first 'init' file, second, ..., last, first, etc. WARNING: EXECUTION OF THIS SCRIPT LEADS TO MONITOR FLICKERING WHICH MAY CAUSE HARM TO YOUR HEALTH. This is needed to ensure that Neovim was actually opened and something was drawn. - 'install.sh' - script for installing all required plugins. NOTE: run `chmod +x install.sh` to make it executable. - 'make_summary.py' - Python script to compute summary statistics of csv-file. - 'startup-times.csv' (ignored by Git, latest one can be seen in [this gist](https://gist.github.com/echasnovski/85c334396df6fd0cea7bb42246efb97b)) - csv-file with measured startup times. Each row represent single startup round: when all 'init' files are run alternately. Each column represents startup times of single 'init' file. - 'startup-summary.md' - markdown file as output of 'make_summary.py'. Contains summaries of 'startup-times.csv'. ================================================ FILE: benchmarks/starter/benchmark.sh ================================================ #! /bin/bash # Perform benchmarking of startup times with different Neovim 'init' files. # Execute `nvim -u <*> --startuptime <*>` several times (as closely to actual # usage as possible) in rounds alternating between input 'init' files (to "mix" # possible random noise). Store output in .csv file with rows containing # startup times for a single round, columns - for a single 'init' file. # WARNING: EXECUTION OF THIS SCRIPT LEADS TO FLICKERING OF SCREEN WHICH WHICH # MAY CAUSE HARM TO YOUR HEALTH. This is because every 'init' file leads to an # actual opening of Neovim with later automatic closing. # Number of rounds to perform benchmark n_rounds=1000 # Path to output .csv file with startup times per round csv_file=startup-times.csv # Path to output .md file with summary table summary_file=startup-summary.md # 'Init' files ids with actual paths computed as 'init-files/init_*.lua' init_files=(starter-default empty startify-starter startify-original startify-alpha dashboard-starter dashboard-original dashboard-alpha) function comma_join { local IFS=","; shift; echo "$*"; } function benchmark { rm -f "$csv_file" touch "$csv_file" local tmp_bench_file="tmp-bench.txt" touch "$tmp_bench_file" comma_join -- "$@" >> startup-times.csv for i in $(seq 1 $n_rounds); do echo "Round $i" local bench_times=() for init_file in "$@"; do nvim -u "init-files/init_$init_file.lua" --startuptime "$tmp_bench_file" local b_time=$(tail -n 1 "$tmp_bench_file" | cut -d " " -f1) bench_times=("${bench_times[@]}" "$b_time") done comma_join -- "${bench_times[@]}" >> "$csv_file" rm "$tmp_bench_file" done } benchmark "${init_files[@]}" # Produce output summary ./make_summary.py "${csv_file}" "${summary_file}" ================================================ FILE: benchmarks/starter/init-files/init_dashboard-alpha.lua ================================================ vim.cmd([[set packpath=/tmp/nvim/site]]) vim.cmd([[packadd alpha-nvim]]) local alpha = require('alpha') local dashboard = require('alpha.themes.dashboard') alpha.setup(dashboard.opts) vim.g.mapleader = ' ' -- Some of these keybindings doesn't exactly match with what is shown in -- buffer, but this doesn't really matter. Main point is that some keybindings -- should be pre-made. vim.api.nvim_set_keymap('n', 'ff', ':Telescope find_files', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', 'fh', ':Telescope oldfiles', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', 'fr', ':Telescope jumplist', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', 'fg', ':Telescope live_grep', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', 'fm', ':Telescope marks', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', 'sl', ':Telescope command_history', { noremap = true, silent = true }) -- Close Neovim just after fully opening it. Randomize to make "more real". vim.defer_fn(function() vim.cmd([[quit]]) end, 100 + 200 * math.random()) ================================================ FILE: benchmarks/starter/init-files/init_dashboard-original.lua ================================================ vim.cmd([[set packpath=/tmp/nvim/site]]) vim.cmd([[packadd dashboard-nvim]]) vim.g.mapleader = ' ' vim.g.dashboard_default_executive = 'telescope' vim.api.nvim_set_keymap('n', 'ss', ':SessionSave', {}) vim.api.nvim_set_keymap('n', 'sl', ':SessionLoad', {}) vim.api.nvim_set_keymap('n', 'fh', ':DashboardFindHistory', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', 'ff', ':DashboardFindFile', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', 'tc', ':DashboardChangeColorscheme', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', 'fa', ':DashboardFindWord', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', 'fb', ':DashboardJumpMark', { noremap = true, silent = true }) vim.api.nvim_set_keymap('n', 'cn', ':DashboardNewFile', { noremap = true, silent = true }) -- Close Neovim just after fully opening it. Randomize to make "more real". vim.defer_fn(function() vim.cmd([[quit]]) end, 100 + 200 * math.random()) ================================================ FILE: benchmarks/starter/init-files/init_dashboard-starter.lua ================================================ vim.cmd([[set packpath=/tmp/nvim/site]]) vim.cmd([[packadd mini.nvim]]) local starter = require('mini.starter') starter.setup({ items = { { name = 'Edit file', action = [[enew]], section = 'Actions' }, { name = 'Quit', action = [[quit]], section = 'Actions' }, starter.sections.telescope(), }, content_hooks = { starter.gen_hook.adding_bullet(), starter.gen_hook.aligning('center', 'center'), }, }) -- Close Neovim just after fully opening it. Randomize to make "more real". vim.defer_fn(function() vim.cmd([[quit]]) end, 100 + 200 * math.random()) ================================================ FILE: benchmarks/starter/init-files/init_empty.lua ================================================ vim.cmd([[set packpath=/tmp/nvim/site]]) -- Close Neovim just after fully opening it. Randomize to make "more real". vim.defer_fn(function() vim.cmd([[quit]]) end, 100 + 200 * math.random()) ================================================ FILE: benchmarks/starter/init-files/init_starter-default.lua ================================================ vim.cmd([[set packpath=/tmp/nvim/site]]) vim.cmd([[packadd mini.nvim]]) require('mini.starter').setup() -- Close Neovim just after fully opening it. Randomize to make "more real". vim.defer_fn(function() vim.cmd([[quit]]) end, 100 + 200 * math.random()) ================================================ FILE: benchmarks/starter/init-files/init_startify-alpha.lua ================================================ vim.cmd([[set packpath=/tmp/nvim/site]]) vim.cmd([[packadd alpha-nvim]]) local alpha = require('alpha') local startify = require('alpha.themes.startify') startify.nvim_web_devicons.enabled = false alpha.setup(startify.opts) -- Close Neovim just after fully opening it. Randomize to make "more real". vim.defer_fn(function() vim.cmd([[quit]]) end, 100 + 200 * math.random()) ================================================ FILE: benchmarks/starter/init-files/init_startify-original.lua ================================================ vim.cmd([[set packpath=/tmp/nvim/site]]) vim.cmd([[packadd vim-startify]]) vim.g.startify_custom_header = '' -- Close Neovim just after fully opening it. Randomize to make "more real". vim.defer_fn(function() vim.cmd([[quit]]) end, 100 + 200 * math.random()) ================================================ FILE: benchmarks/starter/init-files/init_startify-starter.lua ================================================ vim.cmd([[set packpath=/tmp/nvim/site]]) vim.cmd([[packadd mini.nvim]]) local starter = require('mini.starter') starter.setup({ evaluate_single = true, items = { starter.sections.builtin_actions(), starter.sections.recent_files(10, false), starter.sections.recent_files(10, true), }, content_hooks = { starter.gen_hook.adding_bullet(), starter.gen_hook.indexing('all', { 'Builtin actions' }), starter.gen_hook.padding(3, 2), }, }) -- Close Neovim just after fully opening it. Randomize to make "more real". vim.defer_fn(function() vim.cmd([[quit]]) end, 100 + 200 * math.random()) ================================================ FILE: benchmarks/starter/install.sh ================================================ #! /bin/bash PLUGINPATH=/tmp/nvim/site/pack/bench/opt rm -rf $PLUGINPATH mkdir -p $PLUGINPATH cd $PLUGINPATH git clone --depth 1 https://github.com/nvim-mini/mini.nvim git clone --depth 1 https://github.com/goolord/alpha-nvim git clone --depth 1 https://github.com/glepnir/dashboard-nvim git clone --depth 1 https://github.com/mhinz/vim-startify ================================================ FILE: benchmarks/starter/make_summary.py ================================================ #!/usr/bin/env python import argparse import csv import statistics def read_csv_columns(csv_path): with open(csv_path, "r") as csvfile: reader = csv.DictReader(csvfile) res = {h: [] for h in reader.fieldnames} for line_dict in reader: for h, val in line_dict.items(): res[h].append(float(val)) return res def summarise_array(x): return { "median": statistics.median(x), "mean": statistics.mean(x), "stdev": statistics.stdev(x), "minimum": min(x), "maximum": max(x), } def save_md_summary(summary, output_path): lines = [] row_names = list(summary.keys()) col_names = ["init file"] + list(summary[row_names[0]].keys()) lines.append(" | ".join(col_names)) lines.append(" | ".join("---" for _ in col_names)) for row_n in row_names: l = [row_n] + [str(round(x, 1)) + 'ms' for x in summary[row_n].values()] lines.append(" | ".join(l)) lines = ["| " + l + " |\n" for l in lines] with open(output_path, "w") as output: for l in lines: output.write(l) def compute_summary(csv_path): columns = read_csv_columns(csv_path) return {h: summarise_array(x) for h, x in columns.items()} def main(): parser = argparse.ArgumentParser() parser.add_argument( "input_csv", help="path to file with startup times in csv format", type=str ) parser.add_argument( "output_md", help="output path where markdown summary table will be written", type=str, ) args = parser.parse_args() save_md_summary(compute_summary(args.input_csv), args.output_md) if __name__ == "__main__": main() ================================================ FILE: benchmarks/starter/startup-summary.md ================================================ | init file | median | mean | stdev | minimum | maximum | | --- | --- | --- | --- | --- | --- | | starter-default | 69.0ms | 70.8ms | 4.3ms | 63.6ms | 82.7ms | | empty | 64.1ms | 65.8ms | 4.3ms | 60.0ms | 79.4ms | | startify-starter | 70.2ms | 71.9ms | 4.5ms | 64.3ms | 85.7ms | | startify-original | 80.3ms | 82.2ms | 4.5ms | 76.4ms | 107.2ms | | startify-alpha | 72.1ms | 73.8ms | 4.3ms | 66.5ms | 86.9ms | | dashboard-starter | 68.4ms | 70.3ms | 4.5ms | 63.3ms | 102.9ms | | dashboard-original | 70.6ms | 72.3ms | 4.4ms | 65.5ms | 99.6ms | | dashboard-alpha | 69.8ms | 71.5ms | 4.4ms | 64.7ms | 97.2ms | ================================================ FILE: colors/miniautumn.lua ================================================ -- "Cooling autumn" -- -- Params for `make_palette` used to make palette (colors in OKLch): -- Dark : bg=15-2-315; fg=85-1-100; saturation=fg:'lowmedium', bg:'medium' -- Light: bg=90-1-315; fg=20-1-100; saturation=fg:'mediumhigh',bg:'high' -- Accent: 'bg' -- -- Notes: -- - Fg hues have different temperature than bg for more contrast. -- They are tweaked to maximize palette's bg colors visibility. -- - Fg is less saturated than spring and summer for "cool" period. -- - Bg is more saturated than fg for more legible diffs. -- - Accent is 'bg' for `make_palette`, but `accent_bg` is set to `red_bg` -- for colorful statusline. -- No `accent='red'` to avoid accent be exactly red: improves legibility -- of diff "delete" color (like in number column with 'mini.diff'). local palette --stylua: ignore if vim.o.background == 'dark' then palette = { bg_edge2 = '#0b060e', bg_edge = '#1a141d', bg = '#262029', bg_mid = '#423b45', bg_mid2 = '#5e5762', fg_edge2 = '#f3f1e9', fg_edge = '#e5e3db', fg = '#d7d5cd', fg_mid = '#b7b5ad', fg_mid2 = '#97958e', accent = '#e4caf1', accent_bg = '#3a0f2f', red = '#f1c6e2', red_bg = '#3a0f2f', orange = '#fac6c1', orange_bg = '#410d0d', yellow = '#efcfab', yellow_bg = '#492c00', green = '#d3daad', green_bg = '#323700', cyan = '#b4e2c7', cyan_bg = '#003c24', azure = '#a7e1e8', azure_bg = '#004b51', blue = '#b8d9fc', blue_bg = '#00284a', purple = '#d7cef9', purple_bg = '#261844', } else palette = { bg_edge2 = '#f8f4fa', bg_edge = '#eeeaf0', bg = '#e5e1e7', bg_mid = '#c5c1c7', bg_mid2 = '#a4a0a6', fg_edge2 = '#0e0d09', fg_edge = '#1f1f1a', fg = '#2f2e29', fg_mid = '#4a4944', fg_mid2 = '#686661', accent = '#431256', accent_bg = '#ffb0e9', red = '#52073f', red_bg = '#ffb0e9', orange = '#5c0207', orange_bg = '#ffaba1', yellow = '#6c4300', yellow_bg = '#ffca87', green = '#4b5400', green_bg = '#ddf069', cyan = '#005e3d', cyan_bg = '#7bffc2', azure = '#006a74', azure_bg = '#7df1ff', blue = '#003b6d', blue_bg = '#92c8ff', purple = '#351962', purple_bg = '#cab3ff', } end require('mini.hues').apply_palette(palette) vim.g.colors_name = 'miniautumn' ================================================ FILE: colors/minicyan.lua ================================================ -- Color scheme 'minicyan' -- Derived from base16 (https://github.com/chriskempson/base16) and -- mini_palette palette generator local use_cterm, palette -- Dark palette is an output of 'MiniBase16.mini_palette': -- - Background '#0A2A2A' (LCh(uv) = 15-10-192) -- - Foreground '#D0D0D0' (Lch(uv) = 83-0-0) -- - Accent chroma 50 if vim.o.background == 'dark' then palette = { base00 = '#0a2a2a', base01 = '#324747', base02 = '#556868', base03 = '#788a8a', base04 = '#bbbbbb', base05 = '#d0d0d0', base06 = '#e6e6e6', base07 = '#fcfcfc', base08 = '#ebcd91', base09 = '#9f8340', base0A = '#209870', base0B = '#82e3ba', base0C = '#bb6d9b', base0D = '#a9d4ff', base0E = '#ffb9e5', base0F = '#598ab9', } use_cterm = { base00 = 235, base01 = 238, base02 = 241, base03 = 102, base04 = 250, base05 = 252, base06 = 254, base07 = 231, base08 = 186, base09 = 136, base0A = 29, base0B = 115, base0C = 132, base0D = 153, base0E = 218, base0F = 67, } end -- Light palette is an 'inverted dark', output of 'MiniBase16.mini_palette': -- - Background '#C0D2D2' (LCh(uv) = 83-10-192) -- - Foreground '#262626' (Lch(uv) = 15-0-0) -- - Accent chroma 80 if vim.o.background == 'light' then palette = { base00 = '#c0d2d2', base01 = '#9badad', base02 = '#778989', base03 = '#546767', base04 = '#353535', base05 = '#262626', base06 = '#181818', base07 = '#040404', base08 = '#402100', base09 = '#855f00', base0A = '#007d3c', base0B = '#003d00', base0C = '#b12985', base0D = '#003fb6', base0E = '#7e0052', base0F = '#006cb4', } use_cterm = { base00 = 252, base01 = 248, base02 = 102, base03 = 241, base04 = 237, base05 = 235, base06 = 234, base07 = 232, base08 = 235, base09 = 94, base0A = 29, base0B = 22, base0C = 126, base0D = 25, base0E = 89, base0F = 25, } end if palette then require('mini.base16').setup({ palette = palette, use_cterm = use_cterm }) vim.g.colors_name = 'minicyan' end ================================================ FILE: colors/minischeme.lua ================================================ -- Color scheme 'minischeme' -- Derived from base16 (https://github.com/chriskempson/base16) and -- mini_palette palette generator local use_cterm, palette -- Dark palette is an output of 'MiniBase16.mini_palette': -- - Background '#112641' (LCh(uv) = 15-20-250) -- - Foreground '#e2e98f' (Lch(uv) = 90-60-90) -- - Accent chroma 75 if vim.o.background == 'dark' then palette = { base00 = '#112641', base01 = '#3a475e', base02 = '#606b81', base03 = '#8691a7', base04 = '#d5dc81', base05 = '#e2e98f', base06 = '#eff69c', base07 = '#fcffaa', base08 = '#ffcfa0', base09 = '#cc7e46', base0A = '#46a436', base0B = '#9ff895', base0C = '#ca6ecf', base0D = '#42f7ff', base0E = '#ffc4ff', base0F = '#00a5c5', } use_cterm = { base00 = 235, base01 = 238, base02 = 242, base03 = 246, base04 = 186, base05 = 186, base06 = 229, base07 = 229, base08 = 223, base09 = 173, base0A = 71, base0B = 156, base0C = 170, base0D = 51, base0E = 189, base0F = 38, } end -- Light palette is an 'inverted dark', output of 'MiniBase16.mini_palette': -- - Background '#e2e5ca' (LCh(uv) = 90-20-90) -- - Foreground '#002a83' (Lch(uv) = 15-60-250) -- - Accent chroma 75 if vim.o.background == 'light' then palette = { base00 = '#e2e5ca', base01 = '#bcbfa4', base02 = '#979a7e', base03 = '#73765a', base04 = '#324490', base05 = '#002a83', base06 = '#0000e4', base07 = '#080500', base08 = '#5e2200', base09 = '#a86400', base0A = '#008818', base0B = '#004500', base0C = '#b34aad', base0D = '#004b76', base0E = '#7d0077', base0F = '#0086ae', } use_cterm = { base00 = 254, base01 = 250, base02 = 246, base03 = 243, base04 = 239, base05 = 18, base06 = 20, base07 = 232, base08 = 52, base09 = 130, base0A = 28, base0B = 22, base0C = 133, base0D = 24, base0E = 90, base0F = 31, } end if palette then require('mini.base16').setup({ palette = palette, use_cterm = use_cterm }) vim.g.colors_name = 'minischeme' end ================================================ FILE: colors/minispring.lua ================================================ -- "Blooming spring" -- -- Params for `make_palette` used to make palette (colors in OKLch): -- Dark : bg=15-3-135; fg=85-1-265; saturation='medium' -- Light: bg=90-1-135; fg=20-1-265; saturation='high' -- Accent: 'bg' -- -- Notes: -- - Fg hues have different temperature than bg for more contrast. -- They are tweaked to maximize palette's bg colors visibility. -- - Accent is 'bg' for `make_palette`, but `accent_bg` is set to `green_bg` -- for colorful statusline. -- No `accent='green'` to avoid accent be exactly green: improves legibility -- of diff "add" color (like in number column with 'mini.diff'). local palette --stylua: ignore if vim.o.background == 'dark' then palette = { bg_edge2 = '#040b02', bg_edge = '#101a0b', bg = '#1c2617', bg_mid = '#374231', bg_mid2 = '#535f4d', fg_edge2 = '#eef1f7', fg_edge = '#e0e3e9', fg = '#d2d5db', fg_mid = '#b2b5bb', fg_mid2 = '#92959b', accent = '#bee2ad', accent_bg = '#00381d', red = '#ffc1bf', red_bg = '#410d12', orange = '#facb9e', orange_bg = '#492900', yellow = '#d8da9d', yellow_bg = '#373700', green = '#abe5be', green_bg = '#00381d', cyan = '#94e5ea', cyan_bg = '#004c4f', azure = '#a9d8ff', azure_bg = '#002d4d', blue = '#d3ccff', blue_bg = '#231946', purple = '#f7c2ea', purple_bg = '#381031', } else palette = { bg_edge2 = '#f3f7f1', bg_edge = '#e9ede7', bg = '#e0e4de', bg_mid = '#c0c4be', bg_mid2 = '#a0a39e', fg_edge2 = '#0b0d11', fg_edge = '#1d1e23', fg = '#2c2e33', fg_mid = '#47494f', fg_mid2 = '#64666c', accent = '#2e5e00', accent_bg = '#80ffb8', red = '#700015', red_bg = '#ffaaa7', orange = '#804c00', orange_bg = '#ffc688', yellow = '#676900', yellow_bg = '#e6ed62', green = '#006d3f', green_bg = '#80ffb8', cyan = '#007f86', cyan_bg = '#72f6ff', azure = '#005085', azure_bg = '#90ccff', blue = '#350775', blue_bg = '#c2b3ff', purple = '#600051', purple_bg = '#ffb2f2', } end require('mini.hues').apply_palette(palette) vim.g.colors_name = 'minispring' ================================================ FILE: colors/minisummer.lua ================================================ -- "Hot summer" -- -- Params for `make_palette` used to make palette (colors in OKLch): -- Dark: bg=15-1-45; fg=85-1-270; saturation=fg:'medium' -- Light: bg=90-1-45; fg=20-1-270; saturation=fg:'high' -- Accent: 'yellow' -- -- Notes: -- - Fg hues have different temperature than bg for more contrast. -- They are tweaked to maximize palette's bg colors visibility. local palette --stylua: ignore if vim.o.background == 'dark' then palette = { bg_edge2 = '#0c0705', bg_edge = '#1b1512', bg = '#27211e', bg_mid = '#433c39', bg_mid2 = '#605855', fg_edge2 = '#eef1f8', fg_edge = '#e0e2e9', fg = '#d2d4db', fg_mid = '#b2b4bb', fg_mid2 = '#93949b', accent = '#f6cc9b', accent_bg = '#492c00', red = '#fac0e4', red_bg = '#3a0f2e', orange = '#ffc1b9', orange_bg = '#410d0c', yellow = '#f6cc9b', yellow_bg = '#492c00', green = '#d1db9f', green_bg = '#313600', cyan = '#a6e5c3', cyan_bg = '#003d26', azure = '#93e4ee', azure_bg = '#004a51', blue = '#acd6ff', blue_bg = '#002649', purple = '#d8caff', purple_bg = '#271844', } else palette = { bg_edge2 = '#fcf4f0', bg_edge = '#f2eae6', bg = '#e9e1dd', bg_mid = '#c9c1bd', bg_mid2 = '#a8a19d', fg_edge2 = '#0b0d11', fg_edge = '#1d1e23', fg = '#2c2e33', fg_mid = '#47494f', fg_mid2 = '#64666c', accent = '#804e00', accent_bg = '#ffc888', red = '#61004f', red_bg = '#ffb2ee', orange = '#700011', orange_bg = '#ffaba5', yellow = '#804e00', yellow_bg = '#ffc888', green = '#636900', green_bg = '#e3ee65', cyan = '#006f44', cyan_bg = '#7fffbd', azure = '#007e87', azure_bg = '#79f4ff', blue = '#004d84', blue_bg = '#91caff', purple = '#370674', purple_bg = '#c5b3ff', } end require('mini.hues').apply_palette(palette) vim.g.colors_name = 'minisummer' ================================================ FILE: colors/miniwinter.lua ================================================ -- "Icy winter" -- -- Params for `make_palette` used to make palette (colors in OKLch): -- Dark: bg=15-3-225; fg=85-1-80; saturation=fg:'lowmedium', bg:'medium' -- Light: bg=90-1-225; fg=20-1-80; saturation=fg:'mediumhigh',bg:'high' -- Accent: 'azure' -- -- Notes: -- - Fg hues have different temperature than bg for more contrast. -- They are tweaked to maximize palette's bg colors visibility. -- - Fg is less saturated than spring and summer for "cool" period. -- - Bg is more saturated than fg for more legible diffs. local palette --stylua: ignore if vim.o.background == 'dark' then palette = { bg_edge2 = '#000f15', bg_edge = '#051a20', bg = '#11262d', bg_mid = '#2c4249', bg_mid2 = '#485f67', fg_edge2 = '#f4f0e9', fg_edge = '#e6e2db', fg = '#d8d4cd', fg_mid = '#b8b4ad', fg_mid2 = '#98948e', accent = '#b3daf9', accent_bg = '#00324f', red = '#fac5c7', red_bg = '#410d14', orange = '#f2ccad', orange_bg = '#492600', yellow = '#d9d8aa', yellow_bg = '#3a3800', green = '#b8e1c1', green_bg = '#003415', cyan = '#a6e1e2', cyan_bg = '#004c4e', azure = '#b3daf9', azure_bg = '#00324f', blue = '#d1cffb', blue_bg = '#211a46', purple = '#edc7e7', purple_bg = '#371134', } else palette = { bg_edge2 = '#eff7fb', bg_edge = '#e5edf1', bg = '#dce4e8', bg_mid = '#bcc4c8', bg_mid2 = '#9ca4a7', fg_edge2 = '#0f0d09', fg_edge = '#211e1a', fg = '#312e29', fg_mid = '#4c4944', fg_mid2 = '#6a6661', accent = '#014772', accent_bg = '#90ceff', red = '#5c0113', red_bg = '#ffaaaa', orange = '#6c3e00', orange_bg = '#ffc488', yellow = '#565600', yellow_bg = '#eaeb5f', green = '#00562e', green_bg = '#83ffb3', cyan = '#016d71', cyan_bg = '#6af9ff', azure = '#014772', azure_bg = '#90ceff', blue = '#301d65', blue_bg = '#beb3ff', purple = '#4f0b46', purple_bg = '#ffb3f6', } end require('mini.hues').apply_palette(palette) vim.g.colors_name = 'miniwinter' ================================================ FILE: colors/randomhue.lua ================================================ local hues = require('mini.hues') -- Generate random config with initialized random seed (otherwise it won't be -- random during startup) math.randomseed(vim.loop.hrtime()) local base_colors = hues.gen_random_base_colors() hues.setup({ background = base_colors.background, foreground = base_colors.foreground, n_hues = 8, saturation = vim.o.background == 'dark' and 'medium' or 'high', accent = 'bg', }) vim.g.colors_name = 'randomhue' ================================================ FILE: doc/mini-ai.txt ================================================ *mini.ai* Extend and create a/i textobjects MIT License Copyright (c) 2022 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniAi* Enhance some builtin |text-objects| (like |a(|, |a)|, |a'|, and more), create new ones (like `a*`, `a`, `af`, `a?`, and more), and allow user to create their own. Features: - Customizable creation of `a`/`i` textobjects using Lua patterns and functions. Supports: - Dot-repeat. - |v:count|. - Different search methods (see |MiniAi.config|). - Consecutive application (update selection without leaving Visual mode). - Aliases for multiple textobjects. - Comprehensive builtin textobjects (see more in |MiniAi-builtin-textobjects|): - Balanced brackets (with and without whitespace) plus alias. - Balanced quotes plus alias. - Function call. - Argument. - Tag. - Derived from user prompt. - Default for anything but Latin letters (to fall back to |text-objects|). For more textobjects see |MiniExtra.gen_ai_spec|. - Motions for jumping to left/right edge of textobject. - Set of specification generators to tweak some builtin textobjects (see |MiniAi.gen_spec|). - Treesitter textobjects (through |MiniAi.gen_spec.treesitter()| helper). This module works by defining mappings for both `a` and `i` in Visual and Operator-pending mode. After typing, they wait for single character user input treated as textobject identifier and apply resolved textobject specification (fall back to other mappings if can't find proper textobject id). For more information see |MiniAi-textobject-specification| and |MiniAi-algorithm|. Known issues which won't be resolved: - Search for builtin textobjects is done mostly using Lua patterns (regex-like approach). Certain amount of false positives is to be expected. - During search for builtin textobjects there is no distinction if it is inside string or comment. For example, in the following case there will be wrong match for a function call: `f(a = ")", b = 1)`. General rule of thumb: any instrument using available parser for document structure (like treesitter) will usually provide more precise results. This module has builtins mostly for plain text textobjects which are useful most of the times (like "inside brackets", "around quotes/underscore", etc.). For advanced use cases define function specification for custom textobjects. What it doesn't (and probably won't) do: - Have special operators to specially handle whitespace (like `I` and `A` in 'targets.vim'). Whitespace handling is assumed to be done inside textobject specification (like `i(` and `i)` handle whitespace differently). # Setup ~ This module needs a setup with `require('mini.ai').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniAi` which you can use for scripting or manually (with `:lua MiniAi.*`). See |MiniAi.config| for available config settings. You can override runtime config settings (like `config.custom_textobjects`) locally to buffer inside `vim.b.miniai_config` which should have same structure as `MiniAi.config`. See |mini.nvim-buffer-local-config| for more details. To stop module from showing non-error feedback, set `config.silent = true`. # Comparisons ~ - [wellle/targets.vim](https://github.com/wellle/targets.vim): - Has limited support for creating own textobjects: it is constrained to pre-defined detection rules. 'mini.ai' allows creating own rules via Lua patterns and functions (see |MiniAi-textobject-specification|). - Doesn't provide any programmatical API for getting information about textobjects. 'mini.ai' does it via |MiniAi.find_textobject()|. - Has no implementation of "moving to edge of textobject". 'mini.ai' does it via |MiniAi.move_cursor()| and `g[` and `g]` default mappings. - Both implement the notion of manual "next"/"last" search directions. - Implements `A`, `I` operators. 'mini.ai' does not by design: it is assumed to be a property of textobject, not operator. - Doesn't implement "function call" and "user prompt" textobjects. 'mini.ai' does (with `f` and `?` identifiers). - Has limited support for "argument" textobject. Although it works in most situations, it often misdetects commas as argument separator (like if it is inside quotes or `{}`). 'mini.ai' deals with these cases. - [nvim-treesitter/nvim-treesitter-textobjects](https://github.com/nvim-treesitter/nvim-treesitter-textobjects): - Along with textobject functionality provides a curated and maintained set of popular textobject queries for many languages (which can power |MiniAi.gen_spec.treesitter()| functionality). - Both support working with |treesitter-directives| allowing more fine-tuned textobjects. - Implements only textobjects based on treesitter. - Doesn't support |v:count|. - Doesn't support multiple search method (basically, only 'cover'). - Doesn't support consecutive application of target textobject. # Disabling ~ To disable, set `vim.g.miniai_disable` (globally) or `vim.b.miniai_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniAi-builtin-textobjects* This table describes all builtin textobjects along with what they represent. Explanation: - `Key` represents the textobject identifier: single character which should be typed after `a`/`i`. - `Name` is a description of textobject. - `Example line` contains a string for which examples are constructed. The `*` denotes the cursor position. - `a`/`i` describe inclusive region representing `a` and `i` textobjects. Use numbers in separators for easier navigation. - `2a`/`2i` describe either `2a`/`2i` (support for |v:count|) textobjects or `a`/`i` textobject followed by another `a`/`i` textobject (consecutive application leads to incremental selection). Example: typing `va)` with cursor on `*` leads to selection from column 2 to column 12. Another typing `a)` changes selection to [1; 13]. Also, besides visual selection, any |operator| can be used or `g[`/`g]` motions to move to left/right edge of `a` textobject. > ┌───┬───────────────┬──────────────────┬────────┬────────┬────────┬────────┐ │Key│ Name │ Example line │ a │ i │ 2a │ 2i │ ├───┴───────────────┴──────────────────┴────────┴────────┴────────┴────────┤ ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈1234567890123456┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ │ ( │ Balanced () │ (( *a (bb) )) │ │ │ │ │ │ [ │ Balanced [] │ [[ *a [bb] ]] │ [2;12] │ [4;10] │ [1;13] │ [2;12] │ │ { │ Balanced {} │ {{ *a {bb} }} │ │ │ │ │ │ < │ Balanced <> │ << *a >> │ │ │ │ │ ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈1234567890123456┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ │ ) │ Balanced () │ (( *a (bb) )) │ │ │ │ │ │ ] │ Balanced [] │ [[ *a [bb] ]] │ │ │ │ │ │ } │ Balanced {} │ {{ *a {bb} }} │ [2;12] │ [3;11] │ [1;13] │ [2;12] │ │ > │ Balanced <> │ << *a >> │ │ │ │ │ │ b │ Alias for │ [( *a {bb} )] │ │ │ │ │ │ │ ), ], or } │ │ │ │ │ │ ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈1234567890123456┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ │ " │ Balanced " │ "*a" " bb " │ │ │ │ │ │ ' │ Balanced ' │ '*a' ' bb ' │ │ │ │ │ │ ` │ Balanced ` │ `*a` ` bb ` │ [1;4] │ [2;3] │ [6;11] │ [7;10] │ │ q │ Alias for │ '*a' " bb " │ │ │ │ │ │ │ ", ', or ` │ │ │ │ │ │ ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈1234567890123456┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ │ ? │ User prompt │ e*e o e o o │ [3;5] │ [4;4] │ [7;9] │ [8;8] │ │ │(typed e and o)│ │ │ │ │ │ ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈1234567890123456┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ │ t │ Tag │ *a │ [4;12] │ [7;8] │ [1;16] │ [4;12] │ ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈1234567890123456┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ │ f │ Function call │ f(a, g(*b, c) ) │ [6;13] │ [8;12] │ [1;15] │ [3;14] │ ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈1234567890123456┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ │ a │ Argument │ f(*a, g(b, c) ) │ [3;5] │ [3;4] │ [5;14] │ [7;13] │ ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈1234567890123456┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ │ │ Default │ aa_*b__cc___ │ [4;7] │ [4;5] │ [8;12] │ [8;9] │ │ │ (typed _) │ │ │ │ │ │ └───┴───────────────┴──────────────────┴────────┴────────┴────────┴────────┘ < Notes: - All examples assume default `config.search_method`. - Open brackets differ from close brackets by how they treat inner edge whitespace for `i` textobject: open ignores it, close - includes. - Default textobject is activated for identifiers which are not Latin letters. They are designed to be treated as separators, so include only right edge in `a` textobject. To include both edges, use custom textobjects (see |MiniAi-textobject-specification| and |MiniAi.config|). Note: - When cursor is exactly on the identifier character while there are two matching candidates on both left and right, the resulting region with smaller width is preferred. ------------------------------------------------------------------------------ *MiniAi-glossary* Note: this is similar to |MiniSurround-glossary|. REGION ~ Table representing region in a buffer. Fields: - and for inclusive start and end positions ( might be `nil` to describe empty region). Each position is also a table with line and column (both start at 1). - for which Visual mode will be used to select textobject. See `opts` argument of |MiniAi.select_textobject()|. One of `'v'`, `'V'`, `'\22'` (escaped `''`). Examples: >lua { from = { line = 1, col = 1 }, to = { line = 2, col = 1 } } -- Forced linewise mode { from = { line = 1, col = 1 }, to = { line = 2, col = 1 }, vis_mode = 'V', } -- Empty region { from = { line = 10, col = 10 } } < PATTERN ~ String describing Lua pattern. SPAN ~ Interval inside a string (end-exclusive). Like [1, 5). Equal `from` and `to` edges describe empty span at that point. Span `A = [a1, a2)` covers `B = [b1, b2)` if every element of `B` is within `A` (`a1 <= b < a2`). It also is described as "B is nested inside A". NESTED PATTERN ~ Array of patterns aimed to describe nested spans. SPAN MATCHES NESTED PATTERN ~ If there is a sequence of consecutively nested spans each matching corresponding pattern within substring of previous span (or input string for first span). Example: >lua -- Nested patterns for balanced `()` with inner space { '%b()', '^. .* .$' } -- Example input string (with columns underneath for easier reading): "( ( () ( ) ) )" -- 12345678901234 < Here are all matching spans [1, 15) and [3, 13). Both [5, 7) and [8, 10) match first pattern but not second. All other combinations of `(` and `)` don't match first pattern (not balanced). COMPOSED PATTERN ~ Array with each element describing possible pattern (or array of them) at that place. Composed pattern basically defines all possible combinations of nested pattern (their cartesian product). Examples: 1. Either balanced `()` or balanced `[]` but both with inner edge space: >lua -- Composed pattern { { '%b()', '%b[]' }, '^. .* .$' } -- Composed pattern expanded into equivalent array of nested patterns { '%b()', '^. .* .$' } -- and { '%b[]', '^. .* .$' } < 2. Either "balanced `()` with inner edge space" or "balanced `[]` with no inner edge space", both with 5 or more characters: >lua -- Composed pattern { { { '%b()', '^. .* .$' }, { '%b[]', '^.[^ ].*[^ ].$' } }, '.....' } -- Composed pattern expanded into equivalent array of nested patterns { '%b()', '^. .* .$', '.....' } -- and { '%b[]', '^.[^ ].*[^ ].$', '.....' } < SPAN MATCHES COMPOSED PATTERN ~ If it matches at least one nested pattern from expanded composed pattern. ------------------------------------------------------------------------------ *MiniAi-textobject-specification* Textobject specification has a structure of composed pattern (see |MiniAi-glossary|) with two differences: - Last pattern(s) should have even number of empty capture groups denoting how the last string should be processed to extract `a` or `i` textobject: - Zero captures mean that whole string represents both `a` and `i`. Example: `xxx` will define textobject matching string `xxx` literally. - Two captures represent `i` textobject inside of them. `a` - whole string. Example: `x()x()x` defines `a` textobject to be `xxx`, `i` - middle `x`. - Four captures define `a` textobject inside captures 1 and 4, `i` - inside captures 2 and 3. Example: `x()()x()x()` defines `a` textobject to be last `xx`, `i` - middle `x`. - Allows callable objects (see |vim.is_callable()|) in certain places (enables more complex textobjects in exchange of increase in configuration complexity and computations): - If specification itself is a callable, it will be called with the same arguments as |MiniAi.find_textobject()| and should return one of: - Composed pattern. Useful for implementing user input. Example of simplified variant of textobject for function call with name taken from user prompt: >lua function() local left_edge = vim.pesc(vim.fn.input('Function name: ')) return { left_edge .. '%b()', '^.-%(().*()%)$' } end < - Single output region. Useful to allow full control over textobject. Will be taken as is. Example of returning whole buffer: >lua function() local from = { line = 1, col = 1 } local to = { line = vim.fn.line('$'), col = math.max(vim.fn.getline('$'):len(), 1) } return { from = from, to = to, vis_mode = 'V' } end < - Array of output region(s). Useful for incorporating other instruments, like treesitter (see |MiniAi.gen_spec.treesitter()|). The best region will be picked in the same manner as with composed pattern (respecting options `n_lines`, `search_method`, etc.). Example of selecting "best" line with display width more than 80: >lua function(_, _, _) local res = {} for i = 1, vim.api.nvim_buf_line_count(0) do local cur_line = vim.fn.getline(i) if vim.fn.strdisplaywidth(cur_line) > 80 then local region = { from = { line = i, col = 1 }, to = { line = i, col = cur_line:len() }, } table.insert(res, region) end end return res end < - If there is a callable instead of assumed string pattern, it is expected to have signature `(line, init)` and behave like `pattern:find()`. It should return two numbers representing span in `line` next after or at `init` (`nil` if there is no such span). !IMPORTANT NOTE!: it means that output's `from` shouldn't be strictly to the left of `init` (it will lead to infinite loop). Not allowed as last item (as it should be pattern with captures). Example of matching only balanced parenthesis with big enough width: >lua { '%b()', function(s, init) if init > 1 or s:len() < 5 then return end return 1, s:len() end, '^.().*().$' } < More examples: >lua -- Pair of balanced brackets from set (used for builtin `b` identifier): { { '%b()', '%b[]', '%b{}' }, '^.().*().$' } -- Imitate word ignoring digits and punctuation (only for Latin alphabet): { '()()%f[%w]%w+()[ \t]*()' } -- Word with camel case support (also supports only Latin alphabet): { { '%u[%l%d]+%f[^%l%d]', '%f[%S][%l%d]+%f[^%l%d]', '%f[%P][%l%d]+%f[^%l%d]', '^[%l%d]+%f[^%l%d]', }, '^().*()$' } -- Number: { '%f[%d]%d+' } -- Date in 'YYYY-MM-DD' format: { '()%d%d%d%d%-%d%d%-%d%d()' } -- Lua block string: { '%[%[().-()%]%]' } < See |MiniAi.gen_spec| for function wrappers to create commonly used textobject specifications. ------------------------------------------------------------------------------ *MiniAi-algorithm* Search for the textobjects relies on these principles: - It uses same input data as described in |MiniAi.find_textobject()|, i.e. whether it is `a` or `i` textobject, its identifier, reference region, etc. - Textobject specification is constructed based on textobject identifier (see |MiniAi-textobject-specification|). - General search is done by converting some 2d buffer region (neighborhood of reference region) into 1d string (each line is appended with `\n`). Then search for a best span matching textobject specification is done inside string (see |MiniAi-glossary|). After that, span is converted back into 2d region. Note: first search is done inside reference region lines, and only after that - inside its neighborhood within `config.n_lines` (see |MiniAi.config|). - The best matching span is chosen by iterating over all spans matching textobject specification and comparing them with "current best". Comparison also depends on reference region (tighter covering is better, otherwise closer is better) and search method (if span is even considered). - Extract span based on extraction pattern (last item in nested pattern). - If task is to perform a consecutive search (`opts.n_times` is greater than 1), steps are repeated with current best match becoming reference region. One such additional step is also done if final region is equal to reference region (this enables consecutive application). Notes: - Iteration over all matched spans is done in depth-first fashion with respect to nested pattern. - It is guaranteed that span is compared only once. - For the sake of increasing functionality, during iteration over all matching spans, some Lua patterns in composed pattern are handled specially. - `%bxx` (`xx` is two identical characters). It denotes balanced pair of identical characters and results into "paired" matches. For example, `%b""` for `"aa" "bb"` would match `"aa"` and `"bb"`, but not middle `" "`. - `x.-y` (`x` and `y` are different strings). It results only in matches with smallest width. For example, `e.-o` for `e e o o` will result only in middle `e o`. Note: it has some implications for when parts have quantifiers (like `+`, etc.), which usually can be resolved with frontier pattern `%f[]` (see examples in |MiniAi-textobject-specification|). ------------------------------------------------------------------------------ *MiniAi.setup()* `MiniAi.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniAi.config|. Usage ~ >lua require('mini.ai').setup() -- use default config -- OR require('mini.ai').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniAi.config* `MiniAi.config` Defaults ~ >lua MiniAi.config = { -- Table with textobject id as fields, textobject specification as values. -- Also use this to disable builtin textobjects. See |MiniAi.config|. custom_textobjects = nil, -- Module mappings. Use `''` (empty string) to disable one. mappings = { -- Main textobject prefixes around = 'a', inside = 'i', -- Next/last textobjects -- NOTE: These override built-in LSP selection mappings on Neovim>=0.12 -- Map LSP selection manually to use it (see `:h MiniAi.config`) around_next = 'an', inside_next = 'in', around_last = 'al', inside_last = 'il', -- Move cursor to corresponding edge of `a` textobject goto_left = 'g[', goto_right = 'g]', }, -- Number of lines within which textobject is searched n_lines = 50, -- How to search for object (first inside current line, then inside -- neighborhood). One of 'cover', 'cover_or_next', 'cover_or_prev', -- 'cover_or_nearest', 'next', 'prev', 'nearest'. search_method = 'cover_or_next', -- Whether to disable showing non-error feedback -- This also affects (purely informational) helper messages shown after -- idle time if user input is required. silent = false, } < # Custom textobjects ~ User can define own textobjects by supplying `config.custom_textobjects`. It should be a table with keys being single character textobject identifier (supported by |getcharstr()|) and values - textobject specification (see |MiniAi-textobject-specification|). General recommendations: - This can be used to override builtin ones (|MiniAi-builtin-textobjects|). Supply non-valid input (not in specification format) to disable module's builtin textobject in favor of external or Neovim's builtin mapping. - Keys should use character representation which can be |getcharstr()| output. For example, `'\r'` and not `''`. Examples: >lua require('mini.ai').setup({ custom_textobjects = { -- Tweak argument textobject a = require('mini.ai').gen_spec.argument({ brackets = { '%b()' } }), -- Disable brackets alias in favor of builtin block textobject b = false, -- Now `vax` should select `xxx` and `vix` - middle `x` x = { 'x()x()x' }, -- Whole buffer g = function() local from = { line = 1, col = 1 } local to = { line = vim.fn.line('$'), col = math.max(vim.fn.getline('$'):len(), 1) } return { from = from, to = to } end } }) -- Use `vim.b.miniai_config` to customize per buffer -- Example of specification useful for Markdown files: local spec_pair = require('mini.ai').gen_spec.pair vim.b.miniai_config = { custom_textobjects = { ['*'] = spec_pair('*', '*', { type = 'greedy' }), ['_'] = spec_pair('_', '_', { type = 'greedy' }), }, } < There are more example specifications in |MiniAi-textobject-specification|. # Search method ~ Value of `config.search_method` defines how best match search is done. Based on its value, one of the following matches will be selected: - Covering match. Left/right edge is before/after left/right edge of reference region. - Previous match. Left/right edge is before left/right edge of reference region. - Next match. Left/right edge is after left/right edge of reference region. - Nearest match. Whichever is closest among previous and next matches. Possible values are: - `'cover'` - use only covering match. Don't use either previous or next; report that there is no textobject found. - `'cover_or_next'` (default) - use covering match. If not found, use next. - `'cover_or_prev'` - use covering match. If not found, use previous. - `'cover_or_nearest'` - use covering match. If not found, use nearest. - `'next'` - use next match. - `'prev'` - use previous match. - `'nearest'` - use nearest match. Note: search is first performed on the reference region lines and only after failure - on the whole neighborhood defined by `config.n_lines`. This means that with `config.search_method` not equal to `'cover'`, "prev" or "next" textobject will end up as search result if they are found on first stage although covering match might be found in bigger, whole neighborhood. This design is based on observation that most of the time operation is done within reference region lines (usually cursor line). Here is an example of what `a)` textobject is based on a value of `'config.search_method'` when cursor is inside `bbb` word: - `'cover'`: `(a) bbb (c)` -> none - `'cover_or_next'`: `(a) bbb (c)` -> `(c)` - `'cover_or_prev'`: `(a) bbb (c)` -> `(a)` - `'cover_or_nearest'`: depends on cursor position. For first and second `b` - as in `cover_or_prev` (as previous match is nearer), for third - as in `cover_or_next` (as next match is nearer). - `'next'`: `(a) bbb (c)` -> `(c)`. Same outcome for `(bbb)`. - `'prev'`: `(a) bbb (c)` -> `(a)`. Same outcome for `(bbb)`. - `'nearest'`: depends on cursor position (same as in `'cover_or_nearest'`). # Mappings ~ Mappings `around_next` / `inside_next` and `around_last` / `inside_last` are essentially `around` / `inside` but using search method `'next'` and `'prev'`. NOTE: with default config, built-in LSP mappings |v_an| and |v_in| on Neovim>=0.12 are overridden. Either use different `around_next` / `inside_next` keys or map manually using |vim.lsp.buf.selection_range()|. For example: >lua local map_lsp_selection = function(lhs, desc) local s = vim.startswith(desc, 'Increase') and 1 or -1 local rhs = function() vim.lsp.buf.selection_range(s * vim.v.count1) end vim.keymap.set('x', lhs, rhs, { desc = desc }) end map_lsp_selection('ls', 'Increase selection') map_lsp_selection('lS', 'Decrease selection') < ------------------------------------------------------------------------------ *MiniAi.find_textobject()* `MiniAi.find_textobject`({ai_type}, {id}, {opts}) Find textobject region Parameters ~ {ai_type} `(string)` One of `'a'` or `'i'`. {id} `(string)` Single character string representing textobject id. It is used to get specification which is later used to compute textobject region. Note: if specification is a function, it is called with all present arguments (`opts` is populated with default arguments). {opts} `(table|nil)` Options. Possible fields: - - Number of lines within which textobject is searched. Default: `config.n_lines` (see |MiniAi.config|). - - Number of times to perform a consecutive search. Each one is done with reference region being previous found textobject region. Default: 1. - - region to try to cover (see |MiniAi-glossary|). It is guaranteed that output region will not be inside or equal to this one. Default: empty region at cursor position. - - Search method. Default: `config.search_method`. Return ~ `(table|nil)` Region of textobject or `nil` if no textobject different from `opts.reference_region` was consecutively found `opts.n_times` times. ------------------------------------------------------------------------------ *MiniAi.move_cursor()* `MiniAi.move_cursor`({side}, {ai_type}, {id}, {opts}) Move cursor to edge of textobject Parameters ~ {side} `(string)` One of `'left'` or `'right'`. {ai_type} `(string)` One of `'a'` or `'i'`. {id} `(string)` Single character string representing textobject id. {opts} `(table|nil)` Same as in |MiniAi.find_textobject()|. `opts.n_times` means number of actual jumps (important when cursor already on the potential jump spot). ------------------------------------------------------------------------------ *MiniAi.gen_spec* `MiniAi.gen_spec` Generate common textobject specifications This is a table with function elements. Call to actually get specification. Example: >lua local gen_spec = require('mini.ai').gen_spec require('mini.ai').setup({ custom_textobjects = { -- Tweak argument to be recognized only inside `()` between `;` a = gen_spec.argument({ brackets = { '%b()' }, separator = ';' }), -- Tweak function call to not detect dot in function name f = gen_spec.function_call({ name_pattern = '[%w_]' }), -- Function definition (needs treesitter queries with these captures) F = gen_spec.treesitter({ a = '@function.outer', i = '@function.inner' }), -- Make `|` select both edges in non-balanced way ['|'] = gen_spec.pair('|', '|', { type = 'non-balanced' }), } }) < ------------------------------------------------------------------------------ *MiniAi.gen_spec.argument()* `MiniAi.gen_spec.argument`({opts}) Argument specification Argument textobject (has default `a` identifier) is a region inside balanced bracket between allowed not excluded separators. Use this function to tweak how it works. Examples: - `argument({ brackets = { '%b()' } })` will search for an argument only inside balanced `()`. - `argument({ separator = '[,;]' })` will treat both `,` and `;` as separators. - `argument({ exclude_regions = { '%b()' } })` will exclude separators which are inside balanced `()` (inside outer brackets). Parameters ~ {opts} `(table|nil)` Options. Allowed fields: - - array of patterns for outer balanced brackets. Default: `{ '%b()', '%b[]', '%b{}' }` (any `()`, `[]`, or `{}` can enclose arguments). - - separator pattern. Default: `','`. One of the practical usages of this option is to include whitespace around character to be a part of separator. For example, `'%s*,%s*'` will treat as separator not only ',', but its possible surrounding whitespace. This has both positive and negative effects. On one hand, `daa` executed over the first argument will delete whitespace after first comma, leading to a more expected outcome. On the other hand it is ambiguous which argument is picked when cursor is over whitespace near the character separator. - - array with patterns for regions inside which separators will be ignored. Default: `{ '%b""', "%b''", '%b()', '%b[]', '%b{}' }` (separators inside balanced quotes or brackets are ignored). ------------------------------------------------------------------------------ *MiniAi.gen_spec.function_call()* `MiniAi.gen_spec.function_call`({opts}) Function call specification Function call textobject (has default `f` identifier) is a region with some characters followed by balanced `()`. Use this function to tweak how it works. Example: - `function_call({ name_pattern = '[%w_]' })` will recognize function name with only alphanumeric or underscore (not dot). Parameters ~ {opts} `(table|nil)` Options. Allowed fields: - - string pattern of character set allowed in function name. Default: `'[%w_%.]'` (alphanumeric, underscore, or dot). Note: should be enclosed in `[]`. ------------------------------------------------------------------------------ *MiniAi.gen_spec.pair()* `MiniAi.gen_spec.pair`({left}, {right}, {opts}) Pair specification Use it to define textobject for region surrounded with `left` from left and `right` from right. The `a` textobject includes both edges, `i` - excludes them. Region can be one of several types (controlled with `opts.type`). All examples are for default search method, `a` textobject, and use `'_'` as both `left` and `right`: - Non-balanced (`{ type = 'non-balanced' }`), default. Equivalent to using `x.-y` as first pattern. Example: on line '_a_b_c_' it consecutively matches '_a_', '_b_', '_c_'. - Balanced (`{ type = 'balanced' }`). Equivalent to using `%bxy` as first pattern. Example: on line '_a_b_c_' it consecutively matches '_a_', '_c_'. Note: both `left` and `right` should be single character. - Greedy (`{ type = 'greedy' }`). Like non-balanced but will select maximum consecutive `left` and `right` edges. Example: on line '__a__b_' it consecutively selects '__a__' and '__b_'. Note: both `left` and `right` should be single character. Parameters ~ {left} `(string)` Left edge. {right} `(string)` Right edge. {opts} `(table|nil)` Options. Possible fields: - - Type of a pair. One of `'non-balanced'` (default), `'balanced'`, `'greedy'`. ------------------------------------------------------------------------------ *MiniAi.gen_spec.treesitter()* `MiniAi.gen_spec.treesitter`({ai_captures}, {opts}) Treesitter specification This is a specification in function form. When called with a pair of treesitter captures, it returns a specification function outputting an array of regions that match corresponding (`a` or `i`) capture. In order for this to work, apart from working treesitter parser for desired language, user should have a reachable language-specific 'textobjects' query (see |vim.treesitter.query.get()|). The most straightforward way for this is to have 'textobjects.scm' query file with treesitter captures stored in some recognized path. This is primarily designed to be compatible with plugin 'nvim-treesitter/nvim-treesitter-textobjects', but can be used without it. Two most common approaches for having a query file: - Install 'nvim-treesitter/nvim-treesitter-textobjects'. It has curated and well maintained builtin query files for many languages with a standardized capture names, like `function.outer`, `function.inner`, etc. - Manually create file 'after/queries//textobjects.scm' in your |$XDG_CONFIG_HOME| directory. It should contain queries with captures (later used to define textobjects). See |lua-treesitter-query|. To verify that query file is reachable, run (example for "lua" language, output should have at least an intended file): >vim :lua print(vim.inspect(vim.treesitter.query.get_files('lua','textobjects'))) < Example configuration for function definition textobject with 'nvim-treesitter/nvim-treesitter-textobjects' captures: >lua local spec_treesitter = require('mini.ai').gen_spec.treesitter require('mini.ai').setup({ custom_textobjects = { F = spec_treesitter({ a = '@function.outer', i = '@function.inner' }), o = spec_treesitter({ a = { '@conditional.outer', '@loop.outer' }, i = { '@conditional.inner', '@loop.inner' }, }) } }) < Notes: - Be sure that query files don't contain unknown |treesitter-directives| (like `#make-range!`, for example). Otherwise textobject for such capture might not be found as |lua-treesitter-core| won't treat them as captures. Verify with `:=vim.treesitter.query.get('lang', 'textobjects')` and see if the target capture is recognized as one. - It uses buffer's |filetype| to determine query language. - On large files it is slower than pattern-based textobjects. Still very fast though (one search should be magnitude of milliseconds or tens of milliseconds on really large file). Parameters ~ {ai_captures} `(table)` Captures for `a` and `i` textobjects: table with and fields with captures for `a` and `i` textobjects respectively. Each value can be either a string capture (should start with `'@'`) or an array of such captures (best among all matches will be chosen). {opts} `(table|nil)` Options. Possible values: - - whether to try to use 'nvim-treesitter' plugin (if present) to do the query. It used to implement more advanced behavior and more coherent experience if 'nvim-treesitter-textobjects' queries are used. However, as |lua-treesitter-core| methods are more capable now, the option will soon be removed. Only present for backward compatibility. Default: `false`. Return ~ `(function)` Function with |MiniAi.find_textobject()| signature which returns array of current buffer regions representing matches for corresponding (`a` or `i`) treesitter capture. See also ~ - |MiniAi-textobject-specification| for how this type of textobject specification is processed. - |vim.treesitter.query.get()| for how query is fetched. - |Query:iter_captures()| for how all query captures are iterated in case of no 'nvim-treesitter'. ------------------------------------------------------------------------------ *MiniAi.gen_spec.user_prompt()* `MiniAi.gen_spec.user_prompt`() Specification from user prompt - Ask user for left and right textobject edges as raw strings (no pattern). - Construct specification for a textobject that matches from left edge string to right edge string: `a` includes both strings, `i` only insides. Used for |MiniAi-builtin-textobjects| with identifier `?`. Return ~ `(function)` Textobject specification as function. ------------------------------------------------------------------------------ *MiniAi.select_textobject()* `MiniAi.select_textobject`({ai_type}, {id}, {opts}) Visually select textobject region Does nothing if no region is found. Parameters ~ {ai_type} `(string)` One of `'a'` or `'i'`. {id} `(string)` Single character string representing textobject id. {opts} `(table|nil)` Same as in |MiniAi.find_textobject()|. Extra fields: - - One of `'v'`, `'V'`, or `'\22'` (escaped version of `''`). Default: Latest visual mode. - - Whether selection is for Operator-pending mode. Used in that mode's mappings, shouldn't be used directly. Default: `false`. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-align.txt ================================================ *mini.align* Align text interactively MIT License Copyright (c) 2022 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniAlign* Rich and flexible customization of both alignment rules and user interaction. Works with charwise, linewise, and blockwise selections in both Normal mode (on textobject/motion; with dot-repeat) and Visual mode. Features: - Alignment is done in three main steps: - lines into parts based on Lua pattern(s) or user-supplied rule. - parts for certain side(s) to be same width inside columns. - parts to be lines, with customizable delimiter(s). Each main step can be preceded by other steps (pre-steps) to achieve highly customizable outcome. See `steps` value in |MiniAlign.config|. For more details, see |MiniAlign-glossary| and |MiniAlign-algorithm|. - User can control alignment interactively by pressing customizable modifiers (single keys representing how alignment steps and/or options should change). Some of default modifiers: - Press `s` to enter split Lua pattern. - Press `j` to choose justification side from available ones ("left", "center", "right", "none"). - Press `m` to enter merge delimiter. - Press `f` to enter filter Lua expression to configure which parts will be affected (like "align only first column"). - Press `i` to ignore some commonly unwanted split matches. - Press `p` to pair neighboring parts so they be aligned together. - Press `t` to trim whitespace from parts. - Press `` (backspace) to delete some last pre-step. For more details, see |MiniAlign-modifiers-builtin| and |MiniAlign-examples|. - Alignment can be done with instant preview (result is updated after each modifier) or without it (result is shown and accepted after non-default split pattern is set). - Every user interaction is accompanied with helper status message showing relevant information about current alignment process. # Setup ~ This module needs a setup with `require('mini.align').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniAlign` which you can use for scripting or manually (with `:lua MiniAlign.*`). See |MiniAlign.config| for available config settings. You can override runtime config settings (like `config.modifiers`) locally to buffer inside `vim.b.minialign_config` which should have same structure as `MiniAlign.config`. See |mini.nvim-buffer-local-config| for more details. To stop module from showing non-error feedback, set `config.silent = true`. # Comparisons ~ - [junegunn/vim-easy-align](https://github.com/junegunn/vim-easy-align): - 'mini.align' is mostly designed after 'junegunn/vim-easy-align', so there are a lot of similarities. - Both plugins allow users to change alignment options interactively by pressing modifier keys (albeit completely different default ones). 'junegunn/vim-easy-align' has those modifiers fixed, while 'mini.align' allows their full customization. See |MiniAlign.config| for examples. - 'junegunn/vim-easy-align' is designed to treat delimiters differently than other parts of strings. 'mini.align' doesn't distinguish split parts from one another by design: splitting is allowed to be done based on some other logic than by splitting on delimiters. - 'junegunn/vim-easy-align' initially aligns by only first delimiter. 'mini.align' initially aligns by all delimiter. - 'junegunn/vim-easy-align' implements special filtering by delimiter row number. 'mini.align' has builtin filtering based on Lua code supplied by user in modifier phase. See |MiniAlign.gen_step.filter()| and 'f' builtin modifier. - 'mini.align' treats any non-registered modifier as a plain delimiter pattern, while 'junegunn/vim-easy-align' does not. - 'mini.align' exports core Lua function used for aligning strings (|MiniAlign.align_strings()|). - [godlygeek/tabular](https://github.com/godlygeek/tabular): - 'godlygeek/tabular' is mostly designed around single command which is customized by printing its parameters. 'mini.align' implements different concept of interactive alignment through pressing customizable single character modifiers. - 'godlygeek/tabular' can detect region upon which alignment can be desirable. 'mini.align' does not by design: use Visual selection or textobject/motion to explicitly define region to align. # Disabling ~ To disable, set `vim.g.minialign_disable` (globally) or `vim.b.minialign_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniAlign-glossary* PARTS ~ 2d array of strings (array of arrays of strings). See more in |MiniAlign.as_parts()|. ROW ~ First-level array of parts (like `parts[1]`). COLUMN ~ Array of strings, constructed from parts elements with the same second-level index (like `{ parts[1][1],` `parts[2][1], ... }`). STEP ~ A named callable. See |MiniAlign.new_step()|. When used in terms of alignment steps, callable takes two arguments: some object (parts or string array) and option table. SPLIT ~ Process of taking array of strings and converting it into parts. JUSTIFY ~ Process of taking parts and converting them to aligned parts (all elements have same widths inside columns). MERGE ~ Process of taking parts and converting it back to array of strings. Usually by concatenating rows into strings. REGION ~ Table representing region in a buffer. Fields / have inclusive start / end positions ( might be `nil` to describe empty region). Positions are also tables with and fields (both start at 1). MODE ~ Either charwise ("char", `v`, |charwise|), linewise ("line", `V`, |linewise|) or blockwise ("block", ``, |blockwise-visual|) ------------------------------------------------------------------------------ *MiniAlign-algorithm* There are two main processes implemented in 'mini.align': strings alignment and interactive region alignment. See |MiniAlign-glossary| for more information about used terms. # Strings alignment ~ Main implementation is in |MiniAlign.align_strings()|. Its input is array of strings and output - array of aligned strings. The process consists from three main steps (split, justify, merge) which can be preceded by any number of preliminary steps (pre-split, pre-justify, pre-merge). Algorithm: - . Take input array of strings and consecutively apply all pre-split steps (`steps.pre_split`). Each one has `(strings, opts)` signature and should modify array in place. - . Take array of strings and convert it to parts with `steps.split()`. It has `(strings, opts)` signature and should return parts. - . Take parts and consecutively apply all pre-justify steps (`steps.pre_justify`). Each one has `(parts, opts)` signature and should modify parts in place. - . Take parts and apply `steps.justify()`. It has `(parts, opts)` signature and should modify parts in place. - . Take parts and consecutively apply all pre-merge steps (`steps.pre_merge`). Each one has `(parts, opts)` signature and should modify parts in place. - . Take parts and convert it to array of strings with `steps.merge()`. It has `(parts, opts)` signature and should return array of strings. Notes: - All table objects are initially copied so that modification in place doesn't affect workflow. - Default main steps are designed to be controlled via options. See |MiniAlign.align_strings()| and default step entries in |MiniAlign.gen_step|. - All steps are guaranteed to take same option table as second argument. This allows steps to "talk" to each other, i.e. earlier steps can pass data to later ones. # Interactive region alignment ~ Interactive alignment is a main entry point for most users. It can be done in two flavors: - . Initiated via mapping defined in `start` of `MiniAlign.config.mappings`. Alignment is accepted once split pattern becomes non-default. - . Initiated via mapping defined in `start_with_preview` of `MiniAlign.config.mappings`. Alignment result is shown after every modifier and is accepted after `` (`Enter`) is hit. Note: each preview is done by applying current alignment steps and options to the initial region lines, not the ones currently displaying in preview. Lifecycle (assuming default mappings): - : - In Normal mode type `ga` (or `gA` to show preview) followed by textobject or motion defining region to be aligned. - In Visual mode select region and type `ga` (or `gA` to show preview). Strings contained in selected region will be used as input to |MiniAlign.align_strings()|. Beware of mode when selecting region: charwise (`v`), linewise (`V`), or blockwise (``). They all behave differently. - . Press single keys one at a time: - If pressed key is among table keys of `modifiers` table of |MiniAlign.config|, its function value is executed. It usually modifies some options(s) and/or affects some pre-step(s). - If pressed key is not among defined modifiers, it is treated as plain split pattern. This process can either end by itself (usually in case of no preview and non-default split pattern being set) or you can choose to end it manually. - . In case of active preview, accept current result by pressing ``. Discard any result and return to initial regions with either `` or ``. See more in |MiniAlign-modifiers-builtin| and |MiniAlign-examples|. Notes: - Visual blockwise selection works best with 'virtualedit' equal to "block" or "all". - Alignment with preview works best with 'showmode' disabled. ------------------------------------------------------------------------------ *MiniAlign-modifiers-builtin* Overview of builtin modifiers All examples assume interactive alignment with preview in linewise mode. With default mappings, use `V` to select lines and `gA` to initiate alignment. It might be helpful to copy lines into modifiable buffer and experiment yourself. Notes: - Any pressed key which doesn't have defined modifier will be treated as plain split pattern. - All modifiers can be customized inside |MiniAlign.setup()|. See "Modifiers" section of |MiniAlign.config|. # Main option modifiers ~ Enter split pattern (confirm prompt by pressing ``). Input is treated as plain delimiter. Before: > a-b-c aa-bb-cc < After typing `s-`: > a -b -c aa-bb-cc < Choose justify side. Prompts user (with helper message) to type single character identifier of side: `l`eft, `c`enter, `r`ight, `n`one. Before: > a_b_c aa_bb_cc < After typing `_jr` (first make split by `_`): > a_ b_ c aa_bb_cc < Enter merge delimiter (confirm prompt by pressing ``). Before: > a_b_c aa_bb_cc < After typing `_m--` (first make split by `_`): > a --_--b --_--c aa--_--bb--_--cc < # Modifiers adding pre-steps ~ Enter filter expression. See more details in |MiniAlign.gen_step.filter()|. Before: > a_b_c aa_bb_cc < After typing `_fn==1` (first make split by `_`): > a _b_c aa_bb_cc < Ignore some split matches. It modifies `split_exclude_patterns` option by adding commonly wanted patterns. See more details in |MiniAlign.gen_step.ignore_split()|. Before: > /* This_is_assumed_to_be_comment */ a"_"_b aa_bb < After typing `_i` (first make split by `_`): > /* This_is_assumed_to_be_comment */ a"_"_b aa _bb <

Pair neighboring parts. Before: > a_b_c aaa_bbb_ccc < After typing `_p` (first make split by `_`): > a_ b_ c aaa_bbb_ccc < Trim parts from whitespace on both sides (keeping indentation). Before: > a _ b _ c aa _bb _cc < After typing `_t` (first make split by `_`): > a _b _c aa_bb_cc < # Delete some last pre-step ~ Delete one of the pre-steps. If there is only one kind of pre-steps, remove its latest added one. If not, prompt user to choose pre-step kind by entering single character: `s`plit, `j`ustify, `m`erge. Examples: - `tp` results in only "trim" step to be left. - `it` prompts to choose which step to delete (pre-split or pre-justify in this case). # Special configurations for common splits ~ <=> Use special pattern to align by a group of consecutive "=". It can be preceded by any number of punctuation marks and followed by some sommon punctuation characters. Trim whitespace and merge with single space. Before: > a=b aa<=bb aaa===bbb aaaa = cccc < After typing `=`: > a = b aa <= bb aaa === bbb aaaa = cccc < <,> Besides splitting by "," character, trim whitespace, pair neighboring parts and merge with single space. Before: > a,b aa,bb aaa , bbb < After typing `,`: > a, b aa, bb aaa, bbb < <|> Split by "|" character, trim whitespace, merge with single space. Before: > |a|b| |aa|bb| |aaa | bbb | < After typing `|`: > | a | b | | aa | bb | | aaa | bbb | < (Space bar) Squash consecutive whitespace into single space (except possible indentation) and split by `%s+` pattern (keeps indentation). Before: > a b c aa bb cc < After typing ``: > a b c aa bb cc < ------------------------------------------------------------------------------ *MiniAlign-examples* Copy lines in modifiable buffer, initiate alignment with preview (`gAip`) and try typing suggested key sequences. These are modified examples taken from 'junegunn/vim-easy-align'. # Equal sign ~ Lines: > # This=is=assumed=to be a comment "a =" a = a = 1 bbbb = 2 ccccccc = 3 ccccccccccccccc ddd = 4 eeee === eee = eee = eee=f fff = ggg += gg &&= gg g != hhhhhhhh == 888 i := 5 i %= 5 i *= 5 j =~ 5 j >= 5 aa => 123 aa <<= 123 aa >>= 123 bbb => 123 c => 1233123 d => 123 dddddd &&= 123 dddddd ||= 123 dddddd /= 123 gg <=> ee < Key sequences: - `=` - `=jc` - `=jr` - `=m!` - `=p` - `=i` (execute `:lua vim.o.commentstring = '# %s'` for full experience) - `=` - `=p` - `=fn==1` - `=fn==1t` - `=frow>7` ------------------------------------------------------------------------------ *MiniAlign.setup()* `MiniAlign.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniAlign.config|. Usage ~ >lua require('mini.align').setup() -- use default config -- OR require('mini.align').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniAlign.config* `MiniAlign.config` Defaults ~ >lua MiniAlign.config = { -- Module mappings. Use `''` (empty string) to disable one. mappings = { start = 'ga', start_with_preview = 'gA', }, -- Modifiers changing alignment steps and/or options modifiers = { -- Main option modifiers ['s'] = --, ['j'] = --, ['m'] = --, -- Modifiers adding pre-steps ['f'] = --, ['i'] = --, ['p'] = --, ['t'] = --, -- Delete some last pre-step [''] = --, -- Special configurations for common splits ['='] = --, ['|'] = --, [' '] = --, }, -- Default options controlling alignment process options = { split_pattern = '', justify_side = 'left', merge_delimiter = '', }, -- Default steps performing alignment (if `nil`, default is used) steps = { pre_split = {}, split = nil, pre_justify = {}, justify = nil, pre_merge = {}, merge = nil, }, -- Whether to disable showing non-error feedback -- This also affects (purely informational) helper messages shown after -- idle time if user input is required. silent = false, } < # Modifiers ~ `MiniAlign.config.modifiers` is used to define interactive user experience of managing alignment process. It is a table with single character keys and modifier function values. Each modifier function: - Is called when corresponding modifier key is pressed. - Has signature `(steps, opts)` and should modify any of its input in place. Examples: - Modifier function used for default 'i' modifier: >lua function(steps, _) table.insert(steps.pre_split, MiniAlign.gen_step.ignore_split()) end < - Tweak 't' modifier to use highest indentation instead of keeping it: >lua require('mini.align').setup({ modifiers = { t = function(steps, _) local trim_high = MiniAlign.gen_step.trim('both', 'high') table.insert(steps.pre_justify, trim_high) end } }) < - Tweak `j` modifier to cycle through available "justify_side" option values (like in 'junegunn/vim-easy-align'): >lua require('mini.align').setup({ modifiers = { j = function(_, opts) local next_option = ({ left = 'center', center = 'right', right = 'none', none = 'left', })[opts.justify_side] opts.justify_side = next_option or 'left' end, }, }) < # Options ~ `MiniAlign.config.options` defines default values of options used to control behavior of steps. Examples: - Set `justify_side = 'center'` to center align at initialization. For more details about options see |MiniAlign.align_strings()| and entries of |MiniAlign.gen_step| for default main steps. # Steps ~ `MiniAlign.config.steps` defines default steps to be applied during alignment process. Examples: - Align by default only first pair of columns: >lua local align = require('mini.align') align.setup({ steps = { pre_justify = { align.gen_step.filter('n == 1') } }, }) < ------------------------------------------------------------------------------ *MiniAlign.align_strings()* `MiniAlign.align_strings`({strings}, {opts}, {steps}) Align strings For details about alignment process see |MiniAlign-algorithm|. Parameters ~ {strings} `(table)` Array of strings. {opts} `(table|nil)` Options. Its copy will be passed to steps as second argument. Extended with `MiniAlign.config.options`. This is a place to control default main steps: - `opts.split_pattern` - Lua pattern(s) used to make split parts. - `opts.split_exclude_patterns` - which split matches should be ignored. - `opts.justify_side` - which direction(s) alignment should be done. - `opts.justify_offsets` - offsets tweaking width of first column - `opts.merge_delimiter` - which delimiter(s) to use when merging. For more information see |MiniAlign.gen_step| entry for corresponding default step. {steps} `(table|nil)` Steps. Extended with `MiniAlign.config.steps`. Possible `nil` values are replaced with corresponding default steps: - `split` - |MiniAlign.gen_step.default_split()|. - `justify` - |MiniAlign.gen_step.default_justify()|. - `merge` - |MiniAlign.gen_step.default_merge()|. ------------------------------------------------------------------------------ *MiniAlign.align_user()* `MiniAlign.align_user`({mode}) Align current region with user-supplied steps Mostly designed to be used inside mappings. Will use |MiniAlign.align_strings()| and set the following options in `opts`: - `justify_offsets` - array of offsets used to achieve actual alignment of a region. It is non-trivial (not array of zeros) only for charwise selection: offset of first string is computed as width of prefix to the left of region start. - `region` - current affected region (see |MiniAlign-glossary|). Can be used to create more advanced steps. - `mode` - mode of selection (see |MiniAlign-glossary|). Parameters ~ {mode} `(string)` Selection mode. One of "char", "line", "block". ------------------------------------------------------------------------------ *MiniAlign.as_parts()* `MiniAlign.as_parts`({arr2d}) Convert 2d array of strings to parts This function verifies if input is a proper 2d array of strings and adds methods to its copy. Class ~ {parts} Fields ~ {apply} `(function)` Takes callable `f` and applies it to every part. Callable should have signature `(s, data)`: `s` is a string part, `data` - table with its data ( has row number, has column number). Returns new 2d array. {apply_inplace} `(function)` Takes callable `f` and applies it to every part. Should have same signature as in `apply` method. Outputs (should all be strings) are assigned in place to a corresponding parts element. Returns parts itself to enable method chaining. {get_dims} `(function)` Return dimensions of parts array: a table with and keys having number of rows and number of columns (maximum number of elements across all rows). {group} `(function)` Concatenate neighboring strings based on supplied boolean mask and direction (one of "left", default, or "right"). Has signature `(mask, direction)` and modifies parts in place. Returns parts itself to enable method chaining. Example: - Parts: `{ { "a", "b", "c" }, { "d", "e" }, { "f" } }` - Mask: `{ { false, false, true }, { true, false }, { false } }` - Result for direction "left": `{ { "abc" }, { "d", "e" }, { "f" } }` - Result for direction "right": `{ { "ab","c" }, { "de" }, { "f" } }` {pair} `(function)` Concatenate neighboring element pairs. Takes `direction` as input (one of "left", default, or "right") and applies `group()` for an alternating mask. Example: - Parts: `{ { "a", "b", "c" }, { "d", "e" }, { "f" } }` - Result for direction "left": `{ { "ab", "c" }, { "de" }, { "f" } }` - Result for direction "right": `{ { "a", "bc" }, { "de" }, { "f" } }` {slice_col} `(function)` Return column with input index `j`. Note: it might not be an array if rows have unequal number of columns. {slice_row} `(function)` Return row with input index `i`. {trim} `(function)` Trim elements whitespace. Has signature `(direction, indent)` and modifies parts in place. Returns parts itself to enable method chaining. - Possible values of `direction`: "both" (default), "left", "right", "none". Defines from which side whitespaces should be removed. - Possible values of `indent`: "keep" (default), "low", "high", "remove". Defines what to do with possible indent (left whitespace of first string in a row). Value "keep" keeps it; "low" makes all indent equal to the lowest across rows; "high" - highest across rows; "remove" - removes indent. Usage ~ >lua parts = MiniAlign.as_parts({ { 'a', 'b' }, { 'c' } }) print(vim.inspect(parts.get_dims())) -- Should be { row = 2, col = 2 } parts.apply_inplace(function(s, data) return ' ' .. data.row .. s .. data.col .. ' ' end) print(vim.inspect(parts)) -- Should be { { ' 1a1 ', ' 1b2 ' }, { ' 2c1 ' } } parts.trim('both', 'remove').pair() print(vim.inspect(parts)) -- Should be { { '1a11b2' }, { '2c1' } } < ------------------------------------------------------------------------------ *MiniAlign.new_step()* `MiniAlign.new_step`({name}, {action}) Create step A step is basically a named callable object. Having a name bundled with some action powers helper status message during interactive alignment process. Parameters ~ {name} `(string)` Step name. {action} `(function|table)` Step action. Should be a callable object (see |vim.is_callable()|). Return ~ `(table)` A table with keys: with `name` argument, with `action`. ------------------------------------------------------------------------------ *MiniAlign.gen_step* `MiniAlign.gen_step` Generate common action steps This is a table with function elements. Call to actually get step. Each step action is a function that has signature `(object, opts)`, where `object` is either parts or array of strings (depends on which stage of alignment process it is assumed to be applied) and `opts` is table of options. Outputs of elements named `default_*` are used as default corresponding main step (split, justify, merge). Behavior of all of them depend on values from supplied options (second argument). Outputs of other elements depend on both step generator input values and options supplied at execution. This design is mostly because their output can be used several times in pre-steps. Usage ~ >lua local align = require('mini.align') align.setup({ modifiers = { -- Use 'T' modifier to remove both whitespace and indent T = function(steps, _) table.insert(steps.pre_justify, align.gen_step.trim('both', 'remove')) end, }, options = { -- By default align "right", "left", "right", "left", ... justify_side = { 'right', 'left' }, }, steps = { -- Align by default only first pair of columns pre_justify = { align.gen_step.filter('n == 1') }, }, }) < ------------------------------------------------------------------------------ *MiniAlign.gen_step.default_split()* `MiniAlign.gen_step.default_split`() Generate default split step Output splits strings using matches of Lua pattern(s) from `split_pattern` option which are not dismissed by `split_exclude_patterns` option. Outline of how single string is split: - Convert `split_pattern` option to array of strings (string is converted as one-element array). This array will be recycled in case there are more split matches than in converted `split_pattern` array (which almost always). - Find all forbidden spans (intervals inside string) - all matches of all patterns in `split_exclude_patterns`. - Find match for the next pattern. If it is not inside any forbidden span, add preceding unmatched substring and matched split as two parts. Repeat with the next pattern. - If no pattern match is found, add the rest of string as final part. Output uses following options (as part second argument, `opts` table): - - string or array of strings used to detect split matches and create parts. Default: `''` meaning no matches (whole string is used as part). Examples: `'%s+'`, `{ '<', '>' }`. - - array of strings defining which regions to exclude from being matched. Default: `{}`. Examples: `{ '".-"', '^%s*#.*' }`. Return ~ `(table)` A step named "split" and with appropriate callable action. See also ~ |MiniAlign.gen_step.ignore_split()| heavily uses `split_exclude_patterns`. ------------------------------------------------------------------------------ *MiniAlign.gen_step.default_justify()* `MiniAlign.gen_step.default_justify`() Generate default justify step Output makes column elements of string parts have equal width by adding left and/or right whitespace padding. Which side(s) to pad is defined by `justify_side` option. Width of first column can be tweaked with `justify_offsets` option. Outline of how parts are justified: - Convert `justify_side` option to array of strings (single string is converted as one-element array). Recycle this array to have length equal to number of columns in parts. - For all columns compute maximum width of strings from it (add offsets from `justify_offsets` to first column widths). Note: for left alignment, width of last row element does not affect column width. This is mainly because it won't be padded and helps dealing with "no single match" lines. - Make all elements have same width inside column by adding appropriate amount of whitespace. Which side(s) to add is controlled by the corresponding `justify_side` array element. Note: padding is done with spaces which might conflict with tab indentation. Output uses following options (as part second argument, `opts` table): - - string or array of strings. Each element can be one of "left" (pad right side), "center" (pad both sides equally), "right" (pad left side), "none" (no padding). Default: "left". - - array of numeric left offsets of rows. Used to adjust for possible not equal indents, like in case of charwise selection when left edge is not on the first column. Default: array of zeros. Set automatically during interactive alignment in charwise mode. Return ~ `(table)` A step named "justify" and with appropriate callable action. ------------------------------------------------------------------------------ *MiniAlign.gen_step.default_merge()* `MiniAlign.gen_step.default_merge`() Generate default merge step Output merges rows of parts into strings by placing merge delimiter(s) between them. Outline of how parts are converted to array of strings: - Convert `merge_delimiter` option to array of strings (single string is converted as one-element array). Recycle this array to have length equal to number of columns in parts minus 1. Also possibly trim leading whitespace in first merge character to not affect indentation. - Exclude empty strings from parts. They add nothing to output except extra usage of merge delimiter. - Concatenate each row interleaving with array of merge delimiters. Output uses following options (as part second argument, `opts` table): - - string or array of strings. Default: `''`. Examples: `' '`, `{ '', ' ' }`. Return ~ `(table)` A step named "merge" and with appropriate callable action. ------------------------------------------------------------------------------ *MiniAlign.gen_step.filter()* `MiniAlign.gen_step.filter`({expr}) Generate filter step Construct function predicate from supplied Lua string expression and make step evaluating it on every part element. Outline of how filtering is done: - Convert Lua filtering expression into function predicate which can be evaluated in manually created context (some specific variables being set). - Compute boolean mask for parts by applying predicate to each element of 2d array with special variables set to specific values (see next section). - Group parts with computed mask. See `group()` method of parts in |MiniAlign.as_parts()|. Special variables which can be used in expression: - - row number of current element. - - total number of rows in parts. - - column number of current element. - - total number of columns in current row. - - string value of current element. - - column pair number of current element. Useful when filtering by result of pattern splitting. - - total number of column pairs in current row. - All variables from global table `_G`. Tips: - This general filtering approach can be used to both include and exclude certain parts from alignment. Examples: - Use `row ~= 2` to align all parts except from second row. - Use `n == 1` to align only by first pair of columns. - Filtering by last equal sign usually can be done with `n >= (N - 1)` (because there is usually something to the right of it). Parameters ~ {expr} `(string)` Lua expression as a string which will be used as predicate. Return ~ `(table|nil)` A step named "filter" and with appropriate callable action. ------------------------------------------------------------------------------ *MiniAlign.gen_step.ignore_split()* `MiniAlign.gen_step.ignore_split`({patterns}, {exclude_comment}) Generate ignore step Output adds certain values to `split_exclude_patterns` option. Should be used as pre-split step. Parameters ~ {patterns} `(table)` Array of patterns to be added to `split_exclude_patterns` as is. Default: `{ [[".-"]] }` (excludes strings for most cases). {exclude_comment} `(boolean|nil)` Whether to add comment pattern to `split_exclude_patterns`. Comment pattern is derived from 'commentstring' option. Default: `true`. Return ~ `(table)` A step named "ignore" and with appropriate callable action. See also ~ |MiniAlign.gen_step.default_split()| for details about `split_exclude_patterns` option. ------------------------------------------------------------------------------ *MiniAlign.gen_step.pair()* `MiniAlign.gen_step.pair`({direction}) Generate pair step Output calls `pair()` method of parts (see |MiniAlign.as_parts()|) with supplied `direction` argument. Parameters ~ {direction} `(string)` Which direction to pair. One of "left" (default) or Return ~ `(table)` A step named "pair" and with appropriate callable action. ------------------------------------------------------------------------------ *MiniAlign.gen_step.trim()* `MiniAlign.gen_step.trim`({direction}, {indent}) Generate trim step Output calls `trim()` method of parts (see |MiniAlign.as_parts()|) with supplied `direction` and `indent` arguments. Parameters ~ {direction} `(string|nil)` Which sides to trim whitespace. One of "both" (default), "left", "right", "none". {indent} `(string|nil)` What to do with possible indent (left whitespace of first string in a row). One of "keep" (default), "low", "high", "remove". Return ~ `(table)` A step named "trim" and with appropriate callable action. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-animate.txt ================================================ *mini.animate* Animate common Neovim actions MIT License Copyright (c) 2022 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniAnimate* Features: - Works out of the box with a single `require('mini.animate').setup()`. No extra mappings or commands needed. - Animate cursor movement inside same buffer by showing customizable path. See |MiniAnimate.config.cursor| for more details. - Animate scrolling with a series of subscrolls ("smooth scrolling"). See |MiniAnimate.config.scroll| for more details. - Animate window resize by gradually changing sizes of all windows. See |MiniAnimate.config.resize| for more details. - Animate window open/close with visually updating floating window. See |MiniAnimate.config.open| and |MiniAnimate.config.close| for more details. - Timings for all actions can be customized independently. See |MiniAnimate-timing| for more details. - Action animations can be enabled/disabled independently. - All animations are asynchronous/non-blocking and trigger a targeted event which can be used to perform actions after animation is done. - |MiniAnimate.animate()| function which can be used to perform own animations. Notes: - Cursor movement is animated inside same window and buffer, not as cursor moves across the screen. - Scroll and resize animations are done with "side effects": they actually change the state of what is animated (window view and sizes respectively). This has a downside of possibly needing extra work to account for asynchronous nature of animation (like adjusting certain mappings, etc.). See |MiniAnimate.config.scroll| and |MiniAnimate.config.resize| for more details. # Setup ~ This module needs a setup with `require('mini.animate').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniAnimate` which you can use for scripting or manually (with `:lua MiniAnimate.*`). See |MiniAnimate.config| for available config settings. You can override runtime config settings (like `config.modifiers`) locally to buffer inside `vim.b.minianimate_config` which should have same structure as `MiniAnimate.config`. See |mini.nvim-buffer-local-config| for more details. # Comparisons ~ - [Neovide](https://neovide.dev/): - Neovide is a standalone GUI which has more control over its animations. While 'mini.animate' works inside terminal emulator (with all its limitations, like lack of pixel-size control over animations). - Neovide animates cursor movement across screen, while 'mini.animate' - as it moves across same buffer. - Neovide has fixed number of animation effects per action, while 'mini.animate' is fully customizable. - 'mini.animate' implements animations for window open/close, while Neovide does not. - [edluffy/specs.nvim](https://github.com/edluffy/specs.nvim): - 'mini.animate' approaches cursor movement visualization via customizable path function (uses extmarks), while 'specs.nvim' can customize within its own visual effects (shading and floating window resizing). - [karb94/neoscroll.nvim](https://github.com/karb94/neoscroll.nvim): - Scroll animation is triggered only inside dedicated mappings. 'mini.animate' animates scroll resulting from any window view change. - [anuvyklack/windows.nvim](https://github.com/anuvyklack/windows.nvim): - Resize animation is done only within custom commands and mappings, while 'mini.animate' animates any resize with appropriate values of 'winheight' / 'winwidth' and 'winminheight' / 'winminwidth'). # Highlight groups ~ - `MiniAnimateCursor` - highlight of cursor during its animated movement. - `MiniAnimateNormalFloat` - highlight of floating window for `open` and `close` animations. To change any highlight group, set it directly with |nvim_set_hl()|. # Disabling ~ To disable, set `vim.g.minianimate_disable` (globally) or `vim.b.minianimate_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniAnimate.setup()* `MiniAnimate.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniAnimate.config|. Usage ~ >lua require('mini.animate').setup() -- use default config -- OR require('mini.animate').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniAnimate.config* `MiniAnimate.config` Defaults ~ >lua MiniAnimate.config = { -- Cursor path cursor = { -- Whether to enable this animation enable = true, -- Timing of animation (how steps will progress in time) timing = --, -- Path generator for visualized cursor movement path = --, }, -- Vertical scroll scroll = { -- Whether to enable this animation enable = true, -- Timing of animation (how steps will progress in time) timing = --, -- Subscroll generator based on total scroll subscroll = --, }, -- Window resize resize = { -- Whether to enable this animation enable = true, -- Timing of animation (how steps will progress in time) timing = --, -- Subresize generator for all steps of resize animations subresize = --, }, -- Window open open = { -- Whether to enable this animation enable = true, -- Timing of animation (how steps will progress in time) timing = --, -- Floating window config generator visualizing specific window winconfig = --, -- 'winblend' (window transparency) generator for floating window winblend = --, }, -- Window close close = { -- Whether to enable this animation enable = true, -- Timing of animation (how steps will progress in time) timing = --, -- Floating window config generator visualizing specific window winconfig = --, -- 'winblend' (window transparency) generator for floating window winblend = --, }, } < # General ~ - *MiniAnimate-timing* Every animation is a non-blockingly scheduled series of specific actions. They are executed in a sequence of timed steps controlled by `timing` option. It is a callable which, given next and total step numbers, returns wait time (in ms). See |MiniAnimate.gen_timing| for builtin timing functions. See |MiniAnimate.animate()| for more details about animation process. - Every animation can be enabled/disabled independently by setting `enable` option to `true`/`false`. - *MiniAnimate-done-event* Every animation triggers custom |User| event when it is finished. It is named `MiniAnimateDoneXxx` with `Xxx` replaced by capitalized supported animation action name (like `MiniAnimateDoneCursor`). Use it to schedule some action after certain animation is completed. Alternatively, you can use |MiniAnimate.execute_after()| (usually preferred in mappings). - Each animation has its main step generator which defines how particular animation is done. They all are callables which take some input data and return an array of step data. Length of that array determines number of animation steps. Outputs `nil` and empty table result in no animation. # Cursor ~ *MiniAnimate.config.cursor* This animation is triggered for each movement of cursor inside same window and buffer. Its visualization step consists from placing single extmark (see |extmarks|) at certain position. This extmark contains single space and is highlighted with `MiniAnimateCursor` highlight group. Exact places of extmark and their number is controlled by `path` option. It is a callable which takes `destination` argument (2d integer point in `(line, col)` coordinates) and returns array of relative to `(0, 0)` places for extmark to be placed. Example: - Input `(2, -3)` means cursor jumped 2 lines forward and 3 columns backward. - Output `{ {0, 0 }, { 0, -1 }, { 0, -2 }, { 0, -3 }, { 1, -3 } }` means that path is first visualized along the initial line and then along final column. See |MiniAnimate.gen_path| for builtin path generators. Notes: - Input `destination` value is computed ignoring folds. This is by design as it helps better visualize distance between two cursor positions. - Outputs of path generator resulting in a place where extmark can't be placed are silently omitted during animation: this step won't show any visualization. Configuration example: >lua local animate = require('mini.animate') animate.setup({ cursor = { -- Animate for 200 milliseconds with linear easing timing = animate.gen_timing.linear({ duration = 200, unit = 'total' }), -- Animate with shortest line for any cursor move path = animate.gen_path.line({ predicate = function() return true end, }), } }) < After animation is done, `MiniAnimateDoneCursor` event is triggered. # Scroll ~ *MiniAnimate.config.scroll* This animation is triggered for each vertical scroll of current window. Its visualization step consists from performing a small subscroll which all in total will result into needed total scroll. Exact subscroll values and their number is controlled by `subscroll` option. It is a callable which takes `total_scroll` argument (single non-negative integer) and returns array of non-negative integers each representing the amount of lines needed to be scrolled inside corresponding step. All subscroll values should sum to input `total_scroll`. Example: - Input `5` means that total scroll consists from 5 lines (either up or down, which doesn't matter). - Output of `{ 1, 1, 1, 1, 1 }` means that there are 5 equal subscrolls. See |MiniAnimate.gen_subscroll| for builtin subscroll generators. Notes: - Input value of `total_scroll` is computed taking folds into account. - As scroll animation is essentially a precisely scheduled non-blocking subscrolls, this has two important interconnected consequences: - If another scroll is attempted during the animation, it is done based on the **currently visible** window view. Example: if user presses |CTRL-D| and then |CTRL-U| when animation is half done, window will not display the previous view half of 'scroll' above it. This especially affects mouse wheel scrolling, as each its turn results in a new scroll for number of lines defined by 'mousescroll'. Tweak it to your liking. - It breaks the use of several relative scrolling commands in the same command. Use |MiniAnimate.execute_after()| to schedule action after reaching target window view. Example: a useful `nnoremap n nzvzz` mapping (consecutive application of |n|, |zv|, and |zz|) should be expressed in the following way: >lua 'lua vim.cmd("normal! n"); ' .. 'MiniAnimate.execute_after("scroll", "normal! zvzz")' < - Default timing might conflict with scrolling via holding a key (like `j` or `k` with 'wrap' enabled) due to high key repeat rate: next scroll is done before first step of current one finishes. Resolve this by not scrolling like that or by ensuring maximum value of step duration to be lower than between repeated keys: set timing like `function(_, n) return math.min(250/n, 10) end` or use timing with constant step duration. Configuration example: >lua local animate = require('mini.animate') animate.setup({ scroll = { -- Animate for 200 milliseconds with linear easing timing = animate.gen_timing.linear({ duration = 200, unit = 'total' }), -- Animate equally but with at most 120 steps instead of default 60 subscroll = animate.gen_subscroll.equal({ max_output_steps = 120 }), } }) < After animation is done, `MiniAnimateDoneScroll` event is triggered. # Resize ~ *MiniAnimate.config.resize* This animation is triggered for window resize while having same layout of same windows. For example, it won't trigger when window is opened/closed or after something like |CTRL-W_K|. Its visualization step consists from setting certain sizes to all visible windows (last step being for "true" final sizes). Exact window step sizes and their number is controlled by `subresize` option. It is a callable which takes `sizes_from` and `sizes_to` arguments (both tables with window id as keys and dimension table as values) and returns array of same shaped data. Example: - Input: >lua -- First { [1000] = {width = 7, height = 5}, [1001] = {width = 7, height = 10} } -- Second { [1000] = {width = 9, height = 5}, [1001] = {width = 5, height = 10} } -- Means window 1000 increased its width by 2 in expense of window 1001 < - The following output demonstrates equal resizing: >lua { { [1000] = {width = 8, height = 5}, [1001] = {width = 6, height = 10} }, { [1000] = {width = 9, height = 5}, [1001] = {width = 5, height = 10} }, } < See |MiniAnimate.gen_subresize| for builtin subresize generators. Notes: - As resize animation is essentially a precisely scheduled non-blocking subresizes, this has two important interconnected consequences: - If another resize is attempted during the animation, it is done based on the **currently visible** window sizes. This might affect relative resizing. - It breaks the use of several relative resizing commands in the same command. Use |MiniAnimate.execute_after()| to schedule action after reaching target window sizes. Configuration example: >lua local is_many_wins = function(sizes_from, sizes_to) return vim.tbl_count(sizes_from) >= 3 end local animate = require('mini.animate') animate.setup({ resize = { -- Animate for 200 milliseconds with linear easing timing = animate.gen_timing.linear({ duration = 200, unit = 'total' }), -- Animate only if there are at least 3 windows subresize = animate.gen_subscroll.equal({ predicate = is_many_wins }), } }) < After animation is done, `MiniAnimateDoneResize` event is triggered. # Window open/close ~ *MiniAnimate.config.open* *MiniAnimate.config.close* These animations are similarly triggered for regular (non-floating) window open/close. Their visualization step consists from drawing empty floating window with customizable config and transparency. Exact window visualization characteristics are controlled by `winconfig` and `winblend` options. The `winconfig` option is a callable which takes window id (|window-ID|) as input and returns an array of floating window configs (as in `config` argument of |nvim_open_win()|). Its length determines number of animation steps. Example: - The following output results into two animation steps with second being upper left quarter of a first: >lua { { row = 0, col = 0, width = 10, height = 10, relative = 'editor', anchor = 'NW', focusable = false, zindex = 1, border = 'none', style = 'minimal', }, { row = 0, col = 0, width = 5, height = 5, relative = 'editor', anchor = 'NW', focusable = false, zindex = 1, border = 'none', style = 'minimal', }, } < The `winblend` option is similar to `timing` option: it is a callable which, given current and total step numbers, returns value of floating window's 'winblend' option. Note, that it is called for current step (so starts from 0), as opposed to `timing` which is called before step. Example: - Function `function(s, n) return 80 + 20 * s / n end` results in linear transition from `winblend` value of 80 to 100. See |MiniAnimate.gen_winconfig| for builtin window config generators. See |MiniAnimate.gen_winblend| for builtin window transparency generators. Configuration example: >lua local animate = require('mini.animate') animate.setup({ open = { -- Animate for 400 milliseconds with linear easing timing = animate.gen_timing.linear({ duration = 400, unit = 'total' }), -- Animate with wiping from nearest edge instead of default static one winconfig = animate.gen_winconfig.wipe({ direction = 'from_edge' }), -- Make bigger windows more transparent winblend = animate.gen_winblend.linear({ from = 80, to = 100 }), }, close = { -- Animate for 400 milliseconds with linear easing timing = animate.gen_timing.linear({ duration = 400, unit = 'total' }), -- Animate with wiping to nearest edge instead of default static one winconfig = animate.gen_winconfig.wipe({ direction = 'to_edge' }), -- Make bigger windows more transparent winblend = animate.gen_winblend.linear({ from = 100, to = 80 }), }, }) < After animation is done, `MiniAnimateDoneOpen` or `MiniAnimateDoneClose` event is triggered for `open` and `close` animation respectively. ------------------------------------------------------------------------------ *MiniAnimate.is_active()* `MiniAnimate.is_active`({animation_type}) Check animation activity Parameters ~ {animation_type} `(string)` One of supported animation types (entries of |MiniAnimate.config|, like `'cursor'`, etc.). Return ~ `(boolean)` Whether the animation is currently active. ------------------------------------------------------------------------------ *MiniAnimate.execute_after()* `MiniAnimate.execute_after`({animation_type}, {action}) Execute action after some animation is done Execute action immediately if animation is not active (checked with |MiniAnimate.is_active()|). Else, schedule its execution until after animation is done (on corresponding "done event", see |MiniAnimate-done-event|). Mostly meant to be used inside mappings. Example: A useful `nnoremap n nzvzz` mapping (consecutive application of |n|, |zv|, and |zz|) should be expressed in the following way: >lua 'lua vim.cmd("normal! n"); ' .. 'MiniAnimate.execute_after("scroll", "normal! zvzz")' < Parameters ~ {animation_type} `(string)` One of supported animation types (as in |MiniAnimate.is_active()|). {action} `(string|function)` Action to be executed. If string, executed as command (via |vim.cmd()|). ------------------------------------------------------------------------------ *MiniAnimate.animate()* `MiniAnimate.animate`({step_action}, {step_timing}, {opts}) Animate action This is equivalent to asynchronous execution of the following algorithm: - Call `step_action(0)` immediately after calling this function. Stop if action returned `false` or `nil`. - Wait `step_timing(1)` milliseconds. - Call `step_action(1)`. Stop if it returned `false` or `nil`. - Wait `step_timing(2)` milliseconds. - Call `step_action(2)`. Stop if it returned `false` or `nil`. - ... Notes: - Animation is also stopped on action error or if maximum number of steps is reached. - Asynchronous execution is done with |uv.new_timer()|. It only allows integer parts as repeat value. This has several implications: - Outputs of `step_timing()` are accumulated in order to preserve total execution time. - Any wait time less than 1 ms means that action will be executed immediately. Parameters ~ {step_action} `(function|table)` Callable which takes `step` (integer 0, 1, 2, etc. indicating current step) and executes some action. Its return value defines when animation should stop: values `false` and `nil` (equivalent to no explicit return) stop animation timer; any other continues it. {step_timing} `(function|table)` Callable which takes `step` (integer 1, 2, etc. indicating next step) and returns how many milliseconds to wait before executing this step action. {opts} `(table|nil)` Options. Possible fields: - - Maximum value of allowed step to execute. Default: 10000000. ------------------------------------------------------------------------------ *MiniAnimate.gen_timing* `MiniAnimate.gen_timing` Generate animation timing Each field corresponds to one family of progression which can be customized further by supplying appropriate arguments. This is a table with function elements. Call to actually get timing function. Example: >lua local animate = require('mini.animate') animate.setup({ cursor = { timing = animate.gen_timing.linear({ duration = 100, unit = 'total' }) }, }) < See also ~ |MiniIndentscope.gen_animation| for similar concept in 'mini.indentscope'. ------------------------------------------------------------------------------ *MiniAnimate.gen_timing.none()* `MiniAnimate.gen_timing.none`() Generate timing with no animation Show final result immediately. Usually better to use `enable` field in `config` if you want to disable animation. ------------------------------------------------------------------------------ *MiniAnimate.gen_timing.linear()* `MiniAnimate.gen_timing.linear`({opts}) Generate timing with linear progression Parameters ~ {opts} `(table|nil)` Options that control progression. Possible keys: - `(string)` - a subtype of progression. One of "in" (accelerating from zero speed), "out" (decelerating to zero speed), "in-out" (default; accelerating halfway, decelerating after). - `(number)` - duration (in ms) of a unit. Default: 20. - `(string)` - which unit's duration `opts.duration` controls. One of "step" (default; ensures average duration of step to be `opts.duration`) or "total" (ensures fixed total duration regardless of scope's range). Return ~ `(function)` Timing function (see |MiniAnimate-timing|). ------------------------------------------------------------------------------ *MiniAnimate.gen_timing.quadratic()* `MiniAnimate.gen_timing.quadratic`({opts}) Generate timing with quadratic progression Parameters ~ {opts} `(table|nil)` Options that control progression. Possible keys: - `(string)` - a subtype of progression. One of "in" (accelerating from zero speed), "out" (decelerating to zero speed), "in-out" (default; accelerating halfway, decelerating after). - `(number)` - duration (in ms) of a unit. Default: 20. - `(string)` - which unit's duration `opts.duration` controls. One of "step" (default; ensures average duration of step to be `opts.duration`) or "total" (ensures fixed total duration regardless of scope's range). Return ~ `(function)` Timing function (see |MiniAnimate-timing|). ------------------------------------------------------------------------------ *MiniAnimate.gen_timing.cubic()* `MiniAnimate.gen_timing.cubic`({opts}) Generate timing with cubic progression Parameters ~ {opts} `(table|nil)` Options that control progression. Possible keys: - `(string)` - a subtype of progression. One of "in" (accelerating from zero speed), "out" (decelerating to zero speed), "in-out" (default; accelerating halfway, decelerating after). - `(number)` - duration (in ms) of a unit. Default: 20. - `(string)` - which unit's duration `opts.duration` controls. One of "step" (default; ensures average duration of step to be `opts.duration`) or "total" (ensures fixed total duration regardless of scope's range). Return ~ `(function)` Timing function (see |MiniAnimate-timing|). ------------------------------------------------------------------------------ *MiniAnimate.gen_timing.quartic()* `MiniAnimate.gen_timing.quartic`({opts}) Generate timing with quartic progression Parameters ~ {opts} `(table|nil)` Options that control progression. Possible keys: - `(string)` - a subtype of progression. One of "in" (accelerating from zero speed), "out" (decelerating to zero speed), "in-out" (default; accelerating halfway, decelerating after). - `(number)` - duration (in ms) of a unit. Default: 20. - `(string)` - which unit's duration `opts.duration` controls. One of "step" (default; ensures average duration of step to be `opts.duration`) or "total" (ensures fixed total duration regardless of scope's range). Return ~ `(function)` Timing function (see |MiniAnimate-timing|). ------------------------------------------------------------------------------ *MiniAnimate.gen_timing.exponential()* `MiniAnimate.gen_timing.exponential`({opts}) Generate timing with exponential progression Parameters ~ {opts} `(table|nil)` Options that control progression. Possible keys: - `(string)` - a subtype of progression. One of "in" (accelerating from zero speed), "out" (decelerating to zero speed), "in-out" (default; accelerating halfway, decelerating after). - `(number)` - duration (in ms) of a unit. Default: 20. - `(string)` - which unit's duration `opts.duration` controls. One of "step" (default; ensures average duration of step to be `opts.duration`) or "total" (ensures fixed total duration regardless of scope's range). Return ~ `(function)` Timing function (see |MiniAnimate-timing|). ------------------------------------------------------------------------------ *MiniAnimate.gen_path* `MiniAnimate.gen_path` Generate cursor animation path For more information see |MiniAnimate.config.cursor|. This is a table with function elements. Call to actually get generator. Example: >lua local animate = require('mini.animate') animate.setup({ cursor = { -- Animate with line-column angle instead of shortest line path = animate.gen_path.angle(), } }) < ------------------------------------------------------------------------------ *MiniAnimate.gen_path.line()* `MiniAnimate.gen_path.line`({opts}) Generate path as shortest line Parameters ~ {opts} `(table|nil)` Options that control generator. Possible keys: - `(function)` - a callable which takes `destination` as input and returns boolean value indicating whether animation should be done. Default: `false` if `destination` is within one line of origin (reduces flickering), `true` otherwise. - `(number)` - maximum number of steps in output. Default: 1000. Return ~ `(function)` Path function (see |MiniAnimate.config.cursor|). ------------------------------------------------------------------------------ *MiniAnimate.gen_path.angle()* `MiniAnimate.gen_path.angle`({opts}) Generate path as line/column angle Parameters ~ {opts} `(table|nil)` Options that control generator. Possible keys: - `(function)` - a callable which takes `destination` as input and returns boolean value indicating whether animation should be done. Default: `false` if `destination` is within one line of origin (reduces flickering), `true` otherwise. - `(number)` - maximum number of steps per side in output. Default: 1000. - `(string)` - one of `"horizontal"` (default; animates across initial line first) or `"vertical"` (animates across initial column first). Return ~ `(function)` Path function (see |MiniAnimate.config.cursor|). ------------------------------------------------------------------------------ *MiniAnimate.gen_path.walls()* `MiniAnimate.gen_path.walls`({opts}) Generate path as closing walls at final position Parameters ~ {opts} `(table|nil)` Options that control generator. Possible keys: - `(function)` - a callable which takes `destination` as input and returns boolean value indicating whether animation should be done. Default: `false` if `destination` is within one line of origin (reduces flickering), `true` otherwise. - `(number)` - initial width of left and right walls. Default: 10. Return ~ `(function)` Path function (see |MiniAnimate.config.cursor|). ------------------------------------------------------------------------------ *MiniAnimate.gen_path.spiral()* `MiniAnimate.gen_path.spiral`({opts}) Generate path as diminishing spiral at final position Parameters ~ {opts} `(table|nil)` Options that control generator. Possible keys: - `(function)` - a callable which takes `destination` as input and returns boolean value indicating whether animation should be done. Default: `false` if `destination` is within one line of origin (reduces flickering), `true` otherwise. - `(number)` - initial width of spiral. Default: 2. Return ~ `(function)` Path function (see |MiniAnimate.config.cursor|). ------------------------------------------------------------------------------ *MiniAnimate.gen_subscroll* `MiniAnimate.gen_subscroll` Generate scroll animation subscroll For more information see |MiniAnimate.config.scroll|. This is a table with function elements. Call to actually get generator. Example: >lua local animate = require('mini.animate') animate.setup({ scroll = { -- Animate equally but with 120 maximum steps instead of default 60 subscroll = animate.gen_subscroll.equal({ max_output_steps = 120 }), } }) < ------------------------------------------------------------------------------ *MiniAnimate.gen_subscroll.equal()* `MiniAnimate.gen_subscroll.equal`({opts}) Generate subscroll with equal steps Parameters ~ {opts} `(table|nil)` Options that control generator. Possible keys: - `(function)` - a callable which takes `total_scroll` as input and returns boolean value indicating whether animation should be done. Default: `false` if `total_scroll` is 1 or less (reduces unnecessary waiting), `true` otherwise. - `(number)` - maximum number of subscroll steps in output. Adjust this to reduce computations in expense of reduced smoothness. Default: 60. Return ~ `(function)` Subscroll function (see |MiniAnimate.config.scroll|). ------------------------------------------------------------------------------ *MiniAnimate.gen_subresize* `MiniAnimate.gen_subresize` Generate resize animation subresize For more information see |MiniAnimate.config.resize|. This is a table with function elements. Call to actually get generator. Example: >lua local is_many_wins = function(sizes_from, sizes_to) return vim.tbl_count(sizes_from) >= 3 end local animate = require('mini.animate') animate.setup({ resize = { -- Animate only if there are at least 3 windows subresize = animate.gen_subresize.equal({ predicate = is_many_wins }), } }) < ------------------------------------------------------------------------------ *MiniAnimate.gen_subresize.equal()* `MiniAnimate.gen_subresize.equal`({opts}) Generate subresize with equal steps Parameters ~ {opts} `(table|nil)` Options that control generator. Possible keys: - `(function)` - a callable which takes `sizes_from` and `sizes_to` as input and returns boolean value indicating whether animation should be done. Default: always `true`. Return ~ `(function)` Subresize function (see |MiniAnimate.config.resize|). ------------------------------------------------------------------------------ *MiniAnimate.gen_winconfig* `MiniAnimate.gen_winconfig` Generate open/close animation winconfig For more information see |MiniAnimate.config.open| or |MiniAnimate.config.close|. This is a table with function elements. Call to actually get generator. Example: >lua local is_not_single_window = function(win_id) local tabpage_id = vim.api.nvim_win_get_tabpage(win_id) return #vim.api.nvim_tabpage_list_wins(tabpage_id) > 1 end local animate = require('mini.animate') animate.setup({ open = { -- Animate with wiping from nearest edge instead of default static one -- and only if it is not a single window in tabpage winconfig = animate.gen_winconfig.wipe({ predicate = is_not_single_window, direction = 'from_edge', }), }, close = { -- Animate with wiping to nearest edge instead of default static one -- and only if it is not a single window in tabpage winconfig = animate.gen_winconfig.wipe({ predicate = is_not_single_window, direction = 'to_edge', }), }, }) < ------------------------------------------------------------------------------ *MiniAnimate.gen_winconfig.static()* `MiniAnimate.gen_winconfig.static`({opts}) Generate winconfig for static floating window This will result into floating window statically covering whole target window. Parameters ~ {opts} `(table|nil)` Options that control generator. Possible keys: - `(function)` - a callable which takes `win_id` as input and returns boolean value indicating whether animation should be done. Default: always `true`. - `(number)` - number of output steps, all with same config. Useful to tweak smoothness of transparency animation (done inside `winblend` config option). Default: 25. Return ~ `(function)` Winconfig function (see |MiniAnimate.config.open| or |MiniAnimate.config.close|). ------------------------------------------------------------------------------ *MiniAnimate.gen_winconfig.center()* `MiniAnimate.gen_winconfig.center`({opts}) Generate winconfig for center-focused animated floating window This will result into floating window growing from or shrinking to the target window center. Parameters ~ {opts} `(table|nil)` Options that control generator. Possible keys: - `(function)` - a callable which takes `win_id` as input and returns boolean value indicating whether animation should be done. Default: always `true`. - `(string)` - one of `"to_center"` (default; window will shrink from full coverage to center) or `"from_center"` (window will grow from center to full coverage). Return ~ `(function)` Winconfig function (see |MiniAnimate.config.open| or |MiniAnimate.config.close|). ------------------------------------------------------------------------------ *MiniAnimate.gen_winconfig.wipe()* `MiniAnimate.gen_winconfig.wipe`({opts}) Generate winconfig for wiping animated floating window This will result into floating window growing from or shrinking to the nearest edge. This also takes into account the split type of target window: vertically split window will progress towards vertical edge; horizontally - towards horizontal. Parameters ~ {opts} `(table|nil)` Options that control generator. Possible keys: - `(function)` - a callable which takes `win_id` as input and returns boolean value indicating whether animation should be done. Default: always `true`. - `(string)` - one of `"to_edge"` (default; window will shrink from full coverage to nearest edge) or `"from_edge"` (window will grow from edge to full coverage). Return ~ `(function)` Winconfig function (see |MiniAnimate.config.open| or |MiniAnimate.config.close|). ------------------------------------------------------------------------------ *MiniAnimate.gen_winblend* `MiniAnimate.gen_winblend` Generate open/close animation `winblend` progression For more information see |MiniAnimate.config.open| or |MiniAnimate.config.close|. This is a table with function elements. Call to actually get transparency function. Example: >lua local animate = require('mini.animate') animate.setup({ open = { -- Change transparency from 60 to 80 instead of default 80 to 100 winblend = animate.gen_winblend.linear({ from = 60, to = 80 }), }, close = { -- Change transparency from 60 to 80 instead of default 80 to 100 winblend = animate.gen_winblend.linear({ from = 60, to = 80 }), }, }) < ------------------------------------------------------------------------------ *MiniAnimate.gen_winblend.linear()* `MiniAnimate.gen_winblend.linear`({opts}) Generate linear `winblend` progression Parameters ~ {opts} `(table|nil)` Options that control generator. Possible keys: - `(number)` - initial value of 'winblend'. - `(number)` - final value of 'winblend'. Return ~ `(function)` Winblend function (see |MiniAnimate.config.open| or |MiniAnimate.config.close|). vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-base16.txt ================================================ *mini.base16* Base16 colorscheme creation MIT License Copyright (c) 2021 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniBase16* Fast implementation of [chriskempson/base16](https://github.com/chriskempson/base16) color scheme (with Copyright (C) 2012 Chris Kempson) adapted for modern Neovim Lua plugins. Extra features: - Configurable automatic support of cterm colors (see |highlight-cterm|). - Opinionated palette generator based only on background and foreground colors. Supported highlight groups: - Built-in Neovim LSP and diagnostic. - Plugins (either with explicit definition or by verification that default highlighting works appropriately): - [nvim-mini/mini.nvim](https://nvim-mini.org/mini.nvim) - [akinsho/bufferline.nvim](https://github.com/akinsho/bufferline.nvim) - [anuvyklack/hydra.nvim](https://github.com/anuvyklack/hydra.nvim) - [DanilaMihailov/beacon.nvim](https://github.com/DanilaMihailov/beacon.nvim) - [folke/lazy.nvim](https://github.com/folke/lazy.nvim) - [folke/noice.nvim](https://github.com/folke/noice.nvim) - [folke/snacks.nvim](https://github.com/folke/snacks.nvim) - [folke/todo-comments.nvim](https://github.com/folke/todo-comments.nvim) - [folke/trouble.nvim](https://github.com/folke/trouble.nvim) - [folke/which-key.nvim](https://github.com/folke/which-key.nvim) - [ggandor/leap.nvim](https://github.com/ggandor/leap.nvim) - [ggandor/lightspeed.nvim](https://github.com/ggandor/lightspeed.nvim) - [glepnir/dashboard-nvim](https://github.com/glepnir/dashboard-nvim) - [glepnir/lspsaga.nvim](https://github.com/glepnir/lspsaga.nvim) - [HiPhish/rainbow-delimiters.nvim](https://github.com/HiPhish/rainbow-delimiters.nvim) - [hrsh7th/nvim-cmp](https://github.com/hrsh7th/nvim-cmp) - [justinmk/vim-sneak](https://github.com/justinmk/vim-sneak) - [ibhagwan/fzf-lua](https://github.com/ibhagwan/fzf-lua) - [kevinhwang91/nvim-bqf](https://github.com/kevinhwang91/nvim-bqf) - [kevinhwang91/nvim-ufo](https://github.com/kevinhwang91/nvim-ufo) - [lewis6991/gitsigns.nvim](https://github.com/lewis6991/gitsigns.nvim) - [lukas-reineke/indent-blankline.nvim](https://github.com/lukas-reineke/indent-blankline.nvim) - [MeanderingProgrammer/render-markdown.nvim](https://github.com/MeanderingProgrammer/render-markdown.nvim) - [neoclide/coc.nvim](https://github.com/neoclide/coc.nvim) - [NeogitOrg/neogit](https://github.com/NeogitOrg/neogit) - [nvim-lualine/lualine.nvim](https://github.com/nvim-lualine/lualine.nvim) - [nvim-neo-tree/neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim) - [nvim-telescope/telescope.nvim](https://github.com/nvim-telescope/telescope.nvim) - [nvim-tree/nvim-tree.lua](https://github.com/nvim-tree/nvim-tree.lua) - [OXY2DEV/helpview.nvim](https://github.com/OXY2DEV/helpview.nvim) - [OXY2DEV/markview.nvim](https://github.com/OXY2DEV/markview.nvim) - [phaazon/hop.nvim](https://github.com/phaazon/hop.nvim) - [rcarriga/nvim-dap-ui](https://github.com/rcarriga/nvim-dap-ui) - [rcarriga/nvim-notify](https://github.com/rcarriga/nvim-notify) - [rlane/pounce.nvim](https://github.com/rlane/pounce.nvim) - [romgrk/barbar.nvim](https://github.com/romgrk/barbar.nvim) - [stevearc/aerial.nvim](https://github.com/stevearc/aerial.nvim) - [williamboman/mason.nvim](https://github.com/williamboman/mason.nvim) # Setup ~ This module needs a setup with `require('mini.base16').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniBase16` which you can use for scripting or manually (with `:lua MiniBase16.*`). See |MiniBase16.config| for `config` structure and default values. This module doesn't have runtime options, so using `vim.b.minibase16_config` will have no effect here. Example: >lua require('mini.base16').setup({ palette = { base00 = '#112641', base01 = '#3a475e', base02 = '#606b81', base03 = '#8691a7', base04 = '#d5dc81', base05 = '#e2e98f', base06 = '#eff69c', base07 = '#fcffaa', base08 = '#ffcfa0', base09 = '#cc7e46', base0A = '#46a436', base0B = '#9ff895', base0C = '#ca6ecf', base0D = '#42f7ff', base0E = '#ffc4ff', base0F = '#00a5c5', }, use_cterm = true, plugins = { default = false, ['nvim-mini/mini.nvim'] = true, }, }) < # Notes ~ 1. This is used to create some of plugin's color schemes (see |MiniBase16-color-schemes|). 2. Using `setup()` doesn't actually create a |:colorscheme|. It basically creates a coordinated set of |highlight-groups|. To create your own theme: - Put "myscheme.lua" file (name after your chosen theme name) inside any "colors" directory reachable from 'runtimepath' ("colors" inside your Neovim config directory is usually enough). - Inside "myscheme.lua" call `require('mini.base16').setup()` with your palette and only after that set |g:colors_name| to "myscheme". ------------------------------------------------------------------------------ *MiniBase16-color-schemes* # Base16 colorschemes ~ This module comes with several pre-built color schemes. Each of them is a |mini.base16| theme created with faster version of the following Lua code: >lua require('mini.base16').setup({ palette = palette, use_cterm = true }) < Activate them as regular |:colorscheme| (for example, `:colorscheme minischeme`). ## minischeme ~ *minischeme* Blue and yellow main colors with high contrast and saturation palette. Palettes are: >lua -- For dark 'background': MiniBase16.mini_palette('#112641', '#e2e98f', 75) -- For light 'background': MiniBase16.mini_palette('#e2e5ca', '#002a83', 75) < ## minicyan ~ *minicyan* Cyan and grey main colors with moderate contrast and saturation palette. Palettes are: >lua -- For dark 'background': MiniBase16.mini_palette('#0A2A2A', '#D0D0D0', 50) -- For light 'background': MiniBase16.mini_palette('#C0D2D2', '#262626', 80) < ------------------------------------------------------------------------------ *MiniBase16.setup()* `MiniBase16.setup`({config}) Module setup Setup is done by applying base16 palette to enable colorscheme. Highlight groups make an extended set from original [base16-vim](https://github.com/chriskempson/base16-vim/) plugin. It is a good idea to have `config.palette` respect the original [styling principles](https://github.com/chriskempson/base16/blob/master/styling.md). By default only 'gui highlighting' (see |highlight-gui| and |'termguicolors'|) is supported. To support 'cterm highlighting' (see |highlight-cterm|) supply `config.use_cterm` argument in one of the formats: - `true` to auto-generate from `palette` (as closest colors). - Table with similar structure to `palette` but having terminal colors (integers from 0 to 255) instead of hex strings. Parameters ~ {config} `(table)` Module config table. See |MiniBase16.config|. Usage ~ >lua require('mini.base16').setup({}) -- replace {} with your config table -- needs `palette` field present < ------------------------------------------------------------------------------ *MiniBase16.config* `MiniBase16.config` Defaults ~ >lua MiniBase16.config = { -- Table with names from `base00` to `base0F` and values being strings of -- HEX colors with format "#RRGGBB". NOTE: this should be explicitly -- supplied in `setup()`. palette = nil, -- Whether to support cterm colors. Can be boolean, `nil` (same as -- `false`), or table with cterm colors. See `setup()` documentation for -- more information. use_cterm = nil, -- Plugin integrations. Use `default = false` to disable all integrations. -- Also can be set per plugin (see |MiniBase16.config|). plugins = { default = true }, } < # Plugin integrations ~ `config.plugins` defines for which supported plugins highlight groups will be created. Limiting number of integrations slightly decreases startup time. It is a table with boolean (`true`/`false`) values which are applied as follows: - If plugin name (as listed in |mini.base16|) has entry, it is used. - Otherwise `config.plugins.default` is used. Example which will load only "mini.nvim" integration: >lua require('mini.base16').setup({ palette = require('mini.base16').mini_palette('#112641', '#e2e98f', 75), plugins = { default = false, ['nvim-mini/mini.nvim'] = true, } }) < ------------------------------------------------------------------------------ *MiniBase16.mini_palette()* `MiniBase16.mini_palette`({background}, {foreground}, {accent_chroma}) Create 'mini' palette Create base16 palette based on the HEX (string '#RRGGBB') colors of main background and foreground with optional setting of accent chroma (see details). # Algorithm design ~ - Main operating color space is [CIELCh(uv)](https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_(CIELCh)) which is a cylindrical representation of a perceptually uniform CIELUV color space. It defines color by three values: lightness L (values from 0 to 100), chroma (positive values), and hue (circular values from 0 to 360 degrees). Useful converting tool: https://www.easyrgb.com/en/convert.php - There are four important lightness values: background, foreground, focus (around the middle of background and foreground, leaning towards foreground), and edge (extreme lightness closest to foreground). - First four colors have the same chroma and hue as `background` but lightness progresses from background towards focus. - Second four colors have the same chroma and hue as `foreground` but lightness progresses from foreground towards edge in such a way that 'base05' color is main foreground color. - The rest eight colors are accent colors which are created in pairs - Each pair has same hue from set of hues 'most different' to background and foreground hues (if respective chorma is positive). - All colors have the same chroma equal to `accent_chroma` (if not provided, chroma of foreground is used, as they will appear next to each other). Note: this means that in case of low foreground chroma, it is a good idea to set `accent_chroma` manually. Values from 30 (low chorma) to 80 (high chroma) are common. - Within pair there is base lightness (equal to foreground lightness) and alternative (equal to focus lightness). Base lightness goes to colors which will be used more frequently in code: base08 (variables), base0B (strings), base0D (functions), base0E (keywords). How exactly accent colors are mapped to base16 palette is a result of trial and error. One rule of thumb was: colors within one hue pair should be more often seen next to each other. This is because it is easier to distinguish them and seems to be more visually appealing. That is why `base0D` and `base0F` have same hues because they usually represent functions and delimiter (brackets included). Parameters ~ {background} `(string)` Background HEX color (formatted as `#RRGGBB`). {foreground} `(string)` Foreground HEX color (formatted as `#RRGGBB`). {accent_chroma} `(number)` Optional positive number (usually between 0 and 100). Default: chroma of foreground color. Return ~ `(table)` Table with base16 palette. Usage ~ >lua local p = require('mini.base16').mini_palette('#112641', '#e2e98f', 75) require('mini.base16').setup({ palette = p }) < ------------------------------------------------------------------------------ *MiniBase16.rgb_palette_to_cterm_palette()* `MiniBase16.rgb_palette_to_cterm_palette`({palette}) Converts palette with RGB colors to terminal colors Useful for caching `use_cterm` variable to increase speed. Parameters ~ {palette} `(table)` Table with base16 palette (same as in `MiniBase16.config.palette`). Return ~ `(table)` Table with base16 palette using |highlight-cterm|. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-basics.txt ================================================ *mini.basics* Common configuration presets MIT License Copyright (c) 2023 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniBasics* Install, create 'init.lua', add `require('mini.basics').setup()`, and you are good to go. Features: - Presets for common options. It will only change option if it wasn't manually set before. See more in |MiniBasics.config.options|. - Presets for common mappings. It will only add a mapping if it wasn't manually created before. See more in |MiniBasics.config.mappings|. - Presets for common autocommands. See more in |MiniBasics.config.autocommands|. - Reverse compatibility is a high priority. Any decision to change already present behavior will be made with great care. Notes: - Main goal of this module is to provide a relatively easier way for new-ish Neovim users to have better "works out of the box" experience while having documented relevant options/mappings/autocommands to study. It is based partially on survey among Neovim users and partially is coming from personal preferences. However, more seasoned users almost surely will find something useful. Still, it is recommended to read about used options/mappings/autocommands and decide if they are needed. The main way to do that is by reading Neovim's help pages (linked in help file) and this module's source code (thoroughly documented for easier comprehension). # Setup ~ This module needs a setup with `require('mini.basics').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniBasics` which you can use for scripting or manually (with `:lua MiniBasics.*`). See |MiniBasics.config| for available config settings. To stop module from showing non-error feedback, set `config.silent = true`. # Comparisons ~ - [tpope/vim-sensible](https://github.com/tpope/vim-sensible): - Most of 'tpope/vim-sensible' is already incorporated as default options in Neovim (see |nvim-defaults|). This module has a much broader effect. - [tpope/vim-unimpaired](https://github.com/tpope/vim-unimpaired): - The 'tpope/vim-unimpaired' has mapping for toggling options with `yo` prefix. This module implements similar functionality with `\` prefix (see |MiniBasics.config.mappings|). ------------------------------------------------------------------------------ *MiniBasics.setup()* `MiniBasics.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniBasics.config|. Usage ~ >lua require('mini.basics').setup() -- use default config -- OR require('mini.basics').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniBasics.config* `MiniBasics.config` Defaults ~ >lua MiniBasics.config = { -- Options. Set field to `false` to disable. options = { -- Basic options ('number', 'ignorecase', and many more) basic = true, -- Extra UI features ('winblend', 'listchars', 'pumheight', ...) extra_ui = false, -- Presets for window borders ('single', 'double', ...) -- Default 'auto' infers from 'winborder' option win_borders = 'auto', }, -- Mappings. Set field to `false` to disable. mappings = { -- Basic mappings (better 'jk', save with Ctrl+S, ...) basic = true, -- Prefix for mappings that toggle common options ('wrap', 'spell', ...). -- Supply empty string to not create these mappings. option_toggle_prefix = [[\]], -- Window navigation with , resize with windows = false, -- Move cursor in Insert, Command, and Terminal mode with move_with_alt = false, }, -- Autocommands. Set field to `false` to disable autocommands = { -- Basic autocommands (highlight on yank, start Insert in terminal, ...) basic = true, -- Set 'relativenumber' only in linewise and blockwise Visual mode relnum_in_visual_mode = false, }, -- Whether to disable showing non-error feedback silent = false, } < # Options ~ *MiniBasics.config.options* Usage example: >lua require('mini.basics').setup({ options = { basic = true, extra_ui = true, win_borders = 'double', } }) < ## options.basic ~ The `config.options.basic` sets certain options to values which are quite commonly used (judging by study of available Neovim pre-configurations, public dotfiles, and surveys). Any option is changed only if it was not set manually beforehand. For exact changes, please see source code ('lua/mini/basics.lua'). Here is the list of affected options (put cursor on it and press |CTRL-]|): - General: - Sets || key to ||. Be sure to make all Leader mappings after this (otherwise they are made with default ). - Runs `:filetype plugin indent on` (see |:filetype-overview|) - |'backup'| - |'mouse'| - |'undofile'| - |'writebackup'| - Appearance - |'breakindent'| - |'cursorline'| - |'fillchars'| - |'linebreak'| - |'number'| - |'ruler'| - |'showmode'| - |'signcolumn'| - |'shortmess'| - |'splitbelow'| - |'splitkeep'| - |'splitright'| - |'termguicolors'| (on Neovim<0.10; later versions have it smartly enabled) - |'wrap'| - Editing - |'completeopt'| - |'formatoptions'| - |'ignorecase'| - |'incsearch'| - |'infercase'| - |'smartcase'| - |'smartindent'| - |'virtualedit'| ## options.extra_ui ~ The `config.options.extra_ui` sets certain options for visual appearance which might not be aligned with common preferences, but still worth trying. Any option is changed only if it was not set manually beforehand. For exact changes, please see source code ('lua/mini/basics.lua'). List of affected options: - |'list'| - |'listchars'| - |'pumblend'| - |'pumheight'| - |'winblend'| - Runs `:syntax on` (see |:syntax-on|) ## options.win_borders ~ The `config.options.win_borders` updates |'fillchars'| to have a consistent set of characters for window border (`vert`, `horiz`, `msgsep`, etc.). Available values: - `'auto'` - infer from |'winborder'|. On Neovim<0.11 do nothing. - `'bold'` - bold lines. - `'dot'` - dot in every cell. - `'double'` - double line. - `'single'` - single line. - `'solid'` - no symbol, only background. # Mappings ~ *MiniBasics.config.mappings* Usage example: >lua require('mini.basics').setup({ mappings = { basic = true, option_toggle_prefix = [[\]], windows = true, move_with_alt = true, } }) < If you want some mappings to be different or not made at all, set or delete them after calling |MiniBasics.setup()|. ## mappings.basic ~ The `config.mappings.basic` creates mappings for certain commonly mapped actions (judging by study of available Neovim pre-configurations and public dotfiles). Some of the mappings override built-in ones to either improve their behavior or override its default not very useful action. It will only add a mapping if it wasn't manually created before. Here is a table with created mappings : > |Keys | Modes | Description | |-------|-----------------|-----------------------------------------------| | j | Normal, Visual | Move down by visible lines with no [count] | | k | Normal, Visual | Move up by visible lines with no [count] | | go | Normal | Add [count] empty lines after cursor | | gO | Normal | Add [count] empty lines before cursor | | gy | Normal, Visual | Copy to system clipboard | | gp | Normal, Visual | Paste from system clipboard | | gV | Normal | Visually select latest changed or yanked text | | g/ | Visual | Search inside current visual selection | | * | Visual | Search forward for current visual selection | | # | Visual | Search backward for current visual selection | | | Normal, Visual, | Save and go to Normal mode | | | Insert | | < Notes: - See |[count]| for its meaning. - On Neovim>=0.10 mappings for `#` and `*` are not created as their enhanced variants are made built-in. See |v_star-default| and |v_#-default|. - On Neovim>=0.11 there are |[| / |]| for adding empty lines. The `gO` and `go` mappings are still created as they are more aligned with similarly purposed |O| and |o| keys (although sometimes conflict with |gO|). ## mappings.option_toggle_prefix ~ The `config.mappings.option_toggle_prefix` defines a prefix used for creating mappings that toggle common options. The result mappings will be ` + `. For example, with default value, `\w` will toggle |'wrap'|. Other viable choices for prefix are - `,` (as a mnemonic for several values to toggle). - `|` (as a same mnemonic). - `yo` (used in 'tpope/vim-unimpaired') - Something with || key, like `t` (`t` for "toggle"). Note: if your prefix contains `` key, make sure to set it before calling |MiniBasics.setup()| (as is done with default `basic` field of |MiniBasics.config.options|). After toggling, there will be a feedback about the current option value if prior to `require('mini.basics').setup()` module wasn't silenced (see "Silencing" section in |mini.basics|). It will only add a mapping if it wasn't manually created before. Here is a list of suffixes for created toggling mappings (all in Normal mode): - `b` - |'background'|. - `c` - |'cursorline'|. - `C` - |'cursorcolumn'|. - `d` - diagnostic (via |vim.diagnostic| functions). - `h` - |'hlsearch'| (or |v:hlsearch| to be precise). - `i` - |'ignorecase'|. - `l` - |'list'|. - `n` - |'number'|. - `r` - |'relativenumber'|. - `s` - |'spell'|. - `w` - |'wrap'|. ## mappings.windows ~ The `config.mappings.windows` creates mappings for easiere window manipulation. It will only add a mapping if it wasn't manually created before. Here is a list with created Normal mode mappings (all respect |[count]|): - Window navigation: - `` - focus on left window (see |CTRL-W_H|). - `` - focus on below window (see |CTRL-W_J|). - `` - focus on above window (see |CTRL-W_K|). - `` - focus on right window (see |CTRL-W_L|). - Window resize (all use arrow keys; variants of |:resize|; respect |[count]|): - `` - decrease window width. - `` - decrease window height. - `` - increase window height. - `` - increase window width. ## mappings.move_with_alt ~ The `config.mappings.move_with_alt` creates mappings for a more consistent cursor move in Insert, Command, and Terminal modes. For example, it proves useful in combination of autopair plugin (like |mini.pairs|) to move right outside of inserted pairs (no matter what the pair is). It will only add a mapping if it wasn't manually created before. Here is a list of created mappings (`` means `Alt`/`Meta` plus `x`): - `` - move cursor left. Modes: Insert, Terminal, Command. - `` - move cursor down. Modes: Insert, Terminal. - `` - move cursor up. Modes: Insert, Terminal. - `` - move cursor right. Modes: Insert, Terminal, Command. # Autocommands ~ *MiniBasics.config.autocommands* Usage example: >lua require('mini.basics').setup({ autocommands = { basic = true, relnum_in_visual_mode = true, } }) < ## autocommands.basic ~ The `config.autocommands.basic` creates some common autocommands: - Starts insert mode when opening terminal (see |:startinsert| and |TermOpen|). - Highlights yanked text for a brief period of time (see |vim.hl.on_yank()|; on Neovim<0.11 - |vim.hl.on_yank()|) and |TextYankPost|). ## autocommands.relnum_in_visual_mode ~ The `config.autocommands.relnum_in_visual_mode` creates autocommands that enable |'relativenumber'| in linewise and blockwise Visual modes and disable otherwise. See |ModeChanged|. ------------------------------------------------------------------------------ *MiniBasics.toggle_diagnostic()* `MiniBasics.toggle_diagnostic`() Toggle diagnostic for current buffer This uses |vim.diagnostic| functions per buffer. Return ~ `(string)` String indicator for new state. Similar to what |:set| `{option}?` shows. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-bracketed.txt ================================================ *mini.bracketed* Go forward/backward with square brackets MIT License Copyright (c) 2023 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniBracketed* Features: - Configurable Lua functions to go forward/backward to a certain target. Each function can be customized with: - Direction. One of "forward", "backward", "first" (forward starting from first one), "last" (backward starting from last one). - Number of times to go. - Whether to wrap on edges (going forward on last one goes to first). - Some other target specific options. - Mappings using square brackets. They are created using configurable target suffix and can be selectively disabled. Each mapping supports |[count]|. Mappings are created in Normal mode; for targets which move cursor in current buffer also Visual and Operator-pending (with dot-repeat) modes are supported. Using `lower-suffix` and `upper-suffix` (lower and upper case suffix) for a single target the following mappings are created: - `[` + `upper-suffix` : go first. - `[` + `lower-suffix` : go backward. - `]` + `lower-suffix` : go forward. - `]` + `upper-suffix` : go last. - Supported targets (for more information see help for corresponding Lua function): `Target` `Mappings` `Lua function` Buffer ......................... `[B` `[b` `]b` `]B` .... |MiniBracketed.buffer()| Comment block .................. `[C` `[c` `]c` `]C` .... |MiniBracketed.comment()| Conflict marker ................ `[X` `[x` `]x` `]X` .... |MiniBracketed.conflict()| Diagnostic ..................... `[D` `[d` `]d` `]D` .... |MiniBracketed.diagnostic()| File on disk ................... `[F` `[f` `]f` `]F` .... |MiniBracketed.file()| Indent change .................. `[I` `[i` `]i` `]I` .... |MiniBracketed.indent()| Jump inside current buffer ..... `[J` `[j` `]j` `]J` .... |MiniBracketed.jump()| Location from |location-list| .... `[L` `[l` `]l` `]L` .... |MiniBracketed.location()| Old files ...................... `[O` `[o` `]o` `]O` .... |MiniBracketed.oldfile()| Quickfix entry from |Quickfix| ... `[Q` `[q` `]q` `]Q` .... |MiniBracketed.quickfix()| Tree-sitter node and parents ... `[T` `[t` `]t` `]T` .... |MiniBracketed.treesitter()| Undo from linear history ....... `[U` `[u` `]u` `]U` .... |MiniBracketed.undo()| Window in current tab .......... `[W` `[w` `]w` `]W` .... |MiniBracketed.window()| Yank entry over put region ..... `[Y` `[y` `]y` `]Y` .... |MiniBracketed.yank()| Notes: - The `undo` target remaps |u| and |CTRL-R| keys to register undo state after undo and redo respectively. If this conflicts with your setup, either disable `undo` target or make your remaps after calling |MiniBracketed.setup()|. To use `undo` target, remap your undo/redo keys to call |MiniBracketed.register_undo_state()| after the action. # Setup ~ This module needs a setup with `require('mini.bracketed').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniBracketed` which you can use for scripting or manually (with `:lua MiniBracketed.*`). See |MiniBracketed.config| for available config settings. You can override runtime config settings (like target options) locally to buffer inside `vim.b.minibracketed_config` which should have same structure as `MiniBracketed.config`. See |mini.nvim-buffer-local-config| for more details. # Comparisons ~ - [tpope/vim-unimpaired](https://github.com/tpope/vim-unimpaired): - Supports buffer, conflict, file, location, and quickfix targets mostly via built-in commands (like |:bprevious|, etc.) without configuration. - Supports files from argument list and tags. This module does not. - Doesn't support most other this module's targets (comment, indent, ...). - |mini.indentscope|: - Target |MiniBracketed.indent()| target can go to "first" and "last" indent change. It also can go not only to line with smaller indent, but also bigger or different one. - Mappings from 'mini.indentscope' have more flexibility in computation of indent scope, like how to treat empty lines near border or whether to compute indent at cursor. # Disabling ~ To disable, set `vim.g.minibracketed_disable` (globally) or `vim.b.minibracketed_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniBracketed.setup()* `MiniBracketed.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniBracketed.config|. Usage ~ >lua require('mini.bracketed').setup() -- use default config -- OR require('mini.bracketed').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniBracketed.config* `MiniBracketed.config` Defaults ~ >lua MiniBracketed.config = { -- First-level elements are tables describing behavior of a target: -- -- - - single character suffix. Used after `[` / `]` in mappings. -- For example, with `b` creates `[B`, `[b`, `]b`, `]B` mappings. -- Supply empty string `''` to not create mappings. -- -- - - table overriding target options. -- -- See `:h MiniBracketed.config` for more info. buffer = { suffix = 'b', options = {} }, comment = { suffix = 'c', options = {} }, conflict = { suffix = 'x', options = {} }, diagnostic = { suffix = 'd', options = {} }, file = { suffix = 'f', options = {} }, indent = { suffix = 'i', options = {} }, jump = { suffix = 'j', options = {} }, location = { suffix = 'l', options = {} }, oldfile = { suffix = 'o', options = {} }, quickfix = { suffix = 'q', options = {} }, treesitter = { suffix = 't', options = {} }, undo = { suffix = 'u', options = {} }, window = { suffix = 'w', options = {} }, yank = { suffix = 'y', options = {} }, } < Options ~ Each entry configures target with the same name and can have data configuring mapping suffix and target options. Example of configuration: >lua require('mini.bracketed').setup({ -- Map [N, [n, ]n, ]N for conflict marker like in 'tpope/vim-unimpaired' conflict = { suffix = 'n' }, -- Make diagnostic advance only by errors diagnostic = { options = { severity = vim.diagnostic.severity.ERROR } }, -- Disable creation of mappings for `indent` target (for example, -- in favor of ones from |mini.indentscope|) indent = { suffix = '' }, -- Disable mappings for `window` target in favor of custom ones window = { suffix = '' }, }) -- Create custom `window` mappings local map = vim.keymap.set map('n', 'wH', "lua MiniBracketed.window('first')") map('n', 'wh', "lua MiniBracketed.window('backward')") map('n', 'wl', "lua MiniBracketed.window('forward')") map('n', 'wL', "lua MiniBracketed.window('last')") < ## Suffix ~ The `suffix` key is used to create target mappings. Supply empty string to disable mapping creation for that particular target. To create a completely different mapping (like with ||) use target function manually. Using `lower-suffix` and `upper-suffix` (lower and upper case suffix) for a single target the following mappings are created: - `[` + `upper-suffix` : go first. - `[` + `lower-suffix` : go backward. - `]` + `lower-suffix` : go forward. - `]` + `upper-suffix` : go last. When supplied with a non-letter, only forward/backward mappings are created. ## Options ~ The `options` key is directly forwarded as `opts` to corresponding Lua function. ------------------------------------------------------------------------------ *MiniBracketed.buffer()* `MiniBracketed.buffer`({direction}, {opts}) Listed buffer Go to next/previous listed buffer. Order by their number (see |bufnr()|). Direction "forward" increases number, "backward" - decreases. Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. ------------------------------------------------------------------------------ *MiniBracketed.comment()* `MiniBracketed.comment`({direction}, {opts}) Comment block Go to next/previous comment block. Only linewise comments using 'commentsring' are recognized. Direction "forward" increases line number, "backward" - decreases. Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. - (`boolean`) - Whether to add current position to jumplist. Default: `false`. - `(string)` - which side of comment block to use. One of "near" (default; use nearest side), "start" (use first line), "end" (use last line), "both" (use both first and last lines). ------------------------------------------------------------------------------ *MiniBracketed.conflict()* `MiniBracketed.conflict`({direction}, {opts}) Git conflict marker Go to next/previous lines containing Git conflict marker. That is, if it starts with "<<<<<<< ", ">>>>>>> ", or is "=======". Direction "forward" increases line number, "backward" - decreases. Notes: - Using this target in Operator-pending mode allows the following approach at resolving merge conflicts: - Place cursor on `=======` line. - Execute one of these: `d]x[xdd` (choose upper part) or `d[x]xdd` (choose lower part). Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. - (`boolean`) - Whether to add current position to jumplist. Default: `false`. ------------------------------------------------------------------------------ *MiniBracketed.diagnostic()* `MiniBracketed.diagnostic`({direction}, {opts}) Diagnostic Go to next/previous diagnostic. This is mostly similar to built-in |vim.diagnostic.jump()| (on Neovim<0.11 it is |vim.diagnostic.goto_next()| and |vim.diagnostic.goto_prev()|) which has an interface and behavior consistent with other methods of the module. Direction "forward" increases line number, "backward" - decreases. Notes: - Using `severity` option, this target can be used in mappings like "go to next/previous error" (), etc. Using code similar to this: >lua local severity_error = vim.diagnostic.severity.ERROR -- Use these inside custom mappings MiniBracketed.diagnostic('forward', { severity = severity_error }) MiniBracketed.diagnostic('backward', { severity = severity_error }) < Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. - `(boolean|table)` - control floating window after movement. For available values see |vim.diagnostic.goto_next()|. - `(string|table)` - which severity to use. For available values see |diagnostic-severity|. ------------------------------------------------------------------------------ *MiniBracketed.file()* `MiniBracketed.file`({direction}, {opts}) File on disk Go to next/previous file on disk alphabetically. Files are taken from directory of file in current buffer (or current working directory if buffer doesn't contain a readable file). Only first-level files are used, i.e. it doesn't go inside subdirectories. Direction "forward" goes forward alphabetically, "backward" - backward. Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. ------------------------------------------------------------------------------ *MiniBracketed.indent()* `MiniBracketed.indent`({direction}, {opts}) Indent change Go to next/previous line with different indent (see |indent()|). Can be used to go to lines with smaller, bigger, or different indent. Notes: - Directions "first" and "last" work differently from most other targets for performance reasons. They are essentially "backward" and "forward" with very big `n_times` option. - For similar reasons, `wrap` is not supported. - Blank line inherit indent from near non-blank line in direction of movement. Direction "forward" increases line number, "backward" - decreases. Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - (`boolean`) - Whether to add current position to jumplist. Default: `false`. - `(string)` - which type of indent change to use. One of "less" (default; smaller indent), "more" (bigger indent), "diff" (different indent). ------------------------------------------------------------------------------ *MiniBracketed.jump()* `MiniBracketed.jump`({direction}, {opts}) Jump inside current buffer Go to next/previous jump from |jumplist| which is inside current buffer. Notes: - There are no Visual mode mappings due to implementation problems. Direction "forward" increases jump number, "backward" - decreases. Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. ------------------------------------------------------------------------------ *MiniBracketed.location()* `MiniBracketed.location`({direction}, {opts}) Location from location list Go to next/previous location from |location-list|. This is similar to |:lfirst|, |:lprevious|, |:lnext|, and |:llast| but with support of wrapping around edges and |[count]| for "first"/"last" direction. Direction "forward" increases location number, "backward" - decreases. Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. ------------------------------------------------------------------------------ *MiniBracketed.oldfile()* `MiniBracketed.oldfile`({direction}, {opts}) Old files from previous and current sessions Go to older/newer readable file either from previous session (see |v:oldfiles|) or the current one (updated automatically after |MiniBracketed.setup()| call). Direction "forward" goes to more recent files, "backward" - to older. Notes: - In current session it tracks only normal buffers (see |'buftype'|) for some readable file. - No new file is tracked when advancing this target. Only after buffer change is done not through this target (like with |MiniBracketed.buffer()|), it updates recency of last advanced and new buffers. Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. ------------------------------------------------------------------------------ *MiniBracketed.quickfix()* `MiniBracketed.quickfix`({direction}, {opts}) Quickfix from quickfix list Go to next/previous entry from |quickfix| list. This is similar to |:cfirst|, |:cprevious|, |:cnext|, and |:clast| but with support of wrapping around edges and |[count]| for "first"/"last" direction. Direction "forward" increases location number, "backward" - decreases. Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. ------------------------------------------------------------------------------ *MiniBracketed.treesitter()* `MiniBracketed.treesitter`({direction}, {opts}) Tree-sitter node Go to end/start of current tree-sitter node and its parents (except root). Notes: - Requires loaded tree-sitter parser in the current buffer. - Directions "first" and "last" work differently from most other targets for performance reasons. They are essentially "backward" and "forward" with very big `n_times` option. - For similar reasons, `wrap` is not supported. Direction "forward" moves cursor forward to node's end, "backward" - backward to node's start. Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - (`boolean`) - Whether to add current position to jumplist. Default: `false`. ------------------------------------------------------------------------------ *MiniBracketed.undo()* `MiniBracketed.undo`({direction}, {opts}) Undo along a tracked linear history In a nutshell: - Keys |u| and |CTRL-R| (although remapped) can be used as usual, but every their execution new state is recorded in this module's linear undo history. - Advancing this target goes along linear undo history revealing undo states **in order they actually appeared**. - One big difference with built-in methods is that tracked linear history can repeat undo states (not consecutively, though). Neovim's default way of managing undo history is through branches (see |undo-branches|). Basically it means that if you undo several changes and then make new ones, it creates new undo branch while usually (see |'undolevels'|) saving previous buffer states in another branch. While there are commands to navigate by time of undo state creation (like |:earlier| and |:later|), there is no intuitive way to cycle through them. Existing |g-| and |g+| cycle through undo states **based on their creation time**, which often gets confusing really guickly in extensively edited buffer. This `undo()` target provides a way to cycle through linear undo history **in order states actually appeared**. It does so by registering any new undo states plus every time |MiniBracketed.register_undo_state()| is called. To have more "out of the box" experience, |u| and |CTRL-R| are remapped to call it after they perform their undo/redo. Example: To show more clearly the difference between advancing this target and using built-in functionality, here is an example: - Create undo history in a new buffer (|:new|): - Enter `one two three` text. - Delete first word with `daw` and undo the change with `u`. - Delete second word with `daw` and undo the change with `u`. - Delete third word with `daw` and undo the change with `u`. - Now try one of the following (each one after performing previous steps in separate new buffer): - Press `u`. It goes back to empty buffer. Press `` twice and it goes to the latest change (`one two`). No way to get to other states (like `two three` or `one three`) with these two keys. - Press `g-`. It goes to an empty buffer. Press `g+` 4 times. It cycles through all available undo states **in order they were created**. - Finally, press `[u`. It goes back to `one two` - state which was **previously visited** by the user. Another `[u` restores `one two three`. Use `]U` to go to latest visited undo state. Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. ------------------------------------------------------------------------------ *MiniBracketed.register_undo_state()* `MiniBracketed.register_undo_state`() Register state for undo target Use this function to add current undo state to this module's linear undo history. It is used in |MiniBracketed.setup()| to remap |u| and |CTRL-R| keys to add their new state to linear undo history. ------------------------------------------------------------------------------ *MiniBracketed.window()* `MiniBracketed.window`({direction}, {opts}) Normal window Go to next/previous normal window. Order by their number (see |winnr()|). Direction "forward" increases window number, "backward" - decreases. Only normal (non-floating) windows are used. Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. ------------------------------------------------------------------------------ *MiniBracketed.yank()* `MiniBracketed.yank`({direction}, {opts}) Replace "latest put region" with yank history entry After |MiniBracketed.setup()| is called, on every yank/delete/change operation (technically, every trigger of |TextYankPost| event) the object of operation is added to yank history. Advancing this target will replace the region of latest put operation with entry from yank history. By default works best if called **right after** text paste (like with |p| or |P|). To better detect "latest put region", use |MiniBracketed.register_put_region()| as described later. Direction "forward" goes to newer yank history entry, "backward" - to older. Example: - Type `one two three`. - Yank each word with `yiw`. - Create new line and press `p`. This should paste `three`. - Type `[y`. This should replace latest `three` with `two`. # Latest put region ~ "Latest put region" is (in order of decreasing priority): - The one from latest advance of this target. - The one registered by user with |MiniBracketed.register_put_region()|. - The one taken from |'[| and |']| marks. For users there are these approaches to manage which region will be used: - Do nothing. In this case region between `[` / `]` marks will always be used for first `yank` advance. Although doable, this has several drawbacks: it will use latest yanked or changed region or the entire buffer if marks are not set. If remember to advance this target only after recent put operation, this should work as expected. - Remap common put operations to use |MiniBracketed.register_put_region()|. After that, only regions from mapped put operations will be used for first advance. Example of custom mappings (note use of |:map-expression|): >lua local put_keys = { 'p', 'P' } for _, lhs in ipairs(put_keys) do local rhs = 'v:lua.MiniBracketed.register_put_region("' .. lhs .. '")' vim.keymap.set({ 'n', 'x' }, lhs, rhs, { expr = true }) end < Parameters ~ {direction} `(string)` One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(boolean)` - Whether to wrap around edges. Default: `true`. - `(table)` - array of operator names ("c", "d", or "y") for which yank entry should be used to advance. For example, use `{ "y" }` to advance only by entries actually resulted from yank operation with |y|. Default: `{ 'c', 'd', 'y' }`. ------------------------------------------------------------------------------ *MiniBracketed.register_put_region()* `MiniBracketed.register_put_region`({put_key}) Register "latest put region" This function should be called after put register becomes relevant (|v:register| is appropriately set) but before put operation takes place (|'[| and |']| marks become relevant). Designed to be used in a user-facing expression mapping (see |:map-expression|). For mapping examples see |MiniBracketed.yank()|. Parameters ~ {put_key} `(string)` Put keys to be remapped. Return ~ `(string)` Returns `put_key` for a better usage inside expression mappings. ------------------------------------------------------------------------------ *MiniBracketed.advance()* `MiniBracketed.advance`({iterator}, {direction}, {opts}) Advance iterator This is the main function which performs any forward/backward/first/last advance in this module. Its basic idea is to take iterator (object containing information about current state and how to go to next/previous one) and go in certain direction until needed/allowed. Notes: - Directions "first" and "last" are convenience wrappers for "forward" and "backward" with pre-setting initial state to `start_edge` and `end_edge`. - Iterators `next()` and `prev()` methods should be able to handle `nil` as input. - This function only returns new state and doesn't modify `iterator.state`. Parameters ~ {iterator} `(table)` Table: - Methods: - - given state, return state in forward direction (no wrap). - - given state, return state in backward direction (no wrap). - Fields: - - object describing current state. - (optional) - object with `forward(start_edge)` describing first state. If `nil`, can't wrap forward or use direction "first". - (optional) - object with `backward(end_edge)` describing last state. If `nil`, can't wrap backward or use direction "last". {direction} `(string)` Direction. One of "first", "backward", "forward", "last". {opts} `(table|nil)` Options with the following keys: - `(number)` - number of times to go in input direction. Default: `v:count1`. - `(boolean)` - whether to wrap around edges when `next()` or `prev()` return `nil`. Default: `true`. Return ~ `(any)` Result state. If `nil`, could not reach any valid result state. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-bufremove.txt ================================================ *mini.bufremove* Remove buffers MIT License Copyright (c) 2021 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniBufremove* Features: - Unshow, delete, and wipeout buffer while saving window layout (opposite to builtin Neovim's commands). # Setup ~ This module doesn't need setup, but it can be done to improve usability. Setup with `require('mini.bufremove').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniBufremove` which you can use for scripting or manually (with `:lua MiniBufremove.*`). See |MiniBufremove.config| for `config` structure and default values. This module doesn't have runtime options, so using `vim.b.minibufremove_config` will have no effect here. To stop module from showing non-error feedback, set `config.silent = true`. # Notes ~ 1. Which buffer to show in window(s) after its current buffer is removed is decided by the algorithm: - If alternate buffer (see |CTRL-^|) is listed (see |buflisted()|), use it. - If previous listed buffer (see |:bprevious|) is different, use it. - Otherwise create a new one with `nvim_create_buf(true, false)` and use it. # Disabling ~ To disable core functionality, set `vim.g.minibufremove_disable` (globally) or `vim.b.minibufremove_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniBufremove.setup()* `MiniBufremove.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniBufremove.config|. Usage ~ >lua require('mini.bufremove').setup() -- use default config -- OR require('mini.bufremove').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniBufremove.config* `MiniBufremove.config` Defaults ~ >lua MiniBufremove.config = { -- Whether to disable showing non-error feedback silent = false, } < ------------------------------------------------------------------------------ *MiniBufremove.delete()* `MiniBufremove.delete`({buf_id}, {force}) Delete buffer `buf_id` with |:bdelete| after unshowing it Parameters ~ {buf_id} `(number|nil)` Buffer identifier (see |bufnr()|) to use. Default: 0 for current. {force} `(boolean|nil)` Whether to ignore unsaved changes (using `!` version of command). If `false`, calling with unsaved changes will prompt confirm dialog. Default: `false`. Return ~ `(boolean|nil)` Whether operation was successful. If `nil`, no operation was done. ------------------------------------------------------------------------------ *MiniBufremove.wipeout()* `MiniBufremove.wipeout`({buf_id}, {force}) Wipeout buffer `buf_id` with |:bwipeout| after unshowing it Parameters ~ {buf_id} `(number|nil)` Buffer identifier (see |bufnr()|) to use. Default: 0 for current. {force} `(boolean|nil)` Whether to ignore unsaved changes (using `!` version of command). If `false`, calling with unsaved changes will prompt confirm dialog. Default: `false`. Return ~ `(boolean|nil)` Whether operation was successful. If `nil`, no operation was done. ------------------------------------------------------------------------------ *MiniBufremove.unshow()* `MiniBufremove.unshow`({buf_id}) Stop showing buffer `buf_id` in all windows Parameters ~ {buf_id} `(number|nil)` Buffer identifier (see |bufnr()|) to use. Default: 0 for current. Return ~ `(boolean|nil)` Whether operation was successful. If `nil`, no operation was done. ------------------------------------------------------------------------------ *MiniBufremove.unshow_in_window()* `MiniBufremove.unshow_in_window`({win_id}) Stop showing current buffer of window `win_id` Notes: - If `win_id` represents |cmdline-window|, this function will close it. Parameters ~ {win_id} `(number|nil)` Window identifier (see |win_getid()|) to use. Default: 0 for current. Return ~ `(boolean|nil)` Whether operation was successful. If `nil`, no operation was done. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-clue.txt ================================================ *mini.clue* Show next key clues MIT License Copyright (c) 2023 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniClue* Features: - Implement custom key query process to reach target key combination: - Starts after customizable opt-in triggers (mode + keys). - Each key press narrows down set of possible targets. Pressing `` removes previous user entry. Pressing `` or `` leads to an early stop. Doesn't depend on 'timeoutlen' and has basic support for 'langmap'. - Ends when there is at most one target left or user pressed ``. Results into emulating pressing all query keys plus possible postkeys. - Show window (after configurable delay) with clues. It lists available next keys along with their descriptions (auto generated from descriptions present keymaps and user-supplied clues; preferring the former). - Configurable "postkeys" for key combinations - keys which will be emulated after combination is reached during key query process. - Provide customizable sets of clues for common built-in keys/concepts: - `g` key. - `z` key. - Window commands. - Built-in completion. - Marks. - Registers. - Lua functions to disable/enable triggers globally or per buffer. For more details see: - |MiniClue-key-query-process|. - |MiniClue-examples|. - |MiniClue.config|. - |MiniClue.gen_clues|. Notes: - There is no functionality to create mappings while defining clues. This is done to clearly separate these two different actions. The best suggested practice is to manually create mappings with descriptions (`desc` field in options), as they will be automatically used inside clue window. - Triggers are implemented as special buffer-local mappings. This leads to several caveats: - They will override same regular buffer-local mappings and have precedence over global one. Example: having set `` as Normal mode trigger means that there should not be another `` mapping. - They need to be the latest created buffer-local mappings or they will not function properly. Most common indicator of this is that some mapping starts to work only after clue window is shown. Example: `g` is set as Normal mode trigger, but `gcc` from |mini.comment| doesn't work right away. This is probably because there are some other buffer-local mappings starting with `g` which were created after mapping for `g` trigger. Most common places for this are in LSP server's `on_attach` or during tree-sitter start in buffer. To check if trigger is the most recent buffer-local mapping, execute `:map ` (like `:nmap g` for previous example). Mapping for trigger should be the first listed. This module makes the best effort to work out of the box and cover most common cases, but it is not foolproof. The solution here is to ensure that triggers are created after making all buffer-local mappings: run either |MiniClue.setup()| or |MiniClue.ensure_buf_triggers()|. - Descriptions from existing mappings take precedence over user-supplied clues. This is to ensure that information shown in clue window is as relevant as possible. To add/customize description of an already existing mapping, use |MiniClue.set_mapping_desc()|. - Due to technical difficulties, there is no foolproof support for Operator-pending mode triggers (like `a`/`i` from |mini.ai|): - Doesn't work as part of a command in "temporary Normal mode" (like after |i_CTRL-O|) due to implementation difficulties. - Can have unexpected behavior with custom operators. - Has (mostly solved) issues with macros: - All triggers are disabled during macro recording due to technical reasons. - The `@` and `Q` keys are specially mapped inside |MiniClue.setup()| (if the key is not already mapped) to temporarily disable triggers. # Setup ~ This module needs a setup with `require('mini.clue').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniClue` which you can use for scripting or manually (with `:lua MiniClue.*`). Config table **needs to have triggers configured**, none is set up by default. See |MiniClue.config| for available config settings. You can override runtime config settings (like clues or window options) locally to a buffer inside `vim.b.miniclue_config` which should have same structure as `MiniClue.config`. See |mini.nvim-buffer-local-config| for more details. # Comparisons ~ - [folke/which-key.nvim](https://github.com/folke/which-key.nvim): - Both have the same main goal: show available next keys along with their customizable descriptions. - Has different UI and content layout. - Allows creating mappings inside its configuration, while this module doesn't have this by design (to clearly separate two different tasks). - Doesn't allow creating submodes, while this module does (via `postkeys`). - [anuvyklack/hydra.nvim](https://github.com/anuvyklack/hydra.nvim): - Both allow creating submodes: state which starts at certain key combination; treats some keys differently; ends after ``. - Doesn't show information about available next keys (outside of submodes), while that is this module's main goal. # Highlight groups ~ - `MiniClueBorder` - window border. - `MiniClueDescGroup` - group description in clue window. - `MiniClueDescSingle` - single target description in clue window. - `MiniClueNextKey` - next key label in clue window. - `MiniClueNextKeyWithPostkeys` - next key label with postkeys in clue window. - `MiniClueSeparator` - separator in clue window. - `MiniClueTitle` - window title. To change any highlight group, set it directly with |nvim_set_hl()|. # Disabling ~ To disable creating triggers, set `vim.g.miniclue_disable` (globally) or `vim.b.miniclue_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniClue-key-query-process* # General info ~ This module implements custom key query process imitating a usual built-in mechanism of user pressing keys in order to execute a mapping. General idea is the same: narrow down key combinations until the target is reached. Main goals of its existence are: - Allow reaching certain mappings be independent of 'timeoutlen'. That is, there is no fixed timeout after which currently typed keys are executed. - Enable automated showing of next key clues after user-supplied delay (also independent of 'timeoutlen'). - Allow emulating configurable key presses after certain key combination is reached. This granular control allows creating so called "submodes". See more at |MiniClue-examples-submodes|. This process is primarily designed for nested `` mappings in Normal mode but works in all other main modes: Visual, Insert, Operator-pending (with caveats; no foolproof guarantees), Command-line, Terminal. # Lifecycle ~ - Key query process starts when user types a trigger: certain keys in certain mode. Those keys are put into key query as a single user input. All possible mode key combinations are filtered to ones starting with the trigger keys. Note: trigger is implemented as a regular mapping, so if it has at least two keys, they should be pressed within 'timeoutlen' milliseconds. - Wait (indefinitely) for user to press a key. Advance depending on the key: - Special key: - If `` or ``, stop the process without any action. - If ``, stop the process and execute current key query, meaning emulate (with |nvim_feedkeys()|) user pressing those keys. - If ``, remove previous user input from the query. If query becomes empty, stop the process without any action. - If a key for scrolling clue window (`scroll_down` / `scroll_up` in `config.window`; `` / `` by default), scroll clue window and wait for the next user key. Note: if clue window is not shown, treated as a not special key. - Not special key. Add key to the query while filtering all available key combinations to start with the current key query. Advance: - If there is a single available key combination matching current key query, execute it. - If there is no key combinations starting with the current query, execute it. This, for instance, allows a seamless execution of operators in presence of a longer key combinations. Example: with `g` as trigger in Normal mode and available mappings `gc` / `gcc` (like from |mini.comment|), this allows typing `gcip` to comment current paragraph, although there are no key combinations starting with `gci`. - Otherwise wait for the new user key press. # Clue window ~ After initiating key query process and after each key press, a timer is started to show a clue window: floating window with information about available next keys along with their descriptions. Note: if window is already shown, its content is updated right away. Clues can have these types: - "Terminal next key": when pressed, will lead to query execution. - "Terminal next key with postkeys": when pressed, will lead to query execution plus some configured postkeys. - "Group next key": when pressed, will narrow down available key combinations and wait for another key press. Note: can have configured description (inside `config.clues`) or it will be auto generated based on the number of available key combinations. ------------------------------------------------------------------------------ *MiniClue-examples* # Full starter example ~ If not sure where to start, try this example with all provided clues from this module plus all || mappings in Normal and Visual modes: >lua local miniclue = require('mini.clue') miniclue.setup({ triggers = { -- Leader triggers { mode = { 'n', 'x' }, keys = '' }, -- `[` and `]` keys { mode = 'n', keys = '[' }, { mode = 'n', keys = ']' }, -- Built-in completion { mode = 'i', keys = '' }, -- `g` key { mode = { 'n', 'x' }, keys = 'g' }, -- Marks { mode = { 'n', 'x' }, keys = "'" }, { mode = { 'n', 'x' }, keys = '`' }, -- Registers { mode = { 'n', 'x' }, keys = '"' }, { mode = { 'i', 'c' }, keys = '' }, -- Window commands { mode = 'n', keys = '' }, -- `z` key { mode = { 'n', 'x' }, keys = 'z' }, }, clues = { -- Enhance this by adding descriptions for mapping groups miniclue.gen_clues.square_brackets(), miniclue.gen_clues.builtin_completion(), miniclue.gen_clues.g(), miniclue.gen_clues.marks(), miniclue.gen_clues.registers(), miniclue.gen_clues.windows(), miniclue.gen_clues.z(), }, }) < # Leader clues ~ Assume there are these || mappings set up: >lua -- Set `` before making any mappings and configuring 'mini.clue' vim.g.mapleader = ' ' local nmap_leader = function(suffix, rhs, desc) vim.keymap.set('n', '' .. suffix, rhs, { desc = desc }) end local xmap_leader = function(suffix, rhs, desc) vim.keymap.set('x', '' .. suffix, rhs, { desc = desc }) end nmap_leader('bd', 'lua MiniBufremove.delete()', 'Delete') nmap_leader('bw', 'lua MiniBufremove.wipeout()', 'Wipeout') nmap_leader('lf', 'lua vim.lsp.buf.format()', 'Format') xmap_leader('lf', 'lua vim.lsp.buf.format()', 'Format') nmap_leader('lr', 'lua vim.lsp.buf.rename()', 'Rename') nmap_leader('lR', 'lua vim.lsp.buf.references()', 'References') < The following setup will enable || as trigger in Normal and Visual modes and add descriptions to mapping groups: >lua require('mini.clue').setup({ -- Register `` as trigger triggers = { { mode = { 'n', 'x' }, keys = '' }, }, -- Add descriptions for mapping groups clues = { { mode = 'n', keys = 'b', desc = '+Buffers' }, { mode = 'n', keys = 'l', desc = '+LSP' }, }, }) < # Clues without mappings ~ Clues can be shown not only for actually present mappings. This is helpful for showing clues for built-in key combinations. Here is an example of clues for a subset of built-in completion (see |MiniClue.gen_clues.builtin_completion()| to generate clues for all available completion sources): >lua require('mini.clue').setup({ -- Make `` a trigger. Otherwise, key query process won't start. triggers = { { mode = 'i', keys = '' }, }, -- Register custom clues clues = { { mode = 'i', keys = '', desc = 'File names' }, { mode = 'i', keys = '', desc = 'Whole lines' }, { mode = 'i', keys = '', desc = 'Omni completion' }, { mode = 'i', keys = '', desc = 'Spelling suggestions' }, { mode = 'i', keys = '', desc = "With 'completefunc'" }, } }) < # Triggers in special buffers ~ By default triggers are automatically created in listed ('buflisted') and some special non-listed buffers. Use |MiniClue.ensure_buf_triggers()| to manually enable in when you need them. For example: >vim au FileType special_ft lua MiniClue.ensure_buf_triggers() < # Submodes ~ *MiniClue-examples-submodes* Submode is a state initiated after pressing certain key combination ("prefix") during which some keys are interpreted differently. In this module submode can be implemented following these steps: - Create mappings for each key inside submode. Left hand side of mappings should consist from prefix followed by the key. - Create clue for each key inside submode with `postkeys` value equal to prefix. It would mean that after executing particular key combination from this submode, pressing its prefix will be automatically emulated (leading back to being inside submode). - Register submode prefix (or some of its starting part) as trigger. Do not register "overlapping" triggers, like `` and `m`. ## Submode examples ~ - Submode for moving with |mini.move|: - Press `m` to start submode. - Press any of `h`/`j`/`k`/`l` to move selection/line. - Press `` to stop submode. The code: >lua require('mini.move').setup({ mappings = { left = 'mh', right = 'ml', down = 'mj', up = 'mk', line_left = 'mh', line_right = 'ml', line_down = 'mj', line_up = 'mk', }, }) require('mini.clue').setup({ triggers = { -- This can also set up directly `m` as a trigger, but make -- sure to not also use ``, as they would "overlap" { mode = { 'n', 'x' }, keys = '' }, }, clues = { { mode = 'n', keys = 'm', desc = '+Move' }, { mode = { 'n', 'x' }, keys = 'mh', postkeys = 'm' }, { mode = { 'n', 'x' }, keys = 'mj', postkeys = 'm' }, { mode = { 'n', 'x' }, keys = 'mk', postkeys = 'm' }, { mode = { 'n', 'x' }, keys = 'ml', postkeys = 'm' }, }, }) < - Submode for iterating buffers and windows with |mini.bracketed|: - Press `[` or `]` to start key query process for certain direction. - Press `b` / `w` to iterate buffers/windows until reach target one. - Press `` to stop submode. The code: >lua require('mini.bracketed').setup() require('mini.clue').setup({ triggers = { { mode = 'n', keys = ']' }, { mode = 'n', keys = '[' }, }, clues = { { mode = 'n', keys = ']b', postkeys = ']' }, { mode = 'n', keys = ']w', postkeys = ']' }, { mode = 'n', keys = '[b', postkeys = '[' }, { mode = 'n', keys = '[w', postkeys = '[' }, }, }) < - Submode for window commands using |MiniClue.gen_clues.windows()|: - Press `` to start key query process. - Press keys which move / change focus / resize windows. - Press `` to stop submode. The code: >lua local miniclue = require('mini.clue') miniclue.setup({ triggers = { { mode = 'n', keys = '' }, }, clues = { miniclue.gen_clues.windows({ submode_move = true, submode_navigate = true, submode_resize = true, }) }, }) < # Window config ~ >lua require('mini.clue').setup({ triggers = { { mode = 'n', keys = '' } }, window = { -- Show window immediately delay = 0, config = { -- Compute window width automatically width = 'auto', -- Use double-line border border = 'double', }, }, }) < ------------------------------------------------------------------------------ *MiniClue.setup()* `MiniClue.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniClue.config|. Usage ~ >lua require('mini.clue').setup({}) -- replace {} with your config table -- needs `triggers` field present < ------------------------------------------------------------------------------ *MiniClue.config* `MiniClue.config` Defaults ~ >lua MiniClue.config = { -- Array of extra clues to show clues = {}, -- Array of opt-in triggers which start custom key query process. -- **Needs to have something in order to show clues**. triggers = {}, -- Clue window settings window = { -- Floating window config config = {}, -- Delay before showing clue window delay = 1000, -- Keys to scroll inside the clue window scroll_down = '', scroll_up = '', }, } < # General info ~ - To use || as part of the config (either as trigger or inside clues), set it prior to running |MiniClue.setup()|. - See |MiniClue-examples| for examples. # Clues ~ `config.clues` is an array with extra information about key combinations. Each element can be one of: - Clue table. - Array (possibly nested) of clue tables. - Callable (function) returning either of the previous two. A clue table is a table with the following fields: - `(string|table)` - single character describing mode short-name of key combination as in `nvim_set_keymap()` ('n', 'x', 'i', 'o', 'c', etc.), or a array thereof. - `(string)` - key combination for which clue will be shown. "Human-readable" key names as in |key-notation| (like "", "", "", etc.) are allowed. - `(string|function|nil)` - optional key combination description which is shown in clue window. If function, should return string description. - `(string|nil)` - optional postkeys which will be executed automatically after `keys`. Allows creation of submodes (see |MiniClue-examples-submodes|). Notes: - Postkeys are literal simulation of keypresses with |nvim_feedkeys()|. - Suggested approach to configuring clues is to create mappings with `desc` field while supplying to `config.clues` only elements describing groups, postkeys, and built-in mappings. # Triggers ~ `config.triggers` is an array with information when |MiniClue-key-query-process| should start. Each element is a trigger table with the fields and which are treated the same as in clue table. # Window ~ `config.window` defines behavior of clue window. `config.window.delay` is a number of milliseconds after which clue window will appear. Can be 0 to show immediately. `config.window.config` is a table defining floating window characteristics or a callable returning such table (will be called with identifier of window's buffer already showing all clues). It should have the same structure as in |nvim_open_win()| with the following enhancements: - field can be equal to `"auto"` leading to window width being computed automatically based on its content. Default is fixed width of 30. - and can be equal to `"auto"` in which case they will be computed to "stick" to set anchor ("SE" by default; see |nvim_open_win()|). This allows changing corner in which window is shown: >lua -- Pick one anchor local anchor = 'NW' -- top-left local anchor = 'NE' -- top-right local anchor = 'SW' -- bottom-left local anchor = 'SE' -- bottom-right require('mini.clue').setup({ window = { config = { anchor = anchor, row = 'auto', col = 'auto' }, }, }) < `config.window.scroll_down` / `config.window.scroll_up` are strings defining keys which will scroll clue window down / up which is useful in case not all clues fit in current window height. Set to empty string `''` to disable either of them. ------------------------------------------------------------------------------ *MiniClue.enable_all_triggers()* `MiniClue.enable_all_triggers`() Enable triggers in loaded listed and some special buffers ------------------------------------------------------------------------------ *MiniClue.enable_buf_triggers()* `MiniClue.enable_buf_triggers`({buf_id}) Enable triggers in buffer Parameters ~ {buf_id} `(number|nil)` Buffer identifier. Default: current buffer. ------------------------------------------------------------------------------ *MiniClue.disable_all_triggers()* `MiniClue.disable_all_triggers`() Disable triggers in loaded buffers ------------------------------------------------------------------------------ *MiniClue.disable_buf_triggers()* `MiniClue.disable_buf_triggers`({buf_id}) Disable triggers in buffer Parameters ~ {buf_id} `(number|nil)` Buffer identifier. Default: current buffer. ------------------------------------------------------------------------------ *MiniClue.ensure_all_triggers()* `MiniClue.ensure_all_triggers`() Ensure all triggers are valid ------------------------------------------------------------------------------ *MiniClue.ensure_buf_triggers()* `MiniClue.ensure_buf_triggers`({buf_id}) Ensure buffer triggers are valid Parameters ~ {buf_id} `(number|nil)` Buffer identifier. Default: current buffer. ------------------------------------------------------------------------------ *MiniClue.set_mapping_desc()* `MiniClue.set_mapping_desc`({mode}, {lhs}, {desc}) Update description of an existing mapping Notes: - Uses buffer-local mapping in case there are both global and buffer-local mappings with same mode and LHS. Similar to |maparg()|. Parameters ~ {mode} `(string)` Mapping mode (as in `maparg()`). {lhs} `(string)` Mapping left hand side (as `name` in `maparg()`). {desc} `(string)` New description to set. ------------------------------------------------------------------------------ *MiniClue.gen_clues* `MiniClue.gen_clues` Generate pre-configured clues This is a table with function elements. Call to actually get array of clues. ------------------------------------------------------------------------------ *MiniClue.gen_clues.builtin_completion()* `MiniClue.gen_clues.builtin_completion`() Generate clues for built-in completion Contains clues for the following triggers: >lua { mode = 'i', keys = '' } < Return ~ `(table)` Array of clues. ------------------------------------------------------------------------------ *MiniClue.gen_clues.g()* `MiniClue.gen_clues.g`() Generate clues for `g` key Contains clues for the following triggers: >lua { mode = { 'n', 'x' }, keys = 'g' } < Return ~ `(table)` Array of clues. ------------------------------------------------------------------------------ *MiniClue.gen_clues.square_brackets()* `MiniClue.gen_clues.square_brackets`() Generate clues for `[` and `]` keys Contains clues for the following triggers: >lua { mode = 'n', keys = '[' } { mode = 'n', keys = ']' } < Return ~ `(table)` Array of clues. ------------------------------------------------------------------------------ *MiniClue.gen_clues.marks()* `MiniClue.gen_clues.marks`() Generate clues for marks Contains clues for the following triggers: >lua { mode = { 'n', 'x' }, keys = "'" } { mode = { 'n', 'x' }, keys = "g'" } { mode = { 'n', 'x' }, keys = '`' } { mode = { 'n', 'x' }, keys = 'g`' } < Note: if you use "g" as trigger (like to enable |MiniClue.gen_clues.g()|), don't add "g'" and "g`" as triggers: they already will be taken into account. Return ~ `(table)` Array of clues. See also ~ |mark-motions| ------------------------------------------------------------------------------ *MiniClue.gen_clues.registers()* `MiniClue.gen_clues.registers`({opts}) Generate clues for registers Contains clues for the following triggers: >lua { mode = { 'n', 'x' }, keys = '"' } { mode = { 'i', 'c' }, keys = '' } < Parameters ~ {opts} `(table|nil)` Options. Possible keys: - `(boolean)` - whether to show contents of all possible registers. If `false`, only description of special registers is shown. Default: `false`. Return ~ `(table)` Array of clues. See also ~ |registers| ------------------------------------------------------------------------------ *MiniClue.gen_clues.windows()* `MiniClue.gen_clues.windows`({opts}) Generate clues for window commands Contains clues for the following triggers: >lua { mode = 'n', keys = '' } < Note: only non-duplicated commands are included. For full list see |CTRL-W|. Parameters ~ {opts} `(table|nil)` Options. Possible keys: - `(boolean)` - whether to make move (change layout) commands a submode by using `postkeys` field. Default: `false`. - `(boolean)` - whether to make navigation (change focus) commands a submode by using `postkeys` field. Default: `false`. - `(boolean)` - whether to make resize (change size) commands a submode by using `postkeys` field. Default: `false`. Return ~ `(table)` Array of clues. ------------------------------------------------------------------------------ *MiniClue.gen_clues.z()* `MiniClue.gen_clues.z`() Generate clues for `z` key Contains clues for the following triggers: >lua { mode = { 'n', 'x' }, keys = 'z' } < Return ~ `(table)` Array of clues. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-cmdline.txt ================================================ *mini.cmdline* Command line tweaks MIT License Copyright (c) 2025 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniCmdline* Features: - Autocomplete with customizable delay. Enhances |cmdline-completion| and manual |'wildchar'| pressing experience. Requires Neovim>=0.11, though Neovim>=0.12 is recommended. - Autocorrect words as-you-type. Only words that must come from a fixed set of candidates (like commands and options) are autocorrected by default. - Autopeek command range as-you-type. Shows a floating window with range lines along with customizable context lines. What it doesn't do: - Customization of command line UI. Use |vim._extui| (on Neovim>=0.12). - Customization of autocompletion candidates. They are computed via |cmdline-completion|. # Setup ~ This module needs a setup with `require('mini.cmdline').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniCmdline` which you can use for scripting or manually (with `:lua MiniCmdline.*`). See |MiniCmdline.config| for `config` structure and default values. You can override runtime config settings locally to buffer inside `vim.b.minicmdline_config` which should have same structure as `MiniCmdline.config`. See |mini.nvim-buffer-local-config| for more details. # Suggested option values ~ Some options are set automatically (if not set before |MiniCmdline.setup()|): - |'wildmode'| is set to "noselect,full" for less intrusive autocompletion. Requires Neovim>=0.11 and enabled `config.autocomplete`. - |'wildoptions'| is set to "pum,fuzzy" to enable fuzzy matching. # Comparisons ~ - [folke/noice.nvim](https://github.com/folke/noice.nvim): - Mostly focuses on visual aspects of the Command line. This modules is aimed to improve its workflow without changing UI. - [nacro90/numb.nvim](https://github.com/nacro90/numb.nvim): - Designed to preview only a single line range defined by numbers. This module handles any form of |:range| and |:range-offset| for both one and two line ranges. - Shows target line directly in the normal window. This module uses a dedicated floating window. - Built-in |cmdline-autocompletion| (on Neovim>=0.12): - This module on Neovim>=0.12 uses that as its base for autocompletion. Ont top of that it also provides customizable delay and predicate. - Built-in |vim._extui| (on Neovim>=0.12): - Mostly focuses on visual aspects of the Command line. This modules is aimed to improve its workflow without changing UI. # Highlight groups ~ - `MiniCmdlinePeekBorder` - border of autopeek window. - `MiniCmdlinePeekLineNr` - line numbers in autopeek window. - `MiniCmdlinePeekNormal` - basic foreground/background of autopeek window. - `MiniCmdlinePeekSep` - statuscolumn separator in autopeek window. - `MiniCmdlinePeekSign` - signs in autopeek window. - `MiniCmdlinePeekTitle` - title of autopeek window. # Disabling ~ To disable acting in mappings, set `vim.g.minicmdline_disable` (globally) or `vim.b.minicmdline_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniCmdline.setup()* `MiniCmdline.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniCmdline.config|. Usage ~ >lua require('mini.cmdline').setup() -- use default config -- OR require('mini.cmdline').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniCmdline.config* `MiniCmdline.config` Defaults ~ >lua MiniCmdline.config = { -- Autocompletion: show `:h 'wildmenu'` as you type autocomplete = { enable = true, -- Delay (in ms) after which to trigger completion -- Neovim>=0.12 is recommended for positive values delay = 0, -- Custom rule of when to trigger completion predicate = nil, -- Whether to map arrow keys for more consistent wildmenu behavior map_arrows = true, }, -- Autocorrection: adjust non-existing words (commands, options, etc.) autocorrect = { enable = true, -- Custom autocorrection rule func = nil, }, -- Autopeek: show command's target range in a floating window autopeek = { enable = true, -- Number of lines to show above and below range lines n_context = 1, -- Custom rule of when to show peek window predicate = nil, -- Window options window = { -- Floating window config config = {}, -- Function to render statuscolumn statuscolumn = nil, }, }, } < # General ~ - Each feature is configured via separate table. - Use `enable = false` to disable a feature. Autocomplete ~ `config.autocomplete` is used to configure autocompletion: automatic show of |'wildmenu'|. `autocomplete.delay` defines a (debounce style) delay after which |'wildchar'| is triggered to show wildmenu. Default: 0. Note: Neovim>=0.12 is recommended for positive values if you want to reduce flicker (thanks to |wildtrigger()|). `autocomplete.predicate` defines a condition of whether to trigger completion at the current command line state. Takes a table with input data and should return `true` to show completion and `false` otherwise. Will be called before the possible delay at current command line state. Default: |MiniCmdline.default_autocomplete_predicate()|. Input data fields: - `(string)` - current command line text. See |getcmdline()|. - `(number)` - current command line column. See |getcmdpos()|. - `(string)` - command line text before the latest change. - `(number)` - command line column before the latest cursor move. Example of blocking completion based on completion type (as some may be slow): >lua local block_compltype = { shellcmd = true } require('mini.cmdline').setup({ autocomplete = { predicate = function() return not block_compltype[vim.fn.getcmdcompltype()] end, }, }) < Similar approach can be used to enable completion only for normal Ex commands. Use `return vim.fn.getcmdtype() == ':'` as a predicate output. Autocorrect ~ `config.autocorrect` is used to configure autocorrection: automatic adjustment of bad words as you type them. This works only when appending single character at the end of the command line. Editing already typed words does not trigger autocorrect (allows correcting the autocorrection). When to autocorrect is computed automatically based on |getcmdcomplpat()| after every key press: if it doesn't add the character to completion pattern, then the pattern before the key press is attempted to be corrected. There is also an autocorrection attempt for the last word just before executing the command. Notes: - This is intended mostly for fixing typos and not as a shortcut for fuzzy matching. Performing the latter automatically is too intrusive. Explicitly use fuzzy completion for that (set up by default). - Default autocorrection is done only for words that must come from a fixed set of candidates (like commands and options) by choosing the one with the lowest string distance. See |MiniCmdline.default_autocorrect_func()| for details. - Word that matches some Command-line |abbreviation| is not autocorrected. - If current command expects only a single argument (like |:colorscheme|), then autocorrection will happen only just before executing the command. `autocorrect.func` is a function that can be used to customize autocorrection. Takes a table with input data and should return a string with the correct word or `nil` for no autocorrection. Default: |MiniCmdline.default_autocorrect_func()|. Input data fields: - `(string)` - word to be autocorrected. Never empty string. - `(string)` - word type. Output of |getcmdcompltype()|. Autopeek ~ `config.autopeek` is used to configure automatic peeking: show command's target range in a floating window. The window will appear above command line and show current buffer with the focus on left and right (if present and differs from left) range lines. `autopeek.n_context` defines how many lines to show above and below the target. The range itself is visualized by default with the statuscolumn signs. Default: 1. `autopeek.predicate` defines a condition of whether to show peek window at the current command line state. Takes a table with input data and should return `true` to peek and `false` otherwise. Will be called only if it is possible to parse range from the current command line text and it is for buffer lines (no command or |:command-addr| is `lines`) Default: |MiniCmdline.default_autopeek_predicate()|. Input data fields: - `(number)` - left range edge. Not necessarily smallest. - `(number)` - right range edge. Same as `left` for a single line range. - `(string)` - full command name. Can be empty string if no valid command is (yet) entered. `autopeek.window` defines behavior of a peek window. `autopeek.window.config` is a table defining floating window characteristics or a callable returning such table. It should have the same structure as in |nvim_open_win()|. `autopeek.window.statuscolumn` is a special function that can be used to customize |'statuscolumn'| value for the peek window. Takes a table with input data and should return a string to display for line |v:lnum|. Default: |MiniCmdline.default_autopeek_statuscolumn()|. Input data fields are the same as for `autopeek.predicate`. Example of showing `<` and `>` signs on range lines: >lua function(data) local n, l, r = vim.v.lnum, data.left, data.right local s = n == l and (n == r and '* ' or '< ') or n == r and '> ' or '' -- Needs explicit highlighting via `:h 'statusline'` syntax return '%#MiniCmdlinePeekSign#' .. s end < Notes: - Peek window directly shows current buffer, which means that all its extmarks, virtual text, virtual lines, etc. are also shown. - Non-zero context might work unreliably if there are virtual lines. - Peeking intentionally hides Visual selection if Command-line mode is entered directly from it. Peeking `'<,'>` range already visualizes the selection. To disable autopeek for this case, add the following code BEFORE executing `require('mini.cmdline').setup()`: >lua local disable = vim.schedule_wrap(function() local is_from_visual = vim.startswith(vim.fn.getcmdline(), "'<,'>") MiniCmdline.config.autopeek.enable = not is_from_visual end) local reenable = function() MiniCmdline.config.autopeek.enable = true end vim.api.nvim_create_autocmd('CmdlineEnter', { callback = disable }) vim.api.nvim_create_autocmd('CmdlineLeave', { callback = reenable }) < ------------------------------------------------------------------------------ *MiniCmdline.default_autocomplete_predicate()* `MiniCmdline.default_autocomplete_predicate`({data}, {opts}) Default autocompletion predicate Parameters ~ {data} `(table)` Input autocompletion data. As described in |MiniCmdline.config|. {opts} `(table|nil)` Options. Reserved for future use. Return ~ `(boolean)` If command line does not (yet) contain a letter - `false`, otherwise - `true`. This makes autopeek easier to use for a numerical range. ------------------------------------------------------------------------------ *MiniCmdline.default_autocorrect_func()* `MiniCmdline.default_autocorrect_func`({data}, {opts}) Default autocorrection function - Return input word if `opts.strict_type=true` and input `type` is not proper. - Get candidates via `opts.get_candidates()`. Default: mostly via |getcompletion()| with empty pattern and input `type`. Exceptions are `help` and `option` types: both list all available candidates in their own ways. - Choose the candidate with the lowest Damerau–Levenshtein distance (smallest number of deletion/insertion/substitution/transposition needed to transform one word into another; slightly prefers transposition). Notes: - Type `'command'` also chooses from all valid candidate abbreviations. - Comparison is done both respecting and ignoring case. Parameters ~ {data} `(table)` Input autocorrection data. As described in |MiniCmdline.config|. {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - whether to restrict output only for types which must have words from a fixed set of candidates (like command or option names). Note: does not include `help` type since |:help| already has "sophisticated algorithm" to handle typos. Default: `true`. - `(function)` - source of candidates. Will be called with `data` as argument and should return array of string candidates to choose from. Default: for most types - |getcompletion()| with empty pattern and input `type`; for `help` and `option` type - all available help tags and option names (long and short) respectively. Return ~ `(string)` Autocorrected word. ------------------------------------------------------------------------------ *MiniCmdline.default_autopeek_predicate()* `MiniCmdline.default_autopeek_predicate`({data}, {opts}) Default autopeek predicate Parameters ~ {data} `(table)` Input autopeek data. As described in |MiniCmdline.config|. {opts} `(table|nil)` Options. Reserved for future use. Return ~ `(boolean)` If command defines |:command-preview| - `false`, otherwise - `true`. This makes autopeek easier to use for commands like |:substitute|, especially if |'inccommand'| is set to `split`. ------------------------------------------------------------------------------ *MiniCmdline.default_autopeek_statuscolumn()* `MiniCmdline.default_autopeek_statuscolumn`({data}, {opts}) Default autopeek statuscolumn - Show signs next to lines depending on their relation to peeked range. Highlighted with `MiniCmdlinePeekSign` group. - Show line numbers for left and right parts of the range. Highlighted with `MiniCmdlinePeekLineNr` group. - Separate statuscolumn and buffer text with dedicated separator character. Highlighted with `MiniCmdlinePeekSep` group. Notes: - Intended to only be used as a part of |'statuscolumn'| function, as it uses |v:lnum| and |v:virtnum| to compute the output. Example of adjusting a `mid` sign: >lua local peek_stc_opts = { signs = { mid = '+' } } local peek_stc = function(data) return MiniCmdline.default_autopeek_statuscolumn(data, peek_stc_opts) end require('mini.cmdline').setup({ autopeek = { window = { statuscolumn = peek_stc } }, }) < Parameters ~ {data} `(table)` Input peek data. As described in |MiniCmdline.config|. {opts} `(table|nil)` Options. Possible fields: - `(table)` - signs to show. Possible fields: - `(string)` - on range if `left=right`. Default: `'🭬'`. - `(string)` - on `left` line. Default: `'┌'`. - `(string)` - inside range. Default: `'┊'`. - `(string)` - on `right` line. Default: `'└'`. - `(string)` - outside of range. Default: `''` (no sign). - `(string)` - virtual line. Default: `'•'`. - `(string)` - wrapped line. Default: `'↳'`. - `(string)` - string to put at the end to separate statuscolumn and buffer text. Default: `'│'` Note: Any sign and separator should have every `%` escaped as `%%` (due to its special meaning in |'statuscolumn'|). vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-colors.txt ================================================ *mini.colors* Tweak and save any color scheme MIT License Copyright (c) 2023 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniColors* Features: - Create colorscheme object: either manually (|MiniColors.as_colorscheme()|) or by querying present color schemes (including currently active one; see |MiniColors.get_colorscheme()|). - Infer data about color scheme and/or modify based on it: - Add transparency by removing background color (requires transparency in terminal emulator). - Infer cterm attributes (|cterm-colors|) based on gui colors making it compatible with 'notermguicolors'. - Resolve highlight group links (|:highlight-link|). - Compress by removing redundant highlight groups. - Extract palette of used colors and/or infer terminal colors (|terminal-config|) based on it. - Modify colors to better fit your taste and/or goals (see more in |MiniColors-colorscheme-methods|): - Apply any function to color hex string. - Update channels (like lightness, saturation, hue, temperature, red, green, blue, etc.; see more in |MiniColors-channels|). Use either own function or one of the implemented methods: - Add value to channel or multiply it by coefficient. Like "add 10 to saturation of every color" or "multiply saturation by 2" to make colors more saturated (less gray). - Invert. Like "invert lightness" to convert between dark/light theme. - Set to one or more values (picks closest to current one). Like "set to one or two hues" to make mono- or dichromatic color scheme. - Repel from certain source(s) with stronger effect for closer values. Like "repel from hue 30" to remove red color from color scheme. Repel hue (how much is removed) is configurable. - Simulate color vision deficiency. - Once color scheme is ready, either apply it to see effects right away or write it into a Lua file as a fully functioning separate color scheme. - Experiment interactively with a feedback (|MiniColors.interactive()|). - Animate transition between color schemes either with |MiniColors.animate()| or with |:Colorscheme| user command. - Convert within supported color spaces (|MiniColors.convert()|): - Hex string. - 8-bit number (terminal colors). - RGB. - Oklab, Oklch, Okhsl (https://bottosson.github.io/posts/oklab/). Notes: - There is a collection of |MiniColors-recipes| with code snippets for some common tasks. - There is no goal to support as many color spaces as possible, only the already present ones. # Tweak quick start ~ - Execute `:lua require('mini.colors').interactive()`. - Experiment by writing calls to exposed color scheme methods and applying them with ``. For more information, see |MiniColors-colorscheme-methods| and |MiniColors-recipes|. - If you are happy with result, write color scheme with ``. If not, reset to initial color scheme with ``. - If only some highlight groups can be made better, adjust them manually inside written color scheme file. # Setup ~ This module doesn't need setup, but it can be done to improve usability. Setup with `require('mini.colors').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniColors` which you can use for scripting or manually (with `:lua MiniColors.*`). See |MiniColors.config| for `config` structure and default values. This module doesn't have runtime options, so using `vim.b.minicolors_config` will have no effect here. # Comparisons ~ - [rktjmp/lush.nvim](https://github.com/rktjmp/lush.nvim): - Oriented towards tweaking separate highlight groups, while 'mini.colors' is more designed to work with color scheme as a whole. - Uses HSL and HSLuv color spaces, while 'mini.colors' uses Oklab, Oklch, and Okhsl which have slightly better perceptual uniformity properties. - Doesn't have functionality to infer and repair missing data in color scheme (like cterm attributes, terminal colors, transparency, etc.), while 'mini.colors' does. - Doesn't implement animation of color scheme transition, while 'mini.colors' does. - [lifepillar/vim-colortemplate](https://github.com/lifepillar/vim-colortemplate): - Comparisons are similar to that of 'rktjmp/lush.nvim'. - [tjdevries/colorbuddy.nvim](https://github.com/tjdevries/colorbuddy.nvim): - Comparisons are similar to that of 'rktjmp/lush.nvim'. ------------------------------------------------------------------------------ *MiniColors-recipes* All following code snippets assume to be executed inside interactive buffer (|MiniColors.interactive()|). They are directly copy-pasteable. To apply single method to current color scheme, use >vim :lua MiniColors.get_colorscheme()::apply(). < Recipes: - Tweak lightness: >lua -- Invert dark/light color scheme to be light/dark chan_invert('lightness', { gamut_clip = 'cusp' }) -- Ensure constant contrast ratio chan_set('lightness', 15, { filter = 'bg' }) chan_set('lightness', 85, { filter = 'fg' }) < - Tweak saturation: >lua -- Make background colors less saturated and foreground - more chan_add('saturation', -20, { filter = 'bg' }) chan_add('saturation', 20, { filter = 'fg' }) -- Convert to grayscale chan_set('saturation', 0) < - Tweak hue: >lua -- Create monochromatic variant (this uses green color) chan_set('hue', 135) -- Create dichromatic variant (this uses Neovim-themed hues) chan_set('hue', { 140, 245 }) < - Tweak temperature: >lua -- Invert temperature (make cold theme become warm and vice versa) chan_invert('temperature') -- Make background colors colder and foreground warmer chan_add('temperature', -40, { filter = 'bg' }) chan_add('temperature', 40, { filter = 'fg' }) < - Counter color vision deficiency (try combinations of these to see which one works best for you): - Improve text saturation contrast (usually the best starting approach): >lua chan_set('saturation', { 10, 90 }, { filter = 'fg' }) < - Remove certain hues from all colors (use 30 for red, 90 for yellow, 135 for green, 270 for blue): >lua -- Repel red color chan_repel('hue', 30, 45) < - Force equally spaced palette (remove ones with which you know you have trouble): >lua -- Might be a good choice for red-green color blindness chan_set('hue', { 90, 180, 270}) -- Might be a good choice for blue-yellow color blindness chan_set('hue', { 0, 90, 180 }) < - Inverting temperature or pressure can sometimes improve readability: >lua chan_invert('temperature') chan_invert('pressure') < - If all hope is lost, hue random generation might help if you are lucky: >lua chan_modify('hue', function() return math.random(0, 359) end) < - For color scheme creators use |MiniColors-colorscheme:simulate_cvd()| to simulate various color vision deficiency types to see how color scheme would look in the eyes of color blind person. ------------------------------------------------------------------------------ *MiniColors-color-spaces* Color space is a way to quantitatively describe a color. In this module color spaces are used both as source for |MiniColors-channels| and inputs for |MiniColors.convert()| List of supported color spaces (along with their id in parenthesis): - 8-bit (`8-bit`) - integer between 16 and 255. Usually values 0-15 are also supported, but they depend on terminal emulator theme which is not reliable. See https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit . - Hex (`hex`) - string of the form "#xxxxxx" where `x` is a hexadecimal number. - RGB (`rgb`) - table with numeric fields `r` (red), `g` (green), `b` (blue). Visible range is from 0 to 255. - Oklab (`oklab`) - table with fields `l` (lightness; numeric in [0; 100]), `a`, `b` (both are unbounded numeric; visible range is usually between -30 to 30). Field `l` describes how light is color; `a` - how "green-red" it is; `b` - how "blue-yellow" it is. - Oklch (`oklch`) - table with fields `l` (same as in Oklab), `c` (chroma; positive numeric, visible range usually lower than 32), `h` (`nil` for grays or periodic numeric in [0, 360)). Field `c` describes how colorful a color is; `h` is a value of "true color" on color circle/wheel. NOTE: gray colors, being achromatic by nature, don't have hue. - Okhsl (`okhsl`) - Oklch but with `c` replaced by `s` (saturation; numeric in [0; 100]). Field `s` describes a percent of chroma relative to maximum visible chroma for the particular lightness and hue combination. Note, that mathematical model used to compute maximum visible chroma is approximate which might lead to inaccuracies for highly saturated colors with relatively low or high lightness. Sources for Oklab/Oklch/Okhsl: - https://bottosson.github.io/posts/oklab/ - initial derivation and introduction of Oklab and Oklch. - https://bottosson.github.io/misc/colorpicker - interactive color picker. Great way for a hands-on introduction to concepts of lightness, chroma, saturation, and hue. Note that Oklab/Oklch/Okhsl use channel normalization for `l`, `a`, `b`, `c`, `s` that is more oriented towards integer numbers (according to the above sources). Some implementations (like in CSS) are more oriented towards [0; 1] range or percentages. Adjust accordingly by dividing/multiplying output by 100. Also use `adjust_lightness = false` in |MiniColors.convert()|. # Gamut clip ~ *MiniColors-gamut-clip* In Neovim highlight group colors are usually specified by their red, green, and blue values from 0 to 255 in the form of HEX string (see |gui-colors|). Although plenty, these are not all possible colors. When performing color manipulation using |MiniColors-colorscheme-methods|, it is possible to end up with "impossible" color (which can't be directly converted to HEX string). For example, inverting lightness of color "#fce094" will lead to a color `{ l = 10, c = 10, h = 90 }` in Oklch space, i.e. "dark yellow" which is impossible to show in HEX. **Gamut clipping** is an action of converting color outside of visible gamut (colors representable with HEX string) to be inside it while preserving certain perceptual characteristics as much as possible. Gamut clipping in this module is done inside Oklch color space. The goal is to preserve hue as much as possible while manipulating lightness and/or chroma. List of supported gamut clip methods (along with their id in parenthesis): - Clip chroma (`'chroma'`) - reduce chroma while preserving lightness until color is inside visible gamut. Default method. - Clip lightness (`'lightness'`) - reduce lightness while preserving chroma until color is inside visible gamut. - Clip according to "cusp" (`'cusp'`) - reduce both lightness and chroma in a compromise way depending on hue. Cusp is a color with the highest chroma inside slice of visible gamut with the same hue (hue leaf). It is called that way because the slice has a roughly triangular shape with points at (0, 0) - (0, 100) - "cusp" in (chroma, lightness) coordinates. Gamut clipping using "cusp" as reference is done by changing color towards (0, cusp_lightness) point (gray with lightness equal to that of a current cusp) until color is inside visible gamut. In short: - Usually `'chroma'` is enough. - If colors are too desaturated - try `'cusp'`. - If still not colorful enough - try `'lightness'`. Notes: - Currently implemented formulas are approximate (by design; to reduce code complexity) so there might be problems for highly saturated colors with relatively low or high lightness. ------------------------------------------------------------------------------ *MiniColors-channels* A color channel is a number describing one particular aspect of a color. It is usually direct or modified coordinate of a color space. See |MiniColors-color-spaces| for information on color spaces. List of supported channels (along with their id in parenthesis): - Lightness (`lightness`) - corrected `l` component of Oklch. Describes how light is a color. Ranges from 0 (black dark) to 100 (white light). - Chroma (`chroma`) - `c` component of Oklch. Describes how colorful is a color in absolute units. Ranges from 0 (gray) to infinity (more like around 30 in practice). - Saturation (`saturation`) - `s` component of Okhsl. Describes how colorful is color in relative units. Ranges from 0 (gray) to 100 (maximum saturation for a given lightness-hue pair). - Hue (`hue`) - `h` component of Oklch. Describes "true color value" (like red/green/blue) as a number. It is a periodic value from 0 (included) to 360 (not included). Best perceived as a degree on a color circle/wheel. Approximate values for common color names: - 0 - pink. - 30 - red. - 60 - orange. - 90 - yellow. - 135 - green. - 180 - cyan. - 225 - light blue. - 270 - blue. - 315 - magenta/purple. - Temperature (`temperature`) - circular distance from current hue to hue 270 angle (blue). Ranges from 0 (cool) to 180 (hot) anchored at hues 270 (blue) and 90 (yellow). Similar to `b` channel but tries to preserve chroma. - Pressure (`pressure`) - circular distance from current hue to hue 180. Ranges from 0 (low; green-ish) to 180 (high; red-ish) anchored at hues 180 and 0. Similar to `a` channel but tries to preserve chroma. Not widely used; added to have something similar to temperature. - a (`a`) - `a` component of Oklab. Describes how "green-red" a color is. Can have any value. Negative values are "green-ish", positive - "red-ish". - b (`b`) - `b` component of Oklab. Describes how "blue-yellow" a color is. Can have any value. Negative values are "blue-ish", positive - "yellow-ish". - Red (`red`) - `r` component of RGB. Describes how much red a color has. Ranges from 0 (no red) to 255 (full red). - Green (`green`) - `g` component of RGB. Describes how much green a color has. Ranges from 0 (no green) to 255 (full green). - Blue (`blue`) - `b` component of RGB. Describes how much blue a color has. Ranges from 0 (no blue) to 255 (full blue). ------------------------------------------------------------------------------ *MiniColors-colorscheme* Colorscheme object is a central structure of this module. It contains all data relevant to colors in fields and provides methods to modify it. Create colorscheme object manually with |MiniColors.as_colorscheme()|: >lua MiniColors.as_colorscheme({ name = 'my_cs', groups = { Normal = { fg = '#dddddd', bg = '#222222' }, SpellBad = { sp = '#dd2222', undercurl = true }, }, terminal = { [0] = '#222222', [1] = '#dd2222' }, }) < Get any registered color scheme (including currently active) as colorscheme object with |MiniColors.get_colorscheme()|: >lua -- Get current color scheme MiniColors.get_colorscheme() -- Get registered color scheme by name MiniColors.get_colorscheme('minischeme', { new_name = 'maxischeme' }) < Class ~ {Colorscheme} *MiniColors-colorscheme-fields* Fields ~ {name} `(string|nil)` Name of the color scheme (as in |g:colors_name|). {groups} `(table|nil)` Table with highlight groups data. Keys are group names appropriate for `name` argument of |nvim_set_hl()|, values - tables appropriate for its `val` argument. Note: gui colors are accepted only in short form (`fg`, `bg`, `sp`). {terminal} `(table|nil)` Table with terminal colors data (|terminal-config|). Keys are numbers from 0 to 15, values - strings representing color (hex string or plain color name; see |nvim_get_color_by_name()|). # Methods ~ *MiniColors-colorscheme-methods* Notes about all methods: - They never modify underlying colorscheme object instead returning deep copy with modified fields. - They accept `self` colorscheme object as first argument meaning they should be called with `:` notation (like `cs:method()`). Example calling methods: >lua -- Get current color scheme, set hue of colors to 135, infer cterm -- attributes and apply local cs = MiniColors.get_colorscheme() cs:chan_set('hue', 135):add_cterm_attributes():apply() < ## add_cterm_attributes() ~ *MiniColors-colorscheme:add_cterm_attributes()* Infer |cterm-colors| based on present |gui-colors|. It updates `ctermbg`/`ctermfg` based on `fg`/`bg` by approximating in perceptually uniform distance in Oklab space (|MiniColors-color-spaces|). ### Parameters ~ {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - Whether to replace already present cterm attributes with inferred ones. Default: `true`. ## add_terminal_colors() ~ *MiniColors-colorscheme:add_terminal_colors()* Infer terminal colors (|terminal-config|) based on colorscheme palette (see |MiniColors-colorscheme:get_palette()|). It updates `terminal` field based on color scheme's palette by picking the most appropriate entry to represent terminal color. Colors from 0 to 7 are attempted to be black, red, green, yellow, blue, magenta, cyan, white. Colors from 8 to 15 are the same as from 0 to 7. ### Parameters ~ {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - Whether to replace already present terminal colors with inferred ones. Default: `true`. - `(table)` - |MiniColors-colorscheme:get_palette()| arguments. ## add_transparency() ~ *MiniColors-colorscheme:add_transparency()* Add transparency by removing background from a certain highlight groups. Requires actual transparency from terminal emulator to see background image. Has no effect on linked groups; use |MiniColors-colorscheme:resolve_links()| explicitly before applying transparency. ### Parameters ~ {opts} `(table|nil)` Options. Possible fields can be used to configure which sets of highlight groups to update: - `(boolean)` - general groups (like `Normal`). Default: `true`. - `(boolean)` - built-in groups for floating windows. Default: `false`. - `(boolean)` - groups related to 'statuscolumn' (signcolumn, numbercolumn, foldcolumn, `DiagnosticSignXxx`, and `XxxMsg` groups). Also updates groups for all currently defined signs. Default: `false`. - `(boolean)` - built-in groups for 'statusline'. Default: `false`. - `(boolean)` - built-in groups for 'tabline'. Default: `false`. - `(boolean)` - built-in groups for 'winbar'. Default: `false`. ## apply() ~ *MiniColors-colorscheme:apply()* Apply colorscheme: - Set |g:colors_name| to a `name` field. - Apply highlight groups in a `groups` field. - Set terminal colors from a `terminal` field. ### Parameters ~ {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - whether to execute |:hi-clear| first. Default: `true`. ## chan_add() ~ *MiniColors-colorscheme:chan_add()* Add value to a channel (see |MiniColors-channels|). ### Parameters ~ {channel} `(string)` One of supported |MiniColors-channels|. {value} `(number)` Number to add (can be negative). {opts} `(table|nil)` Options. Possible fields: - `(function|string)` - filter colors to update. Possible values: - String representing target attributes. One of `'fg'`, `'bg'`, `'sp'`, `'term'` (only terminal colors). - Callable with signature as in |MiniColors-colorscheme:color_modify()|. Default: `nil` to update all colors. - `(string)` - gamut clipping method. One of `'chroma'`, `'lightness'`, `'cusp'`. See |MiniColors-gamut-clip|. Default: `'chroma'`. ## chan_invert() ~ *MiniColors-colorscheme:chan_invert()* Invert value in a channel (see |MiniColors-channels|). Notes: - Most Oklab/Oklch inversions are not exactly invertible: applying it twice might lead to slightly different colors depending on gamut clip method (|MiniColors-gamut-clip|) like smaller chroma with default `'chroma'` method. ### Parameters ~ {channel} `(string)` One of supported |MiniColors-channels|. {opts} `(table|nil)` Options. Possible fields: - `(function|string)` - filter colors to update. Possible values: - String representing target attributes. One of `'fg'`, `'bg'`, `'sp'`, `'term'` (only terminal colors). - Callable with signature as in |MiniColors-colorscheme:color_modify()|. Default: `nil` to update all colors. - `(string)` - gamut clipping method. One of `'chroma'`, `'lightness'`, `'cusp'`. See |MiniColors-gamut-clip|. Default: `'chroma'`. ## chan_modify() ~ *MiniColors-colorscheme:chan_modify()* Modify channel with a callable. ### Parameters ~ {channel} `(string)` One of supported |MiniColors-channels|. {f} `(function)` - callable which defines modification. Should take current value of a channel and return a new one. {opts} `(table|nil)` Options. Possible fields: - `(function|string)` - filter colors to update. Possible values: - String representing target attributes. One of `'fg'`, `'bg'`, `'sp'`, `'term'` (only terminal colors). - Callable with signature as in |MiniColors-colorscheme:color_modify()|. Default: `nil` to update all colors. - `(string)` - gamut clipping method. One of `'chroma'`, `'lightness'`, `'cusp'`. See |MiniColors-gamut-clip|. Default: `'chroma'`. ## chan_multiply() ~ *MiniColors-colorscheme:chan_multiply()* Multiply value of a channel (see |MiniColors-channels|). ### Parameters ~ {channel} `(string)` One of supported |MiniColors-channels|. {coef} `(number)` Number to multiply with (can be negative). {opts} `(table|nil)` Options. Possible fields: - `(function|string)` - filter colors to update. Possible values: - String representing target attributes. One of `'fg'`, `'bg'`, `'sp'`, `'term'` (only terminal colors). - Callable with signature as in |MiniColors-colorscheme:color_modify()|. Default: `nil` to update all colors. - `(string)` - gamut clipping method. One of `'chroma'`, `'lightness'`, `'cusp'`. See |MiniColors-gamut-clip|. Default: `'chroma'`. ## chan_repel() ~ *MiniColors-colorscheme:chan_repel()* Repel from certain sources. Given an array of repel centers (`sources`) and repel degree (`coef`) add to current channel value some amount ("nudge") with the following properties: - Nudges from several sources are added together. - Nudge is directly proportional to `coef`: bigger `coef` means bigger nudge. - Nudge is inversely proportional to the distance between current value and source: for positive `coef` bigger distance means smaller nudge, i.e. repel effect weakens with distance. - With positive `coef` nudges close to source are computed in a way to remove whole `[source - coef; source + coef]` range. - Negative `coef` results into attraction to source. Nudges in `[source - coef; source + coef]` range are computed to completely collapse it into `source`. Examples: >lua -- Repel hue from red color removing hue in range from 20 to 40 chan_repel('hue', 30, 10) -- Attract hue to red color collapsing [20; 40] range into 30. chan_repel('hue', 30, -10) < ### Parameters ~ {channel} `(string)` One of supported |MiniColors-channels|. {sources} `(table|number)` Single or multiple source from which to repel. {coef} `(number)` Repel degree (can be negative to attract). {opts} `(table|nil)` Options. Possible fields: - `(function|string)` - filter colors to update. Possible values: - String representing target attributes. One of `'fg'`, `'bg'`, `'sp'`, `'term'` (only terminal colors). - Callable with signature as in |MiniColors-colorscheme:color_modify()|. Default: `nil` to update all colors. - `(string)` - gamut clipping method. One of `'chroma'`, `'lightness'`, `'cusp'`. See |MiniColors-gamut-clip|. Default: `'chroma'`. ## chan_set() ~ *MiniColors-colorscheme:chan_set()* Set channel to certain value(s). This can be used to ensure that channel has value(s) only within supplied set. If more than one is supplied, closest element to current value is used. ### Parameters ~ {channel} `(string)` One of supported |MiniColors-channels|. {values} `(table|number)` Single or multiple values to set. {opts} `(table|nil)` Options. Possible fields: - `(function|string)` - filter colors to update. Possible values: - String representing target attributes. One of `'fg'`, `'bg'`, `'sp'`, `'term'` (only terminal colors). - Callable with signature as in |MiniColors-colorscheme:color_modify()|. Default: `nil` to update all colors. - `(string)` - gamut clipping method. One of `'chroma'`, `'lightness'`, `'cusp'`. See |MiniColors-gamut-clip|. Default: `'chroma'`. ## color_modify() ~ *MiniColors-colorscheme:color_modify()* Modify all colors with a callable. It should return new color value (hex string or `nil` to remove attribute) base on the following input: - Current color as hex string. - Data about the color: a table with fields: - - one of `'fg'`, `'bg'`, `'sp'`, and `'term'` for terminal color. - - name of color source. Either a name of highlight group or string of the form `terminal_color_x` for terminal color (as in |terminal-config|). Example: >lua -- Set to '#dd2222' all foreground colors for groups starting with "N" color_modify(function(hex, data) if data.attr == 'fg' and data.name:find('^N') then return '#dd2222' end return hex end) < ### Parameters ~ {f} `(function)` Callable returning new color value. ## compress() ~ *MiniColors-colorscheme:compress()* Remove redundant highlight groups. These are one of the two kinds: - Having values identical to ones after |:hi-clear| (meaning they usually don't add new information). - Coming from a curated list of plugins with highlight groups usually not worth keeping around. Current list of such plugins: - [nvim-tree/nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons) - [norcalli/nvim-colorizer.lua](https://github.com/norcalli/nvim-colorizer.lua) This method is useful to reduce size of color scheme before writing into the file with |MiniColors-colorscheme:write()|. ### Parameters ~ {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - whether to remove highlight groups from a curated list of plugins. Default: `true`. ## get_palette() ~ *MiniColors-colorscheme:get_palette()* Get commonly used colors. This basically counts number of all color occurrences and filter out rare ones. It is usually a good idea to apply both |MiniColors-colorscheme:compress()| and |MiniColors-colorscheme:resolve_links()| before applying this. ### Parameters ~ {opts} `(table|nil)` Options. Possible fields: - `(number)` - relative threshold for groups to keep. A group is not included in output if it has less than this many occurrences relative to a total number of colors. Default: 0.01. ## resolve_links() ~ *MiniColors-colorscheme:resolve_links()* Resolve links (|:highlight-link|). This makes all highlight groups with `link` attribute have data from a linked one. Notes: - Resolves nested links. - If some group is linked to a group missing in current colorscheme object, it is not resolved. ## simulate_cvd() ~ *MiniColors-colorscheme:simulate_cvd()* Simulate color vision deficiency (CVD, color blindness). This is basically a wrapper using |MiniColors.simulate_cvd()| as a part of call to |MiniColors-colorscheme:color_modify()| method. ### Parameters ~ {cvd_type} `(string)` One of `'protan'`, `'deutan'`, `'tritan'`, `'mono'`. {severity} `(number|nil)` Severity of CVD, number between 0 and 1. Default: 1. ## write() ~ *MiniColors-colorscheme:write()* Write color scheme to a file. It will be a Lua script readily usable as a regular color scheme. Useful to both save results of color scheme tweaking and making local snapshot of some other color scheme. Sourcing this file on startup usually leads to a better performance that sourcing initial color scheme, as it is essentially a conditioned |:hi-clear| call followed by a series of |nvim_set_hl()| calls. Default writing location is a "colors" directory of your Neovim config directory (see |base-directories|). After writing, it should be available for sourcing with |:colorscheme| or |:Colorscheme|. Name of the file by default is taken from `name` field (`'mini_colors'` is used if it is `nil`). If color scheme with this name already exists, it appends prefix based on current time to make it unique. Notes: - If colors were updated, it is usually a good idea to infer cterm attributes with |MiniColors-colorscheme:add_cterm_attributes()| prior to writing. ### Parameters ~ {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - whether to call |MiniColors-colorscheme:compress()| prior to writing. Default: `true`. - `(string|nil)` - basename of written file. Default: `nil` to infer from `name` field. - `(string)` - directory to where file should be saved. Default: "colors" subdirectory of Neovim home config (`stdpath("config")`). ------------------------------------------------------------------------------ *MiniColors.setup()* `MiniColors.setup`({config}) Module setup # :Colorscheme ~ *:Colorscheme* Calling this function creates a `:Colorscheme` user command. It takes one or more registered color scheme names and performs animated transition between them (starting from currently active color scheme). It uses |MiniColors.animate()| with default options. Parameters ~ {config} `(table|nil)` Module config table. See |MiniColors.config|. Usage ~ >lua require('mini.colors').setup() -- use default config -- OR require('mini.colors').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniColors.config* `MiniColors.config` Defaults ~ >lua MiniColors.config = {} < ------------------------------------------------------------------------------ *MiniColors.as_colorscheme()* `MiniColors.as_colorscheme`({x}) Create colorscheme object Parameters ~ {x} `(table)` Table to be transformed into |MiniColors-colorscheme| object. Return ~ `(table)` Copy of `x` transformed into a colorscheme object. ------------------------------------------------------------------------------ *MiniColors.get_colorscheme()* `MiniColors.get_colorscheme`({name}, {opts}) Get colorscheme object from registered color scheme Parameters ~ {name} `(string|nil)` Name of color scheme to use. If `nil` (default) creates colorscheme object based on currently active data (|g:colors_name|, highlight groups, terminal colors). If string, converts color scheme with that name to a colorscheme object. {opts} `(table|nil)` Options. Possible fields: - `(string|nil)` - new name of colorscheme object. Return ~ `(table)` Colorscheme object (|MiniColors-colorscheme|). ------------------------------------------------------------------------------ *MiniColors.interactive()* `MiniColors.interactive`({opts}) Start interactive experiments Create a special buffer in which user can write plain Lua code to tweak color scheme and apply to get visual feedback. # General principles ~ - Initial colorscheme object is fixed to interactive buffer on its creation. - There are special buffer convenience mappings: - Apply (source) current buffer content. - Reset color scheme (make initial colorscheme the current one). - Write to a file the result of applying current buffer content. This sources current content and calls |MiniColors-colorscheme:write()|. - Quit interactive buffer. - User is expected to iteratively tweak color scheme by writing general Lua code in interactive buffer and applying it using convenience mapping. - Application of interactive buffer is essentially these steps: - Expose `self` as initial colorscheme object on any application. It is always the same for every application. - Expose initial colorscheme methods as standalone functions. So instead of writing `self = self:add_transparency()` user can only write `add_transparency()`. - Source buffer content as plain Lua code. Example of interactive buffer content: >lua chan_modify('hue', function() return math.random(0, 359) end) simulate_cvd('protan') add_cterm_attributes() add_terminal_colors() < Parameters ~ {opts} `(table|nil)` Options. Possible fields: - `(table|nil)` - |MiniColors-colorscheme| object to be used as initial colorscheme for executed code. By default uses current color scheme. - `table` - buffer mappings for actions. Possible fields: - `(string)` - apply buffer code. Default: `''`. - `(string)` - apply initial color scheme as is. Default: `''`. - `(string)` - close interactive buffer. Default: `''`. - `(string)` - write result of buffer code into a file. Prompts for file name with |vim.ui.input()| and then uses |MiniColors-colorscheme:write()| with other options being default. Default: `''`. ------------------------------------------------------------------------------ *MiniColors.animate()* `MiniColors.animate`({cs_array}, {opts}) Animate color scheme change Start from currently active color scheme and loop through `cs_array`. Powers |:Colorscheme| user command created in |MiniColors.setup()|. Parameters ~ {cs_array} `(table)` Array of |MiniColors-colorscheme| objects. {opts} `(table|nil)` Options. Possible fields: - `(number)` - number of intermediate steps to show during transition between two color schemes. Bigger values result in smoother visual feedback but require more computational power. Default: 25. - `(number)` - number of milliseconds to spend showing transition. Default: 1000. - `(number)` - number of milliseconds to show intermediate color schemes (all but last in `cs_array`). Default: 1000. ------------------------------------------------------------------------------ *MiniColors.convert()* `MiniColors.convert`({x}, {to_space}, {opts}) Convert between color spaces For a list of supported colors spaces see |MiniColors-color-spaces|. Parameters ~ {x} `(table|string|number|nil)` Color to convert from. Its color space is inferred automatically. {to_space} `(string)` Id of allowed color space. {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - whether to adjust lightness value to have a more uniform progression from 0 to 100. Set `false` for results more compatible with some other Oklab/Oklch implementations (like in CSS). Source: "Intermission - a new lightness estimate for Oklab" section of https://bottosson.github.io/posts/colorpicker Default: `true`. - `(string)` - method for |MiniColors-gamut-clip|. Default: `'chroma'`. Return ~ `(table|string|number|nil)` Color in space `to_space` or `nil` if input is `nil`. ------------------------------------------------------------------------------ *MiniColors.modify_channel()* `MiniColors.modify_channel`({x}, {channel}, {f}, {opts}) Modify channel Parameters ~ {x} `(table|string|number|nil)` Color which channel will be modified. Color space is inferred automatically. {channel} `(string)` One of supported |MiniColors-channels|. {f} `(function)` Callable which defines modification. Should take current value of a channel and return a new one. {opts} `(table|nil)` Options. Possible fields: - `(string)` - method for |MiniColors-gamut-clip|. Default: `'chroma'`. Return ~ `(string|nil)` Hex string of color with modified channel or `nil` if input is `nil`. ------------------------------------------------------------------------------ *MiniColors.simulate_cvd()* `MiniColors.simulate_cvd`({x}, {cvd_type}, {severity}) Simulate color vision deficiency Parameters ~ {x} `(table|string|number|nil)` Color to convert from. Its color space is inferred automatically. {cvd_type} `(string)` Type of CVD. One of `'protan'`, `'deutan'`, or `'mono'` (equivalent to converting to graysacle). {severity} `(number|nil)` Severity of CVD. A number between 0 and 1 (default). Return ~ `(string|nil)` Hex string of simulated color or `nil` if input is `nil`. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-comment.txt ================================================ *mini.comment* Comment lines MIT License Copyright (c) 2021 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniComment* Features: - Commenting in Normal mode respects |count| and is dot-repeatable. - Comment structure by default is inferred from 'commentstring': either from current buffer or from locally active tree-sitter language. It can be customized via `options.custom_commentstring` (see |MiniComment.config| for details). - Allows custom hooks before and after successful commenting. - Configurable options for some nuanced behavior. What it doesn't do: - Block and sub-line comments. This will only support per-line commenting. - Handle indentation with mixed tab and space. - Preserve trailing whitespace in empty lines. Notes: - To use tree-sitter aware commenting, global value of 'commentstring' should be `''` (empty string). This is the default value, so make sure to not set it manually to a different value. # Setup ~ This module needs a setup with `require('mini.comment').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniComment` which you can use for scripting or manually (with `:lua MiniComment.*`). See |MiniComment.config| for `config` structure and default values. You can override runtime config settings locally to buffer inside `vim.b.minicomment_config` which should have same structure as `MiniComment.config`. See |mini.nvim-buffer-local-config| for more details. # Disabling ~ To disable core functionality, set `vim.g.minicomment_disable` (globally) or `vim.b.minicomment_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniComment.setup()* `MiniComment.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniComment.config|. Usage ~ >lua require('mini.comment').setup() -- use default config -- OR require('mini.comment').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniComment.config* `MiniComment.config` Defaults ~ >lua MiniComment.config = { -- Options which control module behavior options = { -- Function to compute custom 'commentstring' (optional) custom_commentstring = nil, -- Whether to ignore blank lines in actions and textobject ignore_blank_line = false, -- Whether to recognize as comment only lines without indent start_of_line = false, -- Whether to force single space inner padding for comment parts pad_comment_parts = true, }, -- Module mappings. Use `''` (empty string) to disable one. mappings = { -- Toggle comment (like `gcip` - comment inner paragraph) for both -- Normal and Visual modes comment = 'gc', -- Toggle comment on current line comment_line = 'gcc', -- Toggle comment on visual selection comment_visual = 'gc', -- Define 'comment' textobject (like `dgc` - delete whole comment block) -- Works also in Visual mode if mapping differs from `comment_visual` textobject = 'gc', }, -- Hook functions to be executed at certain stage of commenting hooks = { -- Before successful commenting. Does nothing by default. pre = function() end, -- After successful commenting. Does nothing by default. post = function() end, }, } < # Options ~ ## Custom commentstring ~ `options.custom_commentstring` can be a function customizing 'commentstring' option used to infer comment structure. It is called once before every commenting action with the following arguments: - `ref_position` - position at which to compute 'commentstring' (might be relevant for a text with locally different commenting rules). Its structure is the same as `opts.ref_position` in |MiniComment.toggle_lines()|. Its output should be a valid 'commentstring' (string containing `%s`). If not set or the output is `nil`, |MiniComment.get_commentstring()| is used. For example, this option can be used to always use buffer 'commentstring' even in case of present active tree-sitter parser: >lua require('mini.comment').setup({ options = { custom_commentstring = function() return vim.bo.commentstring end, } }) < # Hooks ~ `hooks.pre` and `hooks.post` functions are executed before and after successful commenting action (toggle or computing textobject). They will be called with a single table argument which has the following fields: - `(string)` - action name. One of "toggle" (when actual toggle direction is yet unknown), "comment", "uncomment", "textobject". - `(number|nil)` - action start line. Can be absent if yet unknown. - `(number|nil)` - action end line. Can be absent if yet unknown. - `(table|nil)` - reference position. Notes: - Changing 'commentstring' in `hooks.pre` is allowed and will take effect. - If hook returns `false`, any further action is terminated. ------------------------------------------------------------------------------ *MiniComment.operator()* `MiniComment.operator`({mode}) Main function to be mapped It is meant to be used in expression mappings (see |:map-|) to enable dot-repeatability and commenting on range. There is no need to do this manually, everything is done inside |MiniComment.setup()|. It has a somewhat unintuitive logic (because of how expression mapping with dot-repeatability works): it should be called without arguments inside expression mapping and with argument when action should be performed. Parameters ~ {mode} `(string|nil)` Optional string with 'operatorfunc' mode (see |g@|). Return ~ `(string|nil)` 'g@' if called without argument, '' otherwise (but after performing action). ------------------------------------------------------------------------------ *MiniComment.toggle_lines()* `MiniComment.toggle_lines`({line_start}, {line_end}, {opts}) Toggle comments between two line numbers It uncomments if lines are comment (every line is a comment or blank) and comments otherwise. It respects indentation and doesn't insert trailing whitespace. Toggle commenting not in visual mode is also dot-repeatable and respects |count|. # Notes ~ - Comment structure is inferred from buffer's 'commentstring' option or local language of tree-sitter parser (if active). - Call to this function will remove all |extmarks| from target range. Parameters ~ {line_start} `(number)` Start line number (inclusive from 1 to number of lines). {line_end} `(number)` End line number (inclusive from 1 to number of lines). {opts} `(table|nil)` Options. Possible fields: - `(table)` - A two-value array with `{ row, col }` (both starting at 1) of reference position at which 'commentstring' value will be computed. Default: `{ line_start, 1 }`. ------------------------------------------------------------------------------ *MiniComment.textobject()* `MiniComment.textobject`() Select comment textobject This selects all commented lines adjacent to cursor line. If `ignore_blank_line` option is enabled (see |MiniComment.config|), blank lines between commented lines are treated as part of textobject. Designed to be used with operator mode mappings (see |mapmode-o|). ------------------------------------------------------------------------------ *MiniComment.get_commentstring()* `MiniComment.get_commentstring`({ref_position}) Get 'commentstring' This function represents default approach of computing relevant 'commentstring' option in current buffer. Used to infer comment structure. It has the following logic: - If there is an active tree-sitter parser, try to get 'commentstring' from the local language at `ref_position`. - If first step is not successful, use buffer's 'commentstring' directly. Parameters ~ {ref_position} `(table)` Reference position inside current buffer at which to compute 'commentstring'. Same structure as `opts.ref_position` in |MiniComment.toggle_lines()|. Return ~ `(string)` Relevant value of 'commentstring'. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-completion.txt ================================================ *mini.completion* Completion and signature help MIT License Copyright (c) 2021 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniCompletion* Key design ideas: - Have an async (with customizable "debounce" delay) "two-stage chain completion": first try to get completion items from LSP client (if set up) and if no result, fallback to custom action. - Managing completion is done as much with Neovim's built-in tools as possible. |popupmenu-completion| is used to show completion suggestions. Features: - Two-stage chain completion: - First stage is an LSP completion implemented via |MiniCompletion.completefunc_lsp()|. It should be set up as either |'completefunc'| or |'omnifunc'|. It tries to get completion items from LSP client (via 'textDocument/completion' request). Custom preprocessing of response items is possible (with `MiniCompletion.config.lsp_completion.process_items`), for example with fuzzy matching. By default items directly starting with completed word are kept and are sorted according to LSP specification. Supports `additionalTextEdits`, like auto-import and others (see 'Notes'), and snippet items (best results require |mini.snippets| dependency). - If first stage is not set up or resulted into no candidates, fallback action is executed. The most tested actions are Neovim's built-in insert completion (see |ins-completion|). - Automatic display in floating window of completion item info (via 'completionItem/resolve' request) and signature help (with highlighting of active parameter if LSP server provides such information). Signature help is shown if character to cursor's left is a dedicated trigger character (configured in `signatureHelpProvider.triggerCharacters` of LSP server capabilities) and updated without delay if is currently opened. Already shown window for signature help is fixed and is closed when there is nothing to show, its text is different, or when leaving Insert mode. Scroll in either info/signature window with `` / `` (by default). - Automatic actions are done after some configurable amount of delay. This reduces computational load and allows fast typing (completion and signature help) and item selection (item info) - Force two-stage/fallback completion (`` / `` by default). - Customizable highlighting of LSP items. Requires Neovim>=0.11. Use `config.lsp_completion.process_items` to set dedicated highlight group in supported fields: - - item label (`abbr` in terms of |complete-items|). By default only checks if item is marked as deprecated and sets `MiniCompletionDeprecated` highlight group. - - LSP kind ("Function", "Keyword", etc.). By default uses "lsp" category of |mini.icons| (if enabled). What it doesn't do: - Many configurable sources. - Automatic mapping of ``, ``, etc. Those tend to have highly variable user expectations. See 'Helpful mappings' for suggestions or use |MiniKeymap.map_multistep()| with `"pmenu_*"` built-in steps. # Dependencies ~ Suggested dependencies (provide extra functionality, will work without them): - Enabled |mini.icons| module to highlight LSP kind (requires Neovim>=0.11). If absent, |MiniCompletion.default_process_items()| does not add highlighting. Also take a look at |MiniIcons.tweak_lsp_kind()|. - Enabled |mini.snippets| module for better snippet handling (much recommended). If absent and custom snippet insert is not configured, |vim.snippet.expand()| is used on Neovim>=0.10 (nothing extra is done on earlier versions). See |MiniCompletion.default_snippet_insert()|. # Setup ~ This module needs a setup with `require('mini.completion').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniCompletion` which you can use for scripting or manually (with `:lua MiniCompletion.*`). See |MiniCompletion.config| for `config` structure and default values. You can override runtime config settings locally to buffer inside `vim.b.minicompletion_config` which should have same structure as `MiniCompletion.config`. See |mini.nvim-buffer-local-config| for more details. # Suggested option values ~ Some options are set automatically (if not set before |MiniCompletion.setup()|): - 'completeopt' is set to "menuone,noselect" for less intrusive popup. To enable fuzzy matching, manually set to "menuone,noselect,fuzzy". Consider also adding "nosort" flag to preserve initial order when filtering. - 'shortmess' is appended with "c" flag for silent fallback. - 'complete' gets removed "t" flag (if fallback action is default), as it leads to visible lags. # Snippets ~ As per LSP specification, some completion items can be supplied in the form of snippet - a template with both pre-defined text and places (called "tabstops") for user to interactively change/add text during snippet session. In 'mini.completion' items that will insert snippet have "S" symbol shown in the popup (as part of `menu` in |complete-items|). To actually insert a snippet: - Select an item via / . This will insert item's label (usually not full snippet) first to reduce visual flicker. The full snippet text will be shown in info window if LSP server doesn't provide its own info for an item. - Press (|complete_CTRL-Y|) or attempt inserting a non-keyword character (like ; new character will be removed). It will clear text from previous step, set cursor, and call `lsp_completion.snippet_insert` with snippet text. - Press (|complete_CTRL-E|) to cancel snippet insert and properly end completion. See |MiniCompletion.default_snippet_insert()| for overview of how to work with inserted snippets. Notes: - To stop LSP server from suggesting snippets, disable (set to `false`) the following capability during LSP server start: `textDocument.completion.completionItem.snippetSupport`. - If snippet body doesn't contain tabstop, variable, tab, or newline, `lsp_completion.snippet_insert` is not called and text is inserted as-is. # Notes ~ - A more appropriate (albeit slightly advanced) LSP completion setup is to set it not on every |BufEnter| event (default), but on every attach of LSP client. To do that: - Use in |MiniCompletion.setup()| config: >lua lsp_completion = { source_func = 'omnifunc', auto_setup = false } < - Set 'omnifunc' option to exactly `v:lua.MiniCompletion.completefunc_lsp` for every client attach in an |LspAttach| event. Like this: >lua local on_attach = function(args) vim.bo[args.buf].omnifunc = 'v:lua.MiniCompletion.completefunc_lsp' end vim.api.nvim_create_autocmd('LspAttach', { callback = on_attach }) < This setup is not default to allow simultaneous usage of filetype-specific 'omnifunc' (with manual |i_CTRL-X_CTRL-O|) and automated LSP completion. - Use |MiniCompletion.get_lsp_capabilities()| to get/set information about part of LSP specification supported by module. See its help for usability notes. - Uses `vim.lsp.protocol.CompletionItemKind` map in LSP step to show a readable version of item's kind. Modify it directly to change what is displayed. If you have |mini.icons| enabled, take a look at |MiniIcons.tweak_lsp_kind()|. - If you have trouble using custom (overridden) |vim.ui.input()|, disable 'mini.completion' for input buffer (usually based on its 'filetype'). # Comparisons ~ - [hrsh7th/nvim-cmp](https://github.com/hrsh7th/nvim-cmp): - Implements own popup menu to show completion candidates, while this module reuses |ins-completion-menu|. - Has more complex design which allows multiple sources, each in a form of a separate plugin. This module has two built-in: LSP and fallback. - Requires separate plugin for automated signature help. - Implements own "ghost text" feature, while this module does not. - [Saghen/blink.cmp](https://github.com/Saghen/blink.cmp): - Mostly similar to 'nvim-cmp' comparison: provides more features at the cost of more code and config complexity, while this module is designed to provide only a handful of "enough" features while relying on Neovim's built-in capabilities as much as possible. - Both provide automated signature help out of the box. # Helpful mappings ~ If there is |mini.keymap| available, prefer using |MiniKeymap.map_multistep()| with `"pmenu_*"` built-in steps. See |MiniKeymap-examples| for examples. To use `` and `` for navigation through completion list, make these mappings: >lua local imap_expr = function(lhs, rhs) vim.keymap.set('i', lhs, rhs, { expr = true }) end imap_expr('', [[pumvisible() ? "\" : "\"]]) imap_expr('', [[pumvisible() ? "\" : "\"]]) < To get more consistent behavior of ``, you can use this template in your 'init.lua' to make customized mapping: >lua _G.cr_action = function() -- If there is selected item in popup, accept it with if vim.fn.complete_info()['selected'] ~= -1 then return '\25' end -- Fall back to plain ``. You might want to customize according -- to other plugins. For example if 'mini.pairs' is set up, replace -- next line with `return MiniPairs.cr()` return '\r' end vim.keymap.set('i', '', 'v:lua.cr_action()', { expr = true }) < # Highlight groups ~ - `MiniCompletionActiveParameter` - signature active parameter. - `MiniCompletionDeprecated` - candidates that marked as deprecated. - `MiniCompletionInfoBorderOutdated` - info window border when text is outdated due to explicit delay during fast movement through candidates. To change any highlight group, set it directly with |nvim_set_hl()|. # Disabling ~ To disable, set `vim.g.minicompletion_disable` (globally) or `vim.b.minicompletion_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniCompletion-events* To allow user customization, certain |User| autocommand events are triggered under common circumstances: - Info and signature help window: - `MiniCompletionWindowOpen` - after opening new window. - `MiniCompletionWindowUpdate` - after updating existing window. Each event's |event-data| table contains `kind` (one of "info" or "signature") and `win_id` (affected window identifier) fields. ------------------------------------------------------------------------------ *MiniCompletion.setup()* `MiniCompletion.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniCompletion.config|. Usage ~ >lua require('mini.completion').setup() -- use default config -- OR require('mini.completion').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniCompletion.config* `MiniCompletion.config` Defaults ~ >lua MiniCompletion.config = { -- Delay (debounce type, in ms) between certain Neovim event and action. -- This can be used to (virtually) disable certain automatic actions by -- setting very high delay time (like 10^7). delay = { completion = 100, info = 100, signature = 50 }, -- Configuration for action windows: -- - `height` and `width` are maximum dimensions. -- - `border` defines border (as in `nvim_open_win()`; default "single"). window = { info = { height = 25, width = 80, border = nil }, signature = { height = 25, width = 80, border = nil }, }, -- Way of how module does LSP completion lsp_completion = { -- `source_func` should be one of 'completefunc' or 'omnifunc'. source_func = 'completefunc', -- `auto_setup` should be boolean indicating if LSP completion is set up -- on every `BufEnter` event. auto_setup = true, -- A function which takes LSP 'textDocument/completion' response items -- (each with `client_id` field for item's server) and word to complete. -- Output should be a table of the same nature as input. Common use case -- is custom filter/sort. Default: `default_process_items` process_items = nil, -- A function which takes a snippet as string and inserts it at cursor. -- Default: `default_snippet_insert` which tries to use 'mini.snippets' -- and falls back to `vim.snippet.expand` (on Neovim>=0.10). snippet_insert = nil, }, -- Fallback action as function/string. Executed in Insert mode. -- To use built-in completion (`:h ins-completion`), set its mapping as -- string. Example: set '' for 'whole lines' completion. fallback_action = '', -- Module mappings. Use `''` (empty string) to disable one. Some of them -- might conflict with system mappings. mappings = { -- Force two-step/fallback completions force_twostep = '', force_fallback = '', -- Scroll info/signature window down/up. When overriding, check for -- conflicts with built-in keys for popup menu (like ``/`` -- for 'completefunc'/'omnifunc' source function; or ``/``). scroll_down = '', scroll_up = '', }, } < ------------------------------------------------------------------------------ *MiniCompletion.complete_twostage()* `MiniCompletion.complete_twostage`({fallback}, {force}) Run two-stage completion Parameters ~ {fallback} `(boolean|nil)` Whether to use fallback completion. Default: `true`. {force} `(boolean|nil)` Whether to force update of completion popup. Default: `true`. ------------------------------------------------------------------------------ *MiniCompletion.complete_fallback()* `MiniCompletion.complete_fallback`() Run fallback completion ------------------------------------------------------------------------------ *MiniCompletion.scroll()* `MiniCompletion.scroll`({direction}) Scroll in info/signature window Designed to be used in |:map-|. Scrolling is done as if |CTRL-F| and |CTRL-B| is pressed inside target window. Used in default `config.mappings.scroll_xxx` mappings. Parameters ~ {direction} `(string)` One of `"down"` or `"up"`. Return ~ `(boolean)` Whether scroll is scheduled to be done. ------------------------------------------------------------------------------ *MiniCompletion.stop()* `MiniCompletion.stop`({actions}) Stop actions This stops currently active (because of module delay or LSP answer delay) actions. Designed to be used with |autocmd|. No need to use it directly, everything is setup in |MiniCompletion.setup()|. Parameters ~ {actions} `(table|nil)` Array containing any of 'completion', 'info', or 'signature' string. Default: array containing all of them. ------------------------------------------------------------------------------ *MiniCompletion.completefunc_lsp()* `MiniCompletion.completefunc_lsp`({findstart}, {base}) Module's |complete-functions| This is the main function which enables two-stage completion. It should be set as one of |'completefunc'| or |'omnifunc'|. No need to use it directly, everything is setup in |MiniCompletion.setup()|. ------------------------------------------------------------------------------ *MiniCompletion.default_process_items()* `MiniCompletion.default_process_items`({items}, {base}, {opts}) Default processing of LSP items Steps: - Filter and sort items according to supplied method. - Arrange items further by completion item kind according to their priority. - Add `MiniCompletionDeprecated` if item is marked as deprecated. - If |mini.icons| is enabled, add based on the "lsp" category. Example of forcing fuzzy matching, filtering out `Text` items, and putting `Snippet` items last: >lua local kind_priority = { Text = -1, Snippet = 99 } local opts = { filtersort = 'fuzzy', kind_priority = kind_priority } local process_items = function(items, base) return MiniCompletion.default_process_items(items, base, opts) end require('mini.completion').setup({ lsp_completion = { process_items = process_items }, }) < Parameters ~ {items} `(table)` Array of items from LSP response. {base} `(string)` Base for which completion is done. See |complete-functions|. {opts} `(table|nil)` Options. Possible fields: - `(string|function)` - method of filtering and sorting items. If string, should be one of the following: - `'prefix'` - filter out items not starting with `base`, sort according to LSP specification. Use `filterText` and `sortText` respectively with fallback to `label`. - `'fuzzy'` - filter and sort with |matchfuzzy()| using `filterText`. - `'none'` - no filter and no sort. If callable, should take `items` and `base` arguments and return items array. Default: `'fuzzy'` if 'completeopt' contains "fuzzy", `'prefix'` otherwise. - `(table)` - map of completion item kinds (like `Variable`, `Snippet`; see string keys of `vim.lsp.protocol.CompletionItemKind`) to their numerical priority. It will be used after applying to arrange by completion item kind: items with negative priority kinds will be filtered out, the rest are sorted by decreasing priority (preserving order in case of same priority). Priorities can be any number, only matters how they compare to each other. Value 100 is used for missing kinds (i.e. not all can be supplied). Default: `{}` (all equal priority). Return ~ `(table)` Array of processed items from LSP response. ------------------------------------------------------------------------------ *MiniCompletion.default_snippet_insert()* `MiniCompletion.default_snippet_insert`({snippet}) Default snippet insert Order of preference: - Use |mini.snippets| if set up (i.e. after `require('mini.snippets').setup()`). - Use |vim.snippet.expand()| on Neovim>=0.10 - Add snippet text at cursor as is. After snippet is inserted, user is expected to navigate/jump between dedicated places (tabstops) to adjust inserted text as needed: - |mini.snippets| by default uses / to jump to next/previous tabstop. Can be adjusted in `mappings` of |MiniSnippets.config|. - |vim.snippet| on Neovim=0.10 requires manually created mappings for jumping between tabstops (see |vim.snippet.jump()|). Neovim>=0.11 sets them up automatically to / (if not overridden by user). End session by navigating all the way to the last tabstop. In 'mini.snippets': - Also make any text edit or exit Insert mode to end the session. This allows smoother navigation to previous tabstops in case of a lately spotted typo. - Press `` to force session stop. Parameters ~ {snippet} `(string)` Snippet body to insert at cursor. See also ~ - |MiniSnippets-session| if 'mini.snippets' is set up. - |vim.snippet| for Neovim's built-in snippet engine. ------------------------------------------------------------------------------ *MiniCompletion.get_lsp_capabilities()* `MiniCompletion.get_lsp_capabilities`({opts}) Get client LSP capabilities Possible usages: - On Neovim>=0.11 via |vim.lsp.config()|: >lua vim.lsp.config('*', {capabilities = MiniCompletion.get_lsp_capabilities()}) < - Together with |vim.lsp.protocol.make_client_capabilities()| to get the full client capabilities (use |vim.tbl_deep_extend()| to merge tables). - Manually execute `:=MiniCompletion.get_lsp_capabilities()` to see the info. Notes: - It declares completion resolve support for `'additionalTextEdits'` (usually used for something like auto-import feature), as it is usually a more robust choice for various LSP servers. As a consequence, this requires selecting completion item and waiting for `config.delay.info` milliseconds plus server response time (i.e. until information window shows relevant text). To not have to wait after an item selection and if the server handles absent `'additionalTextEdits'` well, set `opts.resolve_additional_text_edits = false`. Parameters ~ {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - whether to declare `'additionalTextEdits'` as possible to resolve in `'completionitem/resolve'` requrest. See above "Notes" section. Default: `true`. Return ~ `(table)` Data about LSP capabilities supported by 'mini.completion'. Has same structure as relevant parts of |vim.lsp.protocol.make_client_capabilities()|. See also ~ Structures of `completionClientCapabilities` and `signatureHelpClientCapabilities` at https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-cursorword.txt ================================================ *mini.cursorword* Autohighlight word under cursor MIT License Copyright (c) 2021 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniCursorword* Features: - Autohighlight word under cursor with customizable delay. - Current word under cursor can be highlighted differently. - Highlighting is triggered only if current cursor character is a |[:keyword:]|. - Highlighting stops in insert and terminal modes. - "Word under cursor" is meant as in Vim's ||: something user would get as 'iw' text object. # Setup ~ This module needs a setup with `require('mini.cursorword').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniCursorword` which you can use for scripting or manually (with `:lua MiniCursorword.*`). See |MiniCursorword.config| for `config` structure and default values. You can override runtime config settings locally to buffer inside `vim.b.minicursorword_config` which should have same structure as `MiniCursorword.config`. See |mini.nvim-buffer-local-config| for more details. # Highlight groups ~ - `MiniCursorword` - highlight group of a non-current cursor word. Default: plain underline. - `MiniCursorwordCurrent` - highlight group of a current word under cursor. Default: links to `MiniCursorword` (so `:hi clear MiniCursorwordCurrent` will lead to showing `MiniCursorword` highlight group). Note: To not highlight it, use the following Lua code: >lua vim.api.nvim_set_hl(0, 'MiniCursorwordCurrent', {}) < To change any highlight group, set it directly with |nvim_set_hl()|. # Disabling ~ To disable core functionality, set `vim.g.minicursorword_disable` (globally) or `vim.b.minicursorword_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. Note: after disabling there might be highlighting left; it will be removed after next highlighting update. Module-specific disabling: - Don't show highlighting if cursor is on the word that is in a blocklist of current filetype. In this example, blocklist for "lua" is "local" and "require" words, for "javascript" - "import": >lua _G.cursorword_blocklist = function() local curword = vim.fn.expand('') local filetype = vim.bo.filetype -- Add any disabling global or filetype-specific logic here local blocklist = {} if filetype == 'lua' then blocklist = { 'local', 'require' } elseif filetype == 'javascript' then blocklist = { 'import' } end vim.b.minicursorword_disable = vim.tbl_contains(blocklist, curword) end -- Make sure to add this autocommand *before* calling module's `setup()`. vim.cmd('au CursorMoved * lua _G.cursorword_blocklist()') < ------------------------------------------------------------------------------ *MiniCursorword.setup()* `MiniCursorword.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniCursorword.config|. Usage ~ >lua require('mini.cursorword').setup() -- use default config -- OR require('mini.cursorword').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniCursorword.config* `MiniCursorword.config` Defaults ~ >lua MiniCursorword.config = { -- Delay (in ms) between when cursor moved and when highlighting appeared delay = 100, } < vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-deps.txt ================================================ *mini.deps* Plugin manager MIT License Copyright (c) 2024 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniDeps* Features: - Manage plugins utilizing Git and built-in |packages| with these actions: - Add plugin to current session, download if absent. See |MiniDeps.add()|. - Update with/without confirm, with/without parallel download of new data. See |MiniDeps.update()|. - Delete unused plugins with/without confirm. See |MiniDeps.clean()|. - Get / set / save / load snapshot. See `MiniDeps.snap_*()` functions. All main actions are available both as Lua functions and user commands (see |MiniDeps-commands|). - Minimal yet flexible plugin |MiniDeps-plugin-specification|: - Plugin source. - Name of target plugin directory. - Checkout target: branch, commit, tag, etc. - Monitor branch to track updates without checking out. - Dependencies to be set up prior to the target plugin. - Hooks to call before/after plugin is created/changed. - Helpers implementing two-stage startup: |MiniDeps.now()| and |MiniDeps.later()|. See |MiniDeps-overview| for how to implement basic lazy loading with them. What it doesn't do: - Manage plugins which are developed without Git. The suggested approach is to create a separate package (see |packages|). - Provide ways to completely remove or update plugin's functionality in current session. Although this is partially doable, it can not be done in full (yet) because plugins can have untraceable side effects (autocmmands, mappings, etc.). The suggested approach is to restart Nvim. Sources with more details: - |MiniDeps-overview| - |MiniDeps-plugin-specification| - |MiniDeps-commands| # Dependencies ~ For most of its functionality this plugin relies on `git` CLI tool. See https://git-scm.com/ for more information about how to install it. Actual knowledge of Git is not required but helpful. # Setup ~ This module needs a setup with `require('mini.deps').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniDeps` which you can use for scripting or manually (with `:lua MiniDeps.*`). See |MiniDeps.config| for `config` structure and default values. You can override runtime config settings locally to buffer inside `vim.b.minideps_config` which should have same structure as `MiniDeps.config`. See |mini.nvim-buffer-local-config| for more details. # Comparisons ~ - [folke/lazy.nvim](https://github.com/folke/lazy.nvim): - More feature-rich and complex. - Uses table specification with dedicated functions to add plugins, while this module uses direct function call approach (calling |MiniDeps.add()| ensures that plugin is usable). - Uses version tags by default, while this module is more designed towards tracking branches. Using tags is possible too (see |MiniDeps-overview|). - [savq/paq-nvim](https://github.com/savq/paq-nvim): - Overall less feature-rich than this module (by design). - Uses array of plugin specifications inside `setup()` call to define which plugins should be installed. Requires separate `:PaqInstall` call to actually install them. This module ensures installation on first load. - [junegunn/vim-plug](https://github.com/junegunn/vim-plug): - Written in Vimscript, while this module is in Lua. - Similar approach to defining and installing plugins as 'savq/paq-nvim'. - Has basic lazy-loading built-in, while this module does not (by design). # Highlight groups ~ Highlight groups are used inside confirmation buffers after default |MiniDeps.update()| and |MiniDeps.clean()|. - `MiniDepsChangeAdded` - added change (commit) during update. - `MiniDepsChangeRemoved` - removed change (commit) during update. - `MiniDepsHint` - various hints. - `MiniDepsInfo` - various information. - `MiniDepsMsgBreaking` - message for (conventional commit) breaking change. - `MiniDepsPlaceholder` - placeholder when there is no valuable information. - `MiniDepsTitle` - various titles. - `MiniDepsTitleError` - title when plugin had errors during update. - `MiniDepsTitleSame` - title when plugin has no changes to update. - `MiniDepsTitleUpdate` - title when plugin has changes to update. To change any highlight group, set it directly with |nvim_set_hl()|. ------------------------------------------------------------------------------ *MiniDeps-overview* # Directory structure ~ This module uses built-in |packages| to make plugins usable in current session. It works with "pack/deps" package inside `config.path.package` directory. By default "opt" subdirectory is used to install optional plugins which are loaded on demand with |MiniDeps.add()|. Non-optional plugins in "start" subdirectory are supported but only if moved there manually after initial install. Use it if you know what you are doing. # Add plugin ~ Use |MiniDeps.add()| to add plugin to current session. Supply plugin's URL source as a string or |MiniDeps-plugin-specification| in general. If plugin is not present in "pack/deps" package, it will be created (a.k.a. installed) before processing anything else. The recommended way of adding a plugin is by calling |MiniDeps.add()| in the |init.lua| file (make sure |MiniDeps.setup()| is called prior): >lua local add = MiniDeps.add -- Add to current session (install if absent) add({ source = 'neovim/nvim-lspconfig', -- Supply dependencies near target plugin depends = { 'williamboman/mason.nvim' }, }) add({ source = 'nvim-treesitter/nvim-treesitter', -- Use 'master' while monitoring updates in 'main' checkout = 'master', monitor = 'main', -- Perform action after every checkout hooks = { post_checkout = function() vim.cmd('TSUpdate') end }, }) -- Possible to immediately execute code which depends on the added plugin require('nvim-treesitter.configs').setup({ ensure_installed = { 'lua', 'vimdoc' }, highlight = { enable = true }, }) < NOTE: - To increase performance, `add()` only ensures presence on disk and nothing else. In particular, it doesn't ensure `opts.checkout` state. Update or modify plugin state explicitly (see later sections). # Lazy loading ~ Any lazy-loading is assumed to be done manually by calling |MiniDeps.add()| at appropriate time. This module provides helpers implementing special safe two-stage loading: - |MiniDeps.now()| safely executes code immediately. Use it to load plugins with UI necessary to make initial screen draw. - |MiniDeps.later()| schedules code to be safely executed later, preserving order. Use it (with caution) for everything else which doesn't need precisely timed effect, as it will be executed some time soon on one of the next event loops. >lua local now, later = MiniDeps.now, MiniDeps.later -- Safely execute immediately now(function() vim.cmd('colorscheme miniwinter') end) now(function() require('mini.statusline').setup() end) -- Safely execute later later(function() require('mini.pick').setup() end) < # Update ~ To update plugins from current session with new data from their sources, use |:DepsUpdate|. This will download updates (utilizing multiple cores) and show confirmation buffer. Follow instructions at its top to finish an update. NOTE: This updates plugins on disk which most likely won't affect current session. Restart Nvim to have them properly loaded. # Modify ~ To change plugin's specification (like set different `checkout`, etc.): - Update corresponding |MiniDeps.add()| call. - Run `:DepsUpdateOffline `. - Review changes and confirm. - Restart Nvim. NOTE: if `add()` prior used a single source string, make sure to convert its argument to `{ source = '', checkout = ''}` # Snapshots ~ Use |:DepsSnapSave| to save state of all plugins from current session into a snapshot file (see `config.path.snapshot`). Use |:DepsSnapLoad| to load snapshot. This will change (without confirmation) state on disk. Plugins present in both snapshot file and current session will be affected. Restart Nvim to see the effect. NOTE: loading snapshot does not change plugin's specification defined inside |MiniDeps.add()| call. This means that next update might change plugin's state. To make it permanent, freeze plugin in target state manually. # Freeze ~ Modify plugin's specification to have `checkout` pointing to a static target: tag, state (commit hash), or 'HEAD' (to freeze in current state). Frozen plugins will not receive updates. You can monitor any new changes from its source by "subscribing" to `monitor` branch which will be shown inside confirmation buffer after |:DepsUpdate|. Example: use `checkout = 'v0.10.0'` to freeze plugin at tag "v0.10.0" while monitoring new versions in the log from `monitor` (usually default) branch. # Rollback ~ To roll back after an unfortunate update: - Get identifier of latest working state: - Use |:DepsShowLog| to see update log, look for plugin's name, and copy identifier listed as "State before:". - See previously saved snapshot file for plugin's name and copy identifier next to it. - Freeze plugin at that state while monitoring appropriate branch. Revert to previous shape of |MiniDeps.add()| call to resume updating. # Remove ~ - Make sure that target plugin is not registered in current session. Usually it means removing corresponding |MiniDeps.add()| call. - Run |:DepsClean|. This will show confirmation buffer with a list of plugins to be deleted from disk. Follow instructions at its top to finish cleaning. Alternatively, manually delete plugin's directory from "pack/deps" package. ------------------------------------------------------------------------------ *MiniDeps-plugin-specification* Each plugin dependency is managed based on its specification (a.k.a. "spec"). See |MiniDeps-overview| for some examples. Specification can be a single string which is inferred as: - Plugin if it doesn't contain "/". - Plugin otherwise. Primarily, specification is a table with the following fields: - `(string|nil)` - field with URI of plugin source used during creation or update. Can be anything allowed by `git clone`. Default: `nil` to rely on source set up during install. Notes: - It is required for creating plugin, but can be omitted afterwards. - As the most common case, URI of the format "user/repo" (if it contains valid characters) is transformed into "https://github.com/user/repo". - `(string|nil)` - directory basename of where to put plugin source. It is put in "pack/deps/opt" subdirectory of `config.path.package`. Default: basename of if it is present, otherwise should be provided explicitly. - `(string|nil)` - checkout target used to set state during update. Can be anything supported by `git checkout` - branch, commit, tag, etc. Default: `nil` for default branch (usually "main" or "master"). - `(string|nil)` - monitor branch used to track new changes from different target than `checkout`. Should be a name of present Git branch. Default: `nil` for default branch (usually "main" or "master"). - `(table|nil)` - array of plugin specifications (strings or tables) to be added prior to the target. Default: `nil` for no dependencies. - `(table|nil)` - table with callable hooks to call on certain events. Possible hook names: - - before creating plugin directory. - - after creating plugin directory (before |:packadd|). - - before making change in existing plugin. - - after making change in existing plugin. Each hook is executed with the following table as an argument: - (`string`) - absolute path to plugin's directory (might not yet exist on disk). - (`string`) - resolved from spec. - (`string`) - resolved from spec. Default: `nil` for no hooks. ------------------------------------------------------------------------------ *MiniDeps-commands* Note: Most commands have a Lua function alternative which they rely on. Like |:DepsAdd| uses |MiniDeps.add()|, etc. # :DepsAdd ~ *:DepsAdd* with `user/repo` argument makes plugin https://github.com/user/repo available in the current session (also creates it, if it is not present). `:DepsAdd name` adds already installed plugin `name` to current session. Accepts only single string compatible with |MiniDeps-plugin-specification|. To add plugin in every session, put |MiniDeps.add()| in |init.lua|. # :DepsUpdate ~ *:DepsUpdate* synchronizes plugins with their session specifications and updates them with new changes from sources. It shows confirmation buffer in a separate |tabpage| with information about an upcoming update to review and (selectively) apply. See |MiniDeps.update()| for more info. `:DepsUpdate name` updates plugin `name`. Any number of names is allowed. `:DepsUpdate!` and `:DepsUpdate! name` update without confirmation. You can see what was done in the log file afterwards (|:DepsShowLog|). # :DepsUpdateOffline ~ *:DepsUpdateOffline* is same as |:DepsUpdate| but doesn't download new updates from sources. Useful to only synchronize plugin specification in code and on disk without unnecessary downloads. # :DepsShowLog ~ *:DepsShowLog* opens log file to review. # :DepsClean ~ *:DepsClean* deletes plugins from disk not added to current session. It shows confirmation buffer in a separate |tabpage| with information about an upcoming deletes to review and (selectively) apply. See |MiniDeps.clean()| for more info. `:DepsClean!` deletes plugins without confirmation. # :DepsSnapSave ~ *:DepsSnapSave* creates snapshot file in default location (see |MiniDeps.config|). `:DepsSnapSave path` creates snapshot file at `path`. # :DepsSnapLoad ~ *:DepsSnapLoad* loads snapshot file from default location (see |MiniDeps.config|). `:DepsSnapLoad path` loads snapshot file at `path`. ------------------------------------------------------------------------------ *MiniDeps.setup()* `MiniDeps.setup`({config}) Module setup Calling this function creates user commands described in |MiniDeps-commands|. Parameters ~ {config} `(table|nil)` Module config table. See |MiniDeps.config|. Usage ~ >lua require('mini.deps').setup() -- use default config -- OR require('mini.deps').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniDeps.config* `MiniDeps.config` Defaults ~ >lua MiniDeps.config = { -- Parameters of CLI jobs job = { -- Number of parallel threads to use. Default: 80% of all available. n_threads = nil, -- Timeout (in ms) for each job before force quit timeout = 30000, }, -- Paths describing where to store data path = { -- Directory for built-in package. -- All plugins are actually stored in 'pack/deps' subdirectory. package = vim.fn.stdpath('data') .. '/site', -- Default file path for a snapshot snapshot = vim.fn.stdpath('config') .. '/mini-deps-snap', -- Log file log = vim.fn.stdpath('log') .. '/mini-deps.log' }, -- Whether to disable showing non-error feedback silent = false, } < # Job ~ `config.job` defines how CLI jobs are run. `job.n_threads` is a maximum number of parallel jobs used when needed. Default: 80% of all available. `job.timeout` is a duration (in ms) from job start until it is forced to stop. Default: 30000. # Paths ~ `config.path` defines main paths used in this module. `path.package` is a string with path inside which "pack/deps" package is stored (see |MiniDeps-overview|). Default: "site" subdirectory of "data" standard path (see |stdpath()|). `path.snapshot` is a string with default path for snapshot. See |:DepsSnapSave| and |:DepsSnapLoad|. Default: "mini-deps-snap" file in "config" standard path (see |stdpath()|). `path.log` is a string with path containing log of operations done by module. In particular, it contains all changes done after making an update. Default: "mini-deps.log" file in "log" standard path (see |stdpath()|). # Silent ~ `config.silent` is a boolean controlling whether to suppress non-error feedback. Default: `false`. ------------------------------------------------------------------------------ *MiniDeps.add()* `MiniDeps.add`({spec}, {opts}) Add plugin to current session - Process specification by expanding dependencies into single spec array. - Ensure plugin is present on disk along with its dependencies by installing (in parallel) absent ones: - Execute `opts.hooks.pre_install`. - Use `git clone` to clone plugin from its source URI into "pack/deps/opt". - Set state according to `opts.checkout`. - Execute `opts.hooks.post_install`. - Register spec(s) in current session. - Make sure plugin(s) can be used in current session (see |:packadd|). - If not during startup and is needed, source all "after/plugin/" scripts. Notes: - Presence of plugin is checked by its name which is the same as the name of its directory inside "pack/deps" package (see |MiniDeps-overview|). - To increase performance, this function only ensures presence on disk and nothing else. In particular, it doesn't ensure `opts.checkout` state. Use |MiniDeps.update()| or |:DepsUpdateOffline| explicitly. - Adding plugin several times updates its session specs. Parameters ~ {spec} `(table|string)` Plugin specification. See |MiniDeps-plugin-specification|. {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - whether to use `:packadd!` instead of plain |:packadd|. ------------------------------------------------------------------------------ *MiniDeps.update()* `MiniDeps.update`({names}, {opts}) Update plugins - Synchronize specs with state of plugins on disk (set `source`, etc.). - Infer data before downloading updates. - If not offline, download updates (in parallel). - Infer data after downloading updates. - If update is forced, apply all changes immediately while updating log file (at `config.path.log`; use |:DepsShowLog| to review). Otherwise show confirmation buffer with instructions on how to proceed. Parameters ~ {names} `(table|nil)` Array of plugin names to update. Default: all plugins from current session (see |MiniDeps.get_session()|). {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - whether to force update without confirmation. Default: `false`. - `(boolean)` - whether to skip downloading updates from sources. Default: `false`. ------------------------------------------------------------------------------ *MiniDeps.clean()* `MiniDeps.clean`({opts}) Clean plugins - Compute absent plugins: not registered in current session (see |MiniDeps.get_session()|) but present on disk in dedicated "pack/deps" package (inside `config.path.package`). - If cleaning is forced, delete all absent plugins from disk. Otherwise show confirmation buffer with instructions on how to proceed. Parameters ~ {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - whether to force delete without confirmation. Default: `false`. ------------------------------------------------------------------------------ *MiniDeps.snap_get()* `MiniDeps.snap_get`() Compute snapshot Return ~ `(table)` A snapshot table: plugin names as keys and state as values. All plugins in current session are processed. ------------------------------------------------------------------------------ *MiniDeps.snap_set()* `MiniDeps.snap_set`({snap}) Apply snapshot Notes: - Checking out states from snapshot does not update session plugin spec (`checkout` field in particular). Among others, it means that next call to |MiniDeps.update()| might override the result of this function. To make changes permanent, set `checkout` spec field to state from snapshot. Parameters ~ {snap} `(table)` A snapshot table: plugin names as keys and state as values. Only plugins in current session are processed. ------------------------------------------------------------------------------ *MiniDeps.snap_save()* `MiniDeps.snap_save`({path}) Save snapshot Parameters ~ {path} `(string|nil)` A valid path on disk where to write snapshot computed with |MiniDeps.snap_get()|. Default: `config.path.snapshot`. ------------------------------------------------------------------------------ *MiniDeps.snap_load()* `MiniDeps.snap_load`({path}) Load snapshot file Notes from |MiniDeps.snap_set()| also apply here. Parameters ~ {path} `(string|nil)` A valid path on disk from where to read snapshot. Default: `config.path.snapshot`. ------------------------------------------------------------------------------ *MiniDeps.get_session()* `MiniDeps.get_session`() Get session Plugin is registered in current session if it either: - Was added with |MiniDeps.add()| (preserving order of calls). - Is a "start" plugin and present in 'runtimpath'. Return ~ `(table)` Array with specifications of all plugins registered in current session. ------------------------------------------------------------------------------ *MiniDeps.now()* `MiniDeps.now`({f}) Execute function now Safely execute function immediately. Errors are shown with |vim.notify()| later, after all queued functions (including with |MiniDeps.later()|) are executed, thus not blocking execution of next code in file. Assumed to be used as a first step during two-stage config execution to load plugins immediately during startup. See |MiniDeps-overview|. Parameters ~ {f} `(function)` Callable to execute. ------------------------------------------------------------------------------ *MiniDeps.later()* `MiniDeps.later`({f}) Execute function later Queue function to be safely executed later without blocking execution of next code in file. All queued functions are guaranteed to be executed in order they were added. Errors are shown with |vim.notify()| after all queued functions are executed. Assumed to be used as a second step during two-stage config execution to load plugins "lazily" after startup. See |MiniDeps-overview|. Parameters ~ {f} `(function)` Callable to execute. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-diff.txt ================================================ *mini.diff* Work with diff hunks MIT License Copyright (c) 2024 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniDiff* Features: - Visualize difference between buffer text and its configurable reference interactively (updates as you type). This is done per line showing whether it is inside added, changed, or deleted part of difference (called hunk). Visualization can be with customizable colored signs or line numbers. - Special toggleable overlay view with more hunk details inside text area. See |MiniDiff.toggle_overlay()|. - Completely configurable per buffer source(s) of reference text used to keep it up to date and define interactions with it. Can be array of sources which are attempted to attach in order. See |MiniDiff-source-specification|. By default uses Git source. See |MiniDiff.gen_source.git()|. - Configurable mappings to manage diff hunks: - Apply and reset hunks inside region (selected visually or with a dot-repeatable operator). - "Hunk range under cursor" textobject to be used as operator target. - Navigate to first/previous/next/last hunk. See |MiniDiff.goto_hunk()|. What it doesn't do: - Provide functionality to work directly with Git outside of visualizing and staging (applying) hunks with (default) Git source. In particular, unstaging hunks is not supported. See |MiniDiff.gen_source.git()|. Sources with more details: - |MiniDiff-overview| - |MiniDiff-source-specification| - |MiniDiff-hunk-specification| - |MiniDiff-diff-summary| # Setup ~ This module needs a setup with `require('mini.diff').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniDiff` which you can use for scripting or manually (with `:lua MiniDiff.*`). See |MiniDiff.config| for `config` structure and default values. You can override runtime config settings locally to buffer inside `vim.b.minidiff_config` which should have same structure as `MiniDiff.config`. See |mini.nvim-buffer-local-config| for more details. # Comparisons ~ - [lewis6991/gitsigns.nvim](https://github.com/lewis6991/gitsigns.nvim): - Main inspiration for this module, so there are many similarities. - Can display only Git hunks, while this module has extensible design. - Provides more functionality to work with Git outside of hunks. This module does not (by design). # Highlight groups ~ - `MiniDiffSignAdd` - "add" hunk lines visualization. - `MiniDiffSignChange` - "change" hunk lines visualization. - `MiniDiffSignDelete` - "delete" hunk lines visualization. - `MiniDiffOverAdd` - added buffer text shown in overlay. - `MiniDiffOverChange` - changed reference text shown in overlay. - `MiniDiffOverChangeBuf` - changed buffer text shown in overlay. - `MiniDiffOverContext` - context of a change shown in reference overlay. - `MiniDiffOverContextBuf` - context of a change shown in buffer overlay. - `MiniDiffOverDelete` - deleted reference text shown in overlay. To change any highlight group, set it directly with |nvim_set_hl()|. # Disabling ~ To temporarily disable features without relying on |MiniDiff.disable()|, set `vim.g.minidiff_disable` (globally) or `vim.b.minidiff_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniDiff-overview* # Diffs and hunks ~ The "diff" (short for "difference") is a result of computing how two text strings differ from one another. This is done on per line basis, i.e. the goal is to compute sequences of lines common to both files, interspersed with groups of differing lines (called "hunks"). Although computing diff is a general concept (used on its own, in Git, etc.), this module computes difference between current text in a buffer and some reference text which is kept up to date specifically for that buffer. For example, default reference text is computed as file content in Git index. This can be customized in `config.source` (see |MiniDiff-source-specification|). # Hunk specification ~ *MiniDiff-hunk-specification* Hunk describes two sets (one from buffer text, one - from reference) of consecutive lines which are different. In this module hunk is stored as a table with the following fields: - `(number)` - start of hunk buffer lines. First line is 1. Can be 0 if first reference lines are deleted. - `(number)` - number of consecutive buffer lines. Can be 0 in case reference lines are deleted. - `(number)` - start of hunk reference lines. First line is 1. Can be 0 if lines are added before first reference line. - `(number)` - number of consecutive reference lines. Can be 0 in case buffer lines are added. - `(string)` - hunk type. Can be one of: - "add" - lines are present in buffer but absent in reference. - "change" - lines are present in both buffer and reference. - "delete" - lines are absent in buffer but present in reference. # Life cycle ~ - When entering proper (not already enabled, valid, showing text) buffer, it is attempted to be enabled for diff processing. - During enabling, attempt attaching the source. This should set up how reference text is kept up to date. - On every text change, diff computation is scheduled in debounced fashion after customizable delay (200 ms by default). - After the diff is computed, do the following: - Update visualization based on configurable style: either by placing colored text in sign column or coloring line numbers. Colors for both styles are defined per hunk type in corresponding `MiniDiffSign*` highlight group (see |mini.diff|) and sign text for "sign" style can be configured in `view.signs` of |MiniDiff.config|. - Update overlay view (if it is enabled). - Update `vim.b.minidiff_summary` and `vim.b.minidiff_summary_string` buffer-local variables. These can be used, for example, in statusline. - *MiniDiff-update-event* Trigger `MiniDiffUpdated` `User` event. See |MiniDiff-diff-summary| for example of how to use it. Notes: - Use |:edit| to reset (disable and re-enable) current buffer. - To work with BOM bytes, set 'bomb' and have `ucs-bom` in 'fileencodings'. # Overlay ~ Along with basic visualization, there is a special view called "overlay". Although it is meant for temporary overview of diff details and can be manually toggled via |MiniDiff.toggle_overlay()|, text can be changed with overlay reacting accordingly. It shows more diff details inside text area: - Added buffer lines are highlighted with `MiniDiffOverAdd` highlight group. - Deleted reference lines are shown as virtual lines and highlighted with `MiniDiffOverDelete` highlight group. - "Change" hunks with equal number of buffer/reference lines show "word diff". This is usually the case when `options.linematch` is enabled (as by default). Reference line is shown next to its buffer counterpart. Changed parts are highlighted with `MiniDiffOverChange` and `MiniDiffOverChangeBuf` in reference and buffer lines. The rest of lines have `MiniDiffOverContext` and `MiniDiffOverContextBuf` highlighting. Change with unequal number of buffer/reference lines is shown with reference part as virtual lines highlighted with `MiniDiffOverChange` group. Corresponding buffer lines are treated as context for the change and are highlighted with `MiniDiffOverContextBuf` group. Notes: - Word diff has non-zero context width. This means if changed characters are close enough, whole range between them is also colored. This usually reduces visual noise. - Virtual lines above line 1 (like deleted or changed lines) need manual scroll to become visible (with |CTRL-Y|). # Mappings ~ This module provides mappings for common actions with diffs, like: - Apply and reset hunks. - "Hunk range under cursor" textobject. - Go to first/previous/next/last hunk range. Examples: - `vip` followed by `gh` / `gH` applies/resets hunks inside current paragraph. Same can be achieved in operator form `ghip` / `gHip`, which has the advantage of being dot-repeatable (see |single-repeat|). - `gh_` / `gH_` applies/resets current line (even if it is not a full hunk). - `ghgh` / `gHgh` applies/resets hunk range under cursor. - `dgh` deletes hunk range under cursor. - `[H` / `[h` / `]h` / `]H` navigate cursor to the first / previous / next / last hunk range of the current buffer. Mappings for some functionality are assumed to be done manually. See |MiniDiff.operator()|. # Buffer-local variables ~ *MiniDiff-diff-summary* Each enabled buffer has the following buffer-local variables which can be used in custom statusline to show an overview of hunks in current buffer: - `vim.b.minidiff_summary` is a table with the following fields: - `source_name` - name of the active source. This is the only present field if buffer's reference text is not (yet) set. - `n_ranges` - number of hunk ranges (sequences of contiguous hunks). - `add` - number of added lines. - `change` - number of changed lines. - `delete` - number of deleted lines. - `vim.b.minidiff_summary_string` is a string representation of summary with a fixed format. Empty string if there is no reference text (yet). It is expected to be used as is. To achieve different formatting, use `vim.b.minidiff_summary` to construct one. The best way to do this is by overriding `vim.b.minidiff_summary_string` inside |MiniDiff-update-event|: >lua local format_summary = function(data) local summary = vim.b[data.buf].minidiff_summary local t = {} if summary.add > 0 then table.insert(t, '+' .. summary.add) end if summary.change > 0 then table.insert(t, '~' .. summary.change) end if summary.delete > 0 then table.insert(t, '-' .. summary.delete) end vim.b[data.buf].minidiff_summary_string = table.concat(t, ' ') end local au_opts = { pattern = 'MiniDiffUpdated', callback = format_summary } vim.api.nvim_create_autocmd('User', au_opts) < ------------------------------------------------------------------------------ *MiniDiff.setup()* `MiniDiff.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniDiff.config|. Usage ~ >lua require('mini.diff').setup() -- use default config -- OR require('mini.diff').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniDiff.config* `MiniDiff.config` Defaults ~ >lua MiniDiff.config = { -- Options for how hunks are visualized view = { -- Visualization style. Possible values are 'sign' and 'number'. -- Default: 'number' if line numbers are enabled, 'sign' otherwise. style = vim.go.number and 'number' or 'sign', -- Signs used for hunks with 'sign' view signs = { add = '▒', change = '▒', delete = '▒' }, -- Priority of used visualization extmarks priority = 199, }, -- Source(s) for how reference text is computed/updated/etc -- Uses content from Git index by default source = nil, -- Delays (in ms) defining asynchronous processes delay = { -- How much to wait before update following every text change text_change = 200, }, -- Module mappings. Use `''` (empty string) to disable one. mappings = { -- Apply hunks inside a visual/operator region apply = 'gh', -- Reset hunks inside a visual/operator region reset = 'gH', -- Hunk range textobject to be used inside operator -- Works also in Visual mode if mapping differs from apply and reset textobject = 'gh', -- Go to hunk range in corresponding direction goto_first = '[H', goto_prev = '[h', goto_next = ']h', goto_last = ']H', }, -- Various options options = { -- Diff algorithm. See `:h vim.diff()`. algorithm = 'histogram', -- Whether to use "indent heuristic". See `:h vim.diff()`. indent_heuristic = true, -- The amount of second-stage diff to align lines linematch = 60, -- Whether to wrap around edges during hunk navigation wrap_goto = false, }, } < # View ~ `config.view` contains settings for how diff hunks are visualized. Example of using custom signs: >lua require('mini.diff').setup({ view = { style = 'sign', signs = { add = '+', change = '~', delete = '-' }, }, }) < `view.style` is a string defining visualization style. Can be one of "sign" (as a colored sign in a |sign-column|) or "number" (colored line number). Default: "number" if |'number'| option is enabled, "sign" otherwise. Note: with "sign" style it is better to have |'signcolumn'| always shown. `view.signs` is a table with one or two character strings used as signs for corresponding ("add", "change", "delete") hunks. Default: all hunks use "▒" character resulting in a contiguous colored lines. `view.priority` is a number with priority used for visualization and overlay |extmarks|. Default: 199 which is one less than `user` in |vim.hl.priorities| (on Neovim<0.11 see |vim.hl.priorities|) to have higher priority than automated extmarks but not as in user enabled ones. # Source ~ *MiniDiff-source-specification* `config.source` is a table with single source or array of them. Single source defines how reference text is managed in a particular buffer. Sources in array are attempted to attach in order; call |MiniDiff.disable()| if none attaches. A single source table can have the following fields: - `(function)` - callable which defines how and when reference text is updated inside a particular buffer. It is used inside |MiniDiff.enable()| with a buffer identifier as a single argument. Should execute logic which results into calling |MiniDiff.set_ref_text()| when reference text for buffer needs to be updated. Like inside callback for an |autocommand| or file watcher (see |watch-file|). For example, default Git source watches when ".git/index" file is changed and computes reference text as the one from Git index for current file. Can return `false` to indicate that attach has failed. If attach fail can not be inferred immediately (for example, due to asynchronous execution), should explicitly call |MiniDiff.fail_attach()| with appropriate arguments. This is important to properly process array of sources. No default value, should be always supplied. - `(string|nil)` - source name. String `"unknown"` is used if not supplied. - `(function|nil)` - callable with cleanup action to be done when buffer is disabled. It is called inside |MiniDiff.disable()| with a buffer identifier as a single argument. If not supplied, nothing is done during detaching. - `(function|nil)` - callable which defines how hunks are applied. It is called with buffer identifier as first argument and array of hunks (see |MiniDiff-hunk-specification|) as second. It should eventually update reference text: either by explicitly calling |MiniDiff.set_ref_text()| or performing action triggering its call. For example, default Git source computes patch based on the hunks and applies it inside file's git repo. If not supplied, applying hunks throws an error. Default: a single |MiniDiff.gen_source.git()|. # Delay ~ `config.delay` contains settings for delays in asynchronous processes. `delay.text_change` is a number (in ms) defining how long to wait after latest text change (in debounced fashion) before updating diff and visualization. Default: 200. # Mappings ~ `config.mappings` contains keys which are mapped during |MiniDiff.setup()|. `mappings.apply` keys can be used to apply hunks inside visual/operator region. What exactly "apply hunks" means depends on the source and its `apply_hunks()`. For example, in default Git source it means stage hunks. `mappings.reset` keys can be used to reset hunks inside visual/operator region. Reset means replacing buffer text in region with corresponding reference text. `mappings.textobject` keys define "hunk range under cursor" textobject which can be used in Operator-pending mode as target for operator (like |d|, |y|, apply/reset hunks, etc.). It is also set up in Visual mode if keys do not conflict with `mappings.apply` and `mappings.reset`. "Hunk range" is used in a sense that contiguous (back-to-back) hunks are considered as parts of a same hunk range. `mappings.goto_first` / `mappings.goto_prev` / `mappings.goto_next` / `mappings.goto_last` keys can be used to navigate to first / previous / next / last hunk range in the current buffer. # Options ~ `config.options` contains various customization options. `options.algorithm` is a string defining which diff algorithm to use. Default: "histogram". See |vim.diff()| for possible values. `options.indent_heuristic` is a boolean defining whether to use indent heuristic for a (possibly) more naturally aligned hunks. Default: `true`. `options.linematch` is a number defining hunk size for which a second stage diff is executed for a better aligned and more granular hunks. Default: 60. See |vim.diff()| and 'diffopt' for more details. `options.wrap_goto` is a boolean indicating whether to wrap around edges during hunk navigation (with |MiniDiff.goto_hunk()| or `goto_*` mappings). Like if cursor is after the last hunk, going "next" will put cursor on the first hunk. Default: `false`. ------------------------------------------------------------------------------ *MiniDiff.enable()* `MiniDiff.enable`({buf_id}) Enable diff processing in buffer Parameters ~ {buf_id} `(number)` Target buffer identifier. Default: 0 for current buffer. ------------------------------------------------------------------------------ *MiniDiff.disable()* `MiniDiff.disable`({buf_id}) Disable diff processing in buffer Parameters ~ {buf_id} `(number)` Target buffer identifier. Default: 0 for current buffer. ------------------------------------------------------------------------------ *MiniDiff.toggle()* `MiniDiff.toggle`({buf_id}) Toggle diff processing in buffer Enable if disabled, disable if enabled. Parameters ~ {buf_id} `(number)` Target buffer identifier. Default: 0 for current buffer. ------------------------------------------------------------------------------ *MiniDiff.toggle_overlay()* `MiniDiff.toggle_overlay`({buf_id}) Toggle overlay view in buffer Parameters ~ {buf_id} `(number)` Target buffer identifier. Default: 0 for current buffer. ------------------------------------------------------------------------------ *MiniDiff.export()* `MiniDiff.export`({format}, {opts}) Export hunks Get and convert hunks from current/all buffers. Example of using it: >lua -- Set quickfix list from all available hunks vim.fn.setqflist(MiniDiff.export('qf')) < Parameters ~ {format} `(string)` Output format. Currently only `'qf'` value is supported. {opts} `(table|nil)` Options. Possible fields: - `(string)` - scope defining from which buffers to use hunks. One of "all" (all enabled buffers) or "current". Return ~ `(table)` Result of export. Depends on the `format`: - If "qf", an array compatible with |setqflist()| and |setloclist()|. ------------------------------------------------------------------------------ *MiniDiff.get_buf_data()* `MiniDiff.get_buf_data`({buf_id}) Get buffer data Parameters ~ {buf_id} `(number)` Target buffer identifier. Default: 0 for current buffer. Return ~ `(table|nil)` Table with buffer diff data or `nil` if buffer is not enabled. Table has the following fields: - `(table)` - config used for this particular buffer. - `(table)` - array of hunks. See |MiniDiff-hunk-specification|. - `(boolean)` - whether an overlay view is shown. - `(string|nil)` - current value of reference text. Lines are separated with newline character (`'\n'`). Can be `nil` indicating that reference text was not yet set (for example, if source did not yet react). -

`(table)` - overall diff summary. See |MiniDiff-diff-summary|. ------------------------------------------------------------------------------ *MiniDiff.set_ref_text()* `MiniDiff.set_ref_text`({buf_id}, {text}) Set reference text for the buffer Note: this will call |MiniDiff.enable()| for target buffer if it is not already enabled. Parameters ~ {buf_id} `(number)` Target buffer identifier. Default: 0 for current buffer. {text} `(string|table)` New reference text. Either a string with `\n` used to separate lines or array of lines. Use empty table to unset current reference text (results into no hunks shown). Default: `{}`. Note: newline character is appended at the end (if it is not there already) for better diffs. ------------------------------------------------------------------------------ *MiniDiff.gen_source* `MiniDiff.gen_source` Generate builtin sources This is a table with function elements. Call to actually get source. Examples: >lua local diff = require('mini.diff') -- Single `save` source diff.setup({ source = diff.gen_source.save() }) -- Multiple sources (attempted to attach in order) diff.setup({ source = { diff.gen_source.git(), diff.gen_source.save() } }) < ------------------------------------------------------------------------------ *MiniDiff.gen_source.git()* `MiniDiff.gen_source.git`() Git source Default source. Uses file text from Git index as reference. This results in: - "Add" hunks represent text present in current buffer, but not in index. - "Change" hunks represent modified text already present in index. - "Delete" hunks represent text deleted from index. Applying hunks means staging, a.k.a adding to index. Notes: - Requires Git version at least 2.38.0. - There is no capability for unstaging hunks. Use full Git client for that. Return ~ `(table)` Source. See |MiniDiff-source-specification|. ------------------------------------------------------------------------------ *MiniDiff.gen_source.none()* `MiniDiff.gen_source.none`() "Do nothing" source Allows buffers to be enabled while not setting any reference text. Use this if the goal is to rely on manual |MiniDiff.set_ref_text()| calls. Return ~ `(table)` Source. See |MiniDiff-source-specification|. ------------------------------------------------------------------------------ *MiniDiff.gen_source.save()* `MiniDiff.gen_source.save`() Latest save source Uses text at latest save as the reference. This results into diff showing difference after the latest save. Return ~ `(table)` Source. See |MiniDiff-source-specification|. ------------------------------------------------------------------------------ *MiniDiff.do_hunks()* `MiniDiff.do_hunks`({buf_id}, {action}, {opts}) Perform action on hunks in region Compute hunks inside a target region (even for hunks only partially inside it) and perform apply/reset/yank operation on them. The "yank" action yanks all reference lines of target hunks into a specified register (should be one of |registers|). Notes: - Whether hunk is inside a region is computed based on position of its buffer lines. - If "change" or "delete" is only partially inside a target region, all reference lines are used in computed "intersection" hunk. Used directly in `config.mappings.apply` and `config.mappings.reset`. Usually there is no need to use this function manually. See |MiniDiff.operator()| for how to set up a mapping for "yank". Parameters ~ {buf_id} `(number)` Target buffer identifier. Default: 0 for current buffer. {action} `(string)` One of "apply", "reset", "yank". {opts} `(table|nil)` Options. Possible fields: - `(number)` - start line of the region. Default: 1. - `(number)` - start line of the region. Default: last buffer line. - `(string)` - register to yank reference lines into. Default: |v:register|. ------------------------------------------------------------------------------ *MiniDiff.goto_hunk()* `MiniDiff.goto_hunk`({direction}, {opts}) Go to hunk range in current buffer Parameters ~ {direction} `(string)` One of "first", "prev", "next", "last". {opts} `(table|nil)` Options. A table with fields: - `(number)` - Number of times to advance. Default: |v:count1|. - `(number)` - Line number to start from for directions "prev" and "next". Default: cursor line. - `(boolean)` - Whether to wrap around edges. Default: `options.wrap` value of the config. ------------------------------------------------------------------------------ *MiniDiff.operator()* `MiniDiff.operator`({mode}) Perform action over region Perform action over region defined by marks. Used in mappings. Example of a mapping to yank reference lines of hunk range under cursor (assuming default 'config.mappings.textobject'): >lua local rhs = function() return MiniDiff.operator('yank') .. 'gh' end vim.keymap.set('n', 'ghy', rhs, { expr = true, remap = true }) < Parameters ~ {mode} `(string)` One of "apply", "reset", "yank", or the ones used in |g@|. ------------------------------------------------------------------------------ *MiniDiff.textobject()* `MiniDiff.textobject`() Select hunk range textobject Selects all contiguous lines adjacent to cursor line which are in any (not necessarily same) hunk (if cursor line itself is in hunk). Used in default mappings. ------------------------------------------------------------------------------ *MiniDiff.fail_attach()* `MiniDiff.fail_attach`({buf_id}) Indicate source attach fail Try to attach next source; if there is none - call |MiniDiff.disable()|. Parameters ~ {buf_id} `(integer)` Buffer identifier for which attach has failed. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-doc.txt ================================================ *mini.doc* Generate Neovim help files MIT License Copyright (c) 2022 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniDoc* Key design ideas: - Keep documentation next to code by writing EmmyLua-like annotation comments. They will be parsed as is, so formatting should follow built-in guide in |help-writing|. However, custom hooks are allowed at many generation stages for more granular management of output help file. - Generation is done by processing a set of ordered files line by line. Each line can either be considered as a part of documentation block (if it matches certain configurable pattern) or not (considered to be an "afterline" of documentation block). See |MiniDoc.generate()| for more details. - Processing is done by using nested data structures (section, block, file, doc) describing certain parts of help file. See |MiniDoc-data-structures| for more details. - Project specific script can be written as plain Lua file with configuratble path. See |MiniDoc.generate()| for more details. What it doesn't do: - It doesn't support markdown or other markup language inside annotations. - It doesn't use treesitter in favor of Lua string manipulation for basic tasks (parsing annotations, formatting, auto-generating tags, etc.). This is done to manage complexity and be dependency free. # Setup ~ This module needs a setup with `require('mini.doc').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniDoc` which you can use for scripting or manually (with `:lua MiniDoc.*`). See |MiniDoc.config| for available config settings. You can override runtime config settings locally to buffer inside `vim.b.minidoc_config` which should have same structure as `MiniDoc.config`. See |mini.nvim-buffer-local-config| for more details. To stop module from showing non-error feedback, set `config.silent = true`. # Tips ~ - Some settings tips that might make writing annotation comments easier: - Set up appropriate 'comments' for `lua` file type to respect EmmyLua-like's `---` comment leader. Value `:---,:--` seems to work. - Set up appropriate 'formatoptions' (see also |fo-table|). Consider adding `j`, `n`, `q`, and `r` flags. - Set up appropriate 'formatlistpat' to help auto-formatting lists (if `n` flag is added to 'formatoptions'). One suggestion (not entirely ideal) is a value `^\s*[0-9\-\+\*]\+[\.\)]*\s\+`. This reads as 'at least one special character (digit, `-`, `+`, `*`) possibly followed by some punctuation (`.` or `)`) followed by at least one space is a start of list item'. - Probably one of the most reliable resources for what is considered to be best practice when using this module is this whole plugin. Look at source code for the reference. # Comparisons ~ - [tjdevries/tree-sitter-lua](https://github.com/tjdevries/tree-sitter-lua): - Its key design is to use treesitter grammar to parse both Lua code and annotation comments. This makes it not easy to install, customize, and support. - It takes more care about automating output formatting (like auto indentation and line width fit). This plugin leans more to manual formatting with option to supply customized post-processing hooks. ------------------------------------------------------------------------------ *MiniDoc-data-structures* Data structures Data structures are basically arrays of other structures accompanied with some fields (keys with data values) and methods (keys with function values): - `Section structure` is an array of string lines describing one aspect (determined by section id like '@param', '@return', '@text') of an annotation subject. All lines will be used directly in help file. - `Block structure` is an array of sections describing one annotation subject like function, table, concept. - `File structure` is an array of blocks describing certain file on disk. Basically, file is split into consecutive blocks: annotation lines go inside block, non-annotation - inside `block_afterlines` element of info. - `Doc structure` is an array of files describing a final help file. Each string line from section (when traversed in depth-first fashion) goes directly into output file. All structures have these keys: - Fields: - `info` - contains additional information about current structure. For more details see next section. - `parent` - table of parent structure (if exists). - `parent_index` - index of this structure in its parent's array. Useful for adding to parent another structure near current one. - `type` - string with structure type (section, block, file, doc). - Methods (use them as `x:method(args)`): - `insert(self, [index,] child)` - insert `child` to `self` at position `index` (optional; if not supplied, child will be appended to end). Basically, a `table.insert()`, but adds `parent` and `parent_index` fields to `child` while properly updating `self`. - `remove(self [,index])` - remove from `self` element at position `index`. Basically, a `table.remove()`, but properly updates `self`. - `has_descendant(self, predicate)` - whether there is a descendant (structure or string) for which `predicate` returns `true`. In case of success also returns the first such descendant as second value. - `has_lines(self)` - whether structure has any lines (even empty ones) to be put in output file. For section structures this is equivalent to `#self`, but more useful for higher order structures. - `clear_lines(self)` - remove all lines from structure. As a result, this structure won't contribute to output help file. Description of `info` fields per structure type: - `Section`: - `id` - captured section identifier. Can be empty string meaning no identifier is captured. - `line_begin` - line number inside file at which section begins (-1 if not generated from file). - `line_end` - line number inside file at which section ends (-1 if not generated from file). - `Block`: - `afterlines` - array of strings which were parsed from file after this annotation block (up until the next block or end of file). Useful for making automated decisions about what is being documented. - `line_begin` - line number inside file at which block begins (-1 if not generated from file). - `line_end` - line number inside file at which block ends (-1 if not generated from file). - `File`: - `path` - absolute path to a file (`''` if not generated from file). - `Doc`: - `input` - array of input file paths (as in |MiniDoc.generate()|). - `output` - output path (as in |MiniDoc.generate()|). - `config` - configuration used (as in |MiniDoc.generate()|). ------------------------------------------------------------------------------ *MiniDoc.setup()* `MiniDoc.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniDoc.config|. Usage ~ >lua require('mini.doc').setup() -- use default config -- OR require('mini.doc').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniDoc.config* `MiniDoc.config` Defaults ~ >lua MiniDoc.config = { -- Function which extracts part of line used to denote annotation. -- For more information see 'Notes' in |MiniDoc.config|. annotation_extractor = function(l) return string.find(l, '^%-%-%-(%S*) ?') end, -- Identifier of block annotation lines until first captured identifier default_section_id = '@text', -- Hooks to be applied at certain stage of document life cycle. Should -- modify its input in place (and not return new one). hooks = { -- Applied to block before anything else block_pre = --, -- Applied to section before anything else section_pre = --, -- Applied if section has specified captured id sections = { ['@alias'] = --, ['@class'] = --, ['@diagnostic'] = --, -- For most typical usage see |MiniDoc.afterlines_to_code| ['@eval'] = --, ['@field'] = --, ['@overload'] = --, ['@param'] = --, ['@private'] = --, ['@return'] = --, ['@seealso'] = --, ['@signature'] = --, ['@tag'] = --, ['@text'] = --, ['@toc'] = --, ['@toc_entry'] = --, ['@type'] = --, ['@usage'] = --, }, -- Applied to section after all previous steps section_post = --, -- Applied to block after all previous steps block_post = --, -- Applied to file after all previous steps file = --, -- Applied to doc after all previous steps doc = --, -- Applied before output file is written. Takes lines array as argument. write_pre = --, -- Applied after output help file is written. Takes doc as argument. write_post = --, }, -- Path (relative to current directory) to script which handles project -- specific help file generation (like custom input files, hooks, etc.). script_path = 'scripts/minidoc.lua', -- Whether to disable showing non-error feedback silent = false, } < # Notes ~ - `annotation_extractor` takes single string line as input. Output describes what makes an input to be an annotation (if anything). It should be similar to `string.find` with one capture group: start and end of annotation indicator (whole part will be removed from help line) with third value being string of section id (if input describes first line of section; `nil` or empty string otherwise). Output should be `nil` if line is not part of annotation. Default value means that annotation line should: - Start with `---` at first column. - Any non-whitespace after `---` will be treated as new section id. - Single whitespace at the start of main text will be ignored. - Hooks are expected to be functions. Their default values might do many things which might change over time, so for more information please look at source code. Some more information can be found in |MiniDoc.default_hooks|. ------------------------------------------------------------------------------ *MiniDoc.current* `MiniDoc.current` Table with information about current state of auto-generation It is reset at the beginning and end of `MiniDoc.generate()`. At least these keys are supported: - {aliases} - table with keys being alias name and values - alias description and single string (using `\n` to separate lines). - {eval_section} - input section of `@eval` section hook. Can be used for information about current block, etc. - {toc} - array with table of contents entries. Each entry is a whole `@toc_entry` section. ------------------------------------------------------------------------------ *MiniDoc.default_hooks* `MiniDoc.default_hooks` Default hooks This is default value of `MiniDoc.config.hooks`. Use it if only a little tweak is needed. Some more insight about their behavior: - Default inference of documented object metadata (tag and object signature at the moment) is done in `block_pre`. Inference is based on string pattern matching, so can lead to false results, although works in most cases. It intentionally works only if first line after block has no indentation and contains all necessary information to determine if inference should happen. - Hooks for sections describing some "variable-like" object ('@class', '@field', '@param') automatically enclose first word in '{}'. - Hooks for sections which supposed to have "type-like" data ('@field', '@param', '@return', '@type') automatically enclose *first found* "type-like" word and its neighbor characters in '`()`' (expect false positives). Algorithm is far from being 100% correct, but seems to work with present allowed type annotation. For allowed types see https://github.com/sumneko/lua-language-server/wiki/EmmyLua-Annotations#types-and-type or, better yet, look in source code of this module. - Automated creation of table of contents (TOC) is done in the following way: - Put section with `@toc_entry` id in the annotation block. Section's lines will be registered as TOC entry. - Put `@toc` section where you want to insert rendered table of contents. TOC entries will be inserted on the left, references for their respective tag section (only first, if present) on the right. Render is done in default `doc` hook (because it should be done after processing all files). - The `write_post` hook executes some actions convenient for iterative annotations writing: - Generate `:helptags` for directory containing output file. - Silently reload buffer containing output file (if such exists). - Display notification message about result. ------------------------------------------------------------------------------ *MiniDoc.generate()* `MiniDoc.generate`({input}, {output}, {config}) Generate help file # Algorithm ~ - Main parameters for help generation are an array of input file paths and path to output help file. - Parse all inputs: - For each file, lines are processed top to bottom in order to create an array of documentation blocks. Each line is tested whether it is an annotation by applying `MiniDoc.config.annotation_extractor`: if anything is extracted, it is considered to be an annotation. Annotation line goes to "current block" after removing extracted annotation indicator, otherwise - to afterlines of "current block". - Each block's annotation lines are processed top to bottom. If line had captured section id, it is a first line of "current section" (first block lines are allowed to not specify section id; by default it is `@text`). All subsequent lines without captured section id go into "current section". - Apply structure hooks (they should modify its input in place, which is possible due to 'table nature' of all inputs): - Each block is processed by `MiniDoc.config.hooks.block_pre`. This is a designated step for auto-generation of sections from described annotation subject (like sections with id `@tag`, `@type`). - Each section is processed by `MiniDoc.config.hooks.section_pre`. - Each section is processed by corresponding `MiniDoc.config.hooks.sections` function (table key equals to section id). This is a step where most of formatting should happen (like wrap first word of `@param` section with `{` and `}`, append empty line to section, etc.). - Each section is processed by `MiniDoc.config.hooks.section_post`. - Each block is processed by `MiniDoc.config.hooks.block_post`. This is a step for processing block after formatting is done (like add first line with `----` delimiter). - Each file is processed by `MiniDoc.config.hooks.file`. This is a step for adding any file-related data (like add first line with `====` delimiter). - Doc is processed by `MiniDoc.config.hooks.doc`. This is a step for adding any helpfile-related data (maybe like table of contents). - Collect all strings from sections in depth-first fashion (equivalent to nested "for all files -> for all blocks -> for all sections -> for all strings -> add string to output"). Strings can have `\n` character indicating start of new line. - Modify collected strings with `MiniDoc.config.write_pre`. Takes strings from previous step as input and should return array of strings. - Write modified strings to output file. - Execute `MiniDoc.config.write_post` hook. This is useful for showing some feedback and making actions involving newly updated help file (like generate tags, etc.). # Project specific script ~ If all arguments have default `nil` values, first there is an attempt to source project specific script. This is basically a `luafile ` with current Lua runtime while caching and restoring current `MiniDoc.config`. Its successful execution stops any further generation actions while error means proceeding generation as if no script was found. Typical script content might include definition of custom hooks, input and output files with eventual call to `require('mini.doc').generate()` (with or without arguments). Parameters ~ {input} `(table|nil)` Array of file paths which will be processed in supplied order. Default: all '.lua' files from current directory following by all such files in these subdirectories: 'lua/', 'after/', 'colors/'. Note: any 'init.lua' file is placed before other files from the same directory. {output} `(string|nil)` Path for output help file. Default: `doc/.txt` (designed to be used for generating help file for plugin). {config} `(table|nil)` Configuration overriding parts of |MiniDoc.config|. Return ~ `(table)` Document structure which was generated and used for output help file. In case `MiniDoc.config.script_path` was successfully used, this is a return from the latest call of this function. ------------------------------------------------------------------------------ *MiniDoc.afterlines_to_code()* `MiniDoc.afterlines_to_code`({struct}) Convert afterlines to code This function is designed to be used together with `@eval` section to automate documentation of certain values (notably default values of a table). It processes afterlines based on certain directives and makes output look like a Lua code block. Most common usage is by adding the following section in your annotation: > ---@eval return MiniDoc.afterlines_to_code(MiniDoc.current.eval_section) < # Directives ~ Directives are special comments that are processed using Lua string pattern capabilities (so beware of false positives). Each directive should be put on its separate line. Supported directives: - `--minidoc_afterlines_end` denotes a line at afterlines end. Only all lines before it will be considered as afterlines. Useful if there is extra code in afterlines which shouldn't be used. - `--minidoc_replace_start ` and `--minidoc_replace_end` denote lines between them which should be replaced with ``. Useful for manually changing what should be placed in output like in case of replacing function body with something else. Here is an example. Suppose having these afterlines: >lua --minidoc_replace_start { M.config = { --minidoc_replace_end param_one = 1, --minidoc_replace_start param_fun = -- param_fun = function(x) return x + 1 end --minidoc_replace_end } --minidoc_afterlines_end return M < After adding `@eval` section those will be formatted as: > { param_one = 1, param_fun = -- } < Parameters ~ {struct} `(table)` Block or section structure which after lines will be converted to code. Return ~ `(string|nil)` Single string (using `\n` to separate lines) describing afterlines as Lua code block in help file. If `nil`, input is not valid. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-extra.txt ================================================ *mini.extra* Extra 'mini.nvim' functionality MIT License Copyright (c) 2023 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniExtra* Extra useful functionality which is not essential enough for other 'mini.nvim' modules to include directly. Features: - Various pickers for |mini.pick|: - Built-in diagnostic (|MiniExtra.pickers.diagnostic()|). - File explorer (|MiniExtra.pickers.explorer()|). - Git branches/commits/files/hunks (|MiniExtra.pickers.git_hunks()|, etc.). - Command/search/input history (|MiniExtra.pickers.history()|). - LSP references/symbols/etc. (|MiniExtra.pickers.lsp()|). - Tree-sitter nodes (|MiniExtra.pickers.treesitter()|). - And much more. See |MiniExtra.pickers| for more. - Various textobject specifications for |mini.ai|. See |MiniExtra.gen_ai_spec|. - Various highlighters for |mini.hipatterns|. See |MiniExtra.gen_highlighter|. Notes: - This module requires only those 'mini.nvim' modules which are needed for a particular functionality: 'mini.pick' for pickers, etc. # Setup ~ This module needs a setup with `require('mini.extra').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniExtra` which you can use for scripting or manually (with `:lua MiniExtra.*`). See |MiniExtra.config| for `config` structure and default values. This module doesn't have runtime options, so using `vim.b.miniextra_config` will have no effect here. # Comparisons ~ - [nvim-telescope/telescope.nvim](https://github.com/nvim-telescope/telescope.nvim): - With |MiniExtra.pickers|, 'mini.pick' is reasonably on par when it comes to built-in pickers. - [ibhagwan/fzf-lua](https://github.com/ibhagwan/fzf-lua): - Same as 'nvim-telescope/telescope.nvim'. ------------------------------------------------------------------------------ *MiniExtra.setup()* `MiniExtra.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniExtra.config|. Usage ~ >lua require('mini.extra').setup() -- use default config -- OR require('mini.extra').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniExtra.config* `MiniExtra.config` Defaults ~ >lua MiniExtra.config = {} < ------------------------------------------------------------------------------ *MiniExtra.gen_ai_spec* `MiniExtra.gen_ai_spec` |mini.ai| textobject specification generators This is a table with function elements. Call to actually get specification. Assumed to be used as part of |MiniAi.setup()|. Example: >lua local gen_ai_spec = require('mini.extra').gen_ai_spec require('mini.ai').setup({ custom_textobjects = { B = gen_ai_spec.buffer(), D = gen_ai_spec.diagnostic(), I = gen_ai_spec.indent(), L = gen_ai_spec.line(), N = gen_ai_spec.number(), }, }) < ------------------------------------------------------------------------------ *MiniExtra.gen_ai_spec.buffer()* `MiniExtra.gen_ai_spec.buffer`() Current buffer textobject Notes: - `a` textobject selects all lines in a buffer. - `i` textobject selects all lines except blank lines at start and end. Return ~ `(function)` Function implementing |MiniAi-textobject-specification|. ------------------------------------------------------------------------------ *MiniExtra.gen_ai_spec.diagnostic()* `MiniExtra.gen_ai_spec.diagnostic`({severity}) Current buffer diagnostic textobject Notes: - Both `a` and `i` textobjects return |vim.diagnostic.get()| output for the current buffer. It is modified to fit |MiniAi-textobject-specification|. Parameters ~ {severity} `(any)` Which severity to use. Forwarded to |vim.diagnostic.get()|. Default: `nil` to use all diagnostic entries. Return ~ `(function)` Function implementing |MiniAi-textobject-specification|. ------------------------------------------------------------------------------ *MiniExtra.gen_ai_spec.indent()* `MiniExtra.gen_ai_spec.indent`() Current buffer indent scopes textobject Indent scope is a set of consecutive lines with the following properties: - Lines above first and below last are non-blank. They are called borders. - There is at least one non-blank line in a set. - All non-blank lines between borders have strictly greater indent (perceived leading space respecting |'tabstop'|) than either of borders. Notes: - `a` textobject selects scope including borders. - `i` textobject selects the scope charwise. - Differences with |MiniIndentscope.textobject()|: - This textobject always treats blank lines on top and bottom of `i` textobject as part of it, while 'mini.indentscope' can configure that. - This textobject can select non-covering scopes, while 'mini.indentscope' can not (by design). - In this textobject scope computation is done only by "casting rays" from top to bottom and not in both ways as in 'mini.indentscope'. This works in most common scenarios and doesn't work only if indent of of the bottom border is expected to be larger than the top. Return ~ `(function)` Function implementing |MiniAi-textobject-specification|. It returns array of regions representing all indent scopes in the buffer ordered increasingly by the start line. ------------------------------------------------------------------------------ *MiniExtra.gen_ai_spec.line()* `MiniExtra.gen_ai_spec.line`() Current line textobject Notes: - `a` textobject selects whole line. - `i` textobject selects line after initial indent. Return ~ `(function)` Function implementing |MiniAi-textobject-specification|. ------------------------------------------------------------------------------ *MiniExtra.gen_ai_spec.number()* `MiniExtra.gen_ai_spec.number`() Number textobject Notes: - `a` textobject selects a whole number possibly preceded with "-" and possibly followed by decimal part (dot and digits). - `i` textobject selects consecutive digits. Return ~ `(function)` Function implementing |MiniAi-textobject-specification|. ------------------------------------------------------------------------------ *MiniExtra.gen_highlighter* `MiniExtra.gen_highlighter` |mini.hipatterns| highlighter generators This is a table with function elements. Call to actually get specification. Assumed to be used as part of |MiniHipatterns.setup()|. Example: >lua local hi_words = require('mini.extra').gen_highlighter.words require('mini.hipatterns').setup({ highlighters = { todo = hi_words({ 'TODO', 'Todo', 'todo' }, 'MiniHipatternsTodo'), }, }) < ------------------------------------------------------------------------------ *MiniExtra.gen_highlighter.words()* `MiniExtra.gen_highlighter.words`({words}, {group}, {extmark_opts}) Highlight words Notes: - Words should start and end with alphanumeric symbol (latin letter or digit). - Words will be highlighted only in full and not if part bigger word, i.e. there should not be alphanumeric symbol before and after it. Parameters ~ {words} `(table)` Array of words to highlight. Will be matched as is, not as Lua pattern. {group} `(string|function)` Proper `group` field for `highlighter`. See |MiniHipatterns.config|. {extmark_opts} `(any)` Proper `extmark_opts` field for `highlighter`. See |MiniHipatterns.config|. ------------------------------------------------------------------------------ *MiniExtra.pickers* `MiniExtra.pickers` |mini.pick| pickers A table with 'mini.pick' pickers (which is a hard dependency). Notes: - All have the same signature: - - optional table with options local to picker. - - optional table with options forwarded to |MiniPick.start()|. - All of them are automatically registered in |MiniPick.registry| inside both |MiniExtra.setup()| or |MiniPick.setup()| (only one is enough). - All use default versions of |MiniPick-source.preview|, |MiniPick-source.choose|, and |MiniPick-source.choose_marked| if not stated otherwise. Shown text and |MiniPick-source.show| are targeted to the picked items. Examples of usage: - As Lua code: `MiniExtra.pickers.buf_lines()`. - With |:Pick| command: `:Pick buf_lines scope='current'` Note: this requires calling |MiniExtra.setup()|. ------------------------------------------------------------------------------ *MiniExtra.pickers.buf_lines()* `MiniExtra.pickers.buf_lines`({local_opts}, {opts}) Buffer lines picker Pick from buffer lines. Notes: - Loads all target buffers which are currently unloaded. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string)` - one of "all" (normal listed buffers) or "current". Default: "all". - `(boolean)` - whether to preserve original order during query. Default: `false`. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.colorschemes()* `MiniExtra.pickers.colorschemes`({local_opts}, {opts}) Color scheme picker Pick and apply color scheme. Preview temporarily applies item's color scheme and shows how selected highlight groups look. Canceling reverts to color scheme before picker start: - With |MiniColors-colorscheme:apply()| if |mini.colors| was available. - With |:colorscheme| if |g:colors_name| was available. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(table)` - array of color scheme names to pick from. Default: all available color schemes. - `(table)` - array of highlight groups to show in preview window. Default: all defined highlight groups in alphabetical order. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.commands()* `MiniExtra.pickers.commands`({local_opts}, {opts}) Neovim commands picker Pick from Neovim built-in (|Ex-commands|) and |user-commands|. Notes: - Preview shows information about the command (if available). - Choosing either executes command (if reliably known that it doesn't need arguments) or populates Command line with the command. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Not used at the moment. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.diagnostic()* `MiniExtra.pickers.diagnostic`({local_opts}, {opts}) Built-in diagnostic picker Pick from |vim.diagnostic| using |vim.diagnostic.get()|. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(table)` - options for |vim.diagnostic.get()|. Can be used to limit severity or namespace. Default: `{}`. - `(string)` - one of "all" (available) or "current" (buffer). Default: "all". - `(string)` - sort priority. One of "severity", "path", "none". Default: "severity". {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.explorer()* `MiniExtra.pickers.explorer`({local_opts}, {opts}) File explorer picker Explore file system and open file. Notes: - Choosing a directory navigates inside it, changing picker's items and current working directory. - Query and preview work as usual (not only `move_next`/`move_prev` can be used). - Preview works for any item. Examples: - `MiniExtra.pickers.explorer()` - `:Pick explorer cwd='..'` - open explorer in parent directory. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string)` - initial directory to explore. Should be a valid directory path. Default: `nil` for |current-directory|. - `(function)` - callable predicate to filter items to show. Will be called for every item and should return `true` if it should be shown. Each item is a table with the following fields: - `(string)` - path type. One of "directory" or "file". - `(string)` - item path. - `(string)` - shown text (path's basename). - `(function)` - callable item sorter. Will be called with array of items (each element with structure as described above) and should return sorted array of items. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.git_branches()* `MiniExtra.pickers.git_branches`({local_opts}, {opts}) Git branches picker Pick from Git branches using `git branch`. Notes: - Requires executable `git`. - Requires target path to be part of git repository. - Present for exploration and navigation purposes. Doing any Git operations is suggested to be done in a dedicated Git client and is not planned. - On choose opens scratch buffer with branch's history. Examples: - `MiniExtra.pickers.git_branches({ scope = 'local' })` - local branches of the |current-directory| parent Git repository. - `:Pick git_branches path='%'` - all branches of the current file parent Git repository. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string|nil)` - target path for Git operation (if required). Also used to find Git repository inside which to construct items. Default: `nil` for root of Git repository containing |current-directory|. - `(string)` - branch scope to show. One of "all", "local", "remotes". Default: "all". {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.git_commits()* `MiniExtra.pickers.git_commits`({local_opts}, {opts}) Git commits picker Pick from Git commits using `git log`. Notes: - Requires executable `git`. - Requires target path to be part of git repository. - Present for exploration and navigation purposes. Doing any Git operations is suggested to be done in a dedicated Git client and is not planned. - On choose opens scratch buffer with commit's diff. Examples: - `MiniExtra.pickers.git_commits()` - all commits from parent Git repository of |current-directory|. - `MiniExtra.pickers.git_commits({ path = 'subdir' })` - commits affecting files from 'subdir' subdirectory. - `:Pick git_commits path='%'` commits affecting current file. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string|nil)` - target path for Git operation (if required). Also used to find Git repository inside which to construct items. Default: `nil` for root of Git repository containing |current-directory|. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.git_files()* `MiniExtra.pickers.git_files`({local_opts}, {opts}) Git files picker Pick from Git files using `git ls-files`. Notes: - Requires executable `git`. - Requires target path to be part of git repository. - Present for exploration and navigation purposes. Doing any Git operations is suggested to be done in a dedicated Git client and is not planned. Examples: - `MiniExtra.pickers.git_files({ scope = 'ignored' })` - ignored files from parent Git repository of |current-directory|. - `:Pick git_files path='subdir' scope='modified'` - files from 'subdir' subdirectory which are ignored by Git. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string|nil)` - target path for Git operation (if required). Also used to find Git repository inside which to construct items. Default: `nil` for root of Git repository containing |current-directory|. - `(string)` - files scope to show. One of - "tracked" (`--cached` Git flag). - "modified" (`--modified` Git flag). - "untracked" (`--others` Git flag). - "ignored" (`--ignored` Git flag). - "deleted" (`--deleted` Git flag). Default: "tracked". {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.git_hunks()* `MiniExtra.pickers.git_hunks`({local_opts}, {opts}) Git hunks picker Pick from Git hunks using `git diff`. Notes: - Requires executable `git`. - Requires target path to be part of git repository. - Present for exploration and navigation purposes. Doing any Git operations is suggested to be done in a dedicated Git client and is not planned. - On choose navigates to hunk's first change. Examples: - `MiniExtra.pickers.git_hunks({ scope = 'staged' })` - staged hunks from parent Git repository of |current-directory|. - `:Pick git_hunks path='%' n_context=0` - hunks from current file computed with no context. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(number)` - number of context lines to show in hunk's preview. Default: 3. - `(string|nil)` - target path for Git operation (if required). Also used to find Git repository inside which to construct items. Default: `nil` for root of Git repository containing |current-directory|. - `(string)` - hunks scope to show. One of "unstaged" or "staged". Default: "unstaged". {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.hipatterns()* `MiniExtra.pickers.hipatterns`({local_opts}, {opts}) Matches from 'mini.hipatterns' picker Pick from |mini.hipatterns| matches using |MiniHipatterns.get_matches()|. Notes: - Requires 'mini.hipatterns'. - Highlighter identifier is highlighted with its highlight group. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string)` - one of "all" (buffers with enabled 'mini.hipatterns') or "current" (buffer). Default: "all". - `(table|nil)` - highlighters for which to find matches. Forwarded to |MiniHipatterns.get_matches()|. Default: `nil`. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.history()* `MiniExtra.pickers.history`({local_opts}, {opts}) Neovim history picker Pick from output of |:history|. Use `` to edit current match in Command line. Notes: - Has no preview. - Choosing action depends on scope: - For "cmd" / ":" scopes, the command is executed. - For "search" / "/" / "?" scopes, search is redone. - For other scopes nothing is done (but chosen item is still returned). - `` only works for "cmd" / ":" / "search" / "/" / "?" scopes. Examples: - Command history: `MiniExtra.pickers.history({ scope = ':' })` - Search history: `:Pick history scope='/'` Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string)` - any allowed {name} flag of |:history| command. Note: word abbreviations are not allowed. Default: "all". {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.hl_groups()* `MiniExtra.pickers.hl_groups`({local_opts}, {opts}) Highlight groups picker Pick and preview highlight groups. Notes: - Item line is colored with same highlight group it represents. - Preview shows highlight's definition (as in |:highlight| with {group-name}). - Choosing places highlight definition in Command line to update and apply. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Not used at the moment. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.keymaps()* `MiniExtra.pickers.keymaps`({local_opts}, {opts}) Neovim keymaps picker Pick and preview data about Neovim keymaps. Notes: - Item line contains data about keymap mode, whether it is buffer local, its left hand side, and inferred description. - Preview shows keymap data or callback source (if present and reachable). - Choosing emulates pressing the left hand side of the keymap. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string)` - modes to show. One of "all" or appropriate mode for |nvim_set_keymap()|. Default: "all". - `(string)` - scope to show. One of "all", "global", "buf". Default: "all". {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.list()* `MiniExtra.pickers.list`({local_opts}, {opts}) Neovim lists picker Pick and navigate to elements of the following Neovim lists: - |quickfix| list. - |location-list| of current window. - |jumplist|. - |changelist|. Note: it requires explicit `scope`. Examples: - `MiniExtra.pickers.list({ scope = 'quickfix' })` - quickfix list. - `:Pick list scope='jump'` - jump list. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string)` - type of list to show. One of "quickfix", "location", "jump", "change". Default: `nil` which means explicit scope is needed. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.lsp()* `MiniExtra.pickers.lsp`({local_opts}, {opts}) LSP picker Pick and navigate with LSP methods. Notes: - Needs an explicit scope from a list of supported ones: - "declaration". - "definition". - "document_symbol". - "implementation". - "references". - "type_definition". - "workspace_symbol". - "workspace_symbol_live" - same as "workspace_symbol", but with live feedback treating picker's prompt as LSP server query. Similar to how |MiniPick.builtin.grep_live()| and |MiniPick.builtin.grep()| are related. To use regular matching, activate |MiniPick-actions-refine|. - Relies on `vim.lsp.buf` methods supporting |vim.lsp.LocationOpts.OnList|. In particular, it means that picker is started only if LSP server returns list of locations and not a single location. - Doesn't return anything due to async nature of `vim.lsp.buf` methods. - Requires set up |mini.icons| to show extra icons and highlighting in "document_symbol", "workspace_symbol", "workspace_symbol_live" scopes. Examples: - `MiniExtra.pickers.lsp({ scope = 'references' })` - references of the symbol under cursor. - `:Pick lsp scope='document_symbol'` - symbols in current file. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string)` - LSP method to use. One of the supported ones (see list above). Default: `nil` which means explicit scope is needed. - `(string)` - query for `"workspace_symbol"` scope. Default: empty string for all symbols (according to LSP specification). {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(nil)` Nothing is returned. ------------------------------------------------------------------------------ *MiniExtra.pickers.manpages()* `MiniExtra.pickers.manpages`({local_opts}, {opts}) Manual pages Pick manual page (like described in |ft-man-plugin|). Notes: - Depends on |:Man| command to preview and choose items. - Shows page in the target window. Use |MiniPick-actions-choose| to split. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Not used at the moment. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.marks()* `MiniExtra.pickers.marks`({local_opts}, {opts}) Neovim marks picker Pick and preview position of Neovim |mark|s. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string)` - scope to show. One of "all", "global", "buf". Default: "all". {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.oldfiles()* `MiniExtra.pickers.oldfiles`({local_opts}, {opts}) Old files picker Pick from |v:oldfiles| entries representing readable files. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(boolean)` - whether to return files only from current working directory and its subdirectories. Default: `false`. - `(boolean)` - whether to preserve original order during query. Default: `false`. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.options()* `MiniExtra.pickers.options`({local_opts}, {opts}) Neovim options picker Pick and preview data about Neovim options. Notes: - Item line is colored based on whether it was set (dimmed if wasn't). - Preview shows option value in target window and its general information. - Choosing places option name in Command line to update and apply. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string)` - options to show. One of "all", "global", "win", "buf". Default: "all". {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.registers()* `MiniExtra.pickers.registers`({local_opts}, {opts}) Neovim registers picker Pick from Neovim |registers|. Notes: - There is no preview (all information is in the item's text). - Choosing pastes content of a register: with |i_CTRL-R| in Insert mode, |c_CTRL-R| in Command-line mode, and |P| otherwise. Expression register |quote=| is reevaluated (if present) and pasted. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Not used at the moment. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.spellsuggest()* `MiniExtra.pickers.spellsuggest`({local_opts}, {opts}) Neovim spell suggestions picker Pick and apply spell suggestions. Notes: - No preview is available. - Choosing replaces current word (||) with suggestion. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(number)` - number of spell suggestions. Default: 25. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.treesitter()* `MiniExtra.pickers.treesitter`({local_opts}, {opts}) Tree-sitter nodes picker Pick and navigate to |treesitter| nodes of current buffer. Notes: - Requires active tree-sitter parser in the current buffer. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Not used at the moment. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.visit_paths()* `MiniExtra.pickers.visit_paths`({local_opts}, {opts}) Visit paths from 'mini.visits' picker Pick paths from |mini.visits| using |MiniVisits.list_paths()|. Notes: - Requires 'mini.visits'. Examples: - `MiniExtra.pickers.visit_paths()` - visits registered for |current-directory| and ordered by "robust frecency". - `:Pick visit_paths cwd='' recency_weight=1 filter='core'` - all visits with "core" label ordered from most to least recent. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string)` - forwarded to |MiniVisits.list_paths()|. Default: `nil` to get paths registered for |current-directory|. - `(function|string)` - forwarded to |MiniVisits.list_paths()|. Default: `nil` to use all paths. - `(boolean)` - whether to preserve original order during query. Default: `false`. - `(number)` - forwarded to |MiniVisits.gen_sort.default()|. Default: 0.5 to use "robust frecency" sorting. - `(function)` - forwarded to |MiniVisits.list_paths()|. Default: `nil` to use "robust frecency". Note: if supplied, has precedence over `recency_weight`. {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(any)` Output of the called picker. ------------------------------------------------------------------------------ *MiniExtra.pickers.visit_labels()* `MiniExtra.pickers.visit_labels`({local_opts}, {opts}) Visit labels from 'mini.visits' picker Pick labels from |mini.visits| using |MiniVisits.list_labels()| and |MiniVisits.list_paths()|. Notes: - Requires 'mini.visits'. - Preview shows target visit paths filtered to those having previewed label. - Choosing essentially starts |MiniExtra.pickers.visit_paths()| for paths with the chosen label. Examples: - `MiniExtra.pickers.visit_labels()` - labels from visits registered for |current-directory|. - `:Pick visit_labels cwd=''` - labels from all visits. Parameters ~ {local_opts} `(table|nil)` Options defining behavior of this particular picker. Possible fields: - `(string)` - forwarded to |MiniVisits.list_labels()|. Default: `nil` to get labels from visits registered for |current-directory|. - `(function|string)` - forwarded to |MiniVisits.list_labels()|. Default: `nil` to use all visits. - `(string)` - forwarded to |MiniVisits.list_labels()|. Default: `""` to get labels from all visits for target `cwd`. - `(function)` - forwarded to |MiniVisits.list_paths()| for preview and choose. Default: `nil` to use "robust frecency". {opts} `(table|nil)` Options forwarded to |MiniPick.start()|. Return ~ `(...)` Chosen path. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-files.txt ================================================ *mini.files* Navigate and manipulate file system MIT License Copyright (c) 2023 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniFiles* Features: - Navigate file system using column view (Miller columns) to display nested directories. See |MiniFiles-navigation| for overview. - Opt-in preview of file or directory under cursor. - Manipulate files and directories by editing text buffers: create, delete, copy, rename, move. See |MiniFiles-manipulation| for overview. - Use as default file explorer instead of `netrw`. - Configurable: - Filter/prefix/sort of file system entries. - Mappings used for common explorer actions. - UI options: whether to show preview of file/directory under cursor, etc. - Bookmarks for quicker navigation. What it doesn't do: - Try to be replacement of system file explorer. It is mostly designed to be used within Neovim to quickly explore file system structure, open files, and perform some quick file system edits. - Work on remote locations. Only local file system is supported. - Provide built-in interactive toggle of content `filter` and `sort`. See |MiniFiles-examples| for some common examples. - Provide out of the box extra information like git or diagnostic status. This can be achieved by setting |extmarks| on appropriate event(s) (see |MiniFiles-events|) Notes: - This module is written and thoroughly tested on Linux. Support for other platform/OS (like Windows or MacOS) is a goal, but there is no guarantee. - This module silently reacts to not enough permissions: - In case of missing file, check its or its parent read permissions. - In case of no manipulation result, check write permissions. # Dependencies ~ Suggested dependencies (provide extra functionality, will work without them): - Enabled |mini.icons| module to show icons near file/directory names. Falls back to [nvim-tree/nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons) plugin or uses default icons. # Setup ~ This module needs a setup with `require('mini.files').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniFiles` which you can use for scripting or manually (with `:lua MiniFiles.*`). See |MiniFiles.config| for available config settings. You can override runtime config settings (like mappings or window options) locally to buffer inside `vim.b.minifiles_config` which should have same structure as `MiniFiles.config`. See |mini.nvim-buffer-local-config| for more details. # Comparisons ~ - [nvim-tree/nvim-tree.lua](https://github.com/nvim-tree/nvim-tree.lua): - Provides tree view of file system, while this module uses column view. - File system manipulation is done with custom set of mappings for each action, while this module is designed to do that by editing text. - Has more out of the box functionality with extra configuration, while this module has not (by design). - [stevearc/oil.nvim](https://github.com/stevearc/oil.nvim): - Uses single window to show information only about currently explored directory, while this module uses column view to show whole currently explored branch. - Also uses text editing to manipulate file system entries. - Can work for remote file systems, while this module can not (by design). - [nvim-neo-tree/neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim): - Compares to this module mostly the same as 'nvim-tree/nvim-tree.lua'. # Highlight groups ~ - `MiniFilesBorder` - border of regular windows. - `MiniFilesBorderModified` - border of windows showing modified buffer. - `MiniFilesCursorLine` - cursor line in explorer windows. - `MiniFilesDirectory` - text and icon representing directory. - `MiniFilesFile` - text representing file. - `MiniFilesNormal` - basic foreground/background highlighting. - `MiniFilesTitle` - title of regular windows. - `MiniFilesTitleFocused` - title of focused window. To change any highlight group, set it directly with |nvim_set_hl()|. # Disabling ~ This plugin provides only manually started functionality, so no disabling is available. ------------------------------------------------------------------------------ *MiniFiles-navigation* Every navigation starts by calling |MiniFiles.open()|, either directly or via mapping (see its help for examples of some common scenarios). It will show an explorer consisting of side-by-side floating windows with the following principles: - Explorer shows one branch of nested directories at a time. - Explorer consists from several windows: - Each window displays entries of a single directory in a modifiable scratch buffer. - Windows are organized left to right: for any particular window the left neighbor is its parent directory and right neighbor - its child. - Explorer windows are the viewport to some part of current branch, meaning that their opening/closing does not affect the branch. This matters, for example, if there are more elements in the branch than can be shown windows. - Every buffer line represents separate file system entry following certain format (not visible for users by default; set |'conceallevel'| to 0 to see it) - Once directory is shown, its buffer is not updated automatically following external file system changes. Manually use |MiniFiles.synchronize()| for that. After opening explorer, in-buffer navigation is done the same way as any regular buffer, except without some keys reserved for built-in actions. Most common ways to navigate are: - Press `j` to move cursor onto next (lower) entry in current directory. - Press `k` to move cursor onto previous (higher) entry in current directory. - Press `l` to expand entry under cursor (see "Go in" action). - Press `h` to focus on parent directory (see "Go out" action). Cursor positions in each directory buffer are tracked and saved during navigation. This allows for more convenient repeated navigation to some previously visited branch. Available built-in actions (see "Details" for more information): > | Action | Keys | Description | |-------------|------|------------------------------------------------| | Close | q | Close explorer | |-------------|------|------------------------------------------------| | Go in | l | Expand entry (show directory or open file) | |-------------|------|------------------------------------------------| | Go in plus | L | Expand entry plus extra action | |-------------|------|------------------------------------------------| | Go out | h | Focus on parent directory | |-------------|------|------------------------------------------------| | Go out plus | H | Focus on parent directory plus extra action | |-------------|------|------------------------------------------------| | Go to mark | ' | Jump to bookmark (waits for single key id) | |-------------|------|------------------------------------------------| | Set mark | m | Set bookmark (waits for single key id) | |-------------|------|------------------------------------------------| | Reset | | Reset current explorer | |-------------|------|------------------------------------------------| | Reveal cwd | @ | Reset current current working directory | |-------------|------|------------------------------------------------| | Show help | g? | Show help window | |-------------|------|------------------------------------------------| | Synchronize | = | Synchronize user edits and/or external changes | |-------------|------|------------------------------------------------| | Trim left | < | Trim left part of branch | |-------------|------|------------------------------------------------| | Trim right | > | Trim right part of branch | |-------------|------|------------------------------------------------| < Details: - "Go in": - Always opens file in the latest window before `MiniFiles.open()` call. - Never closes explorer. - Works in linewise Visual mode to expand multiple entries. - "Go in plus" is regular "Go in" but closes explorer after opening a file. - "Go out plus" is regular "Go out" but trims right part of branch. - "Set mark" and "Go to mark" both wait for user to press a single character of a bookmark id. Example: `ma` sets directory path of focused window as bookmark "a"; `'a` jumps (sets as whole branch) to bookmark "a". Special bookmark "'" always points to path before the latest bookmark jump. - "Reset" focuses only on "anchor" directory (the one used to open current explorer) and resets all stored directory cursor positions. - "Reveal cwd" extends branch to include |current-directory|. If it is not an ancestor of the current branch, nothing is done. - "Show help" results into new window with helpful information about current explorer (like buffer mappings and bookmarks). Press `q` to close it. - "Synchronize" parses user edits in directory buffers, applies them (after confirmation), and updates all directory buffers with the most relevant file system information. Can also be used without user edits to show up to date file system entries. See |MiniFiles-manipulation| for more info about file system manipulation. - "Trim left" and "Trim right" trim parts of the whole branch, not only its currently visible parts. Notes: - Each action has exported function with more details about it. - Keys can be configured with `mappings` table of |MiniFiles.config|. ------------------------------------------------------------------------------ *MiniFiles-manipulation* File system manipulation is done by editing text inside directory buffers, which are shown inside dedicated window(s). See |MiniFiles-navigation| for more information about navigating to a particular directory. General workflow: - Navigate to the directory in which manipulation should be done. - Edit buffer in the way representing file system action. - Repeat previous steps until all necessary file system actions are recorded. Note: even if directory buffer is hidden, its modifications are preserved, so you can navigate in and out of directory with modified buffer. - Execute |MiniFiles.synchronize()| (default key is `=`). This will prompt confirmation dialog listing all file system actions (per directory) it is about to perform. READ IT CAREFULLY. - Confirm by pressing `y` / `` (apply edits and update buffers) or don't confirm by pressing `n` / `` (update buffers without applying edits). Note: prefer small and not related steps with more frequent synchronization over single complex manipulation. There are (known) cases which won't work. # How does it work ~ All manipulation functionality is powered by creating and keeping track of path indexes: text of the form `/xxx` (`xxx` is the number path index) placed at the start of every line representing file system entry. By default they are hidden as concealed text (along with prefix separators) for more convenience but you can see them by setting |'conceallevel'| to 0. DO NOT modify text to the left of entry name. During synchronization, actual text for entry name is compared to path index at that line (if present) to deduce which file system action to perform. Note that order of text manipulation steps does not affect performed actions. # Supported file system actions ~ ## Create ~ - Create file by creating new line with file name (including extension). - Create directory by creating new line with directory name followed by `/`. - Create file or directory inside nested directories by creating new line with text like 'dir/nested-dir/' or 'dir/nested-dir/file'. Always use `/` on any OS. ## Delete ~ - Delete file or directory by deleting **whole line** describing it. - If `options.permanent_delete` is `true`, delete is permanent. Otherwise file system entry is moved to a module-specific trash directory (see |MiniFiles.config| for more details). ## Rename ~ - Rename file or directory by editing its name (not icon or path index to the left of it). - With default mappings for `h` / `l` it might be not convenient to rename only part of an entry. You can adopt any of the following approaches: - Use different motions, like |$|, |e|, |f|, etc. - Go into Insert mode and navigate inside it. - Change mappings to be more suited for manipulation and not navigation. See "Mappings" section in |MiniFiles.config|. - It is not needed to end directory name with `/`. - Appending `/` to a file name will delete it and create empty directory with the same name. - Cyclic renames ("a" to "b" and "b" to "a") are not supported. ## Copy ~ - Copy file or directory by copying **whole line** describing it and pasting it inside buffer of target directory. - Change of target path is allowed. Edit only entry name in target location (not icon or path index to the left of it). - Copying inside same parent directory is supported only if target path has different name. - Copying inside child directory is supported. ## Move ~ - Move file or directory by cutting **whole line** describing it and then pasting it inside target directory. - Change of target path is allowed. Edit only entry name in target location (not icon or path index to the left of it). - Moving directory inside itself is not supported. ------------------------------------------------------------------------------ *MiniFiles-events* To allow user customization and integration of external tools, certain |User| autocommand events are triggered under common circumstances. # UI events ~ - `MiniFilesExplorerOpen` - just after explorer finishes opening. - `MiniFilesExplorerClose` - just before explorer starts closing. - `MiniFilesBufferCreate` - when buffer is created to show a particular directory/file. Triggered once per path during explorer session. Can be used to create buffer-local mappings. - `MiniFilesBufferUpdate` - when path buffer is updated with new content. Can be used for integrations to set useful |extmarks|. - `MiniFilesWindowOpen` - when new window is opened. Can be used to set window-local settings (like border, 'winblend', etc.) - `MiniFilesWindowUpdate` - when a window is updated. Triggers VERY frequently. At least after every cursor movement and "go in" / "go out" action. Callback for each buffer/window UI event will receive field (see |nvim_create_autocmd()|) with the following information: - - index of target buffer. - - index of target window. Can be `nil`, like in `MiniFilesBufferCreate` and buffer's first `MiniFilesBufferUpdate` as they are triggered before window is created. # File action events ~ - `MiniFilesActionCreate` - after entry is successfully created. - `MiniFilesActionDelete` - after entry is successfully deleted. - `MiniFilesActionRename` - after entry is successfully renamed. - `MiniFilesActionCopy` - after entry is successfully copied. - `MiniFilesActionMove` - after entry is successfully moved. Callback for each file action event will receive `data` field (see |nvim_create_autocmd()|) with the following information: - - string with action name. - - full path of entry before action (`nil` for "create" action). - - full path of entry after action (`nil` for permanent "delete" action). ------------------------------------------------------------------------------ *MiniFiles-examples* # Toggle explorer ~ Use a combination of |MiniFiles.open()| and |MiniFiles.close()|: >lua local minifiles_toggle = function(...) if not MiniFiles.close() then MiniFiles.open(...) end end < # Customize windows ~ For most of the common customizations using `MiniFilesWindowOpen` event autocommand is the suggested approach: >lua vim.api.nvim_create_autocmd('User', { pattern = 'MiniFilesWindowOpen', callback = function(args) local win_id = args.data.win_id -- Customize window-local settings vim.wo[win_id].winblend = 50 local config = vim.api.nvim_win_get_config(win_id) config.border, config.title_pos = 'double', 'right' vim.api.nvim_win_set_config(win_id, config) end, }) < However, some parts (like window title and height) of window config are later updated internally. Use `MiniFilesWindowUpdate` event for them: >lua vim.api.nvim_create_autocmd('User', { pattern = 'MiniFilesWindowUpdate', callback = function(args) local config = vim.api.nvim_win_get_config(args.data.win_id) -- Ensure fixed height config.height = 10 -- Ensure no title padding local n = #config.title config.title[1][1] = config.title[1][1]:gsub('^ ', '') config.title[n][1] = config.title[n][1]:gsub(' $', '') vim.api.nvim_win_set_config(args.data.win_id, config) end, }) < # Customize icons ~ Use different directory icon (if you don't use |mini.icons|): >lua local my_prefix = function(fs_entry) if fs_entry.fs_type == 'directory' then -- NOTE: it is usually a good idea to use icon followed by space return ' ', 'MiniFilesDirectory' end return MiniFiles.default_prefix(fs_entry) end require('mini.files').setup({ content = { prefix = my_prefix } }) < Show no icons: >lua require('mini.files').setup({ content = { prefix = function() end } }) < # Create mapping to show/hide dot-files ~ Create an autocommand for `MiniFilesBufferCreate` event which calls |MiniFiles.refresh()| with explicit `content.filter` functions: >lua local show_dotfiles = true local filter_show = function(fs_entry) return true end local filter_hide = function(fs_entry) return not vim.startswith(fs_entry.name, '.') end local toggle_dotfiles = function() show_dotfiles = not show_dotfiles local new_filter = show_dotfiles and filter_show or filter_hide MiniFiles.refresh({ content = { filter = new_filter } }) end vim.api.nvim_create_autocmd('User', { pattern = 'MiniFilesBufferCreate', callback = function(args) local buf_id = args.data.buf_id -- Tweak left-hand side of mapping to your liking vim.keymap.set('n', 'g.', toggle_dotfiles, { buffer = buf_id }) end, }) < # Create mappings to modify target window via split ~ Combine |MiniFiles.get_explorer_state()| and |MiniFiles.set_target_window()|: >lua local map_split = function(buf_id, lhs, direction) local rhs = function() -- Make new window and set it as target local cur_target = MiniFiles.get_explorer_state().target_window local new_target = vim.api.nvim_win_call(cur_target, function() vim.cmd(direction .. ' split') return vim.api.nvim_get_current_win() end) MiniFiles.set_target_window(new_target) -- This intentionally doesn't act on file under cursor in favor of -- explicit "go in" action (`l` / `L`). To immediately open file, -- add appropriate `MiniFiles.go_in()` call instead of this comment. end -- Adding `desc` will result into `show_help` entries local desc = 'Split ' .. direction vim.keymap.set('n', lhs, rhs, { buffer = buf_id, desc = desc }) end vim.api.nvim_create_autocmd('User', { pattern = 'MiniFilesBufferCreate', callback = function(args) local buf_id = args.data.buf_id -- Tweak keys to your liking map_split(buf_id, '', 'belowright horizontal') map_split(buf_id, '', 'belowright vertical') map_split(buf_id, '', 'tab') end, }) < # Create mappings which use data from entry under cursor ~ Use |MiniFiles.get_fs_entry()|: >lua -- Set focused directory as current working directory local set_cwd = function() local path = (MiniFiles.get_fs_entry() or {}).path if path == nil then return vim.notify('Cursor is not on valid entry') end vim.fn.chdir(vim.fs.dirname(path)) end -- Yank in register full path of entry under cursor local yank_path = function() local path = (MiniFiles.get_fs_entry() or {}).path if path == nil then return vim.notify('Cursor is not on valid entry') end vim.fn.setreg(vim.v.register, path) end -- Open path with system default handler (useful for non-text files) local ui_open = function() vim.ui.open(MiniFiles.get_fs_entry().path) end vim.api.nvim_create_autocmd('User', { pattern = 'MiniFilesBufferCreate', callback = function(args) local b = args.data.buf_id vim.keymap.set('n', 'g~', set_cwd, { buffer = b, desc = 'Set cwd' }) vim.keymap.set('n', 'gX', ui_open, { buffer = b, desc = 'OS open' }) vim.keymap.set('n', 'gy', yank_path, { buffer = b, desc = 'Yank path' }) end, }) < # Set custom bookmarks ~ Use |MiniFiles.set_bookmark()| inside `MiniFilesExplorerOpen` event: >lua local set_mark = function(id, path, desc) MiniFiles.set_bookmark(id, path, { desc = desc }) end vim.api.nvim_create_autocmd('User', { pattern = 'MiniFilesExplorerOpen', callback = function() set_mark('c', vim.fn.stdpath('config'), 'Config') -- path set_mark('w', vim.fn.getcwd, 'Working directory') -- callable set_mark('~', '~', 'Home directory') end, }) < ------------------------------------------------------------------------------ *MiniFiles.setup()* `MiniFiles.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniFiles.config|. Usage ~ >lua require('mini.files').setup() -- use default config -- OR require('mini.files').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniFiles.config* `MiniFiles.config` Defaults ~ >lua MiniFiles.config = { -- Customization of shown content content = { -- Predicate for which file system entries to show filter = nil, -- Highlight group to use for a file system entry highlight = nil, -- Prefix text and highlight to show to the left of file system entry prefix = nil, -- Order in which to show file system entries sort = nil, }, -- Module mappings created only inside explorer. -- Use `''` (empty string) to not create one. mappings = { close = 'q', go_in = 'l', go_in_plus = 'L', go_out = 'h', go_out_plus = 'H', mark_goto = "'", mark_set = 'm', reset = '', reveal_cwd = '@', show_help = 'g?', synchronize = '=', trim_left = '<', trim_right = '>', }, -- General options options = { -- Whether to delete permanently or move into module-specific trash permanent_delete = true, -- Whether to use for editing directories use_as_default_explorer = true, }, -- Customization of explorer windows windows = { -- Maximum number of windows to show side by side max_number = math.huge, -- Whether to show preview of file/directory under cursor preview = false, -- Width of focused window width_focus = 50, -- Width of non-focused window width_nofocus = 15, -- Width of preview window width_preview = 25, }, } < # Content ~ `content.filter` is a predicate which takes file system entry data as input and returns `true`-ish value if it should be shown. Uses |MiniFiles.default_filter()| by default. A file system entry data is a table with the following fields: - `(string)` - one of "file" or "directory". - `(string)` - basename of an entry (including extension). - `(string)` - full path of an entry. `content.highlight` describes how file system entry name should be highlighted. Takes file system entry data as input and returns a highlight group name. Uses |MiniFiles.default_highlight()| by default. `content.prefix` describes what text (prefix) to show to the left of file system entry name (if any) and how to highlight it. It also takes file system entry data as input and returns tuple of text and highlight group name to be used to highlight prefix. See |MiniFiles-examples| for common examples of how to use it. Note: due to how lines are parsed to detect user edits for file system manipulation, output of `content.prefix` should not contain `/` character. Uses |MiniFiles.default_prefix()| by default. `content.sort` describes in which order directory entries should be shown in directory buffer. Takes as input and returns as output an array of file system entry data. Note: technically, it can be used to filter and modify its elements as well. Uses |MiniFiles.default_sort()| by default. # Mappings ~ `mappings` table can be used to customize buffer-local mappings created in each directory buffer for built-in actions. Entry name corresponds to the function name of the action, value - right hand side of the mapping. Supply empty string to not create a particular mapping. Default mappings are mostly designed for consistent navigation experience. Here are some alternatives: >lua -- Close explorer after opening file with `l` mappings = { go_in = 'L', go_in_plus = 'l', } -- Don't use `h`/`l` for easier cursor navigation during text edit mappings = { go_in = 'L', go_in_plus = '', go_out = 'H', go_out_plus = '', } < # Options ~ `options.use_as_default_explorer` is a boolean indicating whether this module will be used as a default file explorer to edit directory (instead of `netrw`). Note: to work with directory in |arglist|, do not lazy load this module. `options.permanent_delete` is a boolean indicating whether to perform permanent delete or move into special trash directory. This is a module-specific variant of "remove to trash". Target directory is 'mini.files/trash' inside standard path of Neovim data directory (execute `:echo stdpath('data')` to see its path in your case). # Windows ~ `windows.max_number` is a maximum number of windows allowed to be open simultaneously. For example, use value 1 to always show single window. There is no constraint by default. `windows.preview` is a boolean indicating whether to show preview of file/directory under cursor. Notes: - It is always shown, even if current line is for not yet existing path. - File preview is highlighted if its size is small enough (less than 1K bytes per line or 1M bytes in total). `windows.width_focus` and `windows.width_nofocus` are number of columns used as `width` for focused and non-focused windows respectively. ------------------------------------------------------------------------------ *MiniFiles.open()* `MiniFiles.open`({path}, {use_latest}, {opts}) Open file explorer Common ways to use this function: >lua -- Open current working directory in a last used state MiniFiles.open() -- Fresh explorer in current working directory MiniFiles.open(nil, false) -- Open directory of current file (in last used state) focused on the file MiniFiles.open(vim.api.nvim_buf_get_name(0)) -- Fresh explorer in directory of current file MiniFiles.open(vim.api.nvim_buf_get_name(0), false) -- Open last used `path` (per tabpage) -- Current working directory for the first time MiniFiles.open(MiniFiles.get_latest_path()) < Parameters ~ {path} `(string|nil)` A valid file system path used as anchor. If it is a path to directory, used directly. If it is a path to file, its parent directory is used as anchor while explorer will focus on the supplied file. Default: path of |current-directory|. {use_latest} `(boolean|nil)` Whether to load explorer state from history (based on the supplied anchor path). Default: `true`. {opts} `(table|nil)` Table of options overriding |MiniFiles.config| and `vim.b.minifiles_config` for this particular explorer session. ------------------------------------------------------------------------------ *MiniFiles.refresh()* `MiniFiles.refresh`({opts}) Refresh explorer Notes: - If in `opts` at least one of `content` entry is not `nil`, all directory buffers are forced to update. Parameters ~ {opts} `(table|nil)` Table of options to update. ------------------------------------------------------------------------------ *MiniFiles.synchronize()* `MiniFiles.synchronize`() Synchronize explorer - Parse user edits in directory buffers. - Convert edits to file system actions and apply them after confirmation. Choosing "No" skips application while "Cancel" stops synchronization. - Update all directory buffers with the most relevant file system information. Can be used without user edits to account for external file system changes. Return ~ `(boolean)` Whether synchronization was done. ------------------------------------------------------------------------------ *MiniFiles.reset()* `MiniFiles.reset`() Reset explorer - Show single window focused on anchor directory (which was used as first argument for |MiniFiles.open()|). - Reset all tracked directory cursors to point at first entry. ------------------------------------------------------------------------------ *MiniFiles.close()* `MiniFiles.close`() Close explorer Return ~ `(boolean|nil)` Whether closing was done or `nil` if there was nothing to close. ------------------------------------------------------------------------------ *MiniFiles.go_in()* `MiniFiles.go_in`({opts}) Go in entry under cursor Depends on entry under cursor: - If directory, focus on it in the window to the right. - If file, open it in the window which was current during |MiniFiles.open()|. Explorer is not closed after that. Parameters ~ {opts} `(table|nil)` Options. Possible fields: - `(boolean)` - whether to close explorer after going inside a file. Powers the `go_in_plus` mapping. Default: `false`. ------------------------------------------------------------------------------ *MiniFiles.go_out()* `MiniFiles.go_out`() Go out to parent directory - Focus on window to the left showing parent of current directory. ------------------------------------------------------------------------------ *MiniFiles.trim_left()* `MiniFiles.trim_left`() Trim left part of branch - Remove all branch paths to the left of currently focused one. This also results into current window becoming the most left one. ------------------------------------------------------------------------------ *MiniFiles.trim_right()* `MiniFiles.trim_right`() Trim right part of branch - Remove all branch paths to the right of currently focused one. This also results into current window becoming the most right one. ------------------------------------------------------------------------------ *MiniFiles.reveal_cwd()* `MiniFiles.reveal_cwd`() Reveal current working directory - Prepend branch with parent paths until current working directory is reached. Do nothing if not inside it. ------------------------------------------------------------------------------ *MiniFiles.show_help()* `MiniFiles.show_help`() Show help window - Open window with helpful information about currently shown explorer and focus on it. To close it, press `q`. ------------------------------------------------------------------------------ *MiniFiles.get_fs_entry()* `MiniFiles.get_fs_entry`({buf_id}, {line}) Get file system entry data Parameters ~ {buf_id} `(number|nil)` Buffer identifier of valid directory buffer. Default: current buffer. {line} `(number|nil)` Line number of entry for which to return information. Default: cursor line. Return ~ `(table|nil)` Table of file system entry data with the following fields: - `(string)` - one of "file" or "directory". - `(string)` - basename of an entry (including extension). - `(string)` - full path of an entry. Returns `nil` if there is no proper file system entry path at the line. ------------------------------------------------------------------------------ *MiniFiles.get_explorer_state()* `MiniFiles.get_explorer_state`() Get state of active explorer Return ~ `(table|nil)` Table with explorer state data or `nil` if no active explorer. State data is a table with the following fields: - `(string)` - anchor directory path (see |MiniFiles.open()|). - `(table)` - map from bookmark id (single character) to its data: table with and fields (see |MiniFiles.set_bookmark()|). - `(table)` - array of nested paths for currently opened branch. - `(number)` - an index in for currently focused path. - `(number)` - identifier of target window. - `(table)` - array with data about currently opened windows. Each element is a table with (window identifier) and (path shown in the window) fields. See also ~ - |MiniFiles.set_bookmark()| - |MiniFiles.set_branch()| - |MiniFiles.set_target_window()| ------------------------------------------------------------------------------ *MiniFiles.set_target_window()* `MiniFiles.set_target_window`({win_id}) Set target window Parameters ~ {win_id} `(number)` Window identifier inside which file will be opened. ------------------------------------------------------------------------------ *MiniFiles.set_branch()* `MiniFiles.set_branch`({branch}, {opts}) Set branch Set which paths to display. Preview (if enabled) is applied afterwards. Parameters ~ {branch} `(table)` Array of strings representing actually present on disk paths. Each consecutive pair should represent direct parent-child paths. Should contain at least one directory path. May end with file path (will be previwed). Relative paths are resolved using |current-directory|. {opts} `(table|nil)` Options. Possible fields: - `(number)` - an index in `branch` for path to focus. Will be normalized to fit inside `branch`. Default: index of deepest directory. See also ~ |MiniFiles.get_explorer_state()| ------------------------------------------------------------------------------ *MiniFiles.set_bookmark()* `MiniFiles.set_bookmark`({id}, {path}, {opts}) Set bookmark Parameters ~ {id} `(string)` Single character bookmark id. {path} `(string|function)` Path of a present on disk directory to set as a bookmark's path. If callable, should return such path. {opts} `(table|nil)` Options. Possible fields: - `(string)` - bookmark description (used in help window). ------------------------------------------------------------------------------ *MiniFiles.get_latest_path()* `MiniFiles.get_latest_path`() Get latest used anchor path Note: if latest used `path` argument for |MiniFiles.open()| was for file, this will return its parent (as it was used as anchor path). ------------------------------------------------------------------------------ *MiniFiles.default_filter()* `MiniFiles.default_filter`({fs_entry}) Default filter of file system entries Currently does not filter anything out. Parameters ~ {fs_entry} `(table)` Table with the following fields: - `(string)` - one of "file" or "directory". - `(string)` - basename of an entry (including extension). - `(string)` - full path of an entry. Return ~ `(boolean)` Always `true`. ------------------------------------------------------------------------------ *MiniFiles.default_prefix()* `MiniFiles.default_prefix`({fs_entry}) Default prefix of file system entries - If set up |mini.icons|, use |MiniIcons.get()| for "directory"/"file" category. - Otherwise: - For directory return fixed icon and "MiniFilesDirectory" group name. - For file try to use `get_icon()` from 'nvim-tree/nvim-web-devicons'. If missing, return fixed icon and 'MiniFilesFile' group name. Parameters ~ {fs_entry} `(table)` Table with the following fields: - `(string)` - one of "file" or "directory". - `(string)` - basename of an entry (including extension). - `(string)` - full path of an entry. Return ~ `(...)` Icon and highlight group name. For more details, see |MiniFiles.config| and |MiniFiles-examples|. ------------------------------------------------------------------------------ *MiniFiles.default_sort()* `MiniFiles.default_sort`({fs_entries}) Default sort of file system entries Sort directories and files separately (alphabetically ignoring case) and put directories first. Parameters ~ {fs_entries} `(table)` Array of file system entry data. Each one is a table with the following fields: - `(string)` - one of "file" or "directory". - `(string)` - basename of an entry (including extension). - `(string)` - full path of an entry. Return ~ `(table)` Sorted array of file system entries. ------------------------------------------------------------------------------ *MiniFiles.default_highlight()* `MiniFiles.default_highlight`({fs_entry}) Default file system entry highlight Returns `'MiniFilesDirectory'` for directory and `'MiniFilesFile'` otherwise. Parameters ~ {fs_entry} `(table)` Table with the following fields: - `(string)` - one of "file" or "directory". - `(string)` - basename of an entry (including extension). - `(string)` - full path of an entry. Return ~ `(string)` Highlight group name. vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-fuzzy.txt ================================================ *mini.fuzzy* Fuzzy matching MIT License Copyright (c) 2021 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniFuzzy* Features: - Minimal and fast fuzzy matching algorithm which prioritizes match width. - Functions to for common fuzzy matching operations: - |MiniFuzzy.match()|. - |MiniFuzzy.filtersort()|. - |MiniFuzzy.process_lsp_items()|. - Generator of sorter (|MiniFuzzy.get_telescope_sorter()|) for [nvim-telescope/telescope.nvim](https://github.com/nvim-telescope/telescope.nvim) # Setup ~ This module doesn't need setup, but it can be done to improve usability. Setup with `require('mini.fuzzy').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniFuzzy` which you can use for scripting or manually (with `:lua MiniFuzzy.*`). See |MiniFuzzy.config| for `config` structure and default values. You can override runtime config settings locally to buffer inside `vim.b.minifuzzy_config` which should have same structure as `MiniFuzzy.config`. See |mini.nvim-buffer-local-config| for more details. # Notes ~ 1. Currently there is no explicit design to work with multibyte symbols, but simple examples should work. 2. Smart case is used: case insensitive if input word (which is usually a user input) is all lower case. Case sensitive otherwise. ------------------------------------------------------------------------------ *MiniFuzzy-algorithm* General design uses only width of found match and index of first letter match. No special characters or positions (like in fzy and fzf) are used. Given non-empty input `word` and target `candidate`: - The goal is to find matching between `word`'s letters and letters in `candidate` which minimizes certain score. It is assumed that order of letters in `word` and those matched in `candidate` should be the same. - Matching is represented by matched positions: an array `positions` of integers with length equal to number of letters in `word`. The following should be always true in case of a match: `candidate`'s letter at index `positions[i]` is letters[i]` for all valid `i`. - Matched positions are evaluated based only on two features: their width (number of indexes between first and last positions) and first match (index of first letter match). There is a global setting `cutoff` for which all feature values greater than it can be considered "equally bad". - Score of matched positions is computed with following explicit formula: `cutoff * min(width, cutoff) + min(first, cutoff)`. It is designed to be equivalent to first comparing widths (lower is better) and then comparing first match (lower is better). For example, if `word = 'time'`: - '_time' (width 4) will have a better match than 't_ime' (width 5). - 'time_a' (width 4, first 1) will have a better match than 'a_time' (width 4, first 3). - Final matched positions are those which minimize score among all possible matched positions of `word` and `candidate`. ------------------------------------------------------------------------------ *MiniFuzzy.setup()* `MiniFuzzy.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniFuzzy.config|. Usage ~ >lua require('mini.fuzzy').setup() -- use default config -- OR require('mini.fuzzy').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniFuzzy.config* `MiniFuzzy.config` Defaults ~ >lua MiniFuzzy.config = { -- Maximum allowed value of match features (width and first match). All -- feature values greater than cutoff can be considered "equally bad". cutoff = 100, } < ------------------------------------------------------------------------------ *MiniFuzzy.match()* `MiniFuzzy.match`({word}, {candidate}) Compute match data Parameters ~ {word} `(string)` Input word (usually user input). {candidate} `(string)` Target word (usually with which matching is done). Return ~ `(table)` Matching information: - `(table|nil)` - array with letter indexes inside `candidate` which matched to corresponding letters in `word`. It is empty array if `word` is empty string and `nil` if no match. - `number` - positive number representing how good the match is (lower is better). It is `-1` if no match or word is empty string. ------------------------------------------------------------------------------ *MiniFuzzy.filtersort()* `MiniFuzzy.filtersort`({word}, {candidate_array}) Filter string array - Keep only input elements which match `word`. - Sort from best to worst matches (based on score and index in original array, both lower is better). Parameters ~ {word} `(string)` String which will be searched. {candidate_array} `(table)` Lua array of strings inside which word will be searched. Return ~ `(...)` Arrays of matched candidates and their indexes in original input. ------------------------------------------------------------------------------ *MiniFuzzy.process_lsp_items()* `MiniFuzzy.process_lsp_items`({items}, {base}) Fuzzy matching for `lsp_completion.process_items` of |MiniCompletion.config| Parameters ~ {items} `(table)` Array with LSP 'textDocument/completion' response items. {base} `(string)` Word to complete. Return ~ `(table)` Array of items with text (`filterText` or `label`) fuzzy matching `base`. ------------------------------------------------------------------------------ *MiniFuzzy.get_telescope_sorter()* `MiniFuzzy.get_telescope_sorter`({opts}) Custom getter for `telescope.nvim` sorter Designed as a value for file and generic sorter of 'telescope.nvim'. Parameters ~ {opts} `(table|nil)` Options (currently not used). Usage ~ >lua require('telescope').setup({ defaults = { generic_sorter = require('mini.fuzzy').get_telescope_sorter } }) < vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-git.txt ================================================ *mini.git* Git integration MIT License Copyright (c) 2024 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniGit* Features: - Automated tracking of Git related data: root path, status, HEAD, etc. Exposes buffer-local variables for convenient use in statusline. See |MiniGit.enable()| and |MiniGit.get_buf_data()| for more information. - |:Git| command for executing any `git` call inside file's repository root with deeper current instance integration (show output as notification/buffer, use to edit commit messages, etc.). - Helper functions to inspect Git history: - |MiniGit.show_range_history()| shows how certain line range evolved. - |MiniGit.show_diff_source()| shows file state as it was at diff entry. - |MiniGit.show_at_cursor()| shows Git related data depending on context. What it doesn't do: - Replace fully featured Git client. Rule of thumb: if feature does not rely on a state of current Neovim (opened buffers, etc.), it is out of scope. For more functionality, use either |mini.diff| or fully featured Git client. Sources with more details: - |:Git| - |MiniGit-examples| - |MiniGit.enable()| - |MiniGit.get_buf_data()| # Setup ~ This module needs a setup with `require('mini.git').setup({})` (replace `{}` with your `config` table). It will create global Lua table `MiniGit` which you can use for scripting or manually (with `:lua MiniGit.*`). See |MiniGit.config| for `config` structure and default values. # Comparisons ~ - [tpope/vim-fugitive](https://github.com/tpope/vim-fugitive): - Mostly a dedicated Git client, while this module is not (by design). - Provides buffer-local Git data only through fixed statusline component, while this module has richer data in the form of a Lua table. - Both provide |:Git| command with 'vim-fugitive' treating some cases extra specially (like `:Git blame`, etc.), while this module mostly treats all cases the same. See |MiniGit-examples| for how they can be manually customized. Also this module provides slightly different (usually richer) completion suggestions. - [NeogitOrg/neogit](https://github.com/NeogitOrg/neogit): - Similar to 'tpope/vim-fugitive', but without `:Git` command. - [lewis6991/gitsigns.nvim](https://github.com/lewis6991/gitsigns.nvim): - Provides buffer-local Git data with emphasis on granular diff status, while this module is more oriented towards repository and file level data (root, HEAD, file status, etc.). Use |mini.diff| for diff tracking. # Disabling ~ To prevent buffer(s) from being tracked, set `vim.g.minigit_disable` (globally) or `vim.b.minigit_disable` (for a buffer) to `true`. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniGit-examples* # Statusline component ~ Tracked buffer data can be used in statusline via `vim.b.minigit_summary_string` buffer-local variable. It is expected to be used as is. To show another info, tweak buffer-local variable directly inside `MiniGitUpdated` `User` event: >lua -- Use only HEAD name as summary string local format_summary = function(data) -- Utilize buffer-local table summary local summary = vim.b[data.buf].minigit_summary vim.b[data.buf].minigit_summary_string = summary.head_name or '' end local au_opts = { pattern = 'MiniGitUpdated', callback = format_summary } vim.api.nvim_create_autocmd('User', au_opts) < # Tweaking command output ~ Buffer output of |:Git| command can be tweaked inside autocommand for `MiniGitCommandSplit` `User` event (see |MiniGit-command-events|). For example, to make `:vertical Git blame -- %` align blame output with the current window state, use the following code: >lua local align_blame = function(au_data) if au_data.data.git_subcommand ~= 'blame' then return end -- Align blame output with source local win_src = au_data.data.win_source vim.wo.wrap = false vim.fn.winrestview({ topline = vim.fn.line('w0', win_src) }) vim.api.nvim_win_set_cursor(0, { vim.fn.line('.', win_src), 0 }) -- Bind both windows so that they scroll together vim.wo[win_src].scrollbind, vim.wo.scrollbind = true, true end local au_opts = { pattern = 'MiniGitCommandSplit', callback = align_blame } vim.api.nvim_create_autocmd('User', au_opts) < # History navigation ~ Function |MiniGit.show_at_cursor()| is specifically exported to make Git history navigation easier. Here are some different ways it can be used: - Call inside buffer for already committed file to show the evolution of the current line (or visually selected range) through history. It is essentially a `:Git log HEAD` with proper `-L` flag. This also works inside output of |MiniGit.show_diff_source()|. - Call with cursor on commit hash to inspect that commit in full. This is usually helpful in the output of `:Git log`. - Call with cursor inside diff entry to inspect its file in the state how it was at certain commit. By default it shows state after commit, unless cursor is on the "deleted" line (i.e. line starting with "-") in which case state before commit is shown. This workflow can be made more interactive when used with mapping, like this: >lua local rhs = 'lua MiniGit.show_at_cursor()' vim.keymap.set({ 'n', 'x' }, 'gs', rhs, { desc = 'Show at cursor' }) < ------------------------------------------------------------------------------ *:Git* The `:Git` user command runs `git` CLI call with extra integration for currently opened Neovim process: - Command is executed inside repository root of the currently active file (or |current-directory| if file is not tracked by this module). - Command output is shown either in dedicated buffer in window split or as notification via |vim.notify()|. Which method is used depends on whether particular Git subcommand is supposed to show data for user to inspect (like `log`, `status`, etc.) or not (like `commit`, `push`, etc.). This is determined automatically based on the data Git itself provides. Split window is made current after command execution. Use split-related |:command-modifiers| (|:vertical|, |:horizontal|, or |:tab|) to force output in a particular type of split. Default split direction is controlled by `command.split` in |MiniGit.config|. Use |:silent| command modifier to not show any output. Errors and warnings are always shown as notifications. See |MiniGit-examples| for the example of tweaking command output. - Editor for tasks that require interactive user input (like `:Git commit` or `:Git rebase --interactive`) is opened inside current session in a separate split. Make modifications as in regular buffer, |:write| changes followed by |:close| / |:quit| for Git CLI command to resume. Examples of usage: - `:Git log --oneline` - show compact log of current repository. - `:vert Git blame -- %` - show latest commits per line in vertical split. - `:Git help rebase` - show help page for `rebase` subcommand. - `:Git -C status` - execute `git status` inside |current-directory|. There is also a context aware completion which can be invoked with ``: - If completed word starts with "-", options for the current Git subcommand are shown. Like completion at `:Git log -` will suggest `-L`, `--oneline`, etc. - If there is an explicit " -- " to the cursor's left, incremental path suggestions will be shown. - If there is no recognized Git subcommand yet, show list of subcommands. Otherwise for some common subcommands list of its targets will be suggested: like for `:Git branch` it will be list of branches, etc. Notes: - Paths are always treated as relative to command's execution directory (file's repository root or |current-directory| if absent). - Don't use quotes for entries containing space, escape it with `\` directly. Like `:Git commit -m Hello\ world` and not `:Git commit -m 'Hello world'` (which treats `'Hello` and `world'` as separate arguments). # Events ~ *MiniGit-command-events* There are several `User` events triggered during command execution: - `MiniGitCommandDone` - after command is done executing. For Lua callbacks it provides a special `data` table with the following fields: - `(table)` - structured data about executed command. Has same structure as Lua function input in |nvim_create_user_command()|. - `(string)` - directory path inside which Git command was executed. - `(number)` - exit code of CLI process. - `(table)` - array with arguments of full executed command. - `(string)` - detected Git subcommand (like "log", etc.). - `(string)` - `stderr` process output. - `(string)` - `stdout` process output. - `MiniGitCommandSplit` - after command showed its output in a split. Triggered after `MiniGitCommandDone` and provides similar `data` table with extra fields: - `(number)` - window identifier of "source" window (current at the moment before command execution). - `(number)` - window identifier of command output. ------------------------------------------------------------------------------ *MiniGit.setup()* `MiniGit.setup`({config}) Module setup Besides general side effects (see |mini.nvim|), it also: - Sets up auto enabling in every normal buffer for an actual file on disk. - Creates |:Git| command. Parameters ~ {config} `(table|nil)` Module config table. See |MiniGit.config|. Usage ~ >lua require('mini.git').setup() -- use default config -- OR require('mini.git').setup({}) -- replace {} with your config table < ------------------------------------------------------------------------------ *MiniGit.config* `MiniGit.config` Defaults ~ >lua MiniGit.config = { -- General CLI execution job = { -- Path to Git executable git_executable = 'git', -- Timeout (in ms) for each job before force quit timeout = 30000, }, -- Options for `:Git` command command = { -- Default split direction split = 'auto', }, } < # Job ~ `config.job` contains options for customizing CLI executions. `job.git_executable` defines a full path to Git executable. Default: "git". `job.timeout` is a duration (in ms) from job start until it is forced to stop. Default: 30000. # Command ~ `config.command` contains options for customizing |:Git| command. `command.split` defines default split direction for |:Git| command output. Can be one of "horizontal", "vertical", "tab", or "auto". Value "auto" uses |:vertical| if only 'mini.git' buffers are shown in the tabpage and |:tab| otherwise. Default: "auto". ------------------------------------------------------------------------------ *MiniGit.show_at_cursor()* `MiniGit.show_at_cursor`({opts}) Show Git related data at cursor - If inside |mini.deps| confirmation buffer, show in split relevant commit data. - If there is a commit-like ||, show it in split. - If possible, show diff source via |MiniGit.show_diff_source()|. - If possible, show range history via |MiniGit.show_range_history()|. - Otherwise throw an error. Parameters ~ {opts} `(table|nil)` Options. Possible values: - `(string)` - split direction. One of "horizontal", "vertical", "tab", or "auto" (default). Value "auto" uses |:vertical| if only 'mini.git' buffers are shown in the tabpage and |:tab| otherwise. - Fields appropriate for forwarding to other functions. ------------------------------------------------------------------------------ *MiniGit.show_diff_source()* `MiniGit.show_diff_source`({opts}) Show diff source When buffer contains text formatted as unified patch (like after `:Git log --patch`, `:Git diff`, or |MiniGit.show_range_history()|), show state of the file at the particular state. Target commit/state, path, and line number are deduced from cursor position. Notes: - Needs |current-directory| to be the Git root for relative paths to work. - Needs cursor to be inside hunk lines or on "---" / "+++" lines with paths. - Only basic forms of `:Git diff` output is supported: `:Git diff`, `:Git diff --cached`, and `:Git diff `. Parameters ~ {opts} `(table|nil)` Options. Possible values: - `(string)` - split direction. One of "horizontal", "vertical", "tab", or "auto" (default). Value "auto" uses |:vertical| if only 'mini.git' buffers are shown in the tabpage and |:tab| otherwise. - `(string)` - which file state to show. One of "before", "after", "both" (both states in vertical split), "auto" (default). Value "auto" shows "before" state if cursor line starts with "-", otherwise - "after". ------------------------------------------------------------------------------ *MiniGit.show_range_history()* `MiniGit.show_range_history`({opts}) Show range history Compute and show in split data about how particular line range in current buffer evolved through Git history. Essentially a `git log` with `-L` flag. Notes: - Works well with |MiniGit.diff_foldexpr()|. - Does not work if there are uncommited changes, as there is no easy way to compute effective range line numbers. Parameters ~ {opts} `(table|nil)` Options. Possible fields: - `(number)` - range start line. - `(number)` - range end line. If both and are not supplied, they default to current line in Normal mode and visual selection in Visual mode. - `(table)` - array of options to append to `git log` call. - `(string)` - split direction. One of "horizontal", "vertical", "tab", or "auto" (default). Value "auto" uses |:vertical| if only 'mini.git' buffers are shown in the tabpage and |:tab| otherwise. ------------------------------------------------------------------------------ *MiniGit.diff_foldexpr()* `MiniGit.diff_foldexpr`({lnum}) Fold expression for Git logs Folds contents of hunks, file patches, and log entries in unified diff. Useful for filetypes "diff" (like after `:Git diff`) and "git" (like after `:Git log --patch` or `:Git show` for commit). Works well with |MiniGit.show_range_history()|. General idea of folding levels (use |zr| and |zm| to adjust interactively): - At level 0 there is one line per whole patch or log entry. - At level 1 there is one line per patched file. - At level 2 there is one line per hunk. - At level 3 there is no folds. For automated setup, set the following for "git" and "diff" filetypes (either inside |FileType| autocommand or |ftplugin|): >vim setlocal foldmethod=expr foldexpr=v:lua.MiniGit.diff_foldexpr() < Parameters ~ {lnum} `(number|nil)` Line number for which fold level is computed. Default: |v:lnum|. Return ~ `(number|string)` Line fold level. See |fold-expr|. ------------------------------------------------------------------------------ *MiniGit.enable()* `MiniGit.enable`({buf_id}) Enable Git tracking in a file buffer Tracking is done by reacting to changes in file content or file's repository in the form of keeping buffer data up to date. The data can be used via: - |MiniGit.get_buf_data()|. See its help for a list of actually tracked data. - `vim.b.minigit_summary` (table) and `vim.b.minigit_summary_string` (string) buffer-local variables which are more suitable for statusline. `vim.b.minigit_summary_string` contains information about HEAD, file status, and in progress action (see |MiniGit.get_buf_data()| for more details). See |MiniGit-examples| for how it can be tweaked and used in statusline. Note: this function is called automatically for all new normal buffers. Use it explicitly if buffer was disabled. `User` event `MiniGitUpdated` is triggered whenever tracking data is updated. Note that not all data listed in |MiniGit.get_buf_data()| can be present (yet) at the point of event being triggered. Parameters ~ {buf_id} `(number)` Target buffer identifier. Default: 0 for current buffer. ------------------------------------------------------------------------------ *MiniGit.disable()* `MiniGit.disable`({buf_id}) Disable Git tracking in buffer Parameters ~ {buf_id} `(number)` Target buffer identifier. Default: 0 for current buffer. ------------------------------------------------------------------------------ *MiniGit.toggle()* `MiniGit.toggle`({buf_id}) Toggle Git tracking in buffer Enable if disabled, disable if enabled. Parameters ~ {buf_id} `(number)` Target buffer identifier. Default: 0 for current buffer. ------------------------------------------------------------------------------ *MiniGit.get_buf_data()* `MiniGit.get_buf_data`({buf_id}) Get buffer data Parameters ~ {buf_id} `(number)` Target buffer identifier. Default: 0 for current buffer. Return ~ `(table|nil)` Table with buffer Git data or `nil` if buffer is not enabled. If the file is not part of Git repo, table will be empty. Table has the following fields: - `(string)` - full path to '.git' directory. - `(string)` - full path to worktree root. - `(string)` - full commit of current HEAD. - `(string)` - short name of current HEAD (like "master"). For detached HEAD it is "HEAD". - `(string)` - two character file status as returned by `git status`. - `(string)` - name of action(s) currently in progress (bisect, merge, etc.). Can be a combination of those separated by ",". vim:tw=78:ts=8:noet:ft=help:norl: ================================================ FILE: doc/mini-hipatterns.txt ================================================ *mini.hipatterns* Highlight patterns in text MIT License Copyright (c) 2023 Evgeni Chasnovski ------------------------------------------------------------------------------ *MiniHipatterns* Features: - Highlight text with configurable patterns and highlight groups (can be string or callable). - Highlighting is updated asynchronously with configurable debounce delay. - Function to get matches in a buffer (see |MiniHipatterns.get_matches()|). See |MiniHipatterns-examples| for common configuration examples. Notes: - It does not define any highlighters by default. Add to `config.highlighters` to have a visible effect. - Sometimes (especially during frequent buffer updates on same line numbers) highlighting can be outdated or not applied when it should be. This is due to asynchronous nature of updates reacting to text changes (via `on_lines` of |nvim_buf_attach()|). To make them up to date, use one of the following: - Scroll window (for example, with |CTRL-E| / |CTRL-Y|). This will ensure up to date highlighting inside window view. - Hide and show buffer. - Execute `:edit` (if you enabled highlighting with |MiniHipatterns.setup()|). - Manually call |MiniHipatterns.update()|. - If you experience flicker when typing near highlighted pattern in Insert mode, it might be due to `delay` configuration of |mini.completion| or using built-in completion. For better experience with 'mini.completion', make sure that its `delay.completion` is less than this module's `delay.text_change` (which it is by default). The reason for this is (currently unresolvable) limitations of Neovim's built-in completion implementation. # Setup ~ Setting up highlights can be done in two ways: - Manually for every buffer with `require('mini.hipatterns').enable()`. This will enable highlighting only in one particular buffer until it is unloaded (which also includes calling `:edit` on current file). - Globally with `require('mini.hipatterns').setup({})` (replace `{}` with your `config` table). This will auto-enable highlighting in "normal" buffers (see 'buftype'). Use |MiniHipatterns.enable()| to manually enable in other buffers. It will also create global Lua table `MiniHipatterns` which you can use for scripting or manually (with `:lua MiniHipatterns.*`). See |MiniHipatterns.config| for `config` structure and default values. You can override runtime config settings (like highlighters and delays) locally to buffer inside `vim.b.minihipatterns_config` which should have same structure as `MiniHipatterns.config`. See |mini.nvim-buffer-local-config| for more details. # Comparisons ~ - [folke/todo-comments](https://github.com/folke/todo-comments): - Oriented for "TODO", "NOTE", "FIXME" like patterns, while this module can work with any Lua patterns and computable highlight groups. - Has functionality beyond text highlighting (sign placing, "telescope.nvim" extension, etc.), while this module only focuses on highlighting text. - [folke/paint.nvim](https://github.com/folke/paint.nvim): - Mostly similar to this module, but with slightly less functionality, such as computed pattern and highlight group, asynchronous delay, etc. - [NvChad/nvim-colorizer.lua](https://github.com/NvChad/nvim-colorizer.lua): - Oriented for color highlighting, while this module can work with any Lua patterns and computable highlight groups. - Has more built-in color spaces to highlight, while this module out of the box provides only hex color highlighting (see |MiniHipatterns.gen_highlighter.hex_color()|). Other types are also possible to implement. - [uga-rosa/ccc.nvim](https://github.com/uga-rosa/ccc.nvim): - Has more than color highlighting functionality, which is compared to this module in the same way as 'NvChad/nvim-colorizer.lua'. # Highlight groups ~ - `MiniHipatternsFixme` - suggested group to use for `FIXME`-like patterns. - `MiniHipatternsHack` - suggested group to use for `HACK`-like patterns. - `MiniHipatternsTodo` - suggested group to use for `TODO`-like patterns. - `MiniHipatternsNote` - suggested group to use for `NOTE`-like patterns. To change any highlight group, set it directly with |nvim_set_hl()|. # Disabling ~ This module can be disabled in three ways: - Globally: set `vim.g.minihipatterns_disable` to `true`. - Locally for buffer permanently: set `vim.b.minihipatterns_disable` to `true`. - Locally for buffer temporarily (until next auto-enabling event if set up with |MiniHipatterns.setup()|): call |MiniHipatterns.disable()|. Considering high number of different scenarios and customization intentions, writing exact rules for disabling module's functionality is left to user. See |mini.nvim-disabling-recipes| for common recipes. ------------------------------------------------------------------------------ *MiniHipatterns-examples* # Common configuration examples ~ - Special words used to convey different level of attention: >lua require('mini.hipatterns').setup({ highlighters = { fixme = { pattern = 'FIXME', group = 'MiniHipatternsFixme' }, hack = { pattern = 'HACK', group = 'MiniHipatternsHack' }, todo = { pattern = 'TODO', group = 'MiniHipatternsTodo' }, note = { pattern = 'NOTE', group = 'MiniHipatternsNote' }, } }) < - To match only when pattern appears as a standalone word, use frontier patterns `%f`. For example, instead of `'TODO'` pattern use `'%f[%w]()TODO()%f[%W]'`. In this case, for example, 'TODOING' or 'MYTODO' won't match, but 'TODO' and 'TODO:' will. - Color hex (like `#rrggbb`) highlighting: >lua local hipatterns = require('mini.hipatterns') hipatterns.setup({ highlighters = { hex_color = hipatterns.gen_highlighter.hex_color(), } }) < You can customize which part of hex color is highlighted by using `style` field of input options. See |MiniHipatterns.gen_highlighter.hex_color()|. - Colored words: >lua local words = { red = '#ff0000', green = '#00ff00', blue = '#0000ff' } local word_color_group = function(_, match) local hex = words[match] if hex == nil then return nil end return MiniHipatterns.compute_hex_color_group(hex, 'bg') end local hipatterns = require('mini.hipatterns') hipatterns.setup({ highlighters = { word_color = { pattern = '%S+', group = word_color_group }, }, }) < - Trailing whitespace (if don't want to use more specific |mini.trailspace|): >lua { pattern = '%f[%s]%s*$', group = 'Error' } < - Censor certain sensitive information: >lua local censor_extmark_opts = function(_, match, _) local mask = string.rep('x', vim.fn.strchars(match)) return { virt_text = { { mask, 'Comment' } }, virt_text_pos = 'overlay', priority = 200, right_gravity = false, } end require('mini.hipatterns').setup({ highlighters = { censor = { pattern = 'password: ()%S+()', group = '', extmark_opts = censor_extmark_opts, }, }, }) < - Enable only in certain filetypes. There are at least these ways to do it: - (Suggested) With `vim.b.minihipatterns_config` in |filetype-plugin|. Basically, create "after/ftplugin/.lua" file in your config directory (see |$XDG_CONFIG_HOME|) and define `vim.b.minihipatterns_config` there with filetype specific highlighters. This assumes `require('mini.hipatterns').setup()` call. For example, to highlight keywords in EmmyLua comments in Lua files, create "after/ftplugin/lua.lua" with the following content: >lua vim.b.minihipatterns_config = { highlighters = { emmylua = { pattern = '^%s*%-%-%-()@%w+()', group = 'Special' } } } < - Use callable `pattern` with condition. For example: >lua require('mini.hipatterns').setup({ highlighters = { emmylua = { pattern = function(buf_id) if vim.bo[buf_id].filetype ~= 'lua' then return nil end return '^%s*%-%-%-()@%w+()' end, group = 'Special', }, }, }) < - Disable only in certain filetypes. Enable with |MiniHipatterns.setup()| and set `vim.b.minihipatterns_disable` buffer-local variable to `true` for buffer you want disabled. See |mini.nvim-disabling-recipes| for more examples. ------------------------------------------------------------------------------ *MiniHipatterns.setup()* `MiniHipatterns.setup`({config}) Module setup Parameters ~ {config} `(table|nil)` Module config table. See |MiniHipatterns.config|. Usage ~ >lua require('mini.hipatterns').setup({}) -- replace {} with your config table -- needs `highlighters` field present < ------------------------------------------------------------------------------ *MiniHipatterns.config* `MiniHipatterns.config` Defaults ~ >lua MiniHipatterns.config = { -- Table with highlighters (see |MiniHipatterns.config| for more details). -- Nothing is defined by default. Add manually for visible effect. highlighters = {}, -- Delays (in ms) defining asynchronous highlighting process delay = { -- How much to wait for update after every text change text_change = 200, -- How much to wait for update after window scroll scroll = 50, }, } < # Highlighters ~ `highlighters` table defines which patterns will be highlighted by placing |extmark| at the match start. It might or might not have explicitly named fields, but having them is recommended and is required for proper use of `vim.b.minihipatterns_config` as buffer-local config. By default it is empty expecting user definition. Each entry defines single highlighter as a table with the following fields: - `(string|function|table)` - Lua pattern to highlight. Can be either string, callable returning the string, or an array of those. If string: - It can have submatch delimited by placing `()` on start and end, NOT by surrounding it with parenthesis (results in an error containing `number expected, got string`). Example: `xx()abcd()xx` will match `abcd` only if `xx` is placed before and after it. If callable: - It will be called for every enabled buffer with its identifier as input. Should return single string pattern or `nil` (meaning this particular highlighter will not work in this particular buffer). If array: - Each element is matched and highlighted with the same highlight group. Note: matching does not result in overlapping (sub)matches (similarly to how |cpo-c| works). For example, with line `xxxxxxx`: - Pattern `xxx` matches columns 1-3, 4-6. - Pattern `()xx()x` matches columns 1-2, 3-4, 5-6. - Pattern `x()xx()` matches columns 2-3, 5-6. - Pattern `x()x()x` matches columns 2-2, 4-4, 6-6. - `(string|function)` - name of highlight group to use. Can be either string or callable returning the string. If callable: - It will be called for every pattern match with the following arguments: - `buf_id` - buffer identifier. - `match` - string pattern match to be highlighted. - `data` - extra table with information about the match. It has at least these fields: - - string with full pattern match. - - match line number (1-indexed). - - match starting byte column (1-indexed). - - match ending byte column (1-indexed, inclusive). - It can return `nil` meaning this particular match will not be highlighted. - `(table|function|nil)` - optional extra options for |nvim_buf_set_extmark()|. If callable, will be called in the same way as callable (`data` will also contain `hl_group` key with value) and should return a table with all options for extmark (including `end_row`, `end_col`, `hl_group`, and `priority`). See "Common use cases" section for the examples. # Delay ~ `delay` is a table defining delays in milliseconds used for asynchronous highlighting process. `delay.text_change` is used to delay highlighting updates by accumulating them (in debounce fashion). Smaller values will lead to faster response but more frequent updates. Bigger - slower response but less frequent updates. `delay.scroll` is used to delay updating highlights in current window view during scrolling (see |WinScrolled| event). These updates are present to ensure up to date highlighting after scroll. ------------------------------------------------------------------------------ *MiniHipatterns.enable()* `MiniHipatterns.enable`({buf_id}, {config}) Enable highlighting in buffer Notes: - With default config it will highlight nothing, as there are no default highlighters. - Buffer highlighting is enabled until buffer is unloaded from memory or |MiniHipatterns.disable()| on this buffer is called. - `:edit` disables this, as it is mostly equivalent to closing and opening buffer. In order for highlighting to persist after `:edit`, call |MiniHipatterns.setup()|. Parameters ~ {buf_id} `(number|nil)` Buffer identifier in which to enable highlighting. Default: 0 for current buffer. {config} `(table|nil)` Optional buffer-local config. Should have the same structure as |MiniHipatterns.config|. Values will be taken in this order: - From this `config` argument (if supplied). - From buffer-local config in `vim.b.minihipatterns_config` (if present). - From global config (if |MiniHipatterns.setup()| was called). - From default values. ------------------------------------------------------------------------------ *MiniHipatterns.disable()* `MiniHipatterns.disable`({buf_id}) Disable highlighting in buffer Note that if |MiniHipatterns.setup()| was called, the effect is present until the next auto-enabling event. To permanently disable highlighting in buffer, set `vim.b.minihipatterns_disable` to `true` Parameters ~ {buf_id} `(number|nil)` Buffer identifier in which to enable highlighting. Default: 0 for current buffer. ------------------------------------------------------------------------------ *MiniHipatterns.toggle()* `MiniHipatterns.toggle`({buf_id}, {config}) Toggle highlighting in buffer Call |MiniHipatterns.disable()| if enabled; |MiniHipatterns.enable()| otherwise. Parameters ~ {buf_id} `(number|nil)` Buffer identifier in which to enable highlighting. Default: 0 for current buffer. {config} `(table|nil)` Forwarded to |MiniHipatterns.enable()|. ------------------------------------------------------------------------------ *MiniHipatterns.update()* `MiniHipatterns.update`({buf_id}, {from_line}, {to_line}) Update highlighting in range Works only in buffer with enabled highlighting. Effect takes immediately without delay. Parameters ~ {buf_id} `(number|nil)` Buffer identifier in which to enable highlighting. Default: 0 for current buffer. {from_line} `(number|nil)` Start line from which to update (1-indexed). {to_line} `(number|nil)` End line from which to update (1-indexed, inclusive). ------------------------------------------------------------------------------ *MiniHipatterns.get_enabled_buffers()* `MiniHipatterns.get_enabled_buffers`() Get an array of enabled buffers Return ~ `(table)` Array of buffer identifiers with enabled highlighting. ------------------------------------------------------------------------------ *MiniHipatterns.get_matches()* `MiniHipatterns.get_matches`({buf_id}, {highlighters}) Get buffer matches Parameters ~ {buf_id} `(number|nil)` Buffer identifier for which to return matches. Default: `nil` for current buffer. {highlighters} `(table|nil)` Array of highlighter identifiers (as in `highlighters` field of |MiniHipatterns.config|) for which to return matches. Default: all available highlighters (ordered by string representation). Return ~ `(table)` Array of buffer matches which are tables with following fields: - `(number)` - buffer identifier of a match. - `(any)` - highlighter identifier which produced the match. - `(number)` - line number of the match start (starts with 1). - `(number)` - column number of the match start (starts with 1). - `(number|nil)` - line number of the match end (starts with 1). - `(number|nil)` - column number next to the match end (implements end-exclusive region; starts with 1). - `(string|nil)` - name of match's highlight group. Matches are ordered first by supplied `highlighters`, then by line and column of match start. ------------------------------------------------------------------------------ *MiniHipatterns.gen_highlighter* `MiniHipatterns.gen_highlighter` Generate builtin highlighters This is a table with function elements. Call to actually get highlighter. ------------------------------------------------------------------------------ *MiniHipatterns.gen_highlighter.hex_color()* `MiniHipatterns.gen_highlighter.hex_color`({opts}) Highlight hex color string This will match color hex string in format `#rrggbb` and highlight it according to `opts.style` displaying matched color. Highlight group is computed using |MiniHipatterns.compute_hex_color_group()|, so all its usage notes apply here. Parameters ~ {opts} `(table|nil)` Options. Possible fields: -