Re: [O] Weight of headers

2012-02-26 Thread Nicolas Goaziou
Hello,

pin...@iro.umontreal.ca (François Pinard) writes:

 Here is a need I have once in a while, but for which I do not even have
 realistic suggestions to offer (at least, so I feel).  Maybe someone
 would offer more precise ideas. :-)

 When I have a big Org file which I want to re-organize, one of the
 criteria I use is to manage the overall plan, always keeping a logical
 organization of things of course, and move things around so top-level
 headers become of comparable weights.  By weight, I mean the amount of
 contents, which is a fuzzy concept (it could be measured as the number
 of sub-headers or sub-items, the depth of structure, or even the raw
 number or lines or characters).

 It may look strange, but this is not so bizarre after all.  When reading
 a book, it is unusual to have a chapter having one page next to a
 chapter having hundreds of page; we expect that the effort of reading a
 chapter is not widely different from the effort of reading another.  In
 the same way, if I decide to tackle the topics under a header, I would
 expect that the energy needed somehow announces the energy that would be
 required to handle another level at the same level.  Of course, there
 could be quite a variance, but nevertheless, I would like to keep that
 variance within bounds.

 And recursively!  The same way I would like to work an weight
 equilibrium for top-level headers, I would like to do the same for the
 sub-headers of a given header.

 My need here is to get an estimate of the weight of displayed headers.
 I could of course expand the whole document and page through to get an
 idea, but at least in the document I'm currently handling, I'm just
 overwhelmed.  (This is not the only document triggering this in me, I
 remember having felt that need many times when I was using WorkFlowy).

 I once thought that colors could encode the weight, but it just would
 not fit Org mode so far that I understand it.  However, it seems that,
 here and there, Org uses some overly magic to display extra information
 -- for example, like with `C-c C-x C-d (`org-clock-display')'.  Maybe
 that some similar machinery could be use to display header weights?  Or
 maybe this would be overkill, because there are simpler ways which I
 just do not know?

The following function will give you the number of sub-headings and
paragraphs (or equivalent, i.e. tables verse-blocks).

You'll need a recent Org to use it. 

