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

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

📦 Turbo Python 6fc62ea · on v1.0.1 · k33g · 9h ago
summary.md · 143 lines · 11.3 KBmarkdown
Blame HistoryOpen raw

turbo-python — summary

A snapshot of the present. Edited in place; the history is in history.md.

What this is

A Turbo C-style terminal IDE for Python, written in Go, built on
turbo-core — the library Turbo Go and
Turbo Rust already share. This repository holds the command, the profile that says the
editor is for Python, and the Python scanner. Everything else — the event loop, the
windows, the dialogs, the themes, the LSP client, the terminal emulator, the project tree,
the snippets and tools machinery — is the library's, and none of it is copied here.

Module rickub.com/turbo-editors/turbo-python, requireing turbo-core v0.4.1 from
the module proxy with no active replace. The commented-out replace at the bottom of
go.mod documents the escape hatch without being one; 01-release.tag.sh refuses to tag a
release whose go.mod carries a live one.

Layout

main.go flags, the terminal, pythonlang.Register(), the profile, the loop
internal/pythonlang/pythonlang.go Name, Slug, Language, Profile(), Register(), the four server directories
internal/pythonlang/scan.go the scanner's dispatcher, comments, decorators
internal/pythonlang/literals.go strings — all six prefixes, both triple quotes, line continuations
internal/pythonlang/words.go numbers, keywords, soft keywords, the name-shape rules
internal/pythonlang/*.toml.tmpl the three starter files, embedded by templates.go
diagram_test.go holds docs/diagrams/packages.drawio to go list
docs/{en,fr}/ 33 pages each (README included), Diátaxis

How to build, test and measure

make check          # fmt, vet, then the whole suite — what a commit should pass
make build          # into bin/turbo-python, then check the binary reports its version
make install        # build, install onto PATH, report what it found
go test ./...       # 129 tests; the pylsp ones skip themselves without a server

Quality gate, separate from the tests:

python3 ~/.claude/skills/quality/scripts/quality_report.py --workspace .

To build against a turbo-core you have changed but not released:

go work init . ../turbo-core
go list -f '{{.Dir}}' rickub.com/turbo-editors/turbo-core/app   # must NOT be under pkg/mod

go.work and go.work.sum are gitignored. Everything still builds and still passes
while testing the published library instead of your changes, so run that second line.

Decisions in force

  • The toolchain menu is ~P~ython, not uv. P is free — the fixed menus take F, E,
    S, R, C, O, W, N and H. Named after the language because the menu holds whatever the
    project put in its tools file, and a menu called uv holding docker compose up is a lie
    about what the menu is.
  • The language server is pylsp, and the install hint says pipx install "python-lsp-server[all]". The [all] is load-bearing: installed bare, pylsp starts,
    completes and jumps, and publishes an empty diagnostics list for a file that does not
    parse, because the linters are extras. A gutter blank for want of a linter looks exactly
    like a gutter blank for want of a bug.
  • pylsp answers seven of turbo-core's nine questions. It advertises neither
    implementation nor workspace/symbol, so those two items report nothing found. That is
    documented rather than worked around, and a test asserts it so a future pylsp gaining them
    is noticed.
  • Profile() is a function, not a variable, because Server.Dirs reads the
    environment, and a variable would freeze whatever VIRTUAL_ENV said at link time — for a
    Python tool, the one value most likely to change between two runs in the same shell.
  • Four places are searched for the server besides PATH: the active virtual
    environment's bin, ~/.local/bin, pyenv's shims, and every
    ~/Library/Python/<version>/bin that exists. The last is read rather than guessed, and is
    on nobody's PATH on macOS.
  • Root markers, in order: pyproject.toml, setup.py, setup.cfg.
  • A name wholly in capitals is a constant; any other capitalised name is a type. Turbo
    Rust has only the second rule and documents SCREAMING_SNAKE_CASE as a known wrong
    answer; PEP 8 separates the two conventions well enough that the wrong answer was worth
    removing rather than inheriting. The cost is a class named HTTP.
  • A capitalised name is a type even when it is called. ValueError("nope") and
    parse("nope") are the same shape. This is the one rule Turbo Python and Turbo Rust order
    differently, on purpose.
  • self and cls are coloured as builtins although the language does not name them.
  • An f-string is one string span, {…} included. Finding where an expression ends
    inside a literal needs a parser; this is a scanner.
  • The starter templates are embedded files, not Go constants, with the .tmpl suffix
    because settings.toml.tmpl holds theme = %q, which is not valid TOML.
  • autosave = true in the starter settings file, false in settings.Default(). Two
    statements in two places on purpose: a project that created a settings file has said what
    it wants; a directory somebody merely started the editor in has not.
  • Agent windows are turbo-core's, and what belongs here is the starter file. acp.toml.tmpl is the fourth embedded template, and profile.Templates.Agents is the whole of Turbo Python's contribution to the feature. The example agent is docker agent serve acp .turbo-python/agent.yaml; the only other thing about this editor in it is the sentence saying a ```python fence is coloured by the scanner this editor colours its own files with. Every other editor got agent windows the same way — one file, one line. The reasoning, and why it could not have been built here, is in docs/*/explanation/agent-windows.md.
  • The starter agents file teaches the window's keyboard as well as the format. Enter, Alt-Enter, Tab, Esc, Ctrl-W and the copying keys are all in its comments, because a file the editor hands you is the one document a user is guaranteed to see.

