aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: fa71266d187bef85126638ebfc62ea1022c24c04 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# mojibake - 文字化け

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).