Skip to content

add verbosity levels - #91

Merged
slinder1 merged 1 commit into
users/slinder1/Ic38b52930d36f3c120fdff959c849643280dba97from
users/slinder1/I7421c5f5841d77789572ced48f3ab689a0c8f39d
Aug 11, 2026
Merged

add verbosity levels#91
slinder1 merged 1 commit into
users/slinder1/Ic38b52930d36f3c120fdff959c849643280dba97from
users/slinder1/I7421c5f5841d77789572ced48f3ab689a0c8f39d

Conversation

@slinder1

Copy link
Copy Markdown
Owner

Change-Id: I7421c5f5841d77789572ced48f3ab689a0c8f39d

@slinder1
slinder1 changed the base branch from main to users/slinder1/Ic38b52930d36f3c120fdff959c849643280dba97 August 11, 2026 16:03
@slinder1

Copy link
Copy Markdown
Owner Author
🛠️ Initial changes (click to expand):
diff --git b/src/cli.rs a/src/cli.rs
@@ -1,5 +1,14 @@
 use clap::{ArgAction, Args, Parser, Subcommand};
 
+fn parse_verbosity(value: &str) -> Result<u8, String> {
+    match value {
+        "0" => Ok(1),
+        "1" => Ok(1),
+        "2" | "v" => Ok(2),
+        _ => Err("verbosity must be 0, 1, or 2/v".into()),
+    }
+}
+
 /// GitHub stacked-PR builder for those who miss Gerrit
 ///
 /// Main features:
@@ -77,9 +86,17 @@ pub struct Globals {
     /// which have the potential to mutate remote state are skipped and printed.
     #[arg(short = '#', long, global = true)]
     pub dry_run: bool,
-    /// Output all commands executed, and their stdout/stderr.
-    #[arg(short, long, global = true)]
-    pub verbose: bool,
+    /// Output commands executed. Repeat for command output as well.
+    #[arg(
+        short,
+        long,
+        global = true,
+        value_parser = parse_verbosity,
+        num_args = 0..=1,
+        default_missing_value = "1",
+        default_value = "0"
+    )]
+    pub verbose: u8,
 }
 
 #[derive(Subcommand)]
diff --git b/src/env.rs a/src/env.rs
@@ -94,12 +94,12 @@ impl Env {
         self.cli.globals.dry_run
     }
 
