0

I have an Org Mode file that I would like to open folded and immediately put the point at the bottom of the file.

With org-startup-folded set to t and this as the first line

# -*- eval: (end-of-buffer) -*-

it seems to miscalculate. My best guess is that end-of-buffer calculates the number of characters *visible and then moves that number of characters forward while counting all characters in the file, not just visible ones.

Could this be the case? And, if so, how to achieve the desired effect of moving point to the end of the buffer?

2 Answers 2

0

Function end-of-buffer is intended for interactive use only. C-h f...

But your real problem is that you are trying to evaluate a variable end-of-buffer. There's no variable end-of-buffer (unless you create one). There is instead a function end-of-buffer. The unbound-variable error isn't reported because this is done in a file-local-variables setting.

You can use (end-of-buffer) (calling the function), instead of end-of-buffer in the file-local-variables list.

However, that likely won't do what you want (which is unspecified in your question). The file-local-variables list is evaluated at the beginning of when the file is loaded. And function end-of-buffer acts in whatever buffer is current at that time.


This answers your X question of what's happening with what you tried. But you no doubt have a Y question behind what you're trying. Specify that as a separate question post: How can I do Y?.

2
  • Apoligies, that was a typo. I amended it to (end-of-buffer) which was in my org file. it doesn't fix the problem May 16, 2023 at 13:56
  • As @Drew points out end-of-buffer is interactive-only. However the problem persists when using the recommended (goto-char (point-max)) May 16, 2023 at 14:04
0

I haven't investigated why the file-local variable approach doesn't work (I suspect that their evaluation is followed by other code that resets point, but I'm not sure), but you can do what you want using a hook, specifically find-file-hook. All you have to do is create a function that does what you want and add it to the hook. The doc string for find-file-hook says:

List of functions to be called after a buffer is loaded from a file. The buffer’s local variables (if any) will have been processed before the functions are called. This includes directory-local variables, if any, for the file’s directory.

So, although it's not guaranteed, the function will be called later in time than the setting of local variables, so it has a better chance of not having something that runs afterwards undo its work.

Remember also that the functions in the hook are run sequentially, so in order to avoid any of them affecting point, we'll add our function at the end of the hook. Like this:

(defun my/move-to-end ()
   (when (string= (buffer-file-name) "/path/to/desired/file.org")
      (goto-char (point-max)))

(add-hook 'find-file-hook #'my/move-to-end 90)

Setting the depth argument to 90 should put the function at the end of the hook at least for now: if somebody adds another function at the end of the hook with an equal (org bigger) depth, they will win. That's one problem here.

The other problem is that the hook is run on every find-file and we probably don't want point at the end for most files, so we limit my/move-to-end to check whether the file is the one we are interested in before acting.

This should work in almost all cases (see the caveats above for the qualification "almost"). But there is a better way to do it. The idea is to use a local variable setting to change the local value of find-file-hook. Then we don't have to worry about the hook running this function on other files, only on the one(s) where we set the hook locally.

Here's how that goes. The function does not need to worry about what buffer it's called from:

(defun my/move-to-end ()
   (goto-char (point-max)))

Then we add this to the top of the file:

# -*- eval: (add-hook 'find-file-hook #'my/move-to-end 90 t) -*-
#+STARTUP: folded

* foo
lorem ipsum
*bar
lorem ipsum

Then kill the buffer and reopen it with C-x C-f. The t at the end of the add-hook call (see its doc string with C-h v add-hook) says to modify the local value of the hook. So find-file opens the file and evaluates the local variables, thereby running the add-hook call which adds the function to the local value of the hook (do C-h v find-file-hook in the resulting buffer to verify that the local value is just (t my/move-to-end)). Then when the hook is run, the t says "run the global value of the hook" and then it runs my/move-to-end. There is no possibility of anybody sneaking another function at the end of the hook: we get the final word. And since only the local value of the hook is changed, we don't have to complicate the function to check where it is called from.

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.