org-mode table 中度用户,时不时会遇到需要进行 table 转置的场景。
没找到现成的,自己 elisp 撸了一个。好玩。
(defun mhb-org-mode--help-transpose-org-table-region ()
"把 region (org table) pivot 转置"
(interactive)
(let* ((region (buffer-substring-no-properties (region-beginning) (region-end)))
(region (string-replace "\n" "" region))
(region (replace-regexp-in-string "[ \t]+" "" region))
;; index of all occurences of "|"
(idxs (cl-loop for c across region
for idx from 0
when (string= (char-to-string c) "|")
collect idx))
;; 换行时两个 "|" 相邻,删除首个
(idxs (cl-loop for c in idxs
for idx from 0
when (and (< (+ 1 idx) (length idxs)) (> (nth (+ 1 idx) idxs) (+ 1 (nth idx idxs))))
collect (nth idx idxs)))
(idxs (append idxs (list (length region))))
;; 计算行数
(nRs (count-matches "\n" (region-beginning) (region-end)))
;; 计算列数
(nCs (let* ((ntmp (count-matches "|" (region-beginning) (region-end))))
(- (/ ntmp nRs) 1))))
(message (format "%s rows, %s columns" nRs nCs))
;; 逐列遍历,打印成行
(cl-loop for cidx from 0 to (- nCs 1)
do (progn
(message (format "column %s" cidx))
(insert "\n|")
(cl-loop for ridx from 0 to (- nRs 1)
do (let* ((beg (nth (+ (* ridx nCs) cidx) idxs))
(end (nth (+ 1 (* ridx nCs) cidx) idxs)))
;; (message (format "row %s" ridx))
(if (and beg end)
(progn
(message (substring region beg end))
(insert (string-replace "|" "" (substring region beg end)))
(insert "|")))))))))
效果: