Mercurial > emacs
comparison lisp/help.el @ 39651:444f50200adc
(help-mode-map): Make button-buffer-map our parent.
Don't bind mouse events or tab/backtab.
(help-function, help-variable, help-face, help-coding-system)
(help-input-method, help-character-set, help-back, help-info)
(help-customize-variable, help-function-def, help-variable-def):
New button types.
(help-button-action): New function.
(describe-function-1): Pass help button-types to `help-xref-button'
rather than help function and help-echo string. Don't put multiple
help-function args in a list to pass them to help-xref-button, just pass
them as multiple arguments. Use `help-insert-xref-button' to make
[back]-button, rather than `help-xref-button'.
(help-xref-button): Take a button-type TYPE as a parameter rather than a
function. Remove HELP-ECHO parameter. Remove DATA parameter and add a
&rest parameter ARGS to serve the same purpose. Use `make-text-button'
to add the button.
(help-insert-xref-button): Use `insert-text-button' to add the button.
(help-follow-mouse, help-next-ref, help-previous-ref): Functions removed.
(help-do-xref): New function.
(help-follow): Use `push-button' and `help-do-xref' to do most of the work.
author | Miles Bader <miles@gnu.org> |
---|---|
date | Sun, 07 Oct 2001 12:05:22 +0000 |
parents | a8abe33e09d1 |
children | 4bd383bb2137 |
comparison
equal
deleted
inserted
replaced
39650:85be22a1994b | 39651:444f50200adc |
---|---|
38 (defvar help-map (make-sparse-keymap) | 38 (defvar help-map (make-sparse-keymap) |
39 "Keymap for characters following the Help key.") | 39 "Keymap for characters following the Help key.") |
40 | 40 |
41 (defvar help-mode-map (make-sparse-keymap) | 41 (defvar help-mode-map (make-sparse-keymap) |
42 "Keymap for help mode.") | 42 "Keymap for help mode.") |
43 | |
44 (set-keymap-parent help-mode-map button-buffer-map) | |
43 | 45 |
44 (define-key global-map (char-to-string help-char) 'help-command) | 46 (define-key global-map (char-to-string help-char) 'help-command) |
45 (define-key global-map [help] 'help-command) | 47 (define-key global-map [help] 'help-command) |
46 (define-key global-map [f1] 'help-command) | 48 (define-key global-map [f1] 'help-command) |
47 (fset 'help-command help-map) | 49 (fset 'help-command help-map) |
95 | 97 |
96 (define-key help-map "v" 'describe-variable) | 98 (define-key help-map "v" 'describe-variable) |
97 | 99 |
98 (define-key help-map "q" 'help-quit) | 100 (define-key help-map "q" 'help-quit) |
99 | 101 |
100 (define-key help-mode-map [mouse-2] 'help-follow-mouse) | |
101 (define-key help-mode-map "\C-c\C-b" 'help-go-back) | 102 (define-key help-mode-map "\C-c\C-b" 'help-go-back) |
102 (define-key help-mode-map "\C-c\C-c" 'help-follow) | 103 (define-key help-mode-map "\C-c\C-c" 'help-follow) |
103 (define-key help-mode-map "\t" 'help-next-ref) | |
104 (define-key help-mode-map [backtab] 'help-previous-ref) | |
105 (define-key help-mode-map [(shift tab)] 'help-previous-ref) | |
106 ;; Documentation only, since we use minor-mode-overriding-map-alist. | 104 ;; Documentation only, since we use minor-mode-overriding-map-alist. |
107 (define-key help-mode-map "\r" 'help-follow) | 105 (define-key help-mode-map "\r" 'help-follow) |
108 | 106 |
109 (defvar help-xref-stack nil | 107 (defvar help-xref-stack nil |
110 "A stack of ways by which to return to help buffers after following xrefs. | 108 "A stack of ways by which to return to help buffers after following xrefs. |
125 (defcustom help-mode-hook nil | 123 (defcustom help-mode-hook nil |
126 "Hook run by `help-mode'." | 124 "Hook run by `help-mode'." |
127 :type 'hook | 125 :type 'hook |
128 :group 'help) | 126 :group 'help) |
129 | 127 |
128 | |
129 ;; Button types used by help | |
130 | |
131 ;; Make some button types that all use the same naming conventions | |
132 (dolist (help-type '("function" "variable" "face" | |
133 "coding-system" "input-method" "character-set")) | |
134 (define-button-type (intern (purecopy (concat "help-" help-type))) | |
135 'help-function (intern (concat "describe-" help-type)) | |
136 'help-echo (purecopy (concat "mouse-2, RET: describe this " help-type)) | |
137 'action #'help-button-action)) | |
138 | |
139 ;; make some more ideosyncratic button types | |
140 | |
141 (define-button-type 'help-symbol | |
142 'help-function #'help-xref-interned | |
143 'help-echo (purecopy "mouse-2, RET: describe this symbol") | |
144 'action #'help-button-action) | |
145 | |
146 (define-button-type 'help-back | |
147 'help-function #'help-xref-go-back | |
148 'help-echo (purecopy "mouse-2, RET: go back to previous help buffer") | |
149 'action #'help-button-action) | |
150 | |
151 (define-button-type 'help-info | |
152 'help-function #'info | |
153 'help-echo (purecopy"mouse-2, RET: read this Info node") | |
154 'action #'help-button-action) | |
155 | |
156 (define-button-type 'help-customize-variable | |
157 'help-function (lambda (v) | |
158 (if help-xref-stack | |
159 (pop help-xref-stack)) | |
160 (customize-variable v)) | |
161 'help-echo (purecopy "mouse-2, RET: customize variable") | |
162 'action #'help-button-action) | |
163 | |
164 (define-button-type 'help-function-def | |
165 'help-function (lambda (fun file) | |
166 (require 'find-func) | |
167 ;; Don't use find-function-noselect because it follows | |
168 ;; aliases (which fails for built-in functions). | |
169 (let* ((location (find-function-search-for-symbol | |
170 fun nil file))) | |
171 (pop-to-buffer (car location)) | |
172 (goto-char (cdr location)))) | |
173 'help-echo (purecopy "mouse-2, RET: find function's definition") | |
174 'action #'help-button-action) | |
175 | |
176 (define-button-type 'help-variable-def | |
177 'help-function (lambda (arg) | |
178 (let ((location | |
179 (find-variable-noselect arg))) | |
180 (pop-to-buffer (car location)) | |
181 (goto-char (cdr location)))) | |
182 'help-echo (purecopy"mouse-2, RET: find variable's definition") | |
183 'action #'help-button-action) | |
184 | |
185 (defun help-button-action (button) | |
186 "Call this button's help function." | |
187 (help-do-xref (button-start button) | |
188 (button-get button 'help-function) | |
189 (button-get button 'help-args))) | |
190 | |
191 | |
130 (defun help-mode () | 192 (defun help-mode () |
131 "Major mode for viewing help text and navigating references in it. | 193 "Major mode for viewing help text and navigating references in it. |
132 Entry to this mode runs the normal hook `help-mode-hook'. | 194 Entry to this mode runs the normal hook `help-mode-hook'. |
133 Commands: | 195 Commands: |
134 \\{help-mode-map}" | 196 \\{help-mode-map}" |
693 (princ string) | 755 (princ string) |
694 (with-current-buffer "*Help*" | 756 (with-current-buffer "*Help*" |
695 (save-excursion | 757 (save-excursion |
696 (save-match-data | 758 (save-match-data |
697 (if (re-search-backward "alias for `\\([^`']+\\)'" nil t) | 759 (if (re-search-backward "alias for `\\([^`']+\\)'" nil t) |
698 (help-xref-button 1 #'describe-function def | 760 (help-xref-button 1 'help-function def))))) |
699 "mouse-2, RET: describe this function"))))) | |
700 (or file-name | 761 (or file-name |
701 (setq file-name (symbol-file function))) | 762 (setq file-name (symbol-file function))) |
702 (if file-name | 763 (if file-name |
703 (progn | 764 (progn |
704 (princ " in `") | 765 (princ " in `") |
708 (princ "'") | 769 (princ "'") |
709 ;; Make a hyperlink to the library. | 770 ;; Make a hyperlink to the library. |
710 (with-current-buffer "*Help*" | 771 (with-current-buffer "*Help*" |
711 (save-excursion | 772 (save-excursion |
712 (re-search-backward "`\\([^`']+\\)'" nil t) | 773 (re-search-backward "`\\([^`']+\\)'" nil t) |
713 (help-xref-button | 774 (help-xref-button 1 'help-function-def function file-name))))) |
714 1 | |
715 #'(lambda (fun file) | |
716 (require 'find-func) | |
717 ;; Don't use find-function-noselect because it follows | |
718 ;; aliases (which fails for built-in functions). | |
719 (let* ((location (find-function-search-for-symbol | |
720 fun nil file))) | |
721 (pop-to-buffer (car location)) | |
722 (goto-char (cdr location)))) | |
723 (list function file-name) | |
724 "mouse-2, RET: find function's definition"))))) | |
725 (if need-close (princ ")")) | 775 (if need-close (princ ")")) |
726 (princ ".") | 776 (princ ".") |
727 (terpri) | 777 (terpri) |
728 ;; Handle symbols aliased to other symbols. | 778 ;; Handle symbols aliased to other symbols. |
729 (setq def (indirect-function def)) | 779 (setq def (indirect-function def)) |
816 (cond | 866 (cond |
817 ((looking-at "\"") (forward-sexp 1)) | 867 ((looking-at "\"") (forward-sexp 1)) |
818 ((looking-at "#<") (search-forward ">" nil 'move)) | 868 ((looking-at "#<") (search-forward ">" nil 'move)) |
819 ((looking-at "\\(\\(\\sw\\|\\s_\\)+\\)") | 869 ((looking-at "\\(\\(\\sw\\|\\s_\\)+\\)") |
820 (let* ((sym (intern-soft (match-string 1))) | 870 (let* ((sym (intern-soft (match-string 1))) |
821 (fn (cond ((fboundp sym) #'describe-function) | 871 (type (cond ((fboundp sym) 'help-function) |
822 ((or (memq sym '(t nil)) | 872 ((or (memq sym '(t nil)) |
823 (keywordp sym)) | 873 (keywordp sym)) |
824 nil) | 874 nil) |
825 ((and sym (boundp sym)) | 875 ((and sym (boundp sym)) |
826 #'describe-variable)))) | 876 'help-variable)))) |
827 (when fn (help-xref-button 1 fn sym))) | 877 (when type (help-xref-button 1 type sym))) |
828 (goto-char (match-end 1))) | 878 (goto-char (match-end 1))) |
829 (t (forward-char 1)))))) | 879 (t (forward-char 1)))))) |
830 (set-syntax-table ost)))) | 880 (set-syntax-table ost)))) |
831 | 881 |
832 (defun describe-variable (variable &optional buffer) | 882 (defun describe-variable (variable &optional buffer) |
926 (princ (concat "You can " customize-label " this variable.")) | 976 (princ (concat "You can " customize-label " this variable.")) |
927 (with-current-buffer "*Help*" | 977 (with-current-buffer "*Help*" |
928 (save-excursion | 978 (save-excursion |
929 (re-search-backward | 979 (re-search-backward |
930 (concat "\\(" customize-label "\\)") nil t) | 980 (concat "\\(" customize-label "\\)") nil t) |
931 (help-xref-button 1 (lambda (v) | 981 (help-xref-button 1 'help-customize-variable variable))))) |
932 (if help-xref-stack | |
933 (pop help-xref-stack)) | |
934 (customize-variable v)) | |
935 variable | |
936 "mouse-2, RET: customize variable"))))) | |
937 ;; Make a hyperlink to the library if appropriate. (Don't | 982 ;; Make a hyperlink to the library if appropriate. (Don't |
938 ;; change the format of the buffer's initial line in case | 983 ;; change the format of the buffer's initial line in case |
939 ;; anything expects the current format.) | 984 ;; anything expects the current format.) |
940 (let ((file-name (symbol-file variable))) | 985 (let ((file-name (symbol-file variable))) |
941 (when file-name | 986 (when file-name |
943 (princ file-name) | 988 (princ file-name) |
944 (princ "'.") | 989 (princ "'.") |
945 (with-current-buffer "*Help*" | 990 (with-current-buffer "*Help*" |
946 (save-excursion | 991 (save-excursion |
947 (re-search-backward "`\\([^`']+\\)'" nil t) | 992 (re-search-backward "`\\([^`']+\\)'" nil t) |
948 (help-xref-button | 993 (help-xref-button 1 'help-variable-def variable))))) |
949 1 (lambda (arg) | |
950 (let ((location | |
951 (find-variable-noselect arg))) | |
952 (pop-to-buffer (car location)) | |
953 (goto-char (cdr location)))) | |
954 variable "mouse-2, RET: find variable's definition"))))) | |
955 | 994 |
956 (print-help-return-message) | 995 (print-help-return-message) |
957 (save-excursion | 996 (save-excursion |
958 (set-buffer standard-output) | 997 (set-buffer standard-output) |
959 ;; Return the text we displayed. | 998 ;; Return the text we displayed. |
1156 (while (re-search-forward help-xref-info-regexp nil t) | 1195 (while (re-search-forward help-xref-info-regexp nil t) |
1157 (let ((data (match-string 1))) | 1196 (let ((data (match-string 1))) |
1158 (save-match-data | 1197 (save-match-data |
1159 (unless (string-match "^([^)]+)" data) | 1198 (unless (string-match "^([^)]+)" data) |
1160 (setq data (concat "(emacs)" data)))) | 1199 (setq data (concat "(emacs)" data)))) |
1161 (help-xref-button 1 #'info data | 1200 (help-xref-button 1 'help-info data)))) |
1162 "mouse-2, RET: read this Info node")))) | |
1163 ;; Mule related keywords. Do this before trying | 1201 ;; Mule related keywords. Do this before trying |
1164 ;; `help-xref-symbol-regexp' because some of Mule | 1202 ;; `help-xref-symbol-regexp' because some of Mule |
1165 ;; keywords have variable or function definitions. | 1203 ;; keywords have variable or function definitions. |
1166 (if help-xref-mule-regexp | 1204 (if help-xref-mule-regexp |
1167 (save-excursion | 1205 (save-excursion |
1169 (let* ((data (match-string 7)) | 1207 (let* ((data (match-string 7)) |
1170 (sym (intern-soft data))) | 1208 (sym (intern-soft data))) |
1171 (cond | 1209 (cond |
1172 ((match-string 3) ; coding system | 1210 ((match-string 3) ; coding system |
1173 (and sym (coding-system-p sym) | 1211 (and sym (coding-system-p sym) |
1174 (help-xref-button | 1212 (help-xref-button 6 'help-coding-system sym))) |
1175 7 #'describe-coding-system sym | |
1176 "mouse-2, RET: describe this coding system"))) | |
1177 ((match-string 4) ; input method | 1213 ((match-string 4) ; input method |
1178 (and (assoc data input-method-alist) | 1214 (and (assoc data input-method-alist) |
1179 (help-xref-button | 1215 (help-xref-button 7 'help-input-method data))) |
1180 7 #'describe-input-method data | |
1181 "mouse-2, RET: describe this input method"))) | |
1182 ((or (match-string 5) (match-string 6)) ; charset | 1216 ((or (match-string 5) (match-string 6)) ; charset |
1183 (and sym (charsetp sym) | 1217 (and sym (charsetp sym) |
1184 (help-xref-button | 1218 (help-xref-button 7 'help-character-set sym))) |
1185 7 #'describe-character-set sym | |
1186 "mouse-2, RET: describe this character set"))) | |
1187 ((assoc data input-method-alist) | 1219 ((assoc data input-method-alist) |
1188 (help-xref-button | 1220 (help-xref-button 7 'help-character-set data)) |
1189 7 #'describe-input-method data | |
1190 "mouse-2, RET: describe this input method")) | |
1191 ((and sym (coding-system-p sym)) | 1221 ((and sym (coding-system-p sym)) |
1192 (help-xref-button | 1222 (help-xref-button 7 'help-coding-system sym)) |
1193 7 #'describe-coding-system sym | |
1194 "mouse-2, RET: describe this coding system")) | |
1195 ((and sym (charsetp sym)) | 1223 ((and sym (charsetp sym)) |
1196 (help-xref-button | 1224 (help-xref-button 7 'help-character-set sym))))))) |
1197 7 #'describe-character-set sym | |
1198 "mouse-2, RET: describe this character set"))))))) | |
1199 ;; Quoted symbols | 1225 ;; Quoted symbols |
1200 (save-excursion | 1226 (save-excursion |
1201 (while (re-search-forward help-xref-symbol-regexp nil t) | 1227 (while (re-search-forward help-xref-symbol-regexp nil t) |
1202 (let* ((data (match-string 8)) | 1228 (let* ((data (match-string 8)) |
1203 (sym (intern-soft data))) | 1229 (sym (intern-soft data))) |
1204 (if sym | 1230 (if sym |
1205 (cond | 1231 (cond |
1206 ((match-string 3) ; `variable' &c | 1232 ((match-string 3) ; `variable' &c |
1207 (and (boundp sym) ; `variable' doesn't ensure | 1233 (and (boundp sym) ; `variable' doesn't ensure |
1208 ; it's actually bound | 1234 ; it's actually bound |
1209 (help-xref-button | 1235 (help-xref-button 8 'help-variable sym))) |
1210 8 #'describe-variable sym | |
1211 "mouse-2, RET: describe this variable"))) | |
1212 ((match-string 4) ; `function' &c | 1236 ((match-string 4) ; `function' &c |
1213 (and (fboundp sym) ; similarly | 1237 (and (fboundp sym) ; similarly |
1214 (help-xref-button | 1238 (help-xref-button 8 'help-function sym))) |
1215 8 #'describe-function sym | |
1216 "mouse-2, RET: describe this function"))) | |
1217 ((match-string 5) ; `face' | 1239 ((match-string 5) ; `face' |
1218 (and (facep sym) | 1240 (and (facep sym) |
1219 (help-xref-button 8 #'describe-face sym | 1241 (help-xref-button 8 'help-face sym))) |
1220 "mouse-2, RET: describe this face"))) | |
1221 ((match-string 6)) ; nothing for `symbol' | 1242 ((match-string 6)) ; nothing for `symbol' |
1222 ((match-string 7) | 1243 ((match-string 7) |
1223 (help-xref-button | 1244 ;; this used: |
1224 8 | 1245 ;; #'(lambda (arg) |
1225 #'(lambda (arg) | 1246 ;; (let ((location |
1226 (let ((location | 1247 ;; (find-function-noselect arg))) |
1227 (find-function-noselect arg))) | 1248 ;; (pop-to-buffer (car location)) |
1228 (pop-to-buffer (car location)) | 1249 ;; (goto-char (cdr location)))) |
1229 (goto-char (cdr location)))) | 1250 (help-xref-button 8 'help-function-def sym)) |
1230 sym | |
1231 "mouse-2, RET: find function's definition")) | |
1232 ((and (boundp sym) (fboundp sym)) | 1251 ((and (boundp sym) (fboundp sym)) |
1233 ;; We can't intuit whether to use the | 1252 ;; We can't intuit whether to use the |
1234 ;; variable or function doc -- supply both. | 1253 ;; variable or function doc -- supply both. |
1235 (help-xref-button | 1254 (help-xref-button 8 'help-symbol sym)) |
1236 8 #'help-xref-interned sym | |
1237 "mouse-2, RET: describe this symbol")) | |
1238 ((boundp sym) | 1255 ((boundp sym) |
1239 (help-xref-button | 1256 (help-xref-button 8 'help-variable sym)) |
1240 8 #'describe-variable sym | |
1241 "mouse-2, RET: describe this variable")) | |
1242 ((fboundp sym) | 1257 ((fboundp sym) |
1243 (help-xref-button | 1258 (help-xref-button 8 'help-function sym)) |
1244 8 #'describe-function sym | |
1245 "mouse-2, RET: describe this function")) | |
1246 ((facep sym) | 1259 ((facep sym) |
1247 (help-xref-button | 1260 (help-xref-button 8 'help-face sym))))))) |
1248 8 #'describe-face sym))))))) | |
1249 ;; An obvious case of a key substitution: | 1261 ;; An obvious case of a key substitution: |
1250 (save-excursion | 1262 (save-excursion |
1251 (while (re-search-forward | 1263 (while (re-search-forward |
1252 ;; Assume command name is only word characters | 1264 ;; Assume command name is only word characters |
1253 ;; and dashes to get things like `use M-x foo.'. | 1265 ;; and dashes to get things like `use M-x foo.'. |
1254 "\\<M-x\\s-+\\(\\sw\\(\\sw\\|-\\)+\\)" nil t) | 1266 "\\<M-x\\s-+\\(\\sw\\(\\sw\\|-\\)+\\)" nil t) |
1255 (let ((sym (intern-soft (match-string 1)))) | 1267 (let ((sym (intern-soft (match-string 1)))) |
1256 (if (fboundp sym) | 1268 (if (fboundp sym) |
1257 (help-xref-button | 1269 (help-xref-button 1 'help-function sym))))) |
1258 1 #'describe-function sym | |
1259 "mouse-2, RET: describe this command"))))) | |
1260 ;; Look for commands in whole keymap substitutions: | 1270 ;; Look for commands in whole keymap substitutions: |
1261 (save-excursion | 1271 (save-excursion |
1262 ;; Make sure to find the first keymap. | 1272 ;; Make sure to find the first keymap. |
1263 (goto-char (point-min)) | 1273 (goto-char (point-min)) |
1264 ;; Find a header and the column at which the command | 1274 ;; Find a header and the column at which the command |
1276 (skip-chars-backward "^\t\n") | 1286 (skip-chars-backward "^\t\n") |
1277 (if (and (>= (current-column) col) | 1287 (if (and (>= (current-column) col) |
1278 (looking-at "\\(\\sw\\|-\\)+$")) | 1288 (looking-at "\\(\\sw\\|-\\)+$")) |
1279 (let ((sym (intern-soft (match-string 0)))) | 1289 (let ((sym (intern-soft (match-string 0)))) |
1280 (if (fboundp sym) | 1290 (if (fboundp sym) |
1281 (help-xref-button | 1291 (help-xref-button 0 'help-function sym)))) |
1282 0 #'describe-function sym | |
1283 "mouse-2, RET: describe this function")))) | |
1284 (zerop (forward-line))))))))) | 1292 (zerop (forward-line))))))))) |
1285 (set-syntax-table stab)) | 1293 (set-syntax-table stab)) |
1286 ;; Delete extraneous newlines at the end of the docstring | 1294 ;; Delete extraneous newlines at the end of the docstring |
1287 (goto-char (point-max)) | 1295 (goto-char (point-max)) |
1288 (while (and (not (bobp)) (bolp)) | 1296 (while (and (not (bobp)) (bolp)) |
1289 (delete-char -1)) | 1297 (delete-char -1)) |
1290 ;; Make a back-reference in this buffer if appropriate. | 1298 ;; Make a back-reference in this buffer if appropriate. |
1291 (when (and help-xref-following help-xref-stack) | 1299 (when (and help-xref-following help-xref-stack) |
1292 (save-excursion | 1300 (insert "\n\n") |
1293 (insert "\n\n" help-back-label)) | 1301 (help-insert-xref-button help-back-label 'help-back |
1294 ;; Just to provide the match data: | 1302 (current-buffer)))) |
1295 (looking-at (concat "\n\n\\(" (regexp-quote help-back-label) "\\)")) | |
1296 (help-xref-button 1 #'help-xref-go-back (current-buffer)))) | |
1297 ;; View mode steals RET from us. | 1303 ;; View mode steals RET from us. |
1298 (set (make-local-variable 'minor-mode-overriding-map-alist) | 1304 (set (make-local-variable 'minor-mode-overriding-map-alist) |
1299 (list (cons 'view-mode | 1305 (list (cons 'view-mode |
1300 (let ((map (make-sparse-keymap))) | 1306 (let ((map (make-sparse-keymap))) |
1301 (set-keymap-parent map view-mode-map) | 1307 (set-keymap-parent map view-mode-map) |
1302 (define-key map "\r" 'help-follow) | 1308 (define-key map "\r" 'help-follow) |
1303 map)))) | 1309 map)))) |
1304 (set-buffer-modified-p old-modified)))) | 1310 (set-buffer-modified-p old-modified)))) |
1305 | 1311 |
1306 (defun help-xref-button (match-number function data &optional help-echo) | 1312 (defun help-xref-button (match-number type &rest args) |
1307 "Make a hyperlink for cross-reference text previously matched. | 1313 "Make a hyperlink for cross-reference text previously matched. |
1308 | |
1309 MATCH-NUMBER is the subexpression of interest in the last matched | 1314 MATCH-NUMBER is the subexpression of interest in the last matched |
1310 regexp. FUNCTION is a function to invoke when the button is | 1315 regexp. TYPE is the type of button to use. Any remaining arguments are |
1311 activated, applied to DATA. DATA may be a single value or a list. | 1316 passed to the button's help-function when it is invoked. |
1312 See `help-make-xrefs'. | 1317 See `help-make-xrefs'." |
1313 If optional arg HELP-ECHO is supplied, it is used as a help string." | |
1314 ;; Don't mung properties we've added specially in some instances. | 1318 ;; Don't mung properties we've added specially in some instances. |
1315 (unless (get-text-property (match-beginning match-number) 'help-xref) | 1319 (unless (button-at (match-beginning match-number)) |
1316 (add-text-properties (match-beginning match-number) | 1320 (make-text-button (match-beginning match-number) |
1317 (match-end match-number) | 1321 (match-end match-number) |
1318 (list 'mouse-face 'highlight | 1322 'type type 'help-args args))) |
1319 'help-xref (cons function | 1323 |
1320 (if (listp data) | 1324 (defun help-insert-xref-button (string type &rest args) |
1321 data | |
1322 (list data))))) | |
1323 (if help-echo | |
1324 (put-text-property (match-beginning match-number) | |
1325 (match-end match-number) | |
1326 'help-echo help-echo)) | |
1327 (if help-highlight-p | |
1328 (put-text-property (match-beginning match-number) | |
1329 (match-end match-number) | |
1330 'face help-highlight-face)))) | |
1331 | |
1332 (defun help-insert-xref-button (string function data &optional help-echo) | |
1333 "Insert STRING and make a hyperlink from cross-reference text on it. | 1325 "Insert STRING and make a hyperlink from cross-reference text on it. |
1334 | 1326 TYPE is the type of button to use. Any remaining arguments are passed |
1335 FUNCTION is a function to invoke when the button is activated, applied | 1327 to the button's help-function when it is invoked. |
1336 to DATA. DATA may be a single value or a list. See `help-make-xrefs'. | 1328 See `help-make-xrefs'." |
1337 If optional arg HELP-ECHO is supplied, it is used as a help string." | 1329 (unless (button-at (point)) |
1338 (let ((pos (point))) | 1330 (insert-text-button string 'type type 'help-args args))) |
1339 (insert string) | |
1340 (goto-char pos) | |
1341 (search-forward string) | |
1342 (help-xref-button 0 function data help-echo))) | |
1343 | |
1344 | 1331 |
1345 | 1332 |
1346 ;; Additional functions for (re-)creating types of help buffers. | 1333 ;; Additional functions for (re-)creating types of help buffers. |
1347 (defun help-xref-interned (symbol) | 1334 (defun help-xref-interned (symbol) |
1348 "Follow a hyperlink which appeared to be an arbitrary interned SYMBOL. | 1335 "Follow a hyperlink which appeared to be an arbitrary interned SYMBOL. |
1371 (defun help-xref-mode (buffer) | 1358 (defun help-xref-mode (buffer) |
1372 "Do a `describe-mode' for the specified BUFFER." | 1359 "Do a `describe-mode' for the specified BUFFER." |
1373 (save-excursion | 1360 (save-excursion |
1374 (set-buffer buffer) | 1361 (set-buffer buffer) |
1375 (describe-mode))) | 1362 (describe-mode))) |
1363 | |
1376 | 1364 |
1377 ;;; Navigation/hyperlinking with xrefs | 1365 ;;; Navigation/hyperlinking with xrefs |
1378 | |
1379 (defun help-follow-mouse (click) | |
1380 "Follow the cross-reference that you click on." | |
1381 (interactive "e") | |
1382 (let* ((start (event-start click)) | |
1383 (window (car start)) | |
1384 (pos (car (cdr start)))) | |
1385 (with-current-buffer (window-buffer window) | |
1386 (help-follow pos)))) | |
1387 | 1366 |
1388 (defun help-xref-go-back (buffer) | 1367 (defun help-xref-go-back (buffer) |
1389 "From BUFFER, go back to previous help buffer text using `help-xref-stack'." | 1368 "From BUFFER, go back to previous help buffer text using `help-xref-stack'." |
1390 (let (item position method args) | 1369 (let (item position method args) |
1391 (with-current-buffer buffer | 1370 (with-current-buffer buffer |
1403 (goto-char (car position)))))) | 1382 (goto-char (car position)))))) |
1404 | 1383 |
1405 (defun help-go-back () | 1384 (defun help-go-back () |
1406 "Invoke the [back] button (if any) in the Help mode buffer." | 1385 "Invoke the [back] button (if any) in the Help mode buffer." |
1407 (interactive) | 1386 (interactive) |
1408 (help-follow (1- (point-max)))) | 1387 (let ((back-button (button-at (1- (point-max))))) |
1388 (if back-button | |
1389 (button-activate back-button) | |
1390 (error "No [back] button")))) | |
1391 | |
1392 (defun help-do-xref (pos function args) | |
1393 "Call the help cross-reference function FUNCTION with args ARGS. | |
1394 Things are set up properly so that the resulting help-buffer has | |
1395 a proper [back] button." | |
1396 (setq help-xref-stack (cons (cons (cons pos (buffer-name)) | |
1397 help-xref-stack-item) | |
1398 help-xref-stack)) | |
1399 (setq help-xref-stack-item nil) | |
1400 ;; There is a reference at point. Follow it. | |
1401 (let ((help-xref-following t)) | |
1402 (apply function args))) | |
1409 | 1403 |
1410 (defun help-follow (&optional pos) | 1404 (defun help-follow (&optional pos) |
1411 "Follow cross-reference at POS, defaulting to point. | 1405 "Follow cross-reference at POS, defaulting to point. |
1412 | 1406 |
1413 For the cross-reference format, see `help-make-xrefs'." | 1407 For the cross-reference format, see `help-make-xrefs'." |
1414 (interactive "d") | 1408 (interactive "d") |
1415 (unless pos | 1409 (unless pos |
1416 (setq pos (point))) | 1410 (setq pos (point))) |
1417 (let* ((help-data | 1411 (unless (push-button pos) |
1418 (or (and (not (= pos (point-max))) | 1412 ;; check if the symbol under point is a function or variable |
1419 (get-text-property pos 'help-xref)) | 1413 (let ((sym |
1420 (and (not (= pos (point-min))) | 1414 (intern |
1421 (get-text-property (1- pos) 'help-xref)) | 1415 (save-excursion |
1422 ;; check if the symbol under point is a function or variable | 1416 (goto-char pos) (skip-syntax-backward "w_") |
1423 (let ((sym | 1417 (buffer-substring (point) |
1424 (intern | 1418 (progn (skip-syntax-forward "w_") |
1425 (save-excursion | 1419 (point))))))) |
1426 (goto-char pos) (skip-syntax-backward "w_") | 1420 (when (or (boundp sym) (fboundp sym)) |
1427 (buffer-substring (point) | 1421 (help-do-xref pos #'help-xref-interned (list sym)))))) |
1428 (progn (skip-syntax-forward "w_") | |
1429 (point))))))) | |
1430 (when (or (boundp sym) (fboundp sym)) | |
1431 (list #'help-xref-interned sym))))) | |
1432 (method (car help-data)) | |
1433 (args (cdr help-data))) | |
1434 (when help-data | |
1435 (setq help-xref-stack (cons (cons (cons pos (buffer-name)) | |
1436 help-xref-stack-item) | |
1437 help-xref-stack)) | |
1438 (setq help-xref-stack-item nil) | |
1439 ;; There is a reference at point. Follow it. | |
1440 (let ((help-xref-following t)) | |
1441 (apply method args))))) | |
1442 | |
1443 ;; For tabbing through buffer. | |
1444 (defun help-next-ref () | |
1445 "Find the next help cross-reference in the buffer." | |
1446 (interactive) | |
1447 (let (pos) | |
1448 (while (not pos) | |
1449 (if (get-text-property (point) 'help-xref) ; move off reference | |
1450 (goto-char (or (next-single-property-change (point) 'help-xref) | |
1451 (point)))) | |
1452 (cond ((setq pos (next-single-property-change (point) 'help-xref)) | |
1453 (if pos (goto-char pos))) | |
1454 ((bobp) | |
1455 (message "No cross references in the buffer.") | |
1456 (setq pos t)) | |
1457 (t ; be circular | |
1458 (goto-char (point-min))))))) | |
1459 | |
1460 (defun help-previous-ref () | |
1461 "Find the previous help cross-reference in the buffer." | |
1462 (interactive) | |
1463 (let (pos) | |
1464 (while (not pos) | |
1465 (if (get-text-property (point) 'help-xref) ; move off reference | |
1466 (goto-char (or (previous-single-property-change (point) 'help-xref) | |
1467 (point)))) | |
1468 (cond ((setq pos (previous-single-property-change (point) 'help-xref)) | |
1469 (if pos (goto-char pos))) | |
1470 ((bobp) | |
1471 (message "No cross references in the buffer.") | |
1472 (setq pos t)) | |
1473 (t ; be circular | |
1474 (goto-char (point-max))))))) | |
1475 | 1422 |
1476 | 1423 |
1477 ;;; Automatic resizing of temporary buffers. | 1424 ;;; Automatic resizing of temporary buffers. |
1478 | 1425 |
1479 (defcustom temp-buffer-max-height (lambda (buffer) (/ (- (frame-height) 2) 2)) | 1426 (defcustom temp-buffer-max-height (lambda (buffer) (/ (- (frame-height) 2) 2)) |