//! `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 } // The path is one we built from the temp dir and our own pid, so it // carries nothing the shell could interpret. os.execute('${pager} ${path}') os.rm(path) or {} return } print(text) if !text.ends_with('\n') { println('') } }