:type 'natnum
:version "28.1")
+(defcustom world-clock-sort-order nil
+ "Sort order of entries in the `world-clock'.
+This variable can take a few different forms:
+
+- A nil value indicates no sorting, and the displayed order is the same
+ as in `world-clock-list'. This is the default.
+
+- A string is taken as a format for `format-time-string', whose output
+ is used as the sorting key. For example, an ISO 8601 format `\"%FT%T\"'
+ means entries are sorted in chronological order.
+
+- A cons cell of the form (STRING . BOOL) again provides a format for
+ `format-time-string'. The boolean part controls the sort direction.
+ For example, `(\"%FT%T\" . t)' means entries are sorted in reverse
+ chronological order.
+
+- A function that takes a list of (TIMEZONE LABEL) entries and a TIME as
+ arguments, and returns another list of entries."
+ :version "31.1"
+ :type '(choice (const :tag "No sorting" nil)
+ (const :tag "Chronological order" "%FT%T")
+ (const :tag "Reverse chronological order" ("%FT%T" . t))
+ (const :tag "Time of day order" "%T")
+ (const :tag "Reverse time of day order" ("%T" . t))
+ (string :tag "Format string")
+ (cons :tag "Format string and reverse flag"
+ (string :tag "Format string")
+ (boolean :tag "Reverse"))
+ (function :tag "Sorting function")))
+
(defface world-clock-label
'((t :inherit font-lock-variable-name-face))
"Face for time zone label in `world-clock' buffer.")
(defvar world-clock--timer nil
"The current world clock timer.")
+(defun world-clock--sort-entries (tzlist time)
+ "Sort TZLIST according to `world-clock-sort-order' at a given TIME."
+ (pcase world-clock-sort-order
+ ((pred null) tzlist)
+ ((or (and (pred stringp) format)
+ `(,(and (pred stringp) format) .
+ ,(and (pred booleanp) reverse)))
+ (sort tzlist
+ :key (lambda (entry)
+ (format-time-string format time (car entry)))
+ :reverse reverse))
+ ((pred functionp) (funcall world-clock-sort-order tzlist time))
+ (_ (error "Invalid `world-clock-sort-order': `%s'"
+ world-clock-sort-order))))
+
(defun world-clock-display (alist)
- "Replace current buffer text with times in various zones, based on ALIST."
- (let ((inhibit-read-only t)
- (buffer-undo-list t)
- (now (current-time))
- (max-width 0)
- result fmt)
+ "Replace current buffer text with times in various zones, based on ALIST.
+The entries are ordered according to `world-clock-sort-order'."
+ (let* ((inhibit-read-only t)
+ (buffer-undo-list t)
+ (now (current-time))
+ (zones (world-clock--sort-entries alist now))
+ (max-width 0)
+ result fmt)
(erase-buffer)
- (dolist (zone alist)
+ (dolist (zone zones)
(let* ((label (cadr zone))
(width (string-width label)))
(push (cons label