adenosine_cli/
pretty.rs

1use adenosine::app_bsky::{FeedViewPost, PostView, ThreadViewPost};
2use anyhow::Result;
3use std::io::Write;
4use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
5
6pub fn pp_thread_post_view(tpv: &ThreadViewPost) -> Result<()> {
7    // TODO: this could do better
8    if let Some(parent) = &tpv.parent {
9        pp_thread_post_view(parent)?;
10    };
11    if let Some(not_found) = &tpv.notFound {
12        if *not_found {
13            let mut stdout = StandardStream::stdout(ColorChoice::Always);
14            stdout.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?;
15            writeln!(
16                &mut stdout,
17                "thread post not found: {}\n",
18                tpv.uri.as_ref().expect("URI for post-not-found")
19            )?;
20            stdout.reset()?;
21        }
22    }
23    if let Some(post) = &tpv.post {
24        pp_post_view(post)?;
25    }
26    if let Some(replies) = &tpv.replies {
27        for child in replies {
28            pp_thread_post_view(child)?;
29        }
30    };
31    Ok(())
32}
33
34pub fn pp_feed_post_view(fpv: &FeedViewPost) -> Result<()> {
35    let mut stdout = StandardStream::stdout(ColorChoice::Always);
36
37    if let Some(repost) = &fpv.reason {
38        stdout.set_color(ColorSpec::new().set_dimmed(true).set_italic(true))?;
39        write!(&mut stdout, "re-posted by ")?;
40        stdout.set_color(
41            ColorSpec::new()
42                .set_fg(Some(Color::Yellow))
43                .set_dimmed(true)
44                .set_italic(true),
45        )?;
46        writeln!(&mut stdout, "@{}", repost.by.handle)?;
47        stdout.reset()?;
48    }
49
50    pp_post_view(&fpv.post)
51}
52
53pub fn pp_post_view(pv: &PostView) -> Result<()> {
54    let mut stdout = StandardStream::stdout(ColorChoice::Always);
55
56    if let Some(reply_to) = &pv.record.reply {
57        stdout.set_color(ColorSpec::new().set_dimmed(true).set_italic(true))?;
58        writeln!(&mut stdout, "reply to {}", reply_to.parent.uri)?;
59        stdout.reset()?;
60    }
61
62    stdout.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true))?;
63    write!(&mut stdout, "@{:<54.54}", pv.author.handle)?;
64    stdout.reset()?;
65    stdout.set_color(ColorSpec::new().set_dimmed(true))?;
66    writeln!(&mut stdout, "{}", pv.indexedAt)?;
67    stdout.reset()?;
68
69    if let Some(entities) = &pv.record.entities {
70        let mut cur: usize = 0;
71        for ent in entities {
72            write!(
73                &mut stdout,
74                "{}",
75                &pv.record.text[cur..ent.index.start as usize]
76            )?;
77            match ent.r#type.as_str() {
78                "mention" => stdout
79                    .set_color(ColorSpec::new().set_fg(Some(Color::Magenta)).set_bold(true))?,
80                "hashtag" => {
81                    stdout.set_color(ColorSpec::new().set_fg(Some(Color::Cyan)).set_bold(true))?
82                }
83                "link" => stdout.set_color(
84                    ColorSpec::new()
85                        .set_fg(Some(Color::Blue))
86                        .set_underline(true),
87                )?,
88                _ => {}
89            }
90            write!(
91                &mut stdout,
92                "{}",
93                &pv.record.text[ent.index.start as usize..ent.index.end as usize]
94            )?;
95            stdout.reset()?;
96            cur = ent.index.end as usize;
97        }
98        writeln!(&mut stdout, "{}", &pv.record.text[cur..])?;
99    } else if !pv.record.text.is_empty() {
100        writeln!(&mut stdout, "{}", &pv.record.text)?;
101    }
102
103    if let Some(embed) = &pv.embed {
104        if let Some(ext) = &embed.external {
105            let desc = format!("{}: {}", ext.title, ext.description);
106            stdout.set_color(
107                ColorSpec::new()
108                    .set_fg(Some(Color::Green))
109                    .set_dimmed(true)
110                    .set_underline(false),
111            )?;
112            writeln!(&mut stdout, " {:<70.70}", desc)?;
113            write!(&mut stdout, " ")?;
114            stdout.set_color(
115                ColorSpec::new()
116                    .set_fg(Some(Color::Green))
117                    .set_dimmed(true)
118                    .set_underline(true),
119            )?;
120            writeln!(&mut stdout, "{}", &ext.uri)?;
121            stdout.reset()?;
122        }
123        if let Some(images) = &embed.images {
124            for img in images.iter() {
125                if !img.alt.is_empty() {
126                    stdout.set_color(
127                        ColorSpec::new()
128                            .set_fg(Some(Color::Green))
129                            .set_dimmed(true)
130                            .set_underline(false),
131                    )?;
132                    writeln!(&mut stdout, " {:<70.70}", img.alt)?;
133                }
134                write!(&mut stdout, " ")?;
135                stdout.set_color(
136                    ColorSpec::new()
137                        .set_fg(Some(Color::Green))
138                        .set_dimmed(true)
139                        .set_underline(true),
140                )?;
141                writeln!(&mut stdout, "{}", &img.fullsize)?;
142                stdout.reset()?;
143            }
144        }
145    }
146
147    stdout.set_color(ColorSpec::new().set_dimmed(true))?;
148    writeln!(&mut stdout, "{}\n", pv.uri)?;
149
150    stdout.reset()?;
151    Ok(())
152}