cyb/prysm/cli/src/main.rs

// ---
// tags: prysm, rust, cli
// crystal-type: source
// crystal-domain: comp
// ---
//! prysm โ€” read a tape stream as prysm reads it: what each frame *becomes*.
//!
//!   prysm render [file]    decode a stream โ†’ the molecule each frame renders as
//!   prysm molecules        the routing table: (sigil, render) โ†’ molecule
//!
//! prysm proper renders meaning to a GPU surface (Bevy). This CLI is its terminal
//! shadow: it applies the same `(sigil, render) โ†’ molecule` routing and shows the
//! content as text โ€” text as text, a log as a log line, a table as a note โ€” so
//! you can read a stream's *meaning* where `tape inspect` shows its envelope.
//!
//! SYNC: the routing table below mirrors `prysm/system/rs/scrollback.rs` โ€” keep
//! them in step.

use std::io::{self, IsTerminal, Read};

use tape::{render, sigil, Chunk, ReadResult, Reader};

fn tty() -> bool {
    io::stdout().is_terminal()
}
fn paint(code: &str, s: &str) -> String {
    if tty() { format!("\x1b[{code}m{s}\x1b[0m") } else { s.to_string() }
}
fn dim(s: &str) -> String {
    paint("90", s)
}
fn cyan(s: &str) -> String {
    paint("36", s)
}
fn green(s: &str) -> String {
    paint("32", s)
}
fn yellow(s: &str) -> String {
    paint("33", s)
}
fn bold(s: &str) -> String {
    paint("1", s)
}
fn red(s: &str) -> String {
    paint("31", s)
}

