branch: elpa/casual
commit 59bd92d024eeb77be4b985611b6675ad5b8f0efe
Merge: 65e9a61038 77c3d73f9e
Author: Charles Choi <[email protected]>
Commit: GitHub <[email protected]>

    Merge pull request #307 from 
kickingvegas/merge-development-to-main-20251006_140334
    
    Merge development to main 20251006_140334
---
 docs/casual.info                                   | Bin 132097 -> 132785 bytes
 docs/casual.org                                    |   6 +-
 docs/casual.texi                                   |  29 ++++---
 docs/images/casual-timezone-planner-screenshot.png | Bin 190433 -> 197780 bytes
 docs/timezone.org                                  |  21 +++--
 lisp/casual-timezone-utils.el                      |  88 ++++++++++++++-------
 lisp/casual.el                                     |   2 +-
 tests/test-casual-timezone-utils.el                |  16 +++-
 8 files changed, 108 insertions(+), 54 deletions(-)

diff --git a/docs/casual.info b/docs/casual.info
index 0a396eadfa..751861b6d7 100644
Binary files a/docs/casual.info and b/docs/casual.info differ
diff --git a/docs/casual.org b/docs/casual.org
index aadd126484..778a29c2e3 100644
--- a/docs/casual.org
+++ b/docs/casual.org
@@ -5,7 +5,7 @@
 #+EMAIL: [email protected]
 #+OPTIONS: ':t toc:t author:t email:t H:4 f:t
 #+LANGUAGE: en
-#+MACRO: version 2.9.0
+#+MACRO: version 2.9.1
 #+MACRO: kbd (eval (org-texinfo-kbd-macro $1))
 #+TEXINFO_FILENAME: casual.info
 #+TEXINFO_CLASS: casual
@@ -55,7 +55,7 @@ Copyright © 2024-2025 Charles Y. Choi
 ** Motivations
 #+CINDEX: Motivations
 
-#+TEXINFO: @majorheading Goals
+#+TEXINFO: @subheading Goals
 
 - To provide a keyboard-driven menu UI toolkit for common Emacs commands.
 
@@ -64,7 +64,7 @@ Copyright © 2024-2025 Charles Y. Choi
 - To be a frequently used interface for modes supported by Casual.
 
 
-#+TEXINFO: @majorheading Non-Goals
+#+TEXINFO: @subheading Non-Goals
 
 - Full coverage of all Emacs commands.
 
diff --git a/docs/casual.texi b/docs/casual.texi
index ab469193bf..678806b0cb 100644
--- a/docs/casual.texi
+++ b/docs/casual.texi
@@ -20,7 +20,7 @@ Copyright © 2024-2025 Charles Y@. Choi
 @finalout
 @titlepage
 @title Casual User Guide
-@subtitle for version 2.9.0
+@subtitle for version 2.9.1
 @author Charles Y@. Choi (@email{kickingvegas@@gmail.com})
 @page
 @vskip 0pt plus 1filll
@@ -33,7 +33,7 @@ Copyright © 2024-2025 Charles Y@. Choi
 @node Top
 @top Casual User Guide
 
-Version: 2.9.0
+Version: 2.9.1
 
 Casual is a project to re-imagine the primary user interface for Emacs using 
keyboard-driven menus.
 
@@ -300,7 +300,7 @@ Timezone Usage
 
 @cindex Motivations
 
-@majorheading Goals
+@subheading Goals
 
 @itemize
 @item
@@ -314,7 +314,7 @@ To be a frequently used interface for modes supported by 
Casual.
 @end itemize
 
 
-@majorheading Non-Goals
+@subheading Non-Goals
 
 @itemize
 @item
@@ -3076,6 +3076,8 @@ Casual Timezone is a library of commands to work with 
different time zones. Answ
 
 Casual Timezone only supports systems that have a 
