mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-09-29 22:47:56 +00:00
org-table: Adding single cell movement functions
* lisp/org-table.el (org-table--swap-cells): (org-table--move-cell): (org-table-move-cell-up): (org-table-move-cell-down): (org-table-move-cell-left): (org-table-move-cell-right): New functions. * testing/lisp/test-org-table.el (test-org-table/move-cell-down): (test-org-table/move-cell-up): (test-org-table/move-cell-right): (test-org-table/move-cell-left): New tests. * doc/org-manual.org (Column and row editing): Document functions and keybindings for single cell movement.
This commit is contained in:
parent
74f769f850
commit
d0a5308435
|
@ -1556,6 +1556,30 @@ you, configure the option ~org-table-auto-blank-field~.
|
|||
#+findex: org-table-kill-row
|
||||
Kill the current row or horizontal line.
|
||||
|
||||
- {{{kbd(S-UP)}}} (~org-table-move-cell-up~) ::
|
||||
|
||||
#+kindex: S-UP
|
||||
#+findex: org-table-move-cell-up
|
||||
Move cell up by swapping with adjacent cell.
|
||||
|
||||
- {{{kbd(S-DOWN)}}} (~org-table-move-cell-down~) ::
|
||||
|
||||
#+kindex: S-DOWN
|
||||
#+findex: org-table-move-cell-down
|
||||
Move cell down by swapping with adjacent cell.
|
||||
|
||||
- {{{kbd(S-LEFT)}}} (~org-table-move-cell-left~) ::
|
||||
|
||||
#+kindex: S-LEFT
|
||||
#+findex: org-table-move-cell-left
|
||||
Move cell left by swapping with adjacent cell.
|
||||
|
||||
- {{{kbd(S-RIGHT)}}} (~org-table-move-cell-right~) ::
|
||||
|
||||
#+kindex: S-RIGHT
|
||||
#+findex: org-table-move-cell-right
|
||||
Move cell right by swapping with adjacent cell.
|
||||
|
||||
- {{{kbd(M-S-DOWN)}}} (~org-table-insert-row~) ::
|
||||
|
||||
#+kindex: M-S-DOWN
|
||||
|
|
|
@ -1442,6 +1442,80 @@ non-nil, the one above is used."
|
|||
(above min)
|
||||
(t max)))))))
|
||||
|
||||
(defun org-table--swap-cells (row1 col1 row2 col2)
|
||||
"Swap two cells indicated by the coordinates provided.
|
||||
ROW1, COL1, ROW2, COL2 are integers indicating the row/column
|
||||
position of the two cells that will be swapped in the table."
|
||||
(let ((content1 (org-table-get row1 col1))
|
||||
(content2 (org-table-get row2 col2)))
|
||||
(org-table-put row1 col1 content2)
|
||||
(org-table-put row2 col2 content1)))
|
||||
|
||||
(defun org-table--move-cell (direction)
|
||||
"Move the current cell in a cardinal direction.
|
||||
DIRECTION is a symbol among `up', `down', `left', and `right'.
|
||||
The contents the current cell are swapped with cell in the
|
||||
indicated direction. Raise an error if the move cannot be done."
|
||||
(let ((row-shift (pcase direction (`up -1) (`down 1) (_ 0)))
|
||||
(column-shift (pcase direction (`left -1) (`right 1) (_ 0))))
|
||||
(when (and (= 0 row-shift) (= 0 column-shift))
|
||||
(error "Invalid direction: %S" direction))
|
||||
;; Initialize `org-table-current-ncol' and `org-table-dlines'.
|
||||
(org-table-analyze)
|
||||
(let* ((row (org-table-current-line))
|
||||
(column (org-table-current-column))
|
||||
(target-row (+ row row-shift))
|
||||
(target-column (+ column column-shift))
|
||||
(org-table-current-nrow (1- (length org-table-dlines))))
|
||||
(when (or (< target-column 1)
|
||||
(< target-row 1)
|
||||
(> target-column org-table-current-ncol)
|
||||
(> target-row org-table-current-nrow))
|
||||
(user-error "Cannot move cell further"))
|
||||
(org-table--swap-cells row column target-row target-column)
|
||||
(org-table-goto-line target-row)
|
||||
(org-table-goto-column target-column))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-table-move-cell-up ()
|
||||
"Move a single cell up in a table.
|
||||
Swap with anything in target cell."
|
||||
(interactive)
|
||||
(unless (org-table-check-inside-data-field)
|
||||
(error "No table at point"))
|
||||
(org-table--move-cell 'up)
|
||||
(org-table-align))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-table-move-cell-down ()
|
||||
"Move a single cell down in a table.
|
||||
Swap with anything in target cell."
|
||||
(interactive)
|
||||
(unless (org-table-check-inside-data-field)
|
||||
(error "No table at point"))
|
||||
(org-table--move-cell 'down)
|
||||
(org-table-align))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-table-move-cell-left ()
|
||||
"Move a single cell left in a table.
|
||||
Swap with anything in target cell."
|
||||
(interactive)
|
||||
(unless (org-table-check-inside-data-field)
|
||||
(error "No table at point"))
|
||||
(org-table--move-cell 'left)
|
||||
(org-table-align))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-table-move-cell-right ()
|
||||
"Move a single cell right in a table.
|
||||
Swap with anything in target cell."
|
||||
(interactive)
|
||||
(unless (org-table-check-inside-data-field)
|
||||
(error "No table at point"))
|
||||
(org-table--move-cell 'right)
|
||||
(org-table-align))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-table-delete-column ()
|
||||
"Delete a column from the table."
|
||||
|
|
|
@ -2277,6 +2277,391 @@ See also `test-org-table/copy-field'."
|
|||
(buffer-string)))))
|
||||
|
||||
|
||||
|
||||
;;; Moving single cells
|
||||
(ert-deftest test-org-table/move-cell-down ()
|
||||
"Test `org-table-move-cell-down' specifications."
|
||||
;; Error out when cell cannot be moved due to not in table, in the
|
||||
;; last row of the table, or is on a hline.
|
||||
(should-error
|
||||
(org-test-with-temp-text "not in\na table\n"
|
||||
(org-table-move-cell-down)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a |"
|
||||
(org-table-move-cell-down)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a |\n"
|
||||
(org-table-move-cell-down)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a | <point>b |\n"
|
||||
(org-table-move-cell-down)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a | b |\n| <point>c | d |\n"
|
||||
(org-table-move-cell-down)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a | b |\n| c | <point>d |\n"
|
||||
(org-table-move-cell-down)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| <point>a |\n|---|\n"
|
||||
(org-table-move-cell-down)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "|<point>---|\n| a |\n"
|
||||
(org-table-move-cell-down)))
|
||||
;; Check for correct cell movement
|
||||
(should (equal (concat "| c | b |\n"
|
||||
"| a | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| <point>a | b |\n"
|
||||
"| c | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-table-move-cell-down)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | d |\n"
|
||||
"| c | b |\n"
|
||||
"| e | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | <point>b |\n"
|
||||
"| c | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-table-move-cell-down)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | b |\n"
|
||||
"| e | d |\n"
|
||||
"| c | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b |\n"
|
||||
"| <point>c | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-table-move-cell-down)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | d |\n"
|
||||
"| c | f |\n"
|
||||
"| e | b |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a |<point> b |\n"
|
||||
"| c | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-table-move-cell-down)
|
||||
(org-table-move-cell-down)
|
||||
(buffer-string))))
|
||||
;; Check for correct handling of hlines which should not change
|
||||
;; position on single cell moves.
|
||||
(should (equal (concat "| c | b |\n"
|
||||
"|---+---|\n"
|
||||
"| a | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| <point>a | b |\n"
|
||||
"|---+---|\n"
|
||||
"| c | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-table-move-cell-down)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | d |\n"
|
||||
"|---+---|\n"
|
||||
"| c | f |\n"
|
||||
"| e | b |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | <point>b |\n"
|
||||
"|---+---|\n"
|
||||
"| c | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-table-move-cell-down)
|
||||
(org-table-move-cell-down)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | b |\n"
|
||||
"|---+---|\n"
|
||||
"| c | f |\n"
|
||||
"| e | d |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b |\n"
|
||||
"|---+---|\n"
|
||||
"| c | <point>d |\n"
|
||||
"| e | f |\n")
|
||||
(org-table-move-cell-down)
|
||||
(buffer-string))))
|
||||
;; Move single cell even without a final newline.
|
||||
(should (equal (concat "| a | d |\n"
|
||||
"|---+---|\n"
|
||||
"| c | f |\n"
|
||||
"| e | b |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | <point>b |\n"
|
||||
"|---+---|\n"
|
||||
"| c | d |\n"
|
||||
"| e | f |")
|
||||
(org-table-move-cell-down)
|
||||
(org-table-move-cell-down)
|
||||
(buffer-string)))))
|
||||
|
||||
(ert-deftest test-org-table/move-cell-up ()
|
||||
"Test `org-table-move-cell-up' specifications."
|
||||
;; Error out when cell cannot be moved due to not in table, in the
|
||||
;; last row of the table, or is on a hline.
|
||||
(should-error
|
||||
(org-test-with-temp-text "not in\na table\n"
|
||||
(org-table-move-cell-up)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a |"
|
||||
(org-table-move-cell-up)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a |\n"
|
||||
(org-table-move-cell-up)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| <point>a | b |\n"
|
||||
(org-table-move-cell-up)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a | <point>b |\n| c | d |\n"
|
||||
(org-table-move-cell-up)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| <point>a |\n|---|\n"
|
||||
(org-table-move-cell-up)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "|<point>---|\n| a |\n"
|
||||
(org-table-move-cell-up)))
|
||||
;; Check for correct cell movement.
|
||||
(should (equal (concat "| c | b |\n"
|
||||
"| a | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b |\n"
|
||||
"| <point>c | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-table-move-cell-up)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | d |\n"
|
||||
"| c | b |\n"
|
||||
"| e | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b |\n"
|
||||
"| c | <point>d |\n"
|
||||
"| e | f |\n")
|
||||
(org-table-move-cell-up)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | b |\n"
|
||||
"| e | d |\n"
|
||||
"| c | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b |\n"
|
||||
"| c | d |\n"
|
||||
"| <point>e | f |\n")
|
||||
(org-table-move-cell-up)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | f |\n"
|
||||
"| c | b |\n"
|
||||
"| e | d |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b |\n"
|
||||
"| c | d |\n"
|
||||
"| e |<point> f |\n")
|
||||
(org-table-move-cell-up)
|
||||
(org-table-move-cell-up)
|
||||
(buffer-string))))
|
||||
;; Check for correct handling of hlines which should not change
|
||||
;; position on single cell moves.
|
||||
(should (equal (concat "| c | b |\n"
|
||||
"|---+---|\n"
|
||||
"| a | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b |\n"
|
||||
"|---+---|\n"
|
||||
"| <point>c | d |\n"
|
||||
"| e | f |\n")
|
||||
(org-table-move-cell-up)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | f |\n"
|
||||
"|---+---|\n"
|
||||
"| c | b |\n"
|
||||
"| e | d |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b |\n"
|
||||
"|---+---|\n"
|
||||
"| c | d |\n"
|
||||
"| e | <point>f |\n")
|
||||
(org-table-move-cell-up)
|
||||
(org-table-move-cell-up)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | b |\n"
|
||||
"|---+---|\n"
|
||||
"| c | f |\n"
|
||||
"| e | d |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b |\n"
|
||||
"|---+---|\n"
|
||||
"| c | d |\n"
|
||||
"| e | <point>f |\n")
|
||||
(org-table-move-cell-up)
|
||||
(buffer-string))))
|
||||
;; Move single cell even without a final newline.
|
||||
(should (equal (concat "| a | f |\n"
|
||||
"|---+---|\n"
|
||||
"| c | b |\n"
|
||||
"| e | d |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b |\n"
|
||||
"|---+---|\n"
|
||||
"| c | d |\n"
|
||||
"| e | <point>f |")
|
||||
(org-table-move-cell-up)
|
||||
(org-table-move-cell-up)
|
||||
(buffer-string)))))
|
||||
|
||||
(ert-deftest test-org-table/move-cell-right ()
|
||||
"Test `org-table-move-cell-right' specifications."
|
||||
;; Error out when cell cannot be moved due to not in table, in the
|
||||
;; last col of the table, or is on a hline.
|
||||
(should-error
|
||||
(org-test-with-temp-text "not in\na table\n"
|
||||
(org-table-move-cell-right)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a |"
|
||||
(org-table-move-cell-right)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a |\n"
|
||||
(org-table-move-cell-right)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| <point>a |\n| b |\n"
|
||||
(org-table-move-cell-right)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a | <point>b |\n| c | d |\n"
|
||||
(org-table-move-cell-right)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| <point>a |\n|---|\n"
|
||||
(org-table-move-cell-right)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "|<point>---|\n| a |\n"
|
||||
(org-table-move-cell-right)))
|
||||
;; Check for correct cell movement.
|
||||
(should (equal (concat "| b | a | c |\n"
|
||||
"| d | e | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| <point>a | b | c |\n"
|
||||
"| d | e | f |\n")
|
||||
(org-table-move-cell-right)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| b | c | a |\n"
|
||||
"| d | e | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| <point>a | b | c |\n"
|
||||
"| d | e | f |\n")
|
||||
(org-table-move-cell-right)
|
||||
(org-table-move-cell-right)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | b | c |\n"
|
||||
"| e | f | d |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b | c |\n"
|
||||
"| <point> d | e | f |\n")
|
||||
(org-table-move-cell-right)
|
||||
(org-table-move-cell-right)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | b | c |\n"
|
||||
"| d | f | e |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b | c |\n"
|
||||
"| d | <point>e | f |\n")
|
||||
(org-table-move-cell-right)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | b | c |\n"
|
||||
"|---+---+---|\n"
|
||||
"| e | f | d |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b | c |\n"
|
||||
"|---+---+---|\n"
|
||||
"| <point>d | e | f |\n")
|
||||
(org-table-move-cell-right)
|
||||
(org-table-move-cell-right)
|
||||
(buffer-string))))
|
||||
;; Move single cell even without a final newline.
|
||||
(should (equal (concat "| a | b | c |\n"
|
||||
"|---+---+---|\n"
|
||||
"| e | d | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b | c |\n"
|
||||
"|---+---+---|\n"
|
||||
"| <point>d | e | f |")
|
||||
(org-table-move-cell-right)
|
||||
(buffer-string)))))
|
||||
|
||||
(ert-deftest test-org-table/move-cell-left ()
|
||||
"Test `org-table-move-cell-left' specifications."
|
||||
;; Error out when cell cannot be moved due to not in table, in the
|
||||
;; last col of the table, or is on a hline.
|
||||
(should-error
|
||||
(org-test-with-temp-text "not in\na table\n"
|
||||
(org-table-move-cell-left)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a |"
|
||||
(org-table-move-cell-left)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| a |\n"
|
||||
(org-table-move-cell-left)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| <point>a |\n| b |\n"
|
||||
(org-table-move-cell-left)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| <point>a | b |\n| c | d |\n"
|
||||
(org-table-move-cell-left)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "| <point>a |\n|---|\n"
|
||||
(org-table-move-cell-left)))
|
||||
(should-error
|
||||
(org-test-with-temp-text "|<point>---|\n| a |\n"
|
||||
(org-table-move-cell-left)))
|
||||
;; Check for correct cell movement.
|
||||
(should (equal (concat "| b | a | c |\n"
|
||||
"| d | e | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | <point>b | c |\n"
|
||||
"| d | e | f |\n")
|
||||
(org-table-move-cell-left)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| c | a | b |\n"
|
||||
"| d | e | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b | <point>c |\n"
|
||||
"| d | e | f |\n")
|
||||
(org-table-move-cell-left)
|
||||
(org-table-move-cell-left)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | b | c |\n"
|
||||
"| f | d | e |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b | c |\n"
|
||||
"| d | e | <point>f |\n")
|
||||
(org-table-move-cell-left)
|
||||
(org-table-move-cell-left)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | b | c |\n"
|
||||
"| d | f | e |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b | c |\n"
|
||||
"| d | e | <point>f |\n")
|
||||
(org-table-move-cell-left)
|
||||
(buffer-string))))
|
||||
(should (equal (concat "| a | b | c |\n"
|
||||
"|---+---+---|\n"
|
||||
"| f | d | e |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b | c |\n"
|
||||
"|---+---+---|\n"
|
||||
"| d | e | <point>f |\n")
|
||||
(org-table-move-cell-left)
|
||||
(org-table-move-cell-left)
|
||||
(buffer-string))))
|
||||
;; Move single cell even without a final newline.
|
||||
(should (equal (concat "| a | b | c |\n"
|
||||
"|---+---+---|\n"
|
||||
"| e | d | f |\n")
|
||||
(org-test-with-temp-text
|
||||
(concat "| a | b | c |\n"
|
||||
"|---+---+---|\n"
|
||||
"| d | <point>e | f |")
|
||||
(org-table-move-cell-left)
|
||||
(buffer-string)))))
|
||||
|
||||
|
||||
;;; Moving rows, moving columns
|
||||
|
||||
|
|
Loading…
Reference in a new issue