State as of 2026-09-03

  • Complete and green. go test ./... passes; gofmt -l and go vet are clean.
  • Quality gate: PASS. 0 errors, 0 warnings, 0 smells; total complexity 91.
  • Documentation: 33 files × EN + FR (32 pages plus each language's README), a README.md at the root, and
    docs/diagrams/packages.drawio checked against go list by diagram_test.go.
  • Verified in a real pty, not only by tests: the Python menu under Alt-P with
    Create tools file available (30;42) and Open tools file greyed (90;47); def
    97;44;1, a called name 93;44;1, print 96;44;1, strings 92;44, comments
    38;2;143;143;143; a triple-quoted f-string carried across a line break; the About box
    reading "A Turbo C-style editor for Python, / written in Go."; Ctrl-Y deleting a
    line; the theme dialog opening on the current theme; and — the one that matters —
    a file that does not parse, opened by a relative path, showing × in the gutter and
    ⚠ invalid syntax on the status bar
    , which is the failure mode Turbo Go shipped with
    for months.
  • The server is found outside PATH. Verified by running the binary with PATH
    stripped to /usr/bin:/bin: it still said LSP: ready, from ~/.local/bin. With HOME
    moved too it says LSP: no pylsp — pipx install "python-lsp-server[all]".
  • The editor is registered in the family. turbo-core's README.md, both doc READMEs,
    profile/profile.go's package comment, the release and workspace how-tos in both
    languages, both architecture explanations and .memory/summary.md now count three
    editors. turbo-core's .go strings were swept for hardcoded language names; every hit was
    a false positive, a doc-comment example, or a true statement about the implementation.
  • Released as v0.1.0, tagged and pushed at bccbb0b on main, working tree clean.
    turbo-core was tagged v0.4.1 the same day — a docs-and-comment release, no behaviour
    change — and all three editors now pin it.

Not yet established

  • Agent windows have never been opened in this editor. The feature is turbo-core's and was driven end to end from turbo-go against a real docker agent and a real llama.cpp; what is here is the starter file, covered by tests that create it, load it back and check it names this editor's own language. Nobody has run turbo-python, pressed Alt-A and talked to an agent from it.

  • Never run on macOS or Windows. Everything here was verified on Linux. The user's
    machine is macOS, so a binary built in this sandbox is an ELF they cannot run.

  • No CI. There is no pipeline configuration in the repository.

  • The release scripts have never been run from this sandbox. v0.1.0 exists, tagged by the user; 0104 have only ever been read here.

  • Performance on a large file is unmeasured. The scanner is a line at a time and carries
    three pieces of state, but nothing has been timed.

  • Only pylsp has been tried. pyright and ruff-lsp would both fit the profile; neither
    has been pointed at.

State as of 2026-09-19 — moved to Rickub, released by a workflow

  • Module path rickub.com/turbo-editors/turbo-python, depending on rickub.com/turbo-editors/turbo-core v1.0.0 — the first turbo-core version published under that path (v0.9.0 on the proxy still declares the Codeberg path and cannot be required as rickub.com/…). Every import, the Makefile's VERSION_PKG, scripts/install.sh, the README and the docs say rickub.com. GOWORK=off make check green. The repository on this side is a fresh git init with origin at ssh://git@rickub.com/turbo-editors/turbo-python.git and no commit yet; 01-release.tag.sh makes the first one.
  • Releases are one script and one workflow, modelled on turbo-core's and identical to turbo-go's. 01-release.tag.sh runs make check under TURBO_PYTHON_RELEASING=1, refuses a tag taken locally or on origin (bump, never move), refuses a replace in go.mod, commits, pushes the current branch, then tags and pushes the tag. That push starts .github/workflows/release.yml: go test with TURBO_PYTHON_RELEASING=1, ./02-build-releases.sh "${GITHUB_REF_NAME}", release notes from the tag message, a run artifact, then softprops/action-gh-release@v2 attaching turbo-python-*, SHA256SUMS and README.md with the job's own GITHUB_TOKEN — the only credential Rickub's release API accepts. 02-release.publish.sh and 04-release.upload-binaries.sh are gone; the build script is now 02-build-releases.sh, takes the tag as $1 (CI has no release.env), validates it, refuses a replace, and starts from an empty release/${TAG}/. release.env holds only TAG and ABOUT; turbo-python.token.env is read by nothing.
  • release_test.go runs 01 for real against a throwaway bare remote (publishes, then refuses the same tag), runs 02 alone to see it refuse v0.o.0, and asserts the workflow's trigger, contents: write, ./02-build-releases.sh, fail_on_unmatched_files, docs linked at the tag, no secrets., and TURBO_PYTHON_RELEASING. The copy of the module for the clone leaves out .git, bin, release, kits, demo, demos, *.env and go.work*; children run with GOWORK=off.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# turbo-python — summary

A snapshot of the present. Edited in place; the history is in `history.md`.

## What this is

A Turbo C-style terminal IDE for Python, written in Go, built on
**[turbo-core](https://rickub.com/turbo-editors/turbo-core)** — the library Turbo Go and
Turbo Rust already share. This repository holds the command, the profile that says the
editor is for Python, and the Python scanner. Everything else — the event loop, the
windows, the dialogs, the themes, the LSP client, the terminal emulator, the project tree,
the snippets and tools machinery — is the library's, and none of it is copied here.

Module `rickub.com/turbo-editors/turbo-python`, `require`ing turbo-core **v0.4.1** from
the module proxy with **no active `replace`**. The commented-out `replace` at the bottom of
`go.mod` documents the escape hatch without being one; `01-release.tag.sh` refuses to tag a
release whose `go.mod` carries a live one.

## Layout

| | |
| --- | --- |
| `main.go` | flags, the terminal, `pythonlang.Register()`, the profile, the loop |
| `internal/pythonlang/pythonlang.go` | `Name`, `Slug`, `Language`, `Profile()`, `Register()`, the four server directories |
| `internal/pythonlang/scan.go` | the scanner's dispatcher, comments, decorators |
| `internal/pythonlang/literals.go` | strings — all six prefixes, both triple quotes, line continuations |
| `internal/pythonlang/words.go` | numbers, keywords, soft keywords, the name-shape rules |
| `internal/pythonlang/*.toml.tmpl` | the three starter files, embedded by `templates.go` |
| `diagram_test.go` | holds `docs/diagrams/packages.drawio` to `go list` |
| `docs/{en,fr}/` | 33 pages each (README included), Diátaxis |

## How to build, test and measure

```bash
make check          # fmt, vet, then the whole suite — what a commit should pass
make build          # into bin/turbo-python, then check the binary reports its version
make install        # build, install onto PATH, report what it found
go test ./...       # 129 tests; the pylsp ones skip themselves without a server
```

Quality gate, separate from the tests:

```bash
python3 ~/.claude/skills/quality/scripts/quality_report.py --workspace .
```

To build against a turbo-core you have changed but not released:

```bash
go work init . ../turbo-core
go list -f '{{.Dir}}' rickub.com/turbo-editors/turbo-core/app   # must NOT be under pkg/mod
```

`go.work` and `go.work.sum` are gitignored. **Everything still builds and still passes**
while testing the published library instead of your changes, so run that second line.

## Decisions in force

- **The toolchain menu is `~P~ython`, not `uv`.** `P` is free — the fixed menus take F, E,
  S, R, C, O, W, N and H. Named after the language because the menu holds whatever the
  project put in its tools file, and a menu called `uv` holding `docker compose up` is a lie
  about what the menu is.
- **The language server is `pylsp`, and the install hint says `pipx install
  "python-lsp-server[all]"`.** The `[all]` is load-bearing: installed bare, pylsp starts,
  completes and jumps, and publishes an **empty** diagnostics list for a file that does not
  parse, because the linters are extras. A gutter blank for want of a linter looks exactly
  like a gutter blank for want of a bug.
- **pylsp answers seven of turbo-core's nine questions.** It advertises neither
  `implementation` nor `workspace/symbol`, so those two items report nothing found. That is
  documented rather than worked around, and a test asserts it so a future pylsp gaining them
  is noticed.
- **`Profile()` is a function, not a variable**, because `Server.Dirs` reads the
  environment, and a variable would freeze whatever `VIRTUAL_ENV` said at link time — for a
  Python tool, the one value most likely to change between two runs in the same shell.
- **Four places are searched for the server besides `PATH`**: the active virtual
  environment's `bin`, `~/.local/bin`, pyenv's shims, and every
  `~/Library/Python/<version>/bin` that exists. The last is read rather than guessed, and is
  on nobody's `PATH` on macOS.
- **Root markers, in order: `pyproject.toml`, `setup.py`, `setup.cfg`.**
- **A name wholly in capitals is a constant; any other capitalised name is a type.** Turbo
  Rust has only the second rule and documents `SCREAMING_SNAKE_CASE` as a known wrong
  answer; PEP 8 separates the two conventions well enough that the wrong answer was worth
  removing rather than inheriting. The cost is a class named `HTTP`.
- **A capitalised name is a type even when it is called.** `ValueError("nope")` and
  `parse("nope")` are the same shape. This is the one rule Turbo Python and Turbo Rust order
  differently, on purpose.
- **`self` and `cls` are coloured as builtins** although the language does not name them.
- **An f-string is one string span**, `{…}` included. Finding where an expression ends
  inside a literal needs a parser; this is a scanner.
- **The starter templates are embedded files, not Go constants**, with the `.tmpl` suffix
  because `settings.toml.tmpl` holds `theme = %q`, which is not valid TOML.
- **`autosave = true` in the starter settings file, `false` in `settings.Default()`.** Two
  statements in two places on purpose: a project that created a settings file has said what
  it wants; a directory somebody merely started the editor in has not.
- **Agent windows are turbo-core's, and what belongs here is the starter file.** `acp.toml.tmpl` is the fourth embedded template, and `profile.Templates.Agents` is the whole of Turbo Python's contribution to the feature. The example agent is `docker agent serve acp .turbo-python/agent.yaml`; the only other thing about this editor in it is the sentence saying a ```python fence is coloured by the scanner this editor colours its own files with. Every other editor got agent windows the same way — one file, one line. The reasoning, and why it could not have been built here, is in `docs/*/explanation/agent-windows.md`.
- **The starter agents file teaches the window's keyboard as well as the format.** `Enter`, `Alt-Enter`, `Tab`, `Esc`, `Ctrl-W` and the copying keys are all in its comments, because a file the editor hands you is the one document a user is guaranteed to see.

## State as of 2026-09-03

- **Complete and green.** `go test ./...` passes; `gofmt -l` and `go vet` are clean.
- **Quality gate: PASS.** 0 errors, 0 warnings, 0 smells; total complexity 91.
- **Documentation**: 33 files × EN + FR (32 pages plus each language's README), a `README.md` at the root, and
  `docs/diagrams/packages.drawio` checked against `go list` by `diagram_test.go`.
- **Verified in a real pty**, not only by tests: the Python menu under `Alt-P` with
  `Create tools file` available (`30;42`) and `Open tools file` greyed (`90;47`); `def`
  `97;44;1`, a called name `93;44;1`, `print` `96;44;1`, strings `92;44`, comments
  `38;2;143;143;143`; a triple-quoted f-string carried across a line break; the About box
  reading **"A Turbo C-style editor for Python, / written in Go."**; `Ctrl-Y` deleting a
  line; the theme dialog opening on the current theme; and — the one that matters —
  **a file that does not parse, opened by a relative path, showing `×` in the gutter and
  `⚠ invalid syntax` on the status bar**, which is the failure mode Turbo Go shipped with
  for months.
- **The server is found outside `PATH`.** Verified by running the binary with `PATH`
  stripped to `/usr/bin:/bin`: it still said `LSP: ready`, from `~/.local/bin`. With `HOME`
  moved too it says `LSP: no pylsp — pipx install "python-lsp-server[all]"`.
- **The editor is registered in the family.** turbo-core's `README.md`, both doc `README`s,
  `profile/profile.go`'s package comment, the release and workspace how-tos in both
  languages, both architecture explanations and `.memory/summary.md` now count three
  editors. turbo-core's `.go` strings were swept for hardcoded language names; every hit was
  a false positive, a doc-comment example, or a true statement about the implementation.
- **Released as `v0.1.0`**, tagged and pushed at `bccbb0b` on `main`, working tree clean.
  turbo-core was tagged `v0.4.1` the same day — a docs-and-comment release, no behaviour
  change — and all three editors now pin it.

## Not yet established

- **Agent windows have never been opened in this editor.** The feature is turbo-core's and was driven end to end from turbo-go against a real `docker agent` and a real llama.cpp; what is here is the starter file, covered by tests that create it, load it back and check it names this editor's own language. Nobody has run `turbo-python`, pressed `Alt-A` and talked to an agent from it.


- **Never run on macOS or Windows.** Everything here was verified on Linux. The user's
  machine is macOS, so a binary built in this sandbox is an ELF they cannot run.
- **No CI.** There is no pipeline configuration in the repository.
- **The release scripts have never been run from this sandbox.** `v0.1.0` exists, tagged by the user; `01`–`04` have only ever been read here.
- **Performance on a large file is unmeasured.** The scanner is a line at a time and carries
  three pieces of state, but nothing has been timed.
- **Only pylsp has been tried.** pyright and ruff-lsp would both fit the profile; neither
  has been pointed at.

## State as of 2026-09-19 — moved to Rickub, released by a workflow

- **Module path `rickub.com/turbo-editors/turbo-python`**, depending on `rickub.com/turbo-editors/turbo-core v1.0.0` — the first turbo-core version published under that path (`v0.9.0` on the proxy still declares the Codeberg path and cannot be required as `rickub.com/…`). Every import, the Makefile's `VERSION_PKG`, `scripts/install.sh`, the README and the docs say `rickub.com`. `GOWORK=off make check` green. The repository on this side is a fresh `git init` with `origin` at `ssh://git@rickub.com/turbo-editors/turbo-python.git` and **no commit yet**; `01-release.tag.sh` makes the first one.
- **Releases are one script and one workflow**, modelled on turbo-core's and identical to turbo-go's. `01-release.tag.sh` runs `make check` under `TURBO_PYTHON_RELEASING=1`, refuses a tag taken locally or on origin (bump, never move), refuses a `replace` in `go.mod`, commits, pushes the current branch, then tags and pushes the tag. That push starts `.github/workflows/release.yml`: `go test` with `TURBO_PYTHON_RELEASING=1`, `./02-build-releases.sh "${GITHUB_REF_NAME}"`, release notes from the tag message, a run artifact, then `softprops/action-gh-release@v2` attaching `turbo-python-*`, `SHA256SUMS` and `README.md` with the job's own `GITHUB_TOKEN` — the only credential Rickub's release API accepts. **`02-release.publish.sh` and `04-release.upload-binaries.sh` are gone**; the build script is now `02-build-releases.sh`, takes the tag as `$1` (CI has no `release.env`), validates it, refuses a `replace`, and starts from an empty `release/${TAG}/`. `release.env` holds only `TAG` and `ABOUT`; `turbo-python.token.env` is read by nothing.
- **`release_test.go`** runs `01` for real against a throwaway bare remote (publishes, then refuses the same tag), runs `02` alone to see it refuse `v0.o.0`, and asserts the workflow's trigger, `contents: write`, `./02-build-releases.sh`, `fail_on_unmatched_files`, docs linked at the tag, no `secrets.`, and `TURBO_PYTHON_RELEASING`. The copy of the module for the clone leaves out `.git`, `bin`, `release`, `kits`, `demo`, `demos`, `*.env` and `go.work*`; children run with `GOWORK=off`.