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:
| 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:
- pyright (
pyright-langserver) wird zuerst versucht. Es ist ein npm-Paket und benötigt daher Node.js:npm i -g pyright. - 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:
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 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:
- einen expliziten Pfad aus den Einstellungen — maßgeblich: Führt er ins Leere, bleibt die Sprache dunkel, statt still auf etwas anderes auszuweichen;
- Ihren
PATH, für den Befehl des Servers und jeden bekannten Alias (clangd-20,clangd-19, …); - die Installationsorte aus der Server-Definition für Ihr Betriebssystem;
- 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.jsonin 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.txtin 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:
.mte-compile-commands/gehört zu den von MTE gescannten Verzeichnissen, die entstehendecompile_commands.jsonwird 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 (etwaQT6_DIRfür ein Qt-Projekt). FindetcmakeCompiler 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}"
}
languageist OctoEdits eigene ID für die Sprache — der Schlüssel, nach dem Einstellungsseite, Statussegment und Verbindung gruppiert sind.command/aliasessind die imPATHprobierten Programmnamen.extensionsist die primäre Zuordnung von Datei zu Sprache (siehe oben). Mit Punkt.argsist 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 imdidOpengesendet wird; Vorgabe istlanguage. Nutzen Sie es, wenn der Name der LSP-Spezifikation von unserem abweicht (bash→shellscript,objc→objective-c).languageIds(optional) überschreibtlanguageIdpro 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 Statussegmentkein <first marker>; den Server hält das nie auf.searchDirsist die Liste der Installationsorte für Windows;searchDirsMacundsearchDirsLinuxsind 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.argsdarf 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 aufcompile_commands.jsongerichtet.priority(optional, Vorgabe0) 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
Jede *.json darin wird nach dem mitgelieferten Satz geladen, und:
- eine Datei, deren
languageundcommandeiner 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).
{
"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,.gitund schließlich eine.editorconfigmitroot = 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 imPATHliegt oder Sie einen bestimmten Build wollen. - Zusätzliche Argumente angeben, die hinter die eigenen Argumente der
Definition gehängt werden — etwa
--log=verbosefü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.jsongreift 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.