Skip to content

Commit 6cc8d8b

Browse files
zerosnacksDaniPopes
authored andcommitted
feat: add foundry_common::shell to unify log behavior (foundry-rs#9109)
* replace existing shell::println, add macros * finish replacing shell::println * remove p_println * remove redundant quiet or silent variables * install global shells in binaries * CastArgs -> Cast, Cast -> CastInstance * fix tests, always initialize Mutex::new(Shell::new()) on initial access, for some reason cfg!(test) path is not handled when running with tokio tests * revert .quiet(true) * add back quiet * undo CastInstance -> Cast, Cast -> CastArgs * add global --json format * use global --json flag * revert sequence / multisequence save silent mode * fix failing tests * fix tests * fix tests * replace cli_warn with sh_warn * use shell json directly instead of passing in * clean up, document print modes in respect to --quiet flag * group shell options under display options * revert global --json flag * remove redundant import * fix: quiet * remove faulty argument conflict test as there is no way to currently assert a conflict between global and local args without custom reject at runtime * add back conflicts_with quiet flag, global args w/ conflicts_with works fine * remove yellow() * Apply suggestions from code review - update dependencies - use default Co-authored-by: DaniPopes <[email protected]> * fix deprecated terminal_size method * revert quiet flag, fix os:fd import for windows * add replacing tests, add back quiet conflicting flag * make output windows compatible * to avoid visual regression, style warning message content in yellow, error message content in red - both not bold * fix docs links * fix junit throwing mixed content on warnings, avoid modifying global verbosity * remove set_verbosity shell helper, redundant * revert default .expect on printing, prefer passing. revert message style formatting - no longer style the message * fix doc test, fix formatting * fix merge issues --------- Co-authored-by: DaniPopes <[email protected]>
1 parent 8c2d86d commit 6cc8d8b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1267
-765
lines changed

Diff for: Cargo.lock

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,11 @@ alloy-trie = "0.6.0"
225225
op-alloy-rpc-types = "0.5.0"
226226
op-alloy-consensus = "0.5.0"
227227

228+
## cli
229+
anstream = "0.6.15"
230+
anstyle = "1.0.8"
231+
terminal_size = "0.4"
232+
228233
# macros
229234
proc-macro2 = "1.0.82"
230235
quote = "1.0"

Diff for: clippy.toml

+8
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,11 @@ msrv = "1.80"
22
# bytes::Bytes is included by default and alloy_primitives::Bytes is a wrapper around it,
33
# so it is safe to ignore it as well
44
ignore-interior-mutability = ["bytes::Bytes", "alloy_primitives::Bytes"]
5+
6+
# disallowed-macros = [
7+
# # See `foundry_common::shell`
8+
# { path = "std::print", reason = "use `sh_print` or similar macros instead" },
9+
# { path = "std::eprint", reason = "use `sh_eprint` or similar macros instead" },
10+
# { path = "std::println", reason = "use `sh_println` or similar macros instead" },
11+
# { path = "std::eprintln", reason = "use `sh_eprintln` or similar macros instead" },
12+
# ]

Diff for: crates/anvil/src/anvil.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
33
use anvil::cmd::NodeArgs;
44
use clap::{CommandFactory, Parser, Subcommand};
5-
use foundry_cli::utils;
5+
use eyre::Result;
6+
use foundry_cli::{opts::ShellOpts, utils};
67

78
#[cfg(all(feature = "jemalloc", unix))]
89
#[global_allocator]
@@ -17,6 +18,9 @@ pub struct Anvil {
1718

1819
#[command(subcommand)]
1920
pub cmd: Option<AnvilSubcommand>,
21+
22+
#[clap(flatten)]
23+
pub shell: ShellOpts,
2024
}
2125

2226
#[derive(Subcommand)]
@@ -33,10 +37,18 @@ pub enum AnvilSubcommand {
3337
GenerateFigSpec,
3438
}
3539

36-
fn main() -> eyre::Result<()> {
40+
fn main() {
41+
if let Err(err) = run() {
42+
let _ = foundry_common::Shell::get().error(&err);
43+
std::process::exit(1);
44+
}
45+
}
46+
47+
fn run() -> Result<()> {
3748
utils::load_dotenv();
3849

3950
let mut args = Anvil::parse();
51+
args.shell.shell().set();
4052
args.node.evm_opts.resolve_rpc_alias();
4153

4254
if let Some(cmd) = &args.cmd {

Diff for: crates/anvil/src/cmd.rs

-5
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,6 @@ pub struct NodeArgs {
7272
#[arg(long)]
7373
pub derivation_path: Option<String>,
7474

75-
/// Don't print anything on startup and don't print logs
76-
#[arg(long)]
77-
pub silent: bool,
78-
7975
/// The EVM hardfork to use.
8076
///
8177
/// Choose the hardfork by name, e.g. `shanghai`, `paris`, `london`, etc...
@@ -258,7 +254,6 @@ impl NodeArgs {
258254
.with_storage_caching(self.evm_opts.no_storage_caching)
259255
.with_server_config(self.server_config)
260256
.with_host(self.host)
261-
.set_silent(self.silent)
262257
.set_config_out(self.config_out)
263258
.with_chain_id(self.evm_opts.chain_id)
264259
.with_transaction_order(self.order)

Diff for: crates/anvil/src/config.rs

+3-21
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,6 @@ pub struct NodeConfig {
123123
pub port: u16,
124124
/// maximum number of transactions in a block
125125
pub max_transactions: usize,
126-
/// don't print anything on startup
127-
pub silent: bool,
128126
/// url of the rpc server that should be used for any rpc calls
129127
pub eth_rpc_url: Option<String>,
130128
/// pins the block number or transaction hash for the state fork
@@ -394,7 +392,7 @@ impl NodeConfig {
394392
/// random, free port by setting it to `0`
395393
#[doc(hidden)]
396394
pub fn test() -> Self {
397-
Self { enable_tracing: true, silent: true, port: 0, ..Default::default() }
395+
Self { enable_tracing: true, port: 0, ..Default::default() }
398396
}
399397

400398
/// Returns a new config which does not initialize any accounts on node startup.
@@ -429,7 +427,6 @@ impl Default for NodeConfig {
429427
port: NODE_PORT,
430428
// TODO make this something dependent on block capacity
431429
max_transactions: 1_000,
432-
silent: false,
433430
eth_rpc_url: None,
434431
fork_choice: None,
435432
account_generator: None,
@@ -732,18 +729,6 @@ impl NodeConfig {
732729
self
733730
}
734731

735-
/// Makes the node silent to not emit anything on stdout
736-
#[must_use]
737-
pub fn silent(self) -> Self {
738-
self.set_silent(true)
739-
}
740-
741-
#[must_use]
742-
pub fn set_silent(mut self, silent: bool) -> Self {
743-
self.silent = silent;
744-
self
745-
}
746-
747732
/// Sets the ipc path to use
748733
///
749734
/// Note: this is a double Option for
@@ -763,7 +748,7 @@ impl NodeConfig {
763748
self
764749
}
765750

766-
/// Makes the node silent to not emit anything on stdout
751+
/// Disables storage caching
767752
#[must_use]
768753
pub fn no_storage_caching(self) -> Self {
769754
self.with_storage_caching(true)
@@ -921,11 +906,8 @@ impl NodeConfig {
921906
)
922907
.expect("Failed writing json");
923908
}
924-
if self.silent {
925-
return;
926-
}
927909

928-
println!("{}", self.as_string(fork))
910+
let _ = sh_println!("{}", self.as_string(fork));
929911
}
930912

931913
/// Returns the path where the cache file should be stored

Diff for: crates/anvil/src/lib.rs

+21-17
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
#![doc = include_str!("../README.md")]
22
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
33

4-
#[macro_use]
5-
extern crate tracing;
6-
74
use crate::{
85
eth::{
96
backend::{info::StorageInfo, mem},
@@ -23,7 +20,10 @@ use crate::{
2320
use alloy_primitives::{Address, U256};
2421
use alloy_signer_local::PrivateKeySigner;
2522
use eth::backend::fork::ClientFork;
26-
use foundry_common::provider::{ProviderBuilder, RetryProvider};
23+
use foundry_common::{
24+
provider::{ProviderBuilder, RetryProvider},
25+
shell,
26+
};
2727
use foundry_evm::revm;
2828
use futures::{FutureExt, TryFutureExt};
2929
use parking_lot::Mutex;
@@ -74,6 +74,12 @@ mod tasks;
7474
#[cfg(feature = "cmd")]
7575
pub mod cmd;
7676

77+
#[macro_use]
78+
extern crate foundry_common;
79+
80+
#[macro_use]
81+
extern crate tracing;
82+
7783
/// Creates the node and runs the server.
7884
///
7985
/// Returns the [EthApi] that can be used to interact with the node and the [JoinHandle] of the
@@ -125,7 +131,7 @@ pub async fn spawn(config: NodeConfig) -> (EthApi, NodeHandle) {
125131
/// ```
126132
pub async fn try_spawn(mut config: NodeConfig) -> io::Result<(EthApi, NodeHandle)> {
127133
let logger = if config.enable_tracing { init_tracing() } else { Default::default() };
128-
logger.set_enabled(!config.silent);
134+
logger.set_enabled(!shell::is_quiet());
129135

130136
let backend = Arc::new(config.setup().await);
131137

@@ -292,19 +298,17 @@ impl NodeHandle {
292298
/// Prints the launch info.
293299
pub(crate) fn print(&self, fork: Option<&ClientFork>) {
294300
self.config.print(fork);
295-
if !self.config.silent {
296-
if let Some(ipc_path) = self.ipc_path() {
297-
println!("IPC path: {ipc_path}");
298-
}
299-
println!(
300-
"Listening on {}",
301-
self.addresses
302-
.iter()
303-
.map(|addr| { addr.to_string() })
304-
.collect::<Vec<String>>()
305-
.join(", ")
306-
);
301+
if let Some(ipc_path) = self.ipc_path() {
302+
let _ = sh_println!("IPC path: {ipc_path}");
307303
}
304+
let _ = sh_println!(
305+
"Listening on {}",
306+
self.addresses
307+
.iter()
308+
.map(|addr| { addr.to_string() })
309+
.collect::<Vec<String>>()
310+
.join(", ")
311+
);
308312
}
309313

310314
/// The address of the launched server.

Diff for: crates/anvil/tests/it/fork.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ pub fn fork_config() -> NodeConfig {
5757
NodeConfig::test()
5858
.with_eth_rpc_url(Some(rpc::next_http_archive_rpc_endpoint()))
5959
.with_fork_block_number(Some(BLOCK_NUMBER))
60-
.silent()
6160
}
6261

6362
#[tokio::test(flavor = "multi_thread")]
@@ -829,10 +828,9 @@ async fn test_fork_init_base_fee() {
829828

830829
#[tokio::test(flavor = "multi_thread")]
831830
async fn test_reset_fork_on_new_blocks() {
832-
let (api, handle) = spawn(
833-
NodeConfig::test().with_eth_rpc_url(Some(rpc::next_http_archive_rpc_endpoint())).silent(),
834-
)
835-
.await;
831+
let (api, handle) =
832+
spawn(NodeConfig::test().with_eth_rpc_url(Some(rpc::next_http_archive_rpc_endpoint())))
833+
.await;
836834

837835
let anvil_provider = handle.http_provider();
838836
let endpoint = next_http_rpc_endpoint();

Diff for: crates/cast/bin/args.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use alloy_primitives::{Address, B256, U256};
88
use alloy_rpc_types::BlockId;
99
use clap::{Parser, Subcommand, ValueHint};
1010
use eyre::Result;
11-
use foundry_cli::opts::{EtherscanOpts, RpcOpts};
11+
use foundry_cli::opts::{EtherscanOpts, RpcOpts, ShellOpts};
1212
use foundry_common::ens::NameOrAddress;
1313
use std::{path::PathBuf, str::FromStr};
1414

@@ -32,6 +32,9 @@ const VERSION_MESSAGE: &str = concat!(
3232
pub struct Cast {
3333
#[command(subcommand)]
3434
pub cmd: CastSubcommand,
35+
36+
#[clap(flatten)]
37+
pub shell: ShellOpts,
3538
}
3639

3740
#[derive(Subcommand)]

Diff for: crates/cast/bin/cmd/run.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub struct RunArgs {
4545
/// Executes the transaction only with the state from the previous block.
4646
///
4747
/// May result in different results than the live execution!
48-
#[arg(long, short)]
48+
#[arg(long)]
4949
quick: bool,
5050

5151
/// Prints the full address of the contract.

Diff for: crates/cast/bin/cmd/send.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use foundry_cli::{
1313
opts::{EthereumOpts, TransactionOpts},
1414
utils,
1515
};
16-
use foundry_common::{cli_warn, ens::NameOrAddress, selectors::pretty_calldata};
16+
use foundry_common::{ens::NameOrAddress, selectors::pretty_calldata};
1717
use foundry_config::Config;
1818
use serde_json::Value;
1919
use std::{path::PathBuf, str::FromStr};
@@ -147,7 +147,7 @@ impl SendTxArgs {
147147
// switch chain if current chain id is not the same as the one specified in the
148148
// config
149149
if config_chain_id != current_chain_id {
150-
cli_warn!("Switching to chain {}", config_chain);
150+
sh_warn!("Switching to chain {}", config_chain)?;
151151
provider
152152
.raw_request(
153153
"wallet_switchEthereumChain".into(),

Diff for: crates/cast/bin/main.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use cast::{Cast, SimpleCast};
88
use clap::{CommandFactory, Parser};
99
use clap_complete::generate;
1010
use eyre::Result;
11-
use foundry_cli::{handler, prompt, stdin, utils};
11+
use foundry_cli::{handler, utils};
1212
use foundry_common::{
1313
abi::get_event,
1414
ens::{namehash, ProviderEnsExt},
@@ -19,6 +19,7 @@ use foundry_common::{
1919
import_selectors, parse_signatures, pretty_calldata, ParsedSignatures, SelectorImportData,
2020
SelectorType,
2121
},
22+
stdin,
2223
};
2324
use foundry_config::Config;
2425
use std::time::Instant;
@@ -29,16 +30,27 @@ pub mod tx;
2930

3031
use args::{Cast as CastArgs, CastSubcommand, ToBaseArgs};
3132

33+
#[macro_use]
34+
extern crate foundry_common;
35+
3236
#[cfg(all(feature = "jemalloc", unix))]
3337
#[global_allocator]
3438
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
3539

36-
fn main() -> Result<()> {
40+
fn main() {
41+
if let Err(err) = run() {
42+
let _ = foundry_common::Shell::get().error(&err);
43+
std::process::exit(1);
44+
}
45+
}
46+
47+
fn run() -> Result<()> {
3748
handler::install();
3849
utils::load_dotenv();
3950
utils::subscriber();
4051
utils::enable_paint();
4152
let args = CastArgs::parse();
53+
args.shell.shell().set();
4254
main_args(args)
4355
}
4456

0 commit comments

Comments
 (0)