From: Cassio Koshikumo <ckoshikumo@gmail.com>
To: emacs-orgmode@gnu.org, Matt Lundin <mdl@imapmail.org>,
Carsten Dominik <carsten.dominik@gmail.com>
Subject: Synopsis view - moving trees around based on a synopsis
Date: Sun, 12 Dec 2010 04:56:57 -0200 [thread overview]
Message-ID: <AANLkTi=6LADUevueMjE5snZRr6FyXKgMAS6jDeiF=H9g@mail.gmail.com> (raw)
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 (= 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,
--
Cássio Koshikumo
next reply other threads:[~2010-12-12 6:57 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-12 6:56 Cassio Koshikumo [this message]
2010-12-12 17:36 ` Synopsis view - moving trees around based on a synopsis Eric S Fraga
2010-12-13 0:33 ` Cassio Koshikumo
2011-01-02 14:52 ` David Maus
2011-01-05 17:21 ` Cassio Koshikumo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='AANLkTi=6LADUevueMjE5snZRr6FyXKgMAS6jDeiF=H9g@mail.gmail.com' \
--to=ckoshikumo@gmail.com \
--cc=carsten.dominik@gmail.com \
--cc=emacs-orgmode@gnu.org \
--cc=mdl@imapmail.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.