[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 7c932fa3078 3/4: Add optional timezone param to erc-echo-timestam
From: |
F. Jason Park |
Subject: |
master 7c932fa3078 3/4: Add optional timezone param to erc-echo-timestamp |
Date: |
Sun, 10 Sep 2023 21:02:11 -0400 (EDT) |
branch: master
commit 7c932fa307851ccef1cf17a1d7eec689af82a0ef
Author: F. Jason Park <jp@neverwas.me>
Commit: F. Jason Park <jp@neverwas.me>
Add optional timezone param to erc-echo-timestamp
* etc/ERC-NEWS: Move `erc-echo-timestamp' from misc section
to own entry, and mention option `erc-echo-timestamp-zone'.
* lisp/erc/erc-stamp.el (erc-echo-timestamps): Mention that some
finagling is required if enabling this option after activating the
module.
(erc-echo-timestamp-format): Add additional Custom choice constants
and make the existing default one of them.
(erc-echo-timestamp-zone): New option to specify timezone for option
`erc-echo-timestamps' and function `erc-echo-timestamp'.
(erc-stamp-mode, erc-stamp-enable, erc-stamp-disable): Call
`erc-stamp--setup' instead of `erc-munge-invisibility-spec'.
(erc-stamp--current-time): Use `current-time' instead of
`erc-current-time'.
(erc-add-timestamp): Improve readability slightly, and change
`fboundp' to `functionp' to avoid signaling an error when the
variable's value is not a symbol.
(erc-munge-invisibility-spec): Perform teardown when boolean flag
options, like `erc-timestamp-intangible' and `erc-echo-timestamps' are
nil.
(erc-stamp--setup): Call `erc-munge-invisibility-spec', possibly
binding timestamp options to nil to force a tear down).
(erc-stamp--last-stamp, erc-stamp--on-clear-message): New function and
helper state variable to tell Emacs not to clear the current timestamp
message when navigating within the same IRC message.
(erc-echo-timestamp): Add optional `zone' parameter, to be passed
directly to `format-time-string', when non-interactive, and massaged
sensibly otherwise. Set the local variable `erc-stamp--last-stamp'.
* test/lisp/erc/erc-stamp-tests.el (erc-echo-timestamp): New test.
(Bug#60936)
---
etc/ERC-NEWS | 13 +++--
lisp/erc/erc-stamp.el | 101 +++++++++++++++++++++++++++++----------
test/lisp/erc/erc-stamp-tests.el | 30 ++++++++++++
3 files changed, 116 insertions(+), 28 deletions(-)
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index 7ee55982b17..8997bd3e97b 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -203,11 +203,18 @@ continued integration. With the existing design, merely
loading the
library 'erc-log' caused 'truncate' to start writing logs, possibly
against a user's wishes.
+** The function 'erc-echo-timestamp' is now a command.
+The option 'erc-echo-timestamps' (plural) has always enabled the
+contextual printing of timestamps to the echo area when moving between
+messages in an ERC buffer. Similar functionality is now available on
+demand by invoking the newly interactive function 'erc-echo-timestamp'
+atop any message. The new companion option 'erc-echo-timestamp-zone'
+determines the default timezone when not specified with a prefix
+argument.
+
** Miscellaneous UX changes.
Some minor quality-of-life niceties have finally made their way to
-ERC. For example, the function 'erc-echo-timestamp' is now
-interactive and can be invoked on any message to view its timestamp in
-the echo area. Fool visibility has become togglable with the new
+ERC. For example, fool visibility has become togglable with the new
command 'erc-match-toggle-hidden-fools'. The 'button' module's
'erc-button-previous' now moves to the beginning instead of the end of
buttons. A new command, 'erc-news', can be invoked to visit this very
diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el
index a021cd26607..f159b6d226f 100644
--- a/lisp/erc/erc-stamp.el
+++ b/lisp/erc/erc-stamp.el
@@ -136,14 +136,27 @@ hidden, they will still be present in the logs."
"If non-nil, print timestamp in the minibuffer when point is moved.
Using this variable, you can turn off normal timestamping,
and simply move point to an irc message to see its timestamp
-printed in the minibuffer."
+printed in the minibuffer. When attempting to enable this option
+after `erc-stamp-mode' is already active, you may need to run the
+command `erc-show-timestamps' (or `erc-hide-timestamps') in the
+appropriate ERC buffer before the change will take effect."
:type 'boolean)
(defcustom erc-echo-timestamp-format "Timestamped %A, %H:%M:%S"
"Format string to be used when `erc-echo-timestamps' is non-nil.
This string specifies the format of the timestamp being echoed in
the minibuffer."
- :type 'string)
+ :type '(choice (const "Timestamped %A, %H:%M:%S")
+ (const "%Y-%m-%d %H:%M:%S %Z")
+ string))
+
+(defcustom erc-echo-timestamp-zone nil
+ "Default timezone for the option `erc-echo-timestamps'.
+Also affects the command `erc-echo-timestamp' (singular). See
+the ZONE parameter of `format-time-string' for a description of
+acceptable value types."
+ :type '(choice boolean number (const wall) (list number string))
+ :package-version '(ERC . "5.6")) ; FIXME sync on release
(defcustom erc-timestamp-intangible nil
"Whether the timestamps should be intangible, i.e. prevent the point
@@ -167,14 +180,15 @@ from entering them and instead jump over them."
(add-hook 'erc-send-modify-hook #'erc-add-timestamp 60)
(add-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect)
(add-hook 'erc--pre-clear-functions #'erc-stamp--reset-on-clear)
- (unless erc--updating-modules-p
- (erc-buffer-do #'erc-munge-invisibility-spec)))
+ (unless erc--updating-modules-p (erc-buffer-do #'erc-stamp--setup)))
((remove-hook 'erc-mode-hook #'erc-munge-invisibility-spec)
(remove-hook 'erc-insert-modify-hook #'erc-add-timestamp)
(remove-hook 'erc-send-modify-hook #'erc-add-timestamp)
(remove-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect)
(remove-hook 'erc--pre-clear-functions #'erc-stamp--reset-on-clear)
(erc-with-all-buffers-of-server nil nil
+ (erc-stamp--setup)
+ (kill-local-variable 'erc-stamp--last-stamp)
(kill-local-variable 'erc-timestamp-last-inserted)
(kill-local-variable 'erc-timestamp-last-inserted-left)
(kill-local-variable 'erc-timestamp-last-inserted-right))))
@@ -200,9 +214,8 @@ the stamp passed to `erc-insert-timestamp-function'.")
(cl-defgeneric erc-stamp--current-time ()
"Return a lisp time object to associate with an IRC message.
-This becomes the message's `erc-timestamp' text property, which
-may not be unique, `equal'-wise."
- (erc-current-time))
+This becomes the message's `erc-timestamp' text property."
+ (let (current-time-list) (current-time)))
(cl-defmethod erc-stamp--current-time :around ()
(or erc-stamp--current-time (cl-call-next-method)))
@@ -218,15 +231,17 @@ or `erc-send-modify-hook'."
(erc-stamp--invisible-property
;; FIXME on major version bump, make this `erc-' prefixed.
(if invisible `(timestamp ,@(ensure-list invisible)) 'timestamp))
+ (skipp (and erc-stamp--skip-when-invisible invisible))
(erc-stamp--current-time ct))
- (unless (setq invisible (and erc-stamp--skip-when-invisible invisible))
+ (unless skipp
(funcall erc-insert-timestamp-function
(erc-format-timestamp ct erc-timestamp-format)))
- ;; FIXME this will error when advice has been applied.
- (when (and (not invisible) (fboundp erc-insert-away-timestamp-function)
- erc-away-timestamp-format
- (erc-away-time)
- (not erc-timestamp-format))
+ ;; Check `erc-insert-away-timestamp-function' for historical
+ ;; reasons even though its Custom :type only allows functions.
+ (when (and (not (or skipp erc-timestamp-format))
+ erc-away-timestamp-format
+ (functionp erc-insert-away-timestamp-function)
+ (erc-away-time))
(funcall erc-insert-away-timestamp-function
(erc-format-timestamp ct erc-away-timestamp-format)))
(add-text-properties (point-min) (1- (point-max))
@@ -640,14 +655,31 @@ Return the empty string if FORMAT is nil."
;; please modify this function and move it to a more appropriate
;; location.
(defun erc-munge-invisibility-spec ()
- (and erc-timestamp-intangible (not (bound-and-true-p cursor-intangible-mode))
- (cursor-intangible-mode 1))
- (and erc-echo-timestamps (not (bound-and-true-p cursor-sensor-mode))
- (cursor-sensor-mode 1))
+ (if erc-timestamp-intangible
+ (cursor-intangible-mode +1) ; idempotent
+ (when (bound-and-true-p cursor-intangible-mode)
+ (cursor-intangible-mode -1)))
+ (if erc-echo-timestamps
+ (progn
+ (cursor-sensor-mode +1) ; idempotent
+ (when (>= emacs-major-version 29)
+ (add-function :before-until (local 'clear-message-function)
+ #'erc-stamp--on-clear-message)))
+ (when (bound-and-true-p cursor-sensor-mode)
+ (cursor-sensor-mode -1))
+ (remove-function (local 'clear-message-function)
+ #'erc-stamp--on-clear-message))
(if erc-hide-timestamps
(add-to-invisibility-spec 'timestamp)
(remove-from-invisibility-spec 'timestamp)))
+(defun erc-stamp--setup ()
+ "Enable or disable buffer-local `erc-stamp-mode' modifications."
+ (if erc-stamp-mode
+ (erc-munge-invisibility-spec)
+ (let (erc-echo-timestamps erc-hide-timestamps erc-timestamp-intangible)
+ (erc-munge-invisibility-spec))))
+
(defun erc-hide-timestamps ()
"Hide timestamp information from display."
(interactive)
@@ -677,14 +709,33 @@ enabled when the message was inserted."
(erc-munge-invisibility-spec)))
(erc-buffer-list)))
-(defun erc-echo-timestamp (dir stamp)
- "Print timestamp text-property of an IRC message."
- ;; Could also pass an &optional `zone' arg to `format-time-string'.
- (interactive (list 'entered (get-text-property (point) 'erc-timestamp)))
- (when (eq 'entered dir)
- (when stamp
- (message "%s" (format-time-string erc-echo-timestamp-format
- stamp)))))
+(defvar-local erc-stamp--last-stamp nil)
+
+(defun erc-stamp--on-clear-message (&rest _)
+ "Return `dont-clear-message' when operating inside the same stamp."
+ (and erc-stamp--last-stamp erc-echo-timestamps
+ (eq (get-text-property (point) 'erc-timestamp) erc-stamp--last-stamp)
+ 'dont-clear-message))
+
+(defun erc-echo-timestamp (dir stamp &optional zone)
+ "Display timestamp of message at point in echo area.
+Interactively, interpret a numeric prefix as a ZONE offset in
+hours (or seconds, if its abs value is larger than 14), and
+interpret a \"raw\" prefix as UTC. To specify a zone for use
+with the option `erc-echo-timestamps', see the companion option
+`erc-echo-timestamp-zone'."
+ (interactive (list nil (get-text-property (point) 'erc-timestamp)
+ (pcase current-prefix-arg
+ ((and (pred numberp) v)
+ (if (<= (abs v) 14) (* v 3600) v))
+ (`(,_) t))))
+ (if (and stamp (or (null dir) (and erc-echo-timestamps (eq 'entered dir))))
+ (progn
+ (setq erc-stamp--last-stamp stamp)
+ (message (format-time-string erc-echo-timestamp-format
+ stamp (or zone erc-echo-timestamp-zone))))
+ (when (and erc-echo-timestamps (eq 'left dir))
+ (setq erc-stamp--last-stamp nil))))
(defun erc--echo-ts-csf (_window _before dir)
(erc-echo-timestamp dir (get-text-property (point) 'erc-timestamp)))
diff --git a/test/lisp/erc/erc-stamp-tests.el b/test/lisp/erc/erc-stamp-tests.el
index c448416cd69..b00aa6dcabf 100644
--- a/test/lisp/erc/erc-stamp-tests.el
+++ b/test/lisp/erc/erc-stamp-tests.el
@@ -274,4 +274,34 @@
(when noninteractive
(kill-buffer)))))
+(ert-deftest erc-echo-timestamp ()
+ (should-not erc-echo-timestamps)
+ (should-not erc-stamp--last-stamp)
+ (insert (propertize "abc" 'erc-timestamp 433483200))
+ (goto-char (point-min))
+ (let ((inhibit-message t)
+ (erc-echo-timestamp-format "%Y-%m-%d %H:%M:%S %Z")
+ (erc-echo-timestamp-zone (list (* 60 60 -4) "EDT")))
+
+ ;; No-op when non-interactive and option is nil
+ (should-not (erc--echo-ts-csf nil nil 'entered))
+ (should-not erc-stamp--last-stamp)
+
+ ;; Non-interactive (cursor sensor function)
+ (let ((erc-echo-timestamps t))
+ (should (equal (erc--echo-ts-csf nil nil 'entered)
+ "1983-09-27 00:00:00 EDT")))
+ (should (= 433483200 erc-stamp--last-stamp))
+
+ ;; Interactive
+ (should (equal (call-interactively #'erc-echo-timestamp)
+ "1983-09-27 00:00:00 EDT"))
+ ;; Interactive with zone
+ (let ((current-prefix-arg '(4)))
+ (should (equal (call-interactively #'erc-echo-timestamp)
+ "1983-09-27 04:00:00 GMT")))
+ (let ((current-prefix-arg -7))
+ (should (equal (call-interactively #'erc-echo-timestamp)
+ "1983-09-26 21:00:00 -07")))))
+
;;; erc-stamp-tests.el ends here