emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Control help- and Info-mode buffers from other buffers


From: Arthur Miller
Subject: Re: Control help- and Info-mode buffers from other buffers
Date: Sat, 03 Jun 2023 15:53:22 +0200
User-agent: Gnus/5.13 (Gnus v5.13)

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Arthur Miller <arthur.miller@live.com>
>> Cc: juri@linkov.net,  manuel@ledu-giraud.fr,  emacs-devel@gnu.org
>> Date: Fri, 02 Jun 2023 17:09:36 +0200
>> 
>> Eli Zaretskii <eliz@gnu.org> writes:
>> 
>> >> >   (with-selected-window (get-buffer-window "*info*")
>> >> >     BODY...
>> >> No you need a bit more than that sometimes. In case that interactive is 
>> >> doing
>> >> some prompting and buffer dependent setup, you will have to wrap 
>> >> interactive
>> >> body for itself, and function body for itself. See Info-mode or Info-find 
>> >> (I
>> >> think) in patch, but conceptually, yes that is about it. If you can live 
>> >> with
>> >> wrapping commands in with-selected-window. Due to fact that interactive 
>> >> form
>> >> must be the first form in a function body.
>> >
>> > You also have call-interactively, which can work around this minor
>> > obstacle.
>> 
>> Can it? I am talking about interactive "marker" when in defun 
>> impelementation; not
>> calling interactive functions. 
>
> Maybe I don't understand the problem you have in mind.
>
> In any case, whatever the problem is, I'm sure we already have a
> solution for it in gazillion other similar cases.

I like the anser :-), but unfortunately I am affraid I will have to say it is
one of those "fundamental problems". But perhaps I just don't know how to
do it better; see this:

#+begin_src emacs-lisp
(defun Info-menu (menu-item &optional fork)
  "Go to the node pointed to by the menu item named (or abbreviated) MENU-ITEM.
The menu item should one of those listed in the current node's menu.
Completion is allowed, and the default menu item is the one point is on.
If FORK is non-nil (interactively with a prefix arg), show the node in
a new Info buffer.  If FORK is a string, it is the name to use for the
new buffer."
  (interactive
   (let (;; If point is within a menu item, use that item as the default
         (default nil)
         (p (point))
         beg
         (case-fold-search t)
         (mouse-autoselect-window nil)
         (info-window (get-buffer-window "*info*" t)))
     (unless (window-live-p info-window)
       (user-error "There is no visible Info buffer."))
     (setq Info-jump (selected-window))
     (select-window info-window)
     (save-excursion
       (goto-char (point-min))
       (if (not (search-forward "\n* menu:" nil t))
           (user-error "No menu in this node"))
       (setq beg (point))
       (and (< (point) p)
            (save-excursion
              (goto-char p)
              (end-of-line)
              (if (re-search-backward (concat "\n\\* +\\("
                                              Info-menu-entry-name-re
                                              "\\):")
                                      beg t)
                  (setq default (match-string-no-properties 1))))))
     (let ((item nil))
       (while (null item)
         (setq item (let ((completion-ignore-case t)
                          (Info-complete-menu-buffer (current-buffer)))
                      (completing-read (format-prompt "Menu item" default)
                                       #'Info-complete-menu-item nil t nil nil
                                       default))))
       (list item current-prefix-arg)))
   Info-mode)
  ;; there is a problem here in that if several menu items have the same
  ;; name you can only go to the node of the first with this command.
  (let ((info-window (get-buffer-window "*info*" t))
        (mouse-autoselect-window nil))
    (select-window info-window)
    (Info-goto-node (Info-extract-menu-item menu-item)
                    (and fork
                         (if (stringp fork) fork menu-item))))
  (select-window Info-jump))
#+end_src

The interactive form has to be the very first form in a function body, which
makes it impossible to just wrap the entire function  into
with-selected-window. In this case I save selected-window in global var
(Info-jump) and select that window back at the very end of the function. It is
the same effect as if being wrapped into with-selected-window, but unfortunately
it uses a global variable. I don't know how to do it otherwise, if there is a
better way, pleae let me know, I would like to learn how to do it in a better
way if there is one.

However, that is just a side note as answer to your remark, but unfortunately I
have found that there is a bigger problem. I am not sure if it is Emacs or my
X11 window manager, but I do suspect the WM in this case.

I have both in my WM and in Emacs that focus should follow mouse. Now what
happens is that, despite the function jumpiing to correct Emacs window on
another frame, due to cursor being in old frame, all input goes to the old
frame, so at least this particular function does not work with multiple
frames. According to the docs for select-window, both frame to which the window
belongs, and the buffer displaying are made selected/current, so it is probably
my WM spooking. I will try to test with some other WM and to boot into Windows
and test there, but on systems where focus follows the mouse, I guess there is
nothing to do? I suppose the same issue will happen with few other functions
that prompt user for the input via minibuffer. It works well when Info window is
on the same frame of course.

I do have another question too: what is a good strategy if there are multiple 
info
windows open? Prompt user to select with a completing read, or just leave as-is,
i.e. return the first info window?

I have tested all help-mode functions with multiple windows, and there are no
problems there.

thanks for help



reply via email to

[Prev in Thread] Current Thread [Next in Thread]