bug#59943: 30.0.50; ERC 5.5+: Add visual indicator to ERC keep-place

"J.P." <[email protected]>
Newsgroups gmane.emacs.erc.general
Message-ID <[email protected]>
Tags: patch

Hi people,

There's been some recent talk regarding ERC's lack of a visual element
to demarcate the boundary between seen and unseen messages in a target
buffer. This approach leverages the existing `keep-place' module located
in erc-goodies. (But perhaps there's a smarter way?) Improvements or
replacements welcome, as always.

Thanks,
J.P.


In GNU Emacs 30.0.50 (build 2, x86_64-pc-linux-gnu, GTK+ Version
 3.24.35, cairo version 1.17.6) of 2022-12-10 built on localhost
Repository revision: 9c670695b91deb3424a74cd2b0f6a37356a4efcc
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12014000
System Description: Fedora Linux 36 (Workstation Edition)

Configured using:
 'configure --enable-check-lisp-object-type --enable-checking=yes,glyphs
 'CFLAGS=-O0 -g3'
 PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY
INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  value of $XMODIFIERS: @im=ibus
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message mailcap yank-media puny dired
dired-loaddefs rfc822 mml mml-sec epa derived epg rfc6068 epg-config
gnus-util text-property-search mm-decode mm-bodies mm-encode mail-parse
rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045
ietf-drums mm-util mail-prsvr mail-utils erc iso8601 time-date
auth-source cl-seq eieio eieio-core cl-macs password-cache json subr-x
map thingatpt pp format-spec cl-loaddefs cl-lib erc-backend erc-goodies
erc-networks byte-opt gv bytecomp byte-compile erc-common erc-compat
erc-loaddefs rmc iso-transl tooltip cconv eldoc paren electric uniquify
ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win
term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode lisp-mode prog-mode register
page tab-bar menu-bar rfn-eshadow isearch easymenu timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame minibuffer nadvice seq simple cl-generic indonesian philippine
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite emoji-zwj charscript
charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote
threads dbusbind inotify lcms2 dynamic-setting system-font-setting
font-render-setting cairo move-toolbar gtk x-toolkit xinput2 x multi-tty
make-network-process emacs)

Memory information:
((conses 16 64369 5963)
 (symbols 48 8607 0)
 (strings 32 23642 2119)
 (string-bytes 1 684025)
 (vectors 16 15217)
 (vector-slots 8 208839 8628)
 (floats 8 24 27)
 (intervals 56 227 0)
 (buffers 984 11))
0001-Add-option-to-show-visual-erc-keep-place-indicator.patch (text/x-patch, 7.2 KB)
From 685e151fa4565970683cd76eb111afd308d1b531 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <[email protected]>
Date: Fri, 9 Dec 2022 22:00:59 -0800
Subject: [PATCH] Add option to show visual erc-keep-place indicator

* etc/ERC-NEWS: Create new section for version 5.6 and mention
keep-place indicator.
* lisp/erc/erc-goodies.el (erc-keep-place-indicator,
erc-keep-place-indicator-follow): New options for anchoring kept place
visually.
(erc-keep-place-indicator-line, erc-keep-place-indicator-arrow): New
faces.
(erc--keep-place-overlay): New internal local state var.
(erc--keep-place-on-window-configuration-change): New function to
subscribe to `window-configuration-change-hook' and maybe update
keep-place indicator.
(erc--keep-place-setup-overlay): New function to initialize buffer for
option `erc-keep-place-indicator'.
(erc-keep-place-enable, erc-keep-place-disable): Add setup and
teardown to support `erc-keep-place-indicator'.
(erc-keep-place-move, erc-keep-place-goto): Add new commands for
manually updating and jumping to keep-place indicator.
(erc-keep-place): Move `erc--keep-place-overlay' when applicable.
---
 etc/ERC-NEWS            |  10 ++++
 lisp/erc/erc-goodies.el | 102 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index d0d84d0a98..af1cfcacea 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -11,6 +11,16 @@ This file is about changes in ERC, the powerful, modular, and
 extensible IRC (Internet Relay Chat) client distributed with
 GNU Emacs since Emacs version 22.1.
 
+
+* Changes in ERC 5.6
+
+** Module 'keep-place' now offers a visual indicator.
+
+Remember your place in a target buffer a bit more easily while also
+having the freedom to roam.  Optionally sync the indicator manually if
+you've made progress but still haven't caught up to the live stream.
+See new option 'erc-keep-place-indicator'.
+
 
 * Changes in ERC 5.5
 
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 1af83b58ba..18e9f665bd 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -46,6 +46,7 @@ erc-log-p
 (declare-function erc-error "erc" (&rest args))
 (declare-function erc-extract-command-from-line "erc" (line))
 (declare-function erc-beg-of-input-line "erc" nil)
+(declare-function erc-default-target "erc" nil)
 
 (defun erc-imenu-setup ()
   "Setup Imenu support in an ERC buffer."
@@ -154,11 +155,106 @@ erc-move-to-prompt-setup
   "Initialize the move-to-prompt module."
   (add-hook 'pre-command-hook #'erc-move-to-prompt nil t))
 
+(defcustom erc-keep-place-indicator nil
+  "Show kept place with visual indicator in target buffers.
+For use with the `keep-place' module.  A value of `arrow'
+displays an arrow in the left fringe or margin.  A value of
+`face' applies `erc-keep-place-indicator-line' to the appropriate
+line.  A value of t does both.  A value of nil does neither."
+  :group 'erc
+  :package-version '(ERC . "5.6")
+  :type '(choice (const nil) (const t) (const face) (const arrow)))
+
+(defcustom erc-keep-place-indicator-follow nil
+  "Whether to sync visual kept place to window's top when reading."
+  :group 'erc
+  :package-version '(ERC . "5.6")
+  :type 'boolean)
+
+(defface erc-keep-place-indicator-line
+  '((((class color) (min-colors 88) (background light)
+      (supports :underline (:style wave)))
+     (:underline (:color "PaleGreen3" :style wave)))
+    (((class color) (min-colors 88) (background dark)
+      (supports :underline (:style wave)))
+     (:underline (:color "PaleGreen1" :style wave)))
+    (t :underline t))
+  "Face for option `erc-keep-place-indicator'."
+  :group 'erc-faces)
+
+(defface erc-keep-place-indicator-arrow
+  '((((class color) (min-colors 88) (background light))
+     (:foreground "PaleGreen3"))
+    (((class color) (min-colors 88) (background dark))
+     (:foreground "PaleGreen1"))
+    (t :inherit fringe))
+  "Face for arrow value of option `erc-keep-place-indicator'."
+  :group 'erc-faces)
+
+(defvar-local erc--keep-place-overlay nil
+  "Overlay for option `erc-keep-place-indicator'.")
+
+(defun erc--keep-place-on-window-configuration-change ()
+  "Maybe sync `erc--keep-place-overlay'."
+  (when erc-keep-place-indicator-follow
+    (unless (minibuffer-window-active-p (minibuffer-window))
+      (when (< (overlay-end erc--keep-place-overlay)
+               (window-start)
+               erc-insert-marker)
+        (erc-keep-place-move (window-start))))))
+
+(defun erc--keep-place-setup-overlay ()
+  (when (erc-default-target)
+    (add-hook 'window-configuration-change-hook
+              #'erc--keep-place-on-window-configuration-change nil t)
+    (setq erc--keep-place-overlay (make-overlay 0 0))
+    (when (memq erc-keep-place-indicator '(t arrow))
+      (overlay-put erc--keep-place-overlay 'before-string
+                   (propertize
+                    " "
+                    'display
+                    (if (zerop (fringe-columns 'left))
+                        `((margin left-margin) ,overlay-arrow-string)
+                      '(left-fringe right-triangle
+                                    erc-keep-place-indicator-arrow)))))
+    (when (memq erc-keep-place-indicator '(t face))
+      (overlay-put erc--keep-place-overlay 'face
+                   'erc-keep-place-indicator-line))))
+
 ;;; Keep place in unvisited channels
 (define-erc-module keep-place nil
   "Leave point above un-viewed text in other channels."
-  ((add-hook 'erc-insert-pre-hook  #'erc-keep-place))
-  ((remove-hook 'erc-insert-pre-hook  #'erc-keep-place)))
+  ((add-hook 'erc-insert-pre-hook  #'erc-keep-place)
+   (when erc-keep-place-indicator
+     (if (derived-mode-p 'erc-mode)
+         (erc--keep-place-setup-overlay)
+       (add-hook 'erc-mode-hook #'erc--keep-place-setup-overlay))))
+  ((remove-hook 'erc-insert-pre-hook  #'erc-keep-place)
+   (when erc-keep-place-indicator
+     (remove-hook 'erc-mode-hook #'erc--keep-place-setup-overlay)
+     (erc-with-all-buffers-of-server erc-server-process nil
+       (when erc--keep-place-overlay
+         (delete-overlay erc--keep-place-overlay)
+         (remove-hook 'window-configuration-change-hook
+                      #'erc--keep-place-on-window-configuration-change t)
+         (kill-local-variable 'erc--keep-place-overlay))))))
+
+(defun erc-keep-place-move (&optional pos)
+  "Move keep-place indicator to the current line."
+  (interactive "P")
+  (save-excursion
+    (let ((inhibit-field-text-motion t))
+      (when (numberp pos)
+        (goto-char pos))
+      (move-overlay erc--keep-place-overlay
+                    (line-beginning-position)
+                    (line-end-position)))))
+
+(defun erc-keep-place-goto ()
+  "Jump to keep-place indicator."
+  (interactive)
+  (goto-char (overlay-start erc--keep-place-overlay))
+  (recenter (truncate (* (window-height) 0.25)) t))
 
 (defun erc-keep-place (_ignored)
   "Move point away from the last line in a non-selected ERC buffer."
@@ -168,6 +264,8 @@ erc-keep-place
     (deactivate-mark)
     (goto-char (erc-beg-of-input-line))
     (forward-line -1)
+    (when erc-keep-place-indicator
+      (erc-keep-place-move))
     ;; if `switch-to-buffer-preserve-window-point' is set,
     ;; we cannot rely on point being saved, and must commit
     ;; it to window-prev-buffers.
-- 
2.38.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.