| 
					
				 | 
			
			
				@@ -74,7 +74,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; TaskJugglerUI. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; * Resources 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-;;  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+;; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; Next you can define resources and assign those to work on specific 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; tasks. You can group your resources hierarchically. Tag the top 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; node of the resources with "taskjuggler_resource" (or whatever you 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -107,7 +107,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; etc for tasks. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; * Dependencies 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-;;  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+;; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; The exporter will handle dependencies that are defined in the tasks 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; either with the ORDERED attribute (see TODO dependencies in the Org 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; mode manual) or with the BLOCKER attribute (see org-depend.el) or 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -137,7 +137,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;;   :Effort:   2.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;;   :BLOCKER:  training_material { gapduration 1d } some_other_task 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;;   :END: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-;;  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+;; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;;;; * TODO 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;;   - Use SCHEDULED and DEADLINE information (not just start and end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;;     properties). 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -181,6 +181,11 @@ resources for the project." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   :group 'org-export-taskjuggler 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   :type 'string) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+(defcustom org-export-taskjuggler-target-version 2.4 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  "Which version of TaskJuggler the exporter is targeting." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  :group 'org-export-taskjuggler 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  :type 'number) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defcustom org-export-taskjuggler-default-project-version "1.0" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "Default version string for the project." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   :group 'org-export-taskjuggler 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -193,7 +198,7 @@ with `org-export-taskjuggler-project-tag'" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   :group 'org-export-taskjuggler 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   :type 'integer) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-(defcustom org-export-taskjuggler-default-reports  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+(defcustom org-export-taskjuggler-default-reports 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   '("taskreport \"Gantt Chart\" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   headline \"Project Gantt Chart\" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   columns hierarchindex, name, start, end, effort, duration, completed, chart 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -212,7 +217,7 @@ with `org-export-taskjuggler-project-tag'" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   :group 'org-export-taskjuggler 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   :type '(repeat (string :tag "Report"))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-(defcustom org-export-taskjuggler-default-global-properties  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+(defcustom org-export-taskjuggler-default-global-properties 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "shift s40 \"Part time shift\" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   workinghours wed, thu, fri off 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -221,7 +226,7 @@ with `org-export-taskjuggler-project-tag'" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 define global properties such as shifts, accounts, rates, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 vacation, macros and flags. Any property that is allowed within 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 the TaskJuggler file can be inserted. You could for example 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-include another TaskJuggler file.  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+include another TaskJuggler file. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 The global properties are inserted after the project declaration 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 but before any resource and task declarations." 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -257,14 +262,15 @@ defined in `org-export-taskjuggler-default-reports'." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (setq-default org-done-keywords org-done-keywords) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (let* ((tasks 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (org-taskjuggler-resolve-dependencies 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	   (org-taskjuggler-assign-task-ids  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	    (org-map-entries  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	     '(org-taskjuggler-components)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	     org-export-taskjuggler-project-tag nil 'archive 'comment)))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	   (org-taskjuggler-assign-task-ids 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	    (org-taskjuggler-compute-task-leafiness 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	     (org-map-entries 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	      '(org-taskjuggler-components) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	      org-export-taskjuggler-project-tag nil 'archive 'comment))))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 (resources 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (org-taskjuggler-assign-resource-ids 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	   (org-map-entries  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	    '(org-taskjuggler-components)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	   (org-map-entries 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	    '(org-taskjuggler-components) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	    org-export-taskjuggler-resource-tag nil 'archive 'comment))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 (filename (expand-file-name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		    (concat 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -278,9 +284,9 @@ defined in `org-export-taskjuggler-default-reports'." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (error "No tasks specified")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ;; add a default resource 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (unless resources 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (setq resources  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	    `((("resource_id" . ,(user-login-name))  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	       ("headline" . ,user-full-name)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (setq resources 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	    `((("resource_id" . ,(user-login-name)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	       ("headline" . ,user-full-name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	       ("level" . 1))))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ;; add a default allocation to the first task if none was given 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (unless (assoc "allocate" (car tasks)) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -331,6 +337,10 @@ with the TaskJuggler GUI." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 (command (concat process-name " " file-name))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (start-process-shell-command process-name nil command))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+(defun org-taskjuggler-targeting-tj3-p () 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  "Return true if we are targeting TaskJuggler III." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (>= org-export-taskjuggler-target-version 3.0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defun org-taskjuggler-parent-is-ordered-p () 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "Return true if the parent of the current node has a property 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 \"ORDERED\". Return nil otherwise." 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -344,7 +354,9 @@ information, all the properties, etc." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (let* ((props (org-entry-properties)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 (components (org-heading-components)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 (level (nth 1 components)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 (headline (nth 4 components)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 (headline  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	  (replace-regexp-in-string  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	   "\"" "\\\"" (nth 4 components) t t)) ; quote double quotes in headlines 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 (parent-ordered (org-taskjuggler-parent-is-ordered-p))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (push (cons "level" level) props) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (push (cons "headline" headline) props) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -362,16 +374,16 @@ a path to the current task." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (dolist (task tasks resolved-tasks) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (let ((level (cdr (assoc "level" task)))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(cond 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 ((< previous-level level)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 ((< previous-level level) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (setq unique-id (org-taskjuggler-get-unique-id task (car unique-ids))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (dotimes (tmp (- level previous-level)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	    (push (list unique-id) unique-ids) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	    (push unique-id path))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 ((= previous-level level)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 ((= previous-level level) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (setq unique-id (org-taskjuggler-get-unique-id task (car unique-ids))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (push unique-id (car unique-ids)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (setcar path unique-id)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 ((> previous-level level)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 ((> previous-level level) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (dotimes (tmp (- previous-level level)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	    (pop unique-ids) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	    (pop path)) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -383,17 +395,37 @@ a path to the current task." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(setq previous-level level) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(setq resolved-tasks (append resolved-tasks (list task))))))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-(defun org-taskjuggler-assign-resource-ids (resources &optional unique-ids) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+(defun org-taskjuggler-compute-task-leafiness (tasks) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  "Figure out if each task is a leaf by looking at it's level, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+and the level of its successor. If the successor is higher (ie 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+deeper), then it's not a leaf." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (let (new-list) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (while (car tasks) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (let ((task (car tasks)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	    (successor (car (cdr tasks)))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(cond 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 ;; if a task has no successors it is a leaf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 ((null successor)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	  (push (cons (cons "leaf-node" t) task) new-list)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 ;; if the successor has a lower level than task it is a leaf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 ((<= (cdr (assoc "level" successor)) (cdr (assoc "level" task)))  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	  (push (cons (cons "leaf-node" t) task) new-list)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 ;; otherwise examine the rest of the tasks 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 (t (push task new-list)))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (setq tasks (cdr tasks))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (nreverse new-list))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+(defun org-taskjuggler-assign-resource-ids (resources) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "Given a list of resources return the same list, assigning a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 unique id to each resource." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (cond 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    ((null resources) nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-   (t  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   (t 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (let* ((resource (car resources)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	   (unique-id (org-taskjuggler-get-unique-id resource unique-ids))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (push (cons "unique-id" unique-id) resource) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (cons resource  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	    (org-taskjuggler-assign-resource-ids (cdr resources)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (cons resource 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	    (org-taskjuggler-assign-resource-ids (cdr resources) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 						 (cons unique-id unique-ids))))))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defun org-taskjuggler-resolve-dependencies (tasks) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -405,24 +437,24 @@ unique id to each resource." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	     (depends (cdr (assoc "depends" task))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	     (parent-ordered (cdr (assoc "parent-ordered" task))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	     (blocker (cdr (assoc "BLOCKER" task))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	     (blocked-on-previous  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	     (blocked-on-previous 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	      (and blocker (string-match "previous-sibling" blocker))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	     (dependencies 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	      (org-taskjuggler-resolve-explicit-dependencies 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	       (append  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	       (append 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		(and depends (org-taskjuggler-tokenize-dependencies depends)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		(and blocker (org-taskjuggler-tokenize-dependencies blocker)))  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		(and blocker (org-taskjuggler-tokenize-dependencies blocker))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	       tasks)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	      previous-sibling) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	; update previous sibling info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(cond 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 ((< previous-level level)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 ((< previous-level level) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (dotimes (tmp (- level previous-level)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	    (push task siblings))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 ((= previous-level level) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (setq previous-sibling (car siblings)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (setcar siblings task)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 ((> previous-level level)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 ((> previous-level level) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (dotimes (tmp (- previous-level level)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	    (pop siblings)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (setq previous-sibling (car siblings)) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -432,7 +464,7 @@ unique id to each resource." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(when (or (and previous-sibling parent-ordered) blocked-on-previous) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (push (format "!%s" (cdr (assoc "unique-id" previous-sibling))) dependencies)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	; store dependency information 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	(when dependencies  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(when dependencies 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (push (cons "depends" (mapconcat 'identity dependencies ", ")) task)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(setq previous-level level) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(setq resolved-tasks (append resolved-tasks (list task))))))) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -442,10 +474,10 @@ unique id to each resource." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 individual dependencies and return them as a list while keeping 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 the optional arguments (such as gapduration) for the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 dependencies. A dependency will have to match `[-a-zA-Z0-9_]+'." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  (cond  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (cond 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    ((string-match "^ *$" dependencies) nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    ((string-match "^[ \t]*\\([-a-zA-Z0-9_]+\\([ \t]*{[^}]+}\\)?\\)[ \t,]*" dependencies) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    (cons  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (cons 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      (substring dependencies (match-beginning 1) (match-end 1)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      (org-taskjuggler-tokenize-dependencies (substring dependencies (match-end 0))))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    (t (error (format "invalid dependency id %s" dependencies))))) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -459,27 +491,27 @@ where a matching tasks was found. If the dependency is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 `org-taskjuggler-resolve-dependencies'). If there is no matching 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 task the dependency is ignored and a warning is displayed ." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (unless (null dependencies) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    (let*  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (let* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	;; the dependency might have optional attributes such as "{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	;; gapduration 5d }", so only use the first string as id for the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	;; dependency 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	((dependency (car dependencies)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 (id (car (split-string dependency))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 (optional-attributes  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 (optional-attributes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (mapconcat 'identity (cdr (split-string dependency)) " ")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 (path (org-taskjuggler-find-task-with-id id tasks))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (cond  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (cond 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        ;; ignore previous sibling dependencies 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        ((equal (car dependencies) "previous-sibling") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(org-taskjuggler-resolve-explicit-dependencies (cdr dependencies) tasks)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        ;; if the id is found in another task use its path 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       ((not (null path))  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       ((not (null path)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(cons (mapconcat 'identity (list path optional-attributes) " ") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	      (org-taskjuggler-resolve-explicit-dependencies  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	      (org-taskjuggler-resolve-explicit-dependencies 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	       (cdr dependencies) tasks))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        ;; warn about dangling dependency but otherwise ignore it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       (t (display-warning  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	   'org-export-taskjuggler  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       (t (display-warning 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	   'org-export-taskjuggler 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	   (format "No task with matching property \"task_id\" found for id %s" id)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (org-taskjuggler-resolve-explicit-dependencies (cdr dependencies) tasks)))))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -488,7 +520,7 @@ task the dependency is ignored and a warning is displayed ." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 return nil." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (let ((task-id (cdr (assoc "task_id" (car tasks)))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(path (cdr (assoc "path" (car tasks))))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    (cond  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (cond 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      ((null tasks) nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      ((equal task-id id) path) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      (t (org-taskjuggler-find-task-with-id id (cdr tasks)))))) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -509,7 +541,7 @@ finally add more underscore characters (\"_\")." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (while (member id unique-ids) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (setq id (concat id "_"))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     id)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defun org-taskjuggler-clean-id (id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "Clean and return ID to make it acceptable for taskjuggler." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (and id (replace-regexp-in-string "[^a-zA-Z0-9_]" "_" id))) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -524,7 +556,7 @@ specified it is calculated 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(version (cdr (assoc "version" project))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(start (cdr (assoc "start" project))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(end (cdr (assoc "end" project)))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    (insert  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (insert 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      (format "project %s \"%s\" \"%s\" %s +%sd {\n }\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	     unique-id headline version start 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	     org-export-taskjuggler-default-project-duration)))) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -534,16 +566,16 @@ specified it is calculated 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 with separator \"\n\"." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (let ((filtered-items (remq nil items))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (and filtered-items (mapconcat 'identity filtered-items "\n")))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defun org-taskjuggler-get-attributes (item attributes) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "Return all attribute as a single formated string. ITEM is an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 alist representing either a resource or a task. ATTRIBUTES is a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 list of symbols. Only entries from ITEM are considered that are 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 listed in ATTRIBUTES." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  (org-taskjuggler-filter-and-join  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (org-taskjuggler-filter-and-join 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    (mapcar 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    (lambda (attribute)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (org-taskjuggler-filter-and-join  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (lambda (attribute) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (org-taskjuggler-filter-and-join 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        (org-taskjuggler-get-attribute item attribute))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     attributes))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -551,7 +583,7 @@ listed in ATTRIBUTES." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "Return a list of strings containing the properly formatted 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 taskjuggler declaration for a given ATTRIBUTE in ITEM (an alist). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 If the ATTRIBUTE is not in ITEM return nil." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  (cond  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (cond 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    ((null item) nil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    ((equal (symbol-name attribute) (car (car item))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (cons (format "%s %s" (symbol-name attribute) (cdr (car item))) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -565,14 +597,14 @@ defines a property \"resource_id\" it will be used as the id for 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 this resource. Otherwise it will use the ID property. If neither 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 is defined it will calculate a unique id for the resource using 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 `org-taskjuggler-get-unique-id'." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  (let ((id (org-taskjuggler-clean-id  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	     (or (cdr (assoc "resource_id" resource))  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		 (cdr (assoc "ID" resource))  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (let ((id (org-taskjuggler-clean-id 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	     (or (cdr (assoc "resource_id" resource)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 (cdr (assoc "ID" resource)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		 (cdr (assoc "unique-id" resource))))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(headline (cdr (assoc "headline" resource))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(attributes '(limits vacation shift booking efficiency journalentry rate))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    (insert  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     (concat  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (insert 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     (concat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       "resource " id " \"" headline "\" {\n " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (org-taskjuggler-get-attributes resource attributes) "\n")))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -584,9 +616,9 @@ Otherwise if it contains something like 3.0 it is assumed to be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 days and will be translated into 3.0d. Other formats that 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 taskjuggler supports (like weeks, months and years) are currently 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 not supported." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  (cond  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (cond 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    ((null effort) effort) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-   ((string-match "\\([0-9]+\\):\\([0-9]+\\)" effort)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   ((string-match "\\([0-9]+\\):\\([0-9]+\\)" effort) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (let ((hours (string-to-number (match-string 1 effort))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (minutes (string-to-number (match-string 2 effort)))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (format "%dh" (+ hours (/ minutes 60.0))))) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -596,7 +628,7 @@ not supported." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defun org-taskjuggler-get-priority (priority) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   "Return a priority between 1 and 1000 based on PRIORITY, an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 org-mode priority string." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  (max 1 (/ (* 1000 (- org-lowest-priority (string-to-char priority)))  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (max 1 (/ (* 1000 (- org-lowest-priority (string-to-char priority))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	    (- org-lowest-priority org-highest-priority)))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defun org-taskjuggler-open-task (task) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -608,31 +640,41 @@ org-mode priority string." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(priority-raw (cdr (assoc "PRIORITY" task))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(priority (and priority-raw (org-taskjuggler-get-priority priority-raw))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(state (cdr (assoc "TODO" task))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	(complete (or (and (member state org-done-keywords) "100")  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(complete (or (and (member state org-done-keywords) "100") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		      (cdr (assoc "complete" task)))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(parent-ordered (cdr (assoc "parent-ordered" task))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(previous-sibling (cdr (assoc "previous-sibling" task))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	(attributes  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(milestone (or (cdr (assoc "milestone" task)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		       (and (assoc "leaf-node" task) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			    (not (or effort 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				     (cdr (assoc "duration" task)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				     (cdr (assoc "end" task)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				     (cdr (assoc "period" task))))))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(attributes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 '(account start note duration endbuffer endcredit end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	   flags journalentry length maxend maxstart milestone 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	   minend minstart period reference responsible 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	   scheduling startbuffer startcredit statusnote))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	   flags journalentry length maxend maxstart minend 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	   minstart period reference responsible scheduling 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	   startbuffer startcredit statusnote))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (insert 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     (concat  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      "task " unique-id " \"" headline "\" {\n"  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     (concat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      "task " unique-id " \"" headline "\" {\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (if (and parent-ordered previous-sibling) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (format " depends %s\n" previous-sibling) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(and depends (format " depends %s\n" depends))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (and allocate (format " purge allocations\n allocate %s\n" allocate)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (and allocate (format " purge %s\n allocate %s\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			    (or (and (org-taskjuggler-targeting-tj3-p) "allocations") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				"allocate") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			    allocate)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (and complete (format " complete %s\n" complete)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (and effort (format " effort %s\n" effort)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (and priority (format " priority %s\n" priority)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (and milestone (format " milestone\n")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (org-taskjuggler-get-attributes task attributes) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       "\n")))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defun org-taskjuggler-close-maybe (level) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  (while (> org-export-taskjuggler-old-level level)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (while (> org-export-taskjuggler-old-level level) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (insert "}\n") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (setq org-export-taskjuggler-old-level (1- org-export-taskjuggler-old-level))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (when (= org-export-taskjuggler-old-level level) 
			 |