diff --git a/examples/custom-backend/main.rs b/examples/custom-backend/main.rs index ccf0044b3..03d138c95 100644 --- a/examples/custom-backend/main.rs +++ b/examples/custom-backend/main.rs @@ -15,10 +15,8 @@ use std::io::Read; use std::path::Path; -use clap::{ArgMatches, FromArgMatches}; use git2::Repository; use jujutsu::cli_util::{CliRunner, CommandError, CommandHelper}; -use jujutsu::commands::run_command; use jujutsu::ui::Ui; use jujutsu_lib::backend::{ Backend, BackendResult, Commit, CommitId, Conflict, ConflictId, FileId, SymlinkId, Tree, TreeId, @@ -45,14 +43,13 @@ fn create_store_factories() -> StoreFactories { store_factories } -fn run( +fn run_custom_command( ui: &mut Ui, - command_helper: &CommandHelper, - matches: &ArgMatches, + _command_helper: &CommandHelper, + command: CustomCommands, ) -> Result<(), CommandError> { - match CustomCommands::from_arg_matches(matches) { - // Handle our custom command - Ok(CustomCommands::InitJit) => { + match command { + CustomCommands::InitJit => { let wc_path = ui.cwd(); // Initialize a workspace with the custom backend Workspace::init_with_backend(ui.settings(), wc_path, |store_path| { @@ -60,16 +57,13 @@ fn run( })?; Ok(()) } - // Handle default commands - Err(_) => run_command(ui, command_helper, matches), } } fn main() { CliRunner::init() .set_store_factories(create_store_factories()) - .add_subcommand::() - .set_dispatch_fn(run) + .add_subcommand(run_custom_command) .run_and_exit(); } diff --git a/examples/custom-command/main.rs b/examples/custom-command/main.rs index 0f21d4717..4d711acfc 100644 --- a/examples/custom-command/main.rs +++ b/examples/custom-command/main.rs @@ -12,9 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use clap::{ArgMatches, FromArgMatches}; use jujutsu::cli_util::{short_commit_description, CliRunner, CommandError, CommandHelper}; -use jujutsu::commands::run_command; use jujutsu::ui::Ui; #[derive(clap::Parser, Clone, Debug)] @@ -30,14 +28,13 @@ struct FrobnicateArgs { revision: String, } -fn run( +fn run_custom_command( ui: &mut Ui, command_helper: &CommandHelper, - matches: &ArgMatches, + command: CustomCommands, ) -> Result<(), CommandError> { - match CustomCommands::from_arg_matches(matches) { - // Handle our custom command - Ok(CustomCommands::Frobnicate(args)) => { + match command { + CustomCommands::Frobnicate(args) => { let mut workspace_command = command_helper.workspace_helper(ui)?; let commit = workspace_command.resolve_single_rev(&args.revision)?; let mut tx = workspace_command.start_transaction("Frobnicate"); @@ -54,14 +51,11 @@ fn run( )?; Ok(()) } - // Handle default commands - Err(_) => run_command(ui, command_helper, matches), } } fn main() { CliRunner::init() - .add_subcommand::() - .set_dispatch_fn(run) + .add_subcommand(run_custom_command) .run_and_exit(); } diff --git a/src/cli_util.rs b/src/cli_util.rs index 1e7201ea5..c6246998e 100644 --- a/src/cli_util.rs +++ b/src/cli_util.rs @@ -1685,14 +1685,17 @@ pub fn handle_command_result(ui: &mut Ui, result: Result<(), CommandError>) -> i /// CLI command builder and runner. #[must_use] -pub struct CliRunner { +pub struct CliRunner { tracing_subscription: TracingSubscription, app: clap::Command, store_factories: Option, - dispatch_fn: F, + dispatch_fn: CliDispatchFn, } -impl CliRunner<()> { +type CliDispatchFn = + Box Result<(), CommandError>>; + +impl CliRunner { /// Initializes CLI environment and returns a builder. This should be called /// as early as possible. pub fn init() -> Self { @@ -1702,7 +1705,7 @@ impl CliRunner<()> { tracing_subscription, app: crate::commands::default_app(), store_factories: None, - dispatch_fn: (), + dispatch_fn: Box::new(crate::commands::run_command), } } @@ -1717,37 +1720,27 @@ impl CliRunner<()> { } /// Registers new subcommands in addition to the default ones. - // TODO: maybe take dispatch_fn for the subcommands? - pub fn add_subcommand(self) -> Self + pub fn add_subcommand(self, custom_dispatch_fn: F) -> Self where C: clap::Subcommand, + F: FnOnce(&mut Ui, &CommandHelper, C) -> Result<(), CommandError> + 'static, { + let old_dispatch_fn = self.dispatch_fn; + let new_dispatch_fn = + move |ui: &mut Ui, command_helper: &CommandHelper, matches: &ArgMatches| { + match C::from_arg_matches(matches) { + Ok(command) => custom_dispatch_fn(ui, command_helper, command), + Err(_) => old_dispatch_fn(ui, command_helper, matches), + } + }; CliRunner { tracing_subscription: self.tracing_subscription, app: C::augment_subcommands(self.app), store_factories: self.store_factories, - dispatch_fn: self.dispatch_fn, + dispatch_fn: Box::new(new_dispatch_fn), } } - // TODO: use crate::commands::run_command() by default - pub fn set_dispatch_fn(self, dispatch_fn: F) -> CliRunner - where - F: FnOnce(&mut Ui, &CommandHelper, &ArgMatches) -> Result<(), CommandError>, - { - CliRunner { - tracing_subscription: self.tracing_subscription, - app: self.app, - store_factories: self.store_factories, - dispatch_fn, - } - } -} - -impl CliRunner -where - F: FnOnce(&mut Ui, &CommandHelper, &ArgMatches) -> Result<(), CommandError>, -{ pub fn run(self, ui: &mut Ui) -> Result<(), CommandError> { ui.reset(crate::config::read_config()?); let (mut command_helper, matches) = parse_args( diff --git a/src/main.rs b/src/main.rs index 2aeeb9e72..b641c0e74 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,10 +13,7 @@ // limitations under the License. use jujutsu::cli_util::CliRunner; -use jujutsu::commands::run_command; fn main() { - CliRunner::init() - .set_dispatch_fn(run_command) - .run_and_exit(); + CliRunner::init().run_and_exit(); }