Přeskočit obsah

Zásuvný modul LSP (jazykový server)

Inteligence kódu poháněná protokolem Language Server Protocol — vlnovky u chyb, navigace, nápovědy při najetí, dokončování, nápověda k signaturám, formátování, hledání odkazů, přejmenování a přechod na symbol — pro každý jazyk, který má jazykový server. Editor s ním komunikuje přes LSP; modul je klient. Které servery existují, určují data (jeden malý JSON na jazyk), takže C++/clangd níže je jen jednou z několika dodávaných definic.

Editor servery nedodává ani nestahuje

Jazykový server je samostatný program, který si jednou nainstalujete. MTE nainstalovaný server rozpozná a nasměruje jej na váš projekt; sám žádný nedodává. Viz Jak získat jazykový server.

Současné funkce

Funkce Jak
Diagnostika Chyby a varování od serveru se objevují jako vlnovkovitá podtržení (červené = chyba, jantarové = varování, modré = informace, šedé = nápověda), aktualizovaná při psaní.
Přejít na definici Umístěte kurzor na symbol a stiskněte F12, nebo použijte Hledat ▸ Navigace v kódu ▸ Přejít na definici. Skočí na definici a v případě potřeby otevře jiný soubor.
Najít odkazy Kurzor na symbolu → Shift+F12 (nebo Hledat ▸ Navigace v kódu ▸ Najít odkazy). Výsledky se otevřou ve spodním panelu Odkazy, seskupené podle souborů s náhledem zdrojového řádku; dvojklikem skočíte.
Nápověda při najetí Podržte ukazatel nad symbolem; vyskakovací okno ukáže jeho typ či signaturu a dokumentaci (vykreslenou z Markdownu od serveru).
Dokončování Ctrl+Space si vyžádá dokončení od serveru a vloží je do nabídky dokončování editoru (před vestavěné návrhy z klíčových slov a slov v bufferu), filtrovaná během psaní.
Nápověda k signaturám Napsání ( nebo , ve volání zobrazí tip s podpisem funkce a zvýrazněným aktivním parametrem; ) jej zavře.
Formátovat dokument Alt+Shift+F (⌃⌥F na macOS; nebo Úpravy ▸ Formátovat dokument) přeformátuje celý dokument prostřednictvím serveru, v jediném kroku zpět. Styl řídí vlastní konfigurace serveru (u clangd soubor .clang-format).
Najít odkazy (uvedeno výše) —
Přejmenovat symbol Kurzor na symbolu → Shift+F6 (nebo Úpravy ▸ Přejmenovat symbol). Zadejte nový název; každé použití se aktualizuje. Když přejmenování zasahuje do několika souborů, budete nejprve požádáni o potvrzení — každý soubor se otevře, změní a zůstane změněný, abyste jej zkontrolovali a uložili.
Přejít na symbol (v souboru) Ctrl+Shift+O otevře Paletu příkazů se seznamem každého symbolu v aktuálním souboru (funkce, třídy, metody…); psaním filtrujete, Enter skočí. Každý řádek ukazuje druh symbolu a jeho kontejner.
Přejít na symbol v pracovním prostoru Ctrl+T hledá během psaní symboly v celém projektu (dotaz vyhodnocuje server); Enter otevře soubor na místě symbolu.

Výběry pro přechod na symbol jsou symbolové režimy Palety příkazů — viz Paleta příkazů.

Příkazy jsou zašedlé, dokud server neběží

Přejít na definici, Najít odkazy, Formátovat dokument a Přejmenovat symbol jsou dostupné, jen když je jazykový server pro jazyk aktuálního souboru připraven — a když onen server ve svém úvodním pozdravu ohlásil, že daný požadavek podporuje. U souboru bez nastaveného serveru, nebo zatímco se nějaký spouští, restartuje či to vzdal, jsou položky nabídky zašedlé, místo aby po stisku neudělaly nic. Který z těchto stavů nastal, říká níže popsaný ukazatel stavu. Restartovat jazykové servery zašedlé nikdy není: je to cesta ven ze serveru, který to vzdal.

Odkazy napříč soubory a přejmenování potřebují index serveru

Najít odkazy a Přejmenovat dosáhnou na ostatní soubory, teprve až server projekt zaindexuje. U C/C++ to znamená compile_commands.json (viz níže) a index clangd na pozadí; bez něj pracují pouze s aktuálním souborem.

Přejmenování má zatím krok zpět po souborech

Přejmenování napříč soubory se uplatňuje soubor po souboru, takže každý soubor je vlastním krokem zpět (potvrzovací okno to říká). Než uložíte, změněné karty si projděte.

V místní nabídce editoru

Klikněte pravým tlačítkem na symbol v textu a nabídka pod editačními příkazy nabídne Přejít na definici, Najít odkazy, Přejmenovat symbol a Formátovat dokument. Každá položka se objeví jen tehdy, když by stejný příkaz v hlavní nabídce právě teď fungoval — jazykový server pro soubor je připravený a příkaz podporuje a u přejmenování a formátování dokument není jen pro čtení. V prostém textovém souboru, v okraji nalevo od textu nebo během spouštění serveru se neobjeví žádná z nich.

