mod cargo_config;
mod elf;
pub(crate) mod list;
mod probe;
mod read;
pub mod reset;
use crate::theme::theme;
use anstream::{eprintln, println};
use clap::{Args, CommandFactory, FromArgMatches, Parser, Subcommand};
use cnt_core::Counters;
use probe::ProbeOptions;
use std::path::{Path, PathBuf};
#[derive(Parser)]
#[command(version)]
#[command(propagate_version = true)]
#[command(color = clap::ColorChoice::Auto)]
#[command(
about = "Command line interface for the embedded counters crate. https://crates.io/crates/cnt"
)]
pub struct Cli {
#[command(subcommand)]
pub command: Command,
}
impl Cli {
pub fn parse_styled() -> Self {
let matches = Self::command().styles(theme().clap.clone()).get_matches();
match Self::from_arg_matches(&matches) {
Ok(cli) => cli,
Err(err) => err.exit(),
}
}
}
#[derive(Args)]
pub(crate) struct Elf {
elf_path: Option<PathBuf>,
}
impl Elf {
pub fn resolve(&self) -> anyhow::Result<PathBuf> {
match &self.elf_path {
Some(path) => Ok(path.clone()),
None => {
let path = elf::find_elf()?;
let (hint, style) = (theme().hint, theme().path);
eprintln!("{hint}Using ELF{hint:#} {style}{}{style:#}", path.display());
Ok(path)
}
}
}
}
#[derive(Subcommand)]
pub(crate) enum Command {
List(Elf),
Read {
#[command(flatten)]
elf: Elf,
#[command(flatten)]
probe: ProbeOptions,
},
Reset {
#[clap(default_value = "false", long)]
bkp: bool,
#[command(flatten)]
elf: Elf,
#[command(flatten)]
probe: ProbeOptions,
},
Tui {
#[command(flatten)]
elf: Elf,
#[command(flatten)]
probe: ProbeOptions,
},
}
impl Command {
pub fn elf(&self) -> &Elf {
match self {
Command::List(elf)
| Command::Read { elf, .. }
| Command::Tui { elf, .. }
| Command::Reset { elf, .. } => elf,
}
}
}
pub fn process_cmd(cmd: Command, mut counters: Counters, elf_path: &Path) -> anyhow::Result<()> {
match cmd {
Command::List(_) => {
list::list(&counters);
}
Command::Read { probe, .. } => {
let mut session = probe.attach(elf_path)?;
let core = session.core(0)?;
read::read(&mut counters, core)?;
}
Command::Reset { bkp, probe, .. } => {
let mut session = probe.attach(elf_path)?;
let mut core = session.core(0)?;
let hint = theme().hint;
if let Some(block) = counters.ram_counters() {
println!("{hint}Resetting RAM counters{hint:#}");
reset::reset(block, &mut core)?;
}
if bkp && let Some(block) = counters.bkp_counters() {
println!("{hint}Resetting BKP counters{hint:#}");
reset::reset(block, &mut core)?;
}
}
Command::Tui { probe, .. } => {
let mut session = probe.attach(elf_path)?;
let mut core = session.core(0)?;
crate::tui::tui(&mut counters, &mut core)?;
}
}
Ok(())
}