Skip to main content

Language Servers

Server definitions describe which files a server handles, how to launch or connect to it, and which settings to send. They are separate from plugin preferences.

Presets​

Require plugins.lsp.config in your user module and call a preset's setup(). Options passed to setup override the preset.

PresetDefault executable
sumneko_lualua-language-server
clangdclangd --background-index
goplsgopls
pyrightpyright-langserver --stdio
basedpyrightbasedpyright-langserver --stdio
rust_analyzerrust-analyzer
tsservertypescript-language-server --stdio

This is a selection of the presets in the plugin's config.lua, not a list of installed programs. Preset availability does not guarantee that a server has been tested on your platform.

local lspconfig = require "plugins.lsp.config"
lspconfig.sumneko_lua.setup {
command = { "/usr/bin/lua-language-server" },
settings = {
Lua = {
diagnostics = { enable = true }
}
}
}

get_options() returns a preset's defaults. on_setup(options) can adjust merged options before registration. Registration is keyed by server name. Change definitions at startup and restart the server to use a new command or initialization options.

Custom Servers​

Use lsp.add_server() when there is no suitable preset:

local lsp = require "plugins.lsp"
lsp.add_server {
name = "my-language-server",
language = "mylanguage",
file_patterns = { "%.my$" },
command = { "/path/to/my-language-server", "--stdio" },
settings = {},
init_options = {},
verbose = false
}

file_patterns are Lua patterns, not shell globs. Escape a literal period with %. and use $ to match the end of a filename. Arguments are separate array elements; an executable path containing spaces still belongs in one element.

OptionPurpose
nameRegistration name, required and unique for each definition.
languageProtocol language ID, or ordered { id, pattern } records for multiple languages.
file_patternsRequired array of filename patterns that activate this definition.
commandExecutable and arguments; required for the default stdio transport.
settingsServer configuration, merged with user/workspace LSP settings.
init_optionsServer-specific initialization options.
envEnvironment variables for the launched process.
quit_timeoutIdle shutdown timeout in seconds for this server.
windows_skip_cmdSkip the Windows shell wrapper when appropriate for your command.
custom_capabilitiesMerge additional client capabilities; use only for features the client can handle.
on_start(server)Callback when the server starts.
requests_per_secondRequest processing limit; default 16.
incremental_changesForce incremental synchronization for a server that supports it but does not advertise it.
verboseEnable per-server protocol logging.

An empty language-match table or a match table with no matching pattern falls back to the file extension for the protocol language ID.

Workspace Settings​

The plugin reads .pragtical_lsp.lua or .pragtical_lsp.json from the user directory and server workspace. It merges settings in this order:

  1. User-directory LSP settings.
  2. The server definition's settings.
  3. Workspace LSP settings.

Later values override earlier values. In each directory the Lua file takes precedence over JSON. A Lua file must return a table; JSON contains the same server-specific settings object. For example, .pragtical_lsp.json for Lua:

{
"Lua": {
"diagnostics": {
"globals": ["SCALE"]
}
}
}

These are language-server settings, not config.plugins.lsp preferences. The Lua variant is executed by the plugin. Use JSON when you only need data. Settings lookups are cached for five seconds; restart the server after changing configuration if it has not picked up the new values.

TCP Connections​

Stdio is the default. TCP requires Pragtical's networking API, a host, and a port. To connect a preset to an already-running TCP server:

local lspconfig = require "plugins.lsp.config"
lspconfig.clangd.setup {
transport = "tcp",
host = "127.0.0.1",
port = 7658,
command = false
}

command = false clears the preset's stdio command. The endpoint must already speak LSP over TCP; ordinary clangd uses stdio, so this example needs a suitable bridge. The plugin does not create that bridge implicitly.

You can also supply a command that starts a TCP server or helper. In that case the transport owns both the socket and launched process and stops them together. With no command it only owns the connection, not the external server.

Multiple Projects and Servers​

The plugin can register multiple definitions and match more than one server to a file, but feature requests do not combine every server's results. Several commands stop at the first applicable server. Running-server entries are keyed by name, and live workspace-folder updates are not implemented. Restart servers when changing project roots rather than assuming independent per-project instances of the same definition.