table: Gracefully align hrule-only tables

* lisp/org-table.el (org-table-align): Try to align the table even
when it only consists of horizontal rules.
* testing/lisp/test-org-table.el (test-org-table/align): Add test.
This commit is contained in:
Nicolas Goaziou 2020-06-15 21:31:06 +02:00
parent a8cc4f7244
commit e3a7247b68
2 changed files with 48 additions and 29 deletions

View file

@ -4348,35 +4348,45 @@ FIELD is a string. WIDTH is a number. ALIGN is either \"c\",
(org-table-with-shrunk-columns (org-table-with-shrunk-columns
(let* ((table (org-table-to-lisp)) (let* ((table (org-table-to-lisp))
(rows (remq 'hline table)) (rows (remq 'hline table))
;; Compute number of columns.
(columns-number (apply #'max (mapcar #'length rows)))
(widths nil) (widths nil)
(alignments nil)) (alignments nil)
;; Compute alignment and width for each column. (columns-number 1))
(dotimes (i columns-number) (if (null rows)
(let* ((max-width 1) ;; Table contains only horizontal rules. Compute the
(fixed-align? nil) ;; number of columns anyway, and choose an arbitrary width
(numbers 0) ;; and alignment.
(non-empty 0)) (let ((end (line-end-position)))
(dolist (row rows) (save-excursion
(let ((cell (or (nth i row) ""))) (while (search-forward "+" end t)
(setq max-width (max max-width (org-string-width cell))) (cl-incf columns-number)))
(cond (fixed-align? nil) (setq widths (make-list columns-number 1))
((equal cell "") nil) (setq alignments (make-list columns-number "l")))
((string-match "\\`<\\([lrc]\\)[0-9]*>\\'" cell) ;; Compute alignment and width for each column.
(setq fixed-align? (match-string 1 cell))) (setq columns-number (apply #'max (mapcar #'length rows)))
(t (dotimes (i columns-number)
(cl-incf non-empty) (let ((max-width 1)
(when (string-match-p org-table-number-regexp cell) (fixed-align? nil)
(cl-incf numbers)))))) (numbers 0)
(push max-width widths) (non-empty 0))
(push (cond (dolist (row rows)
(fixed-align?) (let ((cell (or (nth i row) "")))
((>= numbers (* org-table-number-fraction non-empty)) "r") (setq max-width (max max-width (org-string-width cell)))
(t "l")) (cond (fixed-align? nil)
alignments))) ((equal cell "") nil)
(setq widths (nreverse widths)) ((string-match "\\`<\\([lrc]\\)[0-9]*>\\'" cell)
(setq alignments (nreverse alignments)) (setq fixed-align? (match-string 1 cell)))
(t
(cl-incf non-empty)
(when (string-match-p org-table-number-regexp cell)
(cl-incf numbers))))))
(push max-width widths)
(push (cond
(fixed-align?)
((>= numbers (* org-table-number-fraction non-empty)) "r")
(t "l"))
alignments)))
(setq widths (nreverse widths))
(setq alignments (nreverse alignments)))
;; Store alignment of this table, for later editing of single ;; Store alignment of this table, for later editing of single
;; fields. ;; fields.
(setq org-table-last-alignment alignments) (setq org-table-last-alignment alignments)

View file

@ -1768,7 +1768,16 @@ See also `test-org-table/copy-field'."
(equal "| <c> |\n| 1 |\n| 123 |" (equal "| <c> |\n| 1 |\n| 123 |"
(org-test-with-temp-text "| <c> |\n| 1 |\n| 123 |" (org-test-with-temp-text "| <c> |\n| 1 |\n| 123 |"
(let ((org-table-number-fraction 0.5)) (org-table-align)) (let ((org-table-number-fraction 0.5)) (org-table-align))
(buffer-string))))) (buffer-string))))
;; Handle gracefully tables with only horizontal rules.
(should
(org-test-with-temp-text "|-<point>--|"
(org-table-align)
t))
(should
(org-test-with-temp-text "|-<point>--|---------|\n|---|---|-----|"
(org-table-align)
t)))
(ert-deftest test-org-table/align-buffer-tables () (ert-deftest test-org-table/align-buffer-tables ()
"Align all tables when updating buffer." "Align all tables when updating buffer."