stumpwm/budget.lisp @ 4f28fbfd7d63 default tip

More
author Steve Losh <steve@stevelosh.com>
date Tue, 09 Apr 2024 09:20:04 -0400
parents 4673e928c08e
children (none)
(in-package :stumpwm-user)

(defparameter *tz/eastern*
  (local-time:find-timezone-by-location-name "US/Eastern"))

(defparameter *budget/start*
  (local-time:encode-timestamp 0 0 0 0 29 8 2023 :timezone *tz/eastern*))

(defun budget/per-day ()
  (first (losh:read-all-from-file "/home/sjl/Sync/budget/per-day")))

(defun budget/elapsed ()
  (local-time:timestamp-difference (local-time:now) *budget/start*))

(defun budget/days-elapsed ()
  (floor (/ (budget/elapsed) (* 60 60 24))))

(defun budget/in ()
  (* (budget/days-elapsed) (budget/per-day)))

(defun budget/out ()
  (loop :for path :in (directory "/home/sjl/Sync/budget/hosts/*/total")
        :summing (print (first (read-all-from-file (print path))))))

(defun budget/current ()
  (- (budget/in) (budget/out)))

(defcommand budget-dump () ()
  (message
    (sh '("sh" "-c" "tail -n 5 /home/sjl/Sync/budget/hosts/*/records")
        :result-type 'string)))

(defcommand budget () ()
  (message "$~D" (budget/current)))

(defmacro with-budget-file ((f file &rest open-args) &body body)
  `(with-open-file
     (,f (format nil "/home/sjl/Sync/budget/hosts/~(~A~)/~A" *host* ,file)
      ,@open-args)
     ,@body))

(defcommand spend (amount what) ((:integer "Amount: $") (:string "For: "))
  (let ((current (with-budget-file (total "total")
                   (first (read-all-from-file total))))
        (timestamp (local-time:to-rfc3339-timestring (local-time:now))))
    (with-budget-file (total "total" :direction :output :if-exists :supersede)
      (print (+ current amount) total))
    (with-budget-file (records "records" :direction :output :if-exists :append :if-does-not-exist :create)
      (print (list timestamp amount what) records))
    (message "Spent $~D for ~A at ~A" amount what timestamp)))