From 5bca2eb80af274b0df351614adbbd7a66181b757 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Wed, 24 Sep 2025 16:56:41 +0100 Subject: [PATCH 01/13] Fix doc comment --- src/settings.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/settings.rs b/src/settings.rs index 1df46a849..a155fa99f 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -44,10 +44,6 @@ impl Settings { /// /// If the file is not present, default values for settings will be used /// - /// # Arguments - /// - /// * `model_dir` - Folder containing model configuration files - /// /// # Returns /// /// The program settings as a `Settings` struct or an error if the file is invalid From 3828d7e47c7d94c36a443cf4570008051ff5ef63 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Fri, 26 Sep 2025 12:33:30 +0100 Subject: [PATCH 02/13] Make a `settings` subcommand and add `dump-default` to it --- src/cli.rs | 26 +++++++++++++------------- src/cli/settings.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 src/cli/settings.rs diff --git a/src/cli.rs b/src/cli.rs index 4676db93e..366f0ff91 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -11,6 +11,9 @@ use std::path::{Path, PathBuf}; pub mod example; use example::ExampleSubcommands; +pub mod settings; +use settings::SettingsSubcommands; + /// The command line interface for the simulation. #[derive(Parser)] #[command(version, about)] @@ -59,21 +62,23 @@ enum Commands { /// The path to the model directory. model_dir: PathBuf, }, - /// Print default settings file. - DumpDefaultSettings, + /// Manage settings file. + Settings { + /// The subcommands for managing the settings file. + #[command(subcommand)] + subcommand: SettingsSubcommands, + }, } impl Commands { /// Execute the supplied CLI command fn execute(self) -> Result<()> { match self { - Self::Run { model_dir, opts } => handle_run_command(&model_dir, &opts, None)?, - Self::Example { subcommand } => subcommand.execute()?, - Self::Validate { model_dir } => handle_validate_command(&model_dir, None)?, - Self::DumpDefaultSettings => handle_dump_default_settings(), + Self::Run { model_dir, opts } => handle_run_command(&model_dir, &opts, None), + Self::Example { subcommand } => subcommand.execute(), + Self::Validate { model_dir } => handle_validate_command(&model_dir, None), + Self::Settings { subcommand } => subcommand.execute(), } - - Ok(()) } } @@ -173,8 +178,3 @@ pub fn handle_validate_command(model_path: &Path, settings: Option) -> Ok(()) } - -/// Handle the `dump-default-settings` command -fn handle_dump_default_settings() { - print!("{}", Settings::default_file_contents()); -} diff --git a/src/cli/settings.rs b/src/cli/settings.rs new file mode 100644 index 000000000..9545ff8ec --- /dev/null +++ b/src/cli/settings.rs @@ -0,0 +1,27 @@ +//! Code related to CLI interface for managing the settings file +use crate::settings::Settings; +use anyhow::Result; +use clap::Subcommand; + +/// Subcommands for settings +#[derive(Subcommand)] +pub enum SettingsSubcommands { + /// Write the contents of a placeholder `settings.toml` to the console + DumpDefault, +} + +impl SettingsSubcommands { + /// Execute the supplied settings subcommand + pub fn execute(self) -> Result<()> { + match self { + Self::DumpDefault => handle_dump_default_command(), + } + + Ok(()) + } +} + +/// Handle the `dump-default` command +fn handle_dump_default_command() { + print!("{}", Settings::default_file_contents()); +} From 2615451aaacddfb2f2b2d3b58ba6ff5ad98f17e1 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Fri, 26 Sep 2025 12:34:20 +0100 Subject: [PATCH 03/13] Add `dirs` to dependencies --- Cargo.lock | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 1 + 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db40d7ae3..7e1664113 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -363,6 +363,27 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.0", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -475,6 +496,17 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.3.3" @@ -484,7 +516,7 @@ dependencies = [ "cfg-if", "libc", "r-efi", - "wasi", + "wasi 0.14.4+wasi-0.2.4", ] [[package]] @@ -761,7 +793,7 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom", + "getrandom 0.3.3", "libc", ] @@ -809,6 +841,16 @@ dependencies = [ "windows-targets 0.53.3", ] +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "libz-sys" version = "1.1.22" @@ -884,6 +926,7 @@ dependencies = [ "csv", "current_dir", "derive_more", + "dirs", "documented", "fern", "float-cmp", @@ -962,6 +1005,12 @@ dependencies = [ "syn", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "os_info" version = "3.12.0" @@ -1130,6 +1179,17 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.11.2" @@ -1377,7 +1437,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84fa4d11fadde498443cca10fd3ac23c951f0dc59e080e9f4b93d4df4e4eea53" dependencies = [ "fastrand", - "getrandom", + "getrandom 0.3.3", "once_cell", "rustix", "windows-sys 0.61.0", @@ -1553,7 +1613,7 @@ version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom", + "getrandom 0.3.3", ] [[package]] @@ -1562,6 +1622,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + [[package]] name = "wasi" version = "0.14.4+wasi-0.2.4" diff --git a/Cargo.toml b/Cargo.toml index 81d3d245c..c600de6d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ derive_more = {version = "2.0", features = ["add", "display"]} petgraph = "0.8.2" strum = {version = "0.27.2", features = ["derive"]} documented = "0.9.2" +dirs = "6.0.0" [dev-dependencies] current_dir = "0.1.2" From 21693982ab01e840453802eed472a128b3ba4c79 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Wed, 24 Sep 2025 17:00:00 +0100 Subject: [PATCH 04/13] By default, load settings file from user's config dir Also add a `settings path` command so the user can find where this is. --- src/cli/settings.rs | 10 +++++++++- src/lib.rs | 16 ++++++++++++++++ src/settings.rs | 37 +++++++++++++++++++++++++------------ 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/cli/settings.rs b/src/cli/settings.rs index 9545ff8ec..23b6e7367 100644 --- a/src/cli/settings.rs +++ b/src/cli/settings.rs @@ -1,11 +1,13 @@ //! Code related to CLI interface for managing the settings file -use crate::settings::Settings; +use crate::settings::{Settings, get_settings_file_path}; use anyhow::Result; use clap::Subcommand; /// Subcommands for settings #[derive(Subcommand)] pub enum SettingsSubcommands { + /// Get the path to where the settings file is read from + Path, /// Write the contents of a placeholder `settings.toml` to the console DumpDefault, } @@ -14,6 +16,7 @@ impl SettingsSubcommands { /// Execute the supplied settings subcommand pub fn execute(self) -> Result<()> { match self { + Self::Path => handle_path_command(), Self::DumpDefault => handle_dump_default_command(), } @@ -21,6 +24,11 @@ impl SettingsSubcommands { } } +/// Handle the `path` command +fn handle_path_command() { + println!("{}", get_settings_file_path().display()); +} + /// Handle the `dump-default` command fn handle_dump_default_command() { print!("{}", Settings::default_file_contents()); diff --git a/src/lib.rs b/src/lib.rs index 0b42d1a88..4c432935f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,9 @@ //! Common functionality for MUSE 2.0. #![warn(missing_docs)] + +use dirs::config_dir; +use std::path::PathBuf; + pub mod agent; pub mod asset; pub mod cli; @@ -21,3 +25,15 @@ pub mod year; #[cfg(test)] mod fixture; + +/// Get config dir for program. +/// +/// In the unlikely event this path cannot be retrieved, the CWD will be returned. +pub fn get_muse2_config_dir() -> PathBuf { + let Some(mut config_dir) = config_dir() else { + return PathBuf::default(); + }; + + config_dir.push("muse2"); + config_dir +} diff --git a/src/settings.rs b/src/settings.rs index a155fa99f..d54a584d3 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,11 +1,12 @@ //! Code for loading program settings. +use crate::get_muse2_config_dir; use crate::input::read_toml; use crate::log::DEFAULT_LOG_LEVEL; use anyhow::Result; use documented::DocumentedFields; use serde::{Deserialize, Serialize}; use std::fmt::Write; -use std::path::Path; +use std::path::{Path, PathBuf}; const SETTINGS_FILE_NAME: &str = "settings.toml"; @@ -14,6 +15,14 @@ const DEFAULT_SETTINGS_FILE_HEADER: &str = "# This file contains the program set # \thttps://energysystemsmodellinglab.github.io/MUSE_2.0/file_formats/program_settings.html "; +/// Get the path to where the settings file will be read from +pub fn get_settings_file_path() -> PathBuf { + let mut path = get_muse2_config_dir(); + path.push(SETTINGS_FILE_NAME); + + path +} + /// Program settings from config file /// /// NOTE: If you add or change a field in this struct, you must also update the schema in @@ -48,7 +57,11 @@ impl Settings { /// /// The program settings as a `Settings` struct or an error if the file is invalid pub fn load() -> Result { - let file_path = Path::new(SETTINGS_FILE_NAME); + Self::load_from_path(&get_settings_file_path()) + } + + /// Read from the specified path, returning + fn load_from_path(file_path: &Path) -> Result { if !file_path.is_file() { return Ok(Settings::default()); } @@ -88,32 +101,32 @@ impl Settings { #[cfg(test)] mod tests { use super::*; - use current_dir::Cwd; use std::fs::File; use std::io::Write; use tempfile::tempdir; #[test] - fn test_settings_from_path_no_file() { + fn test_settings_load_from_path_no_file() { let dir = tempdir().unwrap(); - let mut cwd = Cwd::mutex().lock().unwrap(); - cwd.set(dir.path()).unwrap(); - assert_eq!(Settings::load().unwrap(), Settings::default()); + let file_path = dir.path().join(SETTINGS_FILE_NAME); // NB: doesn't exist + assert_eq!( + Settings::load_from_path(&file_path).unwrap(), + Settings::default() + ); } #[test] - fn test_settings_from_path() { + fn test_settings_load_from_path() { let dir = tempdir().unwrap(); - let mut cwd = Cwd::mutex().lock().unwrap(); - cwd.set(dir.path()).unwrap(); + let file_path = dir.path().join(SETTINGS_FILE_NAME); { - let mut file = File::create(Path::new(SETTINGS_FILE_NAME)).unwrap(); + let mut file = File::create(&file_path).unwrap(); writeln!(file, "log_level = \"warn\"").unwrap(); } assert_eq!( - Settings::load().unwrap(), + Settings::load_from_path(&file_path).unwrap(), Settings { log_level: "warn".to_string(), debug_model: false, From f2e5be5acfd70568aa3266b0842cab27c913651b Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Fri, 26 Sep 2025 12:40:06 +0100 Subject: [PATCH 05/13] Add `edit` to dependencies --- Cargo.lock | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 7e1664113..413eebdad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -421,6 +421,16 @@ dependencies = [ "syn", ] +[[package]] +name = "edit" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f364860e764787163c8c8f58231003839be31276e821e2ad2092ddf496b1aa09" +dependencies = [ + "tempfile", + "which", +] + [[package]] name = "either" version = "1.15.0" @@ -581,6 +591,15 @@ dependencies = [ "cmake", ] +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "human-panic" version = "2.0.3" @@ -863,6 +882,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + [[package]] name = "linux-raw-sys" version = "0.9.4" @@ -928,6 +953,7 @@ dependencies = [ "derive_more", "dirs", "documented", + "edit", "fern", "float-cmp", "highs", @@ -1273,6 +1299,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + [[package]] name = "rustix" version = "1.1.1" @@ -1439,7 +1478,7 @@ dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", - "rustix", + "rustix 1.1.1", "windows-sys 0.61.0", ] @@ -1696,6 +1735,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index c600de6d7..9ad54fbaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ petgraph = "0.8.2" strum = {version = "0.27.2", features = ["derive"]} documented = "0.9.2" dirs = "6.0.0" +edit = "0.1.5" [dev-dependencies] current_dir = "0.1.2" From 029511e4129b8ab68949bec04224f0b23f449bca Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Fri, 26 Sep 2025 12:53:09 +0100 Subject: [PATCH 06/13] Add `settings edit` command --- src/cli/settings.rs | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/cli/settings.rs b/src/cli/settings.rs index 23b6e7367..657f8ffa7 100644 --- a/src/cli/settings.rs +++ b/src/cli/settings.rs @@ -1,11 +1,15 @@ //! Code related to CLI interface for managing the settings file use crate::settings::{Settings, get_settings_file_path}; -use anyhow::Result; +use anyhow::{Context, Result}; use clap::Subcommand; +use std::fs; +use std::path::Path; /// Subcommands for settings #[derive(Subcommand)] pub enum SettingsSubcommands { + /// Edit the program settings file + Edit, /// Get the path to where the settings file is read from Path, /// Write the contents of a placeholder `settings.toml` to the console @@ -16,6 +20,7 @@ impl SettingsSubcommands { /// Execute the supplied settings subcommand pub fn execute(self) -> Result<()> { match self { + Self::Edit => handle_edit_command()?, Self::Path => handle_path_command(), Self::DumpDefault => handle_dump_default_command(), } @@ -24,6 +29,37 @@ impl SettingsSubcommands { } } +/// Get the path to the settings file, creating it if it doesn't exist +fn ensure_settings_file_exists(file_path: &Path) -> Result<()> { + if file_path.is_file() { + // File already exists + return Ok(()); + } + + if let Some(dir_path) = file_path.parent() { + // Create parent directory + fs::create_dir_all(dir_path) + .with_context(|| format!("Failed to create directory: {}", dir_path.display()))?; + } + + // Create placeholder settings file + fs::write(file_path, Settings::default_file_contents())?; + + Ok(()) +} + +/// Handle the `edit` command +fn handle_edit_command() -> Result<()> { + let file_path = get_settings_file_path(); + ensure_settings_file_exists(&file_path)?; + + // Allow user to edit in text editor + println!("Opening settings file for editing: {}", file_path.display()); + edit::edit_file(&file_path)?; + + Ok(()) +} + /// Handle the `path` command fn handle_path_command() { println!("{}", get_settings_file_path().display()); From 4f843f7dae57341156105fc77ad8eb1b6e812844 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Fri, 26 Sep 2025 12:56:50 +0100 Subject: [PATCH 07/13] Add `settings delete` command --- src/cli/settings.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/cli/settings.rs b/src/cli/settings.rs index 657f8ffa7..10701774e 100644 --- a/src/cli/settings.rs +++ b/src/cli/settings.rs @@ -10,6 +10,8 @@ use std::path::Path; pub enum SettingsSubcommands { /// Edit the program settings file Edit, + /// Delete the settings file, if any + Delete, /// Get the path to where the settings file is read from Path, /// Write the contents of a placeholder `settings.toml` to the console @@ -21,6 +23,7 @@ impl SettingsSubcommands { pub fn execute(self) -> Result<()> { match self { Self::Edit => handle_edit_command()?, + Self::Delete => handle_delete_command()?, Self::Path => handle_path_command(), Self::DumpDefault => handle_dump_default_command(), } @@ -60,6 +63,20 @@ fn handle_edit_command() -> Result<()> { Ok(()) } +/// Handle the `delete` command +fn handle_delete_command() -> Result<()> { + let file_path = get_settings_file_path(); + if file_path.exists() { + fs::remove_file(&file_path) + .with_context(|| format!("Error deleting file: {}", file_path.display()))?; + println!("Deleted settings file: {}", file_path.display()); + } else { + eprintln!("No settings file to delete"); + } + + Ok(()) +} + /// Handle the `path` command fn handle_path_command() { println!("{}", get_settings_file_path().display()); From 8296767915c3a5b4c274d76ea6c27312fd6ac520 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Fri, 26 Sep 2025 13:31:23 +0100 Subject: [PATCH 08/13] Add info about changing settings to docs --- docs/user_guide.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/user_guide.md b/docs/user_guide.md index 00ca1fb63..af05d88d2 100644 --- a/docs/user_guide.md +++ b/docs/user_guide.md @@ -5,10 +5,22 @@ Once you have installed MUSE 2.0, you should be able to run it via the `muse2` command-line program. For details of the command-line interface, [see here](./command_line_help.md). -You can also configure the behaviour of MUSE 2.0 by creating a `settings.toml` file. For more -information, see [the documentation for this file][settings.toml-docs]. +## Modifying the program settings -[settings.toml-docs]: https://energysystemsmodellinglab.github.io/MUSE_2.0/file_formats/program_settings.html +You can configure the behaviour of MUSE 2.0 with the `settings.toml` file. To edit this file, run: + +```sh +muse2 settings edit +``` + +There are also some more commands for working with the settings file; for details, run: `muse2 +settings help`. + +For information about the available settings, see [the documentation for the `settings.toml` +file][settings.toml-docs]. + +[settings.toml-docs]: +https://energysystemsmodellinglab.github.io/MUSE_2.0/file_formats/program_settings.html ## Setting the log level From 402d507362486b981087f5cf6ea1a92793c2e795 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Tue, 30 Sep 2025 09:07:31 +0100 Subject: [PATCH 09/13] user_guide.md: the => a MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Diego Alonso Álvarez <6095790+dalonsoa@users.noreply.github.com> --- docs/user_guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user_guide.md b/docs/user_guide.md index af05d88d2..cc1ca296d 100644 --- a/docs/user_guide.md +++ b/docs/user_guide.md @@ -7,7 +7,7 @@ For details of the command-line interface, [see here](./command_line_help.md). ## Modifying the program settings -You can configure the behaviour of MUSE 2.0 with the `settings.toml` file. To edit this file, run: +You can configure the behaviour of MUSE 2.0 with a `settings.toml` file. To edit this file, run: ```sh muse2 settings edit From 9c4d340036e778eec0c4038d4f67f82110af623c Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Tue, 30 Sep 2025 09:15:09 +0100 Subject: [PATCH 10/13] Rename `settings dump-default` command to `settings show-default` --- src/cli/settings.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cli/settings.rs b/src/cli/settings.rs index 10701774e..909fdeb1a 100644 --- a/src/cli/settings.rs +++ b/src/cli/settings.rs @@ -14,8 +14,8 @@ pub enum SettingsSubcommands { Delete, /// Get the path to where the settings file is read from Path, - /// Write the contents of a placeholder `settings.toml` to the console - DumpDefault, + /// Show the default settings for `settings.toml` + ShowDefault, } impl SettingsSubcommands { @@ -25,7 +25,7 @@ impl SettingsSubcommands { Self::Edit => handle_edit_command()?, Self::Delete => handle_delete_command()?, Self::Path => handle_path_command(), - Self::DumpDefault => handle_dump_default_command(), + Self::ShowDefault => handle_show_default_command(), } Ok(()) @@ -82,7 +82,7 @@ fn handle_path_command() { println!("{}", get_settings_file_path().display()); } -/// Handle the `dump-default` command -fn handle_dump_default_command() { +/// Handle the `show-default` command +fn handle_show_default_command() { print!("{}", Settings::default_file_contents()); } From a3ee242cde824306b3e452438e4904caf53686eb Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Tue, 30 Sep 2025 09:37:18 +0100 Subject: [PATCH 11/13] Add `settings show` command --- src/cli/settings.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/cli/settings.rs b/src/cli/settings.rs index 909fdeb1a..791ddfc3e 100644 --- a/src/cli/settings.rs +++ b/src/cli/settings.rs @@ -1,8 +1,9 @@ //! Code related to CLI interface for managing the settings file use crate::settings::{Settings, get_settings_file_path}; -use anyhow::{Context, Result}; +use anyhow::{Context, Result, bail}; use clap::Subcommand; use std::fs; +use std::io::{self, Write}; use std::path::Path; /// Subcommands for settings @@ -14,6 +15,8 @@ pub enum SettingsSubcommands { Delete, /// Get the path to where the settings file is read from Path, + /// Show the contents of the `settings.toml`, if present + Show, /// Show the default settings for `settings.toml` ShowDefault, } @@ -25,6 +28,7 @@ impl SettingsSubcommands { Self::Edit => handle_edit_command()?, Self::Delete => handle_delete_command()?, Self::Path => handle_path_command(), + Self::Show => handle_show_command()?, Self::ShowDefault => handle_show_default_command(), } @@ -82,6 +86,25 @@ fn handle_path_command() { println!("{}", get_settings_file_path().display()); } +/// Handle the `show` command +fn handle_show_command() -> Result<()> { + let file_path = get_settings_file_path(); + + match fs::read(&file_path) { + // Write contents of file to stdout + Ok(ref contents) => io::stdout().write_all(contents)?, + Err(err) => { + if err.kind() == io::ErrorKind::NotFound { + bail!("Settings file not found at: {}", file_path.display()) + } + // Some other kind of IO error occurred; just return it + Err(err)?; + } + } + + Ok(()) +} + /// Handle the `show-default` command fn handle_show_default_command() { print!("{}", Settings::default_file_contents()); From 629459ccb705b1b7b4503fae23ebd779ee3b4add Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Tue, 30 Sep 2025 10:38:21 +0100 Subject: [PATCH 12/13] Print error if `settings path` run and file doesn't exist --- src/cli/settings.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cli/settings.rs b/src/cli/settings.rs index 791ddfc3e..3eeee62a6 100644 --- a/src/cli/settings.rs +++ b/src/cli/settings.rs @@ -83,7 +83,12 @@ fn handle_delete_command() -> Result<()> { /// Handle the `path` command fn handle_path_command() { - println!("{}", get_settings_file_path().display()); + let file_path = get_settings_file_path(); + if file_path.is_file() { + println!("{}", file_path.display()); + } else { + eprintln!("Settings file not found at: {}", file_path.display()); + } } /// Handle the `show` command From 1ffefaca4bb5e201e62e0f1c8ebf20924c4db82b Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Tue, 30 Sep 2025 10:49:05 +0100 Subject: [PATCH 13/13] Add more information to top of default settings file --- src/settings.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/settings.rs b/src/settings.rs index d54a584d3..e2ac261ed 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -10,10 +10,21 @@ use std::path::{Path, PathBuf}; const SETTINGS_FILE_NAME: &str = "settings.toml"; -const DEFAULT_SETTINGS_FILE_HEADER: &str = "# This file contains the program settings for MUSE 2.0 -# For more information, visit: +const DEFAULT_SETTINGS_FILE_HEADER: &str = concat!( + "# This file contains the program settings for MUSE 2.0. +# +# The default options for MUSE2 v", + env!("CARGO_PKG_VERSION"), + " are shown below, commented out. To change an option, uncomment it and set the value +# appropriately. +# +# To show the default options for the current version of MUSE2, run: +# \tmuse2 settings show-default +# +# For information about the possible settings, visit: # \thttps://energysystemsmodellinglab.github.io/MUSE_2.0/file_formats/program_settings.html -"; +" +); /// Get the path to where the settings file will be read from pub fn get_settings_file_path() -> PathBuf {