Search code examples
emacsorg-mode

Org mode agenda: Reuse code in block agenda


I have an org-agenda-custom-commands like so:

("u" "Unscheduled TODO"
           todo ""
           ((org-agenda-overriding-header "\nUnscheduled TODO")
           (org-agenda-skip-function '(org-agenda-skip-entry-if
                                              'scheduled 'deadline 'timestamp
                                              'todo '("BACKBURNER")))))

I would like to reuse the todo part of this agenda view in other block agenda views. So for instance defining an unscheduled-todo list for reuse (pseudocode, not working):

(setq unscheduled-todo '((org-agenda-overriding-header "\nUnscheduled TODO")
                           (org-agenda-skip-function '(org-agenda-skip-entry-if
                                                       'scheduled 'deadline 'timestamp
                                                       'todo '("BACKBURNER")))))
(setq org-agenda-custom-commands
        '(("u" "Unscheduled TODO"
            (todo "" unscheduled-todo))
          ("c" "Complete View"
            ((agenda "")
             (todo "" unscheduled-todo))))

How do I get the above code to work? I think I have a fundamental misunderstanding of how and when the code and lists are getting evaluated. I've tried a number of configurations of ' and () in both setq and org-agenda-custom-commands, along with append to create lists, but I'd also like to understand what's going on here.


Solution

  • Here's an implementation along the lines of my comment (although I think you really don't need a macro here: a function does just as well or better):

    (defun unscheduled-todo ()
        '((org-agenda-overriding-header "\nUnscheduled TODO")
          (org-agenda-skip-function '(org-agenda-skip-entry-if
                                      'scheduled 'deadline 'timestamp
                                      'todo '("BACKBURNER")))))
    
    (setq org-agenda-custom-commands
          ; N.B. the character following this comment is a *backquote* 
          ; (the key to the left of the 1 key on a standard US keyboard);
          ; it is *NOT* a quote (the key to the left of the ENTER key
          ; on a standard US keyboard).
          `(("u" "Unscheduled TODO"
             todo "" ,(unscheduled-todo))
            ("c" "Complete View"
                ((agenda "")
                 (todo "" ,(unscheduled-todo))))))
    
    

    I hope it's correct now (I had to fix it a couple of bugs) but it's only lightly tested.

    Note that this uses the backquote mechanism to quote most of the value in the setq of org-agenda-custom-commands while allowing the evaluation of the call to the macro using the comma mechanism.

    EDIT: As @Rorschach points out in a (now deleted) comment, I'm overcomplicating things. You still need backquote and comma, but you can use the variable you defined:

    (setq unscheduled-todo
        '((org-agenda-overriding-header "\nUnscheduled TODO")
          (org-agenda-skip-function '(org-agenda-skip-entry-if
                                      'scheduled 'deadline 'timestamp
                                      'todo '("BACKBURNER")))))
    
    (setq org-agenda-custom-commands
          ; N.B. the character following this comment is a *backquote* 
          ; (the key to the left of the 1 key on a standard US keyboard);
          ; it is *NOT* a quote (the key to the left of the ENTER key
          ; on a standard US keyboard).
          `(("u" "Unscheduled TODO"
             todo "" ,unscheduled-todo)
            ("c" "Complete View"
                ((agenda "")
                 (todo "" ,unscheduled-todo)))))
    
    

    The backquote/comma mechanism allows the evaluation of a spliced-in variable just as well as it allows the evaluation of a spliced-in function call.