From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: John J Foerch Newsgroups: gmane.emacs.devel Subject: Re: Outline mode Date: Sat, 01 Sep 2007 13:31:30 -0400 Message-ID: <871wdicmx9.fsf@earthlink.net> References: <87odgnbr9q.fsf@earthlink.net> <87fy1zb77e.fsf@earthlink.net> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: sea.gmane.org 1188667443 2700 80.91.229.12 (1 Sep 2007 17:24:03 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Sat, 1 Sep 2007 17:24:03 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat Sep 01 19:24:02 2007 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1IRWhD-000683-Dt for ged-emacs-devel@m.gmane.org; Sat, 01 Sep 2007 19:24:02 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IRWhA-0001lW-BR for ged-emacs-devel@m.gmane.org; Sat, 01 Sep 2007 13:23:40 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1IRWh7-0001lB-0m for emacs-devel@gnu.org; Sat, 01 Sep 2007 13:23:37 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1IRWh3-0001kt-He for emacs-devel@gnu.org; Sat, 01 Sep 2007 13:23:36 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IRWh3-0001km-Bn for emacs-devel@gnu.org; Sat, 01 Sep 2007 13:23:33 -0400 Original-Received: from main.gmane.org ([80.91.229.2] helo=ciao.gmane.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1IRWh0-00013U-Bx for emacs-devel@gnu.org; Sat, 01 Sep 2007 13:23:33 -0400 Original-Received: from list by ciao.gmane.org with local (Exim 4.43) id 1IRWgi-0008J4-FK for emacs-devel@gnu.org; Sat, 01 Sep 2007 19:23:12 +0200 Original-Received: from dialup-4.158.210.1.dial1.chicago1.level3.net ([4.158.210.1]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sat, 01 Sep 2007 19:23:12 +0200 Original-Received: from jjfoerch by dialup-4.158.210.1.dial1.chicago1.level3.net with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sat, 01 Sep 2007 19:23:12 +0200 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 435 Original-X-Complaints-To: usenet@sea.gmane.org X-Gmane-NNTP-Posting-Host: dialup-4.158.210.1.dial1.chicago1.level3.net User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1.50 (gnu/linux) Cancel-Lock: sha1:9PPjjRZOiZBCBSUZa32IG5yjnoo= X-Detected-Kernel: Linux 2.6, seldom 2.4 (older, 4) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:77548 Archived-At: --=-=-= Stefan Monnier writes: > Duh, I overlooked this "detail", sorry. > But then in what way does it help? You may now move the cursor to just > after the ellipsis but actually be placed right after the newline (rather > than at the end of the text). And if you remove the newline, you get into > the undesired situation where there is no ellipsis any more to warn about > the presence of invisible text. > > Of course I'm biased: it would break reveal-mode which I wrote and use > extensively with outline-minor-mode ;-) > > > Stefan The ellipsis is implemented as a display property in an overlay on the newline of the heading, so point can be just before the ellipsis, and still be on the same line as the heading. If you move point past the ellipsis, then point will be in the first column of the next heading. Thank you for mentioning deletion of the heading's newline. I hadn't considered that situation, but now I have updated my patch to handle it, as well as other situations where invisible text could get modified. I will attach the new version to this message. That's cool that you wrote reveal-mode. I want to help update it to make it work with my changes to outline-mode. I really think my changes are an improvement, but I also see that it will take patience and effort to make sure it works perfectly. It seems that the best way to proceed will be to add sections to this elisp file for each mode that needs to be updated. Then all the changes for everything can be in one place, and people can use eval-buffer for testing, until it's finished. I can put the relevant `require's at the top of the file to avoid problems with autoload. --John --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=outline-patch.el Content-Transfer-Encoding: quoted-printable Content-Description: outline-patch version 0.2 ;;; title: Outline-patch ;;; version: 0.2 ;;; author: John Foerch ;;; date: Saturday, September 1, 2007 ;;; ;;; This script overrides parts of outline-mode to achieve a more ;;; natural behavior concerning the ellipses for hidden entries. With ;;; these changes in place, when you move point to the end of a ;;; heading of a collapsed entry, point will still be on the same line ;;; as the heading. With the old way, point would be located at the ;;; end of the entry, even though it would appear to be on the same ;;; line as the heading. ;;; ;;; Changes in 0.2: Fixed behavior concerning deletion of the ;;; ellipsis and hidden text. ;;; ;;; fixed bug in hide-sublevels that allowed point to ;;; be left on invisible text. ;new (defconst outline-ellipsis "...\n" "String to display in place of the newline character at the end of a heading whose text is hidden.") ;258 (define-derived-mode outline-mode text-mode "Outline" "Set major mode for editing outlines with selective display. Headings are lines which start with asterisks: one for major headings, two for subheadings, etc. Lines not starting with asterisks are body lines. Body text or subheadings under a heading can be made temporarily invisible, or visible again. Invisible lines are attached to the end of the heading, so they move with it, if the line is killed and yanked back. A heading with text hidden under it is marked with an ellipsis (...). Commands:\\ \\[outline-next-visible-heading] outline-next-visible-heading move b= y visible headings \\[outline-previous-visible-heading] outline-previous-visible-heading \\[outline-forward-same-level] outline-forward-same-level similar = but skip subheadings \\[outline-backward-same-level] outline-backward-same-level \\[outline-up-heading] outline-up-heading move from subheading to he= ading \\[hide-body] make all text invisible (not headings). \\[show-all] make everything in buffer visible. \\[hide-sublevels] make only the first N levels of headers visible. The remaining commands are used when point is on a heading line. They apply to some of the body or subheadings of that heading. \\[hide-subtree] hide-subtree make body and subheadings invisible. \\[show-subtree] show-subtree make body and subheadings visible. \\[show-children] show-children make direct subheadings visible. No effect on body, or subheadings 2 or more levels down. With arg N, affects subheadings N levels down. \\[hide-entry] make immediately following body invisible. \\[show-entry] make it visible. \\[hide-leaves] make body under heading and under its subheadings invisi= ble. The subheadings remain visible. \\[show-branches] make all subheadings at all levels visible. The variable `outline-regexp' can be changed to control what is a heading. A line is a heading if `outline-regexp' matches something at the beginning of the line. The longer the match, the deeper the level. Turning on outline mode calls the value of `text-mode-hook' and then of `outline-mode-hook', if they are non-nil." (make-local-variable 'line-move-ignore-invisible) (setq line-move-ignore-invisible t) ;; Cause use of ellipses for invisible text. (add-to-invisibility-spec '(outline)) (set (make-local-variable 'paragraph-start) (concat paragraph-start "\\|\\(?:" outline-regexp "\\)")) ;; Inhibit auto-filling of header lines. (set (make-local-variable 'auto-fill-inhibit-regexp) outline-regexp) (set (make-local-variable 'paragraph-separate) (concat paragraph-separate "\\|\\(?:" outline-regexp "\\)")) (set (make-local-variable 'font-lock-defaults) '(outline-font-lock-keywords t nil nil backward-paragraph)) (setq imenu-generic-expression (list (list nil (concat "^\\(?:" outline-regexp "\\).*$") 0))) (add-hook 'change-major-mode-hook 'show-all nil t)) ;322 (define-minor-mode outline-minor-mode "Toggle Outline minor mode. With arg, turn Outline minor mode on if arg is positive, off otherwise. See the command `outline-mode' for more information on this mode." nil " Outl" (list (cons [menu-bar] outline-minor-mode-menu-bar-map) (cons outline-minor-mode-prefix outline-mode-prefix-map)) :group 'outlines (if outline-minor-mode (progn ;; Turn off this mode if we change major modes. (add-hook 'change-major-mode-hook (lambda () (outline-minor-mode -1)) nil t) (set (make-local-variable 'line-move-ignore-invisible) t) (add-to-invisibility-spec '(outline))) (setq line-move-ignore-invisible nil) (remove-from-invisibility-spec '(outline)) ;; When turning off outline mode, get rid of any outline hiding. (show-all))) ;new (defun outline-auto-show-entry (overlay after-change-p beg end &optional ch= anged-length) (unless after-change-p (save-excursion (goto-char beg) (show-entry)))) ;new (defun outline-do-ellipsis (where &optional remove) (if remove (let ((inhibit-read-only t)) (remove-overlays where (1+ where) 'display outline-ellipsis)) (let ((o (make-overlay where (1+ where) nil t nil))) (overlay-put o 'display outline-ellipsis) (overlay-put o 'modification-hooks '(outline-auto-show-entry))))) ;new (defun outline-end-of-entry () "Skip forward to the end of the entry. This may be the same as the start of the next heading, or possibly a line before, if `outline-blank-line' is non-null." (outline-next-heading) (and outline-blank-line (not (eobp)) (not (bobp)) (eq (char-before (1- (point))) ?\n) (forward-char -1))) ;614 (defun outline-move-subtree-down (&optional arg) "Move the currrent subtree down past ARG headlines of the same level." (interactive "p") (let ((movfunc (if (> arg 0) 'outline-get-next-sibling 'outline-get-last-sibling)) (ins-point (make-marker)) (cnt (abs arg)) beg end 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 (1+ (point))))) (outline-end-of-subtree)) (if (=3D (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 (=3D (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))) ;688 (defun outline-mark-subtree () "Mark the current subtree in an outlined document. This puts point at the start of the current subtree, and mark at the end." (interactive) (let (beg) (if (outline-on-heading-p) ;; we are already looking at a heading (beginning-of-line) ;; else go back to previous heading (outline-previous-visible-heading 1)) (setq beg (point)) (outline-end-of-subtree) (push-mark (point) nil t) (goto-char beg))) ;710 (defun outline-flag-region (from to flag) "Hide or show lines from FROM to TO, according to FLAG. If FLAG is nil then text is shown, while if FLAG is t the text is hidden." (remove-overlays from to 'invisible 'outline) (when flag (let ((o (make-overlay from to))) (overlay-put o 'invisible 'outline) (overlay-put o 'modification-hooks '(outline-auto-show-entry)) (overlay-put o 'isearch-open-invisible (or outline-isearch-open-invisible-function 'outline-isearch-open-invisible)))) ;; Seems only used by lazy-lock. I.e. obsolete. (run-hooks 'outline-view-change-hook)) ;771 (defun hide-entry () "Hide the body directly following this heading." (interactive) (save-excursion (outline-back-to-heading) (outline-end-of-heading) (outline-do-ellipsis (point)) (outline-flag-region (1+ (point)) (progn (outline-end-of-entry) (point)= ) t)) ;; leave point in a visible spot. (when (outline-invisible-p) (outline-back-to-heading) (outline-end-of-heading))) ;779 (defun show-entry () "Show the body directly following this heading. Show the heading too, if it is currently invisible." (interactive) (save-excursion (outline-back-to-heading t) (save-excursion (outline-end-of-heading) (outline-do-ellipsis (point) t)) (outline-flag-region (point) (progn (outline-end-of-entry) (point)) nil))) ;793 (defun hide-region-body (start end) "Hide all body lines in the region, but not headings." ;; Nullify the hook to avoid repeated calls to `outline-flag-region' ;; wasting lots of time running `lazy-lock-fontify-after-outline' ;; and run the hook finally. (let (outline-view-change-hook) (save-excursion (save-restriction (narrow-to-region start end) (goto-char (point-min)) (unless (outline-on-heading-p) (outline-next-heading)) (while (not (eobp)) (outline-end-of-heading) (outline-do-ellipsis (point)) (outline-flag-region (1+ (point)) (progn ;; to-do: implement outline-blank-line (outline-next-heading) (point)) t)))) ;; make sure we leave point in a visible spot (when (outline-invisible-p) (outline-back-to-heading) (outline-end-of-heading))) (run-hooks 'outline-view-change-hook)) ;814 (defun show-all () "Show all of the text in the buffer." (interactive) (outline-flag-region (point-min) (point-max) nil) (remove-overlays (point-min) (point-max) 'display outline-ellipsis)) ;824 (defun hide-leaves () "Hide the body after this heading and at deeper levels." (interactive) (save-excursion (outline-back-to-heading) ;; Turned off to fix bug reported by Otto Maddox on 22 Nov 2005. ;; (outline-end-of-heading) (hide-region-body (point) (progn (outline-end-of-subtree) (point))))) ;838 (defun outline-show-heading () "Show the current heading and move to its end." (outline-flag-region (- (point) (if (bobp) 0 (if (and outline-blank-line (eq (char-before (1- (point))) ?\n)) 1 0))) (progn (outline-end-of-heading) (1+ (point))) nil) (outline-do-ellipsis (point) (not (outline-invisible-p (1+ (point)))))) ;848 (defun hide-sublevels (levels) "Hide everything but the top LEVELS levels of headers, in whole buffer." (interactive (list (cond (current-prefix-arg (prefix-numeric-value current-prefix-arg)) ((save-excursion (beginning-of-line) (looking-at outline-regexp)) (funcall outline-level)) (t 1)))) (if (< levels 1) (error "Must keep at least one level of headers")) (let (outline-view-change-hook) (save-excursion (goto-char (point-min)) ;; Skip the prelude, if any. (unless (outline-on-heading-p t) (outline-next-heading)) ;; First hide everything. (outline-flag-region (point) (point-max) t) ;; Then unhide the top level headers. (outline-map-region (lambda () (if (<=3D (funcall outline-level) levels) (outline-show-heading))) (point) (point-max)))) ;; make sure we leave point on visible text. (when (outline-invisible-p) (outline-back-to-heading) (outline-end-of-heading)) (run-hooks 'outline-view-change-hook)) ;880 (defun hide-other () "Hide everything except current body and parent and top-level headings." (interactive) (hide-sublevels 1) (let (outline-view-change-hook) (save-excursion (outline-back-to-heading t) (show-entry) (while (condition-case nil (progn (outline-up-heading 1 t) (not (bobp= ))) (error nil)) (outline-flag-region (1- (point)) (save-excursion (forward-line 1) (point)) nil)))) (run-hooks 'outline-view-change-hook)) ;895 (defun outline-toggle-children () "Show or hide the current subtree depending on its current state." (interactive) (save-excursion (outline-back-to-heading) (if (not (outline-invisible-p (1+ (line-end-position)))) (hide-subtree) (show-children) (show-entry)))) ;905 (defun outline-flag-subtree (flag) (save-excursion (outline-back-to-heading) (outline-end-of-heading) (outline-do-ellipsis (point) (not flag)) (outline-flag-region (1+ (point)) (progn (outline-end-of-subtree) (point)) flag))) ;913 (defun outline-end-of-subtree () (outline-back-to-heading) (let ((first t) (level (funcall outline-level))) (while (and (not (eobp)) (or first (> (funcall outline-level) level))) (setq first nil) (outline-next-heading)) (if (and (bolp) (not (eolp)) ;; We stopped at a nonempty line (the next heading). outline-blank-line (not (eobp)) (eq (char-before (1- (point))) ?\n)) (forward-char -1)))) --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-devel mailing list Emacs-devel@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-devel --=-=-=--