Zum Inhalt

LSP-Plugin (Language Server)

Code-Intelligenz auf Basis des Language Server Protocol — Fehler-Unterschlängelungen, Navigation, Hover, Vervollständigung, Signaturhilfe, Formatierung, Verweise suchen, Umbenennen und Gehe-zu-Symbol — für jede Sprache mit einem Language Server. Der Editor spricht über LSP mit dem Server; das Plugin ist der Client. Welche Server es gibt, ist datengetrieben (ein kleines JSON pro Sprache) — C++/clangd unten ist nur eine von mehreren mitgelieferten Definitionen.

Der Editor bündelt oder lädt keine Server

Ein Language Server ist ein separates Programm, das Sie einmal installieren. MTE erkennt einen installierten Server und richtet ihn auf Ihr Projekt; es liefert nie einen mit. Siehe Einen Language Server beschaffen.

Aktuelle Funktionen

Funktion Wie
Diagnosen Fehler/Warnungen des Servers erscheinen als Wellenlinien (rot = Fehler, bernstein = Warnung, blau = Info, grau = Hinweis), aktualisiert beim Tippen.
Gehe zu Definition Cursor auf ein Symbol und F12, oder Suchen ▸ Code-Navigation ▸ Gehe zu Definition. Springt zur Definition und öffnet bei Bedarf eine andere Datei.
Verweise suchen Cursor auf ein Symbol → Shift+F12 (oder Suchen ▸ Code-Navigation ▸ Verweise suchen). Ergebnisse öffnen sich in einem unteren Referenzen-Panel, nach Datei gruppiert mit Quellzeilen-Vorschau; Doppelklick springt.
Hover Zeiger über einem Symbol ruhen lassen; ein Popup zeigt Typ/Signatur und Dokumentation (gerendert aus dem Markdown des Servers).
Vervollständigung Ctrl+Space fragt den Server nach Vervollständigungen und mischt sie in das Vervollständigungs-Popup des Editors (vor den eingebauten Schlüsselwort-/Pufferwort-Vorschlägen), gefiltert beim Tippen.
Signaturhilfe Das Tippen von ( eines Aufrufs oder , zeigt einen Calltip mit der Funktionssignatur und dem hervorgehobenen aktiven Parameter; ) schließt ihn.
Dokument formatieren Alt+Shift+F (⌃⌥F auf macOS; oder Bearbeiten ▸ Dokument formatieren) formatiert das ganze Dokument über den Server, als ein Rückgängig-Schritt. Den Stil bestimmt die Konfiguration des Servers (bei clangd eine .clang-format-Datei).
Verweise suchen (oben gelistet) —
Symbol umbenennen Cursor auf ein Symbol → Shift+F6 (oder Bearbeiten ▸ Symbol umbenennen). Neuen Namen eingeben; jede Verwendung wird aktualisiert. Umfasst das Umbenennen mehrere Dateien, werden Sie erst um Bestätigung gebeten — jede Datei wird geöffnet, geändert und modifiziert belassen, damit Sie prüfen und speichern.
Gehe zu Symbol (in Datei) Ctrl+Shift+O öffnet die Befehlspalette mit allen Symbolen der aktuellen Datei (Funktionen, Klassen, Methoden…); tippen filtert, Enter springt. Jede Zeile zeigt Symbolart und Container.
Gehe zu Symbol im Arbeitsbereich Ctrl+T durchsucht beim Tippen Symbole im ganzen Projekt (der Server matcht die Anfrage); Enter öffnet die Datei am Symbol.

Die Gehe-zu-Symbol-Auswahlen sind die Symbolmodi der Befehlspalette — siehe Befehlspalette.

Die Befehle sind ausgegraut, bis ein Server läuft

Gehe zu Definition, Referenzen suchen, Dokument formatieren und Symbol umbenennen sind nur aktiv, wenn ein Sprachserver für die Sprache der aktuellen Datei bereit ist — und wenn dieser Server im Handshake gemeldet hat, dass er die Anfrage unterstützt. Bei einer Datei ohne konfigurierten Server sowie während ein Server startet, neu startet oder aufgegeben hat, sind die Menüeinträge ausgegraut, statt beim Klicken nichts zu tun. Die Statusanzeige unten sagt, welcher Fall vorliegt. Sprachserver neu starten wird nie ausgegraut: das ist der Ausweg aus einem Server, der aufgegeben hat.

Dateiübergreifende Referenzen und Umbenennen brauchen den Server-Index

Verweise suchen und Umbenennen erreichen andere Dateien erst, wenn der Server das Projekt indiziert hat. Für C/C++ heißt das compile_commands.json (siehe unten) und clangds Hintergrund-Index; ohne ihn arbeiten sie nur auf der aktuellen Datei.

Umbenennen ist vorerst Rückgängig pro Datei

Ein mehrdateiiges Umbenennen wird Datei für Datei angewendet, jede Datei ist also ein eigener Rückgängig-Schritt (der Bestätigungsdialog sagt das). Prüfen Sie die geänderten Tabs vor dem Speichern.

Im Kontextmenü des Editors

Klicken Sie mit der rechten Maustaste auf ein Symbol im Text, und das Menü bietet unter den Bearbeitungsbefehlen Gehe zu Definition, Verweise suchen, Symbol umbenennen und Dokument formatieren an. Jeder Eintrag erscheint nur, wenn derselbe Befehl im Hauptmenü gerade funktionieren würde — ein Language-Server für die Datei ist bereit und unterstützt ihn, und für Umbenennen und Formatieren ist das Dokument nicht schreibgeschützt. In einer reinen Textdatei, im Rand links vom Text oder während der Server startet, erscheint keiner von ihnen.

Die Einträge wirken auf das Symbol, auf das Sie geklickt haben, nicht auf das unter der Einfügemarke; Einfügemarke und Auswahl bleiben, wo sie waren. Umbenennen schlägt die Auswahl als alten Namen vor, wenn Sie in sie hinein geklickt haben, sonst das Wort unter dem Mauszeiger. Dokument formatieren formatiert immer das ganze Dokument. Ein über die Tastatur geöffnetes Menü wirkt an der Einfügemarke.

