From ca4516c6dcfa7de97c38ca96a6ec3d7aeb28afa7 Mon Sep 17 00:00:00 2001 From: Casper Rogild Storm Date: Wed, 25 Sep 2024 21:42:07 +0200 Subject: [PATCH 1/4] Only highlight if user nick isn't part of another word --- data/src/message.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/data/src/message.rs b/data/src/message.rs index 406940222..30d8e175f 100644 --- a/data/src/message.rs +++ b/data/src/message.rs @@ -1061,11 +1061,16 @@ fn monitored_targets_text(targets: Vec) -> Option { } pub fn reference_user(sender: NickRef, own_nick: NickRef, message: &Message) -> bool { + let contains_nick = |text: &str, nick: &str| { + text.split(|c: char| !c.is_alphanumeric()) + .any(|word| word == nick) + }; + let has_nick = match &message.content { - Content::Plain(text) => text.contains(own_nick.as_ref()), + Content::Plain(text) => contains_nick(text, own_nick.as_ref()), Content::Fragments(fragments) => fragments .iter() - .any(|f| f.as_str().contains(own_nick.as_ref())), + .any(|f| contains_nick(f.as_str(), own_nick.as_ref())), }; sender != own_nick && has_nick From 5fb64e2bddc5b973c3a96716cd0f3d20699ab790 Mon Sep 17 00:00:00 2001 From: Casper Rogild Storm Date: Fri, 27 Sep 2024 14:10:21 +0200 Subject: [PATCH 2/4] Refactored into helper function --- data/src/message.rs | 56 ++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/data/src/message.rs b/data/src/message.rs index 30d8e175f..570089216 100644 --- a/data/src/message.rs +++ b/data/src/message.rs @@ -383,30 +383,37 @@ fn parse_url_fragments(text: String) -> Vec { fragments } +/// Checks if a given `text` contains or matches a user's nickname. +fn text_reference_nickname(text: &str, nickname: NickRef) -> Option { + // TODO: Consider server case-mapping settings vs just ascii lowercase + let nick = nickname.as_ref(); + let nick_lower = nick.to_ascii_lowercase(); + let lower = text.to_ascii_lowercase(); + let trimmed = text.trim_matches(|c: char| c.is_ascii_punctuation()); + let lower_trimmed = trimmed.to_ascii_lowercase(); + + if nick == text || nick_lower == lower { + // Contains the user's nickname without trimming. + Some(false) + } else if nick == trimmed || nick_lower == lower_trimmed { + // Contains the user's nickname with trimming. + Some(true) + } else { + // Doesn't contain the user's nickname. + None + } +} + fn parse_user_and_channel_fragments(text: &str, channel_users: &[User]) -> Vec { text.chars() .group_by(|c| c.is_whitespace()) .into_iter() .flat_map(|(is_whitespace, chars)| { let text = chars.collect::(); - let trimmed = text.trim_matches(|c: char| c.is_ascii_punctuation()); - let lower = text.to_ascii_lowercase(); - let lower_trimmed = trimmed.to_ascii_lowercase(); - if !is_whitespace { if let Some((is_trimmed, user)) = channel_users.iter().find_map(|user| { - let nickname = user.nickname(); - let nick = nickname.as_ref(); - // TODO: Consider server case-mapping settings vs just ascii lowercase - let nick_lower = nick.to_ascii_lowercase(); - - if nick == text || nick_lower == lower { - Some((false, user.clone())) - } else if nick == trimmed || nick_lower == lower_trimmed { - Some((true, user.clone())) - } else { - None - } + text_reference_nickname(text.as_str(), user.nickname()) + .map(|is_trimmed| (is_trimmed, user.clone())) }) { if is_trimmed { let prefix_end = text.find(|c: char| !c.is_ascii_punctuation()); @@ -1061,23 +1068,16 @@ fn monitored_targets_text(targets: Vec) -> Option { } pub fn reference_user(sender: NickRef, own_nick: NickRef, message: &Message) -> bool { - let contains_nick = |text: &str, nick: &str| { - text.split(|c: char| !c.is_alphanumeric()) - .any(|word| word == nick) - }; - - let has_nick = match &message.content { - Content::Plain(text) => contains_nick(text, own_nick.as_ref()), + match &message.content { + Content::Plain(text) => reference_user_text(sender, own_nick, text), Content::Fragments(fragments) => fragments .iter() - .any(|f| contains_nick(f.as_str(), own_nick.as_ref())), - }; - - sender != own_nick && has_nick + .any(|f| reference_user_text(sender, own_nick, f.as_str())), + } } pub fn reference_user_text(sender: NickRef, own_nick: NickRef, text: &str) -> bool { - sender != own_nick && text.contains(own_nick.as_ref()) + sender != own_nick && text_reference_nickname(text, own_nick).is_some() } #[derive(Debug, Clone)] From c50eae678d5004a953c7c23d9f992615e2c3ca49 Mon Sep 17 00:00:00 2001 From: Casper Rogild Storm Date: Fri, 27 Sep 2024 19:00:36 +0200 Subject: [PATCH 3/4] s/reference/references/ --- data/src/client.rs | 2 +- data/src/message.rs | 14 +++++++------- src/buffer/channel.rs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/data/src/client.rs b/data/src/client.rs index 846368c96..c9bea4a23 100644 --- a/data/src/client.rs +++ b/data/src/client.rs @@ -650,7 +650,7 @@ impl Client { } // Highlight notification - if message::reference_user_text(user.nickname(), self.nickname(), text) + if message::references_user_text(user.nickname(), self.nickname(), text) && self.highlight_blackout.allow_highlights() { return Some(vec![Event::Notification( diff --git a/data/src/message.rs b/data/src/message.rs index 570089216..cfa037d60 100644 --- a/data/src/message.rs +++ b/data/src/message.rs @@ -384,7 +384,7 @@ fn parse_url_fragments(text: String) -> Vec { } /// Checks if a given `text` contains or matches a user's nickname. -fn text_reference_nickname(text: &str, nickname: NickRef) -> Option { +fn text_references_nickname(text: &str, nickname: NickRef) -> Option { // TODO: Consider server case-mapping settings vs just ascii lowercase let nick = nickname.as_ref(); let nick_lower = nick.to_ascii_lowercase(); @@ -412,7 +412,7 @@ fn parse_user_and_channel_fragments(text: &str, channel_users: &[User]) -> Vec(); if !is_whitespace { if let Some((is_trimmed, user)) = channel_users.iter().find_map(|user| { - text_reference_nickname(text.as_str(), user.nickname()) + text_references_nickname(text.as_str(), user.nickname()) .map(|is_trimmed| (is_trimmed, user.clone())) }) { if is_trimmed { @@ -1067,17 +1067,17 @@ fn monitored_targets_text(targets: Vec) -> Option { } } -pub fn reference_user(sender: NickRef, own_nick: NickRef, message: &Message) -> bool { +pub fn references_user(sender: NickRef, own_nick: NickRef, message: &Message) -> bool { match &message.content { - Content::Plain(text) => reference_user_text(sender, own_nick, text), + Content::Plain(text) => references_user_text(sender, own_nick, text), Content::Fragments(fragments) => fragments .iter() - .any(|f| reference_user_text(sender, own_nick, f.as_str())), + .any(|f| references_user_text(sender, own_nick, f.as_str())), } } -pub fn reference_user_text(sender: NickRef, own_nick: NickRef, text: &str) -> bool { - sender != own_nick && text_reference_nickname(text, own_nick).is_some() +pub fn references_user_text(sender: NickRef, own_nick: NickRef, text: &str) -> bool { + sender != own_nick && text_references_nickname(text, own_nick).is_some() } #[derive(Debug, Clone)] diff --git a/src/buffer/channel.rs b/src/buffer/channel.rs index 3f8bb4a95..b97e55e80 100644 --- a/src/buffer/channel.rs +++ b/src/buffer/channel.rs @@ -147,7 +147,7 @@ pub fn view<'a>( )) .push(container(text).style(move |theme| match our_nick { Some(nick) - if message::reference_user( + if message::references_user( user.nickname(), nick, message, From 225716d2cb93e95d5df93412b771233c097db5ef Mon Sep 17 00:00:00 2001 From: Casper Rogild Storm Date: Fri, 27 Sep 2024 19:01:17 +0200 Subject: [PATCH 4/4] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c85cb561..295815805 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Added: Fixed: - Inverted scrolling direction. +- Only highlight if user nick isn't part of another word. # 2024.12 (2024-09-17)