;; `kill-line' anyway so that users can see the error.
(erc-fill--wrap-move #'kill-line #'kill-visual-line arg))
-(defun erc-fill--wrap-escape-hidden-speaker ()
+(defun erc-fill--wrap-escape-hidden-speaker (&optional old-point)
"Move to start of message text when left of speaker.
-Basically mimic what `move-beginning-of-line' does with invisible text."
+Basically mimic what `move-beginning-of-line' does with invisible text.
+Stay put if OLD-POINT lies within hidden region."
(when-let ((erc-fill-wrap-merge)
- (prop (get-text-property (point) 'display))
- ((or (equal prop "") (eq 'margin (car-safe (car-safe prop))))))
- (goto-char (text-property-not-all (point) (pos-eol) 'display prop))))
+ (prop (get-text-property (point) 'erc-fill--wrap-merge))
+ ((or (member prop '("" t))
+ (eq 'margin (car-safe (car-safe prop)))))
+ (end (text-property-not-all (point) (pos-eol)
+ 'erc-fill--wrap-merge prop))
+ ((or (null old-point) (>= old-point end))))
+ (goto-char end)))
(defun erc-fill--wrap-beginning-of-line (arg)
"Defer to `move-beginning-of-line' or `beginning-of-visual-line'."
(interactive "^p")
- (let ((inhibit-field-text-motion t))
- (erc-fill--wrap-move #'move-beginning-of-line
- #'beginning-of-visual-line arg))
- (if (get-text-property (point) 'erc-prompt)
- (goto-char erc-input-marker)
- ;; Mimic what `move-beginning-of-line' does with invisible text.
- (erc-fill--wrap-escape-hidden-speaker)))
+ (let ((opoint (point)))
+ (let ((inhibit-field-text-motion t))
+ (erc-fill--wrap-move #'move-beginning-of-line
+ #'beginning-of-visual-line arg))
+ (if (get-text-property (point) 'erc-prompt)
+ (goto-char erc-input-marker)
+ (when erc-fill-wrap-merge
+ (erc-fill--wrap-escape-hidden-speaker opoint)))))
(defun erc-fill--wrap-previous-line (&optional arg try-vscroll)
"Move to ARGth previous logical or screen line."
(erc-fill--wrap-move (if visp #'previous-line #'previous-logical-line)
#'previous-line
arg try-vscroll))
- (erc-fill--wrap-escape-hidden-speaker)))
+ (when erc-fill-wrap-merge
+ (erc-fill--wrap-escape-hidden-speaker))))
(defun erc-fill--wrap-next-line (&optional arg try-vscroll)
"Move to ARGth next logical or screen line."
erc-fill-wrap-force-screen-line-movement)))
(erc-fill--wrap-move (if visp #'next-line #'next-logical-line)
#'next-line
- arg try-vscroll)))
+ arg try-vscroll)
+ (when erc-fill-wrap-merge
+ (erc-fill--wrap-escape-hidden-speaker))))
(defun erc-fill--wrap-end-of-line (arg)
"Defer to `move-end-of-line' or `end-of-visual-line'."
(defvar-local erc-fill--wrap-merge-indicator-pre nil)
(defun erc-fill--wrap-insert-merged-pre ()
- "Add `display' property in lieu of speaker."
+ "Add `display' text property to speaker.
+Also cover region with text prop `erc-fill--wrap-merge' set to t."
(if erc-fill--wrap-merge-indicator-pre
(progn
- (put-text-property (point-min) (point) 'display
- (car erc-fill--wrap-merge-indicator-pre))
+ (add-text-properties (point-min) (point)
+ (list 'display
+ (car erc-fill--wrap-merge-indicator-pre)
+ 'erc-fill--wrap-merge t))
(cdr erc-fill--wrap-merge-indicator-pre))
(let* ((option erc-fill-wrap-merge-indicator)
(s (if (stringp option)
(concat (propertize (string (car option))
'font-lock-face (cdr option))
" "))))
- (put-text-property (point-min) (point) 'display s)
+ (add-text-properties (point-min) (point)
+ (list 'display s 'erc-fill--wrap-merge t))
(cdr (setq erc-fill--wrap-merge-indicator-pre
(cons s (erc-fill--wrap-measure (point-min) (point))))))))
(delete-region (1- (point)) (point))))))
((and erc-fill-wrap-merge
(erc-fill--wrap-continued-message-p))
- (put-text-property (point-min) (point)
- 'display "")
+ (add-text-properties
+ (point-min) (point)
+ '(display "" erc-fill--wrap-merge ""))
(if erc-fill-wrap-merge-indicator
(erc-fill--wrap-insert-merged-pre)
0))
case this module's insert hooks run by way of the process filter.
With REPAIRP, destructively fill gaps and re-merge speakers."
(goto-char start)
- (cl-assert (null erc-fill--wrap-rejigger-last-message))
(setq erc-fill--wrap-merge-indicator-pre nil)
- (let (erc-fill--wrap-rejigger-last-message)
+ (let ((erc-fill--wrap-rejigger-last-message
+ erc-fill--wrap-rejigger-last-message))
(while-let
(((< (point) finish))
(beg (if (get-text-property (point) 'line-prefix)
;; If this is a left-side stamp on its own line.
(remove-text-properties beg (1+ end) '(line-prefix nil wrap-prefix nil))
(when-let ((repairp)
- (dbeg (text-property-not-all beg end 'display nil))
+ (dbeg (text-property-not-all beg end
+ 'erc-fill--wrap-merge nil))
((get-text-property (1+ dbeg) 'erc--speaker))
- (dval (get-text-property dbeg 'display))
- ((equal "" dval)))
- (remove-text-properties
- dbeg (text-property-not-all dbeg end 'display dval) '(display)))
+ (dval (get-text-property dbeg 'erc-fill--wrap-merge)))
+ (remove-list-of-text-properties
+ dbeg (text-property-not-all dbeg end 'erc-fill--wrap-merge dval)
+ '(display erc-fill--wrap-merge)))
;; This "should" work w/o `front-sticky' and `rear-nonsticky'.
(let* ((pos (if-let (((eq 'erc-timestamp (field-at-pos beg)))
(b (field-beginning beg))
callback repair)
(progress-reporter-done rep)))))
-;; FIXME use own text property to avoid false positives.
(defun erc-fill--wrap-merged-button-p (point)
- (equal "" (get-text-property point 'display)))
+ (get-text-property point 'erc-fill--wrap-merge))
(defun erc-fill--wrap-nudge (arg)
(when (zerop arg)