#+title:    Change log of TMR
#+author:   Protesilaos Stavrou
#+email:    info@protesilaos.com
#+options:  ':nil toc:nil num:nil author:nil email:nil

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

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

* Version 0.4.0 on 2022-07-07

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

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

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

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]].
