aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md5
-rw-r--r--mingling_core/src/program/once_exec.rs25
2 files changed, 21 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index de97204..60b8f2c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -76,6 +76,11 @@
7. **\[macros:dispatch_tree\]** Fixed the static name generation for dispatch tree nodes to use `snake_case` conversion instead of simple `.` → `_` replacement, and fixed the `__comp` completion dispatcher static name from `__internal_dispatcher___comp` (triple underscore) to `__internal_dispatcher_comp` (double underscore), resolving a mismatch between the name generated by `register_dispatcher!` and the name used in `program_comp_gen`.
+8. **\[core\]** Changed the `exec_without_render` and `exec` methods' behavior: when `stdout_setting.render_output` is `false` or the result is empty, the exit code from the result is now returned instead of hardcoded `0`. This ensures that programs which set a non-zero exit code without producing renderable output (e.g., via `ExitCodeSetup` or `ProgramControlUnit::OverrideExitCode`) will exit with the correct code. Specific changes in `once_exec.rs`:
+
+ - `exec()` (async) and `exec_without_render_and_print()` (sync): The `exit_code` is now read from the result before the render check, and returned as the fallback value instead of `0` when output is not printed.
+ - This means `ExitCode` / `ProgramControls` overrides are now respected regardless of whether any output is rendered.
+
#### Optimizations:
1. **\[core:flag\]** Refactored the `special_argument!` and `special_arguments!` macros to replace index‑based `while` loops with iterator `position` and `drain`, improving both performance and readability.
diff --git a/mingling_core/src/program/once_exec.rs b/mingling_core/src/program/once_exec.rs
index 4c44597..9d6f1e4 100644
--- a/mingling_core/src/program/once_exec.rs
+++ b/mingling_core/src/program/once_exec.rs
@@ -48,10 +48,13 @@ where
}
/// Run the command line program
+ #[must_use]
pub async fn exec(self) -> i32
where
C: 'static + Send + Sync,
{
+ use crate::error::ProgramExecuteError;
+
let stdout_setting = self.stdout_setting.clone();
let result = match self.exec_without_render().await {
Ok(r) => r,
@@ -61,35 +64,37 @@ where
return 1;
}
ProgramExecuteError::RendererNotFound(renderer_name) => {
- eprintln!("Renderer `{}` not found", renderer_name);
+ eprintln!("Renderer `{renderer_name}` not found");
return 1;
}
ProgramExecuteError::Other(e) => {
- eprintln!("{}", e);
+ eprintln!("{e}");
return 1;
}
ProgramExecuteError::Panic(unwinded_error) => {
- eprintln!("{}", unwinded_error);
+ eprintln!("{unwinded_error}");
return 1;
}
},
};
+ // Read exit code
+ let exit_code = result.exit_code;
+
// Render result
if stdout_setting.render_output && !result.is_empty() {
- let exit_code = result.exit_code;
- print!("{}", result);
+ print!("{result}");
if let Err(e) = std::io::Write::flush(&mut std::io::stdout())
&& stdout_setting.error_output
{
- eprintln!("{}", e);
+ eprintln!("{e}");
1
} else {
exit_code
}
} else {
- 0
+ exit_code
}
}
@@ -211,9 +216,11 @@ where
},
};
+ // Read exit code
+ let exit_code = result.exit_code;
+
// Render result
if stdout_setting.render_output && !result.is_empty() {
- let exit_code = result.exit_code;
print!("{result}");
if let Err(e) = std::io::Write::flush(&mut std::io::stdout())
@@ -225,7 +232,7 @@ where
exit_code
}
} else {
- 0
+ exit_code
}
}