chiark / gitweb /
otter: Introduce RawArgParserContext
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 6 Jun 2021 22:03:22 +0000 (23:03 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 6 Jun 2021 22:03:22 +0000 (23:03 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
cli/clisupport.rs
cli/otter.rs

index 022351a40b49fc0976416a9e2089f04eea877406..fc8d16294878a45129e830d00a3fa71f9eeab854 100644 (file)
@@ -127,39 +127,52 @@ pub type ExtraMessage<'exh> =
 pub type ApCompleter<'apc,T,U> =
   &'apc dyn Fn(T) -> Result<U, ArgumentParseError>;
 
-pub fn run_argparse<T>(parsed: &mut T, apmaker: ApMaker<T>,
-                       args: Vec<String>,
-                       extra_help: Option<ExtraMessage>,
-                       extra_error: Option<ExtraMessage>)
-                       -> String /* us */{
-  let ap = apmaker(parsed);
-  let us = args.get(0).expect("argv[0] must be provided!").clone();
-
-  let mut stdout = CookedStdout::new();
-  let mut stderr = io::stderr();
-
-  let em_call = |em: Option<ExtraMessage>, f| {
-    if let Some(em) = em { em(f).unwrap() };
-  };
+pub struct RawArgParserContext<'a> {
+  pub ap: ArgumentParser<'a>,
+  pub us: String,
+  pub stdout: CookedStdout,
+  pub stderr: io::Stderr,
+}
+
+impl<'a> RawArgParserContext<'a> {
+  pub fn new<T>(args0: &[String], parsed: &'a mut T, apmaker: ApMaker<T>)
+                -> Self
+  {
+    RawArgParserContext {
+      ap: apmaker(parsed),
+      us: args0.get(0).expect("argv[0] must be provided!").clone(),
+      stdout: CookedStdout::new(),
+      stderr: io::stderr(),
+    }
+  }
 
-  let r = ap.parse(args, &mut stdout, &mut stderr);
-  if let Err(rc) = r {
-    exit(match rc {
-      0 => {
-        em_call(extra_help, &mut stdout);
-        0
-      },
-      2 => {
-        em_call(extra_error, &mut stderr);
-        EXIT_USAGE
-      },
-      _ => panic!("unexpected error rc {} from ArgumentParser::parse", rc),
-    });
+  pub fn run(&mut self,
+             args: Vec<String>,
+             extra_help: Option<ExtraMessage>,
+             extra_error: Option<ExtraMessage>) {
+    let em_call = |em: Option<ExtraMessage>, f| {
+      if let Some(em) = em { em(f).unwrap() };
+    };
+
+    let r = self.ap.parse(args, &mut self.stdout, &mut self.stderr);
+    if let Err(rc) = r {
+      exit(match rc {
+        0 => {
+          em_call(extra_help, &mut self.stdout);
+          0
+        },
+        2 => {
+          em_call(extra_error, &mut self.stderr);
+          EXIT_USAGE
+        },
+        _ => panic!("unexpected error rc {} from ArgumentParser::parse", rc),
+      });
+    }
   }
-  mem::drop(stdout);
-  mem::drop(ap);
 
-  us
+  pub fn done(self) -> String /* us */ {
+    self.us
+  }
 }
 
 pub fn argparse_more<T,U,F>(us: String, apmaker: ApMaker<T>, f: F) -> U
@@ -176,7 +189,9 @@ pub fn parse_args<T:Default,U>(
   extra_help: Option<ExtraMessage>,
 ) -> U {
   let mut parsed = default();
-  let us = run_argparse(&mut parsed, apmaker, args, extra_help, None);
+  let mut rapc = RawArgParserContext::new(&args, &mut parsed, apmaker);
+  rapc.run(args, extra_help, None);
+  let us = rapc.done();
   let completed = argparse_more(us, apmaker, || completer(parsed));
   completed
 }
index b8b2a3cc3e01953459e114d858f4090db75aac68..a2b557be1306a7da3aedb9f228f79922365e9b24 100644 (file)
@@ -321,8 +321,9 @@ fn main() {
   let mut parsed: RawMainArgs = default();
   let args: Vec<String> = env::args().collect();
 
-  let us = run_argparse(&mut parsed, apmaker, args.clone(),
-                        Some(extra_help), None);
+  let mut rapc = RawArgParserContext::new(&args, &mut parsed, apmaker);
+  rapc.run(args.clone(), Some(extra_help), None);
+  let us = rapc.done();
 
   let completed = argparse_more(us, apmaker, || ap_completer(parsed));
   let (subcommand, subargs, mo) = completed;
@@ -330,7 +331,7 @@ fn main() {
   let stdout = CookedStdout::new();
   let mut subargs = subargs;
   subargs.insert(0, format!("{} {}",
-                            env::args().next().unwrap(),
+                            &args[0],
                             &subcommand));
 
   (mo.sc.call)(SubCommandCallArgs { ma: mo, out: stdout, args: subargs })