Mercurial > hg > xemacs-beta
comparison lisp/info.el @ 367:a4f53d9b3154 r21-1-13
Import from CVS: tag r21-1-13
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:01:07 +0200 |
parents | 8e84bee8ddd0 |
children | cc15677e0335 |
comparison
equal
deleted
inserted
replaced
366:83d76f480a59 | 367:a4f53d9b3154 |
---|---|
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 (defvar Info-emacs-info-file-name "xemacs.info" | 425 (defconst Info-emacs-info-file-name "xemacs.info" |
426 "The filename of the XEmacs info for | 426 "The filename of the XEmacs info for `Info-goto-emacs-command-node' |
427 `Info-goto-emacs-command-node' (`\\<help-mode-map>\\[Info-goto-emacs-command-node]')") | 427 (`\\<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 |
439 search path, make the needed modifications on the variable's value | 439 search path, make the needed modifications on the variable's value |
440 from .emacs. For instance: | 440 from .emacs. For instance: |
441 | 441 |
442 (setq Info-directory-list (cons \"~/info\" Info-directory-list))") | 442 (setq Info-directory-list (cons \"~/info\" Info-directory-list))") |
443 | 443 |
444 (defcustom Info-localdir-heading-regexp | 444 ;; This could as well be hard-coded since ${srcdir}/info/dir is in CVS --dv |
445 "^Locally installed XEmacs Packages:?" | 445 (defconst Info-localdir-heading-regexp "^Local Packages:$" |
446 "The menu part of localdir files will be inserted below this topic | 446 "The menu part of localdir files will be inserted below this topic |
447 heading." | 447 heading.") |
448 :type 'regexp | |
449 :group 'info) | |
450 | 448 |
451 (defface info-node '((t (:bold t :italic t))) | 449 (defface info-node '((t (:bold t :italic t))) |
452 "Face used for node links in info." | 450 "Face used for node links in info." |
453 :group 'info-faces) | 451 :group 'info-faces) |
454 | 452 |
455 (defface info-xref '((t (:bold t))) | 453 (defface info-xref '((t (:bold t))) |
456 "Face used for cross-references in info." | 454 "Face used for cross-references in info." |
457 :group 'info-faces) | 455 :group 'info-faces) |
458 | 456 |
459 ;; Is this right for NT? .zip, with -c for to stdout, right? | 457 ;; This list is based on Karl Berry-s advice about extensions `info' itself |
460 (defvar Info-suffix-list '( ("" . nil) | 458 ;; might encounter. --dv |
461 (".info" . nil) | 459 (defcustom Info-suffix-list '(("" . nil) |
462 (".info.gz" . "gzip -dc %s") | 460 (".info" . nil) |
463 (".info-z" . "gzip -dc %s") | 461 (".gz" . "gzip -dc %s") |
464 (".info.Z" . "uncompress -c %s") | 462 (".info.gz" . "gzip -dc %s") |
465 (".gz" . "gzip -dc %s") | 463 (".z" . "gzip -dc %s") |
466 (".Z" . "uncompress -c %s") | 464 (".info.z" . "gzip -dc %s") |
467 (".zip" . "unzip -c %s") ) | 465 (".bz2" . "bzip2 -dc %s") |
468 "List of file name suffixes and associated decoding commands. | 466 (".info.bz2" . "bzip2 -dc %s") |
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. | |
469 Each entry should be (SUFFIX . STRING); if STRING contains %s, that is | 478 Each entry should be (SUFFIX . STRING); if STRING contains %s, that is |
470 changed to name of the file to decode, otherwise the file is given to | 479 changed to name of the file to decode, otherwise the file is given to |
471 the command as standard input. If STRING is nil, no decoding is done.") | 480 the command as standard input. If STRING is nil, no decoding is done." |
472 | 481 :type '(repeat (cons (string :tag "suffix") |
473 (defvar Info-footnote-tag "Note" | 482 (choice :tag "command" |
483 (const :tag "none" :value nil) | |
484 (string :tag "")))) | |
485 :group 'info) | |
486 | |
487 (defcustom Info-footnote-tag "Note" | |
474 "*Symbol that identifies a footnote or cross-reference. | 488 "*Symbol that identifies a footnote or cross-reference. |
475 All \"*Note\" references will be changed to use this word instead.") | 489 All \"*Note\" references will be changed to use this word instead." |
490 :type 'string | |
491 :group 'info) | |
476 | 492 |
477 (defvar Info-current-file nil | 493 (defvar Info-current-file nil |
478 "Info file that Info is now looking at, or nil. | 494 "Info file that Info is now looking at, or nil. |
479 This is the name that was specified in Info, not the actual file name. | 495 This is the name that was specified in Info, not the actual file name. |
480 It doesn't contain directory names or file name extensions added by Info.") | 496 It doesn't contain directory names or file name extensions added by Info.") |
496 (defvar Info-current-annotation-completions nil | 512 (defvar Info-current-annotation-completions nil |
497 "Cached completion list for current annotation files.") | 513 "Cached completion list for current annotation files.") |
498 | 514 |
499 (defvar Info-index-alternatives nil | 515 (defvar Info-index-alternatives nil |
500 "List of possible matches for last Info-index command.") | 516 "List of possible matches for last Info-index command.") |
517 | |
501 (defvar Info-index-first-alternative nil) | 518 (defvar Info-index-first-alternative nil) |
502 | 519 |
503 (defcustom Info-annotations-path '("~/.xemacs/info.notes" | 520 (defcustom Info-annotations-path '("~/.xemacs/info.notes" |
504 "~/.infonotes" | 521 "~/.infonotes" |
505 "/usr/lib/info.notes") | 522 "/usr/lib/info.notes") |
524 This is the file .../info/dir, which contains the topmost node of the | 541 This is the file .../info/dir, which contains the topmost node of the |
525 Info hierarchy. The first time you invoke Info you start off | 542 Info hierarchy. The first time you invoke Info you start off |
526 looking at that node, which is (dir)Top. | 543 looking at that node, which is (dir)Top. |
527 | 544 |
528 File: dir Node: Top This is the top of the INFO tree | 545 File: dir Node: Top This is the top of the INFO tree |
529 This (the Directory node) gives a menu of major topics. | 546 This (the Directory node) gives a menu of major topics. |
530 | 547 |
531 * Menu: The list of major topics begins on the next line. | 548 * Menu: The list of major topics begins on the next line. |
532 | 549 |
533 ") | 550 ") |
534 | 551 |
535 (defvar Info-no-description-string "[No description available]" | 552 (defcustom Info-no-description-string "[No description available]" |
536 "Description string for info files that have none") | 553 "*Description string for info files that have none" |
554 :type 'string | |
555 :group 'info) | |
537 | 556 |
538 ;;;###autoload | 557 ;;;###autoload |
539 (defun info (&optional file) | 558 (defun info (&optional file) |
540 "Enter Info, the documentation browser. | 559 "Enter Info, the documentation browser. |
541 Optional argument FILE specifies the file to examine; | 560 Optional argument FILE specifies the file to examine; |
594 ;; empty filename is simple case | 613 ;; empty filename is simple case |
595 ((null filename) | 614 ((null filename) |
596 (Info-find-file-node nil nodename no-going-back tryfile line)) | 615 (Info-find-file-node nil nodename no-going-back tryfile line)) |
597 ;; Convert filename to lower case if not found as specified. | 616 ;; Convert filename to lower case if not found as specified. |
598 ;; Expand it, look harder... | 617 ;; Expand it, look harder... |
599 ((let (temp temp-downcase found | 618 ((let ((fname (substitute-in-file-name filename)) |
600 (fname (substitute-in-file-name filename))) | 619 temp found) |
601 (let ((dirs (cond | 620 (let ((dirs (cond |
602 ((string-match "^\\./" fname) ; If specified name starts with `./' | 621 ;; If specified name starts with `./', then just try |
603 (list default-directory)) ; then just try current directory. | 622 ;; current directory. No point in searching for an absolute |
623 ;; file name | |
624 ((string-match "^\\./" fname) | |
625 (list default-directory)) | |
604 ((file-name-absolute-p fname) | 626 ((file-name-absolute-p fname) |
605 '(nil)) ; No point in searching for an absolute file name | 627 '(nil)) |
606 (Info-additional-search-directory-list | 628 (Info-additional-search-directory-list |
607 (append Info-directory-list | 629 (append Info-directory-list |
608 Info-additional-search-directory-list)) | 630 Info-additional-search-directory-list)) |
609 (t Info-directory-list)))) | 631 (t Info-directory-list)))) |
610 ;; Search the directory list for file FNAME. | 632 ;; Search the directory list for file FNAME. |
611 (while (and dirs (not found)) | 633 (while (and dirs (not found)) |
612 (setq temp (expand-file-name fname (car dirs))) | 634 (setq temp (expand-file-name fname (car dirs))) |
613 (setq temp-downcase | 635 (setq found (Info-suffixed-file temp)) |
614 (expand-file-name (downcase fname) (car dirs))) | |
615 (if (equal temp-downcase temp) (setq temp-downcase nil)) | |
616 ;; Try several variants of specified name. | |
617 ;; Try downcasing, appending a suffix, or both. | |
618 (setq found (Info-suffixed-file temp temp-downcase)) | |
619 (setq dirs (cdr dirs))) | 636 (setq dirs (cdr dirs))) |
620 (if found | 637 (if found |
621 (progn (setq filename (expand-file-name found)) | 638 (progn (setq filename (expand-file-name found)) |
622 t)))) | 639 t)))) |
623 (Info-find-file-node filename nodename no-going-back tryfile line)) | 640 (Info-find-file-node filename nodename no-going-back tryfile line)) |
624 ;; Look for a URL. This pattern is stolen from w3.el to prevent | 641 ;; Look for a URL. This pattern is stolen from w3.el to prevent |
625 ;; loading it if we won't need it. | 642 ;; loading it if we won't need it. |
796 ;; constructed Info-dir-contents. | 813 ;; constructed Info-dir-contents. |
797 (defvar Info-dir-file-attributes nil) | 814 (defvar Info-dir-file-attributes nil) |
798 | 815 |
799 (defun Info-insert-dir () | 816 (defun Info-insert-dir () |
800 "Construct the Info directory node by merging the files named | 817 "Construct the Info directory node by merging the files named |
801 \"dir\" or \"localdir\" from the directories in `Info-directory-list' | 818 \"dir\" or \"localdir\" from the directories in `Info-directory-list'. |
802 The \"dir\" files will take precedence in cases where both exist. It | 819 The \"dir\" files will take precedence in cases where both exist. It |
803 sets the *info* buffer's `default-directory' to the first directory we | 820 sets the *info* buffer's `default-directory' to the first directory we |
804 actually get any text from." | 821 actually get any text from." |
805 (if (and Info-dir-contents Info-dir-file-attributes | 822 (if (and Info-dir-contents Info-dir-file-attributes |
806 ;; Verify that none of the files we used has changed | 823 ;; Verify that none of the files we used has changed |
822 ;; Search the directory list for the directory file. | 839 ;; Search the directory list for the directory file. |
823 (while dirs | 840 (while dirs |
824 (let ((truename (file-truename (expand-file-name (car dirs))))) | 841 (let ((truename (file-truename (expand-file-name (car dirs))))) |
825 (or (member truename dirs-done) | 842 (or (member truename dirs-done) |
826 (member (directory-file-name truename) dirs-done) | 843 (member (directory-file-name truename) dirs-done) |
827 ;; Try several variants of specified name. | 844 ;; Karl Berry recently added the ability all possibilities for |
828 ;; Try upcasing, appending `.info', or both. | 845 ;; extension as for normal info files. This code however is |
829 (let* (buf | 846 ;; still unsatisfactory: if one day, we find a compressed dir |
830 file | 847 ;; file (which looks possible), we should be able to handle it |
831 (attrs | 848 ;; (which means decompress and read it, update it, save and |
832 (or | 849 ;; recompress it). --dv |
833 (progn (setq file (expand-file-name "dir" truename)) | 850 (let ((trials '("dir" "DIR" |
834 (file-attributes file)) | 851 "dir.info" "DIR.INFO" |
835 (progn (setq file (expand-file-name "DIR" truename)) | 852 "dir.inf" "DIR.INF" |
836 (file-attributes file)) | 853 "localdir" "LOCALDIR" |
837 (progn (setq file (expand-file-name "dir.info" truename)) | 854 "localdir.info" "LOCALDIR.INFO" |
838 (file-attributes file)) | 855 "localdir.inf" "LOCALDIR.INF")) |
839 (progn (setq file (expand-file-name "DIR.INFO" truename)) | 856 buf file attrs) |
840 (file-attributes file)) | 857 (catch 'found |
841 (progn (setq file (expand-file-name "localdir" truename)) | 858 (while (setq file (pop trials)) |
842 (file-attributes file)) | 859 (setq file (expand-file-name file truename)) |
843 (progn (setq file (expand-file-name "dir" truename)) | 860 (and (setq attrs (file-attributes file)) |
844 nil) | 861 (throw 'found t)))) |
845 ))) | 862 (unless file |
863 (setq file (expand-file-name "dir" truename))) | |
846 (setq dirs-done | 864 (setq dirs-done |
847 (cons truename | 865 (cons truename |
848 (cons (directory-file-name truename) | 866 (cons (directory-file-name truename) |
849 dirs-done))) | 867 dirs-done))) |
850 (Info-maybe-update-dir file) | 868 (Info-maybe-update-dir file) |
857 (set-buffer (or buf | 875 (set-buffer (or buf |
858 (generate-new-buffer | 876 (generate-new-buffer |
859 (if (string-match "localdir" file) | 877 (if (string-match "localdir" file) |
860 "localdir" | 878 "localdir" |
861 "info dir")))) | 879 "info dir")))) |
862 (if (not buf) | 880 (if (not buf) |
863 (insert-file-contents file)) | 881 (insert-file-contents file)) |
864 (if (string-match "localdir" (buffer-name)) | 882 (if (string-match "localdir" (buffer-name)) |
865 (setq lbuffers (cons (current-buffer) lbuffers)) | 883 (setq lbuffers (cons (current-buffer) lbuffers)) |
866 (setq buffers (cons (current-buffer) buffers))) | 884 (setq buffers (cons (current-buffer) buffers))) |
867 (if attrs | 885 (if attrs |
868 (setq Info-dir-file-attributes | 886 (setq Info-dir-file-attributes |
869 (cons (cons file attrs) | 887 (cons (cons file attrs) |
870 Info-dir-file-attributes))))))) | 888 Info-dir-file-attributes))))))) |
871 (or (cdr dirs) (setq Info-dir-contents-directory (car dirs))) | 889 (or (cdr dirs) (setq Info-dir-contents-directory (car dirs))) |
872 (setq dirs (cdr dirs)))) | 890 (setq dirs (cdr dirs)))) |
873 | 891 |
874 ;; ensure that the localdir files are inserted last, and reverse | 892 ;; ensure that the localdir files are inserted last, and reverse |
875 ;; the list of them so that when they get pushed in, they appear | 893 ;; the list of them so that when they get pushed in, they appear |
876 ;; in the same order they got specified in the path, from top to | 894 ;; in the same order they got specified in the path, from top to |
877 ;; bottom. | 895 ;; bottom. |
878 (nconc buffers (reverse lbuffers)) | 896 (nconc buffers (reverse lbuffers)) |
879 | 897 |
880 (or buffers | 898 (or buffers |
881 (error "Can't find the Info directory node")) | 899 (error "Can't find the Info directory node")) |
882 ;; Distinguish the dir file that comes with Emacs from all the | 900 ;; Distinguish the dir file that comes with Emacs from all the |
883 ;; others. Yes, that is really what this is supposed to do. | 901 ;; others. Yes, that is really what this is supposed to do. |
884 ;; If it doesn't work, fix it. | 902 ;; If it doesn't work, fix it. |
943 (search-forward "\n\^_" nil 'move) | 961 (search-forward "\n\^_" nil 'move) |
944 (beginning-of-line) | 962 (beginning-of-line) |
945 (setq end (point)) | 963 (setq end (point)) |
946 (setq nodes (cons (list nodename other beg end) nodes)))))) | 964 (setq nodes (cons (list nodename other beg end) nodes)))))) |
947 (setq others (cdr others)))) | 965 (setq others (cdr others)))) |
948 | 966 |
949 ;; Add to the main menu a menu item for each other node. | 967 ;; Add to the main menu a menu item for each other node. |
950 (re-search-forward "^\\* Menu:" nil t) | 968 (re-search-forward "^\\* Menu:" nil t) |
951 (forward-line 1) | 969 (forward-line 1) |
952 (let ((menu-items '("top")) | 970 (let ((menu-items '("top")) |
953 (nodes nodes) | 971 (nodes nodes) |
996 (message "Composing main Info directory...done")) | 1014 (message "Composing main Info directory...done")) |
997 (setq Info-dir-contents (buffer-string))) | 1015 (setq Info-dir-contents (buffer-string))) |
998 (setq default-directory Info-dir-contents-directory) | 1016 (setq default-directory Info-dir-contents-directory) |
999 (setq buffer-file-name (caar Info-dir-file-attributes))) | 1017 (setq buffer-file-name (caar Info-dir-file-attributes))) |
1000 | 1018 |
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 | |
1001 (defun Info-maybe-update-dir (file) | 1064 (defun Info-maybe-update-dir (file) |
1002 "Rebuild dir or localdir according to `Info-auto-generate-directory'." | 1065 "Rebuild dir or localdir according to `Info-auto-generate-directory'." |
1003 (unless (or (not (file-exists-p (file-name-directory file))) | 1066 (unless (or (not (file-exists-p (file-name-directory file))) |
1004 (null (directory-files (file-name-directory file) nil "\\.info"))) | 1067 (null (Info-directory-files file 'all))) |
1005 (if (not (find-buffer-visiting file)) | 1068 (if (not (find-buffer-visiting file)) |
1006 (if (not (file-exists-p file)) | 1069 (if (not (file-exists-p file)) |
1007 (if (or (eq Info-auto-generate-directory 'always) | 1070 (if (or (eq Info-auto-generate-directory 'always) |
1008 (eq Info-auto-generate-directory 'if-missing)) | 1071 (eq Info-auto-generate-directory 'if-missing)) |
1009 (Info-build-dir-anew (file-name-directory file))) | 1072 (Info-build-dir-anew (file-name-directory file))) |
1010 (if (or (eq Info-auto-generate-directory 'always) | 1073 (if (or (eq Info-auto-generate-directory 'always) |
1011 (and (eq Info-auto-generate-directory 'if-outdated) | 1074 (and (eq Info-auto-generate-directory 'if-outdated) |
1012 (Info-dir-outdated-p file))) | 1075 (Info-dir-outdated-p file))) |
1013 (Info-rebuild-dir file)))))) | 1076 (Info-rebuild-dir file)))))) |
1018 (defun Info-dir-outdated-p (file) | 1081 (defun Info-dir-outdated-p (file) |
1019 "Return non-nil if dir or localdir is outdated. | 1082 "Return non-nil if dir or localdir is outdated. |
1020 dir or localdir are outdated when an info file in the same | 1083 dir or localdir are outdated when an info file in the same |
1021 directory has been modified more recently." | 1084 directory has been modified more recently." |
1022 (let ((dir-mod-time (nth 5 (file-attributes file))) | 1085 (let ((dir-mod-time (nth 5 (file-attributes file))) |
1023 f-mod-time | 1086 f-mod-time newer) |
1024 newer) | |
1025 (setq Info-dir-newer-info-files nil) | 1087 (setq Info-dir-newer-info-files nil) |
1026 (mapcar | 1088 (mapcar |
1027 '(lambda (f) | 1089 '(lambda (f) |
1028 (prog2 | 1090 (prog2 |
1029 (setq f-mod-time (nth 5 (file-attributes f))) | 1091 (setq f-mod-time (nth 5 (file-attributes f))) |
1030 (setq newer (or (> (car f-mod-time) (car dir-mod-time)) | 1092 (setq newer (or (> (car f-mod-time) (car dir-mod-time)) |
1031 (and (= (car f-mod-time) (car dir-mod-time)) | 1093 (and (= (car f-mod-time) (car dir-mod-time)) |
1032 (> (car (cdr f-mod-time)) (car (cdr dir-mod-time)))))) | 1094 (> (car (cdr f-mod-time)) |
1033 (if (and (file-readable-p f) | 1095 (car (cdr dir-mod-time)))))) |
1034 newer) | 1096 (if (and (file-readable-p f) newer) |
1035 (setq Info-dir-newer-info-files | 1097 (setq Info-dir-newer-info-files |
1036 (cons f Info-dir-newer-info-files))))) | 1098 (cons f Info-dir-newer-info-files))))) |
1037 (directory-files (file-name-directory file) | 1099 (Info-directory-files file nil 'fullname 'nosort t)) |
1038 'fullname | |
1039 ".*\\.info\\(.gz\\|.Z\\|-z\\|.zip\\)?$" | |
1040 'nosort | |
1041 t)) | |
1042 Info-dir-newer-info-files)) | 1100 Info-dir-newer-info-files)) |
1043 | 1101 |
1044 (defun Info-extract-dir-entry-from (file) | 1102 (defun Info-extract-dir-entry-from (file) |
1045 "Extract the dir entry from the info FILE. | 1103 "Extract the dir entry from the info FILE. |
1046 The dir entry is delimited by the markers `START-INFO-DIR-ENTRY' | 1104 The dir entry is delimited by the markers `START-INFO-DIR-ENTRY' |
1064 (let (entry entries) | 1122 (let (entry entries) |
1065 (save-excursion | 1123 (save-excursion |
1066 (save-restriction | 1124 (save-restriction |
1067 (narrow-to-region beg end) | 1125 (narrow-to-region beg end) |
1068 (goto-char beg) | 1126 (goto-char beg) |
1069 (while (re-search-forward "^\\* \\([^:]+\\):\\([ \t]*(\\([^)]*\\))\\w*\\.\\|:\\)" nil t) | 1127 (while (re-search-forward |
1128 "^\\* \\([^:]+\\):\\([ \t]*(\\([^)]*\\))\\w*\\.\\|:\\)" nil t) | |
1070 (setq entry (list (match-string 2) | 1129 (setq entry (list (match-string 2) |
1071 (match-string 1) | 1130 (match-string 1) |
1072 (downcase (or (match-string 3) | 1131 (downcase (or (match-string 3) |
1073 (match-string 1))))) | 1132 (match-string 1))))) |
1074 (setq entry | 1133 (setq entry |
1075 (cons (nreverse | 1134 (cons (nreverse |
1076 (cdr | 1135 (cdr |
1077 (nreverse | 1136 (nreverse |
1078 (split-string | 1137 (split-string |
1079 (buffer-substring | 1138 (buffer-substring |
1080 (re-search-forward "[ \t]*" nil t) | 1139 (re-search-forward "[ \t]*" nil t) |
1081 (or (and (re-search-forward "^[^ \t]" nil t) | 1140 (or (and (re-search-forward "^[^ \t]" nil t) |
1082 (goto-char (match-beginning 0))) | 1141 (goto-char (match-beginning 0))) |
1083 (point-max))) | 1142 (point-max))) |
1084 "[ \t]*\n[ \t]*")))) | 1143 "[ \t]*\n[ \t]*")))) |
1095 (setq len (length (concat (car e) | 1154 (setq len (length (concat (car e) |
1096 (car (cdr e))))) | 1155 (car (cdr e))))) |
1097 (if (> len description-col) | 1156 (if (> len description-col) |
1098 (setq description-col len))) | 1157 (setq description-col len))) |
1099 entries) | 1158 entries) |
1100 (setq description-col (+ 5 description-col)) | 1159 (setq description-col (+ 5 description-col)) |
1101 (mapcar '(lambda (e) | 1160 (mapcar '(lambda (e) |
1102 (setq e (cdr e)) ; Drop filename | 1161 (setq e (cdr e)) ; Drop filename |
1103 (insert "* " (car e) ":" (car (cdr e))) | 1162 (insert "* " (car e) ":" (car (cdr e))) |
1104 (setq e (car (cdr (cdr e)))) | 1163 (setq e (car (cdr (cdr e)))) |
1105 (while e | 1164 (while e |
1110 (insert "\n"))) | 1169 (insert "\n"))) |
1111 | 1170 |
1112 | 1171 |
1113 (defun Info-build-dir-anew (directory) | 1172 (defun Info-build-dir-anew (directory) |
1114 "Build info directory information for DIRECTORY. | 1173 "Build info directory information for DIRECTORY. |
1115 The generated directory listing may be saved to a `dir' according | 1174 The generated directory listing may be saved to a `dir' according |
1116 to the value of `Info-save-auto-generated-dir'" | 1175 to the value of `Info-save-auto-generated-dir'" |
1117 (save-excursion | 1176 (save-excursion |
1118 (let* ((dirfile (expand-file-name "dir" directory)) | 1177 (let* ((dirfile (expand-file-name "dir" directory)) |
1119 (to-temp (or (null Info-save-auto-generated-dir) | 1178 (to-temp (or (null Info-save-auto-generated-dir) |
1120 (eq Info-save-auto-generated-dir 'never) | 1179 (eq Info-save-auto-generated-dir 'never) |
1121 (and (not (file-writable-p dirfile)) | 1180 (and (not (file-writable-p dirfile)) |
1122 (message "File not writable %s. Using temporary." dirfile)))) | 1181 (message "File not writable %s. Using temporary." |
1123 (info-files | 1182 dirfile)))) |
1124 (directory-files directory | 1183 (info-files (Info-directory-files dirfile nil 'fullname nil t))) |
1125 'fullname | |
1126 ".*\\.info\\(.gz\\|.Z\\|-z\\|.zip\\)?$" | |
1127 nil | |
1128 t))) | |
1129 (if to-temp | 1184 (if to-temp |
1130 (message "Creating temporary dir in %s..." directory) | 1185 (message "Creating temporary dir in %s..." directory) |
1131 (message "Creating %s..." dirfile)) | 1186 (message "Creating %s..." dirfile)) |
1132 (set-buffer (find-file-noselect dirfile t)) | 1187 (set-buffer (find-file-noselect dirfile t)) |
1133 (setq buffer-read-only nil) | 1188 (setq buffer-read-only nil) |
1134 (erase-buffer) | 1189 (erase-buffer) |
1135 (insert Info-dir-prologue | 1190 (insert Info-dir-prologue "Info files in " directory ":\n\n") |
1136 "Info files in " directory ":\n\n") | 1191 (Info-dump-dir-entries |
1137 (Info-dump-dir-entries | 1192 (mapcar |
1138 (mapcar | |
1139 '(lambda (f) | 1193 '(lambda (f) |
1140 (or (Info-extract-dir-entry-from f) | 1194 (or (Info-extract-dir-entry-from f) |
1141 (list 'dummy | 1195 (list 'dummy |
1142 (progn | 1196 (progn (string-match "\\([^.]*\\)\\(\\..*\\)?$" |
1143 (string-match "\\(.*\\)\\.info\\(.gz\\|.Z\\|-z\\|.zip\\)?$" | 1197 (file-name-nondirectory f)) |
1144 (file-name-nondirectory f)) | 1198 (capitalize |
1145 (capitalize (match-string 1 (file-name-nondirectory f)))) | 1199 (match-string 1 (file-name-nondirectory f)))) |
1146 ":" | 1200 ":" |
1147 (list Info-no-description-string)))) | 1201 (list Info-no-description-string)))) |
1148 info-files)) | 1202 info-files)) |
1149 (if to-temp | 1203 (if to-temp |
1150 (set-buffer-modified-p nil) | 1204 (set-buffer-modified-p nil) |
1154 (message "Creating %s...done" dirfile))))) | 1208 (message "Creating %s...done" dirfile))))) |
1155 | 1209 |
1156 | 1210 |
1157 (defun Info-rebuild-dir (file) | 1211 (defun Info-rebuild-dir (file) |
1158 "Build info directory information in the directory of dir FILE. | 1212 "Build info directory information in the directory of dir FILE. |
1159 Description of info files are merged from the info files in the | 1213 Description of info files are merged from the info files in the |
1160 directory and the contents of FILE with the description in info files | 1214 directory and the contents of FILE with the description in info files |
1161 taking precedence over descriptions in FILE. | 1215 taking precedence over descriptions in FILE. |
1162 The generated directory listing may be saved to a `dir' according to | 1216 The generated directory listing may be saved to a `dir' according to |
1163 the value of `Info-save-auto-generated-dir' " | 1217 the value of `Info-save-auto-generated-dir' " |
1164 (save-excursion | 1218 (save-excursion |
1165 (save-restriction | 1219 (save-restriction |
1166 (let (dir-section-contents dir-full-contents | 1220 (let (dir-section-contents dir-full-contents |
1167 dir-entry | 1221 dir-entry |
1168 file-dir-entry | 1222 file-dir-entry |
1169 mark next-section | 1223 mark next-section |
1170 not-first-section | 1224 not-first-section |
1171 (to-temp | 1225 (to-temp |
1172 (or (null Info-save-auto-generated-dir) | 1226 (or (null Info-save-auto-generated-dir) |
1173 (eq Info-save-auto-generated-dir 'never) | 1227 (eq Info-save-auto-generated-dir 'never) |
1174 (and (eq Info-save-auto-generated-dir 'always) | 1228 (and (eq Info-save-auto-generated-dir 'always) |
1175 (not (file-writable-p file)) | 1229 (not (file-writable-p file)) |
1176 (message "File not writable %s. Using temporary." file)) | 1230 (message "File not writable %s. Using temporary." file)) |
1177 (and (eq Info-save-auto-generated-dir 'conservative) | 1231 (and (eq Info-save-auto-generated-dir 'conservative) |
1178 (or (and (not (file-writable-p file)) | 1232 (or (and (not (file-writable-p file)) |
1179 (message "File not writable %s. Using temporary." file)) | 1233 (message |
1180 (not (y-or-n-p | 1234 "File not writable %s. Using temporary." file)) |
1181 (message "%s is outdated. Overwrite ? " | 1235 (not (y-or-n-p |
1236 (message "%s is outdated. Overwrite ? " | |
1182 file)))))))) | 1237 file)))))))) |
1183 (set-buffer (find-file-noselect file t)) | 1238 (set-buffer (find-file-noselect file t)) |
1184 (setq buffer-read-only nil) | 1239 (setq buffer-read-only nil) |
1185 (if to-temp | 1240 (if to-temp |
1186 (message "Rebuilding temporary %s..." file) | 1241 (message "Rebuilding temporary %s..." file) |
1192 (re-search-forward "^\\* Menu:.*$" nil t) | 1247 (re-search-forward "^\\* Menu:.*$" nil t) |
1193 (setq mark (and (re-search-forward "^\\* " nil t) | 1248 (setq mark (and (re-search-forward "^\\* " nil t) |
1194 (match-beginning 0)))) | 1249 (match-beginning 0)))) |
1195 (throw 'done nil)) | 1250 (throw 'done nil)) |
1196 (setq dir-full-contents (Info-parse-dir-entries mark (point-max))) | 1251 (setq dir-full-contents (Info-parse-dir-entries mark (point-max))) |
1197 (setq next-section (or (and (re-search-forward "^[^* \t].*:[ \t]*$" nil t) | 1252 (setq next-section (or (and (re-search-forward |
1253 "^[^* \t].*:[ \t]*$" nil t) | |
1198 (match-beginning 0)) | 1254 (match-beginning 0)) |
1199 (point-max))) | 1255 (point-max))) |
1200 (while next-section | 1256 (while next-section |
1201 (narrow-to-region mark next-section) | 1257 (narrow-to-region mark next-section) |
1202 (setq dir-section-contents (nreverse (Info-parse-dir-entries (point-min) | 1258 (setq dir-section-contents (nreverse (Info-parse-dir-entries |
1203 (point-max)))) | 1259 (point-min) (point-max)))) |
1204 (mapcar '(lambda (file) | 1260 (mapcar |
1205 (setq dir-entry (assoc (downcase | 1261 '(lambda (file) |
1206 (file-name-sans-extension | 1262 (setq dir-entry (assoc (downcase |
1207 (file-name-nondirectory file))) | 1263 (file-name-sans-extension |
1208 dir-section-contents) | 1264 (file-name-nondirectory file))) |
1209 file-dir-entry (Info-extract-dir-entry-from file)) | 1265 dir-section-contents) |
1210 (if dir-entry | 1266 file-dir-entry (Info-extract-dir-entry-from file)) |
1211 (if file-dir-entry | 1267 (if dir-entry |
1212 ;; A dir entry in the info file takes precedence over an | 1268 (if file-dir-entry |
1213 ;; existing entry in the dir file | 1269 ;; A dir entry in the info file takes precedence over |
1214 (setcdr dir-entry (cdr file-dir-entry))) | 1270 ;; an existing entry in the dir file |
1215 (unless (or not-first-section | 1271 (setcdr dir-entry (cdr file-dir-entry))) |
1216 (assoc (downcase | 1272 (unless (or not-first-section |
1217 (file-name-sans-extension | 1273 (assoc (downcase |
1218 (file-name-nondirectory file))) | 1274 (file-name-sans-extension |
1219 dir-full-contents)) | 1275 (file-name-nondirectory file))) |
1220 (if file-dir-entry | 1276 dir-full-contents)) |
1221 (setq dir-section-contents (cons file-dir-entry | 1277 (if file-dir-entry |
1222 dir-section-contents)) | 1278 (setq dir-section-contents |
1223 (setq dir-section-contents | 1279 (cons file-dir-entry dir-section-contents)) |
1224 (cons (list 'dummy | 1280 (setq dir-section-contents |
1225 (capitalize (file-name-sans-extension | 1281 (cons (list 'dummy |
1226 (file-name-nondirectory file))) | 1282 (capitalize (file-name-sans-extension |
1227 ":" | 1283 (file-name-nondirectory |
1228 (list Info-no-description-string)) | 1284 file))) |
1229 dir-section-contents)))))) | 1285 ":" |
1230 Info-dir-newer-info-files) | 1286 (list Info-no-description-string)) |
1287 dir-section-contents)))))) | |
1288 Info-dir-newer-info-files) | |
1231 (delete-region (point-min) (point-max)) | 1289 (delete-region (point-min) (point-max)) |
1232 (Info-dump-dir-entries (nreverse dir-section-contents)) | 1290 (Info-dump-dir-entries (nreverse dir-section-contents)) |
1233 (widen) | 1291 (widen) |
1234 (if (= next-section (point-max)) | 1292 (if (= next-section (point-max)) |
1235 (setq next-section nil) | 1293 (setq next-section nil) |
1236 (or (setq mark (and (re-search-forward "^\\* " nil t) | 1294 (or (setq mark (and (re-search-forward "^\\* " nil t) |
1237 (match-beginning 0))) | 1295 (match-beginning 0))) |
1238 (throw 'done nil)) | 1296 (throw 'done nil)) |
1239 (setq next-section (or (and (re-search-forward "^[^* \t].*:[ \t]*$" nil t) | 1297 (setq next-section (or (and (re-search-forward |
1298 "^[^* \t].*:[ \t]*$" nil t) | |
1240 (match-beginning 0)) | 1299 (match-beginning 0)) |
1241 (point-max)))) | 1300 (point-max)))) |
1242 (setq not-first-section t))) | 1301 (setq not-first-section t))) |
1243 (if to-temp | 1302 (if to-temp |
1244 (progn | 1303 (progn |
1245 (set-buffer-modified-p nil) | 1304 (set-buffer-modified-p nil) |
1246 (message "Rebuilding temporary %s...done" file)) | 1305 (message "Rebuilding temporary %s...done" file)) |
1247 (save-buffer) | 1306 (save-buffer) |
1248 (message "Rebuilding %s...done" file)))))) | 1307 (message "Rebuilding %s...done" file)))))) |
1249 | 1308 |
1250 ;;;###autoload | 1309 ;;;###autoload |
1251 (defun Info-batch-rebuild-dir () | 1310 (defun Info-batch-rebuild-dir () |
1252 "(Re)build info `dir' files in the directories remaining on the command line. | 1311 "(Re)build `dir' files in the directories remaining on the command line. |
1253 Use this from the command line, with `-batch'; | 1312 Use this from the command line, with `-batch', it won't work in an |
1254 it won't work in an interactive Emacs. | 1313 interactive XEmacs. |
1255 Each file is processed even if an error occurred previously. | 1314 |
1256 For example, invoke \"xemacs -batch -f Info-batch-rebuild-dir /usr/local/info\"" | 1315 Each file is processed even if an error occurred previously. For example, |
1316 invoke \"xemacs -batch -f Info-batch-rebuild-dir /usr/local/info\"" | |
1257 ;; command-line-args-left is what is left of the command line (from | 1317 ;; command-line-args-left is what is left of the command line (from |
1258 ;; startup.el) | 1318 ;; startup.el) |
1259 (defvar command-line-args-left) ; Avoid 'free variable' warning | 1319 (defvar command-line-args-left) ; Avoid 'free variable' warning |
1260 (if (not noninteractive) | 1320 (if (not noninteractive) |
1261 (error "`Info-batch-rebuild-dir' is to be used only with -batch")) | 1321 (error "`Info-batch-rebuild-dir' is to be used only with -batch")) |
1264 (while command-line-args-left | 1324 (while command-line-args-left |
1265 (if (not (file-directory-p (car command-line-args-left))) | 1325 (if (not (file-directory-p (car command-line-args-left))) |
1266 (message "Warning: Skipped %s. Not a directory." | 1326 (message "Warning: Skipped %s. Not a directory." |
1267 (car command-line-args-left)) | 1327 (car command-line-args-left)) |
1268 (setq dir (expand-file-name "dir" (car command-line-args-left))) | 1328 (setq dir (expand-file-name "dir" (car command-line-args-left))) |
1269 (setq localdir (expand-file-name "localdir" (car command-line-args-left))) | 1329 (setq localdir (expand-file-name "localdir" |
1270 (cond | 1330 (car command-line-args-left))) |
1331 (cond | |
1271 ((file-exists-p dir) | 1332 ((file-exists-p dir) |
1272 (Info-rebuild-dir dir)) | 1333 (Info-rebuild-dir dir)) |
1273 ((file-exists-p localdir) | 1334 ((file-exists-p localdir) |
1274 (Info-rebuild-dir localdir)) | 1335 (Info-rebuild-dir localdir)) |
1275 (t | 1336 (t |
1328 (widen) | 1389 (widen) |
1329 (erase-buffer) | 1390 (erase-buffer) |
1330 (Info-insert-file-contents (Info-suffixed-file | 1391 (Info-insert-file-contents (Info-suffixed-file |
1331 (expand-file-name lastfilename | 1392 (expand-file-name lastfilename |
1332 (file-name-directory | 1393 (file-name-directory |
1333 Info-current-file))) | 1394 Info-current-file)) |
1395 'exact) | |
1334 t) | 1396 t) |
1335 (set-buffer-modified-p nil) | 1397 (set-buffer-modified-p nil) |
1336 (setq Info-current-subfile lastfilename))) | 1398 (setq Info-current-subfile lastfilename))) |
1337 (goto-char (point-min)) | 1399 (goto-char (point-min)) |
1338 (search-forward "\n\^_") | 1400 (search-forward "\n\^_") |
1339 (+ (- nodepos lastfilepos) (point)))) | 1401 (+ (- nodepos lastfilepos) (point)))) |
1340 | 1402 |
1341 (defun Info-suffixed-file (name &optional name2) | 1403 (defun Info-all-case-regexp (str) |
1342 "Look for NAME with each of the `Info-suffix-list' extensions in | 1404 (let ((regexp "") |
1343 turn. Optional NAME2 is the name of a fallback info file to check | 1405 (len (length str)) |
1344 for; usually a downcased version of NAME." | 1406 (i 0) |
1345 (let ((suff Info-suffix-list) | 1407 c) |
1346 (found nil) | 1408 (while (< i len) |
1347 file file2) | 1409 (setq c (aref str i)) |
1348 (while (and suff (not found)) | 1410 (cond ((or (and (>= c ?A) (<= c ?Z)) |
1349 (setq file (concat name (caar suff)) | 1411 (and (>= c ?a) (<= c ?z))) |
1350 file2 (and name2 (concat name2 (caar suff)))) | 1412 (setq regexp (concat regexp |
1351 (cond | 1413 "[" |
1352 ((file-regular-p file) | 1414 (char-to-string (downcase c)) |
1353 (setq found file)) | 1415 "\\|" |
1354 ((and file2 (file-regular-p file2)) | 1416 (char-to-string (upcase c)) |
1355 (setq found file2)) | 1417 "]"))) |
1356 (t | 1418 (t |
1357 (setq suff (cdr suff))))) | 1419 (setq regexp (concat regexp (char-to-string c))))) |
1358 (or found | 1420 (setq i (1+ i))) |
1359 (and name (when (file-regular-p name) | 1421 regexp)) |
1360 name)) | 1422 |
1361 (and name2 (when (file-regular-p name2) | 1423 (defun Info-suffixed-file (name &optional exact) |
1362 name2))))) | 1424 "Look for an info file named NAME. This function tries to be smart in |
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 ))) | |
1363 | 1473 |
1364 (defun Info-insert-file-contents (file &optional visit) | 1474 (defun Info-insert-file-contents (file &optional visit) |
1365 (setq file (expand-file-name file default-directory)) | 1475 (setq file (expand-file-name file default-directory)) |
1366 (let ((suff Info-suffix-list)) | 1476 (let ((suff Info-suffix-list) |
1367 (while (and suff (or (<= (length file) (length (car (car suff)))) | 1477 len) |
1368 (not (equal (substring file | 1478 (while (and suff |
1369 (- (length (car (car suff))))) | 1479 (setq len (length (car (car suff)))) |
1370 (car (car suff)))))) | 1480 (or (<= (length file) len) |
1481 (not (or | |
1482 (equal (substring file (- len)) | |
1483 (car (car suff))) | |
1484 (equal (substring file (- len)) | |
1485 (upcase (car (car suff))))) | |
1486 ))) | |
1371 (setq suff (cdr suff))) | 1487 (setq suff (cdr suff))) |
1372 (if (stringp (cdr (car suff))) | 1488 (if (stringp (cdr (car suff))) |
1373 (let ((command (if (string-match "%s" (cdr (car suff))) | 1489 (let ((command (if (string-match "%s" (cdr (car suff))) |
1374 (format (cdr (car suff)) file) | 1490 (format (cdr (car suff)) file) |
1375 (concat (cdr (car suff)) " < " file)))) | 1491 (concat (cdr (car suff)) " < " file)))) |
1435 (list (cons modeline-buffer-id-left-extent "Info: ") | 1551 (list (cons modeline-buffer-id-left-extent "Info: ") |
1436 (cons modeline-buffer-id-right-extent | 1552 (cons modeline-buffer-id-right-extent |
1437 (concat | 1553 (concat |
1438 "(" | 1554 "(" |
1439 (if Info-current-file | 1555 (if Info-current-file |
1440 (let ((name (file-name-nondirectory Info-current-file))) | 1556 (let ((name (file-name-nondirectory |
1441 (if (string-match "\\.info$" name) | 1557 Info-current-file))) |
1442 (substring name 0 -5) | 1558 (if (string-match "^\\([^.]*\\)\\..*$" name) |
1559 (match-string 1 name) | |
1443 name)) | 1560 name)) |
1444 "") | 1561 "") |
1445 ")" | 1562 ")" |
1446 (or Info-current-node "")))))) | 1563 (or Info-current-node "")))))) |
1447 | 1564 |
1558 (forward-line 1) | 1675 (forward-line 1) |
1559 (let ((beg (point))) | 1676 (let ((beg (point))) |
1560 (forward-line 1) | 1677 (forward-line 1) |
1561 (if (re-search-backward "Node: *\\([^,\n]*\\) *[,\n\t]" | 1678 (if (re-search-backward "Node: *\\([^,\n]*\\) *[,\n\t]" |
1562 beg t) | 1679 beg t) |
1563 (setq compl | 1680 (setq compl |
1564 (cons (list (buffer-substring (match-beginning 1) | 1681 (cons (list (buffer-substring (match-beginning 1) |
1565 (match-end 1))) | 1682 (match-end 1))) |
1566 compl)))))))) | 1683 compl)))))))) |
1567 (setq Info-current-file-completions compl)))) | 1684 (setq Info-current-file-completions compl)))) |
1568 | 1685 |
1589 (if (null Info-current-subfile) | 1706 (if (null Info-current-subfile) |
1590 (progn (re-search-forward regexp) (setq found (point))) | 1707 (progn (re-search-forward regexp) (setq found (point))) |
1591 (condition-case nil | 1708 (condition-case nil |
1592 (progn (re-search-forward regexp) (setq found (point))) | 1709 (progn (re-search-forward regexp) (setq found (point))) |
1593 (search-failed nil))))) | 1710 (search-failed nil))))) |
1594 (if (not found) ;can only happen in subfile case -- else would have erred | 1711 (if (not found) |
1712 ;; can only happen in subfile case -- else would have erred | |
1595 (unwind-protect | 1713 (unwind-protect |
1596 (let ((list ())) | 1714 (let ((list ())) |
1597 (set-buffer (marker-buffer Info-tag-table-marker)) | 1715 (set-buffer (marker-buffer Info-tag-table-marker)) |
1598 (goto-char (point-min)) | 1716 (goto-char (point-min)) |
1599 (search-forward "\n\^_\nIndirect:") | 1717 (search-forward "\n\^_\nIndirect:") |
1606 (beginning-of-line) | 1724 (beginning-of-line) |
1607 (while (not (eobp)) | 1725 (while (not (eobp)) |
1608 (re-search-forward "\\(^.*\\): [0-9]+$") | 1726 (re-search-forward "\\(^.*\\): [0-9]+$") |
1609 (goto-char (+ (match-end 1) 2)) | 1727 (goto-char (+ (match-end 1) 2)) |
1610 (setq list (cons (cons (read (current-buffer)) | 1728 (setq list (cons (cons (read (current-buffer)) |
1611 (buffer-substring (match-beginning 1) | 1729 (buffer-substring |
1612 (match-end 1))) | 1730 (match-beginning 1) |
1731 (match-end 1))) | |
1613 list)) | 1732 list)) |
1614 (goto-char (1+ (match-end 0)))) | 1733 (goto-char (1+ (match-end 0)))) |
1615 (setq list (nreverse list) | 1734 (setq list (nreverse list) |
1616 list (cdr list))) | 1735 list (cdr list))) |
1617 (while list | 1736 (while list |
1634 (or (and (equal onode Info-current-node) | 1753 (or (and (equal onode Info-current-node) |
1635 (equal ofile Info-current-file)) | 1754 (equal ofile Info-current-file)) |
1636 (Info-history-add ofile onode opoint))))) | 1755 (Info-history-add ofile onode opoint))))) |
1637 | 1756 |
1638 ;; Extract the value of the node-pointer named NAME. | 1757 ;; Extract the value of the node-pointer named NAME. |
1639 ;; If there is none, use ERRORNAME in the error message; | 1758 ;; If there is none, use ERRORNAME in the error message; |
1640 ;; if ERRORNAME is nil, just return nil. | 1759 ;; if ERRORNAME is nil, just return nil. |
1641 (defun Info-extract-pointer (name &optional errorname) | 1760 (defun Info-extract-pointer (name &optional errorname) |
1642 (save-excursion | 1761 (save-excursion |
1643 (goto-char (point-min)) | 1762 (goto-char (point-min)) |
1644 (forward-line 4) | 1763 (forward-line 4) |
1896 (setq item nil)))) | 2015 (setq item nil)))) |
1897 (list item)))) | 2016 (list item)))) |
1898 ;; there is a problem here in that if several menu items have the same | 2017 ;; there is a problem here in that if several menu items have the same |
1899 ;; name you can only go to the node of the first with this command. | 2018 ;; name you can only go to the node of the first with this command. |
1900 (Info-goto-node (Info-extract-menu-item menu-item) nil t)) | 2019 (Info-goto-node (Info-extract-menu-item menu-item) nil t)) |
1901 | 2020 |
1902 (defun Info-extract-menu-item (menu-item &optional noerror) | 2021 (defun Info-extract-menu-item (menu-item &optional noerror) |
1903 (save-excursion | 2022 (save-excursion |
1904 (goto-char (point-min)) | 2023 (goto-char (point-min)) |
1905 (if (let ((case-fold-search t)) | 2024 (if (let ((case-fold-search t)) |
1906 (search-forward "\n* menu:" nil t)) | 2025 (search-forward "\n* menu:" nil t)) |
2245 ;;;###autoload | 2364 ;;;###autoload |
2246 (defun Info-elisp-ref (func) | 2365 (defun Info-elisp-ref (func) |
2247 "Look up an Emacs Lisp function in the Elisp manual in the Info system. | 2366 "Look up an Emacs Lisp function in the Elisp manual in the Info system. |
2248 This command is designed to be used whether you are already in Info or not." | 2367 This command is designed to be used whether you are already in Info or not." |
2249 (interactive (let ((fn (function-at-point)) | 2368 (interactive (let ((fn (function-at-point)) |
2250 (enable-recursive-minibuffers t) | 2369 (enable-recursive-minibuffers t) |
2251 val) | 2370 val) |
2252 (setq val (completing-read | 2371 (setq val (completing-read |
2253 (format "Look up Emacs Lisp function%s: " | 2372 (format "Look up Emacs Lisp function%s: " |
2254 (if fn | 2373 (if fn |
2255 (format " (default %s)" fn) | 2374 (format " (default %s)" fn) |
2318 (setq bufs (cdr bufs)))) | 2437 (setq bufs (cdr bufs)))) |
2319 (goto-char savept))))) | 2438 (goto-char savept))))) |
2320 | 2439 |
2321 (defvar Info-annotate-map nil | 2440 (defvar Info-annotate-map nil |
2322 "Local keymap used within `a' command of Info.") | 2441 "Local keymap used within `a' command of Info.") |
2442 | |
2323 (if Info-annotate-map | 2443 (if Info-annotate-map |
2324 nil | 2444 nil |
2325 ;; (setq Info-annotate-map (nconc (make-sparse-keymap) text-mode-map)) | 2445 ;; (setq Info-annotate-map (nconc (make-sparse-keymap) text-mode-map)) |
2326 (setq Info-annotate-map (copy-keymap text-mode-map)) | 2446 (setq Info-annotate-map (copy-keymap text-mode-map)) |
2327 (define-key Info-annotate-map "\C-c\C-c" 'Info-cease-annotate)) | 2447 (define-key Info-annotate-map "\C-c\C-c" 'Info-cease-annotate)) |
2633 ((>= x (- w bx)) (Info-next) t) | 2753 ((>= x (- w bx)) (Info-next) t) |
2634 (t nil))))) | 2754 (t nil))))) |
2635 | 2755 |
2636 (defvar Info-mode-map nil | 2756 (defvar Info-mode-map nil |
2637 "Keymap containing Info commands.") | 2757 "Keymap containing Info commands.") |
2758 | |
2638 (if Info-mode-map | 2759 (if Info-mode-map |
2639 nil | 2760 nil |
2640 (setq Info-mode-map (make-sparse-keymap)) | 2761 (setq Info-mode-map (make-sparse-keymap)) |
2641 (suppress-keymap Info-mode-map) | 2762 (suppress-keymap Info-mode-map) |
2642 (define-key Info-mode-map "." 'beginning-of-buffer) | 2763 (define-key Info-mode-map "." 'beginning-of-buffer) |
2791 (run-hooks 'Info-mode-hook) | 2912 (run-hooks 'Info-mode-hook) |
2792 (Info-set-mode-line)) | 2913 (Info-set-mode-line)) |
2793 | 2914 |
2794 (defvar Info-edit-map nil | 2915 (defvar Info-edit-map nil |
2795 "Local keymap used within `e' command of Info.") | 2916 "Local keymap used within `e' command of Info.") |
2917 | |
2796 (if Info-edit-map | 2918 (if Info-edit-map |
2797 nil | 2919 nil |
2798 ;; XEmacs: remove FSF stuff | 2920 ;; XEmacs: remove FSF stuff |
2799 (setq Info-edit-map (make-sparse-keymap)) | 2921 (setq Info-edit-map (make-sparse-keymap)) |
2800 (set-keymap-name Info-edit-map 'Info-edit-map) | 2922 (set-keymap-name Info-edit-map 'Info-edit-map) |
2930 (progn | 3052 (progn |
2931 (goto-char (match-end 0)) | 3053 (goto-char (match-end 0)) |
2932 (while | 3054 (while |
2933 (looking-at "[ \t]*[^:, \t\n]+:[ \t]+\\([^:,\t\n]+\\),?\n?") | 3055 (looking-at "[ \t]*[^:, \t\n]+:[ \t]+\\([^:,\t\n]+\\),?\n?") |
2934 (goto-char (match-end 0)) | 3056 (goto-char (match-end 0)) |
2935 (Info-highlight-region (match-beginning 1) (match-end 1) 'info-xref)))) | 3057 (Info-highlight-region (match-beginning 1) (match-end 1) |
3058 'info-xref)))) | |
2936 ;; Now get the xrefs in the body | 3059 ;; Now get the xrefs in the body |
2937 (goto-char (point-min)) | 3060 (goto-char (point-min)) |
2938 (while (re-search-forward xref-regexp nil t) | 3061 (while (re-search-forward xref-regexp nil t) |
2939 (if (= (char-after (1- (match-beginning 0))) ?\") ; hack | 3062 (if (= (char-after (1- (match-beginning 0))) ?\") ; hack |
2940 nil | 3063 nil |
2941 (Info-highlight-region (match-beginning 1) (match-end 1) 'info-xref))) | 3064 (Info-highlight-region (match-beginning 1) (match-end 1) |
3065 'info-xref))) | |
2942 ;; then highlight the nodes in the menu. | 3066 ;; then highlight the nodes in the menu. |
2943 (goto-char (point-min)) | 3067 (goto-char (point-min)) |
2944 (if (and (search-forward "\n* menu:" nil t)) | 3068 (if (and (search-forward "\n* menu:" nil t)) |
2945 (while (re-search-forward | 3069 (while (re-search-forward |
2946 "^\\* \\([^:\t\n]*\\):?:[ \t\n]" nil t) | 3070 "^\\* \\([^:\t\n]*\\):?:[ \t\n]" nil t) |
2947 (Info-highlight-region (match-beginning 1) (match-end 1) 'info-node))) | 3071 (Info-highlight-region (match-beginning 1) (match-end 1) |
3072 'info-node))) | |
2948 (set-buffer-modified-p nil)))) | 3073 (set-buffer-modified-p nil)))) |
2949 | 3074 |
2950 (defun Info-construct-menu (&optional event) | 3075 (defun Info-construct-menu (&optional event) |
2951 "Construct a menu of Info commands. | 3076 "Construct a menu of Info commands. |
2952 Adds an entry for the node at EVENT, or under point if EVENT is omitted. | 3077 Adds an entry for the node at EVENT, or under point if EVENT is omitted. |
2953 Used to construct the menubar submenu and popup menu." | 3078 Used to construct the menubar submenu and popup menu." |
2954 (or event (setq event (point))) | 3079 (or event (setq event (point))) |
2955 (let ((case-fold-search t) | 3080 (let ((case-fold-search t) |
2956 (xref-regexp (concat "\\*" | 3081 (xref-regexp (concat "\\*" |
2957 (regexp-quote Info-footnote-tag) | 3082 (regexp-quote Info-footnote-tag) |
2958 "[ \n\t]*\\([^:]*\\):")) | 3083 "[ \n\t]*\\([^:]*\\):")) |
2959 up-p prev-p next-p menu xrefs subnodes in) | 3084 up-p prev-p next-p menu xrefs subnodes in) |
2960 (save-excursion | 3085 (save-excursion |
2961 ;; `one-space' fixes "Notes:" xrefs that are split across lines. | 3086 ;; `one-space' fixes "Notes:" xrefs that are split across lines. |