Move definitions from chronometrist-events.el to chronometrist.org

This commit is contained in:
contrapunctus 2021-02-04 21:46:40 +05:30
parent edf63ee269
commit 3c5a3c5556
2 changed files with 100 additions and 120 deletions

View File

@ -1,119 +0,0 @@
;;; chronometrist-events.el --- Event management and querying code for Chronometrist -*- lexical-binding: t; -*-
;; Author: contrapunctus <xmpp:contrapunctus@jabber.fr>
;; This is free and unencumbered software released into the public domain.
;;
;; Anyone is free to copy, modify, publish, use, compile, sell, or
;; distribute this software, either in source code form or as a compiled
;; binary, for any purpose, commercial or non-commercial, and by any
;; means.
;;
;; For more information, please refer to <https://unlicense.org>
;; (require 'chronometrist-plist-pp)
(require 'chronometrist-common)
(require 'chronometrist-sexp)
(require 'ts)
;; external -
;; chronometrist-day-start-time (-custom)
;; chronometrist-midnight-spanning-p (-time)
;; chronometrist-date-less-p (-time)
;;; Commentary:
;;
;;; Code:
(defvar chronometrist-events (make-hash-table :test #'equal)
"Each key is a date in the form (YEAR MONTH DAY).
Values are lists containing events, where each event is a list in
the form (:name \"NAME\" :tags (TAGS) <key value pairs> ...
:start TIME :stop TIME).")
(defun chronometrist-day-start (timestamp)
"Get start of day (according to `chronometrist-day-start-time') for TIMESTAMP.
TIMESTAMP must be a time string in the ISO-8601 format.
Return value is a time value (see `current-time')."
(let ((timestamp-date-list (->> timestamp
(parse-iso8601-time-string)
(decode-time)
(-drop 3)
(-take 3))))
(--> chronometrist-day-start-time
(split-string it ":")
(mapcar #'string-to-number it)
(reverse it)
(append it timestamp-date-list)
(apply #'encode-time it))))
(defun chronometrist-events-maybe-split (event)
"Split EVENT if it spans midnight.
Return a list of two events if EVENT was split, else nil."
(when (plist-get event :stop)
(let ((split-time (chronometrist-midnight-spanning-p (plist-get event :start)
(plist-get event :stop))))
(when split-time
(let ((first-start (plist-get (cl-first split-time) :start))
(first-stop (plist-get (cl-first split-time) :stop))
(second-start (plist-get (cl-second split-time) :start))
(second-stop (plist-get (cl-second split-time) :stop))
;; plist-put modifies lists in-place. The resulting bugs
;; left me puzzled for a while.
(event-1 (cl-copy-list event))
(event-2 (cl-copy-list event)))
(list (-> event-1
(plist-put :start first-start)
(plist-put :stop first-stop))
(-> event-2
(plist-put :start second-start)
(plist-put :stop second-stop))))))))
;; TODO - Maybe strip dates from values, since they're part of the key
;; anyway. Consider using a state machine.
;; OPTIMIZE - It should not be necessary to call this unless the file
;; has changed. Any other refresh situations should not require this.
(defun chronometrist-events-populate ()
"Clear hash table `chronometrist-events' (which see) and populate it.
The data is acquired from `chronometrist-file'.
Return final number of events read from file, or nil if there
were none."
(clrhash chronometrist-events)
(chronometrist-sexp-events-populate))
(defun chronometrist-events-update (plist &optional replace)
"Add PLIST to the end of `chronometrist-events'.
If REPLACE is non-nil, replace the last event with PLIST."
(let* ((date (->> (plist-get plist :start)
(chronometrist-iso-timestamp->ts )
(ts-format "%F" )))
(events-today (gethash date chronometrist-events)))
(--> (if replace (-drop-last 1 events-today) events-today)
(append it (list plist))
(puthash date it chronometrist-events))))
(defun chronometrist-events-subset (start end)
"Return a subset of `chronometrist-events'.
The subset will contain values between dates START and END (both
inclusive).
START and END must be ts structs (see `ts.el'). They will be
treated as though their time is 00:00:00."
(let ((subset (make-hash-table :test #'equal))
(start (chronometrist-date start))
(end (chronometrist-date end)))
(maphash (lambda (key value)
(when (ts-in start end (chronometrist-iso-date->ts key))
(puthash key value subset)))
chronometrist-events)
subset))
(provide 'chronometrist-events)
;;; chronometrist-events.el ends here

View File

@ -60,7 +60,6 @@ This is displayed when the user clicks on the package's entry in =M-x list-packa
(require 'filenotify)
(require 'cl-lib)
(require 'subr-x)
(require 'chronometrist-common)
(require 'chronometrist-key-values)
(require 'chronometrist-queries)
(require 'chronometrist-migrate)
@ -78,6 +77,106 @@ This is displayed when the user clicks on the package's entry in =M-x list-packa
(autoload 'chronometrist-report "chronometrist-report" nil t)
(autoload 'chronometrist-statistics "chronometrist-statistics" nil t)
#+END_SRC
*** Hash Table
**** chronometrist-events :variable:
#+BEGIN_SRC emacs-lisp
(defvar chronometrist-events (make-hash-table :test #'equal)
"Each key is a date in the form (YEAR MONTH DAY).
Values are lists containing events, where each event is a list in
the form (:name \"NAME\" :tags (TAGS) <key value pairs> ...
:start TIME :stop TIME).")
#+END_SRC
**** day-start :function:
#+BEGIN_SRC emacs-lisp
(defun chronometrist-day-start (timestamp)
"Get start of day (according to `chronometrist-day-start-time') for TIMESTAMP.
TIMESTAMP must be a time string in the ISO-8601 format.
Return value is a time value (see `current-time')."
(let ((timestamp-date-list (->> timestamp
(parse-iso8601-time-string)
(decode-time)
(-drop 3)
(-take 3))))
(--> chronometrist-day-start-time
(split-string it ":")
(mapcar #'string-to-number it)
(reverse it)
(append it timestamp-date-list)
(apply #'encode-time it))))
#+END_SRC
**** events-maybe-split :function:
#+BEGIN_SRC emacs-lisp
(defun chronometrist-events-maybe-split (event)
"Split EVENT if it spans midnight.
Return a list of two events if EVENT was split, else nil."
(when (plist-get event :stop)
(let ((split-time (chronometrist-midnight-spanning-p (plist-get event :start)
(plist-get event :stop))))
(when split-time
(let ((first-start (plist-get (cl-first split-time) :start))
(first-stop (plist-get (cl-first split-time) :stop))
(second-start (plist-get (cl-second split-time) :start))
(second-stop (plist-get (cl-second split-time) :stop))
;; plist-put modifies lists in-place. The resulting bugs
;; left me puzzled for a while.
(event-1 (cl-copy-list event))
(event-2 (cl-copy-list event)))
(list (-> event-1
(plist-put :start first-start)
(plist-put :stop first-stop))
(-> event-2
(plist-put :start second-start)
(plist-put :stop second-stop))))))))
#+END_SRC
;; TODO - Maybe strip dates from values, since they're part of the key
;; anyway. Consider using a state machine.
;; OPTIMIZE - It should not be necessary to call this unless the file
;; has changed. Any other refresh situations should not require this.
**** events-populate :function:
#+BEGIN_SRC emacs-lisp
(defun chronometrist-events-populate ()
"Clear hash table `chronometrist-events' (which see) and populate it.
The data is acquired from `chronometrist-file'.
Return final number of events read from file, or nil if there
were none."
(clrhash chronometrist-events)
(chronometrist-sexp-events-populate))
#+END_SRC
**** events-update :function:
#+BEGIN_SRC emacs-lisp
(defun chronometrist-events-update (plist &optional replace)
"Add PLIST to the end of `chronometrist-events'.
If REPLACE is non-nil, replace the last event with PLIST."
(let* ((date (->> (plist-get plist :start)
(chronometrist-iso-timestamp->ts )
(ts-format "%F" )))
(events-today (gethash date chronometrist-events)))
(--> (if replace (-drop-last 1 events-today) events-today)
(append it (list plist))
(puthash date it chronometrist-events))))
#+END_SRC
**** events-subset :function:
#+BEGIN_SRC emacs-lisp
(defun chronometrist-events-subset (start end)
"Return a subset of `chronometrist-events'.
The subset will contain values between dates START and END (both
inclusive).
START and END must be ts structs (see `ts.el'). They will be
treated as though their time is 00:00:00."
(let ((subset (make-hash-table :test #'equal))
(start (chronometrist-date start))
(end (chronometrist-date end)))
(maphash (lambda (key value)
(when (ts-in start end (chronometrist-iso-date->ts key))
(puthash key value subset)))
chronometrist-events)
subset))
#+END_SRC
*** Chronometrist
**** custom group :custom:group:
#+BEGIN_SRC emacs-lisp