diff --git a/crates/libtiny_tui/src/config.rs b/crates/libtiny_tui/src/config.rs index c7c26fa6..76d22dc4 100644 --- a/crates/libtiny_tui/src/config.rs +++ b/crates/libtiny_tui/src/config.rs @@ -31,6 +31,9 @@ pub(crate) struct Config { #[serde(default)] pub(crate) key_map: Option, + + #[serde(default)] + pub(crate) completion_char: Option, } #[derive(Debug, Deserialize, PartialEq, Eq)] diff --git a/crates/libtiny_tui/src/input_area/mod.rs b/crates/libtiny_tui/src/input_area/mod.rs index de8887d5..a33ac8aa 100644 --- a/crates/libtiny_tui/src/input_area/mod.rs +++ b/crates/libtiny_tui/src/input_area/mod.rs @@ -52,6 +52,9 @@ pub(crate) struct InputArea { /// Current nickname. Not available on initialization (e.g. before registration with the /// server). Set with `set_nick`. nick: Option, + + // Autocompletion character to be used when at the start of the line. Set with `set_completion_char`. + completion_char: Option, } enum Mode { @@ -120,6 +123,7 @@ impl InputArea { history: Vec::with_capacity(HIST_SIZE), mode: Mode::Edit, nick: None, + completion_char: None, } } @@ -127,6 +131,11 @@ impl InputArea { self.nick = Some(Nickname::new(value, color)) } + /// Set completion char. + pub(crate) fn set_completion_char(&mut self, completion_char: Option) { + self.completion_char = completion_char; + } + pub(crate) fn get_nick(&self) -> Option { self.nick.as_ref().map(|nick| nick.value.clone()) } @@ -746,7 +755,17 @@ impl InputArea { } }; - dict.drop_pfx(&mut word.iter().cloned()) + let mut completions = dict.drop_pfx(&mut word.iter().cloned()); + + if let Some(completion_suffix) = &self.completion_char { + if cursor_left == 0 { + for completion in completions.iter_mut() { + completion.push_str(&format!("{} ", completion_suffix)); + } + } + } + + completions }; if !completions.is_empty() { diff --git a/crates/libtiny_tui/src/messaging.rs b/crates/libtiny_tui/src/messaging.rs index 159c6e45..55e814ce 100644 --- a/crates/libtiny_tui/src/messaging.rs +++ b/crates/libtiny_tui/src/messaging.rs @@ -218,6 +218,10 @@ impl MessagingUI { self.input_field.set(str) } + pub(crate) fn set_completion_char(&mut self, completion_char: Option) { + self.input_field.set_completion_char(completion_char); + } + /// Set cursor location in the input field. pub(crate) fn set_cursor(&mut self, cursor: i32) { self.input_field.set_cursor(cursor); diff --git a/crates/libtiny_tui/src/tui.rs b/crates/libtiny_tui/src/tui.rs index ba950d30..27d8e482 100644 --- a/crates/libtiny_tui/src/tui.rs +++ b/crates/libtiny_tui/src/tui.rs @@ -108,6 +108,9 @@ pub struct TUI { /// TabConfig settings loaded from config file tab_configs: TabConfigs, + + // Autocompletion character to be used when at the start of the line. + completion_char: Option, } pub(crate) enum CmdResult { @@ -175,6 +178,7 @@ impl TUI { key_map: KeyMap::default(), config_path, tab_configs: TabConfigs::default(), + completion_char: None, }; // Init "mentions" tab. This needs to happen right after creating the TUI to be able to @@ -365,9 +369,11 @@ impl TUI { max_nick_length, key_map, layout, + completion_char, .. } = config; self.set_colors(colors); + self.set_completion_char(completion_char); self.scrollback = scrollback.max(1); self.key_map.load(&key_map.unwrap_or_default()); if let Some(layout) = layout { @@ -394,6 +400,14 @@ impl TUI { self.colors = colors; } + fn set_completion_char(&mut self, completion_char: Option) { + self.completion_char = completion_char; + for tab in &mut self.tabs { + tab.widget + .set_completion_char((&self.completion_char).clone()); + } + } + fn new_tab(&mut self, idx: usize, src: MsgSource, alias: Option) { let visible_name = alias.unwrap_or_else(|| match &src { MsgSource::Serv { serv } => serv.to_owned(), diff --git a/crates/tiny/config.yml b/crates/tiny/config.yml index b5458151..1e0b9e2b 100644 --- a/crates/tiny/config.yml +++ b/crates/tiny/config.yml @@ -66,6 +66,10 @@ defaults: # Location for chat logs. log_dir: "{}" +# Optional character(s) that will be appended at the end of a completed +# nick, if at the beginning of the line. Uncomment to enable. +# completion_char: ":" + # Limits the maximum number of messages stored in each tab. Default is # unlimited. # scrollback: 512