emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/org-contrib 8e32471fc8: ox-taskjuggler.el: Update


From: ELPA Syncer
Subject: [nongnu] elpa/org-contrib 8e32471fc8: ox-taskjuggler.el: Update
Date: Wed, 15 May 2024 13:00:25 -0400 (EDT)

branch: elpa/org-contrib
commit 8e32471fc8d7b4edc07e416488e55f0f33c86f23
Author: Harold Ollivier <holl@mailbox.org>
Commit: Bastien Guerry <bzg@gnu.org>

    ox-taskjuggler.el: Update
    
    * lisp/ox-taskjuggler.el (org-taskjuggler-report-tag): New option.
    (org-taskjuggler-valid-resource-attributes): New argument.
    (org-taskjuggler-valid-account-attributes): New option.
    (org-taskjuggler-valid-report-attributes): New arguments.
    (org-taskjuggler-assign-account-ids): New function.
    (org-taskjuggler-get-end): Use `org-taskjuggler-valid-task-attributes'.
    (org-taskjuggler-project-plan): Use `org-taskjuggler-account-tag'.
    (org-taskjuggler-project-plan): Rewrite.
    (org-taskjuggler--build-account): New function.
    (org-taskjuggler--build-report): Update.
---
 lisp/ox-taskjuggler.el | 238 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 165 insertions(+), 73 deletions(-)

diff --git a/lisp/ox-taskjuggler.el b/lisp/ox-taskjuggler.el
index 4144685e1a..19e4da9d01 100644
--- a/lisp/ox-taskjuggler.el
+++ b/lisp/ox-taskjuggler.el
@@ -177,6 +177,13 @@ for the project."
   :group 'org-export-taskjuggler
   :type 'string)
 
+(defcustom org-taskjuggler-account-tag "taskjuggler_account"
+  "Tag marking project's accounts.
+This tag is used to find the tree containing all the accounts
+for the project."
+  :group 'org-export-taskjuggler
+  :type 'string)
+
 (defcustom org-taskjuggler-report-tag "taskjuggler_report"
   "Tag marking project's reports.
 This tag is used to find the tree containing all the reports for
@@ -330,16 +337,23 @@ list."
 
 (defcustom org-taskjuggler-valid-resource-attributes
   '(limits vacation shift booking efficiency journalentry rate
-          workinghours flags)
+          workinghours flags chargeset)
   "Valid attributes for Taskjuggler resources.
 If one of these appears as a property for a headline, it will be
 exported with the corresponding resource."
   :group 'org-export-taskjuggler
   :type '(repeat symbol))
 
+(defcustom org-taskjuggler-valid-account-attributes
+  '(aggregate credits flags)
+  "Valid attributes for Taskjuggler accounts.
+If one of these appears as a property for a headline, it will be
+exported with the corresponding account."
+  :group 'org-export-taskjuggler)
+
 (defcustom org-taskjuggler-valid-report-attributes
-  '(headline columns definitions timeformat hideresource hidetask
-            loadunit sorttasks formats period)
+  '(headline columns definitions timeformat hideaccount hideresource hidetask
+            loadunit sorttasks formats period start end)
   "Valid attributes for Taskjuggler reports.
 If one of these appears as a property for a headline, it will be
 exported with the corresponding report."
@@ -446,6 +460,19 @@ headlines and their associated ID."
           (cons resource id)))
       info)))
 
+(defun org-taskjuggler-assign-account-ids (accounts info)
+  "Assign a unique ID to each account within ACCOUNTS.
+ACCOUNTS is a list of headlines.  INFO is a plist used as a
+communication channel.  Return value is an alist between
+headlines and their associated ID."
+  (let (ids)
+    (org-element-map accounts 'headline
+      (lambda (account)
+        (let ((id (org-taskjuggler--build-unique-id account ids)))
+          (push id ids)
+          (cons account id)))
+      info)))
+
 
 
 ;;; Accessors
