pax_global_header00006660000000000000000000000064147563552060014527gustar00rootroot0000000000000052 comment=fcbf4eea17cb299c02557d576f0d568878e354a4 folke-which-key.nvim-fcbf4ee/000077500000000000000000000000001475635520600163255ustar00rootroot00000000000000folke-which-key.nvim-fcbf4ee/.editorconfig000066400000000000000000000001421475635520600207770ustar00rootroot00000000000000root = true [*] insert_final_newline = true indent_style = space indent_size = 2 charset = utf-8 folke-which-key.nvim-fcbf4ee/.github/000077500000000000000000000000001475635520600176655ustar00rootroot00000000000000folke-which-key.nvim-fcbf4ee/.github/.release-please-manifest.json000066400000000000000000000000241475635520600253250ustar00rootroot00000000000000{ ".": "3.17.0" } folke-which-key.nvim-fcbf4ee/.github/ISSUE_TEMPLATE/000077500000000000000000000000001475635520600220505ustar00rootroot00000000000000folke-which-key.nvim-fcbf4ee/.github/ISSUE_TEMPLATE/bug_report.yml000066400000000000000000000055111475635520600247450ustar00rootroot00000000000000name: Bug Report description: File a bug/issue title: "bug: " labels: [bug] body: - type: markdown attributes: value: | **Before** reporting an issue, make sure to read the [documentation](https://github.com/folke/which-key.nvim) and search [existing issues](https://github.com/folke/which-key.nvim/issues). Usage questions such as ***"How do I...?"*** belong in [Discussions](https://github.com/folke/which-key.nvim/discussions) and will be closed. - type: checkboxes attributes: label: Did you check docs and existing issues? description: Make sure you checked all of the below before submitting an issue options: - label: I have read all the which-key.nvim docs required: true - label: I have updated the plugin to the latest version before submitting this issue required: true - label: I have searched the existing issues of which-key.nvim required: true - label: I have searched the existing issues of plugins related to this issue required: true - type: input attributes: label: "Neovim version (nvim -v)" placeholder: "0.8.0 commit db1b0ee3b30f" validations: required: true - type: input attributes: label: "Operating system/version" placeholder: "MacOS 11.5" validations: required: true - type: textarea attributes: label: Describe the bug description: A clear and concise description of what the bug is. Please include any related errors you see in Neovim. validations: required: true - type: textarea attributes: label: Steps To Reproduce description: Steps to reproduce the behavior. placeholder: | 1. 2. 3. validations: required: true - type: textarea attributes: label: Expected Behavior description: A concise description of what you expected to happen. validations: required: true - type: textarea attributes: label: Health description: Attach the output of `:checkhealth which-key` here render: log - type: textarea attributes: label: Log description: Please enable logging with `opts.debug = true` and attach the contents of `./wk.log` here render: log - type: textarea attributes: label: Repro description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua` value: | vim.env.LAZY_STDPATH = ".repro" load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))() require("lazy.minit").repro({ spec = { { "folke/which-key.nvim", opts = {} }, -- add any other plugins here }, }) render: lua validations: required: false folke-which-key.nvim-fcbf4ee/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000002531475635520600240400ustar00rootroot00000000000000blank_issues_enabled: false contact_links: - name: Ask a question url: https://github.com/folke/which-key.nvim/discussions about: Use Github discussions instead folke-which-key.nvim-fcbf4ee/.github/ISSUE_TEMPLATE/feature_request.yml000066400000000000000000000023441475635520600260010ustar00rootroot00000000000000name: Feature Request description: Suggest a new feature title: "feature: " labels: [enhancement] body: - type: checkboxes attributes: label: Did you check the docs? description: Make sure you read all the docs before submitting a feature request options: - label: I have read all the which-key.nvim docs required: true - type: textarea validations: required: true attributes: label: Is your feature request related to a problem? Please describe. description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - type: textarea validations: required: true attributes: label: Describe the solution you'd like description: A clear and concise description of what you want to happen. - type: textarea validations: required: true attributes: label: Describe alternatives you've considered description: A clear and concise description of any alternative solutions or features you've considered. - type: textarea validations: required: false attributes: label: Additional context description: Add any other context or screenshots about the feature request here. folke-which-key.nvim-fcbf4ee/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000005161475635520600234700ustar00rootroot00000000000000## Description ## Related Issue(s) ## Screenshots folke-which-key.nvim-fcbf4ee/.github/dependabot.yml000066400000000000000000000001661475635520600225200ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" folke-which-key.nvim-fcbf4ee/.github/release-please-config.json000066400000000000000000000003401475635520600247070ustar00rootroot00000000000000{ "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", "packages": { ".": { "release-type": "simple", "extra-files": ["lua/which-key/config.lua"] } } } folke-which-key.nvim-fcbf4ee/.github/workflows/000077500000000000000000000000001475635520600217225ustar00rootroot00000000000000folke-which-key.nvim-fcbf4ee/.github/workflows/ci.yml000066400000000000000000000003421475635520600230370ustar00rootroot00000000000000name: CI on: push: branches: [main, master] pull_request: jobs: ci: uses: folke/github/.github/workflows/ci.yml@main secrets: inherit with: plugin: which-key.nvim repo: folke/which-key.nvim folke-which-key.nvim-fcbf4ee/.github/workflows/labeler.yml000066400000000000000000000002201475635520600240450ustar00rootroot00000000000000name: "PR Labeler" on: - pull_request_target jobs: labeler: uses: folke/github/.github/workflows/labeler.yml@main secrets: inherit folke-which-key.nvim-fcbf4ee/.github/workflows/pr.yml000066400000000000000000000004231475635520600230650ustar00rootroot00000000000000name: PR Title on: pull_request_target: types: - opened - edited - synchronize - reopened - ready_for_review permissions: pull-requests: read jobs: pr-title: uses: folke/github/.github/workflows/pr.yml@main secrets: inherit folke-which-key.nvim-fcbf4ee/.github/workflows/stale.yml000066400000000000000000000003541475635520600235570ustar00rootroot00000000000000name: Stale Issues & PRs on: schedule: - cron: "30 1 * * *" jobs: stale: if: contains(fromJSON('["folke", "LazyVim"]'), github.repository_owner) uses: folke/github/.github/workflows/stale.yml@main secrets: inherit folke-which-key.nvim-fcbf4ee/.github/workflows/update.yml000066400000000000000000000004201475635520600237230ustar00rootroot00000000000000name: Update Repo on: workflow_dispatch: schedule: # Run every hour - cron: "0 * * * *" jobs: update: if: contains(fromJSON('["folke", "LazyVim"]'), github.repository_owner) uses: folke/github/.github/workflows/update.yml@main secrets: inherit folke-which-key.nvim-fcbf4ee/.gitignore000066400000000000000000000001061475635520600203120ustar00rootroot00000000000000*.log /.repro /.tests /build /debug /doc/tags foo.* node_modules tt.* folke-which-key.nvim-fcbf4ee/.lua-format000066400000000000000000000006011475635520600203720ustar00rootroot00000000000000# https://github.com/Koihik/LuaFormatter/blob/master/docs/Style-Config.md column_limit: 100 indent_width: 2 continuation_indent_width: 2 use_tab: false chop_down_parameter: true chop_down_table: true chop_down_kv_table: true single_quote_to_double_quote: true spaces_inside_table_braces: true align_parameter: true keep_simple_control_block_one_line: true extra_sep_at_table_end: true folke-which-key.nvim-fcbf4ee/.neoconf.json000066400000000000000000000004361475635520600207300ustar00rootroot00000000000000{ "lspconfig": { "sumneko_lua": { "Lua.format.defaultConfig": { "indent_style": "space", "indent_size": "2", "continuation_indent_size": "2" }, "Lua.diagnostics.neededFileStatus": { // "codestyle-check": "Any" } } } } folke-which-key.nvim-fcbf4ee/CHANGELOG.md000066400000000000000000002412321475635520600201420ustar00rootroot00000000000000# Changelog ## [3.17.0](https://github.com/folke/which-key.nvim/compare/v3.16.0...v3.17.0) (2025-02-14) ### Features * **mappings:** allow flagging a mapping as `real`. It will be hidden if there's no real keymap. ([bcfe1e4](https://github.com/folke/which-key.nvim/commit/bcfe1e4596dc0c6cc25a5b14b32f60a81d18c08d)) * **preset:** some extra win keymaps ([ff61f4f](https://github.com/folke/which-key.nvim/commit/ff61f4fe0d21de199c44a9d893395b5005e96270)) ## [3.16.0](https://github.com/folke/which-key.nvim/compare/v3.15.0...v3.16.0) (2025-01-05) ### Features * **icons:** add refactoring ([#923](https://github.com/folke/which-key.nvim/issues/923)) ([7b7e3d0](https://github.com/folke/which-key.nvim/commit/7b7e3d0788957592e12970bbb9e0e14c4cd143d4)) ### Bug Fixes * **mappings:** add missing keybinds for g; & g, ([#924](https://github.com/folke/which-key.nvim/issues/924)) ([57f4438](https://github.com/folke/which-key.nvim/commit/57f4438158e93be6856317e999758ed77f286dd9)) ## [3.15.0](https://github.com/folke/which-key.nvim/compare/v3.14.1...v3.15.0) (2024-12-15) ### Features * **icons:** icons for snacks and profiler ([d533d8a](https://github.com/folke/which-key.nvim/commit/d533d8a2e0da3444986500ecc2fb0528062d6003)) ### Bug Fixes * **config:** load early when executing WhichKey command. Fixes [#912](https://github.com/folke/which-key.nvim/issues/912) ([c890020](https://github.com/folke/which-key.nvim/commit/c8900201501ab6f0dcfabd55c70f6ba03ada3bd8)) ## [3.14.1](https://github.com/folke/which-key.nvim/compare/v3.14.0...v3.14.1) (2024-11-28) ### Bug Fixes * **state:** do proper redraw that works on nightly and on stable ([3a9b162](https://github.com/folke/which-key.nvim/commit/3a9b162026a4ad4b9ee7b09009b8bbe69ba19520)) ## [3.14.0](https://github.com/folke/which-key.nvim/compare/v3.13.3...v3.14.0) (2024-11-28) ### Features * **icons:** add grapple icon ([#838](https://github.com/folke/which-key.nvim/issues/838)) ([c21b71f](https://github.com/folke/which-key.nvim/commit/c21b71ff0bc4e516705811ec6916131e880cb882)) ### Bug Fixes * **state:** use redraw flush to prevent issues with selecting visual line etc. Fixes [#898](https://github.com/folke/which-key.nvim/issues/898) ([3974c2d](https://github.com/folke/which-key.nvim/commit/3974c2d21b117236ec4f5be4e61a9e4f02aa4c46)) * **triggers:** when in macro defer re-checking suspended for 100ms. Fixes [#864](https://github.com/folke/which-key.nvim/issues/864) ([f46556b](https://github.com/folke/which-key.nvim/commit/f46556b2b1bb7dbbd3b1086eaa24ca5db52b1986)) ### Performance Improvements * **state:** only redraw when waiting for a key longer than 200ms ([1c5aeba](https://github.com/folke/which-key.nvim/commit/1c5aeba42861a2cd446156ec8cbb7e7a5b5a9dfd)) * **tree:** small perf optims ([5610eb6](https://github.com/folke/which-key.nvim/commit/5610eb6bd7193e78d31eb399effacd2dfc25dedf)) ## [3.13.3](https://github.com/folke/which-key.nvim/compare/v3.13.2...v3.13.3) (2024-09-18) ### Bug Fixes * **config:** disable wk by default for terminal mode ([#825](https://github.com/folke/which-key.nvim/issues/825)) ([e7b415c](https://github.com/folke/which-key.nvim/commit/e7b415cc1d9ac9aee180ee5c8e46ca1484ebda78)) * **triggers:** never attach when macro is recording / executing. Fixes [#851](https://github.com/folke/which-key.nvim/issues/851). Fixes [#822](https://github.com/folke/which-key.nvim/issues/822). Fixes [#807](https://github.com/folke/which-key.nvim/issues/807) ([6b023b4](https://github.com/folke/which-key.nvim/commit/6b023b4c29ecc0aad06a51dd14bd2754b43bb0c8)) * **view:** display actual scroll up/down keys in help ([#821](https://github.com/folke/which-key.nvim/issues/821)) ([dafe27a](https://github.com/folke/which-key.nvim/commit/dafe27a06919bc5077db2ee97feec54d0932450e)) ## [3.13.2](https://github.com/folke/which-key.nvim/compare/v3.13.1...v3.13.2) (2024-07-24) ### Bug Fixes * **view:** fix epanded keys. Fixes [#795](https://github.com/folke/which-key.nvim/issues/795) ([f5e0cd5](https://github.com/folke/which-key.nvim/commit/f5e0cd5c7712ac63d8e6184785fb7bdac3b7b50d)) ## [3.13.1](https://github.com/folke/which-key.nvim/compare/v3.13.0...v3.13.1) (2024-07-24) ### Bug Fixes * **state:** better current buf/mode check ([711453b](https://github.com/folke/which-key.nvim/commit/711453bb945433362636e918a5238172ffd21e43)) * **state:** deal with the fact that ModeChanged doesn't always seems to trigger. Fixes [#787](https://github.com/folke/which-key.nvim/issues/787) ([388bd3f](https://github.com/folke/which-key.nvim/commit/388bd3f83de06d1a1758ea6a342cf3ae614401f1)) ## [3.13.0](https://github.com/folke/which-key.nvim/compare/v3.12.1...v3.13.0) (2024-07-24) ### Features * **debug:** add git info to log when using lazy ([550338d](https://github.com/folke/which-key.nvim/commit/550338dc292c014d83687afccb0afb06e3e769f2)) ## [3.12.1](https://github.com/folke/which-key.nvim/compare/v3.12.0...v3.12.1) (2024-07-24) ### Bug Fixes * **node:** dynamic mappings only support functions as rhs. Fixes [#790](https://github.com/folke/which-key.nvim/issues/790) ([ba91db7](https://github.com/folke/which-key.nvim/commit/ba91db72ffc745983f06ca4e7d969101287a9afe)) * **state:** use cached mode. Fixes [#787](https://github.com/folke/which-key.nvim/issues/787). Closes [#789](https://github.com/folke/which-key.nvim/issues/789) ([c1b062a](https://github.com/folke/which-key.nvim/commit/c1b062ae95c3ca3e6eb87c075da991523605d79b)) * **triggers:** check for existing keymaps in the correct buffer. Fixes [#783](https://github.com/folke/which-key.nvim/issues/783) ([977fa23](https://github.com/folke/which-key.nvim/commit/977fa23622425e3c8ae837b9f7c710d9c78bdeab)) * **triggers:** nil error ([dae3bd2](https://github.com/folke/which-key.nvim/commit/dae3bd271826887771a7fb6deec231d2eb344f02)) ## [3.12.0](https://github.com/folke/which-key.nvim/compare/v3.11.1...v3.12.0) (2024-07-22) ### Features * **api:** allow overriding delay. Closes [#778](https://github.com/folke/which-key.nvim/issues/778) ([e6fea48](https://github.com/folke/which-key.nvim/commit/e6fea4889c20f22a7c6267cf1f1d091bc96f8ca0)) ### Bug Fixes * dont expand nodes without children. Fixes [#782](https://github.com/folke/which-key.nvim/issues/782) ([53a1d2a](https://github.com/folke/which-key.nvim/commit/53a1d2a674df5fb667497fe3bbda625c39a2c0e1)) ## [3.11.1](https://github.com/folke/which-key.nvim/compare/v3.11.0...v3.11.1) (2024-07-21) ### Bug Fixes * **config:** keys can be any case. Fixes [#771](https://github.com/folke/which-key.nvim/issues/771) ([0a44d55](https://github.com/folke/which-key.nvim/commit/0a44d55d3bcdf75a134ec57c90aaec1055731014)) * **config:** normalize keys ([c96be9b](https://github.com/folke/which-key.nvim/commit/c96be9bd54ffbc2ec7fc818001cad712119d778c)) ## [3.11.0](https://github.com/folke/which-key.nvim/compare/v3.10.0...v3.11.0) (2024-07-20) ### Features * **icons:** icon for grug-far ([b2a2a0c](https://github.com/folke/which-key.nvim/commit/b2a2a0c9486211da23acdf18087f8203bfbca0e4)) * **state:** detect recursion by users mapping wk manually. Closes [#761](https://github.com/folke/which-key.nvim/issues/761) ([55fa07f](https://github.com/folke/which-key.nvim/commit/55fa07fbbd8a4c6d75399b1d1f9005d146cda22c)) * **view:** expand recursively. Closes [#767](https://github.com/folke/which-key.nvim/issues/767) ([5ae87af](https://github.com/folke/which-key.nvim/commit/5ae87af42914afe8b478ad6cdb3cb179fb73a62b)) ### Bug Fixes * **config:** disable wk by default for insert/command mode ([9d2b2e7](https://github.com/folke/which-key.nvim/commit/9d2b2e7059547c0481db2e93fd98547b26c7c05a)) * **config:** more checks in validate ([bdcc429](https://github.com/folke/which-key.nvim/commit/bdcc429afaecc5896b462b0b07c2b3a9e9c1c60f)) * **mappings:** preset descriptions should not override existing keymap descriptions. Fixes [#769](https://github.com/folke/which-key.nvim/issues/769) ([82d628f](https://github.com/folke/which-key.nvim/commit/82d628f4cfa397cf4bb233bd500e9cd9a018ded1)) * **state:** don't feed count in insert mode. Fixes [#770](https://github.com/folke/which-key.nvim/issues/770) ([63690ff](https://github.com/folke/which-key.nvim/commit/63690ff34a8921c2de44fad289e2e04ee324b031)) * **util:** better `<nop>` check. Fixes [#766](https://github.com/folke/which-key.nvim/issues/766) ([b7b3bd1](https://github.com/folke/which-key.nvim/commit/b7b3bd1b609524472f67e4a69d2bc14b80ea997f)) * **view:** dont set title when no border. Fixes [#764](https://github.com/folke/which-key.nvim/issues/764) ([6e61b09](https://github.com/folke/which-key.nvim/commit/6e61b0904e9c038b6c511c43591ae2d811b4975e)) ### Performance Improvements * prevent expanding nodes when not needed ([78cc92c](https://github.com/folke/which-key.nvim/commit/78cc92c6cb7da88df60227bc334a598a7e772e51)) ## [3.10.0](https://github.com/folke/which-key.nvim/compare/v3.9.0...v3.10.0) (2024-07-18) ### Features * **view:** expand all nodes by default when filter.global = false ([c168905](https://github.com/folke/which-key.nvim/commit/c168905d62d9b8859b261de69910dfb7e3438996)) ### Bug Fixes * **buf:** always use nowait. Fixes [#755](https://github.com/folke/which-key.nvim/issues/755) ([ae1a235](https://github.com/folke/which-key.nvim/commit/ae1a235c53233c58a2f7cc14e5cdd09346cf27ed)) * **buf:** early exit to determine if a trigger is safe to create. Fixes [#754](https://github.com/folke/which-key.nvim/issues/754) ([27e4716](https://github.com/folke/which-key.nvim/commit/27e47163165fee8e45b43d340db9335001403d2f)) * **icons:** added frontier pattern for `ai` ([#760](https://github.com/folke/which-key.nvim/issues/760)) ([6fe0657](https://github.com/folke/which-key.nvim/commit/6fe065716e08550328c471689e6f8c1e42a0effc)) * list_contains doesn't exists in Neovim < 0.10. Fixes [#758](https://github.com/folke/which-key.nvim/issues/758) ([7e4eae8](https://github.com/folke/which-key.nvim/commit/7e4eae8836e4ad28d478fedc421700b1138d1e0c)) * **node:** allow custom mappings to override proxy/plugin/expand mappings ([9820900](https://github.com/folke/which-key.nvim/commit/982090080fa11da06038cf8e71af90d3a4fbd05a)) * **node:** is_local check now also includes children ([fdd27f9](https://github.com/folke/which-key.nvim/commit/fdd27f9b6a991586943eb865275b279fb411ff0b)) * **registers:** don't try to get `+*` registers when no clipboard is available. Fixes [#754](https://github.com/folke/which-key.nvim/issues/754) ([ae4ec03](https://github.com/folke/which-key.nvim/commit/ae4ec030489d7ecda908e473aea096a7594f84e8)) * **state:** always honor defer. Fixes [#690](https://github.com/folke/which-key.nvim/issues/690) ([c512d13](https://github.com/folke/which-key.nvim/commit/c512d135531be81e17c85e254994cc755d3016c5)) * **state:** redraw cursor before getchar ([cf6cbf2](https://github.com/folke/which-key.nvim/commit/cf6cbf2fd8f0c6497f130d07f6c88a2833c15d80)) * **triggers:** prevent creating triggers for single upper-case alpha keys expect for Z. Fixes [#756](https://github.com/folke/which-key.nvim/issues/756) ([d19fa07](https://github.com/folke/which-key.nvim/commit/d19fa07b6e818ab55c34815784470a6d5f023524)) ## [3.9.0](https://github.com/folke/which-key.nvim/compare/v3.8.0...v3.9.0) (2024-07-18) ### Features * **config:** simplified config. Some options are now deprecated ([8ddf2da](https://github.com/folke/which-key.nvim/commit/8ddf2da5a6aa76f5b3cec976f1d61e7c7fea42b5)) * **view:** show and expand localleader mappings with filter.global = false ([ed5f762](https://github.com/folke/which-key.nvim/commit/ed5f7622771d0b5c0ac3a5e286ec6cd17b6be131)) ### Bug Fixes * **ui:** remove deprecated opts.layout.align option. (wasn't used). Closes [#752](https://github.com/folke/which-key.nvim/issues/752) ([db32ac6](https://github.com/folke/which-key.nvim/commit/db32ac67abb36789a43fe497ff7d0b8ab7e8109e)) ## [3.8.0](https://github.com/folke/which-key.nvim/compare/v3.7.0...v3.8.0) (2024-07-17) ### Features * **mappings:** added health check for invalid modes ([640724a](https://github.com/folke/which-key.nvim/commit/640724a541af75e6bbfe98f78cdebbec701d23a8)) ### Bug Fixes * **buf:** never create proxy/plugin mappings when a keymap exists. Fixes [#738](https://github.com/folke/which-key.nvim/issues/738) ([b4c4e36](https://github.com/folke/which-key.nvim/commit/b4c4e3648261399a97bfdc44bb8fa31b485fd3b9)) * **registers:** use x instead of v ([#742](https://github.com/folke/which-key.nvim/issues/742)) ([5c3b3e8](https://github.com/folke/which-key.nvim/commit/5c3b3e834852a44efb26725f9c08917145f2c0c6)) * **state:** schedule redraw. Fixes [#740](https://github.com/folke/which-key.nvim/issues/740) ([09f21a1](https://github.com/folke/which-key.nvim/commit/09f21a133104b66a5cede8fc0a8082b85b0eee9b)) * **triggers:** allow overriding keymaps with empty rhs or <Nop>. Fixes [#748](https://github.com/folke/which-key.nvim/issues/748) ([843a93f](https://github.com/folke/which-key.nvim/commit/843a93fac6bca58167aafa392e6f7fd5a77633c9)) * **triggers:** make sure no keymaps exists for triggers ([e8b454f](https://github.com/folke/which-key.nvim/commit/e8b454fb03e3cab398c894e5d462c84595ee57ca)) * **typo:** replace 'exras' for 'extras' in README. ([#745](https://github.com/folke/which-key.nvim/issues/745)) ([af48cdc](https://github.com/folke/which-key.nvim/commit/af48cdc4bb8f1982a6124bf6bb5570349f690822)) ## [3.7.0](https://github.com/folke/which-key.nvim/compare/v3.6.0...v3.7.0) (2024-07-17) ### Features * added `expand` property to create dynamic mappings. An example for `buf` and `win` is included ([02f6e6f](https://github.com/folke/which-key.nvim/commit/02f6e6f4951ff993ad1d5c699784e6847a6c7b4c)) * proxy mappings ([c3cfc2b](https://github.com/folke/which-key.nvim/commit/c3cfc2bdb03c1b87943a6d02485ad50b86567341)) * **state:** allow defering on certain operators. Closes [#733](https://github.com/folke/which-key.nvim/issues/733) ([984d930](https://github.com/folke/which-key.nvim/commit/984d930711341ac118e6712804e8e22e575ba9d3)) ### Bug Fixes * **buf:** create triggers for xo anyway. Fixes [#728](https://github.com/folke/which-key.nvim/issues/728) ([96b2e93](https://github.com/folke/which-key.nvim/commit/96b2e93979373744056c921f82b0c356e6f900de)) * **icons:** added frontier pattern for `git`. Fixes [#727](https://github.com/folke/which-key.nvim/issues/727) ([bb4e82b](https://github.com/folke/which-key.nvim/commit/bb4e82bdaff50a4a93867e4c90938d18e7615af6)) * **state:** dont popup when switching between v and V mode. Fixes [#729](https://github.com/folke/which-key.nvim/issues/729) ([8ddb527](https://github.com/folke/which-key.nvim/commit/8ddb527bcffc6957a59518f11c34a84d91e075f9)) * **view:** always show a group as a group ([96a9eb3](https://github.com/folke/which-key.nvim/commit/96a9eb3f0b3299dffc241cf0f9ee5cf0509e6cd2)) * **view:** empty icons ([e2cacc6](https://github.com/folke/which-key.nvim/commit/e2cacc6f1e4ba77e82e7a34e0dc6b2ad69cf075b)) ## [3.6.0](https://github.com/folke/which-key.nvim/compare/v3.5.0...v3.6.0) (2024-07-16) ### Features * added icons for <D mappings ([aaf71ab](https://github.com/folke/which-key.nvim/commit/aaf71ab078d86a48a26fafb5d451af609fd19c64)) * added option to disable all mapping icons. Fixes [#721](https://github.com/folke/which-key.nvim/issues/721) ([33f6ac0](https://github.com/folke/which-key.nvim/commit/33f6ac04bdbce855ce43eecacb4c421876e246d7)) * make which-key work without setup or calling add/register ([9ca5f4a](https://github.com/folke/which-key.nvim/commit/9ca5f4ab7cb541ef48dcaa4f03d3cd914a5e62fb)) * **presets:** added some missing mappings ([6e1b3f2](https://github.com/folke/which-key.nvim/commit/6e1b3f290a3f89ffca68148aa639c866c24e2b77)) * **state:** improve trigger/mode logic. Fixes [#715](https://github.com/folke/which-key.nvim/issues/715) ([3617e47](https://github.com/folke/which-key.nvim/commit/3617e47673d027989e9c3caa645edb6412c7fa30)) ### Bug Fixes * **config:** replacement for plug mappings ([495f9d9](https://github.com/folke/which-key.nvim/commit/495f9d953a86d630ef308f555ed452e332f417ee)) * **icons:** get icons from parent nodes when needed ([3f0a7ed](https://github.com/folke/which-key.nvim/commit/3f0a7ed4401b98764740cbe8e1b954ac6adeca1b)) * **icons:** use nerdfont symbol for BS. Fixes [#722](https://github.com/folke/which-key.nvim/issues/722) ([18c1ff5](https://github.com/folke/which-key.nvim/commit/18c1ff5ccb813d95c86f4ead6dac7e6cc5728f08)) * **mode:** never create triggers for xo mode ([15d3a70](https://github.com/folke/which-key.nvim/commit/15d3a70304607417b2dc1df3da4992d5b8ce077a)) * **presets:** motions in normal mode ([e2ffc26](https://github.com/folke/which-key.nvim/commit/e2ffc263fc05bf20f090ccaae7a06f88fd6e2fee)) * tmp fix for op mode ([91641e2](https://github.com/folke/which-key.nvim/commit/91641e2a3af116ffaf739302a65cdb2865fb2415)) * **view:** fix format for keymaps with 3+ keys ([#723](https://github.com/folke/which-key.nvim/issues/723)) ([0db7896](https://github.com/folke/which-key.nvim/commit/0db7896057d046576c829a87e2ff2de37c49e0fe)) ## [3.5.0](https://github.com/folke/which-key.nvim/compare/v3.4.0...v3.5.0) (2024-07-15) ### Features * **api:** using wk.show() always assumes you want to see the group, and not the actual mapping in case of overlap. Fixes [#714](https://github.com/folke/which-key.nvim/issues/714) ([f5067d2](https://github.com/folke/which-key.nvim/commit/f5067d2b244c19eca38b5b495b6eb3e361ac565d)) ### Bug Fixes * **state:** attach on BufNew as well. Fixes [#681](https://github.com/folke/which-key.nvim/issues/681) ([0f58176](https://github.com/folke/which-key.nvim/commit/0f581764dc2c89c0ac3d8363369152735ae265ab)) * **state:** make sure mode always exists even when not safe. See [#681](https://github.com/folke/which-key.nvim/issues/681) ([7915964](https://github.com/folke/which-key.nvim/commit/7915964e73c30ba5657e9a762c6570925dad421b)) ### Performance Improvements * **plugin:** only expand plugins when needed ([1fcfc72](https://github.com/folke/which-key.nvim/commit/1fcfc72374c705d68f0607a1dcbbbce13873b4e2)) * **view:** set buf/win opts with eventignore ([e81e55b](https://github.com/folke/which-key.nvim/commit/e81e55b647a781f306453734834eb543e1f43c20)) ## [3.4.0](https://github.com/folke/which-key.nvim/compare/v3.3.0...v3.4.0) (2024-07-15) ### Features * added icons for function keys ([9222280](https://github.com/folke/which-key.nvim/commit/9222280970e8a7d74b4e0f6dab06c2f7a54d668d)) * **mode:** allow certain modes to start hidden and only show after keypress. See [#690](https://github.com/folke/which-key.nvim/issues/690) ([b4fa48f](https://github.com/folke/which-key.nvim/commit/b4fa48f473796f5d9e3c9c31e6c9d7d509e51ca6)) * **presets:** added gw ([09b80a6](https://github.com/folke/which-key.nvim/commit/09b80a68085c1fc792b595a851f702bc071d6310)) * **presets:** better padding defaults for helix preset ([4c36b9b](https://github.com/folke/which-key.nvim/commit/4c36b9b8c722bcf51d038dcfba8b967f0ee818b8)) * **presets:** increase default height for helix ([df0ad20](https://github.com/folke/which-key.nvim/commit/df0ad205ebd661ef101666ae21a62b77b3024a83)) * simplified/documented/fixed mappings sorting. Closes [#694](https://github.com/folke/which-key.nvim/issues/694) ([eb73f7c](https://github.com/folke/which-key.nvim/commit/eb73f7c05785a83e07f1ea155b3b2833d8bbb532)) * **state:** skip mouse keys in debug ([5f85b77](https://github.com/folke/which-key.nvim/commit/5f85b770c386c9435eb8da5db3081aa19078211a)) * **ui:** show keys/help in an overlay and added scrolling hint ([50b2c43](https://github.com/folke/which-key.nvim/commit/50b2c43532e6ea5cca3ef4c2838d5a8bb535757f)) * **view:** get parent icon if possible ([b9de927](https://github.com/folke/which-key.nvim/commit/b9de9278bdc57adfa69a67d8a3309f07c83951d0)) ### Bug Fixes * **buf:** always detach " when executing keys. Fixes [#689](https://github.com/folke/which-key.nvim/issues/689) ([d36f722](https://github.com/folke/which-key.nvim/commit/d36f722f114dfdafc8098496e9b5dcbd9f8fc3e8)) * **config:** set expand=0 by default. Fixes [#693](https://github.com/folke/which-key.nvim/issues/693) ([89434aa](https://github.com/folke/which-key.nvim/commit/89434aa356abd4a694d2b89eccb203e0742bc0d7)) * **config:** warn when deprecated config options were used. Fixes [#696](https://github.com/folke/which-key.nvim/issues/696) ([81413ef](https://github.com/folke/which-key.nvim/commit/81413ef02dffbe6e4c73f418e4acc920e68b3aa7)) * **health:** move deprecated option check to health ([af7a30f](https://github.com/folke/which-key.nvim/commit/af7a30fa24ce0a13dba00cbd7b836330facf9f1a)) * **mappings:** allow creating keymaps without desc. Fixes [#695](https://github.com/folke/which-key.nvim/issues/695) ([c442aaa](https://github.com/folke/which-key.nvim/commit/c442aaa6aafe2742c2e92df7ee127df90099ce17)) * **plugins:** add existing keymaps to plugin view. Fixes [#681](https://github.com/folke/which-key.nvim/issues/681) ([26f6fd2](https://github.com/folke/which-key.nvim/commit/26f6fd258b66e9656bb86c7269c6497a9ce8a5fa)) * **presets:** don't override title setting for classic. See [#649](https://github.com/folke/which-key.nvim/issues/649) ([9a53c1f](https://github.com/folke/which-key.nvim/commit/9a53c1ff46421450b5563baab1599591d81de111)) * **presets:** shorter descriptions ([20600e4](https://github.com/folke/which-key.nvim/commit/20600e422277b383e8c921feec2111a281935217)) * **state:** always do full update on BufReadPost since buffer-local keymaps would be deleted. Fixes [#709](https://github.com/folke/which-key.nvim/issues/709) ([6068887](https://github.com/folke/which-key.nvim/commit/60688872f4ecc552a5e2bcbd01e7629a155f377f)) * **state:** don't show when coming from cmdline mode. Fixes [#692](https://github.com/folke/which-key.nvim/issues/692) ([8cba66b](https://github.com/folke/which-key.nvim/commit/8cba66b5a1a0ea8fe8dd5d3d55a42755924e47d8)) * **state:** honor timeoutlen and nowait. Fixes [#648](https://github.com/folke/which-key.nvim/issues/648). Closes [#697](https://github.com/folke/which-key.nvim/issues/697) ([80f20ee](https://github.com/folke/which-key.nvim/commit/80f20ee62311505fe6d675212f7b246900570450)) * **state:** properly disable which-key when recording macros. Fixes [#702](https://github.com/folke/which-key.nvim/issues/702) ([b506275](https://github.com/folke/which-key.nvim/commit/b506275acfb4383f678b9ba3aa8db88787c24680)) * **state:** scrolling ([dce9167](https://github.com/folke/which-key.nvim/commit/dce9167025a0801e4bab146a2856508a9af52ea2)) * **tree:** rawget for existing plugin node children ([c77cda8](https://github.com/folke/which-key.nvim/commit/c77cda8cd2f54965e4316699f1d124a2b3bf9d49)) * **util:** when no clipboard provider exists, use the " register as default. Fixes [#687](https://github.com/folke/which-key.nvim/issues/687) ([d077a3f](https://github.com/folke/which-key.nvim/commit/d077a3f36d4b4d29eccc7feb1ba8e78a421df920)) * **view:** disable footer on Neovim < 0.10 ([6d544a4](https://github.com/folke/which-key.nvim/commit/6d544a43a21a228482155d65c3ca18fd7038b422)) * **view:** ensure highlights get set for title padding ([#684](https://github.com/folke/which-key.nvim/issues/684)) ([2e4f7af](https://github.com/folke/which-key.nvim/commit/2e4f7afa4aa444483d8ade5989d524c7f4131368)) * **view:** hide existing title/footer when no trail ([4f589a1](https://github.com/folke/which-key.nvim/commit/4f589a1368e100a6e33aabd904f34716b75360f6)) * **view:** include group keymaps in expand results. See [#682](https://github.com/folke/which-key.nvim/issues/682) ([39e703c](https://github.com/folke/which-key.nvim/commit/39e703ceaa9a05dcc664e0ab0ea88c03c3b6bf90)) * **view:** overlap protection should keep at least 4 lines ([0d89475](https://github.com/folke/which-key.nvim/commit/0d89475f87756199efc2bc52537fc4d11b0f695a)) * **view:** padding & column spacing. Fixes [#704](https://github.com/folke/which-key.nvim/issues/704) ([11eec49](https://github.com/folke/which-key.nvim/commit/11eec49509490c023bf0272efef955f86f18c1d2)) * **view:** spacing when more than one box ([89568f3](https://github.com/folke/which-key.nvim/commit/89568f3438f1fbc6c340a8af05ea67feac494c46)) * **view:** special handling of `<NL>/`. Fixes [#706](https://github.com/folke/which-key.nvim/issues/706) ([f8c91b2](https://github.com/folke/which-key.nvim/commit/f8c91b2b4a2d239d3b1d49f901a393e7326a5da8)) ## [3.3.0](https://github.com/folke/which-key.nvim/compare/v3.2.0...v3.3.0) (2024-07-14) ### Features * **expand:** allow expand to be a function. Closes [#670](https://github.com/folke/which-key.nvim/issues/670) ([dfaa10c](https://github.com/folke/which-key.nvim/commit/dfaa10cd24badb321a4667fb9135f242393e5680)) * **mappings:** mapping `desc` and `icon` can now be a function that is evaluated when which-key is show. Fixes [#666](https://github.com/folke/which-key.nvim/issues/666) ([c634af1](https://github.com/folke/which-key.nvim/commit/c634af1295512dc2062fbec38f563f5793de245c)) * **mappings:** opts.filter to exclude certain mappings from showing up in which-key. ([763ea00](https://github.com/folke/which-key.nvim/commit/763ea000cce9589124515ba34f6d9a6347a02891)) * **view:** add operator to trail in op mode ([5a6eaaa](https://github.com/folke/which-key.nvim/commit/5a6eaaa4ebc072625b9fc906943e3798028bd817)) * **view:** when in visual mode, propagate esc. See [#656](https://github.com/folke/which-key.nvim/issues/656) ([30ef44a](https://github.com/folke/which-key.nvim/commit/30ef44a13065a157f97d3fb5bbf23a5c23e513eb)) ### Bug Fixes * default preset ([38987d3](https://github.com/folke/which-key.nvim/commit/38987d3f18a8ffc5eaa404d746fd8ee4017b5f37)) * **mappings:** don't show `<SNR>` mappings ([d700244](https://github.com/folke/which-key.nvim/commit/d700244acc1f1474b34737e14a45df2aa3a324ba)) * **presets:** max 1 column in helix mode. Fixes [#665](https://github.com/folke/which-key.nvim/issues/665) ([b2a6910](https://github.com/folke/which-key.nvim/commit/b2a6910e9e97526f2327327d2751834049cbd334)) * **presets:** shorter descriptions ([9a73d6a](https://github.com/folke/which-key.nvim/commit/9a73d6a0b0d5f456a9768d434a83d6d4cdb83efa)) * **state:** cooldown till next tick when not safe to open which-key. Fixes [#672](https://github.com/folke/which-key.nvim/issues/672) ([bdf3b27](https://github.com/folke/which-key.nvim/commit/bdf3b272ea34ac137af3cb1ebcd5cf8c9745abbb)) * **util:** nt mode should map to n ([969afc9](https://github.com/folke/which-key.nvim/commit/969afc95d374bc0d6ce397d3d2357d8faa38041a)) * **view:** set nowrap for the which-key window ([6e1c098](https://github.com/folke/which-key.nvim/commit/6e1c0987024adf63ab91f281f8f9c355abf3f3d8)) * **view:** set winhl groups. Fixes [#661](https://github.com/folke/which-key.nvim/issues/661) ([baff8ea](https://github.com/folke/which-key.nvim/commit/baff8ea846cbb613dee79333aad7a1d2b912a5bc)) ## [3.2.0](https://github.com/folke/which-key.nvim/compare/v3.1.0...v3.2.0) (2024-07-13) ### Features * added `opts.debug` that writes to wk.log in the current directory ([c23df71](https://github.com/folke/which-key.nvim/commit/c23df711884d97963d0c17ed29f5d8c1064d4adc)) * hydra mode. will document later ([65f2e72](https://github.com/folke/which-key.nvim/commit/65f2e7236a3bc278dd163d7c98c9ea5d9ab6e42e)) * **icons:** add telescope icon ([#643](https://github.com/folke/which-key.nvim/issues/643)) ([fca3d9e](https://github.com/folke/which-key.nvim/commit/fca3d9eaef57ddb3ce438d208ebc32e23c9f290a)) ### Bug Fixes * layout stuff ([7423096](https://github.com/folke/which-key.nvim/commit/742309697cff6aa7f377b72e2f54d34afef09ee1)) * **mappings:** always use mapping even when it's creating a keymap. Fixes [#637](https://github.com/folke/which-key.nvim/issues/637) ([2d744cb](https://github.com/folke/which-key.nvim/commit/2d744cb824c0f310be420bf33688bc005f164f46)) * **mappings:** make replace_keycodes default to false in v1 spec ([6ec0a1e](https://github.com/folke/which-key.nvim/commit/6ec0a1ef89209680c799269227b4d0c28de1d877)) * **state:** dont start which-key during dot repeat. Fixes [#636](https://github.com/folke/which-key.nvim/issues/636) ([5971ecd](https://github.com/folke/which-key.nvim/commit/5971ecdf4465425d6bc6e2277101c6fc896cbe06)) * **state:** dont start which-key more than once during the same tick in xo mode. Fixes [#635](https://github.com/folke/which-key.nvim/issues/635) ([0218fce](https://github.com/folke/which-key.nvim/commit/0218fce1c3d54307217391215db28e63de9b8980)) * **state:** dont start wk when chars are pending. Fixes [#658](https://github.com/folke/which-key.nvim/issues/658). Fixes [#655](https://github.com/folke/which-key.nvim/issues/655). Fixes [#648](https://github.com/folke/which-key.nvim/issues/648) ([877ce16](https://github.com/folke/which-key.nvim/commit/877ce163d764bbe7c82a7fec5671c32188607754)) * **state:** only hide on focus lost when still hidden after 1s. Fixes [#638](https://github.com/folke/which-key.nvim/issues/638) ([649a51b](https://github.com/folke/which-key.nvim/commit/649a51bc81b09443c326d390e3d182e0cdf98c15)) * **types:** spec field types ([#645](https://github.com/folke/which-key.nvim/issues/645)) ([c6ffb1c](https://github.com/folke/which-key.nvim/commit/c6ffb1ce63959d5f1effe5924712f36eac1e940e)) * **util:** set local window opts for notify. Fixes [#641](https://github.com/folke/which-key.nvim/issues/641) ([63f2112](https://github.com/folke/which-key.nvim/commit/63f2112361a53b0cf68245868977773f210bb5cd)) * **view:** check for real overlap instead of just row overlap. See [#649](https://github.com/folke/which-key.nvim/issues/649) ([0427e91](https://github.com/folke/which-key.nvim/commit/0427e91dbbd9c37eb20e6fbc2386f890dc0d7e2a)) * **view:** disable folds. Fixes [#99](https://github.com/folke/which-key.nvim/issues/99) ([6860e3b](https://github.com/folke/which-key.nvim/commit/6860e3b681b40e3620049f714ae53a6bad594701)) ## [3.1.0](https://github.com/folke/which-key.nvim/compare/v3.0.0...v3.1.0) (2024-07-12) ### Features * allow disabling any trigger ([94b7951](https://github.com/folke/which-key.nvim/commit/94b795154fb213db6ed8aeba3d7f53cbce7c147c)) ### Bug Fixes * added support for vim.loop ([54db192](https://github.com/folke/which-key.nvim/commit/54db1928c17ac420e897a40f5ad560ee9f28b186)) * automatically do setup if setup wasn't called within 500ms. Fixes [#630](https://github.com/folke/which-key.nvim/issues/630) ([632ad41](https://github.com/folke/which-key.nvim/commit/632ad41b5fcf60fac897d0b6530a699eb980748d)) * **buf:** buffer-local mappings were broken (not keymaps). Fixes [#629](https://github.com/folke/which-key.nvim/issues/629) ([58d7f82](https://github.com/folke/which-key.nvim/commit/58d7f822ecc80ca4b43e9c14fd6ec962483e2168)) * **colors:** compat with older Neovim vesions. Fixes [#631](https://github.com/folke/which-key.nvim/issues/631) ([4516dc9](https://github.com/folke/which-key.nvim/commit/4516dc9422f571c9e189ff6696853d445a3058d6)) ## [3.0.0](https://github.com/folke/which-key.nvim/compare/v2.1.0...v3.0.0) (2024-07-12) ### ⚠ BREAKING CHANGES * v3 release ### Features * added health check back with better wording on what actually gets checked ([97e6e41](https://github.com/folke/which-key.nvim/commit/97e6e4166134aad826454588ae764c7a54f5d298)) * added WhichKey command ([7c12ab9](https://github.com/folke/which-key.nvim/commit/7c12ab9c2569a7459932bc19a4e52ea5a48437b2)) * automatically use nowait based on delay and timeoutlen ([110ed72](https://github.com/folke/which-key.nvim/commit/110ed728bedd0182e4d11726194f7eb5db63e2fb)) * bring config back and create mappings when needed ([add7ab9](https://github.com/folke/which-key.nvim/commit/add7ab92163399c47f7149c96387d382e9d8996b)) * buffer-local sort & refactor API ([14309d0](https://github.com/folke/which-key.nvim/commit/14309d0446dcc6a24421c56e914e06b1fe2d4f41)) * close which-key on FocusLost ([aa99460](https://github.com/folke/which-key.nvim/commit/aa99460e117d0348c7f1f77ab669398c04fcba6b)) * config, and presets ([541989d](https://github.com/folke/which-key.nvim/commit/541989db167e04eb3db24ba57decab0326614f0f)) * expand groups with less than n mappings. Closes [#374](https://github.com/folke/which-key.nvim/issues/374). Fixes [#90](https://github.com/folke/which-key.nvim/issues/90). Closes [#208](https://github.com/folke/which-key.nvim/issues/208) ([5caf057](https://github.com/folke/which-key.nvim/commit/5caf057b3a204a94d53b4b0200ce915463b4a922)) * fancy key icons ([e4d0134](https://github.com/folke/which-key.nvim/commit/e4d01347434b31e8a90720463076bbbeebbef199)) * fix hidden and empty groups ([afc4aa9](https://github.com/folke/which-key.nvim/commit/afc4aa96ae5671f5d4d14f332789dec72dd5db02)) * **health:** duplicate mappings check ([4762e06](https://github.com/folke/which-key.nvim/commit/4762e06f9dc45b3470ab5b2efa0a4b3de6148298)) * **health:** icon providers & overlapping keys ([dcbf29a](https://github.com/folke/which-key.nvim/commit/dcbf29ae337bd4d621e326b6f1caad66cfe0770a)) * initial rewrite ([eb3ad2e](https://github.com/folke/which-key.nvim/commit/eb3ad2eb062392497d0fed3489e2582d4e5bc289)) * keep track of virtual mappings ([4537d3e](https://github.com/folke/which-key.nvim/commit/4537d3ea52b2b11b96ca2fdde2bb4573f0ca7c73)) * key/desc replacements ([cf34ffe](https://github.com/folke/which-key.nvim/commit/cf34ffe9384941dc833ed2a3bb2a3bf3aa050373)) * layout ([347288a](https://github.com/folke/which-key.nvim/commit/347288acd8398ae7c641bd6159261e98f9a6b929)) * manual sorting. Closes [#131](https://github.com/folke/which-key.nvim/issues/131), Closes [#362](https://github.com/folke/which-key.nvim/issues/362), Closes [#264](https://github.com/folke/which-key.nvim/issues/264) ([c2daf9d](https://github.com/folke/which-key.nvim/commit/c2daf9dcf48e8c8cca61cfc27b1731272b9bc2c6)) * **mappings:** added support for lazy.nvim style mappings ([6f7a945](https://github.com/folke/which-key.nvim/commit/6f7a945f1dc679ce2c35064e12e4dc531ebf2c3c)) * **mappings:** added support for setting custom icons from the spec ([951ae7a](https://github.com/folke/which-key.nvim/commit/951ae7a89d164f39f8aa49f51da424539370f6c4)) * new spec and migration recommendation for health ([41374bc](https://github.com/folke/which-key.nvim/commit/41374bcae462d897fa98c904a44127e258c0438c)) * option to disable icon colors ([79c8ac8](https://github.com/folke/which-key.nvim/commit/79c8ac87139dcb816072c1a5ca1800d9ce5d64aa)) * option to disable notify ([4cc46ff](https://github.com/folke/which-key.nvim/commit/4cc46ffa57b8a6ebf6ca7a07128d353f5569a802)) * play nice with macros ([1abc2bf](https://github.com/folke/which-key.nvim/commit/1abc2bf96472e7816252719de06d60e9b09035dc)) * plugins partially working again ([b925b31](https://github.com/folke/which-key.nvim/commit/b925b31bab1f91507d15a96f226f7f7423c4fced)) * **registers:** show non-printable with keytrans ([1832197](https://github.com/folke/which-key.nvim/commit/183219772d01e0ea744c0ff8bf656895f7d7c8d3)) * spec parser rewrite & proper typings ([07065fe](https://github.com/folke/which-key.nvim/commit/07065fe345bc9dd20aff11ab9a6a3b078aacd42e)) * state management ([e2ee1fa](https://github.com/folke/which-key.nvim/commit/e2ee1fae13f7a6c38652994dedb0cb34e2608918)) * state management ([e6beb88](https://github.com/folke/which-key.nvim/commit/e6beb8845e80558194c6027b7a985e1211e76878)) * title trail ([aef2e53](https://github.com/folke/which-key.nvim/commit/aef2e535c5b7c8f100b534a4b781a82e36f20e39)) * **ui:** added scrolling ([5f1ab35](https://github.com/folke/which-key.nvim/commit/5f1ab35d099a252f204e2806747980c192a9c265)) * **ui:** keymap icons ([21d7108](https://github.com/folke/which-key.nvim/commit/21d71081d86872189a3ce90b7c13593f15b78459)) * **ui:** sorters ([ffeea79](https://github.com/folke/which-key.nvim/commit/ffeea7933249d5ce33b2b3838171cc5299ef1893)) * update ui when new mappings become available ([a8f66f5](https://github.com/folke/which-key.nvim/commit/a8f66f5ebd9b94f409a88c4a77244167f6edd05f)) * v3 release ([da258a8](https://github.com/folke/which-key.nvim/commit/da258a89a700916ad0e6af1ad8f9889ff0308253)) * **view:** nerd font icons for cmd keys ([2787dbd](https://github.com/folke/which-key.nvim/commit/2787dbd158184af67ead5af5bcc0cbdb17856c31)) ### Bug Fixes * **api:** show view immediately when opened through the API ([b0e0af0](https://github.com/folke/which-key.nvim/commit/b0e0af0957a648735a43fae52ef34059721f7b42)) * autmatically blacklist all single key hooks except for z and g ([87c5a4b](https://github.com/folke/which-key.nvim/commit/87c5a4b1be1f882c8b27252464d777a76ea15839)) * **icons:** check that mini icons hl groups exist in the current colorscheme. If not use which-key default groups ([2336350](https://github.com/folke/which-key.nvim/commit/233635039bf828e341f5ca9b4b8444ac3c56b974)) * **icons:** proper icons check ([2eaed99](https://github.com/folke/which-key.nvim/commit/2eaed99585f08787d6b5060c89184973eb5aa276)) * **keys:** delete nop keymaps with a description ([ccf0276](https://github.com/folke/which-key.nvim/commit/ccf027625df6c4e22febfdd786c5e1f7521c2ccb)) * **layout:** display vs multibyte ellipsis ([0442a73](https://github.com/folke/which-key.nvim/commit/0442a7340cebe13cc5a5fd70dd6cdc989f9086fe)) * **layout:** empty columns ([600881a](https://github.com/folke/which-key.nvim/commit/600881a9b0cf8119819a97d8900d99fd7a406d36)) * op-mode, count and reg ([e4d54d1](https://github.com/folke/which-key.nvim/commit/e4d54d11cc247edd0ed4bde7a501caa8e119c1ff)) * pcall keymap.del ([e47ee13](https://github.com/folke/which-key.nvim/commit/e47ee139b6a082deab16e436cbd2711923e01625)) * plugin actions & spelling ([e7da411](https://github.com/folke/which-key.nvim/commit/e7da411b45415e8d0d6a5e14b9c1bd5207d09869)) * presets ([bcf52ba](https://github.com/folke/which-key.nvim/commit/bcf52ba08a57a90e85d4397245a0350c34f2b9d1)) * readme ([5fe6c91](https://github.com/folke/which-key.nvim/commit/5fe6c91e6f2d7d6dd1a8473ac0cd9bbe311512d9)) * respect mappings with `<esc>` and close on cursor moved ([22deda5](https://github.com/folke/which-key.nvim/commit/22deda5458b15a10b02b516c68dd409cbaeb53f4)) * set check debounce to 50 ([754bcc7](https://github.com/folke/which-key.nvim/commit/754bcc7be77b9f9ecac02598121eb97a243b7efa)) * **state:** dont return or autocmd will cancel ([9a77986](https://github.com/folke/which-key.nvim/commit/9a779869ef557ff6fa84a8b0b478a0f84781c67e)) * **state:** keyboard interrupts ([1ed9182](https://github.com/folke/which-key.nvim/commit/1ed91823d47f34ce5c52da9ca14e202606caf215)) * **state:** make sure the buffer mode exists when changing modes ([df64366](https://github.com/folke/which-key.nvim/commit/df64366d8633ac13ba2da7134cc6bbe242a97237)) * stuff ([f67eb19](https://github.com/folke/which-key.nvim/commit/f67eb192ca6d579add84086d4d1b4ce6ce8732ac)) * **tree:** check for which_key_ignore in existing keymaps ([f17d78b](https://github.com/folke/which-key.nvim/commit/f17d78bdf8a0afce5bec97c70e68203a6cddf2b7)) * **ui:** box height ([528fc43](https://github.com/folke/which-key.nvim/commit/528fc43b87cfc29bbc1dddc17051a99cdfdf9ad2)) * **ui:** make sure the which-key window never overlaps the user's cursor position ([1bb30a7](https://github.com/folke/which-key.nvim/commit/1bb30a7a6901aa842f31c96af7009ef645b29edd)) * **ui:** scroll and topline=1 on refresh ([28b648d](https://github.com/folke/which-key.nvim/commit/28b648daeabfd2aad8496ffc7a2096bf7d2441b5)) * which_key_ignore ([ab5ffa8](https://github.com/folke/which-key.nvim/commit/ab5ffa83b4f10ea2360a32d855b016f72a2be6b6)) * which-key ignore and cleanup ([aeae826](https://github.com/folke/which-key.nvim/commit/aeae826f948cbaeb3a89d9025c423e8300cb5dd3)) ## [2.1.0](https://github.com/folke/which-key.nvim/compare/v2.0.1...v2.1.0) (2024-06-06) ### Features * **presets:** add descriptions for fold deletion ([#504](https://github.com/folke/which-key.nvim/issues/504)) ([53b6085](https://github.com/folke/which-key.nvim/commit/53b6085367a92740664783330583facd958dbceb)) ### Bug Fixes * black hole z= replacements ([#602](https://github.com/folke/which-key.nvim/issues/602)) ([f5b9124](https://github.com/folke/which-key.nvim/commit/f5b912451f33fd19e52230e73617ad099ffd3ab1)) * **keys:** fix nested operators. See [#600](https://github.com/folke/which-key.nvim/issues/600). Fixes [#609](https://github.com/folke/which-key.nvim/issues/609) ([25d5b9e](https://github.com/folke/which-key.nvim/commit/25d5b9e9b5775525248b8d5c95271ba28f75d326)) * restore win view after rendering buffer ([#516](https://github.com/folke/which-key.nvim/issues/516)) ([ea4a17d](https://github.com/folke/which-key.nvim/commit/ea4a17d63571c81f529669a373d20c855b9b351d)), closes [#515](https://github.com/folke/which-key.nvim/issues/515) * support nested operators ([#600](https://github.com/folke/which-key.nvim/issues/600)) ([476f4ca](https://github.com/folke/which-key.nvim/commit/476f4cacb15da81dcebe68ea45333e660409612d)) ## [2.0.1](https://github.com/folke/which-key.nvim/compare/v2.0.0...v2.0.1) (2024-06-06) ### Bug Fixes * label -> desc ([b8eb534](https://github.com/folke/which-key.nvim/commit/b8eb5348a749e214dfd08d38654a736d91191918)) ## [2.0.0](https://github.com/folke/which-key.nvim/compare/v1.6.1...v2.0.0) (2024-06-06) ### ⚠ BREAKING CHANGES * which-key now requires Neovim >= 0.9 ### Features * **keys:** `desc` in `"<nop>"` or `""` keymaps can now become prefix label ([#522](https://github.com/folke/which-key.nvim/issues/522)) ([c1958e2](https://github.com/folke/which-key.nvim/commit/c1958e2529433ef096e924c72315733790ca7f88)) * **mappings:** check if desc exists when parsing mappings ([#589](https://github.com/folke/which-key.nvim/issues/589)) ([a7ced9f](https://github.com/folke/which-key.nvim/commit/a7ced9f00a309418865ec2e3c272113147d167fe)) * which-key now requires Neovim >= 0.9 ([53ba0ac](https://github.com/folke/which-key.nvim/commit/53ba0accc2d607ef3f2b4f6e40aa9ac75e611dee)) ### Bug Fixes * **ignore_missing:** not showing key maps with desc field ([#577](https://github.com/folke/which-key.nvim/issues/577)) ([928c6c8](https://github.com/folke/which-key.nvim/commit/928c6c8fb62df55fa640399b7d76410c037b5f55)) * **is_enabled:** disable whichkey in cmdline-window ([#581](https://github.com/folke/which-key.nvim/issues/581)) ([26ff0e6](https://github.com/folke/which-key.nvim/commit/26ff0e6084a4e957fc13ffe00bafd7c0c5ab81cc)) * **keys:** fix buffer-local mapping groups ([d87c01c](https://github.com/folke/which-key.nvim/commit/d87c01c9bbcc7c1c2d248dca1b11285259d66be8)) * **mappings:** dont remove desc ([4a7d732](https://github.com/folke/which-key.nvim/commit/4a7d7328b26d3f3355a43af4d8dc5ffd33cbd793)) ## [1.6.1](https://github.com/folke/which-key.nvim/compare/v1.6.0...v1.6.1) (2024-05-31) ### Bug Fixes * **reg:** Added check for OSC 52 to disable related register previews ([#604](https://github.com/folke/which-key.nvim/issues/604)) ([8063a7f](https://github.com/folke/which-key.nvim/commit/8063a7f33bfea6a6387907c93a30a5877aa02633)) * small typo in operator description ([#528](https://github.com/folke/which-key.nvim/issues/528)) ([d65087b](https://github.com/folke/which-key.nvim/commit/d65087b892c45d3722b6511c83a029671d6290e5)) ## [1.6.0](https://github.com/folke/which-key.nvim/compare/v1.5.1...v1.6.0) (2023-10-17) ### Features * **presets:** added gt and gT. Fixes [#457](https://github.com/folke/which-key.nvim/issues/457) ([3ba77f0](https://github.com/folke/which-key.nvim/commit/3ba77f0b0961b3fe685397b8d8f34f231b9350a6)) ### Bug Fixes * call config in issue template ([#489](https://github.com/folke/which-key.nvim/issues/489)) ([09a8188](https://github.com/folke/which-key.nvim/commit/09a8188224dc890618dfbc961436b106d912c2c1)) * **view:** set modifiable flag for view buffer ([#506](https://github.com/folke/which-key.nvim/issues/506)) ([1d17760](https://github.com/folke/which-key.nvim/commit/1d1776012eda4258985f6f1f0c02b78594a3f37b)) ## [1.5.1](https://github.com/folke/which-key.nvim/compare/v1.5.0...v1.5.1) (2023-07-15) ### Bug Fixes * revert: never overwrite actual keymaps with group names. Fixes [#478](https://github.com/folke/which-key.nvim/issues/478) Fixes [#479](https://github.com/folke/which-key.nvim/issues/479) Fixes [#480](https://github.com/folke/which-key.nvim/issues/480) ([fc25407](https://github.com/folke/which-key.nvim/commit/fc25407a360d27c36a30a90ff36861aa20ef2e54)) ## [1.5.0](https://github.com/folke/which-key.nvim/compare/v1.4.3...v1.5.0) (2023-07-14) ### Features * **marks:** show filename as label when no label ([25babc6](https://github.com/folke/which-key.nvim/commit/25babc6add21c17d6391a585302aee5632266622)) ### Bug Fixes * **keys:** don't show empty groups ([8503c0d](https://github.com/folke/which-key.nvim/commit/8503c0d725420b37ac31e44753657cde91435597)) * never overwrite actual keymaps with group names ([f61da3a](https://github.com/folke/which-key.nvim/commit/f61da3a3a6143b7a42b4b16e983004856ec26bd1)) * **registers:** dont trigger on @. Fixes [#466](https://github.com/folke/which-key.nvim/issues/466) ([65b36cc](https://github.com/folke/which-key.nvim/commit/65b36cc258e857dea92fc11cdc0d6e2bb01d3e87)) ## [1.4.3](https://github.com/folke/which-key.nvim/compare/v1.4.2...v1.4.3) (2023-05-22) ### Bug Fixes * **health:** dont show duplicates between global and buffer-local. It's too confusing ([015fdf3](https://github.com/folke/which-key.nvim/commit/015fdf3e3e052d4a9fee997ca0aa387c2dd3731c)) ## [1.4.2](https://github.com/folke/which-key.nvim/compare/v1.4.1...v1.4.2) (2023-05-10) ### Bug Fixes * **health:** update the deprecated function ([#453](https://github.com/folke/which-key.nvim/issues/453)) ([12d3b11](https://github.com/folke/which-key.nvim/commit/12d3b11a67b94d65483f10c6ba0a47474039543a)) ## [1.4.1](https://github.com/folke/which-key.nvim/compare/v1.4.0...v1.4.1) (2023-05-04) ### Bug Fixes * **keys:** dont overwrite existing keymaps with a callback. Fixes [#449](https://github.com/folke/which-key.nvim/issues/449) ([4db6bb0](https://github.com/folke/which-key.nvim/commit/4db6bb080b269ac155e5aa1696d26f2376c749ab)) ## [1.4.0](https://github.com/folke/which-key.nvim/compare/v1.3.0...v1.4.0) (2023-04-18) ### Features * **view:** ensure it's above other floating windows ([#442](https://github.com/folke/which-key.nvim/issues/442)) ([9443778](https://github.com/folke/which-key.nvim/commit/94437786a0d0fde61284f8476ac142896878c2d7)) ## [1.3.0](https://github.com/folke/which-key.nvim/compare/v1.2.3...v1.3.0) (2023-04-17) ### Features * **health:** move health check to separate health file ([b56c512](https://github.com/folke/which-key.nvim/commit/b56c5126752fcd498a81c6d8d1e7f51f251166eb)) * **preset:** add `z<CR>` preset ([#346](https://github.com/folke/which-key.nvim/issues/346)) ([ed37330](https://github.com/folke/which-key.nvim/commit/ed3733059ffa281c8144e44f1b4819a771ddf4de)) * **preset:** added `zi` and `CTRL-W_o` ([#378](https://github.com/folke/which-key.nvim/issues/378)) ([5e8e6b1](https://github.com/folke/which-key.nvim/commit/5e8e6b1c70d3fcbe2712453ef3ebbf07d0d2aff4)) * **view:** allow percentages for margins. Fixes [#436](https://github.com/folke/which-key.nvim/issues/436) ([0b5a653](https://github.com/folke/which-key.nvim/commit/0b5a6537b66ee37d03c6c3f0e21fd147f817422d)) ### Bug Fixes * **health:** add OK output to check_health fn ([#375](https://github.com/folke/which-key.nvim/issues/375)) ([c9c430a](https://github.com/folke/which-key.nvim/commit/c9c430ab19a3bf8dd394dd9925a3a219063276b9)) * **keys:** allow keymap desc to override preset labels. Fixes [#386](https://github.com/folke/which-key.nvim/issues/386) ([6aa1b2f](https://github.com/folke/which-key.nvim/commit/6aa1b2fa93a2a26a1bd752080ec6a51beb009e75)) * **tree:** don't cache plugin nodes. Fixes [#441](https://github.com/folke/which-key.nvim/issues/441) ([20fcd7b](https://github.com/folke/which-key.nvim/commit/20fcd7b602a2c58d634eaa1f1d28b16a6acbfad3)) * **util:** clear cache when leader changes ([df3597f](https://github.com/folke/which-key.nvim/commit/df3597f7dc0f379bda865e3c9dd6303fa6e4c959)) * **util:** missing return statement ([f6bb21c](https://github.com/folke/which-key.nvim/commit/f6bb21c8c1d72008783466e80e0c993ef056a3a9)) * **util:** nil check ([6ab25e2](https://github.com/folke/which-key.nvim/commit/6ab25e24ec2b2a8fb88f43eb13feb21e5042c280)) ### Performance Improvements * **keys:** optimized `update_keymaps` ([476d137](https://github.com/folke/which-key.nvim/commit/476d13754db0da7831fc3581fb243cd7f0d3e581)) * **tree:** added fast nodes lookup ([8e5e012](https://github.com/folke/which-key.nvim/commit/8e5e0126aaff9bd73eb25a6d5568f6b5bdff58f0)) * **util:** cache parse_keys ([8649bf5](https://github.com/folke/which-key.nvim/commit/8649bf5c66b8fa1fa6ee879b9af78e89f886d13c)) * **util:** cache replace termcodes ([eaa8027](https://github.com/folke/which-key.nvim/commit/eaa80272ef488c68cd51698c64e795767c6e0624)) ## [1.2.3](https://github.com/folke/which-key.nvim/compare/v1.2.2...v1.2.3) (2023-04-17) ### Bug Fixes * **util:** dont parse empty lhs ([8d5ab76](https://github.com/folke/which-key.nvim/commit/8d5ab76836d89be1c761a4ed61bf700d98c71e5d)) * **util:** only collect valid <> keys ([#438](https://github.com/folke/which-key.nvim/issues/438)) ([4bd6dca](https://github.com/folke/which-key.nvim/commit/4bd6dcaa6d7e1650590303f0066d32aa6762d8f3)) * **util:** replace `<lt>` by `<` before parsing ([789ac71](https://github.com/folke/which-key.nvim/commit/789ac718ee7a2b49dd82409e3d7cf45b52ea95ce)) * **view:** allow deviating paddings per side ([#400](https://github.com/folke/which-key.nvim/issues/400)) ([3090eaf](https://github.com/folke/which-key.nvim/commit/3090eafb780da76eb4876986081551db80bf35cd)) ### Performance Improvements * **util:** simplify and optimize parsers ([#435](https://github.com/folke/which-key.nvim/issues/435)) ([b0ebb67](https://github.com/folke/which-key.nvim/commit/b0ebb6722c77dda1ab1e3ce13521fe7db20cbc79)) ## [1.2.2](https://github.com/folke/which-key.nvim/compare/v1.2.1...v1.2.2) (2023-04-16) ### Performance Improvements * **mappings:** avoid computing error string on hot path ([#429](https://github.com/folke/which-key.nvim/issues/429)) ([6892f16](https://github.com/folke/which-key.nvim/commit/6892f165bb984561f8cac298a6747da338d04668)) ## [1.2.1](https://github.com/folke/which-key.nvim/compare/v1.2.0...v1.2.1) (2023-03-26) ### Bug Fixes * **icons:** fixed obsolete icons with nerdfix ([151f21d](https://github.com/folke/which-key.nvim/commit/151f21d34d50fc53506ddc9d8ec58234202df795)) * **view:** wrong window position when statusline is not set ([#363](https://github.com/folke/which-key.nvim/issues/363)) ([e14f8dc](https://github.com/folke/which-key.nvim/commit/e14f8dc6304e774ce005d09f7feebbd191fe20f9)) ## [1.2.0](https://github.com/folke/which-key.nvim/compare/v1.1.1...v1.2.0) (2023-03-01) ### Features * enable spelling plugin by default ([6d886f4](https://github.com/folke/which-key.nvim/commit/6d886f4dcaa25d1fe20e332f779fe1edb726d063)) * make delay configurable for marks/registers/spelling. Fixes [#379](https://github.com/folke/which-key.nvim/issues/379). Fixes [#152](https://github.com/folke/which-key.nvim/issues/152), Fixes [#220](https://github.com/folke/which-key.nvim/issues/220), Fixes [#334](https://github.com/folke/which-key.nvim/issues/334) ([5649320](https://github.com/folke/which-key.nvim/commit/56493205745597abdd8d3ceb22f502ffe74784f5)) ## [1.1.1](https://github.com/folke/which-key.nvim/compare/v1.1.0...v1.1.1) (2023-02-10) ### Bug Fixes * remove duplicate kaymap ([#361](https://github.com/folke/which-key.nvim/issues/361)) ([9a4680e](https://github.com/folke/which-key.nvim/commit/9a4680e95b7026c58f0a377de0f13ee2507ece7a)) ## [1.1.0](https://github.com/folke/which-key.nvim/compare/v1.0.0...v1.1.0) (2023-01-10) ### Features * Hide mapping when `desc = "which_key_ignore"` ([#391](https://github.com/folke/which-key.nvim/issues/391)) ([fd07b61](https://github.com/folke/which-key.nvim/commit/fd07b6137f1e362a66df04f7c7055b99319e3a4d)) ### Bug Fixes * visual-multi compatibility ([#389](https://github.com/folke/which-key.nvim/issues/389)) ([#385](https://github.com/folke/which-key.nvim/issues/385)) ([01334bb](https://github.com/folke/which-key.nvim/commit/01334bb48c53231fc8b2e2932215bfee05474904)) ## 1.0.0 (2023-01-04) ### Features * add <C-w>_ to misc ([#296](https://github.com/folke/which-key.nvim/issues/296)) ([03b8c1d](https://github.com/folke/which-key.nvim/commit/03b8c1dde8c02f187869c56a6019d5e2578f7af7)) * add preset key to mappings for API usage ([ed7d6c5](https://github.com/folke/which-key.nvim/commit/ed7d6c523ae8ef7b8059d2fee0836009e71bcd0c)) * added a winblend option for the floating window ([#161](https://github.com/folke/which-key.nvim/issues/161)) ([d3032b6](https://github.com/folke/which-key.nvim/commit/d3032b6d3e0adb667975170f626cb693bfc66baa)) * added duplicate mapping checks to checkhealth [#34](https://github.com/folke/which-key.nvim/issues/34) ([710c5f8](https://github.com/folke/which-key.nvim/commit/710c5f81da2c34e6e0f361d87cfca27207e1b994)) * added healthcheck to check for conflicting keymaps ([44d3c3f](https://github.com/folke/which-key.nvim/commit/44d3c3f9307930ce8c877383d51fca1a353982d8)) * added ignore_missing option to hide any keymap for which no label exists [#60](https://github.com/folke/which-key.nvim/issues/60) ([1ccba9d](https://github.com/folke/which-key.nvim/commit/1ccba9d0b553b08feaca9f432386f9c33bd1656f)) * added operators plugin ([c7f8496](https://github.com/folke/which-key.nvim/commit/c7f84968e44f1a9ab9687ddf0b3dc5465e48bc75)) * added option to configure scroll bindings inside the popup ([#175](https://github.com/folke/which-key.nvim/issues/175)) ([a54ef5f](https://github.com/folke/which-key.nvim/commit/a54ef5f5db5819ee65a5ec3dea9bae64476c5017)) * added options to align columns left, center or right [#82](https://github.com/folke/which-key.nvim/issues/82) ([2467fb1](https://github.com/folke/which-key.nvim/commit/2467fb15e8775928fba3d7d20a68b64852f44122)) * added settings to disable the WhichKey popup for certain buftypes and filetyes ([fb276a0](https://github.com/folke/which-key.nvim/commit/fb276a07c7dc305e48ecc2683e4bd28cda49499a)) * added support for expr mappings ([9d2785c](https://github.com/folke/which-key.nvim/commit/9d2785c4d44b4a8ca1095856cb4ee34a32497cf6)) * added triggers_blacklist to blacklist certain whichkey hooks [#73](https://github.com/folke/which-key.nvim/issues/73) ([ec1474b](https://github.com/folke/which-key.nvim/commit/ec1474bb0c373eb583962deff20860c2af54f932)) * added WhichKeyBorder highlight group ([9c190ea](https://github.com/folke/which-key.nvim/commit/9c190ea91939eba8c2d45660127e0403a5300b5a)) * allow functions to be passed to create keybindings. Implements [#31](https://github.com/folke/which-key.nvim/issues/31) ([cf644cd](https://github.com/folke/which-key.nvim/commit/cf644cd9a0e989ad3e0a6dffb98beced742f3297)) * allow manual setup of triggers [#30](https://github.com/folke/which-key.nvim/issues/30) ([423a50c](https://github.com/folke/which-key.nvim/commit/423a50cccfeb8b812e0e89f156316a4bd9d2673a)) * allow mapping to have multiple modes as a table ([0d559fa](https://github.com/folke/which-key.nvim/commit/0d559fa5573aa48c4822e8874315316bd075e17e)) * allow mode to be set on a single mapping ([2a08d58](https://github.com/folke/which-key.nvim/commit/2a08d58658e1de0fae3b44e21e8ed72399465701)) * allow overriding key labels [#77](https://github.com/folke/which-key.nvim/issues/77) ([2be929e](https://github.com/folke/which-key.nvim/commit/2be929e34b2f2b982e6b978c0bd94cd2e1d500e6)) * allow to close popup with <c-c> [#33](https://github.com/folke/which-key.nvim/issues/33) ([410523a](https://github.com/folke/which-key.nvim/commit/410523a6d7bcbcab73f8c7b0fc567893d7cd8c44)) * better logging ([c39df95](https://github.com/folke/which-key.nvim/commit/c39df95881a6cd8ac27fce5926dc2dc1b4597df9)) * better support for plugin actions with custom lua function ([222a8ee](https://github.com/folke/which-key.nvim/commit/222a8eeaf727f9b1b767424198f7c71274c04d43)) * builtin key mappings ([0063ceb](https://github.com/folke/which-key.nvim/commit/0063ceb161475097885d567500fe764358983c62)) * check for rogue existsing WhichKey mappings and show error. WK handles triggers automatically, no need to define them ([db97a30](https://github.com/folke/which-key.nvim/commit/db97a301fb7691b61cd6c975e3cc060fb53fd980)) * easily reset WK with plenary for development of WK ([55b4dab](https://github.com/folke/which-key.nvim/commit/55b4dabab649d59e657917eb17c9d57716817719)) * expose registers to customize order ([2b83fe7](https://github.com/folke/which-key.nvim/commit/2b83fe74dee00763e4c037d198c88ff11c843914)) * for nvim 0.7.0 or higher, use native keymap callbacks instead of which key functions ([5e96cf9](https://github.com/folke/which-key.nvim/commit/5e96cf950a864a4600512c90f2080b0b6f0eacb7)) * group symbol ([5e02b66](https://github.com/folke/which-key.nvim/commit/5e02b66b9e7add373967b798552a7cc9a427efb4)) * handle [count] with motion. Implements [#11](https://github.com/folke/which-key.nvim/issues/11) ([d93ef0f](https://github.com/folke/which-key.nvim/commit/d93ef0f2f1a9a6288016a3a82f70399e350a574f)) * hide mapping boilerplate ([#6](https://github.com/folke/which-key.nvim/issues/6)) ([b3357de](https://github.com/folke/which-key.nvim/commit/b3357de005f27a3cc6aabe922e8ee308470d9343)) * honor timeoutlen when typing an operator followed by i or a instead of showing immediately ([54d1b3a](https://github.com/folke/which-key.nvim/commit/54d1b3ab3ed9132142f2139964cfa68d018b38c5)) * initial commit ([970e79f](https://github.com/folke/which-key.nvim/commit/970e79f7016f6cc2a89dad8c50e2e89657684f55)) * keyamp functions ([801cc81](https://github.com/folke/which-key.nvim/commit/801cc810f4d57eca029261f383b2483ec21e5824)) * make custom operators configurable (fixes [#9](https://github.com/folke/which-key.nvim/issues/9)) ([81875d8](https://github.com/folke/which-key.nvim/commit/81875d875f7428c7a087e0d051744c7b3f9dc1b3)) * make help message configurable ([7b1c6aa](https://github.com/folke/which-key.nvim/commit/7b1c6aa23061a9ed1acdfec3d20dc5e361ec01a3)) * Make keypress message configuratble ([#351](https://github.com/folke/which-key.nvim/issues/351)) ([fd2422f](https://github.com/folke/which-key.nvim/commit/fd2422fb7030510cf9c3304047e653e8adcd8f20)) * motions plugin ([f989fcf](https://github.com/folke/which-key.nvim/commit/f989fcfeafd4fd333a8e87617fce39a449ae81ca)) * new keymap dsl ([#352](https://github.com/folke/which-key.nvim/issues/352)) Docs to come ([fbf0381](https://github.com/folke/which-key.nvim/commit/fbf038110edb5e2cbecaac57570aae2c9fa2939c)) * option to make some triggers show immediately, regardless of timeoutlen ([3a52dc0](https://github.com/folke/which-key.nvim/commit/3a52dc02b6e542d5cd216381ccfa108943bab17c)) * plugin for registers ([5415832](https://github.com/folke/which-key.nvim/commit/541583280fab4ea96900f35fb6b5ffb8de103a4c)) * plugin support + first builtin marks plugin ([9d5e631](https://github.com/folke/which-key.nvim/commit/9d5e6311c20970741eaaf7a3950c1a33de5eedaa)) * prefer `desc` to `cmd` as the fallback label ([#253](https://github.com/folke/which-key.nvim/issues/253)) ([bd4411a](https://github.com/folke/which-key.nvim/commit/bd4411a2ed4dd8bb69c125e339d837028a6eea71)) * preset with misc keybindings ([e610338](https://github.com/folke/which-key.nvim/commit/e61033858b8d5208a49c24d70eb9576cbd22e887)) * set keymap desc when creating new mappings based on the WhichKey labels ([f4518ca](https://github.com/folke/which-key.nvim/commit/f4518ca50193a545681ba65ba0c5bb8a8479c5b5)) * set popup filetype to WhichKey and buftype to nofile [#86](https://github.com/folke/which-key.nvim/issues/86) ([20682f1](https://github.com/folke/which-key.nvim/commit/20682f189a0c452203f6365f66eccb0407b20936)) * show a warning if <leader> is already mapped, even if it's ([ac56f45](https://github.com/folke/which-key.nvim/commit/ac56f45095e414c820f621423611aac4027f74bd)) * show breadcrumb and help on command line ([c27535c](https://github.com/folke/which-key.nvim/commit/c27535ca085c05ade1e23b3b347e39e53c24d33a)) * show keys and help in float when cmdheight == 0 ([f645017](https://github.com/folke/which-key.nvim/commit/f64501787bebe9ff28c10dbe470ffad5dd017769)) * show/hide a fake cursor when WK is open ([0f53f40](https://github.com/folke/which-key.nvim/commit/0f53f40c1b827d35771c82a5c47c5a54d9408f7c)) * spelling suggestion plugin ([4b74f21](https://github.com/folke/which-key.nvim/commit/4b74f218f4541991a40719286f96cce9447a89c4)) * support for custom text object completion. Fixes [#10](https://github.com/folke/which-key.nvim/issues/10) ([394ff5a](https://github.com/folke/which-key.nvim/commit/394ff5a37bab051857de4216ee25db2284de2196)) * support opts.remap for keymap ([#339](https://github.com/folke/which-key.nvim/issues/339)) ([6885b66](https://github.com/folke/which-key.nvim/commit/6885b669523ff4238de99a7c653d47b081b5506d)) * support using lua function for expr ([#110](https://github.com/folke/which-key.nvim/issues/110)) ([e0dce15](https://github.com/folke/which-key.nvim/commit/e0dce1552ea37964ae6ac7144709867544eae7f3)) * text objects ([d255b71](https://github.com/folke/which-key.nvim/commit/d255b71992494ce4998caae7fe281144fb669abb)) * WhichKey vim command to show arbitrary keymaps ([df615d4](https://github.com/folke/which-key.nvim/commit/df615d44987a8bfe8910c618164f696e227ecfd4)) ### Bug Fixes * :norm .. commands keep feeding <esc> at the end of the command [#58](https://github.com/folke/which-key.nvim/issues/58) ([d66ffdd](https://github.com/folke/which-key.nvim/commit/d66ffdd5a845c713f581ac6da36173e88096e0fa)) * add delay option to macro key ([#152](https://github.com/folke/which-key.nvim/issues/152)) ([#156](https://github.com/folke/which-key.nvim/issues/156)) ([bd226c4](https://github.com/folke/which-key.nvim/commit/bd226c4d02d7f360747364a59cc5f0da50524f2c)) * add remaining <esc> to pending in case there's no other characters ([29a82b5](https://github.com/folke/which-key.nvim/commit/29a82b575b9752a45b005327030948ce8cb513a0)) * add triggers for other modes in marks and register plugin ([#116](https://github.com/folke/which-key.nvim/issues/116)) ([bbfc640](https://github.com/folke/which-key.nvim/commit/bbfc640c44612d705f4b0670ec1387c8a6ff2c7c)) * added @ trigger for showing registers ([01b6676](https://github.com/folke/which-key.nvim/commit/01b66769480fac14f6efa7c31327234398d05837)) * added builtin plugins to config ([6e461ca](https://github.com/folke/which-key.nvim/commit/6e461caec3d3aa43f1fa2b7890b299705bccfe8d)) * added hidden option to disable the popup on motion counts (motions.count) ([ea975ef](https://github.com/folke/which-key.nvim/commit/ea975ef254f10c4938cd663a7c4fb14e2d7514c0)) * added support for operator pending keymaps ([1f6b510](https://github.com/folke/which-key.nvim/commit/1f6b510f6ef0c223b51f3599200bbf6abc30f909)) * added z= for spelling correction ([59603de](https://github.com/folke/which-key.nvim/commit/59603dee2f67f623a520148d60c634f6f56f6017)) * always escape <leader> when it's a backslash ([41636a3](https://github.com/folke/which-key.nvim/commit/41636a3be909af5d20d811f8ce6a304a5ee3cc21)) * always execute keys with remap, but unhook / hook WK triggers (Fixes [#8](https://github.com/folke/which-key.nvim/issues/8)) ([bf329df](https://github.com/folke/which-key.nvim/commit/bf329df0ee11d6c80c7208b40eab74368e963245)) * always map <leader>, even without register ([512631c](https://github.com/folke/which-key.nvim/commit/512631c1bdce96dd048115cb139ea3a8452a931a)) * always unhook and ignore errors ([01a60cd](https://github.com/folke/which-key.nvim/commit/01a60cd5929b395042c8ba3d872f6f25ccd55ecb)) * always use noremap=false for <plug> commands ([9b9cece](https://github.com/folke/which-key.nvim/commit/9b9cece006b78ff7527a35285a4b5c1359d70fd8)) * always use word under the cursor for spelling suggestions ([c5b19ec](https://github.com/folke/which-key.nvim/commit/c5b19ecf4d1d8f8c77ee982caf9792740f6d5e53)) * better handling of weird norm and getchar endless <esc> bug [#68](https://github.com/folke/which-key.nvim/issues/68) ([bfd37e9](https://github.com/folke/which-key.nvim/commit/bfd37e93761d622328c673828b537d5671389413)) * better sorting ([99e8940](https://github.com/folke/which-key.nvim/commit/99e894032afbe2543dbbf9bba05518d96b852aa0)) * center alignemnt should be an integer ([db85198](https://github.com/folke/which-key.nvim/commit/db851981595fc360e9b6196a7c3995611aceac3b)) * check for FloatBorder before setting winhighlight ([af6b91d](https://github.com/folke/which-key.nvim/commit/af6b91dc09e4ed830d8cd4a3652a5b3f80ccefac)) * check is hook exists before unhooking ([f6cf3a2](https://github.com/folke/which-key.nvim/commit/f6cf3a2e49c09aba739c0f6fc85d3aebf2b96cb6)) * cmd can be nil ([060a574](https://github.com/folke/which-key.nvim/commit/060a574c228433e9b17960fa0eafca0a975381e8)) * **colors:** Separator links to DiffAdd ([#302](https://github.com/folke/which-key.nvim/issues/302)) ([a2749c5](https://github.com/folke/which-key.nvim/commit/a2749c5b039ad34734c98f8752b9fb5da7ceac55)) * Compatibility with Visual Multi plug ([#278](https://github.com/folke/which-key.nvim/issues/278)) ([92916b6](https://github.com/folke/which-key.nvim/commit/92916b6cede0ffd7d5c1ce9abad93ec0c4d9635e)) * convert trings with strtrans to properly render non printable characters ([d85ce36](https://github.com/folke/which-key.nvim/commit/d85ce3627f4060f622e4c0a9657f26c0151829de)) * correct floating window position in Neovim 0.6 nightly ([#176](https://github.com/folke/which-key.nvim/issues/176)) ([a35a910](https://github.com/folke/which-key.nvim/commit/a35a910d28683294fd23d35dd03c06f6f7c37b17)) * correctly handle counts before commands [#17](https://github.com/folke/which-key.nvim/issues/17) ([4feb319](https://github.com/folke/which-key.nvim/commit/4feb319ff89fb8659efa2a788f808bc390afa490)) * correctly unhook buffer local mappings before executing keys ([4f98b47](https://github.com/folke/which-key.nvim/commit/4f98b4713ea9d4534662ceb7b542b0626eeb9ea8)) * disable folding on whichkey popup. Fixes [#99](https://github.com/folke/which-key.nvim/issues/99) ([78821de](https://github.com/folke/which-key.nvim/commit/78821de0b633275d6934660e67989639bc7a784c)) * disable operator pending maps for now ([#2](https://github.com/folke/which-key.nvim/issues/2)) ([0cd66a8](https://github.com/folke/which-key.nvim/commit/0cd66a84520fc0e7e3eec81f081157541cb48dbd)) * do feedkeys in correct mode when dealing with operator pending commands. Fixes [#8](https://github.com/folke/which-key.nvim/issues/8) ([cf30788](https://github.com/folke/which-key.nvim/commit/cf307886b68ed53334ffdcee809a751376269e33)) * don't show <esc> mappings since closes the popup ([09db756](https://github.com/folke/which-key.nvim/commit/09db756b5d357767a635a4d169e2e820b2962ea8)) * don't show spelling when the command was started with a count [#80](https://github.com/folke/which-key.nvim/issues/80) ([20a85bd](https://github.com/folke/which-key.nvim/commit/20a85bd8bc54a11cf040aafa5d60f8a735eecfbd)) * dont do feedkeys when user uses WhichKey command with non existing prefix ([f9537ce](https://github.com/folke/which-key.nvim/commit/f9537ce0f7457665e3b90d82c5f3f2c37fe0506f)) * dont pass zero counts ([0c3cfb0](https://github.com/folke/which-key.nvim/commit/0c3cfb0064ceec5b182bac580033e0654d9575e6)) * dont show errors about loading order of setup and register ([2adbc17](https://github.com/folke/which-key.nvim/commit/2adbc17e00061073f2c2a40b6420ee2a80ea458d)) * explicitely check if we try to execute an auto which-key mapping. shouldn't happen, but still safer to check ([30fdd46](https://github.com/folke/which-key.nvim/commit/30fdd465433d48cab3b1f894daf52fa0005cf7ac)) * expose presets so one can change them if needed [#70](https://github.com/folke/which-key.nvim/issues/70) ([46ea686](https://github.com/folke/which-key.nvim/commit/46ea686c6cc9bfc96bc492c76a76d43548a587c4)) * feed CTRL-O again if called from CTRL-O ([#145](https://github.com/folke/which-key.nvim/issues/145)) ([833b5ea](https://github.com/folke/which-key.nvim/commit/833b5ea1a0d4b3bddf4b5c68fc89f1234960edec)) * feed the keys as typed ([#333](https://github.com/folke/which-key.nvim/issues/333)) ([33b4e72](https://github.com/folke/which-key.nvim/commit/33b4e72a07546bc4798b4bafb99ae06df47bd790)) * fix flickering on tmux ([f112602](https://github.com/folke/which-key.nvim/commit/f11260251ad942ba1635db9bc25c2efaf75caf0a)) * fix issue when cmdheight=0 [#301](https://github.com/folke/which-key.nvim/issues/301) ([#305](https://github.com/folke/which-key.nvim/issues/305)) ([9cd09ca](https://github.com/folke/which-key.nvim/commit/9cd09ca6bbe5acfbce86ca023fdc720f6aa132d6)) * fixed 0 after an operator. Wrongly assumed any number to be a count for following op mode, but not the case for 0 [#59](https://github.com/folke/which-key.nvim/issues/59) [#61](https://github.com/folke/which-key.nvim/issues/61) ([36616ca](https://github.com/folke/which-key.nvim/commit/36616cacba5d9eb716017bf23b7bbbe4cb4a6822)) * fixed possible nil error when showing marks ([b44fc09](https://github.com/folke/which-key.nvim/commit/b44fc095f6d0144278f3413533ad2d40ae664229)) * for sporadic loss of lua function for mapping ([#216](https://github.com/folke/which-key.nvim/issues/216)) ([312c386](https://github.com/folke/which-key.nvim/commit/312c386ee0eafc925c27869d2be9c11ebdb807eb)) * formatting of text-objects plugin ([442d2d3](https://github.com/folke/which-key.nvim/commit/442d2d383284390c5ee1b922036fc10fff530b2d)) * get value of register '=' with getreg('=',1) ([#114](https://github.com/folke/which-key.nvim/issues/114)) ([6224ea8](https://github.com/folke/which-key.nvim/commit/6224ea81f505c66a9644f89129149b108f722e56)) * handle backslash as localleader [#47](https://github.com/folke/which-key.nvim/issues/47) ([cd23fdc](https://github.com/folke/which-key.nvim/commit/cd23fdc1b0cbdb22769bed5cb275a6d1c4bd9bfc)) * handle baskslashes when leader or localleader isn't set ([d155ab3](https://github.com/folke/which-key.nvim/commit/d155ab3bef11a8156995b47d5552586e5c9f66a3)) * handle keymaps with a <nop> rhs as non existing and possibly overwrite them with WK hooks [#35](https://github.com/folke/which-key.nvim/issues/35) ([402be18](https://github.com/folke/which-key.nvim/commit/402be18dc656897b1dc68c88fab4ffe8635b8209)) * handle nvim_{buf_}get_keymap return no rhs due to 'callback' mapping ([#223](https://github.com/folke/which-key.nvim/issues/223)) ([28d2bd1](https://github.com/folke/which-key.nvim/commit/28d2bd129575b5e9ebddd88506601290bb2bb221)) * handle possible errors when getting last expression register [#64](https://github.com/folke/which-key.nvim/issues/64) ([7a1be6f](https://github.com/folke/which-key.nvim/commit/7a1be6ff950c7fb94a4f9e9bdb428a514e569503)) * highlighting of line number in marks ([9997d93](https://github.com/folke/which-key.nvim/commit/9997d93e5adcf0352aa73c42d3c395ba775600e9)) * immediately show registers and marks. Fixes [#144](https://github.com/folke/which-key.nvim/issues/144) ([653ce71](https://github.com/folke/which-key.nvim/commit/653ce711e6c27416ac79c4811ff814e9a38fddcf)) * link default WhichKeyBorder to FloatBorder. Fixes [#331](https://github.com/folke/which-key.nvim/issues/331) ([1698d6d](https://github.com/folke/which-key.nvim/commit/1698d6d0ff0b00b8499d9aea8715d120dc526900)) * make register selection work in INSERT mode ([d4315f8](https://github.com/folke/which-key.nvim/commit/d4315f8991da816c30e9387a891c02774552dc36)) * make spelling suggestions also work for correctly spelled words ([d02dc34](https://github.com/folke/which-key.nvim/commit/d02dc344bdaf273dfde7672f3f8e70a307593f62)) * make sure we never accidentally show WK triggers ([197b4d3](https://github.com/folke/which-key.nvim/commit/197b4d3403c04c0045e8d541e8cd2504aba5f168)) * make which-key's lazy loading work when it is also lazy-loaded ([7d929b9](https://github.com/folke/which-key.nvim/commit/7d929b96e2588fe9710ad795402eaead1aa0f70f)) * manual command now uses proper escaping for prefix ([334fcca](https://github.com/folke/which-key.nvim/commit/334fcca64611dbca8c0c669260f4fb2a8ff81509)) * mapleader=\ ([b5c8985](https://github.com/folke/which-key.nvim/commit/b5c89851d580459c1dd33ecbda611ae06e22eec4)) * mapping when right-hand side is `nil` ([#323](https://github.com/folke/which-key.nvim/issues/323)) ([1d449d4](https://github.com/folke/which-key.nvim/commit/1d449d44e01787ef17dc7b0672eec01a8121b36e)) * never hook in SELECT mode and properly handle v, x, s [#45](https://github.com/folke/which-key.nvim/issues/45) [#46](https://github.com/folke/which-key.nvim/issues/46) ([2844e1c](https://github.com/folke/which-key.nvim/commit/2844e1cbf298129afa58c13a90f91be907232dbf)) * never hook j and k in INSERT mode automatcally to prevent jk kj <ESC> mappings to work as intended ([9a2faed](https://github.com/folke/which-key.nvim/commit/9a2faed055459d3226634344468f78bf85d77fa8)) * never hook numbers. locks up due to v:count. Fixes [#118](https://github.com/folke/which-key.nvim/issues/118) ([2d2954a](https://github.com/folke/which-key.nvim/commit/2d2954a1d05b4f074e022e64db9aa6093d439bb0)) * never hook on <esc> ([fd08322](https://github.com/folke/which-key.nvim/commit/fd0832233bd0c733618fab1c3df92f261c13d6b3)) * never hook q [#63](https://github.com/folke/which-key.nvim/issues/63) ([95ae9d2](https://github.com/folke/which-key.nvim/commit/95ae9d2d00e8714379e64994e69ae17fc540a7d6)) * never hook to operators in visual mode [#61](https://github.com/folke/which-key.nvim/issues/61) ([43d799a](https://github.com/folke/which-key.nvim/commit/43d799ad0e6218964e802ff342ca5f9352105175)) * nil in health check ([5c018ae](https://github.com/folke/which-key.nvim/commit/5c018ae412b235abe17e24b46057564db0944dc4)) * nvim_win_close force = true ([ca73a0e](https://github.com/folke/which-key.nvim/commit/ca73a0e03f142067a16891b712c7ea73ac646dff)) * nvim-0.7.0 check ([#338](https://github.com/folke/which-key.nvim/issues/338)) ([1491c35](https://github.com/folke/which-key.nvim/commit/1491c355ec9bb0ec4c8e71c8625bc5f55a54b925)) * only create mappings for builtin operators. plugings will always have their own mappings ([1b2ec76](https://github.com/folke/which-key.nvim/commit/1b2ec760d65ce9eda473879bec5c31c4771079e7)) * only enable plugins that are specified in the configuration ([b8ed0e8](https://github.com/folke/which-key.nvim/commit/b8ed0e8e675b747ce21aa830c38ddf4fb2458e05)) * only show message about existing <leader> mapping in NORMAL mode [#75](https://github.com/folke/which-key.nvim/issues/75) ([bcc8297](https://github.com/folke/which-key.nvim/commit/bcc829775b7d366f61bd2db1753e2c6b3d1ec4d3)) * only show up/down when scrolling is posible (fixes [#4](https://github.com/folke/which-key.nvim/issues/4)) ([9e7986d](https://github.com/folke/which-key.nvim/commit/9e7986d8726291ee93ef448ae8c452981f1fc75f)) * override <leader> if it's mapped to ([928288b](https://github.com/folke/which-key.nvim/commit/928288b543d77c38ade936ee8bdef32a769ebe3a)) * pass + and * regsiters to feedkeys [#36](https://github.com/folke/which-key.nvim/issues/36) ([ce37f41](https://github.com/folke/which-key.nvim/commit/ce37f41641edb90bf51b975999553d13961ed8fa)) * pass 0 instead of nil for current buffer ([#227](https://github.com/folke/which-key.nvim/issues/227)) ([387fd67](https://github.com/folke/which-key.nvim/commit/387fd676d3f9b419d38890820f6e262dc0fadb46)) * passing registers in INSERT mode, is not by pasting them 😅 [#62](https://github.com/folke/which-key.nvim/issues/62) ([342c8cd](https://github.com/folke/which-key.nvim/commit/342c8cdb3651967c96c356eb2d79561c0c9273ee)) * place popup correctly respecting cmdheight [#28](https://github.com/folke/which-key.nvim/issues/28) ([490e4d5](https://github.com/folke/which-key.nvim/commit/490e4d55315b74c63a63ada89ecf0e660a94db9a)) * possible nil value in health check ([b1627ca](https://github.com/folke/which-key.nvim/commit/b1627caa25e24c580bbc88377942353875f93a41)) * possible recursion ([f7fef32](https://github.com/folke/which-key.nvim/commit/f7fef32701aba0a822ac0a82679aea454bec702f)) * prevent double escaping of key codes ([1676611](https://github.com/folke/which-key.nvim/commit/167661151204ea7da2d365113a76ab223b3dc880)) * properly escape sequence ([2473329](https://github.com/folke/which-key.nvim/commit/24733293bb7b28f3d98d4a88323eb13cbe5b46f2)) * properly escape terminal chars to see if we already hooked a trigger ([1bee8a1](https://github.com/folke/which-key.nvim/commit/1bee8a151e72e5738d813964492248c9bbc4c5ba)) * properly format unicode text in columns (fixes [#66](https://github.com/folke/which-key.nvim/issues/66)) ([e3066fa](https://github.com/folke/which-key.nvim/commit/e3066facb6ed91ac013e4ff8faf24997ed44459c)) * properly handle < chatracters (should be [#40](https://github.com/folke/which-key.nvim/issues/40) ([c4a59d7](https://github.com/folke/which-key.nvim/commit/c4a59d76135563ea73beb87cf0d6d7a3302563be)) * start of visual selection mark should be <lt> instead of < [#69](https://github.com/folke/which-key.nvim/issues/69) ([840311c](https://github.com/folke/which-key.nvim/commit/840311c272eda2c4fc0d92070e9ef2dd13f884e7)) * typo ([4bacbfd](https://github.com/folke/which-key.nvim/commit/4bacbfdacb9eebee339d36243fe17b9185ccbb74)) * use buffer instead of bufnr + added warning ([df49a59](https://github.com/folke/which-key.nvim/commit/df49a59efdfd6a90f412aa251914183fec8593af)) * use Comment as fallback color for the Separator ([7ee35a7](https://github.com/folke/which-key.nvim/commit/7ee35a7614e34e562fd3f815ad35bd6d7e456093)) * use config.key_labels for cmdline trail as well (Fixes [#108](https://github.com/folke/which-key.nvim/issues/108)) ([1872dd8](https://github.com/folke/which-key.nvim/commit/1872dd8ca9daa0f6478a7771087aedae8518cb97)) * use mode instead of redraw when cmdheight=0. (Fixes [#327](https://github.com/folke/which-key.nvim/issues/327)) ([c966279](https://github.com/folke/which-key.nvim/commit/c96627900191355e6788629bbf5239d7295221f0)) * use secret nop bindings to make sure timeoutlen is always respected ([eccd5f8](https://github.com/folke/which-key.nvim/commit/eccd5f8bf22e60620eee833946638b90552c9b69)) * use strwidth instead of strdisplaywidth ([386591e](https://github.com/folke/which-key.nvim/commit/386591e24afe88c1c52c2291d450e7d7ad9cf02a)) ### Performance Improvements * as long as we didnt finish loading, queue registers ([1bac978](https://github.com/folke/which-key.nvim/commit/1bac978464fd00dddbeee9c5584120f553b1a660)) * defer loading to VimEnter and only process hooks once when ready ([84ddcdc](https://github.com/folke/which-key.nvim/commit/84ddcdcd862c4bb6dcac84a876f66f9777ecef7c)) * no need to create triggers for all levels. first level that is not a cmd is enough ([3cc0424](https://github.com/folke/which-key.nvim/commit/3cc042498db5792b8f3b081310926c779c7aac07)) * no need to hook buffer-local if we have a global hook for a certain prefix ([bb5e0d9](https://github.com/folke/which-key.nvim/commit/bb5e0d9be9c73b7d343ff4bf0ffbb9b6b4696811)) * only load modules when needed ([6f8ae23](https://github.com/folke/which-key.nvim/commit/6f8ae23540bc5f980862d2d5aa6d3c02bb1e2da0)) folke-which-key.nvim-fcbf4ee/LICENSE000066400000000000000000000261351475635520600173410ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. folke-which-key.nvim-fcbf4ee/NEWS.md000066400000000000000000000036341475635520600174310ustar00rootroot00000000000000# 💥 What's New in 3.0? Major update for [which-key.nvim](https://github.com/folke/which-key.nvim)! This release includes a complete rewrite and several new features. **which-key** was my very first plugin, so it was time for a fresh start. 🎉 - ✨ **Full Rewrite**: Improved performance and functionality. - 👀 **Visual & Operator Pending Mode Integration**: Now uses `ModeChanged`, eliminating the need for operator remappings. - 🔧 **Simplified Mappings**: Removed obscure secret mappings. - 🔒 **Safer Auto Triggers**: Auto triggers are now never created for single keys apart from `g` and `z`. All other letters are unsafe. - ⏱️ **Delay**: Set delay independently of `timeoutlen`. - 🛠️ **Layout**: - Presets: `classic`, `modern`, and `helix`. - Enable/disable which-key for specific modes. - Configurable sorting with options like `local`, `order`, `group`, `alphanum`, `mod`, `lower`, `icase`, `desc`, and `manual`. - Expand groups with fewer keymaps. - Customizable string replacements for `key` and `desc`. - 🎨 **Icon Support**: - Auto-detect icons for keymaps using `lazy.nvim`. - Custom icon rules and specifications for mapping levels. - 🚫 **Never Get in the Way**: Avoids overlapping with the cursor. - 🗂️ **New Mapping Spec**: New and better mappings spec, more in line with `vim.keymap.set` and how you define keymaps with [lazy.nvim](https://github.com/folke/lazy.nvim) - 🐛 New Bugs: Lots of new and exciting bugs to discover! 🐞 ## Screenshots **Classic Mode** ![image](https://github.com/folke/which-key.nvim/assets/292349/14195bd3-1015-4c44-81c6-4ef8f2410c1b) **Modern Mode** ![image](https://github.com/folke/which-key.nvim/assets/292349/842e9311-ded9-458a-bed4-2b12f075c85f) **Helix Mode** ![image](https://github.com/folke/which-key.nvim/assets/292349/ca553e0c-e92d-4968-9dce-de91601c5c5c) For detailed configuration and usage instructions, refer to the updated README. folke-which-key.nvim-fcbf4ee/README.md000066400000000000000000000404471475635520600176150ustar00rootroot00000000000000# 💥 Which Key **WhichKey** helps you remember your Neovim keymaps, by showing available keybindings in a popup as you type. ![image](https://github.com/user-attachments/assets/89277334-dcdc-4b0f-9fd4-02f27012f589) ![image](https://github.com/user-attachments/assets/f8d71a75-312e-4a42-add8-d153493b2633) ![image](https://github.com/user-attachments/assets/e4400a1d-7e71-4439-b6ff-6cbc40647a6f) ## ✨ Features - 🔍 **Key Binding Help**: show available keybindings in a popup as you type. - ⌨️ **Modes**: works in normal, insert, visual, operator pending, terminal and command mode. Every mode can be enabled/disabled. - 🛠️ **Customizable Layouts**: choose from `classic`, `modern`, and `helix` presets or customize the window. - 🔄 **Flexible Sorting**: sort by `local`, `order`, `group`, `alphanum`, `mod`, `lower`, `icase`, `desc`, or `manual`. - 🎨 **Formatting**: customizable key labels and descriptions - 🖼️ **Icons**: integrates with [mini.icons](https://github.com/echasnovski/mini.icons) and [nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons) - ⏱️ **Delay**: delay is independent of `timeoutlen` - 🌐 **Plugins**: built-in plugins for marks, registers, presets, and spelling suggestions - 🚀 **Operators, Motions, Text Objects**: help for operators, motions and text objects - 🐙 **Hydra Mode**: keep the popup open until you hit `` ## ⚡️ Requirements - **Neovim** >= 0.9.4 - for proper icons support: - [mini.icons](https://github.com/echasnovski/mini.icons) _(optional)_ - [nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons) _(optional)_ - a [Nerd Font](https://www.nerdfonts.com/) **_(optional)_** ## 📦 Installation Install the plugin with your package manager: ### [lazy.nvim](https://github.com/folke/lazy.nvim) ```lua { "folke/which-key.nvim", event = "VeryLazy", opts = { -- your configuration comes here -- or leave it empty to use the default settings -- refer to the configuration section below }, keys = { { "?", function() require("which-key").show({ global = false }) end, desc = "Buffer Local Keymaps (which-key)", }, }, } ``` ## ⚙️ Configuration > [!important] > Make sure to run `:checkhealth which-key` if something isn't working properly **WhichKey** is highly configurable. Expand to see the list of all the default options below.
Default Options ```lua ---@class wk.Opts local defaults = { ---@type false | "classic" | "modern" | "helix" preset = "classic", -- Delay before showing the popup. Can be a number or a function that returns a number. ---@type number | fun(ctx: { keys: string, mode: string, plugin?: string }):number delay = function(ctx) return ctx.plugin and 0 or 200 end, ---@param mapping wk.Mapping filter = function(mapping) -- example to exclude mappings without a description -- return mapping.desc and mapping.desc ~= "" return true end, --- You can add any mappings here, or use `require('which-key').add()` later ---@type wk.Spec spec = {}, -- show a warning when issues were detected with your mappings notify = true, -- Which-key automatically sets up triggers for your mappings. -- But you can disable this and setup the triggers manually. -- Check the docs for more info. ---@type wk.Spec triggers = { { "", mode = "nxso" }, }, -- Start hidden and wait for a key to be pressed before showing the popup -- Only used by enabled xo mapping modes. ---@param ctx { mode: string, operator: string } defer = function(ctx) return ctx.mode == "V" or ctx.mode == "" end, plugins = { marks = true, -- shows a list of your marks on ' and ` registers = true, -- shows your registers on " in NORMAL or in INSERT mode -- the presets plugin, adds help for a bunch of default keybindings in Neovim -- No actual key bindings are created spelling = { enabled = true, -- enabling this will show WhichKey when pressing z= to select spelling suggestions suggestions = 20, -- how many suggestions should be shown in the list? }, presets = { operators = true, -- adds help for operators like d, y, ... motions = true, -- adds help for motions text_objects = true, -- help for text objects triggered after entering an operator windows = true, -- default bindings on nav = true, -- misc bindings to work with windows z = true, -- bindings for folds, spelling and others prefixed with z g = true, -- bindings for prefixed with g }, }, ---@type wk.Win.opts win = { -- don't allow the popup to overlap with the cursor no_overlap = true, -- width = 1, -- height = { min = 4, max = 25 }, -- col = 0, -- row = math.huge, -- border = "none", padding = { 1, 2 }, -- extra window padding [top/bottom, right/left] title = true, title_pos = "center", zindex = 1000, -- Additional vim.wo and vim.bo options bo = {}, wo = { -- winblend = 10, -- value between 0-100 0 for fully opaque and 100 for fully transparent }, }, layout = { width = { min = 20 }, -- min and max width of the columns spacing = 3, -- spacing between columns }, keys = { scroll_down = "", -- binding to scroll down inside the popup scroll_up = "", -- binding to scroll up inside the popup }, ---@type (string|wk.Sorter)[] --- Mappings are sorted using configured sorters and natural sort of the keys --- Available sorters: --- * local: buffer-local mappings first --- * order: order of the items (Used by plugins like marks / registers) --- * group: groups last --- * alphanum: alpha-numerical first --- * mod: special modifier keys last --- * manual: the order the mappings were added --- * case: lower-case first sort = { "local", "order", "group", "alphanum", "mod" }, ---@type number|fun(node: wk.Node):boolean? expand = 0, -- expand groups when <= n mappings -- expand = function(node) -- return not node.desc -- expand all nodes without a description -- end, -- Functions/Lua Patterns for formatting the labels ---@type table replace = { key = { function(key) return require("which-key.view").format(key) end, -- { "", "SPC" }, }, desc = { { "%(?(.*)%)?", "%1" }, { "^%+", "" }, { "<[cC]md>", "" }, { "<[cC][rR]>", "" }, { "<[sS]ilent>", "" }, { "^lua%s+", "" }, { "^call%s+", "" }, { "^:%s*", "" }, }, }, icons = { breadcrumb = "»", -- symbol used in the command line area that shows your active key combo separator = "➜", -- symbol used between a key and it's label group = "+", -- symbol prepended to a group ellipsis = "…", -- set to false to disable all mapping icons, -- both those explicitly added in a mapping -- and those from rules mappings = true, --- See `lua/which-key/icons.lua` for more details --- Set to `false` to disable keymap icons from rules ---@type wk.IconRule[]|false rules = {}, -- use the highlights from mini.icons -- When `false`, it will use `WhichKeyIcon` instead colors = true, -- used by key format keys = { Up = " ", Down = " ", Left = " ", Right = " ", C = "󰘴 ", M = "󰘵 ", D = "󰘳 ", S = "󰘶 ", CR = "󰌑 ", Esc = "󱊷 ", ScrollWheelDown = "󱕐 ", ScrollWheelUp = "󱕑 ", NL = "󰌑 ", BS = "󰁮", Space = "󱁐 ", Tab = "󰌒 ", F1 = "󱊫", F2 = "󱊬", F3 = "󱊭", F4 = "󱊮", F5 = "󱊯", F6 = "󱊰", F7 = "󱊱", F8 = "󱊲", F9 = "󱊳", F10 = "󱊴", F11 = "󱊵", F12 = "󱊶", }, }, show_help = true, -- show a help message in the command line for using WhichKey show_keys = true, -- show the currently pressed key and its label as a message in the command line -- disable WhichKey for certain buf types and file types. disable = { ft = {}, bt = {}, }, debug = false, -- enable wk.log in the current directory } ```
## ⌨️ Mappings **WhichKey** automatically gets the descriptions of your keymaps from the `desc` attribute of the keymap. So for most use-cases, you don't need to do anything else. However, the **mapping spec** is still useful to configure group descriptions and mappings that don't really exist as a regular keymap. > [!WARNING] > The **mappings spec** changed in `v3`, so make sure to only use the new `add` method if > you updated your existing mappings. Mappings can be added as part of the config `opts.spec`, or can be added later using `require("which-key").add()`. `wk.add()` can be called multiple times from anywhere in your config files. A mapping has the following attributes: - **[1]**: (`string`) lhs **_(required)_** - **[2]**: (`string|fun()`) rhs **_(optional)_**: when present, it will create the mapping - **desc**: (`string|fun():string`) description **_(required for non-groups)_** - **group**: (`string|fun():string`) group name **_(optional)_** - **mode**: (`string|string[]`) mode **_(optional, defaults to `"n"`)_** - **cond**: (`boolean|fun():boolean`) condition to enable the mapping **_(optional)_** - **hidden**: (`boolean`) hide the mapping **_(optional)_** - **icon**: (`string|wk.Icon|fun():(wk.Icon|string)`) icon spec **_(optional)_** - **proxy**: (`string`) proxy to another mapping **_(optional)_** - **expand**: (`fun():wk.Spec`) nested mappings **_(optional)_** - any other option valid for `vim.keymap.set`. These are only used for creating mappings. When `desc`, `group`, or `icon` are functions, they are evaluated every time the popup is shown. The `expand` property allows to create dynamic mappings. Only functions as `rhs` are supported for dynamic mappings. Two examples are included in `which-key.extras`: - `require("which-key.extras").expand.buf`: creates numerical key to buffer mappings - `require("which-key.extras").expand.win`: creates numerical key to window mappings ```lua local wk = require("which-key") wk.add({ { "f", group = "file" }, -- group { "ff", "Telescope find_files", desc = "Find File", mode = "n" }, { "fb", function() print("hello") end, desc = "Foobar" }, { "fn", desc = "New File" }, { "f1", hidden = true }, -- hide this keymap { "w", proxy = "", group = "windows" }, -- proxy to window mappings { "b", group = "buffers", expand = function() return require("which-key.extras").expand.buf() end }, { -- Nested mappings are allowed and can be added in any order -- Most attributes can be inherited or overridden on any level -- There's no limit to the depth of nesting mode = { "n", "v" }, -- NORMAL and VISUAL mode { "q", "q", desc = "Quit" }, -- no need to specify mode since it's inherited { "w", "w", desc = "Write" }, } }) ``` ## 🎯 Triggers There's two ways that **which-key** can be triggered: - by a trigger keymap - by a `ModeChanged` event for visual and operator pending mode Both can be configured using `opts.triggers` and `opts.defer`. By default `opts.triggers` includes `{ "", mode = "nixsotc" }`, which will setup keymap triggers for every mode automatically and will trigger during `ModeChanged`. > [!NOTE] > Auto triggers will never be created for existing keymaps. > That includes every valid single key Neovim builtin mapping. > If you want to trigger on a builtin keymap, you have to add it manually. > > ```lua > triggers = { > { "", mode = "nixsotc" }, > { "a", mode = { "n", "v" } }, > } > ``` > [!TIP] > To manually setup triggers, you can set `opts.triggers` to: > > ```lua > triggers = { > { "", mode = { "n", "v" } }, > } > ``` For `ModeChanged` triggers, you can configure the `opts.defer` option. When it returns `true`, the popup will be shown only after an additional key is pressed. So `yaf`, would show which-key after pressing `ya`, but not after `y`. > [!TIP] > Defer some operators: > > ```lua > ---@param ctx { mode: string, operator: string } > defer = function(ctx) > if vim.list_contains({ "d", "y" }, ctx.operator) then > return true > end > return vim.list_contains({ "", "V" }, ctx.mode) > end, > ``` ## 🎨 Icons > [!note] > For full support, you need to install either [mini.icons](https://github.com/echasnovski/mini.icons) or [nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons) There's multiple ways to set icons for your keymaps: - if you use lazy.nvim, then some icons will be autodetected for keymaps belonging to certain plugins. - custom rules to decide what icon to use - in your mapping spec, you can specify what icon to use at any level, so at the node for `g` for example, to apply to all git keymaps. The `icon` attribute of a mapping can be a `string`, which will be used as the actual icon, or an `wk.Icon` object, which can have the following attributes: - `icon` (`string`): the icon to use **_(optional)_** - `hl` (`string`): the highlight group to use for the icon **_(optional)_** - `color` (`string`): the color to use for the icon **_(optional)_** valid colors are: `azure`, `blue`, `cyan`, `green`, `grey`, `orange`, `purple`, `red`, `yellow` - `cat` (`string`): the category of the icon **_(optional)_** valid categories are: `file`, `filetype`, `extension` - `name` (`string`): the name of the icon in the specified category **_(optional)_** > [!TIP] > If you'd rather not use icons, you can disable them > by setting `opts.icons.mappings` to `false`. ## 🚀 Usage When the **WhichKey** popup is open, you can use the following key bindings (they are also displayed at the bottom of the screen): - hit one of the keys to open a group or execute a key binding - `` to cancel and close the popup - `` go up one level - `` scroll down - `` scroll up ## 🐙 Hydra Mode Hydra mode is a special mode that keeps the popup open until you hit ``. ```lua -- Show hydra mode for changing windows require("which-key").show({ keys = "", loop = true, -- this will keep the popup open until you hit }) ``` ## 🔥 Plugins Four built-in plugins are included with **WhichKey**. ### Presets Built-in key binding help for `motions`, `text-objects`, `operators`, `windows`, `nav`, `z` and `g` and more. ### Marks Shows a list of your buffer local and global marks when you hit \` or ' ![image](https://github.com/user-attachments/assets/43fb0874-7f79-4521-aee9-03e2b0841758) ### Registers Shows a list of your buffer local and global registers when you hit " in _NORMAL_ mode, or `` in _INSERT_ mode. ![image](https://github.com/user-attachments/assets/d8077dcb-56fb-47b0-ad9e-1aba5db16950) ### Spelling When enabled, this plugin hooks into `z=` and replaces the full-screen spelling suggestions window by a list of suggestions within **WhichKey**. ![image](https://github.com/user-attachments/assets/102c7963-329a-40b9-b0a8-72c8656318b7) ## 🎨 Colors The table below shows all the highlight groups defined for **WhichKey** with their default link. | Highlight Group | Default Group | Description | | --- | --- | --- | | **WhichKey** | ***Function*** | | | **WhichKeyBorder** | ***FloatBorder*** | Border of the which-key window | | **WhichKeyDesc** | ***Identifier*** | description | | **WhichKeyGroup** | ***Keyword*** | group name | | **WhichKeyIcon** | ***@markup.link*** | icons | | **WhichKeyIconAzure** | ***Function*** | | | **WhichKeyIconBlue** | ***DiagnosticInfo*** | | | **WhichKeyIconCyan** | ***DiagnosticHint*** | | | **WhichKeyIconGreen** | ***DiagnosticOk*** | | | **WhichKeyIconGrey** | ***Normal*** | | | **WhichKeyIconOrange** | ***DiagnosticWarn*** | | | **WhichKeyIconPurple** | ***Constant*** | | | **WhichKeyIconRed** | ***DiagnosticError*** | | | **WhichKeyIconYellow** | ***DiagnosticWarn*** | | | **WhichKeyNormal** | ***NormalFloat*** | Normal in th which-key window | | **WhichKeySeparator** | ***Comment*** | the separator between the key and its description | | **WhichKeyTitle** | ***FloatTitle*** | Title of the which-key window | | **WhichKeyValue** | ***Comment*** | values by plugins (like marks, registers, etc) | folke-which-key.nvim-fcbf4ee/TODO.md000066400000000000000000000030041475635520600174110ustar00rootroot00000000000000# Todo - [x] create keymaps in register() - [x] distinction between actual keymap and just a desc - [x] virtual mappings wihtout real children? - [x] registers / counts? - [x] presets / plugins - [x] config? - [x] auto blacklist single keys for default keymaps (for mappings like `aa`, a hook would be created for `a` and `a` would be ignored) - [x] custom sorting - [x] gr doesn't work because of grn and friends - [x] same for gc opmode and gc normal mode - [x] yank and shift-paste hangs - [x] macro recording / macro execution - [x] spell - [x] spell with count, like `1z=` - [x] which-key-ignore - [x] empty groups? - [x] timeoutlen and nowait - [x] ui presets - [x] ui opts & columns etc - [x] scroll window - [x] help text? - [x] plugin layout? - [x] ✅ 🔥🔥🚀 - [x] minimize attach - [x] sometimes incorrectly attached `gcc` not working - [x] error handling for view - [x] spelling layout - [x] better mappings parser? Especially needs typings - [x] Mappings with mode `v` - [x] allow register from opts - [x] auto gen docs - [x] health - [x] `gh_` - [x] devicons support - [x] nowait, timeoutlen and delay - [x] new mappings DSL - [x] News - [x] normal mode mappings in terminal mode? - [x] dynamic size - [x] situation with visual mode - [x] fix timeoutlen - [x] document hydra mode - [x] floating help text? - [x] move old option check to checkhealth - [x] show scrolling hint when can't fit all mappings - [ ] more tests - [ ] hint characters in desc - [ ] intgerate with lazy.nvim. Get description there if set folke-which-key.nvim-fcbf4ee/doc/000077500000000000000000000000001475635520600170725ustar00rootroot00000000000000folke-which-key.nvim-fcbf4ee/doc/which-key.nvim.txt000066400000000000000000000474211475635520600225030ustar00rootroot00000000000000*which-key.nvim.txt* For Neovim Last change: 2025 February 14 ============================================================================== Table of Contents *which-key.nvim-table-of-contents* 1. Which Key |which-key.nvim-which-key| - Features |which-key.nvim-which-key-features| - Requirements |which-key.nvim-which-key-requirements| - Installation |which-key.nvim-which-key-installation| - Configuration |which-key.nvim-which-key-configuration| - Mappings |which-key.nvim-which-key-mappings| - Triggers |which-key.nvim-which-key-triggers| - Icons |which-key.nvim-which-key-icons| - Usage |which-key.nvim-which-key-usage| - Hydra Mode |which-key.nvim-which-key-hydra-mode| - Plugins |which-key.nvim-which-key-plugins| - Colors |which-key.nvim-which-key-colors| 2. Links |which-key.nvim-links| ============================================================================== 1. Which Key *which-key.nvim-which-key* **WhichKey** helps you remember your Neovim keymaps, by showing available keybindings in a popup as you type. FEATURES *which-key.nvim-which-key-features* - **Key Binding Help**show available keybindings in a popup as you type. - **Modes**works in normal, insert, visual, operator pending, terminal and command mode. Every mode can be enabled/disabled. - **Customizable Layouts**choose from `classic`, `modern`, and `helix` presets or customize the window. - **Flexible Sorting**sort by `local`, `order`, `group`, `alphanum`, `mod`, `lower`, `icase`, `desc`, or `manual`. - **Formatting**customizable key labels and descriptions - **Icons**integrates with mini.icons and nvim-web-devicons - **Delay**delay is independent of `timeoutlen` - **Plugins**built-in plugins for marks, registers, presets, and spelling suggestions - **Operators, Motions, Text Objects**help for operators, motions and text objects - **Hydra Mode**keep the popup open until you hit `` REQUIREMENTS *which-key.nvim-which-key-requirements* - **Neovim** >= 0.9.4 - for proper icons support: - mini.icons _(optional)_ - nvim-web-devicons _(optional)_ - a Nerd Font **(optional)** INSTALLATION *which-key.nvim-which-key-installation* Install the plugin with your package manager: LAZY.NVIM ~ >lua { "folke/which-key.nvim", event = "VeryLazy", opts = { -- your configuration comes here -- or leave it empty to use the default settings -- refer to the configuration section below }, keys = { { "?", function() require("which-key").show({ global = false }) end, desc = "Buffer Local Keymaps (which-key)", }, }, } < CONFIGURATION *which-key.nvim-which-key-configuration* [!important] Make sure to run `:checkhealth which-key` if something isn’t working properly **WhichKey** is highly configurable. Expand to see the list of all the default options below. Default Options ~ >lua ---@class wk.Opts local defaults = { ---@type false | "classic" | "modern" | "helix" preset = "classic", -- Delay before showing the popup. Can be a number or a function that returns a number. ---@type number | fun(ctx: { keys: string, mode: string, plugin?: string }):number delay = function(ctx) return ctx.plugin and 0 or 200 end, ---@param mapping wk.Mapping filter = function(mapping) -- example to exclude mappings without a description -- return mapping.desc and mapping.desc ~= "" return true end, --- You can add any mappings here, or use `require('which-key').add()` later ---@type wk.Spec spec = {}, -- show a warning when issues were detected with your mappings notify = true, -- Which-key automatically sets up triggers for your mappings. -- But you can disable this and setup the triggers manually. -- Check the docs for more info. ---@type wk.Spec triggers = { { "", mode = "nxso" }, }, -- Start hidden and wait for a key to be pressed before showing the popup -- Only used by enabled xo mapping modes. ---@param ctx { mode: string, operator: string } defer = function(ctx) return ctx.mode == "V" or ctx.mode == "" end, plugins = { marks = true, -- shows a list of your marks on ' and ` registers = true, -- shows your registers on " in NORMAL or in INSERT mode -- the presets plugin, adds help for a bunch of default keybindings in Neovim -- No actual key bindings are created spelling = { enabled = true, -- enabling this will show WhichKey when pressing z= to select spelling suggestions suggestions = 20, -- how many suggestions should be shown in the list? }, presets = { operators = true, -- adds help for operators like d, y, ... motions = true, -- adds help for motions text_objects = true, -- help for text objects triggered after entering an operator windows = true, -- default bindings on nav = true, -- misc bindings to work with windows z = true, -- bindings for folds, spelling and others prefixed with z g = true, -- bindings for prefixed with g }, }, ---@type wk.Win.opts win = { -- don't allow the popup to overlap with the cursor no_overlap = true, -- width = 1, -- height = { min = 4, max = 25 }, -- col = 0, -- row = math.huge, -- border = "none", padding = { 1, 2 }, -- extra window padding [top/bottom, right/left] title = true, title_pos = "center", zindex = 1000, -- Additional vim.wo and vim.bo options bo = {}, wo = { -- winblend = 10, -- value between 0-100 0 for fully opaque and 100 for fully transparent }, }, layout = { width = { min = 20 }, -- min and max width of the columns spacing = 3, -- spacing between columns }, keys = { scroll_down = "", -- binding to scroll down inside the popup scroll_up = "", -- binding to scroll up inside the popup }, ---@type (string|wk.Sorter)[] --- Mappings are sorted using configured sorters and natural sort of the keys --- Available sorters: --- * local: buffer-local mappings first --- * order: order of the items (Used by plugins like marks / registers) --- * group: groups last --- * alphanum: alpha-numerical first --- * mod: special modifier keys last --- * manual: the order the mappings were added --- * case: lower-case first sort = { "local", "order", "group", "alphanum", "mod" }, ---@type number|fun(node: wk.Node):boolean? expand = 0, -- expand groups when <= n mappings -- expand = function(node) -- return not node.desc -- expand all nodes without a description -- end, -- Functions/Lua Patterns for formatting the labels ---@type table replace = { key = { function(key) return require("which-key.view").format(key) end, -- { "", "SPC" }, }, desc = { { "%(?(.*)%)?", "%1" }, { "^%+", "" }, { "<[cC]md>", "" }, { "<[cC][rR]>", "" }, { "<[sS]ilent>", "" }, { "^lua%s+", "" }, { "^call%s+", "" }, { "^:%s*", "" }, }, }, icons = { breadcrumb = "»", -- symbol used in the command line area that shows your active key combo separator = "➜", -- symbol used between a key and it's label group = "+", -- symbol prepended to a group ellipsis = "…", -- set to false to disable all mapping icons, -- both those explicitly added in a mapping -- and those from rules mappings = true, --- See `lua/which-key/icons.lua` for more details --- Set to `false` to disable keymap icons from rules ---@type wk.IconRule[]|false rules = {}, -- use the highlights from mini.icons -- When `false`, it will use `WhichKeyIcon` instead colors = true, -- used by key format keys = { Up = " ", Down = " ", Left = " ", Right = " ", C = "󰘴 ", M = "󰘵 ", D = "󰘳 ", S = "󰘶 ", CR = "󰌑 ", Esc = "󱊷 ", ScrollWheelDown = "󱕐 ", ScrollWheelUp = "󱕑 ", NL = "󰌑 ", BS = "󰁮", Space = "󱁐 ", Tab = "󰌒 ", F1 = "󱊫", F2 = "󱊬", F3 = "󱊭", F4 = "󱊮", F5 = "󱊯", F6 = "󱊰", F7 = "󱊱", F8 = "󱊲", F9 = "󱊳", F10 = "󱊴", F11 = "󱊵", F12 = "󱊶", }, }, show_help = true, -- show a help message in the command line for using WhichKey show_keys = true, -- show the currently pressed key and its label as a message in the command line -- disable WhichKey for certain buf types and file types. disable = { ft = {}, bt = {}, }, debug = false, -- enable wk.log in the current directory } < MAPPINGS *which-key.nvim-which-key-mappings* **WhichKey** automatically gets the descriptions of your keymaps from the `desc` attribute of the keymap. So for most use-cases, you don’t need to do anything else. However, the **mapping spec** is still useful to configure group descriptions and mappings that don’t really exist as a regular keymap. [!WARNING] The **mappings spec** changed in `v3`, so make sure to only use the new `add` method if you updated your existing mappings. Mappings can be added as part of the config `opts.spec`, or can be added later using `require("which-key").add()`. `wk.add()` can be called multiple times from anywhere in your config files. A mapping has the following attributes: - **[1]**(`string`) lhs **(required)** - **[2]**(`string|fun()`) rhs **(optional)**when present, it will create the mapping - **desc**(`string|fun():string`) description **(required for non-groups)** - **group**(`string|fun():string`) group name **(optional)** - **mode**(`string|string[]`) mode **(optional, defaults to "n")** - **cond**(`boolean|fun():boolean`) condition to enable the mapping **(optional)** - **hidden**(`boolean`) hide the mapping **(optional)** - **icon**(`string|wk.Icon|fun():(wk.Icon|string)`) icon spec **(optional)** - **proxy**(`string`) proxy to another mapping **(optional)** - **expand**(`fun():wk.Spec`) nested mappings **(optional)** - any other option valid for `vim.keymap.set`. These are only used for creating mappings. When `desc`, `group`, or `icon` are functions, they are evaluated every time the popup is shown. The `expand` property allows to create dynamic mappings. Only functions as `rhs` are supported for dynamic mappings. Two examples are included in `which-key.extras` - `require("which-key.extras").expand.buf`creates numerical key to buffer mappings - `require("which-key.extras").expand.win`creates numerical key to window mappings >lua local wk = require("which-key") wk.add({ { "f", group = "file" }, -- group { "ff", "Telescope find_files", desc = "Find File", mode = "n" }, { "fb", function() print("hello") end, desc = "Foobar" }, { "fn", desc = "New File" }, { "f1", hidden = true }, -- hide this keymap { "w", proxy = "", group = "windows" }, -- proxy to window mappings { "b", group = "buffers", expand = function() return require("which-key.extras").expand.buf() end }, { -- Nested mappings are allowed and can be added in any order -- Most attributes can be inherited or overridden on any level -- There's no limit to the depth of nesting mode = { "n", "v" }, -- NORMAL and VISUAL mode { "q", "q", desc = "Quit" }, -- no need to specify mode since it's inherited { "w", "w", desc = "Write" }, } }) < TRIGGERS *which-key.nvim-which-key-triggers* There’s two ways that **which-key** can be triggered: - by a trigger keymap - by a `ModeChanged` event for visual and operator pending mode Both can be configured using `opts.triggers` and `opts.defer`. By default `opts.triggers` includes `{ "", mode = "nixsotc" }`, which will setup keymap triggers for every mode automatically and will trigger during `ModeChanged`. [!NOTE] Auto triggers will never be created for existing keymaps. That includes every valid single key Neovim builtin mapping. If you want to trigger on a builtin keymap, you have to add it manually. >lua triggers = { { "", mode = "nixsotc" }, { "a", mode = { "n", "v" } }, } < [!TIP] To manually setup triggers, you can set `opts.triggers` to: >lua triggers = { { "", mode = { "n", "v" } }, } < For `ModeChanged` triggers, you can configure the `opts.defer` option. When it returns `true`, the popup will be shown only after an additional key is pressed. So `yaf`, would show which-key after pressing `ya`, but not after `y`. [!TIP] Defer some operators: >lua ---@param ctx { mode: string, operator: string } defer = function(ctx) if vim.list_contains({ "d", "y" }, ctx.operator) then return true end return vim.list_contains({ "", "V" }, ctx.mode) end, < ICONS *which-key.nvim-which-key-icons* [!note] For full support, you need to install either mini.icons or nvim-web-devicons There’s multiple ways to set icons for your keymaps: - if you use lazy.nvim, then some icons will be autodetected for keymaps belonging to certain plugins. - custom rules to decide what icon to use - in your mapping spec, you can specify what icon to use at any level, so at the node for `g` for example, to apply to all git keymaps. The `icon` attribute of a mapping can be a `string`, which will be used as the actual icon, or an `wk.Icon` object, which can have the following attributes: - `icon` (`string`): the icon to use **(optional)** - `hl` (`string`): the highlight group to use for the icon **(optional)** - `color` (`string`): the color to use for the icon **(optional)** valid colors are: `azure`, `blue`, `cyan`, `green`, `grey`, `orange`, `purple`, `red`, `yellow` - `cat` (`string`): the category of the icon **(optional)** valid categories are: `file`, `filetype`, `extension` - `name` (`string`): the name of the icon in the specified category **(optional)** [!TIP] If you’d rather not use icons, you can disable them by setting `opts.icons.mappings` to `false`. USAGE *which-key.nvim-which-key-usage* When the **WhichKey** popup is open, you can use the following key bindings (they are also displayed at the bottom of the screen): - hit one of the keys to open a group or execute a key binding - `` to cancel and close the popup - `` go up one level - `` scroll down - `` scroll up HYDRA MODE *which-key.nvim-which-key-hydra-mode* Hydra mode is a special mode that keeps the popup open until you hit ``. >lua -- Show hydra mode for changing windows require("which-key").show({ keys = "", loop = true, -- this will keep the popup open until you hit }) < PLUGINS *which-key.nvim-which-key-plugins* Four built-in plugins are included with **WhichKey**. PRESETS ~ Built-in key binding help for `motions`, `text-objects`, `operators`, `windows`, `nav`, `z` and `g` and more. MARKS ~ Shows a list of your buffer local and global marks when you hit ` or ’ REGISTERS ~ Shows a list of your buffer local and global registers when you hit ” in _NORMAL_ mode, or `` in _INSERT_ mode. SPELLING ~ When enabled, this plugin hooks into `z=` and replaces the full-screen spelling suggestions window by a list of suggestions within **WhichKey**. COLORS *which-key.nvim-which-key-colors* The table below shows all the highlight groups defined for **WhichKey** with their default link. ----------------------------------------------------------------------- Highlight Group Default Group Description ----------------------- ----------------------- ----------------------- WhichKey Function WhichKeyBorder FloatBorder Border of the which-key window WhichKeyDesc Identifier description WhichKeyGroup Keyword group name WhichKeyIcon @markup.link icons WhichKeyIconAzure Function WhichKeyIconBlue DiagnosticInfo WhichKeyIconCyan DiagnosticHint WhichKeyIconGreen DiagnosticOk WhichKeyIconGrey Normal WhichKeyIconOrange DiagnosticWarn WhichKeyIconPurple Constant WhichKeyIconRed DiagnosticError WhichKeyIconYellow DiagnosticWarn WhichKeyNormal NormalFloat Normal in th which-key window WhichKeySeparator Comment the separator between the key and its description WhichKeyTitle FloatTitle Title of the which-key window WhichKeyValue Comment values by plugins (like marks, registers, etc) ----------------------------------------------------------------------- ============================================================================== 2. Links *which-key.nvim-links* 1. *image*: https://github.com/user-attachments/assets/89277334-dcdc-4b0f-9fd4-02f27012f589 2. *image*: https://github.com/user-attachments/assets/f8d71a75-312e-4a42-add8-d153493b2633 3. *image*: https://github.com/user-attachments/assets/e4400a1d-7e71-4439-b6ff-6cbc40647a6f 4. *image*: https://github.com/user-attachments/assets/43fb0874-7f79-4521-aee9-03e2b0841758 5. *image*: https://github.com/user-attachments/assets/d8077dcb-56fb-47b0-ad9e-1aba5db16950 6. *image*: https://github.com/user-attachments/assets/102c7963-329a-40b9-b0a8-72c8656318b7 Generated by panvimdoc vim:tw=78:ts=8:noet:ft=help:norl: folke-which-key.nvim-fcbf4ee/lua/000077500000000000000000000000001475635520600171065ustar00rootroot00000000000000folke-which-key.nvim-fcbf4ee/lua/which-key/000077500000000000000000000000001475635520600207765ustar00rootroot00000000000000folke-which-key.nvim-fcbf4ee/lua/which-key/buf.lua000066400000000000000000000130211475635520600222520ustar00rootroot00000000000000local Config = require("which-key.config") local Tree = require("which-key.tree") local Triggers = require("which-key.triggers") local Util = require("which-key.util") ---@class wk.Mode ---@field buf wk.Buffer ---@field mode string ---@field tree wk.Tree ---@field triggers wk.Node[] local Mode = {} Mode.__index = Mode ---@param node wk.Node local function is_special(node) return (node:is_plugin() or node:is_proxy()) and not node.keymap end --- Checks if it's safe to add a trigger for the given node ---@param node wk.Node ---@param no_single? boolean local function is_safe(node, no_single) if node.keymap or is_special(node) or node:count() == 0 then return false end if no_single and #node.path == 1 then local key = node.path[1] -- only z or g are safe if key:match("^[a-z]$") and not key:match("^[gz]$") then return false end -- only Z is safe if key:match("^[A-Z]$") and not key:match("^[Z]$") then return false end end return true end function Mode:__tostring() return string.format("Mode(%s:%d)", self.mode, self.buf.buf) end ---@param buf wk.Buffer ---@param mode string function Mode.new(buf, mode) local self = setmetatable({}, Mode) self.buf = buf self.mode = mode self.tree = Tree.new() self.triggers = {} self:update() return self end function Mode:attach() self.triggers = {} -- NOTE: order is important for nowait to work! -- * first add plugin mappings -- * then add triggers self.tree:walk(function(node) if is_special(node) and not node:has_nowait_ancestor() then table.insert(self.triggers, node) return false end end) if Config.triggers.modes[self.mode] then -- Auto triggers self.tree:walk(function(node) if node.keymap and node.keymap.nowait then return false end if is_safe(node, true) then table.insert(self.triggers, node) return false end end) end -- Manual triggers for _, t in ipairs(Config.triggers.mappings) do if self:has(t) then local node = self.tree:find(t.lhs) if node and is_safe(node) then table.insert(self.triggers, node) end end end Triggers.schedule(self) end function Mode:xo() return self.mode:find("[xo]") ~= nil end function Mode:clear() Triggers.detach(self) self.tree:clear() end ---@param mode string function Mode:is(mode) if mode == "v" then return self.mode == "x" or self.mode == "s" end return self.mode == mode end ---@param mapping wk.Keymap function Mode:has(mapping) return self:is(mapping.mode) and (not mapping.buffer or mapping.buffer == self.buf.buf) end function Mode:update() self.tree:clear() local mappings = vim.api.nvim_get_keymap(self.mode) vim.list_extend(mappings, vim.api.nvim_buf_get_keymap(self.buf.buf, self.mode)) ---@cast mappings wk.Keymap[] for _, mapping in ipairs(mappings) do if mapping.desc and mapping.desc:find("which-key-trigger", 1, true) then -- ignore which-key triggers elseif Util.is_nop(mapping.rhs) then self.tree:add(mapping, true) elseif mapping.lhs:sub(1, 6) ~= "" and mapping.lhs:sub(1, 5) ~= "" then self.tree:add(mapping) end end for _, m in ipairs(Config.mappings) do if self:has(m) then self.tree:add(m, true) end end self.tree:fix() self:attach() vim.schedule(function() require("which-key.state").update() end) end ---@class wk.Buffer ---@field buf number ---@field modes table local Buf = {} Buf.__index = Buf ---@param buf? number function Buf.new(buf) local self = setmetatable({}, Buf) buf = buf or 0 self.buf = buf == 0 and vim.api.nvim_get_current_buf() or buf self.modes = {} return self end ---@param opts? wk.Filter function Buf:clear(opts) opts = opts or {} assert(not opts.buf or opts.buf == self.buf, "buffer mismatch") ---@type string[] local modes = opts.mode and { opts.mode } or vim.tbl_keys(self.modes) for _, m in ipairs(modes) do local mode = self.modes[m] if mode then mode:clear() self.modes[m] = nil end end end function Buf:valid() return vim.api.nvim_buf_is_valid(self.buf) end ---@param opts? wk.Filter ---@return wk.Mode? function Buf:get(opts) if not self:valid() then return end opts = opts or {} local mode = opts.mode or Util.mapmode() local ret = self.modes[mode] if not ret then self.modes[mode] = Mode.new(self, mode) Util.debug("new " .. tostring(self.modes[mode])) return self.modes[mode] elseif opts.update then Util.debug("update " .. tostring(ret)) ret:update() end return ret end local M = {} M.Buf = Buf M.bufs = {} ---@type table ---@param opts? wk.Filter function M.get(opts) M.cleanup() opts = opts or {} local buf = opts.buf or vim.api.nvim_get_current_buf() if not vim.api.nvim_buf_is_valid(buf) then return end local ft = vim.bo[buf].filetype local bt = vim.bo[buf].buftype if vim.tbl_contains(Config.disable.ft, ft) then return end if vim.tbl_contains(Config.disable.bt, bt) then return end M.bufs[buf] = M.bufs[buf] or Buf.new(buf) return M.bufs[buf]:get(opts) end function M.cleanup() for buf, _ in pairs(M.bufs) do if not vim.api.nvim_buf_is_valid(buf) then M.bufs[buf] = nil end end end ---@param opts? wk.Filter function M.clear(opts) M.cleanup() opts = opts or {} ---@type number[] local bufs = opts.buf and { opts.buf } or vim.tbl_keys(M.bufs) for _, b in ipairs(bufs) do if M.bufs[b] then M.bufs[b]:clear(opts) end end end return M folke-which-key.nvim-fcbf4ee/lua/which-key/colors.lua000066400000000000000000000032021475635520600227770ustar00rootroot00000000000000local M = {} M.colors = { [""] = "Function", -- the key Separator = "Comment", -- the separator between the key and its description Group = "Keyword", -- group name Desc = "Identifier", -- description Normal = "NormalFloat", -- Normal in th which-key window Title = "FloatTitle", -- Title of the which-key window Border = "FloatBorder", -- Border of the which-key window Value = "Comment", -- values by plugins (like marks, registers, etc) Icon = "@markup.link", -- icons IconAzure = "Function", IconBlue = "DiagnosticInfo", IconCyan = "DiagnosticHint", IconGreen = "DiagnosticOk", IconGrey = "Normal", IconOrange = "DiagnosticWarn", IconPurple = "Constant", IconRed = "DiagnosticError", IconYellow = "DiagnosticWarn", } function M.setup() for k, v in pairs(M.colors) do vim.api.nvim_set_hl(0, "WhichKey" .. k, { link = v, default = true }) end M.fix_colors() vim.api.nvim_create_autocmd("ColorScheme", { group = vim.api.nvim_create_augroup("wk-colors", { clear = true }), callback = M.fix_colors, }) end function M.fix_colors() for k in pairs(M.colors) do if k:find("^Icon") then local color = k:gsub("^Icon", "") local wk_hl_group = "WhichKeyIcon" .. color local mini_hl_group = "MiniIcons" .. color local wk_hl = vim.api.nvim_get_hl(0, { name = wk_hl_group, link = true, }) local mini_hl = vim.api.nvim_get_hl(0, { name = mini_hl_group, link = true, }) if wk_hl.default and not vim.tbl_isempty(mini_hl) then vim.api.nvim_set_hl(0, wk_hl_group, { link = mini_hl_group }) end end end end return M folke-which-key.nvim-fcbf4ee/lua/which-key/config.lua000066400000000000000000000244221475635520600227520ustar00rootroot00000000000000---@class wk.Config: wk.Opts ---@field triggers {mappings: wk.Mapping[], modes: table} local M = {} M.version = "3.17.0" -- x-release-please-version ---@class wk.Opts local defaults = { ---@type false | "classic" | "modern" | "helix" preset = "classic", -- Delay before showing the popup. Can be a number or a function that returns a number. ---@type number | fun(ctx: { keys: string, mode: string, plugin?: string }):number delay = function(ctx) return ctx.plugin and 0 or 200 end, ---@param mapping wk.Mapping filter = function(mapping) -- example to exclude mappings without a description -- return mapping.desc and mapping.desc ~= "" return true end, --- You can add any mappings here, or use `require('which-key').add()` later ---@type wk.Spec spec = {}, -- show a warning when issues were detected with your mappings notify = true, -- Which-key automatically sets up triggers for your mappings. -- But you can disable this and setup the triggers manually. -- Check the docs for more info. ---@type wk.Spec triggers = { { "", mode = "nxso" }, }, -- Start hidden and wait for a key to be pressed before showing the popup -- Only used by enabled xo mapping modes. ---@param ctx { mode: string, operator: string } defer = function(ctx) return ctx.mode == "V" or ctx.mode == "" end, plugins = { marks = true, -- shows a list of your marks on ' and ` registers = true, -- shows your registers on " in NORMAL or in INSERT mode -- the presets plugin, adds help for a bunch of default keybindings in Neovim -- No actual key bindings are created spelling = { enabled = true, -- enabling this will show WhichKey when pressing z= to select spelling suggestions suggestions = 20, -- how many suggestions should be shown in the list? }, presets = { operators = true, -- adds help for operators like d, y, ... motions = true, -- adds help for motions text_objects = true, -- help for text objects triggered after entering an operator windows = true, -- default bindings on nav = true, -- misc bindings to work with windows z = true, -- bindings for folds, spelling and others prefixed with z g = true, -- bindings for prefixed with g }, }, ---@type wk.Win.opts win = { -- don't allow the popup to overlap with the cursor no_overlap = true, -- width = 1, -- height = { min = 4, max = 25 }, -- col = 0, -- row = math.huge, -- border = "none", padding = { 1, 2 }, -- extra window padding [top/bottom, right/left] title = true, title_pos = "center", zindex = 1000, -- Additional vim.wo and vim.bo options bo = {}, wo = { -- winblend = 10, -- value between 0-100 0 for fully opaque and 100 for fully transparent }, }, layout = { width = { min = 20 }, -- min and max width of the columns spacing = 3, -- spacing between columns }, keys = { scroll_down = "", -- binding to scroll down inside the popup scroll_up = "", -- binding to scroll up inside the popup }, ---@type (string|wk.Sorter)[] --- Mappings are sorted using configured sorters and natural sort of the keys --- Available sorters: --- * local: buffer-local mappings first --- * order: order of the items (Used by plugins like marks / registers) --- * group: groups last --- * alphanum: alpha-numerical first --- * mod: special modifier keys last --- * manual: the order the mappings were added --- * case: lower-case first sort = { "local", "order", "group", "alphanum", "mod" }, ---@type number|fun(node: wk.Node):boolean? expand = 0, -- expand groups when <= n mappings -- expand = function(node) -- return not node.desc -- expand all nodes without a description -- end, -- Functions/Lua Patterns for formatting the labels ---@type table replace = { key = { function(key) return require("which-key.view").format(key) end, -- { "", "SPC" }, }, desc = { { "%(?(.*)%)?", "%1" }, { "^%+", "" }, { "<[cC]md>", "" }, { "<[cC][rR]>", "" }, { "<[sS]ilent>", "" }, { "^lua%s+", "" }, { "^call%s+", "" }, { "^:%s*", "" }, }, }, icons = { breadcrumb = "»", -- symbol used in the command line area that shows your active key combo separator = "➜", -- symbol used between a key and it's label group = "+", -- symbol prepended to a group ellipsis = "…", -- set to false to disable all mapping icons, -- both those explicitly added in a mapping -- and those from rules mappings = true, --- See `lua/which-key/icons.lua` for more details --- Set to `false` to disable keymap icons from rules ---@type wk.IconRule[]|false rules = {}, -- use the highlights from mini.icons -- When `false`, it will use `WhichKeyIcon` instead colors = true, -- used by key format keys = { Up = " ", Down = " ", Left = " ", Right = " ", C = "󰘴 ", M = "󰘵 ", D = "󰘳 ", S = "󰘶 ", CR = "󰌑 ", Esc = "󱊷 ", ScrollWheelDown = "󱕐 ", ScrollWheelUp = "󱕑 ", NL = "󰌑 ", BS = "󰁮", Space = "󱁐 ", Tab = "󰌒 ", F1 = "󱊫", F2 = "󱊬", F3 = "󱊭", F4 = "󱊮", F5 = "󱊯", F6 = "󱊰", F7 = "󱊱", F8 = "󱊲", F9 = "󱊳", F10 = "󱊴", F11 = "󱊵", F12 = "󱊶", }, }, show_help = true, -- show a help message in the command line for using WhichKey show_keys = true, -- show the currently pressed key and its label as a message in the command line -- disable WhichKey for certain buf types and file types. disable = { ft = {}, bt = {}, }, debug = false, -- enable wk.log in the current directory } M.loaded = false ---@type wk.Keymap[] M.mappings = {} ---@type wk.Opts M.options = nil ---@type {opt:string, msg:string}[] M.issues = {} function M.validate() local deprecated = { ["operators"] = "see `opts.defer`", ["key_labels"] = "see `opts.replace`", "motions", ["popup_mappings"] = "see `opts.keys`", ["window"] = "see `opts.win`", ["ignore_missing"] = "see `opts.filter`", "hidden", ["triggers_nowait"] = "see `opts.delay`", ["triggers_blacklist"] = "see `opts.triggers`", ["disable.trigger"] = "see `opts.triggers`", ["modes"] = "see `opts.triggers`", } for k, v in pairs(deprecated) do local opt = type(k) == "number" and v or k local msg = "option is deprecated." .. (type(k) == "number" and "" or " " .. v) local parts = vim.split(opt, ".", { plain = true }) if vim.tbl_get(M.options, unpack(parts)) ~= nil then table.insert(M.issues, { opt = opt, msg = msg }) end end if type(M.options.triggers) ~= "table" then table.insert(M.issues, { opt = "triggers", msg = "triggers must be a table" }) end end ---@param opts? wk.Opts function M.setup(opts) if vim.fn.has("nvim-0.9.4") == 0 then return vim.notify("which-key.nvim requires Neovim >= 0.9.4", vim.log.levels.ERROR) end M.options = vim.tbl_deep_extend("force", {}, defaults, opts or {}) local function load() if M.loaded then return end local Util = require("which-key.util") if M.options.preset then local Presets = require("which-key.presets") M.options = vim.tbl_deep_extend("force", {}, defaults, Presets[M.options.preset] or {}, opts or {}) end M.validate() if #M.issues > 0 then Util.warn({ "There are issues with your config.", "Use `:checkhealth which-key` to find out more.", }, { once = true }) end for k, v in pairs(M.options.keys) do M.options.keys[k] = Util.norm(v) end if M.options.debug then Util.debug("\n\nDebug Started for v" .. M.version) if package.loaded.lazy then local Git = require("lazy.manage.git") local plugin = require("lazy.core.config").plugins["which-key.nvim"] Util.debug(vim.inspect(Git.info(plugin.dir))) end end local wk = require("which-key") -- replace by the real add function wk.add = M.add if type(M.options.triggers) ~= "table" then ---@diagnostic disable-next-line: inject-field M.options.triggers = defaults.triggers end M.triggers = { mappings = require("which-key.mappings").parse(M.options.triggers), modes = {}, } ---@param m wk.Mapping M.triggers.mappings = vim.tbl_filter(function(m) if m.lhs == "" then M.triggers.modes[m.mode] = true return false end return true end, M.triggers.mappings) -- load presets first so that they can be overriden by the user require("which-key.plugins").setup() -- process mappings queue for _, todo in ipairs(wk._queue) do M.add(todo.spec, todo.opts) end wk._queue = {} -- finally, add the mapppings from the config M.add(M.options.spec) -- setup colors and start which-key require("which-key.colors").setup() require("which-key.state").setup() M.loaded = true end local _load = vim.schedule_wrap(load) if vim.v.vim_did_enter == 1 then _load() else vim.api.nvim_create_autocmd("VimEnter", { once = true, callback = _load }) end vim.api.nvim_create_user_command("WhichKey", function(cmd) load() local mode, keys = cmd.args:match("^([nixsotc]?)%s*(.*)$") if not mode then return require("which-key.util").error("Usage: WhichKey [mode] [keys]") end if mode == "" then mode = "n" end require("which-key").show({ mode = mode, keys = keys }) end, { nargs = "*", }) end ---@param opts? wk.Parse ---@param mappings wk.Spec function M.add(mappings, opts) opts = opts or {} opts.create = opts.create ~= false local Mappings = require("which-key.mappings") for _, km in ipairs(Mappings.parse(mappings, opts)) do table.insert(M.mappings, km) km.idx = #M.mappings end if M.loaded then require("which-key.buf").clear() end end return setmetatable(M, { __index = function(_, k) if rawget(M, "options") == nil then M.setup() end local opts = rawget(M, "options") return k == "options" and opts or opts[k] end, }) folke-which-key.nvim-fcbf4ee/lua/which-key/docs.lua000066400000000000000000000006621475635520600224350ustar00rootroot00000000000000local Docs = require("lazy.docs") local M = {} function M.update() local config = Docs.extract("lua/which-key/config.lua", "\n(--@class wk%.Opts.-\n})") config = config:gsub("%s*debug = false.\n", "\n") Docs.save({ config = config, colors = Docs.colors({ modname = "which-key.colors", path = "lua/which-key/colors.lua", name = "WhichKey", }), }) end M.update() print("Updated docs") return M folke-which-key.nvim-fcbf4ee/lua/which-key/extras.lua000066400000000000000000000031011475635520600230020ustar00rootroot00000000000000local M = {} ---@type table M.expand = {} ---@return number[] function M.bufs() local current = vim.api.nvim_get_current_buf() return vim.tbl_filter(function(buf) return buf ~= current and vim.bo[buf].buflisted end, vim.api.nvim_list_bufs()) end function M.bufname(buf) local name = vim.api.nvim_buf_get_name(buf) return name == "" and "[No Name]" or vim.fn.fnamemodify(name, ":~:.") end ---@param spec wk.Spec[] function M.add_keys(spec) table.sort(spec, function(a, b) return a.desc < b.desc end) spec = vim.list_slice(spec, 1, 10) for i, v in ipairs(spec) do v[1] = tostring(i - 1) end return spec end function M.expand.buf() local ret = {} ---@type wk.Spec[] for _, buf in ipairs(M.bufs()) do local name = M.bufname(buf) ret[#ret + 1] = { "", function() vim.api.nvim_set_current_buf(buf) end, desc = name, icon = { cat = "file", name = name }, } end return M.add_keys(ret) end function M.expand.win() ---@type wk.Spec[] local ret = {} local current = vim.api.nvim_get_current_win() for _, win in ipairs(vim.api.nvim_list_wins()) do local is_float = vim.api.nvim_win_get_config(win).relative ~= "" if win ~= current and not is_float then local buf = vim.api.nvim_win_get_buf(win) local name = M.bufname(buf) ret[#ret + 1] = { "", function() vim.api.nvim_set_current_win(win) end, desc = name, icon = { cat = "file", name = name }, } end end return M.add_keys(ret) end return M folke-which-key.nvim-fcbf4ee/lua/which-key/health.lua000066400000000000000000000124521475635520600227520ustar00rootroot00000000000000local Buf = require("which-key.buf") local Config = require("which-key.config") local Icons = require("which-key.icons") local Mappings = require("which-key.mappings") local Migrate = require("which-key.migrate") local Tree = require("which-key.tree") local Util = require("which-key.util") local M = {} local start = vim.health.start or vim.health.report_start local ok = vim.health.ok or vim.health.report_ok local warn = vim.health.warn or vim.health.report_warn local error = vim.health.error or vim.health.report_error local info = vim.health.info or vim.health.report_info -- TODO: Add more checks -- * duplicate desc -- * mapping.desc ~= keymap.desc -- * check for old-style mappings function M.check() ok( "Most of these checks are for informational purposes only.\n" .. "WARNINGS should be treated as a warning, and don't necessarily indicate a problem with your config.\n" .. "Please |DON'T| report these warnings as an issue." ) start("Checking your config") if #Config.issues > 0 then local msg = { "There are issues with your config:", } vim.list_extend( msg, vim.tbl_map(function(issue) return "- `opts." .. issue.opt .. "`: " .. issue.msg end, Config.issues) ) msg[#msg + 1] = "Please refer to the docs for more info." warn(table.concat(msg, "\n")) end local have_icons = false for _, provider in ipairs(Icons.providers) do if provider.available == nil then provider.available = pcall(require, provider.name) end if provider.available then ok("|" .. provider.name .. "| is installed") have_icons = true else warn("|" .. provider.name .. "| is not installed") end end if not have_icons then warn("Keymap icon support will be limited.") end start("Checking for issues with your mappings") if #Mappings.notifs == 0 then ok("No issues reported") end for _, notif in ipairs(Mappings.notifs) do local msg = notif.msg if notif.spec then msg = msg .. ": >\n" .. vim.inspect(notif.spec) if msg:find("old version") then local fixed = Migrate.migrate(notif.spec) msg = msg .. "\n\n-- Suggested Spec:\n" .. fixed end end (notif.level >= vim.log.levels.ERROR and error or warn)(msg) end start("checking for overlapping keymaps") local found = false Buf.cleanup() ---@type table local reported = {} local mapmodes = vim.split("nixsotc", "") for _, buf in pairs(Buf.bufs) do for _, mapmode in ipairs(mapmodes) do local mode = buf:get({ mode = mapmode }) if mode then mode.tree:walk(function(node) local km = node.keymap if not km or Util.is_nop(km.rhs) or node.keys:sub(1, 6) == "" then return end if node.keymap and node:count() > 0 then local id = mode.mode .. ":" .. node.keys if reported[id] then return end reported[id] = true local overlaps = {} local descs = {} if node.desc and node.desc ~= "" then descs[#descs + 1] = "- <" .. node.keys .. ">: " .. node.desc end local queue = node:children() while #queue > 0 do local child = table.remove(queue) if child.keymap then table.insert(overlaps, "<" .. child.keys .. ">") if child.desc and child.desc ~= "" then descs[#descs + 1] = "- <" .. child.keys .. ">: " .. child.desc end end vim.list_extend(queue, child:children()) end if #overlaps > 0 then found = true warn( "In mode `" .. mode.mode .. "`, <" .. node.keys .. "> overlaps with " .. table.concat(overlaps, ", ") .. ":\n" .. table.concat(descs, "\n") ) end return false end end) end end end if found then ok( "Overlapping keymaps are only reported for informational purposes.\n" .. "This doesn't necessarily mean there is a problem with your config." ) else ok("No overlapping keymaps found") end start("Checking for duplicate mappings") if vim.tbl_isempty(Tree.dups) then ok("No duplicate mappings found") else for _, mappings in pairs(Tree.dups) do ---@type wk.Mapping[] mappings = vim.tbl_keys(mappings) local first = mappings[1] warn( "Duplicates for <" .. first.lhs .. "> in mode `" .. first.mode .. "`:\n" .. table.concat( vim.tbl_map(function(m) m = vim.deepcopy(m) local desc = (m.desc and (m.desc .. ": ") or "") m.desc = nil m.idx = nil m.mode = nil m.lhs = nil return "* " .. desc .. "`" .. vim.inspect(m):gsub("%s+", " ") .. "`" end, mappings), "\n" ) ) end ok( "Duplicate mappings are only reported for informational purposes.\n" .. "This doesn't necessarily mean there is a problem with your config." ) end end return M folke-which-key.nvim-fcbf4ee/lua/which-key/icons.lua000066400000000000000000000154041475635520600226200ustar00rootroot00000000000000local Config = require("which-key.config") local M = {} --- * `WhichKeyColorAzure` - azure. --- * `WhichKeyColorBlue` - blue. --- * `WhichKeyColorCyan` - cyan. --- * `WhichKeyColorGreen` - green. --- * `WhichKeyColorGrey` - grey. --- * `WhichKeyColorOrange` - orange. --- * `WhichKeyColorPurple` - purple. --- * `WhichKeyColorRed` - red. --- * `WhichKeyColorYellow` - yellow. ---@type wk.IconRule[] M.rules = { { plugin = "fzf-lua", cat = "filetype", name = "fzf" }, { plugin = "neo-tree.nvim", cat = "filetype", name = "neo-tree" }, { plugin = "octo.nvim", cat = "filetype", name = "git" }, { plugin = "yanky.nvim", icon = "󰅇", color = "yellow" }, { plugin = "zen-mode.nvim", icon = "󱅻 ", color = "cyan" }, { plugin = "telescope.nvim", pattern = "telescope", icon = "", color = "blue" }, { plugin = "trouble.nvim", cat = "filetype", name = "trouble" }, { plugin = "todo-comments.nvim", cat = "file", name = "TODO" }, { plugin = "grapple.nvim", pattern = "grapple", icon = "󰛢", color = "azure" }, { plugin = "nvim-spectre", icon = "󰛔 ", color = "blue" }, { plugin = "grug-far.nvim", pattern = "grug", icon = "󰛔 ", color = "blue" }, { plugin = "noice.nvim", pattern = "noice", icon = "󰈸", color = "orange" }, { plugin = "persistence.nvim", icon = " ", color = "azure" }, { plugin = "neotest", cat = "filetype", name = "neotest-summary" }, { plugin = "lazy.nvim", cat = "filetype", name = "lazy" }, { plugin = "snacks.nvim", icon = "󱥰 ", color = "purple" }, { plugin = "refactoring.nvim", pattern = "refactor", icon = " ", color = "cyan" }, { pattern = "profiler", icon = "⚡", color = "orange" }, { plugin = "CopilotChat.nvim", icon = " ", color = "orange" }, { pattern = "%f[%a]git", cat = "filetype", name = "git" }, { pattern = "terminal", icon = " ", color = "red" }, { pattern = "find", icon = " ", color = "green" }, { pattern = "search", icon = " ", color = "green" }, { pattern = "test", cat = "filetype", name = "neotest-summary" }, { pattern = "lazy", cat = "filetype", name = "lazy" }, { pattern = "buffer", icon = "󰈔", color = "cyan" }, { pattern = "file", icon = "󰈔", color = "cyan" }, { pattern = "window", icon = " ", color = "blue" }, { pattern = "diagnostic", icon = "󱖫 ", color = "green" }, { pattern = "format", icon = " ", color = "cyan" }, { pattern = "debug", icon = "󰃤 ", color = "red" }, { pattern = "code", icon = " ", color = "orange" }, { pattern = "notif", icon = "󰵅 ", color = "blue" }, { pattern = "toggle", icon = " ", color = "yellow" }, { pattern = "session", icon = " ", color = "azure" }, { pattern = "exit", icon = "󰈆 ", color = "red" }, { pattern = "quit", icon = "󰈆 ", color = "red" }, { pattern = "tab", icon = "󰓩 ", color = "purple" }, { pattern = "%f[%a]ai", icon = " ", color = "green" }, { pattern = "ui", icon = "󰙵 ", color = "cyan" }, } ---@type wk.IconProvider[] M.providers = { { name = "mini.icons", get = function(icon) local Icons = require("mini.icons") local ico, ico_hl, ico_def = Icons.get(icon.cat, icon.name) --[[@as string, string, boolean]] if not ico_def then return ico, ico_hl end end, }, { name = "nvim-web-devicons", get = function(icon) local Icons = require("nvim-web-devicons") if icon.cat == "filetype" then return Icons.get_icon_by_filetype(icon.name, { default = false }) elseif icon.cat == "file" then return Icons.get_icon(icon.name, nil, { default = false }) --[[@as string, string]] elseif icon.cat == "extension" then return Icons.get_icon(nil, icon.name, { default = false }) --[[@as string, string]] end end, }, } ---@return wk.IconProvider? function M.get_provider() for _, provider in ipairs(M.providers) do if provider.available == nil then provider.available = pcall(require, provider.name) end if provider.available then return provider end end end function M.have() return M.get_provider() ~= nil end ---@param icon wk.Icon|string ---@return string?, string? function M.get_icon(icon) icon = type(icon) == "string" and { cat = "filetype", name = icon } or icon --[[@as wk.Icon]] ---@type string?, string? local ret, hl if icon.icon then ret, hl = icon.icon, icon.hl elseif icon.cat and icon.name then local provider = M.get_provider() if provider then ret, hl = provider.get(icon) end end if ret then if icon.color then hl = "WhichKeyIcon" .. icon.color:sub(1, 1):upper() .. icon.color:sub(2) end if not hl or Config.icons.colors == false or icon.color == false then hl = "WhichKeyIcon" end return ret, hl end end ---@param rules wk.IconRule[] ---@param opts? {keymap?: wk.Keymap, desc?: string, ft?:string|string[]}|wk.Icon ---@param check_ft? boolean ---@return string?, string? function M._get(rules, opts, check_ft) opts = opts or {} opts.ft = type(opts.ft) == "string" and { opts.ft } or opts.ft ---@type string? local plugin local fts = opts.ft or {} --[[@as string[] ]] if opts.keymap and package.loaded.lazy then local LazyUtil = require("lazy.core.util") local Keys = require("lazy.core.handler").handlers.keys --[[@as LazyKeysHandler]] local keys = Keys.parse(opts.keymap.lhs, opts.keymap.mode) plugin = Keys.managed[keys.id] if plugin then fts[#fts + 1] = LazyUtil.normname(plugin) end end -- plugin icons if plugin then for _, icon in ipairs(rules) do if icon.plugin == plugin then local ico, hl = M.get_icon(icon) if ico then return ico, hl end end end end -- filetype icons if check_ft then if opts.keymap and opts.keymap.buffer and opts.keymap.buffer ~= 0 then pcall(function() fts[#fts + 1] = vim.bo[opts.keymap.buffer].filetype end) end for _, ft in ipairs(fts) do local icon, hl = M.get_icon({ cat = "filetype", name = ft }) if icon then return icon, hl end end end -- pattern icons if opts.desc then for _, icon in ipairs(rules) do if icon.pattern and opts.desc:lower():find(icon.pattern) then local ico, hl = M.get_icon(icon) if ico then return ico, hl end end end end end ---@param opts {keymap?: wk.Keymap, desc?: string, ft?:string|string[]}|wk.Icon|string function M.get(opts) if not Config.icons.mappings then return end if type(opts) == "string" then opts = { icon = opts } end if opts.icon or opts.cat then return M.get_icon(opts) end if Config.icons.rules == false then return end local icon, hl = M._get(Config.icons.rules, opts) if icon then return icon, hl end return M._get(M.rules, opts, true) end return M folke-which-key.nvim-fcbf4ee/lua/which-key/init.lua000066400000000000000000000023461475635520600224510ustar00rootroot00000000000000---@class wk ---@field private _queue {spec: wk.Spec, opts?: wk.Parse}[] local M = {} M._queue = {} M.did_setup = false --- Open which-key ---@param opts? wk.Filter|string function M.show(opts) opts = opts or {} opts = type(opts) == "string" and { keys = opts } or opts if opts.delay == nil then opts.delay = 0 end opts.waited = vim.o.timeoutlen ---@diagnostic disable-next-line: param-type-mismatch if not require("which-key.state").start(opts) then require("which-key.util").warn( "No mappings found for mode `" .. (opts.mode or "n") .. "` and keys `" .. (opts.keys or "") .. "`" ) end end ---@param opts? wk.Opts function M.setup(opts) M.did_setup = true require("which-key.config").setup(opts) end -- Use `require("which-key").add()` instead. -- The spec is different though, so check the docs! ---@deprecated ---@param mappings wk.Spec ---@param opts? wk.Mapping function M.register(mappings, opts) if opts then for k, v in pairs(opts) do mappings[k] = v end end M.add(mappings, { version = 1 }) end --- Add mappings to which-key ---@param mappings wk.Spec ---@param opts? wk.Parse function M.add(mappings, opts) table.insert(M._queue, { spec = mappings, opts = opts }) end return M folke-which-key.nvim-fcbf4ee/lua/which-key/layout.lua000066400000000000000000000077021475635520600230240ustar00rootroot00000000000000local Config = require("which-key.config") local M = {} local dw = vim.fn.strdisplaywidth --- When `size` is a number, it is returned as is (fixed dize). --- Otherwise, it is a percentage of `parent` (relative size). --- If `size` is negative, it is subtracted from `parent`. --- If `size` is a table, it is a range of values. ---@alias wk.Dim number|{min:number, max:number} ---@param size number ---@param parent number ---@param ... wk.Dim ---@return number function M.dim(size, parent, ...) size = math.abs(size) < 1 and parent * size or size size = size < 0 and parent + size or size for _, dim in ipairs({ ... } --[[ @as wk.Dim[] ]]) do if type(dim) == "number" then size = M.dim(dim, parent) else local min = dim.min and M.dim(dim.min, parent) or 0 local max = dim.max and M.dim(dim.max, parent) or parent size = math.max(min, math.min(max, size)) end end return math.floor(math.max(0, math.min(parent, size)) + 0.5) end ---@class wk.Table: wk.Table.opts local Table = {} Table.__index = Table ---@param opts wk.Table.opts function Table.new(opts) local self = setmetatable({}, Table) self.cols = opts.cols self.rows = opts.rows return self end ---@param opts? {spacing?: number} ---@return string[][], number[], number function Table:cells(opts) opts = opts or {} opts.spacing = opts.spacing or 1 local widths = {} ---@type number[] actual column widths local cells = {} ---@type string[][] local total = 0 for c, col in ipairs(self.cols) do widths[c] = 0 local all_ws = true for r, row in ipairs(self.rows) do cells[r] = cells[r] or {} local value = row[col.key] or col.default or "" value = tostring(value) value = value:gsub("%s*$", "") value = value:gsub("\n", Config.icons.keys.NL) value = vim.fn.strtrans(value) if value:find("%S") then all_ws = false end if col.padding then value = (" "):rep(col.padding[1] or 0) .. value .. (" "):rep(col.padding[2] or 0) end if c ~= #self.cols then value = value .. (" "):rep(opts.spacing) end cells[r][c] = value widths[c] = math.max(widths[c], dw(value)) end if all_ws then widths[c] = 0 for _, cell in pairs(cells) do cell[c] = "" end end total = total + widths[c] end return cells, widths, total end ---@param opts {width: number, spacing?: number} function Table:layout(opts) local cells, widths = self:cells(opts) local free = opts.width for c, col in ipairs(self.cols) do if not col.width then free = free - widths[c] end end free = math.max(free, 0) for c, col in ipairs(self.cols) do if col.width then widths[c] = M.dim(widths[c], free, { max = col.width }) free = free - widths[c] end end ---@type {value: string, hl?:string}[][] local ret = {} for _, row in ipairs(cells) do ---@type {value: string, hl?:string}[] local line = {} for c, col in ipairs(self.cols) do local value = row[c] local width = dw(value) if width > widths[c] then local old = value value = "" for i = 0, vim.fn.strchars(old) do value = value .. vim.fn.strcharpart(old, i, 1) if dw(value) >= widths[c] - 1 - (opts.spacing or 1) then break end end value = value .. Config.icons.ellipsis .. string.rep(" ", opts.spacing or 1) else local align = col.align or "left" if align == "left" then value = value .. (" "):rep(widths[c] - width) elseif align == "right" then value = (" "):rep(widths[c] - width) .. value elseif align == "center" then local pad = (widths[c] - width) / 2 value = (" "):rep(math.floor(pad)) .. value .. (" "):rep(math.ceil(pad)) end end line[#line + 1] = { value = value, hl = col.hl } end ret[#ret + 1] = line end return ret end M.new = Table.new return M folke-which-key.nvim-fcbf4ee/lua/which-key/mappings.lua000066400000000000000000000206321475635520600233220ustar00rootroot00000000000000local Config = require("which-key.config") local Util = require("which-key.util") local M = {} M.VERSION = 2 M.notifs = {} ---@type {msg:string, level:number, spec?:wk.Spec}[] ---@class wk.Field ---@field transform? string|(fun(value: any, parent:table): (value:any, key:string?)) ---@field inherit? boolean ---@field deprecated? boolean ---@class wk.Parse ---@field version? number ---@field create? boolean ---@field notify? boolean M.notify = true ---@type table M.fields = { -- map args rhs = {}, lhs = {}, buffer = { inherit = true }, callback = { transform = "rhs" }, desc = {}, expr = { inherit = true }, mode = { inherit = true }, noremap = { transform = function(value) return not value, "remap" end, }, nowait = { inherit = true }, remap = { inherit = true }, replace_keycodes = { inherit = true }, script = {}, silent = { inherit = true }, unique = { inherit = true }, -- wk args plugin = { inherit = true }, group = {}, hidden = { inherit = true }, cond = { inherit = true }, preset = { inherit = true }, icon = { inherit = true }, real = { inherit = true }, proxy = {}, expand = {}, -- deprecated name = { transform = "group", deprecated = true }, prefix = { inherit = true, deprecated = true }, cmd = { transform = "rhs", deprecated = true }, } ---@param msg string ---@param spec? wk.Spec function M.error(msg, spec) M.log(msg, vim.log.levels.ERROR, spec) end ---@param msg string ---@param spec? wk.Spec function M.warn(msg, spec) M.log(msg, vim.log.levels.WARN, spec) end ---@param msg string ---@param level number ---@param spec? wk.Spec function M.log(msg, level, spec) if not M.notify then return end M.notifs[#M.notifs + 1] = { msg = msg, level = level, spec = spec } if Config.notify then Util.warn({ "There were issues reported with your **which-key** mappings.", "Use `:checkhealth which-key` to find out more.", }, { once = true }) end end ---@param spec wk.Spec ---@param field string|number ---@param types string|string[] function M.expect(spec, field, types) types = type(types) == "string" and { types } or types local ok = false for _, t in ipairs(types) do if type(spec[field]) == t then ok = true break end end if not ok then M.error("Expected `" .. field .. "` to be " .. table.concat(types, ", "), spec) end return ok end ---@param spec wk.Spec ---@param ret? wk.Mapping[] ---@param opts? wk.Parse function M._parse(spec, ret, opts) opts = opts or {} opts.version = opts.version or M.VERSION if spec.version then opts.version = spec.version spec.version = nil end if ret == nil and opts.version ~= M.VERSION then M.warn( "You're using an old version of the which-key spec.\n" .. "Your mappings will work, but it's recommended to update them to the new version.\n" .. "Please check the docs and suggested spec below for more info.\nMappings", vim.deepcopy(spec) ) end ret = ret or {} spec = type(spec) == "string" and { desc = spec } or spec ---@type wk.Mapping local mapping = {} ---@type wk.Spec[] local children = {} local keys = vim.tbl_keys(spec) table.sort(keys, function(a, b) local ta, tb = type(a), type(b) if type(a) == type(b) then return a < b end return ta < tb end) -- process fields for _, k in ipairs(keys) do local v = spec[k] local field = M.fields[k] ---@type wk.Field? if field then if type(field.transform) == "string" then k = field.transform --[[@as string]] elseif type(field.transform) == "function" then local vv, kk = field.transform(v, spec) v, k = vv, (kk or k) end mapping[k] = v elseif type(k) == "string" then if opts.version == 1 then if M.expect(spec, k, { "string", "table" }) then if type(v) == "string" then table.insert(children, { prefix = (spec.prefix or "") .. k, desc = v }) elseif type(v) == "table" then v.prefix = (spec.prefix or "") .. k table.insert(children, v) end end else M.error("Invalid field `" .. k .. "`", spec) end elseif type(k) == "number" and type(v) == "table" then if opts.version == 1 then v.prefix = spec.prefix or "" end table.insert(children, v) spec[k] = nil end end local count = #spec -- process mapping if opts.version == M.VERSION then if count == 1 then if M.expect(spec, 1, "string") then mapping.lhs = spec[1] --[[@as string]] end elseif count == 2 then if M.expect(spec, 1, "string") and M.expect(spec, 2, { "string", "function" }) then mapping.lhs = spec[1] --[[@as string]] mapping.rhs = spec[2] --[[@as string]] end elseif count > 2 then M.error("expected 1 or 2 elements, got " .. count, spec) end elseif opts.version == 1 then if mapping.expr and mapping.replace_keycodes == nil then mapping.replace_keycodes = false end if count == 1 then if M.expect(spec, 1, "string") then if mapping.desc then M.warn("overwriting desc", spec) end mapping.desc = spec[1] --[[@as string]] end elseif count == 2 then if M.expect(spec, 1, { "string", "function" }) and M.expect(spec, 2, "string") then if mapping.desc then M.warn("overwriting desc", spec) end mapping.rhs = spec[1] --[[@as string]] mapping.desc = spec[2] --[[@as string]] end elseif count > 2 then M.error("expected 1 or 2 elements, got " .. count, spec) end end -- add mapping M.add(mapping, ret, opts) -- process children for _, child in ipairs(children) do for k, v in pairs(mapping) do if M.fields[k] and M.fields[k].inherit and child[k] == nil then child[k] = v end end M._parse(child, ret, opts) end return ret end ---@param mapping wk.Spec ---@param opts? wk.Parse ---@param ret wk.Mapping[] function M.add(mapping, ret, opts) opts = opts or {} if mapping.cond == false or ((type(mapping.cond) == "function") and not mapping.cond()) then return end ---@cast mapping wk.Mapping|wk.Spec mapping.cond = nil if mapping.desc == "which_key_ignore" then mapping.hidden = true mapping.desc = nil end if type(mapping.group) == "string" or type(mapping.group) == "function" then mapping.desc = mapping.group --[[@as string]] mapping.group = true end if mapping.plugin then mapping.group = true end if mapping.group and mapping.desc then mapping.desc = mapping.desc if type(mapping.desc) == "string" then mapping.desc = mapping.desc:gsub("^%+", "") end end if mapping.buffer == 0 or mapping.buffer == true then mapping.buffer = vim.api.nvim_get_current_buf() end if mapping.rhs then mapping.silent = mapping.silent ~= false end mapping.lhs = mapping.lhs or mapping.prefix if not mapping.lhs then return end mapping.prefix = nil local has_desc = mapping.desc ~= nil Util.getters(mapping, { "desc", "icon" }) if has_desc or mapping.group or mapping.hidden or mapping.rhs or (opts.version == M.VERSION and mapping.lhs) then local modes = mapping.mode or { "n" } --[[@as string|string[] ]] modes = type(modes) == "string" and vim.split(modes, "") or modes --[[@as string[] ]] for _, mode in ipairs(modes) do if mode ~= "v" and mode ~= Util.mapmode(mode) then M.warn("Invalid mode `" .. mode .. "`", mapping) end local m = vim.deepcopy(mapping) m.mode = mode table.insert(ret, m) end end end ---@param mapping wk.Mapping function M.create(mapping) assert(mapping.lhs, "Missing lhs") assert(mapping.mode, "Missing mode") assert(mapping.rhs, "Missing rhs") local valid = { "remap", "noremap", "buffer", "silent", "nowait", "expr", "unique", "script", "desc", "replace_keycodes" } local opts = {} ---@type vim.keymap.set.Opts for _, k in ipairs(valid) do if mapping[k] ~= nil then opts[k] = mapping[k] end end vim.keymap.set(mapping.mode, mapping.lhs, mapping.rhs, opts) end ---@param spec wk.Spec ---@param opts? wk.Parse function M.parse(spec, opts) opts = opts or {} M.notify = opts.notify ~= false local ret = M._parse(spec, nil, opts) M.notify = true for _, m in ipairs(ret) do if m.rhs and opts.create then M.create(m) end end return ret end return M folke-which-key.nvim-fcbf4ee/lua/which-key/migrate.lua000066400000000000000000000036071475635520600231370ustar00rootroot00000000000000local Mappings = require("which-key.mappings") local M = {} ---@param spec wk.Spec function M.migrate(spec) spec = vim.deepcopy(spec) local mappings = Mappings.parse(spec, { version = 1, notify = false }) ---@type table local mapping_modes = {} for _, m in ipairs(mappings) do m.preset = nil m[1] = m.lhs:gsub("", "<") m[2] = m.rhs m.lhs = nil m.rhs = nil local mode = m.mode m.mode = nil if m.silent then m.silent = nil end if m.group then m.group = m.desc m.desc = nil end local id = vim.inspect(m) mapping_modes[id] = mapping_modes[id] or { m = m, mode = {} } table.insert(mapping_modes[id].mode, mode) end mappings = vim.tbl_map(function(v) local m = v.m if not vim.deep_equal(v.mode, { "n" }) then m.mode = v.mode end return m end, vim.tbl_values(mapping_modes)) table.sort(mappings, function(a, b) return a[1] < b[1] end) -- Group by modes ---@type table local modes = {} for _, m in pairs(mappings) do local mode = m.mode or {} table.sort(mode) local id = table.concat(mode) modes[id] = modes[id] or {} table.insert(modes[id], m) end local lines = {} for mode, maps in pairs(modes) do if #maps > 2 and mode ~= "" then lines[#lines + 1] = " {" lines[#lines + 1] = " mode = " .. vim.inspect(maps[1].mode) .. "," for _, m in ipairs(maps) do m.mode = nil lines[#lines + 1] = " " .. vim.inspect(m):gsub("%s+", " ") .. "," end lines[#lines + 1] = " }," else for _, m in ipairs(maps) do if m.mode and #m.mode == 1 then m.mode = m.mode[1] end lines[#lines + 1] = " " .. vim.inspect(m):gsub("%s+", " ") .. "," end end end return "{\n" .. table.concat(lines, "\n") .. "\n}" end return M folke-which-key.nvim-fcbf4ee/lua/which-key/node.lua000066400000000000000000000114461475635520600224340ustar00rootroot00000000000000local Util = require("which-key.util") ---@class wk.Node ---@field _children table local M = {} ---@param parent? wk.Node ---@param key? string ---@return wk.Node function M.new(parent, key) local self = setmetatable({}, M) self.parent = parent self.key = key or "" self.path = {} self.global = true self._children = {} self.keys = (parent and parent.keys or "") .. self.key for _, p in ipairs(parent and parent.path or {}) do table.insert(self.path, p) end if key then table.insert(self.path, key) end return self end function M:has_nowait_ancestor() local node = self while node do if node.keymap and node.keymap.nowait then return true end node = node.parent end return false end function M:is_local() if self.path[1] == Util.norm("") then return true end if self.buffer and self.buffer > 0 then return true end for _, child in pairs(self._children) do if child:is_local() then return true end end return false end function M:__index(k) if k == "mapping" or k == "keymap" then return end local v = rawget(M, k) if v ~= nil then return v end for _, m in ipairs({ "mapping", "keymap" }) do local mm = rawget(self, m) if k == m then return mm end if mm and mm[k] ~= nil then return mm[k] end end end function M:__tostring() local info = { "Node(" .. self.keys .. ")" } if self:is_plugin() then info[#info + 1] = "Plugin(" .. self.plugin .. ")" end if self:is_proxy() then info[#info + 1] = "Proxy(" .. self.mapping.proxy .. ")" end return table.concat(info, " ") end ---@param depth? number function M:inspect(depth) local indent = (" "):rep(depth or 0) local ret = { indent .. tostring(self) } for _, child in ipairs(self:children()) do table.insert(ret, child:inspect((depth or 0) + 1)) end return table.concat(ret, "\n") end function M:count() return not self:can_expand() and vim.tbl_count(self._children) or #self:children() end function M:is_group() return self:can_expand() or self:count() > 0 end function M:is_proxy() return self.mapping and self.mapping.proxy end function M:is_plugin() return self.plugin ~= nil end function M:can_expand() return self.plugin or (self.mapping and (self.mapping.proxy or self.mapping.expand)) end ---@return wk.Node[] function M:children() return vim.tbl_values(self:expand()) end ---@return table function M:expand() if not self:can_expand() then return self._children end ---@type table local ret = {} -- plugin mappings if self.plugin then local plugin = require("which-key.plugins").plugins[self.plugin or ""] assert(plugin, "plugin not found") Util.debug(("Plugin(%q).expand"):format(self.plugin)) for i, item in ipairs(plugin.expand()) do item.order = i local child = M.new(self, item.key) --[[@as wk.Node.plugin.item]] setmetatable(child, { __index = setmetatable(item, M) }) ret[item.key] = child end end -- proxy mappings local proxy = self.mapping.proxy if proxy then local keys = Util.keys(proxy) local root = self:root() local node = root:find(keys, { expand = true }) if node then for k, v in pairs(node:expand()) do ret[k] = v end end end -- expand mappings local expand = self.mapping and self.mapping.expand if expand then local Tree = require("which-key.tree") local tmp = Tree.new() local mappings = require("which-key.mappings").parse(expand()) for _, mapping in ipairs(mappings) do tmp:add(mapping, true) end for _, child in ipairs(tmp.root:children()) do local action = child.mapping and child.mapping.rhs if type(action) == "function" then child.action = action elseif type(action) == "string" then Util.error("expand mappings only support functions as rhs:\n" .. vim.inspect(child.mapping)) end ret[child.key] = child end end -- custom mappings for k, v in pairs(self._children) do ret[k] = v end return ret end function M:root() local node = self while node.parent do node = node.parent end return node end ---@param path string[]|string ---@param opts? { create?: boolean, expand?: boolean } ---@return wk.Node? function M:find(path, opts) path = (type(path) == "string" and { path } or path) --[[@as string[] ]] opts = opts or {} local node = self for _, key in ipairs(path) do local child ---@type wk.Node? if opts.expand then child = node:expand()[key] else child = node._children[key] end if not child then if not opts.create then return end child = M.new(node, key) node._children[key] = child end node = child end return node end return M folke-which-key.nvim-fcbf4ee/lua/which-key/plugins/000077500000000000000000000000001475635520600224575ustar00rootroot00000000000000folke-which-key.nvim-fcbf4ee/lua/which-key/plugins/init.lua000066400000000000000000000021211475635520600241210ustar00rootroot00000000000000local Config = require("which-key.config") local Util = require("which-key.util") local M = {} ---@type table M.plugins = {} function M.setup() for name, opts in pairs(Config.plugins) do -- only setup plugin if we didnt load it before if not M.plugins[name] then if type(opts) == "boolean" then opts = { enabled = opts } end opts.enabled = opts.enabled ~= false if opts.enabled then M.plugins[name] = require("which-key.plugins." .. name) M._setup(M.plugins[name], opts) end end end end ---@param plugin wk.Plugin function M._setup(plugin, opts) if plugin.mappings then Config.add(plugin.mappings) end if plugin.setup then plugin.setup(opts) end end ---@param name string function M.cols(name) local plugin = M.plugins[name] assert(plugin, "plugin not found") local ret = {} ---@type wk.Col[] vim.list_extend(ret, plugin.cols or {}) ret[#ret + 1] = { key = "value", hl = "WhichKeyValue", width = 0.5 } return ret end ---@class wk.Node.plugin.item: wk.Node,wk.Plugin.item return M folke-which-key.nvim-fcbf4ee/lua/which-key/plugins/marks.lua000066400000000000000000000033361475635520600243040ustar00rootroot00000000000000---@diagnostic disable: missing-fields, inject-field ---@type wk.Plugin local M = {} M.name = "marks" M.mappings = { icon = { icon = "󰸕 ", color = "orange" }, plugin = "marks", { "`", desc = "marks" }, { "'", desc = "marks" }, { "g`", desc = "marks" }, { "g'", desc = "marks" }, } local labels = { ["^"] = "Last position of cursor in insert mode", ["."] = "Last change in current buffer", ['"'] = "Last exited current buffer", ["0"] = "In last file edited", ["'"] = "Back to line in current buffer where jumped from", ["`"] = "Back to position in current buffer where jumped from", ["["] = "To beginning of previously changed or yanked text", ["]"] = "To end of previously changed or yanked text", [""] = "To beginning of last visual selection", [">"] = "To end of last visual selection", } M.cols = { { key = "lnum", hl = "Number", align = "right" }, } function M.expand() local buf = vim.api.nvim_get_current_buf() local items = {} ---@type wk.Plugin.item[] local marks = {} ---@type vim.fn.getmarklist.ret.item[] vim.list_extend(marks, vim.fn.getmarklist(buf)) vim.list_extend(marks, vim.fn.getmarklist()) for _, mark in pairs(marks) do local key = mark.mark:sub(2, 2) local lnum = mark.pos[2] local line ---@type string? if mark.pos[1] and mark.pos[1] ~= 0 then line = vim.api.nvim_buf_get_lines(mark.pos[1], lnum - 1, lnum, false)[1] end local file = mark.file and vim.fn.fnamemodify(mark.file, ":p:~:.") table.insert(items, { key = key, desc = labels[key] or file and ("file: " .. file) or "", value = vim.trim(line or file or ""), highlights = { { 1, 5, "Number" } }, lnum = lnum, }) end return items end return M folke-which-key.nvim-fcbf4ee/lua/which-key/plugins/presets.lua000066400000000000000000000152721475635520600246560ustar00rootroot00000000000000local M = {} M.name = "presets" M.operators = { preset = true, mode = { "n", "x" }, { "!", desc = "Run program" }, { "<", desc = "Indent left" }, { ">", desc = "Indent right" }, { "V", desc = "Visual Line" }, { "c", desc = "Change" }, { "d", desc = "Delete" }, { "gU", desc = "Uppercase" }, { "gu", desc = "Lowercase" }, { "g~", desc = "Toggle case" }, { "gw", desc = "Format" }, { "r", desc = "Replace" }, { "v", desc = "Visual" }, { "y", desc = "Yank" }, { "zf", desc = "Create fold" }, { "~", desc = "Toggle case" }, } M.motions = { mode = { "o", "x", "n" }, preset = true, { "$", desc = "End of line" }, { "%", desc = "Matching (){}[]" }, { "0", desc = "Start of line" }, { "F", desc = "Move to prev char" }, { "G", desc = "Last line" }, { "T", desc = "Move before prev char" }, { "^", desc = "Start of line (non ws)" }, { "b", desc = "Prev word" }, { "e", desc = "Next end of word" }, { "f", desc = "Move to next char" }, { "ge", desc = "Prev end of word" }, { "gg", desc = "First line" }, { "h", desc = "Left" }, { "j", desc = "Down" }, { "k", desc = "Up" }, { "l", desc = "Right" }, { "t", desc = "Move before next char" }, { "w", desc = "Next word" }, { "{", desc = "Prev empty line" }, { "}", desc = "Next empty line" }, { ";", desc = "Next ftFT" }, { ",", desc = "Prev ftFT" }, { "/", desc = "Search forward" }, { "?", desc = "Search backward" }, { "B", desc = "Prev WORD" }, { "E", desc = "Next end of WORD" }, { "W", desc = "Next WORD" }, } M.text_objects = { mode = { "o", "x" }, preset = true, { "a", group = "around" }, { 'a"', desc = '" string' }, { "a'", desc = "' string" }, { "a(", desc = "[(]) block" }, { "a)", desc = "[(]) block" }, { "a<", desc = "<> block" }, { "a>", desc = "<> block" }, { "aB", desc = "[{]} block" }, { "aW", desc = "WORD with ws" }, { "a[", desc = "[] block" }, { "a]", desc = "[] block" }, { "a`", desc = "` string" }, { "ab", desc = "[(]) block" }, { "ap", desc = "paragraph" }, { "as", desc = "sentence" }, { "at", desc = "tag block" }, { "aw", desc = "word with ws" }, { "a{", desc = "[{]} block" }, { "a}", desc = "[{]} block" }, { "i", group = "inside" }, { 'i"', desc = 'inner " string' }, { "i'", desc = "inner ' string" }, { "i(", desc = "inner [(])" }, { "i)", desc = "inner [(])" }, { "i<", desc = "inner <>" }, { "i>", desc = "inner <>" }, { "iB", desc = "inner [{]}" }, { "iW", desc = "inner WORD" }, { "i[", desc = "inner []" }, { "i]", desc = "inner []" }, { "i`", desc = "inner ` string" }, { "ib", desc = "inner [(])" }, { "ip", desc = "inner paragraph" }, { "is", desc = "inner sentence" }, { "it", desc = "inner tag block" }, { "iw", desc = "inner word" }, { "i{", desc = "inner [{]}" }, { "i}", desc = "inner [{]}" }, } M.windows = { preset = true, mode = { "n", "x" }, { "", group = "window" }, { "+", desc = "Increase height" }, { "-", desc = "Decrease height" }, { "<", desc = "Decrease width" }, { "=", desc = "Equally high and wide" }, { ">", desc = "Increase width" }, { "T", desc = "Break out into a new tab" }, { "_", desc = "Max out the height" }, { "h", desc = "Go to the left window" }, { "j", desc = "Go to the down window" }, { "k", desc = "Go to the up window" }, { "l", desc = "Go to the right window" }, { "o", desc = "Close all other windows" }, { "q", desc = "Quit a window" }, { "s", desc = "Split window" }, { "v", desc = "Split window vertically" }, { "w", desc = "Switch windows" }, { "x", desc = "Swap current with next" }, { "|", desc = "Max out the width" }, { "H", desc = "Move window to far left" }, { "J", desc = "Move window to far bottom" }, { "K", desc = "Move window to far top" }, { "L", desc = "Move window to far right" }, } M.z = { preset = true, { "z", desc = "Top this line" }, { "z=", desc = "Spelling suggestions" }, { "zA", desc = "Toggle all folds under cursor" }, { "zC", desc = "Close all folds under cursor" }, { "zD", desc = "Delete all folds under cursor" }, { "zE", desc = "Delete all folds in file" }, { "zH", desc = "Half screen to the left" }, { "zL", desc = "Half screen to the right" }, { "zM", desc = "Close all folds" }, { "zO", desc = "Open all folds under cursor" }, { "zR", desc = "Open all folds" }, { "za", desc = "Toggle fold under cursor" }, { "zb", desc = "Bottom this line" }, { "zc", desc = "Close fold under cursor" }, { "zd", desc = "Delete fold under cursor" }, { "ze", desc = "Right this line" }, { "zg", desc = "Add word to spell list" }, { "zi", desc = "Toggle folding" }, { "zm", desc = "Fold more" }, { "zo", desc = "Open fold under cursor" }, { "zr", desc = "Fold less" }, { "zs", desc = "Left this line" }, { "zt", desc = "Top this line" }, { "zv", desc = "Show cursor line" }, { "zw", desc = "Mark word as bad/misspelling" }, { "zx", desc = "Update folds" }, { "zz", desc = "Center this line" }, } M.nav = { preset = true, { "H", desc = "Home line of window (top)" }, { "L", desc = "Last line of window" }, { "M", desc = "Middle line of window" }, { "[%", desc = "Previous unmatched group" }, { "[(", desc = "Previous (" }, { "[<", desc = "Previous <" }, { "[M", desc = "Previous method end" }, { "[m", desc = "Previous method start" }, { "[s", desc = "Previous misspelled word" }, { "[{", desc = "Previous {" }, { "]%", desc = "Next unmatched group" }, { "](", desc = "Next (" }, { "]<", desc = "Next <" }, { "]M", desc = "Next method end" }, { "]m", desc = "Next method start" }, { "]s", desc = "Next misspelled word" }, { "]{", desc = "Next {" }, } M.g = { preset = true, { "g%", desc = "Cycle backwards through results" }, { "g,", desc = "Go to [count] newer position in change list" }, { "g;", desc = "Go to [count] older position in change list" }, { "gN", desc = "Search backwards and select" }, { "gT", desc = "Go to previous tab page" }, { "gf", desc = "Go to file under cursor" }, { "gi", desc = "Go to last insert" }, { "gn", desc = "Search forwards and select" }, { "gt", desc = "Go to next tab page" }, { "gv", desc = "Last visual selection" }, { "gx", desc = "Open file with system app" }, } function M.setup(opts) local wk = require("which-key") -- Operators if opts.operators then wk.add(M.operators) end -- Motions if opts.motions then wk.add(M.motions) end -- Text objects if opts.text_objects then wk.add(M.text_objects) end -- Misc for _, preset in pairs({ "windows", "nav", "z", "g" }) do if opts[preset] ~= false then wk.add(M[preset]) end end end return M folke-which-key.nvim-fcbf4ee/lua/which-key/plugins/registers.lua000066400000000000000000000035471475635520600252020ustar00rootroot00000000000000local Util = require("which-key.util") ---@diagnostic disable: missing-fields, inject-field ---@type wk.Plugin local M = {} M.name = "registers" M.mappings = { icon = { icon = "󰅍 ", color = "blue" }, plugin = "registers", { '"', mode = { "n", "x" }, desc = "registers" }, { "", mode = { "i", "c" }, desc = "registers" }, } M.registers = '*+"-:.%/#=_abcdefghijklmnopqrstuvwxyz0123456789' local labels = { ['"'] = "last deleted, changed, or yanked content", ["0"] = "last yank", ["-"] = "deleted or changed content smaller than one line", ["."] = "last inserted text", ["%"] = "name of the current file", [":"] = "most recent executed command", ["#"] = "alternate buffer", ["="] = "result of an expression", ["+"] = "synchronized with the system clipboard", ["*"] = "synchronized with the selection clipboard", ["_"] = "black hole", ["/"] = "last search pattern", } M.replace = { [""] = " ", [""] = "<", [""] = "\n", ["\r"] = "", } function M.expand() local items = {} ---@type wk.Plugin.item[] local is_osc52 = vim.g.clipboard and vim.g.clipboard.name == "OSC 52" local has_clipboard = vim.g.loaded_clipboard_provider == 2 for i = 1, #M.registers, 1 do local key = M.registers:sub(i, i) local value = "" if is_osc52 and key:match("[%+%*]") then value = "OSC 52 detected, register not checked to maintain compatibility" elseif has_clipboard or not key:match("[%+%*]") then local ok, reg_value = pcall(vim.fn.getreg, key, 1) value = (ok and reg_value or "") --[[@as string]] end if value ~= "" then value = vim.fn.keytrans(value) --[[@as string]] for k, v in pairs(M.replace) do value = value:gsub(k, v) --[[@as string]] end table.insert(items, { key = key, desc = labels[key] or "", value = value }) end end return items end return M folke-which-key.nvim-fcbf4ee/lua/which-key/plugins/spelling.lua000066400000000000000000000023351475635520600250020ustar00rootroot00000000000000---@diagnostic disable: missing-fields, inject-field ---@type wk.Plugin local M = {} M.name = "spelling" M.mappings = { { "z=", icon = { icon = " ", color = "red" }, plugin = "spelling", desc = "Spelling Suggestions", }, } ---@type table M.opts = {} function M.setup(opts) M.opts = opts end function M.expand() -- if started with a count, let the default keybinding work local count = vim.v.count if count and count > 0 then return {} end local cursor_word = vim.fn.expand("") -- get a misspelled word from under the cursor, if not found, then use the cursor_word instead local bad = vim.fn.spellbadword(cursor_word) local word = bad[1] == "" and cursor_word or bad[1] ---@type string[] local suggestions = vim.fn.spellsuggest(word, M.opts.suggestions or 20, bad[2] == "caps" and 1 or 0) local items = {} ---@type wk.Plugin.item[] local keys = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" for i, label in ipairs(suggestions) do local key = keys:sub(i, i) table.insert(items, { key = key, desc = label, action = function() vim.cmd("norm! " .. i .. "z=") end, }) end return items end return M folke-which-key.nvim-fcbf4ee/lua/which-key/presets.lua000066400000000000000000000012651475635520600231720ustar00rootroot00000000000000---@type table return { helix = { win = { width = { min = 30, max = 60 }, height = { min = 4, max = 0.75 }, padding = { 0, 1 }, col = -1, row = -1, border = "rounded", title = true, title_pos = "left", }, layout = { width = { min = 30 }, }, }, modern = { win = { width = 0.9, height = { min = 4, max = 25 }, col = 0.5, row = -1, border = "rounded", title = true, title_pos = "center", }, }, classic = { win = { width = math.huge, height = { min = 4, max = 25 }, col = 0, row = -1, border = "none", }, }, } folke-which-key.nvim-fcbf4ee/lua/which-key/state.lua000066400000000000000000000237121475635520600226260ustar00rootroot00000000000000local Buf = require("which-key.buf") local Config = require("which-key.config") local Triggers = require("which-key.triggers") local Util = require("which-key.util") local uv = vim.uv or vim.loop local M = {} ---@class wk.State ---@field mode wk.Mode ---@field node wk.Node ---@field filter wk.Filter ---@field started number ---@field show boolean ---@type wk.State? M.state = nil M.recursion = 0 M.recursion_timer = uv.new_timer() M.redraw_timer = uv.new_timer() ---@return boolean safe, string? reason function M.safe(mode_change) local old, _new = unpack(vim.split(mode_change, ":", { plain = true })) if old == "c" then return false, "command-mode" elseif Util.in_macro() then return false, "macro" elseif mode_change:lower() == "v:v" then return false, "visual-block" end local pending = vim.fn.getcharstr(1) if pending ~= "" then return false, "pending " .. ("%q"):format(vim.fn.strtrans(pending)) end return true end function M.setup() local group = vim.api.nvim_create_augroup("wk", { clear = true }) if Config.debug then vim.on_key(function(_raw, key) if key and #key > 0 then key = vim.fn.keytrans(key) if not key:find("ScrollWheel") and not key:find("Mouse") then Util.debug("on_key", key) end end end) end vim.api.nvim_create_autocmd({ "RecordingEnter", "RecordingLeave" }, { group = group, callback = function(ev) Util.debug(ev.event) if ev.event == "RecordingEnter" then Buf.clear({ buf = ev.buf }) M.stop() end end, }) local hide = uv.new_timer() vim.api.nvim_create_autocmd({ "FocusLost", "FocusGained" }, { group = group, callback = function(ev) if ev.event == "FocusGained" then hide:stop() elseif M.state then hide:start(5000, 0, function() vim.api.nvim_input("") end) end end, }) local function defer() local mode = vim.api.nvim_get_mode().mode local mode_keys = Util.keys(mode) local ctx = { operator = mode:find("o") and vim.v.operator or nil, mode = mode_keys[1], } return Config.defer(ctx) end local cooldown = Util.cooldown() -- this prevents restarting which-key in the same tick vim.api.nvim_create_autocmd("ModeChanged", { group = group, callback = function(ev) Util.trace("ModeChanged(" .. ev.match .. ")") local mode = Buf.get() if cooldown() then Util.debug("cooldown") Util.trace() return end local safe, reason = M.safe(ev.match) Util.debug(safe and "Safe(true)" or ("Unsafe(" .. reason .. ")")) if not safe then if mode then Triggers.suspend(mode) end -- dont start when recording or when chars are pending cooldown(true) -- cooldown till next tick M.stop() -- make sure the buffer mode exists elseif mode and Util.xo() then if Config.triggers.modes[mode.mode] and not M.state then M.start({ defer = defer() }) end elseif not ev.match:find("c") then M.stop() end Util.trace() end, }) vim.api.nvim_create_autocmd({ "LspAttach", "LspDetach" }, { group = group, callback = function(ev) Util.trace(ev.event .. "(" .. ev.buf .. ")") Buf.clear({ buf = ev.buf }) Util.trace() end, }) vim.api.nvim_create_autocmd({ "BufReadPost", "BufNew" }, { group = group, callback = function(ev) Util.trace(ev.event .. "(" .. ev.buf .. ")") Buf.clear({ buf = ev.buf }) Util.trace() end, }) local current_buf = vim.api.nvim_get_current_buf() vim.api.nvim_create_autocmd({ "BufEnter" }, { group = group, callback = function(ev) current_buf = ev.buf ---@type number Util.trace(ev.event .. "(" .. ev.buf .. ")") Buf.get() Util.trace() end, }) -- HACK: ModeChanged does not always trigger, so we need to manually -- check for mode changes. This seems to be due to the usage of `:norm` in autocmds. -- See https://github.com/folke/which-key.nvim/issues/787 local timer = uv.new_timer() timer:start(0, 50, function() local mode = Util.mapmode() -- check if the mode exists for the current buffer if Buf.bufs[current_buf] and Buf.bufs[current_buf].modes[mode] then return end vim.schedule(Buf.get) end) end function M.stop() if M.state == nil then return end Util.debug("state:stop") M.state = nil vim.schedule(function() if not M.state then require("which-key.view").hide() end end) end ---@param state wk.State ---@param key? string ---@return wk.Node? node function M.check(state, key) local View = require("which-key.view") local node = key == nil and state.node or (key and state.node:find(key, { expand = true })) local delta = uv.hrtime() / 1e6 - state.started local timedout = vim.o.timeout and delta > vim.o.timeoutlen if node then -- NOTE: a node can be both a keymap and a group -- when it's both, we honor timeoutlen and nowait to decide what to do local has_children = node:count() > 0 local is_nowait = node.keymap and (node.keymap.nowait == 1 or not timedout) local is_action = node.action ~= nil if has_children and not is_nowait and not is_action then Util.debug("continue", node.keys, tostring(state.mode), node.plugin) return node end elseif key == "" then if state.mode:xo() then Util.exit() -- cancel and exit if in xo mode end return elseif key == "" then return state.node.parent or state.mode.tree.root elseif View.valid() and key == Config.keys.scroll_down then View.scroll(false) return state.node elseif View.valid() and key == Config.keys.scroll_up then View.scroll(true) return state.node end M.execute(state, key, node) end ---@param state wk.State ---@param key? string ---@param node? wk.Node ---@return false|wk.Node? function M.execute(state, key, node) Triggers.suspend(state.mode) if node and node.action then return node.action() end local keystr = node and node.keys or (state.node.keys .. (key or "")) if not state.mode:xo() then if vim.v.count > 0 and state.mode.mode ~= "i" and state.mode.mode ~= "c" then keystr = vim.v.count .. keystr end if vim.v.register ~= Util.reg() and state.mode.mode ~= "i" and state.mode.mode ~= "c" then keystr = '"' .. vim.v.register .. keystr end end Util.debug("feedkeys", tostring(state.mode), keystr) local feed = vim.api.nvim_replace_termcodes(keystr, true, true, true) vim.api.nvim_feedkeys(feed, "mit", false) end function M.getchar() return pcall(vim.fn.getcharstr) end ---@param state wk.State ---@return wk.Node? node, boolean? exit function M.step(state) M.redraw_timer:start( 50, 0, vim.schedule_wrap(function() if vim.api.nvim__redraw then vim.api.nvim__redraw({ cursor = true, valid = true, flush = true }) else vim.cmd.redraw() end end) ) vim.schedule(function() end) Util.debug("getchar") local ok, char = M.getchar() if not ok then Util.debug("nok", char) return nil, true end local key = vim.fn.keytrans(char) Util.debug("got", key) local node = M.check(state, key) if node == state.node then return M.step(state) -- same node, so try again (scrolling) end return node, key == "" end ---@param opts? wk.Filter function M.start(opts) Util.trace("State(start)", function() local mode = opts and opts.mode or Util.mapmode() local buf = opts and opts.buf or 0 local keys = opts and opts.keys or "" return { "Mode(" .. mode .. ":" .. buf .. ") Node(" .. keys .. ")", opts } end) opts = opts or {} opts.update = true local mode = Buf.get(opts) opts.update = nil if not mode then Util.debug("no mode") Util.trace() return false end local node = mode.tree:find(opts.keys or {}, { expand = true }) if not node then Util.debug("no node") Util.trace() return false end local mapmode = mode.mode M.recursion = M.recursion + 1 M.recursion_timer:start(500, 0, function() M.recursion = 0 end) if M.recursion > 50 then Util.error({ "Recursion detected.", "Are you manually loading which-key in a keymap?", "Use `opts.triggers` instead.", "Please check the docs.", }) Util.debug("recursion detected. Aborting") Util.trace() return false end local View = require("which-key.view") M.state = { mode = mode, node = node, filter = opts, started = uv.hrtime() / 1e6 - (opts.waited or 0), show = opts.defer ~= true, } if not M.check(M.state) then Util.debug("executed") Util.trace() return true end local exit = false while M.state do mode = Buf.get(opts) if not mode or mode.mode ~= mapmode then break end if M.state.show then View.update(opts) end local child, _exit = M.step(M.state) if child and M.state then M.state.node = child M.state.show = true else exit = _exit or false break end end M.redraw_timer:stop() if opts.loop and not exit then -- NOTE: flush pending keys to prevent a trigger loop vim.api.nvim_feedkeys("", "x", false) vim.schedule(function() M.start(opts) end) else M.state = nil View.hide() end Util.trace() return true end function M.update() if not M.state then return end local mode = Buf.get() if not mode or mode.mode ~= M.state.mode.mode then return end local node = mode.tree:find(M.state.node.path) if not node then return end M.state.node = node require("which-key.view").update({ schedule = false }) end ---@param opts {delay?:number, mode:string, keys:string, plugin?:string, waited?: number} function M.delay(opts) local delay = opts.delay or type(Config.delay) == "function" and Config.delay(opts) or Config.delay --[[@as number]] if opts.waited then delay = delay - opts.waited end return math.max(0, delay) end return M folke-which-key.nvim-fcbf4ee/lua/which-key/text.lua000066400000000000000000000071201475635520600224650ustar00rootroot00000000000000local Util = require("which-key.util") ---@class wk.Segment ---@field str string Text ---@field hl? string Extmark hl group ---@field line? number line number in a multiline segment ---@field width? number ---@class wk.Text.opts ---@field multiline? boolean ---@field indent? boolean ---@class wk.Text ---@field _lines wk.Segment[][] ---@field _col number ---@field _indents string[] ---@field _opts wk.Text.opts local M = {} M.__index = M M.ns = vim.api.nvim_create_namespace("wk.text") ---@param opts? wk.Text.opts function M.new(opts) local self = setmetatable({}, M) self._lines = {} self._col = 0 self._opts = opts or {} self._indents = {} for i = 0, 100, 1 do self._indents[i] = (" "):rep(i) end return self end function M:height() return #self._lines end ---@return number function M:width() local width = 0 for _, line in ipairs(self._lines) do local w = 0 for _, segment in ipairs(line) do w = w + vim.fn.strdisplaywidth(segment.str) end width = math.max(width, w) end return width end ---@param text string|wk.Segment[] ---@param opts? string|{hl?:string, line?:number} function M:append(text, opts) opts = opts or {} if #self._lines == 0 then self:nl() end if type(text) == "table" then for _, s in ipairs(text) do s.width = s.width or #s.str self._col = self._col + s.width table.insert(self._lines[#self._lines], s) end return self end opts = type(opts) == "string" and { hl = opts } or opts for l, line in ipairs(vim.split(text, "\n", { plain = true })) do local width = #line self._col = self._col + width table.insert(self._lines[#self._lines], { str = line, width = width, hl = opts.hl, line = opts.line or l, }) end return self end function M:nl() table.insert(self._lines, {}) self._col = 0 return self end ---@param opts? {sep?:string} function M:statusline(opts) local sep = opts and opts.sep or " " local lines = {} ---@type string[] for _, line in ipairs(self._lines) do local parts = {} for _, segment in ipairs(line) do local str = segment.str:gsub("%%", "%%%%") if segment.hl then str = ("%%#%s#%s%%*"):format(segment.hl, str) end parts[#parts + 1] = str end table.insert(lines, table.concat(parts, "")) end return table.concat(lines, sep) end function M:render(buf) local lines = {} for _, line in ipairs(self._lines) do local parts = {} ---@type string[] for _, segment in ipairs(line) do parts[#parts + 1] = segment.str end table.insert(lines, table.concat(parts, "")) end vim.bo[buf].modifiable = true vim.api.nvim_buf_clear_namespace(buf, M.ns, 0, -1) vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) for l, line in ipairs(self._lines) do local col = 0 local row = l - 1 for _, segment in ipairs(line) do local width = segment.width if segment.hl then Util.set_extmark(buf, M.ns, row, col, { hl_group = segment.hl, end_col = col + width, }) end col = col + width end end vim.bo[buf].modifiable = false end function M:trim() while #self._lines > 0 and #self._lines[#self._lines] == 0 do table.remove(self._lines) end end function M:row() return #self._lines == 0 and 1 or #self._lines end ---@param opts? {display:boolean} function M:col(opts) if opts and opts.display then local ret = 0 for _, segment in ipairs(self._lines[#self._lines] or {}) do ret = ret + vim.fn.strdisplaywidth(segment.str) end return ret end return self._col end return M folke-which-key.nvim-fcbf4ee/lua/which-key/tree.lua000066400000000000000000000050611475635520600224420ustar00rootroot00000000000000local Config = require("which-key.config") local Node = require("which-key.node") local Util = require("which-key.util") ---@class wk.Tree ---@field root wk.Node local M = {} M.__index = M ---@type table> M.dups = {} function M.new() local self = setmetatable({}, M) self:clear() return self end function M:clear() self.root = Node.new() end ---@param keymap wk.Mapping|wk.Keymap ---@param virtual? boolean function M:add(keymap, virtual) if not Config.filter(keymap) then return end local keys = Util.keys(keymap.lhs, { norm = true }) local node = assert(self.root:find(keys, { create = true })) node.plugin = node.plugin or keymap.plugin if virtual then ---@cast node wk.Node if node.mapping and not keymap.preset and not node.mapping.preset then local id = keymap.mode .. ":" .. node.keys M.dups[id] = M.dups[id] or {} M.dups[id][keymap] = true M.dups[id][node.mapping] = true end if not (keymap.preset and node.keymap and node.keymap.desc) then node.mapping = keymap --[[@as wk.Mapping]] end else node.keymap = keymap end end ---@param node wk.Node function M:del(node) if node == self.root then return self:clear() end local parent = node.parent assert(parent, "node has no parent") parent._children[node.key] = nil if not self:keep(parent) then self:del(parent) end end ---@param node wk.Node function M:keep(node) if node.hidden or (node.keymap and node.keymap.desc == "which_key_ignore") then return false end if node.mapping and node.mapping.real and not node.keymap then return false end return node.keymap or (node.mapping and not node.group) or node:is_group() end function M:fix() self:walk(function(node) if not self:keep(node) then self:del(node) return false end end) end ---@param keys string|string[] ---@param opts? { create?: boolean, expand?: boolean } ---@return wk.Node? function M:find(keys, opts) keys = type(keys) == "string" and Util.keys(keys) or keys return self.root:find(keys, opts) end ---@param fn fun(node: wk.Node):boolean? ---@param opts? {expand?: boolean} function M:walk(fn, opts) opts = opts or {} ---@type wk.Node[] local queue = { self.root } while #queue > 0 do local node = table.remove(queue, 1) ---@type wk.Node if node == self.root or fn(node) ~= false then local children = opts.expand and node:children() or node._children for _, child in pairs(children) do queue[#queue + 1] = child end end end end return M folke-which-key.nvim-fcbf4ee/lua/which-key/triggers.lua000066400000000000000000000076101475635520600233330ustar00rootroot00000000000000local Util = require("which-key.util") ---@class wk.Trigger ---@field buf number ---@field mode string ---@field keys string ---@field plugin? string local M = {} M._triggers = {} ---@type table M.suspended = {} ---@type table M.timer = (vim.uv or vim.loop).new_timer() --- Checks if a mapping already exists that is not a which-key trigger. ---@param trigger wk.Trigger function M.is_mapped(trigger) ---@type wk.Keymap? local km pcall(vim.api.nvim_buf_call, trigger.buf, function() km = vim.fn.maparg(trigger.keys, trigger.mode, false, true) --[[@as wk.Keymap]] end) -- not mapped if not km or vim.tbl_isempty(km) then return false end -- ignore mappings if Util.is_nop(km.rhs) then return false end -- ignore which-key triggers if km.desc and km.desc:find("which-key-trigger", 1, true) then return false end return true end ---@param trigger wk.Trigger function M.add(trigger) if M.is_mapped(trigger) then return end vim.keymap.set(trigger.mode, trigger.keys, function() require("which-key.state").start({ keys = trigger.keys, }) end, { buffer = trigger.buf, nowait = true, desc = "which-key-trigger" .. (trigger.plugin and " " .. trigger.plugin or ""), }) M._triggers[M.id(trigger)] = trigger end function M.is_active() return vim.tbl_isempty(M._triggers) end ---@param trigger wk.Trigger function M.del(trigger) M._triggers[M.id(trigger)] = nil if not vim.api.nvim_buf_is_valid(trigger.buf) then return end if M.is_mapped(trigger) then return end pcall(vim.keymap.del, trigger.mode, trigger.keys, { buffer = trigger.buf }) end ---@param trigger wk.Trigger function M.id(trigger) return trigger.buf .. ":" .. trigger.mode .. ":" .. trigger.keys end ---@param trigger wk.Trigger function M.has(trigger) return M._triggers[M.id(trigger)] ~= nil end ---@param mode wk.Mode ---@param triggers? wk.Trigger[] function M.update(mode, triggers) M.cleanup() if not mode.buf:valid() then for _, trigger in pairs(M._triggers) do if trigger.buf == mode.buf.buf then M.del(trigger) end end return end local adds = {} ---@type string[] local dels = {} ---@type string[] local keep = {} ---@type table for _, node in ipairs(triggers or mode.triggers) do ---@type wk.Trigger local trigger = { buf = mode.buf.buf, mode = mode.mode, keys = node.keys, plugin = node.plugin, } local id = M.id(trigger) keep[id] = true if not M.has(trigger) then adds[#adds + 1] = trigger.keys M.add(trigger) end end for id, trigger in pairs(M._triggers) do if trigger.buf == mode.buf.buf and trigger.mode == mode.mode and not keep[id] then M.del(trigger) dels[#dels + 1] = trigger.keys end end if #adds > 0 then Util.debug("Trigger(add) " .. tostring(mode) .. " " .. table.concat(adds, " ")) end if #dels > 0 then Util.debug("Trigger(del) " .. tostring(mode) .. " " .. table.concat(dels, " ")) end end ---@param mode wk.Mode function M.attach(mode) if M.suspended[mode] then return end M.update(mode) end ---@param mode wk.Mode function M.detach(mode) M.update(mode, {}) end ---@param mode? wk.Mode function M.schedule(mode) if mode then M.suspended[mode] = true end M.timer:start( 0, 0, vim.schedule_wrap(function() if Util.in_macro() then return vim.defer_fn(M.schedule, 100) end for m, _ in pairs(M.suspended) do M.suspended[m] = nil M.attach(m) end end) ) end function M.cleanup() for _, trigger in pairs(M._triggers) do if not vim.api.nvim_buf_is_valid(trigger.buf) then M.del(trigger) end end end ---@param mode wk.Mode function M.suspend(mode) Util.debug("suspend", tostring(mode)) M.detach(mode) M.suspended[mode] = true M.schedule() end return M folke-which-key.nvim-fcbf4ee/lua/which-key/types.lua000066400000000000000000000063031475635520600226470ustar00rootroot00000000000000---@meta --# selene: allow(unused_variable) ---@class wk.Filter ---@field mode? string ---@field buf? number ---@field keys? string ---@field global? boolean ---@field local? boolean ---@field update? boolean ---@field delay? number ---@field loop? boolean ---@field defer? boolean don't show the popup immediately. Wait for the first key to be pressed ---@field waited? number ---@field check? boolean ---@field expand? boolean ---@class wk.Icon ---@field icon? string ---@field hl? string ---@field cat? "file" | "filetype" | "extension" ---@field name? string ---@field color? false | "azure" | "blue" | "cyan" | "green" | "grey" | "orange" | "purple" | "red" | "yellow" ---@class wk.IconProvider ---@field name string ---@field available? boolean ---@field get fun(icon: wk.Icon):(icon: string?, hl: string?) ---@class wk.IconRule: wk.Icon ---@field pattern? string ---@field plugin? string ---@class wk.Keymap: vim.api.keyset.keymap ---@field lhs string ---@field mode string ---@field rhs? string|fun() ---@field lhsraw? string ---@field buffer? number --- Represents a node in the which-key tree ---@class wk.Node: wk.Mapping ---@field key string single key of the node ---@field path string[] path to the node (all keys leading to this node) ---@field keys string full key sequence ---@field parent? wk.Node parent node ---@field keymap? wk.Keymap Real keymap ---@field mapping? wk.Mapping Mapping info supplied by user ---@field action? fun() action to execute when node is selected (used by plugins) ---@class wk.Mapping: wk.Keymap ---@field idx? number ---@field plugin? string ---@field group? boolean ---@field remap? boolean ---@field hidden? boolean ---@field real? boolean this is a mapping for a real keymap. Hide it if the real keymap does not exist ---@field preset? boolean ---@field icon? wk.Icon|string ---@field proxy? string ---@field expand? fun():wk.Spec ---@class wk.Spec: {[number]: wk.Spec} , wk.Mapping ---@field [1]? string ---@field [2]? string|fun() ---@field lhs? string ---@field group? string|fun():string ---@field desc? string|fun():string ---@field icon? wk.Icon|string|fun():(wk.Icon|string) ---@field buffer? number|boolean ---@field mode? string|string[] ---@field cond? boolean|fun():boolean? ---@class wk.Win.opts: vim.api.keyset.win_config ---@field width? wk.Dim ---@field height? wk.Dim ---@field wo? vim.wo ---@field bo? vim.bo ---@field padding? {[1]: number, [2]:number} ---@field no_overlap? boolean ---@class wk.Col ---@field key string ---@field hl? string ---@field width? number ---@field padding? number[] ---@field default? string ---@field align? "left"|"right"|"center" ---@class wk.Table.opts ---@field cols wk.Col[] ---@field rows table[] ---@class wk.Plugin.item ---@field key string ---@field value string ---@field desc string ---@field order? number ---@field action? fun() ---@class wk.Plugin ---@field name string ---@field cols? wk.Col[] ---@field mappings? wk.Spec ---@field expand fun():wk.Plugin.item[] ---@field setup fun(opts: table) ---@class wk.Item: wk.Node ---@field node wk.Node ---@field key string ---@field raw_key string ---@field desc string ---@field group? boolean ---@field order? number ---@field icon? string ---@field icon_hl? string folke-which-key.nvim-fcbf4ee/lua/which-key/util.lua000066400000000000000000000167571475635520600224760ustar00rootroot00000000000000local M = {} M.cache = { keys = {}, ---@type table norm = {}, ---@type table termcodes = {}, ---@type table } function M.t(str) M.cache.termcodes[str] = M.cache.termcodes[str] or vim.api.nvim_replace_termcodes(str, true, true, true) return M.cache.termcodes[str] end M.CR = M.t("") M.ESC = M.t("") M.BS = M.t("") M.EXIT = M.t("") M.LUA_CALLBACK = "\x80\253g" M.CMD = "\x80\253h" function M.exit() vim.api.nvim_feedkeys(M.EXIT, "n", false) vim.api.nvim_feedkeys(M.ESC, "n", false) end function M.in_macro() return vim.fn.reg_recording() ~= "" or vim.fn.reg_executing() ~= "" end ---@param rhs string|fun() function M.is_nop(rhs) return type(rhs) == "string" and (rhs == "" or rhs:lower() == "") end --- Normalizes (and fixes) the lhs of a keymap ---@param lhs string function M.norm(lhs) if M.cache.norm[lhs] then return M.cache.norm[lhs] end M.cache.norm[lhs] = vim.fn.keytrans(M.t(lhs)) return M.cache.norm[lhs] end -- Default register function M.reg() -- this will be set to 2 if there is a non-empty clipboard -- tool available if vim.g.loaded_clipboard_provider ~= 2 then return '"' end local cb = vim.o.clipboard return cb:find("unnamedplus") and "+" or cb:find("unnamed") and "*" or '"' end --- Returns the keys of a keymap, taking multibyte and special keys into account ---@param lhs string ---@param opts? {norm?: boolean} function M.keys(lhs, opts) lhs = opts and opts.norm == false and lhs or M.norm(lhs) if M.cache.keys[lhs] then return M.cache.keys[lhs] end local ret = {} ---@type string[] local bytes = vim.fn.str2list(lhs) ---@type number[] local special = nil ---@type string? for _, byte in ipairs(bytes) do local char = vim.fn.nr2char(byte) ---@type string if char == "<" then special = "<" elseif special then special = special .. char if char == ">" then ret[#ret + 1] = special == "" and "<" or special special = nil end else ret[#ret + 1] = char end end M.cache.keys[lhs] = ret return ret end ---@param mode? string function M.mapmode(mode) mode = mode or vim.api.nvim_get_mode().mode mode = mode:gsub(M.t(""), "v"):gsub(M.t(""), "s"):lower() if mode:sub(1, 2) == "no" then return "o" end if mode:sub(1, 1) == "v" then return "x" -- mapmode is actually "x" for visual only mappings end return mode:sub(1, 1):match("[ncitsxo]") or "n" end function M.xo() return M.mapmode():find("[xo]") ~= nil end ---@alias NotifyOpts {level?: number, title?: string, once?: boolean, id?:string} ---@param msg string|string[] ---@param opts? NotifyOpts function M.notify(msg, opts) opts = opts or {} msg = type(msg) == "table" and table.concat(msg, "\n") or msg ---@cast msg string msg = vim.trim(msg) return vim[opts.once and "notify_once" or "notify"](msg, opts.level, { title = opts.title or "which-key.nvim", on_open = function(win) M.wo(win, { conceallevel = 3, spell = false, concealcursor = "n" }) vim.treesitter.start(vim.api.nvim_win_get_buf(win), "markdown") end, }) end ---@param msg string|string[] ---@param opts? NotifyOpts function M.warn(msg, opts) M.notify(msg, vim.tbl_extend("keep", { level = vim.log.levels.WARN }, opts or {})) end ---@param msg string|string[] ---@param opts? NotifyOpts function M.info(msg, opts) M.notify(msg, vim.tbl_extend("keep", { level = vim.log.levels.INFO }, opts or {})) end ---@param msg string|string[] ---@param opts? NotifyOpts function M.error(msg, opts) M.notify(msg, vim.tbl_extend("keep", { level = vim.log.levels.ERROR }, opts or {})) end ---@generic F: fun() ---@param ms number ---@param fn F ---@return F function M.debounce(ms, fn) local timer = (vim.uv or vim.loop).new_timer() return function(...) local args = { ... } timer:start( ms, 0, vim.schedule_wrap(function() fn(args) end) ) end end ---@param opts? {msg?: string} function M.try(fn, opts) local ok, err = pcall(fn) if not ok then local msg = opts and opts.msg or "Something went wrong:" msg = msg .. "\n" .. err M.error(msg) end end ---@param buf number ---@param row number ---@param ns number ---@param col number ---@param opts vim.api.keyset.set_extmark ---@param debug_info? any function M.set_extmark(buf, ns, row, col, opts, debug_info) local ok, err = pcall(vim.api.nvim_buf_set_extmark, buf, ns, row, col, opts) if not ok then M.error( "Failed to set extmark for preview:\n" .. vim.inspect({ info = debug_info, row = row, col = col, opts = opts, error = err }) ) end end ---@param n number buffer or window number ---@param type "win" | "buf" ---@param opts vim.wo | vim.bo local function set_opts(n, type, opts) ---@diagnostic disable-next-line: no-unknown for k, v in pairs(opts or {}) do ---@diagnostic disable-next-line: no-unknown pcall(vim.api.nvim_set_option_value, k, v, type == "win" and { scope = "local", win = n, } or { buf = n }) end end ---@param win number ---@param opts vim.wo function M.wo(win, opts) set_opts(win, "win", opts) end ---@param buf number ---@param opts vim.bo function M.bo(buf, opts) set_opts(buf, "buf", opts) end local trace_level = 0 ---@param msg? string ---@param ...? any function M.trace(msg, ...) if not msg then trace_level = trace_level - 1 return end trace_level = math.max(trace_level, 0) M.debug(msg, ...) trace_level = trace_level + 1 end ---@param msg? string ---@param ...? any function M.debug(msg, ...) if not require("which-key.config").debug then return end local data = { ... } if #data == 0 then data = nil elseif #data == 1 then data = data[1] end if type(data) == "function" then data = data() end if type(data) == "table" then data = table.concat( vim.tbl_map(function(value) return type(value) == "string" and value or vim.inspect(value):gsub("%s+", " ") end, data), " " ) end if data and type(data) ~= "string" then data = vim.inspect(data):gsub("%s+", " ") end msg = data and ("%s: %s"):format(msg, data) or msg msg = string.rep(" ", trace_level) .. msg M.log(msg .. "\n") end function M.log(msg) local file = "./wk.log" local fd = io.open(file, "a+") if not fd then error(("Could not open file %s for writing"):format(file)) end fd:write(msg) fd:close() end --- Returns a function that returns true if the cooldown is active. --- The cooldown will be active for the given duration or 0 if no duration is given. --- Runs in the main loop. --- cooldown(true) will wait till the next tick. ---@return fun(cooldown?: number|boolean): boolean function M.cooldown() local waiting = false ---@param cooldown? number|boolean return function(cooldown) if waiting then return true elseif cooldown then waiting = true vim.defer_fn(function() waiting = false end, type(cooldown) == "number" and cooldown or 0) end return false end end ---@generic T: table ---@param t T ---@param fields string[] ---@return T function M.getters(t, fields) local getters = {} ---@type table for _, prop in ipairs(fields) do if type(t[prop]) == "function" then getters[prop] = t[prop] rawset(t, prop, nil) end end if not vim.tbl_isempty(getters) then setmetatable(t, { __index = function(_, key) if getters[key] then return getters[key](t) end end, }) end end return M folke-which-key.nvim-fcbf4ee/lua/which-key/view.lua000066400000000000000000000326201475635520600224560ustar00rootroot00000000000000local Buf = require("which-key.buf") local Config = require("which-key.config") local Icons = require("which-key.icons") local Layout = require("which-key.layout") local Plugins = require("which-key.plugins") local State = require("which-key.state") local Text = require("which-key.text") local Tree = require("which-key.tree") local Util = require("which-key.util") local Win = require("which-key.win") local M = {} M.view = nil ---@type wk.Win? M.footer = nil ---@type wk.Win? M.timer = (vim.uv or vim.loop).new_timer() ---@alias wk.Sorter fun(node:wk.Item): (string|number) ---@type table M.fields = { order = function(item) return item.order and item.order or 1000 end, ["local"] = function(item) return item.keymap and item.keymap.buffer ~= 0 and 0 or 1000 end, manual = function(item) return item.mapping and item.mapping.idx or 10000 end, desc = function(item) return item.desc or "~" end, group = function(item) return item.group and 1 or 0 end, alphanum = function(item) return item.key:find("^%w+$") and 0 or 1 end, mod = function(item) return item.key:find("^<.*>$") and 0 or 1 end, case = function(item) return item.key:lower() == item.key and 0 or 1 end, natural = function(item) local ret = item.key:gsub("%d+", function(d) return ("%09d"):format(tonumber(d)) end) return ret:lower() end, } ---@param lhs string function M.format(lhs) local keys = Util.keys(lhs) local ret = vim.tbl_map(function(key) local inner = key:match("^<(.*)>$") if not inner then return key end if inner == "NL" then inner = "C-J" end local parts = vim.split(inner, "-", { plain = true }) for i, part in ipairs(parts) do if i == 1 or i ~= #parts or not part:match("^%w$") then parts[i] = Config.icons.keys[part] or parts[i] end end return table.concat(parts, "") end, keys) return table.concat(ret, "") end ---@param nodes wk.Item[] ---@param fields? (string|wk.Sorter)[] function M.sort(nodes, fields) fields = vim.deepcopy(fields or Config.sort) vim.list_extend(fields, { "natural", "case" }) table.sort(nodes, function(a, b) for _, f in ipairs(fields) do local field = type(f) == "function" and f or M.fields[f] if field then local aa = field(a) local bb = field(b) if aa ~= bb then return aa < bb end end end return a.raw_key < b.raw_key end) end function M.valid() return M.view and M.view:valid() end ---@param opts? {delay?: number, schedule?: boolean, waited?: number} function M.update(opts) local state = State.state if not state then M.hide() return end opts = opts or {} if M.valid() then M.show() elseif opts.schedule ~= false then local delay = opts.delay or State.delay({ mode = state.mode.mode, keys = state.node.keys, plugin = state.node.plugin, waited = opts.waited, }) M.timer:start( delay, 0, vim.schedule_wrap(function() Util.try(M.show) end) ) end end function M.hide() if M.view then M.view:hide() M.view = nil end if M.footer then M.footer:hide() M.footer = nil end end ---@param field string ---@param value string ---@return string function M.replace(field, value) for _, repl in pairs(Config.replace[field]) do value = type(repl) == "function" and (repl(value) or value) or value:gsub(repl[1], repl[2]) end return value end ---@param node wk.Node function M.icon(node) -- plugin items should not get icons if node.parent and node.parent.plugin then return end if node.mapping and node.mapping.icon then return Icons.get(node.mapping.icon) end local icon, icon_hl = Icons.get({ keymap = node.keymap, desc = node.desc }) if icon then return icon, icon_hl end if node.parent then return M.icon(node.parent) end end ---@param node wk.Node ---@param opts? {default?: "count"|"path", parent?: wk.Node, group?: boolean} function M.item(node, opts) opts = opts or {} opts.default = opts.default or "count" local child_count = (node:can_expand() or opts.group == false) and 0 or node:count() local desc = node.desc if not desc and node.keymap and node.keymap.rhs ~= "" and type(node.keymap.rhs) == "string" then desc = node.keymap.rhs --[[@as string]] end if not desc and opts.default == "count" and child_count > 0 then desc = child_count .. " keymap" .. (child_count > 1 and "s" or "") end if not desc and opts.default == "path" then desc = node.keys end desc = M.replace("desc", desc or "") local icon, icon_hl = M.icon(node) local raw_key = node.key if opts.parent and opts.parent ~= node and node.keys:find(opts.parent.keys, 1, true) == 1 then raw_key = node.keys:sub(opts.parent.keys:len() + 1) end local group = node:is_group() ---@type wk.Item return setmetatable({ node = node, icon = icon or "", icon_hl = icon_hl, key = M.replace("key", raw_key), raw_key = raw_key, desc = group and Config.icons.group .. desc or desc, group = group, }, { __index = node }) end ---@param node wk.Node ---@param opts? {title?: boolean} function M.trail(node, opts) opts = opts or {} ---@param group? string local function hl(group) return opts.title and "WhichKeyTitle" or (group and ("WhichKey" .. group) or "WhichKeyGroup") end local trail = {} ---@type string[][] local did_op = false while node do local desc = node.desc and (Config.icons.group .. M.replace("desc", node.desc)) or node.key and M.replace("key", node.key) or "" node = node.parent if desc ~= "" then if node and #trail > 0 then table.insert(trail, 1, { " " .. Config.icons.breadcrumb .. " ", hl("Separator") }) end table.insert(trail, 1, { desc, hl() }) end local m = State.state.mode.mode if not did_op and not node and (m == "x" or m == "o") then did_op = true local mode = Buf.get({ buf = State.state.mode.buf.buf, mode = "n" }) if mode then node = mode.tree:find(m == "x" and "v" or vim.v.operator) end end end if #trail > 0 then table.insert(trail, 1, { " ", hl() }) table.insert(trail, { " ", hl() }) return trail end end ---@param root wk.Node ---@param node wk.Node ---@param expand fun(node:wk.Node): boolean ---@param filter fun(node:wk.Node): boolean ---@param ret? wk.Item[] function M.expand(root, node, expand, filter, ret) ret = ret or {} if not filter(node) then return ret end if not node:is_plugin() and expand(node) then if node.keymap then ret[#ret + 1] = M.item(node, { group = false, parent = root }) end for _, child in ipairs(node:children()) do M.expand(root, child, expand, filter, ret) end else ret[#ret + 1] = M.item(node, { parent = root }) end return ret end function M.show() local state = State.state if not (state and state.show and state.node:is_group()) then M.hide() return end local text = Text.new() ---@type wk.Node[] local children = state.node:children() if state.filter.global == false and state.filter.expand == nil then state.filter.expand = true end ---@param node wk.Node local function filter(node) local l = state.filter["local"] ~= false local g = state.filter.global ~= false if not g and not l then return false end if g and l then return true end local is_local = node:is_local() return l and is_local or g and not is_local end ---@param node wk.Node local function expand(node) if node:is_plugin() then return false end if state.filter.expand then return true end if node:can_expand() then return false end if type(Config.expand) == "function" then return Config.expand(node) end local child_count = node:count() return child_count > 0 and child_count <= Config.expand end ---@type wk.Item[] local items = {} for _, node in ipairs(children) do vim.list_extend(items, M.expand(state.node, node, expand, filter)) end M.sort(items) ---@type wk.Col[] local cols = { { key = "key", hl = "WhichKey", align = "right" }, { key = "sep", hl = "WhichKeySeparator", default = Config.icons.separator }, { key = "icon", padding = { 0, 0 } }, } if state.node.plugin then vim.list_extend(cols, Plugins.cols(state.node.plugin)) end cols[#cols + 1] = { key = "desc", width = math.huge } local t = Layout.new({ cols = cols, rows = items }) local opts = Win.defaults(Config.win) local container = { width = Layout.dim(vim.o.columns, vim.o.columns, opts.width), height = Layout.dim(vim.o.lines, vim.o.lines, opts.height), } local _, _, max_row_width = t:cells() local box_width = Layout.dim(max_row_width, container.width, Config.layout.width) local box_count = math.max(math.floor(container.width / (box_width + Config.layout.spacing)), 1) box_width = math.floor(container.width / box_count) local box_height = math.max(math.ceil(#items / box_count), 2) local rows = t:layout({ width = box_width - Config.layout.spacing }) for _ = 1, Config.win.padding[1] + 1 do text:nl() end for l = 1, box_height do text:append(string.rep(" ", Config.win.padding[2])) for b = 1, box_count do local i = (b - 1) * box_height + l local item = items[i] local row = rows[i] if b ~= 1 or box_count > 1 then text:append(string.rep(" ", Config.layout.spacing)) end if item then for c, col in ipairs(row) do local hl = col.hl if cols[c].key == "desc" then hl = item.group and "WhichKeyGroup" or "WhichKeyDesc" end if cols[c].key == "icon" then hl = item.icon_hl end text:append(col.value, hl) end end end text:append(string.rep(" ", Config.win.padding[2])) text:nl() end text:trim() for _ = 1, Config.win.padding[1] do text:nl() end local show_keys = Config.show_keys local has_border = opts.border and opts.border ~= "none" if has_border then if opts.title == true then opts.title = M.trail(state.node, { title = true }) show_keys = false end if opts.footer == true then opts.footer = M.trail(state.node, { title = true }) show_keys = false end if not opts.title then opts.title = "" opts.title_pos = nil end if not opts.footer then opts.footer = "" opts.footer_pos = nil end else opts.footer = nil opts.footer_pos = nil opts.title = nil opts.title_pos = nil end local bw = has_border and 2 or 0 opts.width = Layout.dim(text:width() + bw, vim.o.columns, opts.width) opts.height = Layout.dim(text:height() + bw, vim.o.lines, opts.height) if Config.show_help then opts.height = opts.height + 1 end -- top-left opts.col = Layout.dim(opts.col, vim.o.columns - opts.width) opts.row = Layout.dim(opts.row, vim.o.lines - opts.height - vim.o.cmdheight) opts.width = opts.width - bw opts.height = opts.height - bw M.check_overlap(opts) M.view = M.view or Win.new(opts) M.view:show(opts) if Config.show_help or show_keys then text:nl() local footer = Text.new() if show_keys then footer:append(" ") for _, segment in ipairs(M.trail(state.node) or {}) do footer:append(segment[1], segment[2]) end end if Config.show_help then ---@type {key: string, desc: string}[] local keys = { { key = "", desc = "close" }, } if state.node.parent then keys[#keys + 1] = { key = "", desc = "back" } end if opts.height < text:height() then keys[#keys + 1] = { key = Config.keys.scroll_down .. "/" .. Config.keys.scroll_up, desc = "scroll" } end local help = Text.new() for k, key in ipairs(keys) do help:append(M.replace("key", Util.norm(key.key)), "WhichKey"):append(" " .. key.desc, "WhichKeySeparator") if k < #keys then help:append(" ") end end local col = footer:col({ display = true }) local ws = string.rep(" ", math.floor((opts.width - help:width()) / 2) - col) footer:append(ws) footer:append(help._lines[1]) end footer:trim() M.footer = M.footer or Win.new() M.footer:show({ relative = "win", win = M.view.win, col = 0, row = opts.height - 1, width = opts.width, height = 1, zindex = M.view.opts.zindex + 1, }) footer:render(M.footer.buf) end text:render(M.view.buf) vim.api.nvim_win_call(M.view.win, function() vim.fn.winrestview({ topline = 1 }) end) vim.cmd.redraw() end ---@param opts wk.Win.opts function M.check_overlap(opts) if Config.win.no_overlap == false then return end local row, col = vim.fn.screenrow(), vim.fn.screencol() local overlaps = (row >= opts.row and row <= opts.row + opts.height) and (col >= opts.col and col <= opts.col + opts.width) -- dd(overlaps and "overlaps" or "no overlap", { -- editor = { lines = vim.o.lines, columns = vim.o.columns }, -- cursor = { col = col, row = row }, -- win = { row = opts.row, col = opts.col, height = opts.height, width = opts.width }, -- overlaps = overlaps, -- }) if overlaps then opts.row = row + 1 opts.height = math.max(vim.o.lines - opts.row, 4) end end ---@param up boolean function M.scroll(up) return M.view and M.view:scroll(up) end return M folke-which-key.nvim-fcbf4ee/lua/which-key/win.lua000066400000000000000000000055041475635520600223020ustar00rootroot00000000000000local Util = require("which-key.util") ---@class wk.Win ---@field win? number ---@field buf? number ---@field opts wk.Win.opts local M = {} M.__index = M ---@class wk.Win.opts local override = { relative = "editor", style = "minimal", focusable = false, noautocmd = true, wo = { scrolloff = 0, foldenable = false, winhighlight = "Normal:WhichKeyNormal,FloatBorder:WhichKeyBorder,FloatTitle:WhichKeyTitle", winbar = "", statusline = "", wrap = false, }, bo = { buftype = "nofile", bufhidden = "wipe", filetype = "wk", }, } ---@type wk.Win.opts local defaults = { col = 0, row = math.huge, zindex = 1000 } ---@param opts? wk.Win.opts function M.defaults(opts) return vim.tbl_deep_extend("force", {}, defaults, opts or {}, override) end ---@param opts? wk.Win.opts function M.new(opts) local self = setmetatable({}, M) self.opts = M.defaults(opts) return self end function M:valid() return self.buf and vim.api.nvim_buf_is_valid(self.buf) and self.win and vim.api.nvim_win_is_valid(self.win) or false end function M:hide() if not (self.buf or self.win) then return end ---@type number?, number? local buf, win = self.buf, self.win self.buf, self.win = nil, nil local function try_close() pcall(vim.api.nvim_win_close, win, true) pcall(vim.api.nvim_buf_delete, buf, { force = true }) win = win and vim.api.nvim_win_is_valid(win) and win or nil buf = buf and vim.api.nvim_buf_is_valid(buf) and buf or nil if win or buf then vim.schedule(try_close) end end try_close() end ---@param opts? wk.Win.opts function M:show(opts) if opts then self.opts = vim.tbl_deep_extend("force", self.opts, opts) end local win_opts = vim.deepcopy(self.opts) win_opts.wo = nil win_opts.bo = nil win_opts.padding = nil win_opts.no_overlap = nil if vim.fn.has("nvim-0.10") == 0 then win_opts.footer = nil end if self:valid() then win_opts.noautocmd = nil return vim.api.nvim_win_set_config(self.win, win_opts) end local ei = vim.go.eventignore vim.go.eventignore = "all" self.buf = vim.api.nvim_create_buf(false, true) Util.bo(self.buf, self.opts.bo or {}) self.win = vim.api.nvim_open_win(self.buf, false, win_opts) Util.wo(self.win, self.opts.wo or {}) vim.go.eventignore = ei end ---@param up boolean function M:scroll(up) if not self:valid() then return end local height = vim.api.nvim_win_get_height(self.win) local delta = math.ceil((up and -1 or 1) * height / 2) local view = vim.api.nvim_win_call(self.win, vim.fn.winsaveview) local top = view.topline ---@type number top = top + delta top = math.max(top, 1) top = math.min(top, vim.api.nvim_buf_line_count(self.buf) - height + 1) vim.api.nvim_win_call(self.win, function() vim.fn.winrestview({ topline = top, lnum = top }) end) end return M folke-which-key.nvim-fcbf4ee/plugin/000077500000000000000000000000001475635520600176235ustar00rootroot00000000000000folke-which-key.nvim-fcbf4ee/plugin/which-key.lua000066400000000000000000000003121475635520600222120ustar00rootroot00000000000000local timer = (vim.uv or vim.loop).new_timer() timer:start( 500, 0, vim.schedule_wrap(function() local wk = require("which-key") if not wk.did_setup then wk.setup() end end) ) folke-which-key.nvim-fcbf4ee/scripts/000077500000000000000000000000001475635520600200145ustar00rootroot00000000000000folke-which-key.nvim-fcbf4ee/scripts/docs000077500000000000000000000001031475635520600206640ustar00rootroot00000000000000#!/bin/env bash nvim -u tests/minit.lua -l lua/which-key/docs.lua folke-which-key.nvim-fcbf4ee/scripts/test000077500000000000000000000000641475635520600207210ustar00rootroot00000000000000#!/bin/env bash nvim -l tests/minit.lua --minitest folke-which-key.nvim-fcbf4ee/selene.toml000066400000000000000000000000471475635520600204760ustar00rootroot00000000000000std="vim" [lints] mixed_table="allow" folke-which-key.nvim-fcbf4ee/stylua.toml000066400000000000000000000001331475635520600205400ustar00rootroot00000000000000indent_type = "Spaces" indent_width = 2 column_width = 120 [sort_requires] enabled = true folke-which-key.nvim-fcbf4ee/tests/000077500000000000000000000000001475635520600174675ustar00rootroot00000000000000folke-which-key.nvim-fcbf4ee/tests/buf_spec.lua000066400000000000000000000005451475635520600217640ustar00rootroot00000000000000local Buf = require("which-key.buf") before_each(function() require("helpers").reset() end) describe("triggers", function() it("does not create hooks for default mappings", function() vim.keymap.set("n", "aa", "") Buf.get({ mode = "n" }) local m = vim.fn.maparg("a", "n", false, true) assert.same(vim.empty_dict(), m) end) end) folke-which-key.nvim-fcbf4ee/tests/helpers.lua000066400000000000000000000004361475635520600216370ustar00rootroot00000000000000local M = {} ---@param lines? string[] function M.reset(lines) vim.o.showmode = false vim.api.nvim_feedkeys(vim.keycode(""), "nx", false) vim.cmd("enew") vim.cmd("normal! o") vim.api.nvim_buf_set_lines(0, 0, -1, false, lines or {}) end return M folke-which-key.nvim-fcbf4ee/tests/layout_spec.lua000066400000000000000000000023611475635520600225230ustar00rootroot00000000000000local layout = require("which-key.layout") describe("dim", function() local tests = { { 100, { 200 }, 100 }, { 0.2, { 100 }, 20 }, { -0.2, { 100 }, 80 }, { -20, { 100 }, 80 }, { 1, { 100 }, 1 }, { 100, { 200, { min = 50 } }, 100 }, { 100, { 200, { max = 150 } }, 100 }, { 100, { 200, { max = 150, min = 50 } }, 100 }, { 100, { 200, { max = 150, min = 150 } }, 150 }, { 0.2, { 100, { max = 150, min = 20 } }, 20 }, { 0.2, { 100, { max = 50, min = 20 } }, 20 }, { math.huge, { 200 }, 200 }, { -0.5, { 200 }, 100 }, { 0.5, { 200 }, 100 }, { 0.5, { 200, { min = 150 } }, 150 }, { -0.5, { 200, { max = 50 } }, 50 }, { 300, { 200, { max = 250 } }, 200 }, { 300, { 200, { min = 250 } }, 200 }, { -100, { 100, { max = 90, min = 20 } }, 20 }, { -200, { 100, { max = -50, min = -50 } }, 0 }, { 0.2, { 100, { min = 0.5 } }, 50 }, { -200, { 100 }, 0 }, { -1, { 100 }, 99 }, { -0.1, { 100 }, 90 }, { 0.1, { 100 }, 10 }, { 14, { 212, 0.9 }, 191 }, } for _, test in ipairs(tests) do it("size=" .. test[1] .. ", parent=" .. test[2][1] .. ", result = " .. test[3], function() assert.are.equal(test[3], layout.dim(test[1], unpack(test[2]))) end) end end) folke-which-key.nvim-fcbf4ee/tests/mappings_spec.lua000066400000000000000000000051561475635520600230310ustar00rootroot00000000000000local Mappings = require("which-key.mappings") before_each(function() Mappings.notifs = {} end) describe("specs v1", function() local tests = { { spec = { [""] = { name = "leader", ["a"] = { "a" }, ["b"] = { "b" }, ["c"] = { "c" }, }, }, mappings = { { lhs = "", group = true, desc = "leader", mode = "n" }, { lhs = "a", desc = "a", mode = "n" }, { lhs = "b", desc = "b", mode = "n" }, { lhs = "c", desc = "c", mode = "n" }, }, }, { spec = { mode = "v", [""] = { name = "leader", ["a"] = { "a" }, ["b"] = { "b" }, ["c"] = { "c" }, }, }, mappings = { { lhs = "", group = true, desc = "leader", mode = "v" }, { lhs = "a", desc = "a", mode = "v" }, { lhs = "b", desc = "b", mode = "v" }, { lhs = "c", desc = "c", mode = "v" }, }, }, { spec = { desc = "foo", noremap = true }, mappings = {}, }, { spec = { a = { desc = "which_key_ignore" } }, mappings = { { lhs = "a", hidden = true, mode = "n" }, }, }, { spec = { a = { "foo", cond = false } }, mappings = {}, }, { spec = { a = { "foo", cond = true } }, mappings = { { desc = "foo", lhs = "a", mode = "n" }, }, }, { spec = { a = { "a", cmd = "aa" }, b = { "b", callback = "bb" }, c = { "cc", "c" }, d = { "dd", desc = "d" }, }, mappings = { { lhs = "a", desc = "a", rhs = "aa", mode = "n", silent = true }, { lhs = "b", desc = "b", rhs = "bb", mode = "n", silent = true }, { lhs = "c", desc = "c", rhs = "cc", mode = "n", silent = true }, { lhs = "d", desc = "dd", mode = "n" }, }, }, { spec = { a = { "a1" }, b = { "b1", "b2" }, c = { "c1", desc = "c2" }, }, mappings = { { lhs = "a", desc = "a1", mode = "n" }, { lhs = "b", desc = "b2", rhs = "b1", mode = "n", silent = true }, { lhs = "c", desc = "c1", mode = "n" }, }, }, } -- Function to run the tests for t, test in ipairs(tests) do it(tostring(t), function() local result = Mappings.parse(test.spec, { version = 1 }) assert.same(test.mappings, result) local errors = vim.tbl_filter(function(n) return n.level >= vim.log.levels.ERROR end, Mappings.notifs) assert.same({}, errors) end) end end) folke-which-key.nvim-fcbf4ee/tests/minit.lua000066400000000000000000000005721475635520600213160ustar00rootroot00000000000000#!/usr/bin/env -S nvim -l vim.env.LAZY_STDPATH = ".tests" vim.env.LAZY_PATH = vim.fs.normalize("~/projects/lazy.nvim") load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))() -- Setup lazy.nvim require("lazy.minit").setup({ spec = { { dir = vim.uv.cwd(), opts = { notify = false, }, }, }, }) folke-which-key.nvim-fcbf4ee/tests/util_spec.lua000066400000000000000000000054011475635520600221610ustar00rootroot00000000000000---@module 'luassert' local Util = require("which-key.util") describe("parse keys", function() local tests = { [" Ä🔥foo"] = { "", "", "", "Ä", "<", "🔥", "f", "o", "o", }, ["\1Ä🔥foo"] = { "", "", "Ä", "<", "🔥", "f", "o", "o", }, [""] = { "" }, ["foo"] = { "f", "o", "o", "<", "b", "a", "z", ">" }, ["foo"] = { "f", "o", "o", "|" }, ["foo"] = { "f", "o", "o", "" }, ["foo"] = { "f", "o", "o", "" }, ["foo"] = { "f", "o", "o", "" }, ["foo"] = { "f", "o", "o", "" }, ["foo<"] = { "f", "o", "o", "<" }, ["foo"] = { "f", "o", "o", ">" }, -- test with japanese chars ["fooあ"] = { "f", "o", "o", "あ" }, ["fooあ"] = { "f", "o", "o", "あ", "<" }, ["fooあbar"] = { "f", "o", "o", "あ", "<", "b", "a", "r" }, ["fooあbar"] = { "f", "o", "o", "あ", "<", "b", "a", "r", "<" }, ["fooあbarbaz"] = { "f", "o", "o", "あ", "<", "b", "a", "r", "<", "b", "a", "z" }, ["fooあbarbaz"] = { "f", "o", "o", "あ", "<", "b", "a", "r", "<", "b", "a", "z", "<" }, ["fooあbarbazqux"] = { "f", "o", "o", "あ", "<", "b", "a", "r", "<", "b", "a", "z", "<", "q", "u", "x", }, ["fooあbarbazqux"] = { "f", "o", "o", "あ", "<", "b", "a", "r", "<", "b", "a", "z", "<", "q", "u", "x", "<", }, } for input, output in pairs(tests) do it(("should parse %q"):format(input), function() local keys = Util.keys(input) assert.same(output, keys) end) end end) describe("modes", function() before_each(function() require("helpers").reset() end) local tests = { ["gg"] = "n", ["vl"] = "x", ["j"] = "x", ["gh"] = "s", ["aa"] = "i", ["ciw"] = "o", ["c"] = "n", ["terminal exit"] = "n", } local inputs = vim.tbl_keys(tests) table.sort(inputs) for _, input in ipairs(inputs) do local output = tests[input] it(("should return %q for %q"):format(output, input), function() local mode = "n" assert.same(mode, Util.mapmode()) vim.api.nvim_create_autocmd("ModeChanged", { once = true, callback = function() mode = Util.mapmode() end, }) vim.api.nvim_feedkeys(vim.keycode(input), "nitx", false) assert.same(output, mode) end) end end) folke-which-key.nvim-fcbf4ee/vim.toml000066400000000000000000000002451475635520600200160ustar00rootroot00000000000000[selene] base = "lua51" name = "vim" [vim] any = true [jit] any = true [assert] any = true [describe] any = true [it] any = true [before_each.args] any = true