* Proposal: Control help- and Info-mode buffers from other buffers
@ 2023-05-30 12:38 Arthur Miller
0 siblings, 0 replies; only message in thread
From: Arthur Miller @ 2023-05-30 12:38 UTC (permalink / raw)
To: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 587 bytes --]
Previously today I have sent in a proposal and a patch to make help- and
Info-mode "remotely" operable (from other buffers). Unfortunately, I have
discovered som copy-pasta errors, and as well some unnecessary byte-compiler
errors, due to where I placed certain function; I guess I hade those definitions
already in my sessions while I tested. Here is the same patch, but I have
furnitured around some code, fixed copy-pasta in the docs and as well replaced
acronym names I have used for local variables for more self-documenting names.
Sorry for not seeing it in the original patch.
[-- Attachment #2: 0001-Use-help-and-Info-mode-commands-from-any-buffer.patch --]
[-- Type: text/x-patch, Size: 82312 bytes --]
From 04334fe2a97d8f21f684fa2860f343b4a236a391 Mon Sep 17 00:00:00 2001
From: Arthur Miller <arthur.miller@live.com>
Date: Tue, 30 May 2023 14:09:42 +0200
Subject: [PATCH] Use help- and Info-mode commands from any buffer
Allow commands that act on help-mode and Info-mode to be called from other
buffers than just help and Info buffer.
* etc/NEWS: Mention the change.
* doc/emacs/help.texi: Update relevant commands mentioned in the text.
* lisp/help-mode.el (help-jump):
New symbol used for both command and global variable.
Command jumps to/from help window; var records 'jumped from'.
* lisp/help-mode.el (help-view-source):
* lisp/help-mode.el (help-goto-info):
* lisp/help-mode.el (help-go-back):
* lisp/help-mode.el (help-go-forward):
* lisp/help-mode.el (help-goto-next-page):
* lisp/help-mode.el (help-goto-previous-page):
* lisp/help-mode.el (help-goto-lispref-info):
* lisp/help-mode.el (help-customize):
Help-mode commands adapted to be called from any buffer.
* lisp/help-mode.el (help-quit-window):
* lisp/help-mode.el (help-revert-buffer):
* lisp/help-mode.el (help-describe-mode):
* lisp/help-mode.el (help-beginning-of-buffer):
* lisp/help-mode.el (help-end-of-buffer):
* lisp/help-mode.el (help-scroll-up-command):
* lisp/help-mode.el (help-scroll-down-command):
* lisp/help-mode.el (help-forward-button):
* lisp/help-mode.el (help-backward-button):
* lisp/help-mode.el (help-button-describe):
* lisp/help-mode.el (help-push-button):
New commands. Do what they wrapped counterparts without 'help-'
prefix do, but specifically in help buffer.
* lisp/help-mode.el (help-mode-map):
* lisp/help-mode.el (help-mode-menu):
Update bindings to reflect the new commands for previously
generic commands Bind help-jump to 'j' (previously unused).
* lisp/help-mode.el (help-mode-prefix-key):
New defcustom declaration. Prefix key for help-mode-map.
* lisp/info.el (Info-mode-prefix-key):
New defcustom declaration. Prefix key for Info-mode-map.
* lisp/info.el (Info-menu):
* lisp/info.el (Info-next):
* lisp/info.el (Info-prev):
* lisp/info.el (Info-up):
* lisp/info.el (Info-history-back):
* lisp/info.el (Info-history-forward):
* lisp/info.el (Info-directory):
* lisp/info.el (Info-toc):
* lisp/info.el (Info-nth-menu-item):
* lisp/info.el (Info-top-node):
* lisp/info.el (Info-final-node):
* lisp/info.el (Info-forward-node):
* lisp/info.el (Info-backward-node):
* lisp/info.el (Info-next-menu-item):
* lisp/info.el (Info-last-menu-item):
* lisp/info.el (Info-next-preorder):
* lisp/info.el (Info-last-preorder):
* lisp/info.el (Info-scroll-up):
* lisp/info.el (Info-scroll-down):
* lisp/info.el (Info-next-reference):
* lisp/info.el (Info-prev-reference):
* lisp/info.el (Info-index):
* lisp/info.el (Info-index-next):
* lisp/info.el (Info-virtual-next):
* lisp/info.el (Info-apropos):
* lisp/info.el (Info-finder):
* lisp/info.el (Info-summary):
* lisp/info.el (Info-copy-current-node-name):
Info-mode commands adapted to be called from any buffer.
* lisp/info.el (Info-describe-mode):
* lisp/info.el (Info-quit-window):
* lisp/info.el (Info-beginning-of-buffer):
* lisp/info.el (Info-end-of-buffer):
New commands. Do what they wrapped counterparts without 'Info-'
prefix do, but specifically in Info buffer.
* lisp/info.el (Info-jump):
New symbol used for both command and global variable.
Command jumps to/from Info window; var records 'jumped from'.
* lisp/info.el (Info-mode-map):
* lisp/info.el (Info-mode-menu):
Update bindings to reflect the new commands for previously
generic commands Bind Info-jump to 'j' (previously unused).
---
doc/emacs/help.texi | 12 +-
etc/NEWS | 19 +
lisp/help-mode.el | 260 ++++++++--
lisp/info.el | 1156 +++++++++++++++++++++++++------------------
4 files changed, 928 insertions(+), 519 deletions(-)
diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi
index 945e12a05d2..b50905c3dc4 100644
--- a/doc/emacs/help.texi
+++ b/doc/emacs/help.texi
@@ -494,9 +494,9 @@ Help Mode
@item @key{RET}
Follow a cross reference at point (@code{help-follow}).
@item @key{TAB}
-Move point forward to the next hyperlink (@code{forward-button}).
+Move point forward to the next hyperlink (@code{help-forward-button}).
@item S-@key{TAB}
-Move point back to the previous hyperlink (@code{backward-button}).
+Move point back to the previous hyperlink (@code{help-backward-button}).
@item mouse-1
@itemx mouse-2
Follow a hyperlink that you click on.
@@ -544,12 +544,12 @@ Help Mode
(@code{help-go-forward}).
@kindex TAB @r{(Help mode)}
-@findex forward-button
+@findex help-forward-button
@kindex S-TAB @r{(Help mode)}
-@findex backward-button
+@findex help-backward-button
To move between hyperlinks in a help buffer, use @key{TAB}
-(@code{forward-button}) to move forward to the next hyperlink and
-@kbd{S-@key{TAB}} (@code{backward-button}) to move back to the
+(@code{help-forward-button}) to move forward to the next hyperlink and
+@kbd{S-@key{TAB}} (@code{help-backward-button}) to move back to the
previous hyperlink. These commands act cyclically; for instance,
typing @key{TAB} at the last hyperlink moves back to the first
hyperlink.
diff --git a/etc/NEWS b/etc/NEWS
index 3c71e52fff4..fe241d604cb 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -30,6 +30,25 @@ applies, and please also update docstrings as needed.
\f
* Changes in Emacs 30.1
++++
+** New user option 'info-mode-prefix-key.
+Prefix key for `Info-mode-map, so it can be used from other buffer but
+just *info* buffer.
+
+** Commands acting on Info buffer can now be used from any buffer
+Similar to help-mode, keyboard-driven commands acting in Info-mode and
+bound in Info-mode-map can now be used from any buffer (acting on Info
+buffer).
++++
+** New user option 'help-mode-prefix-key'.
+The key is used to assign `help-mode-map' to a prefix, so it can be
+used as a prefix-key from other buffers but just *Help* buffer.
+
+** Commands acting on Help buffer can now be used from any buffer
+This means that all commands that normally required a user to switch
+to *Help* buffer before the invocation, can now be invoked from any
+buffer. With other words, you can now control Help buffer from any
+other buffer, which lessens amount of switching between buffers.
---
** New user option 'describe-bindings-outline-rules'.
This user option controls outline visibility in the output buffer of
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index bf64d032b65..af41686e3fd 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -47,7 +47,22 @@ help-mode-map
"s" #'help-view-source
"I" #'help-goto-lispref-info
"i" #'help-goto-info
- "c" #'help-customize)
+ "j" #'help-jump
+ "c" #'help-customize
+ "g" #'help-revert-buffer
+ "q" #'help-quit-window
+ "<" #'help-beginning-of-buffer
+ ">" #'help-end-of-buffer
+ "h" #'help-describe-mode
+ "?" #'help-describe-mode
+ "DEL" #'help-scroll-down-command
+ "SPC" #'help-scroll-down-command
+ "S-SPC" #'help-scroll-up-command
+ "RET" #'help-push-button
+ "TAB" #'help-forward-button
+ "C-M-i" #'help-backward-button
+ "<backtab>" #'help-backward-button
+ "ESC TAB" #'help-backward-button)
(easy-menu-define help-mode-menu help-mode-map
"Menu for Help mode."
@@ -60,9 +75,9 @@ help-mode-menu
["Next Topic" help-go-forward
:help "Go back to next topic in this help buffer"
:active help-xref-forward-stack]
- ["Move to Previous Button" backward-button
+ ["Move to Previous Button" help-backward-button
:help "Move to the Previous Button in the help buffer"]
- ["Move to Next Button" forward-button
+ ["Move to Next Button" help-forward-button
:help "Move to the Next Button in the help buffer"]
["View Source" help-view-source
:help "Go to the source file for the current help item"]
@@ -150,6 +165,22 @@ help-mode-hook
"Hook run by `help-mode'."
:type 'hook
:group 'help)
+
+;; with a little help from Helm
+(defcustom help-mode-prefix-key "C-h M-h"
+ "`help-mode-map' prefix key for invocation from other buffers."
+ :version "30.1"
+ :type '(choice (string :tag "Key") (const :tag "no binding"))
+ :set (lambda (var key)
+ (when (and (boundp var) (symbol-value var))
+ (define-key (current-global-map)
+ (read-kbd-macro (symbol-value var)) nil))
+ (when key
+ (define-key (current-global-map)
+ (read-kbd-macro key)
+ help-mode-map))
+ (set var key))
+ :group 'help)
\f
;; Button types used by help
@@ -763,7 +794,127 @@ help-xref-on-pp
;;;###autoload
(define-obsolete-function-alias 'help-xref-interned #'describe-symbol "25.1")
+\f
+;; commands from special-mode wrapped to work on help-mode only
+
+(defun help-quit-window ()
+ "As `quit-window' but works only on *Help* buffer."
+ (interactive)
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (user-error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (quit-window nil help-window))))
+
+(defun help-describe-mode ()
+ "As `describe-mode' but for *Help* buffer only."
+ (interactive)
+ (let ((help-buffer (get-buffer (help-buffer))))
+ (unless (window-live-p (get-buffer-window help-buffer))
+ (user-error "Help buffer is not currently visible."))
+ (describe-mode help-buffer)))
+
+(defun help-beginning-of-buffer ()
+ "As `help-beginning-of-buffer' but for *Help* buffer only."
+ (interactive)
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (user-error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (goto-char (point-min)))))
+
+(defun help-end-of-buffer ()
+ "As `help-end-of-buffer' but for *Help* buffer only."
+ (interactive)
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (user-error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (goto-char (point-max)))))
+\f
+;; from files.el, for completeness and to eliminate potential confusion
+(defun help-revert-buffer ()
+ "As `revert-buffer', but act on help buffer specifically."
+ (interactive)
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (user-error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (call-interactively #'revert-buffer))))
+\f
+;; Commands from button.el wrapped to work on help-mode only
+
+(defun help-forward-button ()
+ (interactive)
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (user-error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (forward-button 1))))
+
+(defun help-backward-button ()
+ (interactive)
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (user-error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (backward-button 1))))
+
+(defun help-button-describe ()
+ (interactive)
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (user-error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (button-describe))))
+
+(defun help-push-button ()
+ (interactive)
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (push-button))))
+\f
+;; Commands from window.el wrapped to work on help-mode only
+
+(defun help-scroll-up-command (&optional arg)
+ "As `scroll-up-command' but works only on *Help* buffer."
+ (interactive "^P")
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (scroll-up-command arg))))
+
+(defun help-scroll-down-command (&optional arg)
+ "As `scroll-down-command' but works only on *Help* buffer."
+ (interactive "^P")
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (user-error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (scroll-down-command arg))))
+
+\f
+
+(defvar help-jump nil)
+(defun help-jump ()
+ "Jump to and from *Help* window."
+ (interactive)
+ (let ((help-window (get-buffer-window (help-buffer)))
+ (current-window (selected-window)))
+ (cond
+ ((eq help-window current-window)
+ (unless help-jump
+ (user-error "No previously selected window to jump to."))
+ (select-window help-jump))
+ (t
+ (unless (window-live-p help-window)
+ (user-error "Help buffer is not currently visible."))
+ (setq help-jump current-window)
+ (select-window help-window)))))
\f
;; Navigation/hyperlinking with xrefs
@@ -810,25 +961,37 @@ help-xref-go-forward
(defun help-go-back ()
"Go back to previous topic in this help buffer."
(interactive)
- (if help-xref-stack
- (help-xref-go-back (current-buffer))
- (user-error "No previous help buffer")))
+ (let ((help-buffer (get-buffer (help-buffer))))
+ (unless (window-live-p (get-buffer-window help-buffer))
+ (user-error "Help buffer is not currently visible."))
+ (with-current-buffer help-buffer
+ (if help-xref-stack
+ (help-xref-go-back (current-buffer))
+ (user-error "No previous help buffer")))))
(defun help-go-forward ()
"Go to the next topic in this help buffer."
(interactive)
- (if help-xref-forward-stack
- (help-xref-go-forward (current-buffer))
- (user-error "No next help buffer")))
+ (let ((help-buffer (get-buffer (help-buffer))))
+ (unless (window-live-p (get-buffer-window help-buffer))
+ (user-error "Help buffer is not currently visible."))
+ (with-current-buffer help-buffer
+ (if help-xref-forward-stack
+ (help-xref-go-forward (current-buffer))
+ (user-error "No next help buffer")))))
(defun help-goto-next-page ()
"Go to the next page (if any) in the current buffer.
The help buffers are divided into \"pages\" by the ^L character."
(interactive nil help-mode)
- (push-mark)
- (forward-page)
- (unless (eobp)
- (forward-line 1)))
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (user-error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (push-mark)
+ (forward-page)
+ (unless (eobp)
+ (forward-line 1)))))
(defun help-goto-previous-page ()
"Go to the previous page (if any) in the current buffer.
@@ -836,47 +999,68 @@ help-goto-previous-page
The help buffers are divided into \"pages\" by the ^L character."
(interactive nil help-mode)
- (push-mark)
- (backward-page (if (looking-back "\f\n" (- (point) 5)) 2 1))
- (unless (bobp)
- (forward-line 1)))
+ (let ((help-window (get-buffer-window (help-buffer))))
+ (unless (window-live-p help-window)
+ (user-error "Help buffer is not currently visible."))
+ (with-selected-window help-window
+ (push-mark)
+ (backward-page (if (looking-back "\f\n" (- (point) 5)) 2 1))
+ (unless (bobp)
+ (forward-line 1)))))
(defun help-view-source ()
"View the source of the current help item."
(interactive nil help-mode)
- (unless (plist-get help-mode--current-data :file)
- (error "Source file for the current help item is not defined"))
- (help-function-def--button-function
- (plist-get help-mode--current-data :symbol)
- (plist-get help-mode--current-data :file)
- (plist-get help-mode--current-data :type)))
+ (let ((help-buffer (get-buffer (help-buffer))))
+ (unless (window-live-p (get-buffer-window help-buffer))
+ (user-error "Help buffer is not currently visible."))
+ (with-current-buffer help-buffer
+ (unless (plist-get help-mode--current-data :file)
+ (error "Source file for the current help item is not defined"))
+ (help-function-def--button-function
+ (plist-get help-mode--current-data :symbol)
+ (plist-get help-mode--current-data :file)
+ (plist-get help-mode--current-data :type)))))
(defun help-goto-info ()
"View the *info* node of the current help item."
(interactive nil help-mode)
- (unless help-mode--current-data
- (error "No symbol to look up in the current buffer"))
- (info-lookup-symbol (plist-get help-mode--current-data :symbol)
- 'emacs-lisp-mode
- help-window-keep-selected))
+ (let ((help-buffer (get-buffer (help-buffer))))
+ (unless (window-live-p (get-buffer-window help-buffer))
+ (user-error "Help buffer is not currently visible."))
+ (with-current-buffer help-buffer
+ (unless help-mode--current-data
+ (error "No symbol to look up in the current buffer"))
+ (with-selected-window (get-buffer-window help-buffer)
+ (info-lookup-symbol (plist-get help-mode--current-data :symbol)
+ 'emacs-lisp-mode
+ help-window-keep-selected)))))
(defun help-goto-lispref-info ()
"View the Emacs Lisp manual *info* node of the current help item."
(interactive nil help-mode)
- (unless help-mode--current-data
- (error "No symbol to look up in the current buffer"))
- (info-lookup-symbol (plist-get help-mode--current-data :symbol)
- 'emacs-lisp-only))
+ (let ((help-buffer (get-buffer (help-buffer))))
+ (unless (window-live-p (get-buffer-window help-buffer))
+ (user-error "Help buffer is not currently visible."))
+ (with-current-buffer help-buffer
+ (unless help-mode--current-data
+ (error "No symbol to look up in the current buffer"))
+ (info-lookup-symbol (plist-get help-mode--current-data :symbol)
+ 'emacs-lisp-only))))
(defun help-customize ()
"Customize variable or face whose doc string is shown in the current buffer."
(interactive nil help-mode)
- (let ((sym (plist-get help-mode--current-data :symbol)))
- (unless (or (boundp sym) (facep sym))
- (user-error "No variable or face to customize"))
- (cond
- ((boundp sym) (customize-variable sym))
- ((facep sym) (customize-face sym)))))
+ (let ((help-buffer (get-buffer (help-buffer))))
+ (unless (window-live-p (get-buffer-window help-buffer))
+ (user-error "Help buffer is not currently visible."))
+ (with-current-buffer help-buffer
+ (let ((sym (plist-get help-mode--current-data :symbol)))
+ (unless (or (boundp sym) (facep sym))
+ (user-error "No variable or face to customize"))
+ (cond
+ ((boundp sym) (customize-variable sym))
+ ((facep sym) (customize-face sym)))))))
(defun help-do-xref (_pos function args)
"Call the help cross-reference function FUNCTION with args ARGS.
diff --git a/lisp/info.el b/lisp/info.el
index 035dff66e75..dcc6ed667d8 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -819,6 +819,22 @@ info-standalone
(save-buffers-kill-emacs)))
(info)))
\f
+(defvar Info-jump nil)
+(defun Info-jump ()
+ "Jump to and from *info* window."
+ (interactive)
+ (let ((info-window (get-buffer-window "*info*"))
+ (current-window (selected-window)))
+ (cond
+ ((eq info-window (selected-window))
+ (unless Info-jump
+ (error "No previously selected window to jump to."))
+ (select-window Info-jump))
+ (t
+ (when (window-live-p info-window)
+ (setq Info-jump current-window)
+ (select-window info-window))))))
+\f
;; See if the accessible portion of the buffer begins with a node
;; delimiter, and the node header line which follows matches REGEXP.
;; Typically, this test will be followed by a loop that examines the
@@ -831,12 +847,12 @@ info-standalone
;; The return value is the value of point at the beginning of matching
;; REGEXP, if the function succeeds, nil otherwise.
(defun Info-node-at-bob-matching (regexp)
- (and (bobp) ; are we at beginning of buffer?
- (looking-at "\^_") ; does it begin with node delimiter?
+ (and (bobp) ; are we at beginning of buffer?
+ (looking-at "\^_") ; does it begin with node delimiter?
(let (beg)
(forward-line 1)
(setq beg (point))
- (forward-line 1) ; does the line after delimiter match REGEXP?
+ (forward-line 1) ; does the line after delimiter match REGEXP?
(re-search-backward regexp beg t))))
(defun Info-find-file (filename &optional noerror no-pop-to-dir)
@@ -2273,85 +2289,108 @@ Info-next
"Go to the \"next\" node, staying on the same hierarchical level.
This command doesn't descend into sub-nodes, like \\<Info-mode-map>\\[Info-forward-node] does."
(interactive nil Info-mode)
- ;; In case another window is currently selected
- (save-window-excursion
- (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
- (Info-goto-node (Info-extract-pointer "next"))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ ;; In case another window is currently selected
+ (save-window-excursion
+ (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
+ (Info-goto-node (Info-extract-pointer "next")))))
(defun Info-prev ()
"Go to the \"previous\" node, staying on the same hierarchical level.
This command doesn't go up to the parent node, like \\<Info-mode-map>\\[Info-backward-node] does."
(interactive nil Info-mode)
- ;; In case another window is currently selected
- (save-window-excursion
- (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
- (Info-goto-node (Info-extract-pointer "prev[ious]*" "previous"))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ ;; In case another window is currently selected
+ (save-window-excursion
+ (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
+ (Info-goto-node (Info-extract-pointer "prev[ious]*" "previous"))
+ ;; for some reason my Emacs does not update correctly info buffer after
+ ;; going back to a previous node, reverting buffer fixes it
+ (revert-buffer t t t))))
(defun Info-up (&optional same-file)
"Go to the superior node of this node.
If SAME-FILE is non-nil, do not move to a different Info file."
(interactive nil Info-mode)
- ;; In case another window is currently selected
- (save-window-excursion
- (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
- (let ((old-node Info-current-node)
- (old-file Info-current-file)
- (node (Info-extract-pointer "up")) p)
- (and same-file
- (string-match "^(" node)
- (error "Up node is in another Info file"))
- (Info-goto-node node)
- (setq p (point))
- (goto-char (point-min))
- (if (and (stringp old-file)
- (search-forward "\n* Menu:" nil t)
- (re-search-forward
- (if (string-equal old-node "Top")
- (concat "\n\\*[^:]+: +(" (file-name-nondirectory old-file) ")")
- (concat "\n\\* +\\(" (regexp-quote old-node)
- ":\\|[^:]+: +" (regexp-quote old-node) "\\)"))
- nil t))
- (progn (beginning-of-line) (if (looking-at "^\\* ") (forward-char 2)))
- (goto-char p)
- (Info-restore-point Info-history))))
- ;; If scroll-conservatively is non-zero and less than 101, display
- ;; as much of the superior node above the target line as possible.
- (when (< 0 scroll-conservatively 101)
- (recenter)))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ ;; In case another window is currently selected
+ (save-window-excursion
+ (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
+ (let ((old-node Info-current-node)
+ (old-file Info-current-file)
+ (node (Info-extract-pointer "up")) p)
+ (and same-file
+ (string-match "^(" node)
+ (error "Up node is in another Info file"))
+ (Info-goto-node node)
+ (setq p (point))
+ (goto-char (point-min))
+ (if (and (stringp old-file)
+ (search-forward "\n* Menu:" nil t)
+ (re-search-forward
+ (if (string-equal old-node "Top")
+ (concat "\n\\*[^:]+: +(" (file-name-nondirectory old-file) ")")
+ (concat "\n\\* +\\(" (regexp-quote old-node)
+ ":\\|[^:]+: +" (regexp-quote old-node) "\\)"))
+ nil t))
+ (progn (beginning-of-line) (if (looking-at "^\\* ") (forward-char 2)))
+ (goto-char p)
+ (Info-restore-point Info-history)))
+ ;; If scroll-conservatively is non-zero and less than 101, display
+ ;; as much of the superior node above the target line as possible.
+ ;; (when (< 0 scroll-conservatively 101) (recenter))
+ ;; for some reason, in my Emacs, this is the only obe that actually
+ ;; displays correctly, recentering leavs last line at the top
+ (revert-buffer t t t)))))
(defun Info-history-back ()
"Go back in the history to the last node visited."
(interactive nil Info-mode)
- (or Info-history
- (user-error "This is the first Info node you looked at"))
- (let ((history-forward
- (cons (list Info-current-file Info-current-node (point))
- Info-history-forward))
- filename nodename opoint)
- (setq filename (car (car Info-history)))
- (setq nodename (car (cdr (car Info-history))))
- (setq opoint (car (cdr (cdr (car Info-history)))))
- (setq Info-history (cdr Info-history))
- (Info-find-node filename nodename)
- (setq Info-history (cdr Info-history))
- (setq Info-history-forward history-forward)
- (goto-char opoint)))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (or Info-history
+ (user-error "This is the first Info node you looked at"))
+ (let ((history-forward
+ (cons (list Info-current-file Info-current-node (point))
+ Info-history-forward))
+ filename nodename opoint)
+ (setq filename (car (car Info-history)))
+ (setq nodename (car (cdr (car Info-history))))
+ (setq opoint (car (cdr (cdr (car Info-history)))))
+ (setq Info-history (cdr Info-history))
+ (Info-find-node filename nodename)
+ (setq Info-history (cdr Info-history))
+ (setq Info-history-forward history-forward)
+ (goto-char opoint)))))
(defalias 'Info-last 'Info-history-back)
(defun Info-history-forward ()
"Go forward in the history of visited nodes."
(interactive nil Info-mode)
- (or Info-history-forward
- (user-error "This is the last Info node you looked at"))
- (let ((history-forward (cdr Info-history-forward))
- filename nodename opoint)
- (setq filename (car (car Info-history-forward)))
- (setq nodename (car (cdr (car Info-history-forward))))
- (setq opoint (car (cdr (cdr (car Info-history-forward)))))
- (Info-find-node filename nodename)
- (setq Info-history-forward history-forward)
- (goto-char opoint)))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (or Info-history-forward
+ (user-error "This is the last Info node you looked at"))
+ (let ((history-forward (cdr Info-history-forward))
+ filename nodename opoint)
+ (setq filename (car (car Info-history-forward)))
+ (setq nodename (car (cdr (car Info-history-forward))))
+ (setq opoint (car (cdr (cdr (car Info-history-forward)))))
+ (Info-find-node filename nodename)
+ (setq Info-history-forward history-forward)
+ (goto-char opoint)))))
\f
(add-to-list 'Info-virtual-files
'("\\`dir\\'"
@@ -2377,7 +2416,11 @@ Info-directory-find-node
(defun Info-directory ()
"Go to the Info directory node."
(interactive)
- (Info-find-node "dir" "top"))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (Info-find-node "dir" "top"))))
\f
(add-to-list 'Info-virtual-files
'("\\`\\*History\\*\\'"
@@ -2416,9 +2459,13 @@ Info-history-find-node
(defun Info-history ()
"Go to a node with a menu of visited nodes."
(interactive nil Info-mode)
- (Info-find-node "*History*" "Top")
- (Info-next-reference)
- (Info-next-reference))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (Info-find-node "*History*" "Top")
+ (Info-next-reference)
+ (Info-next-reference))))
\f
(add-to-list 'Info-virtual-nodes
'("\\`\\*TOC\\*\\'"
@@ -2453,12 +2500,16 @@ Info-toc
"Go to a node with table of contents of the current Info file.
Table of contents is created from the tree structure of menus."
(interactive nil Info-mode)
- (Info-find-node Info-current-file "*TOC*")
- (let ((prev-node (nth 1 (car Info-history))) p)
- (goto-char (point-min))
- (if (setq p (search-forward (concat "*Note " prev-node ":") nil t))
- (setq p (- p (length prev-node) 2)))
- (goto-char (or p (point-min)))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (Info-find-node Info-current-file "*TOC*")
+ (let ((prev-node (nth 1 (car Info-history))) p)
+ (goto-char (point-min))
+ (if (setq p (search-forward (concat "*Note " prev-node ":") nil t))
+ (setq p (- p (length prev-node) 2)))
+ (goto-char (or p (point-min)))))))
(defun Info-toc-insert (nodes node-list level curr-file)
"Insert table of contents with references to nodes."
@@ -2798,38 +2849,45 @@ Info-menu
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))
+ (default nil)
+ (p (point))
+ beg
+ (case-fold-search t)
+ (info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (if (not (eq (selected-window) info-window))
+ (Info-jump)
+ (setq Info-jump nil))
(save-excursion
(goto-char (point-min))
(if (not (search-forward "\n* menu:" nil t))
- (user-error "No menu in this node"))
+ (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
- "\\):")
+ (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))))))
+ (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
+ (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.
(Info-goto-node (Info-extract-menu-item menu-item)
- (and fork
- (if (stringp fork) fork menu-item))))
+ (and fork
+ (if (stringp fork) fork menu-item)))
+ (when Info-jump (Info-jump)))
(defun Info-extract-menu-item (menu-item)
(setq menu-item (regexp-quote menu-item))
@@ -2869,32 +2927,44 @@ Info-nth-menu-item
"Go to the node of the Nth menu item.
N is the digit argument used to invoke this command."
(interactive nil Info-mode)
- (Info-goto-node
- (Info-extract-menu-counting
- (- (aref (this-command-keys) (1- (length (this-command-keys)))) ?0))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (Info-goto-node
+ (Info-extract-menu-counting
+ (- (aref (this-command-keys) (1- (length (this-command-keys)))) ?0))))))
(defun Info-top-node ()
"Go to the Top node of this file."
(interactive nil Info-mode)
- (Info-goto-node "Top"))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (Info-goto-node "Top"))))
(defun Info-final-node ()
"Go to the final node in this file."
(interactive nil Info-mode)
- (Info-goto-node "Top")
- (let ((Info-history nil)
- (case-fold-search t))
- ;; Go to the last node in the menu of Top. But don't delve into
- ;; detailed node listings.
- (Info-goto-node (Info-extract-menu-counting nil t))
- ;; If the last node in the menu is not last in pointer structure,
- ;; move forward (but not down- or upward - see bug#1116) until we
- ;; can't go any farther.
- (while (Info-forward-node t t t) nil)
- ;; Then keep moving down to last subnode, unless we reach an index.
- (while (and (not (Info-index-node))
- (save-excursion (search-forward "\n* Menu:" nil t)))
- (Info-goto-node (Info-extract-menu-counting nil)))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (Info-goto-node "Top")
+ (let ((Info-history nil)
+ (case-fold-search t))
+ ;; Go to the last node in the menu of Top. But don't delve into
+ ;; detailed node listings.
+ (Info-goto-node (Info-extract-menu-counting nil t))
+ ;; If the last node in the menu is not last in pointer structure,
+ ;; move forward (but not down- or upward - see bug#1116) until we
+ ;; can't go any farther.
+ (while (Info-forward-node t t t) nil)
+ ;; Then keep moving down to last subnode, unless we reach an index.
+ (while (and (not (Info-index-node))
+ (save-excursion (search-forward "\n* Menu:" nil t)))
+ (Info-goto-node (Info-extract-menu-counting nil)))))))
(defun Info-forward-node (&optional not-down not-up no-error)
"Go forward one node, considering all nodes as forming one sequence.
@@ -2905,66 +2975,76 @@ Info-forward-node
NOT-UP non-nil means don't go to parent nodes, and NO-ERROR non-nil means
don't signal a user-error if there's no node to go to."
(interactive nil Info-mode)
- (goto-char (point-min))
- (forward-line 1)
- (let ((case-fold-search t))
- ;; three possibilities, in order of priority:
- ;; 1. next node is in a menu in this node (but not in an index)
- ;; 2. next node is next at same level
- ;; 3. next node is up and next
- (cond ((and (not not-down)
- (save-excursion (search-forward "\n* menu:" nil t))
- (not (Info-index-node)))
- (Info-goto-node (Info-extract-menu-counting 1))
- t)
- ((save-excursion (search-backward "next:" nil t))
- (Info-next)
- t)
- ((and (not not-up)
- (save-excursion (search-backward "up:" nil t))
- ;; Use string-equal, not equal, to ignore text props.
- (not (string-equal (downcase (Info-extract-pointer "up"))
- "top")))
- (let ((old-node Info-current-node))
- (Info-up)
- (let ((old-history Info-history)
- success)
- (unwind-protect
- (setq success (Info-forward-node t nil no-error))
- (or success (Info-goto-node old-node)))
- (if Info-history-skip-intermediate-nodes
- (setq Info-history old-history)))))
- (no-error nil)
- (t (user-error "No pointer forward from this node")))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (goto-char (point-min))
+ (forward-line 1)
+ (let ((case-fold-search t))
+ ;; three possibilities, in order of priority:
+ ;; 1. next node is in a menu in this node (but not in an index)
+ ;; 2. next node is next at same level
+ ;; 3. next node is up and next
+ (cond ((and (not not-down)
+ (save-excursion (search-forward "\n* menu:" nil t))
+ (not (Info-index-node)))
+ (Info-goto-node (Info-extract-menu-counting 1))
+ t)
+ ((save-excursion (search-backward "next:" nil t))
+ (Info-next)
+ t)
+ ((and (not not-up)
+ (save-excursion (search-backward "up:" nil t))
+ ;; Use string-equal, not equal, to ignore text props.
+ (not (string-equal (downcase (Info-extract-pointer "up"))
+ "top")))
+ (let ((old-node Info-current-node))
+ (Info-up)
+ (let ((old-history Info-history)
+ success)
+ (unwind-protect
+ (setq success (Info-forward-node t nil no-error))
+ (or success (Info-goto-node old-node)))
+ (if Info-history-skip-intermediate-nodes
+ (setq Info-history old-history)))))
+ (no-error nil)
+ (t (user-error "No pointer forward from this node")))))))
(defun Info-backward-node ()
"Go backward one node, considering all nodes as forming one sequence.
If the current node has a \"previous\" node, go to it, descending into its
last sub-node, if any; otherwise go \"up\" to the parent node."
(interactive nil Info-mode)
- (let ((prevnode (Info-extract-pointer "prev[ious]*" t))
- (upnode (Info-extract-pointer "up" t))
- (case-fold-search t))
- (cond ((and upnode (string-search "(" upnode))
- (user-error "First node in file"))
- ((and upnode (or (null prevnode)
- ;; Use string-equal, not equal,
- ;; to ignore text properties.
- (string-equal (downcase prevnode)
- (downcase upnode))))
- (Info-up))
- (prevnode
- ;; If we move back at the same level,
- ;; go down to find the last subnode*.
- (Info-prev)
- (let ((old-history Info-history))
- (while (and (not (Info-index-node))
- (save-excursion (search-forward "\n* Menu:" nil t)))
- (Info-goto-node (Info-extract-menu-counting nil)))
- (if Info-history-skip-intermediate-nodes
- (setq Info-history old-history))))
- (t
- (user-error "No pointer backward from this node")))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (let ((prevnode (Info-extract-pointer "prev[ious]*" t))
+ (upnode (Info-extract-pointer "up" t))
+ (case-fold-search t))
+ (cond ((and upnode (string-search "(" upnode))
+ (user-error "First node in file"))
+ ((and upnode (or (null prevnode)
+ ;; Use string-equal, not equal,
+ ;; to ignore text properties.
+ (string-equal (downcase prevnode)
+ (downcase upnode))))
+ (Info-up))
+ (prevnode
+ ;; If we move back at the same level,
+ ;; go down to find the last subnode*.
+ (Info-prev)
+ (let ((old-history Info-history))
+ (while (and (not (Info-index-node))
+ (save-excursion (search-forward "\n* Menu:" nil t)))
+ (Info-goto-node (Info-extract-menu-counting nil)))
+ (if Info-history-skip-intermediate-nodes
+ (setq Info-history old-history))))
+ (t
+ (user-error "No pointer backward from this node")))
+ ;; Emacs sometimes display just the very last line
+ (goto-char (point-min))))))
(define-obsolete-function-alias 'Info-exit #'quit-window "27.1")
@@ -2972,31 +3052,39 @@ Info-next-menu-item
"Go to the node of the next menu item."
(interactive nil Info-mode)
;; Bind this in case the user sets it to nil.
- (let* ((case-fold-search t)
- (node
- (save-excursion
- (forward-line -1)
- (search-forward "\n* menu:" nil t)
- (and (search-forward "\n* " nil t)
- (Info-extract-menu-node-name)))))
- (if node (Info-goto-node node)
- (user-error "No more items in menu"))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (let* ((case-fold-search t)
+ (node
+ (save-excursion
+ (forward-line -1)
+ (search-forward "\n* menu:" nil t)
+ (and (search-forward "\n* " nil t)
+ (Info-extract-menu-node-name)))))
+ (if node (Info-goto-node node)
+ (user-error "No more items in menu"))))))
(defun Info-last-menu-item ()
"Go to the node of the previous menu item."
(interactive nil Info-mode)
- (save-excursion
- (forward-line 1)
- ;; Bind this in case the user sets it to nil.
- (let* ((case-fold-search t)
- (beg (save-excursion
- (and (search-backward "\n* menu:" nil t)
- (point)))))
- (or (and beg (search-backward "\n* " beg t))
- (user-error "No previous items in menu")))
- (Info-goto-node (save-excursion
- (goto-char (match-end 0))
- (Info-extract-menu-node-name)))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (save-excursion
+ (forward-line 1)
+ ;; Bind this in case the user sets it to nil.
+ (let* ((case-fold-search t)
+ (beg (save-excursion
+ (and (search-backward "\n* menu:" nil t)
+ (point)))))
+ (or (and beg (search-backward "\n* " beg t))
+ (user-error "No previous items in menu")))
+ (Info-goto-node (save-excursion
+ (goto-char (match-end 0))
+ (Info-extract-menu-node-name)))))))
(defmacro Info-no-error (&rest body)
`(condition-case nil (progn ,@body t) (error nil)))
@@ -3004,61 +3092,69 @@ Info-no-error
(defun Info-next-preorder ()
"Go to the next subnode or the next node, or go up a level."
(interactive nil Info-mode)
- (cond ((Info-no-error (Info-next-menu-item)))
- ((Info-no-error (Info-next)))
- ((Info-no-error (Info-up t))
- ;; Since we have already gone thru all the items in this menu,
- ;; go up to the end of this node.
- (goto-char (point-max))
- ;; Since logically we are done with the node with that menu,
- ;; move on from it. But don't add intermediate nodes
- ;; to the history on recursive calls.
- (let ((old-history Info-history))
- (Info-next-preorder)
- (if Info-history-skip-intermediate-nodes
- (setq Info-history old-history))))
- (t
- (user-error "No more nodes"))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (cond ((Info-no-error (Info-next-menu-item)))
+ ((Info-no-error (Info-next)))
+ ((Info-no-error (Info-up t))
+ ;; Since we have already gone thru all the items in this menu,
+ ;; go up to the end of this node.
+ (goto-char (point-max))
+ ;; Since logically we are done with the node with that menu,
+ ;; move on from it. But don't add intermediate nodes
+ ;; to the history on recursive calls.
+ (let ((old-history Info-history))
+ (Info-next-preorder)
+ (if Info-history-skip-intermediate-nodes
+ (setq Info-history old-history))))
+ (t
+ (user-error "No more nodes"))))))
(defun Info-last-preorder ()
"Go to the last node, popping up a level if there is none."
(interactive nil Info-mode)
- (cond ((and Info-scroll-prefer-subnodes
- (Info-no-error
- (Info-last-menu-item)
- ;; If we go down a menu item, go to the end of the node
- ;; so we can scroll back through it.
- (goto-char (point-max))))
- ;; Keep going down, as long as there are nested menu nodes.
- (let ((old-history Info-history))
- (while (Info-no-error
- (Info-last-menu-item)
- ;; If we go down a menu item, go to the end of the node
- ;; so we can scroll back through it.
- (goto-char (point-max))))
- (if Info-history-skip-intermediate-nodes
- (setq Info-history old-history)))
- (recenter -1))
- ((and (Info-no-error (Info-extract-pointer "prev"))
- (not (equal (Info-extract-pointer "up")
- (Info-extract-pointer "prev"))))
- (Info-no-error (Info-prev))
- (goto-char (point-max))
- (let ((old-history Info-history))
- (while (Info-no-error
- (Info-last-menu-item)
- ;; If we go down a menu item, go to the end of the node
- ;; so we can scroll back through it.
- (goto-char (point-max))))
- (if Info-history-skip-intermediate-nodes
- (setq Info-history old-history)))
- (recenter -1))
- ((Info-no-error (Info-up t))
- (goto-char (point-min))
- (let ((case-fold-search t))
- (or (search-forward "\n* Menu:" nil t)
- (goto-char (point-max)))))
- (t (user-error "No previous nodes"))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (cond ((and Info-scroll-prefer-subnodes
+ (Info-no-error
+ (Info-last-menu-item)
+ ;; If we go down a menu item, go to the end of the node
+ ;; so we can scroll back through it.
+ (goto-char (point-max))))
+ ;; Keep going down, as long as there are nested menu nodes.
+ (let ((old-history Info-history))
+ (while (Info-no-error
+ (Info-last-menu-item)
+ ;; If we go down a menu item, go to the end of the node
+ ;; so we can scroll back through it.
+ (goto-char (point-max))))
+ (if Info-history-skip-intermediate-nodes
+ (setq Info-history old-history)))
+ (recenter -1))
+ ((and (Info-no-error (Info-extract-pointer "prev"))
+ (not (equal (Info-extract-pointer "up")
+ (Info-extract-pointer "prev"))))
+ (Info-no-error (Info-prev))
+ (goto-char (point-max))
+ (let ((old-history Info-history))
+ (while (Info-no-error
+ (Info-last-menu-item)
+ ;; If we go down a menu item, go to the end of the node
+ ;; so we can scroll back through it.
+ (goto-char (point-max))))
+ (if Info-history-skip-intermediate-nodes
+ (setq Info-history old-history)))
+ (recenter -1))
+ ((Info-no-error (Info-up t))
+ (goto-char (point-min))
+ (let ((case-fold-search t))
+ (or (search-forward "\n* Menu:" nil t)
+ (goto-char (point-max)))))
+ (t (user-error "No previous nodes"))))))
(defun Info-scroll-up ()
"Scroll one screenful forward in Info, considering all nodes as one sequence.
@@ -3075,23 +3171,27 @@ Info-scroll-up
in other ways.)"
(interactive nil Info-mode)
- (if (or (< (window-start) (point-min))
- (> (window-start) (point-max)))
- (set-window-start (selected-window) (point)))
- (let* ((case-fold-search t)
- (virtual-end (save-excursion
- (goto-char (point-min))
- (if (and Info-scroll-prefer-subnodes
- (search-forward "\n* Menu:" nil t))
- (point)
- (point-max)))))
- (if (or (< virtual-end (window-start))
- (pos-visible-in-window-p virtual-end))
- (cond
- (Info-scroll-prefer-subnodes (Info-next-preorder))
- ((Info-no-error (Info-goto-node (Info-extract-menu-counting 1))))
- (t (Info-next-preorder)))
- (scroll-up))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (if (or (< (window-start) (point-min))
+ (> (window-start) (point-max)))
+ (set-window-start (selected-window) (point)))
+ (let* ((case-fold-search t)
+ (virtual-end (save-excursion
+ (goto-char (point-min))
+ (if (and Info-scroll-prefer-subnodes
+ (search-forward "\n* Menu:" nil t))
+ (point)
+ (point-max)))))
+ (if (or (< virtual-end (window-start))
+ (pos-visible-in-window-p virtual-end))
+ (cond
+ (Info-scroll-prefer-subnodes (Info-next-preorder))
+ ((Info-no-error (Info-goto-node (Info-extract-menu-counting 1))))
+ (t (Info-next-preorder)))
+ (scroll-up))))))
(defun Info-mouse-scroll-up (e)
"Scroll one screenful forward in Info, using the mouse.
@@ -3109,21 +3209,25 @@ Info-scroll-down
beginning of a node, that goes to the previous node or back up to the
parent node."
(interactive nil Info-mode)
- (if (or (< (window-start) (point-min))
- (> (window-start) (point-max)))
- (set-window-start (selected-window) (point)))
- (let* ((case-fold-search t)
- (current-point (point))
- (virtual-end
- (and Info-scroll-prefer-subnodes
- (save-excursion
- (setq current-point (line-beginning-position))
- (goto-char (point-min))
- (search-forward "\n* Menu:" current-point t)))))
- (if (or virtual-end
- (pos-visible-in-window-p (point-min) nil t))
- (Info-last-preorder)
- (scroll-down))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (if (or (< (window-start) (point-min))
+ (> (window-start) (point-max)))
+ (set-window-start (selected-window) (point)))
+ (let* ((case-fold-search t)
+ (current-point (point))
+ (virtual-end
+ (and Info-scroll-prefer-subnodes
+ (save-excursion
+ (setq current-point (line-beginning-position))
+ (goto-char (point-min))
+ (search-forward "\n* Menu:" current-point t)))))
+ (if (or virtual-end
+ (pos-visible-in-window-p (point-min) nil t))
+ (Info-last-preorder)
+ (scroll-down))))))
(defun Info-mouse-scroll-down (e)
"Scroll one screenful backward in Info, using the mouse.
@@ -3175,55 +3279,63 @@ Info-next-reference
If COUNT is non-nil (interactively with a prefix arg), jump over
COUNT cross-references."
(interactive "i\np" Info-mode)
- (unless count
- (setq count 1))
- (if (< count 0)
- (Info-prev-reference recur (- count))
- (while (unless (zerop count) (setq count (1- count)))
- (let ((pat "\\*note[ \n\t]+\\([^:]+\\):\\|^\\* .*:\\|[hf]t?tps?://")
- (old-pt (point))
- (case-fold-search t))
- (or (eobp) (forward-char 1))
- (or (Info-next-reference-or-link pat 'link)
- (progn
- (goto-char (point-min))
- (or (Info-next-reference-or-link pat 'link)
- (progn
- (goto-char old-pt)
- (user-error "No cross references in this node")))))
- (if (looking-at "\\* Menu:")
- (if recur
- (user-error "No cross references in this node")
- (Info-next-reference t))
- (if (looking-at "^\\* ")
- (forward-char 2)))))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (unless count
+ (setq count 1))
+ (if (< count 0)
+ (Info-prev-reference recur (- count))
+ (while (unless (zerop count) (setq count (1- count)))
+ (let ((pat "\\*note[ \n\t]+\\([^:]+\\):\\|^\\* .*:\\|[hf]t?tps?://")
+ (old-pt (point))
+ (case-fold-search t))
+ (or (eobp) (forward-char 1))
+ (or (Info-next-reference-or-link pat 'link)
+ (progn
+ (goto-char (point-min))
+ (or (Info-next-reference-or-link pat 'link)
+ (progn
+ (goto-char old-pt)
+ (user-error "No cross references in this node")))))
+ (if (looking-at "\\* Menu:")
+ (if recur
+ (user-error "No cross references in this node")
+ (Info-next-reference t))
+ (if (looking-at "^\\* ")
+ (forward-char 2)))))))))
(defun Info-prev-reference (&optional recur count)
"Move cursor to the previous cross-reference or menu item in the node.
If COUNT is non-nil (interactively with a prefix arg), jump over
COUNT cross-references."
(interactive "i\np" Info-mode)
- (unless count
- (setq count 1))
- (if (< count 0)
- (Info-next-reference recur (- count))
- (while (unless (zerop count) (setq count (1- count)))
- (let ((pat "\\*note[ \n\t]+\\([^:]+\\):\\|^\\* .*:\\|[hf]t?tps?://")
- (old-pt (point))
- (case-fold-search t))
- (or (Info-prev-reference-or-link pat 'link)
- (progn
- (goto-char (point-max))
- (or (Info-prev-reference-or-link pat 'link)
- (progn
- (goto-char old-pt)
- (user-error "No cross references in this node")))))
- (if (looking-at "\\* Menu:")
- (if recur
- (user-error "No cross references in this node")
- (Info-prev-reference t))
- (if (looking-at "^\\* ")
- (forward-char 2)))))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (unless count
+ (setq count 1))
+ (if (< count 0)
+ (Info-next-reference recur (- count))
+ (while (unless (zerop count) (setq count (1- count)))
+ (let ((pat "\\*note[ \n\t]+\\([^:]+\\):\\|^\\* .*:\\|[hf]t?tps?://")
+ (old-pt (point))
+ (case-fold-search t))
+ (or (Info-prev-reference-or-link pat 'link)
+ (progn
+ (goto-char (point-max))
+ (or (Info-prev-reference-or-link pat 'link)
+ (progn
+ (goto-char old-pt)
+ (user-error "No cross references in this node")))))
+ (if (looking-at "\\* Menu:")
+ (if recur
+ (user-error "No cross references in this node")
+ (Info-prev-reference t))
+ (if (looking-at "^\\* ")
+ (forward-char 2)))))))))
\f
(defun Info-index-nodes (&optional file)
"Return a list of names of all index nodes in Info FILE.
@@ -3345,64 +3457,71 @@ Info-index
Give an empty topic name to go to the Index node itself."
(interactive
(list
- (let ((completion-ignore-case t)
- (Info-complete-menu-buffer (clone-buffer))
- (Info-complete-nodes (Info-index-nodes))
- (Info-history-list nil))
- (info--ensure-not-in-directory-node)
- (unwind-protect
- (with-current-buffer Info-complete-menu-buffer
- (Info-goto-index)
- (completing-read "Index topic: " #'Info-complete-menu-item))
- (kill-buffer Info-complete-menu-buffer)))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (if (not (eq (selected-window) info-window))
+ (Info-jump)
+ (setq Info-jump nil))
+ (let ((completion-ignore-case t)
+ (Info-complete-menu-buffer (clone-buffer))
+ (Info-complete-nodes (Info-index-nodes))
+ (Info-history-list nil))
+ (info--ensure-not-in-directory-node)
+ (unwind-protect
+ (with-current-buffer Info-complete-menu-buffer
+ (Info-goto-index)
+ (completing-read "Index topic: " #'Info-complete-menu-item))
+ (kill-buffer Info-complete-menu-buffer))))))
(info--ensure-not-in-directory-node)
;; Strip leading colon in topic; index format does not allow them.
(if (and (stringp topic)
- (> (length topic) 0)
- (= (aref topic 0) ?:))
+ (> (length topic) 0)
+ (= (aref topic 0) ?:))
(setq topic (substring topic 1)))
(let ((orignode Info-current-node)
- (pattern (format "\n\\* +\\([^\n]*\\(%s\\)[^\n]*\\):[ \t]+\\([^\n]*\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?"
- (regexp-quote topic)))
- node (nodes (Info-index-nodes))
- (ohist-list Info-history-list)
- (case-fold-search t))
+ (pattern (format "\n\\* +\\([^\n]*\\(%s\\)[^\n]*\\):[ \t]+\\([^\n]*\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?"
+ (regexp-quote topic)))
+ node (nodes (Info-index-nodes))
+ (ohist-list Info-history-list)
+ (case-fold-search t))
(Info-goto-index)
(or (equal topic "")
- (let ((matches nil)
- (exact nil)
- ;; We bind Info-history to nil for internal node-switches so
- ;; that we don't put junk in the history. In the first
- ;; Info-goto-index call, above, we do update the history
- ;; because that is what the user's previous node choice into it.
- (Info-history nil)
- found)
- (while
- (progn
- (goto-char (point-min))
- (while (re-search-forward pattern nil t)
- (let ((entry (match-string-no-properties 1))
- (nodename (match-string-no-properties 3))
- (line (string-to-number (concat "0" (match-string 4)))))
- (add-text-properties
- (- (match-beginning 2) (match-beginning 1))
- (- (match-end 2) (match-beginning 1))
- '(face info-index-match) entry)
- (push (list entry nodename Info-current-node line) matches)))
- (setq nodes (cdr nodes) node (car nodes)))
- (Info-goto-node node))
- (or matches
- (progn
- (Info-goto-node orignode)
- (user-error "No `%s' in index" topic)))
- ;; Here it is a feature that assoc is case-sensitive.
- (while (setq found (assoc topic matches))
- (setq exact (cons found exact)
- matches (delq found matches)))
+ (let ((matches nil)
+ (exact nil)
+ ;; We bind Info-history to nil for internal node-switches so
+ ;; that we don't put junk in the history. In the first
+ ;; Info-goto-index call, above, we do update the history
+ ;; because that is what the user's previous node choice into it.
+ (Info-history nil)
+ found)
+ (while
+ (progn
+ (goto-char (point-min))
+ (while (re-search-forward pattern nil t)
+ (let ((entry (match-string-no-properties 1))
+ (nodename (match-string-no-properties 3))
+ (line (string-to-number (concat "0" (match-string 4)))))
+ (add-text-properties
+ (- (match-beginning 2) (match-beginning 1))
+ (- (match-end 2) (match-beginning 1))
+ '(face info-index-match) entry)
+ (push (list entry nodename Info-current-node line) matches)))
+ (setq nodes (cdr nodes) node (car nodes)))
+ (Info-goto-node node))
+ (or matches
+ (progn
+ (Info-goto-node orignode)
+ (user-error "No `%s' in index" topic)))
+ ;; Here it is a feature that assoc is case-sensitive.
+ (while (setq found (assoc topic matches))
+ (setq exact (cons found exact)
+ matches (delq found matches)))
(setq Info-history-list ohist-list)
- (setq Info-index-alternatives (nconc exact (nreverse matches))
+ (setq Info-index-alternatives (nconc exact (nreverse matches))
Info--current-index-alternative 0)
- (Info-index-next 0)))))
+ (Info-index-next 0))))
+ (when Info-jump (select-window Info-jump)))
(defun Info-index-next (num)
"Go to the next matching index item from the last \\<Info-mode-map>\\[Info-index] command.
@@ -3411,45 +3530,49 @@ Info-index-next
Also see the `Info-warn-on-index-alternatives-wrap' user option."
(interactive "p" Info-mode)
- (unless Info-index-alternatives
- (user-error "No previous `i' command"))
- (let ((index (+ Info--current-index-alternative num))
- (total (length Info-index-alternatives))
- (next-key (key-description (where-is-internal
- 'Info-index-next overriding-local-map t))))
- (if (and Info-warn-on-index-alternatives-wrap
- (> total 1)
- (cond
- ((< index 0)
- (setq Info--current-index-alternative (- total 2))
- (message
- "No previous matches, use `%s' to continue from end of list"
- next-key)
- t)
- ((>= index total)
- (setq Info--current-index-alternative -1)
- (message
- "No previous matches, use `%s' to continue from start of list"
- next-key)
- t)))
- () ; Do nothing
- (setq index (mod index total)
- Info--current-index-alternative index)
- (let ((entry (nth index Info-index-alternatives)))
- (Info-goto-node (nth 1 entry))
- (if (> (nth 3 entry) 0)
- ;; Forward 2 lines less because `Info-find-node-2' initially
- ;; puts point to the 2nd line.
- (forward-line (- (nth 3 entry) 2))
- (forward-line 3) ; don't search in headers
- (Info-find-index-name (car entry)))
- (message "Found `%s' in %s. %s"
- (car entry)
- (nth 2 entry)
- (if (> total 1)
- (format-message
- "(%s total; use `%s' for next)" total next-key)
- "(Only match)"))))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (unless Info-index-alternatives
+ (user-error "No previous `i' command"))
+ (let ((index (+ Info--current-index-alternative num))
+ (total (length Info-index-alternatives))
+ (next-key (key-description (where-is-internal
+ 'Info-index-next overriding-local-map t))))
+ (if (and Info-warn-on-index-alternatives-wrap
+ (> total 1)
+ (cond
+ ((< index 0)
+ (setq Info--current-index-alternative (- total 2))
+ (message
+ "No previous matches, use `%s' to continue from end of list"
+ next-key)
+ t)
+ ((>= index total)
+ (setq Info--current-index-alternative -1)
+ (message
+ "No previous matches, use `%s' to continue from start of list"
+ next-key)
+ t)))
+ () ; Do nothing
+ (setq index (mod index total)
+ Info--current-index-alternative index)
+ (let ((entry (nth index Info-index-alternatives)))
+ (Info-goto-node (nth 1 entry))
+ (if (> (nth 3 entry) 0)
+ ;; Forward 2 lines less because `Info-find-node-2' initially
+ ;; puts point to the 2nd line.
+ (forward-line (- (nth 3 entry) 2))
+ (forward-line 3) ; don't search in headers
+ (Info-find-index-name (car entry)))
+ (message "Found `%s' in %s. %s"
+ (car entry)
+ (nth 2 entry)
+ (if (> total 1)
+ (format-message
+ "(%s total; use `%s' for next)" total next-key)
+ "(Only match)"))))))))
(defun Info-find-index-name (name)
"Move point to the place within the current node where NAME is defined."
@@ -3534,32 +3657,39 @@ Info-virtual-index
;; `interactive' is a copy from `Info-index'
(interactive
(list
- (let ((completion-ignore-case t)
- (Info-complete-menu-buffer (clone-buffer))
- (Info-complete-nodes (Info-index-nodes))
- (Info-history-list nil))
- (info--ensure-not-in-directory-node)
- (unwind-protect
- (with-current-buffer Info-complete-menu-buffer
- (Info-goto-index)
- (completing-read "Index topic: " #'Info-complete-menu-item))
- (kill-buffer Info-complete-menu-buffer))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (if (not (eq (selected-window) info-window))
+ (Info-jump)
+ (setq Info-jump nil))
+ (let ((completion-ignore-case t)
+ (Info-complete-menu-buffer (clone-buffer))
+ (Info-complete-nodes (Info-index-nodes))
+ (Info-history-list nil))
+ (info--ensure-not-in-directory-node)
+ (unwind-protect
+ (with-current-buffer Info-complete-menu-buffer
+ (Info-goto-index)
+ (completing-read "Index topic: " #'Info-complete-menu-item))
+ (kill-buffer Info-complete-menu-buffer)))))
Info-mode)
(if (equal topic "")
(Info-find-node Info-current-file "*Index*")
(unless (assoc (cons Info-current-file topic) Info-virtual-index-nodes)
(let ((orignode Info-current-node)
- (ohist-list Info-history-list))
- ;; Reuse `Info-index' to set `Info-index-alternatives'.
- (Info-index topic)
- (push (cons (cons Info-current-file topic) Info-index-alternatives)
- Info-virtual-index-nodes)
- ;; Clean up unnecessary side-effects of `Info-index'.
- (setq Info-history-list ohist-list)
- (Info-goto-node orignode)
- (message "")))
+ (ohist-list Info-history-list))
+ ;; Reuse `Info-index' to set `Info-index-alternatives'.
+ (Info-index topic)
+ (push (cons (cons Info-current-file topic) Info-index-alternatives)
+ Info-virtual-index-nodes)
+ ;; Clean up unnecessary side-effects of `Info-index'.
+ (setq Info-history-list ohist-list)
+ (Info-goto-node orignode)
+ (message "")))
(Info-find-node Info-current-file
- (format "*Index for ‘%s’*" topic))))
+ (format "*Index for ‘%s’*" topic)))
+ (when Info-jump (Info-jump)))
\f
(add-to-list 'Info-virtual-files
'("\\`\\*Apropos\\*\\'"
@@ -3696,18 +3826,22 @@ info-apropos
Display a menu of the possible matches."
(interactive "sIndex apropos: \nP")
- (if (equal string "")
- (Info-find-node Info-apropos-file "Top")
- (let ((nodes Info-apropos-nodes)
- nodename)
- (while (and nodes (not (equal string (nth 1 (car nodes)))))
- (setq nodes (cdr nodes)))
- (if nodes
- (Info-find-node Info-apropos-file (car (car nodes)) nil nil t)
- (setq nodename (format "Index for ‘%s’" string))
- (push (list nodename string (Info-apropos-matches string regexp))
- Info-apropos-nodes)
- (Info-find-node Info-apropos-file nodename)))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (if (equal string "")
+ (Info-find-node Info-apropos-file "Top")
+ (let ((nodes Info-apropos-nodes)
+ nodename)
+ (while (and nodes (not (equal string (nth 1 (car nodes)))))
+ (setq nodes (cdr nodes)))
+ (if nodes
+ (Info-find-node Info-apropos-file (car (car nodes)) nil nil t)
+ (setq nodename (format "Index for ‘%s’" string))
+ (push (list nodename string (Info-apropos-matches string regexp))
+ Info-apropos-nodes)
+ (Info-find-node Info-apropos-file nodename)))))))
\f
(add-to-list 'Info-virtual-files
'("\\`\\*Finder.*\\*\\'"
@@ -3842,17 +3976,29 @@ info-finder
(interactive
(when current-prefix-arg
(require 'finder)
- (list
- (completing-read-multiple
- "Keywords (separated by comma): "
- (mapcar #'symbol-name (mapcar #'car (append finder-known-keywords
- (finder-unknown-keywords))))
- nil t))))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (if (not (eq (selected-window) info-window))
+ (Info-jump)
+ (setq Info-jump nil))
+ (list
+ (completing-read-multiple
+ "Keywords (separated by comma): "
+ (mapcar #'symbol-name (mapcar #'car (append finder-known-keywords
+ (finder-unknown-keywords))))
+ nil t)))))
(require 'finder)
- (if keywords
- (Info-find-node Info-finder-file (mapconcat 'identity keywords ", "))
- (Info-find-node Info-finder-file "Top")))
-
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (if (not (eq (selected-window) info-window))
+ (Info-jump)
+ (setq Info-jump nil))
+ (if keywords
+ (Info-find-node Info-finder-file (mapconcat 'identity keywords ", "))
+ (Info-find-node Info-finder-file "Top")))
+ (when Info-jump (Info-jump)))
\f
(defun Info-undefined ()
"Make command be undefined in Info."
@@ -3871,22 +4017,26 @@ Info-help
(defun Info-summary ()
"Display a brief summary of all Info commands."
(interactive)
- (save-window-excursion
- (switch-to-buffer "*Help*")
- (setq buffer-read-only nil)
- (erase-buffer)
- (insert (documentation 'Info-mode))
- (help-mode)
- (goto-char (point-min))
- (let (ch flag)
- (while (progn (setq flag (not (pos-visible-in-window-p (point-max))))
- (message (if flag "Type Space to see more"
- "Type Space to return to Info"))
- (if (not (eq ?\s (setq ch (read-event))))
- (progn (push ch unread-command-events) nil)
- flag))
- (scroll-up)))
- (bury-buffer "*Help*")))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (save-window-excursion
+ (switch-to-buffer "*Help*")
+ (setq buffer-read-only nil)
+ (erase-buffer)
+ (insert (documentation 'Info-mode))
+ (help-mode)
+ (goto-char (point-min))
+ (let (ch flag)
+ (while (progn (setq flag (not (pos-visible-in-window-p (point-max))))
+ (message (if flag "Type Space to see more"
+ "Type Space to return to Info"))
+ (if (not (eq ?\s (setq ch (read-event))))
+ (progn (push ch unread-command-events) nil)
+ flag))
+ (scroll-up)))
+ (bury-buffer "*Help*")))))
\f
(defun Info-get-token (pos start all &optional errorstring)
"Return the token around POS.
@@ -4038,7 +4188,7 @@ Info-mouse-follow-link
(defvar Info-mode-map
(let ((map (make-keymap)))
(suppress-keymap map)
- (define-key map "." 'beginning-of-buffer)
+ (define-key map "." 'Info-beginning-of-buffer)
(define-key map " " 'Info-scroll-up)
(define-key map [?\S-\ ] 'Info-scroll-down)
(define-key map "\C-m" 'Info-follow-nearest-node)
@@ -4060,10 +4210,10 @@ Info-mode-map
(define-key map "[" 'Info-backward-node)
(define-key map "<" 'Info-top-node)
(define-key map ">" 'Info-final-node)
- (define-key map "b" 'beginning-of-buffer)
+ (define-key map "b" 'Info-beginning-of-buffer)
(put 'beginning-of-buffer :advertised-binding "b")
(define-key map "d" 'Info-directory)
- (define-key map "e" 'end-of-buffer)
+ (define-key map "e" 'Info-end-of-buffer)
(define-key map "f" 'Info-follow-reference)
(define-key map "g" 'Info-goto-node)
(define-key map "G" 'Info-goto-node-web)
@@ -4071,15 +4221,16 @@ Info-mode-map
;; This is for compatibility with standalone info (>~ version 5.2).
;; Though for some time, standalone info had H and h reversed.
;; See <https://debbugs.gnu.org/16455>.
- (define-key map "H" 'describe-mode)
+ (define-key map "H" 'Info-describe-mode)
(define-key map "i" 'Info-index)
+ (define-key map "j" 'Info-jump)
(define-key map "I" 'Info-virtual-index)
(define-key map "l" 'Info-history-back)
(define-key map "L" 'Info-history)
(define-key map "m" 'Info-menu)
(define-key map "n" 'Info-next)
(define-key map "p" 'Info-prev)
- (define-key map "q" 'quit-window)
+ (define-key map "q" 'Info-quit-window)
(define-key map "r" 'Info-history-forward)
(define-key map "s" 'Info-search)
(define-key map "S" 'Info-search-case-sensitively)
@@ -4104,6 +4255,21 @@ Info-mode-map
map)
"Keymap containing Info commands.")
+;; with a little help from Helm
+(defcustom Info-mode-prefix-key "C-h M-i"
+ "`Info-mode-map' prefix key for invocation from other buffers."
+ :version "30.1"
+ :type '(choice (string :tag "Key") (const :tag "no binding"))
+ :set (lambda (var key)
+ (when (and (boundp var) (symbol-value var))
+ (define-key (current-global-map)
+ (read-kbd-macro (symbol-value var)) nil))
+ (when key
+ (define-key (current-global-map)
+ (read-kbd-macro key)
+ Info-mode-map))
+ (set var key))
+ :group 'info)
(defun Info-check-pointer (item)
"Non-nil if ITEM is present in this node."
@@ -4125,7 +4291,7 @@ Info-check-pointer
:help "Go backward one node, considering all as a sequence"]
["Forward" Info-forward-node
:help "Go forward one node, considering all as a sequence"]
- ["Beginning" beginning-of-buffer
+ ["Beginning" Info-beginning-of-buffer
:help "Go to beginning of this node"]
["Top" Info-top-node
:help "Go to top node of file"]
@@ -4323,20 +4489,24 @@ Info-copy-current-node-name
The name of the Info file is prepended to the node name in parentheses.
With a zero prefix arg, put the name inside a function call to `info'."
(interactive "P" Info-mode)
- (unless Info-current-node
- (user-error "No current Info node"))
- (let ((node (if (stringp Info-current-file)
- (concat "(" (file-name-sans-extension
- (file-name-nondirectory Info-current-file))
- ") "
- Info-current-node))))
- (if (zerop (prefix-numeric-value arg))
- (setq node (concat "(info \"" node "\")")))
- (unless (stringp Info-current-file)
- (setq node (format "(Info-find-node '%S '%S)"
- Info-current-file Info-current-node)))
- (kill-new node)
- (message "%s" node)))
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (unless Info-current-node
+ (user-error "No current Info node"))
+ (let ((node (if (stringp Info-current-file)
+ (concat "(" (file-name-sans-extension
+ (file-name-nondirectory Info-current-file))
+ ") "
+ Info-current-node))))
+ (if (zerop (prefix-numeric-value arg))
+ (setq node (concat "(info \"" node "\")")))
+ (unless (stringp Info-current-file)
+ (setq node (format "(Info-find-node '%S '%S)"
+ Info-current-file Info-current-node)))
+ (kill-new node)
+ (message "%s" node)))))
\f
;; Info mode is suitable only for specially formatted data.
@@ -5509,6 +5679,42 @@ info--manual-names
(apply-partially #'Info-read-node-name-2
Info-directory-list
(mapcar #'car Info-suffix-list))))))))
+\f
+;; commands from special-mode wrapped to work on Info-mode only
+
+(defun Info-beginning-of-buffer ()
+ "Move point to the beginning of *info* buffer."
+ (interactive)
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (goto-char (point-min)))))
+
+(defun Info-end-of-buffer ()
+ "Move point to the beginning of *info* buffer."
+ (interactive)
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (goto-char (point-max)))))
+
+(defun Info-describe-mode ()
+ "As `describe-mode' but for *Help* buffer only."
+ (interactive)
+ (let ((info-window (get-buffer "*info*")))
+ (unless (window-live-p (get-buffer-window info-window))
+ (user-error "There is no visible Info buffer."))
+ (describe-mode info-window)))
+
+(defun Info-quit-window ()
+ (interactive)
+ (let ((info-window (get-buffer-window "*info*")))
+ (unless (window-live-p info-window)
+ (user-error "There is no visible Info buffer."))
+ (with-selected-window info-window
+ (quit-window nil info-window))))
(provide 'info)
--
2.40.1
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2023-05-30 12:38 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-30 12:38 Proposal: Control help- and Info-mode buffers from other buffers Arthur Miller
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).