changeset 52522:92c6c8ab6f94

rhg: simplify the subcommands macro Reduce the scope of the macro to only generate individual `SubCommand` values. This way, it will be easy to tweak the behavior of `add_subcommand_args` and `subcommand_run_fn` without having to understand the details of the macro. It also lets us easy add commands that don't fit the idiom, for example the "admin::" commands or "script::" commands.
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Fri, 13 Dec 2024 15:43:50 +0000
parents b52f2b365eff
children 021c1b1671e5
files rust/rhg/src/main.rs
diffstat 1 files changed, 39 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/rust/rhg/src/main.rs	Mon Dec 16 03:04:44 2024 -0500
+++ b/rust/rhg/src/main.rs	Fri Dec 13 15:43:50 2024 +0000
@@ -536,39 +536,51 @@
     pub mod status;
 }
 
-macro_rules! subcommands {
-    ($( $command: ident )+) => {
-
-        fn add_subcommand_args(app: clap::Command) -> clap::Command {
-            app
-            $(
-                .subcommand(commands::$command::args())
-            )+
-        }
+pub type RunFn = fn(&CliInvocation) -> Result<(), CommandError>;
 
-        pub type RunFn = fn(&CliInvocation) -> Result<(), CommandError>;
+struct SubCommand {
+    run: RunFn,
+    args: clap::Command,
+    name: String,
+}
 
-        fn subcommand_run_fn(name: &str) -> Option<RunFn> {
-            match name {
-                $(
-                    stringify!($command) => Some(commands::$command::run),
-                )+
-                _ => None,
-            }
+macro_rules! subcommand {
+    ($command: ident) => {
+        SubCommand {
+            args: commands::$command::args(),
+            run: commands::$command::run,
+            name: stringify!($command).to_string(),
         }
     };
 }
+fn subcommands() -> Vec<SubCommand> {
+    vec![
+        subcommand!(cat),
+        subcommand!(debugdata),
+        subcommand!(debugrequirements),
+        subcommand!(debugignorerhg),
+        subcommand!(debugrhgsparse),
+        subcommand!(files),
+        subcommand!(root),
+        subcommand!(config),
+        subcommand!(status),
+    ]
+}
 
-subcommands! {
-    cat
-    debugdata
-    debugrequirements
-    debugignorerhg
-    debugrhgsparse
-    files
-    root
-    config
-    status
+fn add_subcommand_args(mut app: clap::Command) -> clap::Command {
+    for s in subcommands() {
+        app = app.subcommand(s.args)
+    }
+    app
+}
+
+fn subcommand_run_fn(name: &str) -> Option<RunFn> {
+    for s in subcommands() {
+        if s.name == name {
+            return Some(s.run);
+        }
+    }
+    None
 }
 
 pub struct CliInvocation<'a> {