commit c3a6d9c

delthas  ·  2022-08-19 20:39:17 +0000 UTC
parent 464ea64
Highlight only on word boundaries

Preivously, we highlighted the user for any message that contained the
nick, even in the middle of a word.

Now, we only send a highlight if the user was mentioned in a single
word, by detecting word boundaries around the mention of the user.

For example, considering user "foo":

Previously, we would highlight on "foo" and "foolish".
Now, we highlight only on "foo".

This was inspired/copied from soju's handling [1].

[1]: https://git.sr.ht/~emersion/soju/tree/5e56cc30c538eb88c21cce732e2e357e80098164/item/irc.go#L473

Fixes: https://todo.sr.ht/~taiite/senpai/97
1 files changed,  +29, -2
M app.go
M app.go
+29, -2
 1@@ -11,6 +11,7 @@ import (
 2 	"sync"
 3 	"time"
 4 	"unicode"
 5+	"unicode/utf8"
 6 
 7 	"golang.org/x/net/proxy"
 8 
 9@@ -1006,14 +1007,40 @@ func isBlackListed(command string) bool {
10 	return false
11 }
12 
13+func isWordBoundary(r rune) bool {
14+	switch r {
15+	case '-', '_', '|': // inspired from weechat.look.highlight_regex
16+		return false
17+	default:
18+		return !unicode.IsLetter(r) && !unicode.IsNumber(r)
19+	}
20+}
21+
22+func isHighlight(text, nick string) bool {
23+	for {
24+		i := strings.Index(text, nick)
25+		if i < 0 {
26+			return false
27+		}
28+
29+		left, _ := utf8.DecodeLastRuneInString(text[:i])
30+		right, _ := utf8.DecodeRuneInString(text[i+len(nick):])
31+		if isWordBoundary(left) && isWordBoundary(right) {
32+			return true
33+		}
34+
35+		text = text[i+len(nick):]
36+	}
37+}
38+
39 // isHighlight reports whether the given message content is a highlight.
40 func (app *App) isHighlight(s *irc.Session, content string) bool {
41 	contentCf := s.Casemap(content)
42 	if app.highlights == nil {
43-		return strings.Contains(contentCf, s.NickCf())
44+		return isHighlight(contentCf, s.NickCf())
45 	}
46 	for _, h := range app.highlights {
47-		if strings.Contains(contentCf, s.Casemap(h)) {
48+		if isHighlight(contentCf, s.Casemap(h)) {
49 			return true
50 		}
51 	}