m³OS docs GitHub

Phase 26

Text Editor

A usable text editor runs inside the OS. Users can create, edit, and save files from the shell. This is the foundational tool that makes all subsequent "do real work inside the OS" phases possible — you cannot write code, configuration files, or documents without an editor.

Complete

Learning goal

Understand how terminal-based editors use raw mode, ANSI escape sequences, and screen coordinates to build a full-screen TUI.

Category

productivity

Builds on

Why this phase matters

A usable text editor runs inside the OS. Users can create, edit, and save files from the shell. This is the foundational tool that makes all subsequent “do real work inside the OS” phases possible — you cannot write code, configuration files, or documents without an editor.

How it works in m3OS

Phase 26 adds edit, a minimal full-screen text editor for m3OS. It is a no_std Rust binary based on kibi/kilo concepts: a line-based text buffer, VT100 escape sequences for screen control, raw terminal mode, and a single-file editing model. The editor is available at /bin/edit and is set as the $EDITOR environment variable.

How it builds on earlier phases

This phase builds on SMP and turns that foundation into Text Editor.

Implementation outline

  • Extend syscall-lib with ioctl, lseek, termios, and winsize wrappers.
  • Add a userspace heap allocator (kibi uses Vec/String via alloc).
  • Create userspace/edit/ crate (no_std, x86_64-unknown-none target).
  • Write an m3OS platform backend (~60-80 lines) implementing terminal I/O.
  • Port kibi’s core modules, replacing std::fs/std::io with syscall-lib.
  • Verify raw mode, file save/load, and search work end-to-end.
  • Add to xtask build, initrd, and set $EDITOR=/bin/edit.

Task progress snapshot

75 of 75 tracked tasks are complete.

Documentation targets

  • Documentation deliverables have not been listed yet.

Deferred follow-on work

  • ncurses or equivalent TUI library
  • terminfo/termcap database
  • Multiple file editing (split views, tabs)
  • Undo/redo (kilo supports single-level undo; full undo tree is deferred)
  • Plugin or macro system
  • Mouse support

Source materials

Important code

Code spotlight cards

Code spotlight

Add `ioctl()` wrapper

userspace/syscall-lib/src/lib.rs L417-L420

Add `ioctl()` wrapper. Why it matters: All terminal control operations (termios, window size) go through the ioctl syscall interface. Focus on `ioctl` in `userspace/syscall-lib/src/lib.rs` while you trace the snippet.

/// Perform an ioctl operation on a file descriptor.
pub fn ioctl(fd: i32, request: usize, arg: usize) -> isize {
    unsafe { syscall3(SYS_IOCTL, fd as u64, request as u64, arg as u64) as isize }
}

Code spotlight

Create userspace heap allocator

userspace/syscall-lib/src/heap.rs L21-L29

Create userspace heap allocator. Why it matters: The editor uses Vec, String, and format! which all require a global allocator in no_std. Focus on `BrkAllocator` and `Vec` in `userspace/syscall-lib/src/heap.rs` while you trace the snippet.

/// A simple brk-based allocator with a free list.
pub struct BrkAllocator {
    /// Start of the free list (first free block).
    free_list: core::cell::UnsafeCell<*mut BlockHeader>,
    /// Current program break (top of heap).
    brk_current: AtomicU64,
    /// Whether brk has been initialized.
    initialized: core::cell::UnsafeCell<bool>,
}

Code spotlight

Verify allocator works

userspace/edit/src/main.rs See file

Verify allocator works. Why it matters: A broken allocator would cause silent corruption or panics in the editor. Focus on `Vec<u8>` in `userspace/edit/src/main.rs` while you trace the snippet.

Key files

  • userspace/edit/ — Create userspace/edit/ crate (no_std, x86_64-unknown-none target).

How real OSes differ

  • Real systems ship with multiple editors (vi, nano, emacs) and editor infrastructure like terminfo/termcap databases that abstract terminal capabilities. Our approach hardcodes VT100 escape sequences, which is fine because QEMU's serial console and virtually all modern terminal emulators support VT100.
  • A production OS would also provide shared libraries for TUI development (ncurses), which we defer.
  • A notable side effect of this phase is establishing the pattern for Rust userspace programs that need heap allocation (`Vec`, `String`, `format!`). The userspace heap allocator built here is reusable by future phases (compiler bootstrap, build tools, etc.).

Success criteria

  • The editor launches from the shell and displays a full-screen TUI.
  • Arrow keys, Page Up/Down, Home/End move the cursor correctly.
  • Users can type text, delete characters, and insert new lines.
  • `Ctrl+S` (or equivalent) saves the file to persistent storage.
  • `Ctrl+Q` (or equivalent) quits the editor.
  • `Ctrl+F` (or equivalent) searches for text within the file.
  • Opening a nonexistent filename creates a new empty file on save.
  • The editor correctly handles files larger than the terminal height (scrolling).

Related phases

Keep exploring the roadmap