Položky působí na symbol, na který jste klikli pravým tlačítkem, ne na symbol pod kurzorem; kurzor i výběr zůstanou, kde byly. Přejmenování navrhne jako starý název výběr, pokud jste klikli dovnitř něj, a jinak slovo pod ukazatelem. Formátovat dokument vždy formátuje celý dokument. Nabídka otevřená z klávesnice působí na pozici kurzoru.

Tam, kde platforma v místních nabídkách zobrazuje klávesové zkratky (Windows), ukazuje každá položka svou zkratku — tu, která právě platí, včetně vašich vlastních změn v Mapování klávesových zkratek. V macOS místní nabídky zkratky nezobrazují.

Jak se vaše úpravy dostanou k serveru

Psaní neposílá zprávu na každý stisk klávesy. Úpravy se na zlomek vteřiny slučují a pak se posílají jako jedna změna — a to jako jediný upravený rozsah, nikoli celý soubor, kdykoli server řekne, že to zvládne (většina ano). Velký soubor tak stojí několik desítek bajtů na každý nával psaní místo své vlastní kopie.

Cokoli, co se serveru na text ptá — nápověda při najetí, přechod na definici, hledání odkazů, přejmenování, formátování, dokončování, nápověda k signaturám — nejprve odešle čekající úpravu, takže se odpověď nikdy netýká verze, kterou už máte za sebou. Uložení souboru dělá totéž.

Ani spuštění serveru editor neblokuje: proces se spustí na pozadí a stavová část ukazuje …, dokud nedokončí úvodní pozdrav. Binárka serveru, která při startu zamrzne, vás nestojí nic kromě onoho jazyka.

Strop na počet vykreslených problémů

Na dokument se vykreslí nanejvýš 2000 vlnovek. Za touto hranicí je soubor stejně nečitelný a každá další značka stojí editor skutečný čas — takže když soubor vyprodukuje víc, zobrazí se prvních 2000 a stavový řádek řekne Zobrazuje se prvních 2000 z N problémů v tomto souboru, místo aby se počet tiše jevil menší, než je. Obvykle je to známka toho, že se server na soubor dívá špatně: chybějící databáze překladu, nebo generovaný soubor, který se ani nemá sám o sobě přeložit.

Ukazatel stavu serveru

Stavový řádek zobrazuje úspornou část LSP: (nalevo od ostatních částí zásuvných modulů), která shrnuje každý jazykový server týkající se vašich otevřených souborů:

LSP: cpp ✓ · no compile database  python ↻2  rust ✗
Znak Význam
… Spouští se — server byl spuštěn a vyměňuje si úvodní pozdrav.
✓ Připraven — obsluhuje požadavky.
↻n Restartuje se — server se nečekaně zastavil; je naplánován automatický pokus o restart číslo n.
✗ Pro tento jazyk není nainstalován žádný server. Nainstalujte jej (viz níže) a pak použijte Restartovat jazykové servery.
⚠ Vzdal to — server opakovaně padal a automatické restarty skončily. Oživí jej jedině ruční restart.

Jazyk může za znakem nést krátký upřesňující údaj — server běží a něco ve vašem projektu přesto omezuje, na co umí odpovědět. Zobrazuje se vždy jen jeden, ten nejzávažnější první:

Upřesnění Význam
· server neodpovídá Několik požadavků po sobě zůstalo bez odpovědi. Server žije, ale zasekl se; použijte Zobrazit protokol jazykového serveru a pak Restartovat jazykové servery. Upřesnění zmizí ve chvíli, kdy server na cokoli odpoví.
· žádná databáze překladu Server pro C/C++ běží, ale vidí pouze soubor, který máte otevřený — viz Projekty C/C++ potřebují compile_commands.json.
· žádný Cargo.toml, · žádný go.mod, · žádný tsconfig.json, … Projekt nemá žádný ze souborů, které tento server potřebuje, aby mu rozuměl jako projektu. Nad otevřeným souborem stále funguje; odpovědi napříč soubory budou neúplné, dokud soubor nevznikne. Přesný název je ten, který server nejvíc chce — viz Co který server od vašeho projektu potřebuje.

Část se objeví, když se otevře první dokument s nastaveným jazykem, sleduje jen ty jazyky, pro které skutečně máte otevřené dokumenty — zavřením posledního souboru daného jazyka jeho položka zmizí (otevřením dalšího se okamžitě vrátí) — a skryje se úplně, když žádný takový dokument nezbude.

Hledat ▸ Navigace v kódu ▸ Zobrazit protokol jazykového serveru zobrazí nejnovější výstup každého běžícího serveru. Tam se server vysvětluje: chybějící sada nástrojů, nečitelný konfigurační soubor, projekt, který odmítl načíst. Okno je běžné okno s měnitelnou velikostí — každý jazyk je nadpisem pojmenovávajícím server, který pro něj běží, text lze vybírat, Kopírovat vloží celý protokol do schránky a velikost, kterou oknu dáte, se zapamatuje.

