soroban_cli/commands/env/
mod.rs1use crate::{
2 commands::global,
3 config::locator::{self},
4 env_vars,
5 print::Print,
6 utils::escape_control_characters,
7};
8use clap::Parser;
9use shell_escape::escape;
10
11#[allow(clippy::doc_markdown)]
12#[derive(Debug, Parser)]
13pub struct Cmd {
14 #[arg()]
18 pub name: Option<String>,
19
20 #[arg(long)]
23 pub reveal: bool,
24
25 #[command(flatten)]
26 pub config_locator: locator::Args,
27}
28
29#[derive(thiserror::Error, Debug)]
30pub enum Error {
31 #[error(transparent)]
32 Locator(#[from] locator::Error),
33}
34
35impl Cmd {
36 pub fn run(&self, global_args: &global::Args) -> Result<(), Error> {
37 let print = Print::new(global_args.quiet);
38 let mut vars: Vec<EnvVar> = Vec::new();
39 let supported = env_vars::prefixed("STELLAR");
40
41 for key in supported {
42 if let Some(mut v) = EnvVar::get(&key) {
43 if self.reveal {
44 v.reveal();
45 }
46
47 vars.push(v);
48 }
49 }
50
51 if let Some(name) = &self.name {
53 if let Some(v) = vars.iter().find(|v| &v.key == name) {
54 if v.is_revealed() {
55 println!("{}", escape_control_characters(&v.value));
56 }
57 }
58
59 return Ok(());
60 }
61
62 if vars.is_empty() {
63 print.warnln("No defaults or environment variables set".to_string());
64 return Ok(());
65 }
66
67 let max_len = vars.iter().map(|v| v.str().len()).max().unwrap_or(0);
68
69 vars.sort();
70
71 for v in vars {
72 println!("{:max_len$} # {}", v.str(), v.source);
73 }
74
75 Ok(())
76 }
77}
78
79#[derive(PartialEq, Eq, PartialOrd, Ord)]
80struct EnvVar {
81 key: String,
82 value: String,
83 source: String,
84 reveal: bool,
85}
86
87impl EnvVar {
88 fn get(key: &str) -> Option<Self> {
89 let source = std::env::var(format!("{key}_SOURCE"))
91 .ok()
92 .unwrap_or("env".to_string());
93
94 if let Ok(value) = std::env::var(key) {
95 return Some(EnvVar {
96 key: key.to_string(),
97 value,
98 source,
99 reveal: false,
100 });
101 }
102
103 None
104 }
105
106 fn reveal(&mut self) {
107 self.reveal = true;
108 }
109
110 fn is_revealed(&self) -> bool {
111 self.reveal || !env_vars::is_concealed(&self.key)
112 }
113
114 fn str(&self) -> String {
115 if self.is_revealed() {
116 let value = escape(escape_control_characters(&self.value).into());
117 format!("{}={value}", self.key)
118 } else {
119 format!("# {}=<concealed>", self.key)
120 }
121 }
122}