Wo die Plattform in Kontextmenüs Tastenkürzel anzeigt (Windows), zeigt jeder Eintrag sein Tastenkürzel — das gerade gültige, einschließlich Ihrer eigenen Änderungen in der Tastenkürzel-Zuordnung. Unter macOS zeigen Kontextmenüs keine Tastenkürzel.

Wie Ihre Änderungen den Server erreichen

Tippen sendet keine Nachricht pro Tastendruck. Änderungen werden für den Bruchteil einer Sekunde zusammengefasst und dann als eine geschickt — und zwar als ein einzelner geänderter Bereich statt als ganze Datei, sofern der Server sagt, dass er das kann (die meisten können es). Eine große Datei kostet damit ein paar Dutzend Byte pro Tippfolge statt einer Kopie ihrer selbst.

Alles, was den Server nach dem Text fragt — Tooltip, Gehe zu Definition, Referenzen suchen, Umbenennen, Formatieren, Vervollständigung, Signaturhilfe — schickt die ausstehende Änderung zuerst, damit sich eine Antwort nie auf eine Fassung bezieht, über die Sie längst hinaus sind. Das Speichern einer Datei ebenso.

Auch das Starten eines Servers blockiert den Editor nicht: der Prozess wird im Hintergrund gestartet, und das Statussegment zeigt …, bis die Verhandlung abgeschlossen ist. Ein Server, der beim Start hängt, kostet Sie nichts außer dieser einen Sprache.

Eine Obergrenze für gezeichnete Probleme

Pro Dokument werden höchstens 2000 Wellenlinien gezeichnet. Darüber ist die Datei ohnehin unlesbar, und jede weitere Markierung kostet den Editor echte Zeit — liefert eine Datei also mehr, werden die ersten 2000 gezeigt und die Statusleiste sagt Es werden die ersten 2000 von N Problemen in dieser Datei angezeigt, statt die Zahl stillschweigend kleiner erscheinen zu lassen. Meist ist es ein Zeichen, dass der Server die Datei falsch ansieht: eine fehlende Kompilierungsdatenbank oder eine generierte Datei, die für sich allein gar nicht übersetzbar ist.

Die Server-Statusanzeige

Die Statusleiste zeigt ein kompaktes LSP:-Segment (links der anderen Plugin-Segmente), das jeden für Ihre offenen Dateien relevanten Language Server zusammenfasst:

LSP: cpp ✓ · no compile database  python ↻2  rust ✗
Zeichen Bedeutung
… Startet — der Server wurde gestartet und verhandelt gerade.
✓ Bereit — bedient Anfragen.
↻n Neustart — der Server endete unerwartet; automatischer Neustartversuch n ist geplant.
✗ Für diese Sprache ist kein Server installiert. Installieren Sie einen (siehe unten) und wählen Sie dann Sprachserver neu starten.
⚠ Aufgegeben — der Server stürzte wiederholt ab und die automatischen Neustarts wurden eingestellt. Nur ein manueller Neustart weckt ihn wieder.

Hinter dem Zeichen kann ein kurzer Zusatz stehen — der Server läuft, und etwas an Ihrem Projekt schränkt trotzdem ein, was er beantworten kann. Es wird immer nur einer angezeigt, der schwerwiegendste zuerst:

Zusatz Bedeutung
· Server antwortet nicht Mehrere Anfragen hintereinander blieben unbeantwortet. Der Server lebt, hängt aber: Sprachserver-Protokoll anzeigen, dann Sprachserver neu starten. Der Zusatz verschwindet, sobald der Server irgendetwas beantwortet.
· keine Kompilierungsdatenbank Der C/C++-Server läuft, sieht aber nur die geöffnete Datei; siehe C/C++-Projekte brauchen compile_commands.json.
· kein Cargo.toml, · kein go.mod, · kein tsconfig.json, … Das Projekt enthält keine der Dateien, die dieser Server braucht, um es als Projekt zu verstehen. An der geöffneten Datei arbeitet er weiter; dateiübergreifende Antworten bleiben unvollständig, bis die Datei existiert. Genannt wird die Datei, an der dem Server am meisten liegt — siehe Was jeder Server vom Projekt erwartet.

Das Segment erscheint, wenn das erste Dokument einer konfigurierten Sprache öffnet, verfolgt nur Sprachen mit tatsächlich offenen Dokumenten — das Schließen der letzten Datei einer Sprache entfernt ihren Eintrag (ein erneutes Öffnen bringt ihn sofort zurück) — und verschwindet ganz, wenn kein solches Dokument mehr offen ist.

Suchen ▸ Code-Navigation ▸ Sprachserver-Protokoll anzeigen zeigt die jüngsten Ausgaben jedes laufenden Servers. Dort erklärt sich ein Server: eine fehlende Toolchain, eine unlesbare Konfigurationsdatei, ein Projekt, das er nicht laden wollte. Das Fenster ist ein normales, größenveränderbares Fenster — jede Sprache ist eine Überschrift, die den für sie laufenden Server nennt, der Text lässt sich markieren, Kopieren legt das gesamte Protokoll in die Zwischenablage, und die von Ihnen gewählte Größe wird gemerkt.

Wenn ein Server abstürzt

Ein unerwartet beendeter Language Server wird automatisch neu gestartet, mit wachsender Verzögerung (1 s, 2 s, 4 s… gedeckelt bei 30 s). Währenddessen zeigt die Anzeige ↻n, und eine Statusleisten-Benachrichtigung meldet den ersten Absturz. Nach einem erfolgreichen Neustart werden Ihre offenen Dokumente dem Server erneut gemeldet, und die Diagnosen kommen von selbst zurück; veraltete Wellenlinien des toten Servers werden sofort gelöscht. Das Bearbeiten wird nie blockiert.

