/lspsaga.nvim

improve neovim lsp experience

Primary LanguageLuaMIT LicenseMIT

                                 __
                                / /________  _________ _____ _____ _
                               / / ___/ __ \/ ___/ __ `/ __ `/ __ `/
                              / (__  ) /_/ (__  ) /_/ / /_/ / /_/ /
                             /_/____/ .___/____/\__,_/\__, /\__,_/
                                   /_/               /____/

                          ⚡ Designed for convenience and efficiency ⚡

Neovim lsp enhance plugin.

  1. Install
  2. Example Configuration
  3. Using Lspsaga
  4. Customizing Lspsaga's Appearance
  5. Backers
  6. Donate
  7. License

Install

You can use plugin managers like lazy.nvim and packer.nvim to install lspsaga and lazy load lspsaga using the plugin manager's keyword for lazy loading (lazy for lazy.nvim and opt for packer.nvim).

  • cmd - Load lspsaga only when a lspsaga command is called.

  • ft - lazy.nvim and packer.nvim both provide lazy loading by filetype. This way, you can load lspsaga according to the filetypes that you use a LSP in.

  • event - Only load lspsaga on an event like BufRead or BufReadPost. Do make sure that your LSP plugins, like lsp-zero or lsp-config, are loaded before loading lspsaga.

  • dependencies - For lazy.nvim you can set glepnir/lspsaga.nvim as a dependency of nvim-lspconfig using the dependencies keyword and vice versa. For packer.nvim you should use requires as the keyword instead.

  • after - For packer.nvim you can use after keyword to ensure lspsaga only loads after your LSP plugins have loaded. This is not necessary for lazy.nvim.

  • Lazy

require("lazy").setup({
    "glepnir/lspsaga.nvim",
    event = "LspAttach",
    config = function()
        require("lspsaga").setup({})
    end,
    dependencies = {
      {"nvim-tree/nvim-web-devicons"},
      --Please make sure you install markdown and markdown_inline parser
      {"nvim-treesitter/nvim-treesitter"}
    }
}, opt)
use({
    "glepnir/lspsaga.nvim",
    opt = true,
    branch = "main",
    event = "LspAttach",
    config = function()
        require("lspsaga").setup({})
    end,
    requires = {
        {"nvim-tree/nvim-web-devicons"},
        --Please make sure you install markdown and markdown_inline parser
        {"nvim-treesitter/nvim-treesitter"}
    }
})

Example Configuration

require("lazy").setup({
    "glepnir/lspsaga.nvim",
    event = "LspAttach",
    config = function()
      require("lspsaga").setup({})
    end,
    dependencies = { {"nvim-tree/nvim-web-devicons"} }
})

local keymap = vim.keymap.set

-- LSP finder - Find the symbol's definition
-- If there is no definition, it will instead be hidden
-- When you use an action in finder like "open vsplit",
-- you can use <C-t> to jump back
keymap("n", "gh", "<cmd>Lspsaga lsp_finder<CR>")

-- Code action
keymap({"n","v"}, "<leader>ca", "<cmd>Lspsaga code_action<CR>")

-- Rename all occurrences of the hovered word for the entire file
keymap("n", "gr", "<cmd>Lspsaga rename<CR>")

-- Rename all occurrences of the hovered word for the selected files
keymap("n", "gr", "<cmd>Lspsaga rename ++project<CR>")

-- Peek definition
-- You can edit the file containing the definition in the floating window
-- It also supports open/vsplit/etc operations, do refer to "definition_action_keys"
-- It also supports tagstack
-- Use <C-t> to jump back
keymap("n", "gp", "<cmd>Lspsaga peek_definition<CR>")

-- Go to definition
keymap("n","gd", "<cmd>Lspsaga goto_definition<CR>")

-- Peek type definition
-- You can edit the file containing the type definition in the floating window
-- It also supports open/vsplit/etc operations, do refer to "definition_action_keys"
-- It also supports tagstack
-- Use <C-t> to jump back
keymap("n", "gt", "<cmd>Lspsaga peek_type_definition<CR>")

-- Go to type definition
keymap("n","gt", "<cmd>Lspsaga goto_type_definition<CR>")


-- Show line diagnostics
-- You can pass argument ++unfocus to
-- unfocus the show_line_diagnostics floating window
keymap("n", "<leader>sl", "<cmd>Lspsaga show_line_diagnostics<CR>")

-- Show buffer diagnostics
keymap("n", "<leader>sb", "<cmd>Lspsaga show_buf_diagnostics<CR>")

-- Show workspace diagnostics
keymap("n", "<leader>sw", "<cmd>Lspsaga show_workspace_diagnostics<CR>")

-- Show cursor diagnostics
keymap("n", "<leader>sc", "<cmd>Lspsaga show_cursor_diagnostics<CR>")

-- Diagnostic jump
-- You can use <C-o> to jump back to your previous location
keymap("n", "[e", "<cmd>Lspsaga diagnostic_jump_prev<CR>")
keymap("n", "]e", "<cmd>Lspsaga diagnostic_jump_next<CR>")

-- Diagnostic jump with filters such as only jumping to an error
keymap("n", "[E", function()
  require("lspsaga.diagnostic"):goto_prev({ severity = vim.diagnostic.severity.ERROR })
end)
keymap("n", "]E", function()
  require("lspsaga.diagnostic"):goto_next({ severity = vim.diagnostic.severity.ERROR })
end)

-- Toggle outline
keymap("n","<leader>o", "<cmd>Lspsaga outline<CR>")

-- Hover Doc
-- If there is no hover doc,
-- there will be a notification stating that
-- there is no information available.
-- To disable it just use ":Lspsaga hover_doc ++quiet"
-- Pressing the key twice will enter the hover window
keymap("n", "K", "<cmd>Lspsaga hover_doc<CR>")

-- If you want to keep the hover window in the top right hand corner,
-- you can pass the ++keep argument
-- Note that if you use hover with ++keep, pressing this key again will
-- close the hover window. If you want to jump to the hover window
-- you should use the wincmd command "<C-w>w"
keymap("n", "K", "<cmd>Lspsaga hover_doc ++keep<CR>")

-- Call hierarchy
keymap("n", "<Leader>ci", "<cmd>Lspsaga incoming_calls<CR>")
keymap("n", "<Leader>co", "<cmd>Lspsaga outgoing_calls<CR>")

-- Floating terminal
keymap({"n", "t"}, "<A-d>", "<cmd>Lspsaga term_toggle<CR>")

Using Lspsaga

Note that the title in the floating window requires Neovim 0.9 or greater. If you are using Neovim 0.8 you won't see a title.

**If you are using Neovim 0.9 and want to disable the title, see Customizing Lspsaga's Appearance

You need not copy all of the options into the setup function. Just set the options that you've changed in the setup function and it will be extended with the default options!

You can find the documentation for Lspsaga in Neovim by using :h lspsaga.

Default options

The top-level default options (command-specific default options below):

  preview = {
    lines_above = 0,
    lines_below = 10,
  },
  scroll_preview = {
    scroll_down = "<C-f>",
    scroll_up = "<C-b>",
  },
  request_timeout = 2000,

Example setup using default options:

require("lspsaga").setup({
  preview = {
    lines_above = 0,
    lines_below = 10,
  },
  scroll_preview = {
    scroll_down = "<C-f>",
    scroll_up = "<C-b>",
  },
  request_timeout = 2000,

  -- See Customizing Lspsaga's Appearance
  ui = { ... },

  -- For default options for each command, see below
  finder = { ... },
  code_action = { ... }
  -- etc.
})

:Lspsaga lsp_finder

A finder to show the definition, reference and implementation (only shown when current hovered word is a function, a type, a class, or an interface).

Default options:

  finder = {
    max_height = 0.5,
    min_width = 30,
    force_max_height = false,
    keys = {
      jump_to = 'p',
      expand_or_jump = 'o',
      vsplit = 's',
      split = 'i',
      tabe = 't',
      tabnew = 'r',
      quit = { 'q', '<ESC>' },
      close_in_preview = '<ESC>',
    },
  },
  • max_height of the finder window.
  • force_max_height force window height to max_height
  • keys.jump_to finder peek window.
  • close_in_preview will close all finder window in when you in preview window.
  • min_width is finder preview window min width.
lsp_finder showcase

:Lspsaga peek_definition

There are two commands, :Lspsaga peek_definition and :Lspsaga goto_definition. The peek_definition command works like the VSCode command of the same name, which shows the target file in an editable floating window.

Default options:

  definition = {
    edit = "<C-c>o",
    vsplit = "<C-c>v",
    split = "<C-c>i",
    tabe = "<C-c>t",
    quit = "q",
  }
peek_definition showcase

The steps demonstrated in this showcase are:

  • Pressing gp to run :Lspsaga peek_definition
  • Editing a comment and using :w to save
  • Pressing <C-c>o to jump to the file in the floating window
  • Lspsaga shows a beacon highlight after jumping to the file

:Lspsaga goto_definition

Jumps to the definition of the hovered word and shows a beacon highlight.

:Lspsaga code_action

Default options:

  code_action = {
    num_shortcut = true,
    show_server_name = false,
    extend_gitsigns = true,
    keys = {
      -- string | table type
      quit = "q",
      exec = "<CR>",
    },
  },
  • num_shortcut - It is true by default so you can quickly run a code action by pressing its corresponding number.
  • extend_gitsigns show gitsings in code action.
code_action showcase

The steps demonstrated in this showcase are:

  • Pressing ga to run :Lspsaga code_action
  • Pressing j to move within the code action preview window
  • Pressing <Cr> to run the action

:Lspsaga Lightbulb

When there are possible code actions to be taken, a lightbulb icon will be shown.

Default options:

  lightbulb = {
    enable = true,
    enable_in_insert = true,
    sign = true,
    sign_priority = 40,
    virtual_text = true,
  },
lightbulb showcase

:Lspasga hover_doc

default options

  hover = {
    max_width = 0.6,
    open_link = 'gx',
    open_browser = '!chrome',
  },

you can use open_link key to open a http link or a file link in hover doc window. the open_browser is chrome in default you need config it to your browser

You need install the treesitter markdown and markdown_line parser. Lspsaga can use it to render the hover window. You can press the keyboard shortcut for :Lspsaga hover_doc twice to enter the hover window.

if you got something wrong in hover please run :checkhealth

hover_docshow case

The steps demonstrated in this showcase are:

  • Pressing K once to run :Lspsaga hover_doc
  • Pressing K again to enter the hover window
  • Pressing q to quit

:Lspsaga diagnostic_jump_next

Jumps to next diagnostic position and show a beacon highlight. Lspsaga will then show the code actions.

Default options:

  diagnostic = {
    on_insert = false,
    on_insert_follow = false,
    insert_winblend = 0,
    show_code_action = true,
    show_source = true,
    jump_num_shortcut = true,
    max_width = 0.7,
    max_height = 0.6,
    max_show_width = 0.9,
    max_show_height = 0.6,
    text_hl_follow = true,
    border_follow = true,
    extend_relatedInformation = false,
    keys = {
      exec_action = 'o',
      quit = 'q',
      expand_or_jump = '<CR>',
      quit_in_show = { 'q', '<ESC>' },
    },
  },
  • jump_num_shortcut - The default is true. After jumping, Lspasga will automatically bind code actions to a number. Afterwards, you can press the number to execute the code action. After the floating window is closed, these numbers will no longer be tied to the same code actions.
  • show_codeaction default is true it will show available actions in the diagnsotic jump window
  • show_source default is true extend source into the diagnostic message
  • max_width is the max width for diagnostic jump window. percentage
  • max_height is the max height of diagnostic jump window percentage
  • text_hl_follow is false default true that you can define DiagnostcText to custom the diagnotic text color
  • border_follow the border highlight will follow the diagnostic type. if false it will use the highlight DiagnosticBorder.
  • on_insert default is true it works like the emacs helix show diagnostic in right but in line.
  • on_insert_follow true will follow current line. false will on top right
  • insert_winblend default is 0, when it's to 100 will completely transparent. the color will changed a little light. 0 will use the NormalFloat group. it will link to Normal by Lspsaga.
  • max_show_width is the width of show diagnostic window
  • max_show_height is the height of show diagnostic widnow
  • extend_relatedInformation default is false when is true it will extend this message into diagnostic message

You can also use a filter when using diagnostic jump by using a Lspsaga function. The function takes a table as its argument. It is functionally identical to :h vim.diagnostic.get_next.

-- This will only jump to an error
-- If no error is found, it executes "goto_next"
require("lspsaga.diagnostic"):goto_prev({ severity = vim.diagnostic.severity.ERROR })
showcase

The steps demonstrated in this showcase are:

  • Pressing [e to jump to the next diagnostic position, which shows the beacon highlight and the code actions in a diagnostic window
  • Use scroll_in_preview keys to show action preview.
  • Pressing the number 2 to execute the code action without needing to enter the floating window
  • If you want to see the code action, you can use <C-w>w to enter the floating window.
  • Press g to go to the action line and see the code action preview.
  • Press o to execute the action.

on_insert is true, on_insert_follow is false

on_insert_follow is true

:Lspsaga show_diagnostics

show_line_diagnostics, show_buf_diagnostics, show_workspace_diagnostics show_cursor_diagnsotics. and support an argument ++unfocus to make it unfocus. like :Lspsaga show_workspace_diagnostics ++unfocus you can press the expand_or_jump key to expand on fname line or jump into location on message line.

show_diagnostics showcase

:Lspsaga rename

Uses the current LSP to rename the hovered word.

Default options:

  rename = {
    quit = "<C-c>",
    exec = "<CR>",
    mark = "x",
    confirm = "<CR>",
    in_select = true,
  },
  • mark is used for the ++project argument. It is used to mark the files which you want to rename the hovered word in.
  • confirm - After you have marked the files, press this key to execute the rename.
rename showcase

The steps demonstrated in this showcase are:

  • Pressing gr to run :Lspsaga rename
  • Typing stesdd and then pressing <CR> to execute the rename

The steps demonstrated in this showcase are:

  • Pressing gR to run :Lspsaga rename ++project
  • Pressing x to mark the file
  • Pressing <CR> to execute rename

:Lspsaga outline

Default options:

  outline = {
    win_position = "right",
    win_with = "",
    win_width = 30,
    preview_width= 0.4,
    show_detail = true,
    auto_preview = true,
    auto_refresh = true,
    auto_close = true,
    custom_sort = nil,
    keys = {
      expand_or_jump = 'o',
      quit = "q",
    },
  },
outline showcase

The steps demonstrated in this showcase are:

  • Pressing <Leader>o run :Lspsaga outline

:Lspsaga incoming_calls / outgoing_calls

Runs the LSP's callhierarchy/incoming_calls.

Default options:

  callhierarchy = {
    show_detail = false,
    keys = {
      edit = "e",
      vsplit = "s",
      split = "i",
      tabe = "t",
      jump = "o",
      quit = "q",
      expand_collapse = "u",
    },
  },
incoming_calls showcase

:Lspsaga symbols in winbar

This requires Neovim version >= 0.8.

Default options:

  symbol_in_winbar = {
    enable = true,
    separator = "",
    ignore_patterns={},
    hide_keyword = true,
    show_file = true,
    folder_level = 2,
    respect_root = false,
    color_mode = true,
  },
  • hide_keyword - The default value is true. Lspsaga will hide some keywords and temporary variables to make the symbols look cleaner.
  • folder_level only works when show_file is true.
  • respect_root will respect the LSP's root. If this is true, Lspsaga will ignore the folder_level option. If no LSP client is being used, Lspsaga will fall back to using folder level.
  • color_mode - The default value is true. When it is set to false, only icons will have color.
  • ignore_patterns table type when fileanme matched the pattern will ignore render symbols. if show_file is true. the file name will still set.
Symbols in winbar

:Lspsaga symbols in a custom winbar/statusline

Lspsaga provides an API that you can use in your custom winbar or statusline.

vim.wo.winbar / vim.wo.stl = require('lspsaga.symbolwinbar'):get_winbar()

:Lspsaga term_toggle

A simple floating terminal.

Toggling the floating terminal

:Lspsaga beacon

after jump from float window there will show beacon to remind you where the cursor is.

  beacon = {
    enable = true,
    frequency = 7,
  },

frequency the blink frequency.

Customizing Lspsaga's Appearance

:Lspsaga UI

Default UI options

  ui = {
    -- This option only works in Neovim 0.9
    title = true,
    -- Border type can be single, double, rounded, solid, shadow.
    border = "single",
    winblend = 0,
    expand = "",
    collapse = "",
    code_action = "💡",
    incoming = "",
    outgoing = "",
    hover = '',
    kind = {},
  },

Custom Highlighting

All highlight groups can be found in highlight.lua.

require('lspsaga.lspkind').get_kind_group() will return all the SagaWinbar + kind name group . also include SagaWinbarFileName SagaWinbarFileIcon SagaWinbarFolderName SagaWinbarSep. These groups are special. so if you want use this api to custom the highlight. you need dealwith these 4 groups the last item is SagaWinbarSep.

Custom Kind

Modify ui.kind to change the icons of the kinds.

All kinds used in Lspsaga are defined in lspkind.lua. The key in ui.kind is the kind name, and the value can either be a string or a table. If a string is passed, it is setting the icon. If table is passed, it will be passed as { icon, highlight group }, for example, to change the a folder's icon color, you could do this: ui = { kind = { ["Folder"] = { " ", "@comment" }, }, },.

Donate

Currently, I am in need of some donations. If you'd like to support my work financially, please donate through Github Sponsor button or PayPal. Thanks!

Backers

Thanks for everyone!

@Tuo Huang @Scott Ming @Möller Lukas @HendrikPetertje @Bojan Wilytsch @zhourrr @Burgess Darrion @Ceserani Alessandro

License

Licensed under the MIT license.