Latency is the feature.
A native code editor built around the gap between a keystroke and a photon, and measured against it rather than described as fast.
Beta. Windows and Apple silicon.
1/// What a frame is allowed to cost. 2pub struct Budget { 3 pub frame: Duration, 4} 5 6impl Budget { 7 // 60 Hz, less the compositor’s slice. 8 pub fn interactive() -> Self { 9 Self { frame: Duration::from_micros(16_667) } 10 } 11 12 pub fn met_by(&self, measured: Duration) -> bool { 13 measured <= self.frame 14 } 15}Measured, not asserted
Every editor worth using is fast at the thing it was designed around and slow at
everything else. The only way that claim means anything is with a figure behind it, so ferrum-bench is a headless latency harness that reports p50 through p99.9,
gates against a baseline, and refuses to call a noisy run a result.
- Frame of a 100k line file
- 545µs
- A pane of a 4,800 row tree
- 171µs
- Languages highlighted
- 14
- Tests in the workspace
- 1022
In-process CPU work on one thread, p50, on a 2070 and an i7-8700K. Not end-to-end latency, and the tool that produces these says so on every run.
ctrl-shift-f searches the project with the same case, whole-word and regex toggles as the find bar. alt-h folds out the replace box and ctrl-alt-Enter replaces every match. Files open with unsaved changes are left alone, and the summary says how many.
ctrl-shift-falt-hctrl-alt-Enter
7 results in 6 files
- ferrum-render/budget.rs:9 frame: Duration::from_micros(16_667),
- ferrum-render/atlas.rs:41 let waited: Duration = start.elapsed();
- ferrum-bench/report.rs:118 fn p99(samples: &[Duration]) -> Duration {
- ferrum-term/pty.rs:64 timeout: Duration::from_millis(8),
- ferrum-render/budget.rs:22 pub fn met_by(&self, m: Duration) -> bool {
- ferrum-text/shape.rs:77 let budget: Duration = self.frame / 4;
- ferrum-bench/run.rs:205 samples: Vec<Duration>,
Clicking a changed file in source control opens it next to the version in HEAD: committed on the left and read only, the working file on the right, changed lines banded on both. It finds the files you have been working on — it does not stage or commit.
HEAD read only
28fn present(&mut self) { 29 let t = Instant::now(); 30 31 self.draw(self.budget); 32 self.swap(); 33 34 let spent = t.elapsed(); 35 if spent.as_millis() > 33 { 36 self.missed += 1; 37 } 38}Working file
28fn present(&mut self) { 29 let t = Instant::now(); 30 31 self.draw(self.budget); 32 self.swap(); 33 34 let spent = t.elapsed(); 35 if !self.budget.met_by(spent) { 36 self.missed(spent); 37 } 38}ctrl-backtick opens a shell in a panel and closes it from inside. It handles what a shell, a compiler and a test runner emit: colour, cursor movement, erasing, scroll regions and the alternate screen. The selection follows the text, not the screen.
ctrl-`ctrl-shift-eshift-PageUp
1/// What a frame is allowed to cost. 2pub struct Budget { 3 pub frame: Duration, 4} 5 6impl Budget {$ cargo test --workspace Compiling ferrum-render v0.1.0 Compiling ferrum-shell v0.1.0 Finished test profile in 4.31stest result: ok. 1022 passed; 0 failed$ ▊Two themes ship, built from one design in two appearances. Beyond those, Ferrum reads any theme installed in Visual Studio Code — a real translation, deriving what a theme leaves unset and compositing translucent colours onto the surface beneath them.
1/// What a frame is allowed to cost. 2pub struct Budget { 3 pub frame: Duration, 4 pub input: Duration, 5} 6 7impl Budget { 8 // 60 Hz, less the compositor’s slice. 9 pub fn interactive() -> Self {10 Self {11 frame: Duration::from_micros(16_667),12 input: Duration::from_millis(8),13 }14 }1516 pub fn met_by(&self, measured: Duration) -> bool {17 measured <= self.frame18 }19}Ferrum Light
ferrum-lightWarm near-neutrals over a white code canvas. The accent is the same hue at a lower lightness, because the dark theme’s orange manages only 3.12:1 on white.
It knows what you are writing
Ferrum speaks the language server protocol, so completions, types, errors and definitions come from the same tools your project already uses.
Completions that finish the job
Accepting a name that is not in scope brings its import in with it, in the same undo step -- so one press of escape takes back the whole thing rather than leaving a `use` line behind. Where no server can answer, the words already in the file are offered instead.
1/// What a frame is allowed to cost. 2pub struct Budget { 3 pub frame: Duration, 4} 5 6impl Budget { 7 pub fn interactive() -> Self { 8 Self { 9 frame: Duration::from_mil 10 11 12 13 14 15 16 Accepting this also writes use std::time::Duration, in the same undo step.
The error where you are looking
Rest on something underlined and the compiler's own words are the first thing in the tip, above what the symbol is. The message you want is the one you are pointing at, not one to go and find in a panel.
30 pub fn present(&mut self) { 31 let began = Instant::now(); 32 self.draw(); 33 34 let spent = began.elapsed(); 35 if spent > self.started { 36 37 38 39 40 41 42 43 expected `Duration`, found `Instant`
pub struct Duration
A span of time, held as whole seconds and a count of nanoseconds.
Fourteen languages, coloured by a real parser
Tree-sitter grammars, resolved against the theme's role table rather than a list of colour names — so a keyword is a keyword in every theme, including the one you brought from Visual Studio Code. Markdown is the block grammar only: headings, fences and lists colour, emphasis inside a paragraph does not.
- Rust
- TypeScript
- JavaScript
- TSX
- Python
- Go
- C
- HTML
- CSS
- JSON
- TOML
- YAML
- Markdown
- Shell
The icons are the editor's own, from the Material Icon Theme it generates its file tree set from.
And the rest of it
Multiple carets
alt-click adds one, ctrl-alt-up and down add one above or below, and every edit applies at every caret. Escape collapses back to one.
Open by typing
ctrl-p opens a file by part of its path. ctrl-o and ctrl-shift-o open a file or a folder through the platform’s own dialog.
Split into columns
ctrl-backslash opens a column beside the current one. Each keeps its own tabs and its own scroll; alt-left and alt-right move between them.
A tree that watches
A file created by a build or a git checkout appears on its own. Icons come from the file type, and git status sits beside the name.
Rendered Markdown and HTML
The dropdown at the right of the path bar switches between source and rendered. There is no CSS and no script — it is a reader, not a browser.
Diagnostics from rust-analyzer
Rust only, and only when rust-analyzer is already on your PATH. Underlines hide while they are stale rather than drifting to the wrong place.
Your fonts
Any family installed on the machine, by name rather than by file — Consolas by default on Windows, because that is what most people arrive reading code in.
Settings that follow you
Sign the editor in from the Account menu and push or pull settings.toml between machines through your account here.
Try it
It opens a project, shows you the files with their icons and what git says about each, lets you edit them in tabs, searches all of them, and runs a shell underneath. The download page says what is not there yet.