Mercurial > emacs
comparison lisp/info.el @ 51735:204ae43066d1
(Info-following-node-name-re): New fun.
(Info-following-node-name): Remove.
(Info-insert-dir): Use the new fun.
(Info-extract-pointer): Don't save restriction; use new fun.
(Info-menu-entry-name-re): New const.
(Info-menu-entry-name-re): Use it along with new fun.
(Info-node-spec-re): Use new fun.
(Info-complete-menu-item, Info-fontify-node): Use new const.
(Info-goto-node, Info-follow-reference, Info-menu-update):
Use match-string.
(Info-follow-reference): Use assoc-string.
Use a list of strings for the completion table.
(Info-fontify-node): Use match-string, line-end-position.
Limit the search for `node:' to the first line.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Fri, 04 Jul 2003 23:05:35 +0000 |
parents | 6b3b6b76e307 |
children | fbd12905244b |
comparison
equal
deleted
inserted
replaced
51734:400a9c7868fd | 51735:204ae43066d1 |
---|---|
908 (while (and (zerop (forward-line 1)) (eolp))) | 908 (while (and (zerop (forward-line 1)) (eolp))) |
909 (let ((beg (point)) | 909 (let ((beg (point)) |
910 nodename end) | 910 nodename end) |
911 (re-search-backward "^\^_") | 911 (re-search-backward "^\^_") |
912 (search-forward "Node: ") | 912 (search-forward "Node: ") |
913 (setq nodename (Info-following-node-name)) | 913 (setq nodename |
914 (and (looking-at (Info-following-node-name-re)) | |
915 (match-string 1))) | |
914 (search-forward "\n\^_" nil 'move) | 916 (search-forward "\n\^_" nil 'move) |
915 (beginning-of-line) | 917 (beginning-of-line) |
916 (setq end (point)) | 918 (setq end (point)) |
917 (push (list nodename other beg end) this-buffer-nodes))) | 919 (push (list nodename other beg end) this-buffer-nodes))) |
918 (if (assoc-ignore-case "top" this-buffer-nodes) | 920 (if (assoc-ignore-case "top" this-buffer-nodes) |
1207 (let (filename) | 1209 (let (filename) |
1208 (string-match "\\s *\\((\\s *\\([^\t)]*\\)\\s *)\\s *\\|\\)\\(.*\\)" | 1210 (string-match "\\s *\\((\\s *\\([^\t)]*\\)\\s *)\\s *\\|\\)\\(.*\\)" |
1209 nodename) | 1211 nodename) |
1210 (setq filename (if (= (match-beginning 1) (match-end 1)) | 1212 (setq filename (if (= (match-beginning 1) (match-end 1)) |
1211 "" | 1213 "" |
1212 (substring nodename (match-beginning 2) (match-end 2))) | 1214 (match-string 2 nodename)) |
1213 nodename (substring nodename (match-beginning 3) (match-end 3))) | 1215 nodename (match-string 3 nodename)) |
1214 (let ((trim (string-match "\\s *\\'" filename))) | 1216 (let ((trim (string-match "\\s *\\'" filename))) |
1215 (if trim (setq filename (substring filename 0 trim)))) | 1217 (if trim (setq filename (substring filename 0 trim)))) |
1216 (let ((trim (string-match "\\s *\\'" nodename))) | 1218 (let ((trim (string-match "\\s *\\'" nodename))) |
1217 (if trim (setq nodename (substring nodename 0 trim)))) | 1219 (if trim (setq nodename (substring nodename 0 trim)))) |
1218 (if transient-mark-mode (deactivate-mark)) | 1220 (if transient-mark-mode (deactivate-mark)) |
1391 Info-history)))))) | 1393 Info-history)))))) |
1392 | 1394 |
1393 (defun Info-extract-pointer (name &optional errorname) | 1395 (defun Info-extract-pointer (name &optional errorname) |
1394 "Extract the value of the node-pointer named NAME. | 1396 "Extract the value of the node-pointer named NAME. |
1395 If there is none, use ERRORNAME in the error message; | 1397 If there is none, use ERRORNAME in the error message; |
1396 if ERRORNAME is nil, just return nil. | 1398 if ERRORNAME is nil, just return nil." |
1397 Bind this in case the user sets it to nil." | 1399 ;; Bind this in case the user sets it to nil. |
1398 (let ((case-fold-search t)) | 1400 (let ((case-fold-search t)) |
1399 (save-excursion | 1401 (save-excursion |
1400 (save-restriction | 1402 (goto-char (point-min)) |
1401 (goto-char (point-min)) | 1403 (let ((bound (point))) |
1402 (let ((bound (point))) | 1404 (forward-line 1) |
1403 (forward-line 1) | 1405 (cond ((re-search-backward |
1404 (cond ((re-search-backward (concat name ":") bound t) | 1406 (concat name ":" (Info-following-node-name-re)) bound t) |
1405 (goto-char (match-end 0)) | 1407 (match-string 1)) |
1406 (Info-following-node-name)) | 1408 ((not (eq errorname t)) |
1407 ((not (eq errorname t)) | 1409 (error "Node has no %s" |
1408 (error "Node has no %s" | 1410 (capitalize (or errorname name))))))))) |
1409 (capitalize (or errorname name)))))))))) | 1411 |
1410 | 1412 (defun Info-following-node-name-re (&optional allowedchars) |
1411 (defun Info-following-node-name (&optional allowedchars) | 1413 "Return a regexp matching a node name. |
1412 "Return the node name in the buffer following point. | |
1413 ALLOWEDCHARS, if non-nil, goes within [...] to make a regexp | 1414 ALLOWEDCHARS, if non-nil, goes within [...] to make a regexp |
1414 saying which chars may appear in the node name." | 1415 saying which chars may appear in the node name. |
1415 (skip-chars-forward " \t") | 1416 Submatch 1 is the complete node name. |
1416 (buffer-substring-no-properties | 1417 Submatch 2 if non-nil is the parenthesized file name part of the node name. |
1417 (point) | 1418 Submatch 3 is the local part of the node name. |
1418 (progn | 1419 End of submatch 0, 1, and 3 are the same, so you can safely concat." |
1419 (while (looking-at (concat "[" (or allowedchars "^,\t\n") "]")) | 1420 (concat "[ \t]*" ;Skip leading space. |
1420 (skip-chars-forward (concat (or allowedchars "^,\t\n") "(")) | 1421 "\\(\\(([^)]+)\\)?" ;Node name can start with a file name. |
1421 (if (looking-at "(") | 1422 "\\([" (or allowedchars "^,\t\n") "]*" ;Any number of allowed chars. |
1422 (skip-chars-forward "^)"))) | 1423 "[" (or allowedchars "^,\t\n") " ]" ;The last char can't be a space. |
1423 (skip-chars-backward " ") | 1424 "\\|\\)\\)")) ;Allow empty node names. |
1424 (point)))) | |
1425 | 1425 |
1426 (defun Info-next () | 1426 (defun Info-next () |
1427 "Go to the next node of this node." | 1427 "Go to the next node of this node." |
1428 (interactive) | 1428 (interactive) |
1429 (Info-goto-node (Info-extract-pointer "next"))) | 1429 (Info-goto-node (Info-extract-pointer "next"))) |
1478 (beginning-of-line) | 1478 (beginning-of-line) |
1479 (setq bol (point)) | 1479 (setq bol (point)) |
1480 | 1480 |
1481 (goto-char (point-min)) | 1481 (goto-char (point-min)) |
1482 (while (re-search-forward "\\*note[ \n\t]*\\([^:]*\\):" nil t) | 1482 (while (re-search-forward "\\*note[ \n\t]*\\([^:]*\\):" nil t) |
1483 (setq str (buffer-substring-no-properties | 1483 (setq str (match-string-no-properties 1)) |
1484 (match-beginning 1) | |
1485 (1- (point)))) | |
1486 ;; See if this one should be the default. | 1484 ;; See if this one should be the default. |
1487 (and (null default) | 1485 (and (null default) |
1488 (<= (match-beginning 0) start-point) | 1486 (<= (match-beginning 0) start-point) |
1489 (<= start-point (point)) | 1487 (<= start-point (point)) |
1490 (setq default t)) | 1488 (setq default t)) |
1500 (setq i (1+ i))) | 1498 (setq i (1+ i))) |
1501 ;; Record as a completion and perhaps as default. | 1499 ;; Record as a completion and perhaps as default. |
1502 (if (eq default t) (setq default str)) | 1500 (if (eq default t) (setq default str)) |
1503 (if (eq alt-default t) (setq alt-default str)) | 1501 (if (eq alt-default t) (setq alt-default str)) |
1504 ;; Don't add this string if it's a duplicate. | 1502 ;; Don't add this string if it's a duplicate. |
1505 ;; We use a loop instead of "(assoc str completions)" because | 1503 (or (assoc-string str completions t) |
1506 ;; we want to do a case-insensitive compare. | 1504 (push str completions)))) |
1507 (let ((tail completions) | |
1508 (tem (downcase str))) | |
1509 (while (and tail | |
1510 (not (string-equal tem (downcase (car (car tail)))))) | |
1511 (setq tail (cdr tail))) | |
1512 (or tail | |
1513 (setq completions | |
1514 (cons (cons str nil) | |
1515 completions)))))) | |
1516 ;; If no good default was found, try an alternate. | 1505 ;; If no good default was found, try an alternate. |
1517 (or default | 1506 (or default |
1518 (setq default alt-default)) | 1507 (setq default alt-default)) |
1519 ;; If only one cross-reference found, then make it default. | 1508 ;; If only one cross-reference found, then make it default. |
1520 (if (eq (length completions) 1) | 1509 (if (eq (length completions) 1) |
1521 (setq default (car (car completions)))) | 1510 (setq default (car completions))) |
1522 (if completions | 1511 (if completions |
1523 (let ((input (completing-read (if default | 1512 (let ((input (completing-read (if default |
1524 (concat | 1513 (concat |
1525 "Follow reference named: (default " | 1514 "Follow reference named: (default " |
1526 default ") ") | 1515 default ") ") |
1549 (setq target (concat (substring target 0 i) " " | 1538 (setq target (concat (substring target 0 i) " " |
1550 (substring target (match-end 0)))) | 1539 (substring target (match-end 0)))) |
1551 (setq i (+ i 1))) | 1540 (setq i (+ i 1))) |
1552 (Info-goto-node target))) | 1541 (Info-goto-node target))) |
1553 | 1542 |
1543 (defconst Info-menu-entry-name-re "\\(?:[^:\n]+\\|:[^,.;() \t\n]\\)*" | |
1544 "Regexp that matches a menu entry name upto but not including the colon. | |
1545 Because of ambiguities, this should be concatenated with something like | |
1546 `:' and `Info-following-node-name-re'.") | |
1547 | |
1554 (defun Info-extract-menu-node-name (&optional multi-line) | 1548 (defun Info-extract-menu-node-name (&optional multi-line) |
1555 (skip-chars-forward " \t\n") | 1549 (skip-chars-forward " \t\n") |
1556 (let ((beg (point)) | 1550 (when (looking-at (concat Info-menu-entry-name-re ":\\(:\\|" |
1557 str) | 1551 (Info-following-node-name-re |
1558 (while (progn | 1552 (if multi-line "^.,\t" "^.,\t\n")) "\\)")) |
1559 (skip-chars-forward "^:") | 1553 (replace-regexp-in-string |
1560 (forward-char 1) | 1554 "[ \n]+" " " |
1561 (not (looking-at ":*[,.;() \t\n]")))) | 1555 (or (match-string 2) |
1562 (setq str | 1556 ;; If the node name is the menu entry name (using `entry::'). |
1563 (if (looking-at ":") | 1557 (buffer-substring (match-beginning 0) (1- (match-beginning 1))))))) |
1564 (buffer-substring-no-properties beg (1- (point))) | |
1565 (skip-chars-forward " \t\n") | |
1566 (Info-following-node-name (if multi-line "^.,\t" "^.,\t\n")))) | |
1567 (replace-regexp-in-string "[ \n]+" " " str))) | |
1568 | 1558 |
1569 ;; No one calls this. | 1559 ;; No one calls this. |
1570 ;;(defun Info-menu-item-sequence (list) | 1560 ;;(defun Info-menu-item-sequence (list) |
1571 ;; (while list | 1561 ;; (while list |
1572 ;; (Info-menu (car list)) | 1562 ;; (Info-menu (car list)) |
1574 | 1564 |
1575 (defvar Info-complete-menu-buffer) | 1565 (defvar Info-complete-menu-buffer) |
1576 (defvar Info-complete-next-re nil) | 1566 (defvar Info-complete-next-re nil) |
1577 (defvar Info-complete-cache nil) | 1567 (defvar Info-complete-cache nil) |
1578 | 1568 |
1579 (defconst Info-node-spec-re "[^.,:(]*\\(([^)]*)[^.,:]*\\)?[,:.]" | 1569 (defconst Info-node-spec-re |
1570 (concat (Info-following-node-name-re "^.,:") "[,:.]") | |
1580 "Regexp to match the text after a : until the terminating `.'.") | 1571 "Regexp to match the text after a : until the terminating `.'.") |
1581 | 1572 |
1582 (defun Info-complete-menu-item (string predicate action) | 1573 (defun Info-complete-menu-item (string predicate action) |
1583 ;; This uses two dynamically bound variables: | 1574 ;; This uses two dynamically bound variables: |
1584 ;; - `Info-complete-menu-buffer' which contains the buffer in which | 1575 ;; - `Info-complete-menu-buffer' which contains the buffer in which |
1601 (if (not (memq action '(nil t))) | 1592 (if (not (memq action '(nil t))) |
1602 (re-search-forward | 1593 (re-search-forward |
1603 (concat "\n\\* +" (regexp-quote string) ":") nil t) | 1594 (concat "\n\\* +" (regexp-quote string) ":") nil t) |
1604 (let ((pattern (concat "\n\\* +\\(" | 1595 (let ((pattern (concat "\n\\* +\\(" |
1605 (regexp-quote string) | 1596 (regexp-quote string) |
1606 "[^\t\n]*?\\):" Info-node-spec-re)) | 1597 Info-menu-entry-name-re "\\):" Info-node-spec-re)) |
1607 completions) | 1598 completions) |
1608 ;; Check the cache. | 1599 ;; Check the cache. |
1609 (if (and (equal (nth 0 Info-complete-cache) Info-current-file) | 1600 (if (and (equal (nth 0 Info-complete-cache) Info-current-file) |
1610 (equal (nth 1 Info-complete-cache) Info-current-node) | 1601 (equal (nth 1 Info-complete-cache) Info-current-node) |
1611 (equal (nth 2 Info-complete-cache) Info-complete-next-re) | 1602 (equal (nth 2 Info-complete-cache) Info-complete-next-re) |
2380 (number 0) | 2371 (number 0) |
2381 (case-fold-search t)) | 2372 (case-fold-search t)) |
2382 (save-excursion | 2373 (save-excursion |
2383 (goto-char (point-min)) | 2374 (goto-char (point-min)) |
2384 (while (re-search-forward "\\*note[ \n\t]*\\([^:]*\\):" nil t) | 2375 (while (re-search-forward "\\*note[ \n\t]*\\([^:]*\\):" nil t) |
2385 (setq str (buffer-substring | 2376 (setq str (match-string 1)) |
2386 (match-beginning 1) | |
2387 (1- (point)))) | |
2388 (setq i 0) | 2377 (setq i 0) |
2389 (while (setq i (string-match "[ \n\t]+" str i)) | 2378 (while (setq i (string-match "[ \n\t]+" str i)) |
2390 (setq str (concat (substring str 0 i) " " | 2379 (setq str (concat (substring str 0 i) " " |
2391 (substring str (match-end 0)))) | 2380 (substring str (match-end 0)))) |
2392 (setq i (1+ i))) | 2381 (setq i (1+ i))) |
2805 (while (looking-at "[ \t]*\\([^:, \t\n]+\\):[ \t]+\\([^:,\t\n]+\\),?") | 2794 (while (looking-at "[ \t]*\\([^:, \t\n]+\\):[ \t]+\\([^:,\t\n]+\\),?") |
2806 (goto-char (match-end 0)) | 2795 (goto-char (match-end 0)) |
2807 (let* ((nbeg (match-beginning 2)) | 2796 (let* ((nbeg (match-beginning 2)) |
2808 (nend (match-end 2)) | 2797 (nend (match-end 2)) |
2809 (tbeg (match-beginning 1)) | 2798 (tbeg (match-beginning 1)) |
2810 (tag (buffer-substring tbeg (match-end 1)))) | 2799 (tag (match-string 1))) |
2811 (if (string-equal tag "Node") | 2800 (if (string-equal tag "Node") |
2812 (put-text-property nbeg nend 'font-lock-face 'info-header-node) | 2801 (put-text-property nbeg nend 'font-lock-face 'info-header-node) |
2813 (put-text-property nbeg nend 'font-lock-face 'info-header-xref) | 2802 (put-text-property nbeg nend 'font-lock-face 'info-header-xref) |
2814 (put-text-property tbeg nend 'mouse-face 'highlight) | 2803 (put-text-property tbeg nend 'mouse-face 'highlight) |
2815 (put-text-property tbeg nend | 2804 (put-text-property tbeg nend |
2824 ((equal tag "Prev") Info-prev-link-keymap) | 2813 ((equal tag "Prev") Info-prev-link-keymap) |
2825 ((equal tag "Next") Info-next-link-keymap) | 2814 ((equal tag "Next") Info-next-link-keymap) |
2826 ((equal tag "Up") Info-up-link-keymap)))))) | 2815 ((equal tag "Up") Info-up-link-keymap)))))) |
2827 (when Info-use-header-line | 2816 (when Info-use-header-line |
2828 (goto-char (point-min)) | 2817 (goto-char (point-min)) |
2829 (let ((header-end (save-excursion (end-of-line) (point))) | 2818 (let ((header-end (line-end-position)) |
2830 header) | 2819 header) |
2831 ;; If we find neither Next: nor Prev: link, show the entire | 2820 ;; If we find neither Next: nor Prev: link, show the entire |
2832 ;; node header. Otherwise, don't show the File: and Node: | 2821 ;; node header. Otherwise, don't show the File: and Node: |
2833 ;; parts, to avoid wasting precious space on information that | 2822 ;; parts, to avoid wasting precious space on information that |
2834 ;; is available in the mode line. | 2823 ;; is available in the mode line. |
2836 "\\(next\\|up\\|prev[ious]*\\): " | 2825 "\\(next\\|up\\|prev[ious]*\\): " |
2837 header-end t) | 2826 header-end t) |
2838 (progn | 2827 (progn |
2839 (goto-char (match-beginning 1)) | 2828 (goto-char (match-beginning 1)) |
2840 (setq header (buffer-substring (point) header-end))) | 2829 (setq header (buffer-substring (point) header-end))) |
2841 (if (re-search-forward "node:[ \t]*[^ \t]+[ \t]*" nil t) | 2830 (if (re-search-forward "node:[ \t]*[^ \t]+[ \t]*" header-end t) |
2842 (setq header | 2831 (setq header |
2843 (concat "No next, prev or up links -- " | 2832 (concat "No next, prev or up links -- " |
2844 (buffer-substring (point) header-end))) | 2833 (buffer-substring (point) header-end))) |
2845 (setq header (buffer-substring (point) header-end)))) | 2834 (setq header (buffer-substring (point) header-end)))) |
2846 | 2835 |
2943 (not (string-match "\\<Index\\>" Info-current-node)) | 2932 (not (string-match "\\<Index\\>" Info-current-node)) |
2944 ;; Don't take time to annotate huge menus | 2933 ;; Don't take time to annotate huge menus |
2945 (< (- (point-max) (point)) Info-fontify-maximum-menu-size)) | 2934 (< (- (point-max) (point)) Info-fontify-maximum-menu-size)) |
2946 (let ((n 0) | 2935 (let ((n 0) |
2947 cont) | 2936 cont) |
2948 (while (re-search-forward (concat "^\\* +\\([^:\t\n]*\\)\\(:" | 2937 (while (re-search-forward |
2949 Info-node-spec-re | 2938 (concat "^\\* +\\(" Info-menu-entry-name-re "\\)\\(:" |
2950 "\\([ \t]*\\)\\)") | 2939 Info-node-spec-re "\\([ \t]*\\)\\)") |
2951 nil t) | 2940 nil t) |
2952 (setq n (1+ n)) | 2941 (setq n (1+ n)) |
2953 (if (and (<= n 9) (zerop (% n 3))) ; visual aids to help with 1-9 keys | 2942 (if (and (<= n 9) (zerop (% n 3))) ; visual aids to help with 1-9 keys |
2954 (put-text-property (match-beginning 0) | 2943 (put-text-property (match-beginning 0) |
2955 (1+ (match-beginning 0)) | 2944 (1+ (match-beginning 0)) |
2956 'font-lock-face 'info-menu-5)) | 2945 'font-lock-face 'info-menu-5)) |
2962 (concat "mouse-2: go to " (match-string 3)) | 2951 (concat "mouse-2: go to " (match-string 3)) |
2963 "mouse-2: go to this node") | 2952 "mouse-2: go to this node") |
2964 '(font-lock-face info-xref | 2953 '(font-lock-face info-xref |
2965 mouse-face highlight)))) | 2954 mouse-face highlight)))) |
2966 (when (eq Info-hide-note-references t) | 2955 (when (eq Info-hide-note-references t) |
2967 (put-text-property (match-beginning 2) (1- (match-end 4)) | 2956 (put-text-property (match-beginning 2) (1- (match-end 6)) |
2968 'invisible t) | 2957 'invisible t) |
2969 ;; We need a stretchable space like :align-to but with | 2958 ;; We need a stretchable space like :align-to but with |
2970 ;; a minimum value. | 2959 ;; a minimum value. |
2971 (put-text-property (1- (match-end 4)) (match-end 4) 'display | 2960 (put-text-property (1- (match-end 6)) (match-end 6) 'display |
2972 (if (>= 22 (- (match-end 1) | 2961 (if (>= 22 (- (match-end 1) |
2973 (match-beginning 0))) | 2962 (match-beginning 0))) |
2974 '(space :align-to 24) | 2963 '(space :align-to 24) |
2975 '(space :width 2))) | 2964 '(space :width 2))) |
2976 (setq cont (looking-at ".")) | 2965 (setq cont (looking-at ".")) |