Když server spadne

Jazykový server, který nečekaně skončí, se automaticky restartuje s rostoucí prodlevou (1 s, 2 s, 4 s… se stropem 30 s). Zatímco se to děje, ukazatel zobrazuje ↻n a oznámení ve stavovém řádku hlásí první pád. Po úspěšném restartu se vaše otevřené dokumenty serveru znovu ohlásí a diagnostika se vrátí sama; zastaralé vlnovky z mrtvého serveru se ihned vymažou. Psaní se nikdy neblokuje.

Po 5 neúspěšných pokusech za sebou to modul vzdá: ukazatel zobrazí ✗, oznámení vás nasměruje do nastavení a jazyk zůstane tmavý, dokud jej ručně nerestartujete. Server, který alespoň minutu běžel v pořádku, dostane při pozdějším pádu čerstvou sadu pokusů.

Ruční restart — jedno z:

  • Hledat ▸ Navigace v kódu ▸ Restartovat jazykové servery (bez výchozí zkratky; dostupné i z Palety příkazů), nebo
  • tlačítko Znovu prohledat / restartovat servery v Předvolby ▸ Jazykový server.

Chcete-li před restartem zjistit, proč je server nespokojený, použijte Hledat ▸ Navigace v kódu ▸ Zobrazit protokol jazykového serveru.

Obojí strhne každý server, znovu spustí hledání s aktuálním nastavením a vynuluje rozpočet selhání — použijte je po instalaci chybějícího serveru nebo po opravě rozbitého.

Jak získat jazykový server

Nainstalujte server pro svůj jazyk a zajistěte, aby byl ve vaší PATH (nebo nastavte výslovnou cestu v nastavení). Nenajde-li se žádný, funkce pro daný jazyk prostě nedělá nic — ukazatel stavu zobrazí ✗ a protokol zaznamená jednorázovou nápovědu, ale nic vás nevyruší.

MTE dodává definice serverů (nikoli servery) pro řadu jazyků, takže většinou stačí server nainstalovat — bez úprav JSON. Dodávané definice pokrývají C/C++, Objective-C, Python, Rust, Go, TypeScript, JavaScript, C#, Javu, Kotlin, Swift, HTML, CSS/SCSS/Less, JSON, YAML a shellové skripty.

