CliRunner: replace start hook by dispatch hook

The `CliRunner` lets a custom binary add processing that should happen
before running a command. This patch replaces that by a hook that can
do processing before and/or after. I thought I would want to use this
for adding telemetry (such as timings) to our custom binary at
Google. I ended up adding that logging outside of `CliRunner::run()`
instead, so it gives a more accurate timing of the whole invocation. I
think this patch is still an improvement, as it's more generic than
the start hook.
This commit is contained in:
Martin von Zweigbergk 2025-04-27 07:41:44 -07:00
parent 517292fd46
commit 4435fae3be

View File

@ -3656,11 +3656,14 @@ pub struct CliRunner {
commit_template_extensions: Vec<Arc<dyn CommitTemplateLanguageExtension>>,
operation_template_extensions: Vec<Arc<dyn OperationTemplateLanguageExtension>>,
dispatch_fn: CliDispatchFn,
start_hook_fns: Vec<CliDispatchFn>,
dispatch_hook_fns: Vec<CliDispatchHookFn>,
process_global_args_fns: Vec<ProcessGlobalArgsFn>,
}
type CliDispatchFn = Box<dyn FnOnce(&mut Ui, &CommandHelper) -> Result<(), CommandError>>;
pub type CliDispatchFn = Box<dyn FnOnce(&mut Ui, &CommandHelper) -> Result<(), CommandError>>;
type CliDispatchHookFn =
Box<dyn FnOnce(&mut Ui, &CommandHelper, CliDispatchFn) -> Result<(), CommandError>>;
type ProcessGlobalArgsFn = Box<dyn FnOnce(&mut Ui, &ArgMatches) -> Result<(), CommandError>>;
@ -3682,7 +3685,7 @@ impl CliRunner {
commit_template_extensions: vec![],
operation_template_extensions: vec![],
dispatch_fn: Box::new(crate::commands::run_command),
start_hook_fns: vec![],
dispatch_hook_fns: vec![],
process_global_args_fns: vec![],
}
}
@ -3779,8 +3782,14 @@ impl CliRunner {
self
}
pub fn add_start_hook(mut self, start_hook_fn: CliDispatchFn) -> Self {
self.start_hook_fns.push(start_hook_fn);
/// Add a hook that gets called when it's time to run the command. It is
/// the hook's responsibility to call the given inner dispatch function to
/// run the command.
pub fn add_dispatch_hook<F>(mut self, dispatch_hook_fn: F) -> Self
where
F: FnOnce(&mut Ui, &CommandHelper, CliDispatchFn) -> Result<(), CommandError> + 'static,
{
self.dispatch_hook_fns.push(Box::new(dispatch_hook_fn));
self
}
@ -3940,10 +3949,15 @@ impl CliRunner {
let command_helper = CommandHelper {
data: Rc::new(command_helper_data),
};
for start_hook_fn in self.start_hook_fns {
start_hook_fn(ui, &command_helper)?;
}
(self.dispatch_fn)(ui, &command_helper)
let dispatch_fn = self.dispatch_hook_fns.into_iter().fold(
self.dispatch_fn,
|old_dispatch_fn, dispatch_hook_fn| {
Box::new(move |ui: &mut Ui, command_helper: &CommandHelper| {
dispatch_hook_fn(ui, command_helper, old_dispatch_fn)
})
},
);
(dispatch_fn)(ui, &command_helper)
}
#[must_use]