emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Bernt Hansen <bernt@norang.ca>
To: Carsten Dominik <carsten.dominik@gmail.com>
Cc: emacs-orgmode@gnu.org
Subject: Re: Lazy project definitions
Date: Mon, 17 May 2010 21:44:12 -0400	[thread overview]
Message-ID: <87vdamnfv7.fsf@gollum.intra.norang.ca> (raw)
In-Reply-To: <D86B0071-9179-4414-B879-07406679C7EB@gmail.com> (Carsten Dominik's message of "Mon\, 17 May 2010 18\:54\:32 +0200")

Carsten Dominik <carsten.dominik@gmail.com> writes:

> On May 17, 2010, at 2:14 PM, Bernt Hansen wrote:
>
>> Carsten Dominik <carsten.dominik@gmail.com> writes:
>>
>>> In the stuck project definition, adding "^\\*\\{3,\\}" as the 4th
>>> element should exclude anything that has level 3 or up in the
>>> subtree.
>>
>> I don't think this will work.  The regexp matches all tasks with
>> level 3
>> or higher subtrees ... which is all projects so all projects are
>> considered unstuck.
>>
>> I need to be able to somehow say a project is not stuck if it doesn't
>> have a level 3 task (ie. no children) because it's not a project in
>> this
>> case.
>
> You are right.  Ahh, I wish we had the power of Perl
> regular expressions in Emacs.  It would be sooo easy then.
> No, I don't see a good way here.
>
> Maybe the best is to completely write your own skipper here.  This
> is actually not too hard, see the Appendix A7 for an example.

Thanks for the pointer to the manual.  I've been beating my head against
the wall for hours on this now.  I tried the example from the manual and
have similar results to the description below.

Here's what I came up with as my skip function

,----
| (defun bh/skip-non-stuck-projects ()
|   "Skip trees that are not projects"
|   (let* ((subtree-end (save-excursion (org-end-of-subtree t)))
| 	 (is-project (save-excursion (re-search-forward "^\\*\\{3,\\}" subtree-end t)))
| 	 (has-next (save-excursion (re-search-forward "^\\*\\** NEXT " subtree-end t))))
|     (if (and is-project (not has-next))
| 	nil ; a stuck project, has subtasks but no next task
|       subtree-end)))
`----

and my custom agenda command is 'x' for testing

,----
|  ("x" "Stuck Projects" tags-todo "LEVEL=2-REFILE/!-DONE-CANCELLED"
|   ((org-agenda-skip-function
|     (bh/skip-non-stuck-projects)))))
`----

but this doesn't work at all like I expect.  I lost a bunch of time when
I had the 'stuck projects' selection instead of tags-todo -- it seems
the skip function doesn't do anything useful with the stuck-projects
setting.

My returned list of tasks is still incorrect -- it contains level 2
tasks with no children.  Sometimes it throws an error -- depending on
what buffer is displayed and where (point) is when I run C-c a x.

In this mail buffer I get

Debugger entered--Lisp error: (error "Before first headline at position 2577 in buffer *wide reply to Carsten Dominik*")
  signal(error ("Before first headline at position 2577 in buffer *wide reply to Carsten Dominik*"))
  error("Before first headline at position %d in buffer %s" 2577 #<buffer *wide reply to Carsten Dominik*>)
  (condition-case nil (outline-back-to-heading invisible-ok) (error (error "Before first headline at position %d in buffer %s" ... ...)))
  org-back-to-heading(t)
  org-end-of-subtree(t)
  (save-excursion (org-end-of-subtree t))
  (let* ((subtree-end ...) (is-project ...) (has-next ...)) (message "is a project %s" is-project) (message "has next %s" has-next) (if (and is-project ...) nil subtree-end))
  (save-excursion (let* (... ... ...) (message "is a project %s" is-project) (message "has next %s" has-next) (if ... nil subtree-end)))
  bh/skip-non-stuck-projects()
  (let ((org-agenda-skip-function ...)) (org-tags-view (quote ...) match))
  eval((let ((org-agenda-skip-function ...)) (org-tags-view (quote ...) match)))
  org-let(((org-agenda-skip-function (bh/skip-non-stuck-projects))) (org-tags-view (quote (4)) match))
  (cond ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-check-for-org-mode) (org-let lprops ...)) ((eq type ...) (org-check-for-org-mode) (org-let lprops ...)) ((eq type ...) (org-check-for-org-mode) (org-let lprops ...)) ((functionp type) (org-let lprops ...)) ((fboundp type) (org-let lprops ...)) (t (error "Invalid custom agenda command type %s" type)))
  (progn (setq type (nth 2 entry) match (eval ...) lprops (nth 4 entry)) (put (quote org-agenda-redo-command) (quote org-lprops) lprops) (cond (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ... ...) (... ... ...) (... ... ...) (... ...) (... ...) (t ...)))
  (if (or (symbolp ...) (functionp ...)) (progn (setq type ... match ... lprops ...) (put ... ... lprops) (cond ... ... ... ... ... ... ... ... ... ... ... ... ...)) (org-run-agenda-series (nth 1 entry) (cddr entry)))
  (cond ((setq entry ...) (if ... ... ...)) ((equal keys "C") (setq org-agenda-custom-commands org-agenda-custom-commands-orig) (customize-variable ...)) ((equal keys "a") (call-interactively ...)) ((equal keys "s") (call-interactively ...)) ((equal keys "t") (call-interactively ...)) ((equal keys "T") (org-call-with-arg ... ...)) ((equal keys "m") (call-interactively ...)) ((equal keys "M") (org-call-with-arg ... ...)) ((equal keys "e") (call-interactively ...)) ((equal keys "?") (org-tags-view nil "+FLAGGED") (org-add-hook ... ... t t)) ((equal keys "L") (unless ... ...) (unless restriction ... ...)) ((equal keys "#") (call-interactively ...)) ((equal keys "/") (call-interactively ...)) ((equal keys "!") (customize-variable ...)) (t (error "Invalid agenda key")))
  (let* ((prefix-descriptions nil) (org-agenda-window-setup ...) (org-agenda-custom-commands-orig org-agenda-custom-commands) (org-agenda-custom-commands ...) (buf ...) (bfn ...) entry key type match lprops ans) (unless org-agenda-overriding-restriction (unless ... ...) (setq org-agenda-restrict nil) (move-marker org-agenda-restrict-begin nil) (move-marker org-agenda-restrict-end nil)) (put (quote org-agenda-redo-command) (quote org-lprops) nil) (setq org-agenda-last-dispatch-buffer (current-buffer)) (unless keys (setq ans ... keys ... restriction ...)) (when (and ... restriction) (put ... ... ...) (cond ... ...)) (cond (... ...) (... ... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ... ...) (... ... ...) (... ...) (... ...) (... ...) (t ...)))
  (catch (quote exit) (let* (... ... ... ... ... ... entry key type match lprops ans) (unless org-agenda-overriding-restriction ... ... ... ...) (put ... ... nil) (setq org-agenda-last-dispatch-buffer ...) (unless keys ...) (when ... ... ...) (cond ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...)))
  org-agenda(nil)
  call-interactively(org-agenda)


