turbo-editors/turbo-corepublic Fork 0
v1.0.1
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

build-an-editor.md · 293 lines · 7.4 KBmarkdown Blame HistoryRaw
🛟 Updated. 28d5985 k33g 20h ago1# Tutoriel : construire un éditeur Turbo pour votre propre langage
2
3À la fin de ce tutoriel, vous disposerez d'un IDE de terminal en plein écran — barre de menus, fenêtres déplaçables, souris, thèmes, arborescence de projet, fenêtres de terminal et coloration syntaxique — pour le langage de votre choix. Nous en construirons un pour **Zig**, et il fera environ quatre-vingts lignes de Go.
4
5Aucune connaissance de turbo-core n'est requise. Il vous faut Go 1.26 ou plus récent, et un terminal.
6
7## Prérequis
8
9- Go 1.26 ou plus récent dans votre PATH.
10- Une copie de turbo-core à côté de l'endroit où vous allez travailler. Si vous n'en avez pas :
11
12```bash
📦 Turbo Core d662ceb k33g 12h ago13git clone ssh://git@rickub.com/turbo-editors/turbo-core.git
🛟 Updated. 28d5985 k33g 20h ago14```
15
16## Étape 1 — Créer le module
17
18À côté de votre copie de turbo-core, tapez :
19
20```bash
21mkdir turbo-zig && cd turbo-zig
22go mod init example.com/turbo-zig
23```
24
25Vous devriez voir :
26
27```
28go: creating new go.mod: module example.com/turbo-zig
29```
30
31Nous avons maintenant un module vide. Nous allons le brancher sur la bibliothèque.
32
33## Étape 2 — Dépendre de turbo-core
34
35Tapez :
36
37```bash
📦 Turbo Core f3ade8d k33g 12h ago38go mod edit -require=rickub.com/turbo-editors/turbo-core@v0.1.0
39go mod edit -replace=rickub.com/turbo-editors/turbo-core=../turbo-core
🛟 Updated. 28d5985 k33g 20h ago40```
41
42Rien ne s'affiche. Regardez `go.mod` :
43
44```bash
45cat go.mod
46```
47
48Vous devriez voir une ligne `require` et une ligne `replace` nommant turbo-core. C'est le `replace` qui fait que la copie posée à côté de vous est celle qui sera utilisée.
49
50## Étape 3 — Dire quel éditeur c'est
51
52Créez `profile.go` :
53
54```go
55package main
56
📦 Turbo Core f3ade8d k33g 12h ago57import "rickub.com/turbo-editors/turbo-core/profile"
🛟 Updated. 28d5985 k33g 20h ago58
59// zig est l'éditeur que nous construisons.
60func zig() profile.Profile {
61 return profile.Profile{
62 Name: "Turbo Zig",
63 Slug: "turbo-zig",
64 Language: "Zig",
65 ToolsMenu: "~Z~ig",
66 RootMarkers: []string{"build.zig"},
67 Server: profile.Server{
68 Command: "zls",
69 InstallHint: "voir https://github.com/zigtools/zls",
70 },
71 Templates: profile.Templates{
72 Settings: settingsTemplate,
73 Snippets: snippetsTemplate,
74 Tools: toolsTemplate,
75 },
76 }
77}
78```
79
80Voilà la totalité de ce qui distingue cet éditeur de Turbo Go. Nous n'avons pas encore écrit les modèles — c'est l'étape suivante.
81
82## Étape 4 — Écrire les trois fichiers de départ
83
84Créez `templates.go` :
85
86```go
87package main
88
89const settingsTemplate = `# turbo-zig project settings.
90
91[editor]
92
93theme = %q
94autosave = false
95autosave_delay = %q
96`
97
98const snippetsTemplate = `# turbo-zig snippets.
99#
100# Un extrait sans groupe va dans %s.
101# Les vôtres vivent dans :
102# %s
103
104[[snippet]]
105name = "TODO"
106body = "TODO: "
107`
108
109const toolsTemplate = `# turbo-zig tools.
110
111[[tool]]
112name = "~B~uild"
113command = "zig build"
114output = "popup"
115
116[[tool]]
117name = "~T~est"
118command = "zig build test"
119output = "popup"
120
121[[tool]]
122name = "~R~un"
123command = "zig build run"
124output = "terminal"
125`
126```
127
128Les trous comptent : `settingsTemplate` prend le nom du thème puis le délai de sauvegarde automatique, `snippetsTemplate` prend le nom du groupe sans nom puis le chemin des extraits de l'utilisateur. La [référence Profile](../reference/profile.md) les donne exactement.
129
130## Étape 5 — Écrire la commande
131
132Créez `main.go` :
133
134```go
135package main
136
137import (
138 "context"
139 "fmt"
140 "os"
141
142 "github.com/gdamore/tcell/v2"
143
📦 Turbo Core f3ade8d k33g 12h ago144 "rickub.com/turbo-editors/turbo-core/app"
🛟 Updated. 28d5985 k33g 20h ago145)
146
147func main() {
148 if err := run(); err != nil {
149 fmt.Fprintln(os.Stderr, "turbo-zig:", err)
150 os.Exit(1)
151 }
152}
153
154func run() error {
155 screen, err := tcell.NewScreen()
156 if err != nil {
157 return err
158 }
159 if err := screen.Init(); err != nil {
160 return err
161 }
162 defer screen.Fini()
163 screen.EnableMouse()
164 screen.EnablePaste()
165
166 p := zig()
167 editor := app.New(screen, "turbo-classic", p)
168
169 files := os.Args[1:]
170 if len(files) == 0 {
171 editor.NewFile()
172 }
173 for _, file := range files {
174 editor.Open(file)
175 }
176
177 ctx, cancel := context.WithCancel(context.Background())
178 defer cancel()
179 editor.StartLanguageServer(ctx, app.ProjectRoot(p, files))
180 defer editor.Language().Stop(context.Background())
181
182 return editor.Run()
183}
184```
185
186## Étape 6 — Le lancer
187
188Tapez :
189
190```bash
191go mod tidy
192go run . main.go
193```
194
195Votre terminal se remplit d'un bureau bleu. En haut, vous devriez lire :
196
197```
198 File Edit Search Run Options Window Snippets Zig Help
199```
200
201et une fenêtre au milieu montrant `main.go`. Appuyez sur **F10** pour ouvrir la barre de menus, les flèches pour vous y déplacer, et **Alt-X** pour sortir.
202
203Nous avons un éditeur qui marche. Tout ce qui est sur cette barre fonctionne : **F3** ouvre un fichier, **F8** ouvre une fenêtre de terminal avec un vrai shell dedans, **F9** ouvre l'arborescence du projet, **Options ▸ Theme** propose onze thèmes de couleurs.
204
205## Étape 7 — Colorer le langage
206
207Les fichiers Zig ne sont pas encore colorés, parce que rien n'a dit à la bibliothèque ce qu'est Zig. Créez `syntax.go` :
208
209```go
210package main
211
📦 Turbo Core f3ade8d k33g 12h ago212import "rickub.com/turbo-editors/turbo-core/syntax"
🛟 Updated. 28d5985 k33g 20h ago213
214// registerZig enseigne à la bibliothèque un tout petit peu de Zig : ses
215// mots-clés, ses commentaires et ses chaînes.
216func registerZig() {
217 syntax.Register(syntax.Definition{
218 Language: "zig",
219 Extensions: []string{".zig"},
220 Highlight: highlightZig,
221 })
222}
223
224var zigKeywords = map[string]bool{
225 "const": true, "var": true, "fn": true, "pub": true, "return": true,
226 "if": true, "else": true, "while": true, "for": true, "struct": true,
227 "try": true, "defer": true, "test": true, "comptime": true,
228}
229
230func highlightZig(src string) [][]syntax.Span {
231 return syntax.ScanLines(src, func(line []rune, carry struct{}) ([]syntax.Span, struct{}) {
232 s := syntax.NewLineScanner(line)
233 for !s.AtEnd() {
234 switch r := s.Peek(0); {
235 case r == ' ' || r == '\t':
236 s.SkipSpaces()
237 case s.HasPrefix(0, "//"):
238 s.TakeRest(syntax.ClassComment)
239 case r == '"':
240 syntax.TakeQuoted(s, '"', syntax.ClassString)
241 case syntax.IsDigit(r):
242 s.TakeWhile(syntax.ClassNumber, syntax.IsWordRune)
243 case syntax.IsLetter(r) || r == '_':
244 start := s.Pos()
245 for !s.AtEnd() && syntax.IsWordRune(s.Peek(0)) {
246 s.Advance(1)
247 }
248 class := syntax.ClassIdentifier
249 if zigKeywords[string(line[start:s.Pos()])] {
250 class = syntax.ClassKeyword
251 }
252 s.Emit(start, s.Pos(), class)
253 default:
254 s.Advance(1)
255 }
256 }
257 return s.Spans(), carry
258 })
259}
260```
261
262Ajoutez une ligne à `run`, juste au-dessus de `p := zig()` :
263
264```go
265 registerZig()
266```
267
268## Étape 8 — Le voir coloré
269
270Écrivez un fichier Zig et ouvrez-le :
271
272```bash
273cat > hello.zig <<'EOF'
274// A greeting.
275const std = @import("std");
276
277pub fn main() void {
278 std.debug.print("hello {d}\n", .{42});
279}
280EOF
281go run . hello.zig
282```
283
284`const`, `pub`, `fn` sont dessinés dans la couleur des mots-clés, `// A greeting.` dans celle des commentaires, `"hello {d}\n"` dans celle des chaînes et `42` dans celle des nombres. Appuyez sur **Alt-X** pour sortir.
285
286## Et maintenant ?
287
288Vous avez un éditeur. Ce qui lui manque encore, c'est un vrai analyseur — celui ci-dessus connaît quatorze mots-clés et ignore tout des chaînes multilignes `\\` et des littéraux de caractère.
289
290- Pour en écrire un correct → [Ajouter un langage](../how-to/add-a-language.md)
291- Pour faire marcher la complétion → [Dialoguer avec un serveur de langage](../how-to/talk-to-a-language-server.md)
292- Pour voir tous les champs que vous avez sautés → [Référence Profile](../reference/profile.md)
293- Pour comprendre pourquoi la bibliothèque a cette forme → [Architecture](../explanation/architecture.md)