diff options
| author | rottedfm <rottedfm@proton.me> | 2026-08-19 11:21:47 -0400 |
|---|---|---|
| committer | rottedfm <rottedfm@proton.me> | 2026-08-19 11:21:47 -0400 |
| commit | ea0bd36167b684c0accdb5ce2b2e21b8d84aeb25 (patch) | |
| tree | be1267972b5de2f1ae592577dfabce67f1fe6e87 /README.md | |
| parent | 8c0b4c53b130555f040884c1f52b90f16b23e241 (diff) | |
feat: implement Helix-style modal buffer under DO-178C DAL-C
The repository was an unmodified ratatui component template: no editor
code, JSON5 config, and placeholder widgets. This establishes the first
working baseline — `moji <file>` opens a file into a ropey rope and edits
it with Helix selection-first semantics.
Requirements, implementation and tests land together because they must:
the traceability check rejects requirements with no implementation and
tests naming requirements that do not exist, so neither half is a valid
commit on its own.
Package renamed to mojibake-editor (mojibake was taken on crates.io);
binary is moji, library target stays mojibake.
Class: New behaviour
Requirements: MJB-HLR-001..019, MJB-LLR-001..205
Derived: MJB-DR-001..007 (DR-001 resolved, six open for review)
Verified: cargo build; clippy --all-targets -D warnings clean;
cargo test 294 passing; ./scripts/check-trace.sh 98/98/98;
cargo package clean
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 190 |
1 files changed, 182 insertions, 8 deletions
@@ -1,9 +1,183 @@ # mojibake - 文字化け ---- - -## TODO -- [ ] setup ratatui component framework base -- [ ] setup core buffer -- [ ] setup feature type system -- [ ] setup testing/documentation rules -- [ ] setup license + +A terminal text editor with Helix-style modal editing. + +> [!WARNING] +> **Early development — not ready for daily use.** +> +> There is no yank/paste, no search, and no syntax highlighting. Undo works one +> keystroke at a time rather than per edit. Treat this as a working foundation, +> not an editor you should trust with real files yet. See [Status](#status) for +> exactly what does and does not work. + +```sh +cargo install --path . +moji <file> +``` + +The crate is `mojibake-editor` (the name `mojibake` was already taken on +crates.io by an unrelated encoder); the command is `moji`. + +A path that does not exist is created on write. With no path, `moji` opens an +empty scratch buffer. + +## Status + +### Works + +- Opens, edits and saves UTF-8 files; UTF-16 with a BOM round-trips +- CRLF and CR line endings are detected and preserved +- Helix selection-first editing: `w` selects a word, so `wd` deletes one +- Motions, goto, insert-entry, delete/change, undo/redo, paging +- Counts (`5l`, `2w`) +- Config-driven modal keymap in TOML; chords resolve without a timeout +- Writes through symlinks, preserves permissions, restores on failure +- Rendering is O(viewport) — a 200k-line file scrolls without lag + +### Does not work yet + +- **No yank or paste.** `y`, `p`, `P` are unbound. +- **No search.** `/`, `?`, `n`, `N` are unbound. +- **No `f`/`t` motions.** They need pending-argument capture, which the keymap + cannot express yet. +- **Undo is per keystroke.** Typing `abc` in insert mode costs three undos; + Helix commits one checkpoint when you leave insert mode. +- **`:w <path>` ignores its argument** and writes to the original path. +- **One file at a time.** No buffer list, no splits. +- No syntax highlighting, no LSP, no multiple cursors, no soft wrap. + +## Keybindings + +Bindings follow the [Helix default keymap](https://docs.helix-editor.com/keymap.html) +and live in `.config/config.toml`. Defaults ship compiled in; user settings +override them **per individual binding**, so rebinding one key keeps every +default you did not mention. + +Editing is **selection-first**, like Helix and unlike Vim: a motion leaves a +selection and an operator acts on it. There is no operator-pending state. + +| Mode | Keys | +|---|---| +| Motion | `h` `j` `k` `l`, `w` `b` `e`, `W` `B` `E` | +| Goto | `gg` `ge` `gh` `gl` `gs` | +| Selection | `x` `;` `%` `v` `Alt-;` | +| Insert | `i` `a` `I` `A` `o` `O` | +| Change | `d` `c`, `u` undo, `U` redo | +| Scroll | `Ctrl-u` `Ctrl-d` half page, `Ctrl-b` `Ctrl-f` full page | +| Command | `:w` `:q` `:wq` `:x` `:q!` `:w!` | + +Counts work as a prefix: `5l`, `12j`. + +## Configuration + +TOML only, at `$MOJIBAKE_CONFIG/config.toml`. See `.config/config.toml` for the +annotated defaults. + +```toml +[editor] +scrolloff = 5 +insert_final_newline = true + +[keybindings.normal] +"<g><g>" = "GotoFileStart" +"<ctrl-d>" = "PageCursorHalfDown" +``` + +## Roadmap + +Ordered by what most blocks real use. + +### 1 — Blocking daily use + +- [ ] Yank and paste: `y`, `p`, `P`, plus a register +- [ ] Undo checkpoints — group an insert session into one step + (Helix commits on leaving insert mode; see `Command::NormalMode`) +- [ ] Search: `/`, `?`, `n`, `N` +- [ ] Pending-argument capture in the keymap, then `f` `t` `F` `T` and `r` +- [ ] Honour the `:w <path>` argument instead of discarding it + (`run_command_line` binds it as `_arg`) +- [ ] Prompt on `:q` with unsaved changes rather than only refusing + +### 2 — Editor features + +- [ ] Multiple buffers and `:b` / `gn` / `gp` +- [ ] Auto-indent on newline; `>` and `<` to shift lines +- [ ] `J` join lines, `~` switch case, `.` repeat +- [ ] Match mode `m` — matching bracket, surround +- [ ] Soft wrap (reworks the viewport anchor — see `MJB-DR-003`) +- [ ] Multiple cursors (`Selection` is already shaped for it — see `MJB-DR-005`) + +### 3 — Language support + +- [ ] tree-sitter syntax highlighting +- [ ] `languages.toml` +- [ ] LSP client: diagnostics, completion, goto-definition + +### 4 — Project and process + +- [ ] CI: build, clippy, test, `scripts/check-trace.sh`, coverage +- [ ] Resolve the six open derived requirements in + `docs/requirements/derived.md` — each needs a judgement, not code +- [ ] Decide on ropey: stay on `2.0.0-beta.1` or move to stable `1.6.1` + (see `docs/reviews/library-selection.md`) +- [ ] Decide whether to publish to crates.io at all, or self-host only +- [ ] Replace the `unwrap` calls in `src/tui.rs::Drop` inherited from the + application template + +## Development + +```sh +cargo build +cargo clippy --all-targets -- -D warnings +cargo test +./scripts/check-trace.sh +cargo llvm-cov --summary-only test +``` + +`direnv` users get `.envrc`, which points config and data at the working tree. + +### Architecture + +- `src/buffer/` — the editor core: rope document, selection, transactions, + motions, viewport, keymap. No `ratatui` dependency, so it is testable without + a terminal. +- `src/components/buffer.rs` — the only widget; renders the visible window. +- `src/app.rs` — event loop and global key routing. + +Text is held in a [ropey](https://github.com/cessen/ropey) rope and addressed by +**byte** offset throughout. Rendering is O(viewport): the view is anchored by +the byte offset of the first visible line, and only that window is walked, so +per-frame cost does not scale with file size. + +## Process + +Developed to **DO-178C DAL-C**. Start with **[`docs/process.md`](docs/process.md)**, +which explains the requirement artifacts, the ID system, and what a commit must +satisfy. + +- `docs/process.md` — the system, and the commit rules +- `docs/requirements/` — high-level, low-level, and derived requirements +- `docs/traceability/trace.md` — HLR → LLR → source → test matrix +- `docs/reviews/` — review checklists and library-selection rationale + +Every low-level requirement is tagged in source as `// MJB-LLR-nnn` and has a +test named `mjb_llr_nnn_*`. The matrix is checked mechanically, not by +inspection: + +```sh +./scripts/check-trace.sh +``` + +It verifies traceability in **both** directions — requirements with no +implementation or no test, and tests naming a requirement that no longer +exists. All three sets must be empty. Run it before every commit. + +`git config commit.template .gitmessage` sets up the commit format; the template +lists the change classes and the pre-commit gate. + +Current: 294 tests, clippy clean at `-D warnings`, 98/98 requirements traced, +96.2% statement coverage of `src/buffer/**`. + +## License + +BSD 2-Clause. See [LICENSE](LICENSE). |
