diff --git a/cli/src/main.rs b/cli/src/main.rs index 53abc911..551ca865 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,7 +1,7 @@ pub(crate) mod output; use backtrace::Backtrace; -use output::build_output_path; +use output::{build_output_path, print_with_less}; use std::{io, panic}; use clap::{Parser, Subcommand}; @@ -108,8 +108,7 @@ async fn main() -> Result<(), Box> { let assembly = disassemble(cmd.clone()).await?; if cmd.output == "print" { - // TODO: use `less` - println!("{}", assembly); + print_with_less(&assembly).await?; } else { let output_path = build_output_path(&cmd.output, &cmd.target, &cmd.rpc_url, "disassembled.asm") @@ -128,12 +127,19 @@ async fn main() -> Result<(), Box> { let result = decompile(cmd.clone()).await?; if cmd.output == "print" { + let mut output_str = String::new(); + if let Some(abi) = &result.abi { - println!("ABI:\n\n{}\n", serde_json::to_string_pretty(abi).unwrap()); + output_str.push_str(&format!( + "ABI:\n\n{}\n", + serde_json::to_string_pretty(abi).unwrap() + )); } if let Some(source) = &result.source { - println!("Source:\n\n{}\n", source); + output_str.push_str(&format!("Source:\n\n{}\n", source)); } + + print_with_less(&output_str).await?; } else { // write the contract ABI if let Some(abi) = result.abi { @@ -206,7 +212,7 @@ async fn main() -> Result<(), Box> { let stringified_dot = build_cfg(&cfg, &cmd); if cmd.output == "print" { - println!("{}", stringified_dot); + print_with_less(&stringified_dot).await?; } else { let output_path = build_output_path(&cmd.output, &cmd.target, &cmd.rpc_url, "cfg.dot").await?; @@ -240,9 +246,7 @@ async fn main() -> Result<(), Box> { } if cmd.output == "print" { - for line in &lines { - println!("{}", line); - } + print_with_less(&lines.join("\n")).await?; } else { let output_path = build_output_path(&cmd.output, &cmd.target, &cmd.rpc_url, "dump.csv").await?; @@ -265,9 +269,7 @@ async fn main() -> Result<(), Box> { ); if cmd.output == "print" { - for line in &csv_lines { - println!("{}", line); - } + print_with_less(&csv_lines.join("\n")).await?; } else { let output_path = build_output_path(&cmd.output, &cmd.target, &cmd.rpc_url, "snapshot.csv") diff --git a/cli/src/output.rs b/cli/src/output.rs index e9f37823..365f5e5c 100644 --- a/cli/src/output.rs +++ b/cli/src/output.rs @@ -1,4 +1,4 @@ -use std::env; +use std::{env, io::Write}; use heimdall_common::{constants::ADDRESS_REGEX, ether::rpc}; @@ -31,6 +31,18 @@ pub async fn build_output_path( Ok(format!("{}/{}", output, filename)) } +/// pass the input to the `less` command +pub async fn print_with_less(input: &str) -> Result<(), Box> { + let mut child = + std::process::Command::new("less").stdin(std::process::Stdio::piped()).spawn()?; + + let stdin = child.stdin.as_mut().unwrap(); + stdin.write_all(input.as_bytes())?; + + child.wait()?; + Ok(()) +} + #[cfg(test)] mod tests { use super::*;