Nach 5 fehlgeschlagenen Versuchen in Folge gibt das Plugin auf: Die Anzeige zeigt ⚠, eine Benachrichtigung verweist auf die Einstellungen, und die Sprache bleibt dunkel, bis Sie manuell neu starten. Ein Server, der mindestens eine Minute sauber lief, erhält bei einem späteren Absturz frische Versuche.

Manueller Neustart — eine der beiden Möglichkeiten:

  • Suchen ▸ Code-Navigation ▸ Sprachserver neu starten (kein Standard-Kürzel; auch über die Befehlspalette), oder
  • der Knopf Neu scannen / Server neu starten in Einstellungen ▸ Sprachserver.

Beide fahren alle Server herunter, wiederholen die Erkennung mit den aktuellen Einstellungen und setzen das Fehlerbudget zurück — nützlich nach der Installation eines fehlenden oder der Reparatur eines defekten Servers.

Um vor dem Neustart zu sehen, warum ein Server unzufrieden ist, verwenden Sie Suchen ▸ Code-Navigation ▸ Sprachserver-Protokoll anzeigen.

Einen Language Server beschaffen

Installieren Sie den Server für Ihre Sprache und stellen Sie sicher, dass er im PATH liegt (oder setzen Sie einen expliziten Pfad in den Einstellungen). Wird keiner gefunden, tut die Funktion für diese Sprache schlicht nichts — die Statusanzeige zeigt ✗, und das Protokoll vermerkt einen einmaligen Hinweis, aber nichts unterbricht Sie.

MTE liefert Server-Definitionen (nicht die Server) für viele Sprachen, meist genügt also die Installation des Servers — kein JSON-Editieren. Mitgelieferte Definitionen decken C/C++, Objective-C, Python, Rust, Go, TypeScript, JavaScript, C#, Java, Kotlin, Swift, HTML, CSS/SCSS/Less, JSON, YAML und Shell-Skripte ab.

Sprache Server Woher
C/C++ clangd winget install LLVM.LLVM (Windows), die Komponente „C++ Clang tools“ im Visual-Studio-Installer, brew install llvm (macOS) oder das Paket clang-tools-extra Ihrer Distribution.
Python pyright oder pylsp npm i -g pyright (benötigt Node.js) oder pip install python-lsp-server (benötigt nur Python).
TypeScript/JS typescript-language-server npm i -g typescript-language-server typescript.
Rust rust-analyzer rustup component add rust-analyzer.
Go gopls go install golang.org/x/tools/gopls@latest.
C# csharp-ls oder OmniSharp dotnet tool install -g csharp-ls (ein einzelnes dotnet-Werkzeug, wird zuerst versucht) oder ein heruntergeladenes OmniSharp-Release.
Java jdtls (Eclipse JDT Language Server) brew install jdtls (macOS) oder ein entpacktes Release, dessen bin im PATH liegt.

Prüfen Sie im Terminal, z. B. clangd --version oder where clangd / which clangd. Für eine Sprache ohne mitgelieferte Definition fügen Sie eine hinzu wie in Eine Sprache hinzufügen beschrieben.

Python: pyright oder pylsp

Python hat zwei mitgelieferte Definitionen, und OctoEdit startet die, die tatsächlich installiert ist:

  1. pyright (pyright-langserver) wird zuerst versucht. Es ist ein npm-Paket und benötigt daher Node.js: npm i -g pyright.
  2. pylsp (python-lsp-server) wird verwendet, wenn pyright nicht gefunden wird. Es ist ein pip-Paket und benötigt nur Python: pip install python-lsp-server.

Sind beide installiert, gewinnt pyright. Für Python gibt es eine einzige Zeile in den Einstellungen (ein Aktivierungsschalter, eine Pfadüberschreibung), und sie gilt für den jeweils verwendeten Server — ein expliziter Pfad auf eine pylsp-Datei startet pylsp mit dessen Startargumenten, nicht mit denen von pyright. Sprachserver-Protokoll anzeigen nennt den Server, der wirklich läuft.

Mehrere Server für eine Sprache

Das ist ein allgemeiner Mechanismus, kein Sonderfall für Python: Eine Sprache darf beliebig viele mitgelieferte Definitionen haben, geordnet über ein Feld priority, und es startet die erste, deren ausführbare Datei auf Ihrem Rechner gefunden wird. C# funktioniert genauso — erst csharp-ls, dann OmniSharp —, weil beide unterschiedliche Startargumente erwarten und nur eines davon richtig sein kann.

Java: der eigene Arbeitsbereich des Servers

jdtls startet nicht ohne ein eigenes, beschreibbares Arbeitsverzeichnis (-data). OctoEdit stellt es automatisch bereit, pro Projekt, im Datenordner des Plugins:

<user data>/plugins/org.mte.lsp/jdtls-workspaces/<project id>/

Sie müssen es nie anlegen oder benennen. Den Ordner zu löschen ist unbedenklich — jdtls baut ihn neu auf, zum Preis einer erneuten Indizierung.

Einrichtung unter Windows

Ein frisch aufgesetztes Windows hat üblicherweise keines von clangd, cmake, ninja, node oder python im PATH. Dieser Abschnitt sagt, woher jedes davon kommt und wie Sie es prüfen. Den PATH müssen Sie normalerweise nicht selbst anpassen — OctoEdit durchsucht auch die unten aufgeführten Ökosystem-Verzeichnisse.

