use clap::{Arg, Command};
use crate::infra::driving::cli::output::OutputFormat;
use crate::infra::driving::cli::render_structured;
use crate::infra::driving::cli::theme;
pub(crate) fn subcommand(
noun: &'static str,
source_help: &'static str,
target_help: &'static str,
relationship_help: &'static str,
list_id_help: &'static str,
) -> Command {
let article = super::indefinite(noun);
Command::new("link")
.about(format!("Manage links on {article}"))
.subcommand_required(true)
.arg_required_else_help(true)
.subcommand(
Command::new("add")
.about(format!("Add a link from an existing {noun} to another"))
.arg(id_arg(source_help))
.arg(target_arg(target_help))
.arg(relationship_arg(relationship_help)),
)
.subcommand(
Command::new("remove")
.about(format!("Remove a link from an existing {noun}"))
.arg(id_arg(source_help))
.arg(target_arg(target_help))
.arg(relationship_arg(relationship_help)),
)
.subcommand(
Command::new("list")
.about(format!("List all links of {article}"))
.arg(id_arg(list_id_help)),
)
}
fn id_arg(help: &'static str) -> Arg {
Arg::new("id").required(true).value_name("ID").help(help)
}
fn target_arg(help: &'static str) -> Arg {
Arg::new("target")
.required(true)
.value_name("TARGET_ID")
.help(help)
}
fn relationship_arg(help: &'static str) -> Arg {
Arg::new("relationship")
.long("relationship")
.required(true)
.value_name("TYPE")
.help(help)
}
pub(crate) enum View {
Linked,
Unlinked,
}
pub(crate) fn render(
view: View,
source_display_id: &str,
source_canonical_id: &str,
target_id: &str,
relationship: &str,
output_fmt: OutputFormat,
) {
if output_fmt.is_structured() {
#[derive(serde::Serialize)]
struct LinkResult<'a> {
id: &'a str,
target: &'a str,
relationship: &'a str,
outcome: &'a str,
}
let r = match &view {
View::Linked => LinkResult {
id: source_canonical_id,
target: target_id,
relationship,
outcome: "linked",
},
View::Unlinked => LinkResult {
id: source_canonical_id,
target: target_id,
relationship,
outcome: "unlinked",
},
};
render_structured(&r, output_fmt);
} else {
match view {
View::Linked => println!(
"{}",
theme::success(&format!("Linked {source_display_id} → {target_id}"))
),
View::Unlinked => println!(
"{}",
theme::success(&format!("Unlinked {source_display_id} ↛ {target_id}"))
),
}
}
}