aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/apropos.el5
-rw-r--r--lisp/emacs-lisp/shortdoc.el18
-rw-r--r--lisp/outline.el158
3 files changed, 145 insertions, 36 deletions
diff --git a/lisp/apropos.el b/lisp/apropos.el
index d9d8f4c372b..a731926f458 100644
--- a/lisp/apropos.el
+++ b/lisp/apropos.el
@@ -492,7 +492,7 @@ Intended as a value for `revert-buffer-function'."
492\\{apropos-mode-map}" 492\\{apropos-mode-map}"
493 (make-local-variable 'apropos--current) 493 (make-local-variable 'apropos--current)
494 (setq-local revert-buffer-function #'apropos--revert-buffer) 494 (setq-local revert-buffer-function #'apropos--revert-buffer)
495 (setq-local outline-regexp "^[^ \n]+" 495 (setq-local outline-search-function #'outline-search-level
496 outline-level (lambda () 1) 496 outline-level (lambda () 1)
497 outline-minor-mode-cycle t 497 outline-minor-mode-cycle t
498 outline-minor-mode-highlight t 498 outline-minor-mode-highlight t
@@ -1188,7 +1188,8 @@ as a heading."
1188 (insert-text-button (symbol-name symbol) 1188 (insert-text-button (symbol-name symbol)
1189 'type 'apropos-symbol 1189 'type 'apropos-symbol
1190 'skip apropos-multi-type 1190 'skip apropos-multi-type
1191 'face 'apropos-symbol) 1191 'face 'apropos-symbol
1192 'outline-level 1)
1192 (setq button-end (point)) 1193 (setq button-end (point))
1193 (if (and (eq apropos-sort-by-scores 'verbose) 1194 (if (and (eq apropos-sort-by-scores 'verbose)
1194 (cadr apropos-item)) 1195 (cadr apropos-item))
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index 022bf1e7360..83283247150 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -1374,13 +1374,20 @@ If SAME-WINDOW, don't pop to a new window."
1374 (unless (bobp) 1374 (unless (bobp)
1375 (insert "\n")) 1375 (insert "\n"))
1376 (insert (propertize 1376 (insert (propertize
1377 (concat (substitute-command-keys data) "\n\n") 1377 (substitute-command-keys data)
1378 'face 'shortdoc-heading
1379 'shortdoc-section t
1380 'outline-level 1))
1381 (insert (propertize
1382 "\n\n"
1378 'face 'shortdoc-heading 1383 'face 'shortdoc-heading
1379 'shortdoc-section t))) 1384 'shortdoc-section t)))
1380 ;; There may be functions not yet defined in the data. 1385 ;; There may be functions not yet defined in the data.
1381 ((fboundp (car data)) 1386 ((fboundp (car data))
1382 (when prev 1387 (when prev
1383 (insert (make-separator-line))) 1388 (insert (make-separator-line)
1389 ;; This helps with hidden outlines (bug#53981)
1390 (propertize "\n" 'face '(:height 0))))
1384 (setq prev t) 1391 (setq prev t)
1385 (shortdoc--display-function data)))) 1392 (shortdoc--display-function data))))
1386 (cdr (assq group shortdoc--groups)))) 1393 (cdr (assq group shortdoc--groups))))
@@ -1397,7 +1404,7 @@ If SAME-WINDOW, don't pop to a new window."
1397 (start-section (point)) 1404 (start-section (point))
1398 arglist-start) 1405 arglist-start)
1399 ;; Function calling convention. 1406 ;; Function calling convention.
1400 (insert (propertize "(" 'shortdoc-function function)) 1407 (insert (propertize "(" 'shortdoc-function function 'outline-level 2))
1401 (if (plist-get data :no-manual) 1408 (if (plist-get data :no-manual)
1402 (insert-text-button 1409 (insert-text-button
1403 (symbol-name function) 1410 (symbol-name function)
@@ -1531,7 +1538,10 @@ Example:
1531 1538
1532(define-derived-mode shortdoc-mode special-mode "shortdoc" 1539(define-derived-mode shortdoc-mode special-mode "shortdoc"
1533 "Mode for shortdoc." 1540 "Mode for shortdoc."
1534 :interactive nil) 1541 :interactive nil
1542 (setq-local outline-search-function #'outline-search-level
1543 outline-level (lambda ()
1544 (get-text-property (point) 'outline-level))))
1535 1545
1536(defun shortdoc--goto-section (arg sym &optional reverse) 1546(defun shortdoc--goto-section (arg sym &optional reverse)
1537 (unless (natnump arg) 1547 (unless (natnump arg)
diff --git a/lisp/outline.el b/lisp/outline.el
index 92135f8b483..7d9e7e10d08 100644
--- a/lisp/outline.el
+++ b/lisp/outline.el
@@ -59,6 +59,18 @@ The recommended way to set this is with a `Local Variables:' list
59in the file it applies to.") 59in the file it applies to.")
60;;;###autoload(put 'outline-heading-end-regexp 'safe-local-variable 'stringp) 60;;;###autoload(put 'outline-heading-end-regexp 'safe-local-variable 'stringp)
61 61
62(defvar outline-search-function nil
63 "Function to search the next outline heading.
64The function is called with four optional arguments: BOUND, MOVE, BACKWARD,
65LOOKING-AT. The first two arguments BOUND and MOVE are almost the same as
66the BOUND and NOERROR arguments of `re-search-forward', with the difference
67that MOVE accepts only a boolean, either nil or non-nil. When the argument
68BACKWARD is non-nil, the search should search backward like
69`re-search-backward' does. In case of a successful search, the
70function should return non-nil, move point, and set match-data
71appropriately. When the argument LOOKING-AT is non-nil, it should
72imitate the function `looking-at'.")
73
62(defvar outline-mode-prefix-map 74(defvar outline-mode-prefix-map
63 (let ((map (make-sparse-keymap))) 75 (let ((map (make-sparse-keymap)))
64 (define-key map "@" 'outline-mark-subtree) 76 (define-key map "@" 'outline-mark-subtree)
@@ -233,7 +245,8 @@ This option is only in effect when `outline-minor-mode-cycle' is non-nil."
233(defvar outline-font-lock-keywords 245(defvar outline-font-lock-keywords
234 '( 246 '(
235 ;; Highlight headings according to the level. 247 ;; Highlight headings according to the level.
236 (eval . (list (concat "^\\(?:" outline-regexp "\\).*") 248 (eval . (list (or outline-search-function
249 (concat "^\\(?:" outline-regexp "\\).*"))
237 0 '(if outline-minor-mode 250 0 '(if outline-minor-mode
238 (if outline-minor-mode-highlight 251 (if outline-minor-mode-highlight
239 (list 'face (outline-font-lock-face))) 252 (list 'face (outline-font-lock-face)))
@@ -366,7 +379,9 @@ data reflects the `outline-regexp'.")
366 "Return one of `outline-font-lock-faces' for current level." 379 "Return one of `outline-font-lock-faces' for current level."
367 (save-excursion 380 (save-excursion
368 (goto-char (match-beginning 0)) 381 (goto-char (match-beginning 0))
369 (looking-at outline-regexp) 382 (if outline-search-function
383 (funcall outline-search-function nil nil nil t)
384 (looking-at outline-regexp))
370 (aref outline-font-lock-faces 385 (aref outline-font-lock-faces
371 (% (1- (funcall outline-level)) 386 (% (1- (funcall outline-level))
372 (length outline-font-lock-faces))))) 387 (length outline-font-lock-faces)))))
@@ -474,8 +489,11 @@ outline font-lock faces to those of major mode."
474 ;; Fallback to overlays when font-lock is unsupported. 489 ;; Fallback to overlays when font-lock is unsupported.
475 (save-excursion 490 (save-excursion
476 (goto-char (point-min)) 491 (goto-char (point-min))
477 (let ((regexp (concat "^\\(?:" outline-regexp "\\).*$"))) 492 (let ((regexp (unless outline-search-function
478 (while (re-search-forward regexp nil t) 493 (concat "^\\(?:" outline-regexp "\\).*$"))))
494 (while (if outline-search-function
495 (funcall outline-search-function)
496 (re-search-forward regexp nil t))
479 (let ((overlay (make-overlay (match-beginning 0) (match-end 0)))) 497 (let ((overlay (make-overlay (match-beginning 0) (match-end 0))))
480 (overlay-put overlay 'outline-highlight t) 498 (overlay-put overlay 'outline-highlight t)
481 ;; FIXME: Is it possible to override all underlying face attributes? 499 ;; FIXME: Is it possible to override all underlying face attributes?
@@ -592,26 +610,37 @@ or else the number of characters matched by `outline-regexp'."
592 "Skip forward to just before the next heading line. 610 "Skip forward to just before the next heading line.
593If there's no following heading line, stop before the newline 611If there's no following heading line, stop before the newline
594at the end of the buffer." 612at the end of the buffer."
595 (if (re-search-forward (concat "\n\\(?:" outline-regexp "\\)") 613 (when (if outline-search-function
596 nil 'move) 614 (progn
597 (goto-char (match-beginning 0))) 615 ;; Emulate "\n" to force finding the next preface
598 (if (and (bolp) (or outline-blank-line (eobp)) (not (bobp))) 616 (unless (eobp) (forward-char 1))
599 (forward-char -1))) 617 (funcall outline-search-function nil t))
618 (re-search-forward (concat "\n\\(?:" outline-regexp "\\)")
619 nil 'move))
620 (goto-char (match-beginning 0))
621 ;; Compensate "\n" from the beginning of regexp
622 (when (and outline-search-function (not (bobp))) (forward-char -1)))
623 (when (and (bolp) (or outline-blank-line (eobp)) (not (bobp)))
624 (forward-char -1)))
600 625
601(defun outline-next-heading () 626(defun outline-next-heading ()
602 "Move to the next (possibly invisible) heading line." 627 "Move to the next (possibly invisible) heading line."
603 (interactive) 628 (interactive)
604 ;; Make sure we don't match the heading we're at. 629 ;; Make sure we don't match the heading we're at.
605 (if (and (bolp) (not (eobp))) (forward-char 1)) 630 (when (and (bolp) (not (eobp))) (forward-char 1))
606 (if (re-search-forward (concat "^\\(?:" outline-regexp "\\)") 631 (when (if outline-search-function
607 nil 'move) 632 (funcall outline-search-function nil t)
608 (goto-char (match-beginning 0)))) 633 (re-search-forward (concat "^\\(?:" outline-regexp "\\)")
634 nil 'move))
635 (goto-char (match-beginning 0))))
609 636
610(defun outline-previous-heading () 637(defun outline-previous-heading ()
611 "Move to the previous (possibly invisible) heading line." 638 "Move to the previous (possibly invisible) heading line."
612 (interactive) 639 (interactive)
613 (re-search-backward (concat "^\\(?:" outline-regexp "\\)") 640 (if outline-search-function
614 nil 'move)) 641 (funcall outline-search-function nil t t)
642 (re-search-backward (concat "^\\(?:" outline-regexp "\\)")
643 nil 'move)))
615 644
616(defsubst outline-invisible-p (&optional pos) 645(defsubst outline-invisible-p (&optional pos)
617 "Non-nil if the character after POS has outline invisible property. 646 "Non-nil if the character after POS has outline invisible property.
@@ -628,8 +657,10 @@ Only visible heading lines are considered, unless INVISIBLE-OK is non-nil."
628 (let (found) 657 (let (found)
629 (save-excursion 658 (save-excursion
630 (while (not found) 659 (while (not found)
631 (or (re-search-backward (concat "^\\(?:" outline-regexp "\\)") 660 (or (if outline-search-function
632 nil t) 661 (funcall outline-search-function nil nil t)
662 (re-search-backward (concat "^\\(?:" outline-regexp "\\)")
663 nil t))
633 (signal 'outline-before-first-heading nil)) 664 (signal 'outline-before-first-heading nil))
634 (setq found (and (or invisible-ok (not (outline-invisible-p))) 665 (setq found (and (or invisible-ok (not (outline-invisible-p)))
635 (point))))) 666 (point)))))
@@ -642,7 +673,9 @@ If INVISIBLE-OK is non-nil, an invisible heading line is ok too."
642 (save-excursion 673 (save-excursion
643 (beginning-of-line) 674 (beginning-of-line)
644 (and (bolp) (or invisible-ok (not (outline-invisible-p))) 675 (and (bolp) (or invisible-ok (not (outline-invisible-p)))
645 (looking-at outline-regexp)))) 676 (if outline-search-function
677 (funcall outline-search-function nil nil nil t)
678 (looking-at outline-regexp)))))
646 679
647(defun outline-insert-heading () 680(defun outline-insert-heading ()
648 "Insert a new heading at same depth at point." 681 "Insert a new heading at same depth at point."
@@ -754,7 +787,9 @@ nil for WHICH, or do not pass any argument)."
754 (while (and (progn (outline-next-heading) (not (eobp))) 787 (while (and (progn (outline-next-heading) (not (eobp)))
755 (<= (funcall outline-level) level)))) 788 (<= (funcall outline-level) level))))
756 (unless (eobp) 789 (unless (eobp)
757 (looking-at outline-regexp) 790 (if outline-search-function
791 (funcall outline-search-function nil nil nil t)
792 (looking-at outline-regexp))
758 (match-string-no-properties 0)))) 793 (match-string-no-properties 0))))
759 ;; Bummer!! There is no higher-level heading in the buffer. 794 ;; Bummer!! There is no higher-level heading in the buffer.
760 (outline-invent-heading head nil)))) 795 (outline-invent-heading head nil))))
@@ -805,7 +840,9 @@ the match data is set appropriately."
805 (save-excursion 840 (save-excursion
806 (setq end (copy-marker end)) 841 (setq end (copy-marker end))
807 (goto-char beg) 842 (goto-char beg)
808 (when (re-search-forward (concat "^\\(?:" outline-regexp "\\)") end t) 843 (when (if outline-search-function
844 (funcall outline-search-function end)
845 (re-search-forward (concat "^\\(?:" outline-regexp "\\)") end t))
809 (goto-char (match-beginning 0)) 846 (goto-char (match-beginning 0))
810 (funcall fun) 847 (funcall fun)
811 (while (and (progn 848 (while (and (progn
@@ -873,21 +910,23 @@ A heading line is one that starts with a `*' (or that
873 (if (< arg 0) 910 (if (< arg 0)
874 (beginning-of-line) 911 (beginning-of-line)
875 (end-of-line)) 912 (end-of-line))
876 (let (found-heading-p) 913 (let ((regexp (unless outline-search-function
914 (concat "^\\(?:" outline-regexp "\\)")))
915 found-heading-p)
877 (while (and (not (bobp)) (< arg 0)) 916 (while (and (not (bobp)) (< arg 0))
878 (while (and (not (bobp)) 917 (while (and (not (bobp))
879 (setq found-heading-p 918 (setq found-heading-p
880 (re-search-backward 919 (if outline-search-function
881 (concat "^\\(?:" outline-regexp "\\)") 920 (funcall outline-search-function nil t t)
882 nil 'move)) 921 (re-search-backward regexp nil 'move)))
883 (outline-invisible-p))) 922 (outline-invisible-p)))
884 (setq arg (1+ arg))) 923 (setq arg (1+ arg)))
885 (while (and (not (eobp)) (> arg 0)) 924 (while (and (not (eobp)) (> arg 0))
886 (while (and (not (eobp)) 925 (while (and (not (eobp))
887 (setq found-heading-p 926 (setq found-heading-p
888 (re-search-forward 927 (if outline-search-function
889 (concat "^\\(?:" outline-regexp "\\)") 928 (funcall outline-search-function nil t)
890 nil 'move)) 929 (re-search-forward regexp nil 'move)))
891 (outline-invisible-p (match-beginning 0)))) 930 (outline-invisible-p (match-beginning 0))))
892 (setq arg (1- arg))) 931 (setq arg (1- arg)))
893 (if found-heading-p (beginning-of-line)))) 932 (if found-heading-p (beginning-of-line))))
@@ -1107,8 +1146,11 @@ of the current heading, or to 1 if the current line is not a heading."
1107 (interactive (list 1146 (interactive (list
1108 (cond 1147 (cond
1109 (current-prefix-arg (prefix-numeric-value current-prefix-arg)) 1148 (current-prefix-arg (prefix-numeric-value current-prefix-arg))
1110 ((save-excursion (beginning-of-line) 1149 ((save-excursion
1111 (looking-at outline-regexp)) 1150 (beginning-of-line)
1151 (if outline-search-function
1152 (funcall outline-search-function nil nil nil t)
1153 (looking-at outline-regexp)))
1112 (funcall outline-level)) 1154 (funcall outline-level))
1113 (t 1)))) 1155 (t 1))))
1114 (if (< levels 1) 1156 (if (< levels 1)
@@ -1255,7 +1297,9 @@ If INVISIBLE-OK is non-nil, also consider invisible lines."
1255 (setq level (funcall outline-level))) 1297 (setq level (funcall outline-level)))
1256 (setq start-level level)) 1298 (setq start-level level))
1257 (setq arg (- arg 1)))) 1299 (setq arg (- arg 1))))
1258 (looking-at outline-regexp)) 1300 (if outline-search-function
1301 (funcall outline-search-function nil nil nil t)
1302 (looking-at outline-regexp)))
1259 1303
1260(defun outline-forward-same-level (arg) 1304(defun outline-forward-same-level (arg)
1261 "Move forward to the ARG'th subheading at same level as this one. 1305 "Move forward to the ARG'th subheading at same level as this one.
@@ -1313,6 +1357,60 @@ If there is no such heading, return nil."
1313 (if (< (funcall outline-level) level) 1357 (if (< (funcall outline-level) level)
1314 nil 1358 nil
1315 (point))))) 1359 (point)))))
1360
1361
1362;;; Search text-property for outline headings
1363
1364;;;###autoload
1365(defun outline-search-level (&optional bound move backward looking-at)
1366 "Search for the next text property `outline-level'.
1367The arguments are the same as in `outline-search-text-property',
1368except the hard-coded property name `outline-level'.
1369This function is intended to be used in `outline-search-function'."
1370 (outline-search-text-property 'outline-level nil bound move backward looking-at))
1371
1372(autoload 'text-property-search-forward "text-property-search")
1373(autoload 'text-property-search-backward "text-property-search")
1374
1375(defun outline-search-text-property (property &optional value bound move backward looking-at)
1376 "Search for the next text property PROPERTY with VALUE.
1377The rest of arguments are described in `outline-search-function'."
1378 (if looking-at
1379 (when (if value (eq (get-text-property (point) property) value)
1380 (get-text-property (point) property))
1381 (set-match-data (list (pos-bol) (pos-eol)))
1382 t)
1383 ;; Go to the end when in the middle of heading
1384 (when (and (not backward)
1385 (if value (eq (get-text-property (point) property) value)
1386 (get-text-property (point) property))
1387 (not (or (bobp)
1388 (not (if value
1389 (eq (get-text-property (1- (point)) property) value)
1390 (get-text-property (1- (point)) property))))))
1391 (goto-char (1+ (pos-eol))))
1392 (let ((prop-match (if backward
1393 (text-property-search-backward property value (and value t))
1394 (text-property-search-forward property value (and value t)))))
1395 (if prop-match
1396 (let ((beg (prop-match-beginning prop-match))
1397 (end (prop-match-end prop-match)))
1398 (if (or (null bound) (if backward (>= beg bound) (<= end bound)))
1399 (cond (backward
1400 (goto-char beg)
1401 (goto-char (pos-bol))
1402 (set-match-data (list (point) end))
1403 t)
1404 (t
1405 (goto-char end)
1406 (goto-char (if (bolp) (1- (point)) (pos-eol)))
1407 (set-match-data (list beg (point)))
1408 t))
1409 (when move (goto-char bound))
1410 nil))
1411 (when move (goto-char (or bound (if backward (point-min) (point-max)))))
1412 nil))))
1413
1316 1414
1317(defun outline-headers-as-kill (beg end) 1415(defun outline-headers-as-kill (beg end)
1318 "Save the visible outline headers between BEG and END to the kill ring. 1416 "Save the visible outline headers between BEG and END to the kill ring.