Code Navigation

When you’re reading code in MarkNode, you can jump from a function call, a type name, or any other reference straight to the place it’s defined — in the same file or a different one — without opening a separate IDE. MarkNode also remembers where you’ve been, so you can retrace your steps.

Jumping to a Definition

Hold the modifier key — Cmd on macOS or Ctrl on Windows and Linux — and hover over a name in a code file. If MarkNode knows exactly where that name is defined, the name underlines and your cursor becomes a pointer. Click while still holding the modifier, and the editor takes you straight there: opening the file first if the definition lives somewhere else, and placing your cursor on the definition itself.

If a name is defined in the same file, the jump moves your cursor without opening a new tab. If it’s defined elsewhere in your project, MarkNode opens that file for you.

Supported Languages

Code navigation works in:

  • Rust
  • JavaScript (including JSX)
  • TypeScript (including TSX)
  • Python
  • Go
  • Java
  • C
  • C++

Configuration and data formats — HTML, CSS, JSON, YAML, TOML, and XML — don’t have a meaningful notion of “definition,” so code navigation doesn’t apply to them. You can still open and edit these files normally; they just won’t underline on modifier-hover.

When MarkNode Won’t Offer a Jump

A few situations where you won’t see the underline:

  • A name that could mean more than one thing — for example, a method called save that exists on several unrelated types. MarkNode has no reliable way to tell which one you mean, so rather than guess and risk landing on the wrong one, it offers no jump at all.
  • A local variable — MarkNode’s own analysis works by matching names across your whole project rather than tracking each variable’s local scope, so it generally won’t offer a jump to a local variable.
  • A name from a dependency — if a name comes from a package or library you installed rather than code inside your own project, MarkNode doesn’t look inside your dependencies, so it can’t resolve it.
  • Comments, strings, and punctuation — these were never meant to be jumped to in the first place.

In every one of these cases, a modifier-click simply places your cursor where you clicked, exactly like an ordinary click would.

Going Back and Forward

Every jump is remembered, so you can retrace your steps the way you would with a web browser’s back and forward buttons:

  • Back: Cmd+[ on macOS, Ctrl+Alt+Left on Windows and Linux
  • Forward: Cmd+] on macOS, Ctrl+Alt+Right on Windows and Linux

Both are also available from the Go menu in the menu bar. Going back returns you to exactly where your cursor was before the jump, opening the file again first if you’ve since switched away from it. Going forward is only available right after going back — jumping somewhere new clears the forward history, the same way it does in a browser.

More Accurate Results with a Language Server

MarkNode’s own code navigation works entirely offline and needs no setup — it’s ready as soon as you open a project. If you also have a language server installed for a language, MarkNode finds it and uses it automatically to sharpen its answers, for example resolving a method call through the type of the object it’s called on, which MarkNode’s own analysis can’t always do on its own.

What MarkNode Looks For

LanguageProgram MarkNode looks for
Rustrust-analyzer
JavaScript and TypeScripttypescript-language-server
Pythonpyright-langserver, then pylsp
Gogopls
C and C++clangd
JavaNone

For Python, MarkNode uses Pyright when it’s installed and the Python LSP Server otherwise.

Java has no supported language server, so Java files always use MarkNode’s own analysis, whatever you have installed.

Installing a Language Server

You install a language server yourself, outside MarkNode, the same way you would for any other editor. Run the command for your language in a terminal:

  • Rust: rustup component add rust-analyzer
  • JavaScript and TypeScript: npm install -g typescript-language-server typescript@6. The language server needs TypeScript 6 or earlier: TypeScript 7 no longer includes the part it runs, so with it the language server can’t start.
  • Python: npm install -g pyright, or pipx install python-lsp-server
  • Go: go install golang.org/x/tools/gopls@latest
  • C and C++:
    • macOS: clangd comes with the Xcode Command Line Tools (xcode-select --install). You can also run brew install llvm — Homebrew doesn’t add LLVM to your PATH, but MarkNode still finds its clangd.
    • Linux: install your distribution’s clangd package, for example sudo apt install clangd.
    • Windows: run the LLVM installer from llvm.org and let it add LLVM to your PATH.

Checking What MarkNode Found

Open Settings, go to the Editor page, and look at the Code Navigation section. It lists every supported language with what code navigation is using for it:

  • MarkNode’s own analysis — no language server was found. The row names the program MarkNode looks for, so you know what to install.
  • Found — the language server is installed, and the row shows where.
  • Running — MarkNode is using the language server. A language server only starts the first time you use go to definition in that language in the open project, so until then its row shows Found.
  • Found, but failed to start — the program is there, but it didn’t start. With Rust, this usually means rustup is installed without its rust-analyzer component; run rustup component add rust-analyzer, then Check again.
  • Stopped after repeated failures — the language server kept failing, so MarkNode stopped it and went back to its own analysis.

When no project is open, the section only shows whether MarkNode can find each language server.

You can also check from a terminal, independently of MarkNode. Run which gopls on macOS or Linux, or where gopls on Windows, using the program name for your language. If it prints a path, the program is installed and your terminal can find it.

Check Again

Right after installing a language server, click Check again in the Code Navigation section. MarkNode looks for language servers again, without restarting. A language server that’s already running keeps running, and one that failed to start or was stopped after repeated failures gets a fresh try.