0

In a long org-mode table, the header line

| header1 | header2 | header3 |
|---------+---------+---------|
|         |         |         |

soon disappears from the visible window as one works further down the table. In tables with many columns, I often must try to understand in which column I am in – specifically its header. As far as I see I have three options:

  • Scroll up; but it can become unwieldy and often is slow.
  • Split the window horizontally, leaving the upper window centred on the header lines; but this steals vertical space.
  • Invoke C-c ? which gives info about column & line number; but it doesn't tell me the header of the present column.

I have been unsuccessfully looking for a neater solution. Is there one?

6
  • 1
    Indeed, it would be nice to have an org-table version of the freeze panel functionality available on spreadsheets. However, you can have this functionality on a browser by exporting your org-table to HTML via some JS libraries.
    – crocefisso
    Commented Jun 12 at 22:42
  • 1
    You can have this functionality in Emacs through the header line (C-h v header-line-format). I believe that org-table-header-line-mode is supposed to take advantage of that, but I cannot make it work and I don't feel like debugging ATM. If you (or anybody else) can make it work, then that would be one answer to this question.
    – NickD
    Commented Jun 13 at 0:58
  • @NickD org-table-header-line-mode works in my Emacs (v29.3, Kubuntu), and is fantastic! Please feel free to post your comment as an answer.
    – pglpm
    Commented Jun 13 at 4:29
  • 1
    Indeed, org-table-header-line-mode is great, I'm just discovering it. @NickD, it also works well on Arch (GNU Emacs 29.3, Org mode 9.8-pre).
    – crocefisso
    Commented Jun 13 at 11:37
  • 1
    It worked well for me too, once I disabused myself from the notion that the implementation uses the Emacs header-line: it does not. Instead, it adds a function to the post-command-hook that checks for the proper conditions and overlays the table header string on the top line of the window. See the heavily revised answer below.
    – NickD
    Commented Jun 14 at 2:08

2 Answers 2

1

org-table-header-line mode is designed to show the headings of the table when they would otherwise be invisible . It is a minor mode, so you can turn it on the usual way you enable or disable any minor mode: M-x org-table-header-line-mode toggles the mode interactively. From Lisp, (org-table-header-line-mode 1) turns it on and (org-table-header-line-mode 0) turns it off footnote. Then when you are looking at a portion of the table near the bottom, making the top of the table (in particular, the line with the table headings) scroll off the top of the window, the top line of the window is overlaid with the line of the table headings, so you can see in which column you are on.

For example, in the following screenshot, you can see that the cursor is in column F (the table that this came from has 40 rows and the columns are various powers of the row number):

enter image description here


I mistakenly stated in my comment and in the previous version of this answer that this takes advantage of an Emacs facility, called the header-line (which is like the mode line, except it's at the top of the window, instead of the bottom - in particular, you control it by using the variable header-line-format, similar to how the mode line is controlled with the variable mode-line-format). But the implementation of org-table-header-line-mode does NOT use the Emacs header-line at all. Mea culpa.


[footnote] Actually any positive argument enables it and any negative (or zero) argument disables it - just like all minor modes.

1
  • This minor mode is a small gem! A little hidden, I'd say. I see your headers also have a different colour. Thank you for this answer.
    – pglpm
    Commented Jun 14 at 3:48
1

Here's a different answer: it implements a small function that gets the header string of the current column and prints it out in the echo area. The implementation is split into a function that does the (not so) heavy lifting and returns the required string (unless there is an error), and a command that prints out the result (or the error message). The latter is bound to a key (C-c z below but you can choose your own) for easy invocation:

(defun ndk/header-of-current-column ()
  (unless (derived-mode-p '(org-mode))
    (user-error "Only Org mode buffers are allowed"))
  (unless (org-at-table-p)
    (user-error "Point is not inside a table"))
  (let ((col (org-table-current-column)))
    (save-excursion
      (goto-char (org-table-begin))
      (let* ((s (org-table-row-get-visible-string (point)))
             (col-header (nth (1- col) (split-string s "|" t))))
        (unless col-header
          (user-error "Col %d - outside the table?" col))
        (string-trim col-header)))))

(defun ndk/print-header-of-current-column ()
  (interactive)
  (message "Header of current column: %s" (ndk/header-of-current-column)))

(define-key org-mode-map (kbd "C-c z") #'ndk/print-header-of-current-column)

The first function could be incorporated into the command org-table-field-info (the command that is bound to C-c ?), so that the column header would be printed together with the other information (row, column and reference notations) that is normally printed by the command.

1
  • 1
    This is very useful too, as it helps save vertical space if needed (sometimes one more visible line makes all the difference). Cheers.
    – pglpm
    Commented Jun 14 at 3:50

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.