Wtyczka LSP (serwer języka)¶
Inteligencja kodu napędzana Language Server Protocol — wężyki błędów, nawigacja, dymki, uzupełnianie, pomoc sygnatur, formatowanie, szukanie odwołań, zmiana nazwy i skok do symbolu — dla każdego języka, który ma serwer języka. Edytor rozmawia z serwerem po LSP; wtyczka jest klientem. To, jakie serwery istnieją, jest sterowane danymi (jeden mały JSON na język), więc C++/clangd poniżej to tylko jedna z kilku dołączonych definicji.
Edytor nie dołącza ani nie pobiera serwerów
Serwer języka to osobny program, który instalujesz raz. MTE wykrywa zainstalowany serwer i kieruje go na Twój projekt; nigdy żadnego nie dostarcza. Zobacz Pobieranie serwera języka.
Bieżące funkcje¶
| Funkcja | Jak |
|---|---|
| Diagnostyka | Błędy/ostrzeżenia z serwera pojawiają się jako faliste podkreślenia (czerwone = błąd, bursztynowe = ostrzeżenie, niebieskie = informacja, szare = wskazówka), aktualizowane podczas pisania. |
| Idź do definicji | Ustaw kursor na symbolu i naciśnij F12 albo użyj Szukaj ▸ Nawigacja po kodzie ▸ Idź do definicji. Skacze do definicji, otwierając w razie potrzeby inny plik. |
| Znajdź odwołania | Kursor na symbolu → Shift+F12 (albo Szukaj ▸ Nawigacja po kodzie ▸ Znajdź odwołania). Wyniki otwierają się w dolnym panelu Odwołania, pogrupowane po plikach z podglądem linii źródłowej; dwuklik skacze. |
| Dymek | Zatrzymaj wskaźnik nad symbolem; okienko pokazuje jego typ/sygnaturę i dokumentację (renderowaną z Markdownu serwera). |
| Uzupełnianie | Ctrl+Space prosi serwer o uzupełnienia i włącza je do okienka uzupełniania edytora (przed wbudowanymi podpowiedziami słów kluczowych/słów z buforów), filtrując podczas pisania. |
| Pomoc sygnatur | Wpisanie ( wywołania albo , pokazuje podpowiedź z sygnaturą funkcji i podświetlonym aktywnym parametrem; ) ją zamyka. |
| Formatuj dokument | Alt+Shift+F (⌃⌥F na macOS; albo Edycja ▸ Formatuj dokument) formatuje cały dokument przez serwer, jako jeden krok cofania. Styl określa konfiguracja samego serwera (dla clangd — plik .clang-format). |
| Znajdź odwołania (wyżej) | — |
| Zmień nazwę symbolu | Kursor na symbolu → Shift+F6 (albo Edycja ▸ Zmień nazwę symbolu). Podaj nową nazwę; każde użycie zostaje zaktualizowane. Gdy zmiana obejmuje kilka plików, najpierw pada prośba o potwierdzenie — każdy plik jest otwierany, zmieniany i zostawiany zmodyfikowany do przeglądu i zapisu. |
| Idź do symbolu (w pliku) | Ctrl+Shift+O otwiera Paletę poleceń z listą wszystkich symboli bieżącego pliku (funkcje, klasy, metody…); pisz, aby filtrować, Enter skacze. Każdy wiersz pokazuje rodzaj symbolu i jego kontener. |
| Idź do symbolu w przestrzeni roboczej | Ctrl+T przeszukuje symbole w całym projekcie podczas pisania (zapytanie dopasowuje serwer); Enter otwiera plik na symbolu. |
Wybieraki skoku do symbolu to tryby symboli Palety poleceń — zobacz Paletę poleceń.
Polecenia są wyszarzone, dopóki serwer nie działa
Przejdź do definicji, Znajdź odwołania, Formatuj dokument i Zmień nazwę symbolu są dostępne tylko wtedy, gdy serwer języka bieżącego pliku jest gotowy — i gdy w powitaniu zgłosił, że obsługuje dane żądanie. Dla pliku bez skonfigurowanego serwera, a także gdy serwer się uruchamia, restartuje albo się poddał, pozycje menu są wyszarzone, zamiast nic nie robić po kliknięciu. Poniższy wskaźnik stanu mówi, który to przypadek. Uruchom ponownie serwery językowe nigdy nie jest wyszarzone: to droga wyjścia z serwera, który się poddał.
Odwołania i zmiana nazwy między plikami wymagają indeksu serwera
Znajdź odwołania i Zmień nazwę sięgają do innych plików dopiero, gdy serwer
zaindeksuje projekt. Dla C/C++ oznacza to compile_commands.json (niżej) i
indeks działający w tle clangd; bez tego działają tylko na bieżącym pliku.
Zmiana nazwy cofa się na razie per plik
Wieloplikowa zmiana nazwy jest stosowana plik po pliku, więc każdy plik to osobny krok cofania (okno potwierdzenia o tym mówi). Przejrzyj zmodyfikowane karty przed zapisem.
W menu kontekstowym edytora¶
Kliknij prawym przyciskiem symbol w tekście, a menu pod poleceniami edycji zaproponuje Przejdź do definicji, Znajdź odwołania, Zmień nazwę symbolu i Formatuj dokument. Każda pozycja pojawia się tylko wtedy, gdy to samo polecenie w menu głównym zadziałałoby w tej chwili — serwer języka dla pliku jest gotowy i je obsługuje, a w przypadku zmiany nazwy i formatowania dokument nie jest tylko do odczytu. W zwykłym pliku tekstowym, na marginesie po lewej stronie tekstu albo podczas uruchamiania serwera żadna z nich się nie pojawia.
Pozycje działają na symbolu, który kliknięto prawym przyciskiem, a nie na tym pod karetką; karetka i zaznaczenie zostają na miejscu. Zmiana nazwy proponuje zaznaczenie jako starą nazwę, jeśli kliknięto wewnątrz niego, a w przeciwnym razie słowo pod wskaźnikiem. Formatuj dokument zawsze formatuje cały dokument. Menu otwarte z klawiatury działa w miejscu karetki.
Tam, gdzie platforma pokazuje skróty klawiszowe w menu kontekstowych (Windows), każda pozycja pokazuje swój skrót — ten obowiązujący, łącznie z Twoimi zmianami w mapowaniu skrótów. W macOS menu kontekstowe nie pokazują skrótów.
Jak Twoje zmiany trafiają do serwera¶
Pisanie nie wysyła komunikatu na każde naciśnięcie klawisza. Zmiany są scalane przez ułamek sekundy i wysyłane jako jedna — i to jako pojedynczy zmieniony zakres, a nie cały plik, o ile serwer zadeklaruje, że to potrafi (większość potrafi). Duży plik kosztuje więc kilkadziesiąt bajtów na serię pisania zamiast kopii samego siebie.
Wszystko, co pyta serwer o tekst — dymki, przejście do definicji, szukanie odwołań, zmiana nazwy, formatowanie, uzupełnianie, pomoc sygnatur — najpierw wysyła oczekującą zmianę, żeby odpowiedź nigdy nie dotyczyła wersji, którą już zdążyłeś zostawić za sobą. Zapis pliku robi to samo.
Uruchomienie serwera także nie blokuje edytora: proces startuje w tle, a
segment stanu pokazuje …, dopóki nie skończy uzgadniania. Serwer, który
zawiesza się przy starcie, kosztuje Cię tylko ten jeden język.
Górna granica liczby rysowanych problemów
Na jeden dokument rysowanych jest najwyżej 2000 wężyków. Powyżej tej liczby plik i tak jest nieczytelny, a każdy dodatkowy znacznik kosztuje edytor realny czas — więc gdy plik daje ich więcej, pokazywane jest pierwsze 2000, a pasek stanu mówi Pokazano pierwsze 2000 z N problemów w tym pliku, zamiast po cichu zaniżać liczbę. Zwykle to znak, że serwer patrzy na plik niewłaściwie: brakuje bazy kompilacji albo jest to plik generowany, który nie ma się kompilować samodzielnie.
Wskaźnik stanu serwera¶
Pasek stanu pokazuje zwarty segment LSP: (na lewo od innych segmentów
wtyczek), podsumowujący każdy serwer języka istotny dla otwartych plików:
| Glif | Znaczenie |
|---|---|
… |
Start — serwer został uruchomiony i trwa uzgadnianie. |
✓ |
Gotowy — obsługuje żądania. |
↻n |
Restart — serwer zakończył się nieoczekiwanie; zaplanowana jest automatyczna próba restartu nr n. |
✗ |
Brak zainstalowanego serwera dla tego języka. Zainstaluj go (patrz niżej), a potem użyj Uruchom ponownie serwery językowe. |
⚠ |
Poddał się — serwer ciągle się wywalał i automatyczne restarty ustały. Przywraca go tylko restart ręczny. |
Za glifem języka może pojawić się krótkie dopowiedzenie — serwer działa, a coś w projekcie nadal ogranicza to, na co potrafi odpowiedzieć. Pokazywane jest tylko jedno naraz, najpoważniejsze najpierw:
| Dopowiedzenie | Znaczenie |
|---|---|
· serwer nie odpowiada |
Kilka żądań z rzędu pozostało bez odpowiedzi. Serwer żyje, ale utknął: Pokaż dziennik serwera językowego, potem Uruchom ponownie serwery językowe. Dopowiedzenie znika w chwili, gdy serwer na cokolwiek odpowie. |
· brak bazy kompilacji |
Serwer C/C++ działa, ale widzi wyłącznie otwarty plik; patrz Projekty C/C++ potrzebują compile_commands.json. |
· brak Cargo.toml, · brak go.mod, · brak tsconfig.json, … |
Projekt nie ma żadnego z plików, których ten serwer potrzebuje, by rozumieć go jako projekt. Otwarty plik nadal działa; odpowiedzi obejmujące wiele plików będą niepełne, dopóki plik nie powstanie. Nazwa jest tą, na której serwerowi zależy najbardziej — patrz Czego każdy serwer oczekuje od projektu. |
Segment pojawia się przy otwarciu pierwszego dokumentu skonfigurowanego języka, śledzi tylko języki, dla których faktycznie masz otwarte dokumenty — zamknięcie ostatniego pliku języka usuwa jego wpis (ponowne otwarcie natychmiast go przywraca) — i znika całkowicie, gdy nie zostaje żaden taki dokument.
Szukaj ▸ Nawigacja po kodzie ▸ Pokaż dziennik serwera językowego pokazuje najnowsze komunikaty każdego działającego serwera. To tam serwer się tłumaczy: brakujący toolchain, nieczytelny plik konfiguracji, projekt, którego nie wczytał. Okno jest zwykłym oknem o zmiennym rozmiarze — każdy język to nagłówek nazywający działający dla niego serwer, tekst można zaznaczać, Kopiuj umieszcza cały dziennik w schowku, a nadany oknu rozmiar jest zapamiętywany.
Gdy serwer się zawiesi¶
Serwer języka, który kończy się nieoczekiwanie, jest restartowany
automatycznie z rosnącym opóźnieniem (1 s, 2 s, 4 s… z limitem 30 s). W tym
czasie wskaźnik pokazuje ↻n, a powiadomienie na pasku stanu zgłasza pierwszą
awarię. Po udanym restarcie otwarte dokumenty są ponownie zgłaszane serwerowi
i diagnostyka wraca sama; nieaktualne wężyki po martwym serwerze są czyszczone
od razu. Edycja nigdy nie jest blokowana.
Po 5 nieudanych próbach z rzędu wtyczka się poddaje: wskaźnik pokazuje
✗, powiadomienie kieruje do ustawień, a język pozostaje ciemny, dopóki nie
zrestartujesz go ręcznie. Serwer, który działał poprawnie przez co najmniej
minutę, przy późniejszej awarii dostaje świeżą pulę prób.
Restart ręczny — jedno z dwojga:
- Szukaj ▸ Nawigacja po kodzie ▸ Uruchom ponownie serwery językowe (bez domyślnego skrótu; dostępne też z Palety poleceń), albo
- przycisk Przeskanuj / zrestartuj serwery w Preferencje ▸ Serwer języka.
Oba zatrzymują wszystkie serwery, ponawiają wykrywanie z bieżącymi ustawieniami i resetują budżet awarii — użyj po zainstalowaniu brakującego serwera albo naprawieniu zepsutego.
Aby przed restartem zobaczyć, dlaczego serwer jest niezadowolony, użyj Szukaj ▸ Nawigacja po kodzie ▸ Pokaż dziennik serwera językowego.
Pobieranie serwera języka¶
Zainstaluj serwer dla swojego języka i upewnij się, że jest w PATH (albo
ustaw jawną ścieżkę w ustawieniach). Jeśli nie
zostanie znaleziony, funkcja po prostu nic nie robi dla tego języka —
wskaźnik stanu pokazuje ✗, a log notuje
jednorazową wskazówkę, ale nic Ci nie przeszkadza.
MTE dostarcza definicje serwerów (nie serwery) dla wielu języków, więc większość wymaga tylko instalacji serwera — bez edycji JSON-a. Dołączone definicje obejmują C/C++, Objective-C, Pythona, Rusta, Go, TypeScript, JavaScript, C#, Javę, Kotlina, Swifta, HTML, CSS/SCSS/Less, JSON, YAML i skrypty powłoki.
| Język | Serwer | Skąd wziąć |
|---|---|---|
| C/C++ | clangd | winget install LLVM.LLVM (Windows), komponent „C++ Clang tools" w instalatorze Visual Studio, brew install llvm (macOS) albo pakiet clang-tools-extra Twojej dystrybucji. |
| Python | pyright lub pylsp | npm i -g pyright (wymaga Node.js) albo pip install python-lsp-server (wymaga tylko Pythona). |
| 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 lub OmniSharp | dotnet tool install -g csharp-ls (pojedyncze narzędzie dotnet, próbowane pierwsze) albo pobrane wydanie OmniSharpa. |
| Java | jdtls (Eclipse JDT Language Server) | brew install jdtls (macOS) albo rozpakowane wydanie z katalogiem bin w PATH. |
Zweryfikuj w terminalu, np. clangd --version albo where clangd /
which clangd. Dla języka bez dołączonej definicji dodaj własną jak w
Dodawaniu języka.
Python: pyright albo pylsp¶
Python ma dwie dołączone definicje, a OctoEdit uruchamia tę, która jest faktycznie zainstalowana:
- pyright (
pyright-langserver) jest próbowany pierwszy. To pakiet npm, więc wymaga Node.js:npm i -g pyright. - pylsp (
python-lsp-server) jest używany, gdy pyrighta nie ma. To pakiet pip i wymaga tylko Pythona:pip install python-lsp-server.
Gdy zainstalowane są oba, wygrywa pyright. W ustawieniach Python ma jeden wiersz
(jedną flagę włączenia, jedno nadpisanie ścieżki) i dotyczy on tego serwera,
który zostanie użyty — wskazanie jawnej ścieżki do pylsp uruchamia pylsp z
jego argumentami, nie z argumentami pyrighta. Pokaż dziennik serwera
językowego nazywa serwer, który faktycznie działa.
Kilka serwerów dla jednego języka
To mechanizm ogólny, nie wyjątek dla Pythona: język może mieć dowolnie wiele
dołączonych definicji, uporządkowanych polem priority, a startuje pierwsza
z nich, której plik wykonywalny znajduje się na Twoim komputerze. C# działa
tak samo — najpierw csharp-ls, potem OmniSharp — bo oba przyjmują
inne argumenty uruchomienia i tylko jedne z nich mogą być poprawne.
Java: własna przestrzeń robocza serwera¶
jdtls nie wystartuje bez własnego, zapisywalnego katalogu roboczego
(-data). OctoEdit dostarcza go automatycznie, osobno dla każdego
projektu, w folderze danych wtyczki:
Nigdy nie musisz go tworzyć ani nazywać. Skasowanie folderu jest bezpieczne — jdtls odbuduje go kosztem jednego ponownego indeksowania.
Konfiguracja w systemie Windows¶
Świeża instalacja Windows zwykle nie ma na PATH żadnego z: clangd,
cmake, ninja, node, python. Ta sekcja mówi, skąd wziąć każde z nich i jak
to sprawdzić. Zwykle nie musisz sam edytować PATH — OctoEdit przeszukuje też
katalogi ekosystemów wymienione niżej.
| Czego chcesz | Instalacja | Gdzie ląduje |
|---|---|---|
| clangd (C/C++) | winget install LLVM.LLVM |
C:\Program Files\LLVM\bin\clangd.exe |
| cmake i ninja | Komponent „C++ CMake tools for Windows" w instalatorze Visual Studio | …\Microsoft Visual Studio\2022\<edition>\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin i …\CMake\Ninja — nie na PATH, ale osiągalne przez środowisko deweloperskie Visual Studio (patrz niżej). Osobne winget install Kitware.CMake / winget install Ninja-build.Ninja umieszcza je na PATH. |
| pyright (Python) | winget install OpenJS.NodeJS.LTS, potem npm i -g pyright |
%APPDATA%\npm\pyright-langserver.cmd |
| pylsp (Python, bez Node) | Python ze Sklepu Microsoft lub python.org, potem pip install python-lsp-server |
%LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.3.*_*\LocalCache\local-packages\Python3*\Scripts\pylsp.exe (Sklep) albo %APPDATA%\Python\Python3*\Scripts\pylsp.exe |
Sprawdzenie, co jest widoczne. W zwykłym wierszu poleceń lub PowerShellu:
where przeszukuje wyłącznie PATH. Narzędzie, którego nie znajdzie, może mimo
to zostać znalezione przez OctoEdit, bo wyszukiwanie obejmuje też powyższe
katalogi ekosystemów — w szczególności katalogi skryptów Pythona nigdy nie są na
PATH. Jeśli po instalacji serwera język nadal pokazuje ✗, użyj Szukaj ▸
Nawigacja po kodzie ▸ Uruchom ponownie serwery językowe, co powtarza całe
wyszukiwanie.
Generowanie bazy kompilacji działa w środowisku deweloperskim Visual Studio.
Gdy OctoEdit uruchamia dla Ciebie CMake (patrz niżej), najpierw lokalizuje Visual
Studio — przez VSINSTALLDIR, a w przeciwnym razie vswhere.exe — i opakowuje
wywołanie w VsDevCmd.bat -arch=x64 tej instalacji. To właśnie udostępnia cl,
Windows SDK oraz cmake/ninja z Visual Studio na czas tego jednego
polecenia, więc edytor w ogóle nie potrzebuje ich na Twoim PATH. Bez Visual
Studio (maszyna tylko z clangiem albo z MinGW) wywołanie jest wykonywane
zwyczajnie, w środowisku samego edytora, i dziennik to odnotowuje; wtedy musisz
sam mieć osiągalne cmake i ninja oraz kompilator, który CMake rozpozna.
Generowanie na żądanie. Szukaj ▸ Nawigacja po kodzie ▸ Wygeneruj bazę
kompilacji… uruchamia to samo generowanie w dowolnym momencie — także gdy baza
już istnieje (jest wtedy przekonfigurowana w miejscu) i gdy wcześniej wybrałeś
Nie pytaj o ten projekt. Pozycja jest zawsze dostępna — gdy nie może nic
wygenerować, mówi na pasku stanu dlaczego (brak dokumentu C/C++, brak folderu
projektu, brak CMakeLists.txt w katalogu głównym, brak cmake albo brak
generatora, który potrafiłby ją tu wyeksportować), zamiast być wyszarzona z
powodu, którego nie widać.
Gdzie zapisywana jest odpowiedź „nie pytaj". Nie pytaj o ten projekt jest
pamiętane per katalog główny projektu w %APPDATA%\7-bits\OctoEdit.ini, pod
plugins/org.mte.lsp/noCompileDbPrompt/<hash> (ścieżka projektu jest hashowana,
bo ścieżka nie jest poprawnym kluczem ustawień). Wygeneruj bazę kompilacji…
czyści ten wpis dla danego projektu.
Gdzie OctoEdit szuka serwera¶
Nie powinieneś musieć niczego konfigurować. Po instalacji serwera wystarczy otworzyć folder i plik źródłowy. Edytor próbuje po kolei:
- jawnej ścieżki ustawionej w ustawieniach — rozstrzygającej: jeśli nie wskazuje na plik wykonywalny, język pozostaje ciemny, zamiast po cichu sięgać po coś innego;
- Twojego
PATH— polecenia serwera i każdego znanego aliasu (clangd-20,clangd-19, …); - lokalizacji instalacji z definicji serwera dla Twojego systemu;
- wbudowanej listy katalogów ekosystemów.
| Przeszukiwane katalogi ekosystemów | |
|---|---|
| Windows | globalny prefiks npm i %APPDATA%\npm, %LOCALAPPDATA%\Microsoft\WinGet\Links, %USERPROFILE%\.cargo\bin, %USERPROFILE%\go\bin i %LOCALAPPDATA%\go\bin, %USERPROFILE%\.dotnet\tools, %ProgramFiles%\LLVM\bin, %ProgramFiles%\nodejs oraz katalogi skryptów Pythona dla użytkownika: %APPDATA%\Python\Python3*\Scripts, %LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.3.*_*\LocalCache\local-packages\Python3*\Scripts (Python ze Sklepu Microsoft) i %LOCALAPPDATA%\Programs\Python\Python3*\Scripts |
| macOS | /opt/homebrew/bin i /opt/homebrew/opt/llvm/bin (clangd z Homebrew leży w tym drugim — nigdy nie jest linkowany do pierwszego), /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 oraz te same ~/.cargo/bin, ~/go/bin, ~/.local/bin, ~/.npm-global/bin, ~/.dotnet/tools |
Wpisy z * to prawdziwe wieloznaczniki: katalog z wersją, który tworzy Python
(Python313, 3.13 albo …Python.3.13_qbz5n2kfra8p0 ze Sklepu), jest
dopasowywany do tego, co faktycznie jest na dysku, od najnowszego. Tam właśnie
pip install python-lsp-server umieszcza pylsp — i dlatego jego instalacja nie
wymaga zmiany PATH.
macOS: uruchomienie z Findera a z terminala
Aplikacja uruchomiona z Findera lub Docka nie dziedziczy PATH z
profilu Twojej powłoki — macOS daje jej minimalny
(/usr/bin:/bin:/usr/sbin:/sbin). Homebrew, Cargo, Go i npm byłyby
niewidoczne. Dlatego OctoEdit pyta Twoją powłokę logowania o jej PATH
i przeszukuje również jego, a wynikowe środowisko przekazuje uruchamianemu
serwerowi — więc serwer zainstalowany dowolnym z tych narzędzi zostaje
znaleziony niezależnie od sposobu uruchomienia edytora.
Serwer startuje raz na język i jest zamykany razem z edytorem.
Projekty C/C++ potrzebują compile_commands.json¶
clangd rozumie Twój kod dokładnie tylko wtedy, gdy zna flagi kompilacji — z
bazy kompilacji (compile_commands.json). Bez niej clangd zgaduje, a
funkcje międzyplikowe (znajdź odwołania, zmiana nazwy) pozostają ograniczone
do otwartego pliku. clangd i tak zostaje uruchomiony.
Projekt C/C++ liczy się jako skonfigurowany, gdy ma dowolne z:
compile_commands.jsonw korzeniu projektu albo w jednym z katalogów budowania skanowanych przez OctoEdit (build/,Build/,out/,out/build/,cmake-build-debug/,cmake-build-release/,.mte-compile-commands/);compile_flags.txtw korzeniu projektu;- plik konfiguracji
.clangdw korzeniu projektu.
Dwa ostatnie clangd czyta sam, więc nic o nich nie zgłaszamy.
Gdy nie ma żadnego z nich — dla każdego projektu C/C++, niezależnie od
systemu budowania — segment stanu pokazuje · brak bazy kompilacji, a
komunikat na pasku stanu mówi o tym raz. Nic nie blokuje, żadne okno nie
przerywa pisania.
Niech OctoEdit ją wygeneruje (projekty CMake)¶
Jeśli korzeń projektu ma CMakeLists.txt i dostępny jest CMake, który
naprawdę wytworzy bazę, raz na projekt dostajesz propozycję:
- Wygeneruj — uruchamia CMake w tle, wyłącznie w trybie konfiguracji:
nic nie jest kompilowane, a Twoje katalogi budowania pozostają nietknięte.
Wynik trafia do
<project>/.mte-compile-commands/. Po sukcesie clangd restartuje się z nową bazą; po niepowodzeniu pokazywane są ostatnie linie logu CMake wraz z dokładnym poleceniem, które zostało użyte, żebyś mógł je powtórzyć samodzielnie. - Jak zrobić to ręcznie — pokazuje to samo polecenie bez uruchamiania go.
- Nie pytaj o ten projekt — zapamiętywane osobno dla każdego korzenia.
Zarówno okno „jak zrobić to ręcznie", jak i okno błędu pokazują dokładny wiersz poleceń w polu kodu, które da się zaznaczyć, a pod nim jeden przycisk Kopiuj, którego podpowiedź mówi, co kopiuje: samo polecenie albo polecenie razem z końcówką logu CMake, gdy jakiś jest. Okno błędu ma zmienny rozmiar i zapamiętuje ten, który mu nadasz — każde z tych okien pamięta własny rozmiar, więc powiększenie dziennika serwera nie sprawia, że dwuwierszowe okno z instrukcją otwiera się równie duże.
Nie jesteś ograniczony do tej jednej propozycji: Szukaj ▸ Nawigacja po kodzie ▸ Wygeneruj bazę kompilacji… uruchamia to samo generowanie, kiedy tylko chcesz — po dodaniu plików, po zmianie opcji budowania albo po wcześniejszym wybraniu Nie pytaj o ten projekt (co zostaje wyczyszczone). Istniejąca baza jest przekonfigurowywana w miejscu. Pozycja jest zawsze dostępna; gdy nie może nic wygenerować, mówi na pasku stanu dlaczego.
Najpierw Twoje zestawy ustawień. Jeśli projekt ma CMakePresets.json (albo
CMakeUserPresets.json), OctoEdit konfiguruje jednym z Twoich presetów,
zamiast wymyślać własny wiersz poleceń — cmake --preset <name> -B
<project>/.mte-compile-commands -DCMAKE_EXPORT_COMPILE_COMMANDS=ON. Dzięki temu
generator, zestaw narzędzi i blok environment presetu (QT6_DIR, ścieżka do
SDK) są tymi, na których projekt już polega, a CMake sam je stosuje. Presety
ukryte, wykluczone przez condition na Twoim systemie albo konfigurujące
generatorem, który nie potrafi eksportować, są pomijane; preferowana jest nazwa
zawierająca debug. Twój własny katalog budowania nigdy nie jest ruszany —
edytor zawsze przekierowuje wynik przez -B.
Na Windows CMake jest uruchamiany w środowisku deweloperskim Visual Studio.
Edytor uruchomiony z Eksploratora lub menu Start nie ma cl w PATH, a CMake
po cichu zadowoli się dowolnym innym kompilatorem, który znajdzie — w tym
clang.exe dostarczanym wewnątrz instalacji Visual Studio, co natychmiast
kończy się błędem na ustawieniach specyficznych dla MSVC. Dlatego OctoEdit
lokalizuje Visual Studio przez vswhere i opakowuje wywołanie w
VsDevCmd.bat -arch=x64. Jeśli Visual Studio nie ma (maszyna wyłącznie z MinGW
lub clangiem), wywołanie idzie wprost, a log to odnotowuje.
Poprzednia nieudana próba jest sprzątana przed ponowieniem: jej
CMakeCache.txt przypiąłby kompilator, który zawiódł. Katalog zawierający już
działający compile_commands.json jest rekonfigurowany w miejscu, nigdy
kasowany.
Dlaczego propozycja czasem się nie pojawia
CMAKE_EXPORT_COMPILE_COMMANDS honorują tylko generatory Ninja i
Makefile; generator Visual Studio go ignoruje i nie zapisuje żadnej
bazy. Dlatego na Windows, dla projektu bez użytecznego presetu, propozycja
pojawia się tylko wtedy, gdy w PATH jest ninja. Gdy jedyne pasujące
presety projektu są tymi od Visual Studio i nie ma też Ninji, OctoEdit mówi,
który preset stanął na przeszkodzie, zamiast proponować uruchomienie czegoś,
co nie mogłoby zadziałać.
Generowanie samodzielne (CMake)¶
CMAKE_EXPORT_COMPILE_COMMANDS honorują tylko generatory Ninja i
Makefile — generator Visual Studio go ignoruje (nie tworzy
compile_commands.json nawet z ustawioną flagą). Generuj więc bazę
Ninją, do dedykowanego katalogu, osobnego od tego, w którym zwykle
budujesz: CMake odmawia rekonfiguracji istniejącego katalogu budowania innym
generatorem, więc projekt budowany zwykle Visual Studio potrzebuje własnego
katalogu Ninja.
To krok wyłącznie konfiguracyjny (pełny build nie jest potrzebny). Z korzenia projektu:
.mte-compile-commands/to jeden ze skanowanych katalogów, więc wynikowycompile_commands.jsonzostaje znaleziony automatycznie. Zadziała też każdy inny skanowany katalog (build/,out/,cmake-build-*albo korzeń projektu) — trzymaj go tylko osobno od katalogu skonfigurowanego innym generatorem.- Uruchom to w środowisku, w którym projekt naprawdę się konfiguruje: właściwy
kompilator w
PATH(np. x64 Native Tools Command Prompt na Windows) i zmienne, których projekt wymaga (jakQT6_DIRdla projektu Qt). Jeślicmakenie znajdzie kompilatora lub SDK, baza wyjdzie pusta albo bez ścieżek include i clangd nie zaindeksuje dobrze. - Potem otwórz folder ponownie. Log nie powinien już mówić „no compile_commands.json"; daj clangd chwilę na zbudowanie indeksu w tle, zanim odwołania/zmiana nazwy obejmą pliki.
Inne systemy budowania: Bear (bear -- make), compiledb, Meson, Bazel i
inne też potrafią wytworzyć compile_commands.json, który wtyczka znajdzie.
Który serwer obsługuje który plik¶
Decyduje nazwa pliku. Każda definicja serwera wymienia rozszerzenia, które
obsługuje, i startuje pierwsza definicja zgłaszająca rozszerzenie pliku.
Dopasowanie ignoruje wielkość liter i liczy się tylko ostatnia kropka —
Deploy.Prod.SH to skrypt powłoki.
Jest to celowo niezależne od kolorowania składni. Wyłączenie kolorowania albo otwarcie pliku większego niż limit rozmiaru kolorowania nie kosztuje Cię już także serwera językowego.
Identyfikator kolorowania nadal jest zapasem
Jeśli żadna definicja nie zgłasza rozszerzenia, OctoEdit sięga po identyfikator języka nadany przez silnik kolorowania. Dzięki temu ręcznie napisana definicja działa, gdy nazywa język, ale nie wymienia rozszerzeń.
Nazwa, którą serwer dostaje, to druga, osobna sprawa: LSP ma własne
słownictwo identyfikatorów języków i kilka z nich nie pokrywa się z tymi
OctoEdit. Plik .sh jest zgłaszany jako shellscript, .scss jako scss,
.jsx jako javascriptreact, .mm jako objective-cpp. Serwery, które
zachowują się różnie zależnie od języka — serwer CSS, serwer TypeScriptu —
potrzebują poprawnej nazwy.
| Rozszerzenie | Obsługuje | Zgłaszane jako |
|---|---|---|
.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 zgłasza definicja C/C++, a nie ta dla Objective-C — obie uruchamiają
clangd, który sam rozstrzyga, co zawiera nagłówek.
Czego każdy serwer oczekuje od projektu¶
Kilka serwerów działa poprawnie dopiero wtedy, gdy w katalogu głównym projektu leży określony plik. Gdy go brakuje, wskaźnik stanu mówi o tym wprost, zamiast udawać, że wszystko jest w porządku:
| Język | Oczekuje | Bez tego |
|---|---|---|
| Rust | Cargo.toml |
rust-analyzer w ogóle nie wczyta skrzynki. |
| Go | go.mod |
gopls nie rozwiąże modułu. |
| TypeScript | tsconfig.json (albo package.json) |
odpowiedzi obejmujące cały projekt są niedostępne. |
| JavaScript | jsconfig.json (albo package.json) |
jak wyżej. |
| Python (pyright) | pyproject.toml / pyrightconfig.json / setup.py |
pyright nadal działa; po prostu używa domyślnych korzeni importu i domyślnej surowości. |
| Java | pom.xml / build.gradle |
jdtls nie zbuduje ścieżki klas. |
| C/C++ | compile_commands.json |
patrz sekcja powyżej. |
Dodawanie języka¶
Serwery opisują pliki JSON ładowane przez wtyczkę przy starcie z
<editor>/lsp-servers/*.json oraz z Twojego
folderu. Każdy wpis mapuje język na jego
polecenie plus wskazówki wykrywania:
{
"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}"
}
languageto własny identyfikator języka w OctoEdit — klucz, wokół którego grupują się strona ustawień, segment stanu i połączenie.command/aliasesto nazwy plików wykonywalnych próbowane wPATH.extensionsto podstawowe odwzorowanie pliku na język (patrz wyżej). Z kropką.argsto jeden element tablicy na każdy argument.["--background-index", "--log=verbose"]przekazuje dwa argumenty;["--background-index --log=verbose"]przekazuje jeden argument, który zawiera spację — a taki odrzuca każdy serwer i natychmiast kończy pracę, więc wygląda to na pętlę awarii, a nie na literówkę. OctoEdit ostrzega o tym kształcie w dzienniku diagnostycznym przy wczytywaniu Twojego pliku.languageId(opcjonalny) to identyfikator wysyłany serwerowi wdidOpen; domyślnie równylanguage. Użyj go, gdy nazwa ze specyfikacji LSP różni się od naszej (bash→shellscript,objc→objective-c).languageIds(opcjonalny) nadpisujelanguageIdper rozszerzenie, dla jednego serwera obsługującego kilka języków ze specyfikacji.projectMarkers(opcjonalny) to nazwy plików, których serwer oczekuje w katalogu głównym projektu. Gdy nie ma żadnego z nich, segment stanu pokazujebrak <first marker>; nigdy nie zatrzymuje to serwera.searchDirsto lista lokalizacji instalacji dla Windows;searchDirsMacisearchDirsLinuxto jej odpowiedniki dla pozostałych systemów. Wszystkie trzy rozwijają${VAR}, a listy POSIX-owe rozwijają też wiodące~. Wpis, którego zmienne nie są ustawione, jest pomijany, a nie zamieniany w bezsensowną ścieżkę.argsmoże użyć dwóch symboli zastępczych:${dataDir}— zapisywalnego folderu danych wtyczki — oraz${rootHash}— krótkiego, stałego identyfikatora bieżącego projektu. Tak jdtls dostaje-data <dir>. Symbol, którego nie da się rozwinąć, zostaje w argumencie dosłownie, zamiast rozwinąć się w nic.compileCommandsArg(opcjonalny) jest dołączany z${dir}zastąpionym znalezionym katalogiem bazy — tak clangd zostaje skierowany nacompile_commands.json.priority(opcjonalny, domyślnie0) porządkuje kilka definicji tego samego języka: najniższa liczba jest próbowana pierwsza, a startuje pierwsza definicja, której plik wykonywalny zostanie znaleziony. Tak Python dostaje pyrighta (priority: 0) z pylsp (priority: 10) jako rozwiązaniem zapasowym.
Twoje własne definicje serwerów¶
Dołączone definicje leżą w katalogu instalacyjnym, którego nie edytujesz (Program Files w Windows, podpisany pakiet aplikacji w macOS). Swoje umieść obok nich: Preferencje ▸ Serwer językowy ▸ Otwórz folder własnych definicji serwerów tworzy i otwiera
Każdy plik *.json w tym folderze jest wczytywany po zestawie dołączonym,
przy czym:
- plik, którego
languageicommandpokrywają się z definicją dołączoną, zastępuje ją — tak zmienisz argumenty clangd albo dodasz katalog wyszukiwania; - wszystko inne jest dodawane — drugi serwer dla języka, który dostarczamy, albo język, dla którego OctoEdit nie dostarcza nic.
Plik, który nie jest poprawnym JSON-em albo nie ma language czy command,
jest pomijany i odnotowany w dzienniku diagnostycznym, zamiast po cichu
kosztować Cię język.
Definicje są czytane raz, przy starcie: po ich edycji uruchom ponownie edytor (przycisk Wyszukaj ponownie / uruchom ponownie serwery ponawia wyszukiwanie, a nie wczytanie).
{
"language": "zig",
"command": "zls",
"extensions": [".zig", ".zon"],
"projectMarkers": ["build.zig"],
"searchDirs": ["${LOCALAPPDATA}/zls"],
"searchDirsMac": ["/opt/homebrew/bin", "~/.local/bin"],
"searchDirsLinux": ["~/.local/bin"]
}
Który folder dostaje serwer¶
Serwer języka musi wiedzieć, gdzie jest projekt: rust-analyzer bez tego nie
wczyta skrzynki, gopls potrzebuje korzenia modułu, pyright czyta stamtąd
pyrightconfig.json, a clangd szuka tam swojej bazy.
- Przy otwartym folderze (Plik ▸ Otwórz folder) pliki w nim należą do tego folderu.
- Dla pliku poza otwartym folderem albo bez otwartego folderu OctoEdit idzie
w górę od pliku, szukając
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, pliku.sln,.git, a na końcu.editorconfigzroot = true. Awaryjnie służy katalog samego pliku, więc serwer nigdy nie zostaje bez projektu. - Otwarcie folderu po pliku działa. Serwery rozumiejące zmiany folderów roboczych dostają o nich powiadomienie; pozostałe są restartowane, a otwarte dokumenty zgłaszane im automatycznie. Ręczny restart nie jest potrzebny.
Rozwiązywanie problemów¶
| Objaw | Co sprawdzić |
|---|---|
Segment LSP: w ogóle się nie pojawia |
Żadna definicja serwera nie zgłasza rozszerzenia tego pliku. Sprawdź który serwer obsługuje który plik albo dodaj definicję. |
· serwer nie odpowiada |
Serwer przestał odpowiadać. Pokaż dziennik serwera językowego, potem Uruchom ponownie serwery językowe. |
✗ dla języka, dla którego zainstalowałeś serwer |
Potwierdź, że plik wykonywalny naprawdę tam jest: where clangd (Windows) / which clangd (macOS, Linux). Potem Szukaj ▸ Nawigacja po kodzie ▸ Uruchom ponownie serwery językowe, co powtarza całe wyszukiwanie. |
⚠ |
Serwer wystartował, a potem ciągle się wywalał. Pokaż dziennik serwera językowego zwykle nazywa przyczynę; napraw ją i zrestartuj serwery. |
· brak bazy kompilacji w projekcie C/C++ |
Patrz wyżej. Znajdź odwołania i Zmień nazwę do tego czasu widzą tylko otwarty plik. |
| Uzupełnianie nic nie zwraca w jednym pliku C++ | Tego pliku najpewniej nie ma w compile_commands.json (nagłówek, którego nie włącza żadna jednostka translacji, albo plik dodany po wygenerowaniu bazy). Wygeneruj ją ponownie. |
| Z terminala działa wszystko, z Findera nie | Zgłoś to — odczyt PATH z powłoki logowania ma zrównywać oba przypadki. Pokaż dziennik serwera językowego i log Diagnostyki notują, co było przeszukiwane. |
| Serwer wymaga pliku projektu, którego nie masz | typescript-language-server potrzebuje pakietu typescript, gopls go.mod, rust-analyzer Cargo.toml, a pyright pyrightconfig.json/pyproject.toml do odpowiedzi obejmujących cały projekt. |
Ustawienia serwera języka¶
Preferencje ▸ Serwer językowy wymienia każdy język z istniejącą definicją serwera. Per język możesz:
- Włączyć / wyłączyć serwer (wyłączony język nigdy go nie uruchamia).
- Ustawić jawną ścieżkę pliku wykonywalnego (z Przeglądaj…). To
nadpisanie wygrywa z powyższym wyszukiwaniem
PATH/searchDirs— przydatne, gdy serwera nie ma wPATHalbo chcesz konkretny build. - Dodać Dodatkowe argumenty, doklejane po własnych argumentach definicji —
na przykład
--log=verbosedla clangd. Wiersz jest dzielony jak wiersz poleceń, więc wartość ze spacjami ujmij w cudzysłów.
Pole ścieżki to ścieżka, nie wiersz poleceń
Wpisanie C:\tools\clangd.exe --log=verbose w Ścieżkę pliku
wykonywalnego każe OctoEdit szukać pliku, którego nazwa kończy się na
.exe --log=verbose — taki nie istnieje, więc język zgłasza brak serwera.
Plik wykonywalny wpisz w pole ścieżki, a jego argumenty w Dodatkowe
argumenty. Jeśli mimo to tak się stanie, dziennik diagnostyczny mówi to
wprost.
Zmiany działają po OK / Zastosuj: jeśli którakolwiek flaga włączenia lub ścieżka faktycznie się zmieniła, serwery restartują się z nowymi ustawieniami automatycznie (niedotknięta strona nigdy nie rusza działających serwerów). Przycisk Przeskanuj / zrestartuj serwery dodatkowo wymusza zatrzymanie i ponowne wykrycie z bieżącymi ustawieniami — przydatne po instalacji serwera, którego edytor wcześniej nie znajdował; resetuje też budżet restartów po awarii.
Otwórz folder własnych definicji serwerów tworzy i otwiera folder opisany w Twoje własne definicje serwerów.
Ograniczenia¶
- Kolorowanie kodu w dymkach nie jest stosowane (tekst jest formatowany — pogrubienia, nagłówki, kod o stałej szerokości — ale bez kolorowania składni).
- Dokładność zależy od serwera: dla C/C++ bez
compile_commands.jsonclangd wraca do heurystyk i wyniki mogą być niepełne. - OctoEdit nigdy nie instaluje ani nie pobiera serwera. Znajduje ten, który zainstalowałeś, i go uruchamia; gdy żadnego nie ma, funkcja pozostaje ciemna, a segment stanu to pokazuje.
- Jeden proces serwera na język, wspólny dla wszystkich otwartych projektów tego języka. Drugi projekt jest dodawany jako folder roboczy, jeśli serwer to obsługuje; w przeciwnym razie jest obsługiwany w korzeniu pierwszego projektu.
- Kotlin, Swift i Objective-C mają inteligencję kodu, ale nie mają kolorowania składni — edytor nie ma dla nich jeszcze kolorowania. Obie rzeczy są teraz niezależne, więc serwer działa mimo to.
- Definicje serwerów są czytane raz, przy starcie; ich edycja (Twoich lub dołączonych) wymaga ponownego uruchomienia edytora.