-    pub fn verbose(&self) -> bool {
+    pub fn verbosity(&self) -> u8 {
         self.cli.globals.verbose
     }
 
     pub fn always_echo(&self) -> bool {
-        self.dry_run() || self.verbose()
+        self.dry_run() || self.verbosity() > 0
     }
 
     pub fn next_exec_id(&self) -> usize {
diff --git b/src/util.rs a/src/util.rs
@@ -5,6 +5,37 @@ use anyhow::{Context, Result, bail};
 use std::fmt::Debug;
 use std::process::{Command, Output};
 
+const MAX_VERBOSE_LINE_BYTES: usize = 100;
+
+fn truncate_line(line: &str) -> String {
+    if line.len() <= MAX_VERBOSE_LINE_BYTES {
+        return line.to_owned();
+    }
+    let marker = "[...]";
+    let prefix_bytes = (MAX_VERBOSE_LINE_BYTES - marker.len()) / 2;
+    let suffix_bytes = MAX_VERBOSE_LINE_BYTES - marker.len() - prefix_bytes;
+    let mut prefix_end = prefix_bytes;
+    while !line.is_char_boundary(prefix_end) {
+        prefix_end -= 1;
+    }
+    let mut suffix_start = line.len() - suffix_bytes;
+    while !line.is_char_boundary(suffix_start) {
+        suffix_start += 1;
+    }
+    format!("{}{}{}", &line[..prefix_end], marker, &line[suffix_start..])
+}
+
+fn print_output(prefix: &str, output: &[u8], truncate: bool) {
+    for line in String::from_utf8_lossy(output).lines() {
+        let line = if truncate {
+            truncate_line(line)
+        } else {
+            line.to_owned()
+        };
+        eprintln!("{prefix}{line}");
+    }
+}
+
 pub fn exec_impl(env: &crate::env::Env, cmd: &mut Command) -> Result<Output> {
     let id = env.next_exec_id();
     if env.always_echo() {
@@ -13,13 +44,18 @@ pub fn exec_impl(env: &crate::env::Env, cmd: &mut Command) -> Result<Output> {
     let output = cmd
         .output()
         .with_context(|| format!("exec-failed: {:?}", cmd))?;
-    if env.always_echo() || !output.status.success() {
-        for line in String::from_utf8_lossy(output.stdout.as_ref()).lines() {
-            eprintln!("exec-{}-stdout: {}", id, line);
-        }
-        for line in String::from_utf8_lossy(output.stderr.as_ref()).lines() {
-            eprintln!("exec-{}-stderr: {}", id, line);
-        }
+    if env.dry_run() || env.verbosity() > 0 || !output.status.success() {
+        let truncate = env.verbosity() == 1;
+        print_output(
+            &format!("exec-{id}-stdout: "),
+            output.stdout.as_ref(),
+            truncate,
+        );
+        print_output(
+            &format!("exec-{id}-stderr: "),
+            output.stderr.as_ref(),
+            truncate,
+        );
     }
     if !output.status.success() {
         bail!("exec-{}-status-non-zero: {:?}", id, output.status);

@slinder1
slinder1 marked this pull request as ready for review August 11, 2026 16:04
@slinder1
slinder1 marked this pull request as draft August 11, 2026 16:05
@slinder1
slinder1 changed the base branch from users/slinder1/Ic38b52930d36f3c120fdff959c849643280dba97 to main August 11, 2026 16:05
@slinder1
slinder1 force-pushed the users/slinder1/I7421c5f5841d77789572ced48f3ab689a0c8f39d branch from c9fcb44 to 4374476 Compare August 11, 2026 16:05
@slinder1
slinder1 changed the base branch from main to users/slinder1/Ic38b52930d36f3c120fdff959c849643280dba97 August 11, 2026 16:05
@slinder1
slinder1 marked this pull request as ready for review August 11, 2026 16:05
@slinder1
slinder1 force-pushed the users/slinder1/I7421c5f5841d77789572ced48f3ab689a0c8f39d branch from 4374476 to a1e8d9d Compare August 11, 2026 16:09
@slinder1
slinder1 marked this pull request as draft August 11, 2026 16:29
@slinder1
slinder1 changed the base branch from users/slinder1/Ic38b52930d36f3c120fdff959c849643280dba97 to main August 11, 2026 16:29
@slinder1
slinder1 force-pushed the users/slinder1/I7421c5f5841d77789572ced48f3ab689a0c8f39d branch from a1e8d9d to 9ba0464 Compare August 11, 2026 16:29
@slinder1
slinder1 changed the base branch from main to users/slinder1/Ic38b52930d36f3c120fdff959c849643280dba97 August 11, 2026 16:29
@slinder1
slinder1 marked this pull request as ready for review August 11, 2026 16:30
@slinder1
slinder1 force-pushed the users/slinder1/I7421c5f5841d77789572ced48f3ab689a0c8f39d branch from 9ba0464 to c4316c0 Compare August 11, 2026 16:45
@slinder1

Copy link
Copy Markdown
Owner Author
🛠️ Changes since last version (click to expand):
diff --git b/src/cli.rs a/src/cli.rs
@@ -2,7 +2,7 @@ use clap::{ArgAction, Args, Parser, Subcommand};
 
 fn parse_verbosity(value: &str) -> Result<u8, String> {
     match value {
-        "0" => Ok(1),
+        "0" => Ok(0),
         "1" => Ok(1),
         "2" | "v" => Ok(2),
         _ => Err("verbosity must be 0, 1, or 2/v".into()),

@slinder1
slinder1 force-pushed the users/slinder1/I7421c5f5841d77789572ced48f3ab689a0c8f39d branch from c4316c0 to 567629c Compare August 11, 2026 16:58
@slinder1
slinder1 force-pushed the users/slinder1/I7421c5f5841d77789572ced48f3ab689a0c8f39d branch from 567629c to e017535 Compare August 11, 2026 17:09
Change-Id: I7421c5f5841d77789572ced48f3ab689a0c8f39d
@slinder1
slinder1 force-pushed the users/slinder1/I7421c5f5841d77789572ced48f3ab689a0c8f39d branch from e017535 to dd5a11a Compare August 11, 2026 17:20
@slinder1
slinder1 merged commit 89fd6f6 into main Aug 11, 2026
3 checks passed
@slinder1
slinder1 deleted the users/slinder1/I7421c5f5841d77789572ced48f3ab689a0c8f39d branch August 11, 2026 17:24
slinder1 added a commit that referenced this pull request Aug 12, 2026
For now this just controls whether stdout/stderr from subprocesses
gets truncated or not. Generally long output is not helpful for the
user, but sometimes (especially since there are no formal tests) it
is necessary to trace the actual responses to find a bug in praddle

Change-Id: I7421c5f5841d77789572ced48f3ab689a0c8f39d
Assisted-by: opencode
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant