From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bernt Hansen Subject: Re: Lazy project definitions Date: Mon, 17 May 2010 21:44:12 -0400 Message-ID: <87vdamnfv7.fsf@gollum.intra.norang.ca> References: <878w7jbl6m.fsf@gollum.intra.norang.ca> <2C475BA4-862D-434D-A123-8AADAF8A8EB2@gmail.com> <878w7ipvxi.fsf@gollum.intra.norang.ca> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Return-path: Received: from [140.186.70.92] (port=49736 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OEBrO-0004ql-Nj for emacs-orgmode@gnu.org; Mon, 17 May 2010 21:44:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OEBrH-0006Fu-TM for emacs-orgmode@gnu.org; Mon, 17 May 2010 21:44:42 -0400 Received: from mho-01-ewr.mailhop.org ([204.13.248.71]:64245) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OEBrH-0006F0-OH for emacs-orgmode@gnu.org; Mon, 17 May 2010 21:44:35 -0400 In-Reply-To: (Carsten Dominik's message of "Mon\, 17 May 2010 18\:54\:32 +0200") 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: Carsten Dominik Cc: emacs-orgmode@gnu.org Carsten Dominik writes: > On May 17, 2010, at 2:14 PM, Bernt Hansen wrote: > >> Carsten Dominik 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-e= nd t))) | (has-next (save-excursion (re-search-forward "^\\*\\** NEXT " subtree-e= nd 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=3D2-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 257= 7 in buffer *wide reply to Carsten Dominik*") signal(error ("Before first headline at position 2577 in buffer *wide rep= ly to Carsten Dominik*")) error("Before first headline at position %d in buffer %s" 2577 #) (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-projec= t ...) 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 ...) mat= ch))) org-let(((org-agenda-skip-function (bh/skip-non-stuck-projects))) (org-ta= gs-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-l= et 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)) (p= ut (quote org-agenda-redo-command) (quote org-lprops) lprops) (cond (... ..= .) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ... ...= ) (... ... ...) (... ... ...) (... ...) (... ...) (t ...))) (if (or (symbolp ...) (functionp ...)) (progn (setq type ... match ... lp= rops ...) (put ... ... lprops) (cond ... ... ... ... ... ... ... ... ... ..= . ... ... ...)) (org-run-agenda-series (nth 1 entry) (cddr entry))) (cond ((setq entry ...) (if ... ... ...)) ((equal keys "C") (setq org-age= nda-custom-commands org-agenda-custom-commands-orig) (customize-variable ..= .)) ((equal keys "a") (call-interactively ...)) ((equal keys "s") (call-int= eractively ...)) ((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-in= teractively ...)) ((equal keys "?") (org-tags-view nil "+FLAGGED") (org-add= -hook ... ... t t)) ((equal keys "L") (unless ... ...) (unless restriction = ... ...)) ((equal keys "#") (call-interactively ...)) ((equal keys "/") (ca= ll-interactively ...)) ((equal keys "!") (customize-variable ...)) (t (erro= r "Invalid agenda key"))) (let* ((prefix-descriptions nil) (org-agenda-window-setup ...) (org-agend= a-custom-commands-orig org-agenda-custom-commands) (org-agenda-custom-comma= nds ...) (buf ...) (bfn ...) entry key type match lprops ans) (unless org-a= genda-overriding-restriction (unless ... ...) (setq org-agenda-restrict nil= ) (move-marker org-agenda-restrict-begin nil) (move-marker org-agenda-restr= ict-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 l= props 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 p= oint)") 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-projec= t ...) 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 ...) mat= ch))) org-let(((org-agenda-skip-function (bh/skip-non-stuck-projects))) (org-ta= gs-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-l= et 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)) (p= ut (quote org-agenda-redo-command) (quote org-lprops) lprops) (cond (... ..= .) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ... ...= ) (... ... ...) (... ... ...) (... ...) (... ...) (t ...))) (if (or (symbolp ...) (functionp ...)) (progn (setq type ... match ... lp= rops ...) (put ... ... lprops) (cond ... ... ... ... ... ... ... ... ... ..= . ... ... ...)) (org-run-agenda-series (nth 1 entry) (cddr entry))) (cond ((setq entry ...) (if ... ... ...)) ((equal keys "C") (setq org-age= nda-custom-commands org-agenda-custom-commands-orig) (customize-variable ..= .)) ((equal keys "a") (call-interactively ...)) ((equal keys "s") (call-int= eractively ...)) ((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-in= teractively ...)) ((equal keys "?") (org-tags-view nil "+FLAGGED") (org-add= -hook ... ... t t)) ((equal keys "L") (unless ... ...) (unless restriction = ... ...)) ((equal keys "#") (call-interactively ...)) ((equal keys "/") (ca= ll-interactively ...)) ((equal keys "!") (customize-variable ...)) (t (erro= r "Invalid agenda key"))) (let* ((prefix-descriptions nil) (org-agenda-window-setup ...) (org-agend= a-custom-commands-orig org-agenda-custom-commands) (org-agenda-custom-comma= nds ...) (buf ...) (bfn ...) entry key type match lprops ans) (unless org-a= genda-overriding-restriction (unless ... ...) (setq org-agenda-restrict nil= ) (move-marker org-agenda-restrict-begin nil) (move-marker org-agenda-restr= ict-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 l= props 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("=C3=86=10 @=C3=87=3D=C2=83!=00=C3=88=C3=89=C3=8A\"=C2=88=C3=8B= =C3=89!=C2=89=1AA@)=C2=A2=C3=8C=3D=C2=83!=00=C3=88=C3=8D=C3=8A\"=C2=88=C3= =8E=0B!=C2=88=C3=8F =C2=88=C3=90 !=C2=88\f=C2=83c=00=C3=91ed\"=0DV=C2=83W= =00eb=C2=88=C3=92=0D=C2=A5y=C2=88`=1E=1Bdb=C2=88=C3=92=0D=C2=A5=0DZy=C2=88= =0E=1B`|=C2=88)=C3=93c=C2=88eb=C2=88=C3=94=C3=95=C3=96 \"=C2=88=C3=97 =C2= =88=C3=94=C3=98!=C2=88=C3=99=C3=8A=1E=1C=1E=1D=C3=94=C3=98!=C2=88=C2=8A=C3= =9A =C2=88+=C3=99=C2=87" [unread-command-char debugger-args x debugger-buff= er noninteractive debugger-batch-max-lines -1 debug backtrace-debug 4 t bac= ktrace-frame lambda 5 pop-to-buffer debugger-mode debugger-setup-buffer cou= nt-lines 2 "...\n" message "%s" buffer-string kill-emacs "" nil recursive-e= dit middlestart buffer-read-only standard-output] 4) debug(error (error "Before first headline at position 2577 in buffer *wid= e reply to Carsten Dominik*")) signal(error ("Before first headline at position 2577 in buffer *wide rep= ly to Carsten Dominik*")) error("Before first headline at position %d in buffer %s" 2577 #) (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-projec= t ...) 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 ...) mat= ch))) org-let(((org-agenda-skip-function (bh/skip-non-stuck-projects))) (org-ta= gs-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-l= et 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)) (p= ut (quote org-agenda-redo-command) (quote org-lprops) lprops) (cond (... ..= .) (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (... ... ...= ) (... ... ...) (... ... ...) (... ...) (... ...) (t ...))) (if (or (symbolp ...) (functionp ...)) (progn (setq type ... match ... lp= rops ...) (put ... ... lprops) (cond ... ... ... ... ... ... ... ... ... ..= . ... ... ...)) (org-run-agenda-series (nth 1 entry) (cddr entry))) (cond ((setq entry ...) (if ... ... ...)) ((equal keys "C") (setq org-age= nda-custom-commands org-agenda-custom-commands-orig) (customize-variable ..= .)) ((equal keys "a") (call-interactively ...)) ((equal keys "s") (call-int= eractively ...)) ((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-in= teractively ...)) ((equal keys "?") (org-tags-view nil "+FLAGGED") (org-add= -hook ... ... t t)) ((equal keys "L") (unless ... ...) (unless restriction = ... ...)) ((equal keys "#") (call-interactively ...)) ((equal keys "/") (ca= ll-interactively ...)) ((equal keys "!") (customize-variable ...)) (t (erro= r "Invalid agenda key"))) (let* ((prefix-descriptions nil) (org-agenda-window-setup ...) (org-agend= a-custom-commands-orig org-agenda-custom-commands) (org-agenda-custom-comma= nds ...) (buf ...) (bfn ...) entry key type match lprops ans) (unless org-a= genda-overriding-restriction (unless ... ...) (setq org-agenda-restrict nil= ) (move-marker org-agenda-restrict-begin nil) (move-marker org-agenda-restr= ict-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 l= props 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