1
0
mirror of https://git.savannah.gnu.org/git/emacs/org-mode.git synced 2024-11-25 07:27:57 +00:00

Enhancement for the clocktable.

The clocktable can now more easily select the correct time range
that should be considered when summing times.  S-right and S-left
in the "#+BEGIN: clocktable" line allow to shift the time block around.

Also some code-cleanup.
This commit is contained in:
Carsten Dominik 2008-04-01 08:59:52 +02:00
parent a0be0664e2
commit 1aec2e86a5
5 changed files with 224 additions and 380 deletions

View File

@ -11,21 +11,22 @@ LISP (emacs-lisp code)
======================
org-annotate-file.el --- Annotate a file with org syntax
org2rem.el --- Convert org appointments into reminders
org-bibtex.el --- Org links to BibTeX entries
org-bookmark.el --- Org links to bookmarks
org-depend.el --- TODO dependencies for Org-mode
org-elisp-symbol.el --- Org links to emacs-lisp symbols
org-expiry.el --- expiry mechanism for Org entries
org-id.el --- Global id's for identifying entries
org-interactive-query.el --- Interactive modification of tags query
org-iswitchb.el --- use iswitchb to select Org buffer
org-mairix.el --- Hook mairix search into Org for different MUAs
org-man.el --- Support for links to manpages in Org-mode
org-mew.el --- Support for links to messages in Mew
org-panel.el --- Simple routines for us with bad memory
org-registry.el --- a registry for Org links
org2rem.el --- Convert org appointments into reminders
org-screen.el --- visit screen sessions through Org-mode links
org-toc.el --- Table of contents for Org-mode buffer
org-mairix.el --- Hook mairix search into Org for different MUAs
org-mew.el --- Support for links to messages in Mew
PACKAGES
========

View File

