Mercurial > hg > xemacs-beta
comparison lisp/info.el @ 272:c5d627a313b1 r21-0b34
Import from CVS: tag r21-0b34
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:28:48 +0200 |
parents | b2472a1930f2 |
children | ca9a9ec9c1c1 |
comparison
equal
deleted
inserted
replaced
271:c7b7086b0a39 | 272:c5d627a313b1 |
---|---|
299 ;; Modified 1997-07-10 by Karl M. Hegbloom | 299 ;; Modified 1997-07-10 by Karl M. Hegbloom |
300 ;; | 300 ;; |
301 ;; Added `Info-minibuffer-history' | 301 ;; Added `Info-minibuffer-history' |
302 ;; (also added to defaults in "lisp/utils/savehist.el") | 302 ;; (also added to defaults in "lisp/utils/savehist.el") |
303 ;; Other changes in main ChangeLog. | 303 ;; Other changes in main ChangeLog. |
304 | |
305 ;; Modified 1998-03-29 by Oscar Figueiredo | |
306 ;; | |
307 ;; Added automatic dir/localdir (re)building capability for directories that | |
308 ;; contain none or when it has become older than info files in the same | |
309 ;; directory. | |
304 | 310 |
305 ;; Code: | 311 ;; Code: |
306 | 312 |
307 (defgroup info nil | 313 (defgroup info nil |
308 "The info package for Emacs." | 314 "The info package for Emacs." |
377 "*List of additional directories to search for Info documentation | 383 "*List of additional directories to search for Info documentation |
378 files. These directories are not searched for merging the `dir' | 384 files. These directories are not searched for merging the `dir' |
379 file. An example might be something like: | 385 file. An example might be something like: |
380 \"/usr/local/lib/xemacs/packages/lisp/calc/\"" | 386 \"/usr/local/lib/xemacs/packages/lisp/calc/\"" |
381 :type '(repeat directory) | 387 :type '(repeat directory) |
388 :group 'info) | |
389 | |
390 (defcustom Info-rebuild-outdated-dir 'ask | |
391 "*What to do if the `dir' or `localdir' file needs to be (re)built. | |
392 Possible values are: | |
393 `never' never (re)build the `dir' or `localdir' file | |
394 `always' automatically (re)builds when needed | |
395 `ask' asks the user before (re)building" | |
396 :type '(choice (const :tag "never" never) | |
397 (const :tag "always" always) | |
398 (const :tag "ask" ask)) | |
382 :group 'info) | 399 :group 'info) |
383 | 400 |
384 (defvar Info-emacs-info-file-name "xemacs.info" | 401 (defvar Info-emacs-info-file-name "xemacs.info" |
385 "The filename of the XEmacs info for | 402 "The filename of the XEmacs info for |
386 `Info-goto-emacs-command-node' (`\\<help-mode-map>\\[Info-goto-emacs-command-node]')") | 403 `Info-goto-emacs-command-node' (`\\<help-mode-map>\\[Info-goto-emacs-command-node]')") |
470 (defvar Info-standalone nil | 487 (defvar Info-standalone nil |
471 "Non-nil if Emacs was started solely as an Info browser.") | 488 "Non-nil if Emacs was started solely as an Info browser.") |
472 | 489 |
473 (defvar Info-in-cross-reference nil) | 490 (defvar Info-in-cross-reference nil) |
474 (defvar Info-window-configuration nil) | 491 (defvar Info-window-configuration nil) |
492 | |
493 (defvar Info-dir-prologue "-*- Text -*- | |
494 This is the file .../info/dir, which contains the topmost node of the | |
495 Info hierarchy. The first time you invoke Info you start off | |
496 looking at that node, which is (dir)Top. | |
497 | |
498 File: dir Node: Top This is the top of the INFO tree | |
499 This (the Directory node) gives a menu of major topics. | |
500 | |
501 * Menu: The list of major topics begins on the next line. | |
502 | |
503 ") | |
475 | 504 |
476 ;;;###autoload | 505 ;;;###autoload |
477 (defun info (&optional file) | 506 (defun info (&optional file) |
478 "Enter Info, the documentation browser. | 507 "Enter Info, the documentation browser. |
479 Optional argument FILE specifies the file to examine; | 508 Optional argument FILE specifies the file to examine; |
762 (let ((truename (file-truename (expand-file-name (car dirs))))) | 791 (let ((truename (file-truename (expand-file-name (car dirs))))) |
763 (or (member truename dirs-done) | 792 (or (member truename dirs-done) |
764 (member (directory-file-name truename) dirs-done) | 793 (member (directory-file-name truename) dirs-done) |
765 ;; Try several variants of specified name. | 794 ;; Try several variants of specified name. |
766 ;; Try upcasing, appending `.info', or both. | 795 ;; Try upcasing, appending `.info', or both. |
767 (let* (file | 796 (let* (buf |
797 file | |
768 (attrs | 798 (attrs |
769 (or | 799 (or |
770 (progn (setq file (expand-file-name "dir" truename)) | 800 (progn (setq file (expand-file-name "dir" truename)) |
771 (file-attributes file)) | 801 (file-attributes file)) |
772 (progn (setq file (expand-file-name "DIR" truename)) | 802 (progn (setq file (expand-file-name "DIR" truename)) |
775 (file-attributes file)) | 805 (file-attributes file)) |
776 (progn (setq file (expand-file-name "DIR.INFO" truename)) | 806 (progn (setq file (expand-file-name "DIR.INFO" truename)) |
777 (file-attributes file)) | 807 (file-attributes file)) |
778 (progn (setq file (expand-file-name "localdir" truename)) | 808 (progn (setq file (expand-file-name "localdir" truename)) |
779 (file-attributes file)) | 809 (file-attributes file)) |
810 (progn (setq file (expand-file-name "dir" truename)) | |
811 nil) | |
780 ))) | 812 ))) |
781 (setq dirs-done | 813 (setq dirs-done |
782 (cons truename | 814 (cons truename |
783 (cons (directory-file-name truename) | 815 (cons (directory-file-name truename) |
784 dirs-done))) | 816 dirs-done))) |
785 (if attrs | 817 (if (not (string= truename |
818 (file-truename (car Info-directory-list)))) | |
819 (Info-maybe-update-dir file)) | |
820 (setq attrs (file-attributes file)) | |
821 (if (or (setq buf (find-buffer-visiting file)) | |
822 attrs) | |
786 (save-excursion | 823 (save-excursion |
787 (or buffers | 824 (or buffers |
788 (message "Composing main Info directory...")) | 825 (message "Composing main Info directory...")) |
789 (set-buffer (generate-new-buffer | 826 (set-buffer (or buf |
790 (if (string-match "localdir" file) | 827 (generate-new-buffer |
791 "localdir" | 828 (if (string-match "localdir" file) |
792 "info dir"))) | 829 "localdir" |
793 (insert-file-contents file) | 830 "info dir")))) |
831 (if (not buf) | |
832 (insert-file-contents file)) | |
794 (if (string-match "localdir" (buffer-name)) | 833 (if (string-match "localdir" (buffer-name)) |
795 (setq lbuffers (cons (current-buffer) lbuffers)) | 834 (setq lbuffers (cons (current-buffer) lbuffers)) |
796 (setq buffers (cons (current-buffer) buffers))) | 835 (setq buffers (cons (current-buffer) buffers))) |
797 (setq Info-dir-file-attributes | 836 (setq Info-dir-file-attributes |
798 (cons (cons file attrs) | 837 (cons (cons file attrs) |
924 (setq lbuffers (cdr lbuffers))) | 963 (setq lbuffers (cdr lbuffers))) |
925 (message "Composing main Info directory...done")) | 964 (message "Composing main Info directory...done")) |
926 (setq Info-dir-contents (buffer-string))) | 965 (setq Info-dir-contents (buffer-string))) |
927 (setq default-directory Info-dir-contents-directory) | 966 (setq default-directory Info-dir-contents-directory) |
928 (setq buffer-file-name (caar Info-dir-file-attributes))) | 967 (setq buffer-file-name (caar Info-dir-file-attributes))) |
968 | |
969 (defun Info-maybe-update-dir (file) | |
970 "Rebuild dir or localdir if it does not exist or is outdated." | |
971 (unless (or (eq Info-rebuild-outdated-dir 'never) | |
972 (not (file-exists-p (file-name-directory file))) | |
973 (null (directory-files (file-name-directory file) nil "\\.info"))) | |
974 (if (not (find-buffer-visiting file)) | |
975 (if (not (file-exists-p file)) | |
976 (if (or (eq Info-rebuild-outdated-dir 'always) | |
977 (and (eq Info-rebuild-outdated-dir 'ask) | |
978 (y-or-n-p (format "No dir file in %s. Rebuild now ? " (file-name-directory file))))) | |
979 (Info-build-dir-anew (file-name-directory file) (not (file-writable-p file)))) | |
980 (if (Info-dir-outdated-p file) | |
981 (if (or (eq Info-rebuild-outdated-dir 'always) | |
982 (and (eq Info-rebuild-outdated-dir 'ask) | |
983 (y-or-n-p (format "%s is outdated. Rebuild now ? " file)))) | |
984 (Info-rebuild-dir file (not (file-writable-p file))))))))) | |
985 | |
986 ;; Record which *.info files are newer than the dir file | |
987 (defvar Info-dir-newer-info-files nil) | |
988 | |
989 (defun Info-dir-outdated-p (file) | |
990 "Return non-nil if dir or localdir is outdated. | |
991 dir or localdir are outdated when an *.info file in the same | |
992 directory has been modified more recently." | |
993 (let ((dir-mod-time (nth 5 (file-attributes file))) | |
994 f-mod-time | |
995 newer) | |
996 (setq Info-dir-newer-info-files nil) | |
997 (mapcar | |
998 '(lambda (f) | |
999 (prog2 | |
1000 (setq f-mod-time (nth 5 (file-attributes f))) | |
1001 (setq newer (or (> (car f-mod-time) (car dir-mod-time)) | |
1002 (and (= (car f-mod-time) (car dir-mod-time)) | |
1003 (> (car (cdr f-mod-time)) (car (cdr dir-mod-time)))))) | |
1004 (if (and (file-readable-p f) | |
1005 newer) | |
1006 (setq Info-dir-newer-info-files | |
1007 (cons f Info-dir-newer-info-files))))) | |
1008 (directory-files (file-name-directory file) | |
1009 'fullname | |
1010 ".*\\.info\\(.gz\\|.Z\\|-z\\|.zip\\)?$" | |
1011 'nosort | |
1012 t)) | |
1013 Info-dir-newer-info-files)) | |
1014 | |
1015 (defun Info-extract-dir-entries-from (file) | |
1016 "Extract dir entries from the info FILE. | |
1017 dir entries are delimited by the markers `START-INFO-DIR-ENTRY' | |
1018 and `END-INFO-DIR-ENTRY'" | |
1019 (save-excursion | |
1020 (set-buffer (get-buffer-create " *Info-tmp*")) | |
1021 (when (file-readable-p file) | |
1022 (insert-file-contents file nil nil nil t) | |
1023 (goto-char (point-min)) | |
1024 (let (beg) | |
1025 (unless (null (re-search-forward "^START-INFO-DIR-ENTRY" nil t)) | |
1026 (forward-line 1) | |
1027 (setq beg (point)) | |
1028 (unless (null (re-search-forward "^END-INFO-DIR-ENTRY" nil t)) | |
1029 (goto-char (match-beginning 0)) | |
1030 (buffer-substring beg (point)))))))) | |
1031 | |
1032 (defun Info-build-dir-anew (directory to-temp) | |
1033 "Build a new info dir file in DIRECTORY" | |
1034 (save-excursion | |
1035 (let ((dirfile (expand-file-name "dir" directory))) | |
1036 (if to-temp | |
1037 (message "Creating temporary dir...") | |
1038 (message "Creating %s..." dirfile)) | |
1039 (set-buffer (find-file-noselect dirfile)) | |
1040 (erase-buffer) | |
1041 (insert Info-dir-prologue | |
1042 "Info files in " directory "\n\n") | |
1043 (mapcar | |
1044 '(lambda (f) | |
1045 (insert (or (Info-extract-dir-entries-from f) | |
1046 (format "* %s::\t[No description available]\n" | |
1047 (file-name-sans-extension (file-name-nondirectory f)))))) | |
1048 (directory-files directory | |
1049 'fullname | |
1050 ".*\\.info\\(.gz\\|.Z\\|-z\\|.zip\\)?$" | |
1051 nil | |
1052 t)) | |
1053 (if to-temp | |
1054 (set-buffer-modified-p nil) | |
1055 (save-buffer)) | |
1056 (if to-temp | |
1057 (message "Creating temporary dir...done") | |
1058 (message "Creating %s...done" dirfile))))) | |
1059 | |
1060 (defvar Info-dir-entry-matcher "^\\* \\([^:]+\\):\\([ \t]*(\\(.*\\))\\w*\\.\\|:\\)[ \t]+\\(.*\\)$") | |
1061 | |
1062 (defun Info-parse-dir-entry (entry) | |
1063 (string-match Info-dir-entry-matcher entry) | |
1064 (list (match-string 1 entry) (match-string 2 entry) (match-string 4 entry))) | |
1065 | |
1066 (defun Info-rebuild-dir (file to-temp) | |
1067 "Update an existing info dir file after info files have been modified" | |
1068 (save-excursion | |
1069 (let (dir-contents | |
1070 dir-entry | |
1071 file-dir-entry) | |
1072 (set-buffer (find-file-noselect file)) | |
1073 (if to-temp | |
1074 (message "Rebuilding temporary dir...") | |
1075 (message "Rebuilding %s..." file)) | |
1076 (setq buffer-read-only nil) | |
1077 (goto-char (point-min)) | |
1078 (search-forward "\^_") | |
1079 (re-search-forward "^\\* Menu:.*$" nil t) | |
1080 (narrow-to-region (or (and (re-search-forward Info-dir-entry-matcher nil t) | |
1081 (match-beginning 0)) | |
1082 (point)) | |
1083 (point-max)) | |
1084 (goto-char (point-min)) | |
1085 (while (re-search-forward Info-dir-entry-matcher nil t) | |
1086 (setq dir-contents (cons (list (downcase (or (match-string 3) | |
1087 (match-string 1))) | |
1088 (match-string 1) | |
1089 (match-string 2) | |
1090 (match-string 4)) | |
1091 dir-contents))) | |
1092 (mapcar '(lambda (file) | |
1093 (setq dir-entry (assoc (downcase | |
1094 (file-name-sans-extension | |
1095 (file-name-nondirectory file))) | |
1096 dir-contents) | |
1097 file-dir-entry (Info-extract-dir-entries-from file)) | |
1098 (if dir-entry | |
1099 (if file-dir-entry | |
1100 ;; A dir entry in the info file takes precedence over an | |
1101 ;; existing entry in the dir file | |
1102 (setcdr dir-entry (Info-parse-dir-entry file-dir-entry))) | |
1103 (if file-dir-entry | |
1104 (setq dir-contents (cons (cons 'dummy (Info-parse-dir-entry file-dir-entry)) | |
1105 dir-contents)) | |
1106 (setq dir-contents (cons (list 'dummy | |
1107 (capitalize (file-name-sans-extension | |
1108 (file-name-nondirectory file))) | |
1109 ":" | |
1110 "[No description available]") | |
1111 dir-contents))))) | |
1112 Info-dir-newer-info-files) | |
1113 (delete-region (point-min) (point-max)) | |
1114 (mapcar '(lambda (entry) | |
1115 (setq entry (cdr entry)) | |
1116 (insert (format "* %s:" | |
1117 (car entry))) | |
1118 (setq entry (cdr entry)) | |
1119 (insert (car entry)) | |
1120 (insert "\t" (car (cdr entry)) "\n")) | |
1121 (nreverse dir-contents)) | |
1122 (widen) | |
1123 (if to-temp | |
1124 (set-buffer-modified-p nil) | |
1125 (save-buffer)) | |
1126 (if to-temp | |
1127 (message "Rebuilding temporary dir...done") | |
1128 (message "Rebuilding %s...done" file))))) | |
1129 | |
929 | 1130 |
930 (defun Info-history-add (file node point) | 1131 (defun Info-history-add (file node point) |
931 (if Info-keeping-history | 1132 (if Info-keeping-history |
932 (let* ((name (format "(%s)%s" (Info-file-name-only file) node)) | 1133 (let* ((name (format "(%s)%s" (Info-file-name-only file) node)) |
933 (found (assoc name Info-history))) | 1134 (found (assoc name Info-history))) |