LSP implementation for fish/fish-shell
npm install fish-lspIntroducing the fish-lsp, a Language Server Protocol (LSP) implementation for the fish shell language.
Please choose a method to install the language server and configure a client to use fish-lsp in your editor.
A detailed explanation of how a language server connection works is described on the following wiki page.
- 🦈 __Efficiency__: enhances the shell scripting experience with an extensive suite of intelligent text-editing features
- 🐡 __Flexibility__: allows for a highly customizable configuration
- 🐚 __Guidance__: friendly hints and documentation to comfortably explore command line tooling
- 🐬 __Community__: improved by a vibrant user base, with supportive and insightful feedback
- 🐙 __Compatibility__: integrates with a wide variety of tooling and language clients
- 🌊 __Reliability__: produces an editor agnostic developer environment,
ensuring __all__ fish user's have access to a consistent set of features
| Feature | Description | Status |
| --- | --- | --- |
| __Completion__ | Provides completions for commands, variables, and functions | ✅ |
| __Hover__ | Shows documentation for commands, variables, and functions. Has special handlers for --flag, commands, functions, and variables | ✅ |
| __Signature Help__ | Shows the signature of a command or function | ✅ |
| __Goto Definition__ | Jumps to the definition of a command, variable, function or --flag | ✅ |
| __Goto Implementation__ | Jumps between symbol definitions and completion definitions | ✅ |
| __Find References__ | Shows all references to a command, variable, function, or --flag | ✅ |
| __Rename__ | Rename within _matching_ __global__ && __local__ scope | ✅ |
| __Document Symbols__ | Shows all commands, variables, and functions in a document | ✅ |
| __Workspace Symbols__ | Shows all commands, variables, and functions in a workspace | ✅ |
| __Document Formatting__ | Formats a document, _full_ & _selection_ | ✅ |
| __On Type Formatting__ | Formats a document while typing | ✅ |
| __Document Highlight__ | Highlights all references to a command, variable, or function. | ✅ |
| __Command Execution__ | Executes a server command from the client | ✅ |
| __Code Action__ | Automate code generation | ✅ |
| __Quick fix__ | Auto fix lint issues | ✅ |
| __Inlay Hint__ | Shows Virtual Text/Inlay Hints | ✅ |
| __Code Lens__ | Shows all available code lenses | ✖ |
| __Logger__ | Logs all server activity | ✅ |
| __Diagnostic__ | Shows all diagnostics | ✅ |
| __Folding Range__ | Toggle ranges to fold text | ✅ |
| __Selection Range__ | Expand ranges when selecting text | ✅ |
| __Semantic Tokens__ | Server provides extra syntax highlighting | ✅ |
| __CLI Interactivity__ | Provides a CLI for server interaction.
Built by fish-lsp complete | ✅ |
| __Client Tree__ | Shows the defined scope as a Tree | ✅ |
| __Indexing__ | Indexes all commands, variables, functions, and source files | ✅ |
Some language clients might support downloading the fish-lsp directly from within the client, but for the most part, you'll typically be required to install the language server manually.
Below are a few methods to install the language server, and how to verify that it's working.
Stability across package managers can vary. Consider using another installation method if issues arise.
``bash
npm install -g fish-lsp
yarn global add fish-lsp
pnpm install -g fish-lsp
nix-shell -p fish-lsp
brew install fish-lsp
conda install fish-lsp
mamba install fish-lsp
`
You can install the completions by running the following command:
`fish`
fish-lsp complete > ~/.config/fish/completions/fish-lsp.fish
Install the standalone binary directly from GitHub releases (no dependencies required):
`bashDownload the latest standalone binary
curl -L https://github.com/ndonfris/fish-lsp/releases/latest/download/fish-lsp.standalone \
-o ~/.local/bin/fish-lsp
> __Note:__
> Ensure
~/.local/bin is in your $PATH.$3
Recommended Dependencies:
yarn@1.22.22 node@22.14.0 fish@4.0.8`bash
git clone https://github.com/ndonfris/fish-lsp
cd fish-lsp/yarn install
yarn build # links
./dist/fish-lsp to yarn global bin $PATH
`Building the project from source is the most portable method for installing the language server.
$3
After installation, verify that
fish-lsp is working correctly:`bash
fish-lsp --help
`Setup
To properly configure fish-lsp, you need to define a client configuration after installing the language server.
Configuring a client should be relatively straightforward. Typically, you're only required to translate the shell command
fish-lsp start for fish files, in the client's configuration. However, further configuration can be specified as a server configuration.Some clients may also allow specifying the server configuration directly in the client configuration.
$3
Theoretically, the language-server should generally be compatible with almost any text-editor or IDE you prefer using. Feel free to setup the project in any fish-lsp-client of your choice, or submit a PR for new configurations.
Full table of options available in the neovim documentation
`lua
vim.api.nvim_create_autocmd('FileType', {
pattern = 'fish',
callback = function()
vim.lsp.start({
name = 'fish-lsp',
cmd = { 'fish-lsp', 'start' },
})
end,
})
` Alternatively, you can also see official documentation for nvim-lspconfig, or use your client of choice below.
> There is also a useful configuration for testing out the language server in
nvim@v0.11.1 included in the fish-lsp-language-clients repository.
Install the
fish-lsp using mason.nvim
`vimscript
:MasonInstall fish-lsp
`
Neovim client using coc.nvim configuration, located inside coc-settings.json
"languageserver" key
`json
{
"fish-lsp": {
"command": "fish-lsp",
"filetypes": ["fish"],
"args": ["start"]
}
}
`
YouCompleteMe configuration for vim/neovim
`vim
let g:ycm_language_server =
\ [
\ {
\ 'name': 'fish',
\ 'cmdline': [ 'fish-lsp', 'start' ],
\ 'filetypes': [ 'fish' ],
\ }
\ ]
`
Configuration of prabirshrestha/vim-lsp in your
init.vim or init.lua file
`vim
if executable('fish-lsp')
au User lsp_setup call lsp#register_server({
\ 'name': 'fish-lsp',
\ 'cmd': {server_info->['fish-lsp', 'start']},
\ 'allowlist': ['fish'],
\ })
endif
`
In config file
~/.config/helix/languages.toml
`toml
[[language]]
name = "fish"
language-servers = [ "fish-lsp" ]
[language-server.fish-lsp]
command = "fish-lsp"
args= ["start"]
environment = { "fish_lsp_show_client_popups" = "false" }
`
Configuration for kakoune-lsp, located in
~/.config/kak-lsp/kak-lsp.toml
`toml
[language.fish]
filetypes = ["fish"]
command = "fish-lsp"
args = ["start"]
` Or in your
~/.config/kak/lsp.kak file
`kak
hook -group lsp-filetype-fish global BufSetOption filetype=fish %{
set-option buffer lsp_servers %{
[fish-lsp]
root_globs = [ "*.fish", "config.fish", ".git", ".hg" ]
args = [ "start" ]
}
}
`
Configuration for kate
`json
{
"servers": {
"fish": {
"command": ["fish-lsp", "start"],
"url": "https://github.com/ndonfris/fish-lsp",
"highlightingModeRegex": "^fish$"
}
}
}
`
Configuration using eglot (Built into Emacs 29+)
`elisp
;; Add to your init.el or .emacs
(require 'eglot) (add-to-list 'eglot-server-programs
'(fish-mode . ("fish-lsp" "start")))
;; Optional: auto-start eglot for fish files
(add-hook 'fish-mode-hook 'eglot-ensure)
` or place in your
languages/fish.el file
`elisp
(use-package fish-mode) (with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(fish-mode . ("fish-lsp" "start"))))
`
Configuration using lsp-mode
`elisp
;; Add to your init.el or .emacs
(require 'lsp-mode) (lsp-register-client
(make-lsp-client
:new-connection (lsp-stdio-connection '("fish-lsp" "start"))
:activation-fn (lsp-activate-on "fish")
:server-id 'fish-lsp))
;; Optional: auto-start lsp for fish files
(add-hook 'fish-mode-hook #'lsp)
` Full example configuration using doom-emacs can be found in the fish-lsp language clients repo.
VSCode (Source Code Repo)
> To download the extension, visit the fish-lsp extension on the VSCode Marketplace.
>
> VSCode configuration does not require a client configuration. The server will automatically start when a
.fish file is opened.
>
> A server configuration can still be specified to control the server's behavior. (see below)
> To install the fish-lsp in BBEdit, please follow the instructions in the repository fish-lsp-language-clients.
>
> This configuration includes a Fish.plist file that provides syntax highlighting and other features for the fish shell.
$3
Specific functionality for the server can be set independently from the client. The server allows for both environment variables and command flags to customize how specific server processes are started.
#### Environment variables
Environment variables provide a way to globally configure the server across all sessions, but can be overridden interactively[\[1\]](https://fishshell.com/docs/current/language.html#variable-scope) by the current shell session as well. They can easily be auto-generated[\[1\]](#environment-variables-default)[\[2\]](#environment-variables-template)[\[3\]](#environment-variables-json)[\[4\]](#environment-variables-confd) for multiple different use cases using the
fish-lsp env command.You can store them directly in your
config.fish to be autoloaded for every fish session. Or if you prefer a more modular approach, checkout the --confd flag which will structure the autoloaded environment variables to only be sourced when the fish-lsp command exists.
`fish
$fish_lsp_enabled_handlers
Enables the fish-lsp handlers. By default, all stable handlers are enabled.
(Options: 'complete', 'hover', 'rename', 'definition', 'implementation',
'reference', 'logger', 'formatting', 'formatRange',
'typeFormatting', 'codeAction', 'codeLens', 'folding',
'selectionRange', 'signature', 'executeCommand', 'inlayHint',
'highlight', 'diagnostic', 'popups', 'semanticTokens')
(Default: [])
set -gx fish_lsp_enabled_handlers $fish_lsp_disabled_handlers
Disables the fish-lsp handlers. By default, non-stable handlers are disabled.
(Options: 'complete', 'hover', 'rename', 'definition', 'implementation',
'reference', 'logger', 'formatting', 'formatRange',
'typeFormatting', 'codeAction', 'codeLens', 'folding',
'selectionRange', 'signature', 'executeCommand', 'inlayHint',
'highlight', 'diagnostic', 'popups', 'semanticTokens')
(Default: [])
set -gx fish_lsp_disabled_handlers $fish_lsp_commit_characters
Array of the completion expansion characters.
Single letter values only.
Commit characters are used to select completion items, as shortcuts.
(Example Options: '.', ',', ';', ':', '(', ')', '[', ']', '{', '}', '<',
'>', ''', '"', '=', '+', '-', '/', '\', '|', '&', '%',
'$', '#', '@', '!', '?', '*', '^', '
', '~', '\t', ' ')$__fish_config_dir before $__fish_data_dir).0 means unlimited diagnostics.fish_lsp_disabled_handlersfish --no-execute.3002 includes/excludes conditionally chained commands to explicitly check existence.command -q ls && command ls || echo 'no ls'command ls || echo 'no ls'2004 which warns the user when they are using a recognized external command that can be replaced by an equivalent fish builtin command.alias, export, etc... are used instead of their equivalent fish builtin commands.2002 is shown when this setting is false, and hidden when true.4008 when an autoloaded function definition does not have a description function -d/--description '...'; end;FishServer.initialize(connection, InitializeParams.initializationOptions), NOT as an environment variable
`fish
$fish_lsp_enabled_handlers
Enables the fish-lsp handlers. By default, all stable handlers are enabled.
(Options: 'complete', 'hover', 'rename', 'definition', 'implementation',
'reference', 'logger', 'formatting', 'formatRange',
'typeFormatting', 'codeAction', 'codeLens', 'folding',
'selectionRange', 'signature', 'executeCommand', 'inlayHint',
'highlight', 'diagnostic', 'popups', 'semanticTokens')
(Default: [])
set -gx fish_lsp_enabled_handlers $fish_lsp_disabled_handlers
Disables the fish-lsp handlers. By default, non-stable handlers are disabled.
(Options: 'complete', 'hover', 'rename', 'definition', 'implementation',
'reference', 'logger', 'formatting', 'formatRange',
'typeFormatting', 'codeAction', 'codeLens', 'folding',
'selectionRange', 'signature', 'executeCommand', 'inlayHint',
'highlight', 'diagnostic', 'popups', 'semanticTokens')
(Default: [])
set -gx fish_lsp_disabled_handlers $fish_lsp_commit_characters
Array of the completion expansion characters.
Single letter values only.
Commit characters are used to select completion items, as shortcuts.
(Example Options: '.', ',', ';', ':', '(', ')', '[', ']', '{', '}', '<',
'>', ''', '"', '=', '+', '-', '/', '\', '|', '&', '%',
'$', '#', '@', '!', '?', '*', '^', '
', '~', '\t', ' ')$__fish_config_dir before $__fish_data_dir).0 means unlimited diagnostics.fish_lsp_disabled_handlersfish --no-execute.3002 includes/excludes conditionally chained commands to explicitly check existence.command -q ls && command ls || echo 'no ls'command ls || echo 'no ls'2004 which warns the user when they are using a recognized external command that can be replaced by an equivalent fish builtin command.alias, export, etc... are used instead of their equivalent fish builtin commands.2002 is shown when this setting is false, and hidden when true.4008 when an autoloaded function definition does not have a description function -d/--description '...'; end;FishServer.initialize(connection, InitializeParams.initializationOptions), NOT as an environment variable
`json
{
"fish_lsp_enabled_handlers": [],
"fish_lsp_disabled_handlers": [],
"fish_lsp_commit_characters": [
"\t",
";",
" "
],
"fish_lsp_log_file": "",
"fish_lsp_log_level": "",
"fish_lsp_all_indexed_paths": [
"$__fish_config_dir",
"$__fish_data_dir"
],
"fish_lsp_modifiable_paths": [
"$__fish_config_dir"
],
"fish_lsp_diagnostic_disable_error_codes": [],
"fish_lsp_max_diagnostics": 0,
"fish_lsp_enable_experimental_diagnostics": false,
"fish_lsp_strict_conditional_command_warnings": false,
"fish_lsp_prefer_builtin_fish_commands": false,
"fish_lsp_allow_fish_wrapper_functions": true,
"fish_lsp_require_autoloaded_functions_to_have_description": true,
"fish_lsp_max_background_files": 10000,
"fish_lsp_show_client_popups": true,
"fish_lsp_single_workspace_support": false,
"fish_lsp_ignore_paths": [
"/.git/",
"/node_modules/",
"/containerized/",
"/docker/"
],
"fish_lsp_max_workspace_depth": 3,
"fish_lsp_fish_path": "fish"
}
`
###### :jigsaw: Writing current values to ~/.config/fish/conf.d/fish-lsp.fish
`fish
clear the current fish-lsp configuration
>_ fish-lsp env --names-only | string split \n | read -e $name;
grab only specific variables
fish-lsp env --show-default --only fish_lsp_all_indexed_paths fish_lsp_diagnostic_disable_error_codes | sourceWrite the current fish-lsp configuration to ~/.config/fish/conf.d/fish-lsp.fish
fish-lsp env --show --confd > ~/.config/fish/conf.d/fish-lsp.fish
`
For language clients that import the source code directly and manually connect with the server (e.g., VSCode), passing the environment configuration through the
initializeParams.initializationOptions is also possible.#### Command Flags
Both the flags
--enable and --disable are provided on the fish-lsp start subcommand. __Default configuration enables all stable server handlers__.`fish
displays what handlers are enabled. Removing the dump flag will run the server.
fish-lsp start --disable complete signature --dump
`#### Further Server Configuration
Any flags will overwrite their corresponding environment variables, if both are seen for the
fish-lsp process. For this reason, it is encouraged to wrap any non-standard behavior of the fish-lsp in functions or aliases.Due to the vast possibilities this project aims to support in the fish shell, sharing useful configurations is highly encouraged.
##### Project Specific configuration via dot-env
If you are using the environment variables, or an alias to start the server from a shell instance, you can also use a
.env file to set project specific overrides.This is not directly supported by the server, but can be achieved using the variety of dotenv tools available.[\[1\]](https://github.com/berk-karaal/loadenv.fish)[\[2\]](https://direnv.net)[\[3\]](https://github.com/jdx/mise)[\[4\]](https://github.com/hyperupcall/autoenv)
##### Configuration via Disable Comments
Single document configurations can be set using fish-shell comments to disable diagnostics or formatting from applying to specific lines or sections of a file. These comments are parsed by the server when a file is opened, and can be placed anywhere in the file.
If you're interested in disabling specific diagnostic messages, the wiki includes a table of error codes that should be helpful. Diagnostics are a newer feature so PRs are welcome to improve their support.
Any diagnostic can be disabled by providing its error code to the environment variable
fish_lsp_diagnostic_disable_error_codes (see the template above for an example).
Trouble Shooting
If you encounter any issues with the server, the following commands may be useful to help diagnose the problem:
- Show every available sub-command and flag for the
fish-lsp
`fish
fish-lsp --help-all
`fish-lsp command is available in your system's $PATH by running which fish-lsp or fish-lsp info --bin.
`fish
fish-lsp info
`- Confirm that the language server is able to startup correctly by indexing the
$fish_lsp_all_indexed_paths directories.
`fish
fish-lsp info --time-startup
` > Note:
> There is also,
fish-lsp info --time-only which will show a less verbose summary of the startup timings. To limit either of these flags to a specific folder, use --use-workspace ~/path/to/fish.- Check the health of the server.
`fish
fish-lsp info --check-health
`- Check the server logs, while a server is running.
`fish
set -gx fish_lsp_log_file /tmp/fish_lsp.log
tail -f (fish-lsp info --log-file)
# open the server somewhere else
`- Enable source maps to debug the bundled server code.
`fish
set -gx NODE_OPTIONS '--enable-source-maps --inspect'
$EDITOR ~/.config/fish/config.fish
`- Show the tree-sitter parse tree for a specific file:
`fish
fish-lsp info --dump-parse-tree path/to/file.fish
``##### Abbreviations to shorten the amount of characters typed for many of the above commands are available on the wiki
- Contributing - documentation describing how to contribute to the fish-lsp project.
- Roadmap - goals for future project releases.
- Wiki - further documentation and knowledge relevant to the project
- Discussions - interact with maintainers
- Site - website homepage
- Client Examples - testable language client configurations
- Sources - major influences for the project
Contributions of any kind are welcome! Special thanks to anyone who contributed to the project! :pray:
nick 💻 | mimikun 💻 | Jaakko Paju 💻 | Sean Perry 💻 | Fabio Coatti 💻 | Peter Cardenas 💻 | Peter Tri Ho 💻 |
bnwa 💻 | Branch Vincent 💻 | Jaeseok Lee 💻 | ClanEver 💻 | Nathan DeGruchy 💻 | Nan Huang 💻 | Sola 💻 |
Jose Alvarez 💻 |
This project follows the all-contributors specification.