@@ -497,11 +524,10 @@ doesn't have any start date defined."
 ITEM is a headline.  Return value is a string or nil if ITEM
 doesn't have any end date defined."
   (let ((deadline (org-element-property :deadline item)))
-    (and deadline (funcall (eval-and-compile
-                            (if (fboundp 'org-format-timestamp)
-                                #'org-format-timestamp
-                              (with-no-warnings #'org-timestamp-format)))
-                          deadline "%Y-%02m-%02d"))))
+    (or
+     (and deadline (org-timestamp-format deadline "%Y-%02m-%02d"))
+     (and (memq 'end org-taskjuggler-valid-task-attributes)
+         (org-element-property :END item)))))
 
 
 
@@ -654,89 +680,115 @@ Return complete project plan as a string in TaskJuggler 
syntax."
      (org-taskjuggler--build-project project info)
      ;; 3. Insert global properties.
      (org-element-normalize-string org-taskjuggler-default-global-properties)
-     ;; 4. Insert resources.  Provide a default one if none is
+     ;; 3.5. Insert accounts.  Provide a default one if none is
      ;;    specified.
-     (let ((main-resources
+     (let ((main-accounts
             ;; Collect contents from various trees marked with
-            ;; `org-taskjuggler-resource-tag'.  Only gather top level
-            ;; resources.
+            ;; `org-taskjuggler-account-tag'.  Only gather top level
+            ;; accounts.
             (apply 'append
                    (org-element-map tree 'headline
                      (lambda (hl)
-                       (and (member org-taskjuggler-resource-tag
+                       (and (member org-taskjuggler-account-tag
                                     (org-export-get-tags hl info))
                             (org-element-map (org-element-contents hl) 
'headline
                               'identity info nil 'headline)))
                      info nil 'headline))))
-       ;; Assign a unique ID to each resource.  Store it under
+       ;; Assign a unique ID to each account.  Store it under
        ;; `:taskjuggler-unique-ids' property in INFO.
        (setq info
              (plist-put info :taskjuggler-unique-ids
-                        (org-taskjuggler-assign-resource-ids
-                         main-resources info)))
+                        (org-taskjuggler-assign-account-ids
+                         main-accounts info)))
        (concat
-        (if main-resources
+        (if main-accounts
             (mapconcat
-             (lambda (resource) (org-taskjuggler--build-resource resource 
info))
-             main-resources "")
-          (format "resource %s \"%s\" {\n}\n" (user-login-name) 
user-full-name))
-        ;; 5. Insert tasks.
-        (let ((main-tasks
-               ;; If `org-taskjuggler-keep-project-as-task' is
-               ;; non-nil, there is only one task.  Otherwise, every
-               ;; direct children of PROJECT is a top level task.
-               (if org-taskjuggler-keep-project-as-task (list project)
-                 (or (org-element-map (org-element-contents project) 'headline
-                       'identity info nil 'headline)
-                     (error "No task specified")))))
-          ;; Assign a unique ID to each task.  Add it to
-          ;; `:taskjuggler-unique-ids' property in INFO.
-          (setq info
-                (plist-put info :taskjuggler-unique-ids
-                           (append
-                            (org-taskjuggler-assign-task-ids main-tasks info)
-                            (plist-get info :taskjuggler-unique-ids))))
-          ;; If no resource is allocated among tasks, allocate one to
-          ;; the first task.
-          (unless (org-element-map main-tasks 'headline
-                    (lambda (task) (org-element-property :ALLOCATE task))
-                    info t)
-            (org-element-put-property
-             (car main-tasks) :ALLOCATE
-             (or (org-taskjuggler-get-id (car main-resources) info)
-                 (user-login-name))))
-          (mapconcat
-           (lambda (task) (org-taskjuggler--build-task task info))
-           main-tasks ""))
-        ;; 6. Insert reports.  If no report is defined, insert default
-        ;;    reports.
-        (let ((main-reports
+             (lambda (account) (org-taskjuggler--build-account account info))
+             main-accounts "")
+          (format "account %s \"%s\" {\n}\n" (user-login-name) user-full-name))
+        ;; 4. Insert resources.  Provide a default one if none is
+        ;;    specified.
+        (let ((main-resources
                ;; Collect contents from various trees marked with
-               ;; `org-taskjuggler-report-tag'.  Only gather top level
-               ;; reports.
+               ;; `org-taskjuggler-resource-tag'.  Only gather top level
+               ;; resources.
                (apply 'append
                       (org-element-map tree 'headline
                         (lambda (hl)
-                          (and (member org-taskjuggler-report-tag
+                          (and (member org-taskjuggler-resource-tag
                                        (org-export-get-tags hl info))
-                               (org-element-map (org-element-contents hl)
-                                   'headline 'identity info nil 'headline)))
+                               (org-element-map (org-element-contents hl) 
'headline
+                                 'identity info nil 'headline)))
                         info nil 'headline))))
-          (if main-reports
-              (mapconcat
-               (lambda (report) (org-taskjuggler--build-report report info))
-               main-reports "")
-           ;; insert title in default reports
-           (let* ((title (org-export-data (plist-get info :title) info))
-                  (report-title (if (string= title "")
-                                    (org-taskjuggler-get-name project)
-                                  title)))
-             (mapconcat
-              'org-element-normalize-string
-              (mapcar
-               (lambda (report)
-                 (replace-regexp-in-string "%title" report-title  report t t))
-               org-taskjuggler-default-reports) "")))))))))
+          ;; Assign a unique ID to each resource.  Store it under
+          ;; `:taskjuggler-unique-ids' property in INFO.
+          (setq info
+                (plist-put info :taskjuggler-unique-ids
+                           (org-taskjuggler-assign-resource-ids
+                            main-resources info)))
+          (concat
+           (if main-resources
+               (mapconcat
+                (lambda (resource) (org-taskjuggler--build-resource resource 
info))
+                main-resources "")
+             (format "resource %s \"%s\" {\n}\n" (user-login-name) 
user-full-name))
+           ;; 5. Insert tasks.
+           (let ((main-tasks
+                  ;; If `org-taskjuggler-keep-project-as-task' is
+                  ;; non-nil, there is only one task.  Otherwise, every
+                  ;; direct children of PROJECT is a top level task.
+                  (if org-taskjuggler-keep-project-as-task (list project)
+                    (or (org-element-map (org-element-contents project) 
'headline
+                          'identity info nil 'headline)
+                        (error "No task specified")))))
+             ;; Assign a unique ID to each task.  Add it to
+             ;; `:taskjuggler-unique-ids' property in INFO.
+             (setq info
+                   (plist-put info :taskjuggler-unique-ids
+                              (append
+                               (org-taskjuggler-assign-task-ids main-tasks 
info)
+                               (plist-get info :taskjuggler-unique-ids))))
+             ;; If no resource is allocated among tasks, allocate one to
+             ;; the first task.
+             (unless (org-element-map main-tasks 'headline
+                       (lambda (task) (org-element-property :ALLOCATE task))
+                       info t)
+               (org-element-put-property
+                (car main-tasks) :ALLOCATE
+                (or (org-taskjuggler-get-id (car main-resources) info)
+                    (user-login-name))))
+             (mapconcat
+              (lambda (task) (org-taskjuggler--build-task task info))
+              main-tasks ""))
+           ;; 6. Insert reports.  If no report is defined, insert default
+           ;;    reports.
+           (let ((main-reports
+                  ;; Collect contents from various trees marked with
+                  ;; `org-taskjuggler-report-tag'.  Only gather top level
+                  ;; reports.
+                  (apply 'append
+                         (org-element-map tree 'headline
+                           (lambda (hl)
+                             (and (member org-taskjuggler-report-tag
+                                          (org-export-get-tags hl info))
+                                  (org-element-map (org-element-contents hl)
+                                      'headline 'identity info nil 'headline)))
+                           info nil 'headline))))
+             (if main-reports
+                 (mapconcat
+                  (lambda (report) (org-taskjuggler--build-report report info))
+                  main-reports "")
+              ;; insert title in default reports
+              (let* ((title (org-export-data (plist-get info :title) info))
+                     (report-title (if (string= title "")
+                                       (org-taskjuggler-get-name project)
+                                     title)))
+                (mapconcat
+                 'org-element-normalize-string
+                 (mapcar
+                  (lambda (report)
+                    (replace-regexp-in-string "%title" report-title  report t 
t))
+                  org-taskjuggler-default-reports) "")))))))))))
 
 (defun org-taskjuggler--build-project (project info)
   "Return a project declaration.
@@ -799,20 +851,60 @@ neither is defined a unique id will be associated to it."
    ;; Closing resource.
    "}\n"))
 
+(defun org-taskjuggler--build-account (account info)
+  "Return a account declaration.
+
+ACCOUNT is a headline.  INFO is a plist used as a communication
+channel.
+
+All valid attributes from ACCOUNT are inserted.  If ACCOUNT
+defines a property \"account_id\" it will be used as the id for
+this account.  Otherwise it will use the ID property.  If
+neither is defined a unique id will be associated to it."
+  (concat
+   ;; Opening account.
+   (format "account %s \"%s\" {\n"
+           (org-taskjuggler--clean-id
+            (or (org-element-property :ACCOUNT_ID account)
+                (org-element-property :ID account)
+                (org-taskjuggler-get-id account info)))
+           (org-taskjuggler-get-name account))
+   ;; Add attributes.
+   (org-taskjuggler--indent-string
+    (org-taskjuggler--build-attributes
+     account org-taskjuggler-valid-account-attributes))
+   ;; Add inner accounts.
+   (org-taskjuggler--indent-string
+    (mapconcat
+     'identity
+     (org-element-map (org-element-contents account) 'headline
+       (lambda (hl) (org-taskjuggler--build-account hl info))
+       info nil 'headline)
+     ""))
+   ;; Closing account.
+   "}\n"))
+
 (defun org-taskjuggler--build-report (report info)
   "Return a report declaration.
 REPORT is a headline.  INFO is a plist used as a communication
 channel."
   (concat
    ;; Opening report.
-   (format "%s \"%s\" {\n"
+   (format "%s %s \"%s\" {\n"
            (or (org-element-property :REPORT_KIND report) "taskreport")
+           (or (org-element-property :REPORT_ID report)
+                (org-element-property :ID report)
+                (org-taskjuggler-get-id report info))
            (org-taskjuggler-get-name report))
    ;; Add attributes.
    (org-taskjuggler--indent-string
     (org-taskjuggler--build-attributes
      report org-taskjuggler-valid-report-attributes))
-   ;; Add inner reports.
+   ;; Add core of report, ie the first paragraph after the headline
+   ;; and before the next sub-headline
+   (format "%s" (if (eq (org-element-type (car (org-element-contents report))) 
'section)
+                    (org-element-interpret-data (car (org-element-contents 
report)))
+                  ""))
    (org-taskjuggler--indent-string
     (mapconcat
      'identity



reply via email to

[Prev in Thread] Current Thread [Next in Thread]