Endless Parentheses

Ramblings on productivity and technical subjects.

profile for Malabarba on Stack Exchange

Org-mode subtrees and file-local variables

As you grow accustomed to fine-tuning your Emacs experience, it’s not unusual to start using local variables in your files. These are specified as comment lines at the end of the file, and are extremely practical in a number of scenarios. Here’s a very simple org file.

* Some headline
Ramblings no one cares about.
* Another headline
Thoughtfully rescinded.

# Local Variables:
# fill-column: 666
# End:

The only problem is that org-mode thinks that everything after a headline is part of its contents, which is clearly not the case here. One example where this is bad is when you want to shuffle the headlines around with M-↓ or M-↑, and you end up with something like this.

* Another headline
Thoughtfully rescinded.

# Local Variables:
# fill-column: 666
# End:
* Some headline
Ramblings no one cares about.

I asked about that on Emacs.StackExchange and got a very simple solution: just add a “dummy” level-1 headline before the local variable specification.

* Some headline
Ramblings no one cares about.
* Another headline
Thoughtfully rescinded.

* COMMENT Footer 
# Local Variables:
# fill-column: 42
# End:

Now you can move, archive, and refile all your headlines as you wish, without fear of destroying your precious variables. You can even fine-tune the visibility to folded, so that the footer is always folded, and you won’t have to see those variables at all.

But this wouldn’t be our weekly Endless Parentheses if I didn’t give you some code to practice your elisp. The following command is just like end-of-buffer, except it places point before the footer. If invoked again, it will move to the real end of buffer.

(defun endless/org-eob ()
  "Move to end of content, then end of buffer."
  (interactive)
  (unless (use-region-p)
    (push-mark))
  (if (looking-at-p "\n\\* COMMENT Footer")
      (goto-char (point-max))
    (goto-char (point-min))
    (if (search-forward "\n* COMMENT Footer"
                        nil 'noerror)
        (goto-char (match-beginning 0))
      (goto-char (point-max)))))
(define-key org-mode-map [remap end-of-buffer]
  #'endless/org-eob)
comments powered by Disqus