Forgive the self reply, but I just made a change which makes the code much more pleasant. The matching functions are bound internally during matching, so instead of:
(org-agenda-ng--agenda :files org-agenda-files :pred (lambda () (and (org-agenda-ng--todo-p) (or (org-agenda-ng--date-p :deadline '<= (org-today)) (org-agenda-ng--date-p :scheduled '<= (org-today))) (not (apply #'org-agenda-ng--todo-p org-done-keywords-for-agenda))))) You can write: (org-agenda-ng--agenda :files org-agenda-files :pred (lambda () (and (todo) (or (date :deadline '<= (org-today)) (date :scheduled '<= (org-today))) (not (apply #'todo org-done-keywords-for-agenda))))) Or: (org-agenda-ng--agenda :files org-agenda-files :any `((date :date <= ,(org-today)) (date :deadline <= ,(+ org-deadline-warning-days (org-today))) (date :scheduled <= ,(org-today))) :none `((apply todo ,org-done-keywords))) This makes the syntax much more pleasant and readable, I think. I also profiled the code, and its performance seems good.