|
@@ -0,0 +1,117 @@
|
|
|
+;;; track-calorie-values.el --- Track calorie values for various foods
|
|
|
+
|
|
|
+;; Copyright (C) 2020 Samuel W. Flint <swflint@flintfam.org>
|
|
|
+
|
|
|
+;; author: Samuel W. Flint <swflint@flintfam.org>
|
|
|
+;; Version: 0.1
|
|
|
+;; Keywords: diet, tracking
|
|
|
+;; URL: https://git.sr.ht/~swflint/track-calorie-values
|
|
|
+
|
|
|
+;; This file is NOT part of Emacs.
|
|
|
+;;
|
|
|
+;; This file is licensed under the GNU GPLv3 or later.
|
|
|
+
|
|
|
+;;; Commentary:
|
|
|
+;;
|
|
|
+
|
|
|
+;;; Code:
|
|
|
+
|
|
|
+(require 'cl-lib)
|
|
|
+
|
|
|
+
|
|
|
+;;; Customizeable values
|
|
|
+
|
|
|
+(defgroup track-calorie-values nil
|
|
|
+ "Track calorie values for various foods"
|
|
|
+ :tag "Track Calorie Values"
|
|
|
+ :group 'org
|
|
|
+ :link '(url-link "https://git.sr.ht/~swflint/track-calorie-values")
|
|
|
+ :prefix "track-calorie-values-")
|
|
|
+
|
|
|
+(defcustom track-calorie-values-save-file
|
|
|
+ (locate-user-emacs-file "track-calorie-values-data.el")
|
|
|
+ "File to store calorie values of food items."
|
|
|
+ :type '(file :must-match t))
|
|
|
+
|
|
|
+
|
|
|
+;;; Hashing
|
|
|
+
|
|
|
+;; Taken from emacs documentation
|
|
|
+(defun case-fold-string= (a b)
|
|
|
+ (eq t (compare-strings a nil nil b nil nil t)))
|
|
|
+(defun case-fold-string-hash (a)
|
|
|
+ (sxhash-equal (upcase a)))
|
|
|
+
|
|
|
+(define-hash-table-test 'case-fold
|
|
|
+ 'case-fold-string= 'case-fold-string-hash)
|
|
|
+
|
|
|
+
|
|
|
+;;; Internal Data
|
|
|
+(defvar track-calorie-values-data (make-hash-table :weakness nil :test 'case-fold)
|
|
|
+ "Storage for calorie values.
|
|
|
+
|
|
|
+Keys are names, values are calories.")
|
|
|
+
|
|
|
+(defvar track-calorie-values-foods nil
|
|
|
+ "Storage for food names.")
|
|
|
+
|
|
|
+(defvar track-calorie-values-loaded-p nil
|
|
|
+ "Have calorie values been loaded?")
|
|
|
+
|
|
|
+(defvar track-calorie-values-modified-p t
|
|
|
+ "Have calorie values been modified?")
|
|
|
+
|
|
|
+(defvar track-calorie-values-current-food nil
|
|
|
+ "Current food being recorded.")
|
|
|
+
|
|
|
+
|
|
|
+;;; I/O functions
|
|
|
+
|
|
|
+(defun track-calorie-values-load-data ()
|
|
|
+ "Load calorie data."
|
|
|
+ (when (file-exists-p track-calorie-values-save-file)
|
|
|
+ (load track-calorie-values-save-file t t t)
|
|
|
+ (setf track-calorie-values-loaded-p t
|
|
|
+ track-calorie-values-foods (hash-table-keys track-calorie-values-data)
|
|
|
+ track-calorie-values-modified-p nil)))
|
|
|
+
|
|
|
+(defun track-calorie-values-save-data ()
|
|
|
+ "Write calorie data."
|
|
|
+ (when track-calorie-values-modified-p
|
|
|
+ (insert ";; generated by track-calorie-values.el -*- mode: lisp-data -*-\n"
|
|
|
+ ";; do not modify by hand\n")
|
|
|
+ (with-temp-buffer
|
|
|
+ (let ((standard-output (current-buffer)))
|
|
|
+ (print `(setq track-calorie-values-data ,track-calorie-values-data)))
|
|
|
+ (write-region (point-min) (point-max) track-calorie-values-save-file))))
|
|
|
+
|
|
|
+
|
|
|
+;;; Primary interaction functions
|
|
|
+
|
|
|
+(defun track-calorie-values-food ()
|
|
|
+ "Get a food item to retrieve or prompt for calories."
|
|
|
+ (unless track-calorie-values-loaded-p
|
|
|
+ (track-calorie-values-load-data))
|
|
|
+ (let ((food (completing-read "Food item: " track-calorie-values-foods
|
|
|
+ #'identity nil nil nil nil t)))
|
|
|
+ (if food
|
|
|
+ (setf track-calorie-values-current-food (downcase food))
|
|
|
+ (user-error "A food name must be provided"))))
|
|
|
+
|
|
|
+(defun track-calorie-values-calories ()
|
|
|
+ "Get or prompt for the number of calories in the current food item."
|
|
|
+ (let ((calories (gethash track-calorie-values-current-food track-calorie-values-data)))
|
|
|
+ (if calories
|
|
|
+ (progn
|
|
|
+ (setf track-calorie-values-current-food nil)
|
|
|
+ (format "%d" calories))
|
|
|
+ (let ((calories (read-number (format "Calories in \"%s\": " track-calorie-values-current-food))))
|
|
|
+ (puthash track-calorie-values-current-food calories track-calorie-values-data)
|
|
|
+ (cl-pushnew track-calorie-values-current-food track-calorie-values-foods :test #'string=)
|
|
|
+ (setf track-calorie-values-current-food nil
|
|
|
+ track-calorie-values-modified-p t)
|
|
|
+ (format "%d" calories)))))
|
|
|
+
|
|
|
+(provide 'track-calorie-values)
|
|
|
+
|
|
|
+;;; track-calorie-values.el ends here
|