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/elisp/chronometrist-spark.org

145 lines
5.3 KiB
Org Mode
Raw Normal View History

2021-05-29 07:40:06 +00:00
#+TITLE: chronometrist-spark
2021-06-03 08:32:22 +00:00
#+AUTHOR: contrapunctus
2021-05-30 19:31:25 +00:00
#+SUBTITLE: Show sparklines in Chronometrist
#+PROPERTY: header-args :tangle yes :load yes
2021-05-29 07:40:06 +00:00
* Library headers and commentary
2021-05-29 07:40:06 +00:00
#+BEGIN_SRC emacs-lisp
2021-05-29 12:14:51 +00:00
;;; chronometrist-spark.el --- Show sparklines in Chronometrist -*- lexical-binding: t; -*-
2021-05-29 07:40:06 +00:00
;; Author: contrapunctus <xmpp:contrapunctus@jabjab.de>
;; Maintainer: contrapunctus <xmpp:contrapunctus@jabjab.de>
2021-05-29 07:40:06 +00:00
;; Keywords: calendar
;; Homepage: https://tildegit.org/contrapunctus/chronometrist
;; Package-Requires: ((emacs "24.3") (chronometrist "0.7.0") (spark "0.1"))
2021-05-29 07:40:06 +00:00
;; Version: 0.1.0
;; 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>
2021-05-29 07:40:06 +00:00
#+END_SRC
"Commentary" is displayed when the user clicks on the package's entry in =M-x list-packages=.
#+BEGIN_SRC emacs-lisp
;;; Commentary:
;;
;; This package adds a column to Chronometrist displaying sparklines for each task.
#+END_SRC
* Dependencies
2021-05-29 07:40:06 +00:00
#+BEGIN_SRC emacs-lisp
;;; Code:
(require 'chronometrist)
(require 'spark)
#+END_SRC
* Code
2021-06-07 16:29:57 +00:00
** custom group :custom:group:
2021-06-02 19:56:19 +00:00
#+BEGIN_SRC emacs-lisp
(defgroup chronometrist-spark nil
"Show sparklines in `chronometrist'."
:group 'applications)
#+END_SRC
2021-06-07 16:29:57 +00:00
** length :custom:variable:
2021-05-29 11:41:05 +00:00
#+BEGIN_SRC emacs-lisp
(defcustom chronometrist-spark-length 7
2021-06-02 19:56:19 +00:00
"Length of each sparkline in number of days."
:type 'integer)
2021-05-29 11:41:05 +00:00
#+END_SRC
2021-06-07 14:18:16 +00:00
** chronometrist-spark-show-range
#+BEGIN_SRC emacs-lisp
(defcustom chronometrist-spark-show-range t
"If non-nil, display range of each sparkline."
:type 'boolean)
#+END_SRC
2021-06-07 16:29:57 +00:00
** TODO row-transformer :function:
2021-05-29 11:41:05 +00:00
if larger than 7
add space after (% length 7)th element
then add space after every 7 elements
#+BEGIN_SRC emacs-lisp
(defun chronometrist-spark-row-transformer (row)
"Add a sparkline cell to ROW.
Used to add a sparkline column to `chronometrist-rows'.
ROW must be a valid element of the list specified by
`tabulated-list-entries'."
(-let* (((task vector) row)
2021-06-07 14:18:16 +00:00
(sparkline
(cl-loop with today = (ts-now)
for day from (- (- chronometrist-spark-length 1)) to 0
collect (chronometrist-task-time-one-day
task (ts-adjust 'day day today))
into durations
finally return
(let ((duration-minutes (mapcar (lambda (sec)
(/ sec 60))
durations)))
(if chronometrist-spark-show-range
(format "%s (min %s, max %s)"
(spark durations)
(apply #'min duration-minutes)
(apply #'max duration-minutes))
(format "%s" (spark durations)))))))
2021-05-29 11:41:05 +00:00
(list task (vconcat vector `[,sparkline]))))
#+END_SRC
2021-06-07 16:29:57 +00:00
** TODO schema-transformer :function:
2021-05-29 11:41:05 +00:00
calculate length while accounting for space
#+BEGIN_SRC emacs-lisp
(defun chronometrist-spark-schema-transformer (schema)
"Add a sparkline column to SCHEMA.
Used to add a sparkline column to `chronometrist-schema-transformers'.
SCHEMA should be a vector as specified by `tabulated-list-format'."
2021-06-07 14:18:16 +00:00
(vconcat schema `[("Graph"
,(if chronometrist-spark-show-range
chronometrist-spark-length
(+ chronometrist-spark-length 20))
t)]))
2021-05-29 11:41:05 +00:00
#+END_SRC
2021-06-07 16:29:57 +00:00
** setup :writer:
2021-05-29 11:41:05 +00:00
#+BEGIN_SRC emacs-lisp
(defun chronometrist-spark-setup ()
"Add `chronometrist-sparkline' functions to `chronometrist' hooks."
(add-to-list 'chronometrist-row-transformers #'chronometrist-spark-row-transformer)
(add-to-list 'chronometrist-schema-transformers #'chronometrist-spark-schema-transformer))
2021-05-29 11:41:05 +00:00
#+END_SRC
2021-06-07 16:29:57 +00:00
** teardown :writer:
2021-05-29 11:41:05 +00:00
#+BEGIN_SRC emacs-lisp
(defun chronometrist-spark-teardown ()
"Remove `chronometrist-sparkline' functions from `chronometrist' hooks."
(setq chronometrist-row-transformers
(remove #'chronometrist-spark-row-transformer chronometrist-row-transformers)
chronometrist-schema-transformers
(remove #'chronometrist-spark-schema-transformer chronometrist-schema-transformers)))
2021-05-29 11:41:05 +00:00
#+END_SRC
2021-06-07 16:29:57 +00:00
** minor-mode :minor:mode:
2021-05-29 11:41:05 +00:00
#+BEGIN_SRC emacs-lisp
(define-minor-mode chronometrist-spark-minor-mode
nil nil nil nil
;; when being enabled/disabled, `chronometrist-spark-minor-mode' will already be t/nil here
(if chronometrist-spark-minor-mode (chronometrist-spark-setup) (chronometrist-spark-teardown)))
#+END_SRC
* Provide
2021-05-29 07:40:06 +00:00
#+BEGIN_SRC emacs-lisp
(provide 'chronometrist-spark)
;;; chronometrist-spark.el ends here
#+END_SRC
* Local variables :noexport:
# Local Variables:
# eval: (add-hook 'after-save-hook (lambda nil (interactive) (compile (mapconcat #'shell-quote-argument `("emacs" "-q" "-Q" "--batch" "--eval=(require 'ob-tangle)" ,(format "--eval=(org-babel-tangle-file \"%s\")" (buffer-file-name))) " "))) nil t)
# End: