6d6918095a35
shorten the help screen to commands and plain words, flags moved to koh man (3.0.76)
- time
- 2026-09-27 10:00 UTC · 2 weeks ago
- machine
- Junes-MacBook-Pro.local
- agent
- deepseek/deepseek-flash
- session
- koh 3 phases 6-8
- parent
- 0c0e6474868d
↓ koh-6d691809.tar.gzatlas at this save
files changed4 files
VERSION+1 −1src/cli/cli.v+37 −37tests/cli_test.v+41 −0v.mod+1 −1src/cli/cli.v+37 −37
@@ -5,48 +5,48 @@55 66 module cli77 8+import src.fmt9+810 // Read from VERSION at build time, so the binary and the manifest cannot drift.911 pub const version = $embed_file('../../VERSION').to_string().trim_space()1012 11-const usage = 'koh ${version} — version control designed for the solo developer13+// The help screen. It is built rather than embedded in a constant, because the14+// colour follows NO_COLOR, KOH_NO_COLOR and whether the output is a terminal.15+// Flags are not shown here: `koh man <command>` documents every one.16+pub fn usage_text() string {17+ groups := [18+ [19+ ['save', 'snapshot your work'],20+ ['checkpoint', 'mark a place to come back to'],21+ ['status', 'what changed'],22+ ['log', 'history'],23+ ['diff', 'show changes'],24+ ],25+ [26+ ['undo', 'step back'],27+ ['revert', 'throw away unsaved changes'],28+ ['load', 'go to any save'],29+ ],30+ [31+ ['offer', 'send to your remote'],32+ ['steal', 'bring in from your remote'],33+ ],34+ ]35+ mut text := '${fmt.light('koh ${version}')} — version control for the solo developer\n'36+ for group in groups {37+ text += '\n'38+ for row in group {39+ text += ' ${fmt.gold(row[0])}${' '.repeat(12 - row[0].len)}${fmt.muted(row[1])}\n'40+ }41+ }42+ text += '\n ${fmt.dim('also: remote · flag · pluck · peek · init · doctor · strip · migrate')}\n'43+ text += '\n ${fmt.dim('koh man <command> for options and examples')}\n'44+ return text45+}1246 13-usage: koh <command> [options]14-15-everyday16- save <message> [--agent <m>] [--session <s>] snapshot the working tree17- checkpoint <message> save, even with no changes18- status what changed since the last save19- log [--since <expr>] [--session <s>] the line, newest first20- diff [<id>] [<id1> <id2>] [--session last|<s>] unified diff21-22-going back23- undo [n] [--session] step back n saves24- revert discard unsaved changes25- load <id> | --checkpoint restore any save26-27-sync28- remote choose S3 or a folder, once per machine29- offer send new saves to the remote30- steal [<name>] [--list] [--mine|--theirs] bring in saves from the remote31-32-occasional33- flag <id> [--reason "..."] | --clear <id> mark a save unsafe34- pluck <id> [--reverse] [--dry-run] [path...] apply one save, or its inverse35- peek <id> restore a save into a temp folder36-37-setup and care38- init create .koh here39- doctor [--backup <path>] integrity check and cleanup40- strip <path> [--save <id>] remove a path from history41-42- migrate [--lane dev|main] convert a Koh 2 repo here43- man [<command>] the manual, built in44- saves / checkpoints open the history view on that tab45- --json on any command that prints data, --yes to skip a confirm prompt'46-4747 pub fn run(argv []string) int {4848 if argv.len < 2 {49- eprintln(usage)49+ eprintln(usage_text())5050 return 25151 }5252 hand_over(argv)@@ -57,7 +57,7 @@5757 return 05858 }5959 '--help', '-h' {60- println(usage)60+ println(usage_text())6161 return 06262 }6363 'init' {tests/cli_test.v+41 −0
@@ -103,6 +103,47 @@103103 }104104 }105105 106+// The help screen is commands and plain words: every flag lives in `koh man`.107+fn test_the_help_screen_lists_commands_and_no_flags() {108+ dir := temp_repo('help')109+ defer { os.rmdir_all(dir) or {} }110+ help := run(dir, '--help')111+ assert help.code == 0112+ for name in ['save', 'checkpoint', 'status', 'log', 'diff', 'undo', 'revert', 'load', 'offer',113+ 'steal'] {114+ assert help.out.contains(' ${name} '), name115+ }116+ assert help.out.contains('koh man <command>')117+ // No flag text anywhere on the screen.118+ assert !help.out.contains('--'), help.out119+ for line in help.out.split_into_lines() {120+ assert line.runes().len <= 80, line121+ }122+ // A bare `koh` keeps its stream and exit code; `-h` shows the same screen.123+ bare := run(dir)124+ assert bare.code == 2125+ assert bare.out == ''126+ assert bare.err.contains('koh man <command>')127+ short := run(dir, '-h')128+ assert short.code == 0129+ assert short.out == help.out130+}131+132+// Colour on the screen follows NO_COLOR, as it does everywhere else.133+fn test_the_help_screen_has_no_colour_when_it_is_off() {134+ dir := temp_repo('help_plain')135+ defer { os.rmdir_all(dir) or {} }136+ home := temp_repo('help_plain_home')137+ defer { os.rmdir_all(home) or {} }138+ out_path := os.join_path(os.temp_dir(), 'koh3-help-${os.getpid()}-${time.now().unix_nano()}')139+ defer { os.rm(out_path) or {} }140+ code := os.system('cd ${q(dir)} && HOME=${q(home)} NO_COLOR=1 ${q(binary)} --help > ${q(out_path)}')141+ assert code == 0142+ text := os.read_file(out_path) or { panic(err) }143+ assert !text.contains('\x1b'), text144+ assert text.contains(' save snapshot your work')145+}146+106147 // The binary embeds VERSION while saves bump v.mod; they drifted once.107148 fn test_version_matches_the_manifest() {108149 dir := temp_repo('version')v.mod+1 −1
@@ -1,6 +1,6 @@11 Module {22 name: 'koh3'3- version: '3.0.75'3+ version: '3.0.76'44 description: 'One SQLite file per repo, one line of history.'55 license: 'MIT'66 }