Jazyk Server Kde jej získat
C/C++ clangd winget install LLVM.LLVM (Windows), komponenta »C++ Clang tools« v instalátoru Visual Studia, brew install llvm (macOS), nebo balíček clang-tools-extra vaší distribuce.
Python pyright nebo pylsp npm i -g pyright (vyžaduje Node.js), nebo pip install python-lsp-server (vyžaduje jen 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 nebo OmniSharp dotnet tool install -g csharp-ls (jediný nástroj dotnet, zkoušený první), nebo stáhněte vydání OmniSharpu.
Java jdtls (Eclipse JDT Language Server) brew install jdtls (macOS), nebo rozbalte vydání a jeho bin dejte do své PATH.

Ověřte to v terminálu, například clangd --version nebo where clangd / which clangd. Pro jazyk, pro který MTE definici nedodává, ji přidejte podle části Přidání jazyka.

Python: pyright, nebo pylsp

Python má dvě dodávané definice a OctoEdit spustí tu, která je skutečně nainstalovaná:

  1. pyright (pyright-langserver) se zkouší první. Je to balíček npm, takže potřebuje Node.js: npm i -g pyright.
  2. pylsp (python-lsp-server) se použije, když se pyright nenajde. Je to balíček pip a potřebuje pouze Python: pip install python-lsp-server.

Jsou-li nainstalované oba, vyhrává pyright. Pro Python je jediný řádek nastavení (jeden příznak zapnutí, jedno přebití cesty) a platí pro server, který se použije — nastavení výslovné cesty ke spustitelnému souboru pylsp spustí pylsp s jeho spouštěcími argumenty, nikoli s těmi od pyrightu. Zobrazit protokol jazykového serveru pojmenuje server, který skutečně běží.

Několik serverů pro jeden jazyk

Jde o obecný mechanismus, nikoli o zvláštní případ Pythonu: jazyk může mít libovolný počet dodávaných definic, seřazených polem priority, a spustí se první z nich, jejíž spustitelný soubor se na vašem stroji najde. C# funguje stejně — nejprve csharp-ls, pak OmniSharp — protože oba přijímají jiné spouštěcí argumenty a správný může být jen jeden.

Java: vlastní pracovní prostor serveru

jdtls se odmítá spustit bez vlastního zapisovatelného adresáře pracovního prostoru (-data). OctoEdit jej dodává automaticky, pro každý projekt zvlášť, ve své datové složce modulu:

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

Nikdy jej nemusíte vytvářet ani pojmenovávat. Smazání složky je bezpečné — jdtls ji znovu vytvoří, za cenu jednoho opětovného zaindexování.

Nastavení ve Windows

Čerstvý stroj s Windows obvykle nemá ve své PATH žádný z nástrojů clangd, cmake, ninja, node či python. Tato část říká, odkud každý z nich pochází a jak jej ověřit. PATH si obvykle upravovat nemusíte — OctoEdit prohledává i níže uvedené ekosystémové adresáře.

Chcete Nainstalujte Kde to přistane
clangd (C/C++) winget install LLVM.LLVM C:\Program Files\LLVM\bin\clangd.exe
cmake a ninja Komponenta »C++ CMake tools for Windows« v instalátoru Visual Studia …\Microsoft Visual Studio\2022\<edition>\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin a …\CMake\Ninja — nejsou ve vaší PATH, ale jsou dosažitelné přes vývojářské prostředí Visual Studia (viz níže). Samostatné winget install Kitware.CMake / winget install Ninja-build.Ninja je místo toho umístí do PATH.
pyright (Python) winget install OpenJS.NodeJS.LTS, pak npm i -g pyright %APPDATA%\npm\pyright-langserver.cmd
pylsp (Python, bez Node) Python z Microsoft Storu nebo z python.org, pak pip install python-lsp-server %LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.3.*_*\LocalCache\local-packages\Python3*\Scripts\pylsp.exe (Store) nebo %APPDATA%\Python\Python3*\Scripts\pylsp.exe

Kontrola toho, co je vidět. V běžném příkazovém řádku nebo v PowerShellu:

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

where prohledává pouze vaši PATH. Nástroj, který nenajde, může OctoEdit přesto najít, protože hledání pokrývá i výše uvedené ekosystémové adresáře — adresáře se skripty Pythonu zvlášť nikdy v PATH nejsou. Zůstane-li jazyk po instalaci svého serveru na ✗, použijte Hledat ▸ Navigace v kódu ▸ Restartovat jazykové servery, což celé hledání spustí znovu.

Generování databáze překladu běží uvnitř vývojářského prostředí Visual Studia. Když za vás OctoEdit spouští CMake (viz níže), nejprve najde Visual Studio — přes VSINSTALLDIR, jinak přes vswhere.exe — a volání obalí do VsDevCmd.bat -arch=x64 oné instalace. Právě to dá do cesty cl, sadu Windows SDK i vlastní cmake/ninja Visual Studia pro ten jediný příkaz, takže je editor ve vaší PATH vůbec nepotřebuje. Bez Visual Studia (stroj jen s clangem nebo s MinGW) se volání provede prostě v prostředí samotného editoru a protokol to řekne; pak potřebujete mít cmake a ninja dosažitelné sami a překladač, který CMake dokáže rozpoznat.

Generování na vyžádání. Hledat ▸ Navigace v kódu ▸ Vygenerovat databázi překladu… spustí totéž generování kdykoli — včetně případu, kdy databáze už existuje (nakonfiguruje se na místě), i když jste dřív odpověděli U tohoto projektu se neptat. Položka je vždy dostupná — když generovat nemůže, řekne proč ve stavovém řádku (žádný dokument C/C++, žádná složka projektu, žádný CMakeLists.txt v kořeni projektu, žádný cmake, nebo zde žádný generátor, který umí export), místo aby byla zašedlá z důvodu, který nevidíte.

Kde se uchovává odpověď »neptat se«. U tohoto projektu se neptat se uchovává pro každý kořen projektu v %APPDATA%\7-bits\OctoEdit.ini, pod plugins/org.mte.lsp/noCompileDbPrompt/<hash> (cesta projektu se hashuje, protože cesta není platným klíčem nastavení). Spuštění Vygenerovat databázi překladu… ji pro daný projekt zruší.

Kde OctoEdit server hledá

Nic byste nastavovat neměli. Po instalaci serveru stačí otevřít složku a zdrojový soubor. Editor zkouší v tomto pořadí:

  1. výslovnou cestu, kterou jste nastavili v nastavení — je závazná: pokud se nevyhodnotí, zůstane jazyk tmavý, místo aby se tiše vrátil k něčemu jinému;
  2. vaši PATH, pro příkaz serveru a každý známý alias (clangd-20, clangd-19, …);
  3. umístění instalace uvedená v definici serveru pro váš operační systém;
  4. vestavěný seznam ekosystémových adresářů.
Prohledávané ekosystémové adresáře
Windows globální prefix npm a %APPDATA%\npm, %LOCALAPPDATA%\Microsoft\WinGet\Links, %USERPROFILE%\.cargo\bin, %USERPROFILE%\go\bin a %LOCALAPPDATA%\go\bin, %USERPROFILE%\.dotnet\tools, %ProgramFiles%\LLVM\bin, %ProgramFiles%\nodejs a adresáře se skripty Pythonu pro uživatele: %APPDATA%\Python\Python3*\Scripts, %LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.3.*_*\LocalCache\local-packages\Python3*\Scripts (Python z Microsoft Storu) a %LOCALAPPDATA%\Programs\Python\Python3*\Scripts
macOS /opt/homebrew/bin a /opt/homebrew/opt/llvm/bin (clangd z Homebrew bydlí v tom druhém — do prvního se nikdy nelinkuje), /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 a tytéž ~/.cargo/bin, ~/go/bin, ~/.local/bin, ~/.npm-global/bin, ~/.dotnet/tools

Položky s * jsou skutečné zástupné znaky: adresář s verzí, který Python vytvoří (Python313, 3.13, nebo …Python.3.13_qbz5n2kfra8p0 ze Storu), se porovná s tím, co je skutečně na disku, od nejnovějšího. Právě tam pip install python-lsp-server umístí pylsp, a proto jeho instalace nevyžaduje žádnou úpravu PATH.

macOS: spuštění z Finderu versus z terminálu

Aplikace spuštěná z Finderu nebo z Docku nedědí PATH z profilu vašeho shellu — macOS jí dá minimální (/usr/bin:/bin:/usr/sbin:/sbin). Homebrew, Cargo, Go i npm by byly neviditelné. OctoEdit se proto zeptá vašeho přihlašovacího shellu, jakou má PATH, a prohledá i tu, a výsledné prostředí předá serveru, který spustí — takže server nainstalovaný kterýmkoli z těchto nástrojů se najde, ať editor spustíte jakkoli.

Server se spouští jednou na jazyk a vypíná se s editorem.

Projekty C/C++ potřebují compile_commands.json

clangd rozumí vašemu kódu přesně, jen když zná příznaky překladu, a to z databáze překladu (compile_commands.json). Bez ní clangd hádá a funkce napříč soubory (hledání odkazů, přejmenování) zůstávají omezené na otevřený soubor. clangd se přesto spustí tak či tak.

Projekt C/C++ se považuje za nastavený, když má cokoli z tohoto:

  • compile_commands.json v kořeni projektu nebo v některém z adresářů sestavení, které OctoEdit prohledává (build/, Build/, out/, out/build/, cmake-build-debug/, cmake-build-release/, .mte-compile-commands/);
  • compile_flags.txt v kořeni projektu;
  • konfigurační soubor .clangd v kořeni projektu.

Poslední dva si clangd načte sám, takže se k nim nic nehlásí.

Když není přítomno nic z toho — u každého projektu C/C++, ať používá jakýkoli systém sestavení — zobrazí stavová část · žádná databáze překladu a zpráva ve stavovém řádku to jednou řekne. Nic se neblokuje; žádné okno vaše psaní nepřeruší.

Nechat OctoEdit, aby ji vygeneroval (projekty CMake)

Má-li kořen projektu CMakeLists.txt a CMake, který by databázi skutečně vytvořil, dostanete jednou na projekt tuto nabídku:

  • Vygenerovat — spustí CMake na pozadí, pouze konfiguraci: nic se nepřekládá a vaše vlastní adresáře sestavení zůstanou nedotčené. Výsledek jde do <project>/.mte-compile-commands/. Při úspěchu se clangd restartuje proti nové databázi; při selhání se zobrazí poslední řádky protokolu CMake spolu s přesným příkazem, který byl zkoušen, abyste jej mohli zopakovat sami.
  • Jak to udělat ručně — ukáže tentýž příkaz, aniž by jej spustil.
  • U tohoto projektu se neptat — pamatuje se pro každý kořen projektu.

Jak okno »jak to udělat ručně«, tak okno se selháním ukazují přesnou příkazovou řádku ve vybíratelném rámečku s kódem, nad jediným tlačítkem Kopírovat, jehož nápověda říká, co zkopíruje: samotný příkaz, nebo příkaz spolu s koncem protokolu CMake, pokud nějaký je. Okno se selháním má měnitelnou velikost a pamatuje si velikost, kterou mu dáte — každé z těchto oken si pamatuje vlastní velikost, takže zvětšení protokolu serveru nezpůsobí, že se okno se dvouřádkovým pokynem otevře stejně veliké.

Nejste omezeni na tu jedinou nabídku: Hledat ▸ Navigace v kódu ▸ Vygenerovat databázi překladu… spustí totéž generování, kdykoli chcete — po přidání souborů, po změně voleb sestavení, nebo poté, co jste odpověděli U tohoto projektu se neptat (což se tím zruší). Existující databáze se nakonfiguruje na místě. Položka je vždy dostupná; když generovat nemůže, řekne proč ve stavovém řádku.

Vaše předvolby mají přednost. Má-li projekt CMakePresets.json (nebo CMakeUserPresets.json), nakonfiguruje OctoEdit vaší předvolbou, místo aby si příkazovou řádku vymýšlel — cmake --preset <name> -B <project>/.mte-compile-commands -DCMAKE_EXPORT_COMPILE_COMMANDS=ON. Tím jsou generátor, sada nástrojů i blok environment z předvolby (QT6_DIR, cesta k SDK) ty, na které projekt už spoléhá, a CMake je uplatní sám. Předvolby, které jsou skryté, které condition na vašem operačním systému vylučuje, nebo které konfigurují generátorem neschopným exportu, se přeskočí; upřednostní se název obsahující debug. Vašeho vlastního adresáře sestavení se to nikdy nedotkne — editor výstup vždy přesměruje přes -B.

Ve Windows se CMake spouští uvnitř vývojářského prostředí Visual Studia. Editor spuštěný z Průzkumníka nebo z nabídky Start nemá ve své PATH žádný cl a CMake by se pak tiše spokojil s jakýmkoli jiným překladačem, který najde — včetně toho clang.exe, který se dodává uvnitř instalace Visual Studia a který okamžitě selže na nastaveních specifických pro MSVC. OctoEdit proto najde Visual Studio pomocí vswhere a volání obalí do VsDevCmd.bat -arch=x64. Není-li nainstalováno žádné Visual Studio (stroj s MinGW nebo jen s clangem), provede se volání prostě a protokol to řekne.

Předchozí neúspěšný pokus se před dalším pokusem uklidí: jeho CMakeCache.txt by jinak připnul překladač, který selhal. Adresář, který už obsahuje funkční compile_commands.json, se nakonfiguruje na místě, nikdy se nesmaže.

Proč se nabídka někdy neobjeví

CMAKE_EXPORT_COMPILE_COMMANDS respektují pouze generátory Ninja a Makefile; generátor Visual Studio jej ignoruje a žádnou databázi nezapíše. Takže ve Windows se u projektu bez použitelné předvolby nabídka objeví, jen když je ninja ve vaší PATH. Když jsou jedinými použitelnými předvolbami projektu ty pro Visual Studio a Ninja není k dispozici, OctoEdit řekne, která předvolba stála v cestě, místo aby nabízel spuštění něčeho, co fungovat nemohlo.

Vygenerovat ji sami (CMake)

CMAKE_EXPORT_COMPILE_COMMANDS respektují pouze generátory Ninja a Makefile — generátor Visual Studio jej ignoruje (žádný compile_commands.json nevytvoří, ani když příznak nastavíte). Databázi proto generujte pomocí Ninjy, do vyhrazeného adresáře odděleného od toho, ve kterém běžně sestavujete: CMake odmítá překonfigurovat existující adresář sestavení jiným generátorem, takže projekt, který obvykle sestavujete pomocí Visual Studia, potřebuje vlastní adresář pro Ninju.

Je to krok pouze s konfigurací (úplné sestavení není potřeba). Z kořene projektu:

cmake -S . -B .mte-compile-commands -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
  • .mte-compile-commands/ je jedním z adresářů, které MTE prohledává, takže se výsledný compile_commands.json najde automaticky. Funguje i kterýkoli jiný prohledávaný adresář (build/, out/, cmake-build-*, nebo kořen projektu) — jen jej udržujte oddělený od adresáře nakonfigurovaného jiným generátorem.
  • Spusťte to z prostředí, v němž se projekt skutečně konfiguruje: se správným překladačem v PATH (například z x64 Native Tools Command Prompt ve Windows) a s proměnnými, které váš projekt potřebuje (jako QT6_DIR u projektu s Qt). Pokud cmake váš překladač nebo SDK nenajde, skončí databáze prázdná nebo bez cest k hlavičkám a clangd ji dobře nezaindexuje.
  • Potom složku znovu otevřete. Protokol by už neměl říkat »žádný compile_commands.json«; dejte clangd chvíli, aby si vystavěl index na pozadí, než odkazy a přejmenování zasáhnou napříč soubory.

Další systémy sestavení: Bear (bear -- make), compiledb, Meson, Bazel i další umí vytvořit compile_commands.json, který modul najde.

Který server obsluhuje který soubor

Rozhoduje název souboru. Každá definice serveru uvádí přípony, které obsluhuje, a spustí se první definice nárokující si příponu daného souboru. Porovnání ignoruje velikost písmen a počítá se jen poslední tečka — Deploy.Prod.SH je shellový skript.

Je to záměrně nezávislé na obarvování syntaxe. Vypnutí obarvování ani otevření souboru většího, než je velikostní limit obarvování, vás už nestojí i jazykový server.

Id obarvovače je stále záložním řešením

Pokud si příponu žádná definice nenárokuje, vrátí se OctoEdit k id jazyka, které přiřadil obarvovací engine. Díky tomu funguje ručně psaná definice, která jazyk pojmenuje, ale neuvádí žádné přípony.

Název, který se serveru sdělí, je druhou, samostatnou věcí: LSP má vlastní slovník id jazyků a několik z nich se s těmi v OctoEditu neshoduje. Soubor .sh se ohlašuje jako shellscript, .scss jako scss, .jsx jako javascriptreact, .mm jako objective-cpp. Servery, které se chovají podle jazyka jinak — server pro CSS, server pro TypeScript — to potřebují mít správně.

Přípona Obsluhuje Ohlašuje se 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 si nárokuje definice pro C/C++, nikoli ta pro Objective-C — obě spouštějí clangd, který si sám rozhodne, co hlavička obsahuje.

Co který server od vašeho projektu potřebuje

Několik serverů pracuje pořádně, jen když v kořeni projektu sedí konkrétní soubor. Když chybí, ukazatel stavu to řekne, místo aby předstíral, že je vše v pořádku:

Jazyk Chce Bez toho
Rust Cargo.toml rust-analyzer crate vůbec nenačte.
Go go.mod gopls nedokáže vyhodnotit modul.
TypeScript tsconfig.json (nebo package.json) odpovědi v rámci celého projektu nejsou k dispozici.
JavaScript jsconfig.json (nebo package.json) jako výše.
Python (pyright) pyproject.toml / pyrightconfig.json / setup.py pyright funguje dál; jen použije výchozí hodnoty pro kořeny importů a přísnost.
Java pom.xml / build.gradle jdtls nedokáže sestavit classpath.
C/C++ compile_commands.json viz část výše.

Přidání jazyka

Servery popisují soubory JSON, které modul načítá při spuštění z <editor>/lsp-servers/*.json, plus z vaší vlastní složky. Každá položka mapuje jazyk na jeho příkaz plus nápovědy pro hledání:

{
    "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 je vlastní id jazyka v OctoEditu — klíč, podle kterého se seskupuje stránka nastavení, stavová část i připojení. command/aliases jsou názvy spustitelných souborů zkoušené v PATH.
  • extensions je primární mapování souboru na jazyk (viz výše). Uveďte i tečku.
  • args je jeden prvek pole na argument. ["--background-index", "--log=verbose"] předá dva argumenty; ["--background-index --log=verbose"] předá jeden argument, který náhodou obsahuje mezeru, což každý server odmítne — a protože pak okamžitě skončí, vypadá výsledek jako smyčka pádů, nikoli jako překlep. OctoEdit na tento tvar při načtení vašeho souboru upozorní v diagnostickém protokolu.
  • languageId (volitelné) je id posílané serveru v didOpen; ve výchozím stavu je rovno language. Použijte jej, když se název ze specifikace LSP liší od našeho (bash → shellscript, objc → objective-c).
  • languageIds (volitelné) přebíjí languageId pro každou příponu zvlášť, u jednoho serveru obsluhujícího několik jazyků specifikace.
  • projectMarkers (volitelné) jsou názvy souborů, které server chce mít v kořeni projektu. Když tam není žádný z nich, stavová část říká žádný <first marker>; server to nikdy nezastaví.
  • searchDirs je seznam umístění instalace pro Windows; searchDirsMac a searchDirsLinux jsou jeho protějšky pro jednotlivé platformy. Všechny tři rozvíjejí ${VAR} a seznamy pro POSIX rozvíjejí i úvodní ~. Položka, jejíž proměnné nejsou nastaveny, se přeskočí, místo aby se z ní stala nesmyslná cesta.
  • args může používat dva zástupné symboly: ${dataDir}, tedy zapisovatelnou datovou složku modulu, a ${rootHash}, krátké stabilní id aktuálního projektu. Právě tak dostane jdtls -data <dir>. Zástupný symbol, který se nepodaří vyhodnotit, zůstane v argumentu doslovně, místo aby se rozvinul na nic.
  • compileCommandsArg (volitelné) se připojí, přičemž ${dir} se nahradí nalezeným adresářem databáze — tak se clangd nasměruje na compile_commands.json.
  • priority (volitelné, výchozí 0) řadí několik definic téhož jazyka: nejnižší číslo se zkouší první a spustí se první definice, jejíž spustitelný soubor se najde. Tak dostane Python pyright (priority: 0) s pylsp (priority: 10) jako záložním řešením.

Vaše vlastní definice serverů

Dodávané definice bydlí uvnitř instalačního adresáře, který není váš k úpravám (Program Files ve Windows, podepsaný balíček aplikace na macOS). Vložte své vedle nich: Předvolby ▸ Jazykový server ▸ Otevřít složku s uživatelskými definicemi serverů vytvoří a otevře

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

Každý *.json v ní se načte po dodávané sadě a:

  • soubor, jehož language i command odpovídají dodávané definici, ji nahradí — tak změníte argumenty clangd nebo přidáte adresář k prohledání;
  • cokoli jiného se přidá — druhý server pro jazyk, který dodáváme, nebo jazyk, pro který OctoEdit nedodává nic.

Soubor, který není platným JSON nebo kterému chybí language či command, se přeskočí a ohlásí v diagnostickém protokolu, místo aby vás tiše připravil o jazyk.

Definice se čtou jednou, při spuštění: po jejich úpravě editor restartujte (tlačítko Znovu prohledat / restartovat servery spustí znovu hledání, nikoli načtení).

Minimální uživatelská definice: <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"]
}

Kterou složku server dostane

Jazykový server potřebuje vědět, kde projekt je: rust-analyzer bez toho crate nenačte, gopls potřebuje kořen modulu, pyright si odtud čte pyrightconfig.json a clangd tam hledá svou databázi.

  • S otevřenou složkou (Soubor ▸ Otevřít složku) patří soubory uvnitř ní právě této složce.
  • U souboru mimo otevřenou složku, nebo když žádná složka otevřená není, stoupá OctoEdit od souboru nahoru a hledá 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, .sln, .git a konečně .editorconfig deklarující root = true. Záložním řešením je vlastní adresář souboru, takže server nezůstane bez projektu nikdy.
  • Otevřít složku až po souboru funguje. Servery, které rozumí změnám složky pracovního prostoru, se o nové složce dozvědí; ostatní se restartují a vaše otevřené dokumenty se jim automaticky znovu ohlásí. Ruční restart není potřeba.

Řešení potíží

Příznak Co zkontrolovat
Část LSP: se nikdy neobjeví Příponu tohoto souboru si nenárokuje žádná definice serveru. Podívejte se na který server obsluhuje který soubor, nebo přidejte definici.
· server neodpovídá Server přestal odpovídat. Zobrazit protokol jazykového serveru a pak Restartovat jazykové servery.
✗ u jazyka, pro který jste server nainstalovali Ověřte, že tam spustitelný soubor opravdu je: where clangd (Windows) / which clangd (macOS, Linux). Pak Hledat ▸ Navigace v kódu ▸ Restartovat jazykové servery, což celé hledání spustí znovu.
⚠ Server nastartoval a pak opakovaně padal. Zobrazit protokol jazykového serveru obvykle důvod pojmenuje; opravte jej a pak Restartovat jazykové servery.
· žádná databáze překladu u projektu C/C++ Viz výše. Najít odkazy a Přejmenovat uvidí jen otevřený soubor, dokud se to neopraví.
Dokončování u jednoho souboru C++ nic nevrací Onen soubor pravděpodobně v compile_commands.json chybí (hlavička, kterou nevkládá žádná překladová jednotka, nebo soubor přidaný až po vygenerování databáze). Vygenerujte ji znovu.
Vše funguje při spuštění z terminálu, ale ne z Finderu Nahlaste to — dohledání PATH z přihlašovacího shellu má obě cesty sjednotit. Zobrazit protokol jazykového serveru a diagnostický protokol zaznamenávají, co se hledalo.
Server potřebuje projektový soubor, který nemáte typescript-language-server potřebuje balíček typescript, gopls go.mod, rust-analyzer Cargo.toml, pyright pyrightconfig.json/pyproject.toml pro odpovědi v rámci celého projektu.

Nastavení jazykového serveru

Předvolby ▸ Jazykový server vypisují každý jazyk, pro který definice serveru existuje. U každého jazyka můžete:

  • Zapnout / vypnout server (vypnutý jazyk žádný nespouští).
  • Nastavit výslovnou cestu ke spustitelnému souboru (pomocí Procházet…). Toto přebití vyhrává nad výše popsaným hledáním v PATH a v searchDirs — užitečné, když server není v PATH nebo když chcete konkrétní sestavení.
  • Přidat Další argumenty, připojené za vlastní argumenty definice — například --log=verbose pro clangd. Řádek se dělí jako příkazová řádka, proto hodnotu obsahující mezery uzavřete do uvozovek.

Pole s cestou je cesta, nikoli příkazová řádka

Napsáním C:\tools\clangd.exe --log=verbose do pole Cesta ke spustitelnému souboru žádáte OctoEdit, aby našel soubor, jehož název končí na .exe --log=verbose, což neexistuje — jazyk pak nehlásí vůbec žádný server. Do pole s cestou dejte spustitelný soubor a jeho argumenty do Dalších argumentů. Pokud se to přesto stane, diagnostický protokol to doslova řekne.

Změny se projeví, když stisknete OK / Použít: pokud se některý příznak zapnutí nebo cesta skutečně změnily, restartují se servery s novým nastavením automaticky (nedotčená stránka běžící servery nikdy neruší). Tlačítko Znovu prohledat / restartovat servery navíc vynutí strhnutí a opětovné vyhledání s aktuálním nastavením — užitečné po instalaci serveru, který editor předtím nenašel, a zároveň vynuluje rozpočet restartů po pádu.

Otevřít složku s uživatelskými definicemi serverů vytvoří a otevře složku popsanou v části Vaše vlastní definice serverů.

Omezení

  • Obarvování kódu uvnitř vyskakovacích oken s nápovědou se neuplatňuje (text je formátovaný — tučné písmo, nadpisy, neproporcionální kód — ale není syntakticky zvýrazněný).
  • Přesnost závisí na serveru: u C/C++ se clangd bez compile_commands.json vrací k heuristikám a výsledky mohou být neúplné.
  • OctoEdit server nikdy neinstaluje ani nestahuje. Najde ten, který jste nainstalovali, a spustí jej; když žádný není, zůstane funkce tmavá a stavová část to řekne.
  • Jeden proces serveru na jazyk, sdílený každým otevřeným projektem tohoto jazyka. Druhý projekt se přidá jako složka pracovního prostoru, pokud to server podporuje; jinak se obsluhuje pod kořenem prvního projektu.
  • Kotlin, Swift a Objective-C dostávají inteligenci kódu, ale žádné obarvování syntaxe — editor pro ně zatím obarvovač nemá. Ty dvě věci jsou nyní nezávislé, takže server funguje bez ohledu na to.
  • Definice serverů se čtou jednou při spuštění; jejich úprava (vašich i dodávaných) vyžaduje restart editoru.