New command - chronometrist-toggle-project-no-reason

This commit is contained in:
Kashish Sharma 2018-09-25 20:15:55 +05:30
parent 28c0a1e37f
commit 284902e70c
2 changed files with 75 additions and 52 deletions

View File

@ -12,7 +12,7 @@ Add the Chronometrist directory to your load-path, and `(require 'chronometrist)
### chronometrist
Run `M-x chronometrist` to see your projects, the time you spent on them today, which one is active, and the total time clocked today.
Hit `RET` on a project to clock in for it. If it's already clocked in, it will be clocked out (and you'll be prompted for an optional reason).
Hit `RET` on a project to clock in for it. If it's already clocked in, it will be clocked out, and you'll be prompted for an optional reason. Use `M-RET` if you don't want to be asked for a reason.
Whenever you call `chronometrist`, the cursor will helpfully be placed on the last activity you clocked out of, or the current activity clocked in.
@ -22,7 +22,7 @@ Press `l` to view your `timeclock-file` (`~/.emacs.d/timelog` by default). Press
Running `M-x chronometrist` when the Chronometrist buffer is visible will kill it, so the key you bind it to can function as a toggle.
`chronometrist` keeps itself updated via an idle timer - no pressing `g` to update.
`chronometrist` keeps itself updated via an idle timer - no need to frequently press `g` to update.
### chronometrist-report
Run `M-x chronometrist-report` (or `chronometrist` with a prefix argument, or press `r` in the `chronometrist` buffer) to see a weekly report.
@ -38,6 +38,12 @@ Just like `chronometrist`, `chronometrist-report` will also toggle the visibilty
## Customization
See the Customize groups `chronometrist` and `chronometrist-report` for variables intended to be user-customizable.
If you find that you usually _don't_ want to enter a reason, you can switch the default bindings -
```elisp
(define-key chronometrist-mode-map (kbd "M-RET") #'chronometrist-toggle-project)
(define-key chronometrist-mode-map (kbd "RET") #'chronometrist-toggle-project-no-reason)
```
## Roadmap
* New commands for statistics
- activity-specific - average time spent in $time_period, average days worked on in $time_period, current/longest streaks, ...
@ -47,32 +53,31 @@ See the Customize groups `chronometrist` and `chronometrist-report` for variable
* [inflatable raptor](https://github.com/MichaelMure/git-bug/#planned-features)
### chronometrist
1. Add variable to let user control prompting-for-reason behaviour
2. Make clocked-in project row bold, either in addition to the star, or replacing it.
3. **'kill'/discard command** (bind to 'k'), which will delete the interval currently being recorded.
1. Make clocked-in project row bold, either in addition to the star, or replacing it.
2. **'kill'/discard command** (bind to 'k'), which will delete the interval currently being recorded.
- Most conservative option - it will only operate on the project at point, and will only kill for a clocked-in project.
- Somewhat less conservative option - it will operate on the currently clocked-in project, no matter where point is.
- It _should_ ask for confirmation.
4. **Custom day start/end time** - option to use a specific time to define when a day starts/ends. e.g. 08:00 will mean a day starts and ends at 08:00 instead of the usual 24:00/00:00. Helpful for late sleepers.
5. **Fix suggested reasons** - the default reason suggested is the last one used. Can't even begin to explain how nonsensical that is. (might be an ido or timeclock.el problem)
3. **Custom day start/end time** - option to use a specific time to define when a day starts/ends. e.g. 08:00 will mean a day starts and ends at 08:00 instead of the usual 24:00/00:00. Helpful for late sleepers.
4. **Fix suggested reasons** - the default reason suggested is the last one used. Can't even begin to explain how nonsensical that is. (might be an ido or timeclock.el problem)
- Make default blank?
- Possibly make suggestions activity-sensitive e.g. when stopping activity A, don't suggest past reasons used for activity B, C, etc. Add a variable to customize this, because it might not be the behaviour everyone wants.
- Suggest reasons by frequency? So your most used reason for the task is the default suggestion. If you usually _don't_ provide a reason for the task, the default is nil.
6. **Better shortcuts** - Shortcuts derived from the first alphabet of each project could be even nicer.
7. **Modeline support** - show currently active project + time spent on it so far in the mode-line (see timeclock-mode-line-display)
5. **Better shortcuts** - Shortcuts derived from the first alphabet of each project could be even nicer.
6. **Modeline support** - show currently active project + time spent on it so far in the mode-line (see timeclock-mode-line-display)
- Maybe make modeline slowly change color the longer you do something?
8. **Improve help**
7. **Improve help**
- Show shortcuts by consulting the keymap rather than using a hardcoded string.
- Change 'see weekly report' and 'open log file' to buttons
9. **Reminder notifications** - a common issue with time trackers is that people forget to clock in/out. A potential solution can be to have Emacs remind people (ideally via desktop notifications?) -
8. **Reminder notifications** - a common issue with time trackers is that people forget to clock in/out. A potential solution can be to have Emacs remind people (ideally via desktop notifications?) -
- when they haven't clocked in, every X minutes (e.g. 30)
- that they are clocked in, every X minutes (e.g. 30)
- of course, modeline support might help too.
10. Use `make-thread` in v26 or the emacs-async library for `chronometrist-entries`/`chronometrist-report-entries`
11. Some way to update buffers every second without making Emacs unusable. (impossible?)
12. "Day summary" - for users who use the "reason" feature to note the specifics of their actual work. Combine the reasons together to create a descriptive overview of the work done in the day.
13. Commands to rename a project, delete a project (erasing all records)
14. Hooks to be run before clocking in and after clocking out. The functions must accept a single parameter - the name of the project. (see `run-hook-with-args`)
9. Use `make-thread` in v26 or the emacs-async library for `chronometrist-entries`/`chronometrist-report-entries`
10. Some way to update buffers every second without making Emacs unusable. (impossible?)
11. "Day summary" - for users who use the "reason" feature to note the specifics of their actual work. Combine the reasons together to create a descriptive overview of the work done in the day.
12. Commands to rename a project, delete a project (erasing all records)
13. Hooks to be run before clocking in and after clocking out. The functions must accept a single parameter - the name of the project. (see `run-hook-with-args`)
### chronometrist-report
1. Highlight column of current day

View File

@ -189,8 +189,10 @@ information (see (info \"(elisp)Time Conversion\"))."
(insert w "Keys")
(insert w "a - ")
(insert-text-button "start a new project"
'action #'chronometrist-add-new-project
'action #'chronometrist-add-new-project-button
'follow-link t)
(insert w "RET/[mouse-1] - toggle project at point")
(insert w "M-RET/[mouse-3] - toggle without asking for reason")
(insert w "<numeric argument N> RET - toggle <N>th project")
(insert w "r - ")
(insert-text-button "see weekly report"
@ -237,13 +239,16 @@ there is no corresponding project."
(tabulated-list-init-header)
(define-key chronometrist-mode-map (kbd "RET") #'chronometrist-toggle-project)
(define-key chronometrist-mode-map (kbd "l") #'chronometrist-open-timeclock-file)
(define-key chronometrist-mode-map (kbd "r") #'chronometrist-report)
(define-key chronometrist-mode-map [mouse-1] #'chronometrist-toggle-project)
(define-key chronometrist-mode-map (kbd "a") #'(lambda () (interactive) (chronometrist-add-new-project nil))))
(define-key chronometrist-mode-map (kbd "RET") #'chronometrist-toggle-project)
(define-key chronometrist-mode-map (kbd "M-RET") #'chronometrist-toggle-project-no-reason)
(define-key chronometrist-mode-map (kbd "l") #'chronometrist-open-timeclock-file)
(define-key chronometrist-mode-map (kbd "r") #'chronometrist-report)
(define-key chronometrist-mode-map [mouse-1] #'chronometrist-toggle-project)
(define-key chronometrist-mode-map [mouse-3] #'chronometrist-toggle-project-no-reason)
(define-key chronometrist-mode-map (kbd "a") #'chronometrist-add-new-project))
;; ## COMMANDS ##
;; ## BUTTONS ##
;; Duplication between this function and `chronometrist-toggle-project's logic
(defun chronometrist-toggle-project-button (button)
@ -261,35 +266,7 @@ there is no corresponding project."
(timeclock-in nil project-at-point nil))
(chronometrist-refresh)))
(defun chronometrist-toggle-project (&optional arg)
"In a `chronometrist' buffer, start or stop the project at
point. If there is no project at point, do nothing.
With a numeric prefix argument, toggle the Nth project. If there
is no corresponding project, do nothing."
(interactive "P")
(let* ((nth-project (when arg (chronometrist-get-nth-project arg)))
(project-at-point (chronometrist-project-at-point))
(target-project (or nth-project project-at-point))
(current-project (chronometrist-current-project)))
(cond ((chronometrist-common-file-empty-p timeclock-file)
(timeclock-in nil nil t))
;; What should we do if the user provides an invalid argument? Currently - nothing.
((and arg (not nth-project)))
(target-project ;; do nothing if there's no project at point
;; If we're clocked in to anything - clock out or change projects
(if current-project
(if (equal target-project current-project)
(timeclock-out nil nil t)
;; We don't use timeclock-change because it doesn't prompt for the reason
(progn
(timeclock-out nil nil t)
(timeclock-in nil target-project nil)))
;; Otherwise, run timeclock-in with project at point as default suggestion
(timeclock-in nil target-project nil))))
(chronometrist-refresh)))
(defun chronometrist-add-new-project (button)
(defun chronometrist-add-new-project-button (button)
(when (chronometrist-current-project)
(timeclock-out nil nil t))
(timeclock-in nil
@ -298,6 +275,47 @@ is no corresponding project, do nothing."
nil)
(chronometrist-refresh))
;; ## COMMANDS ##
(defun chronometrist-toggle-project (&optional prefix no-prompt)
"In a `chronometrist' buffer, start or stop the project at
point. If there is no project at point, do nothing.
With a numeric prefix argument, toggle the Nth project. If there
is no corresponding project, do nothing."
(interactive "P")
(let* ((nth-project (when prefix (chronometrist-get-nth-project prefix)))
(project-at-point (chronometrist-project-at-point))
(target-project (or nth-project project-at-point))
(current-project (chronometrist-current-project))
(ask (not no-prompt)))
(cond ((chronometrist-common-file-empty-p timeclock-file)
(timeclock-in nil nil t))
;; What should we do if the user provides an invalid argument? Currently - nothing.
((and prefix (not nth-project)))
(target-project ;; do nothing if there's no project at point
;; If we're clocked in to anything - clock out or change projects
(if current-project
(if (equal target-project current-project)
(timeclock-out nil nil ask)
;; We don't use timeclock-change because it doesn't prompt for the reason
(progn
(timeclock-out nil nil ask)
(timeclock-in nil target-project nil)))
;; Otherwise, run timeclock-in with project at point as default suggestion
(timeclock-in nil target-project nil))))
(chronometrist-refresh)))
(defun chronometrist-toggle-project-no-reason (&optional prefix)
"Like `chronometrist-toggle-project', but do not ask for a
reason if clocking out."
(interactive "P")
(funcall-interactively #'chronometrist-toggle-project prefix t))
(defun chronometrist-add-new-project ()
(interactive)
(chronometrist-add-new-project-button nil))
(defun chronometrist (&optional arg)
"Displays a list of the user's timeclock.el projects and the
time spent on each today, based on their timelog file