spotify_cli/output/
pin.rs

1//! Pin output formatting.
2use serde::Serialize;
3
4use crate::domain::pin::PinnedPlaylist;
5use crate::error::Result;
6use crate::output::human::truncate_cell;
7use crate::output::{DEFAULT_MAX_WIDTH, TableConfig};
8
9pub fn pin_list_human(pins: Vec<PinnedPlaylist>, table: TableConfig) -> Result<()> {
10    if pins.is_empty() {
11        return Ok(());
12    }
13
14    let max_width = table.max_width.unwrap_or(DEFAULT_MAX_WIDTH);
15    let mut names: Vec<String> = pins
16        .iter()
17        .map(|pin| {
18            if table.truncate {
19                truncate_cell(&pin.name, max_width)
20            } else {
21                pin.name.clone()
22            }
23        })
24        .collect();
25    let mut urls: Vec<String> = pins
26        .iter()
27        .map(|pin| {
28            if table.truncate {
29                truncate_cell(&pin.url, max_width)
30            } else {
31                pin.url.clone()
32            }
33        })
34        .collect();
35
36    let name_width = names
37        .iter()
38        .map(|name| name.len())
39        .max()
40        .unwrap_or(0)
41        .max("NAME".len());
42
43    println!("{:<width$}  {}", "NAME", "URL", width = name_width);
44
45    for (name, url) in names.drain(..).zip(urls.drain(..)) {
46        println!("{:<width$}  {}", name, url, width = name_width);
47    }
48    Ok(())
49}
50
51#[derive(Serialize)]
52struct PinPayload {
53    name: String,
54    url: String,
55}
56
57pub fn pin_list_json(pins: Vec<PinnedPlaylist>) -> Result<()> {
58    let payload = pin_list_payload(pins);
59    println!("{}", serde_json::to_string(&payload)?);
60    Ok(())
61}
62
63fn pin_list_payload(pins: Vec<PinnedPlaylist>) -> Vec<PinPayload> {
64    pins.into_iter()
65        .map(|pin| PinPayload {
66            name: pin.name,
67            url: pin.url,
68        })
69        .collect()
70}
71
72#[cfg(test)]
73mod tests {
74    use super::pin_list_payload;
75    use crate::domain::pin::PinnedPlaylist;
76
77    #[test]
78    fn pin_list_payload_shape() {
79        let payload = pin_list_payload(vec![PinnedPlaylist {
80            name: "Release Radar".to_string(),
81            url: "url".to_string(),
82        }]);
83        assert_eq!(payload.len(), 1);
84        assert_eq!(payload[0].name, "Release Radar");
85    }
86}