From a6d33eb399c95a4efec3ffdab65c349f930a6a4d Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Sun, 19 Nov 2023 17:18:29 -0800 Subject: [PATCH 4/5] [5.6] Optionally align prompt to prefix in erc-fill-wrap * lisp/erc/erc-fill.el (erc-fill-wrap-align-prompt): New option for aligning prompt with leading portion of messages at the common "static center" pivot column, so it appears "dedented" along with all the speakers. Tests for this functionality appear in the subsequent patch of this same change set. (erc-fill-wrap-use-pixels): Demote from user option to normal variable because it has no practical use other than for testing. Don't rename as internal variable to spare the improbable user of ERC on HEAD who's already customized this some minor churn. (erc-fill-wrap-mode, erc-fill-wrap-enable): Take care to disable prompt-in-left-margin behavior when option `erc-fill-wrap-align-prompt' is non-nil. (erc-fill--wrap-measure): Improve doc string and always attempt to leverage `buffer-text-pixel-size', even when the variable `erc-fill-wrap-use-pixels' is nil. (erc-fill--wrap-indent-prompt): New function to massage prompt `line-prefix' after updates, such as changes to away status. (Bug#51082) --- lisp/erc/erc-fill.el | 47 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el index e48d5540c86..50b5aefd27a 100644 --- a/lisp/erc/erc-fill.el +++ b/lisp/erc/erc-fill.el @@ -138,6 +138,11 @@ erc-fill-wrap-margin-side :package-version '(ERC . "5.6") :type '(choice (const nil) (const left) (const right))) +(defcustom erc-fill-wrap-align-prompt nil + "Whether to align the prompt at the common `wrap-prefix'." + :package-version '(ERC . "5.6") + :type 'boolean) + (defcustom erc-fill-line-spacing nil "Extra space between messages on graphical displays. Its value should be larger than that of the variable @@ -223,13 +228,11 @@ erc-fill-variable (defvar-local erc-fill--wrap-value nil) (defvar-local erc-fill--wrap-visual-keys nil) -(defcustom erc-fill-wrap-use-pixels t +(defvar erc-fill-wrap-use-pixels t "Whether to calculate padding in pixels when possible. A value of nil means ERC should use columns, which may happen regardless, depending on the Emacs version. This option only -matters when `erc-fill-wrap-mode' is enabled." - :package-version '(ERC . "5.6") - :type 'boolean) +matters when `erc-fill-wrap-mode' is enabled.") (defcustom erc-fill-wrap-visual-keys 'non-input "Whether to retain keys defined by `visual-line-mode'. @@ -448,6 +451,13 @@ fill-wrap (or (eq erc-fill-wrap-margin-side 'left) (eq (default-value 'erc-insert-timestamp-function) #'erc-insert-timestamp-left))) + (when erc-fill-wrap-align-prompt + (add-hook 'erc--refresh-prompt-hook + #'erc-fill--wrap-indent-prompt nil t)) + (when erc-stamp--margin-left-p + (if erc-fill-wrap-align-prompt + (setq erc-stamp--skip-left-margin-prompt-p t) + (setq erc--inhibit-prompt-display-property-p t))) (setq erc-fill--function #'erc-fill-wrap) (when erc-fill-wrap-merge (add-hook 'erc-button--prev-next-predicate-functions @@ -460,6 +470,9 @@ fill-wrap (kill-local-variable 'erc-fill--function) (kill-local-variable 'erc-fill--wrap-visual-keys) (kill-local-variable 'erc-fill--wrap-last-msg) + (kill-local-variable 'erc--inhibit-prompt-display-property-p) + (remove-hook 'erc--refresh-prompt-hook + #'erc-fill--wrap-indent-prompt) (remove-hook 'erc-button--prev-next-predicate-functions #'erc-fill--wrap-merged-button-p t)) 'local) @@ -515,15 +528,20 @@ erc-fill--wrap-continued-message-p (defun erc-fill--wrap-measure (beg end) "Return display spec width for inserted region between BEG and END. -Ignore any `invisible' props that may be present when figuring." - (if (and erc-fill-wrap-use-pixels (fboundp 'buffer-text-pixel-size)) +Ignore any `invisible' props that may be present when figuring. +Expect the target region to be free of `line-prefix' and +`wrap-prefix' properties, and expect `display-line-numbers-mode' +to be disabled." + (if (fboundp 'buffer-text-pixel-size) ;; `buffer-text-pixel-size' can move point! (save-excursion (save-restriction (narrow-to-region beg end) (let* ((buffer-invisibility-spec) (rv (car (buffer-text-pixel-size)))) - (if (zerop rv) 0 (list rv))))) + (if erc-fill-wrap-use-pixels + (if (zerop rv) 0 (list rv)) + (/ rv (frame-char-width)))))) (- end beg))) ;; An escape hatch for third-party code expecting speakers of ACTION @@ -575,6 +593,21 @@ erc-fill-wrap 'erc-fill--wrap-value)) wrap-prefix (space :width erc-fill--wrap-value)))))) +(defun erc-fill--wrap-indent-prompt () + "Recompute the `line-prefix' of the prompt." + ;; Clear an existing `line-prefix' before measuring (bug#64971). + (remove-text-properties erc-insert-marker erc-input-marker + '(line-prefix nil wrap-prefix nil)) + ;; Restoring window configuration seems to prevent unwanted + ;; recentering reminiscent of `scrolltobottom'-related woes. + (let ((c (and (get-buffer-window) (current-window-configuration))) + (len (erc-fill--wrap-measure erc-insert-marker erc-input-marker))) + (when c + (set-window-configuration c)) + (put-text-property erc-insert-marker erc-input-marker + 'line-prefix + `(space :width (- erc-fill--wrap-value ,len))))) + (defvar erc-fill--wrap-rejigger-last-message nil "Temporary working instance of `erc-fill--wrap-last-msg'.") -- 2.41.0