Mercurial > emacs
changeset 50124:d4f965eb8fd5
(outline-mode-menu-bar-map): Add entries.
(outline-mode-prefix-map): Match new bindings to those of allout.
(outline-map-region): New fun.
(outline-map-tree): Remove.
(outline-promote, outline-demote): Apply to region if active.
Change the default to apply to the subtree.
(outline-move-subtree-up, outline-move-subtree-down): New funs.
(outline-invisible-p): Add optional `pos' argument.
(outline-next-visible-heading, outline-toggle-children): Use it.
(outline-get-next-sibling): Don't call outline-level at eob.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Thu, 13 Mar 2003 18:15:07 +0000 |
parents | 7c924263658d |
children | a9135466b161 |
files | lisp/textmodes/outline.el |
diffstat | 1 files changed, 157 insertions(+), 79 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/textmodes/outline.el Thu Mar 13 18:10:41 2003 +0000 +++ b/lisp/textmodes/outline.el Thu Mar 13 18:15:07 2003 +0000 @@ -80,9 +80,12 @@ (define-key map "\C-k" 'show-branches) (define-key map "\C-q" 'hide-sublevels) (define-key map "\C-o" 'hide-other) - (define-key map "\C-^" 'outline-promote) - (define-key map "\C-v" 'outline-demote) - ;; Where to bind toggle and insert-heading ? + (define-key map "\C-^" 'outline-move-subtree-up) + (define-key map "\C-v" 'outline-move-subtree-down) + (define-key map [(control ?<)] 'outline-promote) + (define-key map [(control ?>)] 'outline-demote) + (define-key map "\C-m" 'outline-insert-heading) + ;; Where to bind outline-cycle ? map)) (defvar outline-mode-menu-bar-map @@ -108,9 +111,19 @@ (define-key map [headings] (cons "Headings" (make-sparse-keymap "Headings"))) + (define-key map [headings demote-subtree] + '(menu-item "Demote subtree" outline-demote)) + (define-key map [headings promote-subtree] + '(menu-item "Promote subtree" outline-promote)) + (define-key map [headings move-subtree-down] + '(menu-item "Move subtree down" outline-move-subtree-down)) + (define-key map [headings move-subtree-up] + '(menu-item "Move subtree up" outline-move-subtree-up)) (define-key map [headings copy] '(menu-item "Copy to kill ring" outline-headers-as-kill :enable mark-active)) + (define-key map [headings outline-insert-heading] + '("New heading" . outline-insert-heading)) (define-key map [headings outline-backward-same-level] '("Previous Same Level" . outline-backward-same-level)) (define-key map [headings outline-forward-same-level] @@ -139,7 +152,7 @@ (cons '(--- "---") (cdr x)))) outline-mode-menu-bar-map)))))) map)) - + (defvar outline-mode-map (let ((map (make-sparse-keymap))) @@ -339,9 +352,9 @@ (re-search-backward (concat "^\\(?:" outline-regexp "\\)") nil 'move)) -(defsubst outline-invisible-p () +(defsubst outline-invisible-p (&optional pos) "Non-nil if the character after point is invisible." - (get-char-property (point) 'invisible)) + (get-char-property (or pos (point)) 'invisible)) (defun outline-visible () (not (outline-invisible-p))) @@ -391,75 +404,144 @@ (run-hooks 'outline-insert-heading-hook))) (defun outline-promote (&optional children) - "Promote the current heading higher up the tree. -If prefix argument CHILDREN is given, promote also all the children." - (interactive "P") - (outline-back-to-heading) - (let* ((head (match-string 0)) - (level (save-match-data (funcall outline-level))) - (up-head (or (car (rassoc (1- level) outline-heading-alist)) - (save-excursion - (save-match-data - (outline-up-heading 1 t) - (match-string 0)))))) + "Promote headings higher up the tree. +If prefix argument CHILDREN is given, promote also all the children. +If the region is active in `transient-mark-mode', promote all headings +in the region." + (interactive + (list (if (and transient-mark-mode mark-active) 'region + (outline-back-to-heading) + (if current-prefix-arg nil 'subtree)))) + (cond + ((eq children 'region) + (outline-map-region 'outline-promote (region-beginning) (region-end))) + (children + (outline-map-region 'outline-promote + (point) + (save-excursion (outline-get-next-sibling) (point)))) + (t + (outline-back-to-heading t) + (let* ((head (match-string 0)) + (level (save-match-data (funcall outline-level))) + (up-head (or (car (rassoc (1- level) outline-heading-alist)) + (save-excursion + (save-match-data + (outline-up-heading 1 t) + (match-string 0)))))) + + (unless (rassoc level outline-heading-alist) + (push (cons head level) outline-heading-alist)) + + (replace-match up-head nil t))))) + +(defun outline-demote (&optional children) + "Demote headings lower down the tree. +If prefix argument CHILDREN is given, demote also all the children. +If the region is active in `transient-mark-mode', demote all headings +in the region." + (interactive + (list (if (and transient-mark-mode mark-active) 'region + (outline-back-to-heading) + (if current-prefix-arg nil 'subtree)))) + (cond + ((eq children 'region) + (outline-map-region 'outline-demote (region-beginning) (region-end))) + (children + (outline-map-region 'outline-demote + (point) + (save-excursion (outline-get-next-sibling) (point)))) + (t + (let* ((head (match-string 0)) + (level (save-match-data (funcall outline-level))) + (down-head + (or (car (rassoc (1+ level) outline-heading-alist)) + (save-excursion + (save-match-data + (while (and (not (eobp)) + (progn + (outline-next-heading) + (<= (funcall outline-level) level)))) + (when (eobp) + ;; Try again from the beginning of the buffer. + (goto-char (point-min)) + (while (and (not (eobp)) + (progn + (outline-next-heading) + (<= (funcall outline-level) level))))) + (unless (eobp) + (looking-at outline-regexp) + (match-string 0)))) + (save-match-data + ;; Bummer!! There is no lower heading in the buffer. + ;; Let's try to invent one by repeating the first char. + (let ((new-head (concat (substring head 0 1) head))) + (if (string-match (concat "\\`" outline-regexp) new-head) + ;; Why bother checking that it is indeed lower level ? + new-head + ;; Didn't work: keep it as is so it's still a heading. + head)))))) (unless (rassoc level outline-heading-alist) (push (cons head level) outline-heading-alist)) + (replace-match down-head nil t))))) - (replace-match up-head nil t) - (when children - (outline-map-tree 'outline-promote level)))) +(defun outline-map-region (fun beg end) + "Call FUN for every heading between BEG and END. +When FUN is called, point is at the beginning of the heading and +the match data is set appropriately." + (save-excursion + (setq end (copy-marker end)) + (goto-char beg) + (when (re-search-forward (concat "^\\(?:" outline-regexp "\\)") end t) + (goto-char (match-beginning 0)) + (funcall fun) + (while (and (progn + (outline-next-heading) + (< (point) end)) + (not (eobp))) + (funcall fun))))) + +;; Vertical tree motion + +(defun outline-move-subtree-up (&optional arg) + "Move the currrent subtree up past ARG headlines of the same level." + (interactive "p") + (outline-move-subtree-down (- arg))) -(defun outline-demote (&optional children) - "Demote the current heading lower down the tree. -If prefix argument CHILDREN is given, demote also all the children." - (interactive "P") - (outline-back-to-heading) - (let* ((head (match-string 0)) - (level (save-match-data (funcall outline-level))) - (down-head - (or (car (rassoc (1+ level) outline-heading-alist)) - (save-excursion - (save-match-data - (while (and (not (eobp)) - (progn - (outline-next-heading) - (<= (funcall outline-level) level)))) - (when (eobp) - ;; Try again from the beginning of the buffer. - (goto-char (point-min)) - (while (and (not (eobp)) - (progn - (outline-next-heading) - (<= (funcall outline-level) level))))) - (unless (eobp) - (looking-at outline-regexp) - (match-string 0)))) - (save-match-data - ;; Bummer!! There is no lower heading in the buffer. - ;; Let's try to invent one by repeating the first char. - (let ((new-head (concat (substring head 0 1) head))) - (if (string-match (concat "\\`" outline-regexp) new-head) - ;; Why bother checking that it is indeed of lower level ? - new-head - ;; Didn't work: keep it as is so it's still a heading. - head)))))) - - (unless (rassoc level outline-heading-alist) - (push (cons head level) outline-heading-alist)) - - (replace-match down-head nil t) - (when children - (outline-map-tree 'outline-demote level)))) - -(defun outline-map-tree (fun level) - "Call FUN for every heading underneath the current one." - (save-excursion - (while (and (progn - (outline-next-heading) - (> (funcall outline-level) level)) - (not (eobp))) - (funcall fun)))) +(defun outline-move-subtree-down (&optional arg) + "Move the currrent subtree down past ARG headlines of the same level." + (interactive "p") + (let ((re (concat "^" outline-regexp)) + (movfunc (if (> arg 0) 'outline-get-next-sibling + 'outline-get-last-sibling)) + (ins-point (make-marker)) + (cnt (abs arg)) + beg end txt folded) + ;; Select the tree + (outline-back-to-heading) + (setq beg (point)) + (save-match-data + (save-excursion (outline-end-of-heading) + (setq folded (outline-invisible-p))) + (outline-end-of-subtree)) + (if (= (char-after) ?\n) (forward-char 1)) + (setq end (point)) + ;; Find insertion point, with error handling + (goto-char beg) + (while (> cnt 0) + (or (funcall movfunc) + (progn (goto-char beg) + (error "Cannot move past superior level"))) + (setq cnt (1- cnt))) + (if (> arg 0) + ;; Moving forward - still need to move over subtree + (progn (outline-end-of-subtree) + (if (= (char-after) ?\n) (forward-char 1)))) + (move-marker ins-point (point)) + (insert (delete-and-extract-region beg end)) + (goto-char ins-point) + (if folded (hide-subtree)) + (move-marker ins-point nil))) (defun outline-end-of-heading () (if (re-search-forward outline-heading-end-regexp nil 'move) @@ -484,9 +566,7 @@ (while (and (not (eobp)) (re-search-forward (concat "^\\(?:" outline-regexp "\\)") nil 'move) - (save-excursion - (goto-char (match-beginning 0)) - (outline-invisible-p)))) + (outline-invisible-p (match-beginning 0)))) (setq arg (1- arg))) (beginning-of-line)) @@ -534,7 +614,7 @@ ;; reveal do the rest, by simply doing: ;; (remove-overlays (overlay-start o) (overlay-end o) ;; 'invisible 'outline) - ;; + ;; ;; That works fine as long as everything is in sync, but if the ;; structure of the document is changed while revealing parts of it, ;; the resulting behavior can be ugly. I.e. we need to make @@ -681,9 +761,7 @@ "Show or hide the current subtree depending on its current state." (interactive) (outline-back-to-heading) - (if (save-excursion - (end-of-line) - (not (outline-invisible-p))) + (if (not (outline-invisible-p (line-end-position))) (hide-subtree) (show-children) (show-entry))) @@ -754,7 +832,7 @@ (point)) (progn (outline-end-of-heading) (point)) nil))))))) - (run-hooks 'outline-view-change-hook)) + (run-hooks 'outline-view-change-hook)) @@ -801,7 +879,7 @@ (while (and (> (funcall outline-level) level) (not (eobp))) (outline-next-visible-heading 1)) - (if (< (funcall outline-level) level) + (if (or (eobp) (< (funcall outline-level) level)) nil (point))))