14

In org it is possible to set a column width like follows:

|---+------------------------------|               |---+----------------| 
|   |                              |               |   | <14>           | 
| 1 | one                          |               | 1 | one            | 
| 2 | two                          |     ----\     | 2 | two            | 
| 3 | This is a long chunk of text |     ----/     | 3 | This is a lo=> | 
| 4 | four                         |               | 4 | four           | 
|---+------------------------------|               |---+----------------| 

I would like to obtain this layout instead:

|---+----------------|
|   | <14>           |
| 1 | one            |
| 2 | two            |
| 3 | This is a long |
|   | chunk of text  |
| 4 | four           |
|---+----------------|

Of course I can use M-S-<down> and M-<ret> to insert a new row and wrap the long field.
However, for many fields, this is inconvenient. Is there any hack or package to speed up this process?

1
  • AFAIK It's not possible. You could try to request it on the org mailing list. I am not sure org-table would easily be amended, though.
    – rasmus
    Commented Mar 22, 2017 at 9:18

2 Answers 2

11

I am new to the Org API and I would be glad if you could give a look to the code and share some comments.

As for the proposed solution, consider the following table:

|---+--------------------------------+---|
| 1 | one                            | a |
| 2 | two                            | b |
| 3 | This is a long chunk of text   | c |
| 4 | four                           | d |
| 5 | Yet another long chunk of text | e |
|---+--------------------------------+---|

Put the cursor anywhere in the second column and type:

M-x org-table-wrap-to-width

Enter a column width as requested. E.g., entering 15, you get:

|---+----------------+---|
| 1 | one            | a |
| 2 | two            | b |
| 3 | This is a long | c |
|   | chunk of text  |   |
| 4 | four           | d |
| 5 | Yet another    | e |
|   | long chunk of  |   |
|   | text           |   |
|---+----------------+---|

If you are dissatisfied with this width and want to try a different value, use the Emacs standard undo, which will restore the previous layout, so you can rerun the wrap function.

Here's the code. If you know Org, please, give feedback.

(defun org-table-wrap-to-width (width)
  "Wrap current column to WIDTH."
  (interactive (list (read-number "Enter column width: ")))
  (org-table-check-inside-data-field)
  (org-table-align)

  (let (cline (ccol (org-table-current-column)) new-row-count (more t))
    (org-table-goto-line 1)
    (org-table-goto-column ccol)

    (while more
      (setq cline (org-table-current-line))

      ;; Cut current field
      (org-table-copy-region (point) (point) 'cut)

      ;; Justify for width
      (setq org-table-clip 
            (mapcar 'list (org-wrap (caar org-table-clip) width nil)))

      ;; Add new lines and fill
      (setq new-row-count (1- (length org-table-clip)))
      (if (> new-row-count 0)
          (org-table-insert-n-row-below new-row-count)) 
      (org-table-goto-line cline)
      (org-table-goto-column ccol)
      (org-table-paste-rectangle)
      (org-table-goto-line (+ cline new-row-count))

      ;; Move to next line
      (setq more (org-table-goto-line (+ cline new-row-count 1)))
      (org-table-goto-column ccol))

    (org-table-goto-line 1)
    (org-table-goto-column ccol)))

(defun org-table-insert-n-row-below (n)
  "Insert N new lines below the current."
  (let* ((line (buffer-substring (point-at-bol) (point-at-eol)))
         (new (org-table-clean-line line)))
    ;; Fix the first field if necessary
    (if (string-match "^[ \t]*| *[#$] *|" line)
        (setq new (replace-match (match-string 0 line) t t new)))
    (beginning-of-line 2)
    (setq new
      (apply 'concat (make-list n (concat new "\n"))))
    (let (org-table-may-need-update) (insert-before-markers new))  ;;; remove? 
    (beginning-of-line 0)
    (re-search-forward "| ?" (point-at-eol) t)
    (and (or org-table-may-need-update org-table-overlay-coordinates) ;;; remove? 
         (org-table-align))
    (org-table-fix-formulas "@" nil (1- (org-table-current-dline)) n)))
5
  • 3
    Interesting. I guess it should be noted though, that org-mode does not know the lines were wrapped, so, for example, sorting will most likely mess it all up. It still looks useful, e.g. to use before exporting. Commented Mar 15, 2017 at 23:39
  • 2
    @RolazaroAzeveires: It would be relatively easy to add a symbol like " to mark the begin/end of a field spanning multiple lines, in order to go back to the non wrapped version, manipulate, and re-wrap. I am not sure whether this should be a visible symbol (which would make the layout less polished) or an invisible one (which would make the table structure obfuscated).
    – antonio
    Commented Mar 22, 2017 at 11:35
  • Yes, that could be interesting. Emacs, and others, use some visible "curly arrow" symbols to show that there is line wrapping (there is probably some unicode character for that but I found none in a quick search) Commented Mar 22, 2017 at 22:35
  • 2
    What about using the broken bar in place of the vertical bar, |, to indicate when a row is wrapped?
    – Melioratus
    Commented Oct 25, 2017 at 23:12
  • 1
    @Melioratus Great choice. Maybe set as a variable org-table-wrapped-boundary-char or similar? Also would be nice to have the bars in alternate row differ by color.
    – Gavin
    Commented Jun 21, 2021 at 10:25
2

I wrote a function (org-table-narrow) that does this across multiple columns simultaneously by using an external solver to calculate which cells to split: https://github.com/vapniks/org-table-jb-extras
There is also org-table-narrow-column for narrowing a single column which doesn't depend on external binaries, and several other useful commands for transforming tables.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.