Convert s-expression backend functions to methods
They are also renamed to match the names of the generic functions.
This commit is contained in:
parent
8acf23b593
commit
1037cacd3c
|
@ -262,7 +262,7 @@ The next one was released in v0.5. Till then, any time the @uref{../elisp/chrono
|
||||||
After the optimization@dots{}
|
After the optimization@dots{}
|
||||||
@enumerate
|
@enumerate
|
||||||
@item
|
@item
|
||||||
Two backend functions (@uref{../elisp/chronometrist-sexp.el, @samp{chronometrist-sexp-new}} and @uref{../elisp/chronometrist-sexp.el, @samp{chronometrist-sexp-replace-last}}) were modified to set a flag (@uref{../elisp/chronometrist.el, @samp{chronometrist--inhibit-read-p}}) before saving the file.
|
Two backend functions (@uref{../elisp/chronometrist-sexp.el, @samp{chronometrist-new}} and @uref{../elisp/chronometrist-sexp.el, @samp{chronometrist-replace-last}}) were modified to set a flag (@uref{../elisp/chronometrist.el, @samp{chronometrist--inhibit-read-p}}) before saving the file.
|
||||||
@item
|
@item
|
||||||
If this flag is non-nil, @uref{../elisp/chronometrist.el, @samp{chronometrist-refresh-file}} skips the expensive calls to @samp{chronometrist-events-populate}, @samp{chronometrist-tasks-from-table}, and @samp{chronometrist-tags-history-populate}, and resets the flag.
|
If this flag is non-nil, @uref{../elisp/chronometrist.el, @samp{chronometrist-refresh-file}} skips the expensive calls to @samp{chronometrist-events-populate}, @samp{chronometrist-tasks-from-table}, and @samp{chronometrist-tags-history-populate}, and resets the flag.
|
||||||
@item
|
@item
|
||||||
|
@ -1106,33 +1106,35 @@ Function - chronometrist-goal-on-file-change ()
|
||||||
|
|
||||||
@enumerate
|
@enumerate
|
||||||
@item
|
@item
|
||||||
|
Class - chronometrist-sexp
|
||||||
|
@item
|
||||||
|
Object - chronometrist-sexp
|
||||||
|
@item
|
||||||
Custom variable - chronometrist-sexp-pretty-print-function
|
Custom variable - chronometrist-sexp-pretty-print-function
|
||||||
@item
|
@item
|
||||||
Macro - chronometrist-sexp-in-file (file &rest body)
|
Macro - chronometrist-sexp-in-file (file &rest body)
|
||||||
@item
|
@item
|
||||||
Function - chronometrist-sexp-open-log ()
|
Method - chronometrist-to-hash ((backend chronometrist-sexp) table)
|
||||||
@item
|
@item
|
||||||
Function - chronometrist-sexp-between (&optional (ts-beg (chronometrist-date)) (ts-end (ts-adjust 'day +1 (chronometrist-date))))
|
Method - chronometrist-from-hash ((backend chronometrist-sexp) table)
|
||||||
@item
|
@item
|
||||||
Function - chronometrist-sexp-query-till (&optional (date (chronometrist-date)))
|
Method - chronometrist-open-log ((backend chronometrist-sexp))
|
||||||
@item
|
@item
|
||||||
Function - chronometrist-sexp-last ()
|
Method - chronometrist-last ((backend chronometrist-sexp))
|
||||||
@itemize
|
@itemize
|
||||||
@item
|
@item
|
||||||
-> plist
|
-> plist
|
||||||
@end itemize
|
@end itemize
|
||||||
@item
|
@item
|
||||||
Function - chronometrist-sexp-current-task ()
|
Method - chronometrist-current-task ((backend chronometrist-sexp))
|
||||||
@item
|
@item
|
||||||
Function - chronometrist-sexp-events-populate ()
|
Method - chronometrist-create-file ((backend chronometrist-sexp))
|
||||||
@item
|
@item
|
||||||
Function - chronometrist-sexp-create-file ()
|
Method - chronometrist-new (((backend chronometrist-sexp)) plist)
|
||||||
@item
|
|
||||||
Function - chronometrist-sexp-new (plist &optional (buffer (find-file-noselect chronometrist-file)))
|
|
||||||
@item
|
@item
|
||||||
Function - chronometrist-sexp-delete-list (&optional arg)
|
Function - chronometrist-sexp-delete-list (&optional arg)
|
||||||
@item
|
@item
|
||||||
Function - chronometrist-sexp-replace-last (plist)
|
Method - chronometrist-replace-last (((backend chronometrist-sexp)) plist)
|
||||||
@item
|
@item
|
||||||
Command - chronometrist-sexp-reindent-buffer ()
|
Command - chronometrist-sexp-reindent-buffer ()
|
||||||
@end enumerate
|
@end enumerate
|
||||||
|
|
|
@ -87,7 +87,7 @@ One of the earliest 'optimizations' of great importance turned out to simply be
|
||||||
The next one was released in v0.5. Till then, any time the [[file:../elisp/chronometrist-custom.el::defcustom chronometrist-file (][=chronometrist-file=]] was modified, we'd clear the [[file:../elisp/chronometrist-events.el::defvar chronometrist-events (][=chronometrist-events=]] hash table and read data into it again. The reading itself is nearly-instant, even with ~2 years' worth of data [fn:1] (it uses Emacs' [[elisp:(describe-function 'read)][=read=]], after all), but the splitting of [[* Midnight-spanning events][midnight-spanning events]] is the real performance killer.
|
The next one was released in v0.5. Till then, any time the [[file:../elisp/chronometrist-custom.el::defcustom chronometrist-file (][=chronometrist-file=]] was modified, we'd clear the [[file:../elisp/chronometrist-events.el::defvar chronometrist-events (][=chronometrist-events=]] hash table and read data into it again. The reading itself is nearly-instant, even with ~2 years' worth of data [fn:1] (it uses Emacs' [[elisp:(describe-function 'read)][=read=]], after all), but the splitting of [[* Midnight-spanning events][midnight-spanning events]] is the real performance killer.
|
||||||
|
|
||||||
After the optimization...
|
After the optimization...
|
||||||
1. Two backend functions ([[file:../elisp/chronometrist-sexp.el::cl-defun chronometrist-sexp-new (][=chronometrist-sexp-new=]] and [[file:../elisp/chronometrist-sexp.el::defun chronometrist-sexp-replace-last (][=chronometrist-sexp-replace-last=]]) were modified to set a flag ([[file:../elisp/chronometrist.el::defvar chronometrist--inhibit-read-p ][=chronometrist--inhibit-read-p=]]) before saving the file.
|
1. Two backend functions ([[file:../elisp/chronometrist-sexp.el::cl-defmethod chronometrist-new (][=chronometrist-new=]] and [[file:../elisp/chronometrist-sexp.el::cl-defmethod chronometrist-replace-last (][=chronometrist-replace-last=]]) were modified to set a flag ([[file:../elisp/chronometrist.el::defvar chronometrist--inhibit-read-p ][=chronometrist--inhibit-read-p=]]) before saving the file.
|
||||||
2. If this flag is non-nil, [[file:../elisp/chronometrist.el::defun chronometrist-refresh-file (][=chronometrist-refresh-file=]] skips the expensive calls to =chronometrist-events-populate=, =chronometrist-tasks-from-table=, and =chronometrist-tags-history-populate=, and resets the flag.
|
2. If this flag is non-nil, [[file:../elisp/chronometrist.el::defun chronometrist-refresh-file (][=chronometrist-refresh-file=]] skips the expensive calls to =chronometrist-events-populate=, =chronometrist-tasks-from-table=, and =chronometrist-tags-history-populate=, and resets the flag.
|
||||||
3. Instead, the aforementioned backend functions modify the relevant variables - =chronometrist-events=, =chronometrist-task-list=, and =chronometrist-tags-history= - via...
|
3. Instead, the aforementioned backend functions modify the relevant variables - =chronometrist-events=, =chronometrist-task-list=, and =chronometrist-tags-history= - via...
|
||||||
* =chronometrist-events-add= / =chronometrist-events-replace-last=
|
* =chronometrist-events-add= / =chronometrist-events-replace-last=
|
||||||
|
@ -455,20 +455,21 @@ Each of these has a corresponding function to clear it and fill it with values -
|
||||||
13. Function - chronometrist-goal-on-file-change ()
|
13. Function - chronometrist-goal-on-file-change ()
|
||||||
|
|
||||||
** chronometrist-sexp
|
** chronometrist-sexp
|
||||||
1. Custom variable - chronometrist-sexp-pretty-print-function
|
1. Class - chronometrist-sexp
|
||||||
2. Macro - chronometrist-sexp-in-file (file &rest body)
|
2. Object - chronometrist-sexp
|
||||||
3. Function - chronometrist-sexp-open-log ()
|
3. Custom variable - chronometrist-sexp-pretty-print-function
|
||||||
4. Function - chronometrist-sexp-between (&optional (ts-beg (chronometrist-date)) (ts-end (ts-adjust 'day +1 (chronometrist-date))))
|
4. Macro - chronometrist-sexp-in-file (file &rest body)
|
||||||
5. Function - chronometrist-sexp-query-till (&optional (date (chronometrist-date)))
|
5. Method - chronometrist-to-hash ((backend chronometrist-sexp) table)
|
||||||
6. Function - chronometrist-sexp-last ()
|
5. Method - chronometrist-from-hash ((backend chronometrist-sexp) table)
|
||||||
* -> plist
|
5. Method - chronometrist-open-log ((backend chronometrist-sexp))
|
||||||
7. Function - chronometrist-sexp-current-task ()
|
8. Method - chronometrist-last ((backend chronometrist-sexp))
|
||||||
8. Function - chronometrist-sexp-events-populate ()
|
* -> plist
|
||||||
9. Function - chronometrist-sexp-create-file ()
|
9. Method - chronometrist-current-task ((backend chronometrist-sexp))
|
||||||
10. Function - chronometrist-sexp-new (plist &optional (buffer (find-file-noselect chronometrist-file)))
|
11. Method - chronometrist-create-file ((backend chronometrist-sexp))
|
||||||
11. Function - chronometrist-sexp-delete-list (&optional arg)
|
12. Method - chronometrist-new (((backend chronometrist-sexp)) plist)
|
||||||
12. Function - chronometrist-sexp-replace-last (plist)
|
13. Function - chronometrist-sexp-delete-list (&optional arg)
|
||||||
13. Command - chronometrist-sexp-reindent-buffer ()
|
14. Method - chronometrist-replace-last (((backend chronometrist-sexp)) plist)
|
||||||
|
15. Command - chronometrist-sexp-reindent-buffer ()
|
||||||
|
|
||||||
# Local Variables:
|
# Local Variables:
|
||||||
# org-link-file-path-type: relative
|
# org-link-file-path-type: relative
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
"The extension used by a file of this backend, without a leading period."
|
"The extension used by a file of this backend, without a leading period."
|
||||||
:initform "")))
|
:initform "")))
|
||||||
|
|
||||||
|
(defvar chronometrist-current-backend nil
|
||||||
|
"The current backend in use.")
|
||||||
|
|
||||||
(defvar chronometrist-backends nil
|
(defvar chronometrist-backends nil
|
||||||
"List of enabled backends.")
|
"List of enabled backends.")
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ file.")
|
||||||
|
|
||||||
(defun chronometrist-current-task ()
|
(defun chronometrist-current-task ()
|
||||||
"Return the name of the currently clocked-in task, or nil if not clocked in."
|
"Return the name of the currently clocked-in task, or nil if not clocked in."
|
||||||
(chronometrist-sexp-current-task))
|
(chronometrist-current-task chronometrist-current-backend))
|
||||||
|
|
||||||
(cl-defun chronometrist-format-time (seconds &optional (blank " "))
|
(cl-defun chronometrist-format-time (seconds &optional (blank " "))
|
||||||
"Format SECONDS as a string suitable for display in Chronometrist buffers.
|
"Format SECONDS as a string suitable for display in Chronometrist buffers.
|
||||||
|
|
|
@ -96,7 +96,7 @@ be removed."
|
||||||
new-kvs
|
new-kvs
|
||||||
`(:start ,old-start)
|
`(:start ,old-start)
|
||||||
(when old-stop `(:stop ,old-stop)))))
|
(when old-stop `(:stop ,old-stop)))))
|
||||||
(chronometrist-sexp-replace-last plist)))
|
(chronometrist-replace-last chronometrist-current-backend plist)))
|
||||||
|
|
||||||
;;;; TAGS ;;;;
|
;;;; TAGS ;;;;
|
||||||
(defvar chronometrist-tags-history (make-hash-table :test #'equal)
|
(defvar chronometrist-tags-history (make-hash-table :test #'equal)
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
(defun chronometrist-last ()
|
(defun chronometrist-last ()
|
||||||
"Return the last entry from `chronometrist-file' as a plist."
|
"Return the last entry from `chronometrist-file' as a plist."
|
||||||
(chronometrist-sexp-last))
|
(chronometrist-last chronometrist-current-backend))
|
||||||
|
|
||||||
(cl-defun chronometrist-task-time-one-day (task &optional (ts (ts-now)))
|
(cl-defun chronometrist-task-time-one-day (task &optional (ts (ts-now)))
|
||||||
"Return total time spent on TASK today or (if supplied) on timestamp TS.
|
"Return total time spent on TASK today or (if supplied) on timestamp TS.
|
||||||
|
|
|
@ -227,7 +227,7 @@ current week. Otherwise, display data from the week specified by
|
||||||
(kill-buffer buffer))
|
(kill-buffer buffer))
|
||||||
(t (unless keep-date
|
(t (unless keep-date
|
||||||
(setq chronometrist-report--ui-date nil))
|
(setq chronometrist-report--ui-date nil))
|
||||||
(chronometrist-common-create-file)
|
(chronometrist-create-file chronometrist-current-backend)
|
||||||
(chronometrist-report-mode)
|
(chronometrist-report-mode)
|
||||||
(switch-to-buffer buffer)
|
(switch-to-buffer buffer)
|
||||||
(chronometrist-report-refresh-file nil)
|
(chronometrist-report-refresh-file nil)
|
||||||
|
|
|
@ -33,32 +33,10 @@ neatly), or falls back to `pp' if it isn't."
|
||||||
`(with-current-buffer (find-file-noselect ,file)
|
`(with-current-buffer (find-file-noselect ,file)
|
||||||
(save-excursion ,@body)))
|
(save-excursion ,@body)))
|
||||||
|
|
||||||
;;;; Queries
|
;; # Migration #
|
||||||
(defun chronometrist-sexp-open-log ()
|
(cl-defmethod chronometrist-to-hash ((backend chronometrist-sexp) table))
|
||||||
"Open `chronometrist-file' in another window."
|
|
||||||
(find-file-other-window chronometrist-file)
|
|
||||||
(goto-char (point-max)))
|
|
||||||
|
|
||||||
(defun chronometrist-sexp-last ()
|
(cl-defmethod chronometrist-from-hash ((backend chronometrist-sexp) table)
|
||||||
"Return last s-expression from `chronometrist-file'."
|
|
||||||
(chronometrist-sexp-in-file chronometrist-file
|
|
||||||
(goto-char (point-max))
|
|
||||||
(backward-list)
|
|
||||||
(ignore-errors (read (current-buffer)))))
|
|
||||||
|
|
||||||
(defun chronometrist-sexp-current-task ()
|
|
||||||
"Return the name of the currently clocked-in task, or nil if not clocked in."
|
|
||||||
(let ((last-event (chronometrist-sexp-last)))
|
|
||||||
(if (plist-member last-event :stop)
|
|
||||||
nil
|
|
||||||
(plist-get last-event :name))))
|
|
||||||
|
|
||||||
(defun chronometrist-sexp-events-populate ()
|
|
||||||
"Populate hash table `chronometrist-events'.
|
|
||||||
The data is acquired from `chronometrist-file'.
|
|
||||||
|
|
||||||
Return final number of events read from file, or nil if there
|
|
||||||
were none."
|
|
||||||
(chronometrist-sexp-in-file chronometrist-file
|
(chronometrist-sexp-in-file chronometrist-file
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(let ((index 0) expr pending-expr)
|
(let ((index 0) expr pending-expr)
|
||||||
|
@ -84,15 +62,30 @@ were none."
|
||||||
chronometrist-events)))
|
chronometrist-events)))
|
||||||
(unless (zerop index) index))))
|
(unless (zerop index) index))))
|
||||||
|
|
||||||
;;;; Modifications
|
;; # Queries #
|
||||||
(defun chronometrist-sexp-create-file ()
|
(cl-defmethod chronometrist-open-log ((backend chronometrist-sexp))
|
||||||
"Create `chronometrist-file' if it doesn't already exist."
|
(find-file-other-window chronometrist-file)
|
||||||
|
(goto-char (point-max)))
|
||||||
|
|
||||||
|
(cl-defmethod chronometrist-last ((backend chronometrist-sexp))
|
||||||
|
(chronometrist-sexp-in-file chronometrist-file
|
||||||
|
(goto-char (point-max))
|
||||||
|
(backward-list)
|
||||||
|
(ignore-errors (read (current-buffer)))))
|
||||||
|
|
||||||
|
(cl-defmethod chronometrist-current-task ((backend chronometrist-sexp))
|
||||||
|
(let ((last-event (chronometrist-last backend)))
|
||||||
|
(if (plist-member last-event :stop)
|
||||||
|
nil
|
||||||
|
(plist-get last-event :name))))
|
||||||
|
|
||||||
|
;; # Modifications #
|
||||||
|
(cl-defmethod chronometrist-create-file ((backend chronometrist-sexp))
|
||||||
(unless (file-exists-p chronometrist-file)
|
(unless (file-exists-p chronometrist-file)
|
||||||
(with-current-buffer (find-file-noselect chronometrist-file)
|
(with-current-buffer (find-file-noselect chronometrist-file)
|
||||||
(write-file chronometrist-file))))
|
(write-file chronometrist-file))))
|
||||||
|
|
||||||
(cl-defun chronometrist-sexp-new (plist)
|
(cl-defmethod chronometrist-new ((backend chronometrist-sexp) plist)
|
||||||
"Add new PLIST at the end of `chronometrist-file'."
|
|
||||||
(chronometrist-sexp-in-file chronometrist-file
|
(chronometrist-sexp-in-file chronometrist-file
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
;; If we're adding the first s-exp in the file, don't add a
|
;; If we're adding the first s-exp in the file, don't add a
|
||||||
|
@ -114,8 +107,7 @@ were none."
|
||||||
(forward-sexp (or arg 1))
|
(forward-sexp (or arg 1))
|
||||||
(delete-region point-1 (point))))
|
(delete-region point-1 (point))))
|
||||||
|
|
||||||
(defun chronometrist-sexp-replace-last (plist)
|
(cl-defmethod chronometrist-replace-last ((backend chronometrist-sexp) plist)
|
||||||
"Replace the last s-expression in `chronometrist-file' with PLIST."
|
|
||||||
(chronometrist-sexp-in-file chronometrist-file
|
(chronometrist-sexp-in-file chronometrist-file
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(unless (and (bobp) (bolp))
|
(unless (and (bobp) (bolp))
|
||||||
|
@ -131,7 +123,7 @@ were none."
|
||||||
;; :name should be removed from `chronometrist-task-list', but to ascertain
|
;; :name should be removed from `chronometrist-task-list', but to ascertain
|
||||||
;; that condition we would have to either read the entire file or
|
;; that condition we would have to either read the entire file or
|
||||||
;; map over the hash table, defeating the optimization. Thus, we
|
;; map over the hash table, defeating the optimization. Thus, we
|
||||||
;; don't update `chronometrist-task-list' here (unlike `chronometrist-sexp-new')
|
;; don't update `chronometrist-task-list' here (unlike `chronometrist-new')
|
||||||
(chronometrist-tags-history-replace-last plist)
|
(chronometrist-tags-history-replace-last plist)
|
||||||
(setq chronometrist--inhibit-read-p t)
|
(setq chronometrist--inhibit-read-p t)
|
||||||
(save-buffer)))
|
(save-buffer)))
|
||||||
|
|
|
@ -260,7 +260,7 @@ specified by `chronometrist-statistics--ui-state'."
|
||||||
(setq chronometrist-statistics--ui-state `(:mode week
|
(setq chronometrist-statistics--ui-state `(:mode week
|
||||||
:start ,week-start
|
:start ,week-start
|
||||||
:end ,week-end)))
|
:end ,week-end)))
|
||||||
(chronometrist-common-create-file)
|
(chronometrist-create-file chronometrist-current-backend)
|
||||||
(chronometrist-statistics-mode)
|
(chronometrist-statistics-mode)
|
||||||
(switch-to-buffer buffer)
|
(switch-to-buffer buffer)
|
||||||
(chronometrist-statistics-refresh))))))
|
(chronometrist-statistics-refresh))))))
|
||||||
|
|
|
@ -89,11 +89,7 @@
|
||||||
Argument _BUTTON is for the purpose of using this command as a
|
Argument _BUTTON is for the purpose of using this command as a
|
||||||
button action."
|
button action."
|
||||||
(interactive)
|
(interactive)
|
||||||
(chronometrist-sexp-open-log))
|
(chronometrist-sexp-open-log chronometrist-current-backend))
|
||||||
|
|
||||||
(defun chronometrist-common-create-file ()
|
|
||||||
"Create `chronometrist-file' if it doesn't already exist."
|
|
||||||
(chronometrist-sexp-create-file))
|
|
||||||
|
|
||||||
(defun chronometrist-task-active? (task)
|
(defun chronometrist-task-active? (task)
|
||||||
"Return t if TASK is currently clocked in, else nil."
|
"Return t if TASK is currently clocked in, else nil."
|
||||||
|
@ -228,7 +224,7 @@ Argument _FS-EVENT is ignored."
|
||||||
TASK is the name of the task, a string. PREFIX is ignored."
|
TASK is the name of the task, a string. PREFIX is ignored."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(let ((plist `(:name ,task :start ,(chronometrist-format-time-iso8601))))
|
(let ((plist `(:name ,task :start ,(chronometrist-format-time-iso8601))))
|
||||||
(chronometrist-sexp-new plist)
|
(chronometrist-new chronometrist-current-backend plist)
|
||||||
(chronometrist-refresh)))
|
(chronometrist-refresh)))
|
||||||
|
|
||||||
(defun chronometrist-out (&optional _prefix)
|
(defun chronometrist-out (&optional _prefix)
|
||||||
|
@ -236,7 +232,7 @@ TASK is the name of the task, a string. PREFIX is ignored."
|
||||||
PREFIX is ignored."
|
PREFIX is ignored."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(let ((plist (plist-put (chronometrist-last) :stop (chronometrist-format-time-iso8601))))
|
(let ((plist (plist-put (chronometrist-last) :stop (chronometrist-format-time-iso8601))))
|
||||||
(chronometrist-sexp-replace-last plist)))
|
(chronometrist-replace-last plist)))
|
||||||
|
|
||||||
;; ## HOOKS ##
|
;; ## HOOKS ##
|
||||||
(defvar chronometrist-mode-hook nil
|
(defvar chronometrist-mode-hook nil
|
||||||
|
@ -443,7 +439,7 @@ If numeric argument ARG is 2, run `chronometrist-statistics'."
|
||||||
(cond ((or (not (file-exists-p chronometrist-file))
|
(cond ((or (not (file-exists-p chronometrist-file))
|
||||||
(chronometrist-common-file-empty-p chronometrist-file))
|
(chronometrist-common-file-empty-p chronometrist-file))
|
||||||
;; first run
|
;; first run
|
||||||
(chronometrist-common-create-file)
|
(chronometrist-create-file chronometrist-current-backend)
|
||||||
(let ((inhibit-read-only t))
|
(let ((inhibit-read-only t))
|
||||||
(chronometrist-common-clear-buffer buffer)
|
(chronometrist-common-clear-buffer buffer)
|
||||||
(insert "Welcome to Chronometrist! Hit RET to ")
|
(insert "Welcome to Chronometrist! Hit RET to ")
|
||||||
|
|
Reference in New Issue
Block a user