#+begin_src emacs-lisp
(defun pinard-count-subtree-and-paragraphs ()
  Return number of subtrees and paragraphs in the subtree at point.
  (interactive)
  (org-with-wide-buffer
   (org-narrow-to-subtree)
   (let ((tree (org-element-parse-buffer 'element)) (num-hl 0) (num-el 0))
 (org-element-map tree 'headline (lambda (hl) (incf num-hl)))
 (org-element-map
  tree '(paragraph table verse-block quote-block src-block example-block)
  (lambda (el) (incf num-el)))
 (message Sub-headings: %d ; Parapraphs (or equivalent): %d
  (1- num-hl) num-el
#+end_src

There's no colour, but it's a starter.


Regards,

-- 
Nicolas Goaziou



Re: [O] Weight of headers

2012-02-26 Thread François Pinard
Nicolas Goaziou n.goaz...@gmail.com writes:

 pin...@iro.umontreal.ca (François Pinard) writes:

 My need here is to get an estimate of the weight of displayed headers.

 The following function will give you the number of sub-headings and
 paragraphs (or equivalent, i.e. tables verse-blocks).

Wow, thanks!  That was a real good starter.

Roughly copying code from here and there (and not even understanding it,
some dead code might remain), I turned your function into the following:

--8---cut here---start-8---
(defun fp-org-weight-display ()
  Show header weights in the entire buffer.

Use \\[fp-org-weight-remove-overlays] to remove the header weights.
  (interactive)
  (fp-org-weight-remove-overlays)
  (let (weights)
  (save-excursion
(goto-char (point-min))
(outline-next-visible-heading 1)
(while (not (eobp))
  (save-excursion
(fp-org-weight-put-overlay (fp-org-weights-at-point)
 (funcall outline-level)))
  (outline-next-visible-heading 1))
;; Arrange to remove the overlays upon next change.
(when org-remove-highlights-with-change
  (org-add-hook 'before-change-functions 'fp-org-weight-remove-overlays
nil 'local)

(defvar fp-org-weight-overlays nil)
(make-variable-buffer-local 'fp-org-weight-overlays)

(defun fp-org-weight-put-overlay (weights optional level)
  Put an overlays on the current line, displaying WEIGHTS.
If LEVEL is given, prefix weights with a corresponding number of stars.
This creates a new overlay and stores it in `fp-org-weight-overlays', so that it
will be easy to remove.
  (let* ((c 60)
 (l (if level (org-get-valid-level level 0) 0))
 (off 0)
 ov tx)
(org-move-to-column c)
(unless (eolp) (skip-chars-backward ^ \t))
(skip-chars-backward  \t)
(setq ov (make-overlay (1- (point)) (point-at-eol))
  tx (concat (buffer-substring (1- (point)) (point))
 (make-string (+ off (max 0 (- c (current-column ?.)
 (org-add-props (format %s %3d headings %4d paragraphs%s
(make-string l ?*)
(car weights)
(cdr weights)
(make-string (- 16 l) ?\ ))
 (list 'face 'org-clock-overlay))
 ))
(if (not (featurep 'xemacs))
(overlay-put ov 'display tx)
  (overlay-put ov 'invisible t)
  (overlay-put ov 'end-glyph (make-glyph tx)))
(push ov fp-org-weight-overlays)))

(defun fp-org-weight-remove-overlays (optional beg end noremove)
  Remove the occur highlights from the buffer.
BEG and END are ignored.  If NOREMOVE is nil, remove this function
from the `before-change-functions' in the current buffer.
  (interactive)
  (unless org-inhibit-highlight-removal
(mapc 'delete-overlay fp-org-weight-overlays)
(setq fp-org-weight-overlays nil)
(unless noremove
  (remove-hook 'before-change-functions
   'fp-org-weight-remove-overlays 'local

;; Compliment of Nicolas Goaziou n.goaz...@gmail.com, 2012-02-26
(defun fp-org-weights-at-point ()
  Return cons of number of subtrees and paragraphs in the subtree at point.
Paragraphs (also encompasses equivalent structures).
  (org-with-wide-buffer
   (org-narrow-to-subtree)
   (let ((tree (org-element-parse-buffer 'element)) (num-hl 0) (num-el 0))
 (org-element-map tree 'headline (lambda (hl) (incf num-hl)))
 (org-element-map
  tree '(paragraph table verse-block quote-block src-block example-block)
  (lambda (el) (incf num-el)))
 (cons (1- num-hl) num-el

(autoload 'org-element-parse-buffer 
~/bureautique/emacs/_/org-mode/contrib/lisp/org-element)
(global-set-key \C-cow 'fp-org-weight-display)
--8---cut here---end---8---

The next to last line was needed because your function depends on
org-element.el, which is not directly available in Org mode, at least
as of today's Git repository.  Is it a better way to install that file?

Another questionable thing is that I'm using the org-clock-overly face,
while the code should probably use and define its own.

Once again, thanks Nicolas!

François



Re: [O] Weight of headers

2012-02-26 Thread François Pinard
pin...@iro.umontreal.ca (François Pinard) writes:

 Roughly copying code from here and there (and not even understanding it,
 some dead code might remain), I turned your function into the
 following:

Hmph!  There seemingly is a problem however.

I tried it on a few files, and it usually does it works quickly, or in
no more than a few seconds.  However, on one of my Org files, after many
minutes, Emacs is still processing the command.  If I interrupt it (with
C-g), the main text displays its information, but the appendices do not.

I do not know if this matters: while all the appendices together do not
use much space in *this* file, they are merely made up of #+INCLUDE
directives, each preceded by a short introductory text.  The included
files may be a bit longish however.

François



Re: [O] Weight of headers

2012-02-26 Thread Samuel Wales
Great way of doing it.

Another option is to create a new buffer and sort the headers by the
weight.  Ideally each header in the new buffer would be a link.

Yet another is to use the agenda.  I think it might have a new format
string option for the weight.  Then use the agenda to sort.

And another possibility is to gather weights recursively vs. for each
header.  This works for bytes.

Samuel

P.S.  Code from years ago.  Might or might not work.

;;(alpha-org-dus-tree)
(defun* alpha-org-dus-tree (optional same (n 10))
  Show the biggest subtrees in agenda files.  SAME says whether
to measure each node vs. each subtree.
  (interactive)
  ;;(show-all)
  ;;(with-current-buffer ...
  (switch-to-buffer *alpha-org-dus-tree*)
  (erase-buffer)
  (insert
;;;  (cl-prettyprint
   (subseq (sort* (alpha-org-dus-tree-1 same)
  #'
  :key #'car)
   0
   n)))
(defun alpha-org-dus-tree-1 (same)
  (org-map-entries #'(lambda ()
   ;;(message doing %s
   (cons (alpha-org-get-size same)
 (org-get-heading)))
   t
   'agenda))
(defun alpha-org-get-size (optional same)
  ;;(current-buffer)
  (- (save-excursion
   (ignore-errors
 (funcall (if same
  ;;org-end-of-subtree t t
  'org-forward-same-level
'outline-next-heading)
  1))
   (point))
 (point)))

-- 
The Kafka Pandemic: http://thekafkapandemic.blogspot.com



Re: [O] Weight of headers

2012-02-26 Thread Nick Dokos
François Pinard pin...@iro.umontreal.ca wrote:

 pin...@iro.umontreal.ca (François Pinard) writes:
 
  Roughly copying code from here and there (and not even understanding it,
  some dead code might remain), I turned your function into the
  following:
 
 Hmph!  There seemingly is a problem however.
 
 I tried it on a few files, and it usually does it works quickly, or in
 no more than a few seconds.  However, on one of my Org files, after many
 minutes, Emacs is still processing the command.  If I interrupt it (with
 C-g), the main text displays its information, but the appendices do not.
 
 I do not know if this matters: while all the appendices together do not
 use much space in *this* file, they are merely made up of #+INCLUDE
 directives, each preceded by a short introductory text.  The included
 files may be a bit longish however.
 

M-x toggle-debug-on-quit RET

Then when it gets into its rut and you interrupt with C-g, you'll get a
backtrace telling you where it was. If you repeat a couple of times and
you get the same backtrace each time, then you've probably found your
infinite looper.

Nick