I spent way too much time noodling around with thisHere is a slightly revised version tested on GNU Emacs:
(defun bracket-sum-line-split-col3 (col3 unit-char)
(let ((regex-pat1 (format "\\([-0-9.]+[ ]*\\)%s" unit-char))
(regex-pat2 (format "\\([-0-9.]+[ ]*\\)%s[ ]*,[ ]*\\([-0-9.]+[ ]*\\)%s" unit-char unit-char)))
(if (string-match regex-pat2 col3)
(list (string-to-number (match-string 1 col3)) (string-to-number (match-string 2 col3)))
(if (string-match regex-pat1 col3)
(list (string-to-number (match-string 1 col3)) (string-to-number (match-string 1 col3)))
)
)
)
)
(defun bracket-sum-line (line unit-char)
(if (string-match "|[ ]*\\(.+?\\)[ ]*|[ ]*\\(.+?\\)[ ]*|[ ]*\\(.+?\\)[ ]*|" line)
(let ((col1 (match-string 1 line))
(col2 (match-string 2 line))
(col3 (match-string 3 line)))
(let* ((ret (bracket-sum-line-split-col3 col3 unit-char))
(val1 (car ret))
(val2 (cadr ret)))
(list col1 col2 val1 val2))
)))
(defun bracket-sum-output (results unit-char)
(let (retval)
(maphash (lambda (key value)
(push (format "|%s|%f %s|%f %s|" key (nth 0 value) unit-char (nth 1 value) unit-char) retval)
(message "hash key: \"%s\"" key)
)
results)
(push "|Category|col1|col2|" retval) ;; header
(push "\nCOMPLETED SUMS" retval)
(insert (mapconcat 'identity retval "\n")) ;;retval
) ;; end let
)
(defun bracket-sum (begin end char)
(interactive "r\nM String: ")
(save-restriction
(save-excursion
(narrow-to-region begin end)
(goto-char (point-min))
(let ((result (make-hash-table :test 'equal))
(curr-line 1)
(begin (point))
(end (point-max)))
(while (< (point) end)
;; (buffer-substring
(forward-line 1)
;; work done here
(message "where %d %d %d \"%s\"" begin (point) curr-line (buffer-substring begin (- (point) 1)))
(if (> curr-line 1) ; skip table header
(let* ((ret (bracket-sum-line (buffer-substring begin (- (point) 1)) char))
(col1 (nth 0 ret))
(col2 (nth 1 ret))
(val1 (nth 2 ret))
(val2 (nth 3 ret)))
(if (string= col2 "COMPLETE")
(if (gethash col1 result)
(let* ((res (gethash col1 result))
(res1 (nth 0 res))
(res2 (nth 1 res)))
(puthash col1 (list (+ val1 res1) (+ val2 res2)) result)) ;; existing entry
(puthash col1 (list val1 val2) result)) ;; new entry
(unless (gethash col1 result)
(puthash col1 (list 0 0) result))) ;; not complete
)
) ;; end if not table header if
;; goto next line
(setq curr-line (+ 1 curr-line))
(setq begin (point))) ;; end while
(message "%s" result)
(bracket-sum-output result char) ;; print output
))))
ok so what is happening here. I used this test file To Run:
- mark (aka select) the area in the org buffer leaving the cursor on the line below the last one in the table
and I get this output:
- call the function
when I evaluate:
- provide the column arg
(format "%s" (bracket-sum "conditional_sum.org" "μ"))
There is probably a much easier way. My LISP is rusty. HereHere is the codewhat I get:
(defun bracket-sum-line-split-col3 (col3 unit-char)
(let ((regex-pat1 (format "\\([-0-9.]+[ ]*\\)%s" unit-char))
(regex-pat2 (format "\\([-0-9.]+[ ]*\\)%s[ ]*,[ ]*\\([-0-9.]+[ ]*\\)%s" unit-char unit-char)))
(if (string-match regex-pat2 col3)
;; (message "match two %f %f" (string-to-number (match-string 1 col3)) (string-to-number (match-string 2 col3)))
(list (string-to-number (match-string 1 col3)) (string-to-number (match-string 2 col3)))
(if (string-match regex-pat1 col3)
;; (message "match one %f %f" (string-to-number (match-string 1 col3)) (string-to-number (match-string 1 col3)))
(list (string-to-number (match-string 1 col3)) (string-to-number (match-string 1 col3)))
)
)
)
)
(defun bracket-sum-line (line unit-char)
(if (string-match "|[ ]*\\(.+?\\)[ ]*|[ ]*\\(.+?\\)[ ]*|[ ]*\\(.+?\\)[ ]*|" line)
(let ((col1 (match-string 1 line))
(col2 (match-string 2 line))
(col3 (match-string 3 line)))
;;(message "line split: \"%s\" \"%s\" \"%s\"" col1 col2 col3)
(let* ((ret (bracket-sum-line-split-col3 col3 unit-char))
(val1 (car ret))
(val2 (cadr ret)))
;; (message "vals %f %f" val1 val2))
(list col1 col2 val1 val2))
)))
(defun bracket-sum (buffer unit-char)
(save-excursion
(or (bufferp buffer)
(setq buffer (get-buffer buffer)))
(set-buffer buffer)
(let ((bstart (point-min))
(bend (point-max))
(result (make-hash-table :test 'equal))
(line 0))
;; (message "buffer start end %d %d" bstart bend)
(goto-char bstart)
(while (< (point) bend)
; (message "line %d %d" line (point))
(if (re-search-forward "^\\(.*+\\)$") ; try to grap the whole line
(if (> line 0) ; skip table header
(let* ((ret (bracket-sum-line (match-string 1) unit-char))
(col1 (nth 0 ret))
(col2 (nth 1 ret))
(val1 (nth 2 ret))
(val2 (nth 3 ret)))
(if (string= col2 "COMPLETE")
;; (message "CLOSE %s %s %f %f" col1 col2 val1 val2))
(if (gethash col1 result)
(let* ((res (gethash col1 result))
(res1 (nth 0 res))
(res2 (nth 1 res)))
(puthash col1 (list (+ val1 res1) (+ val2 res2)) result)) ;; existing entry
(puthash col1 (list val1 val2) result)) ;; new entry
(unless (gethash col1 result)
(puthash col1 (list 0 0) result))) ;; not complete
)
)
)
;; let do the next line
(forward-line 1)
(setq line (1+ line))
) ;; end while
;; lets try to format the return list
(let (retval)
(maphash (lambda (key value)
(push (format "Category: %s, %f %s, %f %s.\n" key (nth 0 value) unit-char (nth 1 value) unit-char) retval))
result)
retval)
)))
;; (format "%s" (bracket-sum "conditional_sum.org" "μ"))
Please note some minor tweaks will be required to use the interactive restriction based selection. To use in org mode I would just CTRL-U then CTRL-X + CTRL-E to have emacs dump the text tojust go into the results and hit tab and org buffermode will format it. I only tested it in GNU Emacs.