Closed wasamasa closed 4 years ago
Hash table version:
(with-eval-after-load 'circe-color-nicks
(defun my-string-ci-equal (a b) (string-equal (downcase a) (downcase b)))
(defun my-string-ci-hash (s) (sxhash (downcase s)))
(define-hash-table-test 'my-string-ci-equal 'my-string-ci-equal
'my-string-ci-hash)
(defvar my-circe-color-nick-table nil)
(make-variable-buffer-local 'my-circe-color-nick-table)
(defun my-circe-add-nick-to-table (channel userstring)
(let* ((user-table (irc-channel-users channel))
(conn (irc-channel-connection channel))
(user (irc-user-from-userstring conn userstring))
(nick (irc-user-nick user)))
(with-current-buffer (irc-connection-get conn :server-buffer)
(let ((name (irc-channel-name channel)))
(with-current-buffer (circe-server-get-chat-buffer name)
(when (not my-circe-color-nick-table)
(setq my-circe-color-nick-table
(make-hash-table :test 'my-string-ci-equal)))
(puthash nick t my-circe-color-nick-table))))))
(defun my-circe-remove-nick-from-table (channel nick)
(let* ((user-table (irc-channel-users channel))
(conn (irc-channel-connection channel)))
(with-current-buffer (irc-connection-get conn :server-buffer)
(let ((name (irc-channel-name channel)))
(with-current-buffer (circe-server-get-chat-buffer name)
(when (not my-circe-color-nick-table)
(setq my-circe-color-nick-table
(make-hash-table :test 'my-string-ci-equal)))
(remhash nick my-circe-color-nick-table))))))
(advice-add 'irc-channel-add-user :after 'my-circe-add-nick-to-table)
(advice-add 'irc-channel-remove-user :after 'my-circe-remove-nick-from-table)
(defun circe-color-nicks ()
"Color nicks on this lui output line."
(when (eq major-mode 'circe-channel-mode)
(let ((nickstart (text-property-any (point-min) (point-max)
'lui-format-argument 'nick)))
(when nickstart
(goto-char nickstart)
(let ((nickend (next-single-property-change nickstart
'lui-format-argument))
(nick (plist-get (plist-get (text-properties-at nickstart)
'lui-keywords)
:nick)))
(when (not (circe-server-my-nick-p nick))
(let ((color (circe-nick-color-for-nick nick)))
(add-face-text-property nickstart nickend
`(:foreground ,color)))))))
(when circe-color-nicks-everywhere
(let ((body (text-property-any (point-min) (point-max)
'lui-format-argument 'body)))
(when (and body my-circe-color-nick-table)
(with-syntax-table circe-nick-syntax-table
(goto-char body)
(while (forward-word 1)
(let ((word (thing-at-point 'word)))
(when (gethash word my-circe-color-nick-table)
(let ((bounds (bounds-of-thing-at-point 'word))
(color (circe-nick-color-for-nick word)))
(add-face-text-property (car bounds) (cdr bounds)
`(:foreground ,color)))))))))))))
Looking at circe-nick-color-for-nick
it appears that a case-sensitive hash table is used, instead a hash table using the test defined above could resolve the issue.
edit: I've also noticed folding isn't what we want here and folded user tables already exist. Maybe the hash table check should use folding instead of making a new table with unfolded users...
Forgot to close this.
I've found that ZNC playback is super slow for me, https://github.com/lastquestion/explain-pause-mode pointed me towards this code in
circe-color-nicks
:This is run on every inserted chat line. It's suboptimal to retrieve the full nick list and convert it to a regular expression every time, especially inside a tight loop. One improvement idea is to instead create the regular expression whenever a user is added or removed in
irc-channel-add-user
andirc-channel-remove-user
. This helped a bit with speed, but not nearly enough as the regexp is still recreated very often at the start of ZNC playback. Another improvement idea was to completely do away with regular expressions and instead looking up each word in a trie holding all nicknames. This finally resolved the speed issue for me, here's my init file hack:This code isn't ideal for several reasons:
irc-channel-add-user
andirc-channel-remove-user
is rather ugly. It would be better to have a hook instead or maybe even exposing hash tables holding all folded nicks instead, then there would be no need for advice or hooks whatsoever.edit: I forgot to mention @TaylanUB who wrote the module in the first place.