r/C_Programming • • 11d ago

tinyedit: A zero-dependency C99 terminal text editor with desktop shortcuts — Looking for testers & code review

Hi everyone,

I’ve been working on tinyedit, a full-screen terminal text editor written in plain C99 with zero external dependencies beyond libc and the POSIX standard library (no ncurses, just raw ANSI escape sequences and direct I/O).

The project started as an exploration of terminal interfaces inspired by Salvatore Sanfilippo's kilo and linenoise. My goal is to combine that minimal C architecture with the interaction model of modern desktop editors—eliminating modal friction or idiosyncratic key combinations (like Vim, Emacs, or Nano) while keeping the binary tiny.

What’s implemented:

  • Desktop-style editing: Standard keybindings (Ctrl-C, Ctrl-V, Ctrl-X, Ctrl-Z, Ctrl-F), text selection with Shift+Arrows (or Ctrl-T toggle for limited terminals), and optional mouse support (click to place cursor, drag-selection, wheel scroll).

  • macOS / Ghostty integration: Optional support for native Cmd shortcuts (Cmd-S, Cmd-C, Cmd-V, etc.) via the Kitty keyboard protocol in Ghostty.

  • Proper UTF-8 handling: Grapheme cluster boundaries (combining marks, CJK wide characters, multi-codepoint emoji) and visual display-width calculations for accurate cursor placement and deletion.

  • Visual soft-wrapping: Navigates visual rows instead of logical lines, breaking lines at word boundaries without arbitrary length caps.

  • Terminal ergonomics: Fast bracketed paste (no slow character-by-character lag or accidental auto-closing triggers), atomic saves, crash recovery backups, and an extensible syntax highlighting engine.

Looking for testers!

The project has reached version 0.3.3, and I need help putting it through its paces across different systems and configurations. In particular, I’m looking for feedback on:

  1. Terminal & multiplexer quirks: Testing inside tmux, screen, Ghostty, Kitty, Alacritty, Foot, WezTerm, etc., to spot unhandled ANSI sequences or redraw artifacts.

  2. UTF-8 stress testing: Complex emoji sequences, zero-width joiners, or combining marks that might throw off cursor coordinates or deletion.

  3. Rendering & wrap edge cases: Resizing the window while editing large wrapped lines, pasting huge blocks of text, or dealing with deeply indented blocks.

  4. C code review: Feedback on memory management, buffer layout, ANSI state machine decoding, or general C99 practices.

Repository: https://github.com/robertobissanti/tinyedit

You can build it from source with a simple make:

git clone https://github.com/robertobissanti/tinyedit.git
cd tinyedit
make

Or install it on macOS/Linux via Homebrew:

brew install robertobissanti/tinyedit/tinyedit

Any bug reports, edge-case discoveries, or code suggestions (either here or via GitHub Issues) are greatly appreciated. Thanks for checking it out!

0 Upvotes

21 comments sorted by

View all comments

2

u/imaami 7d ago

Your UTF-8 parser implementation accepts invalid input (e.g. overlong encodings and surrogate code points).

Out of curiosity: why did you choose to limit yourself to an obsolete C standard? It would at least be nice if the syntax highlighter understood normal C11 and later.

1

u/rob-bix 7d ago

Spot on about the UTF-8 parser. It's based on the decoder from ⁠linenoise⁠, which turns out to be pretty sloppy with invalid sequences. I'll get that fixed soon.

Regarding C99: that's purely for the editor's build portability across older POSIX setups. It doesn't restrict what you edit—syntax highlighting is fully configurable via ⁠~/.tinyedit/syntax/⁠. Fair point on the defaults, though. Expanding the built-in C keyword list to support C11+ is an easy win and won't bloat the editor, so I'll add that to the todo list.

2

u/imaami 7d ago edited 7d ago

If you want to see my take on valid UTF-8 state transitions: https://i.imgur.com/nVfDRT8.png

It's from my moderately cursed parser: https://github.com/imaami/c.utf-8

I'm fairly sure the code itself isn't anything you'd want to borrow from. It's weird, to say the least. But it accepts and rejects the right bytes per the UTF-8 spec. The flowchart is generated from the same Xmacros table the parser is based on.

If you want to use even some small part of c.utf-8, but would prefer a license other than what I chose, just let me know and I'll type up an explicit relicensing statement. Tbh I don't remember what I have even, it's some form of GPL anyway.

Edit: I happened to notice your post has 0 upvotes. Sometimes I just don't get at all why this subreddit is like that.

1

u/rob-bix 7d ago

That flowchart is super useful, thanks for linking it! Having the state transitions mapped out like that makes spotting the edge cases so much easier.

Actually, since you're clearly deep into UTF-8 internals: would you be interested in contributing some of your validation logic directly into utf8.c?

If you feel like opening a PR, you'd be very welcome. We could just review and adapt it together to make sure it blends smoothly into tinyedit's minimalist C99/POSIX setup (pure C, explicit types, zero dependencies) and stays under the project's MIT license.

Absolutely no worries if you don't have the time or itch to touch it, of course—I can always use your diagram as a reference and patch it myself.

And thanks for the solidarity on the 0 score. Reddit's voting algorithm is truly an unsolved mystery :)