emacs-devel
[Top][All Lists]
Advanced

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

Re: Virtual Info files and nodes


From: Juri Linkov
Subject: Re: Virtual Info files and nodes
Date: Tue, 30 Jun 2009 02:55:19 +0300
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1.50 (x86_64-pc-linux-gnu)

>>> - Why check (stringp filename) in Info-virtual-file?  Isn't it an
>>> error to call it with something else than a string.
>>
>> Really only nil can be expected now,
>
> Can it?  In which circumstance?

`filename' can be nil when `Info-virtual-fun' is called with non-nil
`nodename' to check for a node name when a file name is irrelevant -
its argument value is nil in this case.

>> but `stringp' is a precaution
>> against t (the current internal value for "dir" ) and former symbol
>> values `apropos', `toc' (maybe some external packages still use them).
>
> Please mention it in a comment.

Ok.

>> Info-virtual-fun expects an argument `op' for an operation type,
>> but these places call (Info-virtual-file file) with only a file name
>> argument to check whether a file name is virtual (if its name is defined
>> in a list of definitions of virtual Info files).
>
> Why not provide a dummy `find-file' value for the `op'?
> And wrap this in an Info-virtual-file-p function?

This is done in the next version below with other fixes including the
handling of "dir":

Index: lisp/info.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/info.el,v
retrieving revision 1.559
diff -c -w -b -r1.559 info.el
*** lisp/info.el        23 May 2009 23:31:52 -0000      1.559
--- lisp/info.el        29 Jun 2009 23:50:55 -0000
***************
*** 329,334 ****
--- 329,381 ----
  (defvar Info-standalone nil
    "Non-nil if Emacs was started solely as an Info browser.")
  
