use crate::cli::ListArgs; use crate::error::Result; use crate::{instance, profile, timefmt, ui}; use serde::Serialize; struct Row { name: String, kind: String, mapping: String, via: String, state: String, uptime: String, } pub fn run(args: ListArgs) -> Result<()> { let profiles = profile::list_all()?; if profiles.is_empty() { ui::info("No profiles saved."); return Ok(()); } let mut rows = Vec::new(); for p in &profiles { let inst = instance::load(&p.name)?; let live = inst.as_ref().is_some_and(|i| instance::supervisor_alive(i.pid, &p.name)); let (state, uptime) = match &inst { None => ("closed".to_string(), String::new()), Some(_) if !live => ("error".to_string(), String::new()), Some(i) => ( i.state.label().to_string(), i.connected_at.map(|c| timefmt::fmt_duration(timefmt::now() - c)).unwrap_or_default(), ), }; if args.running && !matches!(state.as_str(), "up" | "reconnecting") { continue; } rows.push(Row { name: p.name.clone(), kind: p.kind.label().to_string(), mapping: p.mapping.clone(), via: p.via.join(","), state, uptime, }); } if args.json { print_json(&rows); return Ok(()); } if rows.is_empty() { ui::info("No matching profiles."); return Ok(()); } print_table(&rows); Ok(()) } fn col(i: usize, r: &Row) -> &str { match i { 0 => &r.name, 1 => &r.kind, 2 => &r.mapping, 3 => &r.via, 4 => &r.state, _ => &r.uptime, } } fn print_table(rows: &[Row]) { let headers = ["NAME", "KIND", "MAPPING", "VIA", "STATE", "UPTIME"]; let widths: Vec = (0..6).map(|i| rows.iter().map(|r| col(i, r).len()).max().unwrap_or(0).max(headers[i].len())).collect(); let header_line: Vec = headers.iter().enumerate().map(|(i, h)| format!("{h: ui::green(&r.state), "reconnecting" => ui::yellow(&r.state), "error" => ui::red(&r.state), _ => r.state.clone(), }; let cells = [ format!("{: { name: &'a str, kind: &'a str, mapping: &'a str, via: &'a str, state: &'a str, uptime: &'a str, } fn print_json(rows: &[Row]) { let out: Vec = rows .iter() .map(|r| RowJson { name: &r.name, kind: &r.kind, mapping: &r.mapping, via: &r.via, state: &r.state, uptime: &r.uptime }) .collect(); if let Ok(text) = serde_json::to_string_pretty(&out) { println!("{text}"); } }