Skip to content

Instantly share code, notes, and snippets.

@Arahnoid
Last active July 25, 2021 09:38
Show Gist options
  • Save Arahnoid/4ceea1e6ac3df84983f91c6ad26186fd to your computer and use it in GitHub Desktop.
Save Arahnoid/4ceea1e6ac3df84983f91c6ad26186fd to your computer and use it in GitHub Desktop.
Diabetes.org

Capture

Variables

Define list of variables for org files used for capturing various tasks

(defvar +org-capture-books-file (concat org-directory "books.org")
  "Default, centralized target for org-capture templates.")
(defvar +org-contacts-file (concat org-directory "contacts.org")
  "Org contacts path")
(defvar +org-capture-diabetes-file (concat org-directory "diabetes.org")
  "Capture diabetes related records")

Templates

Let’s setup some org-capture templates

(,(format "%s\tAdd contact" (all-the-icons-octicon "star" :face 'all-the-icons-green :v-adjust 0.01))
 :keys "c"
 :file +org-contacts-file
 :prepend t
 :headline "New"
 ;; :olp ("Inbox" "Family" "Close friends" "Work coleagues")
 :type entry
 :template ("* %^{Name Surname}"
            ":PROPERTIES:"
            ":address: %^{Address}"
            ":birthday: \"%^{yyyy-mm-dd}\""
            ":email: \"%^{Email}\""
            ":note: \"%^{Note}\""
            ":END:"))
(,(format "%s\tBooks to read" (all-the-icons-octicon "book" :face 'all-the-icons-green :v-adjust 0.01))
   :keys "b"
   :file +org-capture-books-file
   :prepend t
   :headline "Inbox"
   :type entry
   :template ("* TOREAD %^{Author}. %^{Book Title} %? :book:"
              "- Why do I want to read this book?"
              "  %^{Why do you want to read this book}"
              "- How did I found this book?"
              "  %^{How did you found this book}\n"
              "- After reading:"
              "  + What did I learn from this book?"
              "  + What its this book about?"
              "  + Would I recommend this book?\n"))
(,(format "%s\tAzure task" (all-the-icons-material "cloud" :face 'all-the-icons-blue :v-adjust 0.01))
   :keys "a"
   :file +org-capture-todo-file
   :prepend t
   :headline "Inbox"
   :type entry
   :template ("* TODO [[azure:%^{Task ID}][%\\1]] P:[[azure:%^{Parent ID}][%\\2]] %^{Task Title} %?:%^G:"))
(,(format "%s\tPersonal todo"
           (all-the-icons-octicon "checklist" :face 'all-the-icons-green :v-adjust 0.01))
    :keys "t"
    :file +org-capture-todo-file
    :prepend t
    :headline "Inbox"
    :type entry
    :template ("* TODO %?" "%i %a"))
(,(format "%s\tPersonal note" (all-the-icons-faicon "sticky-note-o" :face 'all-the-icons-green :v-adjust 0.01))
  :keys "n"
  :file +org-capture-todo-file
  :prepend t
  :headline "Inbox"
  :type entry
  :template ("* %?"
            "%i %a")
  )
(,(format "%s\tEmail" (all-the-icons-faicon "envelope" :face 'all-the-icons-blue :v-adjust 0.01))
  :keys "e"
  :file +org-capture-todo-file
  :prepend t
  :headline "Inbox"
  :type entry
  :template ("* TODO %^{type|reply to|contact} %\\3 %? :email:"
            "Send an email %^{urgancy|soon|ASAP|anon|at some point|eventually} to %^{recipiant}"
            "about %^{topic}"
            "%U %i %a"))
(,(format "%s\tWebpage" (all-the-icons-faicon "globe" :face 'all-the-icons-green :v-adjust 0.01))
  :keys "w"
  :desc "%(org-cliplink-capture) "
  :i-type "read:web"
  )
(,(format "%s\tArticle" (all-the-icons-octicon "file-text" :face 'all-the-icons-yellow :v-adjust 0.01))
  :keys "a"
  :desc ""
  :i-type "read:reaserch"
  )
(,(format "%s\tInformation" (all-the-icons-faicon "info-circle" :face 'all-the-icons-blue :v-adjust 0.01))
  :keys "i"
  :desc ""
  :i-type "read:info"
  )
(,(format "%s\tIdea" (all-the-icons-material "bubble_chart" :face 'all-the-icons-silver :v-adjust 0.01))
  :keys "I"
  :desc ""
  :i-type "idea"
  )
(,(format "%s\tGeneral Task" (all-the-icons-octicon "inbox" :face 'all-the-icons-yellow :v-adjust 0.01))
  :keys "k"
  :extra ""
  )
(,(format "%s\tTask with deadline" (all-the-icons-material "timer" :face 'all-the-icons-orange :v-adjust -0.1))
  :keys "d"
  :extra "\nDEADLINE: %^{Deadline:}t"
  )
(,(format "%s\tScheduled Task" (all-the-icons-octicon "calendar" :face 'all-the-icons-orange :v-adjust 0.01))
  :keys "s"
  :extra "\nSCHEDULED: %^{Start time:}t"
  )
(,(format "%s\tProject-local todo" (all-the-icons-octicon "checklist" :face 'all-the-icons-green :v-adjust 0.01))
  :keys "t"
  :time-or-todo "TODO"
  :file +org-capture-project-todo-file)
(,(format "%s\tProject-local note" (all-the-icons-faicon "sticky-note" :face 'all-the-icons-yellow :v-adjust 0.01))
 :keys "n"
 :time-or-todo "%U"
 :file +org-capture-project-notes-file)
(,(format "%s\tProject-local changelog" (all-the-icons-faicon "list" :face 'all-the-icons-blue :v-adjust 0.01))
  :keys "c"
  :time-or-todo "%U"
  :heading "Unreleased"
  :file +org-capture-project-changelog-file)
(,(format "%s\tNew blog post" (all-the-icons-octicon "star" :face 'all-the-icons-green :v-adjust 0.01))
 :keys "z"
 :file (lambda () (concat
                   "~/blog/org/posts/"
                   (format-time-string "%Y_%m_%d_%H-")
                   (read-string "Post File name :")
                   ".org"))

 :prepend nil
 :type plain
 :template ("#+title: %^{Post title}"
            "#+date: <%<%Y-%m-%d>>"
            "#+keywords: draft\n\n"))
(,(format "%s\tMeal" (all-the-icons-faicon "apple" :face 'all-the-icons-green :v-adjust 0.01))
  :keys "m"
  :type entry
  :headline "Meals"
  :template ("* %<%Y-%m-%d %H:%M>\n- %?\n"))
(,(format "%s\tInsulin injection" (all-the-icons-material "healing" :face 'all-the-icons-yellow :v-adjust 0.01))
  :keys "i"
  :type table-line
  :headline "Insulin Injections"
  :template ("| %<%Y-%m-%d | %H:%M> | %^{Units} |"))
(,(format "%s\tGlucose level" (all-the-icons-faicon "heart" :face 'all-the-icons-red :v-adjust 0.01))
  :keys "g"
  :type table-line
  :headline "Glucose Levels"
  :template ("| %<%Y-%m-%d | %H:%M> | %^{Glucose level} |"))

Combined

(use-package! doct
  :commands (doct))

(after! org-capture
  ;; <<prettify-capture>>
  (setq org-capture-templates
        (doct `(
                <<add-blog-post>>
                (,(format "%s\tDiabet" (all-the-icons-faicon "medkit" :face 'all-the-icons-red :v-adjust 0.01))
                :keys "d"
                :file +org-capture-diabetes-file
                :prepend nil
                ;; :headline (format "%s" (format-time-string "%D"))
                :children (
                            <<diabet-meal>>
                            <<diabet-injection>>
                            <<diabet-glucose>>
                            ))
                <<add-contact>>
                <<books-to-read>>
                <<personal-todo>>
                <<personal-note>>
                <<email>>
                (,(format "%s\tInteresting" (all-the-icons-faicon "eye" :face 'all-the-icons-lcyan :v-adjust 0.01))
                 :keys "i"
                 :file +org-capture-todo-file
                 :prepend t
                 :headline "Interesting"
                 :type entry
                 :template ("* [ ] %{desc}%? :%{i-type}:"
                            "%i %a")
                 :children (
                            <<interesting-webpage>>
                            <<interesting-article>>
                            <<interesting-information>>
                            <<interesting-idea>>
                            ))
                (,(format "%s\tTasks" (all-the-icons-octicon "inbox" :face 'all-the-icons-yellow :v-adjust 0.01))
                 :keys "k"
                 :file +org-capture-todo-file
                 :prepend t
                 :headline "Tasks"
                 :type entry
                 :template ("* TODO %? %^G%{extra}"
                            "%i %a")
                 :children (
                            <<task-azure>> ; a
                            <<task-general>>
                            <<task-with-deadline>>
                            <<task-scheduled>>
                            ))
                (,(format "%s\tProject" (all-the-icons-octicon "repo" :face 'all-the-icons-silver :v-adjust 0.01))
                 :keys "p"
                 :prepend t
                 :type entry
                 :headline "Inbox"
                 :template ("* %{time-or-todo} %?"
                            "%i"
                            "%a")
                 :file ""
                 :custom (:time-or-todo "")
                 :children (
                            <<project-local-todo>>
                            <<project-local-note>>
                            <<project-local-changelog>>
                            ))
               ))))

Prettify capture

It would also be nice to improve how the capture dialogue looks

(defun org-capture-select-template-prettier (&optional keys)
  "Select a capture template, in a prettier way than default
Lisp programs can force the template by setting KEYS to a string."
  (let ((org-capture-templates
         (or (org-contextualize-keys
              (org-capture-upgrade-templates org-capture-templates)
              org-capture-templates-contexts)
             '(("t" "Task" entry (file+headline "" "Tasks")
                "* TODO %?\n  %u\n  %a")))))
    (if keys
        (or (assoc keys org-capture-templates)
            (error "No capture template referred to by \"%s\" keys" keys))
      (org-mks org-capture-templates
               "Select a capture template\n━━━━━━━━━━━━━━━━━━━━━━━━━"
               "Template key: "
               `(("q" ,(concat (all-the-icons-octicon "stop" :face 'all-the-icons-red :v-adjust 0.01) "\tAbort")))))))
(advice-add 'org-capture-select-template :override #'org-capture-select-template-prettier)

(defun org-mks-pretty (table title &optional prompt specials)
  "Select a member of an alist with multiple keys. Prettified.

TABLE is the alist which should contain entries where the car is a string.
There should be two types of entries.

1. prefix descriptions like (\"a\" \"Description\")
   This indicates that `a' is a prefix key for multi-letter selection, and
   that there are entries following with keys like \"ab\", \"ax\"

2. Select-able members must have more than two elements, with the first
   being the string of keys that lead to selecting it, and the second a
   short description string of the item.

The command will then make a temporary buffer listing all entries
that can be selected with a single key, and all the single key
prefixes.  When you press the key for a single-letter entry, it is selected.
When you press a prefix key, the commands (and maybe further prefixes)
under this key will be shown and offered for selection.

TITLE will be placed over the selection in the temporary buffer,
PROMPT will be used when prompting for a key.  SPECIALS is an
alist with (\"key\" \"description\") entries.  When one of these
is selected, only the bare key is returned."
  (save-window-excursion
    (let ((inhibit-quit t)
    (buffer (org-switch-to-buffer-other-window "*Org Select*"))
    (prompt (or prompt "Select: "))
    case-fold-search
    current)
      (unwind-protect
    (catch 'exit
      (while t
        (setq-local evil-normal-state-cursor (list nil))
        (erase-buffer)
        (insert title "\n\n")
        (let ((des-keys nil)
        (allowed-keys '("\C-g"))
        (tab-alternatives '("\s" "\t" "\r"))
        (cursor-type nil))
    ;; Populate allowed keys and descriptions keys
    ;; available with CURRENT selector.
    (let ((re (format "\\`%s\\(.\\)\\'"
          (if current (regexp-quote current) "")))
          (prefix (if current (concat current " ") "")))
      (dolist (entry table)
        (pcase entry
          ;; Description.
          (`(,(and key (pred (string-match re))) ,desc)
           (let ((k (match-string 1 key)))
       (push k des-keys)
       ;; Keys ending in tab, space or RET are equivalent.
       (if (member k tab-alternatives)
           (push "\t" allowed-keys)
         (push k allowed-keys))
       (insert (propertize prefix 'face 'font-lock-comment-face) (propertize k 'face 'bold) (propertize "" 'face 'font-lock-comment-face) "  " desc "" "\n")))
          ;; Usable entry.
          (`(,(and key (pred (string-match re))) ,desc . ,_)
           (let ((k (match-string 1 key)))
       (insert (propertize prefix 'face 'font-lock-comment-face) (propertize k 'face 'bold) "   " desc "\n")
       (push k allowed-keys)))
          (_ nil))))
    ;; Insert special entries, if any.
    (when specials
      (insert "─────────────────────────\n")
      (pcase-dolist (`(,key ,description) specials)
        (insert (format "%s   %s\n" (propertize key 'face '(bold all-the-icons-red)) description))
        (push key allowed-keys)))
    ;; Display UI and let user select an entry or
    ;; a sub-level prefix.
    (goto-char (point-min))
    (unless (pos-visible-in-window-p (point-max))
      (org-fit-window-to-buffer))
    (let ((pressed (org--mks-read-key allowed-keys prompt)))
      (setq current (concat current pressed))
      (cond
       ((equal pressed "\C-g") (user-error "Abort"))
       ;; Selection is a prefix: open a new menu.
       ((member pressed des-keys))
       ;; Selection matches an association: return it.
       ((let ((entry (assoc current table)))
          (and entry (throw 'exit entry))))
       ;; Selection matches a special entry: return the
       ;; selection prefix.
       ((assoc current specials) (throw 'exit current))
       (t (error "No entry available")))))))
  (when buffer (kill-buffer buffer))))))
(advice-add 'org-mks :override #'org-mks-pretty)

The org-capture bin is rather nice, but I’d be nicer with a smaller frame, and no modeline.

(setf (alist-get 'height +org-capture-frame-parameters) 15)
      ;; (alist-get 'name +org-capture-frame-parameters) "❖ Capture") ;; ATM hardcoded in other places, so changing breaks stuff
(setq +org-capture-fn
      (lambda ()
        (interactive)
        (set-window-parameter nil 'mode-line-format 'none)
        (org-capture)))

Diabetes

Insulin Injections

DateTimeInsulin
2021-07-1105:3420
2021-07-1119:0820
2021-07-1213:0820
2021-07-1217:5410
2021-07-1310:1415
2021-07-1401:2510
2021-07-1412:5215
2021-07-1417:5715
2021-07-1519:0015
2021-07-1523:1210
2021-07-1612:3315
2021-07-1622:2910
2021-07-1720:0015
2021-07-1812:0215
2021-07-1818:4110
2021-07-1913:4015
2021-07-2011:4515
2021-07-2023:3315
2021-07-2112:5110
2021-07-2211:0115
2021-07-2215:5810
2021-07-2220:2910
2021-07-2309:5015
2021-07-2411:3515
2021-07-2420:4015
2021-07-2507:3320

Glucose Levels

DateTimeGlucose
2021-07-1019:223.8
2021-07-1114:536.4
2021-07-1118:368.3
2021-07-1123:067.2
2021-07-1213:058.8
2021-07-1217:498.8
2021-07-1220:263.7
2021-07-1301:515.4
2021-07-1310:107.1
2021-07-1316:386.7
2021-07-1319:524.5
2021-07-1401:236.8
2021-07-1412:426.7
2021-07-1417:558
2021-07-1501:324.3
2021-07-1512:187.6
2021-07-1516:257.4
2021-07-1523:107.8
2021-07-1610:186.7
2021-07-1617:076.5
2021-07-1622:268.2
2021-07-1701:404.0
2021-07-1706:055.5
2021-07-1711:286.7
2021-07-1801:335.2
2021-07-1812:007.9
2021-07-1817:243.8
2021-07-1818:3812.2
2021-07-1821:475.2
2021-07-1901:584.4
2021-07-1911:236.7
2021-07-1913:3415.6
2021-07-1915:548.4
2021-07-1919:404.1
2021-07-2001:405.1
2021-07-2010:146.9
2021-07-2016:186.6
2021-07-2019:205.8
2021-07-2112:466.4
2021-07-2119:154.0
2021-07-2203:215.3
2021-07-2210:437.7
2021-07-2215:567.9
2021-07-2217:533.5
2021-07-2220:276.1
2021-07-2309:346.6
2021-07-2314:337.6
2021-07-2321:505.6
2021-07-2400:195.7
2021-07-2411:107.4
2021-07-2418:125.5
2021-07-2423:415.7
2021-07-2507:309.4

Meals

2021-07-11 15:03

  • 2 loaf of bread
  • 1 sausage
  • souse

2021-07-11 19:05

  • 2 leafs of bread
  • 2 fried eggs
  • 2 loafs of cheese

Plots

reset
set terminal svg size 1800,400
set title "Glucose Level"
set xlabel "Date and time"
set ylabel "Glucose level in blood (ml mol)"
set key on outside
set key center bottom

set xdata time
set timefmt "%Y-%m-%d\t%H:%M"
set format x "%H:%M\n%b,%d"

set grid ytics lt 0 lw 1 lc rgb "#880000"
set grid xtics lt 0 lw 1 lc rgb "#cccccc"
set yrange [2:14]

max_y = 7
min_y = 4

plot max_y with filledcurves y1=min_y lt 1 lc rgb "#d4f98930" title "Safe", \
     ins using 1:(2):(20) w errorbars ls 1 lw 1 ps 1 title "I. injection", \
     data using 1:3:(sprintf("(%.1f)", $3)) with labels point pt 7 lw 3 ps 1 offset char -0.5,1 notitle, \
     data using 1:3 w linespoints ls 7 lw 3 ps 1 title "G. level"
# splot data using 1:3 w linespoints ls 7 lw 3 ps 1 title "G. level average"
reset
set terminal svg size 800,400
set title "Glucose level on ".strftime("%b, %d", time(0))
set xlabel "Date and time"
set ylabel "Glucose level in blood (ml mol)"
# set key on outside
# set key center bottom

set xdata time
set timefmt "%Y-%m-%d\t%H:%M"
set format x "%H:%M"

set grid ytics lt 0 lw 1 lc rgb "#880000"
set grid xtics lt 0 lw 1 lc rgb "#cccccc"
set yrange [2:14]

# this sets the currrent day for a dayly plot
day = strftime("%d", time(0))
mon = strftime("%m", time(0))
year = strftime("%Y", time(0))

# you can also checkout a specific day by changed values above to a specific day month or year
# day = 3
# mon = 7
# year = 2021

set xrange [year."-".mon."-".day."\t00:00":year."-".mon."-".day."\t24:00"]

max_y = 7
min_y = 4

plot max_y with filledcurves y1=min_y lt 1 lc rgb "#d4f98930" title "Safe", \
     ins using 1:(2):(20) w errorbars ls 1 lw 1 ps 1 title "I. injection", \
     data using 1:3:(sprintf("(%.1f)", $3)) with labels point pt 7 lw 3 ps 1 offset char -0.5,1 notitle, \
     data using 1:3 w linespoints ls 7 lw 3 ps 1 title "G. level"
reset
set terminal svg size 1800,400
set title "Insulin Injections"
set xlabel "Date Time"
set ylabel "Inuslin (ml)"

set xdata time
set timefmt "%Y-%m-%d\t%H:%M"
set format x "%H:%M\n%b,%d"

set grid ytics lt 0 lw 1 lc rgb "#880000"
set grid xtics lt 0 lw 1 lc rgb "#cccccc"
set yrange [0:30]
set key off
plot data using 1:3 w linespoints ls 7 lw 3 ps 1

~/Dropbox/org/diabetes-plots/glucose.svg ~/Dropbox/org/diabetes-plots/insulin.svg ~/Dropbox/org/diabetes-plots/glucose-dayly.svg

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment