about summary refs log tree commit diff
path: root/tools/emacs-pkgs/dottime/dottime.el
blob: b4445d3c0bdc564f8bd8a8f33cb261f025531b2c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
;;; dottime.el --- use dottime in the modeline
;;
;; Copyright (C) 2019 Google Inc.
;;
;; Author: Vincent Ambo <tazjin@google.com>
;; Version: 1.0
;; Package-Requires: (cl-lib)
;;
;;; Commentary:
;;
;; This package changes the display of time in the modeline to use
;; dottime (see https://dotti.me/) instead of the standard time
;; display.
;;
;; Modeline dottime display is enabled by calling
;; `dottime-display-mode' and dottime can be used in Lisp code via
;; `dottime-format'.

(require 'cl-lib)
(require 'time)

(defun dottime--format-string ()
  "Creates the dottime format string for `format-time-string'
  based on the local timezone."

  (let* ((offset-sec (car (current-time-zone)))
         (offset-hours (/ offset-sec 60 60)))
    (if (/= offset-hours 0)
        (concat "%m-%dT%H·%M" (format "%0+3d" offset-hours))
      "%m-%dT%H·%M")))

(defun dottime--display-time-update-advice (orig)
  "Function used as advice to `display-time-update' with a
  rebound definition of `format-time-string' that renders all
  timestamps as dottime."

  (cl-letf* ((format-orig (symbol-function 'format-time-string))
             ((symbol-function 'format-time-string)
              (lambda (&rest _)
                (funcall format-orig (dottime--format-string) nil t))))
    (funcall orig)))

(defun dottime-format (&optional time)
  "Format the given TIME in dottime. If TIME is nil, the current
  time will be used."

  (format-time-string (dottime--format-string) time t))

(defun dottime-display-mode (arg)
  "Enable time display as dottime. Disables dottime if called
  with prefix 0 or nil."

  (interactive "p")
  (if (or (eq arg 0) (eq arg nil))
      (advice-remove 'display-time-update #'dottime--display-time-update-advice)
    (advice-add 'display-time-update :around #'dottime--display-time-update-advice))
  (display-time-update))

;; Amend the time display in telega.el to use dottime.
;;
;; This will never display offsets in the chat window, as those are
;; always visible in the modeline anyways.
(when (-contains? features 'telega)
  (defun telega-ins--dottime-advice (orig timestamp)
    (let* ((dtime (decode-time timestamp t))
           (current-ts (time-to-seconds (current-time)))
           (ctime (decode-time current-ts))
           (today00 (telega--time-at00 current-ts ctime)))
      (if (> timestamp today00)
          (telega-ins-fmt "%02d·%02d" (nth 2 dtime) (nth 1 dtime))
        (funcall orig timestamp))))

  (advice-add 'telega-ins--date :around #'telega-ins--dottime-advice))

(provide 'dottime)