From 891257d3c321c05b409b4a112dd0e2548b8d64bd Mon Sep 17 00:00:00 2001 From: Alexander Rosenberg Date: Sat, 25 Oct 2025 18:56:41 -0700 Subject: [PATCH] Update format stuff --- clash/clash.lisp | 64 ++++++++++++++++++++++++++++++++++++----------- clash/format.lisp | 37 +++++++++++++++++---------- 2 files changed, 73 insertions(+), 28 deletions(-) diff --git a/clash/clash.lisp b/clash/clash.lisp index c923b7a..d2a6940 100644 --- a/clash/clash.lisp +++ b/clash/clash.lisp @@ -425,25 +425,57 @@ list of trash directories that were present in INFOS." (no-sort infos) (t (sort-trashinfos-for-cmd infos cmd))))) -(defun print-objects-for-command (cmd objs &optional (indices t) extra-action) +(defun print-objects-for-command (cmd objs &key (indices t) extra-action) "Print OBJS, a list of trashinfos or trash directories, for CMD." (if (clingon:getopt cmd :directory-wise) - (format-list t (clingon:getopt cmd :dir-format) objs indices extra-action) - (format-list t (clingon:getopt cmd :file-format) objs indices extra-action))) + (format-list t (clingon:getopt cmd :dir-format) objs + :indices indices :extra-action extra-action) + (format-list t (clingon:getopt cmd :file-format) objs + :indices indices :extra-action extra-action))) ;; List command (defun list/handler (cmd) "Handler for the \"list\" subcommand." - (let ((objs (list-objects-for-command cmd))) - (print-objects-for-command cmd objs))) + (let* ((quiet (clingon:getopt cmd :quiet)) + (objs (list-objects-for-command cmd quiet)) + (total (clingon:getopt cmd :total)) + (dir-wise (clingon:getopt cmd :directory-wise)) + (total-count 0)) + (when (and quiet (not total)) + (error "Can't have -q without -t")) + (cond + ((and quiet dir-wise) + (dolist (path-and-infos objs) + (incf total-count (length (cdr path-and-infos))))) + (quiet (setq total-count (length objs))) + (t (print-objects-for-command + cmd objs + :extra-action (lambda (obj) + (incf total-count + (if dir-wise (length (cdr obj)) 1)))))) + (when total + (format t "~@[~*Total Matches: ~]~D~%" (not quiet) total-count)))) (defun list/options () "Return options for the \"list\" subcommand." (append (clingon-format-options "%t %o\\n" "Found %c file%m in %p\\n") (clingon-filtering-options) - (clingon-sort-options))) + (clingon-sort-options) + (list + (clingon:make-option + :flag + :key :total + :description "print a total after all matches" + :short-name #\t + :long-name "total") + (clingon:make-option + :flag + :key :quiet + :description "suppress print matches (use with -t)" + :short-name #\q + :long-name "quiet")))) (defun list/command () "Return the Clingon command for the \"list\" subcommand." @@ -592,7 +624,7 @@ return a list of many indices instead." (when (and indices all) (error "Can't use -a and -n together")) (unless (or yes quiet) - (print-objects-for-command cmd objs (or indices t))) + (print-objects-for-command cmd objs :indices (or indices t))) (cond ((not objs) (unless quiet (error "Nothing to do..."))) @@ -797,7 +829,8 @@ return a list of many indices instead." (dir-wise (clingon:getopt cmd :directory-wise)) (base-two (clingon:getopt cmd :base-two)) (bytes (clingon:getopt cmd :bytes)) - (total-size 0)) + (total-size 0) + (*format-switch-base-two-base-ten* base-two)) (when (and bytes base-two) (error "Can't pass both -t and -b")) (flet ((sum (size) @@ -812,14 +845,14 @@ return a list of many indices instead." (sum (trashinfo-size info)))) (dir-wise (print-objects-for-command - cmd objs t (lambda (path-and-infos) - (dolist (info (cdr path-and-infos)) - (sum (trashinfo-size info)))))) + cmd objs :extra-action (lambda (path-and-infos) + (dolist (info (cdr path-and-infos)) + (sum (trashinfo-size info)))))) (t (print-objects-for-command - cmd objs t (lambda (info) - (sum (trashinfo-size info))))))) - (format t "~@[~*Total Size: ~]~A" + cmd objs :extra-action (lambda (info) + (sum (trashinfo-size info))))))) + (format t "~@[~*Total Size: ~]~D~%" (not quiet) (if bytes total-size (format-size total-size base-two))))) @@ -834,7 +867,8 @@ return a list of many indices instead." (clingon:make-option :flag :key :base-two - :description "use base two sizes for the final tally" + :description + "use base two sizes for the final tally (also switch %h and %H format codes)" :short-name #\t :long-name "base-two") (clingon:make-option diff --git a/clash/format.lisp b/clash/format.lisp index 5fb15f2..560c11c 100644 --- a/clash/format.lisp +++ b/clash/format.lisp @@ -23,7 +23,8 @@ #:*trashinfo-formatters* #:*directory-formatters* #:print-clash-format-info - #:*missing-file-formatters*)) + #:*missing-file-formatters* + #:*format-switch-base-two-base-ten*)) (in-package :clash/format) @@ -182,7 +183,8 @@ add one to the result." (defun format-object (stream control-obj obj &key (index 1) (max-index 1) - (max-index-length (number-length max-index))) + (max-index-length (number-length max-index)) + extra-args) "Format the object OBJ to STREAM according to CONTROL-OBJECT (which is from parse-format-string)." (dolist (part control-obj) @@ -200,21 +202,22 @@ parse-format-string)." (with-slots (padder action) (car part) (funcall padder stream (cdr part) (with-output-to-string (tmp-output) - (funcall action tmp-output obj)) + (apply action tmp-output obj extra-args)) obj))) (t (funcall (format-code-action part) stream obj))))) -(defun format-list (stream control-obj objs &optional (indices t) extra-action) +(defun format-list (stream control-obj objs + &key (indices t) extra-action extra-args) "Format a list of objects OBJS with format-object." (if (eq t indices) (loop with max-index = (length objs) with max-index-length = (number-length max-index) for obj in objs for i upfrom 1 - do (format-object stream control-obj obj :index i - :max-index max-index - :max-index-length - max-index-length) + do (format-object stream control-obj obj + :index i :max-index max-index + :max-index-length max-index-length + :extra-args extra-args) when extra-action do (funcall extra-action obj)) (loop with max-index = (reduce #'max indices :initial-value 0) @@ -223,7 +226,8 @@ parse-format-string)." for index in indices do (format-object stream control-obj (aref objs-arr index) :index (1+ index) :max-index max-index - :max-index-length max-index-length) + :max-index-length max-index-length + :extra-args extra-args) when extra-action do (funcall extra-action (aref objs-arr index))))) @@ -264,6 +268,9 @@ The recognized printf-style sequences for ~A are: (:right (format stream "~V<~A~>" width text)) (t (format stream "~A" text))))) +(defvar *format-switch-base-two-base-ten* nil + "Switch the base 2 and base 10 for codes.") + (defparameter *trashinfo-formatters* (list (make-format-code @@ -319,14 +326,16 @@ The recognized printf-style sequences for ~A are: :name #\h :action (lambda (stream info) (format stream "~A" - (format-size (trashinfo-size info)))) + (format-size (trashinfo-size info) + *format-switch-base-two-base-ten*))) :padder (make-fixed-with-padder 9) :doc "the file's size with a (h)uman readable suffix (powers of 10)") (make-format-code :name #\H :action (lambda (stream info) (format stream "~A" - (format-size (trashinfo-size info) t))) + (format-size (trashinfo-size info) + (not *format-switch-base-two-base-ten*)))) :padder (make-fixed-with-padder 10) :doc "the file's size with a (H)uman readable suffix (power of 2)"))) @@ -353,14 +362,16 @@ The recognized printf-style sequences for ~A are: :name #\h :action (lambda (stream path-and-infos) (format stream "~A" (format-size - (trashinfo-list-size (cdr path-and-infos))))) + (trashinfo-list-size (cdr path-and-infos)) + *format-switch-base-two-base-ten*))) :padder (make-fixed-with-padder 9) :doc "the directory's size with a (h)uman readable suffix (powers of 10)") (make-format-code :name #\H :action (lambda (stream path-and-infos) (format stream "~A" - (format-size (trashinfo-list-size (cdr path-and-infos)) t))) + (format-size (trashinfo-list-size (cdr path-and-infos)) + (not *format-switch-base-two-base-ten*)))) :padder (make-fixed-with-padder 10) :doc "the directory's size with a (H)uman readable suffix (powers of 2)") (make-format-code