1use std::io::{self, Write};
2use std::{env, fmt::Display};
3
4use crate::xdr::{Error as XdrError, Transaction};
5
6use crate::{
7 config::network::Network, utils::explorer_url_for_transaction, utils::transaction_hash,
8};
9
10#[derive(Clone)]
11pub struct Print {
12 pub quiet: bool,
13}
14
15impl Print {
16 pub fn new(quiet: bool) -> Print {
17 Print { quiet }
18 }
19
20 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) {
29 if !self.quiet {
30 eprintln!("{message}");
31 }
32 }
33
34 pub fn clear_previous_line(&self) {
35 if !self.quiet {
36 if cfg!(windows) {
37 eprint!("\x1b[2A\r\x1b[2K");
38 } else {
39 eprint!("\x1b[1A\x1b[2K\r");
40 }
41
42 io::stderr().flush().unwrap();
43 }
44 }
45
46 pub fn compute_emoji<T: Display + Sized>(&self, emoji: T) -> String {
51 if should_add_additional_space()
52 && (emoji.to_string().chars().count() == 2 || format!("{emoji}") == " ")
53 {
54 return format!("{emoji} ");
55 }
56
57 emoji.to_string()
58 }
59
60 pub fn log_transaction(
64 &self,
65 tx: &Transaction,
66 network: &Network,
67 show_link: bool,
68 ) -> Result<(), XdrError> {
69 let tx_hash = transaction_hash(tx, &network.network_passphrase)?;
70 let hash = hex::encode(tx_hash);
71
72 self.infoln(format!("Transaction hash is {hash}").as_str());
73
74 if show_link {
75 if let Some(url) = explorer_url_for_transaction(network, &hash) {
76 self.linkln(url);
77 }
78 }
79
80 Ok(())
81 }
82}
83
84macro_rules! create_print_functions {
85 ($name:ident, $nameln:ident, $icon:expr) => {
86 impl Print {
87 #[allow(dead_code)]
88 pub fn $name<T: Display + Sized>(&self, message: T) {
89 if !self.quiet {
90 eprint!("{} {}", self.compute_emoji($icon), message);
91 }
92 }
93
94 #[allow(dead_code)]
95 pub fn $nameln<T: Display + Sized>(&self, message: T) {
96 if !self.quiet {
97 eprintln!("{} {}", self.compute_emoji($icon), message);
98 }
99 }
100 }
101 };
102}
103
104fn should_add_additional_space() -> bool {
105 const TERMS: &[&str] = &["Apple_Terminal", "vscode", "unknown"];
106 let term_program = env::var("TERM_PROGRAM").unwrap_or("unknown".to_string());
107
108 if TERMS.contains(&term_program.as_str()) {
109 return true;
110 }
111
112 false
113}
114
115create_print_functions!(bucket, bucketln, "đĒŖ");
116create_print_functions!(check, checkln, "â
");
117create_print_functions!(error, errorln, "â");
118create_print_functions!(globe, globeln, "đ");
119create_print_functions!(info, infoln, "âšī¸");
120create_print_functions!(link, linkln, "đ");
121create_print_functions!(plus, plusln, "â");
122create_print_functions!(save, saveln, "đž");
123create_print_functions!(search, searchln, "đ");
124create_print_functions!(warn, warnln, "â ī¸");
125create_print_functions!(exclaim, exclaimln, "âī¸");
126create_print_functions!(arrow, arrowln, "âĄī¸");
127create_print_functions!(log, logln, "đ");
128create_print_functions!(event, eventln, "đ
");
129create_print_functions!(blank, blankln, " ");
130create_print_functions!(gear, gearln, "âī¸");
131create_print_functions!(dir, dirln, "đ");