@ -1,310 +0,0 @@
;;; org-interactive-query.el --- Interactive modification of agenda query
;;
;; Copyright 2007 Free Software Foundation, Inc.
;;
;; Author: Christopher League <league at contrapunctus dot net>
;; Version: 1.0
;; Keywords: org, wp
;;
;; This program 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, or (at your option)
;; any later version.
;;
;; This program 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 this program; if not, write to the Free Software
;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;;
;;; Commentary:
;;
;; This ibrary implements interactive modification of a tags/todo query
;; in the org-agenda. It adds 4 keys to the agenda
;;
;; / add a keyword as a positive selection criterion
;; \ add a keyword as a newgative selection criterion
;; = clear a keyword from the selection string
;; ;
(require 'org)
(org-defkey org-agenda-mode-map "=" 'org-agenda-query-clear-cmd)
(org-defkey org-agenda-mode-map "/" 'org-agenda-query-and-cmd)
(org-defkey org-agenda-mode-map ";" 'org-agenda-query-or-cmd)
(org-defkey org-agenda-mode-map "\\" 'org-agenda-query-not-cmd)
;;; Agenda interactive query manipulation
(defcustom org-agenda-query-selection-single-key t
"Non-nil means, query manipulation exits after first change.
When nil, you have to press RET to exit it.
During query selection, you can toggle this flag with `C-c'.
This variable can also have the value `expert'. In this case, the window
displaying the tags menu is not even shown, until you press C-c again."
:group 'org-agenda
:type '(choice
(const :tag "No" nil)
(const :tag "Yes" t)
(const :tag "Expert" expert)))
(defun org-agenda-query-selection (current op table &optional todo-table)
"Fast query manipulation with single keys.
CURRENT is the current query string, OP is the initial
operator (one of \"+|-=\"), TABLE is an alist of tags and
corresponding keys, possibly with grouping information.
TODO-TABLE is a similar table with TODO keywords, should these
have keys assigned to them. If the keys are nil, a-z are
automatically assigned. Returns the new query string, or nil to
not change the current one."
(let* ((fulltable (append table todo-table))
(maxlen (apply 'max (mapcar
(lambda (x)
(if (stringp (car x)) (string-width (car x)) 0))
fulltable)))
(fwidth (+ maxlen 3 1 3))
(ncol (/ (- (window-width) 4) fwidth))
(expert (eq org-agenda-query-selection-single-key 'expert))
(exit-after-next org-agenda-query-selection-single-key)
(done-keywords org-done-keywords)
tbl char cnt e groups ingroup
tg c2 c c1 ntable rtn)
(save-window-excursion
(if expert
(set-buffer (get-buffer-create " *Org tags*"))
(delete-other-windows)
(split-window-vertically)
(org-switch-to-buffer-other-window (get-buffer-create " *Org tags*")))
(erase-buffer)
(org-set-local 'org-done-keywords done-keywords)
(insert "Query: " current "\n")
(org-agenda-query-op-line op)
(insert "\n\n")
(org-fast-tag-show-exit exit-after-next)
(setq tbl fulltable char ?a cnt 0)
(while (setq e (pop tbl))
(cond
((equal e '(:startgroup))
(push '() groups) (setq ingroup t)
(when (not (= cnt 0))
(setq cnt 0)
(insert "\n"))
(insert "{ "))
((equal e '(:endgroup))
(setq ingroup nil cnt 0)
(insert "}\n"))
(t
(setq tg (car e) c2 nil)
(if (cdr e)
(setq c (cdr e))
;; automatically assign a character.
(setq c1 (string-to-char
(downcase (substring
tg (if (= (string-to-char tg) ?@) 1 0)))))
(if (or (rassoc c1 ntable) (rassoc c1 table))
(while (or (rassoc char ntable) (rassoc char table))
(setq char (1+ char)))
(setq c2 c1))
(setq c (or c2 char)))
(if ingroup (push tg (car groups)))
(setq tg (org-add-props tg nil 'face
(cond
((not (assoc tg table))
(org-get-todo-face tg))
(t nil))))
(if (and (= cnt 0) (not ingroup)) (insert " "))
(insert "[" c "] " tg (make-string
(- fwidth 4 (length tg)) ?\ ))
(push (cons tg c) ntable)
(when (= (setq cnt (1+ cnt)) ncol)
(insert "\n")
(if ingroup (insert " "))
(setq cnt 0)))))
(setq ntable (nreverse ntable))
(insert "\n")
(goto-char (point-min))
(if (and (not expert) (fboundp 'fit-window-to-buffer))
(fit-window-to-buffer))
(setq rtn
(catch 'exit
(while t
(message "[a-z..]:Toggle [SPC]:clear [RET]:accept [TAB]:free%s%s"
(if groups " [!] no groups" " [!]groups")
(if expert " [C-c]:window" (if exit-after-next " [C-c]:single" " [C-c]:multi")))
(setq c (let ((inhibit-quit t)) (read-char-exclusive)))
(cond
((= c ?\r) (throw 'exit t))
((= c ?!)
(setq groups (not groups))
(goto-char (point-min))
(while (re-search-forward "[{}]" nil t) (replace-match " ")))
((= c ?\C-c)
(if (not expert)
(org-fast-tag-show-exit
(setq exit-after-next (not exit-after-next)))
(setq expert nil)
(delete-other-windows)
(split-window-vertically)
(org-switch-to-buffer-other-window " *Org tags*")
(and (fboundp 'fit-window-to-buffer)
(fit-window-to-buffer))))
((or (= c ?\C-g)
(and (= c ?q) (not (rassoc c ntable))))
(setq quit-flag t))
((= c ?\ )
(setq current "")
(if exit-after-next (setq exit-after-next 'now)))
((= c ?\[) ; clear left
(org-agenda-query-decompose current)
(setq current (concat "/" (match-string 2 current)))
(if exit-after-next (setq exit-after-next 'now)))
((= c ?\]) ; clear right
(org-agenda-query-decompose current)
(setq current (match-string 1 current))
(if exit-after-next (setq exit-after-next 'now)))
((= c ?\t)
(condition-case nil
(setq current (read-string "Query: " current))
(quit))
(if exit-after-next (setq exit-after-next 'now)))
;; operators
((or (= c ?/) (= c ?+)) (setq op "+"))
((or (= c ?\;) (= c ?|)) (setq op "|"))
((or (= c ?\\) (= c ?-)) (setq op "-"))
((= c ?=) (setq op "="))
;; todos
((setq e (rassoc c todo-table) tg (car e))
(setq current (org-agenda-query-manip
current op groups 'todo tg))
(if exit-after-next (setq exit-after-next 'now)))
;; tags
((setq e (rassoc c ntable) tg (car e))
(setq current (org-agenda-query-manip
current op groups 'tag tg))
(if exit-after-next (setq exit-after-next 'now))))
(if (eq exit-after-next 'now) (throw 'exit t))
(goto-char (point-min))
(beginning-of-line 1)
(delete-region (point) (point-at-eol))
(insert "Query: " current)
(beginning-of-line 2)
(delete-region (point) (point-at-eol))
(org-agenda-query-op-line op)
(goto-char (point-min)))))
(if rtn current nil))))
(defun org-agenda-query-op-line (op)
(insert "Operator: "
(org-agenda-query-op-entry (equal op "+") "/+" "and")
(org-agenda-query-op-entry (equal op "|") ";|" "or")
(org-agenda-query-op-entry (equal op "-") "\\-" "not")
(org-agenda-query-op-entry (equal op "=") "=" "clear")))
(defun org-agenda-query-op-entry (matchp chars str)
(if matchp
(org-add-props (format "[%s %s] " chars (upcase str))
nil 'face 'org-todo)
(format "[%s]%s " chars str)))
(defun org-agenda-query-decompose (current)
(string-match "\\([^/]*\\)/?\\(.*\\)" current))
(defun org-agenda-query-clear (current prefix tag)
(if (string-match (concat prefix "\\b" (regexp-quote tag) "\\b") current)
(replace-match "" t t current)
current))
(defun org-agenda-query-manip (current op groups kind tag)
"Apply an operator to a query string and a tag.
CURRENT is the current query string, OP is the operator, GROUPS is a
list of lists of tags that are mutually exclusive. KIND is 'tag for a
regular tag, or 'todo for a TODO keyword, and TAG is the tag or
keyword string."
;; If this tag is already in query string, remove it.
(setq current (org-agenda-query-clear current "[-\\+&|]?" tag))
(if (equal op "=") current
;; When using AND, also remove mutually exclusive tags.
(if (equal op "+")
(loop for g in groups do
(if (member tag g)
(mapc (lambda (x)
(setq current
(org-agenda-query-clear current "\\+" x)))
g))))
;; Decompose current query into q1 (tags) and q2 (TODOs).
(org-agenda-query-decompose current)
(let* ((q1 (match-string 1 current))
(q2 (match-string 2 current)))
(cond
((eq kind 'tag)
(concat q1 op tag "/" q2))
;; It's a TODO; when using AND, drop all other TODOs.
((equal op "+")
(concat q1 "/+" tag))
(t
(concat q1 "/" q2 op tag))))))
(defun org-agenda-query-global-todo-keys (&optional files)
"Return alist of all TODO keywords and their fast keys, in all FILES."
(let (alist)
(unless (and files (car files))
(setq files (org-agenda-files)))
(save-excursion
(loop for f in files do
(set-buffer (find-file-noselect f))
(loop for k in org-todo-key-alist do
(setq alist (org-agenda-query-merge-todo-key
alist k)))))
alist))
(defun org-agenda-query-merge-todo-key (alist entry)
(let (e)
(cond
;; if this is not a keyword (:startgroup, etc), ignore it
((not (stringp (car entry))))
;; if keyword already exists, replace char if it's null
((setq e (assoc (car entry) alist))
(when (null (cdr e)) (setcdr e (cdr entry))))
;; if char already exists, prepend keyword but drop char
((rassoc (cdr entry) alist)
(message "TRACE POSITION 2")
(setq alist (cons (cons (car entry) nil) alist)))
;; else, prepend COPY of entry
(t
(setq alist (cons (cons (car entry) (cdr entry)) alist)))))
alist)
(defun org-agenda-query-generic-cmd (op)
"Activate query manipulation with OP as initial operator."
(let ((q (org-agenda-query-selection org-agenda-query-string op
org-tag-alist
(org-agenda-query-global-todo-keys))))
(when q
(setq org-agenda-query-string q)
(org-agenda-redo))))
(defun org-agenda-query-clear-cmd ()
"Activate query manipulation, to clear a tag from the string."
(interactive)
(org-agenda-query-generic-cmd "="))
(defun org-agenda-query-and-cmd ()
"Activate query manipulation, initially using the AND (+) operator."
(interactive)
(org-agenda-query-generic-cmd "+"))
(defun org-agenda-query-or-cmd ()
"Activate query manipulation, initially using the OR (|) operator."
(interactive)
(org-agenda-query-generic-cmd "|"))
(defun org-agenda-query-not-cmd ()
"Activate query manipulation, initially using the NOT (-) operator."
(interactive)
(org-agenda-query-generic-cmd "-"))
(provide 'org-interactive-query)

View File

@ -1,3 +1,17 @@
2008-04-01 Carsten Dominik <dominik@science.uva.nl>
* lisp/org.el (org-modules): Allow additional symbols for external
packages.
(org-ctrl-c-ctrl-c): Allow for `org-clock-overlays' to be
undefined.
2008-03-31 Carsten Dominik <dominik@science.uva.nl>
* lisp/org.el (org-clock-goto): Hide drawers after showing an
entry with `org-clock-goto.'
(org-shiftup, org-shiftdown, org-shiftright, org-shiftleft): Try
also a clocktable block shift.
(org-clocktable-try-shift): New function.
2008-03-30 Carsten Dominik <dominik@science.uva.nl>

View File

@ -5,10 +5,45 @@
#+EMAIL: carsten at orgmode dot org
#+OPTIONS: H:3 num:nil toc:nil \n:nil @:t ::t |:t ^:{} *:t TeX:t LaTeX:nil
* Version 5.24
* Version 6.00
** Details
*** Improvements to clocktable
- The clocktable is now much more flexible and user friendly
when trying to specify the time block that should be
considered when constructing the table.
The =:block= parameter to the table can now look like any
of these:
| :block | meaning |
|--------------+-----------------------|
| 2008 | The entire year 2008 |
| 2008-04 | The month April 2008 |
| 2008-04-02 | The day April 2, 2008 |
| 2008-W14 | ISO-Week 14 in 2008 |
| today | Today |
| today-5 | The day five days ago |
| thisweek | The current week |
| thisweek-2 | Two weeks ago |
| thismonth | The current month |
| thismonth-12 | Same month, last year |
| lastmonth | Same as thismonth-1 |
What is more, you can now use the =S-left= and =S-right=
keys while the cursor is on the =#+BEGIN: clocktable= line
and the the time block around. If the current block is
=today=, =S-left= with switch to yesterday. If the current
block is =2008-W14=, =S-right= will switch to the following
week.
- When the clocktable is collecting from several files, the
total time for each file will now also be listed. This was
a request from Bernt Hansen.
*** Selective tag inheritance
Inheritance of tags can now be limited to a subset of all
@ -17,7 +52,7 @@
the inherited tags. Thanks to Michael Ekstrand for this
excellent proposal.
The regexp option is also inplemented for
The regexp option is also implemented for
=org-use-property-inheritance=, so that you can now select
properties for inheritance my name.
@ -25,11 +60,11 @@
The INHERIT flag to the function =org-entry-get= can be set
to the symbol =selective=. If this is the case, then the
value of the property will be retrived using inheritance if
value of the property will be retrieved using inheritance if
and only if the setting in =org-use-property-inheritance=
selects the property for inheritance.
*** Suport for ISO week dates (ISO 6801)
*** Support for ISO week dates (ISO 6801)
Dates in the agenda now show the ISO week an day
specification, in the form =W08 2=, meaning Tuesday of
@ -43,8 +78,8 @@
or year, respectively. For example, =32 d= jumps to February
1st, =9 w= to ISO week number 9. When setting day, week, or
month view, a year may be encoded in the prefix argument as
well. For example, =200712 w= will jump to week 12 in
2007. If such a year specification has only one or two
well. For example, =200712 w= will jump to week 12 in the
year 2007. If such a year specification has only one or two
digits, it will be mapped to the interval 1938-2037.
When entering a date at the date prompt, you may now also
@ -56,7 +91,7 @@
: 2012 w4 fri Friday of week 4 in 2012.
: 2012-W04-5 Same as above
So far I have not implements the effect of
So far I have not implemented the effect of
`org-read-date-prefer-future' on this functionality, because
it seemed too magic for me. I'd appreciate comments on this
issue: Should `org-read-date-prefer-future' also push dates
@ -84,19 +119,19 @@
*** Improvements in Search View
- Calling search view with a C-u prefix will makt it match
- Calling search view with a C-u prefix will make it match
only in TODO entries.
- The single quote is no longer considered a word character
durin search, so that searching for the word "Nasim" will
during search, so that searching for the word "Nasim" will
also match in "Nasim's".
*** Misc
- When an entry already has a scheduling or deadline time
stamp, calling `C-c C-s' or `C-c C-d', respectively, will no
use that old date as the default, and you can can use the
"++4d" syntax to invoke shifts relative to that default
stamp, calling `C-c C-s' or `C-c C-d', respectively, will
now use that old date as the default, and you can can use
the "++4d" syntax to invoke shifts relative to that default
date. Simply pressing RET at the prompt will keep the
default date, not switch to today.
@ -3775,3 +3810,4 @@ Version 4.00

View File

@ -141,11 +141,16 @@ With prefix arg HERE, insert it at point."
(defcustom org-modules '(org-bbdb org-gnus org-info org-irc org-mhe org-rmail org-vm org-wl)
"Modules that should always be loaded together with org.el.
If the description starts with <A>, this means the extension
will be autoloaded when needed, preloading is not necessary.
If a description starts with <C>, the file is not part of emacs
and loading it will require that you have downloaded and properly installed
the org-mode distribution."
the org-mode distribution.
You can also use this system to load external packages (i.e. neither Org
core modules, not modules from the CONTRIB directory). Just add symbols
to the end of the list. If the package is called org-xyz.e, then you need
to add the symbol `xyz', and the package must have a call to
(provide 'org-xyz)"
:group 'org
:set 'org-set-modules
:type
@ -160,11 +165,10 @@ the org-mode distribution."
(const :tag " vm: Links to VM folders/messages" org-vm)
(const :tag " wl: Links to Wanderlust folders/messages" org-wl)
(const :tag " mouse: Additional mouse support" org-mouse)
; (const :tag "A export-latex: LaTeX export" org-export-latex)
; (const :tag "A publish: Publishing" org-publish)
(const :tag "C annotate-file: Annotate a file with org syntax" org-annotate-file)
(const :tag "C bibtex: Org links to BibTeX entries" org-bibtex)
(const :tag "C bookmark: Org links to bookmarks" org-bookmark)
(const :tag "C depend: TODO dependencies for Org-mode" org-depend)
(const :tag "C elisp-symbol: Org links to emacs-lisp symbols" org-elisp-symbol)
(const :tag "C expiry: Expiry mechanism for Org entries" org-expiry)
@ -178,7 +182,8 @@ the org-mode distribution."
(const :tag "C registry: A registry for Org links" org-registry)
(const :tag "C org2rem: Convert org appointments into reminders" org2rem)
(const :tag "C screen: Visit screen sessions through Org-mode links" org-screen)
(const :tag "C toc: Table of contents for Org-mode buffer" org-toc)))
(const :tag "C toc: Table of contents for Org-mode buffer" org-toc)
(repeat :tag "External packages" :inline t (symbol :tag "Package"))))
;; FIXME: Needs a separate group...
(defcustom org-completion-fallback-command 'hippie-expand
@ -12767,6 +12772,7 @@ If there is no running clock, throw an error, unless FAIL-QUIETLY is set."
(goto-char org-clock-marker)
(org-show-entry)
(org-back-to-heading)
(org-cycle-hide-drawers 'children)
(recenter))
(defvar org-clock-file-total-minutes nil
@ -12981,38 +12987,125 @@ The range is determined relative to TIME. TIME defaults to the current time.
The return value is a cons cell with two internal times like the ones
returned by `current time' or `encode-time'. if AS-STRINGS is non-nil,
the returned times will be formatted strings."
(if (integerp key) (setq key (intern (number-to-string key))))
(let* ((tm (decode-time (or time (current-time))))
(s 0) (m (nth 1 tm)) (h (nth 2 tm))
(d (nth 3 tm)) (month (nth 4 tm)) (y (nth 5 tm))
(dow (nth 6 tm))
s1 m1 h1 d1 month1 y1 diff ts te fm)
(skey (symbol-name key))
(shift 0)
s1 m1 h1 d1 month1 y1 diff ts te fm txt w date)
(cond
((eq key 'today)
(setq h 0 m 0 h1 24 m1 0))
((eq key 'yesterday)
(setq d (1- d) h 0 m 0 h1 24 m1 0))
((eq key 'thisweek)
(setq diff (if (= dow 0) 6 (1- dow))
((string-match "^[0-9]+$" skey)
(setq y (string-to-number skey) m 1 d 1 key 'year))
((string-match "^\\([0-9]+\\)-\\([0-9]\\{1,2\\}\\)$" skey)
(setq y (string-to-number (match-string 1 skey))
month (string-to-number (match-string 2 skey))
d 1 key 'month))
((string-match "^\\([0-9]+\\)-[wW]\\([0-9]\\{1,2\\}\\)$" skey)
(require 'cal-iso)
(setq y (string-to-number (match-string 1 skey))
w (string-to-number (match-string 2 skey)))
(setq date (calendar-gregorian-from-absolute
(calendar-absolute-from-iso (list w 1 y))))
(setq d (nth 1 date) month (car date) y (nth 2 date)
key 'week))
((string-match "^\\([0-9]+\\)-\\([0-9]\\{1,2\\}\\)-\\([0-9]\\{1,2\\}\\)$" skey)
(setq y (string-to-number (match-string 1 skey))
month (string-to-number (match-string 2 skey))
d (string-to-number (match-string 3 skey))
key 'day))
((string-match "\\([-+][0-9]+\\)$" skey)
(setq shift (string-to-number (match-string 1 skey))
key (intern (substring skey 0 (match-beginning 1))))))
(unless shift
(cond ((eq key 'yesterday) (setq key 'today shift -1))
((eq key 'lastweek) (setq key 'week shift -1))
((eq key 'lastmonth) (setq key 'month shift -1))
((eq key 'lastyear) (setq key 'year shift -1))))
(cond
((memq key '(day today))
(setq d (+ d shift) h 0 m 0 h1 24 m1 0))
((memq key '(week thisweek))
(setq diff (+ (* -7 shift) (if (= dow 0) 6 (1- dow)))
m 0 h 0 d (- d diff) d1 (+ 7 d)))
((eq key 'lastweek)
(setq diff (+ 7 (if (= dow 0) 6 (1- dow)))
m 0 h 0 d (- d diff) d1 (+ 7 d)))
((eq key 'thismonth)
(setq d 1 h 0 m 0 d1 1 month1 (1+ month) h1 0 m1 0))
((eq key 'lastmonth)
(setq d 1 h 0 m 0 d1 1 month (1- month) month1 (1+ month) h1 0 m1 0))
((eq key 'thisyear)
(setq m 0 h 0 d 1 month 1 y1 (1+ y)))
((eq key 'lastyear)
(setq m 0 h 0 d 1 month 1 y (1- y) y1 (1+ y)))
((memq key '(month thismonth))
(setq d 1 h 0 m 0 d1 1 month (+ month shift) month1 (1+ month) h1 0 m1 0))
((memq key '(year thisyear))
(setq m 0 h 0 d 1 month 1 y (+ y shift) y1 (1+ y)))
(t (error "No such time block %s" key)))
(setq ts (encode-time s m h d month y)
te (encode-time (or s1 s) (or m1 m) (or h1 h)
(or d1 d) (or month1 month) (or y1 y)))
(setq fm (cdr org-time-stamp-formats))
(cond
((memq key '(day today))
(setq txt (format-time-string "%A, %B %d, %Y" ts)))
((memq key '(week thisweek))
(setq txt (format-time-string "week %G-W%V" ts)))
((memq key '(month thismonth))
(setq txt (format-time-string "%B %Y" ts)))
((memq key '(year thisyear))
(setq txt (format-time-string "the year %Y" ts))))
(if as-strings
(cons (format-time-string fm ts) (format-time-string fm te))
(cons ts te))))
(list (format-time-string fm ts) (format-time-string fm te) txt)
(list ts te txt))))
(defun org-clocktable-try-shift (dir n)
"Try to shift the :block date of the clocktable at point.
Point must be in the #+BEGIN: line of a clocktable, or this function
will throw an error.
DIR is a direction, a symbol `left', `right', `up', or `down'.
Both `left' and `down' shift the block toward the past, `up' and `right'
push it toward the future.
N is the number of shift steps to take. The size of the step depends on
the currently selected interval size."
(setq n (prefix-numeric-value n))
(and (memq dir '(left down)) (setq n (- n)))
(save-excursion
(goto-char (point-at-bol))
(when (looking-at "#\\+BEGIN: clocktable\\>.*?:block[ \t]+\\(\\S-+\\)")
(let* ((b (match-beginning 1)) (e (match-end 1))
(s (match-string 1))
block shift ins y mw d date)
(cond
((string-match "^\\(today\\|thisweek\\|thismonth\\|thisyear\\)\\([-+][0-9]+\\)?$" s)
(setq block (match-string 1 s)
shift (if (match-end 2)
(string-to-number (match-string 2 s))
0))
(setq shift (+ shift n))
(setq ins (if (= shift 0) block (format "%s%+d" block shift))))
((string-match "\\([0-9]+\\)\\(-\\([wW]?\\)\\([0-9]\\{1,2\\}\\)\\(-\\([0-9]\\{1,2\\}\\)\\)?\\)?" s)
;; 1 1 2 3 3 4 4 5 6 6 5 2
(setq y (string-to-number (match-string 1 s))
wp (and (match-end 3) (match-string 3 s))
mw (and (match-end 4) (string-to-number (match-string 4 s)))
d (and (match-end 6) (string-to-number (match-string 6 s))))
(cond
(d (setq ins (format-time-string
"%Y-%m-%d"
(encode-time 0 0 0 (+ d n) m y))))
((and wp mw (> (length wp) 0))
(require 'cal-iso)
(setq date (calendar-gregorian-from-absolute (calendar-absolute-from-iso (list (+ mw n) 1 y))))
(setq ins (format-time-string
"%G-W%V"
(encode-time 0 0 0 (nth 1 date) (car date) (nth 2 date)))))
(mw
(setq ins (format-time-string
"%Y-%m"
(encode-time 0 0 0 1 (+ mw n) y))))
(y
(setq ins (number-to-string (+ y n))))))
(t (error "Cannot shift clocktable block")))
(when ins
(goto-char b)
(insert ins)
(delete-region (point) (+ (point) (- e b)))
(beginning-of-line 1)
(org-update-dblock)
t)))))
(defun org-dblock-write:clocktable (params)
"Write the standard clocktable."
@ -13031,14 +13124,14 @@ the returned times will be formatted strings."
(te (plist-get params :tend))
(block (plist-get params :block))
(link (plist-get params :link))
ipos time h m p level hlc hdl
cc beg end pos tbl)
ipos time p level hlc hdl
cc beg end pos tbl tbl1 range-text)
(when step
(org-clocktable-steps params)
(throw 'exit nil))
(when block
(setq cc (org-clock-special-range block nil t)
ts (car cc) te (cdr cc)))
ts (car cc) te (nth 1 cc) range-text (nth 2 cc)))
(if ts (setq ts (time-to-seconds
(apply 'encode-time (org-parse-time-string ts)))))
(if te (setq te (time-to-seconds
@ -13076,10 +13169,17 @@ the returned times will be formatted strings."
(org-prepare-agenda-buffers files)
(while (setq file (pop files))
(with-current-buffer (find-buffer-visiting file)
(push (org-clocktable-add-file
file (org-dblock-write:clocktable p1)) tbl)
(setq total-time (+ (or total-time 0)
org-clock-file-total-minutes)))))))
(setq tbl1 (org-dblock-write:clocktable p1))
(when tbl1
(push (org-clocktable-add-file
file
(concat "| |*File time*|*"
(org-minutes-to-hours
org-clock-file-total-minutes)
"*|\n"
tbl1)) tbl)
(setq total-time (+ (or total-time 0)
org-clock-file-total-minutes))))))))
(goto-char pos)
(unless (eq scope 'agenda)
@ -13103,14 +13203,12 @@ the returned times will be formatted strings."
(save-match-data
(org-make-org-heading-search-string
(match-string 2))))
(match-string 2)))
h (/ time 60)
m (- time (* 60 h)))
(match-string 2))))
(if (and (not multifile) (= level 1)) (push "|-" tbl))
(push (concat
"| " (int-to-string level) "|" hlc hdl hlc " |"
(make-string (1- level) ?|)
hlc (format "%d:%02d" h m) hlc
hlc (org-minutes-to-hours time) hlc
" |") tbl))))))
(setq tbl (nreverse tbl))
(if tostring
@ -13123,23 +13221,19 @@ the returned times will be formatted strings."
(substring
(format-time-string (cdr org-time-stamp-formats))
1 -1)
"]."
(if block
(format " Considered range is /%s/." block)
"")
"]"
(if block (concat ", for " range-text ".") "")
"\n\n"))
(if (eq scope 'agenda) "|File" "")
"|L|Headline|Time|\n")
(setq total-time (or total-time org-clock-file-total-minutes)
h (/ total-time 60)
m (- total-time (* 60 h)))
(setq total-time (or total-time org-clock-file-total-minutes))
(insert-before-markers
"|-\n|"
(if (eq scope 'agenda) "|" "")
"|"
"*Total time*| "
(format "*%d:%02d*" h m)
"|\n|-\n")
"*Total time*| *"
(org-minutes-to-hours total-time)
"*|\n|-\n")
(setq tbl (delq nil tbl))
(if (and (stringp (car tbl)) (> (length (car tbl)) 1)
(equal (substring (car tbl) 0 2) "|-"))
@ -13152,6 +13246,11 @@ the returned times will be formatted strings."
(skip-chars-forward "^|")
(org-table-align))))))
(defun org-minutes-to-hours (m)
(let ((h (/ m 60)))
(setq m (- m (* 60 h)))
(format "%d:%02d" h m)))
(defun org-clocktable-steps (params)
(let* ((p1 (copy-sequence params))
(ts (plist-get p1 :tstart))
@ -13159,10 +13258,10 @@ the returned times will be formatted strings."
(step0 (plist-get p1 :step))
(step (cdr (assoc step0 '((day . 86400) (week . 604800)))))
(block (plist-get p1 :block))
cc)
cc range-text)
(when block
(setq cc (org-clock-special-range block nil t)
ts (car cc) te (cdr cc)))
ts (car cc) te (nth 1 cc) range-text (nth 2 cc)))
(if ts (setq ts (time-to-seconds
(apply 'encode-time (org-parse-time-string ts)))))
(if te (setq te (time-to-seconds
@ -14149,6 +14248,7 @@ depending on context. See the individual commands for more information."
'org-timestamp-down 'org-timestamp-up)))
((org-on-heading-p) (call-interactively 'org-priority-up))
((org-at-item-p) (call-interactively 'org-previous-item))
((org-clocktable-try-shift 'up arg))
(t (call-interactively 'org-beginning-of-item) (beginning-of-line 1))))
(defun org-shiftdown (&optional arg)
@ -14161,27 +14261,30 @@ depending on context. See the individual commands for more information."
(call-interactively (if org-edit-timestamp-down-means-later
'org-timestamp-up 'org-timestamp-down)))
((org-on-heading-p) (call-interactively 'org-priority-down))
((org-clocktable-try-shift 'down arg))
(t (call-interactively 'org-next-item))))
(defun org-shiftright ()
(defun org-shiftright (&optional arg)
"Next TODO keyword or timestamp one day later, depending on context."
(interactive)
(interactive "P")
(cond
((org-at-timestamp-p t) (call-interactively 'org-timestamp-up-day))
((org-on-heading-p) (org-call-with-arg 'org-todo 'right))
((org-at-item-p) (org-call-with-arg 'org-cycle-list-bullet nil))
((org-at-property-p) (call-interactively 'org-property-next-allowed-value))
((org-clocktable-try-shift 'right arg))
(t (org-shiftcursor-error))))
(defun org-shiftleft ()
(defun org-shiftleft (&optional arg)
"Previous TODO keyword or timestamp one day earlier, depending on context."
(interactive)
(interactive "P")
(cond
((org-at-timestamp-p t) (call-interactively 'org-timestamp-down-day))
((org-on-heading-p) (org-call-with-arg 'org-todo 'left))
((org-at-item-p) (org-call-with-arg 'org-cycle-list-bullet 'previous))
((org-at-property-p)
(call-interactively 'org-property-previous-allowed-value))
((org-clocktable-try-shift 'left arg))
(t (org-shiftcursor-error))))
(defun org-shiftcontrolright ()
@ -14268,10 +14371,10 @@ This command does many different things, depending on context:
(interactive "P")
(let ((org-enable-table-editor t))
(cond
((or org-clock-overlays
((or (and (boundp 'org-clock-overlays) org-clock-overlays)
org-occur-highlights
org-latex-fragment-image-overlays)
(org-remove-clock-overlays)
(and (boundp 'org-clock-overlays) (org-remove-clock-overlays))
(org-remove-occur-highlights)
(org-remove-latex-fragment-image-overlays)
(message "Temporary highlights/overlays removed from current buffer"))