Merge branch 'master' of git+ssh://repo.or.cz/srv/git/org-mode
This commit is contained in:
commit
153f0241da
2
Makefile
2
Makefile
|
@ -107,6 +107,7 @@ LISPF = org.el \
|
|||
org-rmail.el \
|
||||
org-src.el \
|
||||
org-table.el \
|
||||
org-taskjuggler.el \
|
||||
org-timer.el \
|
||||
org-vm.el \
|
||||
org-w3m.el \
|
||||
|
@ -388,6 +389,7 @@ lisp/org-remember.elc: lisp/org.el
|
|||
lisp/org-rmail.elc: lisp/org.el
|
||||
lisp/org-src.elc: lisp/org-macs.el lisp/org-compat.el
|
||||
lisp/org-table.elc: lisp/org.el
|
||||
lisp/org-taskjuggler.elc: lisp/org.el lisp/org-exp.el
|
||||
lisp/org-timer.elc: lisp/org.el
|
||||
lisp/org-vm.elc: lisp/org.el
|
||||
lisp/org-w3m.elc: lisp/org.el
|
||||
|
|
|
@ -41,25 +41,19 @@ something.
|
|||
|
||||
** Structure
|
||||
*** TODO Get rid of all the \r instances, which were used only for XEmacs.
|
||||
*** TODO proper visibility cycling for items
|
||||
*** WISH proper visibility cycling for items
|
||||
Make them not hide the text after the final list item.
|
||||
This is not trivial, we cannot usenormal outline stuff,
|
||||
needs a separate implementaiton.
|
||||
*** WISH Inline TODO entries
|
||||
A way to put a TODO entry without starting a new section.
|
||||
needs a separate implementation.
|
||||
|
||||
** Agenda issues
|
||||
*** WISH Make more modes changeable from the agenda
|
||||
These could be made available for toggling, just like
|
||||
follow-mode. Examples:
|
||||
- org-agenda-todo-list-sublevels
|
||||
- org-tags-match-list-sublevels
|
||||
- org-agenda-todo-ignore-scheduled
|
||||
|
||||
** Links
|
||||
*** WISH Variable of standard links for completion with C-c C-l
|
||||
Or something like that, to make standard links fast.
|
||||
|
||||
*** IDEA Find all links to a specific file
|
||||
|
||||
*** IDEA Make info HTML links work for links to Info files
|
||||
Info links of course only work inside Emacs. However, many info
|
||||
documents are on the web, so the HTML exporter could try to be
|
||||
|
@ -70,11 +64,6 @@ something.
|
|||
question is, is this URL going to be stable so that it makes sense
|
||||
to actually put this into org.el?
|
||||
|
||||
*** TODO Remove irretrievable links from /published/ HTML output
|
||||
This is on David's table, and he will hopefully integrate a
|
||||
mechanism for this into org-publish.el. The discussion about this
|
||||
was started by [[http://thread.gmane.org/gmane.emacs.orgmode/281][Austin Frank]]
|
||||
|
||||
*** TODO Document the character protection in links
|
||||
I don't think this is really covered anywhere.
|
||||
Maybe we also should protect characters in the visible part, to
|
||||
|
@ -90,80 +79,18 @@ something.
|
|||
@4=.....
|
||||
|
||||
*** WISH Make a variable that current line should be recomputed always
|
||||
in each table, skipping headers of course.
|
||||
In each table. Skipping headers of course.
|
||||
|
||||
*** BUG When computing in a narrowed column, aligning may go wrong.
|
||||
Computing changes fields and does not yet see correctly if the column
|
||||
width has changed, in the case of a narrowed column.
|
||||
|
||||
** Compatibility issues
|
||||
*** Emacs 21 compatibility
|
||||
This is being phased out. Almost everything works under Emacs 21,
|
||||
but in the future I will make little effort to support it.
|
||||
|
||||
*** XEmacs compatibility
|
||||
|
||||
** Exporting
|
||||
*** IDEA Convert links to footnotes for ASCII export.
|
||||
But the question is: where should these footnotes be placed?
|
||||
|
||||
** Publishing
|
||||
|
||||
We need to simplify the publishing options. Here are some of the
|
||||
options for publishing projects
|
||||
|
||||
*** Publishing options
|
||||
|
||||
:`:base-directory' Directory containing publishing source files
|
||||
:
|
||||
:`:publishing-directory' Directory (possibly remote) where output files
|
||||
: will be published.
|
||||
:
|
||||
:`:preparation-function' Function called before starting publishing
|
||||
: process, for example to run `make' for updating
|
||||
: files to be published.
|
||||
:
|
||||
:`:base-extension' Extension (without the dot!) of source files. This
|
||||
: actually is a regular expression.
|
||||
:
|
||||
:`:exclude' Regular expression to match file names that should
|
||||
: not be published, even though they have been selected
|
||||
: on the basis of their extension.
|
||||
:
|
||||
:`:include' List of files to be included regardless of
|
||||
: `:base-extension' and `:exclude'.
|
||||
:
|
||||
:`:publishing-function' Function executing the publication of a file.
|
||||
: This may also be a list of functions, which will
|
||||
: all be called in turn.
|
||||
:
|
||||
:`:link-validation-function' Function to validate links
|
||||
:
|
||||
:`:auto-index' When non-nil, publish an index during
|
||||
: org-publish-current-project or org-publish-all.
|
||||
:
|
||||
:`:index-filename' Filename for output of index. Defaults to `index.org'
|
||||
: (which becomes `index.html').
|
||||
:
|
||||
:`:index-title' Title of index page. Defaults to name of file.
|
||||
:
|
||||
:`:index-function' Plug-in function to use for generation of index.
|
||||
: Defaults to `org-publish-org-index', which generates
|
||||
: a plain list of links to all files in the project.
|
||||
|
||||
*** TODO Document the :recursive option
|
||||
*** QUESTION Does anyone use the index related options
|
||||
*** QUESTION Remove :base-extension and only use :include
|
||||
*** WISH Simple interaction between :include :exclude :recursive
|
||||
*** QUESTION Use an export-directory option per file?
|
||||
|
||||
For now we use publishing-directory but this is not consistent with the
|
||||
convention of using "publishing" when there is a /project/ to publish.
|
||||
*** TODO Document the :recursive option for org-publish
|
||||
|
||||
** Miscellaneous Stuff
|
||||
*** BUG Comments cannot be filled
|
||||
*** WISH Inlining of images in Org-mode files
|
||||
*** TODO Fixup outline-magic.el, so that it can be used.
|
||||
|
||||
*** TODO Use the new argument of bibtex-url
|
||||
Roland Winkler was kind enough to implement a new argument to the
|
||||
|
@ -180,6 +107,7 @@ convention of using "publishing" when there is a /project/ to publish.
|
|||
*** Priorities
|
||||
Here is some information about priorities, which is not yet
|
||||
documented. Actually, I am not sur if the list here is correct
|
||||
either
|
||||
**** QUOTE Priorities
|
||||
TODO entries: 1 or 1,2,...
|
||||
DEADLINE is 10-ddays, i.e. it is 10 on the due day
|
||||
|
@ -195,22 +123,10 @@ convention of using "publishing" when there is a /project/ to publish.
|
|||
|
||||
Priority * 1000
|
||||
|
||||
*** INCONSISTENCY: items don't grow/shrink due to promotion.
|
||||
In plain lists, multiple demote/promote commands executed directly
|
||||
after each other don't change the scope of the command - the
|
||||
initially selected text continues to be selected. This is
|
||||
inconsistent with the behavior of outline sections, were the subtree
|
||||
for promotion/demotion is newly defined after each command. Which
|
||||
convention is better? Should this be consistent between trees and
|
||||
plain lists?
|
||||
|
||||
*** QUESTION grep on directory does not yet work.
|
||||
I am actually not sure, I might have addressed this already, but
|
||||
my memory is failing me. Needs some checking.
|
||||
|
||||
|
||||
* Archive
|
||||
** Archived Tasks
|
||||
* COMMENT HTML style specifications
|
||||
|
||||
# Local Variables:
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2010-06-03 Christian Egli <christian.egli@sbszh.ch>
|
||||
|
||||
* org.texi (TaskJuggler export): Added documentation for the
|
||||
TaskJuggler exporter.
|
||||
|
||||
2010-05-19 Carsten Dominik <carsten.dominik@gmail.com>
|
||||
|
||||
* org.texi (Column attributes): Document that the ":" operator
|
||||
|
|
145
doc/org.texi
145
doc/org.texi
|
@ -339,6 +339,7 @@ Exporting
|
|||
* HTML export:: Exporting to HTML
|
||||
* LaTeX and PDF export:: Exporting to La@TeX{}, and processing to PDF
|
||||
* DocBook export:: Exporting to DocBook
|
||||
* TaskJuggler export:: Exporting to TaskJuggler
|
||||
* Freemind export:: Exporting to Freemind mind maps
|
||||
* XOXO export:: Exporting to XOXO
|
||||
* iCalendar export:: Exporting in iCalendar format
|
||||
|
@ -8957,10 +8958,11 @@ the web, while the XOXO format provides a solid base for exchange with a
|
|||
broad range of other applications. La@TeX{} export lets you use Org mode and
|
||||
its structured editing functions to easily create La@TeX{} files. DocBook
|
||||
export makes it possible to convert Org files to many other formats using
|
||||
DocBook tools. To incorporate entries with associated times like deadlines
|
||||
or appointments into a desktop calendar program like iCal, Org mode can also
|
||||
produce extracts in the iCalendar format. Currently Org mode only supports
|
||||
export, not import of these different formats.
|
||||
DocBook tools. For project management you can create gantt and resource
|
||||
charts by using TaskJuggler export. To incorporate entries with associated
|
||||
times like deadlines or appointments into a desktop calendar program like
|
||||
iCal, Org mode can also produce extracts in the iCalendar format. Currently
|
||||
Org mode only supports export, not import of these different formats.
|
||||
|
||||
Org supports export of selected regions when @code{transient-mark-mode} is
|
||||
enabled (default in Emacs 23).
|
||||
|
@ -8973,6 +8975,7 @@ enabled (default in Emacs 23).
|
|||
* HTML export:: Exporting to HTML
|
||||
* LaTeX and PDF export:: Exporting to La@TeX{}, and processing to PDF
|
||||
* DocBook export:: Exporting to DocBook
|
||||
* TaskJuggler export:: Exporting to TaskJuggler
|
||||
* Freemind export:: Exporting to Freemind mind maps
|
||||
* XOXO export:: Exporting to XOXO
|
||||
* iCalendar export:: Exporting in iCalendar format
|
||||
|
@ -9898,7 +9901,7 @@ Here is a simple example Org document that is intended for beamer export.
|
|||
|
||||
For more information, see the documentation on Worg.
|
||||
|
||||
@node DocBook export, Freemind export, LaTeX and PDF export, Exporting
|
||||
@node DocBook export, TaskJuggler export, LaTeX and PDF export, Exporting
|
||||
@section DocBook export
|
||||
@cindex DocBook export
|
||||
@cindex PDF export
|
||||
|
@ -10098,7 +10101,137 @@ special characters included in XHTML entities:
|
|||
"
|
||||
@end example
|
||||
|
||||
@node Freemind export, XOXO export, DocBook export, Exporting
|
||||
@node TaskJuggler export, Freemind export, DocBook export, Exporting
|
||||
@section TaskJuggler export
|
||||
@cindex TaskJuggler export
|
||||
@cindex Project management
|
||||
|
||||
@uref{http://www.taskjuggler.org/, TaskJuggler} is a project management tool.
|
||||
It provides an optimizing scheduler that computes your project time lines and
|
||||
resource assignments based on the project outline and the constraints that
|
||||
you have provided.
|
||||
|
||||
The TaskJuggler exporter is a bit different from other exporters, such as the
|
||||
HTML and LaTeX exporters for example, in that it does not export all the
|
||||
nodes of a document or strictly follow the order of the nodes in the
|
||||
document.
|
||||
|
||||
Instead the TaskJuggler exporter looks for a tree that defines the tasks and
|
||||
a optionally tree that defines the resources for this project. It then
|
||||
creates a TaskJuggler file based on these trees and the attributes defined in
|
||||
all the nodes.
|
||||
|
||||
@subsection TaskJuggler export commands
|
||||
|
||||
@table @kbd
|
||||
@kindex C-c C-e j
|
||||
@item C-c C-e j
|
||||
Export as TaskJuggler file.
|
||||
|
||||
@kindex C-c C-e J
|
||||
@item C-c C-e J
|
||||
Export as TaskJuggler file and then open the file with TaskJugglerUI.
|
||||
@end table
|
||||
|
||||
@subsection Tasks
|
||||
|
||||
@vindex org-export-taskjuggler-project-tag
|
||||
Create your tasks as you usually do with Org-mode. Assign efforts to each
|
||||
task using properties (it's easiest to do this in the column view). You
|
||||
should end up with something similar to the example by Peter Jones in
|
||||
@url{http://www.contextualdevelopment.com/static/artifacts/articles/2008/project-planning/project-planning.org}.
|
||||
Now mark the top node of your tasks with a tag named
|
||||
@code{:taskjuggler_project:} (or whatever you customized
|
||||
@code{org-export-taskjuggler-project-tag} to). You are now ready to export
|
||||
the project plan with @kbd{C-c C-e J} which will export the project plan and
|
||||
open a gantt chart in TaskJugglerUI.
|
||||
|
||||
@subsection Resources
|
||||
|
||||
@vindex org-export-taskjuggler-resource-tag
|
||||
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 @code{:taskjuggler_resource:} (or whatever you customized
|
||||
@code{org-export-taskjuggler-resource-tag} to). You can optionally assign an
|
||||
identifier (named @samp{resource_id}) to the resources (using the standard
|
||||
Org properties commands, @pxref{Property syntax}) or you can let the exporter
|
||||
generate identifiers automatically (the exporter picks the first word of the
|
||||
headline as the identifier as long as it is unique, see the documentation of
|
||||
@code{org-taskjuggler-get-unique-id}). Using that identifier you can then
|
||||
allocate resources to tasks. This is again done with the @samp{allocate}
|
||||
property on the tasks. Do this in column view or when on the task type
|
||||
@kbd{C-c C-x p allocate @key{RET} <resource_id> @key{RET}}.
|
||||
|
||||
Once the allocations are done you can again export to TaskJuggler and check
|
||||
in the Resource Allocation Graph which person is working on what task at what
|
||||
time.
|
||||
|
||||
@subsection Export of properties
|
||||
|
||||
The exporter also takes TODO state information into consideration, i.e. if a
|
||||
task is marked as done it will have the corresponding attribute in
|
||||
TaskJuggler (@samp{complete 100}). Also it will export any property on a task
|
||||
resource or resource node which is known to TaskJuggler, such as
|
||||
@samp{limits}, @samp{vacation}, @samp{shift}, @samp{booking},
|
||||
@samp{efficiency}, @samp{journalentry}, @samp{rate} for resources or
|
||||
@samp{account}, @samp{start}, @samp{note}, @samp{duration}, @samp{end},
|
||||
@samp{journalentry}, @samp{milestone}, @samp{reference}, @samp{responsible},
|
||||
@samp{scheduling}, etc for tasks.
|
||||
|
||||
@subsection Dependencies
|
||||
|
||||
The exporter will handle dependencies that are defined in the tasks either
|
||||
with the @samp{ORDERED} attribute (@pxref{TODO dependencies}), with the
|
||||
@samp{BLOCKER} attribute (see org-depend.el) or alternatively with a
|
||||
@samp{depends} attribute. Both the @samp{BLOCKER} and the @samp{depends}
|
||||
attribute can be either @samp{previous-sibling} or a reference to an
|
||||
identifier (named @samp{task_id}) which is defined for another task in the
|
||||
project. @samp{BLOCKER} and the @samp{depends} attribute can define multiple
|
||||
dependencies separated by either space or comma. You can also specify
|
||||
optional attributes on the dependency by simply appending it. The following
|
||||
examples should illustrate this:
|
||||
|
||||
@example
|
||||
* Preparation
|
||||
:PROPERTIES:
|
||||
:task_id: preparation
|
||||
:ORDERED: t
|
||||
:END:
|
||||
* Training material
|
||||
:PROPERTIES:
|
||||
:task_id: training_material
|
||||
:ORDERED: t
|
||||
:END:
|
||||
** Markup Guidelines
|
||||
:PROPERTIES:
|
||||
:Effort: 2.0
|
||||
:END:
|
||||
** Workflow Guidelines
|
||||
:PROPERTIES:
|
||||
:Effort: 2.0
|
||||
:END:
|
||||
* Presentation
|
||||
:PROPERTIES:
|
||||
:Effort: 2.0
|
||||
:BLOCKER: training_material @{ gapduration 1d @} preparation
|
||||
:END:
|
||||
@end example
|
||||
|
||||
@subsection Reports
|
||||
|
||||
@vindex org-export-taskjuggler-default-reports
|
||||
TaskJuggler can produce many kinds of reports (e.g. gantt chart, resource
|
||||
allocation, etc). The user defines what kind of reports should be generated
|
||||
for a project in the TaskJuggler file. The exporter will automatically insert
|
||||
some default reports in the file. These defaults are defined in
|
||||
@code{org-export-taskjuggler-default-reports}. They can be modified using
|
||||
customize along with a number of other options. For a more complete list, see
|
||||
@kbd{M-x customize-group @key{RET} org-export-taskjuggler @key{RET}}.
|
||||
|
||||
For more information and examples see the Org-taskjuggler tutorial at
|
||||
@uref{http://orgmode.org/worg/org-tutorials/org-taskjuggler.php}.
|
||||
|
||||
@node Freemind export, XOXO export, TaskJuggler export, Exporting
|
||||
@section Freemind export
|
||||
@cindex Freemind export
|
||||
@cindex mind map
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
2010-06-08 Christian Egli <christian.egli@sbszh.ch>
|
||||
|
||||
* org-taskjuggler.el (org-export-taskjuggler-old-level):
|
||||
define local variable to avoid compiler warning.
|
||||
|
||||
2010-06-07 Christian Egli <christian.egli@sbszh.ch>
|
||||
|
||||
* org-exp.el (org-export): Added taskjuggler export to the export
|
||||
dispatcher.
|
||||
|
||||
2010-06-08 Bastien Guerry <bzg@altern.org>
|
||||
|
||||
* org-timer.el (org-timer-set-timer): Fix typo in the docstring.
|
||||
|
||||
2010-05-28 Bastien Guerry <bzg@altern.org>
|
||||
|
||||
* org-timer.el (org-timer-set-timer): Use a prefix argument.
|
||||
|
@ -291,6 +305,15 @@
|
|||
* org-html.el (org-format-org-table-html): Test all columns
|
||||
for number content.
|
||||
|
||||
2010-04-28 Christian Egli <christian.egli@sbszh.ch>
|
||||
|
||||
* org-taskjuggler.el (org-taskjuggler-find-task-with-id): Do not
|
||||
use the ID property frivolously, i.e. use a property named
|
||||
"task_id" instead as we do not search for ids across files.
|
||||
(org-taskjuggler-resolve-explicit-dependencies): Issue a warning
|
||||
if a dependency cannot be resolved.
|
||||
(org-taskjuggler-open-resource): Add documentation.
|
||||
|
||||
2010-04-28 Carsten Dominik <carsten.dominik@gmail.com>
|
||||
|
||||
* org-latex.el (org-export-latex-treat-sub-super-char): Make
|
||||
|
@ -687,6 +710,11 @@
|
|||
(org-export-latex-default-packages-alist): hyperref must be loaded
|
||||
late.
|
||||
|
||||
2010-04-07 Christian Egli <christian.egli@sbszh.ch>
|
||||
|
||||
* org-taskjuggler.el (org-taskjuggler-tokenize-dependencies): Add
|
||||
support for optional attributes on dependencies.
|
||||
|
||||
2010-04-07 Carsten Dominik <carsten.dominik@gmail.com>
|
||||
|
||||
* org-latex.el (org-export-latex-preprocess): Do not yet protect
|
||||
|
@ -825,6 +853,11 @@
|
|||
|
||||
* org-faces.el (org-faces): Change Customize group variable name
|
||||
|
||||
2010-03-30 Christian Egli <christian.egli@sbszh.ch>
|
||||
|
||||
* org-taskjuggler.el: Added a new exporter to export org-mode
|
||||
projects to taskjuggler files.
|
||||
|
||||
2010-03-29 Carsten Dominik <carsten.dominik@gmail.com>
|
||||
|
||||
* org-agenda.el (org-diary-last-run-time): New variable.
|
||||
|
|
|
@ -862,6 +862,8 @@ value of `org-export-run-in-background'."
|
|||
|
||||
\[D] export as DocBook [V] export as DocBook, process to PDF, and open
|
||||
|
||||
\[j] export as TaskJuggler [J] ... and open
|
||||
|
||||
\[m] export as Freemind mind map
|
||||
\[x] export as XOXO
|
||||
\[g] export using Wes Hardaker's generic exporter
|
||||
|
@ -888,6 +890,8 @@ value of `org-export-run-in-background'."
|
|||
(?g org-export-generic t)
|
||||
(?D org-export-as-docbook t)
|
||||
(?V org-export-as-docbook-pdf-and-open t)
|
||||
(?j org-export-as-taskjuggler t)
|
||||
(?J org-export-as-taskjuggler-and-open t)
|
||||
(?m org-export-as-freemind t)
|
||||
(?l org-export-as-latex t)
|
||||
(?p org-export-as-pdf t)
|
||||
|
|
|
@ -0,0 +1,647 @@
|
|||
;;; org-taskjuggler.el --- TaskJuggler exporter for org-mode
|
||||
;;
|
||||
;; Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
;;
|
||||
;; Emacs Lisp Archive Entry
|
||||
;; Filename: org-taskjuggler.el
|
||||
;; Version: 6.34trans
|
||||
;; Author: Christian Egli
|
||||
;; Maintainer: Christian Egli
|
||||
;; Keywords: org, taskjuggler, project planning
|
||||
;; Description: Converts an org-mode buffer into a taskjuggler project plan
|
||||
;; URL:
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;; Commentary:
|
||||
;;
|
||||
;; This library implements a TaskJuggler exporter for org-mode.
|
||||
;; TaskJuggler uses a text format to define projects, tasks and
|
||||
;; resources, so it is a natural fit for org-mode. It can produce all
|
||||
;; sorts of reports for tasks or resources in either HTML, CSV or PDF.
|
||||
;; The current version of TaskJuggler requires KDE but the next
|
||||
;; version is implemented in Ruby and should therefore run on any
|
||||
;; platform.
|
||||
;;
|
||||
;; The exporter is a bit different from other exporters, such as the
|
||||
;; HTML and LaTeX exporters for example, in that it does not export
|
||||
;; all the nodes of a document or strictly follow the order of the
|
||||
;; nodes in the document.
|
||||
;;
|
||||
;; Instead the TaskJuggler exporter looks for a tree that defines the
|
||||
;; tasks and a optionally tree that defines the resources for this
|
||||
;; project. It then creates a TaskJuggler file based on these trees
|
||||
;; and the attributes defined in all the nodes.
|
||||
;;
|
||||
;; * Installation
|
||||
;;
|
||||
;; Put this file into your load-path and the following line into your
|
||||
;; ~/.emacs:
|
||||
;;
|
||||
;; (require 'org-taskjuggler)
|
||||
;;
|
||||
;; The interactive functions are similar to those of the HTML and LaTeX
|
||||
;; exporters:
|
||||
;;
|
||||
;; M-x `org-export-as-taskjuggler'
|
||||
;; M-x `org-export-as-taskjuggler-and-open'
|
||||
;;
|
||||
;; * Tasks
|
||||
;;
|
||||
;; Let's illustrate the usage with a small example. Create your tasks
|
||||
;; as you usually do with org-mode. Assign efforts to each task using
|
||||
;; properties (it's easiest to do this in the column view). You should
|
||||
;; end up with something similar to the example by Peter Jones in
|
||||
;; http://www.contextualdevelopment.com/static/artifacts/articles/2008/project-planning/project-planning.org.
|
||||
;; Now mark the top node of your tasks with a tag named
|
||||
;; "taskjuggler_project" (or whatever you customized
|
||||
;; `org-export-taskjuggler-project-tag' to). You are now ready to
|
||||
;; export the project plan with `org-export-as-taskjuggler-and-open'
|
||||
;; which will export the project plan and open a gant chart in
|
||||
;; 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
|
||||
;; customized `org-export-taskjuggler-resource-tag' to). You can
|
||||
;; optionally assign an identifier (named "resource_id") to the
|
||||
;; resources (using the standard org properties commands) or you can
|
||||
;; let the exporter generate identifiers automatically (the exporter
|
||||
;; picks the first word of the headline as the identifier as long as
|
||||
;; it is unique, see the documentation of
|
||||
;; `org-taskjuggler-get-unique-id'). Using that identifier you can
|
||||
;; then allocate resources to tasks. This is again done with the
|
||||
;; "allocate" property on the tasks. Do this in column view or when on
|
||||
;; the task type
|
||||
;;
|
||||
;; C-c C-x p allocate RET <resource_id> RET
|
||||
;;
|
||||
;; Once the allocations are done you can again export to TaskJuggler
|
||||
;; and check in the Resource Allocation Graph which person is working
|
||||
;; on what task at what time.
|
||||
;;
|
||||
;; * Export of properties
|
||||
;;
|
||||
;; The exporter also takes TODO state information into consideration,
|
||||
;; i.e. if a task is marked as done it will have the corresponding
|
||||
;; attribute in TaskJuggler ("complete 100"). Also it will export any
|
||||
;; property on a task resource or resource node which is known to
|
||||
;; TaskJuggler, such as limits, vacation, shift, booking, efficiency,
|
||||
;; journalentry, rate for resources or account, start, note, duration,
|
||||
;; end, journalentry, milestone, reference, responsible, scheduling,
|
||||
;; 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
|
||||
;; alternatively with a depends attribute. Both the BLOCKER and the
|
||||
;; depends attribute can be either "previous-sibling" or a reference
|
||||
;; to an identifier (named "task_id") which is defined for another
|
||||
;; task in the project. BLOCKER and the depends attribute can define
|
||||
;; multiple dependencies separated by either space or comma. You can
|
||||
;; also specify optional attributes on the dependency by simply
|
||||
;; appending it. The following examples should illustrate this:
|
||||
;;
|
||||
;; * Training material
|
||||
;; :PROPERTIES:
|
||||
;; :task_id: training_material
|
||||
;; :ORDERED: t
|
||||
;; :END:
|
||||
;; ** Markup Guidelines
|
||||
;; :PROPERTIES:
|
||||
;; :Effort: 2.0
|
||||
;; :END:
|
||||
;; ** Workflow Guidelines
|
||||
;; :PROPERTIES:
|
||||
;; :Effort: 2.0
|
||||
;; :END:
|
||||
;; * Presentation
|
||||
;; :PROPERTIES:
|
||||
;; :Effort: 2.0
|
||||
;; :BLOCKER: training_material { gapduration 1d } some_other_task
|
||||
;; :END:
|
||||
;;
|
||||
;;;; * TODO
|
||||
;; - Use SCHEDULED and DEADLINE information (not just start and end
|
||||
;; properties).
|
||||
;; - Look at org-file-properties, org-global-properties and
|
||||
;; org-global-properties-fixed
|
||||
;; - What about property inheritance and org-property-inherit-p?
|
||||
;; - Use TYPE_TODO as an way to assign resources
|
||||
;; - Make sure multiple dependency definitions (i.e. BLOCKER on
|
||||
;; previous-sibling and on a specific task_id) in multiple
|
||||
;; attributes are properly exported.
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(eval-when-compile
|
||||
(require 'cl))
|
||||
|
||||
(require 'org)
|
||||
(require 'org-exp)
|
||||
|
||||
;;; User variables:
|
||||
|
||||
(defgroup org-export-taskjuggler nil
|
||||
"Options for exporting Org-mode files to TaskJuggler."
|
||||
:tag "Org Export TaskJuggler"
|
||||
:group 'org-export)
|
||||
|
||||
(defcustom org-export-taskjuggler-extension ".tjp"
|
||||
"Extension of TaskJuggler files."
|
||||
:group 'org-export-taskjuggler
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-export-taskjuggler-project-tag "taskjuggler_project"
|
||||
"Tag, property or todo used to find the tree containing all
|
||||
the tasks for the project."
|
||||
:group 'org-export-taskjuggler
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-export-taskjuggler-resource-tag "taskjuggler_resource"
|
||||
"Tag, property or todo used to find the tree containing all the
|
||||
resources for the project."
|
||||
:group 'org-export-taskjuggler
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-export-taskjuggler-default-project-version "1.0"
|
||||
"Default version string for the project."
|
||||
:group 'org-export-taskjuggler
|
||||
:type 'string)
|
||||
|
||||
(defcustom org-export-taskjuggler-default-project-duration 280
|
||||
"Default project duration if no start and end date have been defined
|
||||
in the root node of the task tree, i.e. the tree that has been marked
|
||||
with `org-export-taskjuggler-project-tag'"
|
||||
:group 'org-export-taskjuggler
|
||||
:type 'integer)
|
||||
|
||||
(defcustom org-export-taskjuggler-default-reports
|
||||
'("taskreport \"Gantt Chart\" {
|
||||
headline \"Project Gantt Chart\"
|
||||
columns hierarchindex, name, start, end, effort, duration, completed, chart
|
||||
timeformat \"%Y-%m-%d\"
|
||||
hideresource 1
|
||||
loadunit shortauto
|
||||
}"
|
||||
"resourcereport \"Resource Graph\" {
|
||||
headline \"Resource Allocation Graph\"
|
||||
columns no, name, utilization, freeload, chart
|
||||
loadunit shortauto
|
||||
sorttasks startup
|
||||
hidetask ~isleaf()
|
||||
}")
|
||||
"Default reports for the project."
|
||||
:group 'org-export-taskjuggler
|
||||
:type '(repeat (string :tag "Report")))
|
||||
|
||||
(defcustom org-export-taskjuggler-default-global-properties
|
||||
"shift s40 \"Part time shift\" {
|
||||
workinghours wed, thu, fri off
|
||||
}
|
||||
"
|
||||
"Default global properties for the project. Here you typically
|
||||
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.
|
||||
|
||||
The global properties are inserted after the project declaration
|
||||
but before any resource and task declarations."
|
||||
:group 'org-export-taskjuggler
|
||||
:type '(string :tag "Preamble"))
|
||||
|
||||
;;; Hooks
|
||||
|
||||
(defvar org-export-taskjuggler-final-hook nil
|
||||
"Hook run at the end of TaskJuggler export, in the new buffer.")
|
||||
|
||||
;;; Autoload functions:
|
||||
|
||||
;; avoid compiler warning about free variable
|
||||
(defvar org-export-taskjuggler-old-level)
|
||||
|
||||
;;;###autoload
|
||||
(defun org-export-as-taskjuggler ()
|
||||
"Export parts of the current buffer as a TaskJuggler file.
|
||||
The exporter looks for a tree with tag, property or todo that
|
||||
matches `org-export-taskjuggler-project-tag' and takes this as
|
||||
the tasks for this project. The first node of this tree defines
|
||||
the project properties such as project name and project period.
|
||||
If there is a tree with tag, property or todo that matches
|
||||
`org-export-taskjuggler-resource-tag' this three is taken as
|
||||
resources for the project. If no resources are specified, a
|
||||
default resource is created and allocated to the project. Also
|
||||
the taskjuggler project will be created with default reports as
|
||||
defined in `org-export-taskjuggler-default-reports'."
|
||||
(interactive)
|
||||
|
||||
(message "Exporting...")
|
||||
(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))))
|
||||
(resources
|
||||
(org-taskjuggler-assign-resource-ids
|
||||
(org-map-entries
|
||||
'(org-taskjuggler-components)
|
||||
org-export-taskjuggler-resource-tag nil 'archive 'comment)))
|
||||
(filename (expand-file-name
|
||||
(concat
|
||||
(file-name-sans-extension
|
||||
(file-name-nondirectory buffer-file-name))
|
||||
org-export-taskjuggler-extension)))
|
||||
(buffer (find-file-noselect filename))
|
||||
(org-export-taskjuggler-old-level 0)
|
||||
task resource)
|
||||
(unless tasks
|
||||
(error "No tasks specified"))
|
||||
;; add a default resource
|
||||
(unless resources
|
||||
(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))
|
||||
(let ((task (car tasks))
|
||||
(resource-id (cdr (assoc "resource_id" (car resources)))))
|
||||
(setcar tasks (push (cons "allocate" resource-id) task))))
|
||||
;; add a default start date to the first task if none was given
|
||||
(unless (assoc "start" (car tasks))
|
||||
(let ((task (car tasks))
|
||||
(time-string (format-time-string "%Y-%m-%d")))
|
||||
(setcar tasks (push (cons "start" time-string) task))))
|
||||
;; add a default version if none was given
|
||||
(unless (assoc "version" (car tasks))
|
||||
(let ((task (car tasks))
|
||||
(version org-export-taskjuggler-default-project-version))
|
||||
(setcar tasks (push (cons "version" version) task))))
|
||||
(with-current-buffer buffer
|
||||
(erase-buffer)
|
||||
(org-taskjuggler-open-project (car tasks))
|
||||
(insert org-export-taskjuggler-default-global-properties)
|
||||
(insert "\n")
|
||||
(dolist (resource resources)
|
||||
(let ((level (cdr (assoc "level" resource))))
|
||||
(org-taskjuggler-close-maybe level)
|
||||
(org-taskjuggler-open-resource resource)
|
||||
(setq org-export-taskjuggler-old-level level)))
|
||||
(org-taskjuggler-close-maybe 1)
|
||||
(setq org-export-taskjuggler-old-level 0)
|
||||
(dolist (task tasks)
|
||||
(let ((level (cdr (assoc "level" task))))
|
||||
(org-taskjuggler-close-maybe level)
|
||||
(org-taskjuggler-open-task task)
|
||||
(setq org-export-taskjuggler-old-level level)))
|
||||
(org-taskjuggler-close-maybe 1)
|
||||
(org-taskjuggler-insert-reports)
|
||||
(save-buffer)
|
||||
(or (org-export-push-to-kill-ring "TaskJuggler")
|
||||
(message "Exporting... done"))
|
||||
(current-buffer))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-export-as-taskjuggler-and-open ()
|
||||
"Export the current buffer as a TaskJuggler file and open it
|
||||
with the TaskJuggler GUI."
|
||||
(interactive)
|
||||
(let ((file-name (buffer-file-name (org-export-as-taskjuggler)))
|
||||
(command "TaskJugglerUI"))
|
||||
(start-process-shell-command command nil command file-name)))
|
||||
|
||||
(defun org-taskjuggler-parent-is-ordered-p ()
|
||||
"Return true if the parent of the current node has a property
|
||||
\"ORDERED\". Return nil otherwise."
|
||||
(save-excursion
|
||||
(and (org-up-heading-safe) (org-entry-get (point) "ORDERED"))))
|
||||
|
||||
(defun org-taskjuggler-components ()
|
||||
"Return an alist containing all the pertinent information for
|
||||
the current node such as the headline, the level, todo state
|
||||
information, all the properties, etc."
|
||||
(let* ((props (org-entry-properties))
|
||||
(components (org-heading-components))
|
||||
(level (nth 1 components))
|
||||
(headline (nth 4 components))
|
||||
(parent-ordered (org-taskjuggler-parent-is-ordered-p)))
|
||||
(push (cons "level" level) props)
|
||||
(push (cons "headline" headline) props)
|
||||
(push (cons "parent-ordered" parent-ordered) props)))
|
||||
|
||||
(defun org-taskjuggler-assign-task-ids (tasks)
|
||||
"Given a list of tasks return the same list assigning a unique id
|
||||
and the full path to each task. Taskjuggler takes hierarchical ids.
|
||||
For that reason we have to make ids locally unique and we have to keep
|
||||
a path to the current task."
|
||||
(let ((previous-level 0)
|
||||
unique-ids unique-id
|
||||
path
|
||||
task resolved-tasks tmp)
|
||||
(dolist (task tasks resolved-tasks)
|
||||
(let ((level (cdr (assoc "level" task))))
|
||||
(cond
|
||||
((< 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)
|
||||
(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)
|
||||
(dotimes (tmp (- previous-level level))
|
||||
(pop unique-ids)
|
||||
(pop path))
|
||||
(setq unique-id (org-taskjuggler-get-unique-id task (car unique-ids)))
|
||||
(push unique-id (car unique-ids))
|
||||
(setcar path unique-id)))
|
||||
(push (cons "unique-id" unique-id) task)
|
||||
(push (cons "path" (mapconcat 'identity (reverse path) ".")) task)
|
||||
(setq previous-level level)
|
||||
(setq resolved-tasks (append resolved-tasks (list task)))))))
|
||||
|
||||
(defun org-taskjuggler-assign-resource-ids (resources &optional unique-ids)
|
||||
"Given a list of resources return the same list, assigning a
|
||||
unique id to each resource."
|
||||
(cond
|
||||
((null resources) nil)
|
||||
(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 unique-id unique-ids)))))))
|
||||
|
||||
(defun org-taskjuggler-resolve-dependencies (tasks)
|
||||
(let ((previous-level 0)
|
||||
siblings
|
||||
task resolved-tasks)
|
||||
(dolist (task tasks resolved-tasks)
|
||||
(let* ((level (cdr (assoc "level" task)))
|
||||
(depends (cdr (assoc "depends" task)))
|
||||
(parent-ordered (cdr (assoc "parent-ordered" task)))
|
||||
(blocker (cdr (assoc "BLOCKER" task)))
|
||||
(blocked-on-previous
|
||||
(and blocker (string-match "previous-sibling" blocker)))
|
||||
(dependencies
|
||||
(org-taskjuggler-resolve-explicit-dependencies
|
||||
(append
|
||||
(and depends (org-taskjuggler-tokenize-dependencies depends))
|
||||
(and blocker (org-taskjuggler-tokenize-dependencies blocker)))
|
||||
tasks))
|
||||
previous-sibling)
|
||||
; update previous sibling info
|
||||
(cond
|
||||
((< 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)
|
||||
(dotimes (tmp (- previous-level level))
|
||||
(pop siblings))
|
||||
(setq previous-sibling (car siblings))
|
||||
(setcar siblings task)))
|
||||
; insert a dependency on previous sibling if the parent is
|
||||
; ordered or if the tasks has a BLOCKER attribute with value "previous-sibling"
|
||||
(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
|
||||
(push (cons "depends" (mapconcat 'identity dependencies ", ")) task))
|
||||
(setq previous-level level)
|
||||
(setq resolved-tasks (append resolved-tasks (list task)))))))
|
||||
|
||||
(defun org-taskjuggler-tokenize-dependencies (dependencies)
|
||||
"Split a dependency property value DEPENDENCIES into the
|
||||
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
|
||||
((string-match "^ *$" dependencies) nil)
|
||||
((string-match "^[ \t]*\\([-a-zA-Z0-9_]+\\([ \t]*{[^}]+}\\)?\\)[ \t,]*" dependencies)
|
||||
(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)))))
|
||||
|
||||
(defun org-taskjuggler-resolve-explicit-dependencies (dependencies tasks)
|
||||
"For each dependency in DEPENDENCIES try to find a
|
||||
corresponding task with a matching property \"task_id\" in TASKS.
|
||||
Return a list containing the resolved links for all DEPENDENCIES
|
||||
where a matching tasks was found. If the dependency is
|
||||
\"previous-sibling\" it is ignored (as this is dealt with in
|
||||
`org-taskjuggler-resolve-dependencies'). If there is no matching
|
||||
task the dependency is ignored and a warning is displayed ."
|
||||
(unless (null dependencies)
|
||||
(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
|
||||
(mapconcat 'identity (cdr (split-string dependency)) " "))
|
||||
(path (org-taskjuggler-find-task-with-id id tasks)))
|
||||
(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))
|
||||
(cons (mapconcat 'identity (list path optional-attributes) " ")
|
||||
(org-taskjuggler-resolve-explicit-dependencies
|
||||
(cdr dependencies) tasks)))
|
||||
;; warn about dangling dependency but otherwise ignore it
|
||||
(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))))))
|
||||
|
||||
(defun org-taskjuggler-find-task-with-id (id tasks)
|
||||
"Find ID in tasks. If found return the path of task. Otherwise
|
||||
return nil."
|
||||
(let ((task-id (cdr (assoc "task_id" (car tasks))))
|
||||
(path (cdr (assoc "path" (car tasks)))))
|
||||
(cond
|
||||
((null tasks) nil)
|
||||
((equal task-id id) path)
|
||||
(t (org-taskjuggler-find-task-with-id id (cdr tasks))))))
|
||||
|
||||
(defun org-taskjuggler-get-unique-id (item unique-ids)
|
||||
"Return a unique id for an ITEM which can be a task or a resource.
|
||||
The id is derived from the headline and made unique against
|
||||
UNIQUE-IDS. If the (downcased) first token of the headline is not
|
||||
unique try to add more (downcased) tokens of the headline or
|
||||
finally add more underscore characters (\"_\")."
|
||||
(let* ((headline (cdr (assoc "headline" item)))
|
||||
(parts (split-string headline))
|
||||
(id (org-taskjuggler-clean-id (downcase (pop parts)))))
|
||||
; try to add more parts of the headline to make it unique
|
||||
(while (member id unique-ids)
|
||||
(setq id (concat id "_" (org-taskjuggler-clean-id (downcase (pop parts))))))
|
||||
; if its still not unique add "_"
|
||||
(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)))
|
||||
|
||||
(defun org-taskjuggler-open-project (project)
|
||||
"Insert the beginning of a project declaration. All valid
|
||||
attributes from the PROJECT alist are inserted. If no end date is
|
||||
specified it is calculated
|
||||
`org-export-taskjuggler-default-project-duration' days from now."
|
||||
(let* ((unique-id (cdr (assoc "unique-id" project)))
|
||||
(headline (cdr (assoc "headline" project)))
|
||||
(version (cdr (assoc "version" project)))
|
||||
(start (cdr (assoc "start" project)))
|
||||
(end (cdr (assoc "end" project))))
|
||||
(insert
|
||||
(format "project %s \"%s\" \"%s\" %s +%sd {\n }\n"
|
||||
unique-id headline version start
|
||||
org-export-taskjuggler-default-project-duration))))
|
||||
|
||||
(defun org-taskjuggler-filter-and-join (items)
|
||||
"Filter all nil elements from ITEMS and join the remaining ones
|
||||
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
|
||||
(mapcar
|
||||
(lambda (attribute)
|
||||
(org-taskjuggler-filter-and-join
|
||||
(org-taskjuggler-get-attribute item attribute)))
|
||||
attributes)))
|
||||
|
||||
(defun org-taskjuggler-get-attribute (item attribute)
|
||||
"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
|
||||
((null item) nil)
|
||||
((equal (symbol-name attribute) (car (car item)))
|
||||
(cons (format "%s %s" (symbol-name attribute) (cdr (car item)))
|
||||
(org-taskjuggler-get-attribute (cdr item) attribute)))
|
||||
(t (org-taskjuggler-get-attribute (cdr item) attribute))))
|
||||
|
||||
(defun org-taskjuggler-open-resource (resource)
|
||||
"Insert the beginning of a resource declaration. All valid
|
||||
attributes from the RESOURCE alist are inserted. If the RESOURCE
|
||||
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))
|
||||
(cdr (assoc "unique-id" resource)))))
|
||||
(headline (cdr (assoc "headline" resource)))
|
||||
(attributes '(limits vacation shift booking efficiency journalentry rate)))
|
||||
(insert
|
||||
(concat
|
||||
"resource " id " \"" headline "\" {\n "
|
||||
(org-taskjuggler-get-attributes resource attributes) "\n"))))
|
||||
|
||||
(defun org-taskjuggler-clean-effort (effort)
|
||||
"Translate effort strings into a format acceptable to taskjuggler,
|
||||
i.e. REAL UNIT. If the effort string is something like 5:30 it
|
||||
will be assumed to be hours and will be translated into 5.5h.
|
||||
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
|
||||
((null effort) 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)))))
|
||||
((string-match "\\([0-9]+\\).\\([0-9]+\\)" effort) (concat effort "d"))
|
||||
(t (error "Not a valid effort (%s)" effort))))
|
||||
|
||||
(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)))
|
||||
(- org-lowest-priority org-highest-priority))))
|
||||
|
||||
(defun org-taskjuggler-open-task (task)
|
||||
(let* ((unique-id (cdr (assoc "unique-id" task)))
|
||||
(headline (cdr (assoc "headline" task)))
|
||||
(effort (org-taskjuggler-clean-effort (cdr (assoc org-effort-property task))))
|
||||
(depends (cdr (assoc "depends" task)))
|
||||
(allocate (cdr (assoc "allocate" task)))
|
||||
(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")
|
||||
(cdr (assoc "complete" task))))
|
||||
(parent-ordered (cdr (assoc "parent-ordered" task)))
|
||||
(previous-sibling (cdr (assoc "previous-sibling" task)))
|
||||
(attributes
|
||||
'(account start note duration endbuffer endcredit end
|
||||
flags journalentry length maxend maxstart milestone
|
||||
minend minstart period reference responsible
|
||||
scheduling startbuffer startcredit statusnote)))
|
||||
(insert
|
||||
(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 complete (format " complete %s\n" complete))
|
||||
(and effort (format " effort %s\n" effort))
|
||||
(and priority (format " priority %s\n" priority))
|
||||
|
||||
(org-taskjuggler-get-attributes task attributes)
|
||||
"\n"))))
|
||||
|
||||
(defun org-taskjuggler-close-maybe (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)
|
||||
(insert "}\n")))
|
||||
|
||||
(defun org-taskjuggler-insert-reports ()
|
||||
(let (report)
|
||||
(dolist (report org-export-taskjuggler-default-reports)
|
||||
(insert report "\n"))))
|
||||
|
||||
(provide 'org-taskjuggler)
|
||||
|
||||
;;; org-taskjuggler.el ends here
|
|
@ -320,10 +320,10 @@ prompt the use if she wants to replace it.
|
|||
Called with a numeric prefix argument, use this numeric value as
|
||||
the duration of the timer.
|
||||
|
||||
Called with a `C-u' prefix argument, use `org-timer-default-timer'
|
||||
Called with a `C-u' prefix arguments, use `org-timer-default-timer'
|
||||
without prompting the user for a duration.
|
||||
|
||||
With two `C-u' prefix argument, use `org-timer-default-timer'
|
||||
With two `C-u' prefix arguments, use `org-timer-default-timer'
|
||||
without prompting the user for a duration and automatically
|
||||
replace any running timer."
|
||||
(interactive "P")
|
||||
|
|
|
@ -259,6 +259,7 @@ to add the symbol `xyz', and the package must have a call to
|
|||
(const :tag "C sqlinsert: Convert Org-mode tables to SQL insertions" orgtbl-sqlinsert)
|
||||
(const :tag "C toc: Table of contents for Org-mode buffer" org-toc)
|
||||
(const :tag "C track: Keep up with Org-mode development" org-track)
|
||||
(const :tag "C TaskJuggler: Export tasks to a TaskJuggler project" org-taskjuggler)
|
||||
(repeat :tag "External packages" :inline t (symbol :tag "Package"))))
|
||||
|
||||
(defcustom org-support-shift-select nil
|
||||
|
|
Loading…
Reference in New Issue