Mercurial > hg > xemacs-beta
comparison lisp/info.el @ 371:cc15677e0335 r21-2b1
Import from CVS: tag r21-2b1
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:03:08 +0200 |
parents | a4f53d9b3154 |
children | 6240c7796c7a |
comparison
equal
deleted
inserted
replaced
370:bd866891f083 | 371:cc15677e0335 |
---|---|
20 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | 20 ;; WITHOUT ANY WARRANTY; without even the implied warranty of |
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
22 ;; General Public License for more details. | 22 ;; General Public License for more details. |
23 | 23 |
24 ;; You should have received a copy of the GNU General Public License | 24 ;; You should have received a copy of the GNU General Public License |
25 ;; along with XEmacs; see the file COPYING. If not, write to the | 25 ;; along with XEmacs; see the file COPYING. If not, write to the |
26 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 26 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
27 ;; Boston, MA 02111-1307, USA. | 27 ;; Boston, MA 02111-1307, USA. |
28 | 28 |
29 ;;; Synched up with: Not synched with FSF. | 29 ;;; Synched up with: Not synched with FSF. |
30 | 30 |
394 use any existing `dir' or `localdir' file and ignore info | 394 use any existing `dir' or `localdir' file and ignore info |
395 directories containing none | 395 directories containing none |
396 `always' auto-generate a directory listing ignoring existing | 396 `always' auto-generate a directory listing ignoring existing |
397 `dir' and `localdir' files | 397 `dir' and `localdir' files |
398 `if-missing', the default, auto-generates a directory listing | 398 `if-missing', the default, auto-generates a directory listing |
399 if no `dir' or `localdir' file is present. Otherwise the | 399 if no `dir' or `localdir' file is present. Otherwise the |
400 contents of any of these files is used instead. | 400 contents of any of these files is used instead. |
401 `if-outdated' auto-generates a directory listing if the `dir' | 401 `if-outdated' auto-generates a directory listing if the `dir' |
402 and `localdir' are either inexistent or outdated (touched | 402 and `localdir' are either inexistent or outdated (touched |
403 less recently than an info file in the same directory)." | 403 less recently than an info file in the same directory)." |
404 :type '(choice (const :tag "never" never) | 404 :type '(choice (const :tag "never" never) |
405 (const :tag "always" always) | 405 (const :tag "always" always) |
406 (const :tag "if-missing" if-missing) | 406 (const :tag "if-missing" if-missing) |
407 (const :tag "if-outdated" if-outdated)) | 407 (const :tag "if-outdated" if-outdated)) |
408 :group 'info) | 408 :group 'info) |
409 | 409 |
410 (defcustom Info-save-auto-generated-dir nil | 410 (defcustom Info-save-auto-generated-dir nil |
411 "*Whether an auto-generated info directory listing should be saved. | 411 "*Whether an auto-generated info directory listing should be saved. |
412 Possible values are: | 412 Possible values are: |
413 nil or `never', the default, auto-generated info directory | 413 nil or `never', the default, auto-generated info directory |
414 information will never be saved. | 414 information will never be saved. |
415 `always', auto-generated info directory information will be saved to | 415 `always', auto-generated info directory information will be saved to |
416 a `dir' file in the same directory overwriting it if it exists | 416 a `dir' file in the same directory overwriting it if it exists |
417 `conservative', auto-generated info directory information will be saved | 417 `conservative', auto-generated info directory information will be saved |
418 to a `dir' file in the same directory but the user is asked before | 418 to a `dir' file in the same directory but the user is asked before |
419 overwriting any existing file." | 419 overwriting any existing file." |
420 :type '(choice (const :tag "never" never) | 420 :type '(choice (const :tag "never" never) |
421 (const :tag "always" always) | 421 (const :tag "always" always) |
422 (const :tag "conservative" conservative)) | 422 (const :tag "conservative" conservative)) |
423 :group 'info) | 423 :group 'info) |
424 | 424 |
425 (defconst Info-emacs-info-file-name "xemacs.info" | 425 (defvar Info-emacs-info-file-name "xemacs.info" |
426 "The filename of the XEmacs info for `Info-goto-emacs-command-node' | 426 "The filename of the XEmacs info for |
427 (`\\<help-mode-map>\\[Info-goto-emacs-command-node]')") | 427 `Info-goto-emacs-command-node' (`\\<help-mode-map>\\[Info-goto-emacs-command-node]')") |
428 | 428 |
429 ;;;###autoload | 429 ;;;###autoload |
430 (defvar Info-directory-list nil | 430 (defvar Info-directory-list nil |
431 "List of directories to search for Info documentation files. | 431 "List of directories to search for Info documentation files. |
432 | 432 |
433 The first directory in this list, the \"dir\" file there will become | 433 The first directory in this list, the \"dir\" file there will become |
434 the (dir)Top node of the Info documentation tree. | 434 the (dir)Top node of the Info documentation tree. If you wish to |
435 | 435 modify the info search path, use `M-x customize-variable, |
436 Note: DO NOT use the `customize' interface to change the value of this | 436 Info-directory-list' to do so.") |
437 variable. Its value is created dynamically on each startup, depending | 437 |
438 on XEmacs packages installed on the system. If you want to change the | 438 (defcustom Info-localdir-heading-regexp |
439 search path, make the needed modifications on the variable's value | 439 "^Locally installed XEmacs Packages:?" |
440 from .emacs. For instance: | |
441 | |
442 (setq Info-directory-list (cons \"~/info\" Info-directory-list))") | |
443 | |
444 ;; This could as well be hard-coded since ${srcdir}/info/dir is in CVS --dv | |
445 (defconst Info-localdir-heading-regexp "^Local Packages:$" | |
446 "The menu part of localdir files will be inserted below this topic | 440 "The menu part of localdir files will be inserted below this topic |
447 heading.") | 441 heading." |
442 :type 'regexp | |
443 :group 'info) | |
448 | 444 |
449 (defface info-node '((t (:bold t :italic t))) | 445 (defface info-node '((t (:bold t :italic t))) |
450 "Face used for node links in info." | 446 "Face used for node links in info." |
451 :group 'info-faces) | 447 :group 'info-faces) |
452 | 448 |
453 (defface info-xref '((t (:bold t))) | 449 (defface info-xref '((t (:bold t))) |
454 "Face used for cross-references in info." | 450 "Face used for cross-references in info." |
455 :group 'info-faces) | 451 :group 'info-faces) |
456 | 452 |
457 ;; This list is based on Karl Berry-s advice about extensions `info' itself | 453 ;; Is this right for NT? .zip, with -c for to stdout, right? |
458 ;; might encounter. --dv | 454 (defvar Info-suffix-list '( ("" . nil) |
459 (defcustom Info-suffix-list '(("" . nil) | 455 (".info" . nil) |
460 (".info" . nil) | 456 (".info.gz" . "gzip -dc %s") |
461 (".gz" . "gzip -dc %s") | 457 (".info-z" . "gzip -dc %s") |
462 (".info.gz" . "gzip -dc %s") | 458 (".info.Z" . "uncompress -c %s") |
463 (".z" . "gzip -dc %s") | 459 (".gz" . "gzip -dc %s") |
464 (".info.z" . "gzip -dc %s") | 460 (".Z" . "uncompress -c %s") |
465 (".bz2" . "bzip2 -dc %s") | 461 (".zip" . "unzip -c %s") ) |
466 (".info.bz2" . "bzip2 -dc %s") | 462 "List of file name suffixes and associated decoding commands. |
467 (".Z" . "uncompress -c %s") | |
468 (".info.Z" . "uncompress -c %s") | |
469 (".zip" . "unzip -c %s") | |
470 (".info.zip" . "unzip -c %s") | |
471 (".y" . "cat %s | unyabba") | |
472 ("info.y" . "cat %s | unyabba") | |
473 ;; These ones are for MS-DOS filenames. | |
474 (".inf" . nil) | |
475 (".igz" . "gzip -dc %s") | |
476 (".inz" . "gzip -c %s")) | |
477 "*List of file name suffixes and associated decoding commands. | |
478 Each entry should be (SUFFIX . STRING); if STRING contains %s, that is | 463 Each entry should be (SUFFIX . STRING); if STRING contains %s, that is |
479 changed to name of the file to decode, otherwise the file is given to | 464 changed to name of the file to decode, otherwise the file is given to |
480 the command as standard input. If STRING is nil, no decoding is done." | 465 the command as standard input. If STRING is nil, no decoding is done.") |
481 :type '(repeat (cons (string :tag "suffix") | 466 |
482 (choice :tag "command" | 467 (defvar Info-footnote-tag "Note" |
483 (const :tag "none" :value nil) | |
484 (string :tag "")))) | |
485 :group 'info) | |
486 | |
487 (defcustom Info-footnote-tag "Note" | |
488 "*Symbol that identifies a footnote or cross-reference. | 468 "*Symbol that identifies a footnote or cross-reference. |
489 All \"*Note\" references will be changed to use this word instead." | 469 All \"*Note\" references will be changed to use this word instead.") |
490 :type 'string | |
491 :group 'info) | |
492 | 470 |
493 (defvar Info-current-file nil | 471 (defvar Info-current-file nil |
494 "Info file that Info is now looking at, or nil. | 472 "Info file that Info is now looking at, or nil. |
495 This is the name that was specified in Info, not the actual file name. | 473 This is the name that was specified in Info, not the actual file name. |
496 It doesn't contain directory names or file name extensions added by Info.") | 474 It doesn't contain directory names or file name extensions added by Info.") |
512 (defvar Info-current-annotation-completions nil | 490 (defvar Info-current-annotation-completions nil |
513 "Cached completion list for current annotation files.") | 491 "Cached completion list for current annotation files.") |
514 | 492 |
515 (defvar Info-index-alternatives nil | 493 (defvar Info-index-alternatives nil |
516 "List of possible matches for last Info-index command.") | 494 "List of possible matches for last Info-index command.") |
517 | |
518 (defvar Info-index-first-alternative nil) | 495 (defvar Info-index-first-alternative nil) |
519 | 496 |
520 (defcustom Info-annotations-path '("~/.xemacs/info.notes" | 497 (defcustom Info-annotations-path '("~/.xemacs/info.notes" |
521 "~/.infonotes" | 498 "~/.infonotes" |
522 "/usr/lib/info.notes") | 499 "/usr/lib/info.notes") |
541 This is the file .../info/dir, which contains the topmost node of the | 518 This is the file .../info/dir, which contains the topmost node of the |
542 Info hierarchy. The first time you invoke Info you start off | 519 Info hierarchy. The first time you invoke Info you start off |
543 looking at that node, which is (dir)Top. | 520 looking at that node, which is (dir)Top. |
544 | 521 |
545 File: dir Node: Top This is the top of the INFO tree | 522 File: dir Node: Top This is the top of the INFO tree |
546 This (the Directory node) gives a menu of major topics. | 523 This (the Directory node) gives a menu of major topics. |
547 | 524 |
548 * Menu: The list of major topics begins on the next line. | 525 * Menu: The list of major topics begins on the next line. |
549 | 526 |
550 ") | 527 ") |
551 | 528 |
552 (defcustom Info-no-description-string "[No description available]" | 529 (defvar Info-no-description-string "[No description available]" |
553 "*Description string for info files that have none" | 530 "Description string for info files that have none") |
554 :type 'string | |
555 :group 'info) | |
556 | 531 |
557 ;;;###autoload | 532 ;;;###autoload |
558 (defun info (&optional file) | 533 (defun info (&optional file) |
559 "Enter Info, the documentation browser. | 534 "Enter Info, the documentation browser. |
560 Optional argument FILE specifies the file to examine; | 535 Optional argument FILE specifies the file to examine; |
613 ;; empty filename is simple case | 588 ;; empty filename is simple case |
614 ((null filename) | 589 ((null filename) |
615 (Info-find-file-node nil nodename no-going-back tryfile line)) | 590 (Info-find-file-node nil nodename no-going-back tryfile line)) |
616 ;; Convert filename to lower case if not found as specified. | 591 ;; Convert filename to lower case if not found as specified. |
617 ;; Expand it, look harder... | 592 ;; Expand it, look harder... |
618 ((let ((fname (substitute-in-file-name filename)) | 593 ((let (temp temp-downcase found |
619 temp found) | 594 (fname (substitute-in-file-name filename))) |
620 (let ((dirs (cond | 595 (let ((dirs (cond |
621 ;; If specified name starts with `./', then just try | 596 ((string-match "^\\./" fname) ; If specified name starts with `./' |
622 ;; current directory. No point in searching for an absolute | 597 (list default-directory)) ; then just try current directory. |
623 ;; file name | |
624 ((string-match "^\\./" fname) | |
625 (list default-directory)) | |
626 ((file-name-absolute-p fname) | 598 ((file-name-absolute-p fname) |
627 '(nil)) | 599 '(nil)) ; No point in searching for an absolute file name |
628 (Info-additional-search-directory-list | 600 (Info-additional-search-directory-list |
629 (append Info-directory-list | 601 (append Info-directory-list |
630 Info-additional-search-directory-list)) | 602 Info-additional-search-directory-list)) |
631 (t Info-directory-list)))) | 603 (t Info-directory-list)))) |
632 ;; Search the directory list for file FNAME. | 604 ;; Search the directory list for file FNAME. |
633 (while (and dirs (not found)) | 605 (while (and dirs (not found)) |
634 (setq temp (expand-file-name fname (car dirs))) | 606 (setq temp (expand-file-name fname (car dirs))) |
635 (setq found (Info-suffixed-file temp)) | 607 (setq temp-downcase |
608 (expand-file-name (downcase fname) (car dirs))) | |
609 (if (equal temp-downcase temp) (setq temp-downcase nil)) | |
610 ;; Try several variants of specified name. | |
611 ;; Try downcasing, appending a suffix, or both. | |
612 (setq found (Info-suffixed-file temp temp-downcase)) | |
636 (setq dirs (cdr dirs))) | 613 (setq dirs (cdr dirs))) |
637 (if found | 614 (if found |
638 (progn (setq filename (expand-file-name found)) | 615 (progn (setq filename (expand-file-name found)) |
639 t)))) | 616 t)))) |
640 (Info-find-file-node filename nodename no-going-back tryfile line)) | 617 (Info-find-file-node filename nodename no-going-back tryfile line)) |
641 ;; Look for a URL. This pattern is stolen from w3.el to prevent | 618 ;; Look for a URL. This pattern is stolen from w3.el to prevent |
642 ;; loading it if we won't need it. | 619 ;; loading it if we won't need it. |
813 ;; constructed Info-dir-contents. | 790 ;; constructed Info-dir-contents. |
814 (defvar Info-dir-file-attributes nil) | 791 (defvar Info-dir-file-attributes nil) |
815 | 792 |
816 (defun Info-insert-dir () | 793 (defun Info-insert-dir () |
817 "Construct the Info directory node by merging the files named | 794 "Construct the Info directory node by merging the files named |
818 \"dir\" or \"localdir\" from the directories in `Info-directory-list'. | 795 \"dir\" or \"localdir\" from the directories in `Info-directory-list' |
819 The \"dir\" files will take precedence in cases where both exist. It | 796 The \"dir\" files will take precedence in cases where both exist. It |
820 sets the *info* buffer's `default-directory' to the first directory we | 797 sets the *info* buffer's `default-directory' to the first directory we |
821 actually get any text from." | 798 actually get any text from." |
822 (if (and Info-dir-contents Info-dir-file-attributes | 799 (if (and Info-dir-contents Info-dir-file-attributes |
823 ;; Verify that none of the files we used has changed | 800 ;; Verify that none of the files we used has changed |
839 ;; Search the directory list for the directory file. | 816 ;; Search the directory list for the directory file. |
840 (while dirs | 817 (while dirs |
841 (let ((truename (file-truename (expand-file-name (car dirs))))) | 818 (let ((truename (file-truename (expand-file-name (car dirs))))) |
842 (or (member truename dirs-done) | 819 (or (member truename dirs-done) |
843 (member (directory-file-name truename) dirs-done) | 820 (member (directory-file-name truename) dirs-done) |
844 ;; Karl Berry recently added the ability all possibilities for | 821 ;; Try several variants of specified name. |
845 ;; extension as for normal info files. This code however is | 822 ;; Try upcasing, appending `.info', or both. |
846 ;; still unsatisfactory: if one day, we find a compressed dir | 823 (let* (buf |
847 ;; file (which looks possible), we should be able to handle it | 824 file |
848 ;; (which means decompress and read it, update it, save and | 825 (attrs |
849 ;; recompress it). --dv | 826 (or |
850 (let ((trials '("dir" "DIR" | 827 (progn (setq file (expand-file-name "dir" truename)) |
851 "dir.info" "DIR.INFO" | 828 (file-attributes file)) |
852 "dir.inf" "DIR.INF" | 829 (progn (setq file (expand-file-name "DIR" truename)) |
853 "localdir" "LOCALDIR" | 830 (file-attributes file)) |
854 "localdir.info" "LOCALDIR.INFO" | 831 (progn (setq file (expand-file-name "dir.info" truename)) |
855 "localdir.inf" "LOCALDIR.INF")) | 832 (file-attributes file)) |
856 buf file attrs) | 833 (progn (setq file (expand-file-name "DIR.INFO" truename)) |
857 (catch 'found | 834 (file-attributes file)) |
858 (while (setq file (pop trials)) | 835 (progn (setq file (expand-file-name "localdir" truename)) |
859 (setq file (expand-file-name file truename)) | 836 (file-attributes file)) |
860 (and (setq attrs (file-attributes file)) | 837 (progn (setq file (expand-file-name "dir" truename)) |
861 (throw 'found t)))) | 838 nil) |
862 (unless file | 839 ))) |
863 (setq file (expand-file-name "dir" truename))) | |
864 (setq dirs-done | 840 (setq dirs-done |
865 (cons truename | 841 (cons truename |
866 (cons (directory-file-name truename) | 842 (cons (directory-file-name truename) |
867 dirs-done))) | 843 dirs-done))) |
868 (Info-maybe-update-dir file) | 844 (Info-maybe-update-dir file) |
875 (set-buffer (or buf | 851 (set-buffer (or buf |
876 (generate-new-buffer | 852 (generate-new-buffer |
877 (if (string-match "localdir" file) | 853 (if (string-match "localdir" file) |
878 "localdir" | 854 "localdir" |
879 "info dir")))) | 855 "info dir")))) |
880 (if (not buf) | 856 (if (not buf) |
881 (insert-file-contents file)) | 857 (insert-file-contents file)) |
882 (if (string-match "localdir" (buffer-name)) | 858 (if (string-match "localdir" (buffer-name)) |
883 (setq lbuffers (cons (current-buffer) lbuffers)) | 859 (setq lbuffers (cons (current-buffer) lbuffers)) |
884 (setq buffers (cons (current-buffer) buffers))) | 860 (setq buffers (cons (current-buffer) buffers))) |
885 (if attrs | 861 (if attrs |
886 (setq Info-dir-file-attributes | 862 (setq Info-dir-file-attributes |
887 (cons (cons file attrs) | 863 (cons (cons file attrs) |
888 Info-dir-file-attributes))))))) | 864 Info-dir-file-attributes))))))) |
889 (or (cdr dirs) (setq Info-dir-contents-directory (car dirs))) | 865 (or (cdr dirs) (setq Info-dir-contents-directory (car dirs))) |
890 (setq dirs (cdr dirs)))) | 866 (setq dirs (cdr dirs)))) |
891 | 867 |
892 ;; ensure that the localdir files are inserted last, and reverse | 868 ;; ensure that the localdir files are inserted last, and reverse |
893 ;; the list of them so that when they get pushed in, they appear | 869 ;; the list of them so that when they get pushed in, they appear |
894 ;; in the same order they got specified in the path, from top to | 870 ;; in the same order they got specified in the path, from top to |
895 ;; bottom. | 871 ;; bottom. |
896 (nconc buffers (reverse lbuffers)) | 872 (nconc buffers (reverse lbuffers)) |
897 | 873 |
898 (or buffers | 874 (or buffers |
899 (error "Can't find the Info directory node")) | 875 (error "Can't find the Info directory node")) |
900 ;; Distinguish the dir file that comes with Emacs from all the | 876 ;; Distinguish the dir file that comes with Emacs from all the |
901 ;; others. Yes, that is really what this is supposed to do. | 877 ;; others. Yes, that is really what this is supposed to do. |
902 ;; If it doesn't work, fix it. | 878 ;; If it doesn't work, fix it. |
961 (search-forward "\n\^_" nil 'move) | 937 (search-forward "\n\^_" nil 'move) |
962 (beginning-of-line) | 938 (beginning-of-line) |
963 (setq end (point)) | 939 (setq end (point)) |
964 (setq nodes (cons (list nodename other beg end) nodes)))))) | 940 (setq nodes (cons (list nodename other beg end) nodes)))))) |
965 (setq others (cdr others)))) | 941 (setq others (cdr others)))) |
966 | 942 |
967 ;; Add to the main menu a menu item for each other node. | 943 ;; Add to the main menu a menu item for each other node. |
968 (re-search-forward "^\\* Menu:" nil t) | 944 (re-search-forward "^\\* Menu:" nil t) |
969 (forward-line 1) | 945 (forward-line 1) |
970 (let ((menu-items '("top")) | 946 (let ((menu-items '("top")) |
971 (nodes nodes) | 947 (nodes nodes) |
1014 (message "Composing main Info directory...done")) | 990 (message "Composing main Info directory...done")) |
1015 (setq Info-dir-contents (buffer-string))) | 991 (setq Info-dir-contents (buffer-string))) |
1016 (setq default-directory Info-dir-contents-directory) | 992 (setq default-directory Info-dir-contents-directory) |
1017 (setq buffer-file-name (caar Info-dir-file-attributes))) | 993 (setq buffer-file-name (caar Info-dir-file-attributes))) |
1018 | 994 |
1019 (defmacro Info-directory-files (dir-file &optional all full nosort files-only) | |
1020 "Return a list of Info files living in the same directory as DIR-FILE. | |
1021 This list actually contains the files living in this directory, except for | |
1022 the dir file itself and the secondary info files (foo-1 foo-2 etc). | |
1023 | |
1024 If the optional argument ALL is non nil, the secondary info files are also | |
1025 included in the list. | |
1026 | |
1027 Please refer to the function `directory-files' for the meaning of the other | |
1028 optional arguments." | |
1029 `(let* ((dir (file-name-directory ,dir-file)) | |
1030 (all-files (remove ,dir-file (directory-files dir ',full nil ',nosort | |
1031 ',files-only)))) | |
1032 (setq all-files | |
1033 (if ,full | |
1034 (remove (concat dir ".") | |
1035 (remove (concat dir "..") all-files)) | |
1036 (remove "." | |
1037 (remove ".." all-files)))) | |
1038 (if ,all | |
1039 all-files | |
1040 (let ((suff-match | |
1041 (concat "-[0-9]+\\(" | |
1042 ;; Extract all known compression suffixes from | |
1043 ;; Info-suffix-list. These suffixes can typically be | |
1044 ;; found in entries of the form `.info.something'. | |
1045 (let ((suff-list Info-suffix-list) | |
1046 suff regexp) | |
1047 (while (setq suff (pop suff-list)) | |
1048 (and (string-match "^\\.info" (car suff)) | |
1049 (setq regexp (concat regexp | |
1050 (regexp-quote | |
1051 (substring | |
1052 (car suff) 5)) | |
1053 (and suff-list "\\|"))))) | |
1054 regexp) | |
1055 "\\)?$")) | |
1056 info-files file) | |
1057 (while (setq file (pop all-files)) | |
1058 (or (string-match suff-match file) | |
1059 (push file info-files))) | |
1060 (reverse info-files) | |
1061 )) | |
1062 )) | |
1063 | |
1064 (defun Info-maybe-update-dir (file) | 995 (defun Info-maybe-update-dir (file) |
1065 "Rebuild dir or localdir according to `Info-auto-generate-directory'." | 996 "Rebuild dir or localdir according to `Info-auto-generate-directory'." |
1066 (unless (or (not (file-exists-p (file-name-directory file))) | 997 (unless (or (not (file-exists-p (file-name-directory file))) |
1067 (null (Info-directory-files file 'all))) | 998 (null (directory-files (file-name-directory file) nil "\\.info"))) |
1068 (if (not (find-buffer-visiting file)) | 999 (if (not (find-buffer-visiting file)) |
1069 (if (not (file-exists-p file)) | 1000 (if (not (file-exists-p file)) |
1070 (if (or (eq Info-auto-generate-directory 'always) | 1001 (if (or (eq Info-auto-generate-directory 'always) |
1071 (eq Info-auto-generate-directory 'if-missing)) | 1002 (eq Info-auto-generate-directory 'if-missing)) |
1072 (Info-build-dir-anew (file-name-directory file))) | 1003 (Info-build-dir-anew (file-name-directory file))) |
1073 (if (or (eq Info-auto-generate-directory 'always) | 1004 (if (or (eq Info-auto-generate-directory 'always) |
1074 (and (eq Info-auto-generate-directory 'if-outdated) | 1005 (and (eq Info-auto-generate-directory 'if-outdated) |
1075 (Info-dir-outdated-p file))) | 1006 (Info-dir-outdated-p file))) |
1076 (Info-rebuild-dir file)))))) | 1007 (Info-rebuild-dir file)))))) |
1081 (defun Info-dir-outdated-p (file) | 1012 (defun Info-dir-outdated-p (file) |
1082 "Return non-nil if dir or localdir is outdated. | 1013 "Return non-nil if dir or localdir is outdated. |
1083 dir or localdir are outdated when an info file in the same | 1014 dir or localdir are outdated when an info file in the same |
1084 directory has been modified more recently." | 1015 directory has been modified more recently." |
1085 (let ((dir-mod-time (nth 5 (file-attributes file))) | 1016 (let ((dir-mod-time (nth 5 (file-attributes file))) |
1086 f-mod-time newer) | 1017 f-mod-time |
1018 newer) | |
1087 (setq Info-dir-newer-info-files nil) | 1019 (setq Info-dir-newer-info-files nil) |
1088 (mapcar | 1020 (mapcar |
1089 '(lambda (f) | 1021 '(lambda (f) |
1090 (prog2 | 1022 (prog2 |
1091 (setq f-mod-time (nth 5 (file-attributes f))) | 1023 (setq f-mod-time (nth 5 (file-attributes f))) |
1092 (setq newer (or (> (car f-mod-time) (car dir-mod-time)) | 1024 (setq newer (or (> (car f-mod-time) (car dir-mod-time)) |
1093 (and (= (car f-mod-time) (car dir-mod-time)) | 1025 (and (= (car f-mod-time) (car dir-mod-time)) |
1094 (> (car (cdr f-mod-time)) | 1026 (> (car (cdr f-mod-time)) (car (cdr dir-mod-time)))))) |
1095 (car (cdr dir-mod-time)))))) | 1027 (if (and (file-readable-p f) |
1096 (if (and (file-readable-p f) newer) | 1028 newer) |
1097 (setq Info-dir-newer-info-files | 1029 (setq Info-dir-newer-info-files |
1098 (cons f Info-dir-newer-info-files))))) | 1030 (cons f Info-dir-newer-info-files))))) |
1099 (Info-directory-files file nil 'fullname 'nosort t)) | 1031 (directory-files (file-name-directory file) |
1032 'fullname | |
1033 ".*\\.info\\(.gz\\|.Z\\|-z\\|.zip\\)?$" | |
1034 'nosort | |
1035 t)) | |
1100 Info-dir-newer-info-files)) | 1036 Info-dir-newer-info-files)) |
1101 | 1037 |
1102 (defun Info-extract-dir-entry-from (file) | 1038 (defun Info-extract-dir-entry-from (file) |
1103 "Extract the dir entry from the info FILE. | 1039 "Extract the dir entry from the info FILE. |
1104 The dir entry is delimited by the markers `START-INFO-DIR-ENTRY' | 1040 The dir entry is delimited by the markers `START-INFO-DIR-ENTRY' |
1122 (let (entry entries) | 1058 (let (entry entries) |
1123 (save-excursion | 1059 (save-excursion |
1124 (save-restriction | 1060 (save-restriction |
1125 (narrow-to-region beg end) | 1061 (narrow-to-region beg end) |
1126 (goto-char beg) | 1062 (goto-char beg) |
1127 (while (re-search-forward | 1063 (while (re-search-forward "^\\* \\([^:]+\\):\\([ \t]*(\\([^)]*\\))\\w*\\.\\|:\\)" nil t) |
1128 "^\\* \\([^:]+\\):\\([ \t]*(\\([^)]*\\))\\w*\\.\\|:\\)" nil t) | |
1129 (setq entry (list (match-string 2) | 1064 (setq entry (list (match-string 2) |
1130 (match-string 1) | 1065 (match-string 1) |
1131 (downcase (or (match-string 3) | 1066 (downcase (or (match-string 3) |
1132 (match-string 1))))) | 1067 (match-string 1))))) |
1133 (setq entry | 1068 (setq entry |
1134 (cons (nreverse | 1069 (cons (nreverse |
1135 (cdr | 1070 (cdr |
1136 (nreverse | 1071 (nreverse |
1137 (split-string | 1072 (split-string |
1138 (buffer-substring | 1073 (buffer-substring |
1139 (re-search-forward "[ \t]*" nil t) | 1074 (re-search-forward "[ \t]*" nil t) |
1140 (or (and (re-search-forward "^[^ \t]" nil t) | 1075 (or (and (re-search-forward "^[^ \t]" nil t) |
1141 (goto-char (match-beginning 0))) | 1076 (goto-char (match-beginning 0))) |
1142 (point-max))) | 1077 (point-max))) |
1143 "[ \t]*\n[ \t]*")))) | 1078 "[ \t]*\n[ \t]*")))) |
1154 (setq len (length (concat (car e) | 1089 (setq len (length (concat (car e) |
1155 (car (cdr e))))) | 1090 (car (cdr e))))) |
1156 (if (> len description-col) | 1091 (if (> len description-col) |
1157 (setq description-col len))) | 1092 (setq description-col len))) |
1158 entries) | 1093 entries) |
1159 (setq description-col (+ 5 description-col)) | 1094 (setq description-col (+ 5 description-col)) |
1160 (mapcar '(lambda (e) | 1095 (mapcar '(lambda (e) |
1161 (setq e (cdr e)) ; Drop filename | 1096 (setq e (cdr e)) ; Drop filename |
1162 (insert "* " (car e) ":" (car (cdr e))) | 1097 (insert "* " (car e) ":" (car (cdr e))) |
1163 (setq e (car (cdr (cdr e)))) | 1098 (setq e (car (cdr (cdr e)))) |
1164 (while e | 1099 (while e |
1169 (insert "\n"))) | 1104 (insert "\n"))) |
1170 | 1105 |
1171 | 1106 |
1172 (defun Info-build-dir-anew (directory) | 1107 (defun Info-build-dir-anew (directory) |
1173 "Build info directory information for DIRECTORY. | 1108 "Build info directory information for DIRECTORY. |
1174 The generated directory listing may be saved to a `dir' according | 1109 The generated directory listing may be saved to a `dir' according |
1175 to the value of `Info-save-auto-generated-dir'" | 1110 to the value of `Info-save-auto-generated-dir'" |
1176 (save-excursion | 1111 (save-excursion |
1177 (let* ((dirfile (expand-file-name "dir" directory)) | 1112 (let* ((dirfile (expand-file-name "dir" directory)) |
1178 (to-temp (or (null Info-save-auto-generated-dir) | 1113 (to-temp (or (null Info-save-auto-generated-dir) |
1179 (eq Info-save-auto-generated-dir 'never) | 1114 (eq Info-save-auto-generated-dir 'never) |
1180 (and (not (file-writable-p dirfile)) | 1115 (and (not (file-writable-p dirfile)) |
1181 (message "File not writable %s. Using temporary." | 1116 (message "File not writable %s. Using temporary." dirfile)))) |
1182 dirfile)))) | 1117 (info-files |
1183 (info-files (Info-directory-files dirfile nil 'fullname nil t))) | 1118 (directory-files directory |
1119 'fullname | |
1120 ".*\\.info\\(.gz\\|.Z\\|-z\\|.zip\\)?$" | |
1121 nil | |
1122 t))) | |
1184 (if to-temp | 1123 (if to-temp |
1185 (message "Creating temporary dir in %s..." directory) | 1124 (message "Creating temporary dir in %s..." directory) |
1186 (message "Creating %s..." dirfile)) | 1125 (message "Creating %s..." dirfile)) |
1187 (set-buffer (find-file-noselect dirfile t)) | 1126 (set-buffer (find-file-noselect dirfile t)) |
1188 (setq buffer-read-only nil) | 1127 (setq buffer-read-only nil) |
1189 (erase-buffer) | 1128 (erase-buffer) |
1190 (insert Info-dir-prologue "Info files in " directory ":\n\n") | 1129 (insert Info-dir-prologue |
1191 (Info-dump-dir-entries | 1130 "Info files in " directory ":\n\n") |
1192 (mapcar | 1131 (Info-dump-dir-entries |
1132 (mapcar | |
1193 '(lambda (f) | 1133 '(lambda (f) |
1194 (or (Info-extract-dir-entry-from f) | 1134 (or (Info-extract-dir-entry-from f) |
1195 (list 'dummy | 1135 (list 'dummy |
1196 (progn (string-match "\\([^.]*\\)\\(\\..*\\)?$" | 1136 (progn |
1197 (file-name-nondirectory f)) | 1137 (string-match "\\(.*\\)\\.info\\(.gz\\|.Z\\|-z\\|.zip\\)?$" |
1198 (capitalize | 1138 (file-name-nondirectory f)) |
1199 (match-string 1 (file-name-nondirectory f)))) | 1139 (capitalize (match-string 1 (file-name-nondirectory f)))) |
1200 ":" | 1140 ":" |
1201 (list Info-no-description-string)))) | 1141 (list Info-no-description-string)))) |
1202 info-files)) | 1142 info-files)) |
1203 (if to-temp | 1143 (if to-temp |
1204 (set-buffer-modified-p nil) | 1144 (set-buffer-modified-p nil) |
1208 (message "Creating %s...done" dirfile))))) | 1148 (message "Creating %s...done" dirfile))))) |
1209 | 1149 |
1210 | 1150 |
1211 (defun Info-rebuild-dir (file) | 1151 (defun Info-rebuild-dir (file) |
1212 "Build info directory information in the directory of dir FILE. | 1152 "Build info directory information in the directory of dir FILE. |
1213 Description of info files are merged from the info files in the | 1153 Description of info files are merged from the info files in the |
1214 directory and the contents of FILE with the description in info files | 1154 directory and the contents of FILE with the description in info files |
1215 taking precedence over descriptions in FILE. | 1155 taking precedence over descriptions in FILE. |
1216 The generated directory listing may be saved to a `dir' according to | 1156 The generated directory listing may be saved to a `dir' according to |
1217 the value of `Info-save-auto-generated-dir' " | 1157 the value of `Info-save-auto-generated-dir' " |
1218 (save-excursion | 1158 (save-excursion |
1219 (save-restriction | 1159 (save-restriction |
1220 (let (dir-section-contents dir-full-contents | 1160 (let (dir-section-contents dir-full-contents |
1221 dir-entry | 1161 dir-entry |
1222 file-dir-entry | 1162 file-dir-entry |
1223 mark next-section | 1163 mark next-section |
1224 not-first-section | 1164 not-first-section |
1225 (to-temp | 1165 (to-temp |
1226 (or (null Info-save-auto-generated-dir) | 1166 (or (null Info-save-auto-generated-dir) |
1227 (eq Info-save-auto-generated-dir 'never) | 1167 (eq Info-save-auto-generated-dir 'never) |
1228 (and (eq Info-save-auto-generated-dir 'always) | 1168 (and (eq Info-save-auto-generated-dir 'always) |
1229 (not (file-writable-p file)) | 1169 (not (file-writable-p file)) |
1230 (message "File not writable %s. Using temporary." file)) | 1170 (message "File not writable %s. Using temporary." file)) |
1231 (and (eq Info-save-auto-generated-dir 'conservative) | 1171 (and (eq Info-save-auto-generated-dir 'conservative) |
1232 (or (and (not (file-writable-p file)) | 1172 (or (and (not (file-writable-p file)) |
1233 (message | 1173 (message "File not writable %s. Using temporary." file)) |
1234 "File not writable %s. Using temporary." file)) | 1174 (not (y-or-n-p |
1235 (not (y-or-n-p | 1175 (message "%s is outdated. Overwrite ? " |
1236 (message "%s is outdated. Overwrite ? " | |
1237 file)))))))) | 1176 file)))))))) |
1238 (set-buffer (find-file-noselect file t)) | 1177 (set-buffer (find-file-noselect file t)) |
1239 (setq buffer-read-only nil) | 1178 (setq buffer-read-only nil) |
1240 (if to-temp | 1179 (if to-temp |
1241 (message "Rebuilding temporary %s..." file) | 1180 (message "Rebuilding temporary %s..." file) |
1247 (re-search-forward "^\\* Menu:.*$" nil t) | 1186 (re-search-forward "^\\* Menu:.*$" nil t) |
1248 (setq mark (and (re-search-forward "^\\* " nil t) | 1187 (setq mark (and (re-search-forward "^\\* " nil t) |
1249 (match-beginning 0)))) | 1188 (match-beginning 0)))) |
1250 (throw 'done nil)) | 1189 (throw 'done nil)) |
1251 (setq dir-full-contents (Info-parse-dir-entries mark (point-max))) | 1190 (setq dir-full-contents (Info-parse-dir-entries mark (point-max))) |
1252 (setq next-section (or (and (re-search-forward | 1191 (setq next-section (or (and (re-search-forward "^[^* \t].*:[ \t]*$" nil t) |
1253 "^[^* \t].*:[ \t]*$" nil t) | |
1254 (match-beginning 0)) | 1192 (match-beginning 0)) |
1255 (point-max))) | 1193 (point-max))) |
1256 (while next-section | 1194 (while next-section |
1257 (narrow-to-region mark next-section) | 1195 (narrow-to-region mark next-section) |
1258 (setq dir-section-contents (nreverse (Info-parse-dir-entries | 1196 (setq dir-section-contents (nreverse (Info-parse-dir-entries (point-min) |
1259 (point-min) (point-max)))) | 1197 (point-max)))) |
1260 (mapcar | 1198 (mapcar '(lambda (file) |
1261 '(lambda (file) | 1199 (setq dir-entry (assoc (downcase |
1262 (setq dir-entry (assoc (downcase | 1200 (file-name-sans-extension |
1263 (file-name-sans-extension | 1201 (file-name-nondirectory file))) |
1264 (file-name-nondirectory file))) | 1202 dir-section-contents) |
1265 dir-section-contents) | 1203 file-dir-entry (Info-extract-dir-entry-from file)) |
1266 file-dir-entry (Info-extract-dir-entry-from file)) | 1204 (if dir-entry |
1267 (if dir-entry | 1205 (if file-dir-entry |
1268 (if file-dir-entry | 1206 ;; A dir entry in the info file takes precedence over an |
1269 ;; A dir entry in the info file takes precedence over | 1207 ;; existing entry in the dir file |
1270 ;; an existing entry in the dir file | 1208 (setcdr dir-entry (cdr file-dir-entry))) |
1271 (setcdr dir-entry (cdr file-dir-entry))) | 1209 (unless (or not-first-section |
1272 (unless (or not-first-section | 1210 (assoc (downcase |
1273 (assoc (downcase | 1211 (file-name-sans-extension |
1274 (file-name-sans-extension | 1212 (file-name-nondirectory file))) |
1275 (file-name-nondirectory file))) | 1213 dir-full-contents)) |
1276 dir-full-contents)) | 1214 (if file-dir-entry |
1277 (if file-dir-entry | 1215 (setq dir-section-contents (cons file-dir-entry |
1278 (setq dir-section-contents | 1216 dir-section-contents)) |
1279 (cons file-dir-entry dir-section-contents)) | 1217 (setq dir-section-contents |
1280 (setq dir-section-contents | 1218 (cons (list 'dummy |
1281 (cons (list 'dummy | 1219 (capitalize (file-name-sans-extension |
1282 (capitalize (file-name-sans-extension | 1220 (file-name-nondirectory file))) |
1283 (file-name-nondirectory | 1221 ":" |
1284 file))) | 1222 (list Info-no-description-string)) |
1285 ":" | 1223 dir-section-contents)))))) |
1286 (list Info-no-description-string)) | 1224 Info-dir-newer-info-files) |
1287 dir-section-contents)))))) | |
1288 Info-dir-newer-info-files) | |
1289 (delete-region (point-min) (point-max)) | 1225 (delete-region (point-min) (point-max)) |
1290 (Info-dump-dir-entries (nreverse dir-section-contents)) | 1226 (Info-dump-dir-entries (nreverse dir-section-contents)) |
1291 (widen) | 1227 (widen) |
1292 (if (= next-section (point-max)) | 1228 (if (= next-section (point-max)) |
1293 (setq next-section nil) | 1229 (setq next-section nil) |
1294 (or (setq mark (and (re-search-forward "^\\* " nil t) | 1230 (or (setq mark (and (re-search-forward "^\\* " nil t) |
1295 (match-beginning 0))) | 1231 (match-beginning 0))) |
1296 (throw 'done nil)) | 1232 (throw 'done nil)) |
1297 (setq next-section (or (and (re-search-forward | 1233 (setq next-section (or (and (re-search-forward "^[^* \t].*:[ \t]*$" nil t) |
1298 "^[^* \t].*:[ \t]*$" nil t) | |
1299 (match-beginning 0)) | 1234 (match-beginning 0)) |
1300 (point-max)))) | 1235 (point-max)))) |
1301 (setq not-first-section t))) | 1236 (setq not-first-section t))) |
1302 (if to-temp | 1237 (if to-temp |
1303 (progn | 1238 (progn |
1304 (set-buffer-modified-p nil) | 1239 (set-buffer-modified-p nil) |
1305 (message "Rebuilding temporary %s...done" file)) | 1240 (message "Rebuilding temporary %s...done" file)) |
1306 (save-buffer) | 1241 (save-buffer) |
1307 (message "Rebuilding %s...done" file)))))) | 1242 (message "Rebuilding %s...done" file)))))) |
1308 | 1243 |
1309 ;;;###autoload | 1244 ;;;###autoload |
1310 (defun Info-batch-rebuild-dir () | 1245 (defun Info-batch-rebuild-dir () |
1311 "(Re)build `dir' files in the directories remaining on the command line. | 1246 "(Re)build info `dir' files in the directories remaining on the command line. |
1312 Use this from the command line, with `-batch', it won't work in an | 1247 Use this from the command line, with `-batch'; |
1313 interactive XEmacs. | 1248 it won't work in an interactive Emacs. |
1314 | 1249 Each file is processed even if an error occurred previously. |
1315 Each file is processed even if an error occurred previously. For example, | 1250 For example, invoke \"xemacs -batch -f Info-batch-rebuild-dir /usr/local/info\"" |
1316 invoke \"xemacs -batch -f Info-batch-rebuild-dir /usr/local/info\"" | |
1317 ;; command-line-args-left is what is left of the command line (from | 1251 ;; command-line-args-left is what is left of the command line (from |
1318 ;; startup.el) | 1252 ;; startup.el) |
1319 (defvar command-line-args-left) ; Avoid 'free variable' warning | 1253 (defvar command-line-args-left) ; Avoid 'free variable' warning |
1320 (if (not noninteractive) | 1254 (if (not noninteractive) |
1321 (error "`Info-batch-rebuild-dir' is to be used only with -batch")) | 1255 (error "`Info-batch-rebuild-dir' is to be used only with -batch")) |
1324 (while command-line-args-left | 1258 (while command-line-args-left |
1325 (if (not (file-directory-p (car command-line-args-left))) | 1259 (if (not (file-directory-p (car command-line-args-left))) |
1326 (message "Warning: Skipped %s. Not a directory." | 1260 (message "Warning: Skipped %s. Not a directory." |
1327 (car command-line-args-left)) | 1261 (car command-line-args-left)) |
1328 (setq dir (expand-file-name "dir" (car command-line-args-left))) | 1262 (setq dir (expand-file-name "dir" (car command-line-args-left))) |
1329 (setq localdir (expand-file-name "localdir" | 1263 (setq localdir (expand-file-name "localdir" (car command-line-args-left))) |
1330 (car command-line-args-left))) | 1264 (cond |
1331 (cond | |
1332 ((file-exists-p dir) | 1265 ((file-exists-p dir) |
1333 (Info-rebuild-dir dir)) | 1266 (Info-rebuild-dir dir)) |
1334 ((file-exists-p localdir) | 1267 ((file-exists-p localdir) |
1335 (Info-rebuild-dir localdir)) | 1268 (Info-rebuild-dir localdir)) |
1336 (t | 1269 (t |
1389 (widen) | 1322 (widen) |
1390 (erase-buffer) | 1323 (erase-buffer) |
1391 (Info-insert-file-contents (Info-suffixed-file | 1324 (Info-insert-file-contents (Info-suffixed-file |
1392 (expand-file-name lastfilename | 1325 (expand-file-name lastfilename |
1393 (file-name-directory | 1326 (file-name-directory |
1394 Info-current-file)) | 1327 Info-current-file))) |
1395 'exact) | |
1396 t) | 1328 t) |
1397 (set-buffer-modified-p nil) | 1329 (set-buffer-modified-p nil) |
1398 (setq Info-current-subfile lastfilename))) | 1330 (setq Info-current-subfile lastfilename))) |
1399 (goto-char (point-min)) | 1331 (goto-char (point-min)) |
1400 (search-forward "\n\^_") | 1332 (search-forward "\n\^_") |
1401 (+ (- nodepos lastfilepos) (point)))) | 1333 (+ (- nodepos lastfilepos) (point)))) |
1402 | 1334 |
1403 (defun Info-all-case-regexp (str) | 1335 (defun Info-suffixed-file (name &optional name2) |
1404 (let ((regexp "") | 1336 "Look for NAME with each of the `Info-suffix-list' extensions in |
1405 (len (length str)) | 1337 turn. Optional NAME2 is the name of a fallback info file to check |
1406 (i 0) | 1338 for; usually a downcased version of NAME." |
1407 c) | 1339 (let ((suff Info-suffix-list) |
1408 (while (< i len) | 1340 (found nil) |
1409 (setq c (aref str i)) | 1341 file file2) |
1410 (cond ((or (and (>= c ?A) (<= c ?Z)) | 1342 (while (and suff (not found)) |
1411 (and (>= c ?a) (<= c ?z))) | 1343 (setq file (concat name (caar suff)) |
1412 (setq regexp (concat regexp | 1344 file2 (and name2 (concat name2 (caar suff)))) |
1413 "[" | 1345 (cond |
1414 (char-to-string (downcase c)) | 1346 ((file-regular-p file) |
1415 "\\|" | 1347 (setq found file)) |
1416 (char-to-string (upcase c)) | 1348 ((and file2 (file-regular-p file2)) |
1417 "]"))) | 1349 (setq found file2)) |
1418 (t | 1350 (t |
1419 (setq regexp (concat regexp (char-to-string c))))) | 1351 (setq suff (cdr suff))))) |
1420 (setq i (1+ i))) | 1352 (or found |
1421 regexp)) | 1353 (and name (when (file-regular-p name) |
1422 | 1354 name)) |
1423 (defun Info-suffixed-file (name &optional exact) | 1355 (and name2 (when (file-regular-p name2) |
1424 "Look for an info file named NAME. This function tries to be smart in | 1356 name2))))) |
1425 finding the file corresponding to NAME: if it doesn't exist, several | |
1426 variants are looked for, notably by appending suffixes from | |
1427 `Info-suffix-list' and by trying to change the characters case in NAME. | |
1428 | |
1429 The optional argument EXACT prevents this function from trying different case | |
1430 versions of NAME. Only the suffixes are tried." | |
1431 (catch 'found | |
1432 ;; First, try NAME alone: | |
1433 (and (file-regular-p name) (throw 'found name)) | |
1434 ;; Then, try different variants | |
1435 (let ((suff-match (concat "\\(" | |
1436 (let ((suff-list Info-suffix-list) | |
1437 suff regexp) | |
1438 (while (setq suff (pop suff-list)) | |
1439 (setq regexp | |
1440 (concat regexp | |
1441 (regexp-quote (car suff)) | |
1442 (and suff-list "\\|")))) | |
1443 regexp) | |
1444 "\\)?$")) | |
1445 (dir (file-name-directory name)) | |
1446 file files) | |
1447 (setq name (file-name-nondirectory name)) | |
1448 (setq files | |
1449 (condition-case data ;; protect against invalid directory | |
1450 ;; First, try NAME[.<suffix>] | |
1451 (append | |
1452 (directory-files dir 'fullname | |
1453 (concat "^" (regexp-quote name) suff-match) | |
1454 nil t) | |
1455 (if exact | |
1456 nil | |
1457 ;; Then, try to match the name independantly of the | |
1458 ;; characters case. | |
1459 (directory-files dir 'fullname | |
1460 (Info-all-case-regexp | |
1461 (concat "^" | |
1462 (regexp-quote name) | |
1463 suff-match)) | |
1464 nil t))) | |
1465 (t | |
1466 (display-warning 'info | |
1467 (format "directory `%s' error: %s" dir data)) | |
1468 nil))) | |
1469 (while (setq file (pop files)) | |
1470 (and (file-regular-p file) | |
1471 (throw 'found file))) | |
1472 ))) | |
1473 | 1357 |
1474 (defun Info-insert-file-contents (file &optional visit) | 1358 (defun Info-insert-file-contents (file &optional visit) |
1475 (setq file (expand-file-name file default-directory)) | 1359 (setq file (expand-file-name file default-directory)) |
1476 (let ((suff Info-suffix-list) | 1360 (let ((suff Info-suffix-list)) |
1477 len) | 1361 (while (and suff (or (<= (length file) (length (car (car suff)))) |
1478 (while (and suff | 1362 (not (equal (substring file |
1479 (setq len (length (car (car suff)))) | 1363 (- (length (car (car suff))))) |
1480 (or (<= (length file) len) | 1364 (car (car suff)))))) |
1481 (not (or | |
1482 (equal (substring file (- len)) | |
1483 (car (car suff))) | |
1484 (equal (substring file (- len)) | |
1485 (upcase (car (car suff))))) | |
1486 ))) | |
1487 (setq suff (cdr suff))) | 1365 (setq suff (cdr suff))) |
1488 (if (stringp (cdr (car suff))) | 1366 (if (stringp (cdr (car suff))) |
1489 (let ((command (if (string-match "%s" (cdr (car suff))) | 1367 (let ((command (if (string-match "%s" (cdr (car suff))) |
1490 (format (cdr (car suff)) file) | 1368 (format (cdr (car suff)) file) |
1491 (concat (cdr (car suff)) " < " file)))) | 1369 (concat (cdr (car suff)) " < " file)))) |
1551 (list (cons modeline-buffer-id-left-extent "Info: ") | 1429 (list (cons modeline-buffer-id-left-extent "Info: ") |
1552 (cons modeline-buffer-id-right-extent | 1430 (cons modeline-buffer-id-right-extent |
1553 (concat | 1431 (concat |
1554 "(" | 1432 "(" |
1555 (if Info-current-file | 1433 (if Info-current-file |
1556 (let ((name (file-name-nondirectory | 1434 (let ((name (file-name-nondirectory Info-current-file))) |
1557 Info-current-file))) | 1435 (if (string-match "\\.info$" name) |
1558 (if (string-match "^\\([^.]*\\)\\..*$" name) | 1436 (substring name 0 -5) |
1559 (match-string 1 name) | |
1560 name)) | 1437 name)) |
1561 "") | 1438 "") |
1562 ")" | 1439 ")" |
1563 (or Info-current-node "")))))) | 1440 (or Info-current-node "")))))) |
1564 | 1441 |
1658 (defun Info-build-node-completions () | 1535 (defun Info-build-node-completions () |
1659 (or Info-current-file-completions | 1536 (or Info-current-file-completions |
1660 (let ((compl (Info-build-annotation-completions))) | 1537 (let ((compl (Info-build-annotation-completions))) |
1661 (save-excursion | 1538 (save-excursion |
1662 (save-restriction | 1539 (save-restriction |
1663 (widen) | |
1664 (if (marker-buffer Info-tag-table-marker) | 1540 (if (marker-buffer Info-tag-table-marker) |
1665 (progn | 1541 (progn |
1666 (set-buffer (marker-buffer Info-tag-table-marker)) | 1542 (set-buffer (marker-buffer Info-tag-table-marker)) |
1667 (goto-char Info-tag-table-marker) | 1543 (goto-char Info-tag-table-marker) |
1668 (while (re-search-forward "\nNode: \\(.*\\)\177" nil t) | 1544 (while (re-search-forward "\nNode: \\(.*\\)\177" nil t) |
1669 (setq compl | 1545 (setq compl |
1670 (cons (list (buffer-substring (match-beginning 1) | 1546 (cons (list (buffer-substring (match-beginning 1) |
1671 (match-end 1))) | 1547 (match-end 1))) |
1672 compl)))) | 1548 compl)))) |
1549 (widen) | |
1673 (goto-char (point-min)) | 1550 (goto-char (point-min)) |
1674 (while (search-forward "\n\^_" nil t) | 1551 (while (search-forward "\n\^_" nil t) |
1675 (forward-line 1) | 1552 (forward-line 1) |
1676 (let ((beg (point))) | 1553 (let ((beg (point))) |
1677 (forward-line 1) | 1554 (forward-line 1) |
1678 (if (re-search-backward "Node: *\\([^,\n]*\\) *[,\n\t]" | 1555 (if (re-search-backward "Node: *\\([^,\n]*\\) *[,\n\t]" |
1679 beg t) | 1556 beg t) |
1680 (setq compl | 1557 (setq compl |
1681 (cons (list (buffer-substring (match-beginning 1) | 1558 (cons (list (buffer-substring (match-beginning 1) |
1682 (match-end 1))) | 1559 (match-end 1))) |
1683 compl)))))))) | 1560 compl)))))))) |
1684 (setq Info-current-file-completions compl)))) | 1561 (setq Info-current-file-completions compl)))) |
1685 | 1562 |
1706 (if (null Info-current-subfile) | 1583 (if (null Info-current-subfile) |
1707 (progn (re-search-forward regexp) (setq found (point))) | 1584 (progn (re-search-forward regexp) (setq found (point))) |
1708 (condition-case nil | 1585 (condition-case nil |
1709 (progn (re-search-forward regexp) (setq found (point))) | 1586 (progn (re-search-forward regexp) (setq found (point))) |
1710 (search-failed nil))))) | 1587 (search-failed nil))))) |
1711 (if (not found) | 1588 (if (not found) ;can only happen in subfile case -- else would have erred |
1712 ;; can only happen in subfile case -- else would have erred | |
1713 (unwind-protect | 1589 (unwind-protect |
1714 (let ((list ())) | 1590 (let ((list ())) |
1715 (set-buffer (marker-buffer Info-tag-table-marker)) | 1591 (set-buffer (marker-buffer Info-tag-table-marker)) |
1716 (goto-char (point-min)) | 1592 (goto-char (point-min)) |
1717 (search-forward "\n\^_\nIndirect:") | 1593 (search-forward "\n\^_\nIndirect:") |
1724 (beginning-of-line) | 1600 (beginning-of-line) |
1725 (while (not (eobp)) | 1601 (while (not (eobp)) |
1726 (re-search-forward "\\(^.*\\): [0-9]+$") | 1602 (re-search-forward "\\(^.*\\): [0-9]+$") |
1727 (goto-char (+ (match-end 1) 2)) | 1603 (goto-char (+ (match-end 1) 2)) |
1728 (setq list (cons (cons (read (current-buffer)) | 1604 (setq list (cons (cons (read (current-buffer)) |
1729 (buffer-substring | 1605 (buffer-substring (match-beginning 1) |
1730 (match-beginning 1) | 1606 (match-end 1))) |
1731 (match-end 1))) | |
1732 list)) | 1607 list)) |
1733 (goto-char (1+ (match-end 0)))) | 1608 (goto-char (1+ (match-end 0)))) |
1734 (setq list (nreverse list) | 1609 (setq list (nreverse list) |
1735 list (cdr list))) | 1610 list (cdr list))) |
1736 (while list | 1611 (while list |
1753 (or (and (equal onode Info-current-node) | 1628 (or (and (equal onode Info-current-node) |
1754 (equal ofile Info-current-file)) | 1629 (equal ofile Info-current-file)) |
1755 (Info-history-add ofile onode opoint))))) | 1630 (Info-history-add ofile onode opoint))))) |
1756 | 1631 |
1757 ;; Extract the value of the node-pointer named NAME. | 1632 ;; Extract the value of the node-pointer named NAME. |
1758 ;; If there is none, use ERRORNAME in the error message; | 1633 ;; If there is none, use ERRORNAME in the error message; |
1759 ;; if ERRORNAME is nil, just return nil. | 1634 ;; if ERRORNAME is nil, just return nil. |
1760 (defun Info-extract-pointer (name &optional errorname) | 1635 (defun Info-extract-pointer (name &optional errorname) |
1761 (save-excursion | 1636 (save-excursion |
1762 (goto-char (point-min)) | 1637 (goto-char (point-min)) |
1763 (forward-line 4) | 1638 (forward-line 4) |
2015 (setq item nil)))) | 1890 (setq item nil)))) |
2016 (list item)))) | 1891 (list item)))) |
2017 ;; there is a problem here in that if several menu items have the same | 1892 ;; there is a problem here in that if several menu items have the same |
2018 ;; name you can only go to the node of the first with this command. | 1893 ;; name you can only go to the node of the first with this command. |
2019 (Info-goto-node (Info-extract-menu-item menu-item) nil t)) | 1894 (Info-goto-node (Info-extract-menu-item menu-item) nil t)) |
2020 | 1895 |
2021 (defun Info-extract-menu-item (menu-item &optional noerror) | 1896 (defun Info-extract-menu-item (menu-item &optional noerror) |
2022 (save-excursion | 1897 (save-excursion |
2023 (goto-char (point-min)) | 1898 (goto-char (point-min)) |
2024 (if (let ((case-fold-search t)) | 1899 (if (let ((case-fold-search t)) |
2025 (search-forward "\n* menu:" nil t)) | 1900 (search-forward "\n* menu:" nil t)) |
2178 (while (>= (setq n (1- n)) 0) | 2053 (while (>= (setq n (1- n)) 0) |
2179 (if (pos-visible-in-window-p (point-min)) | 2054 (if (pos-visible-in-window-p (point-min)) |
2180 (progn | 2055 (progn |
2181 (Info-global-prev) | 2056 (Info-global-prev) |
2182 (message "Node: %s" Info-current-node) | 2057 (message "Node: %s" Info-current-node) |
2183 (goto-char (point-max)) | 2058 (sit-for 0) |
2184 (recenter -1) | 2059 ;;(scroll-up 1) ; work around bug in pos-visible-in-window-p |
2185 (move-to-window-line 0)) | 2060 ;;(scroll-down 1) |
2061 (while (not (pos-visible-in-window-p (point-max))) | |
2062 (scroll-up))) | |
2186 (scroll-down))))) | 2063 (scroll-down))))) |
2187 | 2064 |
2188 (defun Info-scroll-prev (arg) | 2065 (defun Info-scroll-prev (arg) |
2189 (interactive "P") | 2066 (interactive "P") |
2190 (if Info-auto-advance | 2067 (if Info-auto-advance |
2191 (if (and (pos-visible-in-window-p (point-min)) | 2068 (if (and (pos-visible-in-window-p (point-min)) |
2192 (not (eq Info-auto-advance t)) | 2069 (not (eq Info-auto-advance t)) |
2193 (not (eq last-command this-command))) | 2070 (not (eq last-command this-command))) |
2194 (message "Hit %s again to go to previous node" | 2071 (message "Hit %s again to go to previous node" |
2195 (if (mouse-event-p last-command-event) | 2072 (if (= last-command-char 0) |
2196 "mouse button" | 2073 "mouse button" |
2197 (key-description (event-key last-command-event)))) | 2074 (key-description (char-to-string last-command-char)))) |
2198 (Info-page-prev) | 2075 (Info-page-prev) |
2199 (setq this-command 'Info)) | 2076 (setq this-command 'Info)) |
2200 (scroll-down arg))) | 2077 (scroll-down arg))) |
2201 | 2078 |
2202 (defun Info-index (topic) | 2079 (defun Info-index (topic) |
2364 ;;;###autoload | 2241 ;;;###autoload |
2365 (defun Info-elisp-ref (func) | 2242 (defun Info-elisp-ref (func) |
2366 "Look up an Emacs Lisp function in the Elisp manual in the Info system. | 2243 "Look up an Emacs Lisp function in the Elisp manual in the Info system. |
2367 This command is designed to be used whether you are already in Info or not." | 2244 This command is designed to be used whether you are already in Info or not." |
2368 (interactive (let ((fn (function-at-point)) | 2245 (interactive (let ((fn (function-at-point)) |
2369 (enable-recursive-minibuffers t) | 2246 (enable-recursive-minibuffers t) |
2370 val) | 2247 val) |
2371 (setq val (completing-read | 2248 (setq val (completing-read |
2372 (format "Look up Emacs Lisp function%s: " | 2249 (format "Look up Emacs Lisp function%s: " |
2373 (if fn | 2250 (if fn |
2374 (format " (default %s)" fn) | 2251 (format " (default %s)" fn) |
2437 (setq bufs (cdr bufs)))) | 2314 (setq bufs (cdr bufs)))) |
2438 (goto-char savept))))) | 2315 (goto-char savept))))) |
2439 | 2316 |
2440 (defvar Info-annotate-map nil | 2317 (defvar Info-annotate-map nil |
2441 "Local keymap used within `a' command of Info.") | 2318 "Local keymap used within `a' command of Info.") |
2442 | |
2443 (if Info-annotate-map | 2319 (if Info-annotate-map |
2444 nil | 2320 nil |
2445 ;; (setq Info-annotate-map (nconc (make-sparse-keymap) text-mode-map)) | 2321 ;; (setq Info-annotate-map (nconc (make-sparse-keymap) text-mode-map)) |
2446 (setq Info-annotate-map (copy-keymap text-mode-map)) | 2322 (setq Info-annotate-map (copy-keymap text-mode-map)) |
2447 (define-key Info-annotate-map "\C-c\C-c" 'Info-cease-annotate)) | 2323 (define-key Info-annotate-map "\C-c\C-c" 'Info-cease-annotate)) |
2736 (defun Info-mouse-track-double-click-hook (event click-count) | 2612 (defun Info-mouse-track-double-click-hook (event click-count) |
2737 "Handle double-clicks by turning pages, like the `gv' ghostscript viewer" | 2613 "Handle double-clicks by turning pages, like the `gv' ghostscript viewer" |
2738 (if (/= click-count 2) | 2614 (if (/= click-count 2) |
2739 ;; Return nil so any other hooks are performed. | 2615 ;; Return nil so any other hooks are performed. |
2740 nil | 2616 nil |
2741 (let* ((fw (face-width 'default)) | 2617 (let* ((x (event-x-pixel event)) |
2742 (fh (face-height 'default)) | 2618 (y (event-y-pixel event)) |
2743 (x (/ (event-x-pixel event) fw)) | 2619 (w (window-pixel-width (event-window event))) |
2744 (y (/ (event-y-pixel event) fw)) | 2620 (h (window-pixel-height (event-window event))) |
2745 (w (/ (window-pixel-width (event-window event)) fw)) | 2621 (w/3 (/ w 3)) |
2746 (h (/ (window-pixel-height (event-window event)) fh)) | 2622 (w/2 (/ w 2)) |
2747 (bx 3) | 2623 (h/4 (/ h 4))) |
2748 (by 2)) | |
2749 (cond | 2624 (cond |
2750 ((<= y by) (Info-up) t) | 2625 ;; In the top 1/4 and inside the middle 1/3 |
2751 ((>= y (- h by)) (Info-nth-menu-item 1) t) | 2626 ((and (<= y h/4) |
2752 ((<= x bx) (Info-prev) t) | 2627 (and (>= x w/3) (<= x (+ w/3 w/3)))) |
2753 ((>= x (- w bx)) (Info-next) t) | 2628 (Info-up) |
2754 (t nil))))) | 2629 t) |
2630 ;; In the bottom 1/4 and inside the middle 1/3 | |
2631 ((and (>= y (+ h/4 h/4 h/4)) | |
2632 (and (>= x w/3) (<= x (+ w/3 w/3)))) | |
2633 (Info-nth-menu-item 1) | |
2634 t) | |
2635 ;; In the lower 3/4 and the right 1/2 | |
2636 ;; OR in the upper 1/4 and the right 1/3 | |
2637 ((or (and (>= y h/4) (>= x w/2)) | |
2638 (and (< y h/4) (>= x (+ w/3 w/3)))) | |
2639 (Info-next) | |
2640 t) | |
2641 ;; In the lower 3/4 and the left 1/2 | |
2642 ;; OR in the upper 1/4 and the left 1/3 | |
2643 ((or (and (>= y h/4) (< x w/2)) | |
2644 (and (< y h/4) (<= x w/3))) | |
2645 (Info-prev) | |
2646 t) | |
2647 ;; This shouldn't happen. | |
2648 (t | |
2649 (error "event out of bounds: %s %s" x y)))))) | |
2755 | 2650 |
2756 (defvar Info-mode-map nil | 2651 (defvar Info-mode-map nil |
2757 "Keymap containing Info commands.") | 2652 "Keymap containing Info commands.") |
2758 | |
2759 (if Info-mode-map | 2653 (if Info-mode-map |
2760 nil | 2654 nil |
2761 (setq Info-mode-map (make-sparse-keymap)) | 2655 (setq Info-mode-map (make-sparse-keymap)) |
2762 (suppress-keymap Info-mode-map) | 2656 (suppress-keymap Info-mode-map) |
2763 (define-key Info-mode-map "." 'beginning-of-buffer) | 2657 (define-key Info-mode-map "." 'beginning-of-buffer) |
2846 Space Scroll forward a full screen. DEL Scroll backward. | 2740 Space Scroll forward a full screen. DEL Scroll backward. |
2847 b Go to beginning of node. Meta-> Go to end of node. | 2741 b Go to beginning of node. Meta-> Go to end of node. |
2848 TAB Go to next cross-reference. Meta-TAB Go to previous ref. | 2742 TAB Go to next cross-reference. Meta-TAB Go to previous ref. |
2849 | 2743 |
2850 Mouse commands: | 2744 Mouse commands: |
2851 Left Button Set point (usual text-mode functionality) | 2745 Left Button Set point. |
2852 Middle Button Click on a highlighted node reference to go to it. | 2746 Middle Button Click on a highlighted node reference to go to it. |
2853 Right Button Pop up a menu of applicable Info commands. | 2747 Right Button Pop up a menu of applicable Info commands. |
2854 | |
2855 Left Button Double Click in window edges: | |
2856 Top edge: Go up to the parent node, like `u'. | |
2857 Left edge: Go to the previous node, like `p'. | |
2858 Right edge: Go to the next node, like `n'. | |
2859 Bottom edge: Follow first menu item, like `1'. | |
2860 | 2748 |
2861 Advanced commands: | 2749 Advanced commands: |
2862 g Move to node, file, or annotation tag specified by name. | 2750 g Move to node, file, or annotation tag specified by name. |
2863 Examples: `g Rectangles' `g (Emacs)Rectangles' `g Emacs'. | 2751 Examples: `g Rectangles' `g (Emacs)Rectangles' `g Emacs'. |
2864 v Move to file, with filename completion. | 2752 v Move to file, with filename completion. |
2912 (run-hooks 'Info-mode-hook) | 2800 (run-hooks 'Info-mode-hook) |
2913 (Info-set-mode-line)) | 2801 (Info-set-mode-line)) |
2914 | 2802 |
2915 (defvar Info-edit-map nil | 2803 (defvar Info-edit-map nil |
2916 "Local keymap used within `e' command of Info.") | 2804 "Local keymap used within `e' command of Info.") |
2917 | |
2918 (if Info-edit-map | 2805 (if Info-edit-map |
2919 nil | 2806 nil |
2920 ;; XEmacs: remove FSF stuff | 2807 ;; XEmacs: remove FSF stuff |
2921 (setq Info-edit-map (make-sparse-keymap)) | 2808 (setq Info-edit-map (make-sparse-keymap)) |
2922 (set-keymap-name Info-edit-map 'Info-edit-map) | 2809 (set-keymap-name Info-edit-map 'Info-edit-map) |
3052 (progn | 2939 (progn |
3053 (goto-char (match-end 0)) | 2940 (goto-char (match-end 0)) |
3054 (while | 2941 (while |
3055 (looking-at "[ \t]*[^:, \t\n]+:[ \t]+\\([^:,\t\n]+\\),?\n?") | 2942 (looking-at "[ \t]*[^:, \t\n]+:[ \t]+\\([^:,\t\n]+\\),?\n?") |
3056 (goto-char (match-end 0)) | 2943 (goto-char (match-end 0)) |
3057 (Info-highlight-region (match-beginning 1) (match-end 1) | 2944 (Info-highlight-region (match-beginning 1) (match-end 1) 'info-xref)))) |
3058 'info-xref)))) | |
3059 ;; Now get the xrefs in the body | 2945 ;; Now get the xrefs in the body |
3060 (goto-char (point-min)) | 2946 (goto-char (point-min)) |
3061 (while (re-search-forward xref-regexp nil t) | 2947 (while (re-search-forward xref-regexp nil t) |
3062 (if (= (char-after (1- (match-beginning 0))) ?\") ; hack | 2948 (if (= (char-after (1- (match-beginning 0))) ?\") ; hack |
3063 nil | 2949 nil |
3064 (Info-highlight-region (match-beginning 1) (match-end 1) | 2950 (Info-highlight-region (match-beginning 1) (match-end 1) 'info-xref))) |
3065 'info-xref))) | |
3066 ;; then highlight the nodes in the menu. | 2951 ;; then highlight the nodes in the menu. |
3067 (goto-char (point-min)) | 2952 (goto-char (point-min)) |
3068 (if (and (search-forward "\n* menu:" nil t)) | 2953 (if (and (search-forward "\n* menu:" nil t)) |
3069 (while (re-search-forward | 2954 (while (re-search-forward |
3070 "^\\* \\([^:\t\n]*\\):?:[ \t\n]" nil t) | 2955 "^\\* \\([^:\t\n]*\\):?:[ \t\n]" nil t) |
3071 (Info-highlight-region (match-beginning 1) (match-end 1) | 2956 (Info-highlight-region (match-beginning 1) (match-end 1) 'info-node))) |
3072 'info-node))) | |
3073 (set-buffer-modified-p nil)))) | 2957 (set-buffer-modified-p nil)))) |
3074 | 2958 |
3075 (defun Info-construct-menu (&optional event) | 2959 (defun Info-construct-menu (&optional event) |
3076 "Construct a menu of Info commands. | 2960 "Construct a menu of Info commands. |
3077 Adds an entry for the node at EVENT, or under point if EVENT is omitted. | 2961 Adds an entry for the node at EVENT, or under point if EVENT is omitted. |
3078 Used to construct the menubar submenu and popup menu." | 2962 Used to construct the menubar submenu and popup menu." |
3079 (or event (setq event (point))) | 2963 (or event (setq event (point))) |
3080 (let ((case-fold-search t) | 2964 (let ((case-fold-search t) |
3081 (xref-regexp (concat "\\*" | 2965 (xref-regexp (concat "\\*" |
3082 (regexp-quote Info-footnote-tag) | 2966 (regexp-quote Info-footnote-tag) |
3083 "[ \n\t]*\\([^:]*\\):")) | 2967 "[ \n\t]*\\([^:]*\\):")) |
3084 up-p prev-p next-p menu xrefs subnodes in) | 2968 up-p prev-p next-p menu xrefs subnodes in) |
3085 (save-excursion | 2969 (save-excursion |
3086 ;; `one-space' fixes "Notes:" xrefs that are split across lines. | 2970 ;; `one-space' fixes "Notes:" xrefs that are split across lines. |