feat: added context for tasks

This commit is contained in:
SqrtMinusOne 2021-11-25 20:48:54 +03:00
parent 62832704ba
commit 60b74bfe9e
2 changed files with 90 additions and 11 deletions

View file

@ -55,6 +55,8 @@ The state of the timer can be reset with "R" or =M-x pomm-reset=.
"u" updates the transient buffer. The update is manual because I didn't figure out how to automate this, and I think this is not /really/ necessary. "u" updates the transient buffer. The update is manual because I didn't figure out how to automate this, and I think this is not /really/ necessary.
With "r" or =M-x pomm-set-context= you can set the current "context", that is some description of the task you are currently working on. This description will show up in history and in the csv file. Also, =M-x pomm-start-with-context= will prompt for the context and then start the timer.
* Customization * Customization
Some settings are available in the transient buffer, but you can customize the relevant variables to make them permanent. Check =M-x customize-group= =pomm= for more information. Some settings are available in the transient buffer, but you can customize the relevant variables to make them permanent. Check =M-x customize-group= =pomm= for more information.
@ -105,6 +107,7 @@ The file has the following columns:
- =status= (=stopped=, =paused= or =running=, according to the [[*Usage][usage]] section) - =status= (=stopped=, =paused= or =running=, according to the [[*Usage][usage]] section)
- =kind= (=work=, =short-break=, =long-break= or =nil=) - =kind= (=work=, =short-break=, =long-break= or =nil=)
- =iteration= - =iteration=
- =context=
A new entry is written after a particular state of the timer comes into being. A new entry is written after a particular state of the timer comes into being.

98
pomm.el
View file