@uref{https://en.wikipedia.org/wiki/Tz_database, tz database}.
 
+Casual Timezone supports viewing multiple time zones in a tabular view with 
the command @code{casual-timezone-planner} as shown below:
+
 @image{images/casual-timezone-planner-screenshot,,,,png}
 
 @menu
@@ -3090,16 +3092,16 @@ Casual Timezone only supports systems that have a 
@uref{https://en.wikipedia.org
 
 Casual Timezone is configured as part of Casual EditKit in the Tools menu 
(@code{casual-editkit-tools-tmenu}). Refer to the @ref{EditKit Install} section 
for instructions on how to install it.
 
-The main menu for Casual Timezone is @code{casual-timezone-tmenu} for users 
who wish to access it directly.
+The main menu for Casual Timezone can be invoked directly using @code{M-x} 
@code{casual-timezone-tmenu}.
 
 @node Timezone Usage
 @subsection Timezone Usage
 
 @cindex Timezone Usage
 
-@image{images/casual-timezone-planner-screenshot,,,,png}
+@image{images/casual-timezone-tmenu-screenshot,,,,png}
 
-Casual Timezone offers the following commands:
+The main menu for Casual Timezone (@code{casual-timezone-tmenu}) offers the 
following commands:
 
 @itemize
 @item
@@ -3109,12 +3111,19 @@ Casual Timezone offers the following commands:
 @code{casual-timezone-remote-time-to-local} (menu binding: @code{r}) will 
convert a date in a remote time zone to its local equivalent.
 
 @item
-@code{casual-timezone-planner} (menu binding: @code{z}) will generate a table 
comparing hours between the local and a remote timezone on a certain date.
+@code{casual-timezone-planner} (menu binding: @code{z}) will generate a table 
comparing hours between the local and a remote time zone on a certain date. 
Multiple remote time zones can be specified.
 @end itemize
 
-These commands are offered in the menu @code{casual-timezone-tmenu} shown 
below.
 
-@image{images/casual-timezone-tmenu-screenshot,,,,png}
+@subheading Timezone Planner
+
+@image{images/casual-timezone-planner-screenshot,,,,png}
+
+The command @code{casual-timezone-planner} will prompt the user for one or 
more time zones and a date to compare in tabular form the local time with the 
zones selected. Multiple time zones are comma-separated.
+
+In this table, the point can be navigated using the @kbd{p}, @kbd{n}, 
@kbd{@key{TAB}}, and @kbd{S-@key{TAB}} bindings.
+
+Use the @kbd{T} binding to copy the timestamp under the current point to the 
@code{kill-ring}. The @kbd{t} binding will copy all timestamps on the current 
line to the @code{kill-ring}.
 
 @menu
 * Timezone Formatting::
diff --git a/docs/images/casual-timezone-planner-screenshot.png 
b/docs/images/casual-timezone-planner-screenshot.png
index d9d6ac8f2b..7f3ac817c5 100644
Binary files a/docs/images/casual-timezone-planner-screenshot.png and 
b/docs/images/casual-timezone-planner-screenshot.png differ
diff --git a/docs/timezone.org b/docs/timezone.org
index 15b8a0018d..d4a8eb0dcd 100644
--- a/docs/timezone.org
+++ b/docs/timezone.org
@@ -6,6 +6,8 @@ Casual Timezone is a library of commands to work with different 
time zones. Answ
 
 Casual Timezone only supports systems that have a 
[[https://en.wikipedia.org/wiki/Tz_database][tz database]].
 
+Casual Timezone supports viewing multiple time zones in a tabular view with 
the command ~casual-timezone-planner~ as shown below:
+
 [[file:images/casual-timezone-planner-screenshot.png]]
 
 ** Timezone Install
@@ -16,24 +18,31 @@ Casual Timezone only supports systems that have a 
[[https://en.wikipedia.org/wik
 
 Casual Timezone is configured as part of Casual EditKit in the Tools menu 
(~casual-editkit-tools-tmenu~). Refer to the [[#editkit-install][EditKit 
Install]] section for instructions on how to install it.
 
-The main menu for Casual Timezone is ~casual-timezone-tmenu~ for users who 
wish to access it directly.
+The main menu for Casual Timezone can be invoked directly using ~M-x~ 
~casual-timezone-tmenu~.
 
 ** Timezone Usage
 #+CINDEX: Timezone Usage
 
-[[file:images/casual-timezone-planner-screenshot.png]]
+[[file:images/casual-timezone-tmenu-screenshot.png]]
 
-Casual Timezone offers the following commands:
+The main menu for Casual Timezone (~casual-timezone-tmenu~) offers the 
following commands:
 
 - ~casual-timezone-local-time-to-remote~ (menu binding: ~l~) will convert a 
local date to its equivalent in remote time zone.
 
 - ~casual-timezone-remote-time-to-local~ (menu binding: ~r~) will convert a 
date in a remote time zone to its local equivalent.
 
-- ~casual-timezone-planner~ (menu binding: ~z~) will generate a table 
comparing hours between the local and a remote timezone on a certain date.
+- ~casual-timezone-planner~ (menu binding: ~z~) will generate a table 
comparing hours between the local and a remote time zone on a certain date. 
Multiple remote time zones can be specified.
 
-These commands are offered in the menu ~casual-timezone-tmenu~ shown below.
 
-[[file:images/casual-timezone-tmenu-screenshot.png]]
+#+TEXINFO: @subheading Timezone Planner
+
+[[file:images/casual-timezone-planner-screenshot.png]]
+
+The command ~casual-timezone-planner~ will prompt the user for one or more 
time zones and a date to compare in tabular form the local time with the zones 
selected. Multiple time zones are comma-separated.
+
+In this table, the point can be navigated using the {{{kbd(p)}}}, 
{{{kbd(n)}}}, {{{kbd(TAB)}}}, and {{{kbd(S-TAB)}}} bindings.
+
+Use the {{{kbd(T)}}} binding to copy the timestamp under the current point to 
the ~kill-ring~. The {{{kbd(t)}}} binding will copy all timestamps on the 
current line to the ~kill-ring~.
 
 
 *** Timezone Formatting
diff --git a/lisp/casual-timezone-utils.el b/lisp/casual-timezone-utils.el
index 801b765ac4..0eda4308a5 100644
--- a/lisp/casual-timezone-utils.el
+++ b/lisp/casual-timezone-utils.el
@@ -33,6 +33,8 @@
     (:next . '("↓" "Next"))
     (:forward . '("→" "Forward"))
     (:backward . '("←" "Backward"))
+    (:right . '("→" "Right"))
+    (:left . '("←" "Left"))
     (:current . '("⨀" "Current Hour")))
 
   "Unicode symbol DB to use for Timezone Transient menus.")
@@ -69,7 +71,7 @@ The specification of this variable conforms to the format 
string used by
   "Datestamp format used by `casual-timezone-planner'.
 
 This customizable variable determines the reporting format used
-by the command `casual-timezone-planner'. The specification of this
+by the command `casual-timezone-planner'.  The specification of this
 variable conforms to the format string used by
 `format-time-string' as described in Info node `(elisp) Time
 Parsing'.
@@ -260,6 +262,7 @@ The format of the timestamp is defined in the variable
   "k" #'previous-line
   "w" #'world-clock
   "z" #'casual-timezone-planner
+  "T" #'casual-timezone-planner-current-point
   "c" #'calendar)
 
 (define-derived-mode casual-timezone-planner-mode
@@ -267,10 +270,16 @@ The format of the timestamp is defined in the variable
   "Major mode for Timezone Planner."
   (hl-line-mode t))
 
-(defun casual-timezone-planner ()
-  "Generate table comparing hours between local and a remote timezone.
+(defun casual-timezone-planner (remote-timezones datestamp)
+  "Generate hours table between local and REMOTE-TIMEZONES on DATESTAMP.
 
-This command will prompt the user twice:
+REMOTE-TIMEZONES is a list of timezones to compare local time with. It
+can be either be a `list' of strings or a comma or space separated
+`string' type.
+
+DATESTAMP is a string in YYYY-MM-DD format.
+
+When called interactively, this command will prompt the user twice:
  1. to specify a remote timezone
  2. to specify a calendar day
 
@@ -280,18 +289,19 @@ updated) comparing the hours between the two timezones.
 The report datestamp format can be customized via the variable
 `casual-timezone-datestamp-format'.
 
-Working hours are annotated with a ☼. The range of working hours can be
+Working hours are annotated with a ☼.  The range of working hours can be
 customized via the variable `casual-timezone-working-hours-range'."
-  (interactive)
+  (interactive (list
+                (completing-read-multiple "Remote Timezone(s): " 
(casual-timezone-zone-info))
+                (org-read-date)))
+  (when (stringp remote-timezones) (setq remote-timezones (split-string 
remote-timezones "[, ]+")))
   (unless (not (eq system-type 'windows-nt))
     (error "Not available on Windows"))
 
-  (let* ((remote-tz (completing-read-default "Remote Timezone: " 
(casual-timezone-zone-info)))
-         ;; (tzcode (casual-timezone-offset-8601 (nth 0 (current-time-zone nil 
remote-tz))))
-         (datestamp (org-read-date))
+  (let* (;; (tzcode (casual-timezone-offset-8601 (nth 0 (current-time-zone nil 
remote-tz))))
          (local-tz (nth 1 (current-time-zone)))
          (start-time (date-to-time (concat datestamp " " "05:00")))
-         (increments (seq-map (lambda (x) (seconds-to-time (* x 
3600)))(number-sequence 0 25)))
+         (increments (seq-map (lambda (x) (seconds-to-time (* x 3600))) 
(number-sequence 0 25)))
          (tztimes (seq-map (lambda (x) (time-add start-time x)) increments))
          (local-times
           (seq-map
@@ -299,13 +309,16 @@ customized via the variable 
`casual-timezone-working-hours-range'."
            tztimes))
          (remote-times
           (seq-map
-           (lambda (x) (time-to-seconds (date-to-time (format-time-string
-                                      "%Y-%m-%dT%H:%M:%S"
-                                      (date-to-time (format-time-string 
(concat x " " local-tz)))
-                                      remote-tz))))
-           local-times))
-         (tz-data (seq-mapn #'list tztimes remote-times))
-         (tz-buffer-name (format "*%s - %s*" local-tz remote-tz)))
+           (lambda (remote-tz)
+             (seq-map
+              (lambda (x) (time-to-seconds (date-to-time (format-time-string
+                                                          "%Y-%m-%dT%H:%M:%S"
+                                                          (date-to-time 
(format-time-string (concat x " " local-tz)))
+                                                          remote-tz))))
+              local-times))
+           remote-timezones))
+         (tz-data (apply #'seq-mapn #'list tztimes remote-times))
+         (tz-buffer-name (format "*%s - %s*" local-tz (string-join 
remote-timezones " - "))))
 
     (get-buffer-create tz-buffer-name)
     (switch-to-buffer (set-buffer tz-buffer-name))
@@ -314,15 +327,16 @@ customized via the variable 
`casual-timezone-working-hours-range'."
     (let ((inhibit-read-only t))
         (erase-buffer)
         (make-vtable
-         :columns `((:name ,local-tz :width 30 :align left) ;; !!! For some 
reason I can't pass in local-tz
-                    (:name ,remote-tz :width 30 :align left))
+         :columns (append
+                   `((:name ,local-tz :width 30 :align left)) ;; !!! For some 
reason I can't pass in local-tz
+                   (seq-map (lambda (remote-tz)
+                              `(:name ,remote-tz :width 30 :align left))
+                            remote-timezones))
 
          :objects tz-data
 
          :getter `(lambda (issue column table)
-                   (pcase (vtable-column table column)
-                     (,local-tz (nth 0 issue))
-                     (,remote-tz (nth 1 issue))))
+                    (nth column issue))
 
          :formatter `(lambda (value column table)
                        (casual-timezone--date-formatter value))
@@ -342,13 +356,14 @@ The format of the timestamp is defined in the variable
     (kill-new result)
     (message result)))
 
-(defun casual-timezone-planner-current-remote ()
-  "Copy remote time on current line to `kill-ring'.
+(defun casual-timezone-planner-current-point ()
+  "Copy time at current point to `kill-ring'.
 
 The format of the timestamp is defined in the variable
 `casual-timezone-datestamp-format'."
   (interactive)
-  (let ((result (casual-timezone-planner--format-current-index 1)))
+  (let ((result (casual-timezone-planner--format-current-index
+                 (vtable-current-column))))
     (kill-new result)
     (message result)))
 
@@ -358,9 +373,13 @@ The format of the timestamp is defined in the variable
 The format of the timestamp is defined in the variable
 `casual-timezone-datestamp-format'."
   (interactive)
-  (let* ((local (casual-timezone-planner--format-current-index 0))
-         (remote (casual-timezone-planner--format-current-index 1))
-         (result (format "%s, %s" local remote)))
+  (let* ((result
+          (string-join
+           (seq-map-indexed
+            (lambda (_ i)
+              (casual-timezone-planner--format-current-index i))
+            (vtable-current-object))
+           "; ")))
     (kill-new result)
     (message result)))
 
@@ -471,6 +490,7 @@ window width has changed."
 
   ["Casual Timezone"
    ["Navigation"
+    :pad-keys t
     ("." "Current Hour" casual-timezone-jump-to-relative-now
      :description (lambda () (casual-timezone-unicode-get :current))
      :transient t)
@@ -479,6 +499,12 @@ window width has changed."
      :transient t)
     ("n" "Next" next-line
      :description (lambda () (casual-timezone-unicode-get :next))
+     :transient t)
+    ("TAB" "Right" vtable-next-column
+     :description (lambda () (casual-timezone-unicode-get :right))
+     :transient t)
+    ("S-TAB" "Left" vtable-previous-column
+     :description (lambda () (casual-timezone-unicode-get :left))
      :transient t)]
 
    ["Day"
@@ -492,11 +518,13 @@ window width has changed."
    ["Copy Time"
     ("t" "Times" casual-timezone-planner-current-time)
     ("l" "Local" casual-timezone-planner-current-local)
-    ("r" "Remote" casual-timezone-planner-current-remote)]
+    ;; ("r" "Remote" casual-timezone-planner-current-remote)
+    ("T" "Point" casual-timezone-planner-current-point)]
 
    ["Misc"
     ("z" "Planner…" casual-timezone-planner)
-    ("w" "World Clock" world-clock)]]
+    ("w" "World Clock" world-clock)
+    ("c" "Calendar" calendar)]]
 
   [:class transient-row
    (casual-lib-quit-one)
diff --git a/lisp/casual.el b/lisp/casual.el
index dee336866f..b07d5c0364 100644
--- a/lisp/casual.el
+++ b/lisp/casual.el
@@ -5,7 +5,7 @@
 ;; Author: Charles Choi <[email protected]>
 ;; URL: https://github.com/kickingvegas/casual
 ;; Keywords: tools, wp
-;; Version: 2.9.0
+;; Version: 2.9.1-rc.1
 ;; Package-Requires: ((emacs "29.1") (transient "0.9.0"))
 
 ;; This program is free software; you can redistribute it and/or modify
diff --git a/tests/test-casual-timezone-utils.el 
b/tests/test-casual-timezone-utils.el
index 1fea140fd9..ee06be4998 100644
--- a/tests/test-casual-timezone-utils.el
+++ b/tests/test-casual-timezone-utils.el
@@ -31,6 +31,8 @@
   (let ((casual-lib-use-unicode nil))
     (should (string-equal (casual-timezone-unicode-get :forward) "Forward"))
     (should (string-equal (casual-timezone-unicode-get :backward) "Backward"))
+    (should (string-equal (casual-timezone-unicode-get :right) "Right"))
+    (should (string-equal (casual-timezone-unicode-get :left) "Left"))
     (should (string-equal (casual-timezone-unicode-get :current) "Current 
Hour"))
     (should (string-equal (casual-timezone-unicode-get :previous) "Previous"))
     (should (string-equal (casual-timezone-unicode-get :next) "Next")))
@@ -38,6 +40,8 @@
   (let ((casual-lib-use-unicode t))
     (should (string-equal (casual-timezone-unicode-get :forward) "→"))
     (should (string-equal (casual-timezone-unicode-get :backward) "←"))
+    (should (string-equal (casual-timezone-unicode-get :right) "→"))
+    (should (string-equal (casual-timezone-unicode-get :left) "←"))
     (should (string-equal (casual-timezone-unicode-get :current) "⨀"))
     (should (string-equal (casual-timezone-unicode-get :previous) "↑"))
     (should (string-equal (casual-timezone-unicode-get :next) "↓"))))
@@ -52,20 +56,24 @@
               (casualt-mock #'casual-timezone-planner-backward-day)
               (casualt-mock #'casual-timezone-planner-current-time)
               (casualt-mock #'casual-timezone-planner-current-local)
-              (casualt-mock #'casual-timezone-planner-current-remote)
+              (casualt-mock #'casual-timezone-planner-current-point)
+              (casualt-mock #'vtable-next-column)
+              (casualt-mock #'vtable-previous-column)
               (casualt-mock #'casual-timezone-planner)
               (casualt-mock #'world-clock)
               (casualt-mock #'quit-window))
 
       (let ((test-vectors
              '((:binding "." :command casual-timezone-jump-to-relative-now)
-               (:binding "p" :command previous-line)
                (:binding "n" :command next-line)
+               (:binding "p" :command previous-line)
                (:binding "f" :command casual-timezone-planner-forward-day)
                (:binding "b" :command casual-timezone-planner-backward-day)
                (:binding "t" :command casual-timezone-planner-current-time)
                (:binding "l" :command casual-timezone-planner-current-local)
-               (:binding "r" :command casual-timezone-planner-current-remote)
+               (:binding "TAB" :command vtable-next-column)
+               (:binding "S-TAB" :command vtable-previous-column)
+               (:binding "T" :command casual-timezone-planner-current-point)
                (:binding "z" :command casual-timezone-planner)
                (:binding "w" :command world-clock)
                (:binding "q" :command quit-window))))
@@ -112,7 +120,7 @@
     (should (eq (keymap-lookup test-map ".") 
#'casual-timezone-jump-to-relative-now))
     (should (eq (keymap-lookup test-map "t") 
#'casual-timezone-planner-current-time))
     (should (eq (keymap-lookup test-map "l") 
#'casual-timezone-planner-current-local))
-    (should (eq (keymap-lookup test-map "r") 
#'casual-timezone-planner-current-remote))
+    (should (eq (keymap-lookup test-map "T") 
#'casual-timezone-planner-current-point))
     (should (eq (keymap-lookup test-map "p") #'previous-line))
     (should (eq (keymap-lookup test-map "n") #'next-line))
     (should (eq (keymap-lookup test-map "q") #'quit-window))

Reply via email to