blob: 0be7b828b3d8cdeb182b9a785cb0f285ae331952 (
plain)
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
154
155
156
157
158
159
160
161
|
;;; count.el --- Easy counting facility -*- lexical-binding: t; -*-
;; Copyright (C) 2024 Jean Sévère Durand
;; Author: Jean Sévère Durand <durand@jsdurand.xyz>
;; Keywords: emulations, games
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Counting mode
;;; Code:
;;; Variables
;;;; Buffer name
(defvar counting-buffer-name "*Count*"
"The name of the buffer within which to count.")
;;;; Font-scaling factor
(defvar counting-font-step 10
"The proportion by which the counting value font size is \
increased.")
;;;; Counted value
(defvar-local count-mode-value 0
"The value of the current count.")
;;; Major mode
(define-derived-mode count-mode special-mode "Count"
"Major mode for counting."
(count-refresh)
(set 'cursor-type nil))
(let ((map count-mode-map))
(define-key map (vector 'up) #'count-up)
(define-key map (vector 'down) #'count-down)
(define-key map (vector ?r) #'count-refresh)
(define-key map (vector ?o) #'count-reset)
(define-key map (vector ?=) #'count-enlarge)
(define-key map (vector ?-) #'count-shrink))
;;; Functions to start counting
;;;; Count in an old buffer if possible
(defun count-start-or-switch ()
"Start counting in an old buffer if possible."
(interactive)
(let ((buffer (get-buffer-create counting-buffer-name)))
(with-current-buffer buffer
(count-mode))
(switch-to-buffer buffer)))
;;;; Count in a new buffer always
(defun count-start ()
"Start counting in a new buffer."
(interactive)
(let* ((name (generate-new-buffer-name counting-buffer-name))
(buffer (get-buffer-create name)))
(with-current-buffer buffer
(count-mode))
(switch-to-buffer buffer)))
;;; Auxiliary functions
;;;; Format the counted value
(defvar text-scale-mode-step)
(defun count-make-pad-string (number)
"Make a padding string that centers the NUMBER."
(declare (pure t) (side-effect-free t))
(let* ((number-str (format "%d" number))
(number-str-width (* (string-pixel-width number-str)
;; account for the font-size scales
(expt
text-scale-mode-step
counting-font-step)))
(space-width (string-pixel-width (string #x20)))
(padding (/ (- (window-pixel-width) (* 2 space-width)
number-str-width)
2.0))
(height (window-body-height nil 'remap))
(half (floor height 2)))
(concat
(make-string half #xa)
(propertize
(string #x20)
'display (list 'space :width (list padding)))
number-str)))
(defun count-refresh ()
"Refresh the counting buffer."
(interactive)
(cond
((derived-mode-p 'count-mode)
(let ((inhibit-read-only t))
(setq text-scale-mode-amount counting-font-step)
(text-scale-mode 1)
(delete-region (point-min) (point-max))
(insert (count-make-pad-string count-mode-value))))
((user-error
"This function needs to be in the count-mode"))))
(defun count-up (&optional arg)
"Increase the count by ARG."
(interactive "P")
(setq arg (cond ((null arg) 1) ((prefix-numeric-value arg))))
(setq count-mode-value (+ arg count-mode-value))
(count-refresh))
(defun count-down (&optional arg)
"Decrease the count by ARG."
(interactive "P")
(setq arg (cond ((null arg) 1) ((prefix-numeric-value arg))))
(setq count-mode-value (- count-mode-value arg))
(count-refresh))
(defun count-reset ()
"Reset `count-mode-value' to zero."
(interactive)
(setq count-mode-value 0)
(count-refresh))
(defun count-enlarge (&optional arg)
"Increase the font size by ARG many times.
The size of one step is defined by `text-scale-mode-step'."
(interactive "p")
(setq arg (cond ((null arg) 1) ((prefix-numeric-value arg))))
(setq counting-font-step (+ counting-font-step arg))
(count-refresh))
(defun count-shrink (&optional arg)
"Decrease the font size by ARG many times.
The size of one step is defined by `text-scale-mode-step'."
(interactive "p")
(setq arg (cond ((null arg) 1) ((prefix-numeric-value arg))))
(setq counting-font-step (- counting-font-step arg))
(count-refresh))
(provide 'count)
;;; count.el ends here
|