Was Sie wollen Installation Wo es landet
clangd (C/C++) winget install LLVM.LLVM C:\Program Files\LLVM\bin\clangd.exe
cmake und ninja Die Komponente „C++ CMake tools for Windows“ im Visual-Studio-Installer …\Microsoft Visual Studio\2022\<edition>\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin und …\CMake\Ninja — nicht im PATH, aber über die Visual-Studio-Entwicklungsumgebung erreichbar (siehe unten). Ein eigenständiges winget install Kitware.CMake / winget install Ninja-build.Ninja legt sie stattdessen in den PATH.
pyright (Python) winget install OpenJS.NodeJS.LTS, dann npm i -g pyright %APPDATA%\npm\pyright-langserver.cmd
pylsp (Python, ohne Node) Python aus dem Microsoft Store oder von python.org, dann pip install python-lsp-server %LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.3.*_*\LocalCache\local-packages\Python3*\Scripts\pylsp.exe (Store) oder %APPDATA%\Python\Python3*\Scripts\pylsp.exe

Prüfen, was sichtbar ist. In einer normalen Eingabeaufforderung oder PowerShell:

where clangd
where cmake
where ninja
where pyright-langserver
where pylsp

where durchsucht nur Ihren PATH. Ein Werkzeug, das es nicht findet, kann von OctoEdit dennoch gefunden werden, denn die Suche umfasst auch die oben genannten Ökosystem-Verzeichnisse — insbesondere Pythons Skriptverzeichnisse liegen nie im PATH. Bleibt eine Sprache nach der Installation ihres Servers auf ✗, nutzen Sie Suchen ▸ Code-Navigation ▸ Sprachserver neu starten; das wiederholt die gesamte Suche.

Die Erzeugung der Kompilierdatenbank läuft in der Visual-Studio-Entwicklungsumgebung. Wenn OctoEdit CMake für Sie ausführt (siehe unten), lokalisiert es zuerst Visual Studio — über VSINSTALLDIR, sonst vswhere.exe — und kapselt den Aufruf in die VsDevCmd.bat -arch=x64 dieser Installation. Genau das stellt cl, das Windows SDK und Visual Studios eigenes cmake/ninja für diesen einen Befehl bereit, sodass der Editor sie gar nicht in Ihrem PATH braucht. Ohne Visual Studio (ein Rechner nur mit clang oder MinGW) wird der Aufruf schlicht in der eigenen Umgebung des Editors gemacht, und das Protokoll sagt das; dann brauchen Sie cmake und ninja selbst erreichbar sowie einen Compiler, den CMake erkennt.

Auf Wunsch neu erzeugen. Suchen ▸ Code-Navigation ▸ Kompilierdatenbank erzeugen… startet dieselbe Erzeugung jederzeit — auch wenn bereits eine Datenbank existiert (sie wird an Ort und Stelle neu konfiguriert) und auch wenn Sie zuvor Für dieses Projekt nicht mehr fragen gewählt haben. Der Eintrag ist immer verfügbar — kann er nichts erzeugen, sagt er in der Statuszeile warum (kein C/C++-Dokument, kein Projektordner, keine CMakeLists.txt in der Projektwurzel, kein cmake, oder kein Generator, der hier exportieren kann), statt aus einem für Sie unsichtbaren Grund ausgegraut zu sein.

Wo die „nicht mehr fragen“-Antwort gespeichert wird. Für dieses Projekt nicht mehr fragen wird pro Projektwurzel in %APPDATA%\7-bits\OctoEdit.ini unter plugins/org.mte.lsp/noCompileDbPrompt/<hash> abgelegt (der Projektpfad wird gehasht, weil ein Pfad kein zulässiger Einstellungsschlüssel ist). Kompilierdatenbank erzeugen… löscht ihn für dieses Projekt.

Wo OctoEdit nach einem Server sucht

Sie sollten nichts konfigurieren müssen. Nach der Installation eines Servers genügt es, einen Ordner und eine Quelldatei zu öffnen. Der Editor versucht der Reihe nach:

  1. einen expliziten Pfad aus den Einstellungen — maßgeblich: Führt er ins Leere, bleibt die Sprache dunkel, statt still auf etwas anderes auszuweichen;
  2. Ihren PATH, für den Befehl des Servers und jeden bekannten Alias (clangd-20, clangd-19, …);
  3. die Installationsorte aus der Server-Definition für Ihr Betriebssystem;
  4. eine eingebaute Liste von Ökosystem-Verzeichnissen.
Durchsuchte Ökosystem-Verzeichnisse
Windows das globale npm-Präfix und %APPDATA%\npm, %LOCALAPPDATA%\Microsoft\WinGet\Links, %USERPROFILE%\.cargo\bin, %USERPROFILE%\go\bin und %LOCALAPPDATA%\go\bin, %USERPROFILE%\.dotnet\tools, %ProgramFiles%\LLVM\bin, %ProgramFiles%\nodejs sowie Pythons benutzereigene Skriptverzeichnisse: %APPDATA%\Python\Python3*\Scripts, %LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.3.*_*\LocalCache\local-packages\Python3*\Scripts (Python aus dem Microsoft Store) und %LOCALAPPDATA%\Programs\Python\Python3*\Scripts
macOS /opt/homebrew/bin und /opt/homebrew/opt/llvm/bin (Homebrews clangd liegt im zweiten — es wird nie ins erste verlinkt), /usr/local/bin, /usr/local/opt/llvm/bin, ~/.cargo/bin, ~/go/bin, ~/.local/bin, ~/.npm-global/bin, ~/.dotnet/tools, ~/Library/Python/3.*/bin
Linux /usr/local/bin, /usr/lib/llvm*/bin, Linuxbrew sowie dieselben ~/.cargo/bin, ~/go/bin, ~/.local/bin, ~/.npm-global/bin, ~/.dotnet/tools

Die Einträge mit * sind echte Platzhalter: Das Versionsverzeichnis, das Python anlegt (Python313, 3.13 oder das …Python.3.13_qbz5n2kfra8p0 des Stores), wird gegen das abgeglichen, was wirklich auf der Platte liegt, neueste zuerst. Genau dorthin legt pip install python-lsp-server das pylsp — und deshalb braucht dessen Installation keine PATH-Änderung.

macOS: Start aus dem Finder gegenüber dem Terminal

