5

I was wondering if anyone knew of a way to open links to info pages (Emacs manual) from org-mode without changing the current buffer to that info page?

The reason I would like to do this is because I have a list of helpful Emacs info pages in an org file and would like to be able to follow these links without leaving that org file.

Even if I have an info buffer already open in another window, it will just open that buffer in my current window and then follow the link instead of just going to that link using the current info buffer and not changing my current buffer.

It would also be nice to be able to open an info page like a help screen using keybindings, but I would at least like to be able to do this for links.

I have tried playing with org-link-frame-setup but have not been able to get it to work. The following is my current value for that variable in my init file.

;; Attempt to open info files in new windows.
(setq org-link-frame-setup
      '((vm . vm-visit-folder-other-frame)
        (vm-imap . vm-visit-imap-folder-other-frame)
        (gnus . org-gnus-no-new-news)
        (file . find-file-other-window)
        (wl . wl-other-frame)))

I am using "GNU Emacs 26.1 (build 1, x86_64-w64-mingw32) of 2018-05-30"

2

I happened on this old thread as I was trying to figure out the same headache myself, and I thought it worthwhile to share my solution. You can modify the info link handling in a few ways. One method I like is advising the function, but that's not really necessary here. Org-mode (probably like many Emacs components and plugins) is easy enough to extend and reconfigure once you know what you want to do and how.

Prying open the org-mode source code, I found that the [[info:some_cool_topic][Clever Link Name]] links are routed to the org-info-open function via org-link-set-parameters (see source here), which really just calls another function in turn. By routing through our own preparatory function instead, we can modify the behavior however we like. Here's my snippet:

(defun org-info-open-new-window (path)
  "Open info in a new buffer"
  (setq available-windows
        (delete (selected-window) (window-list)))
  (setq new-window
         (or (car available-windows)
             (split-window-sensibly)
             (split-window-right)))
  (select-window new-window)
  (org-info-follow-link path))
(org-link-set-parameters "info" :follow #'org-info-open-new-window)

Someone with more than a week's experience in Elisp could likely write a better function, but that gets the job done without doing anything overly clever. It's also not necessary to have so many options for selecting a new window. We could default to splitting right if there's no other available window, for instance. But split-window-sensibly can fail in some cases, so you need a default in case it comes back with nil.

1
  • Very nice solution! – NickD Nov 26 '20 at 2:16
0

(This doesn't really answer the question, as this is not for links from Org mode -- it is for links within Info itself. But perhaps looking at the code will help.)

Try S-RET (command Info-follow-nearest-node-new-window) or S-mouse-2 (command Info-mouse-follow-nearest-node-new-window) from library info+.el.

That takes you to the node in another window, and if another window already shows that node then it takes you there (doesn't open an additional window for the same node).

0

Yeah... Emacs window behavior can be a real nuisance. It seems there are packages, such as shackle, to help with this, but sometimes I just go the brute force route and make my own function.

Suppose you have the following link:

[[elisp:(info "(org) Tags")]]

To open the link, you press C-o for org-open-at-point. This is really running the underlying code (info "(org) Tags"). It's the info function which is the root of our problem.

If we look at the documentation using C-h f info, we see a link to its source code, info.el. Click on that and it will take you to the definition of info.

(defun info (&optional file-or-node buffer)
  (interactive (list
                (if (and current-prefix-arg (not (numberp current-prefix-arg)))
                    (read-file-name "Info file name: " nil nil t))
                (if (numberp current-prefix-arg)
                    (format "*info*<%s>" current-prefix-arg))))
  (info-setup file-or-node
          (pop-to-buffer-same-window (or buffer "*info*"))))

I'm not going to explain how this function works. You can explore that yourself with C-h v, C-h f, and elisp-search-index. The offending line, however, is pop-to-buffer-same-window (this is a common suspect). The documentation for it states,

Select buffer BUFFER in some window, preferably the same one.

It also gives us a hint for how to fix it:

Unlike ‘pop-to-buffer’, this function prefers using the selected window over popping up a new window or frame.

Let's just create our own function that uses pop-to-buffer instead.

(defun my-info (&optional file-or-node buffer)
  "A hacky reimplementation of `info' which instead opens in the other window."
  (interactive (list
                (if (and current-prefix-arg (not (numberp current-prefix-arg)))
                    (read-file-name "Info file name: " nil nil t))
                (if (numberp current-prefix-arg)
                    (format "*info*<%s>" current-prefix-arg))))
  (info-setup file-or-node
          (pop-to-buffer (or buffer "*info*"))))

Place point after the last parens and execute the function with C-x C-e. Throw the function in your init.el for next time.

Now, we can use the link [[elisp:(my-info "(org) Tags")]] and the info page will open in the other buffer.

Of course, if you share this with anyone else, they'll need my-info.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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