Skip to content

Repository files navigation

Insert Inlay Hints

A neovim plugin that enables inserting inlay hints as code.

Not all LSPs offer a native ability to insert inlay hints as code. This plugin can insert inlay hints from any LSP as code in a buffer.

I feel that the UX of LSPs that do offer the ability to insert inlay hints doesn't fit well with my workflow (such as needing to place the cursor where inlay hint will be inserted). This plugin offers a more streamlined UX for doing this task.

Important

Some LSPs use inlay hints that may not be valid syntax. This plugin doesn't check if the inserted syntax is valid.

Demo

insert-inlay-hints_demo.mp4

Installation

Install with your favorite package manager.

Example for lazy.nvim:

{
  "AbysmalBiscuit/insert-inlay-hints.nvim",
  keys = {
    {
      "<leader>ic",
      function()
        require("insert-inlay-hints").closest()
      end,
      desc = "Insert the colsest inline hint as code.",
    },
    {
      "<leader>il",
      function()
        require("insert-inlay-hints").line()
      end,
      desc = "Insert all inline hints on current line as code.",
    },
    {
      "<leader>i",
      function()
        require("insert-inlay-hints").visual()
      end,
      desc = "Insert all inlay hints in the current visual selection as code.",
      mode = { "v" },
    },
    {
      "<leader>ia",
      function()
        return require("insert-inlay-hints").all()
      end,
      desc = "Insert all inlay hints in the current buffer as code.",
    },
  },
}

This plugin lazy loads by default when used with lazy.nvim. It has its own specification, that declares the user commands.

Examples for other package managers:

`vim.pack`

vim.pack.add({
  src = "AbysmalBiscuit/insert-inlay-hints.nvim",
  data = {
    cmd = {
      "InsertHints",
      "InsertHintsPlugin",
    },
    keys = {
      {
        "<leader>ic",
        function()
          require("insert-inlay-hints").closest()
        end,
        desc = "Insert the colsest inline hint as code.",
      },
      {
        "<leader>il",
        function()
          require("insert-inlay-hints").line()
        end,
        desc = "Insert all inline hints on current line as code.",
      },
      {
        "<leader>i",
        function()
          require("insert-inlay-hints").visual()
        end,
        desc = "Insert all inlay hints in the current visual selection as code.",
        mode = { "v" },
      },
      {
        "<leader>ia",
        function()
          return require("insert-inlay-hints").all()
        end,
        desc = "Insert all inlay hints in the current buffer as code.",
      },
    },
    after = function(_)
      require("insert-inlay-hints").setup({
        -- Add config options here to change the defaults
      })
    end,
  },
})

Configuration

Default configuration:

---@class insert-inlay-hints.Config
local defaults = {
  ---Whether to print debug messages.
  ---@type boolean
  debug = false,

  ---Whether to enable the plugin by default.
  ---@type boolean
  enable = true,

  ---List of filetypes for which to enable the plugin.
  ---When left empty it will be enabled for all filetypes, except for those defined in `disabled_filetypes`.
  ---When values are passed, it will only activate for those filetypes.
  ---@type Filetypes
  enabled_filetypes = {},

  ---List of filetypes for which to disable the plugin.
  ---The disabled filetypes are applied after the enabled_filetypes.
  ---Use this to exclude filetypes.
  ---@type Filetypes
  disabled_filetypes = { "lua", "javascript", "haskell" },

  ---List of LSPs for which to disable the plugin.
  ---Run `:LspInfo` to see the LSPs attached to a given buffer.
  ---@type string[]
  disabled_lsps = {},

  ---Config options for `insert-inlay-hints.insert.closest`.
  ---@class InsertClosestConfig
  insert_closest = {
    ---Will move the cursor to the end of the inlay hint that was just inserted.
    ---This imitates the end result of manually typing the inlay hint.
    ---@type boolean
    move_cursor = true,

    ---Will prioritize hints on the current line if they're available.
    ---If no hints are available on the current line, then it will prioritize lines closer line-wise.
    ---@type boolean
    prioritize_lines = true,

    ---Function to use for calculating the distance from the cursor to inlay hints.
    ---The closest inlay hint will be inserted.
    ---You can use one of the predefined functions, or define your own.
    ---The function needs to take four parameters and return a number:
    ---`fun(cursor_line: integer, cursor_character: integer, hint_line: integer, hint_character: integer): number`
    ---@type "euclidian" | "manhattan" | "chebyshev" | "minkowski" | DistanceFunction
    distance_function = "euclidian",

    ---The exponent to use when calculating minkowski distance.
    ---Setting this to math.huge, will default to using the chebyshev distance.
    ---@type integer
    minkowski_exponent = 5,
  },
}

Usage

User Commands

The plugin defines two user commands and and several public-API functions (see init.lua).

User command to enable/disable/toggle the plugin:

  • InsertHintsPlugin: enable, disable, or toggle the plugin functionality. Takes one of the following arguments:
    • enable: enable the insert-inlay-hints plugin.
    • disable: disable the insert-inlay-hints plugin.
    • toggle: toggle the insert-inlay-hints plugin.

User command to insert inlay hints as code:

  • InsertHints: insert inlay hints in various ways. Takes one of the following arguments:
    • closest: insert the inlay hint closest to the cursor as code. See the insert_closest part of the configuration for how to configure how the closest inlay hint is determined.
    • line: insert all inlay hints on the current line as code.
    • visual: insert all inlay hints in the current visual selection as code.
    • all: insert all inlay hints in the current buffer as code.

Keymaps

The insert-inlay-hints module offers four public-API functions for inserting hints:

  • insert-inlay-hints.closest: insert the inlay hint closest to the cursor as code. See the insert_closest part of the configuration for how to configure how the closest inlay hint is determined.
  • line: insert all inlay hints on the current line as code.
  • visual: insert all inlay hints in the current visual selection as code.
  • all: insert all inlay hints in the current buffer as code.

These functions can be easily bound to keymaps and and are dot-repeatable.

I like to use the mnemonic <leader> [i]nsert [...]. For example:

  • <leader>il (insert [hints] line).
  • <leader>i (insert all [hints] in visual selection)

Example: creating a keymap

local insert = require("insert-inlay-hints")

-- Create a non dot-repeatable command
vim.keymap.set(
  "n",
  "<leader>ic",
  insert.closest,
  { noremap = true, desc = "Insert the inlay hint closest to the cursor as code." }
)

-- Alternative if you don't want to load the module before (no need to return something)
vim.keymap.set(
  "n",
  "<leader>ic",
  function()
    require("insert-inlay-hints").closest()
  end,
  { noremap = true, desc = "Insert the inlay hint closest to the cursor as code." }
)

Non Dot-Repeatable Keymaps

The insert-inlay-hints.insert module offers the base functions that are not dot-repeatable.

Example: creating a non dot-repeatable keymap (using functions from the `insert-inlay-hints.insert` module)

local insert = require("insert-inlay-hints.insert")

-- Create a non dot-repeatable command
vim.keymap.set(
  "n",
  "<leader>ic",
  insert.closest,
  { noremap = true, desc = "Insert the inlay hint closest to the cursor as code." }
)

-- Alternative if you don't want to load the module before (no need to return something)
vim.keymap.set(
  "n",
  "<leader>ic",
  function()
    require("insert-inlay-hints.insert").closest()
  end,
  { noremap = true, desc = "Insert the inlay hint closest to the cursor as code." }
)

Similar Plugins

About

A neovim plugin that enables inserting inlay hints as code.

Topics

Resources

Stars

7 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages