(if trim (setq nodename (substring nodename 0 trim))))
(if transient-mark-mode (deactivate-mark))
(Info-find-node (if (equal filename "") nil filename)
- (if (equal nodename "") "Top" nodename) nil strict-case)))
+ (if (equal nodename "") "Top" nodename) nil strict-case)))
+
+(defun Info-goto-node-web (node)
+ "Use `browse-url' to go to the gnu.org web server's version of NODE.
+By default, go to the current Info node."
+ (interactive (list (Info-read-node-name
+ "Go to node (default current page): " Info-current-node))
+ Info-mode)
+ (browse-url-button-open-url
+ (Info-url-for-node (format "(%s)%s" (file-name-sans-extension
+ (file-name-nondirectory
+ Info-current-file))
+ node))))
+
+(defun Info-url-for-node (node)
+ "Return a URL for NODE, a node in the GNU Emacs or Elisp manual.
+NODE should be a string on the form \"(manual)Node\". Only emacs
+and elisp manuals are supported."
+ (unless (string-match "\\`(\\(.+\\))\\(.+\\)\\'" node)
+ (error "Invalid node name %s" node))
+ (let ((manual (match-string 1 node))
+ (node (match-string 2 node)))
+ (unless (member manual '("emacs" "elisp"))
+ (error "Only emacs/elisp manuals are supported"))
+ ;; Encode a bunch of characters the way that makeinfo does.
+ (setq node
+ (mapconcat (lambda (ch)
+ (if (or (< ch 32) ; ^@^A-^Z^[^\^]^^^-
+ (<= 33 ch 47) ; !"#$%&'()*+,-./
+ (<= 58 ch 64) ; :;<=>?@
+ (<= 91 ch 96) ; [\]_`
+ (<= 123 ch 127)) ; {|}~ DEL
+ (format "_00%x" ch)
+ (char-to-string ch)))
+ node
+ ""))
+ (concat "https://www.gnu.org/software/emacs/manual/html_node/"
+ manual "/"
+ (url-hexify-string (string-replace " " "-" node))
+ ".html")))
(defvar Info-read-node-completion-table)
code Info-read-node-completion-table string predicate))))
;; Arrange to highlight the proper letters in the completion list buffer.
-(defun Info-read-node-name (prompt)
+(defun Info-read-node-name (prompt &optional default)
"Read an Info node name with completion, prompting with PROMPT.
A node name can have the form \"NODENAME\", referring to a node
in the current Info file, or \"(FILENAME)NODENAME\", referring to
the Top node in FILENAME."
(let* ((completion-ignore-case t)
(Info-read-node-completion-table (Info-build-node-completions))
- (nodename (completing-read prompt #'Info-read-node-name-1 nil t)))
+ (nodename (completing-read prompt #'Info-read-node-name-1 nil t nil
+ 'Info-minibuf-history default)))
(if (equal nodename "")
(Info-read-node-name prompt)
nodename)))
(define-key map "T" 'Info-toc)
(define-key map "u" 'Info-up)
;; `w' for consistency with `dired-copy-filename-as-kill'.
+ (define-key map "W" 'Info-goto-node-web)
(define-key map "w" 'Info-copy-current-node-name)
(define-key map "c" 'Info-copy-current-node-name)
;; `^' for consistency with `dired-up-directory'.
--- /dev/null
+;;; info-tests.el --- Tests for info.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'info)
+(require 'ert)
+(require 'ert-x)
+
+(ert-deftest test-info-urls ()
+ (should (equal (Info-url-for-node "(emacs)Minibuffer")
+ "https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer.html"))
+ (should (equal (Info-url-for-node "(emacs)Minibuffer File")
+ "https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer-File.html"))
+ (should (equal (Info-url-for-node "(elisp)Backups and Auto-Saving")
+ "https://www.gnu.org/software/emacs/manual/html_node/elisp/Backups-and-Auto_002dSaving.html"))
+ (should-error (Info-url-for-node "(gnus)Minibuffer File")))
+
+;;; info-tests.el ends here