Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (defun my/string-to-number (line re)
- (let ((matched (string-match re line)))
- (if matched
- (list (match-string 0 line)
- (substring line (length (match-string 0 line))))
- (list nil line))))
- (defun my/string-to-double (line)
- (my/string-to-number
- line
- "\\s-*[+-]?[0-9]+\\(?:\\.[0-9]+\\(?:[eE][+-]?[0-9]+\\)?\\)?"))
- (defun my/string-to-int (line)
- (my/string-to-number line "\\s-*[+-]?[0-9]+"))
- (defun my/vector-transpose (vec)
- (cl-coerce
- (cl-loop for i below (length (aref vec 0))
- collect (cl-coerce
- (cl-loop for j below (length vec)
- collect (aref (aref vec j) i))
- 'vector))
- 'vector))
- (defun my/align-metric (col num-parser)
- (cl-loop with max-left = 0
- with max-right = 0
- with decimal = 0
- for cell across col
- for nump = (car (funcall num-parser cell))
- for has-decimals = (cl-position ?\. cell) do
- (if nump
- (if has-decimals
- (progn
- (setf decimal 1)
- (when (> has-decimals max-left)
- (setf max-left has-decimals))
- (when (> (1- (- (length cell) has-decimals))
- max-right)
- (setf max-right (1- (- (length cell) has-decimals)))))
- (when (> (length cell) max-left)
- (setf max-left (length cell))))
- (when (> (length cell) max-left)
- (setf max-left (length cell))))
- finally (cl-return (list max-left decimal max-right))))
- (defun my/print-matrix (rows metrics num-parser prefix spacer)
- (cl-loop with first-line = t
- for i upfrom 0
- for row across rows do
- (unless first-line (insert prefix))
- (setf first-line nil)
- (cl-loop with first-row = t
- for cell across row
- for metric in metrics
- for has-decimals =
- (and (cl-position ?\. cell)
- (car (funcall num-parser cell)))
- do
- (unless first-row (insert spacer))
- (setf first-row nil)
- (cl-destructuring-bind (left decimal right) metric
- (if has-decimals
- (cl-destructuring-bind (whole fraction)
- (split-string cell "\\.")
- (insert (make-string (- left (length whole)) ?\ )
- whole
- "."
- fraction
- (make-string (- right (length fraction)) ?\ )))
- (insert (make-string (- left (length cell)) ?\ )
- cell
- (make-string (1+ right) ?\ )))))
- (unless (= i (1- (length rows)))
- (insert "\n"))))
- (defun my/read-rows (beg end)
- (cl-coerce
- (cl-loop for line in (split-string
- (buffer-substring-no-properties beg end) "\n")
- collect
- (cl-coerce
- (nreverse
- (cl-loop with result = nil
- with remaining = line do
- (cl-destructuring-bind (num remainder)
- (funcall num-parser remaining)
- (if num
- (progn
- (push (org-trim num) result)
- (setf remaining remainder))
- (push (org-trim remaining) result)
- (cl-return result)))))
- 'vector))
- 'vector))
- (defun my/align-matrix (parser)
- (interactive "SParse numbers using: ")
- (let ((num-parser
- (cl-case parser
- (:double 'my/string-to-double)
- (:int 'my/string-to-int)
- (otherwise
- (if (functionp parser)
- parser
- 'my/string-to-number))))
- beg end)
- (if (region-active-p)
- (setf beg (region-beginning)
- end (region-end))
- (setf end (1- (search-forward-regexp "\\s)" nil t))
- beg (1+ (progn (backward-sexp) (point)))))
- (goto-char beg)
- (let* ((prefix (make-string (current-column) ?\ ))
- (spacer " ")
- (rows (my/read-rows beg end))
- (cols (my/vector-transpose rows))
- (metrics
- (cl-loop for col across cols
- collect (my/align-metric col num-parser))))
- (delete-region beg end)
- (my/print-matrix rows metrics num-parser prefix spacer))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement