Subject: Re: bug#78205: [PATCH] Recenter for the calendar

From: Manuel Giraud <[email-masked]>
Date: Sun, 04 May 2025 16:05:51 +0200

Hi,

Here is a new version of the patch that includes all your improvements.
>From cdac82cef98ed3997f7a9b872295f42eff78ae5a Mon Sep 17 00:00:00 2001
From: Manuel Giraud <[email-masked]>
Date: Thu, 1 May 2025 17:06:07 +0200
Subject: [PATCH] Recenter for the calendar (bug#78205)

* lisp/calendar/cal-move.el (calendar-recenter-last-op): New
variable to track last recenter operation.
(calendar-recenter): New command to recenter the calendar.
* lisp/calendar/calendar.el (calendar-mode-map): Keybinding for
this command.
* doc/emacs/calendar.texi (Scroll Calendar): Document this
command.
* etc/NEWS: Announce this command.
---
 doc/emacs/calendar.texi   | 11 +++++++++++
 etc/NEWS                  |  6 ++++++
 lisp/calendar/cal-move.el | 33 +++++++++++++++++++++++++++++++++
 lisp/calendar/calendar.el |  1 +
 4 files changed, 51 insertions(+)

diff --git a/doc/emacs/calendar.texi b/doc/emacs/calendar.texi
index 55798eae16e..56f297db5d0 100644
--- a/doc/emacs/calendar.texi
+++ b/doc/emacs/calendar.texi
@@ -258,6 +258,8 @@ Scroll Calendar
 @itemx @key{PageUp}
 @itemx @key{prior}
 Scroll backward by three months (@code{calendar-scroll-right-three-months}).
+@item C-l
+Recenter the date at point.
 @end table
 
 @kindex > @r{(Calendar mode)}
@@ -293,6 +295,15 @@ Scroll Calendar
 (or @key{prior}) are equivalent to @kbd{C-v} and @kbd{M-v}, just as
 they are in other modes.
 
+@kindex C-l @r{(Calendar mode)}
+@findex calendar-recenter
+  The command @kbd{C-l} (@code{calendar-recenter}) scrolls the calendar
+on display so that the month of the date at point is centered
+horizontally.  Next invocation of this command puts that month on the
+leftmost position, and another invocation puts it on the rightmost
+position.  Subsequent invocations reuse the same order in a cyclical
+manner.
+
 @node Counting Days
 @section Counting Days
 
diff --git a/etc/NEWS b/etc/NEWS
index a5936b1c6cf..f3711d4e6e4 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1990,6 +1990,12 @@ DISABLE-URI non-nil.
 When starting these debuggers (e.g., 'M-x pdb') while visiting a file,
 pressing 'M-n' in the command prompt suggests a command line including
 the file name, using the minibuffer's "future history".
+** Calendar
+
++++
+*** New command 'calendar-recenter'.
+This command recenters the month of the date at point.  By default, it
+is bound to 'C-l' in the calendar buffer.
 
 
 * New Modes and Packages in Emacs 31.1
diff --git a/lisp/calendar/cal-move.el b/lisp/calendar/cal-move.el
index b0a8917209f..70d2c27d96f 100644
--- a/lisp/calendar/cal-move.el
+++ b/lisp/calendar/cal-move.el
@@ -217,6 +217,39 @@ calendar-scroll-right-three-months
                      last-nonmenu-event))
   (calendar-scroll-left (* -3 arg) event))
 
+(defvar calendar-recenter-last-op nil
+  "Last calendar recenter operation performed.")
+
+;;;###cal-autoload
+(defun calendar-recenter ()
+  "Scroll the calendar so that the month of the date at point is centered.
+Next invocation puts this month on the leftmost position, and another
+invocation puts this month on the rightmost position.  Subsequent
+invocations reuse the same order in a cyclical manner."
+  (interactive)
+  (let ((positions '(center first last))
+        (cursor-month (calendar-extract-month
+                       (calendar-cursor-to-nearest-date))))
+    ;; Update global last position upon repeat.
+    (setq calendar-recenter-last-op
+          (if (eq this-command last-command)
+              (car (or (cdr (memq calendar-recenter-last-op positions))
+                       positions))
+            (car positions)))
+    ;; XXX: like most functions in calendar, a span of three displayed
+    ;; months is implied here.
+    (cond ((eq calendar-recenter-last-op 'center)
+           (cond ((= cursor-month (1- displayed-month))
+                  (calendar-scroll-right))
+                 ((= cursor-month (1+ displayed-month))
+                  (calendar-scroll-left))))
+          ;; Other sub-cases should not happen as we should be centered
+          ;; from here.
+          ((eq calendar-recenter-last-op 'first)
+           (calendar-scroll-left))
+          ((eq calendar-recenter-last-op 'last)
+           (calendar-scroll-right 2)))))
+
 ;;;###cal-autoload
 (defun calendar-forward-day (arg)
   "Move the cursor forward ARG days.
diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el
index 058982647fe..b0f6a9152d5 100644
--- a/lisp/calendar/calendar.el
+++ b/lisp/calendar/calendar.el
@@ -1593,6 +1593,7 @@ calendar-mode-map
     (define-key map "\C-x>" 'calendar-scroll-left)
     (define-key map [next]  'calendar-scroll-left-three-months)
     (define-key map "\C-v"  'calendar-scroll-left-three-months)
+    (define-key map "\C-l"  'calendar-recenter)
     (define-key map "\C-b"  'calendar-backward-day)
     (define-key map "\C-p"  'calendar-backward-week)
     (define-key map "\e{"   'calendar-backward-month)
-- 
2.49.0

-- 
Manuel Giraud