# Comment dialoguer avec un serveur de langage Ce guide montre comment brancher un éditeur bâti sur turbo-core sur un serveur de langage, pour que la complétion, le survol et le saut à la définition fonctionnent. Il suppose que vous avez un éditeur et un serveur qui parle LSP sur son entrée et sa sortie standard. ## Étapes ### 1. Décrire le serveur dans votre profil ```go Server: profile.Server{ Command: "rust-analyzer", Args: nil, InstallHint: "rustup component add rust-analyzer", Dirs: []string{cargoBinDir()}, }, ``` | Champ | À quoi il sert | | --- | --- | | `Command` | le nom de l'exécutable, cherché dans PATH | | `Args` | ce avec quoi il démarre — gopls veut `serve`, rust-analyzer ne veut rien | | `InstallHint` | une commande que l'utilisateur peut copier, affichée sur la barre d'état quand le serveur manque | | `Dirs` | des répertoires supplémentaires à fouiller quand PATH ne donne rien | `Dirs` compte plus qu'il n'y paraît. L'installateur de chaque langage pose ses binaires quelque part qui n'est très souvent pas dans PATH — `GOPATH/bin`, `~/.cargo/bin` — et « la complétion ne fait rien » est ce que voit l'utilisateur quand l'éditeur ne trouve pas un serveur qu'il croit avoir installé. ### 2. Dire où commence le projet ```go RootMarkers: []string{"Cargo.toml"}, ``` Le serveur est démarré dans le premier répertoire, à partir du fichier et en remontant, qui contient l'un de ces fichiers. Un serveur lancé à la mauvaise racine charge le mauvais code puis ne répond rien du tout, sans erreur — ce qui est la façon la plus déroutante dont la complétion peut échouer. ### 3. Le démarrer depuis votre commande ```go editor.StartLanguageServer(ctx, app.ProjectRoot(p, files)) defer editor.Language().Stop(context.Background()) ``` Démarrez-le **après** avoir ouvert les fichiers, pas avant. L'éditeur annonce les documents déjà ouverts au premier tour de sa boucle d'événements où le serveur est prêt, et c'est ce qui rend cet ordre sûr. ## Variantes ### Un fichier est créé dans l'éditeur Rien à faire. Une fenêtre née sans titre n'a pas de chemin, donc le serveur n'en entend pas parler — jusqu'à la première sauvegarde, qui annonce le document au lieu de simplement signaler une écriture. La complétion, le survol et les diagnostics fonctionnent dans cette fenêtre dès qu'elle a un nom, sans redémarrage. Un « Enregistrer sous » vers un nom réellement nouveau ferme aussi l'ancien document côté serveur, pour qu'aucun fantôme n'y reste ouvert. ### Le serveur a besoin d'une configuration turbo-core répond à `workspace/configuration` par un objet vide. Si votre serveur exige des réglages avant de fonctionner, cette réponse est dans `lsp.Client.handleRequest` et n'est pas encore configurable — dites-le à vos utilisateurs plutôt que de laisser la complétion échouer en silence. ### Il n'existe pas de serveur pour votre langage Laissez `Server` à sa valeur nulle. `app.Language` ne fait rien quand rien n'est connecté, donc rien d'autre dans l'éditeur n'a à vérifier : la coloration, l'édition, les thèmes, l'arborescence et les fenêtres de terminal fonctionnent exactement pareil. ### La commande existe mais ne s'exécute pas C'est réel et cela mérite d'être traité. `rustup` installe un *relais* nommé `rust-analyzer` que le composant soit là ou non, et le relais n'échoue qu'une fois lancé. Trouver le fichier n'est pas la même chose que pouvoir s'en servir ; si vous cherchez un serveur dans un script d'installation, exécutez-le plutôt que de faire un `stat` dessus. ## Le vérifier de bout en bout Le test qui vaut la peine d'être écrit est celui qui tape un texte que le serveur n'a jamais vu sur le disque : 1. Écrivez un fichier qui s'arrête juste avant ce qu'on veut compléter. 2. Ouvrez-le, **puis** démarrez le serveur. 3. Faites un tour de boucle avec `editor.Tick()`. 4. Tapez la suite dans le tampon avec `editor.Handle(...)`. 5. Demandez une complétion. Un fichier de test qui contient déjà le texte ne prouve rien : le serveur répond depuis le disque pour tout ce qu'on ne lui a pas dit être ouvert, si bien qu'un tel test passe que l'éditeur ait parlé ou non. Attendez-vous à devoir demander plusieurs fois. rust-analyzer répond une liste vide tant qu'il n'a pas fini de charger l'espace de travail, et il le signale par une notification `$/progress` que ce client ne lit pas. ## Voir aussi - Tous les champs : [référence profile](../reference/profile.md) - Ce que l'éditeur expose pour être piloté : [référence app](../reference/app.md)