use crate::reply::files::{Files, Preview};
use crate::reply::governing::Governing;
use crate::reply::inbox::Row as InboxRow;
use crate::reply::rail::Rail;
use crate::reply::steps::Steps;
use super::parts::{brief, clause, line, line_over, listing, things, when};
pub(super) fn steps(steps: &Steps) -> String {
let rows = steps
.rows
.iter()
.map(|row| {
line(vec![
Some(row.seq.clone()),
Some(row.framing.clone()),
things(row.attempts, "attempt"),
Some(format!("{} tokens", row.tokens.total)),
clause("commit", row.commit.as_deref()),
clause("started", row.started_at.as_deref()),
clause("ended", row.ended_at.as_deref()),
clause("as", row.auth_row.as_deref()),
when(row.wound != "none", &row.wound),
clause("—", row.wound_reason.as_deref()),
])
})
.collect();
let head = line(vec![
Some("steps".to_owned()),
when(steps.orphan != "none", &format!("orphan: {}", steps.orphan)),
clause("—", steps.orphan_reason.as_deref()),
]);
listing(&head, rows, "this loop has taken no step")
}
pub(super) fn files(files: &Files) -> String {
let rows = files
.listing
.as_ref()
.map(|listing| {
listing
.rows
.iter()
.map(|row| {
line(vec![
Some(format!("{}{}", row.path, if row.dir { "/" } else { "" })),
when(!row.dir, &format!("{} bytes", row.size)),
])
})
.collect::<Vec<String>>()
})
.unwrap_or_default();
let head = line(vec![
Some("files".to_owned()),
clause("in", files.working_dir.as_deref()),
when(
files.listing.as_ref().is_some_and(|l| l.truncated),
"(truncated)",
),
]);
line_over(
&listing(&head, rows, "no worktree listing came back"),
files.preview.as_ref().map(|body| preview("preview", body)),
)
}
pub(super) fn preview(name: &str, preview: &Preview) -> String {
match preview {
Preview::Text(text) => line_over(name, Some(text.clone())),
Preview::Truncated { text, size } => line_over(
&format!("{name} (head of {size} bytes)"),
Some(text.clone()),
),
Preview::Binary { size } => format!("{name}: {size} bytes, binary"),
Preview::Unknown(word) => {
format!("{name}: {word} (this seat has no reading of that preview)")
}
}
}
pub(super) fn inbox(rows: &[InboxRow]) -> String {
let painted = rows
.iter()
.map(|row| {
line_over(
&line(vec![
Some(row.name.clone()),
clause("from", row.deposit.said_by().as_deref()),
clause("at", row.deposit.deposited_at.as_deref()),
clause("epitaph:", row.deposit.epitaph.as_deref()),
clause("ref", row.deposit.terminal_ref.as_deref()),
]),
Some(row.deposit.body.clone()),
)
})
.collect();
listing("inbox", painted, "no mail is waiting")
}
pub(super) fn rail(rail: &Rail) -> String {
let notches = rail
.notches
.iter()
.map(|notch| {
line(vec![
Some(notch.seq.clone()),
Some(notch.short()),
when(!notch.operable(), "(not operable)"),
Some(format!("{} tokens", notch.budget)),
clause(
"seat",
notch
.seat
.as_ref()
.map(|seat| format!("{} cut {}", seat.row, seat.cut))
.as_deref(),
),
])
})
.chain(rail.cards.iter().map(|card| {
line(vec![
Some(format!("↳ {}", card.name)),
Some(card.state.label()),
Some(format!("off {}", card.fork)),
Some(format!("notch {}", card.notch)),
Some(format!("{} tokens", card.tokens)),
clause("—", card.tail.as_deref().map(brief).as_deref()),
])
}))
.collect();
listing("spine", notches, "no operable commit yet")
}
pub(super) fn governing(governing: &Governing) -> String {
listing(
&line(vec![Some("governing".to_owned()), Some(governing.label())]),
governing.files.clone(),
"no file governs it",
)
}