+ (defvar Info-virtual-files nil
+   "List of definitions of virtual Info files.
+ Each element of the list has the format (FILENAME (OPERATION . HANDLER) ...)
+ where FILENAME is a regexp that matches a class of virtual Info file names.
+ It should be carefully choosen to not cause file name clashes with
+ real file names.  OPERATION is one of the following operation symbols
+ `find-file', `find-node', `toc-nodes' that define what HANDLER
+ function to call instead of calling the default corresponding function
+ to override it.")
+ 
+ (defvar Info-virtual-nodes nil
+   "List of definitions of virtual Info nodes.
+ Each element of the list has the format (NODENAME (OPERATION . HANDLER) ...)
+ where NODENAME is a regexp that matches a class of virtual Info node names.
+ It should be carefully choosen to not cause node name clashes with
+ real node names.  OPERATION is one of the following operation symbols
+ `find-node' that define what HANDLER function to call instead of
+ calling the default corresponding function to override it.")
+ 
+ (defvar Info-current-node-virtual nil
+   "Non-nil if the current Info node is virtual.")
+ 
+ (defun Info-virtual-file-p (filename)
+   "Check if Info file FILENAME is virtual."
+   (Info-virtual-fun 'find-file filename nil))
+ 
+ (defun Info-virtual-fun (op filename nodename)
+   "Find a function that handles operations on virtual manuals.
+ OP is an operation symbol (`find-file', `find-node' or `toc-nodes'),
+ FILENAME is a virtual Info file name, NODENAME is a virtual Info
+ node name.  Return a function found either in `Info-virtual-files'
+ or `Info-virtual-nodes'."
+   (or (and (stringp filename) ; some legacy code can still use a symbol
+          (cdr-safe (assoc op (assoc-default filename
+                                             Info-virtual-files
+                                             'string-match))))
+       (and (stringp nodename) ; some legacy code can still use a symbol
+          (cdr-safe (assoc op (assoc-default nodename
+                                             Info-virtual-nodes
+                                             'string-match))))))
+ 
+ (defun Info-virtual-call (virtual-fun &rest args)
+   "Call a function that handles operations on virtual manuals."
+   (when (functionp virtual-fun)
+     (or (apply virtual-fun args) t)))
+ 
+ 
  (defvar Info-suffix-list
    ;; The MS-DOS list should work both when long file names are
    ;; supported (Windows 9X), and when only 8+3 file names are available.
***************
*** 481,487 ****
    (or (assoc file Info-file-supports-index-cookies-list)
        ;; Skip virtual Info files
        (and (or (not (stringp file))
!              (member file '("dir" apropos history toc)))
             (setq Info-file-supports-index-cookies-list
                 (cons (cons file nil) Info-file-supports-index-cookies-list)))
        (save-excursion
--- 528,534 ----
    (or (assoc file Info-file-supports-index-cookies-list)
        ;; Skip virtual Info files
        (and (or (not (stringp file))
!              (Info-virtual-file-p file))
             (setq Info-file-supports-index-cookies-list
                 (cons (cons file nil) Info-file-supports-index-cookies-list)))
        (save-excursion
***************
*** 660,672 ****
  just return nil (no error)."
    ;; Convert filename to lower case if not found as specified.
    ;; Expand it.
!   (if (stringp filename)
        (let (temp temp-downcase found)
          (setq filename (substitute-in-file-name filename))
-       (cond
-        ((string= (downcase filename) "dir")
-         (setq found t))
-        (t
          (let ((dirs (if (string-match "^\\./" filename)
                            ;; If specified name starts with `./'
                            ;; then just try current directory.
--- 707,719 ----
  just return nil (no error)."
    ;; Convert filename to lower case if not found as specified.
    ;; Expand it.
!   (cond
!    ((Info-virtual-call
!      (Info-virtual-fun 'find-file filename nil)
!      filename noerror))
!    ((stringp filename)
      (let (temp temp-downcase found)
        (setq filename (substitute-in-file-name filename))
        (let ((dirs (if (string-match "^\\./" filename)
                      ;; If specified name starts with `./'
                      ;; then just try current directory.
***************
*** 705,718 ****
                                temp (car (car suffix-list)) nil)))
                         (setq found temp)))
                    (setq suffix-list (cdr suffix-list))))
!               (setq dirs (cdr dirs))))))
          (if found
              (setq filename found)
            (if noerror
                (setq filename nil)
              (error "Info file %s does not exist" filename)))
!         filename)
!     (and (member filename '(apropos history toc)) filename)))
  
  (defun Info-find-node (filename nodename &optional no-going-back)
    "Go to an Info node specified as separate FILENAME and NODENAME.
--- 752,764 ----
                            temp (car (car suffix-list)) nil)))
                     (setq found temp)))
              (setq suffix-list (cdr suffix-list))))
!         (setq dirs (cdr dirs))))
        (if found
          (setq filename found)
        (if noerror
            (setq filename nil)
          (error "Info file %s does not exist" filename)))
!       filename))))
  
  (defun Info-find-node (filename nodename &optional no-going-back)
    "Go to an Info node specified as separate FILENAME and NODENAME.
***************
*** 862,889 ****
    (setq Info-current-node nil)
    (unwind-protect
        (let ((case-fold-search t)
            anchorpos)
!         ;; Switch files if necessary
          (or (null filename)
!             (equal Info-current-file filename)
              (let ((inhibit-read-only t))
                (setq Info-current-file nil
                      Info-current-subfile nil
                      Info-current-file-completions nil
                      buffer-file-name nil)
                (erase-buffer)
-             (cond
-              ((eq filename t)
-               (Info-insert-dir))
-              ((eq filename 'apropos)
-               (insert-buffer-substring " *info-apropos*"))
-              ((eq filename 'history)
-               (insert-buffer-substring " *info-history*"))
-              ((eq filename 'toc)
-               (insert-buffer-substring " *info-toc*"))
-              (t
                  (info-insert-file-contents filename nil)
!                 (setq default-directory (file-name-directory filename))))
                (set-buffer-modified-p nil)
              (set (make-local-variable 'Info-file-supports-index-cookies)
                   (Info-file-supports-index-cookies filename))
--- 908,944 ----
    (setq Info-current-node nil)
    (unwind-protect
        (let ((case-fold-search t)
+           (virtual-fun (Info-virtual-fun 'find-node
+                                          (or filename Info-current-file)
+                                          nodename))
            anchorpos)
!       (cond
!        ((functionp virtual-fun)
!         (let ((inhibit-read-only t)
!               (filename (or filename Info-current-file)))
!           (setq buffer-file-name nil)
!           (erase-buffer)
!           (setq Info-current-file filename)
!           (Info-virtual-call virtual-fun filename nodename no-going-back)
!           (set-buffer-modified-p nil)
!           (set-marker Info-tag-table-marker nil)
!           (set (make-local-variable 'Info-current-node-virtual) t)))
!        ((not (and
!               ;; Reread a file when moving from a virtual node.
!               (not Info-current-node-virtual)
                (or (null filename)
!                   (equal Info-current-file filename))))
!         ;; Switch files if necessary
          (let ((inhibit-read-only t))
+           (if (and Info-current-node-virtual (null filename))
+               (setq filename Info-current-file))
            (setq Info-current-file nil
                  Info-current-subfile nil
                  Info-current-file-completions nil
                  buffer-file-name nil)
            (erase-buffer)
            (info-insert-file-contents filename nil)
!           (setq default-directory (file-name-directory filename))
            (set-buffer-modified-p nil)
            (set (make-local-variable 'Info-file-supports-index-cookies)
                 (Info-file-supports-index-cookies filename))
***************
*** 919,929 ****
                                        (match-end 0) tagbuf))
                        (set-marker Info-tag-table-marker pos)))
                  (set-marker Info-tag-table-marker nil))
!               (setq Info-current-file
!                   (cond
!                    ((eq filename t) "dir")
!                    (t filename)))
!             ))
          ;; Use string-equal, not equal, to ignore text props.
          (if (string-equal nodename "*")
              (progn (setq Info-current-node nodename)
--- 974,982 ----
                                    (match-end 0) tagbuf))
                    (set-marker Info-tag-table-marker pos)))
              (set-marker Info-tag-table-marker nil))
!           (setq Info-current-file filename)
!           )))
! 
          ;; Use string-equal, not equal, to ignore text props.
          (if (string-equal nodename "*")
              (progn (setq Info-current-node nodename)
***************
*** 1999,2076 ****
      (setq Info-history-forward history-forward)
      (goto-char opoint)))
  
  ;;;###autoload
  (defun Info-directory ()
    "Go to the Info directory node."
    (interactive)
    (Info-find-node "dir" "top"))
  
! (defun Info-history ()
!   "Go to a node with a menu of visited nodes."
!   (interactive)
!   (let ((curr-file Info-current-file)
!         (curr-node Info-current-node)
!         p)
!     (with-current-buffer (get-buffer-create " *info-history*")
!       (let ((inhibit-read-only t))
!         (erase-buffer)
!         (goto-char (point-min))
!         (insert "\n\^_\nFile: history,  Node: Top,  Up: (dir)\n\n")
!         (insert "Recently Visited Nodes\n**********************\n\n")
          (insert "* Menu:\n\n")
!         (let ((hl (delete '("history" "Top") Info-history-list)))
            (while hl
              (let ((file (nth 0 (car hl)))
                    (node (nth 1 (car hl))))
-               (if (and (equal file curr-file)
-                        (equal node curr-node))
-                   (setq p (point)))
                (if (stringp file)
                  (insert "* " node ": ("
                          (propertize (or (file-name-directory file) "") 
'invisible t)
                          (file-name-nondirectory file)
                          ")" node ".\n")))
!             (setq hl (cdr hl))))))
!     (Info-find-node 'history "Top")
!     (goto-char (or p (point-min)))))
  
! (defun 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)
!   (if (stringp Info-current-file)
!       (let ((curr-file (substring-no-properties Info-current-file))
!           (curr-node (substring-no-properties Info-current-node))
!           p)
!       (with-current-buffer (get-buffer-create " *info-toc*")
!         (let ((inhibit-read-only t)
                (node-list (Info-toc-nodes curr-file)))
!           (erase-buffer)
!           (goto-char (point-min))
!           (insert "\n\^_\nFile: toc,  Node: Top,  Up: (dir)\n\n")
!           (insert "Table of Contents\n*****************\n\n")
!           (insert "*Note Top: (" curr-file ")Top.\n")
!           (Info-insert-toc
             (nth 3 (assoc "Top" node-list)) ; get Top nodes
!            node-list 0 curr-file))
!         (if (not (bobp))
              (let ((Info-hide-note-references 'hide)
                    (Info-fontify-visited-nodes nil))
!               (Info-mode)
!               (setq Info-current-file 'toc Info-current-node "Top")
                (goto-char (point-min))
                (narrow-to-region (or (re-search-forward "\n[\^_\f]\n" nil t)
                                      (point-min))
                                  (point-max))
                (Info-fontify-node)
!               (widen)))
          (goto-char (point-min))
!         (if (setq p (search-forward (concat "*Note " curr-node ":") nil t))
!             (setq p (- p (length curr-node) 2))))
!       (Info-find-node 'toc "Top")
!       (goto-char (or p (point-min))))))
  
! (defun Info-insert-toc (nodes node-list level curr-file)
    "Insert table of contents with references to nodes."
    (let ((section "Top"))
      (while nodes
--- 2052,2165 ----
      (setq Info-history-forward history-forward)
      (goto-char opoint)))
  
+ (add-to-list 'Info-virtual-files
+            '("\\`dir\\'"
+              (toc-nodes . Info-directory-toc-nodes)
+              (find-file . Info-directory-find-file)
+              (find-node . Info-directory-find-node)
+              ))
+ 
+ (defun Info-directory-toc-nodes (filename)
+   "Directory-specific implementation of Info-directory-toc-nodes."
+   `(,filename
+     ("Top" nil nil nil)))
+ 
+ (defun Info-directory-find-file (filename &optional noerror)
+   "Directory-specific implementation of Info-find-file."
+   filename)
+ 
+ (defun Info-directory-find-node (filename nodename &optional no-going-back)
+   "Directory-specific implementation of Info-find-node-2."
+   (Info-insert-dir))
+ 
  ;;;###autoload
  (defun Info-directory ()
    "Go to the Info directory node."
    (interactive)
    (Info-find-node "dir" "top"))
  
! (add-to-list 'Info-virtual-files
!            '("\\`\\*History\\*\\'"
!              (toc-nodes . Info-history-toc-nodes)
!              (find-file . Info-history-find-file)
!              (find-node . Info-history-find-node)
!              ))
! 
! (defun Info-history-toc-nodes (filename)
!   "History-specific implementation of Info-history-toc-nodes."
!   `(,filename
!     ("Top" nil nil nil)))
! 
! (defun Info-history-find-file (filename &optional noerror)
!   "History-specific implementation of Info-find-file."
!   filename)
! 
! (defun Info-history-find-node (filename nodename &optional no-going-back)
!   "History-specific implementation of Info-find-node-2."
!   (insert (format "\n\^_\nFile: %s,  Node: %s,  Up: (dir)\n\n"
!                 (or filename Info-current-file) nodename))
!   (insert "Recently Visited Nodes\n")
!   (insert "**********************\n\n")
    (insert "* Menu:\n\n")
!   (let ((hl (delete '("*History*" "Top") Info-history-list)))
      (while hl
        (let ((file (nth 0 (car hl)))
            (node (nth 1 (car hl))))
        (if (stringp file)
            (insert "* " node ": ("
                    (propertize (or (file-name-directory file) "") 'invisible t)
                    (file-name-nondirectory file)
                    ")" node ".\n")))
!       (setq hl (cdr hl)))))
  
! (defun Info-history ()
!   "Go to a node with a menu of visited nodes."
    (interactive)
!   (Info-find-node "*History*" "Top")
!   (Info-next-reference)
!   (Info-next-reference))
! 
! (add-to-list 'Info-virtual-nodes
!            '("\\`\\*TOC\\*\\'"
!              (find-node . Info-toc-find-node)
!              ))
! 
! (defun Info-toc-find-node (filename nodename &optional no-going-back)
!   "Toc-specific implementation of Info-find-node-2."
!   (let* ((curr-file (substring-no-properties (or filename Info-current-file)))
!        (curr-node (substring-no-properties (or nodename Info-current-node)))
         (node-list (Info-toc-nodes curr-file)))
!     (insert (format "\n\^_\nFile: %s,  Node: %s,  Up: Top\n\n"
!                   curr-file curr-node))
!     (insert "Table of Contents\n")
!     (insert "*****************\n\n")
!     (insert "*Note Top::\n")
!     (Info-toc-insert
       (nth 3 (assoc "Top" node-list))  ; get Top nodes
!      node-list 0 curr-file)
!     (unless (bobp)
        (let ((Info-hide-note-references 'hide)
            (Info-fontify-visited-nodes nil))
!       (setq Info-current-file filename Info-current-node "*TOC*")
        (goto-char (point-min))
        (narrow-to-region (or (re-search-forward "\n[\^_\f]\n" nil t)
                              (point-min))
                          (point-max))
        (Info-fontify-node)
!       (widen)))))
! 
! (defun 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)
!   (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."
    (let ((section "Top"))
      (while nodes
***************
*** 2078,2088 ****
          (unless (member (nth 2 node) (list nil section))
            (insert (setq section (nth 2 node)) "\n"))
          (insert (make-string level ?\t))
!         (insert "*Note " (car nodes) ": (" curr-file ")" (car nodes) ".\n")
!         (Info-insert-toc (nth 3 node) node-list (1+ level) curr-file)
          (setq nodes (cdr nodes))))))
  
! (defun Info-build-toc (file)
    "Build table of contents from menus of Info FILE and its subfiles."
    (with-temp-buffer
      (let* ((file (and (stringp file) (Info-find-file file)))
--- 2167,2177 ----
          (unless (member (nth 2 node) (list nil section))
            (insert (setq section (nth 2 node)) "\n"))
          (insert (make-string level ?\t))
!         (insert "*Note " (car nodes) ":: \n")
!         (Info-toc-insert (nth 3 node) node-list (1+ level) curr-file)
          (setq nodes (cdr nodes))))))
  
! (defun Info-toc-build (file)
    "Build table of contents from menus of Info FILE and its subfiles."
    (with-temp-buffer
      (let* ((file (and (stringp file) (Info-find-file file)))
***************
*** 2162,2184 ****
  SECTION is the section name in the Top node where this node is placed,
  CHILDREN is a list of child nodes extracted from the node menu.")
  
! (defun Info-toc-nodes (file)
!   "Return a node list of Info FILE with parent-children information.
  This information is cached in the variable `Info-toc-nodes' with the help
! of the function `Info-build-toc'."
!   (or file (setq file Info-current-file))
!   (or (assoc file Info-toc-nodes)
        ;; Skip virtual Info files
!       (and (or (not (stringp file))
!              (member file '("dir" apropos history toc)))
!            (push (cons file nil) Info-toc-nodes))
        ;; Scan the entire manual and cache the result in Info-toc-nodes
!       (let ((nodes (Info-build-toc file)))
!       (push (cons file nodes) Info-toc-nodes)
        nodes)
        ;; If there is an error, still add nil to the cache
!       (push (cons file nil) Info-toc-nodes))
!   (cdr (assoc file Info-toc-nodes)))
  
  
  (defun Info-follow-reference (footnotename &optional fork)
--- 2251,2278 ----
  SECTION is the section name in the Top node where this node is placed,
  CHILDREN is a list of child nodes extracted from the node menu.")
  
! (defun Info-toc-nodes (filename)
!   "Return a node list of Info FILENAME with parent-children information.
  This information is cached in the variable `Info-toc-nodes' with the help
! of the function `Info-toc-build'."
!   (cond
!    ((Info-virtual-call
!      (Info-virtual-fun 'toc-nodes (or filename Info-current-file) nil)
!      filename))
!    (t
!     (or filename (setq filename Info-current-file))
!     (or (assoc filename Info-toc-nodes)
        ;; Skip virtual Info files
!       (and (or (not (stringp filename))
!                (Info-virtual-file-p filename))
!            (push (cons filename nil) Info-toc-nodes))
        ;; Scan the entire manual and cache the result in Info-toc-nodes
!       (let ((nodes (Info-toc-build filename)))
!         (push (cons filename nodes) Info-toc-nodes)
          nodes)
        ;; If there is an error, still add nil to the cache
!       (push (cons filename nil) Info-toc-nodes))
!     (cdr (assoc filename Info-toc-nodes)))))
  
  
  (defun Info-follow-reference (footnotename &optional fork)
***************
*** 2792,2798 ****
    (or (assoc file Info-index-nodes)
        ;; Skip virtual Info files
        (and (or (not (stringp file))
!              (member file '("dir" apropos history toc)))
             (setq Info-index-nodes (cons (cons file nil) Info-index-nodes)))
        (if (Info-file-supports-index-cookies file)
          ;; Find nodes with index cookie
--- 2886,2892 ----
    (or (assoc file Info-index-nodes)
        ;; Skip virtual Info files
        (and (or (not (stringp file))
!              (Info-virtual-file-p file))
             (setq Info-index-nodes (cons (cons file nil) Info-index-nodes)))
        (if (Info-file-supports-index-cookies file)
          ;; Find nodes with index cookie
***************
*** 2860,2867 ****
  If NODE is nil, check the current Info node.
  If FILE is nil, check the current Info file."
    (or file (setq file Info-current-file))
!   (if (or (and node (not (equal node Info-current-node)))
            (assoc file Info-index-nodes))
        (member (or node Info-current-node) (Info-index-nodes file))
      ;; Don't search all index nodes if request is only for the current node
      ;; and file is not in the cache of index nodes
--- 2954,2962 ----
  If NODE is nil, check the current Info node.
  If FILE is nil, check the current Info file."
    (or file (setq file Info-current-file))
!   (if (and (or (and node (not (equal node Info-current-node)))
               (assoc file Info-index-nodes))
+          (not Info-current-node-virtual))
        (member (or node Info-current-node) (Info-index-nodes file))
      ;; Don't search all index nodes if request is only for the current node
      ;; and file is not in the cache of index nodes
***************
*** 3001,3010 ****
        (progn (beginning-of-line) t)  ;; non-nil for recursive call
        (goto-char (point-min)))))
  
! ;;;###autoload
! (defun info-apropos (string)
!   "Grovel indices of all known Info files on your system for STRING.
! Build a menu of the possible matches."
    (interactive "sIndex apropos: ")
    (unless (string= string "")
      (let ((pattern (format "\n\\* +\\([^\n]*%s[^\n]*\\):[ 
\t]+\\([^\n]+\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?"
--- 3096,3251 ----
        (progn (beginning-of-line) t)  ;; non-nil for recursive call
        (goto-char (point-min)))))
  
! (add-to-list 'Info-virtual-nodes
!            '("\\`\\*Index.*\\*\\'"
!              (find-node . Info-virtual-index-find-node)
!              ))
! 
! (defvar Info-virtual-index-nodes nil
!   "Alist of cached matched index search nodes.
! Each element is ((FILENAME . TOPIC) MATCHES) where
! FILENAME is the file name of the manual,
! TOPIC is the search string given as an argument to `Info-virtual-index',
! MATCHES is a list of index matches found by `Info-index'.")
! 
! (defun Info-virtual-index-find-node (filename nodename &optional 
no-going-back)
!   "Index-specific implementation of Info-find-node-2."
!   ;; Generate Index-like menu of matches
!   (if (string-match "^\\*Index for `\\(.+\\)'\\*$" nodename)
!       ;; Generate Index-like menu of matches
!       (let* ((topic (match-string 1 nodename))
!            (matches (cdr (assoc (cons (or filename Info-current-file) topic)
!                                 Info-virtual-index-nodes))))
!       (insert (format "\n\^_\nFile: %s,  Node: %s,  Up: *Index*\n\n"
!                       (or filename Info-current-file) nodename))
!       (insert "Info Virtual Index\n")
!       (insert "******************\n\n")
!       (insert "Index entries that match `" topic "':\n\n")
!       (insert "\0\b[index\0\b]\n")
!       (if (null matches)
!           (insert "No matches found.\n")
!         (insert "* Menu:\n\n")
!         (dolist (entry matches)
!           (insert (format "* %-38s %s.%s\n"
!                           (format "%s [%s]:" (nth 0 entry) (nth 2 entry))
!                           (nth 1 entry)
!                           (if (nth 3 entry)
!                               (format " (line %s)" (nth 3 entry))
!                             ""))))))
!     ;; Else, Generate a list of previous search results
!     (let ((nodes (reverse Info-virtual-index-nodes)))
!       (insert (format "\n\^_\nFile: %s,  Node: %s,  Up: Top\n\n"
!                     (or filename Info-current-file) nodename))
!       (insert "Info Virtual Index\n")
!       (insert "******************\n\n")
!       (insert "This is a list of search results produced by\n"
!             "`Info-virtual-index' for the current manual.\n\n")
!       (insert "* Menu:\n\n")
!       (dolist (nodeinfo nodes)
!       (when (equal (car (nth 0 nodeinfo)) (or filename Info-current-file))
!         (insert
!          (format "* %-20s %s.\n"
!                  (format "*Index for `%s'*::" (cdr (nth 0 nodeinfo)))
!                  (cdr (nth 0 nodeinfo)))))))))
! 
! (defun Info-virtual-index (topic)
!   "Show a node with all lines in the index containing a string TOPIC."
!   ;; `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))
!       (if (equal Info-current-file "dir")
!         (error "The Info directory node has no index; use m to select a 
manual"))
!       (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)))))
!   (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)
!           nodename)
!       (Info-index topic)
!       (setq Info-history-list ohist-list)
!       (Info-goto-node orignode)
!       (push (cons (cons Info-current-file topic) Info-index-alternatives)
!             Info-virtual-index-nodes)))
!     (Info-find-node Info-current-file (format "*Index for `%s'*" topic))))
! 
! (add-to-list 'Info-virtual-files
!            '("\\`\\*Apropos\\*\\'"
!              (toc-nodes . Info-apropos-toc-nodes)
!              (find-file . Info-apropos-find-file)
!              (find-node . Info-apropos-find-node)
!              ))
! 
! (defvar Info-apropos-file "*Apropos*"
!   "Info file name of the virtual manual for matches of `info-apropos'.")
! 
! (defvar Info-apropos-nodes nil
!   "Alist of cached apropos matched nodes.
! Each element is (NODENAME STRING MATCHES) where
! NODENAME is the name of the node that holds the search result,
! STRING is the search string given as an argument to `info-apropos',
! MATCHES is a list of index matches found by `Info-apropos-matches'.")
! 
! (defun Info-apropos-toc-nodes (filename)
!   "Apropos-specific implementation of Info-apropos-toc-nodes."
!   (let ((nodes (mapcar 'car (reverse Info-apropos-nodes))))
!     `(,filename
!       ("Top" nil nil ,nodes)
!       ,@(mapcar (lambda (node) `(,node "Top" nil nil)) nodes))))
! 
! (defun Info-apropos-find-file (filename &optional noerror)
!   "Apropos-specific implementation of Info-find-file."
!   filename)
! 
! (defun Info-apropos-find-node (filename nodename &optional no-going-back)
!   "Apropos-specific implementation of Info-find-node-2."
!   (if (equal nodename "Top")
!       ;; Generate Top menu
!       (let ((nodes (reverse Info-apropos-nodes)))
!       (insert (format "\n\^_\nFile: %s,  Node: %s,  Up: (dir)\n\n"
!                       Info-apropos-file nodename))
!       (insert "Apropos Index\n")
!       (insert "*************\n\n")
!       (insert "This is a list of search results produced by 
`info-apropos'.\n\n")
!       (insert "* Menu:\n\n")
!       (dolist (nodeinfo nodes)
!         (insert (format "* %-20s %s.\n"
!                         (format "%s::" (nth 0 nodeinfo))
!                         (nth 1 nodeinfo)))))
!     ;; Else, Generate Index-like menu of matches
!     (let* ((nodeinfo (assoc nodename Info-apropos-nodes))
!          (matches (nth 2 nodeinfo)))
!       (when matches
!       (insert (format "\n\^_\nFile: %s,  Node: %s,  Up: Top\n\n"
!                       Info-apropos-file nodename))
!       (insert "Apropos Index\n")
!       (insert "*************\n\n")
!       (insert "Index entries that match `" (nth 1 nodeinfo) "':\n\n")
!       (insert "\0\b[index\0\b]\n")
!       (if (eq matches t)
!           (insert "No matches found.\n")
!         (insert "* Menu:\n\n")
!         (dolist (entry matches)
!           (insert (format "* %-38s (%s)%s.%s\n"
!                           (format "%s [%s]:" (nth 1 entry) (nth 0 entry))
!                           (nth 0 entry)
!                           (nth 2 entry)
!                           (if (nth 3 entry)
!                               (format " (line %s)" (nth 3 entry))
!                             "")))))))))
! 
! (defun Info-apropos-matches (string)
!   "Collect STRING matches from all known Info files on your system.
! Return a list of matches where each element is in the format
! \((FILENAME INDEXTEXT NODENAME LINENUMBER))."
    (interactive "sIndex apropos: ")
    (unless (string= string "")
      (let ((pattern (format "\n\\* +\\([^\n]*%s[^\n]*\\):[ 
\t]+\\([^\n]+\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?"
***************
*** 3056,3078 ****
        (setq Info-history ohist
            Info-history-list ohist-list)
        (message "Searching indices...done")
!       (if (null matches)
!         (message "No matches found")
!       (with-current-buffer (get-buffer-create " *info-apropos*")
!         (erase-buffer)
!         (insert "\n\^_\nFile: apropos, Node: Index, Up: (dir)\n")
!         (insert "* Menu: \nNodes whose indices contain `" string "':\n\n")
!         (dolist (entry (nreverse matches))
!           (insert
!            (format "* %-38s (%s)%s.%s\n"
!                    (concat (nth 1 entry) " [" (nth 0 entry) "]:")
!                    (nth 0 entry)
!                    (nth 2 entry)
!                    (if (nth 3 entry)
!                        (concat " (line " (nth 3 entry) ")")
!                      "")))))
!       (Info-find-node 'apropos "Index")
!       (setq Info-complete-cache nil)))))
  
  (defun Info-undefined ()
    "Make command be undefined in Info."
--- 3297,3320 ----
        (setq Info-history ohist
            Info-history-list ohist-list)
        (message "Searching indices...done")
!       (or (nreverse matches) t))))
! 
! ;;;###autoload
! (defun info-apropos (string)
!   "Grovel indices of all known Info files on your system for STRING.
! Build a menu of the possible matches."
!   (interactive "sIndex apropos: ")
!   (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)))
!       (setq nodename (format "Index for `%s'" string))
!       (push (list nodename string (Info-apropos-matches string))
!             Info-apropos-nodes)
!       (Info-find-node Info-apropos-file nodename)))))
  
  (defun Info-undefined ()
    "Make command be undefined in Info."
***************
*** 3248,3253 ****
--- 3490,3496 ----
      (define-key map "g" 'Info-goto-node)
      (define-key map "h" 'Info-help)
      (define-key map "i" 'Info-index)
+     (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)
***************
*** 3830,3836 ****
                 (format "(%s)Top"
                         (if (stringp Info-current-file)
                             (file-name-nondirectory Info-current-file)
-                          ;; Can be `toc', `apropos', or even `history'.
                           Info-current-file)))))
          (insert (if (bolp) "" " > ")
                  (cond
--- 4073,4078 ----
***************
*** 4414,4420 ****
  
  (defun Info-desktop-buffer-misc-data (desktop-dirname)
    "Auxiliary information to be saved in desktop file."
!   (unless (member Info-current-file '(apropos history toc nil))
      (list Info-current-file Info-current-node)))
  
  (defun Info-restore-desktop-buffer (desktop-buffer-file-name
--- 4656,4663 ----
  
  (defun Info-desktop-buffer-misc-data (desktop-dirname)
    "Auxiliary information to be saved in desktop file."
!   (unless (or (null Info-current-file)
!             (Info-virtual-file-p Info-current-file))
      (list Info-current-file Info-current-node)))
  
  (defun Info-restore-desktop-buffer (desktop-buffer-file-name

-- 
Juri Linkov
http://www.jurta.org/emacs/




reply via email to

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