Kealler — the Keal IDE

An editor for Keal, written in Keal and drawn by keal-view. There is no toolkit under it: every pixel, the gutter and the syntax colours included, comes out of a loop written in Keal.

Download

PlatformArchitectureFile
macOSApple siliconkealler-macos-arm64.tar.gz
Linuxx86-64kealler-linux-x86_64.tar.gz
Windowsx86-64kealler-windows-x86_64.tar.gz

On Windows, fetch it with curl rather than through this page. Windows marks what a browser downloads and SmartScreen reads that mark, not the file, so an unsigned program gets “Windows protected your PC” with the way through hidden behind “More info”. A terminal fetch attaches no mark. If you already downloaded it here, Unblock-File .\kealler.exe in PowerShell removes it.

On macOS, fetch it with curl rather than through this page. macOS quarantines what a browser downloads and Gatekeeper reads that attribute, not the file — and this build is signed only ad-hoc, so it will object. curl sets no such attribute, so there is nothing to override: curl -L -o kealler.tar.gz <the link below> && tar xzf kealler.tar.gz && ./kealler. If you already downloaded it here, xattr -dr com.apple.quarantine kealler removes it.

What it does

Open, edit, save

A file tree with a filter that matches letters in order — apk finds app.keal. Undo grouped the way an editor groups, so undoing a word takes one press and not five. Find across every file in the tree, with the matches painted over the syntax rather than instead of it. A file's line endings are kept: a Windows file opened here stays a Windows file.

Coloured by the compiler, not by a copy of it

The highlighting is keal tokens — the lexer that compiles the file. A second grammar written in regular expressions agrees with the compiler on the day it is written and disagrees the first time the language grows.

And thirteen other file types coloured by a table that says so

Java, Kotlin, Go, Rust, C, C++, Python, SQL, JavaScript, TypeScript, JSON, shell, TOML and YAML. This one is a second grammar, which is the wrong answer everywhere else here and the only answer where there is no first grammar to defer to: javac hands out no token stream. Asked about five of these, keal tokens refuses at the first unfamiliar character and returns nothing, so borrowing Keal's lexer does not stretch — measured, and each of those five characters is now a test. What the table is allowed to do is narrow: it colours and decides nothing. No outline, no definition, no completion comes from it.

Go to a definition anywhere, and to any name by typing it

⌘B asks three questions in the order of what they cost and stops at the first that answers: this file’s outline, free; the files it imports, 97 ms for twenty; then the project, 0.3 s here and 1.16 s on the largest repository measured. ⇧⌘O lists every declaration behind a filter. This is the one thing here that does not come from the compiler, and it says so: keal types gives a name’s position with no file, so this reads each file’s tokens and asks its outline. A name declared twice is two answers — which the checker would pick is scope and visibility, and that belongs to the language.

What the compiler thinks, where it happened

keal check runs on the file you are looking at, and each thing it found is drawn on the line it names rather than in a list somewhere else.

The type under the caret, and completion that knows imports

The status bar says what the thing under the caret ishelper : (String) -> Int — and completion offers names with their signatures, including names declared in another file. This was planned as a language server and is not one: keal types prints the checked typed tree, follows imports, and answers in 40 ms on a thousand lines. It is asked when the file is opened and when it is saved, never while you type — the compiler reads the file on disk, and a type that lags the text beside it is worse than no type.

A project that compiles before you have written anything

Ten templates — Keal, Keal with a window, Java, Kotlin, Go, Rust, C, C++, Python, Spring Boot — each laid out the way that language expects, with a manifest its tool accepts. The toolchain is probed while you type the name, so a missing compiler is said there rather than two steps later, with one command to fix it. Nothing is installed for you.

A toolchain fetched, with the checksum as the feature

Go, for now, from Nouveau projet when it is missing. The source must publish its checksum as plain text at a URL derived from the archive's own, fetched separately and before the archive — so a wrong version, a wrong platform, a truncated download or a substituted mirror all end the same way: the hash does not match, the file is deleted, nothing is unpacked. Then the binary runs its own version before anything calls it installed. Java is absent because Temurin's link and checksum live in the same JSON document, so a parse that picks the wrong asset picks its matching checksum and the check passes — that fails open. Nothing touches your PATH.

git in the margin and in the tree

M, ? and D beside the files, and the diff in the gutter: green added, amber changed, red removed. Refreshed on open and on save, not while you type, for the same reason the types are.

Run it without freezing the editor, and see a web app's routes

Every program is started detached, its output streaming into the Journal, with a way to stop it — because a server or any other program that does not end used to hang the window until it was killed from outside. A kealeb application also gets its routes as its outline, read from keal tokens rather than from a scan of the text, and the address to open in a browser comes from the line the server itself printed rather than from a port the editor picked. What it will never do is draw the page: kealeb emits HTML for a browser engine, and a picture that is nearly the page is wrong exactly where it is interesting.

A kealeb page previewed, as that program prints it

Click voir beside a route and the file is built, then asked for that page with kealeb’s --render — a flag added for this, which puts a browser’s request through the same filter chain the server uses and prints what comes back. Measured on a live page: --render and a real browser fetch differ in the session token and in nothing else. What Kealler will never do is draw the page. kealeb emits HTML for a browser engine; a picture that is nearly the page is wrong exactly where it is interesting.

A preview that is the program's own output

Building a keal-view program and showing the frame it drew — with no display involved, through --snapshot. No second renderer to keep in agreement with the first, so the preview cannot be subtly wrong.

A layout that survives being closed

Panels are dragged, split and tabbed, and where you left them is where they are. An arrangement naming a panel that has gone is pruned rather than refused.

What it needs

The Keal compiler, beside it or on your path — the colouring is keal tokens, the diagnostics are keal check, and building is keal build. With none it says so and keeps working: the tree, the source and the layout do not need one, the colouring goes plain, and nothing is checked. That is the honest state rather than a silent one.