Plugin LSP (language server)¶
Intelligenza del codice mossa dal Language Server Protocol: ghirigori di errore, navigazione, suggerimenti al passaggio del mouse, completamento, aiuto sulla firma, formattazione, trova riferimenti, rinomina e vai al simbolo, per qualsiasi linguaggio che abbia un language server. L'editor parla con il server tramite LSP; il plugin è il client. Quali server esistono è guidato dai dati (un piccolo JSON per linguaggio), quindi C++/clangd qui sotto è solo una di diverse definizioni incluse.
L'editor non include né scarica server
Un language server è un programma separato che installi una volta. MTE rileva un server installato e lo punta al tuo progetto; non ne distribuisce mai uno. Vedi Procurarsi un language server.
Funzionalità attuali¶
| Funzionalità | Come |
|---|---|
| Diagnostiche | Errori/avvisi del server compaiono come sottolineature ondulate (rosso = errore, ambra = avviso, blu = informazione, grigio = suggerimento), aggiornate mentre digiti. |
| Vai alla definizione | Metti il cursore su un simbolo e premi F12, oppure usa Cerca ▸ Navigazione nel codice ▸ Vai alla definizione. Salta alla definizione, aprendo un altro file se serve. |
| Trova i riferimenti | Cursore su un simbolo → Shift+F12 (o Cerca ▸ Navigazione nel codice ▸ Trova i riferimenti). I risultati si aprono in un pannello inferiore Riferimenti, raggruppati per file con un'anteprima della riga sorgente; doppio clic per saltare. |
| Suggerimento al passaggio del mouse | Lascia il puntatore su un simbolo; una finestra a comparsa mostra il tipo/la firma e la documentazione (resi dal Markdown del server). |
| Completamento | Ctrl+Space richiede completamenti al server e li fonde nella finestra di completamento dell'editor (davanti ai suggerimenti integrati da parole chiave e buffer), filtrati mentre digiti. |
| Aiuto sulla firma | Digitare la ( o una , di una chiamata mostra un suggerimento con la firma della funzione e il parametro attivo evidenziato; ) lo chiude. |
| Formatta il documento | Alt+Shift+F (⌃⌥F su macOS; oppure Modifica ▸ Formatta il documento) riformatta l'intero documento tramite il server, in un unico passo di annullamento. Lo stile è retto dalla configurazione del server stesso (per clangd, un file .clang-format). |
| Trova i riferimenti (elencato sopra) | — |
| Rinomina il simbolo | Cursore su un simbolo → Shift+F6 (o Modifica ▸ Rinomina il simbolo). Inserisci un nome nuovo; ogni uso viene aggiornato. Quando la rinomina abbraccia più file ti viene chiesta prima una conferma: ogni file viene aperto, modificato e lasciato modificato perché tu lo esamini e lo salvi. |
| Vai al simbolo (nel file) | Ctrl+Shift+O apre la tavolozza dei comandi con l'elenco di ogni simbolo del file corrente (funzioni, classi, metodi…); digita per filtrare, Invio salta. Ogni riga mostra il tipo del simbolo e il suo contenitore. |
| Vai al simbolo nell'area di lavoro | Ctrl+T cerca simboli in tutto il progetto mentre digiti (è il server a fare la corrispondenza); Invio apre il file al simbolo. |
I selettori di vai-al-simbolo sono le modalità simbolo della tavolozza dei comandi: vedi Tavolozza dei comandi.
I comandi restano in grigio finché un server non è in esecuzione
Vai alla definizione, Trova i riferimenti, Formatta il documento e Rinomina il simbolo sono attivi solo quando un language server per il linguaggio del file corrente è Pronto, e quando quel server ha dichiarato nel suo saluto iniziale di supportare la richiesta. Su un file senza server configurato, o mentre uno sta partendo, riavviandosi o ha rinunciato, le voci di menu appaiono in grigio invece di non fare nulla quando le premi. L'indicatore di stato qui sotto ti dice quale dei casi sia. Riavvia i language server non va mai in grigio: è la via d'uscita da un server che ha rinunciato.
Riferimenti tra file e rinomina richiedono l'indice del server
Trova riferimenti e Rinomina raggiungono altri file solo dopo che il server ha
indicizzato il progetto. Per C/C++ questo significa un compile_commands.json
(vedi sotto) e l'indice in secondo piano di clangd; senza, operano solo sul file
corrente.
Per ora la rinomina si annulla per file
Una rinomina su più file viene applicata un file per volta, quindi ogni file è un proprio passo di annullamento (la finestra di conferma lo dice). Esamina le schede modificate prima di salvare.
Nel menu contestuale dell'editor¶
Fai clic con il tasto destro su un simbolo nel testo e il menu offre, sotto i comandi di modifica, Vai alla definizione, Trova i riferimenti, Rinomina il simbolo e Formatta il documento. Ciascuno compare solo quando lo stesso comando del menu principale funzionerebbe in quel momento: un language server per il file è pronto e lo supporta e, per Rinomina e Formatta, il documento non è in sola lettura. In un file di testo semplice, nel margine a sinistra del testo o mentre il server si sta avviando, non ne compare nessuno.
Le voci agiscono sul simbolo su cui hai fatto clic con il tasto destro, non su quello sotto il cursore; il cursore e la selezione restano dove erano. Rinomina propone la selezione come vecchio nome quando hai fatto clic al suo interno, altrimenti la parola sotto il puntatore. Formatta il documento formatta sempre l'intero documento. Un menu aperto dalla tastiera agisce sulla posizione del cursore.
Dove la piattaforma mostra le scorciatoie da tastiera nei menu contestuali (Windows), ogni voce mostra la propria scorciatoia: quella in vigore, comprese le tue modifiche nella Mappatura delle scorciatoie. Su macOS i menu contestuali non mostrano scorciatoie.
Come le tue modifiche raggiungono il server¶
Digitare non invia un messaggio per ogni tasto. Le modifiche vengono raggruppate per una frazione di secondo e poi inviate come un'unica modifica, e come un unico intervallo modificato invece dell'intero file, ogni volta che il server dichiara di poterne accettare uno (la maggior parte può). Un file grande costa quindi qualche decina di byte per raffica di digitazione invece di una copia di se stesso.
Tutto ciò che chiede al server qualcosa sul testo —suggerimento al passaggio del mouse, vai alla definizione, trova riferimenti, rinomina, formatta, completamento, aiuto sulla firma— invia prima la modifica in sospeso, così una risposta non si riferisce mai a una versione che hai già superato. Salvare un file fa lo stesso.
Avviare un server non blocca nemmeno l'editor: il processo viene lanciato in secondo
piano e il segmento di stato mostra … finché non ha completato il saluto iniziale. Un
binario di server che si blocca all'avvio non ti costa nulla oltre quel linguaggio.
Un tetto a quanti problemi vengono disegnati
Vengono disegnati al massimo 2000 ghirigori per documento. Oltre quella soglia il file è comunque illeggibile, e ogni indicatore in più costa tempo reale all'editor; quindi, quando un file ne produce di più, vengono mostrati i primi 2000 e la barra di stato dice Mostrati i primi 2000 di N problemi in questo file, invece di lasciare che il conteggio appaia in silenzio inferiore a quello che è. Di solito è segno che il server sta guardando male il file: un database di compilazione mancante, o un file generato che non è pensato per compilare da solo.
L'indicatore di stato del server¶
La barra di stato mostra un segmento compatto LSP: (a sinistra degli altri
segmenti dei plugin) che riassume ogni language server rilevante per i tuoi file
aperti:
| Glifo | Significato |
|---|---|
… |
In avvio — il server è stato lanciato e sta facendo il saluto iniziale. |
✓ |
Pronto — sta servendo le richieste. |
↻n |
In riavvio — il server si è fermato inaspettatamente; è programmato il tentativo automatico di riavvio numero n. |
✗ |
Nessun server installato per questo linguaggio. Installane uno (vedi sotto), poi usa Riavvia i language server. |
⚠ |
Ha rinunciato — il server continuava a fallire e i riavvii automatici si sono fermati. Solo un riavvio manuale lo rianima. |
Un linguaggio può portare un breve qualificatore dopo il glifo: il server è in esecuzione, e qualcosa nel tuo progetto limita ancora ciò a cui può rispondere. Ne viene mostrato uno alla volta, il più grave per primo:
| Qualificatore | Significato |
|---|---|
· server not responding |
Diverse richieste di fila sono rimaste senza risposta. Il server è vivo ma bloccato; usa Mostra il log del language server, poi Riavvia i language server. Il qualificatore sparisce nel momento in cui il server risponde a qualcosa. |
· no compile database |
Il server C/C++ è in esecuzione, ma vede solo il file che hai aperto: vedi I progetti C/C++ richiedono compile_commands.json. |
· no Cargo.toml, · no go.mod, · no tsconfig.json, … |
Il progetto non ha nessuno dei file di cui questo server ha bisogno per intenderlo come progetto. Funziona comunque sul file aperto; le risposte tra file resteranno incomplete finché quel file non esiste. Il nome esatto è quello che il server desidera di più: vedi Che cosa serve a ciascun server dal tuo progetto. |
Il segmento compare quando si apre il primo documento con un linguaggio configurato, segue solo i linguaggi di cui hai davvero documenti aperti —chiudere l'ultimo file di un linguaggio ne rimuove la voce (riaprirne uno la riporta all'istante)— e si nasconde del tutto quando non resta alcun documento del genere.
Cerca ▸ Navigazione nel codice ▸ Mostra il log del language server mostra l'output più recente di ogni server in esecuzione. È lì che un server si spiega: una catena di strumenti mancante, un file di configurazione illeggibile, un progetto che ha rifiutato di caricare. La finestra è normale e ridimensionabile: ogni linguaggio è un titolo che nomina il server in esecuzione per esso, il testo si può selezionare, Copia mette l'intero log negli appunti, e la dimensione che dai alla finestra viene ricordata.
Se un server si arresta¶
Un language server che termina inaspettatamente viene riavviato
automaticamente con un ritardo crescente (1 s, 2 s, 4 s… con un tetto di 30 s).
Mentre questo accade l'indicatore mostra ↻n e una notifica nella barra di stato
segnala il primo arresto. Dopo un riavvio riuscito i tuoi documenti aperti vengono
riannunciati al server e le diagnostiche tornano da sole; i ghirigori obsoleti del
server morto vengono cancellati subito. La modifica non viene mai bloccata.
Dopo 5 tentativi falliti di fila il plugin rinuncia: l'indicatore mostra ✗, una
notifica ti rimanda alle impostazioni, e il linguaggio resta spento finché non lo
riavvii a mano. Un server che è girato bene per almeno un minuto riceve una nuova
serie di tentativi quando si arresta più tardi.
Riavvio manuale — uno dei due:
- Cerca ▸ Navigazione nel codice ▸ Riavvia i language server (senza scorciatoia predefinita; disponibile anche nella tavolozza dei comandi), oppure
- il pulsante Nuova scansione / riavvia i server in Preferenze ▸ Server di linguaggio.
Per vedere perché un server è scontento prima di riavviarlo, usa Cerca ▸ Navigazione nel codice ▸ Mostra il log del language server.
Entrambi smontano ogni server, rieseguono il rilevamento con le impostazioni attuali e azzerano il budget di fallimenti: usali dopo aver installato un server mancante o dopo averne riparato uno rotto.
Procurarsi un language server¶
Installa il server del tuo linguaggio e assicurati che sia nel tuo PATH (oppure
imposta un percorso esplicito nelle impostazioni). Se non
ne viene trovato nessuno, la funzionalità semplicemente non fa nulla per quel
linguaggio: l'indicatore di stato mostra ✗ e il log
registra un suggerimento una volta sola, ma nulla ti interrompe.
MTE include definizioni di server (non i server) per molti linguaggi, quindi alla maggior parte basta che il server sia installato, senza modificare alcun JSON. Le definizioni incluse coprono C/C++, Objective-C, Python, Rust, Go, TypeScript, JavaScript, C#, Java, Kotlin, Swift, HTML, CSS/SCSS/Less, JSON, YAML e script di shell.
| Linguaggio | Server | Dove procurarselo |
|---|---|---|
| C/C++ | clangd | winget install LLVM.LLVM (Windows), il componente «C++ Clang tools» nell'installer di Visual Studio, brew install llvm (macOS), oppure il pacchetto clang-tools-extra della tua distribuzione. |
| Python | pyright o pylsp | npm i -g pyright (richiede Node.js), oppure pip install python-lsp-server (richiede solo 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 o OmniSharp | dotnet tool install -g csharp-ls (un unico strumento dotnet, provato per primo), oppure scarica una versione di OmniSharp. |
| Java | jdtls (Eclipse JDT Language Server) | brew install jdtls (macOS), oppure scompatta una versione e metti il suo bin nel tuo PATH. |
Verifica in un terminale, ad esempio clangd --version oppure where clangd /
which clangd. Per un linguaggio di cui MTE non include una definizione, aggiungine
una come descritto in Aggiungere un linguaggio.
Python: pyright o pylsp¶
Python ha due definizioni incluse, e OctoEdit esegue quella davvero installata:
- pyright (
pyright-langserver) viene provato per primo. È un pacchetto npm, quindi richiede Node.js:npm i -g pyright. - pylsp (
python-lsp-server) viene usato quando pyright non si trova. È un pacchetto pip e richiede solo Python:pip install python-lsp-server.
Se sono installati entrambi, vince pyright. C'è un'unica riga di impostazioni per
Python (un indicatore di attivazione, una sostituzione di percorso) e vale per
qualunque server venga usato: impostare un percorso esplicito a un eseguibile pylsp
esegue pylsp con i suoi argomenti di avvio, non quelli di pyright. Mostra il log
del language server nomina il server davvero in esecuzione.
Più server per un linguaggio
Questo è un meccanismo generale, non un caso speciale di Python: un linguaggio può
avere un numero qualsiasi di definizioni incluse, ordinate da un campo priority,
e la prima il cui eseguibile si trova sulla tua macchina è quella che parte. C#
funziona allo stesso modo —csharp-ls prima, OmniSharp poi— perché i due
ricevono argomenti di avvio diversi e solo uno può essere quello giusto.
Java: l'area di lavoro del server stesso¶
jdtls si rifiuta di partire senza una directory di area di lavoro scrivibile
propria (-data). OctoEdit ne fornisce una automaticamente, per progetto, sotto
la sua cartella dati del plugin:
Non devi mai crearla né darle un nome. Eliminare la cartella è sicuro: jdtls la ricostruisce, al costo di una reindicizzazione.
Configurazione su Windows¶
Una macchina Windows appena installata di solito non ha nessuno di clangd,
cmake, ninja, node o python nel suo PATH. Questa sezione dice da dove viene
ciascuno e come controllare. Normalmente non devi modificare tu il PATH: OctoEdit
cerca anche nelle directory di ecosistema
elencate sotto.
| Ciò che vuoi | Installa | Dove finisce |
|---|---|---|
| clangd (C/C++) | winget install LLVM.LLVM |
C:\Program Files\LLVM\bin\clangd.exe |
| cmake e ninja | Il componente «C++ CMake tools for Windows» nell'Installer di Visual Studio | …\Microsoft Visual Studio\2022\<edition>\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin e …\CMake\Ninja — non nel tuo PATH, ma raggiungibili attraverso l'ambiente di sviluppo di Visual Studio (vedi sotto). Un winget install Kitware.CMake / winget install Ninja-build.Ninja autonomo li mette invece nel PATH. |
| pyright (Python) | winget install OpenJS.NodeJS.LTS, poi npm i -g pyright |
%APPDATA%\npm\pyright-langserver.cmd |
| pylsp (Python, senza Node) | Python dal Microsoft Store o da python.org, poi pip install python-lsp-server |
%LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.3.*_*\LocalCache\local-packages\Python3*\Scripts\pylsp.exe (Store) oppure %APPDATA%\Python\Python3*\Scripts\pylsp.exe |
Controllare che cosa è visibile. In un normale Prompt dei comandi o PowerShell:
where cerca solo nel tuo PATH. Uno strumento che non trova può comunque essere
trovato da OctoEdit, perché la ricerca copre anche le directory di ecosistema qui
sopra: le directory degli script di Python, in particolare, non sono mai nel PATH.
Se un linguaggio resta a ✗ dopo aver installato il suo server, usa Cerca ▸
Navigazione nel codice ▸ Riavvia i language server, che riesegue l'intera
ricerca.
La generazione del database di compilazione gira dentro l'ambiente di sviluppo di
Visual Studio. Quando OctoEdit esegue CMake al posto tuo (sotto), prima individua
Visual Studio —tramite VSINSTALLDIR, altrimenti con vswhere.exe— e avvolge la
chiamata nel VsDevCmd.bat -arch=x64 di quell'installazione. È questo a mettere cl,
l'SDK di Windows e il cmake/ninja di Visual Studio nel percorso per quel singolo
comando, così l'editor non ha affatto bisogno che siano nel tuo PATH. Senza
Visual Studio (una macchina con solo clang o con MinGW) la chiamata viene fatta
semplicemente, nell'ambiente dell'editor stesso, e il log lo dice; ti servono allora
cmake e ninja raggiungibili per conto tuo, e un compilatore che CMake possa
identificare.
Rigenerare su richiesta. Cerca ▸ Navigazione nel codice ▸ Genera il database di
compilazione… esegue la stessa generazione in qualsiasi momento, anche quando un
database esiste già (viene riconfigurato sul posto) e quando in passato avevi risposto
Non chiedere per questo progetto. La voce è sempre disponibile: quando non può
generare, dice perché nella barra di stato (nessun documento C/C++, nessuna cartella di
progetto, nessun CMakeLists.txt nella radice del progetto, nessun cmake, o nessun
generatore qui in grado di esportarne uno) invece di restare in grigio per un motivo
che non puoi vedere.
Dove viene salvata la risposta di «non chiedere». Non chiedere per questo
progetto viene salvata per radice di progetto in %APPDATA%\7-bits\OctoEdit.ini,
sotto plugins/org.mte.lsp/noCompileDbPrompt/<hash> (il percorso del progetto viene
ridotto a hash perché un percorso non è una chiave di impostazioni valida). Eseguire
Genera il database di compilazione… la cancella per quel progetto.
Dove OctoEdit cerca un server¶
Non dovresti dover configurare nulla. Dopo aver installato un server, basta aprire una cartella e un file sorgente. In ordine, l'editor prova:
- un percorso esplicito che hai impostato nelle impostazioni — che comanda: se non si risolve, il linguaggio resta spento invece di ricadere in silenzio su qualcos'altro;
- il tuo
PATH, per il comando del server e per ogni alias noto (clangd-20,clangd-19, …); - le posizioni di installazione della definizione del server per il tuo sistema operativo;
- un elenco integrato di directory di ecosistema.
| Directory di ecosistema esaminate | |
|---|---|
| Windows | il prefisso globale di npm e %APPDATA%\npm, %LOCALAPPDATA%\Microsoft\WinGet\Links, %USERPROFILE%\.cargo\bin, %USERPROFILE%\go\bin e %LOCALAPPDATA%\go\bin, %USERPROFILE%\.dotnet\tools, %ProgramFiles%\LLVM\bin, %ProgramFiles%\nodejs, e le directory degli script di Python per utente: %APPDATA%\Python\Python3*\Scripts, %LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.3.*_*\LocalCache\local-packages\Python3*\Scripts (Python dal Microsoft Store) e %LOCALAPPDATA%\Programs\Python\Python3*\Scripts |
| macOS | /opt/homebrew/bin e /opt/homebrew/opt/llvm/bin (il clangd di Homebrew vive nel secondo: non viene mai collegato nel primo), /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, e gli stessi ~/.cargo/bin, ~/go/bin, ~/.local/bin, ~/.npm-global/bin, ~/.dotnet/tools |
Le voci con * sono veri caratteri jolly: la directory di versione che Python crea
(Python313, 3.13, oppure il …Python.3.13_qbz5n2kfra8p0 dello Store) viene
confrontata con ciò che c'è davvero su disco, dalla più recente. È lì che
pip install python-lsp-server mette pylsp, ed è per questo che installarlo non
richiede modifiche al PATH.
macOS: avviare dal Finder contro avviare da un terminale
Un'applicazione avviata dal Finder o dal Dock non eredita il PATH dal profilo
della tua shell: macOS gliene dà uno minimo (/usr/bin:/bin:/usr/sbin:/sbin).
Homebrew, Cargo, Go e npm sarebbero tutti invisibili. Per questo OctoEdit chiede
alla tua shell di accesso qual è il suo PATH e cerca anche lì, e passa
l'ambiente risultante al server che avvia: così un server installato da uno
qualsiasi di quegli strumenti si trova comunque tu avvii l'editor.
Il server viene avviato una volta per linguaggio e spento con l'editor.
I progetti C/C++ richiedono compile_commands.json¶
clangd comprende il tuo codice con precisione solo quando conosce le opzioni di
compilazione, da un database di compilazione (compile_commands.json). Senza,
clangd ricade su supposizioni e le funzionalità tra file (trova riferimenti,
rinomina) restano limitate al file aperto. clangd viene avviato comunque.
Un progetto C/C++ conta come configurato quando ha uno qualsiasi di questi:
- un
compile_commands.jsonnella radice del progetto o in una delle directory di build che OctoEdit esamina (build/,Build/,out/,out/build/,cmake-build-debug/,cmake-build-release/,.mte-compile-commands/); - un
compile_flags.txtnella radice del progetto; - un file di configurazione
.clangdnella radice del progetto.
clangd legge gli ultimi due per conto suo, quindi su di essi non viene segnalato nulla.
Quando non ce n'è nessuno —per ogni progetto C/C++, qualunque sia il suo sistema
di build— il segmento di stato mostra · no compile database e un messaggio nella
barra di stato lo dice una volta. Nulla si blocca; nessuna finestra interrompe la tua
digitazione.
Lasciare che OctoEdit lo generi (progetti CMake)¶
Se la radice del progetto ha un CMakeLists.txt e un CMake che produrrebbe
davvero un database, questo ti viene proposto una volta per progetto:
- Genera — esegue CMake in secondo piano, solo la configurazione: non viene
compilato nulla e le tue directory di build restano intatte. Il risultato va in
<project>/.mte-compile-commands/. Se riesce, clangd viene riavviato sul nuovo database; se fallisce, vengono mostrate le ultime righe del log di CMake, insieme al comando esatto che è stato tentato, così puoi ripeterlo tu. - Come farlo manualmente — mostra quello stesso comando senza eseguirlo.
- Non chiedere per questo progetto — ricordato per radice di progetto.
Sia la finestra di «come farlo a mano» sia quella di errore mostrano la riga di comando esatta in una casella di codice selezionabile, sopra un unico pulsante Copia il cui suggerimento dice che cosa porta con sé: il comando da solo, oppure il comando insieme al tratto finale del log di CMake quando c'è. La finestra di errore è ridimensionabile e ricorda la dimensione che le dai: ognuna di queste finestre ricorda la propria dimensione, così ingrandire il log del server non fa aprire altrettanto grande una finestra di istruzioni di due righe.
Non sei limitato a quell'unica proposta: Cerca ▸ Navigazione nel codice ▸ Genera il database di compilazione… avvia la stessa generazione quando vuoi —dopo aver aggiunto file, dopo aver cambiato opzioni di build, o dopo aver risposto Non chiedere per questo progetto (che così viene cancellata)—. Un database esistente viene riconfigurato sul posto. La voce è sempre disponibile; e quando non può generare, dice perché nella barra di stato.
Le tue preimpostazioni vengono prima. Se il progetto ha un CMakePresets.json (o
un CMakeUserPresets.json), OctoEdit configura con una delle tue preimpostazioni
invece di inventarsi una riga di comando:
cmake --preset <name> -B <project>/.mte-compile-commands -DCMAKE_EXPORT_COMPILE_COMMANDS=ON.
Così il generatore, la catena di strumenti e il blocco environment della
preimpostazione (un QT6_DIR, un percorso di SDK) sono quelli su cui il progetto già
fa affidamento, ed è CMake ad applicarli. Le preimpostazioni nascoste, quelle che una
condition esclude sul tuo sistema operativo, o quelle che configurano con un
generatore incapace di esportare vengono saltate; si preferisce un nome che contenga
debug. La tua directory di build non viene mai toccata: l'editor reindirizza sempre
l'output con -B.
Su Windows, CMake viene eseguito dentro un ambiente di sviluppo di Visual Studio.
Un editor avviato da Esplora risorse o dal menu Start non ha cl nel suo PATH, e
CMake si accontenterebbe allora in silenzio di qualunque altro compilatore trovi,
incluso il clang.exe che sta dentro un'installazione di Visual Studio, che fallisce
subito su impostazioni specifiche di MSVC. Per questo OctoEdit individua Visual Studio
con vswhere e avvolge la chiamata in VsDevCmd.bat -arch=x64. Se non c'è alcun
Visual Studio installato (una macchina MinGW o solo con clang) la chiamata viene fatta
semplicemente e il log lo dice.
Un tentativo fallito precedente viene ripulito prima di un nuovo tentativo: il suo
CMakeCache.txt fisserebbe altrimenti il compilatore che ha fallito. Una directory che
contiene già un compile_commands.json funzionante viene riconfigurata sul posto, mai
eliminata.
Perché a volte la proposta non compare
CMAKE_EXPORT_COMPILE_COMMANDS è rispettato solo dai generatori Ninja e
Makefile; il generatore di Visual Studio lo ignora e non scrive alcun
database. Quindi su Windows, per un progetto senza alcuna preimpostazione
utilizzabile, la proposta compare solo quando ninja è nel tuo PATH. Quando le
uniche preimpostazioni applicabili di un progetto sono di Visual Studio e non c'è
nemmeno Ninja, OctoEdit dice quale preimpostazione si è messa di traverso invece di
proporsi di eseguire qualcosa che non potrebbe funzionare.
Generarlo tu stesso (CMake)¶
CMAKE_EXPORT_COMPILE_COMMANDS è rispettato solo dai generatori Ninja e Makefile:
il generatore di Visual Studio lo ignora (non produce alcun compile_commands.json
nemmeno con l'opzione attiva). Quindi genera il database con Ninja, in una
directory dedicata, separata da quella in cui compili di solito: CMake si rifiuta
di riconfigurare una directory di build esistente con un generatore diverso, quindi un
progetto che di solito compili con Visual Studio ha bisogno di una propria directory
Ninja.
Questo è un passo di sola configurazione (non serve una compilazione completa). Dalla radice del progetto:
.mte-compile-commands/è una delle directory che MTE esamina, quindi ilcompile_commands.jsonrisultante viene trovato automaticamente. Va bene anche qualsiasi altra directory esaminata (build/,out/,cmake-build-*, o la radice del progetto): tienila solo separata da una directory configurata con un altro generatore.- Eseguilo da un ambiente in cui il progetto si configuri davvero: il compilatore
giusto nel
PATH(ad esempio un x64 Native Tools Command Prompt su Windows) e le variabili di cui il tuo progetto ha bisogno (comeQT6_DIRper un progetto Qt). Secmakenon trova il tuo compilatore o SDK, il database finisce vuoto o senza percorsi di inclusione e clangd non indicizzerà bene. - Riapri la cartella dopo. Il log non dovrebbe più dire «no compile_commands.json»; concedi a clangd un momento per costruire il suo indice in secondo piano prima che riferimenti e rinomina abbraccino più file.
Altri sistemi di build: Bear (bear -- make), compiledb, Meson, Bazel e altri
possono produrre un compile_commands.json che il plugin troverà.
Quale server serve quale file¶
Decide il nome del file. Ogni definizione di server elenca le estensioni che serve,
e la prima definizione che reclama l'estensione di un file è quella che parte. La
corrispondenza ignora maiuscole e minuscole, e conta solo l'ultimo punto:
Deploy.Prod.SH è uno script di shell.
Questo è deliberatamente indipendente dalla colorazione della sintassi. Spegnere la colorazione, o aprire un file più grande del limite di dimensione della colorazione, non ti costa più anche il language server.
L'id del colorizzatore resta una riserva
Se nessuna definizione reclama l'estensione, OctoEdit ricade sull'id di linguaggio assegnato dal motore di colorazione. Questo mantiene funzionante una definizione scritta a mano che nomina un linguaggio ma non elenca estensioni.
Il nome che viene comunicato al server è una seconda cosa, separata: LSP ha un
proprio vocabolario di id di linguaggio, e diversi non coincidono con quelli di
OctoEdit. Un file .sh viene annunciato come shellscript, uno .scss come scss,
uno .jsx come javascriptreact, uno .mm come objective-cpp. I server che si
comportano diversamente a seconda del linguaggio —il server CSS, quello TypeScript—
hanno bisogno che questo sia corretto.
| Estensione | Servita da | Annunciata come |
|---|---|---|
.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 |
Il .h è reclamato dalla definizione C/C++ e non da quella Objective-C: entrambe
eseguono clangd, che decide da sé che cosa contiene un'intestazione.
Che cosa serve a ciascun server dal tuo progetto¶
Diversi server funzionano bene solo quando un file preciso si trova nella radice del progetto. Quando manca, l'indicatore di stato lo dice invece di far finta che vada tutto bene:
| Linguaggio | Vuole | Senza di esso |
|---|---|---|
| Rust | Cargo.toml |
rust-analyzer non caricherà affatto il crate. |
| Go | go.mod |
gopls non riesce a risolvere il modulo. |
| TypeScript | tsconfig.json (o package.json) |
le risposte di ambito progetto non sono disponibili. |
| JavaScript | jsconfig.json (o package.json) |
come sopra. |
| Python (pyright) | pyproject.toml / pyrightconfig.json / setup.py |
pyright funziona comunque; usa solo valori predefiniti per le radici di importazione e il rigore. |
| Java | pom.xml / build.gradle |
jdtls non riesce a costruire un classpath. |
| C/C++ | compile_commands.json |
vedi la sezione qui sopra. |
Aggiungere un linguaggio¶
I server sono descritti da file JSON che il plugin carica all'avvio da
<editor>/lsp-servers/*.json, più la tua cartella.
Ogni voce associa un linguaggio al suo comando, più suggerimenti per il rilevamento:
{
"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è l'id che OctoEdit dà al linguaggio: la chiave per cui sono raggruppati la pagina delle impostazioni, il segmento di stato e la connessione.command/aliasessono i nomi di eseguibile provati nelPATH.extensionsè la mappatura principale da file a linguaggio (vedi sopra). Includi il punto.argsprevede un elemento dell'array per argomento.["--background-index", "--log=verbose"]passa due argomenti;["--background-index --log=verbose"]passa un argomento che per caso contiene uno spazio, cosa che ogni server rifiuta; e poiché esso termina subito, il risultato sembra un ciclo di arresti invece di un refuso. OctoEdit avvisa di quella forma nel log di diagnostica quando carica il tuo file.languageId(facoltativo) è l'id inviato al server indidOpen; per impostazione predefinita assume il valore dilanguage. Usalo quando il nome della specifica LSP differisce dal nostro (bash→shellscript,objc→objective-c).languageIds(facoltativo) sostituiscelanguageIdper estensione, per un solo server che serve più linguaggi della specifica.projectMarkers(facoltativo) sono i nomi di file che il server vuole nella radice del progetto. Quando nessuno di essi è presente il segmento di stato dicenessun <first marker>; non ferma mai il server.searchDirsè l'elenco delle posizioni di installazione di Windows;searchDirsMacesearchDirsLinuxsono le controparti per piattaforma. Tutte e tre espandono${VAR}, e gli elenchi POSIX espandono anche una~iniziale. Una voce le cui variabili non sono impostate viene saltata invece di trasformarsi in un percorso senza senso.argspuò usare due segnaposto:${dataDir}, la cartella dati scrivibile del plugin, e${rootHash}, un id breve e stabile del progetto corrente. È così che jdtls riceve-data <dir>. Un segnaposto che non si può risolvere viene lasciato alla lettera nell'argomento invece di essere espanso a nulla.compileCommandsArg(facoltativo) viene aggiunto in coda, con${dir}sostituito dalla directory del database individuata: è così che clangd viene puntato acompile_commands.json.priority(facoltativo,0per impostazione predefinita) ordina più definizioni dello stesso linguaggio: il numero più basso viene provato per primo, e la prima definizione il cui eseguibile si trova è quella che parte. È così che Python ottiene pyright (priority: 0) con pylsp (priority: 10) come riserva.
Le tue definizioni di server¶
Le definizioni incluse vivono dentro la directory di installazione, che non è tua da modificare (Program Files su Windows, un bundle di applicazione firmato su macOS). Metti le tue accanto a esse: Preferenze ▸ Language server ▸ Apri la cartella delle definizioni server dell'utente crea e apre
Ogni *.json al suo interno viene caricato dopo l'insieme incluso, e:
- un file il cui
languageecommandcorrispondono a una definizione inclusa la sostituisce: è così che cambi gli argomenti di clangd o aggiungi una directory di ricerca; - qualsiasi altra cosa viene aggiunta: un secondo server per un linguaggio che distribuiamo, o un linguaggio per cui OctoEdit non distribuisce nulla.
Un file che non è JSON valido, o a cui manca language o command, viene saltato e
segnalato nel log di diagnostica invece di costarti un linguaggio in silenzio.
Le definizioni vengono lette una volta sola, all'avvio: riavvia l'editor dopo averle modificate (il pulsante Riesamina / riavvia i server riesegue la ricerca, non il caricamento).
{
"language": "zig",
"command": "zls",
"extensions": [".zig", ".zon"],
"projectMarkers": ["build.zig"],
"searchDirs": ["${LOCALAPPDATA}/zls"],
"searchDirsMac": ["/opt/homebrew/bin", "~/.local/bin"],
"searchDirsLinux": ["~/.local/bin"]
}
Quale cartella viene data al server¶
Un language server ha bisogno di sapere dov'è il progetto: rust-analyzer non
carica un crate senza, gopls ha bisogno della radice del modulo, pyright vi legge
pyrightconfig.json e clangd vi cerca il suo database.
- Con una cartella aperta (File ▸ Apri cartella), i file al suo interno appartengono a quella cartella.
- Per un file fuori dalla cartella aperta, o senza alcuna cartella aperta,
OctoEdit risale dal file cercando
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, un.sln,.gite, da ultimo, un.editorconfigche dichiariroot = true. La directory del file stesso è la riserva, così un server non resta mai senza progetto. - Aprire la cartella dopo il file funziona. Ai server che comprendono i cambi di cartella dell'area di lavoro viene comunicata la nuova cartella; gli altri vengono riavviati, e i tuoi documenti aperti vengono riannunciati loro automaticamente. Non serve alcun riavvio manuale.
Risoluzione dei problemi¶
| Sintomo | Che cosa controllare |
|---|---|
Il segmento LSP: non compare mai |
Nessuna definizione di server reclama l'estensione di questo file. Controlla quale server serve quale file, oppure aggiungi una definizione. |
· server not responding |
Il server ha smesso di rispondere. Usa Mostra il log del language server, poi Riavvia i language server. |
✗ per un linguaggio di cui hai installato un server |
Verifica che l'eseguibile ci sia davvero: where clangd (Windows) / which clangd (macOS, Linux). Poi Cerca ▸ Navigazione nel codice ▸ Riavvia i language server, che riesegue l'intera ricerca. |
⚠ |
Il server è partito e poi ha continuato a fallire. Mostra il log del language server di solito nomina il motivo; risolvilo, poi usa Riavvia i language server. |
· no compile database su un progetto C/C++ |
Vedi sopra. Trova riferimenti e Rinomina vedranno solo il file aperto finché non viene risolto. |
| Il completamento non restituisce nulla su un file C++ | Quel file probabilmente manca in compile_commands.json (un'intestazione non inclusa da alcuna unità di traduzione, o un file aggiunto dopo la generazione del database). Rigeneralo. |
| Tutto funziona avviando da un terminale ma non dal Finder | Segnalalo: la consultazione del PATH della shell di accesso esiste proprio per rendere identiche le due vie. Mostra il log del language server e il log di diagnostica registrano che cosa è stato cercato. |
| Un server ha bisogno di un file di progetto che non hai | typescript-language-server ha bisogno del pacchetto typescript, gopls di un go.mod, rust-analyzer di un Cargo.toml, e pyright di un pyrightconfig.json/pyproject.toml per le risposte di ambito progetto. |
Impostazioni del language server¶
Preferenze ▸ Language server elenca ogni linguaggio per cui esiste una definizione di server. Per linguaggio puoi:
- Attivare / disattivare il server (un linguaggio disattivato non ne avvia mai uno).
- Impostare un percorso esplicito dell'eseguibile (con Sfoglia…). Questa
sostituzione vince sulla ricerca per
PATH/searchDirsdi cui sopra: utile quando il server non è nelPATHo vuoi una build precisa. - Aggiungere argomenti extra, accodati dopo quelli della definizione stessa — ad
esempio
--log=verboseper clangd. La riga viene divisa come si divide una riga di comando, quindi metti le virgolette attorno a un valore che contiene spazi.
Il campo del percorso è un percorso, non una riga di comando
Digitare C:\tools\clangd.exe --log=verbose in Percorso dell'eseguibile chiede
a OctoEdit di trovare un file il cui nome finisce in .exe --log=verbose, che
non esiste: il linguaggio riporta allora nessun server. Metti l'eseguibile nel
campo del percorso e i suoi argomenti in Argomenti aggiuntivi. Se succede comunque,
il log di diagnostica lo dice a chiare lettere.
Le modifiche hanno effetto quando premi OK / Applica: se qualche indicatore di attivazione o percorso è davvero cambiato, i server vengono riavviati automaticamente con le nuove impostazioni (una pagina non toccata non disturba mai i server in esecuzione). Il pulsante Nuova scansione / riavvia i server forza inoltre uno smontaggio e un nuovo rilevamento con le impostazioni attuali —utile dopo aver installato un server che l'editor prima non trovava— e azzera anche il budget di riavvii per arresto.
Apri la cartella delle definizioni server dell'utente crea e apre la cartella descritta in Le tue definizioni di server.
Limitazioni¶
- Dentro le finestre a comparsa dei suggerimenti non viene applicata la colorazione del codice (il testo è formattato —grassetto, titoli, codice a spaziatura fissa— ma senza evidenziazione della sintassi).
- La precisione dipende dal server: per C/C++, senza
compile_commands.jsonclangd ricade su euristiche e i risultati possono essere incompleti. - OctoEdit non installa né scarica mai un server. Trova quello che hai installato e lo avvia; quando non ce n'è nessuno, la funzionalità resta spenta e il segmento di stato lo dice.
- Un processo di server per linguaggio, condiviso da ogni progetto aperto di quel linguaggio. Un secondo progetto viene aggiunto come cartella di area di lavoro quando il server lo supporta; altrimenti viene servito sotto la radice del primo progetto.
- Kotlin, Swift e Objective-C ottengono intelligenza del codice ma non colorazione della sintassi: l'editor non ha ancora un colorizzatore per loro. Ora le due cose sono indipendenti, quindi il server funziona comunque.
- Le definizioni di server vengono lette una volta all'avvio; modificarle (le tue o quelle incluse) richiede il riavvio dell'editor.