From mboxrd@z Thu Jan 1 00:00:00 1970 From: Cassio Koshikumo Subject: Synopsis view - moving trees around based on a synopsis Date: Sun, 12 Dec 2010 04:56:57 -0200 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Return-path: Received: from [140.186.70.92] (port=44702 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PRfs3-00055B-Ri for emacs-orgmode@gnu.org; Sun, 12 Dec 2010 01:57:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PRfs1-0007fL-6r for emacs-orgmode@gnu.org; Sun, 12 Dec 2010 01:57:23 -0500 Received: from mail-ww0-f49.google.com ([74.125.82.49]:58543) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PRfs0-0007ez-PA for emacs-orgmode@gnu.org; Sun, 12 Dec 2010 01:57:21 -0500 Received: by wwb17 with SMTP id 17so5152665wwb.30 for ; Sat, 11 Dec 2010 22:57:19 -0800 (PST) List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: emacs-orgmode@gnu.org, Matt Lundin , Carsten Dominik Hi there, So, after fiddling a lot, I finally came up with a nice (I think) solution to my synopsis-associated-with-text problem (http://article.gmane.org/gmane.emacs.orgmode/34279/). A little hackish, maybe, but it works fine. Funny thing is, this solution utilizes the first method I had discarded: using a drawer to keep the synopsis. Here's what I wanted to achieve: I'm writing a long text. I'd like to divide it into more manageable chunks (using subtrees), and associate a small synopsis with each of them. Then, I'd like to have a view of the synopsis only, and be able to move the chunks based on those synopsis -- without the main text getting on the way. Here's the solution: 1. Create a new drawer and name it SYNOPSIS. (Of course, you can choose whatever name you like.) Put the synopsis text inside this drawer. * Heading :SYNOPSIS: The synopsis goes here. :END: And the real text goes where it normally goes: on the entry body. 2. On your .emacs, paste the following function: (defun k-synopsis-view () "Show all headings (contents view) and, if any, their synopsis." (interactive) (save-excursion (goto-char (point-min)) (hide-sublevels 1) (while (re-search-forward "\\(^[ \t]*:SYNOPSIS:[. \t]*$\\)" nil t) (org-flag-drawer nil) (re-search-forward "^[ \t]*:END:[ \t]*" nil t) (outline-flag-region (match-beginning 0) (match-end 0) t)) (org-content) )) Notice that the name of the drawer is hard-coded into the function. So, if you chose another name, change it accordingly. (I /think/ this function is not too stupid, but, if anyone knows how to improve it, please do. Calling "hide-sublevels" and then "org-content" was the only way I found to show all the headings and still keep the text entry invisible when moving trees around.) Now you can M-x k-synopsis-view and see only the synopsis, without the real text. 3. For even better results, I recommend setting org-ellipsis to " ": (setq org-ellipsis " ") The "..." makes the view a little dirty. Of course, only do this if you don't mind losing the indicator that there's something hidden (I don't). 4. Now, if you're in the synopsis view and try to move trees around -- which is a primary objective of this setup -- things will not work as expected; the synopsis of the subtree you moved and a few others around it will collapse, leaving you with only the headings. (Promoting and demoting is no problem.) To solve this, I changed the functions "org-move-subtree-up" and "org-move-subtree-down" just a tad: (defun k-move-synopsis-subtree-up (&optional arg) "Move the current subtree up past ARG headlines of the same level, and keep (or enter) synopsis view." (interactive "p") (k-move-synopsis-subtree-down (- (prefix-numeric-value arg)))) (defun k-move-synopsis-subtree-down (&optional arg) "Move the current subtree down past ARG headlines of the same level, and keep (or enter) synopsis view." (interactive "p") (setq arg (prefix-numeric-value arg)) (let ((movfunc (if (> arg 0) 'org-get-next-sibling 'org-get-last-sibling)) (ins-point (make-marker)) (cnt (abs arg)) beg beg0 end txt folded ne-beg ne-end ne-ins ins-end) ;; Select the tree (org-back-to-heading) (setq beg0 (point)) (save-excursion (setq ne-beg (org-back-over-empty-lines)) (setq beg (point))) (save-match-data (save-excursion (outline-end-of-heading) (setq folded (org-invisible-p))) (outline-end-of-subtree)) (outline-next-heading) (setq ne-end (org-back-over-empty-lines)) (setq end (point)) (goto-char beg0) (when (and (> arg 0) (org-first-sibling-p) (< ne-end ne-beg)) ;; include less whitespace (save-excursion (goto-char beg) (forward-line (- ne-beg ne-end)) (setq beg (point)))) ;; Find insertion point, with error handling (while (> cnt 0) (or (and (funcall movfunc) (looking-at outline-regexp)) (progn (goto-char beg0) (error "Cannot move past superior level or buffer limit"))) (setq cnt (1- cnt))) (if (> arg 0) ;; Moving forward - still need to move over subtree (progn (org-end-of-subtree t t) (save-excursion (org-back-over-empty-lines) (or (bolp) (newline))))) (setq ne-ins (org-back-over-empty-lines)) (move-marker ins-point (point)) (setq txt (buffer-substring beg end)) (org-save-markers-in-region beg end) (delete-region beg end) (org-remove-empty-overlays-at beg) (or (=3D beg (point-min)) (outline-flag-region (1- beg) beg nil)) (or (bobp) (outline-flag-region (1- (point)) (point) nil)) (and (not (bolp)) (looking-at "\n") (forward-char 1)) (let ((bbb (point))) (insert-before-markers txt) (org-reinstall-markers-in-region bbb) (move-marker ins-point bbb)) (or (bolp) (insert "\n")) (setq ins-end (point)) (goto-char ins-point) (org-skip-whitespace) (when (and (< arg 0) (org-first-sibling-p) (> ne-ins ne-beg)) ;; Move whitespace back to beginning (save-excursion (goto-char ins-end) (let ((kill-whole-line t)) (kill-line (- ne-ins ne-beg)) (point))) (insert (make-string (- ne-ins ne-beg) ?\n))) (move-marker ins-point nil) (k-synopsis-view))) The only differences from the normal functions are: - The names and descriptions, obviously; - At the end of the function, various visibility settings were removed and replaced with a call to "k-synopsis-view". This guarantees that, after a move, you'll still be in synopsis view (or enter it, if you weren't already.) 5. Now you just need to define some key bindings. Mine are: (add-hook 'org-mode-hook (lambda() (local-set-key (kbd "C-M-n") 'k-move-synopsis-subtree-down) (local-set-key (kbd "C-M-p") 'k-move-synopsis-subtree-up) (local-set-key (kbd "C-\\") 'k-synopsis-view))) And that's it. The cool thing is that, since the synopsis are inside drawers, they won't be exported by default. And, if you want to export only the synopsis to have an overview of the project, just "limit export to visible part of outline tree" when in synopsis view. One thing to notice: when you're in synopsis view, any text you enter will go /inside/ the :SYNOPSIS: drawer -- unless you move the point (cursor) to /after the ellipsis/. (Extra care when using a space as ellipsis, as I do.) So, if you want to insert a new heading when in synopsis view, you can; just make sure to go to the right place with the cursor. (I think the same applies to other kinds of sparse trees, but it's specially relevant here.) Again: I'm no elisp master (oh my, far from it). If you can improve these functions, please do. I hope this is useful to someone else. It sure is for me. Cheers, --=20 C=E1ssio Koshikumo