render.lisp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. (in-package #:pta-ledger)
  2. (defvar *posting-length* 46 "Length of posting without amount")
  3. (defvar *allowed-statuses* '(#\! #\*))
  4. (defun render-date (universal-time)
  5. (when universal-time
  6. (format nil "~{~4,'0D/~2,'0D/~2,'0D~}" (get-date universal-time))))
  7. (defun when-allowed (status)
  8. (find status *allowed-statuses*))
  9. (defgeneric render (object &optional stream)
  10. (:documentation "Render OBJECT to STREAM in text format."))
  11. (defmethod render ((null null) &optional stream)
  12. (declare (ignore stream)))
  13. (defmethod render ((amount amount) &optional stream)
  14. (format stream "~$ ~A" (amount-quantity amount) (amount-commodity amount)))
  15. (defmethod render ((posting posting) &optional stream)
  16. (with-slots (status virtual account amount unit-price total-price comment) posting
  17. (let* ((amount-text (render amount))
  18. (status-text (format nil "~@[~A ~]" (when-allowed status)))
  19. (account (if virtual
  20. (format nil "~A~A~A" virtual account
  21. (ecase virtual
  22. (#\( #\))
  23. (#\[ #\])))
  24. account))
  25. (text (format nil " ~A~vA~@[ ~A~]~@[ @ ~A~]~@[ @@ ~A~]"
  26. status-text
  27. (if amount-text (- *posting-length*
  28. (position #\Space amount-text)
  29. (length status-text)) 0)
  30. account
  31. amount-text
  32. (when unit-price (render unit-price))
  33. (when total-price (render total-price))))
  34. (comments (split comment))
  35. (first-comment (first comments))
  36. (rest-comments (rest comments)))
  37. (format stream "~A~@[ ; ~A~]~{~%~vA ; ~A~}" text first-comment
  38. (loop for comment in rest-comments append (list (length text) "" comment))))))
  39. (defmethod render ((entry entry) &optional stream)
  40. (with-slots (date secondary-date status code description comment postings) entry
  41. (let* ((text (format nil "~A~@[=~A~]~@[ ~A~]~@[ (~A)~]~@[ ~A~]"
  42. (render-date date) (render-date secondary-date)
  43. (when-allowed status) code description))
  44. (comments (split comment))
  45. (first-comment (first comments))
  46. (rest-comments (rest comments)))
  47. (format stream "~A~@[ ; ~A~]~{~%~vA ; ~A~}~{~%~A~}" text first-comment
  48. (loop for comment in rest-comments append (list (length text) "" comment))
  49. (loop for posting in postings collect (render posting))))))