Ihor Radchenko <[email protected]> writes: > Björn Kettunen <[email protected]> writes: > >> The only thing I would love is if it's possible to make this optionally >> behave like file-with-archives but for a list of files. >> >> My motivation with this patch is that I can track the time of a list of >> various agenda files that I use for work. I don't want that the tracked >> time in the table change if a task is archived. > > Then, you can additionally introduce something like > (file-with-archives "file1" "file2" ...). If you want to implement such > feature, it is probably best to combine this patch and the extra addition.
Thats's a good I think I have a patch. How is the multifile parameter supposed be handled in such an instance? I made it so that in case the parameter was consp that it uses the multifile parameter. Ideally I would like that similar to single file-with-archices that archive and the their files are shown as one file. But not sure how to do that. With the current patch now the archive handling is moved to be done after the files have been expanded so it's just called once for all cases. The side effect is that if a user uses a function it can now also return the scope and let org-mode expand the returned scope if it isn't already expanded. The updated patch is below:
>From 30cadf1c23ec70775103e8edb592770b8ef84a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kettunen?= <[email protected]> Date: Tue, 3 Mar 2026 22:47:12 +0200 Subject: [PATCH 1/2] org-clock: clock-report be able to also take directories * lisp/org-clock.el (org-dblock-write:clocktable): Expand files in directories if any of the entries in scope is a directory. Just like in org-agenda-files. * lisp/org.el (org-file-list-expand): (org-agenda-files): Refactor file expansion into separate function. * doc/org-manual.org: Document. * etc/ORG-NEWS: Announce --- doc/org-manual.org | 2 +- etc/ORG-NEWS | 9 +++++++++ lisp/org-clock.el | 45 +++++++++++++++++++++++++++------------------ lisp/org.el | 20 +++++++++++++------- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/doc/org-manual.org b/doc/org-manual.org index 9c4c27877..cfcf8994b 100644 --- a/doc/org-manual.org +++ b/doc/org-manual.org @@ -7109,7 +7109,7 @@ *** The clock table | =treeN= | the surrounding level N tree, for example =tree3= | | =tree= | the surrounding level 1 tree | | =agenda= | all agenda files | - | =("file" ...)= | scan these files | + | =("file" "dir" "...)= | scan these files or files in directories | | =FUNCTION= | scan files returned by calling {{{var(FUNCTION)}}} with no argument | | =file-with-archives= | current file and its archives | | =agenda-with-archives= | all agenda files, including archives | diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 40fa1e6aa..ca18ab041 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -40,6 +40,11 @@ into a "Tags" section and a "Priorities" section. Priorities can now be increased, decreased, set to the default, and set interactively from the priority context menus. +*** Clocktable option =:scope (file)= list of files can now also include directories + +The scope option can now also include directories in the list of files. +Files are resolved just like in ~org-agenda-files~. + ** New and changed options # Changes dealing with changing default values of customizations, @@ -60,6 +65,10 @@ variable. Given the completed and total number of tasks, format the percent cookie =[N%]=. +*** New function ~org-agenda-directory-files-recursively~ + +Expand list of flies according to ~org-agenda-file-regexp~. + ** Removed or renamed functions and variables ** Miscellaneous diff --git a/lisp/org-clock.el b/lisp/org-clock.el index ce2d23a9b..8b5cf64aa 100644 --- a/lisp/org-clock.el +++ b/lisp/org-clock.el @@ -2677,22 +2677,20 @@ (defun org-dblock-write:clocktable (params) (catch 'exit (let* ((scope (plist-get params :scope)) (base-buffer (org-base-buffer (current-buffer))) + (scope (or (and (functionp scope) + (funcall scope)) + scope)) (files (pcase scope - (`agenda + ((or `agenda `agenda-with-archives) (org-agenda-files t)) - (`agenda-with-archives - (org-add-archive-files (org-agenda-files t))) - (`file-with-archives - (let ((base-file (buffer-file-name base-buffer))) - (and base-file - (org-add-archive-files (list base-file))))) - ((or `nil `file `subtree `tree + ((or `nil `file `subtree `tree `file-with-archives (and (pred symbolp) + (pred (not symbolp)) (guard (string-match "\\`tree\\([0-9]+\\)\\'" (symbol-name scope))))) base-buffer) - ((pred functionp) (funcall scope)) ((pred consp) scope) + ((pred stringp) scope) ;; To not break previous function calls here (_ (user-error "Unknown scope: %S" scope)))) (block (plist-get params :block)) (ts (plist-get params :tstart)) @@ -2704,7 +2702,25 @@ (defun org-dblock-write:clocktable (params) (formatter (or (plist-get params :formatter) org-clock-clocktable-formatter 'org-clocktable-write-default)) - cc) + (multifile + ;; Even though `file-with-archives' can consist of + ;; multiple files, we consider this is one extended file + ;; instead. + (and (not hide-files) + (consp files) + (not (eq scope 'file-with-archives)))) + cc) + + (when (consp files) + (when-let* ((cons-scope (car files)) + (cons-scope (and (symbolp cons-scope) + cons-scope))) + (setq scope cons-scope) + (setq files (cdr files))) + (setq files (org-agenda-directory-files-recursively files))) + (pcase scope ((or `agenda-with-archives `file-with-archives) + (setq files (org-add-archive-files files)))) + ;; Check if we need to do steps (when block ;; Get the range text for the header @@ -2750,14 +2766,7 @@ (defun org-dblock-write:clocktable (params) level) (throw 'exit nil)))) (org-narrow-to-subtree)))) - (list (org-clock-get-table-data nil params))))) - (multifile - ;; Even though `file-with-archives' can consist of - ;; multiple files, we consider this is one extended file - ;; instead. - (and (not hide-files) - (consp files) - (not (eq scope 'file-with-archives))))) + (list (org-clock-get-table-data nil params)))))) (funcall formatter origin diff --git a/lisp/org.el b/lisp/org.el index fc51d4ba3..05607bd2c 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -15977,6 +15977,18 @@ (defun org-switchb (&optional arg) (mapcar #'list (mapcar #'buffer-name blist)) nil t)))) + +(defun org-agenda-directory-files-recursively (files) + "Expand list of FILES according to `org-agenda-file-regexp'." + (apply 'append + (mapcar (lambda (f) + (if (file-directory-p f) + (directory-files + f t org-agenda-file-regexp) + (list (expand-file-name f org-directory)))) + files))) + + (defun org-agenda-files (&optional unrestricted archives) "Get the list of agenda files. Optional UNRESTRICTED means return the full list even if a restriction @@ -15990,13 +16002,7 @@ (defun org-agenda-files (&optional unrestricted archives) ((stringp org-agenda-files) (org-read-agenda-file-list)) ((listp org-agenda-files) org-agenda-files) (t (error "Invalid value of `org-agenda-files'"))))) - (setq files (apply 'append - (mapcar (lambda (f) - (if (file-directory-p f) - (directory-files - f t org-agenda-file-regexp) - (list (expand-file-name f org-directory)))) - files))) + (setq files (org-agenda-directory-files-recursively files)) (when org-agenda-skip-unavailable-files (setq files (delq nil (mapcar (lambda (file) -- 2.53.0
