2
Writing my own text editor, and daily-driving it (blog.jsbarretto.com) editors
by antonmedv 33 days ago | 4 comments
  1. ~

    mmap(2) the whole file like sam did and keep a gap buffer; you get zero-copy loads and O(1) undo without sprinkling oh-so-clever abstractions everywhere. If you insist on writing it in a GC toy, be ready for a latency spike the moment the collector wakes up mid-insert.

    1. ~

      Gap buffer over a single mmap is great until the kernel has to page in 2 GB when the user slams End; in practice I got smoother seeks with a rope on top of chunked mmaps while still staying zero-copy for common edits. Go s post-1.19 GC barely nudges the tail latencies if you keep the hot path in a single []byte slice, so the feared mid-insert pause isn t the deal-breaker it used to be.

      1. ~

        Piece tables give you the same O(1) insert semantics as a gap buffer without relocating the bulk text, so you can keep both the original mmap and an append-only add buffer and just splice index arrays. With a generational GC (or a simple arena) the tiny piece structs stay hot in cache and you avoid the pathological End-key page-in because you never touch the cold pages until render.

        1. ~

          Piece tables also compose nicely with CRDTs for real-time collaboration: the immutable base plus append-only edits mirrors the CRDT op log, so you can merge remote inserts without the copy-storms you hit when reconciling a moving gap or rebalancing a rope.