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/doc/manual.org

16 KiB
Raw Blame History

Chronometrist

Getting started

Installation

Usage

How-to guides

Explanation

Design goals

  1. Don't make assumptions about the user's profession

    • e.g. timeclock seems to assume you're using it for a 9-to-5/contractor job
  2. Incentivize use

    • Hooks allow the time tracker to automate tasks and become a useful part of your workflow
  3. Make it easy to edit data using existing, familiar tools

    • We don't use an SQL database, where changing a single field is tricky [1]
    • We use a text file containing s-expressions (easy for humans to read and write)
    • We use ISO-8601 for timestamps (easy for humans to read and write) rather than UNIX epoch time
  4. Reduce human errors in tracking
  5. Have a useful, informative, interactive interface
  6. Support mouse and keyboard use equally

[1] I still have doubts about this. Having SQL as a query language would be very useful in perusing the stored data. Maybe we should have tried to create a companion mode to edit SQL databases interactively?

Midnight-spanning events

A unique problem in working with Chronometrist, one I had never foreseen, was tasks which start on one day and end on another. These mess up data consumption (especially interval calculations and acquiring data for a specific date) in all sorts of unforeseen ways.

There are a few different approaches of dealing with them. (Currently, Chronometrist uses #3.)

1. (timeclock format) When the code of the first event in the day is "o", it's a midnight-spanning event.
  • Advantage - very simple to detect
  • Disadvantage - "in" and "out" events must be represented separately
2. Split them at the file level
  • Advantage - operation is performed only once for each such event + simpler data-consuming code + reduced post-parsing load.
  • What happens when the user changes their day-start-time? The split-up events are now split wrongly, and the second event may get split again. Possible solutions -

    1. Add function to check if, for two events A and B, the :stop of A is the same as the :start of B, and that all their other tags are identical. Then we can re-split them according to the new day-start-time.
    2. Add a :split tag to split events. It can denote that the next event was originally a part of this one.
    3. Re-check and update the file when the day-start-time changes.

      • Possible with add-variable-watcher or :custom-set in Customize (thanks bpalmer)
3. Split them at the hash-table-level

Handled by chronometrist-sexp-events-populate

  • Advantage - simpler data-consuming code.
4. Split them at the data-consumer level (e.g. when calculating time for one day/getting events for one day)
  • Advantage - reduced repetitive post-parsing load.

Reference

Legend of currently-used time formats

1. ts

ts.el struct

  • Used by nearly all internal functions
2. iso-timestamp

"YYYY-MM-DDTHH:MM:SSZ"

  • Used in the s-expression file format
  • Read by chronometrist-sexp-events-populate
  • Used in the plists in the chronometrist-events hash table values
3. iso-date

"YYYY-MM-DD"

  • Used as hash table keys in chronometrist-events - can't use ts structs for keys, you'd have to make a hash table predicate which uses ts=
4. seconds

integer seconds as duration

  • Used for most durations
  • May be changed to floating point to allow larger durations. The minimum range of `most-positive-fixnum` is 536870911, which seems to be enough to represent durations of 17 years.
  • Used for update intervals (chronometrist-update-interval, chronometrist-change-update-interval)
5. minutes

integer minutes as duration

  • Used for goals (chronometrist-goals-list, chronometrist-get-goal) - minutes seems like the ideal unit for users to enter
6. list-duration

(hours minute seconds)

  • Only returned by chronometrist-seconds-to-hms, called by chronometrist-format-time

chronometrist-common.el

  1. Variable - chronometrist-empty-time-string
  2. Variable - chronometrist-date-re
  3. Variable - chronometrist-time-re-ui
  4. Variable - chronometrist-task-list
  5. Internal Variable - chronometristfs-watch
  6. Function - chronometrist-current-task ()
  7. Function - chronometrist-format-time (seconds &optional (blank " "))

    • seconds -> "hⓂ️s"
  8. Function - chronometrist-common-file-empty-p (file)
  9. Function - chronometrist-common-clear-buffer (buffer)
  10. Function - chronometrist-format-keybinds (command map &optional firstonly)
  11. Function - chronometrist-events->ts-pairs (events)

    • (plist …) -> ((ts . ts) …)
  12. Function - chronometrist-ts-pairs->durations (ts-pairs)

    • ((ts . ts) …) -> seconds
  13. Function - chronometrist-previous-week-start (ts)

    • ts -> ts

chronometrist-custom.el

  1. Custom variable - chronometrist-file
  2. Custom variable - chronometrist-buffer-name
  3. Custom variable - chronometrist-hide-cursor
  4. Custom variable - chronometrist-update-interval
  5. Custom variable - chronometrist-activity-indicator
  6. Custom variable - chronometrist-day-start-time

chronometrist-diary-view.el

  1. Variable - chronometrist-diary-buffer-name
  2. Internal Variable - chronometrist-diarycurrent-date
  3. Function - chronometrist-intervals-on (date)
  4. Function - chronometrist-diary-tasks-reasons-on (date)
  5. Function - chronometrist-diary-refresh (&optional ignore-auto noconfirm date)
  6. Major Mode - chronometrist-diary-view-mode
  7. Command - chronometrist-diary-view (&optional date)

chronometrist.el

  1. Internal Variable - chronometristtask-history
  2. Internal Variable - chronometristpoint
  3. Keymap - chronometrist-mode-map
  4. Command - chronometrist-open-log (&optional button)
  5. Function - chronometrist-common-create-file ()
  6. Function - chronometrist-task-active? (task)

    • String -> Boolean
  7. Function - chronometrist-use-goals? ()
  8. Function - chronometrist-activity-indicator ()
  9. Function - chronometrist-entries ()
  10. Function - chronometrist-task-at-point ()
  11. Function - chronometrist-goto-last-task ()
  12. Function - chronometrist-print-keybind (command &optional description firstonly)
  13. Function - chronometrist-print-non-tabular ()
  14. Function - chronometrist-goto-nth-task (n)
  15. Function - chronometrist-refresh (&optional ignore-auto noconfirm)
  16. Function - chronometrist-refresh-file (fs-event)
  17. Command - chronometrist-query-stop ()
  18. Command - chronometrist-in (task &optional _prefix)
  19. Command - chronometrist-out (&optional _prefix)
  20. Variable - chronometrist-before-in-functions
  21. Variable - chronometrist-after-in-functions
  22. Variable - chronometrist-before-out-functions
  23. Variable - chronometrist-after-out-functions
  24. Function - chronometrist-run-functions-and-clock-in (task)
  25. Function - chronometrist-run-functions-and-clock-out (task)
  26. Keymap - chronometrist-mode-map
  27. Major Mode - chronometrist-mode
  28. Function - chronometrist-toggle-task-button (button)
  29. Function - chronometrist-add-new-task-button (button)
  30. Command - chronometrist-toggle-task (&optional prefix inhibit-hooks)
  31. Command - chronometrist-toggle-task-no-hooks (&optional prefix)
  32. Command - chronometrist-add-new-task ()
  33. Command - chronometrist (&optional arg)

chronometrist-events.el

  1. Variable - chronometrist-events

    • keys - iso-date
  2. Function - chronometrist-day-start (timestamp)

    • iso-timestamp -> encode-time
  3. Function - chronometrist-file-clean ()

    • commented out, unused
  4. Function - chronometrist-events-maybe-split (event)
  5. Function - chronometrist-events-populate ()
  6. Function - chronometrist-tasks-from-table ()
  7. Function - chronometrist-events-subset (start end)

    • ts ts -> hash-table
  8. Function - chronometrist-events-query-spec-match-p (plist specifiers)
  9. Function - chronometrist-events-query (table &key get specifiers except)

chronometrist-migrate.el

  1. Variable - chronometrist-migrate-table
  2. Function - chronometrist-migrate-populate (in-file)
  3. Function - chronometrist-migrate-timelog-file->sexp-file (&optional in-file out-file)
  4. Function - chronometrist-migrate-check ()

chronometrist-plist-pp.el

  1. Variable - chronometrist-plist-pp-keyword-re
  2. Variable - chronometrist-plist-pp-whitespace-re
  3. Function - chronometrist-plist-pp-longest-keyword-length ()
  4. Function - chronometrist-plist-pp-buffer-keyword-helper ()
  5. Function - chronometrist-plist-pp-buffer ()
  6. Function - chronometrist-plist-pp-to-string (object)
  7. Function - chronometrist-plist-pp (object &optional stream)

chronometrist-queries.el

  1. Function - chronometrist-last ()

    • -> plist
  2. Function - chronometrist-task-time-one-day (task &optional (ts (ts-now)))

    • String &optional ts -> seconds
  3. Function - chronometrist-active-time-one-day (&optional ts)

    • &optional ts -> seconds
  4. Function - chronometrist-statistics-count-active-days (task &optional (table chronometrist-events))
  5. Function - chronometrist-task-events-in-day (task ts)

chronometrist-report-custom.el

  1. Custom variable - chronometrist-report-buffer-name
  2. Custom variable - chronometrist-report-week-start-day
  3. Custom variable - chronometrist-report-weekday-number-alist

chronometrist-report.el

  1. Internal Variable - chronometrist-reportui-date
  2. Internal Variable - chronometrist-reportui-week-dates
  3. Internal Variable - chronometrist-reportpoint
  4. Function - chronometrist-report-date ()
  5. Function - chronometrist-report-date->dates-in-week (first-date-in-week)

    • ts-1 -> (ts-1 … ts-7)
  6. Function - chronometrist-report-date->week-dates ()
  7. Function - chronometrist-report-entries ()
  8. Function - chronometrist-report-print-keybind (command &optional description firstonly)
  9. Function - chronometrist-report-print-non-tabular ()
  10. Function - chronometrist-report-refresh (&optional _ignore-auto _noconfirm)
  11. Function - chronometrist-report-refresh-file (_fs-event)
  12. Keymap - chronometrist-report-mode-map
  13. Major Mode - chronometrist-report-mode
  14. Function - chronometrist-report (&optional keep-date)
  15. Function - chronometrist-report-previous-week (arg)
  16. Function - chronometrist-report-next-week (arg)

chronometrist-key-values.el

  1. Internal Variable - chronometristtag-suggestions
  2. Internal Variable - chronometristvalue-suggestions
  3. Function - chronometrist-plist-remove (plist &rest keys)
  4. Function - chronometrist-maybe-string-to-symbol (list)
  5. Function - chronometrist-maybe-symbol-to-string (list)
  6. Function - chronometrist-append-to-last (tags plist)
  7. Variable - chronometrist-tags-history
  8. Function - chronometrist-tags-history-populate ()
  9. Function - chronometrist-tags-history-combination-strings (task)
  10. Function - chronometrist-tags-history-individual-strings (task)
  11. Function - chronometrist-tags-prompt (task &optional initial-input)
  12. Function - chronometrist-tags-add (&rest args)
  13. Custom Variable - chronometrist-kv-buffer-name
  14. Variable - chronometrist-key-history
  15. Variable - chronometrist-value-history
  16. Function - chronometrist-ht-history-prep (table)
  17. Function - chronometrist-key-history-populate ()
  18. Function - chronometrist-value-history-populate ()
  19. Keymap - chronometrist-kv-read-mode-map
  20. Major Mode - chronometrist-kv-read-mode
  21. Function - chronometrist-kv-completion-quit-key ()
  22. Function - chronometrist-string-has-whitespace-p (string)
  23. Function - chronometrist-key-prompt (used-keys)
  24. Function - chronometrist-value-prompt (key)
  25. Function - chronometrist-value-insert (value)
  26. Function - chronometrist-kv-add (&rest args)
  27. Command - chronometrist-kv-accept ()
  28. Command - chronometrist-kv-reject ()

chronometrist-statistics-custom.el

  1. Custom variable - chronometrist-statistics-buffer-name

chronometrist-statistics.el

  1. Internal Variable - chronometrist-statisticsui-state
  2. Internal Variable - chronometrist-statisticspoint
  3. Function - chronometrist-statistics-count-average-time-spent (task &optional (table chronometrist-events))

    • string &optional hash-table -> seconds
  4. Function - chronometrist-statistics-entries-internal (table)
  5. Function - chronometrist-statistics-entries ()
  6. Function - chronometrist-statistics-print-keybind (command &optional description firstonly)
  7. Function - chronometrist-statistics-print-non-tabular ()
  8. Function - chronometrist-statistics-refresh (&optional ignore-auto noconfirm)
  9. Keymap - chronometrist-statistics-mode-map
  10. Major Mode - chronometrist-statistics-mode
  11. Command - chronometrist-statistics (&optional preserve-state)
  12. Command - chronometrist-statistics-previous-range (arg)
  13. Command - chronometrist-statistics-next-range (arg)

chronometrist-time.el

  1. Function - chronometrist-iso-timestamp->ts (timestamp)

    • iso-timestamp -> ts
  2. Function - chronometrist-iso-date->ts (date)

    • iso-date -> ts
  3. Function - chronometrist-date (&optional (ts (ts-now)))

    • &optional ts -> ts (with time 00:00:00)
  4. Function - chronometrist-format-time-iso8601 (&optional unix-time)
  5. Function - chronometrist-midnight-spanning-p (start-time stop-time)
  6. Function - chronometrist-seconds-to-hms (seconds)

    • seconds -> list-duration

chronometrist-timer.el

  1. Internal Variable - chronometristtimer-object
  2. Function - chronometrist-timer ()
  3. Command - chronometrist-stop-timer ()
  4. Command - chronometrist-maybe-start-timer (&optional interactive-test)
  5. Command - chronometrist-force-restart-timer ()
  6. Command - chronometrist-change-update-interval (arg)

chronometrist-goals

  1. Internal Variable - chronometristtimers-list
  2. Custom Variable - chronometrist-goals-list nil
  3. Function - chronometrist-run-at-time (time repeat function &rest args)
  4. Function - chronometrist-seconds->alert-string (seconds)

    • seconds -> string
  5. Function - chronometrist-approach-alert (task goal spent)

    • string minutes minutes
  6. Function - chronometrist-complete-alert (task goal spent)

    • string minutes minutes
  7. Function - chronometrist-exceed-alert (task goal spent)

    • string minutes minutes
  8. Function - chronometrist-no-goal-alert (task goal spent)

    • string minutes minutes
  9. Custom Variable - chronometrist-goals-alert-functions

    • each function is passed - string minutes minutes
  10. Function - chronometrist-get-goal (task &optional (goals-list chronometrist-goals-list))

    • String &optional List -> minutes
  11. Function - chronometrist-goals-run-alert-timers (task)
  12. Function - chronometrist-goals-stop-alert-timers (&optional _task)
  13. Function - chronometrist-goals-on-file-change ()

chronometrist-sexp

  1. Function - chronometrist-sexp-open-log ()
  2. Function - chronometrist-sexp-last ()

    • -> plist
  3. Function - chronometrist-sexp-current-task ()
  4. Function - chronometrist-sexp-events-populate ()
  5. Function - chronometrist-sexp-create-file ()
  6. Function - chronometrist-sexp-new (plist &optional (buffer (find-file-noselect chronometrist-file)))
  7. Function - chronometrist-sexp-delete-list (&optional arg)
  8. Function - chronometrist-sexp-replace-last (plist)
  9. Command - chronometrist-sexp-reindent-buffer ()