assumptions explained in its doc string. For clarity, it has been
renamed 'erc-ensure-target-buffer-on-privmsg'.
+** Subtle changes in two fundamental faces.
+Users of the default theme may notice that 'erc-action-face' and
+'erc-notice-face' now appear slightly less bold on systems supporting
+a weight of 'semi-bold'. This was done to make buttons detectable and
+to spare users from resorting to tweaking these faces, or options like
+'erc-notice-highlight-type', just to achieve this effect.
+
** Improved interplay between buffer truncation and message logging.
While most of these improvements are subtle, some affect everyday use.
For example, users of the 'truncate' module may notice that truncation
:package-version '(ERC . "5.6") ; FIXME sync on release
:type '(choice (const nil) number))
-(defcustom erc-fill-spaced-commands '(PRIVMSG NOTICE)
+(defvar erc-fill--spaced-commands '(PRIVMSG NOTICE)
"Types of messages to add space between on graphical displays.
-Only considered when `erc-fill-line-spacing' is non-nil."
- :package-version '(ERC . "5.6") ; FIXME sync on release
- :type '(repeat (choice integer symbol)))
+Only considered when `erc-fill-line-spacing' is non-nil.")
(defvar-local erc-fill--function nil
"Internal copy of `erc-fill-function'.
(p (point-min)))
(widen)
(when (or (and-let* ((cmd (get-text-property p 'erc-command)))
- (memq cmd erc-fill-spaced-commands))
+ (memq cmd erc-fill--spaced-commands))
(and-let* ((cmd (save-excursion
(forward-line -1)
(get-text-property (point)
'erc-command))))
- (memq cmd erc-fill-spaced-commands)))
+ (memq cmd erc-fill--spaced-commands)))
(put-text-property (1- p) p
'line-spacing erc-fill-line-spacing))))))))
(when (eq 'erc-timestamp (field-at-pos m))
(set-marker m (field-end m)))
(and (eq 'PRIVMSG (get-text-property m 'erc-command))
- (not (eq (get-text-property m 'font-lock-face)
- 'erc-action-face))
+ (not (eq (get-text-property m 'erc-ctcp) 'ACTION))
(cons (get-text-property m 'erc-timestamp)
(get-text-property (1+ m) 'erc-data)))))
(ts (pop props))
`(space :width (- erc-fill--wrap-value ,width))))
args)
+;; An escape hatch for third-party code expecting speakers of ACTION
+;; messages to be exempt from `line-prefix'. This could be converted
+;; into a user option if users feel similarly.
+(defvar erc-fill--wrap-action-dedent-p t
+ "Whether to dedent speakers in CTCP \"ACTION\" lines.")
+
(defun erc-fill-wrap ()
"Use text props to mimic the effect of `erc-fill-static'.
See `erc-fill-wrap-mode' for details."
(let ((len (or (and erc-fill--wrap-length-function
(funcall erc-fill--wrap-length-function))
(progn
+ (when-let ((e (erc--get-speaker-bounds))
+ (b (pop e))
+ ((or erc-fill--wrap-action-dedent-p
+ (not (eq (get-text-property b 'erc-ctcp)
+ 'ACTION)))))
+ (goto-char e))
(skip-syntax-forward "^-")
(forward-char)
;; Using the `invisible' property might make more
(defface erc-notice-face
'((default :weight bold)
+ (((class color) (min-colors 88) (supports :weight semi-bold))
+ :weight semi-bold :foreground "SlateBlue")
(((class color) (min-colors 88)) :foreground "SlateBlue")
(t :foreground "blue"))
"ERC face for notices."
+ :package-version '(ERC . "5.6") ; FIXME sync on release
:group 'erc-faces)
-(defface erc-action-face '((t :weight bold))
+(defface erc-action-face '((((supports :weight semi-bold)) :weight semi-bold)
+ (t :weight bold))
"ERC face for actions generated by /ME."
+ :package-version '(ERC . "5.6") ; FIXME sync on release
:group 'erc-faces)
(defface erc-error-face '((t :foreground "red"))
(erc-send-ctcp-message tgt (format "ACTION %s" str) force)
(let ((erc-insert-pre-hook
(cons (lambda (s) ; Leave newline be.
- (put-text-property 0 (1- (length s)) 'erc-command 'PRIVMSG s))
- erc-insert-pre-hook)))
+ (put-text-property 0 (1- (length s)) 'erc-command 'PRIVMSG s)
+ (put-text-property 0 (1- (length s)) 'erc-ctcp 'ACTION s))
+ erc-insert-pre-hook))
+ (nick (erc-current-nick)))
+ (setq nick (propertize nick 'erc-speaker nick))
(erc-display-message nil 'input (current-buffer)
- 'ACTION ?n (erc-current-nick) ?a str ?u "" ?h "")))
+ 'ACTION ?n nick ?a str ?u "" ?h "")))
;; Display interface
(concat "#" channel)))
(defvar erc--own-property-names
- '( tags erc-parsed display ; core
+ '( tags erc-speaker erc-parsed display ; core
;; `erc-display-prompt'
rear-nonsticky erc-prompt field front-sticky read-only
;; stamp
(mark-e (if msgp (if privp "*" ">") "-"))
(str (format "%s%s%s %s" mark-s nick mark-e msg))
(nick-face (if privp 'erc-nick-msg-face 'erc-nick-default-face))
+ (nick-prefix-face (get-text-property 0 'font-lock-face nick))
+ (prefix-len (or (and nick-prefix-face (text-property-not-all
+ 0 (length nick) 'font-lock-face
+ nick-prefix-face nick))
+ 0))
(msg-face (if privp 'erc-direct-msg-face 'erc-default-face)))
;; add text properties to text before the nick, the nick and after the nick
(erc-put-text-property 0 (length mark-s) 'font-lock-face msg-face str)
- (erc-put-text-property (length mark-s) (+ (length mark-s) (length nick))
- 'font-lock-face nick-face str)
+ (erc-put-text-properties (+ (length mark-s) prefix-len)
+ (+ (length mark-s) (length nick))
+ '(font-lock-face erc-speaker) str
+ (list nick-face
+ (substring-no-properties nick prefix-len)))
(erc-put-text-property (+ (length mark-s) (length nick)) (length str)
'font-lock-face msg-face str)
str))
(concat
(propertize open 'font-lock-face 'erc-default-face)
(propertize mode 'font-lock-face 'erc-my-nick-prefix-face)
- (propertize nick 'font-lock-face 'erc-my-nick-face)
+ (propertize nick 'font-lock-face 'erc-my-nick-face 'erc-speaker nick)
(propertize close 'font-lock-face 'erc-default-face)))
(let ((prefix "> "))
(propertize prefix 'font-lock-face 'erc-default-face))))
'ctcp-empty ?n nick)
(while queries
(let* ((type (upcase (car (split-string (car queries)))))
- (hook (intern-soft (concat "erc-ctcp-query-" type "-hook"))))
+ (hook (intern-soft (concat "erc-ctcp-query-" type "-hook")))
+ (erc-insert-pre-hook
+ (cons (lambda (s)
+ (put-text-property 0 (1- (length s)) 'erc-ctcp
+ (intern type) s))
+ erc-insert-pre-hook)))
(if (and hook (boundp hook))
(if (string-equal type "ACTION")
(run-hook-with-args-until-success
(buf (or (erc-get-buffer to proc)
(erc-get-buffer nick proc)
(process-buffer proc))))
+ (setq nick (propertize nick 'erc-speaker nick))
(erc-display-message
parsed 'action buf
'ACTION ?n nick ?u login ?h host ?a s))))
(with-temp-file expect-file
(insert repr))
(if (file-exists-p expect-file)
- ;; Compare set-equal over intervals
+ ;; Compare set-equal over intervals. This comparison is
+ ;; less useful for messages treated by other modules because
+ ;; it doesn't compare "nested" props belonging to
+ ;; string-valued properties, like timestamps.
(should (equal-including-properties
(read repr)
(read (with-temp-buffer
(kill-buffer "ExampleNet")
(kill-buffer "#chan")))
+(defmacro erc-tests--equal-including-properties (a b)
+ (list (if (< emacs-major-version 29)
+ 'ert-equal-including-properties
+ 'equal-including-properties)
+ a b))
+
+(ert-deftest erc-format-privmessage ()
+ ;; Basic PRIVMSG
+ (should (erc-tests--equal-including-properties
+ (erc-format-privmessage (copy-sequence "bob")
+ (copy-sequence "oh my")
+ nil 'msgp)
+ #("<bob> oh my"
+ 0 1 (font-lock-face erc-default-face)
+ 1 4 (erc-speaker "bob" font-lock-face erc-nick-default-face)
+ 4 11 (font-lock-face erc-default-face))))
+
+ ;; Basic NOTICE
+ (should (erc-tests--equal-including-properties
+ (erc-format-privmessage (copy-sequence "bob")
+ (copy-sequence "oh my")
+ nil nil)
+ #("-bob- oh my"
+ 0 1 (font-lock-face erc-default-face)
+ 1 4 (erc-speaker "bob" font-lock-face erc-nick-default-face)
+ 4 11 (font-lock-face erc-default-face))))
+
+ ;; Prefixed PRIVMSG
+ (let* ((user (make-erc-server-user :nickname (copy-sequence "Bob")))
+ (cuser (make-erc-channel-user :op t))
+ (erc-channel-users (make-hash-table :test #'equal)))
+ (puthash "bob" (cons user cuser) erc-channel-users)
+
+ (should (erc-tests--equal-including-properties
+ (erc-format-privmessage (erc-format-@nick user cuser)
+ (copy-sequence "oh my")
+ nil 'msgp)
+ #("<@Bob> oh my"
+ 0 1 (font-lock-face erc-default-face)
+ 1 2 (font-lock-face erc-nick-prefix-face help-echo "operator")
+ 2 5 (erc-speaker "Bob" font-lock-face erc-nick-default-face)
+ 5 12 (font-lock-face erc-default-face))))))
+
(defvar erc-tests--ipv6-examples
'("1:2:3:4:5:6:7:8"
"::ffff:10.0.0.1" "::ffff:1.2.3.4" "::ffff:0.0.0.0"