diff --git a/CHANGELOG.md b/CHANGELOG.md index ecbfe2eb..444b6921 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Thanks to @nate-sys and @jubalh for contributing to this release. (#403, #410) - Default config updated with better comments, color config for join/part messages. (#412) +- `/join` command errors now print usage help once instead of twice. # 2023/07/16: 0.11.0 diff --git a/crates/libtiny_tui/src/config.rs b/crates/libtiny_tui/src/config.rs index 9e5d6441..560893fc 100644 --- a/crates/libtiny_tui/src/config.rs +++ b/crates/libtiny_tui/src/config.rs @@ -92,6 +92,7 @@ where Ok(ChanName::new(name)) } +// `FromStr` implementation used when parsing channel names in commands (not in config file). impl FromStr for Chan { type Err = String; @@ -196,10 +197,11 @@ impl From<&Config> for TabConfigs { #[derive(Debug, Default, Copy, Clone, Deserialize, PartialEq, Eq)] pub struct TabConfig { - /// `true` if tab is ignoring join/part messages + /// Whether the join/part messages are ignored. #[serde(default)] pub ignore: Option, - /// Notification setting for tab + + /// Notification setting for tab. #[serde(default)] pub notify: Option, } @@ -226,28 +228,31 @@ impl TabConfig { } } +// `FromStr` implementation used when parsing channel names in commands (not in config file). impl FromStr for TabConfig { type Err = String; fn from_str(s: &str) -> Result { - let config = s - .split('-') - .filter_map(|arg| (!arg.is_empty()).then(|| arg.trim())) - .try_fold(TabConfig::default(), |mut tc, arg| match arg { - // flag - "ignore" => { - tc.ignore = Some(true); - Ok(tc) - } - arg => match arg.split_once(' ') { - // arg with parameter - Some(("notify", val)) => { - tc.notify = Some(Notifier::from_str(val)?); - Ok(tc) + let mut config = TabConfig::default(); + let mut words = s.trim().split(' ').map(str::trim); + + while let Some(word) = words.next() { + // `"".split(' ')` yields one empty string. + if word.is_empty() { + continue; + } + match word { + "-ignore" => config.ignore = Some(true), + "-notify" => match words.next() { + Some(notify_setting) => { + config.notify = Some(Notifier::from_str(notify_setting)?) } - _ => Err(format!("Unexpected argument: {:?}", arg)), + None => return Err("-notify parameter missing".to_string()), }, - })?; + other => return Err(format!("Unexpected channel parameter: {:?}", other)), + } + } + Ok(config) } } diff --git a/crates/libtiny_tui/src/key_map.rs b/crates/libtiny_tui/src/key_map.rs index f5a83e5e..cbca5384 100644 --- a/crates/libtiny_tui/src/key_map.rs +++ b/crates/libtiny_tui/src/key_map.rs @@ -103,7 +103,7 @@ impl KeyMap { } pub(crate) fn load(&mut self, key_map: &KeyMap) { - self.0.extend(key_map.0.clone().into_iter()) + self.0.extend(key_map.0.clone()) } } diff --git a/crates/libtiny_tui/src/notifier.rs b/crates/libtiny_tui/src/notifier.rs index 107ab4a7..b5e359da 100644 --- a/crates/libtiny_tui/src/notifier.rs +++ b/crates/libtiny_tui/src/notifier.rs @@ -14,8 +14,10 @@ use serde::Deserialize; pub enum Notifier { /// Notifications are disabled. Off, + /// Generate notifications only for mentions. Mentions, + /// Generate notifications for all messages. Messages, } diff --git a/crates/libtiny_tui/src/tests/config.rs b/crates/libtiny_tui/src/tests/config.rs index b9632892..8ebcc39b 100644 --- a/crates/libtiny_tui/src/tests/config.rs +++ b/crates/libtiny_tui/src/tests/config.rs @@ -3,6 +3,8 @@ use libtiny_common::{ChanName, ChanNameRef}; use crate::config::*; use crate::notifier::Notifier; +use std::str::FromStr; + #[test] fn parsing_tab_configs() { let config_str = r##" @@ -98,3 +100,42 @@ fn parsing_tab_configs() { }) ); } + +#[test] +fn tab_config_command() { + assert_eq!( + TabConfig::from_str("").unwrap(), + TabConfig { + ignore: None, + notify: None + } + ); + assert_eq!( + TabConfig::from_str("-ignore").unwrap(), + TabConfig { + ignore: Some(true), + notify: None + } + ); + assert_eq!( + TabConfig::from_str("-notify off").unwrap(), + TabConfig { + ignore: None, + notify: Some(Notifier::Off) + } + ); + assert_eq!( + TabConfig::from_str("-notify off -ignore").unwrap(), + TabConfig { + ignore: Some(true), + notify: Some(Notifier::Off) + } + ); + assert_eq!( + TabConfig::from_str("-ignore -notify off").unwrap(), + TabConfig { + ignore: Some(true), + notify: Some(Notifier::Off) + } + ); +} diff --git a/crates/tiny/src/cmd.rs b/crates/tiny/src/cmd.rs index 62c51d31..b0011278 100644 --- a/crates/tiny/src/cmd.rs +++ b/crates/tiny/src/cmd.rs @@ -321,10 +321,7 @@ fn join(args: CmdArgs) { .filter_map(|c| match Chan::from_str(c) { Ok(c) => Some(c), Err(err) => { - ui.add_client_err_msg( - &format!("{}, Usage: {}", err, JOIN_CMD.usage), - &MsgTarget::CurrentTab, - ); + ui.add_client_err_msg(&err, &MsgTarget::CurrentTab); None } }) @@ -333,12 +330,12 @@ fn join(args: CmdArgs) { let chans = if chans.is_empty() { match ui.current_tab() { None => return, - // rejoin current tab's channel Some(MsgSource::Chan { serv, chan }) => { + // Rejoin current tab's channel. let config = ui.get_tab_config(&serv, Some(chan.as_ref())); vec![Chan::WithConfig { name: chan, config }] } - Some(_) => { + Some(MsgSource::Serv { .. } | MsgSource::User { .. }) => { return ui.add_client_err_msg( &format!("Usage: {}", JOIN_CMD.usage), &MsgTarget::CurrentTab,