Turbo Python
A Python IDE in the shape of Turbo Pascal 7.0: a desktop of windows, a menu bar, a status line, and the compile-land-on-the-error-fix-recompile loop that made the original worth using.
File Edit Search Run Compile Debug Tools Options Window Help
╔[■]════════════════════════════ GREET.PY ═════════════════════════════ 1 [↑]╗
║ 1 def greet(name): ║
║ 2 """Say hello.""" ║
║ 3 return f"hello {name}" ║
║ 4 ║
║ 5 ║
║ 6 for who in ['world', 'turbodesk']: ║
║ 7 print(greet(who)) ║
║ 8 ║
║ ║
╚ 1:1 ══════════════════════════════════════════════════════════════════════◢
F1 Help F2 Save F3 Open Alt+F9 Compile F9 Make F10 Menu
Run it
uv sync
uv run turbopython greet.py
F10 opens the menu bar and File ▸ Exit leaves, so there is a way out before you have learned a single key.
What it does today
Run a program and land on the line that broke it. A traceback goes into the Messages window as a jump list, and the cursor lands on the deepest frame in your code — not the one inside json/decoder.py, which is not a file you can fix.
Compile without running. Alt-F9 is compile(src, name, "exec"): instant, and a SyntaxError puts the message on the window's top line with the cursor on the column it names.
Make and test the way Python projects actually do. Compile ▸ Make reads the nearest Makefile and lists its targets; Run ▸ Tests runs pytest and puts every failure where Enter jumps to it. Borland's Make byte-compiled the units a program needed, which is a step Python does for itself.
File Edit Search Run Compile Debug Tools Options Window Help
╔[■]══════════════════┌────────────────────────┐═══════════════════════ 1 [↑]╗
║ 1 def greet(name): │ Run Ctrl-F9 │ ║
║ 2 """Say hello."│ Tests │ ║
║ 3 return f"hello├────────────────────────┤ ║
║ 4 │ Step over F8 │ ║
║ 5 │ Trace into F7 │ ║
║ 6 for who in ['world│ Go to cursor F4 │ ║
║ 7 print(greet(wh├────────────────────────┤ ║
║ 8 │ Program reset Ctrl-F2 │ ║
║ │ Parameters... │ ║
║ └────────────────────────┘ ║
╚ 1:1 ══════════════════════════════════════════════════════════════════════◢
F1 Help F2 Save F3 Open Alt+F9 Compile F9 Make F10 Menu
Greyed items are the ones with nothing behind them right now — no window open, no program running — which is how Borland's menus worked. It is worth knowing what that greying cannot tell you: an item naming a command nobody ever wrote greys identically, and three of those sat on these menus for months. A test now reads commands.py and fails if a menu item names something unimplemented.
See the shape of the project. Search ▸ Outline docks a window showing what is in the file in front, rebuilt from the live buffer as you type. Search ▸ Class browser is the same ast walk read across every file: what derives from what, project-wide, with the module beside each class. Arrows walk either one and open the file it names; Space folds. Both are stdlib and neither needs a language server. Ctrl+Enter on a name goes to where this file defines it, and looks for a module only when it does not.
A language server, when there is one. ruff server starts in the background after the first frame and never before it: the IDE is up and working without one, which is the rule the whole layer is built to. Diagnostics land in the Messages window as the same jump list the compiler's errors and the test failures use — Enter goes to the line. Tools ▸ Diagnostics lists them, and the status line says which mode you are in (lsp, lsp down, or nothing at all when none was asked for). No node runtime, and nothing on any menu exists only when a server is running.
Find a file by typing at it. File ▸ Find file (Shift-F3) is a fuzzy picker over the project — wfr finds widgets/frame.py. F3 still opens the tree, because the two answer different questions: one is for looking around, the other for when you already know the name.
A primary file, which is what 7.0 called a run configuration. Compile ▸ Primary file... names the program Run acts on however many windows are open over it, so editing a module and pressing Run does not run the module. Clear primary file gives the front window back.
An editor with the things an editor needs. Syntax colouring, line numbers, find and replace, undo that groups a run of keystrokes, standard / vim / emacs keymaps, and a mouse that puts the caret where you press and selects what you drag over.
Windows. Overlapping, draggable by the title bar, resizable from any corner, zoom, tile, cascade. Alt-1 to Alt-9 raise one by number.
Ruff, mypy and pytest in the Tools menu, each parsed into the same jump list.
Keys
Two schemes, and it asks which on first run rather than guessing:
- Turbo Pascal — what Borland shipped. Needs a terminal that sends Alt.
- Modern — every Turbo binding that works anyway, plus a second key for each one Borland put on Alt:
F7forAlt-F9,F12forAlt-F5,Ctrl-WforAlt-F3,Ctrl-QforAlt-X.
macOS sends no Alt by default. The Option key composes characters there — Option-E then e is é — so Alt-X never arrives. Modern is the default on a Mac, and Help ▸ Key test says which setting turns Alt on for your terminal (Use Option as Meta key in Terminal.app, Esc+ in iTerm2).
The menu shows the key the active scheme binds, so an accelerator never promises something that does nothing.
What it is not, yet
No debugger. That is the next milestone: breakpoints in the gutter, step and trace, a watch window and the call stack, over bdb in a subprocess. No class browser, no project files, no REPL window. notes/turbopython-ide.md in this repository is the plan, and it is honest about what is missing.
Why it exists
It is the largest application built on turbodesk, and it was built to find out what the library was missing. It found a great deal: the window stack, the menu bar, focus groups, drag gestures, an editor gutter and syntax colouring are all in the library now because this needed them. notes/turbodesk-roadmap.md records that trade in both directions.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file turbopython_ide-0.5.0.tar.gz.
File metadata
- Download URL: turbopython_ide-0.5.0.tar.gz
- Upload date:
- Size: 78.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.30 {"installer":{"name":"uv","version":"0.11.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
53ba8b4630afe67005aa98245cd897f8bf2977fc2ec12d322eb1ce66682a9e05
|
|
| MD5 |
f51720f6379ef50c880c0cffa1f784fa
|
|
| BLAKE2b-256 |
089ebc38396a05637f45290523bb789b126c5731e48c994d5a6bc46edafb550a
|
File details
Details for the file turbopython_ide-0.5.0-py3-none-any.whl.
File metadata
- Download URL: turbopython_ide-0.5.0-py3-none-any.whl
- Upload date:
- Size: 92.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.30 {"installer":{"name":"uv","version":"0.11.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1cf1a3293883270c333564199ab591445481b1fb5b7ba5f3c4a6e92f5487ac2
|
|
| MD5 |
0d6777394b1e1c1ef0f92ba6cf9e27f3
|
|
| BLAKE2b-256 |
1a6eddc91c395bd260faa884ce962d91ebc9c0665f6a39d1d7b20de9e09daec7
|