If I call it on a task headline or body I get a bunch of tasks but the
results are incorrect.

If I call it from the last line (blank) of an org-mode buffer I get this

Debugger entered--Lisp error: (error "Invalid search bound (wrong side of point)")
  re-search-forward("^\\*\\{3,\\}" 154508 t)
  (save-excursion (re-search-forward "^\\*\\{3,\\}" subtree-end t))
  (let* ((subtree-end ...) (is-project ...) (has-next ...)) (message "is a project %s" is-project) (message "has next %s" has-next) (if (and is-project ...) nil subtree-end))
  (save-excursion (let* (... ... ...) (message "is a project %s" is-project) (message "has next %s" has-next) (if ... nil subtree-end)))
  bh/skip-non-stuck-projects()
  (let ((org-agenda-skip-function ...)) (org-tags-view (quote ...) match))
  eval((let ((org-agenda-skip-function ...)) (org-tags-view (quote ...) match)))
  org-let(((org-agenda-skip-function (bh/skip-non-stuck-projects))) (org-tags-view (quote (4)) match))
  (cond ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-check-for-org-mode) (org-let lprops ...)) ((eq type ...) (org-check-for-org-mode) (org-let lprops ...)) ((eq type ...) (org-check-for-org-mode) (org-let lprops ...)) ((functionp type) (org-let lprops ...)) ((fboundp type) (org-let lprops ...)) (t (error "Invalid custom agenda command type %s" type)))
  (progn (setq type (nth 2 entry) match (eval ...) lprops (nth 4 entry)) (put (quote org-agenda-redo-command) (quote org-lprops) lprops) (cond (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ... ...) (... ... ...) (... ... ...) (... ...) (... ...) (t ...)))
  (if (or (symbolp ...) (functionp ...)) (progn (setq type ... match ... lprops ...) (put ... ... lprops) (cond ... ... ... ... ... ... ... ... ... ... ... ... ...)) (org-run-agenda-series (nth 1 entry) (cddr entry)))
  (cond ((setq entry ...) (if ... ... ...)) ((equal keys "C") (setq org-agenda-custom-commands org-agenda-custom-commands-orig) (customize-variable ...)) ((equal keys "a") (call-interactively ...)) ((equal keys "s") (call-interactively ...)) ((equal keys "t") (call-interactively ...)) ((equal keys "T") (org-call-with-arg ... ...)) ((equal keys "m") (call-interactively ...)) ((equal keys "M") (org-call-with-arg ... ...)) ((equal keys "e") (call-interactively ...)) ((equal keys "?") (org-tags-view nil "+FLAGGED") (org-add-hook ... ... t t)) ((equal keys "L") (unless ... ...) (unless restriction ... ...)) ((equal keys "#") (call-interactively ...)) ((equal keys "/") (call-interactively ...)) ((equal keys "!") (customize-variable ...)) (t (error "Invalid agenda key")))
  (let* ((prefix-descriptions nil) (org-agenda-window-setup ...) (org-agenda-custom-commands-orig org-agenda-custom-commands) (org-agenda-custom-commands ...) (buf ...) (bfn ...) entry key type match lprops ans) (unless org-agenda-overriding-restriction (unless ... ...) (setq org-agenda-restrict nil) (move-marker org-agenda-restrict-begin nil) (move-marker org-agenda-restrict-end nil)) (put (quote org-agenda-redo-command) (quote org-lprops) nil) (setq org-agenda-last-dispatch-buffer (current-buffer)) (unless keys (setq ans ... keys ... restriction ...)) (when (and ... restriction) (put ... ... ...) (cond ... ...)) (cond (... ...) (... ... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ... ...) (... ... ...) (... ...) (... ...) (... ...) (t ...)))
  (catch (quote exit) (let* (... ... ... ... ... ... entry key type match lprops ans) (unless org-agenda-overriding-restriction ... ... ... ...) (put ... ... nil) (setq org-agenda-last-dispatch-buffer ...) (unless keys ...) (when ... ... ...) (cond ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...)))
  org-agenda(nil)
  call-interactively(org-agenda)
  recursive-edit()
  byte-code("Æ\x10	@Ç=ƒ!\0ÈÉÊ\"ˆËÉ!‰\x1aA@)¢Ì=ƒ!\0ÈÍÊ\"ˆÎ\v!ˆÏ ˆÐ	!ˆ\fƒc\0Ñed\"\rVƒW\0ebˆÒ\r¥yˆ`\x1e^[dbˆÒ\r¥\rZyˆ\x0e^[`|ˆ)ÓcˆebˆÔÕÖ \"ˆ× ˆÔØ!ˆÙÊ\x1e\x1c\x1e\x1dÔØ!ˆŠÚ ˆ+Ù‡" [unread-command-char debugger-args x debugger-buffer noninteractive debugger-batch-max-lines -1 debug backtrace-debug 4 t backtrace-frame lambda 5 pop-to-buffer debugger-mode debugger-setup-buffer count-lines 2 "...\n" message "%s" buffer-string kill-emacs "" nil recursive-edit middlestart buffer-read-only standard-output] 4)
  debug(error (error "Before first headline at position 2577 in buffer *wide reply to Carsten Dominik*"))
  signal(error ("Before first headline at position 2577 in buffer *wide reply to Carsten Dominik*"))
  error("Before first headline at position %d in buffer %s" 2577 #<buffer *wide reply to Carsten Dominik*>)
  (condition-case nil (outline-back-to-heading invisible-ok) (error (error "Before first headline at position %d in buffer %s" ... ...)))
  org-back-to-heading(t)
  org-end-of-subtree(t)
  (save-excursion (org-end-of-subtree t))
  (let* ((subtree-end ...) (is-project ...) (has-next ...)) (message "is a project %s" is-project) (message "has next %s" has-next) (if (and is-project ...) nil subtree-end))
  (save-excursion (let* (... ... ...) (message "is a project %s" is-project) (message "has next %s" has-next) (if ... nil subtree-end)))
  bh/skip-non-stuck-projects()
  (let ((org-agenda-skip-function ...)) (org-tags-view (quote ...) match))
  eval((let ((org-agenda-skip-function ...)) (org-tags-view (quote ...) match)))
  org-let(((org-agenda-skip-function (bh/skip-non-stuck-projects))) (org-tags-view (quote (4)) match))
  (cond ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-let lprops ...)) ((eq type ...) (org-check-for-org-mode) (org-let lprops ...)) ((eq type ...) (org-check-for-org-mode) (org-let lprops ...)) ((eq type ...) (org-check-for-org-mode) (org-let lprops ...)) ((functionp type) (org-let lprops ...)) ((fboundp type) (org-let lprops ...)) (t (error "Invalid custom agenda command type %s" type)))
  (progn (setq type (nth 2 entry) match (eval ...) lprops (nth 4 entry)) (put (quote org-agenda-redo-command) (quote org-lprops) lprops) (cond (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ... ...) (... ... ...) (... ... ...) (... ...) (... ...) (t ...)))
  (if (or (symbolp ...) (functionp ...)) (progn (setq type ... match ... lprops ...) (put ... ... lprops) (cond ... ... ... ... ... ... ... ... ... ... ... ... ...)) (org-run-agenda-series (nth 1 entry) (cddr entry)))
  (cond ((setq entry ...) (if ... ... ...)) ((equal keys "C") (setq org-agenda-custom-commands org-agenda-custom-commands-orig) (customize-variable ...)) ((equal keys "a") (call-interactively ...)) ((equal keys "s") (call-interactively ...)) ((equal keys "t") (call-interactively ...)) ((equal keys "T") (org-call-with-arg ... ...)) ((equal keys "m") (call-interactively ...)) ((equal keys "M") (org-call-with-arg ... ...)) ((equal keys "e") (call-interactively ...)) ((equal keys "?") (org-tags-view nil "+FLAGGED") (org-add-hook ... ... t t)) ((equal keys "L") (unless ... ...) (unless restriction ... ...)) ((equal keys "#") (call-interactively ...)) ((equal keys "/") (call-interactively ...)) ((equal keys "!") (customize-variable ...)) (t (error "Invalid agenda key")))
  (let* ((prefix-descriptions nil) (org-agenda-window-setup ...) (org-agenda-custom-commands-orig org-agenda-custom-commands) (org-agenda-custom-commands ...) (buf ...) (bfn ...) entry key type match lprops ans) (unless org-agenda-overriding-restriction (unless ... ...) (setq org-agenda-restrict nil) (move-marker org-agenda-restrict-begin nil) (move-marker org-agenda-restrict-end nil)) (put (quote org-agenda-redo-command) (quote org-lprops) nil) (setq org-agenda-last-dispatch-buffer (current-buffer)) (unless keys (setq ans ... keys ... restriction ...)) (when (and ... restriction) (put ... ... ...) (cond ... ...)) (cond (... ...) (... ... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ... ...) (... ... ...) (... ...) (... ...) (... ...) (t ...)))
  (catch (quote exit) (let* (... ... ... ... ... ... entry key type match lprops ans) (unless org-agenda-overriding-restriction ... ... ... ...) (put ... ... nil) (setq org-agenda-last-dispatch-buffer ...) (unless keys ...) (when ... ... ...) (cond ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...)))
  org-agenda(nil)
  call-interactively(org-agenda)

so either I'm doing something fundamentally wrong here or there's a bug
somewhere.

Any suggestions are most welcome.  I can't wait to get this new setup to
work! :)

Regards,
Bernt

  reply	other threads:[~2010-05-18  1:44 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-05-16 21:17 Lazy project definitions Bernt Hansen
2010-05-17  9:43 ` Carsten Dominik
2010-05-17 11:28   ` Bernt Hansen
2010-05-17 12:14   ` Bernt Hansen
2010-05-17 16:54     ` Carsten Dominik
2010-05-18  1:44       ` Bernt Hansen [this message]
2010-05-18  4:18         ` Matt Lundin
2010-05-18 11:31           ` Bernt Hansen

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

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87vdamnfv7.fsf@gollum.intra.norang.ca \
    --to=bernt@norang.ca \
    --cc=carsten.dominik@gmail.com \
    --cc=emacs-orgmode@gnu.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 public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).