This repository has been archived on 2022-05-13. You can view files and clone it, but cannot push or open issues or pull requests.
chronometrist/manual.org

444 lines
18 KiB
Org Mode
Raw Permalink Normal View History

2022-04-14 08:43:33 +00:00
#+TITLE: Chronometrist
#+SUBTITLE: Friendly and powerful personal time tracker/analyzer with Emacs and CLIM frontends
2022-01-23 05:12:54 +00:00
#+DESCRIPTION: User Manual
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="style.css" />
#+BEGIN_EXPORT html
2022-02-20 08:03:01 +00:00
<a href="https://liberapay.com/contrapunctus/donate">
<img alt="Donate using Liberapay" src="https://img.shields.io/liberapay/receives/contrapunctus.svg?logo=liberapay">
</a>
2022-02-20 08:03:01 +00:00
<a href="https://melpa.org/#/chronometrist">
<img src="https://melpa.org/packages/chronometrist-badge.svg">
</a>
#+END_EXPORT
2021-05-26 07:53:58 +00:00
* Explanation
2022-04-27 10:56:26 +00:00
:PROPERTIES:
:CUSTOM_ID: explanation
:END:
Chronometrist is a friendly and powerful personal time tracker and analyzer. It has frontends for Emacs and [[https://mcclim.common-lisp.dev/][CLIM]].
2021-05-26 07:53:58 +00:00
2022-02-20 08:03:01 +00:00
#+CAPTION: The main Chronometrist buffer, with the enabled extensions [[#time-goals][chronometrist-goal]] ("Targets" column + alerts) and chronometrist-spark ("Graph" column displaying the activity for the past 4 weeks).
[[file:doc/2022-02-20 13-26-53.png]]
2021-05-26 07:53:58 +00:00
** Benefits
:PROPERTIES:
:CUSTOM_ID: benefits
:END:
2021-05-26 07:53:58 +00:00
1. Extremely simple and efficient to use
2022-04-15 04:30:34 +00:00
2. Displays useful information about your time usage (including fancy graphs with the =chronometrist-spark= extension)
2021-05-26 07:53:58 +00:00
3. Support for both mouse and keyboard
2022-04-15 04:30:34 +00:00
4. Human errors in tracking can be easily fixed by editing a plain text file
5. Hooks to integrate time tracking into your workflow
2021-05-26 07:53:58 +00:00
** Limitations
:PROPERTIES:
:CUSTOM_ID: limitations
:END:
2022-01-23 05:26:08 +00:00
1. No support for concurrent tasks.
2021-05-26 07:53:58 +00:00
** Comparisons
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: comparisons
:END:
*** timeclock.el (Emacs built-in)
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: timeclock.el
:END:
Compared to timeclock.el, Chronometrist
+ stores data in an s-expression format rather than a line-based one
+ supports attaching tags and arbitrary key-values to time intervals
+ has commands to shows useful summaries
+ has more hooks
2021-05-26 07:53:58 +00:00
*** Org time tracking
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: org-time-tracking
:END:
Chronometrist and Org time tracking seem to be equivalent in terms of capabilities, approaching the same ends through different means.
+ Chronometrist doesn't have a mode line indicator at the moment. (planned)
+ Chronometrist doesn't have Org's sophisticated querying facilities. (an SQLite backend is planned)
+ Org does so many things that keybindings seem to necessarily get longer. Chronometrist has far fewer commands than Org, so most of the keybindings are single keys, without modifiers.
+ Chronometrist's UI is cleaner, since the storage is separate from the display. It doesn't show tasks as trees like Org, but it uses tags and key-values to achieve that. Additionally, navigating a flat list takes fewer user operations than navigating a tree.
+ Chronometrist data is just s-expressions (plists), and may be easier to parse than a complex text format with numerous use-cases.
2022-04-14 08:02:19 +00:00
** Common Lisp port
2022-04-27 10:56:26 +00:00
:PROPERTIES:
:CUSTOM_ID: common-lisp-port
:END:
2022-04-14 08:02:19 +00:00
In March 2022, work began on the long-awaited Common Lisp port of Chronometrist, which aims to create -
1. a greater variety of backends (e.g. SQLite)
2. a common reusable library for frontends to use,
3. a greater variety of frontends, such as -
* a command line interface (CLI), for UNIX scripting;
* a terminal user inteface (TUI), for those so inclined;
* a CLIM (Common Lisp Interface Manager) GUI [fn:1],
* Qt and Android interfaces using [[https://gitlab.com/eql/lqml][LQML]],
* web frontends (possibly via [[https://common-lisp.net/project/parenscript/][Parenscript]] or [[https://github.com/rabbibotton/clog][CLOG]]),
* and perhaps even an interface for wearable devices!
The port was also driven by the desire to have access to Common Lisp's better performance, and features such as namespaces, a /de facto/ standard build system, multithreading, SQLite bindings, a more fully-featured implementation of CLOS and MOP, and type annotations, checking, and inference.
2022-04-15 12:13:34 +00:00
The literate sources for the Common Lisp port may be found in [[file:cl/chronometrist.org][cl/chronometrist.org]]. Currently, this port can -
2022-04-14 08:02:19 +00:00
1. import from a plist-group file and export to an SQLite database
#+BEGIN_SRC lisp
2022-04-15 12:13:34 +00:00
(chronometrist:to-file (chronometrist:to-hash-table
(make-instance 'chronometrist.plist-group:plist-group-backend
:file "/path/to/file.plg"))
(make-instance 'chronometrist.sqlite:sqlite-backend)
"/path/to/file.sqlite")
2022-04-14 08:02:19 +00:00
#+END_SRC
2. display a (WIP) CLIM GUI - =(chronometrist.clim:run-chronometrist)=
The Emacs Lisp codebase will probably become an Emacs frontend to a future Common Lisp CLI client.
2022-04-15 05:05:22 +00:00
2022-04-14 08:02:19 +00:00
[fn:1] McCLIM also has an incomplete ncurses backend - when completed, a CLIM frontend could provide a TUI "for free".
2022-04-15 05:05:22 +00:00
** Literate program
:PROPERTIES:
:CUSTOM_ID: explanation-literate-program
:END:
2022-04-15 05:05:22 +00:00
Chronometrist is written as an Org literate program, which makes it easy to obtain different views of the program source, thanks to tree- and source-block folding, tags, properties, and the =org-match= command.
2022-04-15 12:13:34 +00:00
The canonical source file is [[file:elisp/chronometrist.org][elisp/chronometrist.org]], which contains source blocks. These are provided to users after /tangling/ (extracting the source into an Emacs Lisp file). [fn:2]
2022-04-15 05:05:22 +00:00
The Org literate program can also be loaded directly using the [[https://github.com/jingtaozf/literate-elisp][literate-elisp]] package, so that all source links (e.g. =xref=, =describe-function=) lead to the Org file. See [[#how-to-literate-elisp][How to load the program using literate-elisp]].
2022-04-15 12:13:34 +00:00
[fn:2] the literate source is also included in MELPA installs, although not loaded through =literate-elisp-load= by default, since doing so would interfere with automatic generation of autoloads.
** Source code overview
2022-04-27 10:56:26 +00:00
:PROPERTIES:
:CUSTOM_ID: source-code-overview
:END:
2022-04-15 12:13:34 +00:00
At its most basic, we read data from a [[file:elisp/chronometrist.org::#program-backend][backend]] and [[file:elisp/chronometrist.org::#program-frontend-chronometrist][display it]] as a [[elisp:(find-library "tabulated-list")][=tabulated-list-mode=]] buffer.
The plist and plist-group backends (collectively known as the s-expression backends) =read= a text file containing s-expressions into a [[file:elisp/chronometrist.org::#program-data-structures][hash table]], and query that. When the file is changed—whether by the program or the user—they [[file:elisp/chronometrist.org::refresh-file][update the hash table]] and the [[file:elisp/chronometrist.org::#program-frontend-chronometrist-refresh][buffer]]. The s-expression backends also make use of a [[file:elisp/chronometrist.org::#program-pretty-printer][plist pretty-printer]] of their own.
There are also some [[file:elisp/chronometrist.org::#program-migration][migration commands]].
Extensions exist for -
1. [[file:elisp/chronometrist-key-values.org][attaching arbitrary metadata]] to time intervals,
2. [[https://tildegit.org/contrapunctus/chronometrist-goal][time goals and alerts]], and
3. support for the [[file:elisp/chronometrist-third.org][Third Time system]]
** Contributions and contact
:PROPERTIES:
:CUSTOM_ID: contributions-contact
:END:
Feedback and MRs are very welcome. 🙂
+ [[file:TODO.org]] has a long list of tasks
+ [[file:elisp/chronometrist.org]] contains all developer-oriented documentation
If you have tried using Chronometrist, I'd love to hear your experiences! Get in touch with the author and other Emacs users in the Emacs channel on the Jabber network - [[https://conversations.im/j/emacs@salas.suchat.org][xmpp:emacs@salas.suchat.org?join]] ([[https://inverse.chat/#converse/room?jid=emacs@salas.suchat.org][web chat]])
(For help in getting started with Jabber, [[https://xmpp.org/getting-started/][click here]])
** License
:PROPERTIES:
:CUSTOM_ID: license
:END:
2022-04-14 07:55:15 +00:00
I'd /like/ for all software to be liberated - transparent, trustable, and accessible for anyone to use, study, or improve.
2022-04-14 07:55:15 +00:00
I'd /like/ anyone using my software to credit me for the work.
2022-04-14 07:55:15 +00:00
I'd /like/ to receive financial support for my efforts, so I can spend all my time doing what I find meaningful.
But I don't want to make demands or threats (e.g. via legal conditions) to accomplish all that, nor restrict my services to only those who can pay.
Thus, Chronometrist is released under your choice of [[https://unlicense.org/][Unlicense]] or the [[http://www.wtfpl.net/][WTFPL]].
(See files [[file:UNLICENSE][UNLICENSE]] and [[file:WTFPL][WTFPL]]).
** Thanks
:PROPERTIES:
:CUSTOM_ID: thanks
:END:
The main buffer and the report buffer are copied from the Android application, [[https://github.com/netmackan/ATimeTracker][A Time Tracker]]
wasamasa, bpalmer, aidalgol, pjb and the rest of #emacs for their tireless help and support
jwiegley for =timeclock.el=, which we used as a backend in earlier versions
blandest for helping me with the name
fiete and wu-lee for testing and bug reports
* Tutorials
:PROPERTIES:
:CUSTOM_ID: usage
:END:
** Installation
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: installation
:END:
*** from MELPA
2021-05-26 07:53:58 +00:00
:PROPERTIES:
2021-06-02 08:11:55 +00:00
:CUSTOM_ID: install-from-melpa
2021-05-26 07:53:58 +00:00
:END:
1. Set up MELPA - https://melpa.org/#/getting-started
2. =M-x package-install RET chronometrist RET=
*** from Git
2021-05-26 07:53:58 +00:00
:PROPERTIES:
2021-06-02 08:11:55 +00:00
:CUSTOM_ID: install-from-git
2021-05-26 07:53:58 +00:00
:END:
2022-01-23 05:53:48 +00:00
You can get =chronometrist= from https://tildegit.org/contrapunctus/chronometrist or https://codeberg.org/contrapunctus/chronometrist
2021-05-26 07:53:58 +00:00
=chronometrist= requires
+ Emacs v25 or higher
+ [[https://github.com/magnars/dash.el][dash.el]]
+ [[https://github.com/alphapapa/ts.el][ts.el]]
Add the ="elisp/"= subdirectory to your load-path, and =(require 'chronometrist)=.
2021-05-26 07:53:58 +00:00
2021-06-02 08:04:41 +00:00
** chronometrist
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: usage-chronometrist
2021-05-26 07:53:58 +00:00
:END:
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.
Click or hit =RET= (=chronometrist-toggle-task=) on a project to start tracking time for it. If it's already clocked in, it will be clocked out.
2021-05-26 07:53:58 +00:00
You can also hit =<numeric prefix> RET= anywhere in the buffer to toggle the corresponding project, e.g. =C-1 RET= will toggle the project with index 1.
Press =r= to see a weekly report (see =chronometrist-report=)
2021-06-02 08:04:41 +00:00
** chronometrist-report
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: usage-chronometrist-report
2021-05-26 07:53:58 +00:00
:END:
Run =M-x chronometrist-report= (or =chronometrist= with a prefix argument of 1, or press =r= in the =chronometrist= buffer) to see a weekly report.
Press =b= to look at past weeks, and =f= for future weeks.
2021-06-02 08:04:41 +00:00
** chronometrist-statistics
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: usage-chronometrist-statistics
2021-05-26 07:53:58 +00:00
:END:
Run =M-x chronometrist-statistics= (or =chronometrist= with a prefix argument of 2) to view statistics.
Press =b= to look at past time ranges, and =f= for future ones.
2021-06-02 08:04:41 +00:00
** chronometrist-details
2022-04-27 10:56:26 +00:00
:PROPERTIES:
:CUSTOM_ID: chronometrist-details
:END:
2021-05-26 07:53:58 +00:00
2021-06-02 08:04:41 +00:00
** common commands
:PROPERTIES:
:CUSTOM_ID: usage-common-commands
:END:
2021-05-26 07:53:58 +00:00
In the buffers created by the previous three commands, you can press =l= (=chronometrist-open-log=) to view/edit your =chronometrist-file=, which by default is =~/.emacs.d/chronometrist.sexp=.
All of these commands will kill their buffer when run again with the buffer visible, so the keys you bind them to behave as a toggle.
All buffers keep themselves updated via an idle timer - no need to frequently press =g= to update.
2021-06-02 08:04:41 +00:00
** Time goals/targets
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: time-goals
2021-05-26 07:53:58 +00:00
:END:
If you wish you could define time goals for some tasks, and have Chronometrist notify you when you're approaching the goal, completing it, or exceeding it, check out the extension [[https://github.com/contrapunctus-1/chronometrist-goal/][chronometrist-goal.el]].
2022-04-14 08:02:19 +00:00
* How-to Guides
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: how-to
2021-05-26 07:53:58 +00:00
:END:
See the Customize groups =chronometrist= and =chronometrist-report= for variables intended to be user-customizable.
** How to display a prompt when exiting with an active task
:PROPERTIES:
:CUSTOM_ID: how-to-prompt-when-exiting-emacs
:END:
Evaluate or add to your init.el the following -
=(add-hook 'kill-emacs-query-functions 'chronometrist-query-stop)=
** How to load the program using literate-elisp
:PROPERTIES:
:CUSTOM_ID: how-to-literate-elisp
:END:
The literate Org document will automatically =literate-elisp-load= itself when opened, if =literate-elisp= is installed via =package.el=.
If you want it to be loaded with =literate-elisp-load= on Emacs startup, add the following to your init.el -
#+BEGIN_SRC emacs-lisp
(add-to-list 'load-path "<directory containing chronometrist.org>")
(require 'literate-elisp) ;; or autoload, use-package, ...
(literate-elisp-load "chronometrist.org")
#+END_SRC
2021-06-02 08:04:41 +00:00
** How to attach tags to time intervals
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: how-to-tags
2021-05-26 07:53:58 +00:00
:END:
2022-04-15 05:05:22 +00:00
1. Add =chronometrist-tags-add= to one or more of these hooks [fn:3] -
#+BEGIN_SRC emacs-lisp
(add-to-list 'chronometrist-after-in-functions 'chronometrist-tags-add)
(add-to-list 'chronometrist-before-out-functions 'chronometrist-tags-add)
(add-to-list 'chronometrist-after-out-functions 'chronometrist-tags-add)
#+END_SRC
2. clock in/clock out to trigger the hook.
2021-05-26 07:53:58 +00:00
The prompt suggests past combinations you used for the current task, which you can browse with =M-p=/=M-n=. You can leave it blank by pressing =RET=.
2021-05-26 07:53:58 +00:00
2022-04-15 05:05:22 +00:00
[fn:3] but not =chronometrist-before-in-functions=
2021-05-26 07:53:58 +00:00
2021-06-02 08:04:41 +00:00
** How to attach key-values to time intervals
:PROPERTIES:
:CUSTOM_ID: how-to-key-value-pairs
:END:
2022-04-15 05:05:22 +00:00
1. Add =chronometrist-kv-add= to one or more of these hooks [fn:3] -
2022-01-23 06:39:57 +00:00
#+BEGIN_SRC emacs-lisp
(add-to-list 'chronometrist-after-in-functions 'chronometrist-kv-add)
(add-to-list 'chronometrist-before-out-functions 'chronometrist-kv-add)
(add-to-list 'chronometrist-after-out-functions 'chronometrist-kv-add)
2022-01-23 06:39:57 +00:00
#+END_SRC
To exit the prompt, press the key it indicates for quitting - you can then edit the resulting key-values by hand if required. Press =C-c C-c= to accept the key-values, or =C-c C-k= to cancel.
2021-06-02 08:04:41 +00:00
** How to skip running hooks/attaching tags and key values
2022-04-27 10:56:26 +00:00
:PROPERTIES:
:CUSTOM_ID: how-to-skip-running-hooks/attaching-tags-and-key-values
:END:
Use =M-RET= (=chronometrist-toggle-task-no-hooks=) to clock in/out.
2021-06-02 08:04:41 +00:00
** How to open certain files when you start a task
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: how-to-open-files-on-task-start
2021-05-26 07:53:58 +00:00
:END:
An idea from the author's own init -
#+BEGIN_SRC emacs-lisp
(defun my-start-project (project)
(pcase project
("Guitar"
(find-file-other-window "~/repertoire.org"))
;; ...
))
(add-hook 'chronometrist-before-in-functions 'my-start-project)
#+END_SRC
2021-06-02 08:04:41 +00:00
** How to warn yourself about uncommitted changes
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: how-to-warn-uncommitted-changes
2021-05-26 07:53:58 +00:00
:END:
Another one, prompting the user if they have uncommitted changes in a git repository (assuming they use [[https://magit.vc/][Magit]]) -
#+BEGIN_SRC emacs-lisp
(autoload 'magit-anything-modified-p "magit")
(defun my-commit-prompt ()
"Prompt user if `default-directory' is a dirty Git repository.
Return t if the user answers yes, if the repository is clean, or
if there is no Git repository.
Return nil (and run `magit-status') if the user answers no."
(cond ((not (magit-anything-modified-p)) t)
((yes-or-no-p
(format "You have uncommitted changes in %S. Really clock out? "
default-directory)) t)
(t (magit-status) nil)))
(add-hook 'chronometrist-before-out-functions 'my-commit-prompt)
#+END_SRC
2021-06-02 08:04:41 +00:00
** How to display the current time interval in the activity indicator
2021-05-26 07:53:58 +00:00
:PROPERTIES:
:CUSTOM_ID: how-to-activity-indicator
2021-05-26 07:53:58 +00:00
:END:
#+BEGIN_SRC emacs-lisp
(defun my-activity-indicator ()
2022-01-23 20:18:42 +00:00
(--> (chronometrist-latest-record (chronometrist-active-backend))
(plist-put it :stop (chronometrist-format-time-iso8601))
(list it)
(chronometrist-events-to-durations it)
(-reduce #'+ it)
(truncate it)
(chronometrist-format-duration it)))
2021-05-26 07:53:58 +00:00
(setq chronometrist-activity-indicator #'my-activity-indicator)
#+END_SRC
** How to back up your Chronometrist data
:PROPERTIES:
:CUSTOM_ID: how-to-backup
:END:
2022-04-15 05:05:22 +00:00
I suggest backing up Chronometrist data on each save using the [[https://tildegit.org/contrapunctus/async-backup][async-backup]] package.[fn:4] Here's how you can do that.
1. Add the following to your init.
#+BEGIN_SRC emacs-lisp
2022-01-23 20:14:48 +00:00
(use-package async-backup)
#+END_SRC
2022-01-23 20:14:48 +00:00
2. Open your Chronometrist file and add =async-backup= to a buffer-local =after-save-hook=.
: M-x chronometrist-open-log
2022-01-23 20:14:48 +00:00
: M-x add-file-local-variable-prop-line RET eval RET (add-hook 'after-save-hook #'async-backup nil t) RET
2022-04-15 04:24:51 +00:00
3. Optionally, configure =async-backup-location= to set a specific directory for the backups -
: (setq async-backup-location "/path/to/backup/dir/")
2022-04-15 05:05:22 +00:00
[fn:4] It is possible to use Emacs' built-in backup system to do it, but since it is synchronous, doing so will greatly slow down saving of the Chronometrist file.
2022-01-23 20:14:48 +00:00
2022-01-23 20:41:56 +00:00
** How to configure Vertico for use with Chronometrist
:PROPERTIES:
:CUSTOM_ID: howto-vertico
:END:
2022-01-23 20:45:41 +00:00
By default, [[https://github.com/minad/vertico][Vertico]] uses its own sorting function - for some commands (such as =chronometrist-key-values-unified-prompt=) this results in /worse/ suggestions, since Chronometrist sorts suggestions in most-recent-first order.
2022-01-23 20:41:56 +00:00
You can either disable Vertico's sorting entirely -
#+BEGIN_SRC emacs-lisp
(setq vertico-sort-function nil)
#+END_SRC
Or use =vertico-multiform= to disable sorting for only specific commands -
2022-01-23 20:41:56 +00:00
#+BEGIN_SRC emacs-lisp
(use-package vertico-multiform
2022-01-23 20:57:09 +00:00
:init (vertico-multiform-mode)
2022-01-23 20:41:56 +00:00
:config
(setq vertico-multiform-commands
'((chronometrist-toggle-task (vertico-sort-function . nil))
(chronometrist-toggle-task-no-hooks (vertico-sort-function . nil))
(chronometrist-key-values-unified-prompt (vertico-sort-function . nil)))))
2022-01-23 20:41:56 +00:00
#+END_SRC
2021-06-02 08:04:41 +00:00
* User's reference
2022-04-27 10:56:26 +00:00
:PROPERTIES:
:CUSTOM_ID: users-reference
:END:
All variables intended for user customization are listed here. They serve as the public API for this project for the purpose of semantic versioning. Any changes to these which require a user to modify their configuration are considered breaking changes.
1. =chronometrist-file=
2. =chronometrist-buffer-name=
3. =chronometrist-report-buffer-name=
4. =chronometrist-details-buffer-name=
5. =chronometrist-sexp-pretty-print-function=
6. =chronometrist-hide-cursor=
7. =chronometrist-update-interval=
8. =chronometrist-activity-indicator=
Buffer schemas
1. =chronometrist-schema=
2. =chronometrist-details-schema=
Hooks
1. =chronometrist-mode-hook=
2. =chronometrist-schema-transformers=
3. =chronometrist-row-transformers=
4. =chronometrist-before-in-functions=
5. =chronometrist-after-in-functions=
6. =chronometrist-before-out-functions=
7. =chronometrist-after-out-functions=
8. =chronometrist-file-change-hook=
9. =chronometrist-timer-hook=
2021-05-26 07:53:58 +00:00
2022-02-12 18:11:39 +00:00
* Local variables :noexport:
2022-04-27 10:56:26 +00:00
:PROPERTIES:
:CUSTOM_ID: local-variables
:END:
2022-01-23 05:26:08 +00:00
# Local Variables:
2022-01-23 20:41:56 +00:00
# my-org-src-default-lang: "emacs-lisp"
2022-01-23 05:26:08 +00:00
# End: