mirror of
https://github.com/vale981/pomm.el
synced 2025-03-05 09:41:42 -05:00
feat: remaining third time features
This commit is contained in:
parent
1691d36473
commit
f66b7cade1
2 changed files with 110 additions and 33 deletions
|
@ -36,7 +36,7 @@
|
||||||
(require 'calc)
|
(require 'calc)
|
||||||
|
|
||||||
(defgroup pomm-third-time nil
|
(defgroup pomm-third-time nil
|
||||||
"Third time timer implementation."
|
"Third Time timer implementation."
|
||||||
:group 'pomm)
|
:group 'pomm)
|
||||||
|
|
||||||
(defcustom pomm-third-time-fraction "1/3"
|
(defcustom pomm-third-time-fraction "1/3"
|
||||||
|
@ -60,7 +60,7 @@ Can be string or number, a string is interpreted with
|
||||||
|
|
||||||
(defcustom pomm-third-time-state-file-location
|
(defcustom pomm-third-time-state-file-location
|
||||||
(locate-user-emacs-file "pomm-third-time")
|
(locate-user-emacs-file "pomm-third-time")
|
||||||
"Location of the pomm-third-time state file."
|
"Location of the `pomm-third-time' state file."
|
||||||
:group 'pomm-third-time
|
:group 'pomm-third-time
|
||||||
:type 'string)
|
:type 'string)
|
||||||
|
|
||||||
|
@ -69,8 +69,25 @@ Can be string or number, a string is interpreted with
|
||||||
:group 'pomm
|
:group 'pomm
|
||||||
:type 'string)
|
:type 'string)
|
||||||
|
|
||||||
|
(defcustom pomm-third-time-csv-history-file nil
|
||||||
|
"If non-nil, save timer history in a CSV format.
|
||||||
|
|
||||||
|
The parent directory has to exist!
|
||||||
|
|
||||||
|
A new entry is written whenever the timer changes status or kind
|
||||||
|
of period. The format is as follows:
|
||||||
|
- timestamp
|
||||||
|
- status
|
||||||
|
- kind
|
||||||
|
- iteration
|
||||||
|
- break-time-remaining
|
||||||
|
- context"
|
||||||
|
:group 'pomm-third-time
|
||||||
|
:type '(choice (string :tag "Path")
|
||||||
|
(const nil :tag "Do not save")))
|
||||||
|
|
||||||
(defvar pomm-third-time--state nil
|
(defvar pomm-third-time--state nil
|
||||||
"The current state of pomm-third-time.el.
|
"The current state of the Third Time timer.
|
||||||
|
|
||||||
This is an alist with the following keys:
|
This is an alist with the following keys:
|
||||||
- status: either 'stopped or 'running
|
- status: either 'stopped or 'running
|
||||||
|
@ -113,7 +130,7 @@ This is an alist with the following keys:
|
||||||
(defun pomm-third-time--init-state ()
|
(defun pomm-third-time--init-state ()
|
||||||
"Initialize the Third Time timer state."
|
"Initialize the Third Time timer state."
|
||||||
(add-hook 'pomm-third-time-on-status-changed-hook #'pomm-third-time--save-state)
|
(add-hook 'pomm-third-time-on-status-changed-hook #'pomm-third-time--save-state)
|
||||||
;; TODO (add-hook 'pomm-on-status-changed-hook #'pomm-third-time--maybe-save-csv)
|
(add-hook 'pomm-on-status-changed-hook #'pomm-third-time--maybe-save-csv)
|
||||||
(add-hook 'pomm-third-time-on-status-changed-hook
|
(add-hook 'pomm-third-time-on-status-changed-hook
|
||||||
#'pomm-third-time--dispatch-current-sound)
|
#'pomm-third-time--dispatch-current-sound)
|
||||||
(add-hook 'pomm-mode-line-mode-hook
|
(add-hook 'pomm-mode-line-mode-hook
|
||||||
|
@ -131,13 +148,13 @@ This is an alist with the following keys:
|
||||||
(pomm-third-time--cleanup-old-history))
|
(pomm-third-time--cleanup-old-history))
|
||||||
|
|
||||||
(defun pomm-third-time--save-state ()
|
(defun pomm-third-time--save-state ()
|
||||||
"Save the current Pomodoro timer state."
|
"Save the current Third Time timer state."
|
||||||
(when pomm-third-time-state-file-location
|
(when pomm-third-time-state-file-location
|
||||||
(with-temp-file pomm-third-time-state-file-location
|
(with-temp-file pomm-third-time-state-file-location
|
||||||
(insert (prin1-to-string pomm-third-time--state)))))
|
(insert (prin1-to-string pomm-third-time--state)))))
|
||||||
|
|
||||||
(defun pomm-third-time--cleanup-old-history ()
|
(defun pomm-third-time--cleanup-old-history ()
|
||||||
"Clear history of previous days from the Pomodoro timer."
|
"Clear history of previous days from the Third Time timer."
|
||||||
(let ((cleanup-time (decode-time)))
|
(let ((cleanup-time (decode-time)))
|
||||||
(setf (decoded-time-second cleanup-time) 0
|
(setf (decoded-time-second cleanup-time) 0
|
||||||
(decoded-time-minute cleanup-time) 0
|
(decoded-time-minute cleanup-time) 0
|
||||||
|
@ -150,6 +167,25 @@ This is an alist with the following keys:
|
||||||
(> (alist-get 'start-time item) cleanup-timestamp))
|
(> (alist-get 'start-time item) cleanup-timestamp))
|
||||||
(alist-get 'history pomm-third-time--state))))))
|
(alist-get 'history pomm-third-time--state))))))
|
||||||
|
|
||||||
|
(defun pomm-third-time--maybe-save-csv ()
|
||||||
|
"Log the current state of the timer to a CSV history file.
|
||||||
|
|
||||||
|
Set `pomm-third-time-csv-history-file' to customize the file location.
|
||||||
|
If the variable is nil, the function does nothing."
|
||||||
|
(when pomm-third-time-csv-history-file
|
||||||
|
(unless (file-exists-p pomm-third-time-csv-history-file)
|
||||||
|
(with-temp-file pomm-third-time-csv-history-file
|
||||||
|
(insert "timestamp,status,period,iteration,break-time-remaining,context\n")))
|
||||||
|
(write-region
|
||||||
|
(format "%s,%s,%s,%d,%d,%s\n"
|
||||||
|
(format-time-string pomm-csv-history-file-timestamp-format)
|
||||||
|
(symbol-name (alist-get 'status pomm--state))
|
||||||
|
(symbol-name (alist-get 'kind (alist-get 'current pomm--state)))
|
||||||
|
(or (alist-get 'iteration (alist-get 'current pomm--state)) 0)
|
||||||
|
(pomm-third-time--break-time)
|
||||||
|
(or (alist-get 'context pomm--state) ""))
|
||||||
|
nil pomm-csv-history-file 'append 1)))
|
||||||
|
|
||||||
(defun pomm-third-time-reset ()
|
(defun pomm-third-time-reset ()
|
||||||
"Reset the Third Time timer."
|
"Reset the Third Time timer."
|
||||||
(interactive)
|
(interactive)
|
||||||
|
@ -166,13 +202,13 @@ This is an alist with the following keys:
|
||||||
(alist-get 'kind (alist-get 'current pomm-third-time--state))))))
|
(alist-get 'kind (alist-get 'current pomm-third-time--state))))))
|
||||||
|
|
||||||
(defun pomm-third-time--calc-eval (value)
|
(defun pomm-third-time--calc-eval (value)
|
||||||
"Convert VALUE to number.
|
"Evaluate VALUE and return number.
|
||||||
|
|
||||||
If VALUE is not a string, return it.
|
If VALUE is not a string, return it.
|
||||||
|
|
||||||
Otherwise, try to evaluate with `calc-eval'. If unsuccessful, return
|
Otherwise, try to evaluate with `calc-eval'. If unsuccessful, return
|
||||||
calc error. If the result is numeric, convert it to number and return
|
the calc error. If the result is numeric, convert it to number and
|
||||||
it, otherwise, return a list with an error."
|
return it, otherwise, return a value like a calc error."
|
||||||
(if (stringp value)
|
(if (stringp value)
|
||||||
(let ((res (calc-eval value)))
|
(let ((res (calc-eval value)))
|
||||||
(if (listp res)
|
(if (listp res)
|
||||||
|
@ -241,7 +277,7 @@ it, otherwise, return a list with an error."
|
||||||
(defun pomm-third-time--dispatch-notification (kind)
|
(defun pomm-third-time--dispatch-notification (kind)
|
||||||
"Dispatch a notification about a start of a period.
|
"Dispatch a notification about a start of a period.
|
||||||
|
|
||||||
KIND is the same as in `pomm--state'"
|
KIND is the same as in `pomm-third-time--state'"
|
||||||
(alert
|
(alert
|
||||||
(pcase kind
|
(pcase kind
|
||||||
('break (concat pomm-third-time-break-message)
|
('break (concat pomm-third-time-break-message)
|
||||||
|
@ -275,7 +311,7 @@ KIND is the same as in `pomm--state'"
|
||||||
(run-hooks 'pomm-third-time-on-status-changed-hook)))
|
(run-hooks 'pomm-third-time-on-status-changed-hook)))
|
||||||
|
|
||||||
(defun pomm-third-time--on-tick ()
|
(defun pomm-third-time--on-tick ()
|
||||||
"A function to execute on each time tick."
|
"Function to execute on each timer tick."
|
||||||
(pcase (alist-get 'status pomm-third-time--state)
|
(pcase (alist-get 'status pomm-third-time--state)
|
||||||
('stopped (when pomm-third-time--timer
|
('stopped (when pomm-third-time--timer
|
||||||
(cancel-timer pomm-third-time--timer)
|
(cancel-timer pomm-third-time--timer)
|
||||||
|
@ -334,12 +370,12 @@ Take a look at the `pomm-third-time' function for more details."
|
||||||
(setf (alist-get 'context pomm-third-time--state) nil))))))
|
(setf (alist-get 'context pomm-third-time--state) nil))))))
|
||||||
|
|
||||||
(defun pomm-third-time-switch ()
|
(defun pomm-third-time-switch ()
|
||||||
"Switch between work and break in the Third Time timer."
|
"Toggle work/break in the Third Time timer."
|
||||||
(interactive)
|
(interactive)
|
||||||
(pomm-third-time--switch))
|
(pomm-third-time--switch))
|
||||||
|
|
||||||
(defun pomm-third-time-format-mode-line ()
|
(defun pomm-third-time-format-mode-line ()
|
||||||
"Format mode string for the Third Time timer."
|
"Format the modeline string for the Third Time timer."
|
||||||
(let ((current-status (alist-get 'status pomm-third-time--state)))
|
(let ((current-status (alist-get 'status pomm-third-time--state)))
|
||||||
(if (or (eq current-status 'stopped)
|
(if (or (eq current-status 'stopped)
|
||||||
(not (alist-get 'current pomm-third-time--state)))
|
(not (alist-get 'current pomm-third-time--state)))
|
||||||
|
@ -376,6 +412,7 @@ Take a look at the `pomm-third-time' function for more details."
|
||||||
(setf (alist-get 'context pomm-third-time--state)
|
(setf (alist-get 'context pomm-third-time--state)
|
||||||
(prin1-to-string (read-minibuffer "Context: " (current-word)))))
|
(prin1-to-string (read-minibuffer "Context: " (current-word)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
(defun pomm-third-time-start-with-context ()
|
(defun pomm-third-time-start-with-context ()
|
||||||
"Prompt for context call call `pomm-third-time-start'."
|
"Prompt for context call call `pomm-third-time-start'."
|
||||||
(interactive)
|
(interactive)
|
||||||
|
@ -384,6 +421,7 @@ Take a look at the `pomm-third-time' function for more details."
|
||||||
|
|
||||||
;;;; Transient
|
;;;; Transient
|
||||||
(defun pomm-third-time--completing-read-calc ()
|
(defun pomm-third-time--completing-read-calc ()
|
||||||
|
"Do `completing-read' with `calc-eval'."
|
||||||
(let ((res (completing-read
|
(let ((res (completing-read
|
||||||
"Time: "
|
"Time: "
|
||||||
(lambda (string fun flag)
|
(lambda (string fun flag)
|
||||||
|
@ -563,7 +601,36 @@ The class doesn't actually have any value, but this is necessary for transient."
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun pomm-third-time ()
|
(defun pomm-third-time ()
|
||||||
"TODO"
|
"Implementation of the Third Time timer in Emacs.
|
||||||
|
|
||||||
|
The idea of the technique is as follows:
|
||||||
|
- Work as long as you need, take a break as 1/3 of the work time (the
|
||||||
|
fraction of work time to break time is set in
|
||||||
|
`pomm-third-time-fraction')
|
||||||
|
- If you've ended a break early, unused break time is saved and added
|
||||||
|
to the next break within the same session.
|
||||||
|
- If you've finished the session, either to take a longer break or to
|
||||||
|
end working, remaining break time is discarded. Each session starts
|
||||||
|
from a clean slate.
|
||||||
|
|
||||||
|
The timer can have two states:
|
||||||
|
- Stopped.
|
||||||
|
Can be started with 's' or `pomm-third-time-start'.
|
||||||
|
- Running.
|
||||||
|
Can be stopped with 'S' or `pomm-third-time-stop'.
|
||||||
|
|
||||||
|
If the timer is running, the current period type (work or break) can
|
||||||
|
be switched by 'b' or `pomm-third-time-switch'. If the break time
|
||||||
|
runs out, the timer automatically switches to work.
|
||||||
|
|
||||||
|
The timer supports setting \"context\", for example, a task on which
|
||||||
|
you're working on. It can be set with '-c' or
|
||||||
|
`pomm-third-time-set-context'. This is useful together with CSV
|
||||||
|
logging, which is enabled if `pomm-third-time-csv-history-file' is
|
||||||
|
non-nil.
|
||||||
|
|
||||||
|
Enable `pomm-mode-line-mode' to display the timer state in the
|
||||||
|
modeline."
|
||||||
(interactive)
|
(interactive)
|
||||||
(unless pomm-third-time--state
|
(unless pomm-third-time--state
|
||||||
(pomm-third-time--init-state))
|
(pomm-third-time--init-state))
|
||||||
|
|
48
pomm.el
48
pomm.el
|
@ -1,10 +1,10 @@
|
||||||
;;; pomm.el --- Yet another Pomodoro timer implementation -*- lexical-binding: t -*-
|
;;; pomm.el --- Pomodoro and Third Time timers. -*- lexical-binding: t -*-
|
||||||
|
|
||||||
;; Copyright (C) 2021 Korytov Pavel
|
;; Copyright (C) 2022 Korytov Pavel
|
||||||
|
|
||||||
;; Author: Korytov Pavel <thexcloud@gmail.com>
|
;; Author: Korytov Pavel <thexcloud@gmail.com>
|
||||||
;; Maintainer: Korytov Pavel <thexcloud@gmail.com>
|
;; Maintainer: Korytov Pavel <thexcloud@gmail.com>
|
||||||
;; Version: 0.1.4
|
;; Version: 0.2.0
|
||||||
;; Package-Requires: ((emacs "27.1") (alert "1.2") (seq "2.22") (transient "0.3.0"))
|
;; Package-Requires: ((emacs "27.1") (alert "1.2") (seq "2.22") (transient "0.3.0"))
|
||||||
;; Homepage: https://github.com/SqrtMinusOne/pomm.el
|
;; Homepage: https://github.com/SqrtMinusOne/pomm.el
|
||||||
|
|
||||||
|
@ -25,14 +25,16 @@
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
||||||
;; An implementation of a Pomodoro timer for Emacs. Distintive features
|
;; Implementation of two time management methods in Emacs: Pomodoro
|
||||||
;; of this particular implementation:
|
;; and Third Time.
|
||||||
;; - Managing the timer with transient.el (`pomm' command)
|
;; This implementation features:
|
||||||
|
;; - Managing the timer with transient.el
|
||||||
;; - Persistent state between Emacs sessions.
|
;; - Persistent state between Emacs sessions.
|
||||||
;; So one could close & reopen Emacs without interruption the timer.
|
;; So one could close & reopen Emacs without interruption the timer.
|
||||||
;;
|
;;
|
||||||
;; Take a look at `pomm-update-mode-line-string' on how to setup this
|
;; Main entrypoints are: `pomm' for Pomodoro and `pomm-third-time' for
|
||||||
;; package with a modeline.
|
;; Third Time.
|
||||||
|
;;
|
||||||
;; Also take a look at README at
|
;; Also take a look at README at
|
||||||
;; <https://github.com/SqrtMinusOne/pomm.el> for more information.
|
;; <https://github.com/SqrtMinusOne/pomm.el> for more information.
|
||||||
|
|
||||||
|
@ -43,7 +45,7 @@
|
||||||
(require 'transient)
|
(require 'transient)
|
||||||
|
|
||||||
(defgroup pomm nil
|
(defgroup pomm nil
|
||||||
"Yet another Pomodoro timer implementation."
|
"Pomodoro and Third Time timers."
|
||||||
:group 'tools)
|
:group 'tools)
|
||||||
|
|
||||||
(defcustom pomm-work-period 25
|
(defcustom pomm-work-period 25
|
||||||
|
@ -77,12 +79,12 @@
|
||||||
:type 'string)
|
:type 'string)
|
||||||
|
|
||||||
(defcustom pomm-ask-before-long-break t
|
(defcustom pomm-ask-before-long-break t
|
||||||
"Ask a user whether to do a long break or stop the pomodoros."
|
"Ask the user whether to do a long break or stop the pomodoros."
|
||||||
:group 'pomm
|
:group 'pomm
|
||||||
:type 'boolean)
|
:type 'boolean)
|
||||||
|
|
||||||
(defcustom pomm-ask-before-work nil
|
(defcustom pomm-ask-before-work nil
|
||||||
"Ask a user whether to start a new pomodoro period."
|
"Ask the user whether to start a new pomodoro period."
|
||||||
:group 'pomm
|
:group 'pomm
|
||||||
:type 'boolean)
|
:type 'boolean)
|
||||||
|
|
||||||
|
@ -120,9 +122,9 @@ The format is the same as in `format-seconds'"
|
||||||
:type 'string)
|
:type 'string)
|
||||||
|
|
||||||
(defcustom pomm-csv-history-file nil
|
(defcustom pomm-csv-history-file nil
|
||||||
"The csv history file location.
|
"If non-nil, save timer history in a CSV format.
|
||||||
|
|
||||||
The parent directory has to exists!
|
The parent directory has to exist!
|
||||||
|
|
||||||
A new entry is written whenever the timer changes status or kind
|
A new entry is written whenever the timer changes status or kind
|
||||||
of period. The format is as follows:
|
of period. The format is as follows:
|
||||||
|
@ -173,9 +175,8 @@ When loading the package, `load-file-name' should point to the
|
||||||
location of this file, which means that resources folder should
|
location of this file, which means that resources folder should
|
||||||
be in the same directory.
|
be in the same directory.
|
||||||
|
|
||||||
If the file is evaluated interactively (for development
|
If the file is evaluated interactively (for development purposes), the
|
||||||
purposes), the `default-directory' is most likely the project
|
`default-directory' variable is most likely the project root."
|
||||||
root."
|
|
||||||
(or (and load-file-name (concat (file-name-directory load-file-name) name))
|
(or (and load-file-name (concat (file-name-directory load-file-name) name))
|
||||||
(concat default-directory name)))
|
(concat default-directory name)))
|
||||||
|
|
||||||
|
@ -208,7 +209,7 @@ Each element of the list is a cons cell, where:
|
||||||
:type 'hook)
|
:type 'hook)
|
||||||
|
|
||||||
(defvar pomm--state nil
|
(defvar pomm--state nil
|
||||||
"The current state of pomm.el.
|
"The current state of the Pomodoro timer.
|
||||||
|
|
||||||
This is an alist with the following keys:
|
This is an alist with the following keys:
|
||||||
- status: either 'stopped, 'paused or 'running
|
- status: either 'stopped, 'paused or 'running
|
||||||
|
@ -228,7 +229,8 @@ History is a list of alists with the following keys:
|
||||||
- iteration
|
- iteration
|
||||||
- start-time: start timestamp
|
- start-time: start timestamp
|
||||||
- end-time: end timestamp
|
- end-time: end timestamp
|
||||||
- paused-time: time spent in a paused state")
|
- paused-time: time spent in a paused state
|
||||||
|
- context: current context.")
|
||||||
|
|
||||||
(defvar pomm--timer nil
|
(defvar pomm--timer nil
|
||||||
"A variable for the pomm timer.")
|
"A variable for the pomm timer.")
|
||||||
|
@ -818,7 +820,15 @@ The timer can have 3 states:
|
||||||
'S' / `pomm-stop'.
|
'S' / `pomm-stop'.
|
||||||
- Running.
|
- Running.
|
||||||
Can be paused with 'p' / `pomm-pause' or stopped with 'S' /
|
Can be paused with 'p' / `pomm-pause' or stopped with 'S' /
|
||||||
`pomm-stop'."
|
`pomm-stop'.
|
||||||
|
|
||||||
|
The timer supports setting \"context\", for example, a task on which
|
||||||
|
you're working on. It can be set with '-c' or `pomm-set-context'.
|
||||||
|
This is useful together with CSV logging, which is enabled if
|
||||||
|
`pomm-csv-history-file' is non-nil.
|
||||||
|
|
||||||
|
Enable `pomm-mode-line-mode' to display the timer state in the
|
||||||
|
modeline."
|
||||||
(interactive)
|
(interactive)
|
||||||
(unless pomm--state
|
(unless pomm--state
|
||||||
(pomm--init-state))
|
(pomm--init-state))
|
||||||
|
|
Loading…
Add table
Reference in a new issue