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)]
23 verbosity: Verbosity,
24
25 #[arg(help_heading = "Display options", global = true, short, long, alias = "silent")]
27 quiet: bool,
28
29 #[arg(help_heading = "Display options", global = true, long, alias = "format-json", conflicts_with_all = &["quiet", "color"])]
31 json: bool,
32
33 #[arg(
35 help_heading = "Display options",
36 global = true,
37 long,
38 alias = "markdown",
39 conflicts_with = "json"
40 )]
41 md: bool,
42
43 #[arg(help_heading = "Display options", global = true, long, value_enum)]
45 color: Option<ColorChoice>,
46
47 #[arg(global = true, long, short = 'j', visible_alias = "jobs")]
49 threads: Option<usize>,
50}
51
52impl GlobalArgs {
53 pub fn init(&self) -> eyre::Result<()> {
55 self.shell().set();
57
58 if self.threads.is_some() {
60 self.force_init_thread_pool()?;
61 }
62
63 if std::env::var("FOUNDRY_DISABLE_NIGHTLY_WARNING").is_err()
65 && !self.json
66 && IS_NIGHTLY_VERSION
67 {
68 let _ = sh_warn!("{}", NIGHTLY_VERSION_WARNING_MESSAGE);
69 }
70
71 Ok(())
72 }
73
74 pub fn shell(&self) -> Shell {
76 let mode = match self.quiet {
77 true => OutputMode::Quiet,
78 false => OutputMode::Normal,
79 };
80 let color = self.json.then_some(ColorChoice::Never).or(self.color).unwrap_or_default();
81 let format = if self.json {
82 OutputFormat::Json
83 } else if self.md {
84 OutputFormat::Markdown
85 } else {
86 OutputFormat::Text
87 };
88
89 Shell::new_with(format, mode, color, self.verbosity)
90 }
91
92 pub fn force_init_thread_pool(&self) -> eyre::Result<()> {
94 init_thread_pool(self.threads.unwrap_or(0))
95 }
96
97 #[track_caller]
99 pub fn tokio_runtime(&self) -> tokio::runtime::Runtime {
100 let mut builder = tokio::runtime::Builder::new_multi_thread();
101 if let Some(threads) = self.threads
102 && threads > 0
103 {
104 builder.worker_threads(threads);
105 }
106 builder.enable_all().build().expect("failed to create tokio runtime")
107 }
108
109 #[track_caller]
111 pub fn block_on<F: std::future::Future>(&self, future: F) -> F::Output {
112 self.tokio_runtime().block_on(future)
113 }
114}
115
116pub fn init_thread_pool(threads: usize) -> eyre::Result<()> {
118 rayon::ThreadPoolBuilder::new()
119 .thread_name(|i| format!("foundry-{i}"))
120 .num_threads(threads)
121 .build_global()?;
122 Ok(())
123}