standout-dispatch
Command dispatch with strict separation of logic and presentation for CLI applications.
use ;
// Handler returns data, not strings
// Renderer is pluggable—you decide how to format
let render = from_fn;
Why standout-dispatch?
CLI commands typically mix business logic with output formatting: database queries interleaved with println!, validation tangled with ANSI codes, error handling scattered across presentation. The result is code that's hard to test, hard to change, and impossible to reuse.
standout-dispatch enforces a clean separation:
CLI args → Handler (logic) → Data → Renderer (presentation) → Output
- Handlers receive parsed arguments, return serializable data
- Renderers are pluggable callbacks you provide
- Hooks intercept execution at defined points
This isn't just architectural nicety—it unlocks:
- Testable handlers — Pure functions with explicit inputs and outputs
- Swappable renderers — JSON, templates, plain text from the same handler
- Cross-cutting concerns — Auth, logging, transformation via hooks
- Incremental adoption — Migrate one command at a time
Features
Handler Traits
Thread-safe and local variants for different use cases:
// Thread-safe handler (Send + Sync, &self)
// Local handler for mutable state (&mut self, no Send + Sync)
Pluggable Render Handlers
Dispatch doesn't know how rendering works—you provide a closure:
use from_fn;
// JSON output
let json_render = from_fn;
// Custom formatting
let custom_render = from_fn;
// Template-based (with standout-render or any engine)
let format = from_cli_args;
let template_render = from_fn;
This design means dispatch orchestrates execution without coupling to any rendering implementation.
Hook System
Intercept execution at three points:
use ;
let hooks = new
// Before handler: validation, auth
.pre_dispatch
// After handler, before render: transform data
.post_dispatch
// After render: transform output
.post_output;
Hooks chain—each receives the output of the previous.
Command Routing Utilities
Extract and navigate clap's ArgMatches:
use ;
// myapp db migrate --steps 5
let path = extract_command_path; // ["db", "migrate"]
let deep = get_deepest_matches; // ArgMatches for "migrate"
// Default command support
if !has_subcommand
Output Types
Handlers produce one of three outputs:
Quick Start
[]
= "2.1"
= { = "4", = ["derive"] }
= { = "1", = ["derive"] }
= "1"
= "1"
use ;
use ;
use Serialize;
use HashMap;
Documentation
Guides
- Introduction to Dispatch — Complete dispatch tutorial
Topics
- Handler Contract — Handler types, Output enum, testing
- Execution Model — Pipeline, hooks, command routing
- Partial Adoption — Incremental migration strategies
Reference
- API Documentation — Full API reference
Used By
This crate provides the dispatch foundation for the standout CLI framework, which combines dispatch with standout-render for a complete CLI solution. Use standout-dispatch directly when you want the separation pattern without the rendering layer.
License
MIT