summaryrefslogtreecommitdiff
path: root/CHANGELOG.org
blob: 7547799bb595ac6e7d9e1454677d0a63c4dc36f5 (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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
#+title: Change log of TMR
#+author: Protesilaos
#+email: info@protesilaos.com
#+options: ':nil toc:nil num:nil author:nil email:nil
#+startup: content

This document contains the release notes for each tagged commit on the
project's main git repository: <https://github.com/protesilaos/tmr>.

The newest release is at the top.  For further details, please consult
the manual: <https://protesilaos.com/emacs/tmr>.

#+toc: headlines 1 insert TOC here, with one headline level

* Version 1.3.0 on 2026-01-25
:PROPERTIES:
:CUSTOM_ID: h:705987e4-60e9-4d06-bdc0-4f08347348a0
:END:

This version adds some user options and new features to an already
stable package.

** Timers can be paused
:PROPERTIES:
:CUSTOM_ID: h:4e740a08-0e29-4d5e-84ec-e5507df3845c
:END:

The command ~tmr-toggle-pause~ will prompt for a running timer and
pause it.

Users who have something like the following in their configuration,
have access to ~tmr-toggle-pause~ under the =P= key:

#+begin_src emacs-lisp
;; All TMR commands are behind this prefix key.  So `tmr-toggle-pause' is C-c t P.
(define-key global-map (kbd "C-c t") #'tmr-prefix-map)
#+end_src

In the buffer produced by the command ~tmr-tabulated-view~ the pause
functionality applies to the timer at point. The ~tmr-toggle-pause~ is
invoked with the =P= key.

An extra column in the tabulated view shows whether a timer is paused
or not. Here is an example:

#+begin_example
Start      End        Duration   Remaining  Paused?  Acknowledge?   Description

08:49:41   09:19:46   30m        29m 17s    Yes                     Work on TMR for 30 minutes
08:49:31   08:54:31   5m         3m 53s                             Prepare tea
08:49:21   08:59:21   10m        8m 42s              Yes            Edit the description with this one instead
#+end_example

** Configure the confirmation text for acknowledgements
:PROPERTIES:
:CUSTOM_ID: h:b08bda30-2991-4d36-83d8-39d619abb20f
:END:

When a timer is set to be acknowledged (i.e. the user must confirm
that they saw it elapse) it prompts for confirmation. The default
input text that confirms the acknowledgement is =ack=. This is now
subject to configuration via the user option ~tmr-acknowledge-timer-text~.

** Change how frequently the tabulated list is refreshed
:PROPERTIES:
:CUSTOM_ID: h:758d2691-14c5-4f3e-9044-a394101f9cff
:END:

The buffer produced by ~tmr-tabulated-view~ is set to automatically
refresh every 5 seconds by default. In previous versions this was every
1 second. The new user option ~tmr-tabulated-refresh-interval~ can be
set to a number of seconds or ~nil~. In the latter case, the automatic
refresh is disabled.

** Removed the long-obsolete =tmr-tabulated.el=
:PROPERTIES:
:CUSTOM_ID: h:5bd873e9-15fa-4660-947f-b4f104d4e577
:END:

Its code was merged into =tmr.el= on 2024-10-30 and all it was doing
thenceforth is issue a warning to those who would ~require~ the
~tmr-tabulated~ feature. Now ~(require 'tmr-tabulated)~ produces an
error.

* Version 1.2.0 on 2025-10-06
:PROPERTIES:
:CUSTOM_ID: h:87d321d7-e88e-4303-a7fc-fa4264e62a92
:END:

This release introduces several quality-of-life refinements to an
already stable and featureful package.

** Timers can now appear on the modeline
:PROPERTIES:
:CUSTOM_ID: h:4a695649-c356-4410-ab3e-27edcf5852e7
:END:

The new minor mode ~tmr-mode-line-mode~ controls whether running
timers are displayed on the mode line. More specifically, they are
displayed in the ~global-mode-string~, which can also be set in the
~tab-bar-mode~ (this way the information appears in one place instead
of all the mode lines, assuming default settings).

The exact format of a timer on display is controlled by the user
option ~tmr-mode-line-format~. The number of timers is set with the
option ~tmr-mode-line-max-timers~. The separator between multiple
timers is ~tmr-mode-line-separator~. The length of each timer's
optional description is subject to ~tmr-mode-line-max-desc-length~.
While the entire indicator can have a prefix, per ~tmr-mode-line-prefix~.

Thanks to Steven Allen for contributing the original version of this
feature in pull request 2: <https://github.com/protesilaos/tmr/pull/2>.
Steven has assigned copyright to the Free Software Foundation. Further
changes by me, such as to make the timers on the mode line clickable
(which produces a tabulated view, per ~tmr-tabulated-view~).

** Notifications for more operating systems
:PROPERTIES:
:CUSTOM_ID: h:5bc7646d-b785-461a-9d85-331afb958002
:END:

Timers can optionally trigger a system notification, via the abnormal
hook ~tmr-timer-finished-functions~. The relevant function is
~tmr-notification-notify~. It used to only support Linux. Now it is
extended to handle Android, Windows, and Haiku.

Thanks to Lucas Quintana for the contribution in pull request 10:
<https://github.com/protesilaos/tmr/pull/10>. Lucas has assigned
copyright to the Free Software Foundation.

** The tabulated timers have a "duration" column
:PROPERTIES:
:CUSTOM_ID: h:78bf9f7d-549c-46e5-bde2-efab21f1fba4
:END:

The ~tmr-tabulated-view~ command (alias ~tmr-list-timers~) now
includes a "duration" column, in addition to all the other informative
data on display.

[ Remember that the tabulated view can be used to create, duplicate,
  edit, etc. the timers. ]

Thanks to jpg for suggesting this in issue 11:
<https://github.com/protesilaos/tmr/issues/11>.

** Miscellaneous
:PROPERTIES:
:CUSTOM_ID: h:5309ee0b-edd0-4d75-849c-df008b4014ae
:END:

- System notifications specify the =:app-icon= of Emacs. It will be
  displayed, if the underlying software supports it (I see it on
  Linux, anyway).

- The option to play the ~tmr-sound-file~ via the abnormal hook
  ~tmr-timer-finished-functions~ is redone to not rely on the system
  shell (implicitly ~bash~). This way, users who use exotic shell
  alternatives will not run into any trouble. This is done in response
  to a relevant problem that g-gundam was facing with the ~nushell~:
  <https://github.com/protesilaos/tmr/pull/7>.

- The function ~tmr-notification-notify~ is better at informing the
  user that it has produced the warning about the lack of DBUS
  support. Before, the notification did not identity itself as
  belonging to the ~tmr~ package.

- The function ~tmr-running-timers-p~ is now available as a standalone
  function to do what was done before inside other functions. This is
  useful for anyone writing custom code on top of ~tmr~. Thanks to
  Eugene Mikhaylov for suggesting the idea in issue 9:
  <https://github.com/protesilaos/tmr/issues/9>.

- The manual is updated to include whatever necessary from the
  aforementioned.

* Version 1.1.0 on 2025-04-18
:PROPERTIES:
:CUSTOM_ID: h:41248cbf-d399-411d-91ff-5359a00a1577
:END:

This version makes small refinements to an already stable package.

** All of =tmr-tabulated.el=  is part of =tmr.el=
:PROPERTIES:
:CUSTOM_ID: h:cd10fa6b-60ed-4045-ae32-780e62b50f21
:END:

The command ~tmr-tabulated-view~, which produces a grid with
timers+descriptions, used to be in a separate file. It now is part of
the singular =tmr.el= to keep things simple. Users who were using
=(require 'tmr-tabulated)= or similar will now get a warning. Simply
load ~tmr~ instead.

** Refined the behaviour of the ~tmr-tabulated-view~ command
:PROPERTIES:
:CUSTOM_ID: h:bd56a213-7714-4bd7-bd1a-f3ac108f27d2
:END:

When the command ~tmr-tabulated-view~ (alias ~tmr-list-timers~) is
called interactively, it uses the =*tmr-tabulated-view*= buffer just
as it did before. Though it also evaluates the new user option
~tmr-list-timers-action-alist~: it is a variable that controls where
the buffer is displayed. The default value displays the buffer at the
bottom of the Emacs frame and makes some other tweaks for usability.

Watch my video on the ~display-buffer-alist~ for further details on
how to control the display of buffers: <https://protesilaos.com/codelog/2024-02-08-emacs-window-rules-display-buffer-alist/>.

The ~tmr-tabulated-view~ command is further revised to make it
callable from a program. One scenario where we do this is to interrupt
the termination of Emacs if there are running timers (more below).

** TMR interrupts the termination of Emacs if it must
:PROPERTIES:
:CUSTOM_ID: h:5a4bf956-b1c2-446b-848c-eb64ffa50109
:END:

In the past, we did not have anything to prevent the termination of
Emacs if timers were running: Emacs would simply shut down. Now we
define the ~tmr-kill-emacs-query-function~, which is added to the
standard ~kill-emacs-query-functions~: if there are running timers, it
asks for confirmation before closing Emacs. To make it easier for
users to decide how to proceed, it also pops up the list with all the
timers (i.e. it uses ~tmr-tabulated-view~ from Lisp, as noted above).

** The list view is easier to follow
:PROPERTIES:
:CUSTOM_ID: h:c432f1ab-dcaf-4a01-8004-cf268a24b228
:END:

The buffer produced by ~tmr-tabulated-view~ now uses more colours to
make it easier to track the data it presents. These are all the faces
it applies:

- ~tmr-tabulated-start-time~ :: The time when the timer was started.

- ~tmr-tabulated-end-time~ :: The time when the timer is set to end.

- ~tmr-tabulated-remaining-time~ :: The remaining time.

- ~tmr-tabulated-acknowledgement~ :: Whether the timer needs to be
  "acknowledged" after it ends (if it is marked as "acknowledged",
  then it will not go away until the user confirms they have seen it).

- ~tmr-tabulated-description~ :: The text describing what the timer is
  about.

* Version 1.0.0 on 2024-08-30
:PROPERTIES:
:CUSTOM_ID: h:88595352-0263-425c-baab-6042f63ae28a
:END:

This version adds quality-of-life improvements to an already stable
base.

** The ~tmr-with-details~ supersedes the ~tmr-with-description~
:PROPERTIES:
:CUSTOM_ID: h:ac3d5ea6-2e89-477b-a5eb-9b408ef30b4e
:END:

The ~tmr-with-description~ would always prompt for a time input and
then a description of the resulting timer object. We now provide a
more general command, ~tmr-with-details~, which does this in addition
to an extra prompt for an acknowledgement. What an "acknowledgement"
is, is documented in the following section.

** Timers can now be "acknowledged"
:PROPERTIES:
:CUSTOM_ID: h:1a971ba1-09a6-4df6-bbe5-73685430417c
:END:

Normally, when a timer elapses it does not stick around to notify the
user again and again. This means that the user may miss the one
notification if, say, they were away from the computer. As such, we
now provide an opt-in mechanism where a timer persists until it is
explicitly acknowledged as finished. The acknowledgement is either an
additional duration for the timer to produce another notification in
the future, or an explicit consent from the timer to count as
finished. The goal is to help the user never miss a timer.

Setting up an acknowledgement can be done in the following ways:

- Call the standard ~tmr~ command with a prefix argument (=C-u= by
  default). This will make it prompt for a description and an
  acknowledgement.

- Use the new command ~tmr-with-details~, which asks for a timer
  input, a description, and whether to include an acknowledgement
  prompt.

- Use the new command ~tmr-toggle-acknowledge~, which will prompt for
  a timer and then toggle the acknowledgement status on/off. In this
  scenario, the timer already exists (e.g. it was created with ~tmr~
  without a prefix argument).

All timers are listed in a nice list with the command
~tmr-tabulated-view~. An extra column will indicate their
acknowledgement status.

Thanks to Daniel Mendler for contributing this feature. This was done
in the form of patches, sent via email. Daniel has assigned copyright
to the Free Software Foundation.

** The ~tmr-list-timers~ is an alias for ~tmr-tabulated-view~
:PROPERTIES:
:CUSTOM_ID: h:f1d80033-45f5-47cc-b76b-c8aee05dd789
:END:

Perhaps the "list timers" is a more meaningful description of what the
command does, as opposed to "tabulated view".

** Use the ~tmr-prefix-map~
:PROPERTIES:
:CUSTOM_ID: h:20dcbc95-a376-4130-8ae8-7be6c7aa149a
:END:

We now define a prefix keymap that users can bind directly to a key
and get all the TMR commands in one go. For example, this adds all TMR
commands behind the =C-c t= prefix:

#+begin_src emacs-lisp
(define-key global-map (kbd "C-c t") 'tmr-prefix-map)
#+end_src

Thanks to Daniel Mendler for this patch.

** TMR uses its own faces
:PROPERTIES:
:CUSTOM_ID: h:1d6ddc5a-8856-40d4-8328-f6413cb37f30
:END:

Theme developers or users can now modify how the various TMR
indicators look by tweaking the faces we provide:

- ~tmr-duration~
- ~tmr-description~
- ~tmr-start-time~
- ~tmr-end-time~
- ~tmr-is-acknowledged~
- ~tmr-must-be-acknowledged~
- ~tmr-finished~

The default values inherit from basic faces that should be supported
everywhere.

Existing users will not notice any visual difference, other things
being equal.

** Fixed some typos in the manual
:PROPERTIES:
:CUSTOM_ID: h:2b0e0105-d142-45de-807d-b2ef60c25dc8
:END:

Thanks to Ed Tavinor for the contribution. The change pertains to
typos and is within the limit of edits that do not require copyright
assignment to the Free Software Foundation.

* Version 0.4.0 on 2022-07-07
:PROPERTIES:
:CUSTOM_ID: h:52e3b3ac-70ef-47c5-895c-92adbd5c92b0
:END:

The general theme of this release is that TMR became simpler, better,
and more robust.  Daniel Mendler provided lots of patches and is now
recognised as co-author of the package together with Damien Cassou and
me (Protesilaos).  With the exception of documentation changes and other
accompanying tweaks, all of the following are courtesy of Daniel
Mendler.  Consult the git log for the minutia.

+ Timers can also be set using an absolute time input.  For example,
  =21:45= will set a timer from now until the specified time.  The
  familiar ways of starting timers with relative values, work as they
  did before.  This is part of a wider internal revision to make the
  parsing of input more strict.

+ TMR no longer maintains distinct feature sets between its minibuffer
  and tabulated interfaces.  What works in one context, works equally in
  the other.  All commands that were formerly available only in the
  ~tmr-tabulated-mode~ (accessed via ~tmr-tabulated-view~) are now
  implemented anew to provide the requisite minibuffer capabilities.
  When called from inside the ~tmr-tabulated-mode~, the commands operate
  on the timer at point.  Otherwise they prompt for completion among the
  available timers (where relevant).  This covers all operations for
  creating, cloning, [re-]describing, rescheduling, and removing timers.
  The ~tmr-tabulated-mode-map~ is updated thus:

  #+begin_src emacs-lisp
  (defvar tmr-tabulated-mode-map
    (let ((map (make-sparse-keymap)))
      (define-key map "k" #'tmr-remove)
      (define-key map "r" #'tmr-remove)
      (define-key map "R" #'tmr-remove-finished)
      (define-key map "+" #'tmr)
      (define-key map "t" #'tmr)
      (define-key map "*" #'tmr-with-description)
      (define-key map "T" #'tmr-with-description)
      (define-key map "c" #'tmr-clone)
      (define-key map "e" #'tmr-edit-description)
      (define-key map "s" #'tmr-reschedule)
      map)
    "Keybindings for `tmr-tabulated-mode-map'.")
  #+end_src

  Similarly, our sample key bindings are these:

  #+begin_src emacs-lisp
  ;; OPTIONALLY set your own global key bindings:
  (let ((map global-map))
    (define-key map (kbd "C-c t t") #'tmr)
    (define-key map (kbd "C-c t T") #'tmr-with-description)
    (define-key map (kbd "C-c t l") #'tmr-tabulated-view) ; "list timers" mnemonic
    (define-key map (kbd "C-c t c") #'tmr-clone)
    (define-key map (kbd "C-c t k") #'tmr-cancel)
    (define-key map (kbd "C-c t s") #'tmr-reschedule)
    (define-key map (kbd "C-c t e") #'tmr-edit-description)
    (define-key map (kbd "C-c t r") #'tmr-remove)
    (define-key map (kbd "C-c t R") #'tmr-remove-finished))
  #+end_src

+ The tabulated view now shows the remaining time for all timer objects.
  This is how the =*tmr-tabulated-view*= buffer is formatted:

  #+begin_example
  Start      End        Remaining  Description
  10:11:49   10:11:54   ✔
  10:11:36   10:31:36   19m 35s
  10:11:32   10:26:32   14m 31s    Yet another test
  10:11:16   10:21:16   9m 14s     Testing how it works
  #+end_example

+ All timer objects are refactored to expose a properly formatted
  completion table.  The completion category is ~tmr-timer~.  In
  practical terms, =embark= (and other standards-compliant packages) can
  operate on them.  The manual provides sample glue code for Embark:

  #+begin_src emacs-lisp
  (defvar tmr-action-map
    (let ((map (make-sparse-keymap)))
      (define-key map "k" #'tmr-remove)
      (define-key map "r" #'tmr-remove)
      (define-key map "R" #'tmr-remove-finished)
      (define-key map "c" #'tmr-clone)
      (define-key map "e" #'tmr-edit-description)
      (define-key map "s" #'tmr-reschedule)
      map))

  (with-eval-after-load 'embark
    (add-to-list 'embark-keymap-alist '(tmr-timer . tmr-action-map))
    (cl-loop
     for cmd the key-bindings of tmr-action-map
     if (commandp cmd) do
     (add-to-list 'embark-post-action-hooks (list cmd 'embark--restart))))
  #+end_src

  The [[https://github.com/oantolin/embark/wiki/Additional-Actions#actions-for-prots-tmr-tmr-may-ring][Embark Wiki]] is updated accordingly.

+ The new user option ~tmr-confirm-single-timer~ governs how TMR should
  behave while operating on the sole timer.  If non-nil (the default),
  TMR will always use the minibuffer to select a timer object to operate
  on, even when there is only one candidate available.  If set to nil,
  TMR will not ask for confirmation when there is one timer available:
  the operation will be carried out outright.  The default value is
  optimal for use with Embark.

+ The existing user option ~tmr-description-list~ is revised to accept
  either a list of strings (the old approach) or a symbol of a variable
  that holds a list of strings.  In the latter case, this can be the
  ~tmr-description-history~, which is a variable that stores the user's
  input at the relevant minibuffer prompt.  We have made this the new
  default value, as it grows naturally to reflect one's usage of TMR.
  Minibuffer histories can persist between sessions if the user enables
  the built-in =savehist= library.  Sample configuration:

  #+begin_src emacs-lisp
  (require 'savehist)
  (setq savehist-file (locate-user-emacs-file "savehist"))
  (setq history-length 10000)
  (setq history-delete-duplicates t)
  (setq savehist-save-minibuffer-history t)
  (add-hook 'after-init-hook #'savehist-mode)
  #+end_src

+ Fixed an edge case where a ~when-let*~ form did not return the
  expected value.  Thanks to Nathan R. DeGruchy for the patch.  The
  patch is below the ~15 line threshold and thus does not require
  copyright assignment to the Free Software Foundation.

+ Named the mailing list address as the =Maintainer:= of Denote.
  Together with the other package headers, they help the user find our
  primary sources and/or communication channels.  This change conforms
  with work being done upstream in package.el by Philip Kaludercic.  I
  was informed about it here:
  <https://lists.sr.ht/~protesilaos/general-issues/%3C875ykl84yi.fsf%40posteo.net%3E>.

+ Updated the manual to reflect the aforementioned.

* Version 0.3.0 on 2022-05-17
:PROPERTIES:
:CUSTOM_ID: h:0a2d4909-0079-47e9-97f4-220e85a811f9
:END:

The gist of TMR's May Release is that TMR is Maintained Rigorously---but
enough with The Mostly Recursive acronyms!

+ This is the first version for which we produce a change log.  The
  short story of previous releases: I (Protesilaos) was using and
  developing TMR (pronounced as "timer" or "T-M-R") as part of my
  personal setup for more than a year until I eventually contributed it
  to GNU ELPA.

+ What was once =tmr.el= is now split up into purpose-specific files:
  =tmr.el= (core functionality), =tmr-tabulated.el= (grid view),
  =tmr-sound.el= (audible notifications), and =tmr-notification.el=
  (desktop notifications).

+ The ~tmr-with-description~ command creates a new timer while always
  asking for a description.  Whereas the standard ~tmr~ command prompts
  for a description only when invoked with a prefix argument.

+ The ~tmr-clone~ command copies the duration and optional description
  of an existing timer object into a new one.  The operation is
  performed without further questions, except if a prefix argument is
  supplied: in that case the command will prompt for a duration and, if
  the original timer had a description, for one as well.  The default
  values of these prompts are those of the original timer.

+ The ~tmr-remove-finished~ deletes all elapsed timers.  This means that
  they are removed from the list of available timers and, thus, cannot
  be cloned.

+ The ~tmr-timer-created-functions~, ~tmr-timer-completed-functions~,
  and ~tmr-timer-cancelled-functions~ are hooks which can be used to
  control what happens once a timer is (i) created, (ii) elapses, or
  (iii) is cancelled.

+ Elapsed and running timers are displayed in a grid view with the
  command ~tmr-tabulated-view~.  The buffer looks like this:

  #+begin_example
  Start      End        Finished?  Description
  09:22:43   09:32:43   ✔         Prepare tea
  09:17:14   09:37:14              Boil water
  09:07:03   09:57:03              Bake bread
  #+end_example

+ In that grid view, it is possible to create a new timer, or operate on
  the one at point to cancel, clone, redescribe, and reschedule it.

+ Thanks to Christian Tietze for implementing changes to how desktop
  notifications are handled.  The overall effect should still be the
  same for existing users, though the implementation has been redesigned.

+ Thanks to Damien Cassou who is now is my co-author due to multiple
  contributions for =tmr.el=, the addition of the grid view, and the
  splitting of TMR into numerous files.  Please consult the Git commit
  log for the details.  (I still am the maintainer.)

+ Christian and Damien have assigned copyright to the Free Software
  Foundation.  It is required for all packages distributed via GNU ELPA.

The manual documents the technicalities and provides a sample
configuration.  Either evaluate the form =(info "(tmr) Top")= if you
have the package installed or visit https://protesilaos.com/emacs/tmr.

* Version 0.2.0 on 2022-04-21
:PROPERTIES:
:CUSTOM_ID: h:054285c2-3d90-4adc-ada4-61222b31fb85
:END:

This entry is retroactively introduced on 2022-07-07.

+ Changed the ~tmr~ and ~tmr-cancel~ commands to handle a list of timers
  instead of only interfacing with the last timer.

+ Improved the documentation.

+ Made various internal tweaks and refinements.

+ Added TMR to the official GNU ELPA archive as =tmr=.

* Version 0.1.0 on 2021-10-02
:PROPERTIES:
:CUSTOM_ID: h:1fce2c20-a16c-4ea9-9006-cf565f78f812
:END:

This entry is retroactively introduced on 2022-07-07.

TMR was originally [[https://protesilaos.com/codelog/2021-10-02-introducing-tmr-el/][announced on my website]].  The code was developed as
part of [[https://protesilaos.com/emacs/dotemacs][my dotemacs]] for several months before it was placed in its own
Git repo.  Even before the Elisp implementation, the core idea existed
as a standalone shell script, which is still part of [[https://git.sr.ht/~protesilaos/dotfiles][my dotfiles]].