Eine aus dem Finder oder dem Dock gestartete Anwendung erbt den PATH Ihres Shell-Profils nicht — macOS gibt ihr einen minimalen (/usr/bin:/bin:/usr/sbin:/sbin). Homebrew, Cargo, Go und npm wären unsichtbar. OctoEdit fragt deshalb Ihre Login-Shell nach deren PATH, durchsucht auch diesen und übergibt die daraus entstandene Umgebung an den gestarteten Server — ein mit einem dieser Werkzeuge installierter Server wird also gefunden, egal wie Sie den Editor starten.

Der Server startet einmal pro Sprache und wird mit dem Editor beendet.

C/C++-Projekte brauchen compile_commands.json

clangd versteht Ihren Code nur dann präzise, wenn es die Compile-Flags kennt — aus einer Kompilierungsdatenbank (compile_commands.json). Ohne sie rät clangd, und dateiübergreifende Funktionen (Verweise suchen, Umbenennen) bleiben auf die offene Datei beschränkt. clangd wird trotzdem gestartet.

Ein C/C++-Projekt gilt als konfiguriert, wenn es irgendeines davon hat:

  • eine compile_commands.json in der Projektwurzel oder in einem der von OctoEdit durchsuchten Build-Verzeichnisse (build/, Build/, out/, out/build/, cmake-build-debug/, cmake-build-release/, .mte-compile-commands/);
  • eine compile_flags.txt in der Projektwurzel;
  • eine .clangd-Konfigurationsdatei in der Projektwurzel.

Die letzten beiden liest clangd selbst, dazu wird also nichts gemeldet.

Fehlt all das — bei jedem C/C++-Projekt, gleich welches Build-System es verwendet — zeigt das Statussegment · keine Kompilierungsdatenbank, und eine Meldung in der Statusleiste sagt es einmal. Nichts blockiert; kein Dialog unterbricht Ihre Eingabe.

OctoEdit sie erzeugen lassen (CMake-Projekte)

Hat die Projektwurzel eine CMakeLists.txt und ist ein CMake vorhanden, das tatsächlich eine Datenbank erzeugen würde, wird Ihnen dies einmal pro Projekt angeboten:

  • Erzeugen — führt CMake im Hintergrund aus, rein konfigurierend: Es wird nichts kompiliert und Ihre eigenen Build-Verzeichnisse bleiben unberührt. Das Ergebnis landet in <project>/.mte-compile-commands/. Bei Erfolg wird clangd mit der neuen Datenbank neu gestartet; bei Misserfolg werden die letzten Zeilen des CMake-Protokolls gezeigt, zusammen mit dem genauen Befehl, der versucht wurde, damit Sie ihn selbst wiederholen können.
  • Wie es manuell geht — zeigt denselben Befehl, ohne ihn auszuführen.
  • Für dieses Projekt nicht mehr fragen — pro Projektwurzel gemerkt.

Sowohl das Fenster „wie es manuell geht“ als auch das Fehlerfenster zeigen die exakte Befehlszeile in einem markierbaren Code-Feld, darunter eine einzige Schaltfläche Kopieren, deren Tooltip sagt, was sie nimmt: den Befehl allein oder den Befehl zusammen mit dem Ende des CMake-Protokolls, wenn es eines gibt. Das Fehlerfenster ist größenveränderbar und merkt sich die Größe, die Sie ihm geben — jedes dieser Fenster merkt sich seine EIGENE Größe, ein vergrößertes Server-Protokoll lässt also ein zweizeiliges Anleitungsfenster nicht ebenso groß aufgehen.

Sie sind nicht auf dieses eine Angebot beschränkt: Suchen ▸ Code-Navigation ▸ Kompilierdatenbank erzeugen… startet dieselbe Erzeugung, wann immer Sie wollen — nach dem Hinzufügen von Dateien, nach geänderten Build-Optionen oder nachdem Sie Für dieses Projekt nicht mehr fragen gewählt haben (was dabei gelöscht wird). Eine vorhandene Datenbank wird an Ort und Stelle neu konfiguriert. Der Eintrag ist immer verfügbar; kann er nichts erzeugen, sagt er in der Statuszeile warum.

Ihre Presets kommen zuerst. Hat das Projekt eine CMakePresets.json (oder eine CMakeUserPresets.json), konfiguriert OctoEdit mit einem Ihrer Presets, statt eine Befehlszeile zu erfinden — cmake --preset <name> -B <project>/.mte-compile-commands -DCMAKE_EXPORT_COMPILE_COMMANDS=ON. So sind der Generator, das Toolset und der environment-Block des Presets (ein QT6_DIR, ein SDK-Pfad) genau die, auf die sich das Projekt ohnehin stützt, und CMake wendet sie selbst an. Presets, die versteckt sind, die eine condition auf Ihrem Betriebssystem ausschließt oder die mit einem nicht exportierenden Generator konfigurieren, werden übersprungen; ein Name mit debug wird bevorzugt. Ihr eigenes Build-Verzeichnis wird nie angefasst — der Editor lenkt die Ausgabe stets mit -B um.

Unter Windows läuft CMake in einer Visual-Studio-Entwicklerumgebung. Ein aus dem Explorer oder dem Startmenü gestarteter Editor hat kein cl im PATH, und CMake gäbe sich dann klaglos mit jedem anderen gefundenen Compiler zufrieden — auch mit der clang.exe, die innerhalb einer Visual-Studio-Installation mitgeliefert wird und prompt an MSVC-spezifischen Einstellungen scheitert. OctoEdit findet Visual Studio deshalb über vswhere und kapselt den Aufruf in VsDevCmd.bat -arch=x64. Ist kein Visual Studio installiert (eine reine MinGW- oder Clang-Maschine), erfolgt der Aufruf schlicht, und das Protokoll sagt es.

Ein vorheriger fehlgeschlagener Versuch wird vor einem erneuten Lauf aufgeräumt: Seine CMakeCache.txt würde sonst den gescheiterten Compiler festnageln. Ein Verzeichnis, das bereits eine funktionierende compile_commands.json enthält, wird an Ort und Stelle neu konfiguriert und nie gelöscht.

