Browse Source

More configuration options, remove Cli::args

David Peter 2 years ago
parent
commit
958dace99e
1 changed files with 51 additions and 41 deletions
  1. 51 41
      numbat-cli/src/main.rs

+ 51 - 41
numbat-cli/src/main.rs

@@ -55,6 +55,9 @@ struct Config {
     exchange_rate_fetching_policy: ExchangeRateFetchingPolicy,
     prompt: String,
     intro_banner: IntroBanner,
+    pretty_print: PrettyPrintMode,
+    load_prelude: bool,
+    load_user_init: bool,
 }
 
 impl Default for Config {
@@ -63,6 +66,9 @@ impl Default for Config {
             exchange_rate_fetching_policy: ExchangeRateFetchingPolicy::Prefetch,
             prompt: ">>> ".to_owned(),
             intro_banner: IntroBanner::default(),
+            pretty_print: PrettyPrintMode::Auto,
+            load_prelude: true,
+            load_user_init: true,
         }
     }
 }
@@ -75,7 +81,8 @@ pub enum ExitStatus {
 
 type ControlFlow = std::ops::ControlFlow<ExitStatus>;
 
-#[derive(Debug, Clone, Copy, PartialEq, ValueEnum)]
+#[derive(Debug, Clone, Copy, PartialEq, ValueEnum, Deserialize)]
+#[serde(rename_all = "kebab-case")]
 enum PrettyPrintMode {
     Always,
     Never,
@@ -108,8 +115,8 @@ struct Args {
     no_init: bool,
 
     /// Whether or not to pretty-print every input expression.
-    #[arg(long, value_name = "WHEN", default_value = "auto")]
-    pretty_print: PrettyPrintMode,
+    #[arg(long, value_name = "WHEN")]
+    pretty_print: Option<PrettyPrintMode>,
 
     /// What kind of intro banner to show (if any).
     #[arg(long, value_name = "MODE")]
@@ -145,15 +152,40 @@ struct NumbatHelper {
 }
 
 struct Cli {
-    args: Args,
     config: Config,
     context: Arc<Mutex<Context>>,
+    file: Option<PathBuf>,
+    expression: Option<Vec<String>>,
 }
 
 impl Cli {
-    fn new() -> Self {
+    fn new() -> Result<Self> {
         let args = Args::parse();
 
+        let user_config_path = Self::get_config_path().join("config.toml");
+
+        let mut config = if let Ok(contents) = fs::read_to_string(&user_config_path) {
+            toml::from_str(&contents).context(format!(
+                "Error while loading {}",
+                user_config_path.to_string_lossy()
+            ))?
+        } else {
+            Config::default()
+        };
+
+        config.load_prelude = !args.no_prelude;
+        config.load_user_init = !(args.no_prelude || args.no_init);
+
+        config.intro_banner = args.intro_banner.unwrap_or(config.intro_banner);
+        config.pretty_print = args.pretty_print.unwrap_or(config.pretty_print);
+
+        config.pretty_print = if args.file.is_none() && config.pretty_print == PrettyPrintMode::Auto
+        {
+            PrettyPrintMode::Always
+        } else {
+            config.pretty_print
+        };
+
         let mut fs_importer = FileSystemImporter::default();
         for path in Self::get_modules_paths() {
             fs_importer.add_path(path);
@@ -167,27 +199,16 @@ impl Cli {
         let mut context = Context::new(importer);
         context.set_debug(args.debug);
 
-        Self {
+        Ok(Self {
             context: Arc::new(Mutex::new(context)),
-            args,
-            config: Config::default(),
-        }
+            config,
+            file: args.file,
+            expression: args.expression,
+        })
     }
 
     fn run(&mut self) -> Result<()> {
-        let load_prelude = !self.args.no_prelude;
-        let load_init = !(self.args.no_prelude || self.args.no_init);
-
-        let user_config_path = Self::get_config_path().join("config.toml");
-
-        if let Ok(contents) = fs::read_to_string(&user_config_path) {
-            self.config = toml::from_str(&contents).context(format!(
-                "Error while loading {}",
-                user_config_path.to_string_lossy()
-            ))?;
-        }
-
-        if load_prelude {
+        if self.config.load_prelude {
             let result = self.parse_and_evaluate(
                 "use prelude",
                 CodeSource::Internal,
@@ -199,7 +220,7 @@ impl Cli {
             }
         }
 
-        if load_init {
+        if self.config.load_user_init {
             let user_init_path = Self::get_config_path().join("init.nbt");
 
             if let Ok(user_init_code) = fs::read_to_string(&user_init_path) {
@@ -215,7 +236,7 @@ impl Cli {
             }
         }
 
-        if load_prelude
+        if self.config.load_prelude
             && self.config.exchange_rate_fetching_policy != ExchangeRateFetchingPolicy::DontFetch
         {
             {
@@ -232,14 +253,7 @@ impl Cli {
             }
         }
 
-        let pretty_print_mode =
-            if self.args.file.is_none() && self.args.pretty_print == PrettyPrintMode::Auto {
-                PrettyPrintMode::Always
-            } else {
-                self.args.pretty_print
-            };
-
-        let code_and_source: Option<(String, CodeSource)> = if let Some(ref path) = self.args.file {
+        let code_and_source: Option<(String, CodeSource)> = if let Some(ref path) = self.file {
             Some((
                 fs::read_to_string(path).context(format!(
                     "Could not load source file '{}'",
@@ -248,8 +262,7 @@ impl Cli {
                 CodeSource::File(path.clone()),
             ))
         } else {
-            self.args
-                .expression
+            self.expression
                 .as_ref()
                 .map(|exprs| (exprs.iter().join("\n"), CodeSource::Text))
         };
@@ -259,7 +272,7 @@ impl Cli {
                 &code,
                 code_source,
                 ExecutionMode::Normal,
-                pretty_print_mode,
+                self.config.pretty_print,
             );
 
             match result {
@@ -277,7 +290,6 @@ impl Cli {
     fn repl(&mut self) -> Result<()> {
         let interactive = std::io::stdin().is_terminal();
         let history_path = self.get_history_path()?;
-        let intro_banner = self.args.intro_banner.unwrap_or(self.config.intro_banner);
 
         let mut rl = Editor::<NumbatHelper, DefaultHistory>::new()?;
         rl.set_max_history_size(1000)
@@ -298,7 +310,7 @@ impl Cli {
         rl.load_history(&history_path).ok();
 
         if interactive {
-            match intro_banner {
+            match self.config.intro_banner {
                 IntroBanner::Long => {
                     println!();
                     println!(
@@ -364,7 +376,7 @@ impl Cli {
                                     &line,
                                     CodeSource::Text,
                                     ExecutionMode::Interactive,
-                                    self.args.pretty_print,
+                                    self.config.pretty_print,
                                 );
 
                                 match result {
@@ -524,9 +536,7 @@ impl Cli {
 }
 
 fn main() {
-    let mut cli = Cli::new();
-
-    if let Err(e) = cli.run() {
+    if let Err(e) = Cli::new().and_then(|mut cli| cli.run()) {
         eprintln!("{:#}", e);
         std::process::exit(1);
     }