Added a link to Greg Newman's article: "Backing up Org files".
[Worg.git] / org-hacks.org
blobba5a113347049cc1bb657b8da13cbbe7adfb2f2d
1 #+OPTIONS:    H:3 num:nil toc:t \n:nil @:t ::t |:t ^:t -:t f:t *:t TeX:t LaTeX:t skip:nil d:(HIDE) tags:not-in-toc
2 #+STARTUP:    align fold nodlcheck hidestars oddeven lognotestate
3 #+SEQ_TODO:   TODO(t) INPROGRESS(i) WAITING(w@) | DONE(d) CANCELED(c@)
4 #+TAGS:       Write(w) Update(u) Fix(f) Check(c)
5 #+TITLE:      Org ad hoc code, quick hacks and workarounds
6 #+AUTHOR:     Worg people
7 #+EMAIL:      bzg AT altern DOT org
8 #+LANGUAGE:   en
9 #+PRIORITIES: A C B
10 #+CATEGORY:   worg
12 # This file is the default header for new Org files in Worg.  Feel free
13 # to tailor it to your needs.
15 [[file:index.org][{Back to Worg's index}]]
17 This page is for ad hoc bits of code.  Feel free to add quick hacks and
18 workaround.  Go crazy.
20 * Automatically add an appointment when clocking in a task
22 #+BEGIN_SRC emacs-lisp
23 ;; Make sure you have a sensible value for `appt-message-warning-time'
24 (defvar bzg-org-clock-in-appt-delay 100
25   "Number of minutes for setting an appointment by clocking-in")
26 #+END_SRC
28 This function let's you add an appointment for the current entry.
29 This can be useful when you need a reminder.
31 #+BEGIN_SRC emacs-lisp
32 (defun bzg-org-clock-in-add-appt (&optional n)
33   "Add an appointment for the Org entry at point in N minutes."
34   (interactive)
35   (save-excursion
36     (org-back-to-heading t)
37     (looking-at org-complex-heading-regexp)
38     (let* ((msg (match-string-no-properties 4))
39            (ct-time (decode-time))
40            (appt-min (+ (cadr ct-time)
41                         (or n bzg-org-clock-in-appt-delay)))
42            (appt-time ; define the time for the appointment
43             (progn (setf (cadr ct-time) appt-min) ct-time)))
44       (appt-add (format-time-string
45                  "%H:%M" (apply 'encode-time appt-time)) msg)
46       (if (interactive-p) (message "New appointment for %s" msg)))))
47 #+END_SRC
49 You can advise =org-clock-in= so that =C-c C-x C-i= will automatically
50 add an appointment:
52 #+BEGIN_SRC emacs-lisp
53 (defadvice org-clock-in (after org-clock-in-add-appt activate)
54   "Add an appointment when clocking a task in."
55   (bzg-org-clock-in-add-appt))
56 #+END_SRC
58 You may also want to delete the associated appointment when clocking
59 out.  This function does this:
61 #+BEGIN_SRC emacs-lisp
62 (defun bzg-org-clock-out-delete-appt nil
63   "When clocking out, delete any associated appointment."
64   (interactive)
65   (save-excursion
66     (org-back-to-heading t)
67     (looking-at org-complex-heading-regexp)
68     (let* ((msg (match-string-no-properties 4)))
69       (setq appt-time-msg-list
70             (delete nil
71                     (mapcar
72                      (lambda (appt)
73                        (if (not (string-match (regexp-quote msg)
74                                               (cadr appt))) appt))
75                      appt-time-msg-list)))
76       (appt-check))))
77 #+END_SRC
79 And here is the advice for =org-clock-out= (=C-c C-x C-o=)
81 #+BEGIN_SRC emacs-lisp
82 (defadvice org-clock-out (before org-clock-out-delete-appt activate)
83   "Delete an appointment when clocking a task out."
84   (bzg-org-clock-out-delete-appt))
85 #+END_SRC
87 *IMPORTANT*: You can add appointment by clocking in in both an
88 =org-mode= and an =org-agenda-mode= buffer.  But clocking out from
89 agenda buffer with the advice above will bring an error.
91 * Use Org-mode with Screen [Andrew Hyatt]
93 "The general idea is that you start a task in which all the work will
94 take place in a shell.  This usually is not a leaf-task for me, but
95 usually the parent of a leaf task.  From a task in your org-file, M-x
96 ash-org-screen will prompt for the name of a session.  Give it a name,
97 and it will insert a link.  Open the link at any time to go the screen
98 session containing your work!"
100 http://article.gmane.org/gmane.emacs.orgmode/5276
102 #+BEGIN_SRC emacs-lisp
103 (require 'term)
105 (defun ash-org-goto-screen (name)
106   "Open the screen with the specified name in the window"
107   (interactive "MScreen name: ")
108   (let ((screen-buffer-name (ash-org-screen-buffer-name name)))
109     (if (member screen-buffer-name
110                 (mapcar 'buffer-name (buffer-list)))
111         (switch-to-buffer screen-buffer-name)
112       (switch-to-buffer (ash-org-screen-helper name "-dr")))))
114 (defun ash-org-screen-buffer-name (name)
115   "Returns the buffer name corresponding to the screen name given."
116   (concat "*screen " name "*"))
118 (defun ash-org-screen-helper (name arg)
119   ;; Pick the name of the new buffer.
120   (let ((term-ansi-buffer-name
121          (generate-new-buffer-name
122           (ash-org-screen-buffer-name name))))
123     (setq term-ansi-buffer-name
124           (term-ansi-make-term
125            term-ansi-buffer-name "/usr/bin/screen" nil arg name))
126     (set-buffer term-ansi-buffer-name)
127     (term-mode)
128     (term-char-mode)
129     (term-set-escape-char ?\C-x)
130     term-ansi-buffer-name))
132 (defun ash-org-screen (name)
133   "Start a screen session with name"
134   (interactive "MScreen name: ")
135   (save-excursion
136     (ash-org-screen-helper name "-S"))
137   (insert-string (concat "[[screen:" name "]]")))
139 ;; And don't forget to add ("screen" . "elisp:(ash-org-goto-screen
140 ;; \"%s\")") to org-link-abbrev-alist.
141 #+END_SRC
143 * Org Agenda + Appt + Zenity
145 Russell Adams posted this setup [[http://article.gmane.org/gmane.emacs.orgmode/5806][on the list]].  It make sure your agenda
146 appointments are known by Emacs, and it displays warnings in a [[http://live.gnome.org/Zenity][zenity]]
147 popup window.
149 #+BEGIN_SRC emacs-lisp
150 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
151 ; For org appointment reminders
153 ;; Get appointments for today
154 (defun my-org-agenda-to-appt ()
155   (interactive)
156   (setq appt-time-msg-list nil)
157   (let ((org-deadline-warning-days 0))    ;; will be automatic in org 5.23
158         (org-agenda-to-appt)))
160 ;; Run once, activate and schedule refresh
161 (my-org-agenda-to-appt)
162 (appt-activate t)
163 (run-at-time "24:01" nil 'my-org-agenda-to-appt)
165 ; 5 minute warnings
166 (setq appt-message-warning-time 15)
167 (setq appt-display-interval 5)
169 ; Update appt each time agenda opened.
170 (add-hook 'org-finalize-agenda-hook 'my-org-agenda-to-appt)
172 ; Setup zenify, we tell appt to use window, and replace default function
173 (setq appt-display-format 'window)
174 (setq appt-disp-window-function (function my-appt-disp-window))
176 (defun my-appt-disp-window (min-to-app new-time msg)
177   (save-window-excursion (shell-command (concat
178     "/usr/bin/zenity --info --title='Appointment' --text='"
179     msg "' &") nil nil)))
180 #+END_SRC
182 * Org-Mode + gnome-osd
184 Richard Riley uses gnome-osd in interaction with Org-Mode to display
185 appointments.  You can look at the code on the [[http://www.emacswiki.org/emacs-en/OrgMode-OSD][emacswiki]].
187 * remind2org
189   From Detlef Steuer
191 http://article.gmane.org/gmane.emacs.orgmode/5073
193 #+BEGIN_QUOTE
194 Remind (http://www.roaringpenguin.com/products/remind) is a very powerful
195 command line calendaring program. Its features superseed the possibilities
196 of orgmode in the area of date specifying, so that I want to use it
197 combined with orgmode.
199 Using the script below I'm able use remind and incorporate its output in my
200 agenda views.  The default of using 13 months look ahead is easily
201 changed. It just happens I sometimes like to look a year into the
202 future. :-)
203 #+END_QUOTE
205 * org-remember-anything
207 [[http://www.emacswiki.org/cgi-bin/wiki/Anything][Anything]] users may find the snippet below interesting:
209 #+BEGIN_SRC emacs-lisp
210 (defvar org-remember-anything
211   '((name . "Org Remember")
212     (candidates . (lambda () (mapcar 'car org-remember-templates)))
213     (action . (lambda (name)
214                 (let* ((orig-template org-remember-templates)
215                        (org-remember-templates
216                         (list (assoc name orig-template))))
217                   (call-interactively 'org-remember))))))
218 #+END_SRC
220 You can add it to your 'anything-sources' variable and open remember directly
221 from anything. I imagine this would be more interesting for people with many
222 remember templatesm, so that you are out of keys to assign those to. You should
223 get something like this:
225 [[file:images/thumbs/org-remember-anything.png]]
227 * Reload Org
229 As of Org version 6.23b (released Sunday Feb 22, 2009) there is a new
230 function to reload org files.
232 Normally you want to use the compiled files since they are faster.
233 If you update your org files you can easily reload them with
235 : M-x org-reload
237 If you run into a bug and want to generate a useful backtrace you can
238 reload the source files instead of the compiled files with
240 : C-u M-x org-reload
242 and turn on the "Enter Debugger On Error" option.  Redo the action
243 that generates the error and cut and paste the resulting backtrace.
244 To switch back to the compiled version just reload again with
246 : M-x org-reload
248 * Split horizontally for agenda
250 If you would like to split the frame into two side-by-side windows when
251 displaying the agenda, try this hack from Jan Rehders, which uses the
252 `toggle-window-split' from
254 http://www.emacswiki.org/cgi-bin/wiki/ToggleWindowSplit
256 #+BEGIN_SRC emacs-lisp
257 ;; Patch org-mode to use vertical splitting
258 (defadvice org-prepare-agenda (after org-fix-split)
259   (toggle-window-split))
260 (ad-activate 'org-prepare-agenda)
261 #+END_SRC
262 * Highlight the agenda line under cursor
264 This is useful to make sure what task you are operating on.
266 #+BEGIN_SRC emacs-lisp
267 (add-hook 'org-agenda-mode-hook '(lambda () (hl-line-mode 1)))
268 #+END_SRC emacs-lisp
270 Under XEmacs:
272 #+BEGIN_SRC emacs-lisp
273 ;; hl-line seems to be only for emacs
274 (require 'highline)
275 (add-hook 'org-agenda-mode-hook '(lambda () (highline-mode 1)))
277 ;; highline-mode does not work straightaway in tty mode.
278 ;; I use a black background
279 (custom-set-faces
280   '(highline-face ((((type tty) (class color))
281                     (:background "white" :foreground "black")))))
282 #+END_SRC emacs-lisp
284 * Remove time grid lines that are in an appointment
286 The agenda shows lines for the time grid.  Some people think that
287 these lines are a distraction when there are appointments at those
288 times.  You can get rid of the lines which coincide exactly with the
289 beginning of an appointment.  Michael Ekstrand has written a piece of
290 advice that also removes lines that are somewhere inside an
291 appointment:
293 #+begin_src emacs-lisp
294 (defun org-time-to-minutes (time)
295   "Convert an HHMM time to minutes"
296   (+ (* (/ time 100) 60) (% time 100)))
298 (defun org-time-from-minutes (minutes)
299   "Convert a number of minutes to an HHMM time"
300   (+ (* (/ minutes 60) 100) (% minutes 60)))
302 (defadvice org-agenda-add-time-grid-maybe (around mde-org-agenda-grid-tweakify
303                                                   (list ndays todayp))
304   (if (member 'remove-match (car org-agenda-time-grid))
305       (flet ((extract-window
306               (line)
307               (let ((start (get-text-property 1 'time-of-day line))
308                     (dur (get-text-property 1 'duration line)))
309                 (cond
310                  ((and start dur)
311                   (cons start
312                         (org-time-from-minutes
313                          (+ dur (org-time-to-minutes start)))))
314                  (start start)
315                  (t nil)))))
316         (let* ((windows (delq nil (mapcar 'extract-window list)))
317                (org-agenda-time-grid
318                 (list (car org-agenda-time-grid)
319                       (cadr org-agenda-time-grid)
320                       (remove-if
321                        (lambda (time)
322                          (find-if (lambda (w)
323                                     (if (numberp w)
324                                         (equal w time)
325                                       (and (>= time (car w))
326                                            (< time (cdr w)))))
327                                   windows))
328                        (caddr org-agenda-time-grid)))))
329           ad-do-it))
330     ad-do-it))
331 (ad-activate 'org-agenda-add-time-grid-maybe)
332 #+end_src
334 * Group task list by a property
336 This advice allows you to group a task list in Org-Mode.  To use it,
337 set the variable =org-agenda-group-by-property= to the name of a
338 property in the option list for a TODO or TAGS search.  The resulting
339 agenda view will group tasks by that property prior to searching.
341 #+begin_src emacs-lisp
342 (defvar org-agenda-group-by-property nil
343   "Set this in org-mode agenda views to group tasks by property")
345 (defun org-group-bucket-items (prop items)
346   (let ((buckets ()))
347     (dolist (item items)
348       (let* ((marker (get-text-property 0 'org-marker item))
349              (pvalue (org-entry-get marker prop t))
350              (cell (assoc pvalue buckets)))
351         (if cell
352             (setcdr cell (cons item (cdr cell)))
353           (setq buckets (cons (cons pvalue (list item))
354                               buckets)))))
355     (setq buckets (mapcar (lambda (bucket)
356                             (cons (car bucket)
357                                   (reverse (cdr bucket))))
358                           buckets))
359     (sort buckets (lambda (i1 i2)
360                     (string< (car i1) (car i2))))))
362 (defadvice org-finalize-agenda-entries (around org-group-agenda-finalize
363                                                (list &optional nosort))
364   "Prepare bucketed agenda entry lists"
365   (if org-agenda-group-by-property
366       ;; bucketed, handle appropriately
367       (let ((text ""))
368         (dolist (bucket (org-group-bucket-items
369                          org-agenda-group-by-property
370                          list))
371           (let ((header (concat "Property "
372                                 org-agenda-group-by-property
373                                 " is "
374                                 (or (car bucket) "<nil>") ":\n")))
375             (add-text-properties 0 (1- (length header))
376                                  (list 'face 'org-agenda-structure)
377                                  header)
378             (setq text
379                   (concat text header
380                           ;; recursively process
381                           (let ((org-agenda-group-by-property nil))
382                             (org-finalize-agenda-entries
383                              (cdr bucket) nosort))
384                           "\n\n"))))
385         (setq ad-return-value text))
386     ad-do-it))
387 (ad-activate 'org-finalize-agenda-entries)
388 #+end_src
389 * Link to Gnus messages by Message-Id
391 In a [[http://thread.gmane.org/gmane.emacs.orgmode/8860][recent thread]] on the Org-Mode mailing list, there was some
392 discussion about linking to Gnus messages without encoding the folder
393 name in the link.  The following code hooks in to the store-link
394 function in Gnus to capture links by Message-Id when in nnml folders,
395 and then provides a link type "mid" which can open this link.  The
396 =mde-org-gnus-open-message-link= function uses the
397 =mde-mid-resolve-methods= variable to determine what Gnus backends to
398 scan.  It will go through them, in order, asking each to locate the
399 message and opening it from the first one that reports success.
401 It has only been tested with a single nnml backend, so there may be
402 bugs lurking here and there.
404 The logic for finding the message was adapted from [[http://www.emacswiki.org/cgi-bin/wiki/FindMailByMessageId][an Emacs Wiki
405 article]].
407 #+begin_src emacs-lisp
408 ;; Support for saving Gnus messages by Message-ID
409 (defun mde-org-gnus-save-by-mid ()
410   (when (memq major-mode '(gnus-summary-mode gnus-article-mode))
411     (when (eq major-mode 'gnus-article-mode)
412       (gnus-article-show-summary))
413     (let* ((group gnus-newsgroup-name)
414            (method (gnus-find-method-for-group group)))
415       (when (eq 'nnml (car method))
416         (let* ((article (gnus-summary-article-number))
417                (header (gnus-summary-article-header article))
418                (from (mail-header-from header))
419                (message-id
420                 (save-match-data
421                   (let ((mid (mail-header-id header)))
422                     (if (string-match "<\\(.*\\)>" mid)
423                         (match-string 1 mid)
424                       (error "Malformed message ID header %s" mid)))))
425                (date (mail-header-date header))
426                (subject (gnus-summary-subject-string)))
427           (org-store-link-props :type "mid" :from from :subject subject
428                                 :message-id message-id :group group
429                                 :link (org-make-link "mid:" message-id))
430           (apply 'org-store-link-props
431                  :description (org-email-link-description)
432                  org-store-link-plist)
433           t)))))
435 (defvar mde-mid-resolve-methods '()
436   "List of methods to try when resolving message ID's.  For Gnus,
437 it is a cons of 'gnus and the select (type and name).")
438 (setq mde-mid-resolve-methods
439       '((gnus nnml "")))
441 (defvar mde-org-gnus-open-level 1
442   "Level at which Gnus is started when opening a link")
443 (defun mde-org-gnus-open-message-link (msgid)
444   "Open a message link with Gnus"
445   (require 'gnus)
446   (require 'org-table)
447   (catch 'method-found
448     (message "[MID linker] Resolving %s" msgid)
449     (dolist (method mde-mid-resolve-methods)
450       (cond
451        ((and (eq (car method) 'gnus)
452              (eq (cadr method) 'nnml))
453         (funcall (cdr (assq 'gnus org-link-frame-setup))
454                  mde-org-gnus-open-level)
455         (when gnus-other-frame-object
456           (select-frame gnus-other-frame-object))
457         (let* ((msg-info (nnml-find-group-number
458                           (concat "<" msgid ">")
459                           (cdr method)))
460                (group (and msg-info (car msg-info)))
461                (message (and msg-info (cdr msg-info)))
462                (qname (and group
463                            (if (gnus-methods-equal-p
464                                 (cdr method)
465                                 gnus-select-method)
466                                group
467                              (gnus-group-full-name group (cdr method))))))
468           (when msg-info
469             (gnus-summary-read-group qname nil t)
470             (gnus-summary-goto-article message nil t))
471           (throw 'method-found t)))
472        (t (error "Unknown link type"))))))
474 (eval-after-load 'org-gnus
475   '(progn
476      (add-to-list 'org-store-link-functions 'mde-org-gnus-save-by-mid)
477      (org-add-link-type "mid" 'mde-org-gnus-open-message-link)))
478 #+end_src
479 * Dynamically adjust tag position
480 Here is a bit of code that allows you to have the tags always
481 right-adjusted in the buffer.
483 This is useful when you have bigger window than default window-size
484 and you dislike the aesthetics of having the tag in the middle of the
485 line.
487 This hack solves the problem of adjusting it whenever you change the
488 window size.
489 Before saving it will revert the file to having the tag position be
490 left-adjusted so that if you track your files with version control,
491 you won't run into artificial diffs just because the window-size
492 changed.
494 *IMPORTANT*: This is probably slow on very big files.
496 #+begin_src emacs-lisp
497 (setq ba/org-adjust-tags-column t)
499 (defun ba/org-adjust-tags-column-reset-tags ()
500   "In org-mode buffers it will reset tag position according to
501 `org-tags-column'."
502   (when (and
503          (not (string= (buffer-name) "*Remember*"))
504          (eql major-mode 'org-mode))
505     (let ((b-m-p (buffer-modified-p)))
506       (condition-case nil
507           (save-excursion
508             (goto-char (point-min))
509             (command-execute 'outline-next-visible-heading)
510             ;; disable (message) that org-set-tags generates
511             (flet ((message (&rest ignored) nil))
512               (org-set-tags 1 t))
513             (set-buffer-modified-p b-m-p))
514         (error nil)))))
516 (defun ba/org-adjust-tags-column-now ()
517   "Right-adjust `org-tags-column' value, then reset tag position."
518   (set (make-local-variable 'org-tags-column)
519        (- (- (window-width) 3)))
520   (ba/org-adjust-tags-column-reset-tags))
522 (defun ba/org-adjust-tags-column-maybe ()
523   "If `ba/org-adjust-tags-column' is set to non-nil, adjust tags."
524   (when ba/org-adjust-tags-column
525     (ba/org-adjust-tags-column-now)))
527 (defun ba/org-adjust-tags-column-before-save ()
528   "Tags need to be left-adjusted when saving."
529   (when ba/org-adjust-tags-column
530      (setq org-tags-column 1)
531      (ba/org-adjust-tags-column-reset-tags)))
533 (defun ba/org-adjust-tags-column-after-save ()
534   "Revert left-adjusted tag position done by before-save hook."
535   (ba/org-adjust-tags-column-maybe)
536   (set-buffer-modified-p nil))
538 ; automatically align tags on right-hand side
539 (add-hook 'window-configuration-change-hook
540           'ba/org-adjust-tags-column-maybe)
541 (add-hook 'before-save-hook 'ba/org-adjust-tags-column-before-save)
542 (add-hook 'after-save-hook 'ba/org-adjust-tags-column-after-save)
543 #+end_src
544 * Compiling Org without make
545   :PROPERTIES:
546   :CUSTOM_ID: compiling-org-without-make
547   :END:
549   This file is the result of  [[http://article.gmane.org/gmane.emacs.orgmode/15264][one of our discussions]] on the mailing list.
550   Enhancements wellcome.
552   To use this function, adjust the variables =my/org-lisp-directory= and
553   =my/org-compile-sources= to suite your needs.
555   #+BEGIN_SRC emacs-lisp
556     (defvar my/org-lisp-directory "~/.emacs.d/org/lisp"
557       "Directory where your org-mode files live.")
559     (defvar my/org-compile-sources t
560       "If `nil', never compile org-sources. `my/compile-org' will only create
561     the autoloads file `org-install.el' then. If `t', compile the sources, too.")
563     ;; Customize:
564     (setq my/org-lisp-directory "~/.emacs.d/org/lisp")
566     ;; Customize:
567     (setq  my/org-compile-sources t)
569     (defun my/compile-org(&optional directory)
570       "Compile all *.el files that come with org-mode."
571       (interactive)
572       (setq directory (concat
573                        (file-truename
574                         (or directory my/org-lisp-directory)) "/"))
576       (add-to-list 'load-path directory)
578       (let ((list-of-org-files (file-expand-wildcards (concat directory "*.el"))))
580         ;; create the org-install file
581         (require 'autoload)
582         (setq esf/org-install-file (concat directory "org-install.el"))
583         (find-file esf/org-install-file)
584         (erase-buffer)
585         (mapc (lambda (x)
586                 (generate-file-autoloads x))
587               list-of-org-files)
588         (insert "\n(provide (quote org-install))\n")
589         (save-buffer)
590         (kill-buffer)
591         (byte-compile-file esf/org-install-file t)
593         (dolist (f list-of-org-files)
594           (if (file-exists-p (concat f "c")) ; delete compiled files
595               (delete-file (concat f "c")))
596           (if my/org-compile-sources     ; Compile, if `my/org-compile-sources' is t
597               (byte-compile-file f)))))
598   #+END_SRC
599 * Customize the size of the frame for remember
601 #FIXME: gmane link?
602 On emacs-orgmode, Ryan C. Thompson suggested this:
604 #+begin_quote 
605 I am using org-remember set to open a new frame when used,
606 and the default frame size is much too large. To fix this, I have
607 designed some advice and a custom variable to implement custom
608 parameters for the remember frame:
609 #+end_quote
611 #+begin_src emacs-lisp
612   (defcustom remember-frame-alist nil
613     "Additional frame parameters for dedicated remember frame."
614     :type 'alist
615     :group 'remember)
616   
617   (defadvice remember (around remember-frame-parameters activate)
618     "Set some frame parameters for the remember frame."
619     (let ((default-frame-alist (append remember-frame-alist
620                                        default-frame-alist)))
621       ad-do-it))
622 #+end_src
624 Setting remember-frame-alist to =((width . 80) (height . 15)))= give a
625 reasonable size for the frame.
628 * Add an effort estimate on the fly when clocking in
630 You can use =org-clock-in-prepare-hook= to add an effort estimate.  
631 This way you can easily have a "tea-timer" for your tasks when they
632 don't already have an effort estimate.
634 #+begin_src emacs-lisp
635 (add-hook 'org-clock-in-prepare-hook 
636           'my-org-mode-ask-effort)
638 (defun my-org-mode-ask-effort ()
639   "Ask for an effort estimate when clocking in."
640   (unless (org-entry-get (point) "Effort")
641     (let ((effort 
642            (completing-read 
643             "Effort: "
644             (org-entry-get-multivalued-property (point) "Effort"))))
645       (unless (equal effort "")
646         (org-set-property "Effort" effort)))))
647 #+end_src
649 Or you can use a default effort for such a timer:
651 #+begin_src emacs-lisp
652 (add-hook 'org-clock-in-prepare-hook 
653           'my-org-mode-add-default-effort)
655 (defvar org-clock-default-effort "1:00")
657 (defun my-org-mode-add-default-effort ()
658   "Add a default effort estimation."
659   (unless (org-entry-get (point) "Effort")
660     (org-set-property "Effort" org-clock-default-effort)))
661 #+end_src
662 * Dates computation in an Org table
664 ** Question ([[http://article.gmane.org/gmane.emacs.orgmode/15692][Xin Shi]])
666 I have a table in org which stores the date, I'm wondering if there is
667 any function to calculate the duration? For example:
669 | Start Date |   End Date | Duration |
670 |------------+------------+----------|
671 | 2004.08.07 | 2005.07.08 |          |
673 I tried to use B&-C&, but failed ...
675 ** Answer ([[http://article.gmane.org/gmane.emacs.orgmode/15694][Nick Dokos]])
677 Try the following:
679 | Start Date |   End Date | Duration |
680 |------------+------------+----------|
681 | 2004.08.07 | 2005.07.08 |      335 |
682 :#+TBLFM: $3=(date(<$2>)-date(<$1>))
684 See this thread:
686     http://thread.gmane.org/gmane.emacs.orgmode/7741
688 as well as this post (which is really a followup on the
689 above):
691     http://article.gmane.org/gmane.emacs.orgmode/7753
693 The problem that this last article pointed out was solved
696     http://article.gmane.org/gmane.emacs.orgmode/8001
698 and Chris Randle's original musings are at
700     http://article.gmane.org/gmane.emacs.orgmode/6536/
701 * Org-mode and saveplace.el
703 Fix a problem with saveplace.el putting you back in a folded position: 
705 #+begin_src emacs-lisp
706 (add-hook 'org-mode-hook
707           (lambda ()
708             (when (outline-invisible-p)
709               (save-excursion
710                 (outline-previous-visible-heading 1)
711                 (org-show-subtree)))))
712 #+end_src
713 * Easy customization of TODO colors
714   -- Ryan C. Thompson
716   Here is some code I came up with some code to make it easier to
717   customize the colors of various TODO keywords. As long as you just
718   want a different color and nothing else, you can customize the
719   variable org-todo-keyword-faces and use just a string color (i.e. a
720   string of the color name) as the face, and then org-get-todo-face
721   will convert the color to a face, inheriting everything else from
722   the standard org-todo face.
724   To demonstrate, I currently have org-todo-keyword-faces set to
726 #+BEGIN_SRC emacs-lisp
727 (("IN PROGRESS" . "dark orange")
728  ("WAITING" . "red4")
729  ("CANCELED" . "saddle brown"))
730 #+END_SRC emacs-lisp
732   Here's the code, in a form you can put in your =.emacs=
734 #+BEGIN_SRC emacs-lisp
735 (eval-after-load 'org-faces
736  '(progn
737     (defcustom org-todo-keyword-faces nil
738       "Faces for specific TODO keywords.
739 This is a list of cons cells, with TODO keywords in the car and
740 faces in the cdr.  The face can be a symbol, a color, or a
741 property list of attributes, like (:foreground \"blue\" :weight
742 bold :underline t)."
743       :group 'org-faces
744       :group 'org-todo
745       :type '(repeat
746               (cons
747                (string :tag "Keyword")
748                (choice color (sexp :tag "Face")))))))
750 (eval-after-load 'org
751  '(progn
752     (defun org-get-todo-face-from-color (color)
753       "Returns a specification for a face that inherits from org-todo
754  face and has the given color as foreground. Returns nil if
755  color is nil."
756       (when color
757         `(:inherit org-warning :foreground ,color)))
759     (defun org-get-todo-face (kwd)
760       "Get the right face for a TODO keyword KWD.
761 If KWD is a number, get the corresponding match group."
762       (if (numberp kwd) (setq kwd (match-string kwd)))
763       (or (let ((face (cdr (assoc kwd org-todo-keyword-faces))))
764             (if (stringp face)
765                 (org-get-todo-face-from-color face)
766               face))
767           (and (member kwd org-done-keywords) 'org-done)
768           'org-todo))))
769 #+END_SRC emacs-lisp