Warum das Angebot manchmal ausbleibt

CMAKE_EXPORT_COMPILE_COMMANDS wird nur von den Generatoren Ninja und Makefile beachtet; der Visual-Studio-Generator ignoriert es und schreibt keine Datenbank. Unter Windows erscheint das Angebot für ein Projekt ohne brauchbares Preset deshalb nur, wenn ninja in Ihrem PATH liegt. Sind die einzigen anwendbaren Presets eines Projekts Visual-Studio-Presets und fehlt auch Ninja, nennt OctoEdit das Preset, das im Weg stand, statt etwas anzubieten, das nicht funktionieren könnte.

Selbst erzeugen (CMake)

CMAKE_EXPORT_COMPILE_COMMANDS beachten nur die Ninja- und Makefile-Generatoren — der Visual-Studio-Generator ignoriert es (er erzeugt auch mit gesetztem Flag keine compile_commands.json). Erzeugen Sie die Datenbank also mit Ninja, in ein eigenes Verzeichnis, getrennt von Ihrem üblichen Build-Verzeichnis: CMake weigert sich, ein bestehendes Build-Verzeichnis mit anderem Generator neu zu konfigurieren — ein sonst mit Visual Studio gebautes Projekt braucht sein eigenes Ninja-Verzeichnis.

Das ist ein reiner Konfigurationsschritt (kein vollständiger Build nötig). Aus der Projektwurzel:

cmake -S . -B .mte-compile-commands -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
  • .mte-compile-commands/ gehört zu den von MTE gescannten Verzeichnissen, die entstehende compile_commands.json wird also automatisch gefunden. Jedes gescannte Verzeichnis funktioniert (build/, out/, cmake-build-* oder die Projektwurzel) — halten Sie es nur getrennt von einem mit anderem Generator konfigurierten Verzeichnis.
  • Führen Sie es in einer Umgebung aus, in der das Projekt wirklich konfiguriert: der richtige Compiler im PATH (z. B. ein x64 Native Tools Command Prompt unter Windows) und alle Variablen, die Ihr Projekt braucht (etwa QT6_DIR für ein Qt-Projekt). Findet cmake Compiler oder SDK nicht, wird die Datenbank leer oder ohne Include-Pfade, und clangd indiziert schlecht.
  • Öffnen Sie den Ordner danach neu. Das Protokoll sollte nicht mehr „no compile_commands.json“ melden; geben Sie clangd einen Moment für seinen Hintergrund-Index, bevor Referenzen/Umbenennen Dateien übergreifen.

Andere Build-Systeme: Bear (bear -- make), compiledb, Meson, Bazel und weitere können ebenfalls eine compile_commands.json erzeugen, die das Plugin findet.

Welcher Server bedient welche Datei

Der Dateiname entscheidet. Jede Serverdefinition nennt die Endungen, die sie bedient, und es startet die erste Definition, die die Endung einer Datei für sich beansprucht. Groß- und Kleinschreibung spielt keine Rolle, und nur der letzte Punkt zählt — Deploy.Prod.SH ist ein Shell-Skript.

Das ist bewusst unabhängig von der Syntaxhervorhebung. Die Hervorhebung abzuschalten oder eine Datei über der Größengrenze zu öffnen kostet Sie nicht länger auch den Sprachserver.

Die Colorizer-ID bleibt als Rückfall

Beansprucht keine Definition die Endung, greift OctoEdit auf die Sprach-ID zurück, die die Hervorhebung vergeben hat. So funktioniert eine von Hand geschriebene Definition weiter, die eine Sprache nennt, aber keine Endungen aufführt.

Der Name, den der Server genannt bekommt, ist eine zweite, davon getrennte Sache: LSP hat ein eigenes Vokabular an Sprach-IDs, und einige davon decken sich nicht mit denen von OctoEdit. Eine .sh-Datei wird als shellscript angekündigt, eine .scss als scss, eine .jsx als javascriptreact, eine .mm als objective-cpp. Server, die sich je nach Sprache anders verhalten — der CSS-Server, der TypeScript-Server — brauchen das korrekt.

Endung Bedient von Angekündigt als
.cpp .cxx .cc .h .hpp .hh .hxx .ipp .inl clangd cpp
.c clangd c
.m / .mm clangd objective-c / objective-cpp
.sh .bash .zsh .ksh bash-language-server shellscript
.css / .scss / .less vscode-css-language-server css / scss / less
.ts .mts .cts / .tsx typescript-language-server typescript / typescriptreact
.js .mjs .cjs / .jsx typescript-language-server javascript / javascriptreact
.json / .jsonc .json5 vscode-json-language-server json / jsonc

.h beansprucht die C/C++-Definition, nicht die für Objective-C — beide starten clangd, das selbst entscheidet, was in einem Header steht.

Was jeder Server vom Projekt erwartet

Mehrere Server arbeiten erst dann richtig, wenn eine bestimmte Datei im Projektwurzelverzeichnis liegt. Fehlt sie, sagt die Statusanzeige es, statt so zu tun, als wäre alles in Ordnung:

Sprache Erwartet Ohne die Datei
Rust Cargo.toml rust-analyzer lädt die Crate überhaupt nicht.
Go go.mod gopls kann das Modul nicht auflösen.
TypeScript tsconfig.json (oder package.json) projektweite Antworten sind nicht verfügbar.
JavaScript jsconfig.json (oder package.json) wie oben.
Python (pyright) pyproject.toml / pyrightconfig.json / setup.py pyright arbeitet weiter; es verwendet nur Vorgaben für Import-Wurzeln und Strenge.
Java pom.xml / build.gradle jdtls kann keinen Klassenpfad bilden.
C/C++ compile_commands.json siehe Abschnitt oben.

Eine Sprache hinzufügen

