about summary refs log tree commit diff
path: root/configs/shared/.emacs.d/wpc/fonts.el
blob: 30459c940a7310aa1f5bf9510820eab1dd19b9f8 (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
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
;;; fonts.el --- Font preferences -*- lexical-binding: t -*-
;; Author: William Carroll <wpcarro@gmail.com>

;;; Commentary:
;; Control my font preferences with ELisp.

;;; Code:

;; TODO: `defcustom' font-size.
;; TODO: `defcustom' fonts.
;; TODO: Remove wpc/ namespace.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dependencies
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(require 'prelude)
(require 'cycle)
(require 'device)
(require 'maybe)
(require 'general)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Constants
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; TODO: Troubleshoot why "8" appears so large on my desktop.

;; TODO: Consider having a different font size when I'm using my 4K monitor.

(defconst fonts/size
  (pcase (device/classify)
    ('work-laptop  "9")
    ('work-desktop "8"))
  "My preferred default font-size, which is device specific.")

(defconst fonts/keybindings? t
  "Install the keybindings when non-nil.")

(defconst fonts/size-step 10
  "The amount (%) by which to increase or decrease a font.")

(defconst fonts/hacker-news-recommendations
  '("APL385 Unicode"
    "Go Mono"
    "Sudo"
    "Monoid"
    "Input Mono Medium" ;; NOTE: Also "Input Mono Thin" is nice.
    )
  "List of fonts optimized for programming I found in a HN article.")

(defconst fonts/whitelist
  (cycle/from-list
   (list/concat
    fonts/hacker-news-recommendations
    '("JetBrainsMono"
      "Mononoki Medium"
      "Monospace"
      "Operator Mono Light"
      "Courier"
      "Andale Mono"
      "Source Code Pro"
      "Terminus")))
  "This is a list of my preferred fonts.")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; TODO: fonts and fonts/whitelist make it difficult to name functions like
;; fonts/set as a generic Emacs function vs choosing a font from the whitelist.

(cl-defun fonts/cycle (&key forward?)
  "Cycle forwards when `FORWARD?' non-nil."
  (let ((font (if forward?
                  (cycle/next fonts/whitelist)
                (cycle/prev fonts/whitelist))))
    (message (s-concat "Active font: " font))
    (fonts/set (fonts/fontify font))))

(defun fonts/next ()
  "Quickly cycle through preferred fonts."
  (interactive)
  (fonts/cycle :forward? t))

(defun fonts/prev ()
  "Quickly cycle through preferred fonts."
  (interactive)
  (fonts/cycle :forward? nil))

(defun fonts/set (font &optional size)
  "Change the font to `FONT' with option integer, SIZE, in pixels."
  (if (maybe/some? size)
      (set-frame-font (string/format "%s %s" font size) nil t)
    (set-frame-font font nil t)))

(defun fonts/whitelist-set (font)
  "Focuses the FONT in the `fonts/whitelist' cycle.
The size of the font is determined by `fonts/size'."
  (prelude/assert (cycle/contains? font fonts/whitelist))
  (cycle/focus (lambda (x) (equal x font)) fonts/whitelist)
  (fonts/set (fonts/current) fonts/size))

(defun fonts/ivy-select ()
  "Select a font from an ivy prompt."
  (interactive)
  (fonts/whitelist-set
   (ivy-read "Font: " (cycle/to-list fonts/whitelist))))

(defun fonts/print-current ()
  "Message the currently enabled font."
  (interactive)
  (message
   (string/format "[fonts] Current font: \"%s\""
                  (fonts/current))))

(defun fonts/current ()
  "Return the currently enabled font."
  (cycle/current fonts/whitelist))

(defun fonts/increase-size ()
  "Increase font size."
  (interactive)
  (->> (face-attribute 'default :height)
       (+ fonts/size-step)
       (set-face-attribute 'default (selected-frame) :height)))

(defun fonts/decrease-size ()
  "Decrease font size."
  (interactive)
  (->> (face-attribute 'default :height)
       (+ (- fonts/size-step))
       (set-face-attribute 'default (selected-frame) :height)))

(defun fonts/reset-size ()
  "Restore font size to its default value."
  (interactive)
  (fonts/whitelist-set (fonts/current)))

(when fonts/keybindings?
  (progn
    (general-define-key
     :prefix "<SPC>"
     :states '(normal)
     "Ff" #'fonts/next
     "Pf" #'fonts/prev)
    (general-define-key "s-9" #'fonts/ivy-select)
    (general-define-key "s-0" #'fonts/reset-size)
    (general-define-key "s-j" #'fonts/decrease-size)
    (general-define-key "s-k" #'fonts/increase-size)))

(provide 'fonts)
;;; fonts.el ends here