Replace "project" with "task"

This commit is contained in:
contrapunctus 2019-11-29 10:11:14 +05:30
parent d52b3ec8b1
commit 624eace181
7 changed files with 114 additions and 115 deletions

View File

@ -43,12 +43,12 @@ Each time interval is a string as returned by `chronometrist-seconds-to-hms'."
(--map (time-subtract (cadr it) (car it)))
(--map (chronometrist-seconds-to-hms (cadr it)))))
;; "X minutes on PROJECT (REASON)"
;; "X minutes on TASK (REASON)"
;; TODO - think of a better way to show details concisely, ideally
;; combining tags and key-values
(defun chronometrist-diary-tasks-reasons-on (date)
"Return a list of projects and reasons on DATE."
"Return a list of tasks and reasons on DATE."
(mapcar (lambda (plist)
(let ((task (plist-get plist :name))
(reason (or (plist-get plist :comment) "")))
@ -69,14 +69,14 @@ Optional argument DATE should be a list in the form
The optional arguments _IGNORE-AUTO and _NOCONFIRM are ignored,
and are present solely for the sake of using this function as a
value of `revert-buffer-function'."
(let* ((date (if date date (chronometrist-date)))
(intervals (->> (chronometrist-intervals-on date)
(mapcar #'chronometrist-format-time)))
(projects-reasons (chronometrist-diary-tasks-reasons-on date))
(let* ((date (if date date (chronometrist-date)))
(intervals (->> (chronometrist-intervals-on date)
(mapcar #'chronometrist-format-time)))
(tasks-reasons (chronometrist-diary-tasks-reasons-on date))
(inhibit-read-only t))
(setq chronometrist-diary--current-date date)
(chronometrist-common-clear-buffer chronometrist-diary-buffer-name)
(seq-mapn #'insert intervals projects-reasons)))
(seq-mapn #'insert intervals tasks-reasons)))
(define-derived-mode chronometrist-diary-view-mode special-mode "Chronometrist-Diary"
"A mode to view your activity today like a diary."

View File

@ -3,7 +3,6 @@
;; Author: contrapunctus <xmpp:contrapunctus@jabber.fr>
;;; Commentary:
;; TODO - convert project names to tags
;;; Code:

View File

@ -74,18 +74,18 @@ The first date is the first occurrence of
"Create entries to be displayed in the `chronometrist-report' buffer."
(let* ((week-dates (chronometrist-report-date->week-dates))) ;; uses today if chronometrist-report--ui-date is nil
(setq chronometrist-report--ui-week-dates week-dates)
(mapcar (lambda (project)
(let ((project-daily-time-list
(--map (chronometrist-task-time-one-day project
(mapcar (lambda (task)
(let ((task-daily-time-list
(--map (chronometrist-task-time-one-day task
(chronometrist-date it))
week-dates)))
(list project
(list task
(vconcat
(vector project)
(->> project-daily-time-list
(vector task)
(->> task-daily-time-list
(mapcar #'chronometrist-format-time)
(apply #'vector))
(->> project-daily-time-list
(->> task-daily-time-list
(-reduce #'chronometrist-time-add)
(chronometrist-format-time)
(vector))))))
@ -182,11 +182,11 @@ Argument _FS-EVENT is ignored."
(define-key map (kbd "l") #'chronometrist-open-file)
(define-key map (kbd "b") #'chronometrist-report-previous-week)
(define-key map (kbd "f") #'chronometrist-report-next-week)
;; Works when number of projects < screen length; after that, you
;; Works when number of tasks < screen length; after that, you
;; probably expect mousewheel to scroll up/down, and
;; alt-mousewheel or something for next/previous week. For now,
;; I'm assuming most people won't have all that many tasks - I've
;; been using it for ~2 months and have 18 projects, which are
;; been using it for ~2 months and have 18 tasks, which are
;; still just half the screen on my 15" laptop. Let's see what
;; people say.
(define-key map [mouse-4] #'chronometrist-report-next-week)
@ -197,7 +197,7 @@ Argument _FS-EVENT is ignored."
(define-derived-mode chronometrist-report-mode tabulated-list-mode "Chronometrist-Report"
"Major mode for `chronometrist-report'."
(make-local-variable 'tabulated-list-format)
(setq tabulated-list-format [("Project" 25 t)
(setq tabulated-list-format [("Task" 25 t)
("Sunday" 10 t)
("Monday" 10 t)
("Tuesday" 10 t)
@ -209,7 +209,7 @@ Argument _FS-EVENT is ignored."
(make-local-variable 'tabulated-list-entries)
(setq tabulated-list-entries 'chronometrist-report-entries)
(make-local-variable 'tabulated-list-sort-key)
(setq tabulated-list-sort-key '("Project" . nil))
(setq tabulated-list-sort-key '("Task" . nil))
(tabulated-list-init-header)
(chronometrist-maybe-start-timer)
(setq revert-buffer-function #'chronometrist-report-refresh)

View File

@ -87,8 +87,8 @@ displayed. They must be dates in the form (YEAR MONTH DAY).")
;; ## FUNCTIONS ##
(defun chronometrist-statistics-count-average-time-spent (project &optional table)
"Return the average time the user has spent on PROJECT from TABLE.
(defun chronometrist-statistics-count-average-time-spent (task &optional table)
"Return the average time the user has spent on TASK from TABLE.
TABLE must be a hash table - if not supplied,
`chronometrist-events' is used.
@ -99,7 +99,7 @@ which span midnights. (see `chronometrist-events-clean')"
(days 0)
(per-day-time-list))
(maphash (lambda (key _value)
(let ((events-in-day (chronometrist-task-events-in-day project key)))
(let ((events-in-day (chronometrist-task-events-in-day task key)))
(when events-in-day
(setq days (1+ days))
(->> events-in-day
@ -123,8 +123,8 @@ It simply operates on the entire hash table TABLE (see
`chronometrist-events' for table format), so ensure that TABLE is
reduced to the desired range using
`chronometrist-events-subset'."
(mapcar (lambda (project)
(let* ((active-days (chronometrist-statistics-count-active-days project table))
(mapcar (lambda (task)
(let* ((active-days (chronometrist-statistics-count-active-days task table))
(active-percent (cl-case (plist-get chronometrist-statistics--ui-state :mode)
('week (* 100 (/ active-days 7.0)))))
(active-percent (if (zerop active-days)
@ -134,15 +134,15 @@ reduced to the desired range using
(if (zerop active-days)
"-"
active-days)))
(average-time (->> (chronometrist-statistics-count-average-time-spent project table)
(average-time (->> (chronometrist-statistics-count-average-time-spent task table)
(chronometrist-seconds-to-hms)
(chronometrist-format-time)
(format "% 5s")))
(content (vector project
(content (vector task
active-days
active-percent
average-time)))
(list project content)))
(list task content)))
chronometrist-task-list))
(defun chronometrist-statistics-entries ()
@ -226,7 +226,7 @@ value of `revert-buffer-function'."
"Major mode for `chronometrist-statistics'."
(make-local-variable 'tabulated-list-format)
(setq tabulated-list-format
[("Project" 25 t)
[("Task" 25 t)
("Active days" 12 t)
("%% of days active" 17 t)
("Average time" 12 t)
@ -237,7 +237,7 @@ value of `revert-buffer-function'."
(make-local-variable 'tabulated-list-entries)
(setq tabulated-list-entries 'chronometrist-statistics-entries)
(make-local-variable 'tabulated-list-sort-key)
(setq tabulated-list-sort-key '("Project" . nil))
(setq tabulated-list-sort-key '("Task" . nil))
(tabulated-list-init-header)
;; (chronometrist-maybe-start-timer)
(setq revert-buffer-function #'chronometrist-statistics-refresh)

View File

@ -19,7 +19,7 @@
"Refresh Chronometrist and related buffers.
Buffers will be refreshed only if they are visible and the user
is clocked in to a project."
is clocked in to a task."
(when (chronometrist-current-task) ;; FIXME - This line is currently
;; resulting in no refresh at midnight. When `chronometrist-entries' is
;; optimized to consume less CPU and avoid unnecessary parsing,

View File

@ -51,7 +51,7 @@
;; ## VARIABLES ##
;;; Code:
(defvar chronometrist--project-history nil)
(defvar chronometrist--task-history nil)
(defvar chronometrist--point nil)
(defvar chronometrist-mode-map)
@ -80,7 +80,7 @@ See custom variable `chronometrist-activity-indicator'."
(list it
(vector (number-to-string (1+ it-index))
(list it
'action 'chronometrist-toggle-project-button
'action 'chronometrist-toggle-task-button
'follow-link t)
(-> (chronometrist-task-time-one-day it)
(chronometrist-format-time))
@ -88,8 +88,8 @@ See custom variable `chronometrist-activity-indicator'."
(chronometrist-activity-indicator)
""))))))
(defun chronometrist-project-at-point ()
"Return the project at point in the `chronometrist' buffer, or nil if there is no project at point."
(defun chronometrist-task-at-point ()
"Return the task at point in the `chronometrist' buffer, or nil if there is no task at point."
(save-excursion
(beginning-of-line)
(if (re-search-forward "[0-9]+ +" nil t)
@ -101,8 +101,8 @@ See custom variable `chronometrist-activity-indicator'."
(replace-regexp-in-string "[ \t]*$" "" it))
nil)))
(defun chronometrist-goto-last-project ()
"In the `chronometrist' buffer, move point to the line containing the last active project."
(defun chronometrist-goto-last-task ()
"In the `chronometrist' buffer, move point to the line containing the last active task."
(goto-char (point-min))
;; FIXME
;; (re-search-forward timeclock-last-project nil t)
@ -125,9 +125,9 @@ If FIRSTONLY is non-nil, return only the first keybinding found."
(with-current-buffer chronometrist-buffer-name
(let ((inhibit-read-only t)
(w "\n ")
;; (keybind-start-new (chronometrist-format-keybinds 'chronometrist-add-new-project
;; (keybind-start-new (chronometrist-format-keybinds 'chronometrist-add-new-task
;; chronometrist-mode-map))
(keybind-toggle (chronometrist-format-keybinds 'chronometrist-toggle-project
(keybind-toggle (chronometrist-format-keybinds 'chronometrist-toggle-task
chronometrist-mode-map
t)))
(goto-char (point-max))
@ -141,21 +141,21 @@ If FIRSTONLY is non-nil, return only the first keybinding found."
(insert w (format "% 17s" "Keys")
w (format "% 17s" "----"))
(chronometrist-print-keybind 'chronometrist-add-new-project)
(insert-text-button "start a new project"
'action #'chronometrist-add-new-project-button
(chronometrist-print-keybind 'chronometrist-add-new-task)
(insert-text-button "start a new task"
'action #'chronometrist-add-new-task-button
'follow-link t)
(chronometrist-print-keybind 'chronometrist-toggle-project
"toggle project at point")
(chronometrist-print-keybind 'chronometrist-toggle-task
"toggle task at point")
(chronometrist-print-keybind 'chronometrist-toggle-project-no-reason
(chronometrist-print-keybind 'chronometrist-toggle-task-no-reason
"toggle without asking for reason")
(insert "\n " (format "%s %s - %s"
"<numeric argument N>"
keybind-toggle
"toggle <N>th project"))
"toggle <N>th task"))
(chronometrist-print-keybind 'chronometrist-report)
(insert-text-button "see weekly report"
@ -168,14 +168,14 @@ If FIRSTONLY is non-nil, return only the first keybinding found."
'follow-link t)
(insert "\n"))))
(defun chronometrist-goto-nth-project (n)
"Move point to the line containing the Nth project.
Return the project at point, or nil if there is no corresponding
project. N must be a positive integer."
(defun chronometrist-goto-nth-task (n)
"Move point to the line containing the Nth task.
Return the task at point, or nil if there is no corresponding
task. N must be a positive integer."
(goto-char (point-min))
(when (re-search-forward (format "^%d" n) nil t)
(beginning-of-line)
(chronometrist-project-at-point)))
(chronometrist-task-at-point)))
(defun chronometrist-refresh (&optional _ignore-auto _noconfirm)
"Refresh the `chronometrist' buffer, without re-reading `chronometrist-file'.
@ -206,39 +206,39 @@ Argument _FS-EVENT is ignored."
;; ## HOOKS ##
(defvar chronometrist-before-in-functions nil
"Functions to run before a project is clocked in.
"Functions to run before a task is clocked in.
Each function in this hook must accept a single argument, which
is the name of the project to be clocked-in.
is the name of the task to be clocked-in.
The commands `chronometrist-toggle-project-button',
`chronometrist-add-new-project-button',
`chronometrist-toggle-project',
`chronometrist-add-new-project', and
`chronometrist-toggle-project-no-reason' will run this hook.")
The commands `chronometrist-toggle-task-button',
`chronometrist-add-new-task-button',
`chronometrist-toggle-task',
`chronometrist-add-new-task', and
`chronometrist-toggle-task-no-reason' will run this hook.")
(defvar chronometrist-after-in-functions nil
"Functions to run after a project is clocked in.
"Functions to run after a task is clocked in.
Each function in this hook must accept a single argument, which
is the name of the project to be clocked-in.
is the name of the task to be clocked-in.
The commands `chronometrist-toggle-project-button',
`chronometrist-add-new-project-button',
`chronometrist-toggle-project',
`chronometrist-add-new-project', and
`chronometrist-toggle-project-no-reason' will run this hook.")
The commands `chronometrist-toggle-task-button',
`chronometrist-add-new-task-button',
`chronometrist-toggle-task',
`chronometrist-add-new-task', and
`chronometrist-toggle-task-no-reason' will run this hook.")
(defvar chronometrist-before-out-functions nil
"Functions to run before a project is clocked out.
"Functions to run before a task is clocked out.
Each function in this hook must accept a single argument, which
is the name of the project to be clocked out of.
is the name of the task to be clocked out of.
The project will be stopped only if all functions in this list
The task will be stopped only if all functions in this list
return a non-nil value.")
(defvar chronometrist-after-out-functions nil
"Functions to run after a project is clocked out.
"Functions to run after a task is clocked out.
Each function in this hook must accept a single argument, which
is the name of the project to be clocked out of.")
is the name of the task to be clocked out of.")
(defun chronometrist-run-functions-and-clock-in (task)
"Run hooks and clock in to TASK."
@ -255,13 +255,13 @@ is the name of the project to be clocked out of.")
;; ## MAJOR-MODE ##
(defvar chronometrist-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "RET") #'chronometrist-toggle-project)
(define-key map (kbd "M-RET") #'chronometrist-toggle-project-no-reason)
(define-key map (kbd "RET") #'chronometrist-toggle-task)
(define-key map (kbd "M-RET") #'chronometrist-toggle-task-no-reason)
(define-key map (kbd "l") #'chronometrist-open-file)
(define-key map (kbd "r") #'chronometrist-report)
(define-key map [mouse-1] #'chronometrist-toggle-project)
(define-key map [mouse-3] #'chronometrist-toggle-project-no-reason)
(define-key map (kbd "a") #'chronometrist-add-new-project)
(define-key map [mouse-1] #'chronometrist-toggle-task)
(define-key map [mouse-3] #'chronometrist-toggle-task-no-reason)
(define-key map (kbd "a") #'chronometrist-add-new-task)
map)
"Keymap used by `chronometrist-mode'.")
@ -269,36 +269,36 @@ is the name of the project to be clocked out of.")
"Major mode for `chronometrist'."
(make-local-variable 'tabulated-list-format)
(setq tabulated-list-format [("#" 3 t)
("Project" 25 t)
("Task" 25 t)
("Time" 10 t)
("Active" 3 t)])
(make-local-variable 'tabulated-list-entries)
(setq tabulated-list-entries 'chronometrist-entries)
(make-local-variable 'tabulated-list-sort-key)
(setq tabulated-list-sort-key '("Project" . nil))
(setq tabulated-list-sort-key '("Task" . nil))
(tabulated-list-init-header)
(setq revert-buffer-function #'chronometrist-refresh))
;; ## BUTTONS ##
;; FIXME - there is duplication between this function and `chronometrist-toggle-project's logic
(defun chronometrist-toggle-project-button (_button)
"Button action to toggle a project.
;; FIXME - there is duplication between this function and `chronometrist-toggle-task's logic
(defun chronometrist-toggle-task-button (_button)
"Button action to toggle a task.
Argument _BUTTON is for the purpose of using this as a button
action, and is ignored."
(let ((current (chronometrist-current-task))
(at-point (chronometrist-project-at-point)))
(at-point (chronometrist-task-at-point)))
;; clocked in + point on current = clock out
;; clocked in + point on some other project = clock out, clock in to project
;; clocked in + point on some other task = clock out, clock in to task
;; clocked out = clock in
(when current
(chronometrist-run-functions-and-clock-out current))
(unless (equal at-point current)
(chronometrist-run-functions-and-clock-in at-point))))
(defun chronometrist-add-new-project-button (_button)
"Button action to add a new project.
(defun chronometrist-add-new-task-button (_button)
"Button action to add a new task.
Argument _BUTTON is for the purpose of using this as a button
action, and is ignored."
@ -310,46 +310,46 @@ action, and is ignored."
;; ## COMMANDS ##
;; TODO - if clocked in and point not on a project, just clock out
;; TODO - if clocked in and point not on a task, just clock out
;; PROFILE
;; TODO - implement `chronometrist-ask-tags-p' and `chronometrist-ask-key-values-p' (don't prompt for them if nil)
(defun chronometrist-toggle-project (&optional prefix)
"Start or stop the project at point.
(defun chronometrist-toggle-task (&optional prefix)
"Start or stop the task at point.
If there is no project at point, do nothing.
If there is no task at point, do nothing.
With numeric prefix argument PREFIX, toggle the Nth project in
the buffer. If there is no corresponding project, do nothing."
With numeric prefix argument PREFIX, toggle the Nth task in
the buffer. If there is no corresponding task, do nothing."
(interactive "P")
(let* ((empty-file (chronometrist-common-file-empty-p chronometrist-file))
(nth (when prefix (chronometrist-goto-nth-project prefix)))
(at-point (chronometrist-project-at-point))
(nth (when prefix (chronometrist-goto-nth-task prefix)))
(at-point (chronometrist-task-at-point))
(target (or nth at-point))
(current (chronometrist-current-task)))
(cond (empty-file (chronometrist-add-new-project)) ;; do not run hooks - chronometrist-add-new-project will do it
(cond (empty-file (chronometrist-add-new-task)) ;; do not run hooks - chronometrist-add-new-task will do it
;; What should we do if the user provides an invalid argument? Currently - nothing.
((and prefix (not nth)))
(target ;; do nothing if there's no project at point
(target ;; do nothing if there's no task at point
;; clocked in + target is current = clock out
;; clocked in + target is some other project = clock out, clock in to project
;; clocked in + target is some other task = clock out, clock in to task
;; clocked out = clock in
(when current
(chronometrist-run-functions-and-clock-out current))
(unless (equal target current)
(chronometrist-run-functions-and-clock-in target))))))
(defun chronometrist-toggle-project-no-reason (&optional prefix)
"Like `chronometrist-toggle-project', but don't ask for a reason.
(defun chronometrist-toggle-task-no-reason (&optional prefix)
"Like `chronometrist-toggle-task', but don't ask for a reason.
With numeric prefix argument PREFIX, toggle the Nth project. If there
is no corresponding project, do nothing."
With numeric prefix argument PREFIX, toggle the Nth task. If there
is no corresponding task, do nothing."
(interactive "P")
(chronometrist-toggle-project prefix))
(chronometrist-toggle-task prefix))
(defun chronometrist-add-new-project ()
"Add a new project."
(defun chronometrist-add-new-task ()
"Add a new task."
(interactive)
(chronometrist-add-new-project-button nil))
(chronometrist-add-new-task-button nil))
;;;###autoload
(defun chronometrist (&optional arg)
@ -379,8 +379,8 @@ If numeric argument ARG is 2, run `chronometrist-statistics'."
(let ((inhibit-read-only t))
(chronometrist-common-clear-buffer buffer)
(insert "Welcome to Chronometrist! Hit RET to ")
(insert-text-button "start a new project."
'action #'chronometrist-add-new-project-button
(insert-text-button "start a new task."
'action #'chronometrist-add-new-task-button
'follow-link t)
(chronometrist-mode)
(switch-to-buffer buffer)))
@ -395,7 +395,7 @@ If numeric argument ARG is 2, run `chronometrist-statistics'."
(chronometrist-refresh-file nil))
(if chronometrist--point
(goto-char chronometrist--point)
(chronometrist-goto-last-project))))
(chronometrist-goto-last-task))))
(unless chronometrist--fs-watch
(setq chronometrist--fs-watch
(file-notify-add-watch chronometrist-file

View File

@ -98,18 +98,18 @@
6. Major Mode - chronometrist-diary-view-mode
7. Command - chronometrist-diary-view (&optional date)
*** chronometrist.el
1. Variable - chronometrist--project-history
1. Variable - chronometrist--task-history
2. Variable - chronometrist--point
3. Variable - chronometrist-mode-map
4. Function - chronometrist-task-active? (task)
* String -> Boolean
5. Function - chronometrist-activity-indicator ()
6. Function - chronometrist-entries ()
7. Function - chronometrist-project-at-point ()
8. Function - chronometrist-goto-last-project ()
7. Function - chronometrist-task-at-point ()
8. Function - chronometrist-goto-last-task ()
9. Function - chronometrist-print-keybind (command &optional description firstonly)
10. Function - chronometrist-print-non-tabular ()
11. Function - chronometrist-goto-nth-project (n)
11. Function - chronometrist-goto-nth-task (n)
12. Function - chronometrist-refresh (&optional ignore-auto noconfirm)
13. Function - chronometrist-refresh-file (fs-event)
14. Variable - chronometrist-before-in-functions
@ -120,11 +120,11 @@
19. Function - chronometrist-run-functions-and-clock-out (task)
20. Variable - chronometrist-mode-map
21. Major Mode - chronometrist-mode
22. Function - chronometrist-toggle-project-button (button)
23. Function - chronometrist-add-new-project-button (button)
24. Command - chronometrist-toggle-project (&optional prefix)
25. Command - chronometrist-toggle-project-no-reason (&optional prefix)
26. Command - chronometrist-add-new-project ()
22. Function - chronometrist-toggle-task-button (button)
23. Function - chronometrist-add-new-task-button (button)
24. Command - chronometrist-toggle-task (&optional prefix)
25. Command - chronometrist-toggle-task-no-reason (&optional prefix)
26. Command - chronometrist-add-new-task ()
27. Command - chronometrist (&optional arg)
*** chronometrist-events.el
1. Variable - chronometrist-events
@ -214,7 +214,7 @@
1. Variable - chronometrist-statistics--ui-state
2. Variable - chronometrist-statistics--point
3. Variable - chronometrist-statistics-mode-map
4. Function - chronometrist-statistics-count-average-time-spent (project &optional table)
4. Function - chronometrist-statistics-count-average-time-spent (task &optional table)
* string &optional hash-table -> seconds
5. Function - chronometrist-statistics-entries-internal (table)
6. Function - chronometrist-statistics-entries ()