turbo-editors/turbo-gopublic Fork 0
v1.0.0
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-go.git
git clone ssh://git@rickub.com/turbo-editors/turbo-go.git

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

architecture.md · 85 lines · 5.4 KBmarkdown Blame HistoryRaw
📦 Turbo Go 3d7798b k33g 10h ago1# Architecture — explanation
2
3## What is this about?
4
5Turbo Go is a command, a profile and a scanner. Everything else — the editing widget, the windows, the menus, the dialogs, the themes, the terminal emulator, the file tree, the LSP client — is [turbo-core](https://rickub.com/turbo-editors/turbo-core), the library every Turbo editor is built on.
6
7That was not always true. Turbo Go was a single program of about eleven and a half thousand lines in fourteen packages until a second editor was wanted, at which point the fourteen moved into a library and one stayed here. This page is about the split that resulted.
8
9## What is in this repository
10
11```
12main.go flags, the terminal, and the wiring
13internal/golang the whole of what makes this Turbo Go
14 golang.go the profile: name, menu, server, root marker
15 scan.go the Go scanner, on top of go/scanner
16 templates.go three //go:embed declarations
17 *.toml.tmpl the three starter files a project gets, embedded
18```
19
20About four hundred lines. There is no `internal/app`, no `internal/ui`, no `internal/buffer` — those exist once, in the library, and every editor built on it uses them unchanged.
21
22## What `main` does
23
24Six things, in this order:
25
261. Parses the flags.
272. Calls `golang.Register()`, which teaches the library to colour `.go` files.
283. Builds `golang.Profile()` — the value that says this editor is Turbo Go.
294. Reads `.turbo-go/settings.toml` from the working directory, if there is one.
305. Opens the terminal and hands the screen, the theme name and the profile to `app.New`.
316. Starts gopls in the module root, and runs the event loop.
32
33That is the whole command. Every decision it makes — which theme wins, which files to open, whether to start a language server — is about *this run*, not about Go.
34
35## The profile is the seam
36
37```go
38profile.Profile{
39 Name: "Turbo Go",
40 Slug: "turbo-go",
41 Language: "Go",
42 ToolsMenu: "~G~o",
43 RootMarkers: []string{"go.mod"},
44 Server: profile.Server{Command: "gopls", Args: []string{"serve"}, },
45 Templates: profile.Templates{Settings: , Snippets: , Tools: },
46}
47```
48
49Everything that used to be a hardcoded `"turbo-go"`, `"gopls"` or `"go.mod"` somewhere in eleven thousand lines is one field here. The library reads them; nothing in the library knows what any of them mean.
50
51`Slug` carries more than it looks. The binary is `turbo-go`, the project directory is `.turbo-go`, the user's own configuration lives in `~/.config/turbo-go`, and the environment variables that override it are `TURBO_GO_THEME_DIR` and `TURBO_GO_SNIPPET_DIR` — all derived from that one word. Those names are unchanged by the refactoring, deliberately: somebody who set `TURBO_GO_THEME_DIR` did so against a released binary.
52
53## Why the Go scanner is here and not in the library
54
55turbo-core colours eight languages itself: TOML, YAML, Markdown, JavaScript, HTML, XML, Dockerfiles and shell. Those are the ones every editor meets whatever it is for — a project's configuration is TOML or YAML, its documentation is Markdown, its scripts are shell, its image build a Dockerfile.
56
57Go is not one of them. The language that *defines* an editor is registered by that editor, which is why a `.rs` file opens as plain text here and a `.go` file opens as plain text in Turbo Rust.
58
59The Go scanner is also the one that is *least* like the others. Every language in the library is scanned a line at a time with `syntax.LineScanner`; Go goes through `go/scanner`, the lexer the Go toolchain itself uses, and converts its byte offsets with `syntax.LineIndex`. That the library supports both shapes is because of this scanner.
60
61## What moved, and what did not
62
63| Was | Is |
64| --- | --- |
65| `internal/buffer`, `internal/ui`, `internal/editor`, … | `turbo-core/buffer`, `turbo-core/ui`, `turbo-core/editor`, … |
66| `internal/syntax` — six languages | `turbo-core/syntax` — eight, plus a registry; Go lives here |
67| `internal/app` with a `Name` constant | `turbo-core/app` taking a `profile.Profile` |
68| `internal/lsp` hardcoding gopls | `turbo-core/lsp` taking a `profile.Server` |
69| `moduleRoot` in `main.go` | `app.ProjectRoot(p, files)`, with `go.mod` in the profile |
70| `settings.DirName = ".turbo-go"` | `p.ProjectDir()` |
71
72**Nothing about the editor's behaviour changed.** The menus, the keys, the themes, the file formats and the environment variables are what they were. What changed is where the code lives.
73
74## Why a library rather than a fork
75
76The alternative to extracting turbo-core was copying Turbo Go and changing the Go bits. It was rejected before it was started: two copies of eleven thousand lines drift within a month, and every fix has to be made twice by somebody who remembers there are two.
77
78The cost, accepted: a change to a menu now affects every editor at once, and Turbo Go can no longer make a decision that suits only Go without either putting it in the profile or arguing for it in the library. That is a real constraint, and it is the one that keeps the editors the same editor.
79
80## How it relates to the rest
81
82- What each of the library's packages does: [turbo-core's package reference](https://rickub.com/turbo-editors/turbo-core/blob/main/docs/en/reference/packages.md)
83- How the colouring works here: [Colouring and completion](colouring-and-completion.md)
84- Why the tools menu is data: [Go tools](go-tools.md)
85- The decisions that outlived the refactoring: [Design decisions](design-decisions.md)