-
Notifications
You must be signed in to change notification settings - Fork 5
Add a configuration mechanism and use it to support user customization of keymaps, user commands and region decorations. #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,9 @@ Requires neovim >= 0.10. | |
|
|
||
| ### Navigation | ||
|
|
||
| The following table lists the treeclimber navigation commands, along with their default keybindings. | ||
| See [Configuration](#configuration) for details on changing the defaults. | ||
|
|
||
| | Key binding | Action | Demo | | ||
| | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | ||
| | `alt-h` | Select the previous sibling node. |  | | ||
|
|
@@ -46,44 +49,190 @@ https://user-images.githubusercontent.com/3162299/203097777-a9a84c2d-8dec-4db8-a | |
|
|
||
| ## Installation | ||
|
|
||
| Use your preferred package manager, or the built-in package system (`:help packages`). | ||
| User your preferred package manager, or the built-in package system (`:help packages`). | ||
|
|
||
| ### [lazy.nvim](https://github.com/folke/lazy.nvim) | ||
|
|
||
| ```lua | ||
| { | ||
| "dkendal/nvim-treeclimber", | ||
| opts = { | ||
| -- Provide your desired configuration here, or leave empty to use defaults. | ||
| -- See Configuration section for details... | ||
| }, | ||
| } | ||
| ``` | ||
|
|
||
| ### Manual installation | ||
|
|
||
| #### Installation via Bash command-line | ||
|
|
||
| ```sh | ||
| mkdir -p ~/.config/nvim/pack/dkendal/opt | ||
| cd ~/.config/nvim/pack/dkendal/opt | ||
| git clone https://github.com/dkendal/nvim-treeclimber.git | ||
| ``` | ||
|
|
||
| #### Loading via Neovim package system | ||
|
|
||
| ```lua | ||
| -- ~/.config/nvim/init.lua | ||
| vim.cmd.packadd('nvim-treeclimber') | ||
|
|
||
| require('nvim-treeclimber').setup() | ||
| require('nvim-treeclimber').setup({ --[[ your config here ]] }) | ||
| ``` | ||
|
|
||
| If you want to change the default keybindings, call `require('nvim-treeclimber')` rather than calling setup. | ||
| See [configuration](#configuration). | ||
| **Note:** If you call the `setup()` function without arguments, treeclimber uses the defaults documented in the following section. | ||
|
|
||
| ## Configuration | ||
|
|
||
| **To use default highlight, keymaps, and commands call `require('nvim-treeclimber').setup()`.** | ||
| To override specific elements of the default configuration, provide a sparse option table containing only the keys you wish to change. | ||
| The default option table is provided below, with comments documenting the meanings of the various keys. | ||
| Any table you provide to `setup()` will be merged into this one, with preference given to your override. | ||
| If your override has an invalid format, treeclimber will generally emit a warning and fall back to the default setting. | ||
|
|
||
| To manually specify the configuration options, take a look at the contents of `lua/nvim-treeclimber.lua` and import or modify the portions that you need. | ||
|
|
||
| For example, if you just want the built in user commands and highlights but you want your own keybindings, you can do the following: | ||
| ### Default Option Table | ||
|
|
||
| ```lua | ||
| { | ||
| ui = { | ||
| -- ** Keymaps ** | ||
| -- Each entry of the 'keys' table configures the keymap for a single treeclimber function. | ||
| -- Note: The `keys` key itself can be set to a boolean to enable defaults or disable keymaps | ||
| -- altogether. | ||
| ---@alias modestr "n"|"v"|"x"|"o"|"s"|"i"|"!"|"" | ||
| ---@alias lhs string # Used as <lhs> in call to `vim.keymap.set` | ||
| ---@alias KeymapSingle | ||
| ---| [(modestr|modestr[]), lhs] # override the default <lhs> and/or modes | ||
| ---@alias KeymapEntry | ||
| ---| boolean # true to accept default, false to disable | ||
| ---| nil # accept default (same as omitting the command name from table) | ||
| ---| lhs # override the default <lhs> in default mode(s) | ||
| ---| KeymapSingle # override the default <lhs> and/or modes | ||
| ---| KeymapSingle[] # idem, but allows multiple, mode-specific <lhs>'s | ||
| ---@type table<string, KeymapEntry> | ||
| keys = { | ||
| show_control_flow = { "n", "<leader>k"}, | ||
| select_current_node = { | ||
| {"n", "<M-k>"}, | ||
| {{ "x", "o" }, "i."} | ||
| }, | ||
| select_first_sibling = {{ "n", "x", "o" }, "<M-[>"}, | ||
| select_last_sibling = {{ "n", "x", "o" }, "<M-]>"}, | ||
| select_top_level = {{ "n", "x", "o" }, "<M-g>"}, | ||
| select_forward = {{ "n", "x", "o" }, "<M-l>"}, | ||
| select_backward = {{ "n", "x", "o" }, "<M-h>"}, | ||
| select_forward_end = {{ "n", "x", "o" }, "<M-e>"}, | ||
| select_grow_forward = {{ "n", "x", "o" }, "<M-L>"}, | ||
| select_grow_backward = {{ "n", "x", "o" }, "<M-H>"}, | ||
| select_expand = { | ||
| {{"x", "o"}, "a."}, | ||
| {{"x", "o"}, "<M-k>"} | ||
| }, | ||
| select_shrink = {{ "n", "x", "o" }, "<M-j>"}, | ||
| }, | ||
|
|
||
| -- ** User commands ** | ||
| -- Each entry of the 'cmds table configures the user command for a single treeclimber function. | ||
| -- Note: The 'cmds' key itself can be set to a boolean to enable the defaults or disable user | ||
| -- commands altogether. | ||
| ---@alias UserCommandEntry | ||
| ---| string # desired name of the user command for this function | ||
| ---| boolean # true to create the command with the default name, false to disable | ||
| ---@type {[string]: UserCommandEntry}|boolean | ||
| cmds = { | ||
| diff_this = "TCDiffThis", | ||
| highlight_external_definitions = "TCHighlightExternalDefinitions", | ||
| show_control_flow = "TCShowControlFlow", | ||
| }, | ||
| }, | ||
|
|
||
| -- ** Display ** | ||
| display = { | ||
| regions = { | ||
| -- Each entry in the table below defines the highlighting applied to one of several regions | ||
| -- relative to the current selection and its siblings/parent. To override the highlighting | ||
| -- for a specific region, set the corresponding key to either a `vim.api.keyset.highlight` or | ||
| -- a callback function that returns one. The callback will be invoked upon colorscheme load | ||
| -- with an `HSLUVHighlights` object that may be used to "mix" new colors from the currently | ||
| -- active normal and visual mode fg/bg colors. | ||
| -- Important Note: The `HSLUV` class provides many color-manipulation methods in addition to | ||
| -- the `mix()` method used in the defaults. The class's type annotation is provided in the | ||
| -- next section. Additional detail may be found in "vivid/hsl_like.lua" in the treeclimber | ||
| -- source. | ||
| -- Note: The `vim.api.keyset.highlight` can be used to specify more than just fg/bg colors: | ||
| -- e.g., the following override would make the currently selected region bold and its siblings | ||
| -- italic: | ||
| -- highlights = { | ||
| -- Selection = {bold = true}, | ||
| -- Sibling = {italic = true) | ||
| -- } | ||
| -- Note: You can also disable unwanted regions by setting the corresponding key(s) `false`. | ||
| -- E.g., to disable all but the primary selection region (Selection)... | ||
| -- highlights = { | ||
| -- SiblingStart = false, Sibling = false, Parent = false, ParentStart = false | ||
| -- } | ||
| ---@alias HSLUVHighlight {bg: HSLUV?, fg: HSLUV?, ctermbg: HSLUV?, ctermfg: HSLUV?} | ||
| ---@alias HSLUVHighlights {normal: HSLUVHighlight, visual: HSLUVHighlight} | ||
| ---@alias HighlightCallback fun(o: HSLUVHighlights) : vim.api.keyset.highlight | ||
| ---@alias HighlightEntry | ||
| ---| vim.api.keyset.highlight # passed to `nvim_set_hl()` | ||
| ---| HighlightCallback # must return a `vim.api.keyset.highlight` | ||
| ---| boolean # true for default highlighting, false to disable the group | ||
| ---| nil # default highlighting | ||
| ---@type table<string, HighlightEntry> | ||
| highlights = { | ||
| Selection = function(o) return { bold = true, bg = o.visual.bg.hex } end, | ||
| SiblingStart = false, | ||
| Sibling = function(o) return { bg = o.visual.bg.mix(o.normal.bg, 50).hex } end, | ||
| -- Make Parent bg color noticeably lighter than Siblings. | ||
| Parent = function(o) return { bg = o.visual.bg.mix(o.normal.bg, 80).hex } end, | ||
| ParentStart = false, | ||
| }, | ||
| -- `true` to cause attributes like bold and italic to "bleed through" from Parent | ||
| -- to Siblings. | ||
| inherit_attrs = true, | ||
| -- `true` to replace default 'highlights' with user overrides, false or nil to merge | ||
| replace_defaults = false, | ||
|
Comment on lines
+191
to
+195
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related to the comments above, I would prefer to not introduce any custom configuration DSL, as it increases the documentation and learning surface area. I'm okay with exposing options that are just delegates to vim api functions, but for anything more advanced I'd prefer to only provide example in the README. This is inline with the advice here. |
||
| }, | ||
| }, | ||
| } | ||
| ``` | ||
|
|
||
| local tc = require('nvim-treeclimber') | ||
| ### HSLUV Color Support | ||
|
|
||
| tc.setup_augroups() | ||
| tc.setup_user_commands() | ||
| As mentioned in the default option comments, an object of type `HSLUV` is made available to the `highlights` option callback functions. | ||
| This object facilitates working with *HSL* colors in the more human-friendly *HSLUV* color space. | ||
| Its methods and fields are shown here. For further details, look in the treeclimber source (vivid/hsl_like.lua). | ||
|
|
||
| -- Copied from setup_keymaps | ||
| vim.keymap.set("n", "<leader>k", tc.show_control_flow, {}) | ||
| vim.keymap.set({ "x", "o" }, "i.", tc.select_current_node, { desc = "select current node" }) | ||
| vim.keymap.set({ "x", "o" }, "a.", tc.select_expand, { desc = "select parent node" }) | ||
| ... | ||
| ```lua | ||
| ---@class HSLUV | ||
| ---@field hex string | ||
| ---@field h number | ||
| ---@field s number | ||
| ---@field l number | ||
| ---@field rotate fun(n: number): HSLUV | ||
| ---@field ro fun(n: number): HSLUV | ||
| ---@field saturate fun(n: number): HSLUV | ||
| ---@field sa fun(n: number): HSLUV | ||
| ---@field abs_saturate fun(n: number): HSLUV | ||
| ---@field abs_sa fun(n: number): HSLUV | ||
| ---@field desaturate fun(n: number): HSLUV | ||
| ---@field de fun(n: number): HSLUV | ||
| ---@field abs_desaturate fun(n: number): HSLUV | ||
| ---@field abs_de fun(n: number): HSLUV | ||
| ---@field lighten fun(n: number): HSLUV | ||
| ---@field li fun(n: number): HSLUV | ||
| ---@field abs_lighten fun(n: number): HSLUV | ||
| ---@field abs_li fun(n: number): HSLUV | ||
| ---@field darken fun(n: number): HSLUV | ||
| ---@field da fun(n: number): HSLUV | ||
| ---@field abs_darken fun(n: number): HSLUV | ||
| ---@field abs_da fun(n: number): HSLUV | ||
| ---@field mix fun(color: HSLUV, n: number): HSLUV | ||
| ---@field readable fun(): HSLUV | ||
| ---@field hue fun(n: number): HSLUV | ||
| ---@field saturation fun(n: number): HSLUV | ||
| ---@field lightness fun(n: number): HSLUV | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of having these highlights configurable - however the choice of the current normal and visual highlight feels arbitrary. I would prefer either make the callback accept 0 parameters, or have one parameter which is the hsluv module.
I'm somewhat of the mind that it's more flexible to not include this in configuration, beyond static values - and just provide an example in the readme on how to define an autocommand that sets the highlights when the colourscheme changes.