//! `koh man` — the manual, built into the binary. //! //! The page lives in `docs/koh3-man.txt` and is embedded at build time, so a //! `koh` copied to another machine still carries its own documentation. With a //! command name it prints just that command's part; otherwise the whole page, //! through the pager on a terminal. module cli import os import src.fmt const manual = $embed_file('../../docs/koh3-man.txt').to_string() pub fn cmd_man(raw []string) int { args := parse('man', raw, Options{}) or { return usage_error(err.msg()) } mut text := manual if args.positional.len > 0 { name := args.positional_at(0) text = section_of(name) or { eprintln(' ${fmt.red(fmt.glyph_fail)} the manual has no "${name}" — try "koh man" for the whole page') return 2 } } page(text) return 0 } // section_of returns the part of the COMMANDS section that documents one // command: from its synopsis to the next command's. fn section_of(name string) ?string { lines := manual.split_into_lines() mut start := -1 for i, line in lines { if line.starts_with(' koh ') && line.contains(' ${name}') { start = i break } } if start < 0 { return none } mut end := lines.len for i := start + 1; i < lines.len; i++ { trimmed := lines[i].trim_space() if trimmed.starts_with('koh ') && lines[i].starts_with(' ') { end = i break } if lines[i].starts_with('OPTIONS') || lines[i].starts_with('ENVIRONMENT') { end = i break } } return lines[start..end].join('\n') } // page hands the text to the pager on a terminal, and prints it plainly when // the output is going somewhere else. The pager gets a temporary file because // that is the one interface every pager understands. fn page(text string) { pager := os.getenv('PAGER') if os.is_atty(1) != 0 && pager != '' { path := os.join_path(os.temp_dir(), 'koh-man-${os.getpid()}.txt') os.write_file(path, text) or { print(text) return } // `system`, not `execute`: the pager must write to the terminal, not // into a captured string. $PAGER itself may carry flags, so only the // path is quoted. os.system('${pager} ${os.quoted_path(path)}') os.rm(path) or {} return } print(text) if !text.ends_with('\n') { println('') } }