foundry_cli/opts/
global.rs1use clap::{ArgAction, Parser};
2use foundry_common::{
3 shell::{ColorChoice, OutputFormat, OutputMode, Shell, Verbosity},
4 version::{IS_NIGHTLY_VERSION, NIGHTLY_VERSION_WARNING_MESSAGE},
5};
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Debug, Default, Serialize, Deserialize, Parser)]
10pub struct GlobalArgs {
11 #[arg(help_heading = "Display options", global = true, short, long, verbatim_doc_comment, conflicts_with = "quiet", action = ArgAction::Count)]
24 verbosity: Verbosity,
25
26 #[arg(help_heading = "Display options", global = true, short, long, alias = "silent")]
28 quiet: bool,
29
30 #[arg(help_heading = "Display options", global = true, long, alias = "format-json", conflicts_with_all = &["quiet", "color"])]
32 json: bool,
33
34 #[arg(
36 help_heading = "Display options",
37 global = true,
38 long,
39 alias = "markdown",
40 conflicts_with = "json"
41 )]
42 md: bool,
43
44 #[arg(help_heading = "Display options", global = true, long, value_enum)]
46 color: Option<ColorChoice>,
47
48 #[arg(global = true, long, short = 'j', visible_alias = "jobs")]
50 threads: Option<usize>,
51}
52
53impl GlobalArgs {
54 pub fn init(&self) -> eyre::Result<()> {
56 let shell = self.shell();
58 match shell.color_choice() {
60 ColorChoice::Auto => {}
61 ColorChoice::Always => yansi::enable(),
62 ColorChoice::Never => yansi::disable(),
63 }
64 shell.set();
65
66 if self.threads.is_some() {
68 self.force_init_thread_pool()?;
69 }
70
71 if IS_NIGHTLY_VERSION
73 && !self.json
74 && std::env::var_os("FOUNDRY_DISABLE_NIGHTLY_WARNING").is_none()
75 {
76 let _ = sh_warn!("{}", NIGHTLY_VERSION_WARNING_MESSAGE);
77 }
78
79 Ok(())
80 }
81
82 pub fn shell(&self) -> Shell {
84 let mode = match self.quiet {
85 true => OutputMode::Quiet,
86 false => OutputMode::Normal,
87 };
88 let color = self.json.then_some(ColorChoice::Never).or(self.color).unwrap_or_default();
89 let format = if self.json {
90 OutputFormat::Json
91 } else if self.md {
92 OutputFormat::Markdown
93 } else {
94 OutputFormat::Text
95 };
96
97 Shell::new_with(format, mode, color, self.verbosity)
98 }
99
100 pub fn force_init_thread_pool(&self) -> eyre::Result<()> {
102 init_thread_pool(self.threads.unwrap_or(0))
103 }
104
105 #[track_caller]
107 pub fn tokio_runtime(&self) -> tokio::runtime::Runtime {
108 let mut builder = tokio::runtime::Builder::new_multi_thread();
109 if let Some(threads) = self.threads
110 && threads > 0
111 {
112 builder.worker_threads(threads);
113 }
114 builder.enable_all().build().expect("failed to create tokio runtime")
115 }
116
117 #[track_caller]
119 pub fn block_on<F: std::future::Future>(&self, future: F) -> F::Output {
120 self.tokio_runtime().block_on(future)
121 }
122}
123
124pub fn init_thread_pool(threads: usize) -> eyre::Result<()> {
126 rayon::ThreadPoolBuilder::new()
127 .thread_name(|i| format!("foundry-{i}"))
128 .num_threads(threads)
129 .build_global()?;
130 Ok(())
131}