0

According to the org agenda docs, I should be able to set a custom local option for a given agenda command. In this case, I want to set a custom org-agenda-files variable, which is an explicit example given by the docs:

(setq org-agenda-custom-commands 
  '(("c" "Desk Work" tags-todo "computer" ;; (1) (2) (3) (4)
     ((org-agenda-files '("~/org/widgets.org" "~/org/clients.org")) ;; (5)
      (org-agenda-sorting-strategy '(priority-up effort-down))) ;; (5) cont.
     ("~/computer.html")) ;; (6)
    ;; ...other commands here
    ))

However, when I try this, it doesn't work. My main org-agenda-files is a recursive directory with thousands of org files, and all are being presented in my org-agenda-custom-command despite me trying to set the org-agenda-files for the given command. I suspect the issue is some misunderstanding I have about lisp syntax. I've tried the following:

At the top of my config is

  (setq org-agenda-files
    (directory-files-recursively "~/Dropbox/org" "\\.org$")
    )

Which works properly. I've tried configuring:

  (add-to-list 'org-agenda-custom-commands
        `("dd" "Daily Agenda"
          (
           (org-agenda-files '(seq-filter (lambda(x) (not (string-match "/notes/"(file-name-directory x))))
                (directory-files-recursively "~/Dropbox/org" "\\.org$")
                ))
           (agenda ""
                   (
                    (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
                    (org-agenda-span 'day)
                    (org-deadline-warning-days 5)
                    (org-super-agenda-groups
                     '((:auto-category t :time-grid t))))))))

This custom command included the files in /notes/.

  (add-to-list 'org-agenda-custom-commands
        `("dd" "Daily Agenda"
          (
           (agenda ""
                   (seq-filter (lambda(x) (not (string-match "/notes/"(file-name-directory x))))
                (directory-files-recursively "~/Dropbox/org" "\\.org$")
                ))
                   (
                    (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
                    (org-agenda-span 'day)
                    (org-deadline-warning-days 5)
                    (org-super-agenda-groups
                     '((:auto-category t :time-grid t))))))))

This custom command included the files in /notes/.

(add-to-list 'org-agenda-custom-commands
        `("dd" "Daily Agenda"
          (
           (agenda ""
                   (
                    (org-agenda-files (seq-filter (lambda(x) (not (string-match "/notes/"(file-name-directory x))))
                (directory-files-recursively "~/Dropbox/org" "\\.org$")
                ))
                    (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
                    (org-agenda-span 'day)
                    (org-deadline-warning-days 5)
                    (org-super-agenda-groups
                     '((:auto-category t :time-grid t))))))))

This custom command included the files in /notes/, and is the one I think most matches the syntax given by the example.

I struggle with lisp syntax and putting things in the right spot, but I'm very confused why this isn't working.

What's the proper way to set a custom variable like org-agenda-files for a org-agenda-custom-command?

Caleb Jay
  • 239
  • 2
  • 12
  • 1
    A good recommendation from the Org manual about `org-agenda-custom-commands`: "As you see, the values and parentheses setting is a little complex. When in doubt, use the customize interface to set this variable—it fully supports its structure." – gusbrs Mar 15 '22 at 12:49
  • I will try that today, however I'm hoping to update my config file afterwards, and I'm not sure how to extract the result of using the customize interface. I use emacs on several machines throughout the week, and prefer to update and maintain just one config location. – Caleb Jay Mar 16 '22 at 02:42
  • 1
    You can save the customizations in the customize interface (with the usual C-x C-s), and then later copy the variable and its value to a regular `setq`, if you prefer. I sometimes do that. I personally set `custom-file` to something "not on my init.el", don't load it, but have it at hand for one or another occasion like that. I can thus save something from the customize interface to make sure the syntax is correct and, when I'm happy with the value, I just copy the result to my init file. – gusbrs Mar 16 '22 at 03:08
  • I tried the setup from the first link. It works fine, limiting itself to the two files that are specified as `org-agenda-files` in the command. Let's hope that the customization interface, as @gusbrs suggested, helps you untangle the forest of parentheses successfully. – NickD Mar 17 '22 at 03:23
  • I got the same issue. If I use `(setq org-agenda-files (list "~/Notebooks/org"))` then the local `org-agenda-files` in `org-agenda-custom-commands` works. But if I use `(add-hook 'org-mode-hook 'my-agenda-file-func)`, where `my-agenda-file-func` is a func to get the file list after some filtering, then `org-agenda-custom-commands` does not respect local `org-agenda-files`. – Jason Mar 17 '22 at 05:22
  • **UPDATE** myself: I think my issue is: (a) should not use `(add-hook 'org-mode-hook 'my-agenda-file-func)`, just use `setq`. (b) I have a custem variable set in `init.el` that is conflicting, similar to [this](https://emacs.stackexchange.com/q/9971/26737). – Jason Mar 17 '22 at 06:18
  • 1
    Please consider update your question? I don't see any `/notes/` in your last two code snippets. – Tianshu Wang Mar 17 '22 at 13:00
  • Thanks, Tianshu, you're correct. – Caleb Jay Mar 17 '22 at 13:14

1 Answers1

1

Try the following - I have not tested it much to make sure that it works as you want, but it at least works well enough to produce an agenda. The main thing I did is I formatted the custom command to conform to the description in the doc string of org-agenda-custom-commands and added comments to the various elements of the structure:

(add-to-list 'org-agenda-custom-commands
    `("dd"                     ;key
      "Daily Agenda"           ;description
      agenda                   ;type
      ""                       ;match - empty string for agenda type
      ;; local settings
      ((org-agenda-files (seq-filter
                            (lambda(x)
                               (not (string-match "/notes/"(file-name-directory x))))
                            (directory-files-recursively "~/Dropbox/org" "\\.org$")))
       (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
       (org-agenda-span 'day)
       (org-deadline-warning-days 5)
       (org-super-agenda-groups '((:auto-category t :time-grid t))))))

Try it out and make sure it does not produce any errors. Then start the more arduous process of checking whether it does what you want and fixing it as necessary. You might find it easier to check if you test your filter separately: evaluate it in the *scratch* buffer and make sure that the list of files you get is the one you expect.

Note that because of the "dd" key, you get a two-level menu: C-c a gets you the agenda menu, a d gets you to the second level menu and another d executes the command. The two-level structure is probably not useful here, but the page you linked to has an example of how to have a whole bunch of second-level commands under a given prefix ("d" in this example).

NickD
  • 27,023
  • 3
  • 23
  • 42