use clap::Subcommand;
use serde::Serialize;
use std::path::PathBuf;
use crate::output::{self, TextFormat};
use altium_format::ops::intlib;
#[derive(Subcommand)]
pub enum IntLibCommands {
Overview {
path: PathBuf,
#[arg(long)]
full: bool,
},
List {
path: PathBuf,
},
Search {
path: PathBuf,
query: String,
#[arg(short, long)]
limit: Option<usize>,
},
Info {
path: PathBuf,
},
Component {
path: PathBuf,
name: String,
#[arg(long)]
params: bool,
},
Crossrefs {
path: PathBuf,
#[arg(short, long)]
footprint: Option<String>,
},
Symbols {
path: PathBuf,
},
Footprints {
path: PathBuf,
},
Parameters {
path: PathBuf,
#[arg(short, long)]
component: Option<String>,
#[arg(short, long)]
keys: Option<String>,
},
ExtractSchlib {
path: PathBuf,
#[arg(short, long)]
output: PathBuf,
},
ExtractPcblib {
path: PathBuf,
#[arg(short, long)]
output: PathBuf,
},
Json {
path: PathBuf,
},
}
pub fn run(cmd: &IntLibCommands, format: &str) -> Result<(), Box<dyn std::error::Error>> {
match cmd {
IntLibCommands::Overview { path, full } => {
let result = intlib::cmd_overview(path, *full)?;
output::print(&TextWrapper(result), format)?;
}
IntLibCommands::List { path } => {
let result = intlib::cmd_list(path)?;
output::print(&TextWrapper(result), format)?;
}
IntLibCommands::Search {
path,
query,
limit,
} => {
let result = intlib::cmd_search(path, query, *limit)?;
output::print(&TextWrapper(result), format)?;
}
IntLibCommands::Info { path } => {
let result = intlib::cmd_info(path)?;
output::print(&TextWrapper(result), format)?;
}
IntLibCommands::Component {
path,
name,
params,
} => {
let result = intlib::cmd_component(path, name, *params)?;
output::print(&TextWrapper(result), format)?;
}
IntLibCommands::Crossrefs { path, footprint } => {
let result = intlib::cmd_crossrefs(path, footprint.as_deref())?;
output::print(&TextWrapper(result), format)?;
}
IntLibCommands::Symbols { path } => {
let result = intlib::cmd_symbols(path)?;
output::print(&TextWrapper(result), format)?;
}
IntLibCommands::Footprints { path } => {
let result = intlib::cmd_footprints(path)?;
output::print(&TextWrapper(result), format)?;
}
IntLibCommands::Parameters { path, component, keys } => {
let result = intlib::cmd_parameters(path, component.as_deref(), keys.as_deref())?;
output::print(&TextWrapper(result), format)?;
}
IntLibCommands::ExtractSchlib { path, output } => {
let result = intlib::cmd_extract_schlib(path, output)?;
println!("{}", result);
}
IntLibCommands::ExtractPcblib { path, output } => {
let result = intlib::cmd_extract_pcblib(path, output)?;
println!("{}", result);
}
IntLibCommands::Json { path } => {
let result = intlib::cmd_overview(path, true)?;
let json_str = serde_json::to_string_pretty(&result)?;
println!("{}", json_str);
}
}
Ok(())
}
#[derive(Serialize)]
#[serde(transparent)]
struct TextWrapper<T>(T);
impl<T: Serialize> TextFormat for TextWrapper<T> {
fn format_text(&self) -> String {
if let Ok(value) = serde_json::to_value(&self.0) {
format_value(&value, 0)
} else {
"Error formatting output".to_string()
}
}
}
fn format_value(value: &serde_json::Value, indent: usize) -> String {
let prefix = " ".repeat(indent);
match value {
serde_json::Value::Object(map) => {
let mut out = String::new();
for (key, val) in map {
match val {
serde_json::Value::String(s) => {
out.push_str(&format!("{}{}: {}\n", prefix, key, s));
}
serde_json::Value::Number(n) => {
out.push_str(&format!("{}{}: {}\n", prefix, key, n));
}
serde_json::Value::Bool(b) => {
out.push_str(&format!("{}{}: {}\n", prefix, key, b));
}
serde_json::Value::Null => {
out.push_str(&format!("{}{}: null\n", prefix, key));
}
serde_json::Value::Array(arr) => {
if arr.is_empty() {
out.push_str(&format!("{}{}: []\n", prefix, key));
} else {
out.push_str(&format!("{}{}:\n", prefix, key));
for item in arr {
out.push_str(&format_value(item, indent + 1));
out.push('\n');
}
}
}
serde_json::Value::Object(_) => {
out.push_str(&format!("{}{}:\n", prefix, key));
out.push_str(&format_value(val, indent + 1));
}
}
}
out
}
serde_json::Value::Array(arr) => {
let mut out = String::new();
for (i, item) in arr.iter().enumerate() {
out.push_str(&format!("{}[{}]\n", prefix, i));
out.push_str(&format_value(item, indent + 1));
}
out
}
serde_json::Value::String(s) => format!("{}{}\n", prefix, s),
serde_json::Value::Number(n) => format!("{}{}\n", prefix, n),
serde_json::Value::Bool(b) => format!("{}{}\n", prefix, b),
serde_json::Value::Null => format!("{}null\n", prefix),
}
}