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