1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! Command dispatch and orchestration for clap-based CLIs.
//!
//! `standout-dispatch` provides command routing, handler execution, and a hook
//! system for CLI applications. It orchestrates the execution flow while remaining
//! agnostic to rendering implementation.
//!
//! # Architecture
//!
//! Dispatch is an orchestration layer that manages this execution flow:
//!
//! ```text
//! parsed CLI args
//! → pre-dispatch hook (validation, setup)
//! → logic handler (business logic → serializable data)
//! → post-dispatch hook (data transformation)
//! → render handler (view + data → string output)
//! → post-output hook (output transformation)
//! ```
//!
//! ## Design Rationale
//!
//! Dispatch deliberately does not own rendering or output format logic:
//!
//! - Logic handlers have a strict input signature (`&ArgMatches`, `&CommandContext`)
//! and return serializable data. They focus purely on business logic.
//!
//! - Render handlers are pluggable callbacks provided by the consuming framework.
//! They receive (view name, data) and return a formatted string. All rendering
//! decisions (format, theme, template engine) live in the render handler.
//!
//! This separation allows:
//! - Using dispatch without any rendering (just return data)
//! - Using dispatch with custom renderers (not just standout-render)
//! - Keeping format/theme/template logic out of the dispatch layer
//!
//! ## Render Handler Pattern
//!
//! The render handler is a closure that captures rendering context:
//!
//! ```rust,ignore
//! // Framework (e.g., standout) creates the render handler at runtime
//! // after parsing CLI args to determine format
//! let format = extract_output_mode(&matches); // --output=json
//! let theme = &config.theme;
//!
//! let render_handler = move |view: &str, data: &Value| {
//! // All format/theme knowledge lives here, not in dispatch
//! my_renderer::render(view, data, theme, format)
//! };
//!
//! dispatcher.run_with_renderer(matches, render_handler);
//! ```
//!
//! This pattern means dispatch calls `render_handler(view, data)` without knowing
//! what format, theme, or template engine is being used.
//!
//! # State Management
//!
//! [`CommandContext`] provides two mechanisms for dependency injection:
//!
//! - **`app_state`**: Immutable, app-lifetime state (database, config, API clients).
//! Configured at app build time, shared across all dispatches via `Rc<Extensions>`.
//!
//! - **`extensions`**: Mutable, per-request state. Injected by pre-dispatch hooks
//! for request-scoped data like user sessions or request IDs.
//!
//! ```rust,ignore
//! // App-level state (build time)
//! App::builder()
//! .app_state(Database::connect()?)
//! .app_state(Config::load()?)
//!
//! // In handler
//! fn handler(matches: &ArgMatches, ctx: &CommandContext) -> HandlerResult<T> {
//! let db = ctx.app_state.get_required::<Database>()?; // shared
//! let scope = ctx.extensions.get_required::<UserScope>()?; // per-request
//! // ...
//! }
//! ```
//!
//! # Features
//!
//! - Command routing: Extract command paths from clap `ArgMatches`
//! - Handler traits: [`Handler`] trait with `&mut self` for mutable state
//! - Hook system: Pre/post dispatch and post-output hooks for cross-cutting concerns
//! - State injection: App-level state via `app_state`, per-request state via `extensions`
//! - Render abstraction: Pluggable render handlers via [`RenderFn`]
//!
//! # Usage
//!
//! ## Standalone (no rendering framework)
//!
//! ```rust,ignore
//! use standout_dispatch::{Handler, Output, from_fn};
//!
//! // Simple render handler that just serializes to JSON
//! let render = from_fn(|data, _| Ok(serde_json::to_string_pretty(data)?));
//!
//! Dispatcher::builder()
//! .command("list", list_handler, render)
//! .build()?
//! .run(cmd, args);
//! ```
//!
//! ## With standout framework
//!
//! The `standout` crate provides full integration with templates and themes:
//!
//! ```rust,ignore
//! use standout::{App, embed_templates};
//!
//! App::builder()
//! .templates(embed_templates!("src/templates"))
//! .command("list", list_handler, "list") // template name
//! .build()?
//! .run(cmd, args);
//! ```
//!
//! In this case, `standout` creates the render handler internally, injecting
//! the template registry, theme, and output format from CLI args.
// Core modules
// Re-export command routing utilities
pub use ;
// Re-export handler types
pub use ;
// Re-export hook types
pub use ;
// Re-export render abstraction
pub use ;