use clap::ArgMatches;
use std::cell::RefCell;
use std::rc::Rc;
use crate::cli::handler::CommandContext;
use crate::cli::handler::Output as HandlerOutput;
use crate::cli::hooks::Hooks;
use crate::context::{ContextRegistry, RenderContext};
use crate::Theme;
use serde::Serialize;
pub use standout_dispatch::{
extract_command_path, get_deepest_matches, has_subcommand, insert_default_command,
};
pub enum DispatchOutput {
Text {
formatted: String,
raw: String,
},
Binary(Vec<u8>, String),
Silent,
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn render_handler_output<T: Serialize>(
result: Result<HandlerOutput<T>, String>,
matches: &ArgMatches,
ctx: &CommandContext,
hooks: Option<&Hooks>,
template: &str,
theme: &Theme,
context_registry: &ContextRegistry,
template_engine: &dyn standout_render::template::TemplateEngine,
output_mode: crate::OutputMode,
) -> Result<DispatchOutput, String> {
match result {
Ok(output) => match output {
HandlerOutput::Render(data) => {
let mut json_data = serde_json::to_value(&data)
.map_err(|e| format!("Failed to serialize handler result: {}", e))?;
if let Some(hooks) = hooks {
json_data = hooks
.run_post_dispatch(matches, ctx, json_data)
.map_err(|e| format!("Hook error: {}", e))?;
}
let render_ctx = RenderContext::new(
output_mode,
crate::cli::app::get_terminal_width(),
theme,
&json_data,
);
let render_result = standout_render::template::render_auto_with_engine_split(
template_engine,
template,
&json_data,
theme,
output_mode,
context_registry,
&render_ctx,
)
.map_err(|e| e.to_string())?;
Ok(DispatchOutput::Text {
formatted: render_result.formatted,
raw: render_result.raw,
})
}
HandlerOutput::Silent => Ok(DispatchOutput::Silent),
HandlerOutput::Binary { data, filename } => Ok(DispatchOutput::Binary(data, filename)),
},
Err(e) => Err(format!("Error: {}", e)),
}
}
pub type DispatchFn = Rc<
RefCell<
dyn FnMut(
&ArgMatches,
&CommandContext,
Option<&Hooks>,
crate::OutputMode,
&crate::Theme,
) -> Result<DispatchOutput, String>,
>,
>;
pub fn dispatch(
dispatch_fn: &DispatchFn,
matches: &ArgMatches,
ctx: &CommandContext,
hooks: Option<&Hooks>,
output_mode: crate::OutputMode,
theme: &crate::Theme,
) -> Result<DispatchOutput, String> {
(dispatch_fn.borrow_mut())(matches, ctx, hooks, output_mode, theme)
}