htoprs 0.3.0

A faithful Rust port of htop — the interactive process viewer
//! Styled `-h` / `--help` screen — an htoprs-original presentation of the
//! command-line options in the MenkeTechnologies `tp -h` house style
//! (figlet banner, status box, `── SECTION ──` dividers, `//` comments).
//!
//! The flag names and their descriptions are htop's, verbatim from
//! `CommandLine.c`'s `printHelpFlag` (kept faithful in
//! [`crate::ported::commandline::printHelpFlag`]); only the layout differs.
//! This lives under [`crate::extensions`] because it is original chrome, not
//! a 1:1 port, so it is exempt from the `build.rs` port-purity gate.

/// htop's `VERSION` — the crate version, matching the ported flag printers.
const VERSION: &str = env!("CARGO_PKG_VERSION");

/// htop's `COPYRIGHT` macro (`configure.ac:1833`).
const COPYRIGHT: &str = "(C) 2004-2019 Hisham Muhammad. (C) 2020-2026 htop dev team.";

/// The `HTOPRS` wordmark in figlet's "ANSI Shadow" font.
const BANNER: &str = "\
 ██╗  ██╗████████╗ ██████╗ ██████╗ ██████╗ ███████╗\n\
 ██║  ██║╚══██╔══╝██╔═══██╗██╔══██╗██╔══██╗██╔════╝\n\
 ███████║   ██║   ██║   ██║██████╔╝██████╔╝███████╗\n\
 ██╔══██║   ██║   ██║   ██║██╔═══╝ ██╔══██╗╚════██║\n\
 ██║  ██║   ██║   ╚██████╔╝██║     ██║  ██║███████║\n\
 ╚═╝  ╚═╝   ╚═╝    ╚═════╝ ╚═╝     ╚═╝  ╚═╝╚══════╝";

/// Visible width of the status box interior, in terminal cells.
const BOX_INNER: usize = 54;
/// Visible width of a `── SECTION ──` divider / the bottom rule.
const RULE_WIDTH: usize = 57;

/// `  ── LABEL ───────…` padded to [`RULE_WIDTH`] cells.
fn section(label: &str) -> String {
    // "  ── " (5) + label + " " (1), then fill with `─` to RULE_WIDTH.
    let used = 5 + label.chars().count() + 1;
    format!("  ── {label} {}", "".repeat(RULE_WIDTH.saturating_sub(used)))
}

/// One option row: `  -x, --long=ARG                 // description`,
/// with the `//` comment aligned to a fixed column.
fn opt(spec: &str, desc: &str) -> String {
    format!("  {spec:<48}// {desc}")
}

/// Render the styled help screen for `htoprs -h` / `--help`.
pub fn print_help(name: &str) {
    let status = format!(" STATUS: ONLINE  // SIGNAL: ████████░░ // v{VERSION}");

    println!("{BANNER}");
    println!("{}", "".repeat(BOX_INNER));
    println!(" │{status:<BOX_INNER$}│");
    println!("{}", "".repeat(BOX_INNER));
    println!("  >> INTERACTIVE PROCESS VIEWER // FULL SPECTRUM <<");
    println!();
    println!("An interactive process viewer\n");
    println!("  USAGE: {name} [OPTIONS]\n");

    println!("{}", section("DISPLAY"));
    println!("{}", opt("-t, --tree", "Show the tree view (can be combined with -s)"));
    println!("{}", opt("-s, --sort-key=COLUMN", "Sort by COLUMN in list view (try --sort-key=help for a list)"));
    println!("{}", opt("-H, --highlight-changes[=DELAY]", "Highlight new and old processes"));
    println!("{}", opt("-C, --no-color", "Use a monochrome color scheme"));
    println!("{}", opt("-U, --no-unicode", "Do not use unicode but plain ASCII"));
    println!("{}", opt("    --no-function-bar", "Hide the function bar"));
    println!("{}", opt("    --no-meters", "Hide meters"));
    println!();

    println!("{}", section("FILTERING"));
    println!("{}", opt("-F, --filter=FILTER", "Show only the commands matching the given filter"));
    println!("{}", opt("-p, --pid=PID[,PID,PID...]", "Show only the given PIDs"));
    println!("{}", opt("-u, --user[=USERNAME]", "Show only processes for a given user (or $USER)"));
    println!();

    println!("{}", section("BEHAVIOR"));
    println!("{}", opt("-d, --delay=DELAY", "Set the delay between updates, in tenths of seconds"));
    println!("{}", opt("-n, --max-iterations=NUMBER", "Exit htoprs after NUMBER iterations/frame updates"));
    println!("{}", opt("-M, --no-mouse", "Disable the mouse"));
    println!("{}", opt("    --readonly", "Disable all system and process changing features"));
    println!();

    println!("{}", section("INFO"));
    println!("{}", opt("-h, --help", "Print this help screen"));
    println!("{}", opt("-V, --version", "Print version info"));
    println!();

    println!("{}", section("SYSTEM"));
    println!("  v{VERSION} // {COPYRIGHT}");
    println!("  Released under the GNU GPLv2+.");
    println!("  Press F1 inside {name} for online help. See 'man {name}' for more.");
    println!(" {}", "".repeat(RULE_WIDTH - 1));
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn section_reaches_rule_width() {
        // `─` is one cell; count chars, not bytes.
        assert_eq!(section("DISPLAY").chars().count(), RULE_WIDTH);
        assert_eq!(section("FILTERING").chars().count(), RULE_WIDTH);
    }

    #[test]
    fn opt_aligns_comment_column() {
        // "  " + 48-wide spec + "// ..." → `//` starts at column 51 (0-based 50).
        let row = opt("-t, --tree", "x");
        assert_eq!(row.find("//"), Some(50));
    }

    #[test]
    fn opt_never_swallows_long_spec() {
        // The widest real spec must still leave a space before `//`.
        let row = opt("-H, --highlight-changes[=DELAY]", "y");
        assert!(row.contains("] //"));
    }
}