branch: elpa/casual
commit d8ee219ef906783ebd251c5cf0a085e54348efaa
Author: Charles Choi <[email protected]>
Commit: Charles Choi <[email protected]>
Add Casual Timezone Planner Features
- Add f/b bindings for forward/backward day in planner.
- Add highlighting for working hours with variable customization.
(casual-timezone-planner-working-highlight)
- Add customizable working hour glyph (casual-timezone-working-hour-glyph).
- Add support for world-clock to casual-timezone-planner-tmenu.
---
docs/casual.info | 39 +++++++---
docs/casual.org | 15 +++-
docs/images/casual-timezone-planner-screenshot.png | Bin 458462 -> 486962 bytes
lisp/casual-timezone-settings.el | 37 ++++++++-
lisp/casual-timezone-utils.el | 83 +++++++++++++++++++--
tests/test-casual-timezone-settings.el | 6 +-
tests/test-casual-timezone-utils.el | 12 +++
7 files changed, 171 insertions(+), 21 deletions(-)
diff --git a/docs/casual.info b/docs/casual.info
index 7be08ce860..072aa56b16 100644
--- a/docs/casual.info
+++ b/docs/casual.info
@@ -11,7 +11,7 @@ File: casual.info, Node: Top, Next: Motivations, Up: (dir)
Casual User Guide
*****************
-Version: 2.4.3
+Version: 2.5.0
Casual is a project to re-imagine the primary user interface for Emacs
using keyboard-driven menus.
@@ -1166,6 +1166,26 @@ Command Format
‘casual-timezone-local-time-to-remote’
‘casual-timezone-convert-datestamp-format’
‘casual-timezone-remote-time-to-local’
‘casual-timezone-convert-datestamp-format’
+These variables can be customized via the Transient menu
+‘casual-timezone-settings-tmenu’.
+
+Planner Configuration
+=====================
+
+The following variables can control how working hours are displayed in
+the timezone planner.
+
+ • ‘casual-timezone-working-hours-range’ will set the range (start,
+ stop) of working hours. The values are integers that map to
+ 24-hour time (0..23).
+ • ‘casual-timezone-working-hour-glyph’ will set the glyph used to
+ denote a working hour (default is ☼).
+ • ‘casual-timezone-planner-working-highlight’ will set the face used
+ to highlight a working hour.
+
+These variables can be customized via the Transient menu
+‘casual-timezone-settings-tmenu’.
+
File: casual.info, Node: UX Conventions, Next: Customization, Prev: Casual
Modes, Up: Top
@@ -1364,6 +1384,7 @@ File: casual.info, Node: Index, Next: Variable Index,
Prev: Acknowledgments,
* Timezone: Timezone. (line 6)
* Timezone Configuration: Timezone. (line 19)
* Timezone Formatting: Timezone. (line 47)
+* Timezone Planner Configuration: Timezone. (line 71)
* Timezone Usage: Timezone. (line 31)
* Transient Conventions: Transient Conventions.
(line 6)
@@ -1401,14 +1422,14 @@ Node: I-Search24468
Node: Make25629
Node: RE-Builder28013
Node: Timezone31437
-Node: UX Conventions33834
-Node: Customization36535
-Node: Feedback & Discussion36909
-Node: Sponsorship37327
-Node: About37621
-Node: Acknowledgments37898
-Node: Index38280
-Node: Variable Index42474
+Node: UX Conventions34567
+Node: Customization37268
+Node: Feedback & Discussion37642
+Node: Sponsorship38060
+Node: About38354
+Node: Acknowledgments38631
+Node: Index39013
+Node: Variable Index43280
End Tag Table
diff --git a/docs/casual.org b/docs/casual.org
index f9514402c2..4b7d9ca2bf 100644
--- a/docs/casual.org
+++ b/docs/casual.org
@@ -6,7 +6,7 @@
#+OPTIONS: ':t toc:t author:t email:t compact-itemx:t
#+LANGUAGE: en
-#+MACRO: version 2.4.3
+#+MACRO: version 2.5.0
#+TEXINFO_FILENAME: casual.info
#+TEXINFO_HEADER: @syncodeindex pg cp
@@ -849,6 +849,19 @@ The following table shows which format variable applies to
which command.
| ~casual-timezone-local-time-to-remote~ |
~casual-timezone-convert-datestamp-format~ |
| ~casual-timezone-remote-time-to-local~ |
~casual-timezone-convert-datestamp-format~ |
+These variables can be customized via the Transient menu
~casual-timezone-settings-tmenu~.
+
+#+TEXINFO: @unnumberedsec Planner Configuration
+#+CINDEX: Timezone Planner Configuration
+
+The following variables can control how working hours are displayed in the
timezone planner.
+
+- ~casual-timezone-working-hours-range~ will set the range (start, stop) of
working hours. The values are integers that map to 24-hour time (0..23).
+- ~casual-timezone-working-hour-glyph~ will set the glyph used to denote a
working hour (default is ☼).
+- ~casual-timezone-planner-working-highlight~ will set the face used to
highlight a working hour.
+
+These variables can be customized via the Transient menu
~casual-timezone-settings-tmenu~.
+
* UX Conventions
#+CINDEX: UX Conventions
diff --git a/docs/images/casual-timezone-planner-screenshot.png
b/docs/images/casual-timezone-planner-screenshot.png
index 78cf0fff96..987ba5a000 100644
Binary files a/docs/images/casual-timezone-planner-screenshot.png and
b/docs/images/casual-timezone-planner-screenshot.png differ
diff --git a/lisp/casual-timezone-settings.el b/lisp/casual-timezone-settings.el
index 62cbf1d76f..ae54c63f32 100644
--- a/lisp/casual-timezone-settings.el
+++ b/lisp/casual-timezone-settings.el
@@ -28,10 +28,21 @@
(transient-define-prefix casual-timezone-settings-tmenu ()
"Casual Timezone settings menu."
["Timezone: Settings"
- ["Customize"
- ("w" "Working Hours" casual-timezone--customize-working-hours-range)
- (casual-lib-customize-unicode)
- (casual-lib-customize-hide-navigation)]
+ ["Working Hours"
+ ("r" "Range" casual-timezone--customize-working-hours-range
+ :description (lambda ()
+ (format
+ "Range (%d..%d)"
+ (map-elt casual-timezone-working-hours-range :start)
+ (map-elt casual-timezone-working-hours-range :stop))))
+
+ ("g" "Glyph" casual-timezone--customize-working-hour-glyph
+ :description (lambda ()
+ (format
+ "Glyph (%s)"
+ casual-timezone-working-hour-glyph)))
+
+ ("F" "Face" casual-timezone--customize-planner-working-highlight)]
["Formats"
("c" "Convert" casual-timezone--customize-convert-timestamp-format
@@ -51,12 +62,30 @@
(current-time)))))
("f" "Describe Format" casual-timezone--describe-format-time-string)]]
+ [:class transient-row
+ (casual-lib-customize-unicode)
+ (casual-lib-customize-hide-navigation)]
+
[:class transient-row
(casual-lib-quit-one)
("a" "About" casual-timezone-about :transient nil)
(casual-lib-quit-all)])
+(defun casual-timezone--customize-working-hour-glyph ()
+ "Set working hour glyph.
+
+This customizes the variable `casual-timezone-working-hour-glyph'."
+ (interactive)
+ (customize-variable 'casual-timezone-working-hour-glyph))
+
+(defun casual-timezone--customize-planner-working-highlight ()
+ "Set working hour highlight face.
+
+This customizes the face `casual-timezone-working-highlight'."
+ (interactive)
+ (customize-face 'casual-timezone-planner-working-highlight))
+
(defun casual-timezone--customize-working-hours-range ()
"Set working hours range.
diff --git a/lisp/casual-timezone-utils.el b/lisp/casual-timezone-utils.el
index f8e0a5b364..8793b0abc1 100644
--- a/lisp/casual-timezone-utils.el
+++ b/lisp/casual-timezone-utils.el
@@ -30,6 +30,8 @@
(defconst casual-timezone-unicode-db
'((:previous . '("↑" "Previous"))
(:next . '("↓" "Next"))
+ (:forward . '("→" "Forward"))
+ (:backward . '("←" "Backward"))
(:current . '("⨀" "Current Hour")))
"Unicode symbol DB to use for Timezone Transient menus.")
@@ -62,7 +64,6 @@ The specification of this variable conforms to the format
string used by
:type 'string
:group 'casual)
-
(defcustom casual-timezone-datestamp-format "%a %b %-e %Y, %l:%M %p"
"Datestamp format used by `casual-timezone-planner'.
@@ -76,6 +77,31 @@ If 24 hour clock time is preferred, use ‘%k’ instead of
‘%l’."
:type 'string
:group 'casual)
+(defcustom casual-timezone-working-hour-glyph "☼"
+ "Working hour glyph used by `casual-timezone-planner'.
+
+This customizable variable contains the glyph used to annotate a
+working hour in `casual-timezone-planner'."
+ :type 'string
+ :group 'casual)
+
+(defface casual-timezone-planner-working-highlight
+ '((((type tty) (class color))
+ :background "gray25")
+ (((class color) (min-colors 88) (background light))
+ :background "#FDFEB1" :foreground "black")
+ (((class color) (min-colors 88) (background dark))
+ :background "gray25")
+ (((class color) (min-colors 16) (background light))
+ :background "yellow")
+ (((class color) (min-colors 16) (background dark))
+ :background "olive")
+ (((class color) (min-colors 8))
+ :background "olive" :foreground "black")
+ (t :inverse-video t))
+ "Casual Timezone Planner working hours highlight."
+ :group 'casual)
+
(defun casual-timezone-zone-info ()
"List of timezones in zoneinfo database.
@@ -207,6 +233,8 @@ The format of the timestamp is defined in the variable
"t" #'casual-timezone-planner-current-time
"l" #'casual-timezone-planner-current-local
"r" #'casual-timezone-planner-current-remote
+ "f" #'casual-timezone-planner-forward-day
+ "b" #'casual-timezone-planner-backward-day
"p" #'previous-line
"n" #'next-line
"q" #'quit-window
@@ -263,7 +291,6 @@ customized via the variable
`casual-timezone-working-hours-range'."
(get-buffer-create tz-buffer-name)
(switch-to-buffer (set-buffer tz-buffer-name))
- ;;(read-only-mode)
(casual-timezone-planner-mode)
(let ((inhibit-read-only t))
@@ -381,11 +408,46 @@ This formats the output result using the customizable
variables
(if (and (>= hour (map-elt casual-timezone-working-hours-range :start))
(<= hour (map-elt casual-timezone-working-hours-range :stop)))
- (concat datestamp " " "☼")
+ (propertize
+ (concat datestamp " " casual-timezone-working-hour-glyph)
+ 'face
+ 'casual-timezone-planner-working-highlight)
datestamp)))
-;; Transients
+(defun casual-timezone-planner-forward-day ()
+ "Move forward one day in timezone planner.
+Note: This command relies on `vtable-update-object' which breaks if the
+window width has changed."
+ (interactive)
+ (unless (vtable-current-table) (error "No planner table"))
+ (casual-timezone--planner-adjust-day nil))
+
+(defun casual-timezone-planner-backward-day ()
+ "Move backward one day in timezone planner.
+
+Note: This command relies on `vtable-update-object' which breaks if the
+window width has changed."
+ (interactive)
+ (unless (vtable-current-table) (error "No planner table"))
+ (casual-timezone--planner-adjust-day t))
+
+(defun casual-timezone--planner-adjust-day (backward)
+ "If BACKWARD is non-nil, adjust timezone planner -24 hours, otherwise ahead."
+ (let* ((table (vtable-current-table))
+ (objects (oref table objects))
+ (posix-day 86400)
+ (time-adjust (if backward
+ (* -1 posix-day)
+ posix-day)))
+ (mapc (lambda (obj)
+ (let ((adjusted-obj
+ (seq-map (lambda (x) (+ x time-adjust)) obj)))
+ (vtable-update-object table adjusted-obj obj)))
+ objects)
+ (casual-timezone-jump-to-relative-now)))
+
+;; Transients
(transient-define-prefix casual-timezone-planner-tmenu ()
"Main menu for Casual Timezone."
@@ -401,13 +463,22 @@ This formats the output result using the customizable
variables
:description (lambda () (casual-timezone-unicode-get :next))
:transient t)]
+ ["Day"
+ ("f" "Forward" casual-timezone-planner-forward-day
+ :description (lambda () (casual-timezone-unicode-get :forward))
+ :transient t)
+ ("b" "Backward" casual-timezone-planner-backward-day
+ :description (lambda () (casual-timezone-unicode-get :backward))
+ :transient t)]
+
["Copy Time"
- ("t" "Time" casual-timezone-planner-current-time)
+ ("t" "Times" casual-timezone-planner-current-time)
("l" "Local" casual-timezone-planner-current-local)
("r" "Remote" casual-timezone-planner-current-remote)]
["Misc"
- ("z" "Planner…" casual-timezone-planner)]]
+ ("z" "Planner…" casual-timezone-planner)
+ ("w" "World Clock" world-clock)]]
[:class transient-row
(casual-lib-quit-one)
diff --git a/tests/test-casual-timezone-settings.el
b/tests/test-casual-timezone-settings.el
index fa8a7dd040..6eef0cc2e3 100644
--- a/tests/test-casual-timezone-settings.el
+++ b/tests/test-casual-timezone-settings.el
@@ -33,12 +33,16 @@
(casualt-timezone-setup)
(cl-letf ((casualt-mock #'casual-timezone-about)
(casualt-mock #'casual-timezone--customize-working-hours-range)
+ (casualt-mock #'casual-timezone--customize-working-hour-glyph)
+ (casualt-mock
#'casual-timezone--customize-planner-working-highlight)
(casualt-mock
#'casual-timezone--customize-convert-timestamp-format)
(casualt-mock #'casual-timezone--customize-datestamp-format)
(casualt-mock #'casual-timezone--describe-format-time-string))
(let ((test-vectors
- '((:binding "w" :command
casual-timezone--customize-working-hours-range)
+ '((:binding "r" :command
casual-timezone--customize-working-hours-range)
+ (:binding "g" :command
casual-timezone--customize-working-hour-glyph)
+ (:binding "F" :command
casual-timezone--customize-planner-working-highlight)
(:binding "c" :command
casual-timezone--customize-convert-timestamp-format)
(:binding "p" :command
casual-timezone--customize-datestamp-format)
(:binding "f" :command
casual-timezone--describe-format-time-string)
diff --git a/tests/test-casual-timezone-utils.el
b/tests/test-casual-timezone-utils.el
index a9f8c6c74b..228ff76866 100644
--- a/tests/test-casual-timezone-utils.el
+++ b/tests/test-casual-timezone-utils.el
@@ -29,10 +29,16 @@
(ert-deftest test-casual-timezone-unicode-get ()
(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 :current) "Current
Hour"))
(should (string-equal (casual-timezone-unicode-get :previous) "Previous"))
(should (string-equal (casual-timezone-unicode-get :next) "Next")))
(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 :current) "⨀"))
(should (string-equal (casual-timezone-unicode-get :previous) "↑"))
(should (string-equal (casual-timezone-unicode-get :next) "↓"))))
@@ -42,20 +48,26 @@
(cl-letf ((casualt-mock #'casual-timezone-jump-to-relative-now)
(casualt-mock #'previous-line)
(casualt-mock #'next-line)
+ (casualt-mock #'casual-timezone-planner-forward-day)
+ (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)
+ (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 "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 "z" :command casual-timezone-planner)
+ (:binding "w" :command world-clock)
(:binding "q" :command quit-window))))
(casualt-suffix-testcase-runner test-vectors