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
4 files VERSION+1 −1src/cli/cli.v+37 −37tests/cli_test.v+41 −0v.mod+1 −1
VERSION+1 −1
@@ -1 +1 @@1-3.0.751+3.0.76

view file

src/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' {

view file

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

view file

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 }

view file