Skip to content

Navigating with LSP

Go to a definition, read a signature, and come back — inside the diff.

You read code that you did not write. The question “what is this function” comes up on almost every line. stage answers it in the pane you are already reading, with a language server.

From an import in one file to its definition in another, and back.

Press 0 to focus the main pane. Then press w to move the cursor to the next identifier. Press W to move it back to the previous identifier.

The cursor moves between identifiers, not between characters. This works in read views only. In the staging editor, w shows a notice instead.

Keys Action
g Go to the definition
r Find the references
s Jump to a symbol by name
K Show the signature
shift+tab Go back
tab Go forward again

g opens the file that holds the definition. shift+tab returns you to the line you came from. stage keeps a stack of these positions, so you can jump several times and walk back through all of them.

The signature from K appears under the diff, above the footer.

stage looks for these language servers on your PATH:

Language Server Other server
TypeScript, JavaScript tsgo typescript-language-server
Deno deno
Python ty pyright-langserver
Rust rust-analyzer
Go gopls
C, C++ clangd
Zig zls
Lua lua-language-server
Bash bash-language-server
Ruby ruby-lsp
Swift sourcekit-lsp
PHP intelephense
Svelte svelteserver
Dart dart
Terraform terraform-ls
Gleam gleam

A language with no server gives no navigation. Nothing else changes, and stage starts normally.

tsgo is the TypeScript 7 compiler. ty is the Python type checker from Astral. Both start faster than the server beside them.

Neither one arrives with an editor or a package install. You get them because you asked for them. For this reason stage uses them first when they are on your PATH.

stage uses the other server in these conditions:

  • The first server is not on your PATH.
  • The first server is off in the configuration.
  • The first server failed earlier in this session.

To keep the conventional server, turn the first one off:

{ "lsp": { "tsgo": false } }

The files in a repository do not change this order. A repository with a ty.toml file still uses ty only when ty is on your PATH.

If no server for the language is on your PATH, the notice names all of them.

A repository with a deno.json file always uses deno. stage does not use another server for that repository.

If deno is not on your PATH, stage shows a notice and stops. typescript-language-server reads a Deno project incorrectly, and a wrong answer is worse than no answer.

If a language server stops during a session, stage does not start it again. For a language with two servers, stage uses the other one. For every other language, g shows a notice.

Open the repository again to clear this state.

Two servers run code from the repository to answer a query: rust-analyzer and sourcekit-lsp. A build script is code, and these servers run it.

CAUTION: Do not trust a repository that you did not read. The language server runs the build scripts of that repository on your machine.

stage asks before it starts one of these two servers. stage remembers the answer for that repository, so the prompt appears one time. The answer goes to <cache>/stage/trust/, where <cache> is XDG_CACHE_HOME or ~/.cache.

The other sixteen servers do not run repository code. They start without a prompt.

Method Effect
Code navigation, in the settings Options section Turns the feature off
codeNav: false in the configuration Turns the feature off
lsp: false in the configuration Turns the feature off, and keeps your server map
STAGE_NO_LSP=1 Turns the feature off for one run

You can also turn off one server, or give a server a different command. Read Configuration for the lsp section.