Skip to content

unified lsp docs style with treesitter support + clickable text

License

Notifications You must be signed in to change notification settings

litoj/reform.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

79 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

reform.nvim

Documentation should be uniform, concise, and easy to read. This plugin aims to reform neovim to feel more like an IDE with a few QoL improvements (all fully customizable).

Features

  • fully customizable - all options expandable with your own functions for dynamic decissions
  • docmd: reformat lsp docs for a consistent docs structure
    • identical look across supported languages (including vim docs in lua)
    • per-ft configurable
    • opt-in support for all places using lsp docs
      • signature help with param highlighting included (cmp-nvim-lsp-signature-help) and builtin
    • speed is key - written in C with simplified utf8 support
    • support more languages - Rust, go
  • link: clickable links like any other IDE
    • keybind creation builtin, but fully optional
    • modular handlers by vimregex/luaptn → a lot can be used for a match (see also toggle module)
      • handler for stacktrace filepaths with cursor position supporting terminal line-wrapping
      • uri handlers, nvim plugin link handler… (see default config)
  • vim.ui.input/select as popups floating at the cursor (instead of cmdline)
  • … - see config

Installation with lazy.nvim

return {
  'litoj/reform.nvim',
  opts = {}, -- put your config here
  event = 'VeryLazy', -- or LspAttach and `key = {your link mapping}`
}

Config defaults

-- table of config options for `input` and `select`:
local util_win = {
  title_pos = 'center', --        ↓ title of the prompt replaces `''`
  title = {{'[', 'FloatBorder'}, {'', 'FloatTitle'}, {']', 'FloatBorder'}},
  relative = 'cursor',
  border = 'rounded',
}
require'reform'.setup {
  docmd = true|{ -- reformat language-server's docs markdown to have a consistent structure
    override = {
      convert = true|fun(), -- main lspdocs-to-markdown conversion
      stylize = true|fun(), -- docs-display buffer highlighting
      convert_sig = true|fun(), -- signature-help docs composition
      cmp_doc = true|fun(), -- cmp preview docs parsing
      cmp_sig = true|fun(), -- cmp signature help docs parsing
    },
    ft = true|{ -- filetypes allowed for parsing (default=all/ ft=true)
      -- lang = name of supported language; boolean/formatter
      lang = true|fun(docs: string, vim.bo.ft): string[]
    },
    labels = {cs = 'c_sharp'}, -- fixes of md ft labels for file previews
    no_preview = {csharp = true}, -- always parse docs with these code labels
    debug = false|'', -- filename/'"io' for input+output save to register(s) or true to print src
  },
  ui = true|{ -- vim.ui.input (used in vim.lsp.buf.rename)
    win = {
      input = { height = 1, row = -3}+util_win,
      select = { col = -2, row = 1, winhl = 'Id:Repeat,VarDelim:Delimiter'}+util_win,
    },
    input_mapping = { -- keybinds are replaced per action -> cancel={'<C-q>'} removes <Esc>
      cancel = { '<Esc>', '<C-q>' },
      confirm = { '<CR>' },
      histPrev = { '<Up>', '<A-k>' },
      histNext = { '<Down>', '<A-j>' },
    },
  },
  link = true|{ -- under-cursor-regex matcher with configurable actions
    mapping = { -- keymapping to open uri links (clicked or under cursor)
      {{'', 'i'}, '<C-LeftMouse>'}, -- maps to link.mouse(), or manually: mouse=…
      {'n', 'gL'},                  -- maps to link.key()
    },
    handlers = { -- return false for failure → try other handlers if matched handler failed
      -- Event fields: buf, line, column, mouse (if generated by a mouse click)
      -- matches contains all matched groups indexed + matched text `from`/`to` boundaries
      {luapat = 'lua(match)', use = fun(match:string, matches, reform.util.Event): false?},
      {vimre = 'vim\\(match\\)regex'}, -- or vim regex match
      'markdown_url',         -- [name](http://url)
      'any_url',              -- http://url
      'markdown_file_uri',    -- [name](file:///path/to/file)
      'markdown_file_path',   -- [name](/file/path)
      'reform_vimdoc_ref',    -- [VimHelpLink]
      'vimdoc_ref',           -- |VimHelpLink|
      'stacktrace_file_path', -- ~/multiline/path/to/file:line:column
      'nvim_plugin',          -- 'litoj/reform.nvim'
    },
    fallback = 'definition' -- action on no match - invalid value / 'noop' means no action
      -- git link generation: {copy: boolean, print: boolean, branch:'default'|'current'|fun(ev)}
      -- generates links to referenced line in the 'default'/'current'/provided branch
  },
  toggle = true|{ -- quick toggle/change of values under cursor - uses same system as `link`
    mapping = { -- if cursor outside match, move cursor to its start
      {{'n', 'i'}, '<A-a>', {action = 'inc', setCol = 'closer'}, -- closer/start/end of match
      {{'n', 'i'}, '<A-A>', {action = 'dec', setCol = 'closer'}, -- or dec=…nvim.Keymap[]
      {{'n', 'i'}, '<A-C-a>', {action = 'tgl', filter={tolerance={startPost=0,endPre=0}}},
    },
    filter = {
      sorting = { order = 1, matcher = 3, offset = 1, length = 1 }, -- multipliers; least score first
      tolerance = {startPost = inf, endPre = 1}, -- how far and in which directions from cursor is OK
    },
    handlers = {
      'int',        -- (-)123 - increase decrease or toggle sign
      'direction',  -- up north east down south west
      'bool',       -- true/True false/False
      'logic',      -- & && and | || or
      'state',      -- enable(d) disable(d)
      'toggle',     -- on off
      'answer',     -- yes no
      'sign',       -- < = + * ^ > ! - / %
    },
  },
  tbl_extras = false|{ -- helpers for debugging table values
    diff = {
      expand_unique = '', -- other tables for the field are `nil` → copy or use custom value
    },
    cut_depth = {
      depth = 2, -- at which depth to stop copying tables
      cuts = {}, -- what value should be put in cut-off places
    },
    -- set global print() to our extension for easy table diff and depth lookup
    override = {print = true},
  },
  sig_help = true|{
    max_line_offset = 5, -- max cursor position change before repositioning the sig_help window
    max_column_offset = 20,
    ignore_width_above = 0.8, -- percentage of current window width or absolute value
    valid_modes = { i = true, s = true }, -- keep displaying the signature in these modes
    require_active_param = false, -- display signature help for activeParameter=-1
    auto_show = true, -- show on CursorHoldI, toggleable with sig_help.toggle() mapping
    win_config = { border = 'rounded', close_events = {'BufLeave', 'WinScrolled'} },
    override = {
      lsp_sig = true|fun(), -- `vim.lsp.handlers['textDocument/signatureHelp]` main override
      lsc_on_attach = true|fun(), -- lspconfig on_attach - keeps sig_help updated in attached bufs
    },
    mapping = { (toggle=) {'i', '<C-S-Space>'} },
  },
}
  • setup function can be called at any time again to change the settings at runtime

Formatting-supported langauges

Language servers bellow were tested.

  • Bash: bashls
  • C/Cpp: clangd
  • Java: nvim-jdtls
  • Lua: lua-language-server with neodev
  • Typescript/Javascript: typescript-launguage-server/typescript-tools.nvim

Screenshots: with TS vs. reform.nvim

  • bashls Bash/sh
  • clangd C/C++
  • typescript-language-server Javascript/Typescript
  • jdtls Java
  • luals, including Vim-style documentation Lua

About

unified lsp docs style with treesitter support + clickable text

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published