This page is for ad hoc bits of code. Feel free to add quick hacks and workaround. Go crazy.
;; Make sure you have a sensible value for `appt-message-warning-time' (defvar bzg-org-clock-in-appt-delay 100 "Number of minutes for setting an appointment by clocking-in")
This function let's you add an appointment for the current entry. This can be useful when you need a reminder.
(defun bzg-org-clock-in-add-appt (&optional n) "Add an appointment for the Org entry at point in N minutes." (interactive) (save-excursion (org-back-to-heading t) (looking-at org-complex-heading-regexp) (let* ((msg (match-string-no-properties 4)) (ct-time (decode-time)) (appt-min (+ (cadr ct-time) (or n bzg-org-clock-in-appt-delay))) (appt-time ; define the time for the appointment (progn (setf (cadr ct-time) appt-min) ct-time))) (appt-add (format-time-string "%H:%M" (apply 'encode-time appt-time)) msg) (if (interactive-p) (message "New appointment for %s" msg)))))
You can advise org-clock-in so that C-c C-x C-i will automatically
add an appointment:
(defadvice org-clock-in (after org-clock-in-add-appt activate) "Add an appointment when clocking a task in." (bzg-org-clock-in-add-appt))
You may also want to delete the associated appointment when clocking out. This function does this:
(defun bzg-org-clock-out-delete-appt nil "When clocking out, delete any associated appointment." (interactive) (save-excursion (org-back-to-heading t) (looking-at org-complex-heading-regexp) (let* ((msg (match-string-no-properties 4))) (setq appt-time-msg-list (delete nil (mapcar (lambda (appt) (if (not (string-match (regexp-quote msg) (cadr appt))) appt)) appt-time-msg-list))) (appt-check))))
And here is the advice for org-clock-out (C-c C-x C-o)
(defadvice org-clock-out (before org-clock-out-delete-appt activate) "Delete an appointment when clocking a task out." (bzg-org-clock-out-delete-appt))
IMPORTANT: You can add appointment by clocking in in both an
org-mode and an org-agenda-mode buffer. But clocking out from
agenda buffer with the advice above will bring an error.
"The general idea is that you start a task in which all the work will take place in a shell. This usually is not a leaf-task for me, but usually the parent of a leaf task. From a task in your org-file, M-x ash-org-screen will prompt for the name of a session. Give it a name, and it will insert a link. Open the link at any time to go the screen session containing your work!"
http://article.gmane.org/gmane.emacs.orgmode/5276
(require 'term) (defun ash-org-goto-screen (name) "Open the screen with the specified name in the window" (interactive "MScreen name: ") (let ((screen-buffer-name (ash-org-screen-buffer-name name))) (if (member screen-buffer-name (mapcar 'buffer-name (buffer-list))) (switch-to-buffer screen-buffer-name) (switch-to-buffer (ash-org-screen-helper name "-dr"))))) (defun ash-org-screen-buffer-name (name) "Returns the buffer name corresponding to the screen name given." (concat "*screen " name "*")) (defun ash-org-screen-helper (name arg) ;; Pick the name of the new buffer. (let ((term-ansi-buffer-name (generate-new-buffer-name (ash-org-screen-buffer-name name)))) (setq term-ansi-buffer-name (term-ansi-make-term term-ansi-buffer-name "/usr/bin/screen" nil arg name)) (set-buffer term-ansi-buffer-name) (term-mode) (term-char-mode) (term-set-escape-char ?\C-x) term-ansi-buffer-name)) (defun ash-org-screen (name) "Start a screen session with name" (interactive "MScreen name: ") (save-excursion (ash-org-screen-helper name "-S")) (insert-string (concat "[[screen:" name "]]"))) ;; And don't forget to add ("screen" . "elisp:(ash-org-goto-screen ;; \"%s\")") to org-link-abbrev-alist.
Russell Adams posted this setup on the list. It make sure your agenda appointments are known by Emacs, and it displays warnings in a zenity popup window.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; For org appointment reminders ;; Get appointments for today (defun my-org-agenda-to-appt () (interactive) (setq appt-time-msg-list nil) (let ((org-deadline-warning-days 0)) ;; will be automatic in org 5.23 (org-agenda-to-appt))) ;; Run once, activate and schedule refresh (my-org-agenda-to-appt) (appt-activate t) (run-at-time "24:01" nil 'my-org-agenda-to-appt) ; 5 minute warnings (setq appt-message-warning-time 15) (setq appt-display-interval 5) ; Update appt each time agenda opened. (add-hook 'org-finalize-agenda-hook 'my-org-agenda-to-appt) ; Setup zenify, we tell appt to use window, and replace default function (setq appt-display-format 'window) (setq appt-disp-window-function (function my-appt-disp-window)) (defun my-appt-disp-window (min-to-app new-time msg) (save-window-excursion (shell-command (concat "/usr/bin/zenity --info --title='Appointment' --text='" msg "' &") nil nil)))
Richard Riley uses gnome-osd in interaction with Org-Mode to display appointments. You can look at the code on the emacswiki.
From Detlef Steuer
http://article.gmane.org/gmane.emacs.orgmode/5073
remind (http://www.roaringpenguin.com/products/remind) is a very powerful command line calendaring program. Its features superseed the possibilities of orgmode in the area of date specifying, so that I want to use it combined with orgmode. Using the script below I'm able use remind and incorporate its output in my agenda views. The default of using 13 months look ahead is easily changed. It just happens I sometimes like to look a year into the future. :-)
Anything users may find the snippet below interesting:
(defvar org-remember-anything '((name . "Org Remember") (candidates . (lambda () (mapcar 'car org-remember-templates))) (action . (lambda (name) (let* ((orig-template org-remember-templates) (org-remember-templates (list (assoc name orig-template)))) (call-interactively 'org-remember))))))
You can add it to your 'anything-sources' variable and open remember directly from anything. I imagine this would be more interesting for people with many remember templatesm, so that you are out of keys to assign those to. You should get something like this:
This function by Bernt Hansen reloads Org's compiled files. This is useful when you update and compile Org often.
By default it reloads compiled org files. If you call it with a prefix argument it reloads source files.
;; Your org-mode directory (setq my-org-mode-git-directory "~/git/org-mode") (defun org-reload-org (&optional source) "Reload Compiled Org lisp files." (interactive "p") (message "source is %s" source) (if (equal source 4) (setq my-org-files "\\.el\\'") (setq my-org-files "\\.elc\\'")) (mapc (lambda(f) (load (car f))) (directory-files-and-attributes (concat my-org-mode-git-directory "/lisp") t my-org-files))) (defun org-reload-org nil "Reload Org lisp files." (interactive) (mapc (lambda(f) (load (car f))) (directory-files-and-attributes (concat my-org-mode-git-directory "/lisp") t "\\.elc\\'")))
Normally you want to use the compiled files since they are faster. If you run into a bug and want to generate a useful backtrace for the maintainer you can reload the source files and enter debugger on error with
C-u M-x org-reload-org
and turn on the "Enter Debugger On Error" option. Redo the action that generates the error and cut and paste the resulting backtrace into an email. To switch back to the compiled version just reload again with
M-x org-reload-org
If you would like to split the frame into two side-by-side windows when displaying the agenda, try this hack from Jan Rehders, which uses the `toggle-window-split' from
http://www.emacswiki.org/cgi-bin/wiki/ToggleWindowSplit
;; Patch org-mode to use vertical splitting (defadvice org-prepare-agenda (after org-fix-split) (toggle-window-split)) (ad-activate 'org-prepare-agenda)
This is useful to make sure what task you are operating on.
(add-hook 'org-agenda-mode-hook '(lambda () (hl-line-mode 1)))
Under XEmacs:
;; hl-line seems to be only for emacs (require 'highline) (add-hook 'org-agenda-mode-hook '(lambda () (highline-mode 1))) ;; highline-mode does not work straightaway in tty mode. ;; I use a black background (custom-set-faces '(highline-face ((((type tty) (class color)) (:background "white" :foreground "black")))))
The agenda shows lines for the time grid. Some people think that these lines are a distraction when there are appointments at those times. You can get rid of the lines which coincide exactly with the beginning of an appointment. Michael Ekstrand has written a piece of advice that also removes lines that are somewhere inside an appointment:
(defun org-time-to-minutes (time) "Convert an HHMM time to minutes" (+ (* (/ time 100) 60) (% time 100))) (defun org-time-from-minutes (minutes) "Convert a number of minutes to an HHMM time" (+ (* (/ minutes 60) 100) (% minutes 60))) (defadvice org-agenda-add-time-grid-maybe (around mde-org-agenda-grid-tweakify (list ndays todayp)) (if (member 'remove-match (car org-agenda-time-grid)) (flet ((extract-window (line) (let ((start (get-text-property 1 'time-of-day line)) (dur (get-text-property 1 'duration line))) (cond ((and start dur) (cons start (org-time-from-minutes (+ dur (org-time-to-minutes start))))) (start start) (t nil))))) (let* ((windows (delq nil (mapcar 'extract-window list))) (org-agenda-time-grid (list (car org-agenda-time-grid) (cadr org-agenda-time-grid) (remove-if (lambda (time) (find-if (lambda (w) (if (numberp w) (equal w time) (and (>= time (car w)) (< time (cdr w))))) windows)) (caddr org-agenda-time-grid))))) ad-do-it)) ad-do-it)) (ad-activate 'org-agenda-add-time-grid-maybe)
This advice allows you to group a task list in Org-Mode. To use it,
set the variable org-agenda-group-by-property to the name of a
property in the option list for a TODO or TAGS search. The resulting
agenda view will group tasks by that property prior to searching.
(defvar org-agenda-group-by-property nil "Set this in org-mode agenda views to group tasks by property") (defun org-group-bucket-items (prop items) (let ((buckets ())) (dolist (item items) (let* ((marker (get-text-property 0 'org-marker item)) (pvalue (org-entry-get marker prop t)) (cell (assoc pvalue buckets))) (if cell (setcdr cell (cons item (cdr cell))) (setq buckets (cons (cons pvalue (list item)) buckets))))) (setq buckets (mapcar (lambda (bucket) (cons (car bucket) (reverse (cdr bucket)))) buckets)) (sort buckets (lambda (i1 i2) (string< (car i1) (car i2)))))) (defadvice org-finalize-agenda-entries (around org-group-agenda-finalize (list &optional nosort)) "Prepare bucketed agenda entry lists" (if org-agenda-group-by-property ;; bucketed, handle appropriately (let ((text "")) (dolist (bucket (org-group-bucket-items org-agenda-group-by-property list)) (let ((header (concat "Property " org-agenda-group-by-property " is " (or (car bucket) "<nil>") ":\n"))) (add-text-properties 0 (1- (length header)) (list 'face 'org-agenda-structure) header) (setq text (concat text header ;; recursively process (let ((org-agenda-group-by-property nil)) (org-finalize-agenda-entries (cdr bucket) nosort)) "\n\n")))) (setq ad-return-value text)) ad-do-it)) (ad-activate 'org-finalize-agenda-entries)
In a recent thread on the Org-Mode mailing list, there was some
discussion about linking to Gnus messages without encoding the folder
name in the link. The following code hooks in to the store-link
function in Gnus to capture links by Message-Id when in nnml folders,
and then provides a link type "mid" which can open this link. The
mde-org-gnus-open-message-link function uses the
mde-mid-resolve-methods variable to determine what Gnus backends to
scan. It will go through them, in order, asking each to locate the
message and opening it from the first one that reports success.
It has only been tested with a single nnml backend, so there may be bugs lurking here and there.
The logic for finding the message was adapted from an Emacs Wiki article.
;; Support for saving Gnus messages by Message-ID (defun mde-org-gnus-save-by-mid () (when (memq major-mode '(gnus-summary-mode gnus-article-mode)) (when (eq major-mode 'gnus-article-mode) (gnus-article-show-summary)) (let* ((group gnus-newsgroup-name) (method (gnus-find-method-for-group group))) (when (eq 'nnml (car method)) (let* ((article (gnus-summary-article-number)) (header (gnus-summary-article-header article)) (from (mail-header-from header)) (message-id (save-match-data (let ((mid (mail-header-id header))) (if (string-match "<\\(.*\\)>" mid) (match-string 1 mid) (error "Malformed message ID header %s" mid))))) (date (mail-header-date header)) (subject (gnus-summary-subject-string))) (org-store-link-props :type "mid" :from from :subject subject :message-id message-id :group group :link (org-make-link "mid:" message-id)) (apply 'org-store-link-props :description (org-email-link-description) org-store-link-plist) t))))) (defvar mde-mid-resolve-methods '() "List of methods to try when resolving message ID's. For Gnus, it is a cons of 'gnus and the select (type and name).") (setq mde-mid-resolve-methods '((gnus nnml ""))) (defvar mde-org-gnus-open-level 1 "Level at which Gnus is started when opening a link") (defun mde-org-gnus-open-message-link (msgid) "Open a message link with Gnus" (require 'gnus) (require 'org-table) (catch 'method-found (message "[MID linker] Resolving %s" msgid) (dolist (method mde-mid-resolve-methods) (cond ((and (eq (car method) 'gnus) (eq (cadr method) 'nnml)) (funcall (cdr (assq 'gnus org-link-frame-setup)) mde-org-gnus-open-level) (when gnus-other-frame-object (select-frame gnus-other-frame-object)) (let* ((msg-info (nnml-find-group-number (concat "<" msgid ">") (cdr method))) (group (and msg-info (car msg-info))) (message (and msg-info (cdr msg-info))) (qname (and group (if (gnus-methods-equal-p (cdr method) gnus-select-method) group (gnus-group-full-name group (cdr method)))))) (when msg-info (gnus-summary-read-group qname nil t) (gnus-summary-goto-article message nil t)) (throw 'method-found t))) (t (error "Unknown link type")))))) (eval-after-load 'org-gnus '(progn (add-to-list 'org-store-link-functions 'mde-org-gnus-save-by-mid) (org-add-link-type "mid" 'mde-org-gnus-open-message-link)))