Core Philosophy:
- Ease-of-Use: Fundamentally non-modal. Prioritizes standard keybindings and a minimal learning curve.
- Efficiency: Uses a lazy-loading piece tree to avoid loading huge files into RAM - reads only what's needed for user interactions. Coded in Rust.
- Extensibility: Uses TypeScript (via Deno) for plugins, making it accessible to a large developer base.
The Performance Challenge:
I focused on resource consumption and speed with large file support as a core feature. I did a quick benchmark loading a 2GB log file with ANSI color codes. Here is the comparison against other popular editors:
- Fresh: Load Time: *~600ms* | Memory: *~36 MB*
- Neovim: Load Time: ~6.5 seconds | Memory: ~2 GB
- Emacs: Load Time: ~10 seconds | Memory: ~2 GB
- VS Code: Load Time: ~20 seconds | Memory: OOM Killed (~4.3 GB available)
(Only Fresh rendered the ansi colors.)Development process:
I embraced Claude Code and made an effort to get good mileage out of it. I gave it strong specific directions, especially in architecture / code structure / UX-sensitive areas. It required constant supervision and re-alignment, especially in the performance critical areas. Added very extensive tests (compared to my normal standards) to keep it aligned as the code grows. Especially, focused on end-to-end testing where I could easily enforce a specific behavior or user flow.
Fresh is an open-source project (GPL-2) seeking early adopters. You're welcome to send feedback, feature requests, and bug reports.
Website: https://sinelaw.github.io/fresh/
GitHub Repository: https://github.com/sinelaw/fresh
extract_config_structs in build.rs (https://github.com/sinelaw/fresh/commit/a9f2fbc74b86840fe441...) does not, in fact, do what the comment says.
Eventually it'd wangle it's way into homebrew or the unstable branch of another package registry.
But that's me, because I really dislike installing binaries via a language's package manager, because they don't get updated unless I frequently run the upgrade commands for each package manager.
The other thing it gives you is the ability to easily upgrade and uninstall so just a script to copy stuff is not on par.
I wouldn’t, because I might be in a repo and it starts upgrading all my local dependencies, and I’m not gonna add a text editor as a dev dependency. I’ll happily take the binary, or a tar.gz with the binary in it, though.
(Btw I love how it’s following the old DOS aesthetic)
I do, religiously, as part of my routine to check for updates.
n lts && npm uninstall -g corepack && npm update -g && n prune
Sometimes things break (that's how `npm uninstall -g corepack` became a part of my one-liner), but it is easier to update often than to neglect updates for years.But I totally get the idea behind this, it's greatly combined with the cargo toolchain and is widely installed than cargo (which by the way npm is much easier to install than cargo with my personal experience), npm handles update nicely, and it can handle multiple arch too. I would still prefer npm install because I have installed a lot recently so it's ok.
Or you can use npm
Or you can download release binary packages from Github releases.
The problem is which option to make more prominent / first
strange thinking!
I've documented that as well it just isn't the first option listed
https://github.com/alshdavid/install-scripts/releases?q=node...
https://github.com/alshdavid/install-scripts/releases
All of the binaries here are expected to be standalone/portable installations, so you can download/extract the archive and just run the binary.
curl -L --url https://github.com/alshdavid/install-scripts/releases/download/terraform-1.14.1/terraform-1.14.1-linux-amd64.tar.gz | tar -xvzf - -C $HOME/.local/bin
$HOME/.local/bin/terraform --help
I haven't yet written a package manager yet, but I was planning for it to just do the same thing as above but figure out your OS/ARCH, handle extraction and also offer a PATH update system so you can run `eval $(xpkg env)` and PATH is updated automatically.That would be Nix. Runs on any Linux distro and OSX. Also particularly useful for NixOS and NixBSD.
Or do you just mean something like Guix?
https://www.youtube.com/playlist?list=PL9KpW-9Hl_het1V3_dLhG...
One of my long-standing "would make if I had the time and perseverance" themes has been a terminal text editor that's hugely VSCode-like + compatible, so always glad to hear anyone going anywhere near that, and hence I perked up from these:
> Prioritizes standard keybindings and a minimal learning curve.
> Extensibility: Uses TypeScript (via Deno) for plugins, making it accessible to a large developer base.
Because where you are now with Fresh, you're probably really not far from supporting say `settings.json`, `launch.json`, `tasks.json`, `keybindings.json`, `.tmTheme`s and theme `.json`s, and indeed bringing up a VSCode-API-implementing "extension host" that can load up and run/host most `.vsix`es. Now, being terminal-based you'd skip over certain feature subsets such as webviews, custom (non-text) editors and the like... and might postpone Notebooks and such fancies initially, but:
Consider! 1000s of high-value, capable, tech-specific dev extensions out there, all readily supported by your just-spawned new editor. Doesn't that sound pretty exciting?
After all, there's a huge subset of VSCode fans who'd always switch in a heartbeat to a just-simply-non-Electron version (whether native or terminal) of the very same feature-scape & extensions & UI dev experience if only it was made and to max compatibility (and MS won't ever do so).
All that's missing (from screenshot glance) is the other sidebars & panels in addition to File Explorer =)
Will be putting your Fresh on my Github Watch list, but then again, I never really read the GH feed anyway.. but maybe I'll remember to check back in every quarter or so =)
Also, there are nuances like VSCode exposing APIs that force the entire file to be in-memory (which is how VSCode works), this is fine but in my editor I'm trying to get extensions to work well even if the file is huge (encouraging incremental / partial stuff).
But yes, it's a very compelling vision... and part of the reason I chose TypeScript.
Thanks for the input :)
Now try opening it in Emacs with vlf [1] ;) Great work overall — looking forward to seeing further development!
It loads instantly, and memory usage is minimal <80 MB.
It does seem like vlf requires configuration and adjustment, e.g. navigation with the normal keys works differently (jumps to beginning/end of current chunk instead of the whole file). Basically it exposes the chunk concept to the user.
In Fresh it's designed into the core and should be more transparent (although there are still limitations).
Great work on this! Very good performance but also a very good UX and you really nailed the discoverability / accessibility - basically everything works intuitively and needs very little explanation - this is something that I can't say about really any other editor I've tried.
This may finally replace nano as my default utility editor, if not my main IDE.
Thank you :)
I searched for that desperately until I discovered micro[1].
Here's a quick comparison between micro and fresh:
- Fresh implements more standard keyboard shortcuts, like Ctrl+ArrowLeft and Ctrl+ArrowRight to skip to the next and previous word, Ctrl+Backspace to delete the previous word and Ctrl+Delete to delete the next one.
- Fresh is extensible in typescript, Micro in lua.
- Fresh is able to open the wikidata json dump (1.7T).
- Micro is included in most repos, so if you rent a new VPS you can immidiately dnf install it.
Getting included in distributions is a worthy goal... So many things to do
I'm on MacOS and I have remapped the fn and command keys so it can be more like Windows (I can't undo 20+ years of muscle memory, and also I just don't wanna)
Anyway, Fresh seems to ignore the remapping - it's back to the command key for copy/paste and the command palette.
Is there a way to access the dropdown menus by keyboard? I can see F underlined for File but no modifier key seems to make it happen
Also I'm already working on a ui for customizing the key bindings so you could do whatever you wanted. (Currently managed by undocumented json)
Thanks for reporting!
Keep up the good work !
I once started writing a text editor on Linux, and first went down a similar route: a piece table over a mmap()'d file. But I abandoned using mmap, because Linux file systems typically don't have mandatory locking enabled, so you can't be sure that the file data won't be modified by another program.
(Then I got bogged down in Unicode handling... so 95% of the code became just about that, and I tired of it)
So I opted for explicit management of chunks, also gives me more control and consistent cross platform behavior.
Because configuring an editor that comes with different plug-in systems in a third programming language is a lot of hassle for people who are too focused at getting the job done and don't want to be distracted with a whole another configuration framework in yet another programming language.
But the developer is clearly talented, no doubt about that. They know their stuff very well. Having tried writing a text editor myself, I could quickly tell they know their stuff by analysing the program design
so many commits authored by `claude` with 100+ lines each, that extent is not "some".
Thanks for reporting!
I feel like thats the opposite behavior. For example, I use https://github.com/zyedidia/micro as my main editor in terminal, where it says `Save changes to filename before closing? (y,n,esc)”` when you try to quit.
2. Thank you for running builds on ubuntu 22.04 so it's compatible with it. You might want to compile with cross or zig to support even older operating systems.
I'm not sure where you got this idea. The binary you distribute is dynamically linked:
> fresh: ELF 64-bit LSB pie executable, x86-64, [...], dynamically linked, [...]
and it links with libc, libm, and libgcc_s, which means the distro will matter, because GLIBC is not compatible that way.
How did you, after building this entire app, come to the conclusion that its statically linked? Rust apps typically aren't, by default.
I've found https://github.com/gphalkes/tilde to work quite well, it also supports the system clipboard. Nice to see a Rust alternative.
In VSCode it adds multiple cursors directly above/below.
In other editors I think it moves (shifts) the current line up or down.
Great work!
I feel like sublime text got most of it right and every editor since then has been a reskin of the same (just written in a different stack)
Since the original post was about a TUI editor, its worth mentioning Helix which supports most modern language out the box. That's amazing and wouldn't have been possible 10 years ago.
For terminal based, there are also many options but not so much in the direction of "VSCode style". They're mostly focused on being "vi-style". And also the huge file support isn't as good in any of the others that I've tried.
What are the reasons behind going with GPL-2 instead of a more permissive license like MIT or 0BSD?
You will probably at minimum build some neat helper functions and maximum code reuse is IMHO the best thing for the world.
I would for instance be curious on the ANSI routines but hesitate to invest mental energy when the code has limitations on usage.
Lastly cool to see new open source programs being built with heavy help from a code generation model. Inspiring!
I was settled on NVim and VSCode, then I discovered Zed, which is fantastic.
I guess you should not keep your life closed for new experiences. Everybody loves fast and responsive software, what can I say.
Thank you for your work, I will enjoy using it, it isn't for everything but that is how I started with Zed.
Or maybe try using a single tab in your terminal, maybe that will let the key pass through?
Anyway I need to add keybinding UX or maybe a different default set of keys for MacOS? hmm.
Modern developers have lost their mind
For extensions, the choice was either TypeScript (and get this bloat) or go with Lua and a much smaller binary (but less popular language).
But - I just realized stripping it brings it down to 76MB so I guess that's ok! Will push a commit :)
Speed. Bun starts fast and runs fast. It extends JavaScriptCore, the performance-minded JS engine built for Safari. Fast start times mean fast apps and fast APIs.
Elegant APIs. Bun provides a minimal set of highly-optimized APIs for performing common tasks, like starting an HTTP server and writing files.
Cohesive DX. Bun is a complete toolkit for building JavaScript apps, including a package manager, test runner, and bundler.
Bun is designed as a drop-in replacement for Node.js. It natively implements thousands of Node.js and Web APIs, including fs, path, Buffer and more."- From the homepage[1] - it's a shame they use semantic html but no anchors for direct linking.
License compatible, probably safe from a rug pull?
Incredible, the technical choice got overridden by popularity, leading straight to bloat
What ever suits you, you didn't mind shipping a 400mb executable after all, so what do i know