From e3a7247b6850d40a75f92bf9ce2a159ed9fe49d6 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Mon, 15 Jun 2020 21:31:06 +0200 Subject: [PATCH] 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. --- lisp/org-table.el | 66 +++++++++++++++++++--------------- testing/lisp/test-org-table.el | 11 +++++- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/lisp/org-table.el b/lisp/org-table.el index 6462b99c4..3bf3ea872 100644 --- a/lisp/org-table.el +++ b/lisp/org-table.el @@ -4348,35 +4348,45 @@ FIELD is a string. WIDTH is a number. ALIGN is either \"c\", (org-table-with-shrunk-columns (let* ((table (org-table-to-lisp)) (rows (remq 'hline table)) - ;; Compute number of columns. - (columns-number (apply #'max (mapcar #'length rows))) (widths nil) - (alignments nil)) - ;; Compute alignment and width for each column. - (dotimes (i columns-number) - (let* ((max-width 1) - (fixed-align? nil) - (numbers 0) - (non-empty 0)) - (dolist (row rows) - (let ((cell (or (nth i row) ""))) - (setq max-width (max max-width (org-string-width cell))) - (cond (fixed-align? nil) - ((equal cell "") nil) - ((string-match "\\`<\\([lrc]\\)[0-9]*>\\'" cell) - (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)) + (alignments nil) + (columns-number 1)) + (if (null rows) + ;; Table contains only horizontal rules. Compute the + ;; number of columns anyway, and choose an arbitrary width + ;; and alignment. + (let ((end (line-end-position))) + (save-excursion + (while (search-forward "+" end t) + (cl-incf columns-number))) + (setq widths (make-list columns-number 1)) + (setq alignments (make-list columns-number "l"))) + ;; Compute alignment and width for each column. + (setq columns-number (apply #'max (mapcar #'length rows))) + (dotimes (i columns-number) + (let ((max-width 1) + (fixed-align? nil) + (numbers 0) + (non-empty 0)) + (dolist (row rows) + (let ((cell (or (nth i row) ""))) + (setq max-width (max max-width (org-string-width cell))) + (cond (fixed-align? nil) + ((equal cell "") nil) + ((string-match "\\`<\\([lrc]\\)[0-9]*>\\'" cell) + (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 ;; fields. (setq org-table-last-alignment alignments) diff --git a/testing/lisp/test-org-table.el b/testing/lisp/test-org-table.el index 64a1b4b16..7a4a39519 100644 --- a/testing/lisp/test-org-table.el +++ b/testing/lisp/test-org-table.el @@ -1768,7 +1768,16 @@ See also `test-org-table/copy-field'." (equal "| |\n| 1 |\n| 123 |" (org-test-with-temp-text "| |\n| 1 |\n| 123 |" (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 "|---|" + (org-table-align) + t)) + (should + (org-test-with-temp-text "|---|---------|\n|---|---|-----|" + (org-table-align) + t))) (ert-deftest test-org-table/align-buffer-tables () "Align all tables when updating buffer."