Server werden durch JSON-Dateien beschrieben, die das Plugin beim Start aus <editor>/lsp-servers/*.json und aus Ihrem Ordner lädt. Jeder Eintrag bildet eine Sprache auf ihr Kommando plus Erkennungshinweise ab:

{
    "language":    "cpp",
    "languageId":  "cpp",
    "languageIds": { ".c": "c" },
    "command":     "clangd",
    "aliases":     ["clangd-20", "clangd-19"],
    "args":        ["--background-index", "--log=verbose"],
    "extensions":  [".cpp", ".h", ".hpp", ".c"],
    "projectMarkers": [],
    "searchDirs":      ["${LLVM}/bin", "${ProgramFiles}/LLVM/bin"],
    "searchDirsMac":   ["/opt/homebrew/opt/llvm/bin"],
    "searchDirsLinux": ["/usr/lib/llvm-20/bin"],
    "docsAnchor":  "cpp-clangd",
    "compileCommandsArg": "--compile-commands-dir=${dir}"
}
  • language ist OctoEdits eigene ID für die Sprache — der Schlüssel, nach dem Einstellungsseite, Statussegment und Verbindung gruppiert sind. command/aliases sind die im PATH probierten Programmnamen.
  • extensions ist die primäre Zuordnung von Datei zu Sprache (siehe oben). Mit Punkt.
  • args ist ein Array-Element pro Argument. ["--background-index", "--log=verbose"] übergibt zwei Argumente; ["--background-index --log=verbose"] übergibt ein Argument, das ein Leerzeichen enthält — das weist jeder Server zurück, und weil er dann sofort endet, sieht es nach einer Absturzschleife aus statt nach einem Tippfehler. OctoEdit warnt beim Laden Ihrer Datei im Diagnoseprotokoll vor dieser Form.
  • languageId (optional) ist die ID, die dem Server im didOpen gesendet wird; Vorgabe ist language. Nutzen Sie es, wenn der Name der LSP-Spezifikation von unserem abweicht (bash → shellscript, objc → objective-c).
  • languageIds (optional) überschreibt languageId pro Endung, für einen Server, der mehrere Sprachen der Spezifikation bedient.
  • projectMarkers (optional) sind die Dateinamen, die der Server im Projektwurzelverzeichnis erwartet. Ist keiner davon vorhanden, zeigt das Statussegment kein <first marker>; den Server hält das nie auf.
  • searchDirs ist die Liste der Installationsorte für Windows; searchDirsMac und searchDirsLinux sind ihre Gegenstücke pro Plattform. Alle drei lösen ${VAR} auf, die POSIX-Listen zusätzlich ein führendes ~. Ein Eintrag, dessen Variablen nicht gesetzt sind, wird übersprungen statt in einen unsinnigen Pfad verwandelt.
  • args darf zwei Platzhalter verwenden: ${dataDir}, den beschreibbaren Datenordner des Plugins, und ${rootHash}, eine kurze stabile ID des aktuellen Projekts. So bekommt jdtls sein -data <dir>. Ein Platzhalter, der sich nicht auflösen lässt, bleibt wörtlich im Argument stehen, statt zu nichts zu werden.
  • compileCommandsArg (optional) wird angehängt, mit ${dir} ersetzt durch das gefundene Datenbank-Verzeichnis — so wird clangd auf compile_commands.json gerichtet.
  • priority (optional, Vorgabe 0) ordnet mehrere Definitionen derselben Sprache: Die niedrigste Zahl wird zuerst versucht, und es startet die erste Definition, deren ausführbare Datei gefunden wird. So bekommt Python pyright (priority: 0) mit pylsp (priority: 10) als Rückfallebene.

Eigene Serverdefinitionen

Die mitgelieferten Definitionen liegen im Installationsverzeichnis, das nicht Ihnen zum Bearbeiten gehört (Program Files unter Windows, ein signiertes Programmbündel unter macOS). Legen Sie Ihre eigenen daneben: Einstellungen ▸ Sprachserver ▸ Ordner für eigene Serverdefinitionen öffnen legt an und öffnet

<user data>/plugins/org.mte.lsp/lsp-servers/

Jede *.json darin wird nach dem mitgelieferten Satz geladen, und:

  • eine Datei, deren language und command einer mitgelieferten Definition entsprechen, ersetzt diese — so ändern Sie clangds Argumente oder ergänzen ein Suchverzeichnis;
  • alles andere wird hinzugefügt — ein zweiter Server für eine Sprache, die wir ausliefern, oder eine Sprache, für die OctoEdit gar nichts mitbringt.

Eine Datei, die kein gültiges JSON ist oder der language oder command fehlt, wird übersprungen und im Diagnoseprotokoll vermerkt, statt Sie stillschweigend eine Sprache zu kosten.

Definitionen werden einmal beim Start gelesen: starten Sie den Editor neu, nachdem Sie sie bearbeitet haben (die Schaltfläche Server neu suchen / neu starten wiederholt die Suche, nicht das Laden).

Eine minimale eigene Definition: <user data>/…/lsp-servers/zig.json
{
    "language":   "zig",
    "command":    "zls",
    "extensions": [".zig", ".zon"],
    "projectMarkers": ["build.zig"],
    "searchDirs":      ["${LOCALAPPDATA}/zls"],
    "searchDirsMac":   ["/opt/homebrew/bin", "~/.local/bin"],
    "searchDirsLinux": ["~/.local/bin"]
}

Welchen Ordner der Server bekommt

Ein Language Server muss wissen, wo das Projekt liegt: rust-analyzer lädt ohne das keine Crate, gopls braucht die Modulwurzel, pyright liest von dort pyrightconfig.json, und clangd sucht dort seine Datenbank.

  • Mit geöffnetem Ordner (Datei ▸ Ordner öffnen) gehören Dateien darin zu diesem Ordner.
  • Für eine Datei außerhalb des geöffneten Ordners oder ganz ohne geöffneten Ordner geht OctoEdit von der Datei aus nach oben und sucht compile_commands.json, compile_flags.txt, .clangd, CMakeLists.txt, Cargo.toml, go.mod, pyrightconfig.json, pyproject.toml, setup.py, tsconfig.json, package.json, pom.xml, build.gradle, eine .sln, .git und schließlich eine .editorconfig mit root = true. Als Rückfall dient das Verzeichnis der Datei selbst, ein Server bleibt also nie ohne Projekt.
  • Den Ordner nach der Datei zu öffnen funktioniert. Server, die Arbeitsordner-Änderungen verstehen, werden über den neuen Ordner informiert; die übrigen werden neu gestartet und Ihre offenen Dokumente ihnen automatisch erneut gemeldet. Ein manueller Neustart ist nicht nötig.

Fehlersuche

Symptom Was zu prüfen ist
Das LSP:-Segment erscheint nie Keine Serverdefinition beansprucht die Endung dieser Datei. Prüfen Sie welcher Server welche Datei bedient oder ergänzen Sie eine Definition.
· Server antwortet nicht Der Server hat aufgehört zu antworten. Sprachserver-Protokoll anzeigen, dann Sprachserver neu starten.
✗ für eine Sprache, für die Sie einen Server installiert haben Prüfen Sie, ob das Programm wirklich dort liegt: where clangd (Windows) / which clangd (macOS, Linux). Dann Suchen ▸ Code-Navigation ▸ Sprachserver neu starten, was die gesamte Suche wiederholt.
⚠ Der Server startete und stürzte dann wiederholt ab. Sprachserver-Protokoll anzeigen nennt meist den Grund; beheben Sie ihn und starten Sie die Server neu.
· keine Kompilierungsdatenbank in einem C/C++-Projekt Siehe oben. Verweise suchen und Umbenennen sehen bis dahin nur die offene Datei.
Vervollständigung liefert in einer C++-Datei nichts Diese Datei fehlt vermutlich in der compile_commands.json (ein Header, den keine Übersetzungseinheit einbindet, oder eine nach dem Erzeugen der Datenbank hinzugefügte Datei). Erzeugen Sie sie neu.
Aus dem Terminal funktioniert alles, aus dem Finder nicht Melden Sie es — die Login-Shell-PATH-Abfrage soll beide Fälle gleichsetzen. Sprachserver-Protokoll anzeigen und das Diagnoseprotokoll halten fest, was durchsucht wurde.
Ein Server braucht eine Projektdatei, die Sie nicht haben typescript-language-server braucht das Paket typescript, gopls eine go.mod, rust-analyzer eine Cargo.toml, pyright eine pyrightconfig.json/pyproject.toml für projektweite Antworten.

Language-Server-Einstellungen

Einstellungen ▸ Sprachserver listet jede Sprache mit vorhandener Server-Definition. Pro Sprache können Sie:

  • den Server aktivieren / deaktivieren (eine deaktivierte Sprache startet nie einen);
  • einen expliziten Programmpfad setzen (mit Durchsuchen…). Diese Vorgabe gewinnt gegen die PATH/searchDirs-Suche oben — nützlich, wenn der Server nicht im PATH liegt oder Sie einen bestimmten Build wollen.
  • Zusätzliche Argumente angeben, die hinter die eigenen Argumente der Definition gehängt werden — etwa --log=verbose für clangd. Die Zeile wird wie eine Befehlszeile zerlegt; setzen Sie einen Wert mit Leerzeichen daher in Anführungszeichen.

Das Pfadfeld ist ein Pfad, keine Befehlszeile

C:\tools\clangd.exe --log=verbose in Pfad zur Programmdatei zu tippen, weist OctoEdit an, eine Datei zu suchen, deren Name auf .exe --log=verbose endet — die gibt es nicht, und die Sprache meldet daraufhin gar keinen Server. Die Programmdatei gehört ins Pfadfeld, ihre Argumente in Zusätzliche Argumente. Passiert es doch, sagt das Diagnoseprotokoll es in klaren Worten.

Änderungen greifen bei OK / Übernehmen: Hat sich ein Aktivieren-Flag oder ein Pfad tatsächlich geändert, starten die Server automatisch mit den neuen Einstellungen neu (eine unberührte Seite stört laufende Server nie). Der Knopf Neu scannen / Server neu starten erzwingt zusätzlich Abbau und Neuerkennung mit den aktuellen Einstellungen — nützlich nach der Installation eines zuvor nicht gefundenen Servers; er setzt auch das Absturz-Neustart-Budget zurück.

Ordner für eigene Serverdefinitionen öffnen legt den in Eigene Serverdefinitionen beschriebenen Ordner an und öffnet ihn.

Grenzen

  • Code-Färbung in Hover-Popups wird nicht angewendet (der Text ist formatiert — fett, Überschriften, Monospace-Code — aber nicht syntaxhervorgehoben).
  • Die Genauigkeit hängt vom Server ab: Bei C/C++ ohne compile_commands.json greift clangd auf Heuristiken zurück, und die Ergebnisse können unvollständig sein.
  • OctoEdit installiert oder lädt niemals einen Server herunter. Es findet den von Ihnen installierten und startet ihn; gibt es keinen, bleibt die Funktion dunkel und das Statussegment sagt es.
  • Ein Serverprozess pro Sprache, gemeinsam für alle offenen Projekte dieser Sprache. Ein zweites Projekt wird als Arbeitsordner hinzugefügt, sofern der Server das unterstützt; sonst wird es unter der Wurzel des ersten Projekts bedient.
  • Kotlin, Swift und Objective-C bekommen Code-Intelligenz, aber keine Syntaxfärbung — der Editor hat für sie noch keinen Colorizer. Beides ist jetzt unabhängig, der Server arbeitet also trotzdem.
  • Serverdefinitionen werden einmal beim Start gelesen; sie zu bearbeiten (Ihre oder die mitgelieferten) erfordert einen Neustart des Editors.