soroban_cli/
print.rs

1use std::{env, fmt::Display};
2
3use crate::xdr::{Error as XdrError, Transaction};
4
5use crate::{
6    config::network::Network, utils::explorer_url_for_transaction, utils::transaction_hash,
7};
8
9const TERMS: &[&str] = &["Apple_Terminal", "vscode"];
10
11#[derive(Clone)]
12pub struct Print {
13    pub quiet: bool,
14}
15
16impl Print {
17    pub fn new(quiet: bool) -> Print {
18        Print { quiet }
19    }
20
21    pub fn print<T: Display + Sized>(&self, message: T) {
22        if !self.quiet {
23            eprint!("{message}");
24        }
25    }
26
27    pub fn println<T: Display + Sized>(&self, message: T) {
28        if !self.quiet {
29            eprintln!("{message}");
30        }
31    }
32
33    pub fn clear_line(&self) {
34        if cfg!(windows) {
35            eprint!("\r");
36        } else {
37            eprint!("\r\x1b[2K");
38        }
39    }
40
41    // Some terminals like vscode's and macOS' default terminal will not render
42    // the subsequent space if the emoji codepoints size is 2; in this case,
43    // we need an additional space.
44    pub fn compute_emoji<T: Display + Sized>(&self, emoji: T) -> String {
45        if let Ok(term_program) = env::var("TERM_PROGRAM") {
46            if TERMS.contains(&term_program.as_str())
47                && (emoji.to_string().chars().count() == 2 || format!("{emoji}") == " ")
48            {
49                return format!("{emoji} ");
50            }
51        }
52
53        emoji.to_string()
54    }
55
56    /// # Errors
57    ///
58    /// Might return an error
59    pub fn log_transaction(
60        &self,
61        tx: &Transaction,
62        network: &Network,
63        show_link: bool,
64    ) -> Result<(), XdrError> {
65        let tx_hash = transaction_hash(tx, &network.network_passphrase)?;
66        let hash = hex::encode(tx_hash);
67
68        self.infoln(format!("Transaction hash is {hash}").as_str());
69
70        if show_link {
71            if let Some(url) = explorer_url_for_transaction(network, &hash) {
72                self.linkln(url);
73            }
74        }
75
76        Ok(())
77    }
78}
79
80macro_rules! create_print_functions {
81    ($name:ident, $nameln:ident, $icon:expr) => {
82        impl Print {
83            #[allow(dead_code)]
84            pub fn $name<T: Display + Sized>(&self, message: T) {
85                if !self.quiet {
86                    eprint!("{} {}", self.compute_emoji($icon), message);
87                }
88            }
89
90            #[allow(dead_code)]
91            pub fn $nameln<T: Display + Sized>(&self, message: T) {
92                if !self.quiet {
93                    eprintln!("{} {}", self.compute_emoji($icon), message);
94                }
95            }
96        }
97    };
98}
99
100create_print_functions!(bucket, bucketln, "đŸĒŖ");
101create_print_functions!(check, checkln, "✅");
102create_print_functions!(error, errorln, "❌");
103create_print_functions!(globe, globeln, "🌎");
104create_print_functions!(info, infoln, "â„šī¸");
105create_print_functions!(link, linkln, "🔗");
106create_print_functions!(plus, plusln, "➕");
107create_print_functions!(save, saveln, "💾");
108create_print_functions!(search, searchln, "🔎");
109create_print_functions!(warn, warnln, "âš ī¸");
110create_print_functions!(exclaim, exclaimln, "â—ī¸");
111create_print_functions!(arrow, arrowln, "âžĄī¸");
112create_print_functions!(log, logln, "📔");
113create_print_functions!(event, eventln, "📅");
114create_print_functions!(blank, blankln, " ");
115create_print_functions!(gear, gearln, "âš™ī¸");