How to move a single cell in an org-table

Posted on March 22, 2017
Tags: howto, emacs, org-mode

Emacs-lisp function to move a single cell in and org-table.

After watching Eric Brechner: “Agile Project Management with Kanban” | Talks at Google - YouTube, I wanted to try Kanban for my personal task management.

Thinking about using an org-mode table, I wrote some emacs-lisp functions to move a single cell around by sequentially swapping it with its neighbor. Actually I found myself using it a lot in most of my org-tables. As I am not (yet) very proficient with emacs-lisp, the code is a bit repetitive but served me well to get going with kanban. Here is the code:

;; org-table move cell
;; https://www.mail-archive.com/emacs-orgmode@gnu.org/msg98407.html
;; https://www.reddit.com/r/emacs/comments/583n1x/movecopy_a_cel_to_the_right/
(defun md-org-table-swap-cells (row col nextrow nextcol)
  (interactive)
  (let ((curfield (org-table-get row col))
        (nextfield (org-table-get nextrow nextcol)))
    (org-table-analyze)
    (org-table-put row col nextfield)
    (org-table-put nextrow nextcol curfield)
    (org-table-align)
    (org-table-goto-field (format "@%s$%s" nextrow nextcol))
    (message "md-org-table-swap-cells %s:%s <-> %s:%s"
             (format "@%s$%s" row col) curfield (format "@%s$%s" nextrow nextcol) nextfield)
    ))

(defun md-org-table-swap-cell-right ()
  (interactive)
  (if (org-at-table-p)
      (let* ((col (org-table-current-column))
             (row (org-table-current-dline))
             (nextrow row)
             (nextcol (+ col 1)))
        (md-org-table-swap-cells row col nextrow nextcol)
        (md-update-todo-status))
    (org-shiftright)
    ))
(define-key org-mode-map (kbd "S-<right>") 'md-org-table-swap-cell-right)

(defun md-org-table-swap-cell-left ()
  (interactive)
  (if (org-at-table-p)
      (let* ((col (org-table-current-column))
             (row (org-table-current-dline))
             (nextrow row)
             (nextcol (- col 1)))
        (md-org-table-swap-cells row col nextrow nextcol)
        (md-update-todo-status))
    (org-shiftleft)))
(define-key org-mode-map (kbd "S-<left>") 'md-org-table-swap-cell-left)

(defun md-org-table-swap-cell-up ()
  (interactive)
  (if (org-at-table-p)
      (let* ((col (org-table-current-column))
             (row (org-table-current-dline))
             (nextrow (- row 1))
             (nextcol col))
        (md-org-table-swap-cells row col nextrow nextcol)
        (md-update-todo-status))
    (org-shiftup)))
(define-key org-mode-map (kbd "S-<up>") 'md-org-table-swap-cell-up)

Along the same lines I thought about similar functions to merge cells, but I somehow never used them.

(defun md-org-table-merge-cells (row col nextrow nextcol)
  (interactive)
  (let ((curfield (org-table-get row col))
        (nextfield (org-table-get nextrow nextcol)))
    (org-table-analyze)
    (org-table-put nextrow nextcol (concat nextfield " " curfield))
    (org-table-put row col " ")
    (org-table-align)
    (org-table-goto-field (format "@%s$%s" nextrow nextcol))
    (message "md-org-table-merge-cells %s:%s <+> %s:%s"
             (format "@%s$%s" row col) curfield (format "@%s$%s" nextrow nextcol) nextfield)
    ))

(defun md-org-table-merge-cell-up ()
  (interactive)
  (if (org-at-table-p)
      (let* ((col (org-table-current-column))
             (row (org-table-current-dline))
             (nextrow (- row 1))
             (nextcol col))
        (md-org-table-merge-cells row col nextrow nextcol)
        (md-update-todo-status))
    (org-shiftup)))
(define-key org-mode-map (kbd "M-S-<up>") 'md-org-table-merge-cell-up)

(defun md-org-table-merge-cell-down ()
  (interactive)
  (if (org-at-table-p)
      (let* ((col (org-table-current-column))
             (row (org-table-current-dline))
             (nextrow (+ row 1))
             (nextcol col))
        (md-org-table-merge-cells row col nextrow next col)
        )))
(define-key org-mode-map (kbd "M-S-<down>") 'md-org-table-merge-cell-down)

I just found a new emacs package called org-kanban, which I still need to try.