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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
;;; modeline.el -*- lexical-binding: t; -*-
;;;
;;; Author: Jakob L. Kreuze <zerodaysfordays@sdf.org>
;;; URL: https://git.sr.ht/~jakob/.emacs.d/
;;;
;;; My custom modeline for Emacs, which seeks to fit the dual role of a
;;; functional status indicator for Emacs, as well as a "bar" in the sense of a
;;; traditional tiling window manager.
;;;
;; My implementation of a clock for the modeline. The modeline is refreshed by a
;; timer to ensure that it doesn't go too stale, as it could theoretically go
;; several minutes without being updated.
(defun mode-line-time ()
(format-time-string "%Y-%m-%d %H:%M"))
(let ((timer (run-at-time t 60.0 #'ignore)))
(timer-set-function timer
(lambda ()
(force-mode-line-update))))
;; For some time, I was using my own implementation of a modeline battery
;; monitor. However, the constant calls to `battery-linux-sysfs' were
;; interfering with the way that EXWM handles input focus, and I've since moved
;; towards reusing `display-battery-mode'. Because strings in `mode-line-format'
;; can contain control sequences, the percent symbol has to be escaped twice --
;; once for `battery-format', and once for `mode-line-format'.
;;
;; Obviously, my tower lacks a battery, so I only enable this on my laptop.
(expand-when (string= (system-name) "Upsilon")
(require 'battery)
(display-battery-mode +1)
(setq battery-mode-line-format "%L: %t, %p%%%%"))
(defun maybe-elide (s &optional max-length)
"Truncate `S' to `MAX-LENGTH'.
Return a string derived from `S', possible elided, that is at
most 1MAX-LENGTH characters long."
(let ((max-length (or max-length 30)))
(if (> (length s) max-length)
(concat (substring s 0 (- max-length 4)) " ...")
s)))
(defun escape-mode-line-construct (s)
"Sanitize `S' for use in `mode-line-format'.
Ensure that no part of S will be interpreted as a modeline format
specifier."
(replace-regexp-in-string (regexp-quote "%") "%%" s t t))
(defun mode-line-render (left right)
"Return a string of `window-width' length containing LEFT, and
RIGHT aligned respectively."
(let* ((right (format-mode-line right))
(left (maybe-elide (format-mode-line left)
(- (window-width) (length right) 1)))
(padding (- (window-width) (length left) (length right) 1))
(padding (if (wholenump padding) (make-string padding ?\ ))))
(if padding
(escape-mode-line-construct (concat " " left padding right))
(concat " " left right))))
(defun remove-unicode (s)
"Remove non-ASCII or non-printable ASCII characters from `S'."
(apply #'string (seq-filter #'(lambda (c) (and (>= c ? ) (<= c ?~))) s)))
(defvar mode-line-time-tracking nil)
(defvar mode-line-time-tracking-counter -1)
(defvar mode-line-time-tracking-timer nil)
(defun mode-line-time-tracking-update ()
(setq mode-line-time-tracking-counter
(+ 1 mode-line-time-tracking-counter))
(setq mode-line-time-tracking
(format "[%.2d:%.2d] %s"
(floor (/ mode-line-time-tracking-counter 60))
(floor (% mode-line-time-tracking-counter 60))
org-clock-heading)))
(defun mode-line-time-tracking-enable ()
(setq mode-line-time-tracking-counter -1)
(setq mode-line-time-tracking-timer
(run-at-time nil 60 #'mode-line-time-tracking-update)))
(defun mode-line-time-tracking-disable ()
(setq mode-line-time-tracking "")
(cancel-timer mode-line-time-tracking-timer))
(add-hook 'org-clock-in-hook #'mode-line-time-tracking-enable)
(add-hook 'org-clock-out-hook #'mode-line-time-tracking-disable)
(setq-default mode-line-format
'((:eval
(mode-line-render
(cond ((eq major-mode 'exwm-mode)
(concat "%b: " (remove-unicode exwm-title)))
((eq major-mode 'pdf-view-mode)
(concat "%b ["
(number-to-string (pdf-view-current-page))
"/"
(number-to-string (pdf-cache-number-of-pages))
"]"))
((and (eq major-mode 'shell-mode) (boundp 'shell-title))
(concat "%b [%m: "
shell-title
"] [%*] Ln: %l/"
(number-to-string (1+ (count-lines 1 (point-max))))
" Col: %c"))
((and (eq major-mode 'vterm-mode)
(boundp 'vterm-buffer-titles)
(gethash (current-buffer) vterm-buffer-titles))
(concat "%b [%m: "
(gethash (current-buffer) vterm-buffer-titles)
"] [%*] Ln: %l/"
(number-to-string (1+ (count-lines 1 (point-max))))
" Col: %c"))
((and (eq major-mode 'eww-mode) (boundp 'eww-data))
(concat (plist-get eww-data :title)
" [%m] [%*] Ln: %l/"
(number-to-string (1+ (count-lines 1 (point-max))))
" Col: %c"))
(t
(concat "%b [%m] [%*] Ln: %l/"
(number-to-string (1+ (count-lines 1 (point-max))))
" Col: %c")))
mode-line-time-tracking))))
|