| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
|
|---|
| 40 |
|
|---|
| 41 |
|
|---|
| 42 |
|
|---|
| 43 |
|
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
|
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 |
|
|---|
| 55 |
|
|---|
| 56 |
|
|---|
| 57 |
|
|---|
| 58 |
|
|---|
| 59 |
|
|---|
| 60 |
|
|---|
| 61 |
(require 'button) |
|---|
| 62 |
(eval-when-compile (require 'cl)) |
|---|
| 63 |
|
|---|
| 64 |
(defgroup apropos nil |
|---|
| 65 |
"Apropos commands for users and programmers." |
|---|
| 66 |
:group 'help |
|---|
| 67 |
:prefix "apropos") |
|---|
| 68 |
|
|---|
| 69 |
|
|---|
| 70 |
(defcustom apropos-do-all nil |
|---|
| 71 |
"*Whether the apropos commands should do more. |
|---|
| 72 |
|
|---|
| 73 |
Slows them down more or less. Set this non-nil if you have a fast machine." |
|---|
| 74 |
:group 'apropos |
|---|
| 75 |
:type 'boolean) |
|---|
| 76 |
|
|---|
| 77 |
|
|---|
| 78 |
(defcustom apropos-symbol-face 'bold |
|---|
| 79 |
"*Face for symbol name in Apropos output, or nil for none." |
|---|
| 80 |
:group 'apropos |
|---|
| 81 |
:type 'face) |
|---|
| 82 |
|
|---|
| 83 |
(defcustom apropos-keybinding-face 'underline |
|---|
| 84 |
"*Face for lists of keybinding in Apropos output, or nil for none." |
|---|
| 85 |
:group 'apropos |
|---|
| 86 |
:type 'face) |
|---|
| 87 |
|
|---|
| 88 |
(defcustom apropos-label-face 'italic |
|---|
| 89 |
"*Face for label (`Command', `Variable' ...) in Apropos output. |
|---|
| 90 |
A value of nil means don't use any special font for them, and also |
|---|
| 91 |
turns off mouse highlighting." |
|---|
| 92 |
:group 'apropos |
|---|
| 93 |
:type 'face) |
|---|
| 94 |
|
|---|
| 95 |
(defcustom apropos-property-face 'bold-italic |
|---|
| 96 |
"*Face for property name in apropos output, or nil for none." |
|---|
| 97 |
:group 'apropos |
|---|
| 98 |
:type 'face) |
|---|
| 99 |
|
|---|
| 100 |
(defcustom apropos-match-face 'match |
|---|
| 101 |
"*Face for matching text in Apropos documentation/value, or nil for none. |
|---|
| 102 |
This applies when you look for matches in the documentation or variable value |
|---|
| 103 |
for the pattern; the part that matches gets displayed in this font." |
|---|
| 104 |
:group 'apropos |
|---|
| 105 |
:type 'face) |
|---|
| 106 |
|
|---|
| 107 |
(defcustom apropos-sort-by-scores nil |
|---|
| 108 |
"*Non-nil means sort matches by scores; best match is shown first. |
|---|
| 109 |
This applies to all `apropos' commands except `apropos-documentation'. |
|---|
| 110 |
If value is `verbose', the computed score is shown for each match." |
|---|
| 111 |
:group 'apropos |
|---|
| 112 |
:type '(choice (const :tag "off" nil) |
|---|
| 113 |
(const :tag "on" t) |
|---|
| 114 |
(const :tag "show scores" verbose))) |
|---|
| 115 |
|
|---|
| 116 |
(defcustom apropos-documentation-sort-by-scores t |
|---|
| 117 |
"*Non-nil means sort matches by scores; best match is shown first. |
|---|
| 118 |
This applies to `apropos-documentation' only. |
|---|
| 119 |
If value is `verbose', the computed score is shown for each match." |
|---|
| 120 |
:group 'apropos |
|---|
| 121 |
:type '(choice (const :tag "off" nil) |
|---|
| 122 |
(const :tag "on" t) |
|---|
| 123 |
(const :tag "show scores" verbose))) |
|---|
| 124 |
|
|---|
| 125 |
(defvar apropos-mode-map |
|---|
| 126 |
(let ((map (make-sparse-keymap))) |
|---|
| 127 |
(set-keymap-parent map button-buffer-map) |
|---|
| 128 |
|
|---|
| 129 |
|
|---|
| 130 |
|
|---|
| 131 |
(define-key map "\C-m" 'apropos-follow) |
|---|
| 132 |
(define-key map " " 'scroll-up) |
|---|
| 133 |
(define-key map "\177" 'scroll-down) |
|---|
| 134 |
(define-key map "q" 'quit-window) |
|---|
| 135 |
map) |
|---|
| 136 |
"Keymap used in Apropos mode.") |
|---|
| 137 |
|
|---|
| 138 |
(defvar apropos-mode-hook nil |
|---|
| 139 |
"*Hook run when mode is turned on.") |
|---|
| 140 |
|
|---|
| 141 |
(defvar apropos-pattern nil |
|---|
| 142 |
"Apropos pattern as entered by user.") |
|---|
| 143 |
|
|---|
| 144 |
(defvar apropos-pattern-quoted nil |
|---|
| 145 |
"Apropos pattern passed through `regexp-quote'.") |
|---|
| 146 |
|
|---|
| 147 |
(defvar apropos-words () |
|---|
| 148 |
"Current list of apropos words extracted from `apropos-pattern'.") |
|---|
| 149 |
|
|---|
| 150 |
(defvar apropos-all-words () |
|---|
| 151 |
"Current list of words and synonyms.") |
|---|
| 152 |
|
|---|
| 153 |
(defvar apropos-regexp nil |
|---|
| 154 |
"Regexp used in current apropos run.") |
|---|
| 155 |
|
|---|
| 156 |
(defvar apropos-all-words-regexp nil |
|---|
| 157 |
"Regexp matching apropos-all-words.") |
|---|
| 158 |
|
|---|
| 159 |
(defvar apropos-files-scanned () |
|---|
| 160 |
"List of elc files already scanned in current run of `apropos-documentation'.") |
|---|
| 161 |
|
|---|
| 162 |
(defvar apropos-accumulator () |
|---|
| 163 |
"Alist of symbols already found in current apropos run.") |
|---|
| 164 |
|
|---|
| 165 |
(defvar apropos-item () |
|---|
| 166 |
"Current item in or for `apropos-accumulator'.") |
|---|
| 167 |
|
|---|
| 168 |
(defvar apropos-synonyms '( |
|---|
| 169 |
("find" "open" "edit") |
|---|
| 170 |
("kill" "cut") |
|---|
| 171 |
("yank" "paste") |
|---|
| 172 |
("region" "selection")) |
|---|
| 173 |
"List of synonyms known by apropos. |
|---|
| 174 |
Each element is a list of words where the first word is the standard Emacs |
|---|
| 175 |
term, and the rest of the words are alternative terms.") |
|---|
| 176 |
|
|---|
| 177 |
|
|---|
| 178 |
|
|---|
| 179 |
|
|---|
| 180 |
(define-button-type 'apropos-symbol |
|---|
| 181 |
'face apropos-symbol-face |
|---|
| 182 |
'help-echo "mouse-2, RET: Display more help on this symbol" |
|---|
| 183 |
'follow-link t |
|---|
| 184 |
'action #'apropos-symbol-button-display-help |
|---|
| 185 |
'skip t) |
|---|
| 186 |
|
|---|
| 187 |
(defun apropos-symbol-button-display-help (button) |
|---|
| 188 |
"Display further help for the `apropos-symbol' button BUTTON." |
|---|
| 189 |
(button-activate |
|---|
| 190 |
(or (apropos-next-label-button (button-start button)) |
|---|
| 191 |
(error "There is nothing to follow for `%s'" (button-label button))))) |
|---|
| 192 |
|
|---|
| 193 |
(define-button-type 'apropos-function |
|---|
| 194 |
'apropos-label "Function" |
|---|
| 195 |
'help-echo "mouse-2, RET: Display more help on this function" |
|---|
| 196 |
'follow-link t |
|---|
| 197 |
'action (lambda (button) |
|---|
| 198 |
(describe-function (button-get button 'apropos-symbol)))) |
|---|
| 199 |
|
|---|
| 200 |
(define-button-type 'apropos-macro |
|---|
| 201 |
'apropos-label "Macro" |
|---|
| 202 |
'help-echo "mouse-2, RET: Display more help on this macro" |
|---|
| 203 |
'follow-link t |
|---|
| 204 |
'action (lambda (button) |
|---|
| 205 |
(describe-function (button-get button 'apropos-symbol)))) |
|---|
| 206 |
|
|---|
| 207 |
(define-button-type 'apropos-command |
|---|
| 208 |
'apropos-label "Command" |
|---|
| 209 |
'help-echo "mouse-2, RET: Display more help on this command" |
|---|
| 210 |
'follow-link t |
|---|
| 211 |
'action (lambda (button) |
|---|
| 212 |
(describe-function (button-get button 'apropos-symbol)))) |
|---|
| 213 |
|
|---|
| 214 |
|
|---|
| 215 |
|
|---|
| 216 |
|
|---|
| 217 |
|
|---|
| 218 |
|
|---|
| 219 |
(define-button-type 'apropos-variable |
|---|
| 220 |
'apropos-label "Variable" |
|---|
| 221 |
'help-echo "mouse-2, RET: Display more help on this variable" |
|---|
| 222 |
'follow-link t |
|---|
| 223 |
'action (lambda (button) |
|---|
| 224 |
(describe-variable (button-get button 'apropos-symbol)))) |
|---|
| 225 |
|
|---|
| 226 |
(define-button-type 'apropos-face |
|---|
| 227 |
'apropos-label "Face" |
|---|
| 228 |
'help-echo "mouse-2, RET: Display more help on this face" |
|---|
| 229 |
'follow-link t |
|---|
| 230 |
'action (lambda (button) |
|---|
| 231 |
(describe-face (button-get button 'apropos-symbol)))) |
|---|
| 232 |
|
|---|
| 233 |
(define-button-type 'apropos-group |
|---|
| 234 |
'apropos-label "Group" |
|---|
| 235 |
'help-echo "mouse-2, RET: Display more help on this group" |
|---|
| 236 |
'follow-link t |
|---|
| 237 |
'action (lambda (button) |
|---|
| 238 |
(customize-group-other-window |
|---|
| 239 |
(button-get button 'apropos-symbol)))) |
|---|
| 240 |
|
|---|
| 241 |
(define-button-type 'apropos-widget |
|---|
| 242 |
'apropos-label "Widget" |
|---|
| 243 |
'help-echo "mouse-2, RET: Display more help on this widget" |
|---|
| 244 |
'follow-link t |
|---|
| 245 |
'action (lambda (button) |
|---|
| 246 |
(widget-browse-other-window (button-get button 'apropos-symbol)))) |
|---|
| 247 |
|
|---|
| 248 |
(define-button-type 'apropos-plist |
|---|
| 249 |
'apropos-label "Plist" |
|---|
| 250 |
'help-echo "mouse-2, RET: Display more help on this plist" |
|---|
| 251 |
'follow-link t |
|---|
| 252 |
'action (lambda (button) |
|---|
| 253 |
(apropos-describe-plist (button-get button 'apropos-symbol)))) |
|---|
| 254 |
|
|---|
| 255 |
(defun apropos-next-label-button (pos) |
|---|
| 256 |
"Return the next apropos label button after POS, or nil if there's none. |
|---|
| 257 |
Will also return nil if more than one `apropos-symbol' button is encountered |
|---|
| 258 |
before finding a label." |
|---|
| 259 |
(let* ((button (next-button pos t)) |
|---|
| 260 |
(already-hit-symbol nil) |
|---|
| 261 |
(label (and button (button-get button 'apropos-label))) |
|---|
| 262 |
(type (and button (button-get button 'type)))) |
|---|
| 263 |
(while (and button |
|---|
| 264 |
(not label) |
|---|
| 265 |
(or (not (eq type 'apropos-symbol)) |
|---|
| 266 |
(not already-hit-symbol))) |
|---|
| 267 |
(when (eq type 'apropos-symbol) |
|---|
| 268 |
(setq already-hit-symbol t)) |
|---|
| 269 |
(setq button (next-button (button-start button))) |
|---|
| 270 |
(when button |
|---|
| 271 |
(setq label (button-get button 'apropos-label)) |
|---|
| 272 |
(setq type (button-get button 'type)))) |
|---|
| 273 |
(and label button))) |
|---|
| 274 |
|
|---|
| 275 |
|
|---|
| 276 |
(defun apropos-words-to-regexp (words wild) |
|---|
| 277 |
"Make regexp matching any two of the words in WORDS." |
|---|
| 278 |
(concat "\\(" |
|---|
| 279 |
(mapconcat 'identity words "\\|") |
|---|
| 280 |
"\\)" |
|---|
| 281 |
(if (cdr words) |
|---|
| 282 |
(concat wild |
|---|
| 283 |
"\\(" |
|---|
| 284 |
(mapconcat 'identity words "\\|") |
|---|
| 285 |
"\\)") |
|---|
| 286 |
""))) |
|---|
| 287 |
|
|---|
| 288 |
|
|---|
| 289 |
(defun apropos-read-pattern (subject) |
|---|
| 290 |
"Read an apropos pattern, either a word list or a regexp. |
|---|
| 291 |
Returns the user pattern, either a list of words which are matched |
|---|
| 292 |
literally, or a string which is used as a regexp to search for. |
|---|
| 293 |
|
|---|
| 294 |
SUBJECT is a string that is included in the prompt to identify what |
|---|
| 295 |
kind of objects to search." |
|---|
| 296 |
(let ((pattern |
|---|
| 297 |
(read-string (concat "Apropos " subject " (word list or regexp): ")))) |
|---|
| 298 |
(if (string-equal (regexp-quote pattern) pattern) |
|---|
| 299 |
|
|---|
| 300 |
(split-string pattern "[ \t]+") |
|---|
| 301 |
pattern))) |
|---|
| 302 |
|
|---|
| 303 |
(defun apropos-parse-pattern (pattern) |
|---|
| 304 |
"Rewrite a list of words to a regexp matching all permutations. |
|---|
| 305 |
If PATTERN is a string, that means it is already a regexp. |
|---|
| 306 |
This updates variables `apropos-pattern', `apropos-pattern-quoted', |
|---|
| 307 |
`apropos-regexp', `apropos-words', and `apropos-all-words-regexp'." |
|---|
| 308 |
(setq apropos-words nil |
|---|
| 309 |
apropos-all-words nil) |
|---|
| 310 |
(if (consp pattern) |
|---|
| 311 |
|
|---|
| 312 |
|
|---|
| 313 |
|
|---|
| 314 |
|
|---|
| 315 |
|
|---|
| 316 |
(let ((words pattern)) |
|---|
| 317 |
(setq apropos-pattern (mapconcat 'identity pattern " ") |
|---|
| 318 |
apropos-pattern-quoted (regexp-quote apropos-pattern)) |
|---|
| 319 |
(dolist (word words) |
|---|
| 320 |
(let ((syn apropos-synonyms) (s word) (a word)) |
|---|
| 321 |
(while syn |
|---|
| 322 |
(if (member word (car syn)) |
|---|
| 323 |
(progn |
|---|
| 324 |
(setq a (mapconcat 'identity (car syn) "\\|")) |
|---|
| 325 |
(if (member word (cdr (car syn))) |
|---|
| 326 |
(setq s a)) |
|---|
| 327 |
(setq syn nil)) |
|---|
| 328 |
(setq syn (cdr syn)))) |
|---|
| 329 |
(setq apropos-words (cons s apropos-words) |
|---|
| 330 |
apropos-all-words (cons a apropos-all-words)))) |
|---|
| 331 |
(setq apropos-all-words-regexp |
|---|
| 332 |
(apropos-words-to-regexp apropos-all-words ".+")) |
|---|
| 333 |
(setq apropos-regexp |
|---|
| 334 |
(apropos-words-to-regexp apropos-words ".*?"))) |
|---|
| 335 |
(setq apropos-pattern-quoted (regexp-quote pattern) |
|---|
| 336 |
apropos-all-words-regexp pattern |
|---|
| 337 |
apropos-pattern pattern |
|---|
| 338 |
apropos-regexp pattern))) |
|---|
| 339 |
|
|---|
| 340 |
|
|---|
| 341 |
(defun apropos-calc-scores (str words) |
|---|
| 342 |
"Return apropos scores for string STR matching WORDS. |
|---|
| 343 |
Value is a list of offsets of the words into the string." |
|---|
| 344 |
(let (scores i) |
|---|
| 345 |
(if words |
|---|
| 346 |
(dolist (word words scores) |
|---|
| 347 |
(if (setq i (string-match word str)) |
|---|
| 348 |
(setq scores (cons i scores)))) |
|---|
| 349 |
|
|---|
| 350 |
(and (string-match apropos-pattern str) |
|---|
| 351 |
(list (match-beginning 0) (match-end 0)))))) |
|---|
| 352 |
|
|---|
| 353 |
(defun apropos-score-str (str) |
|---|
| 354 |
"Return apropos score for string STR." |
|---|
| 355 |
(if str |
|---|
| 356 |
(let* ((l (length str)) |
|---|
| 357 |
(score (- (/ l 10)))) |
|---|
| 358 |
(dolist (s (apropos-calc-scores str apropos-all-words) score) |
|---|
| 359 |
(setq score (+ score 1000 (/ (* (- l s) 1000) l))))) |
|---|
| 360 |
0)) |
|---|
| 361 |
|
|---|
| 362 |
(defun apropos-score-doc (doc) |
|---|
| 363 |
"Return apropos score for documentation string DOC." |
|---|
| 364 |
(let ((l (length doc))) |
|---|
| 365 |
(if (> l 0) |
|---|
| 366 |
(let ((score 0) i) |
|---|
| 367 |
(when (setq i (string-match apropos-pattern-quoted doc)) |
|---|
| 368 |
(setq score 10000)) |
|---|
| 369 |
(dolist (s (apropos-calc-scores doc apropos-all-words) score) |
|---|
| 370 |
(setq score (+ score 50 (/ (* (- l s) 50) l))))) |
|---|
| 371 |
0))) |
|---|
| 372 |
|
|---|
| 373 |
(defun apropos-score-symbol (symbol &optional weight) |
|---|
| 374 |
"Return apropos score for SYMBOL." |
|---|
| 375 |
(setq symbol (symbol-name symbol)) |
|---|
| 376 |
(let ((score 0) |
|---|
| 377 |
(l (length symbol))) |
|---|
| 378 |
(dolist (s (apropos-calc-scores symbol apropos-words) (* score (or weight 3))) |
|---|
| 379 |
(setq score (+ score (- 60 l) (/ (* (- l s) 60) l)))))) |
|---|
| 380 |
|
|---|
| 381 |
(defun apropos-true-hit (str words) |
|---|
| 382 |
"Return t if STR is a genuine hit. |
|---|
| 383 |
This may fail if only one of the keywords is matched more than once. |
|---|
| 384 |
This requires that at least 2 keywords (unless only one was given)." |
|---|
| 385 |
(or (not str) |
|---|
| 386 |
(not words) |
|---|
| 387 |
(not (cdr words)) |
|---|
| 388 |
(> (length (apropos-calc-scores str words)) 1))) |
|---|
| 389 |
|
|---|
| 390 |
(defun apropos-false-hit-symbol (symbol) |
|---|
| 391 |
"Return t if SYMBOL is not really matched by the current keywords." |
|---|
| 392 |
(not (apropos-true-hit (symbol-name symbol) apropos-words))) |
|---|
| 393 |
|
|---|
| 394 |
(defun apropos-false-hit-str (str) |
|---|
| 395 |
"Return t if STR is not really matched by the current keywords." |
|---|
| 396 |
(not (apropos-true-hit str apropos-words))) |
|---|
| 397 |
|
|---|
| 398 |
(defun apropos-true-hit-doc (doc) |
|---|
| 399 |
"Return t if DOC is really matched by the current keywords." |
|---|
| 400 |
(apropos-true-hit doc apropos-all-words)) |
|---|
| 401 |
|
|---|
| 402 |
(define-derived-mode apropos-mode fundamental-mode "Apropos" |
|---|
| 403 |
"Major mode for following hyperlinks in output of apropos commands. |
|---|
| 404 |
|
|---|
| 405 |
\\{apropos-mode-map}") |
|---|
| 406 |
|
|---|
| 407 |
|
|---|
| 408 |
(defun apropos-variable (pattern &optional do-all) |
|---|
| 409 |
"Show user variables that match PATTERN. |
|---|
| 410 |
PATTERN can be a word, a list of words (separated by spaces), |
|---|
| 411 |
or a regexp (using some regexp special characters). If it is a word, |
|---|
| 412 |
search for matches for that word as a substring. If it is a list of words, |
|---|
| 413 |
search for matches for any two (or more) of those words. |
|---|
| 414 |
|
|---|
| 415 |
With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, also show |
|---|
| 416 |
normal variables." |
|---|
| 417 |
(interactive (list (apropos-read-pattern |
|---|
| 418 |
(if (or current-prefix-arg apropos-do-all) |
|---|
| 419 |
"variable" "user option")) |
|---|
| 420 |
current-prefix-arg)) |
|---|
| 421 |
(apropos-command pattern nil |
|---|
| 422 |
(if (or do-all apropos-do-all) |
|---|
| 423 |
#'(lambda (symbol) |
|---|
| 424 |
(and (boundp symbol) |
|---|
| 425 |
(get symbol 'variable-documentation))) |
|---|
| 426 |
'user-variable-p))) |
|---|
| 427 |
|
|---|
| 428 |
|
|---|
| 429 |
|
|---|
| 430 |
(defalias 'command-apropos 'apropos-command) |
|---|
| 431 |
|
|---|
| 432 |
(defun apropos-command (pattern &optional do-all var-predicate) |
|---|
| 433 |
"Show commands (interactively callable functions) that match PATTERN. |
|---|
| 434 |
PATTERN can be a word, a list of words (separated by spaces), |
|---|
| 435 |
or a regexp (using some regexp special characters). If it is a word, |
|---|
| 436 |
search for matches for that word as a substring. If it is a list of words, |
|---|
| 437 |
search for matches for any two (or more) of those words. |
|---|
| 438 |
|
|---|
| 439 |
With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, also show |
|---|
| 440 |
noninteractive functions. |
|---|
| 441 |
|
|---|
| 442 |
If VAR-PREDICATE is non-nil, show only variables, and only those that |
|---|
| 443 |
satisfy the predicate VAR-PREDICATE. |
|---|
| 444 |
|
|---|
| 445 |
When called from a Lisp program, a string PATTERN is used as a regexp, |
|---|
| 446 |
while a list of strings is used as a word list." |
|---|
| 447 |
(interactive (list (apropos-read-pattern |
|---|
| 448 |
(if (or current-prefix-arg apropos-do-all) |
|---|
| 449 |
"command or function" "command")) |
|---|
| 450 |
current-prefix-arg)) |
|---|
| 451 |
(apropos-parse-pattern pattern) |
|---|
| 452 |
(let ((message |
|---|
| 453 |
(let ((standard-output (get-buffer-create "*Apropos*"))) |
|---|
| 454 |
(print-help-return-message 'identity)))) |
|---|
| 455 |
(or do-all (setq do-all apropos-do-all)) |
|---|
| 456 |
(setq apropos-accumulator |
|---|
| 457 |
(apropos-internal apropos-regexp |
|---|
| 458 |
(or var-predicate |
|---|
| 459 |
(if do-all 'functionp 'commandp)))) |
|---|
| 460 |
(let ((tem apropos-accumulator)) |
|---|
| 461 |
(while tem |
|---|
| 462 |
(if (or (get (car tem) 'apropos-inhibit) |
|---|
| 463 |
(apropos-false-hit-symbol (car tem))) |
|---|
| 464 |
(setq apropos-accumulator (delq (car tem) apropos-accumulator))) |
|---|
| 465 |
(setq tem (cdr tem)))) |
|---|
| 466 |
(let ((p apropos-accumulator) |
|---|
| 467 |
doc symbol score) |
|---|
| 468 |
(while p |
|---|
| 469 |
(setcar p (list |
|---|
| 470 |
(setq symbol (car p)) |
|---|
| 471 |
(setq score (apropos-score-symbol symbol)) |
|---|
| 472 |
(unless var-predicate |
|---|
| 473 |
(if (functionp symbol) |
|---|
| 474 |
(if (setq doc (documentation symbol t)) |
|---|
| 475 |
(progn |
|---|
| 476 |
(setq score (+ score (apropos-score-doc doc))) |
|---|
| 477 |
(substring doc 0 (string-match "\n" doc))) |
|---|
| 478 |
"(not documented)"))) |
|---|
| 479 |
(and var-predicate |
|---|
| 480 |
(funcall var-predicate symbol) |
|---|
| 481 |
(if (setq doc (documentation-property |
|---|
| 482 |
symbol 'variable-documentation t)) |
|---|
| 483 |
(progn |
|---|
| 484 |
(setq score (+ score (apropos-score-doc doc))) |
|---|
| 485 |
(substring doc 0 |
|---|
| 486 |
(string-match "\n" doc))))))) |
|---|
| 487 |
(setcar (cdr (car p)) score) |
|---|
| 488 |
(setq p (cdr p)))) |
|---|
| 489 |
(and (apropos-print t nil nil t) |
|---|
| 490 |
message |
|---|
| 491 |
(message "%s" message)))) |
|---|
| 492 |
|
|---|
| 493 |
|
|---|
| 494 |
|
|---|
| 495 |
(defun apropos-documentation-property (symbol property raw) |
|---|
| 496 |
"Like (documentation-property SYMBOL PROPERTY RAW) but handle errors." |
|---|
| 497 |
(condition-case () |
|---|
| 498 |
(let ((doc (documentation-property symbol property raw))) |
|---|
| 499 |
(if doc (substring doc 0 (string-match "\n" doc)) |
|---|
| 500 |
"(not documented)")) |
|---|
| 501 |
(error "(error retrieving documentation)"))) |
|---|
| 502 |
|
|---|
| 503 |
|
|---|
| 504 |
|
|---|
| 505 |
(defun apropos (pattern &optional do-all) |
|---|
| 506 |
"Show all meaningful Lisp symbols whose names match PATTERN. |
|---|
| 507 |
Symbols are shown if they are defined as functions, variables, or |
|---|
| 508 |
faces, or if they have nonempty property lists. |
|---|
| 509 |
|
|---|
| 510 |
PATTERN can be a word, a list of words (separated by spaces), |
|---|
| 511 |
or a regexp (using some regexp special characters). If it is a word, |
|---|
| 512 |
search for matches for that word as a substring. If it is a list of words, |
|---|
| 513 |
search for matches for any two (or more) of those words. |
|---|
| 514 |
|
|---|
| 515 |
With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, |
|---|
| 516 |
consider all symbols (if they match PATTERN). |
|---|
| 517 |
|
|---|
| 518 |
Returns list of symbols and documentation found." |
|---|
| 519 |
(interactive (list (apropos-read-pattern "symbol") |
|---|
| 520 |
current-prefix-arg)) |
|---|
| 521 |
(apropos-parse-pattern pattern) |
|---|
| 522 |
(apropos-symbols-internal |
|---|
| 523 |
(apropos-internal apropos-regexp |
|---|
| 524 |
(and (not do-all) |
|---|
| 525 |
(not apropos-do-all) |
|---|
| 526 |
(lambda (symbol) |
|---|
| 527 |
(or (fboundp symbol) |
|---|
| 528 |
(boundp symbol) |
|---|
| 529 |
(facep symbol) |
|---|
| 530 |
(symbol-plist symbol))))) |
|---|
| 531 |
(or do-all apropos-do-all))) |
|---|
| 532 |
|
|---|
| 533 |
(defun apropos-symbols-internal (symbols keys &optional text) |
|---|
| 534 |
|
|---|
| 535 |
(let ((all nil)) |
|---|
| 536 |
(dolist (symbol symbols) |
|---|
| 537 |
(unless (get symbol 'apropos-inhibit) |
|---|
| 538 |
(push symbol all))) |
|---|
| 539 |
(setq symbols all)) |
|---|
| 540 |
(let ((apropos-accumulator |
|---|
| 541 |
(mapcar |
|---|
| 542 |
(lambda (symbol) |
|---|
| 543 |
(let (doc properties) |
|---|
| 544 |
(list |
|---|
| 545 |
symbol |
|---|
| 546 |
(apropos-score-symbol symbol) |
|---|
| 547 |
(when (fboundp symbol) |
|---|
| 548 |
(if (setq doc (condition-case nil |
|---|
| 549 |
(documentation symbol t) |
|---|
| 550 |
(void-function |
|---|
| 551 |
"(alias for undefined function)") |
|---|
| 552 |
(error |
|---|
| 553 |
"(can't retrieve function documentation)"))) |
|---|
| 554 |
(substring doc 0 (string-match "\n" doc)) |
|---|
| 555 |
"(not documented)")) |
|---|
| 556 |
(when (boundp symbol) |
|---|
| 557 |
(apropos-documentation-property |
|---|
| 558 |
symbol 'variable-documentation t)) |
|---|
| 559 |
(when (setq properties (symbol-plist symbol)) |
|---|
| 560 |
(setq doc (list (car properties))) |
|---|
| 561 |
(while (setq properties (cdr (cdr properties))) |
|---|
| 562 |
(setq doc (cons (car properties) doc))) |
|---|
| 563 |
(mapconcat #'symbol-name (nreverse doc) " ")) |
|---|
| 564 |
(when (get symbol 'widget-type) |
|---|
| 565 |
(apropos-documentation-property |
|---|
| 566 |
symbol 'widget-documentation t)) |
|---|
| 567 |
(when (facep symbol) |
|---|
| 568 |
(apropos-documentation-property |
|---|
| 569 |
symbol 'face-documentation t)) |
|---|
| 570 |
(when (get symbol 'custom-group) |
|---|
| 571 |
(apropos-documentation-property |
|---|
| 572 |
symbol 'group-documentation t))))) |
|---|
| 573 |
symbols))) |
|---|
| 574 |
(apropos-print keys nil text))) |
|---|
| 575 |
|
|---|
| 576 |
|
|---|
| 577 |
|
|---|
| 578 |
(defun apropos-value (pattern &optional do-all) |
|---|
| 579 |
"Show all symbols whose value's printed representation matches PATTERN. |
|---|
| 580 |
PATTERN can be a word, a list of words (separated by spaces), |
|---|
| 581 |
or a regexp (using some regexp special characters). If it is a word, |
|---|
| 582 |
search for matches for that word as a substring. If it is a list of words, |
|---|
| 583 |
search for matches for any two (or more) of those words. |
|---|
| 584 |
|
|---|
| 585 |
With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, also looks |
|---|
| 586 |
at the function and at the names and values of properties. |
|---|
| 587 |
Returns list of symbols and values found." |
|---|
| 588 |
(interactive (list (apropos-read-pattern "value") |
|---|
| 589 |
current-prefix-arg)) |
|---|
| 590 |
(apropos-parse-pattern pattern) |
|---|
| 591 |
(or do-all (setq do-all apropos-do-all)) |
|---|
| 592 |
(setq apropos-accumulator ()) |
|---|
| 593 |
(let (f v p) |
|---|
| 594 |
(mapatoms |
|---|
| 595 |
(lambda (symbol) |
|---|
| 596 |
(setq f nil v nil p nil) |
|---|
| 597 |
(or (memq symbol '(apropos-regexp |
|---|
| 598 |
apropos-pattern apropos-all-words-regexp |
|---|
| 599 |
apropos-words apropos-all-words |
|---|
| 600 |
do-all apropos-accumulator |
|---|
| 601 |
symbol f v p)) |
|---|
| 602 |
(setq v (apropos-value-internal 'boundp symbol 'symbol-value))) |
|---|
| 603 |
(if do-all |
|---|
| 604 |
(setq f (apropos-value-internal 'fboundp symbol 'symbol-function) |
|---|
| 605 |
p (apropos-format-plist symbol "\n " t))) |
|---|
| 606 |
(if (apropos-false-hit-str v) |
|---|
| 607 |
(setq v nil)) |
|---|
| 608 |
(if (apropos-false-hit-str f) |
|---|
| 609 |
(setq f nil)) |
|---|
| 610 |
(if (apropos-false-hit-str p) |
|---|
| 611 |
(setq p nil)) |
|---|
| 612 |
(if (or f v p) |
|---|
| 613 |
(setq apropos-accumulator (cons (list symbol |
|---|
| 614 |
(+ (apropos-score-str f) |
|---|
| 615 |
(apropos-score-str v) |
|---|
| 616 |
(apropos-score-str p)) |
|---|
| 617 |
f v p) |
|---|
| 618 |
apropos-accumulator)))))) |
|---|
| 619 |
(apropos-print nil "\n----------------\n")) |
|---|
| 620 |
|
|---|
| 621 |
|
|---|
| 622 |
|
|---|
| 623 |
(defun apropos-documentation (pattern &optional do-all) |
|---|
| 624 |
"Show symbols whose documentation contains matches for PATTERN. |
|---|
| 625 |
PATTERN can be a word, a list of words (separated by spaces), |
|---|
| 626 |
or a regexp (using some regexp special characters). If it is a word, |
|---|
| 627 |
search for matches for that word as a substring. If it is a list of words, |
|---|
| 628 |
search for matches for any two (or more) of those words. |
|---|
| 629 |
|
|---|
| 630 |
With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, also use |
|---|
| 631 |
documentation that is not stored in the documentation file and show key |
|---|
| 632 |
bindings. |
|---|
| 633 |
Returns list of symbols and documentation found." |
|---|
| 634 |
(interactive (list (apropos-read-pattern "documentation") |
|---|
| 635 |
current-prefix-arg)) |
|---|
| 636 |
(apropos-parse-pattern pattern) |
|---|
| 637 |
(or do-all (setq do-all apropos-do-all)) |
|---|
| 638 |
(setq apropos-accumulator () apropos-files-scanned ()) |
|---|
| 639 |
(let ((standard-input (get-buffer-create " apropos-temp")) |
|---|
| 640 |
(apropos-sort-by-scores apropos-documentation-sort-by-scores) |
|---|
| 641 |
f v sf sv) |
|---|
| 642 |
(unwind-protect |
|---|
| 643 |
(save-excursion |
|---|
| 644 |
(set-buffer standard-input) |
|---|
| 645 |
(apropos-documentation-check-doc-file) |
|---|
| 646 |
(if do-all |
|---|
| 647 |
(mapatoms |
|---|
| 648 |
(lambda (symbol) |
|---|
| 649 |
(setq f (apropos-safe-documentation symbol) |
|---|
| 650 |
v (get symbol 'variable-documentation)) |
|---|
| 651 |
(if (integerp v) (setq v)) |
|---|
| 652 |
(setq f (apropos-documentation-internal f) |
|---|
| 653 |
v (apropos-documentation-internal v)) |
|---|
| 654 |
(setq sf (apropos-score-doc f) |
|---|
| 655 |
sv (apropos-score-doc v)) |
|---|
| 656 |
(if (or f v) |
|---|
| 657 |
(if (setq apropos-item |
|---|
| 658 |
(cdr (assq symbol apropos-accumulator))) |
|---|
| 659 |
(progn |
|---|
| 660 |
(if f |
|---|
| 661 |
(progn |
|---|
| 662 |
(setcar (nthcdr 1 apropos-item) f) |
|---|
| 663 |
(setcar apropos-item (+ (car apropos-item) sf)))) |
|---|
| 664 |
(if v |
|---|
| 665 |
(progn |
|---|
| 666 |
(setcar (nthcdr 2 apropos-item) v) |
|---|
| 667 |
(setcar apropos-item (+ (car apropos-item) sv))))) |
|---|
| 668 |
(setq apropos-accumulator |
|---|
| 669 |
(cons (list symbol |
|---|
| 670 |
(+ (apropos-score-symbol symbol 2) sf sv) |
|---|
| 671 |
f v) |
|---|
| 672 |
apropos-accumulator))))))) |
|---|
| 673 |
(apropos-print nil "\n----------------\n" nil t)) |
|---|
| 674 |
(kill-buffer standard-input)))) |
|---|
| 675 |
|
|---|
| 676 |
|
|---|
| 677 |
(defun apropos-value-internal (predicate symbol function) |
|---|
| 678 |
(if (funcall predicate symbol) |
|---|
| 679 |
(progn |
|---|
| 680 |
(setq symbol (prin1-to-string (funcall function symbol))) |
|---|
| 681 |
(if (string-match apropos-regexp symbol) |
|---|
| 682 |
(progn |
|---|
| 683 |
(if apropos-match-face |
|---|
| 684 |
(put-text-property (match-beginning 0) (match-end 0) |
|---|
| 685 |
'face apropos-match-face |
|---|
| 686 |
symbol)) |
|---|
| 687 |
symbol))))) |
|---|
| 688 |
|
|---|
| 689 |
(defun apropos-documentation-internal (doc) |
|---|
| 690 |
(if (consp doc) |
|---|
| 691 |
(apropos-documentation-check-elc-file (car doc)) |
|---|
| 692 |
(if (and doc |
|---|
| 693 |
(string-match apropos-all-words-regexp doc) |
|---|
| 694 |
(apropos-true-hit-doc doc)) |
|---|
| 695 |
(when apropos-match-face |
|---|
| 696 |
(setq doc (substitute-command-keys (copy-sequence doc))) |
|---|
| 697 |
(if (or (string-match apropos-pattern-quoted doc) |
|---|
| 698 |
(string-match apropos-all-words-regexp doc)) |
|---|
| 699 |
(put-text-property (match-beginning 0) |
|---|
| 700 |
(match-end 0) |
|---|
| 701 |
'face apropos-match-face doc)) |
|---|
| 702 |
doc)))) |
|---|
| 703 |
|
|---|
| 704 |
(defun apropos-format-plist (pl sep &optional compare) |
|---|
| 705 |
(setq pl (symbol-plist pl)) |
|---|
| 706 |
(let (p p-out) |
|---|
| 707 |
(while pl |
|---|
| 708 |
(setq p (format "%s %S" (car pl) (nth 1 pl))) |
|---|
| 709 |
(if (or (not compare) (string-match apropos-regexp p)) |
|---|
| 710 |
(if apropos-property-face |
|---|
| 711 |
(put-text-property 0 (length (symbol-name (car pl))) |
|---|
| 712 |
'face apropos-property-face p)) |
|---|
| 713 |
(setq p nil)) |
|---|
| 714 |
(if p |
|---|
| 715 |
(progn |
|---|
| 716 |
(and compare apropos-match-face |
|---|
| 717 |
(put-text-property (match-beginning 0) (match-end 0) |
|---|
| 718 |
'face apropos-match-face |
|---|
| 719 |
p)) |
|---|
| 720 |
(setq p-out (concat p-out (if p-out sep) p)))) |
|---|
| 721 |
(setq pl (nthcdr 2 pl))) |
|---|
| 722 |
p-out)) |
|---|
| 723 |
|
|---|
| 724 |
|
|---|
| 725 |
|
|---|
| 726 |
|
|---|
| 727 |
(defun apropos-documentation-check-doc-file () |
|---|
| 728 |
(let (type symbol (sepa 2) sepb) |
|---|
| 729 |
(insert ?\^_) |
|---|
| 730 |
(backward-char) |
|---|
| 731 |
(insert-file-contents (concat doc-directory internal-doc-file-name)) |
|---|
| 732 |
(forward-char) |
|---|
| 733 |
(while (save-excursion |
|---|
| 734 |
(setq sepb (search-forward "\^_")) |
|---|
| 735 |
(not (eobp))) |
|---|
| 736 |
(beginning-of-line 2) |
|---|
| 737 |
(if (save-restriction |
|---|
| 738 |
(narrow-to-region (point) (1- sepb)) |
|---|
| 739 |
(re-search-forward apropos-all-words-regexp nil t)) |
|---|
| 740 |
(progn |
|---|
| 741 |
(goto-char (1+ sepa)) |
|---|
| 742 |
(setq type (if (eq ?F (preceding-char)) |
|---|
| 743 |
2 |
|---|
| 744 |
3) |
|---|
| 745 |
symbol (read) |
|---|
| 746 |
doc (buffer-substring (1+ (point)) (1- sepb))) |
|---|
| 747 |
(when (apropos-true-hit-doc doc) |
|---|
| 748 |
(or (and (setq apropos-item (assq symbol apropos-accumulator)) |
|---|
| 749 |
(setcar (cdr apropos-item) |
|---|
| 750 |
(apropos-score-doc doc))) |
|---|
| 751 |
(setq apropos-item (list symbol |
|---|
| 752 |
(+ (apropos-score-symbol symbol 2) |
|---|
| 753 |
(apropos-score-doc doc)) |
|---|
| 754 |
nil nil) |
|---|
| 755 |
apropos-accumulator (cons apropos-item |
|---|
| 756 |
apropos-accumulator))) |
|---|
| 757 |
(when apropos-match-face |
|---|
| 758 |
(setq doc (substitute-command-keys doc)) |
|---|
| 759 |
(if (or (string-match apropos-pattern-quoted doc) |
|---|
| 760 |
(string-match apropos-all-words-regexp doc)) |
|---|
| 761 |
(put-text-property (match-beginning 0) |
|---|
| 762 |
(match-end 0) |
|---|
| 763 |
'face apropos-match-face doc))) |
|---|
| 764 |
(setcar (nthcdr type apropos-item) doc)))) |
|---|
| 765 |
(setq sepa (goto-char sepb))))) |
|---|
| 766 |
|
|---|
| 767 |
(defun apropos-documentation-check-elc-file (file) |
|---|
| 768 |
(if (member file apropos-files-scanned) |
|---|
| 769 |
nil |
|---|
| 770 |
(let (symbol doc beg end this-is-a-variable) |
|---|
| 771 |
(setq apropos-files-scanned (cons file apropos-files-scanned)) |
|---|
| 772 |
(erase-buffer) |
|---|
| 773 |
(insert-file-contents file) |
|---|
| 774 |
(while (search-forward "\n#@" nil t) |
|---|
| 775 |
|
|---|
| 776 |
(setq end (read) |
|---|
| 777 |
beg (1+ (point)) |
|---|
| 778 |
end (+ (point) end -1)) |
|---|
| 779 |
(forward-char) |
|---|
| 780 |
(if (save-restriction |
|---|
| 781 |
|
|---|
| 782 |
(narrow-to-region beg end) |
|---|
| 783 |
(re-search-forward apropos-all-words-regexp nil t)) |
|---|
| 784 |
(progn |
|---|
| 785 |
(goto-char (+ end 2)) |
|---|
| 786 |
(setq doc (buffer-substring beg end) |
|---|
| 787 |
end (- (match-end 0) beg) |
|---|
| 788 |
beg (- (match-beginning 0) beg)) |
|---|
| 789 |
(when (apropos-true-hit-doc doc) |
|---|
| 790 |
(setq this-is-a-variable (looking-at "(def\\(var\\|const\\) ") |
|---|
| 791 |
symbol (progn |
|---|
| 792 |
(skip-chars-forward "(a-z") |
|---|
| 793 |
(forward-char) |
|---|
| 794 |
(read)) |
|---|
| 795 |
symbol (if (consp symbol) |
|---|
| 796 |
(nth 1 symbol) |
|---|
| 797 |
symbol)) |
|---|
| 798 |
(if (if this-is-a-variable |
|---|
| 799 |
(get symbol 'variable-documentation) |
|---|
| 800 |
(and (fboundp symbol) (apropos-safe-documentation symbol))) |
|---|
| 801 |
(progn |
|---|
| 802 |
(or (and (setq apropos-item (assq symbol apropos-accumulator)) |
|---|
| 803 |
(setcar (cdr apropos-item) |
|---|
| 804 |
(+ (cadr apropos-item) (apropos-score-doc doc)))) |
|---|
| 805 |
(setq apropos-item (list symbol |
|---|
| 806 |
(+ (apropos-score-symbol symbol 2) |
|---|
| 807 |
&n |
|---|