const LOGO: &str = "\
\x1b[31mโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—   โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•—   โ–ˆโ–ˆโ–ˆโ•—\x1b[0m
\x1b[33mโ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ•‘\x1b[0m
\x1b[32mโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•‘\x1b[0m
\x1b[36mโ–ˆโ–ˆโ•”โ•โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—  โ•šโ–ˆโ–ˆโ•”โ•  โ•šโ•โ•โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘\x1b[0m
\x1b[34mโ–ˆโ–ˆโ•‘     โ–ˆโ–ˆโ•‘  โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ•šโ•โ• โ–ˆโ–ˆโ•‘\x1b[0m
\x1b[35mโ•šโ•โ•     โ•šโ•โ•  โ•šโ•โ•   โ•šโ•โ•   โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•     โ•šโ•โ•\x1b[0m";

/// The `(sigil, render) โ†’ molecule` routing โ€” mirrors prysm's scrollback dispatch.
fn molecule(sig: u8, ren: u8) -> &'static str {
    match (sig, ren) {
        (sigil::HAX, render::TEXT) => "text",
        (sigil::SIG, render::TEXT) => "annotation",
        (sigil::PAT, render::TEXT) => "neuron",
        (sigil::DOT, render::LOG) => "log",
        (sigil::ZAP, render::ERROR) => "error",
        (sigil::DOT, render::STATUS) => "status",
        (sigil::DOT, render::PROGRESS) => "progress",
        (sigil::ZAP, render::COMPONENT) => "action",
        (sigil::BAR, render::COMPONENT) => "component",
        (sigil::FAS, render::COMPONENT) => "scope",
        (sigil::HAX, render::TABLE) => "table",
        _ => "raw",
    }
}

const ROUTES: &[(&str, &str, &str)] = &[
    ("# hax", "t text", "text"),
    ("~ sig", "t text", "annotation"),
    ("@ pat", "t text", "neuron"),
    (". dot", "l log", "log"),
    ("! zap", "e error", "error"),
    (". dot", "x status", "status"),
    (". dot", "p progress", "progress"),
    ("! zap", "c component", "action"),
    ("| bar", "c component", "component"),
    ("/ fas", "c component", "scope"),
    ("# hax", "T table", "table"),
];

fn banner() {
    if !tty() {
        return;
    }
    println!("{LOGO}");
    println!("{}", paint("37", "    the visual protocol"));
    println!("{}", dim("\n    meaning, not pixels ยท molecules decoded from tape\n"));
}

fn help() {
    banner();
    println!("{}", dim("commands"));
    println!("  {}   {}", bold("render [file]"), dim("decode a stream โ†’ the molecule each frame becomes (stdin if no file)"));
    println!("  {}       {}", bold("molecules"), dim("the routing table: (sigil, render) โ†’ molecule"));
}

/// A payload preview: text-bearing renders decode to a string, the rest to hex.
fn content(c: &Chunk) -> String {
    let textual = matches!(
        c.render,
        render::TEXT | render::LOG | render::ERROR | render::STATUS | render::INPUT | render::TOKEN
    );
    if textual {
        String::from_utf8_lossy(&c.payload).chars().take(60).collect::<String>().replace('\n', "โŽ")
    } else if c.payload.is_empty() {
        "ยท".into()
    } else {
        let hex: String = c.payload.iter().take(10).map(|b| format!("{b:02x}")).collect();
        format!("{hex}{}", if c.payload.len() > 10 { "โ€ฆ" } else { "" })
    }
}

fn cmd_render(path: Option<&str>) {
    let mut bytes = Vec::new();
    let read = match path {
        Some(p) => std::fs::File::open(p).and_then(|mut f| f.read_to_end(&mut bytes)),
        None => io::stdin().read_to_end(&mut bytes),
    };
    if let Err(e) = read {
        eprintln!("  {}: {e}", red("error"));
        std::process::exit(1);
    }

    let mut reader = Reader::new();
    reader.feed(&bytes);
    println!("  {}   {}  {}", dim("#"), dim(&format!("{:<11}", "molecule")), dim("content"));
    let mut n = 0u64;
    loop {
        match reader.next_chunk() {
            ReadResult::Chunk(c) => {
                let mol = molecule(c.sigil, c.render);
                let name = if mol == "raw" { dim(&format!("{mol:<11}")) } else { cyan(&format!("{mol:<11}")) };
                println!("  {:>2}   {}  {}", yellow(&n.to_string()), name, content(&c));
                n += 1;
            }
            ReadResult::Pending | ReadResult::Eof => break,
        }
    }
    if n == 0 {
        println!("  {}", dim("(no frames)"));
    } else {
        println!("  {}", dim(&format!("{n} frame(s)")));
    }
}

fn cmd_molecules() {
    println!("{}", dim("(sigil, render) โ†’ molecule"));
    println!("  {}  {}  {}", dim(&format!("{:<8}", "sigil")), dim(&format!("{:<14}", "render")), dim("molecule"));
    for (sig, ren, mol) in ROUTES {
        println!("  {}  {}  {}", cyan(&format!("{sig:<8}")), green(&format!("{ren:<14}")), bold(mol));
    }
}

fn main() {
    let args: Vec<String> = std::env::args().skip(1).collect();
    match args.first().map(String::as_str) {
        Some("render" | "read" | "cat") => cmd_render(args.get(1).map(String::as_str)),
        Some("molecules" | "routes") => cmd_molecules(),
        Some("help" | "--help" | "-h") | None => help(),
        Some(other) => {
            eprintln!("  {}: {other}  (try: prysm help)", dim("unknown"));
            std::process::exit(2);
        }
    }
}

Homonyms

neural/rune/cli/main.rs
cyb/optica/src/main.rs
soft3/nox/cli/main.rs
warriors/trisha/cli/main.rs
soft3/glia/import/main.rs
cyb/shell/src/main.rs
cyb/cli/src/main.rs
neural/trident/src/main.rs
soft3/tru/cli/main.rs
cyb/apps/src/main.rs
cyberia/cyberia-my/src/main.rs
soft3/lens/cli/src/main.rs
soft3/glia/run/cli/main.rs
warriors/erga/cli/src/main.rs
cyberia/research/cyberia-my/src/main.rs
soft3/glia/cli/src/main.rs
soft3/radio/iroh-relay/src/main.rs
soft3/strata/cli/src/main.rs
neural/rs/cli/src/main.rs
neural/rs/macho-linker/src/main.rs
soft3/radio/iroh-dns-server/src/main.rs
soft3/cybergraph/cli/src/main.rs
soft3/hemera/cli/src/main.rs
soft3/radio/particle/src/main.rs
soft3/radio/radio-cli/src/main.rs
neural/rs/link/src/main.rs
soft3/bbg/cli/src/main.rs
neural/eidos/cli/src/main.rs
neural/rs/pure-rust-check/src/main.rs
neural/rs/rsc/src/main.rs
soft3/zheng/cli/src/main.rs
soft3/foculus/src/bin/main.rs
warriors/erga/rs/blake-bench/src/main.rs
soft3/lytics/rs/agent/src/main.rs
warriors/erga/rs/mine-bench/src/main.rs
soft3/strata/trop/cli/src/main.rs
soft3/strata/genies/cli/src/main.rs
soft3/strata/kuro/cli/src/main.rs
soft3/strata/jali/cli/src/main.rs
cyb/wysm/crates/cli/src/main.rs
warriors/erga/rs/rtable-bench/src/main.rs
soft3/lytics/rs/ingest/src/main.rs
cyb/honeycrisp/acpu/src/probe/main.rs
neural/inf/rs/cli/src/main.rs
soft3/strata/nebu/cli/src/main.rs
cyb/honeycrisp/rane/src/probe/main.rs
neural/inf/rs/cozo/cozo-bin/src/main.rs
cyb/honeycrisp/unimem/experiments/hyp_probe/src/main.rs
cyb/honeycrisp/unimem/experiments/iosurface_probe/src/main.rs
cyb/honeycrisp/unimem/experiments/dext_contiguous_alloc/client/src/main.rs
cyb/honeycrisp/unimem/experiments/dext_iosurface_pa/client/src/main.rs
cyb/honeycrisp/.claude/worktrees/agent-ad6c77c38e86bc291/rane/src/probe/main.rs
cyb/honeycrisp/.claude/worktrees/agent-ad6c77c38e86bc291/acpu/src/probe/main.rs
cyb/honeycrisp/.claude/worktrees/agent-aa1259cb10112b22a/acpu/src/probe/main.rs
cyb/honeycrisp/.claude/worktrees/agent-aa1259cb10112b22a/rane/src/probe/main.rs
cyb/honeycrisp/.claude/worktrees/agent-ad6c77c38e86bc291/unimem/experiments/iosurface_probe/src/main.rs
cyb/honeycrisp/.claude/worktrees/agent-aa1259cb10112b22a/unimem/experiments/iosurface_probe/src/main.rs
cyb/honeycrisp/.claude/worktrees/agent-ad6c77c38e86bc291/unimem/experiments/hyp_probe/src/main.rs
cyb/honeycrisp/.claude/worktrees/agent-aa1259cb10112b22a/unimem/experiments/hyp_probe/src/main.rs
cyb/honeycrisp/.claude/worktrees/agent-ad6c77c38e86bc291/unimem/experiments/dext_contiguous_alloc/client/src/main.rs
cyb/honeycrisp/.claude/worktrees/agent-aa1259cb10112b22a/unimem/experiments/dext_contiguous_alloc/client/src/main.rs
cyb/honeycrisp/.claude/worktrees/agent-ad6c77c38e86bc291/unimem/experiments/dext_iosurface_pa/client/src/main.rs
cyb/honeycrisp/.claude/worktrees/agent-aa1259cb10112b22a/unimem/experiments/dext_iosurface_pa/client/src/main.rs

Graph