diff --git a/Cargo.lock b/Cargo.lock index b6d93ec..6279e0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2004,6 +2004,7 @@ dependencies = [ "temp-dir", "thiserror", "tokio", + "toml", "tracing", "tracing-appender", "tracing-subscriber", @@ -2527,7 +2528,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93779aa78d39c2fe34746287b10a866192cf8af1b81767fff76bd64099acc0f5" dependencies = [ - "proc-macro-crate 2.0.2", + "proc-macro-crate 2.0.0", "proc-macro-error", "proc-macro2", "quote", @@ -3416,11 +3417,10 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "toml_datetime", "toml_edit 0.20.2", ] @@ -3925,7 +3925,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0280534a4b3e34416f883285fac4f9c408cd0b737890ae66f3e7a7056d14be80" dependencies = [ "once_cell", - "proc-macro-crate 2.0.2", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "ruma-identifiers-validation", @@ -4743,21 +4743,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.2" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.22.9", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] @@ -4770,7 +4770,7 @@ checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap 2.0.2", "toml_datetime", - "winnow", + "winnow 0.5.15", ] [[package]] @@ -4778,12 +4778,23 @@ name = "toml_edit" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.2", + "toml_datetime", + "winnow 0.5.15", +] + +[[package]] +name = "toml_edit" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ "indexmap 2.0.2", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.5", ] [[package]] @@ -5530,6 +5541,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/Cargo.toml b/Cargo.toml index da68a57..5efbfed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ serde_json = "^1.0" sled = "0.34.7" temp-dir = "0.1.12" thiserror = "^1.0.37" +toml = "^0.8.12" tracing = "~0.1.36" tracing-appender = "~0.2.2" tracing-subscriber = "0.3.16" diff --git a/config.example.toml b/config.example.toml new file mode 100644 index 0000000..5e47176 --- /dev/null +++ b/config.example.toml @@ -0,0 +1,45 @@ +default_profile = "default" + +[profiles.default] +user_id = "@user:matrix.org" +url = "https://matrix.org" + +[settings] +default_room = "#iamb-users:0x.badd.cafe" +log_level = "warn" +message_shortcode_display = false +open_command = ["my-open", "--file"] +reaction_display = true +reaction_shortcode_display = false +read_receipt_display = true +read_receipt_send = true +request_timeout = 10000 +typing_notice_display = true +typing_notice_send = true +user_gutter_width = 30 +username_display = "username" + +[settings.image_preview] +protocol.type = "sixel" +size = { "width" = 66, "height" = 10 } + +[settings.sort] +rooms = ["favorite", "lowpriority", "unread", "name"] +members = ["power", "id"] + +[settings.users] +"@user:matrix.org" = { "name" = "John Doe", "color" = "magenta" } + +[layout] +style = "restore" + +[macros.insert] +"jj" = "" + +[macros."normal|visual"] +"V" = "m" + +[dirs] +cache = "/home/user/.cache/iamb/" +logs = "/home/user/.local/share/iamb/logs/" +downloads = "/home/user/Downloads/" diff --git a/docs/example_config.json b/docs/example_config.json deleted file mode 100644 index 2ba9e90..0000000 --- a/docs/example_config.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "default_profile": "default", - "profiles": { - "default": { - "user_id": "@user:matrix.org", - "url": "https://matrix.org", - "settings": {}, - "dirs": {} - } - }, - "settings": { - "log_level": "warn", - "message_shortcode_display": false, - "reaction_display": true, - "reaction_shortcode_display": false, - "read_receipt_send": true, - "read_receipt_display": true, - "request_timeout": 10000, - "typing_notice_send": true, - "typing_notice_display": true, - "users": { - "@user:matrix.org": { - "name": "John Doe", - "color": "magenta" - } - }, - "default_room": "#iamb-users:0x.badd.cafe", - "image_preview": { - "protocol": { - "type": "sixel" - }, - "size": { - "width": 66, - "height": 10 - } - } - }, - "layout": { - "style": "restore" - }, - "macros": { - "n|v": { - "V": "m" - }, - "i": { - "jj": "" - } - }, - "dirs": { - "cache": "/home/user/.cache/iamb/", - "logs": "/home/user/.local/share/iamb/logs/", - "downloads": "/home/user/Downloads/" - } -} diff --git a/src/config.rs b/src/config.rs index ab40850..5603ce0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -141,7 +141,10 @@ pub enum ConfigError { IO(#[from] std::io::Error), #[error("Error loading configuration file: {0}")] - Invalid(#[from] serde_json::Error), + Invalid(#[from] toml::de::Error), + + #[error("Error loading JSON configuration file: {0}")] + InvalidJSON(#[from] serde_json::Error), } #[derive(Clone, Debug, Eq, Hash, PartialEq)] @@ -717,18 +720,16 @@ pub struct IambConfig { } impl IambConfig { - pub fn load(config_json: &Path) -> Result { - if !config_json.is_file() { - usage!( - "Please create a configuration file at {}\n\n\ - For more information try '--help'", - config_json.display(), - ); - } + pub fn load_toml(path: &Path) -> Result { + let s = std::fs::read_to_string(path)?; + let config = toml::from_str(&s)?; - let file = File::open(config_json)?; - let reader = BufReader::new(file); - let config = serde_json::from_reader(reader)?; + Ok(config) + } + + pub fn load_json(path: &Path) -> Result { + let s = std::fs::read_to_string(path)?; + let config = serde_json::from_str(&s)?; Ok(config) } @@ -758,9 +759,22 @@ impl ApplicationSettings { For more information try '--help'" ); }); + config_dir.push("iamb"); - let mut config_json = config_dir.clone(); - config_json.push("config.json"); + let config_json = config_dir.join("config.json"); + let config_toml = config_dir.join("config.toml"); + + let config = if config_toml.is_file() { + IambConfig::load_toml(config_toml.as_path())? + } else if config_json.is_file() { + IambConfig::load_json(config_json.as_path())? + } else { + usage!( + "Please create a configuration file at {}\n\n\ + For more information try '--help'", + config_toml.display(), + ); + }; let IambConfig { mut profiles, @@ -769,7 +783,7 @@ impl ApplicationSettings { settings: global, layout, macros, - } = IambConfig::load(config_json.as_path())?; + } = config; validate_profile_names(&profiles); @@ -786,9 +800,8 @@ impl ApplicationSettings { } else { usage!( "No profile specified. \ - Please use -P or add \"default_profile\" to {}.\n\n\ + Please use -P or add \"default_profile\" to your configuration.\n\n\ For more information try '--help'", - config_json.display() ); }; @@ -1158,9 +1171,9 @@ mod tests { } #[test] - fn test_load_example_config_json() { - let path = PathBuf::from("docs/example_config.json"); - let config = IambConfig::load(&path).expect("can load example_config.json"); + fn test_load_example_config_toml() { + let path = PathBuf::from("config.example.toml"); + let config = IambConfig::load_toml(&path).expect("can load example_config.toml"); let IambConfig { profiles, @@ -1169,7 +1182,7 @@ mod tests { dirs, layout, macros, - } = config; + } = &config; // There should be an example object for each top-level field. assert!(!profiles.is_empty());