@ -81,6 +81,11 @@
:group 'pomm :group 'pomm
:type 'boolean) :type 'boolean)
(defcustom pomm-reset-context-on-iteration-end t
"Whether to reset the context when the iteration ends."
:group 'pomm
:type 'boolean)
(defcustom pomm-work-message "Time for work!" (defcustom pomm-work-message "Time for work!"
"Message for a start of a work period." "Message for a start of a work period."
:group 'pomm :group 'pomm
@ -119,7 +124,8 @@ of period. The format is as follows:
- timestamp - timestamp
- status - status
- kind - kind
- iteration" - iteration
- context"
:group 'pomm :group 'pomm
:type 'string) :type 'string)
@ -203,6 +209,7 @@ This is an alist of with the following keys:
- current: an alist with a current period - current: an alist with a current period
- history: a list with today's history - history: a list with today's history
- last-changed-time: a timestamp of the last change in status - last-changed-time: a timestamp of the last change in status
- context: a string that describes the current task
'current is also an alist with the following keys: 'current is also an alist with the following keys:
- kind: either 'short-break, 'long-break or 'work - kind: either 'short-break, 'long-break or 'work
@ -288,13 +295,14 @@ variable doesn't exist, function does nothing."
(when pomm-csv-history-file (when pomm-csv-history-file
(unless (file-exists-p pomm-csv-history-file) (unless (file-exists-p pomm-csv-history-file)
(with-temp-file pomm-csv-history-file (with-temp-file pomm-csv-history-file
(insert "timestamp,status,period,iteration\n"))) (insert "timestamp,status,period,iteration,context\n")))
(write-region (write-region
(format "%s,%s,%s,%d\n" (format "%s,%s,%s,%d,%s\n"
(format-time-string pomm-csv-history-file-timestamp-format) (format-time-string pomm-csv-history-file-timestamp-format)
(symbol-name (alist-get 'status pomm--state)) (symbol-name (alist-get 'status pomm--state))
(symbol-name (alist-get 'kind (alist-get 'current pomm--state))) (symbol-name (alist-get 'kind (alist-get 'current pomm--state)))
(or (alist-get 'iteration (alist-get 'current pomm--state)) 0)) (or (alist-get 'iteration (alist-get 'current pomm--state)) 0)
(or (alist-get 'context pomm--state) ""))
nil pomm-csv-history-file 'append 1))) nil pomm-csv-history-file 'append 1)))
(defun pomm-reset () (defun pomm-reset ()
@ -383,12 +391,14 @@ The condition is: (effective-start-time + length) < now."
(end-time (time-convert nil 'integer)) (end-time (time-convert nil 'integer))
(paused-time (- end-time (paused-time (- end-time
start-time start-time
(pomm--get-kind-length current-kind)))) (pomm--get-kind-length current-kind)))
(context (alist-get 'context pomm--state)))
(push `((kind . ,current-kind) (push `((kind . ,current-kind)
(iteration . ,current-iteration) (iteration . ,current-iteration)
(start-time . ,start-time) (start-time . ,start-time)
(end-time . ,end-time) (end-time . ,end-time)
(paused-time . ,paused-time)) (paused-time . ,paused-time)
(context . ,context))
(alist-get 'history pomm--state)))) (alist-get 'history pomm--state))))
(defun pomm--switch-to-next () (defun pomm--switch-to-next ()
@ -427,7 +437,9 @@ The condition is: (effective-start-time + length) < now."
(setf (alist-get 'current pomm--state) nil) (setf (alist-get 'current pomm--state) nil)
(setf (alist-get 'status pomm--state) 'stopped)) (setf (alist-get 'status pomm--state) 'stopped))
(pomm--save-state) (pomm--save-state)
(run-hooks 'pomm-on-status-changed-hook))) (run-hooks 'pomm-on-status-changed-hook)
(when (and (eq next-kind 'long-break) pomm-reset-context-on-iteration-end)
(setf (alist-get 'context pomm--state) nil))))
(defun pomm--on-tick () (defun pomm--on-tick ()
"A function to be ran on a timer tick." "A function to be ran on a timer tick."
@ -531,6 +543,18 @@ minor mode."
(unless pomm--timer (unless pomm--timer
(setq pomm--timer (run-with-timer 0 1 'pomm--on-tick)))) (setq pomm--timer (run-with-timer 0 1 'pomm--on-tick))))
(defun pomm-set-context ()
"Set the current context for the pomodoro timer."
(interactive)
(setf (alist-get 'context pomm--state)
(prin1-to-string (read-minibuffer "Context: " (current-word)))))
(defun pomm-start-with-context ()
"Prompt for context and call `pomm-start'."
(interactive)
(pomm-set-context)
(pomm-start))
(defun pomm-stop () (defun pomm-stop ()
"Stop the current iteration of the pomodoro timer." "Stop the current iteration of the pomodoro timer."
(interactive) (interactive)
@ -540,7 +564,9 @@ minor mode."
(setf (alist-get 'status pomm--state) 'stopped (setf (alist-get 'status pomm--state) 'stopped
(alist-get 'current pomm--state) nil (alist-get 'current pomm--state) nil
(alist-get 'last-changed-time pomm--state) (time-convert nil 'integer)) (alist-get 'last-changed-time pomm--state) (time-convert nil 'integer))
(run-hooks 'pomm-on-status-changed-hook))) (run-hooks 'pomm-on-status-changed-hook)
(when pomm-reset-context-on-iteration-end
(setf (alist-get 'context pomm--state) nil))))
(defun pomm-pause () (defun pomm-pause ()
"Pause the pomodoro timer." "Pause the pomodoro timer."
@ -589,6 +615,49 @@ minor mode."
(read-number "Number of work periods before a long break:" (read-number "Number of work periods before a long break:"
pomm-number-of-periods))) pomm-number-of-periods)))
(defclass pomm--set-context-on-iteration-end-infix (transient-switch)
((transient :initform t))
"A transient class to toggle `pomm-reset-context-on-iteration-end'.")
(cl-defmethod transient-init-value ((obj pomm--set-context-on-iteration-end-infix))
(oset obj value
pomm-reset-context-on-iteration-end))
(cl-defmethod transient-infix-read ((_ transient-switch))
"Toggle the switch on or off."
(setq pomm-reset-context-on-iteration-end
(not pomm-reset-context-on-iteration-end)))
(transient-define-infix pomm--set-reset-context-on-iteration-end ()
:class 'pomm--set-context-on-iteration-end-infix
:argument "--context-reset"
:key "-r"
:description "Reset the context on the interation end")
(defclass pomm--set-context-infix (transient-variable)
((transient :initform 'transient--do-call)
(always-read :initform t)))
(cl-defmethod transient-init-value ((_ pomm--set-context-infix))
(alist-get 'context pomm--state))
(cl-defmethod transient-infix-set ((_ pomm--set-context-infix) value)
(setf (alist-get 'context pomm--state) value))
(cl-defmethod transient-prompt ((_ pomm--set-context-infix))
"Set context: ")
(cl-defmethod transient-format-value ((_ pomm--set-context-infix))
(propertize (if-let (val (alist-get 'context pomm--state))
(prin1-to-string val)
"unset")
'face 'transient-value))
(transient-define-infix pomm--set-context ()
:class 'pomm--set-context-infix
:key "-c"
:description "Context:")
(defclass pomm--transient-current (transient-suffix) (defclass pomm--transient-current (transient-suffix)
((transient :initform t)) ((transient :initform t))
"A transient class to display the current state of the timer.") "A transient class to display the current state of the timer.")
@ -660,7 +729,8 @@ The class doesn't actually have any value, but this is necessary for transient."
(let ((kind (alist-get 'kind item)) (let ((kind (alist-get 'kind item))
(iteration (alist-get 'iteration item)) (iteration (alist-get 'iteration item))
(start-time (alist-get 'start-time item)) (start-time (alist-get 'start-time item))
(end-time (alist-get 'end-time item))) (end-time (alist-get 'end-time item))
(context (alist-get 'context item)))
(concat (concat
(if (< iteration previous-iteration) (if (< iteration previous-iteration)
(let ((is-first (= previous-iteration 1000))) (let ((is-first (= previous-iteration 1000)))
@ -675,7 +745,10 @@ The class doesn't actually have any value, but this is necessary for transient."
'face (pomm--get-kind-face kind)) 'face (pomm--get-kind-face kind))
(format-time-string "%H:%M" (seconds-to-time start-time)) (format-time-string "%H:%M" (seconds-to-time start-time))
"-" "-"
(format-time-string "%H:%M" (seconds-to-time end-time))))) (format-time-string "%H:%M" (seconds-to-time end-time))
(if context
(format " : %s" (propertize context 'face 'transient-value))
""))))
(alist-get 'history pomm--state) (alist-get 'history pomm--state)
"\n")))) "\n"))))
@ -696,11 +769,14 @@ The class doesn't actually have any value, but this is necessary for transient."
(interactive)) (interactive))
(transient-define-prefix pomm-transient () (transient-define-prefix pomm-transient ()
["Settings" ["Timer settings"
(pomm--set-short-break-period) (pomm--set-short-break-period)
(pomm--set-long-break-period) (pomm--set-long-break-period)
(pomm--set-work-period) (pomm--set-work-period)
(pomm--set-number-of-periods)] (pomm--set-number-of-periods)]
["Context settings"
(pomm--set-context)
(pomm--set-reset-context-on-iteration-end)]
["Commands" ["Commands"
:class transient-row :class transient-row
("s" "Start the timer" pomm-start :transient t) ("s" "Start the timer" pomm-start :transient t)