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

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

project-settings.md · 68 lines · 6.8 KBmarkdown Blame HistoryRaw
📦 Turbo Rust 713ea5c k33g 10h ago1# Project settings — explanation
2
3## What is this about?
4
5A project can keep a `.turbo-rust/settings.toml` beside its code, saying which theme to use and whether to save files automatically. This page is about the decisions inside that sentence: why the file is only ever looked for in one place, why creating it is a menu item rather than something that happens by itself, and why automatic saving works the way it does.
6
7## Why the directory is not searched for upwards
8
9`Cargo.toml` is found by walking up from the file you opened until one turns up, and the language server uses exactly that. The settings file deliberately does not.
10
11The walk is right for `Cargo.toml` because a module has a real boundary: the file is either above you or it is not, and being inside a module is a fact about the code. "The project" is not a fact about the code. It is where you decided to start working, and the same directory tree can be several projects depending on what you are doing in it — a monorepo's `services/api` is a project when you are working on the API and part of a larger one when you are not.
12
13A walk would also make the setting act at a distance. You open a file, and the editor's colours change because of a file three directories up that you did not know existed. Every explanation of that behaviour has to start with "well, it searches upwards", and the rule you would rather be able to state is the one that is now true: **the project is the directory you started the editor in.**
14
15The cost is real and worth naming. Start the editor from `internal/app` and the project's theme does not apply. The answer is to start from the project root, which is where you would run `go build` and `git` anyway.
16
17## Why creating the file is a menu item
18
19The alternative was tempting: the first time you pick a theme, write `.turbo-rust/settings.toml` so the choice sticks. Every editor that stores workspace state does something like it.
20
21It was rejected because it puts a directory into someone's repository as a side effect of trying a colour. The user is one `git status` away from a change they did not make, in a project that may not be theirs, possibly in a review. A theme picked to look at for ten seconds should not leave anything behind.
22
23So the file is created only by **Options ▸ Create project settings**, and its existence means something: this project has settings on purpose. That is also what makes the write-back rule simple to state — **the theme is written to the file when the file exists, and not otherwise** — with no flag anywhere for "do you want to remember this?".
24
25## Why the theme is written in place rather than re-encoded
26
27Once the file exists, picking a theme rewrites it. Marshalling the `Settings` struct back to TOML would be four lines and would delete every comment in the file.
28
29That matters more here than it usually would, because this file is *meant* to be edited by hand. It is the reason TOML colouring exists in the editor at all; the created file is mostly comments explaining the keys; a team will add comments of their own saying why they chose what they chose. Losing all of it the first time someone tries a different theme would be a silent, surprising deletion of somebody's writing.
30
31So the rewrite finds the `theme` line inside the `[editor]` table and changes the value between the `=` and any trailing comment. Everything else in the file comes back byte for byte. It is about forty lines rather than four, and it is the difference between a file you can keep things in and a file that eats them.
32
33## Why automatic saving waits for a pause
34
35Three triggers were considered.
36
37**On a fixed interval** is the simplest and is wrong: it writes in the middle of an edit. Half a renamed identifier reaches disk, a file watcher rebuilds, and a test suite fails on code that never existed as anyone's intention.
38
39**On leaving the window** never writes while you work, which sounds safe and means the thing on disk can be an hour behind the thing on screen — precisely when it matters, because the reason to want autosave is usually a tool watching the file.
40
41**After a pause in typing** is what both other editors and this one settled on. Two seconds is long enough that a pause for thought is not a write, short enough that a rebuild follows a change closely. A run of typing is one write, not one per keystroke.
42
43There is one deadline for the whole editor rather than one per window, because "you stopped typing" is one event. A per-window deadline would save the file you have moved away from at a different moment from the one in front of you, which nobody could observe and which is more state to keep right.
44
45## Why the deadline is checked, and only nudged by a timer
46
47This is the same trap the language-server announcement and the terminal redraws both hit, and it is worth stating once more because it will come up again.
48
49The editor blocks in `PollEvent`. To notice a deadline while nothing is happening, something has to wake it, and the only way to wake it from a timer is `PostEvent` — which **drops** events when its queue is full.
50
51So the timer is not what decides. The deadline is state, checked at the top of every turn of the event loop, exactly as `announceOpenDocuments` checks whether the language server is ready. The timer's only job is to make sure a turn happens. A nudge that gets dropped costs a save that is late until the next keystroke or click; a design where the timer did the saving would lose it altogether.
52
53## Why a failed automatic save does not open a dialog
54
55An autosave nobody asked for should not interrupt with a modal, and a modal that reappears every two seconds because a file is read-only is worse than the problem it reports. It goes on the status bar instead, and the deadline is cleared *before* the write is attempted, so a file that cannot be written is tried once per edit rather than forever.
56
57## Why TOML colouring reuses the code classes
58
59Adding `syntax.tomlkey` and friends would have meant every theme — including the ones users have written — silently failing to colour TOML until it was updated.
60
61The classes already there fit: a table header names a structure, so it reads as a type; a key names a thing, so it reads as an identifier; `true` and `false` are constants because that is what they are. The result is that every theme that ever worked colours TOML correctly, with no change and no new keys. The scanner is hand-written for the same reason the terminal emulator is — TOML is a small, fully specified language, and it is one file against a third dependency.
62
63## How it relates to the rest
64
65- The exact keys and their defaults: [Project settings reference](../reference/project-settings.md)
66- Setting one up: [How to give a project its own settings](../how-to/configure-a-project.md)
67- The other TOML file the editor reads: [Theme file format](../reference/themes.md)
68- Where `settings` sits among the packages: [Architecture](architecture.md)