{"id":14258694,"url":"https://github.com/AstroNvim/astrolsp","last_synced_at":"2025-08-13T01:31:41.541Z","repository":{"id":182409770,"uuid":"663546510","full_name":"AstroNvim/astrolsp","owner":"AstroNvim","description":"LSP Configuration Engine built for AstroNvim","archived":false,"fork":false,"pushed_at":"2024-11-08T20:45:31.000Z","size":230,"stargazers_count":50,"open_issues_count":1,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-14T00:07:19.331Z","etag":null,"topics":["astronvim","astrovim","lsp","lspconfig","lua","mason","mason-lspconfig","neovim","neovim-lsp","neovim-lua-plugin","neovim-plugin","none-ls","null-ls"],"latest_commit_sha":null,"homepage":"https://AstroNvim.com","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AstroNvim.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-07T14:46:14.000Z","updated_at":"2024-12-08T23:51:23.000Z","dependencies_parsed_at":"2024-02-16T16:26:35.662Z","dependency_job_id":"9a1a1a9d-a069-450c-82c7-2b5f8eef6e70","html_url":"https://github.com/AstroNvim/astrolsp","commit_stats":null,"previous_names":["astronvim/astrolsp"],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AstroNvim%2Fastrolsp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AstroNvim%2Fastrolsp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AstroNvim%2Fastrolsp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AstroNvim%2Fastrolsp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AstroNvim","download_url":"https://codeload.github.com/AstroNvim/astrolsp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229721645,"owners_count":18114043,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["astronvim","astrovim","lsp","lspconfig","lua","mason","mason-lspconfig","neovim","neovim-lsp","neovim-lua-plugin","neovim-plugin","none-ls","null-ls"],"created_at":"2024-08-22T09:01:29.329Z","updated_at":"2025-08-13T01:31:41.476Z","avatar_url":"https://github.com/AstroNvim.png","language":"Lua","readme":"# 🛠️ AstroLSP\n\nAstroLSP provides a simple API for configuring and setting up language servers in Neovim. This is the LSP configuration engine that [AstroNvim](https://github.com/AstroNvim/AstroNvim) uses, but can be used by itself as well.\n\n## ✨ Features\n\n- Unified interface for configuring language servers:\n  - Key mappings when attaching\n  - Capabilities and language server settings\n- Format on save\n- Easily toggle features such as inlay hints, codelens, and semantic tokens\n\n## ⚡️ Requirements\n\n- Neovim \u003e= 0.10\n\n## 📦 Installation\n\nInstall the plugin with your plugin manager of choice:\n\n[**lazy.nvim**][lazy]\n\n```lua\n{\n  \"AstroNvim/astrolsp\",\n  opts = {\n    -- set configuration options  as described below\n  }\n}\n```\n\n[**packer.nvim**](https://github.com/wbthomason/packer.nvim)\n\n```lua\nuse {\n  \"AstroNvim/astrolsp\",\n}\n\nrequire(\"astrolsp\").setup {\n  -- set configuration options  as described below\n}\n```\n\n## ⚙️ Configuration\n\n**AstroLSP** comes with the no defaults, but can be configured fully through the `opts` table in lazy or through calling `require(\"astrolsp\").setup({})`. Here are descriptions of the options and some example usages:\n\n```lua\n---@type AstroLSPConfig\nlocal opts = {\n  -- Configuration table of features provided by AstroLSP\n  features = {\n    codelens = true, -- enable/disable codelens refresh on start\n    inlay_hints = false, -- enable/disable inlay hints on start\n    semantic_tokens = true, -- enable/disable semantic token highlighting\n  },\n  -- Configure buffer local auto commands to add when attaching a language server\n  autocmds = {\n    -- first key is the `augroup` (:h augroup)\n    lsp_document_highlight = {\n      -- condition to create/delete auto command group\n      -- can either be a string of a client capability or a function of `fun(client, bufnr): boolean`\n      -- condition will be resolved for each client on each execution and if it ever fails for all clients,\n      -- the auto commands will be deleted for that buffer\n      cond = \"textDocument/documentHighlight\",\n      -- list of auto commands to set\n      {\n        -- events to trigger\n        event = { \"CursorHold\", \"CursorHoldI\" },\n        -- the rest of the autocmd options (:h nvim_create_autocmd)\n        desc = \"Document Highlighting\",\n        callback = function() vim.lsp.buf.document_highlight() end,\n      },\n      {\n        event = { \"CursorMoved\", \"CursorMovedI\", \"BufLeave\" },\n        desc = \"Document Highlighting Clear\",\n        callback = function() vim.lsp.buf.clear_references() end,\n      },\n    },\n  },\n  -- Configure buffer local user commands to add when attaching a language server\n  commands = {\n    Format = {\n      function() vim.lsp.buf.format() end,\n      -- condition to create the user command\n      -- can either be a string of a client capability or a function of `fun(client, bufnr): boolean`\n      cond = \"textDocument/formatting\",\n      -- the rest of the user command options (:h nvim_create_user_command)\n      desc = \"Format file with LSP\",\n    },\n  },\n  -- Configure default capabilities for language servers (`:h vim.lsp.protocol.make_client.capabilities()`)\n  capabilities = {\n    textDocument = {\n      foldingRange = { dynamicRegistration = false },\n    },\n  },\n  -- Configure language servers for `lspconfig` (`:h lspconfig-setup`)\n  config = {\n    lua_ls = {\n      settings = {\n        Lua = {\n          hint = { enable = true, arrayIndex = \"Disable\" },\n        },\n      },\n    },\n    clangd = {\n      capabilities = {\n        offsetEncoding = \"utf-8\",\n      },\n    },\n  },\n  defaults = {\n    hover = { border = \"rounded\", silent = true } -- customize lsp hover window\n    signature_help = false, -- disable any default customizations\n  },\n  -- Configuration of LSP file operation functionality\n  file_operations = {\n    -- the timeout when executing LSP client operations\n    timeout = 10000,\n    -- fully disable/enable file operation methods\n    operations = {\n      willRename = true,\n      didRename = true,\n      willCreate = true,\n      didCreate = true,\n      willDelete = true,\n      didDelete = true,\n    },\n  },\n  -- A custom flags table to be passed to all language servers  (`:h lspconfig-setup`)\n  flags = {\n    exit_timeout = 5000,\n  },\n  -- Configuration options for controlling formatting with language servers\n  formatting = {\n    -- control auto formatting on save\n    format_on_save = {\n      -- enable or disable format on save globally\n      enabled = true,\n      -- enable format on save for specified filetypes only\n      allow_filetypes = {\n        \"go\",\n      },\n      -- disable format on save for specified filetypes\n      ignore_filetypes = {\n        \"python\",\n      },\n    },\n    -- disable formatting capabilities for specific language servers\n    disabled = {\n      \"lua_ls\",\n    },\n    -- default format timeout\n    timeout_ms = 1000,\n    -- fully override the default formatting function\n    filter = function(client) return true end,\n  },\n  -- Configure how language servers get set up\n  handlers = {\n    -- default handler, first entry with no key\n    function(server, opts) require(\"lspconfig\")[server].setup(opts) end,\n    -- custom function handler for pyright\n    pyright = function(_, opts) require(\"lspconfig\").pyright.setup(opts) end,\n    -- set to false to disable the setup of a language server\n    rust_analyzer = false,\n  },\n  -- Configure `vim.lsp.handlers`\n  lsp_handlers = {\n    [\"textDocument/publishDiagnostics\"] = function(...) end, -- customize a handler with a custom function\n  },\n  -- Configuration of mappings added when attaching a language server during the core `on_attach` function\n  -- The first key into the table is the vim map mode (`:h map-modes`), and the value is a table of entries to be passed to `vim.keymap.set` (`:h vim.keymap.set`):\n  --   - The key is the first parameter or the vim mode (only a single mode supported) and the value is a table of keymaps within that mode:\n  --     - The first element with no key in the table is the action (the 2nd parameter) and the rest of the keys/value pairs are options for the third parameter.\n  --       There is also a special `cond` key which can either be a string of a language server capability or a function with `client` and `bufnr` parameters that returns a boolean of whether or not the mapping is added.\n  mappings = {\n    -- map mode (:h map-modes)\n    n = {\n      -- a binding with no condition and therefore is always added\n      gl = {\n        function() vim.diagnostic.open_float() end,\n        desc = \"Hover diagnostics\",\n      },\n      -- condition for only server with declaration capabilities\n      gD = {\n        function() vim.lsp.buf.declaration() end,\n        desc = \"Declaration of current symbol\",\n        cond = \"textDocument/declaration\",\n      },\n      -- condition with a full function with `client` and `bufnr`\n      [\"\u003cleader\u003euY\"] = {\n        function() require(\"astrolsp.toggles\").buffer_semantic_tokens() end,\n        desc = \"Toggle LSP semantic highlight (buffer)\",\n        cond = function(client, bufnr)\n          return client.server_capabilities.semanticTokensProvider and vim.lsp.semantic_tokens\n        end,\n      },\n    },\n  },\n -- Extra configuration for the `mason-lspconfig.nvim` plugin\n  mason_lspconfig = {\n    -- Allow registering more Mason packages as language servers for autodetection/setup\n    servers = {\n      -- The key is the lspconfig server name to register a package for\n      nextflow_ls = {\n        -- The Mason package name to register to the language server\n        package = \"nextflow-language-server\",\n        -- The filetypes that apply to the package and language server\n        filetypes = { \"nextflow\" },\n        -- (Optional) any default configuration changes that may need to happen (can be a table or a function that returns a table)\n        config = { cmd = { \"nextflow-language-server\" } }\n      }\n    }\n  }\n  -- A list like table of servers that should be setup, useful for enabling language servers not installed with Mason.\n  servers = { \"dartls\" },\n  -- A custom `on_attach` function to be run after the default `on_attach` function, takes two parameters `client` and `bufnr`  (`:h lspconfig-setup`)\n  on_attach = function(client, bufnr) client.server_capabilities.semanticTokensProvider = nil end,\n}\n```\n\n## 🔌 Integrations\n\n**AstroLSP** can be used as the basis for configuring plugins such as [`nvim-lspconfig`][lspconfig] and [`mason-lspconfig`][mason-lspconfig]. Here are a few examples (using [`lazy.nvim`][lazy] plugin manager):\n\n### [nvim-lspconfig][lspconfig]\n\n```lua\n{\n  \"neovim/nvim-lspconfig\",\n  dependencies = {\n    { \"AstroNvim/astrolsp\", opts = {} },\n  },\n  config = function()\n    -- set up servers configured with AstroLSP\n    vim.tbl_map(require(\"astrolsp\").lsp_setup, require(\"astrolsp\").config.servers)\n  end,\n}\n```\n\n### [nvim-lspconfig][lspconfig] + [mason.nvim][mason] + [mason-lspconfig.nvim][mason-lspconfig]\n\n```lua\n{\n  \"neovim/nvim-lspconfig\",\n  dependencies = {\n    { \"AstroNvim/astrolsp\", opts = {} },\n    {\n      \"williamboman/mason-lspconfig.nvim\", -- MUST be set up before `nvim-lspconfig`\n      dependencies = { \"williamboman/mason.nvim\" },\n      opts = {\n        -- use AstroLSP setup for mason-lspconfig\n        handlers = { function(server) require(\"astrolsp\").lsp_setup(server) end },\n      },\n      config = function(_, opts)\n        -- Optionally tell AstroLSP to register new language servers before calling the `setup` function\n        -- this enables the `mason-lspconfig.servers` option in the AstroLSP configuration\n        require(\"astrolsp.mason-lspconfig\").register_servers()\n        require(\"mason-lspconfig\").setup(opts)\n      end\n    },\n  },\n  config = function()\n    -- set up servers configured with AstroLSP\n    vim.tbl_map(require(\"astrolsp\").lsp_setup, require(\"astrolsp\").config.servers)\n  end,\n}\n```\n\n### [none-ls.nvim][none-ls]\n\n```lua\n{\n  \"nvimtools/none-ls.nvim\",\n  dependencies = {\n    { \"AstroNvim/astrolsp\", opts = {} },\n  },\n  opts = function() return { on_attach = require(\"astrolsp\").on_attach } end,\n}\n```\n\n### LSP File Operations\n\nAstroLSP provides an API for triggering LSP based file operations and currently supports:\n\n- `workspace/willCreateFiles`\n- `workspace/didCreateFiles`\n- `workspace/willDeleteFiles`\n- `workspace/didDeleteFiles`\n- `workspace/willRenameFiles`\n- `workspace/didRenameFiles`\n\nThese methods can be integrated with file management plugins such as [mini.files](https://github.com/echasnovski/mini.files), [neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim), [nvim-tree.lua](https://github.com/nvim-tree/nvim-tree.lua), and [triptych.nvim](https://github.com/simonmclean/triptych.nvim). (Some file managers already have support out of the box such as [oil.nvim](https://github.com/stevearc/oil.nvim) so integration with them is unnecessary).\n\n#### [mini.files](https://github.com/echasnovski/mini.files)\n\n`mini.files` provides `autocommand` events which can be used to trigger functionality. As of writing these only include events after an operation is completed and therefore does not support the `willCreateFiles`/`willDeleteFiles`/`willRenameFiles` events.\n\n```lua\nvim.api.nvim_create_autocmd(\"User\", {\n  pattern = \"MiniFilesActionCreate\",\n  desc = \"trigger `workspace/didCreateFiles` after creating files\",\n  callback = function(args) require(\"astrolsp.file_operations\").didCreateFiles(args.data.to) end,\n})\nvim.api.nvim_create_autocmd(\"User\", {\n  pattern = \"MiniFilesActionDelete\",\n  desc = \"trigger `workspace/didDeleteFiles` after deleting files\",\n  callback = function(args) require(\"astrolsp.file_operations\").didDeleteFiles(args.data.from) end,\n})\nvim.api.nvim_create_autocmd(\"User\", {\n  pattern = { \"MiniFilesActionRename\", \"MiniFilesActionMove\" },\n  desc = \"trigger `workspace/didRenameFiles` after renaming or moving files\",\n  callback = function(args) require(\"astrolsp.file_operations\").didRenameFiles(args.data) end,\n})\n```\n\n#### [neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim)\n\n`neo-tree.nvim` provides configuration options for event handlers which can be used to set up the necessary handling before/after file operations. There is also a Lua API to do this outside of the plugin configuration (information on this can be found in their documentation). Here is an example for doing it within the setup of `neo-tree.nvim`:\n\n```lua\nlocal events = require \"neo-tree.events\"\nrequire(\"neo-tree\").setup {\n  event_handlers = {\n    {\n      event = events.BEFORE_FILE_ADD,\n      handler = function(args) require(\"astrolsp.file_operations\").willCreateFiles(args) end,\n    },\n    {\n      event = events.FILE_ADDED,\n      handler = function(args) require(\"astrolsp.file_operations\").didCreateFiles(args) end,\n    },\n    {\n      event = events.BEFORE_FILE_DELETE,\n      handler = function(args) require(\"astrolsp.file_operations\").willDeleteFiles(args) end,\n    },\n    {\n      event = events.FILE_DELETED,\n      handler = function(args) require(\"astrolsp.file_operations\").didDeleteFiles(args) end,\n    },\n    {\n      event = events.BEFORE_FILE_MOVE,\n      handler = function(args)\n        require(\"astrolsp.file_operations\").willRenameFiles { from = args.source, to = args.destination }\n      end,\n    },\n    {\n      event = events.BEFORE_FILE_RENAME,\n      handler = function(args)\n        require(\"astrolsp.file_operations\").willRenameFiles { from = args.source, to = args.destination }\n      end,\n    },\n    {\n      event = events.FILE_MOVED,\n      handler = function(args)\n        require(\"astrolsp.file_operations\").didRenameFiles { from = args.source, to = args.destination }\n      end,\n    },\n    {\n      event = events.FILE_RENAMED,\n      handler = function(args)\n        require(\"astrolsp.file_operations\").didRenameFiles { from = args.source, to = args.destination }\n      end,\n    },\n  },\n}\n```\n\n#### [nvim-tree.lua](https://github.com/nvim-tree/nvim-tree.lua)\n\n`nvim-tree.lua` provides a Lua API to subscribe to file operation events which can be easily accessed through an `autocommand` which runs after the plugin is setup.\n\n```lua\nvim.api.nvim_create_autocmd(\"User\", {\n  pattern = \"NvimTreeSetup\",\n  desc = \"Subscribe file operation events to AstroLSP file operations\",\n  callback = function()\n    local events = require(\"nvim-tree.api\").events\n    events.subscribe(\n      events.Event.WillCreateFile,\n      function(args) require(\"astrolsp.file_operations\").willCreateFiles(args.fname) end\n    )\n    events.subscribe(\n      events.Event.FileCreated,\n      function(args) require(\"astrolsp.file_operations\").didCreateFiles(args.fname) end\n    )\n    events.subscribe(\n      events.Event.WillRemoveFile,\n      function(args) require(\"astrolsp.file_operations\").willDeleteFiles(args.fname) end\n    )\n    events.subscribe(\n      events.Event.FileRemoved,\n      function(args) require(\"astrolsp.file_operations\").didDeleteFiles(args.fname) end\n    )\n    events.subscribe(\n      events.Event.WillRenameNode,\n      function(args) require(\"astrolsp.file_operations\").willRenameFiles { from = args.old_name, to = args.new_name } end\n    )\n    events.subscribe(\n      events.Event.NodeRenamed,\n      function(args) require(\"astrolsp.file_operations\").didRenameFiles { from = args.old_name, to = args.new_name } end\n    )\n  end,\n})\n```\n\n#### [triptych.nvim](https://github.com/simonmclean/triptych.nvim)\n\n`triptych.nvim` provides `autocommand` events which can be used to trigger functionality.\n\n```lua\nvim.api.nvim_create_autocmd(\"User\", {\n  pattern = \"TriptychWillCreateNode\",\n  desc = \"trigger `workspace/willCreateFiles` before creating files\",\n  callback = function(args) require(\"astrolsp.file_operations\").willCreateFiles(args.data.path) end,\n})\nvim.api.nvim_create_autocmd(\"User\", {\n  pattern = \"TriptychDidCreateNode\",\n  desc = \"trigger `workspace/didCreateFiles` after creating files\",\n  callback = function(args) require(\"astrolsp.file_operations\").didCreateFiles(args.data.path) end,\n})\nvim.api.nvim_create_autocmd(\"User\", {\n  pattern = \"TriptychWillDeleteNode\",\n  desc = \"trigger `workspace/willDeleteFiles` before deleting files\",\n  callback = function(args) require(\"astrolsp.file_operations\").willDeleteFiles(args.data.path) end,\n})\nvim.api.nvim_create_autocmd(\"User\", {\n  pattern = \"TriptychDidDeleteNode\",\n  desc = \"trigger `workspace/didDeleteFiles` after deleting files\",\n  callback = function(args) require(\"astrolsp.file_operations\").didDeleteFiles(args.data.path) end,\n})\nvim.api.nvim_create_autocmd(\"User\", {\n  pattern = \"TriptychWillMoveNode\",\n  desc = \"trigger `workspace/willRenameFiles` before moving files\",\n  callback = function(args)\n    require(\"astrolsp.file_operations\").willRenameFiles { from = args.data.from_path, to = args.data.to_path }\n  end,\n})\nvim.api.nvim_create_autocmd(\"User\", {\n  pattern = \"TriptychDidMoveNode\",\n  desc = \"trigger `workspace/didRenameFiles` after moving files\",\n  callback = function(args)\n    require(\"astrolsp.file_operations\").didRenameFiles { from = args.data.from_path, to = args.data.to_path }\n  end,\n})\n```\n\n## 📦 API\n\n**AstroLSP** provides a Lua API with utility functions. This can be viewed with `:h astrolsp` or in the repository at [doc/api.md](doc/api.md)\n\n## 🚀 Contributing\n\nIf you plan to contribute, please check the [contribution guidelines](https://github.com/AstroNvim/.github/blob/main/CONTRIBUTING.md) first.\n\n[lazy]: https://github.com/folke/lazy.nvim\n[lspconfig]: https://github.com/neovim/nvim-lspconfig\n[mason]: https://github.com/williamboman/mason.nvim\n[mason-lspconfig]: https://github.com/williamboman/mason-lspconfig.nvim\n[none-ls]: https://github.com/nvimtools/none-ls.nvim\n","funding_links":[],"categories":["Lua"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAstroNvim%2Fastrolsp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAstroNvim%2Fastrolsp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAstroNvim%2Fastrolsp/lists"}