= tags, and assigned CSS classes by their content
type. For example, Perl content will have an opening tag like
=

=. You can use those classes to add styling
to the output, such as here where a small language tag is added at the
top of each kind of code box:
#+BEGIN_SRC lisp
(setq org-export-html-style
"")
#+END_SRC
Additionally, we use color to distinguish code output (the =.example=
class) from input (all the =.src-*= classes).
*** Including external text fragments
#+INDEX: Export!including external text fragments
I recently had to document some source code but could not modify the
source files themselves. Here is a setup that lets you refer to
fragments of external files, such that the fragments are inserted as
source blocks in the current file during evaluation of the ~call~
lines (thus during export as well).
#+BEGIN_SRC org
,* Setup :noexport:
,#+name: fetchsrc
,#+BEGIN_SRC emacs-lisp :results raw :var f="foo" :var s="Definition" :var e="\\. *$" :var b=()
(defvar coqfiles nil)
(defun fetchlines (file-path search-string &optional end before)
"Searches for the SEARCH-STRING in FILE-PATH and returns the matching line.
If the optional argument END is provided as a number, then this
number of lines is printed. If END is a string, then it is a
regular expression indicating the end of the expression to print.
If END is omitted, then 10 lines are printed. If BEFORE is set,
then one fewer line is printed (this is useful when END is a
string matching the first line that should not be printed)."
(with-temp-buffer
(insert-file-contents file-path nil nil nil t)
(goto-char (point-min))
(let ((result
(if (search-forward search-string nil t)
(buffer-substring
(line-beginning-position)
(if end
(cond
((integerp end)
(line-end-position (if before (- end 1) end)))
((stringp end)
(let ((point (re-search-forward end nil t)))
(if before (line-end-position 0) point)))
(t (line-end-position 10)))
(line-end-position 10))))))
(or result ""))))
(fetchlines (concat coqfiles f ".v") s e b)
,#+END_SRC
,#+name: wrap-coq
,#+BEGIN_SRC emacs-lisp :var text="" :results raw
(concat "#+BEGIN_SRC coq\n" text "\n#+END_SRC")
,#+END_SRC
#+END_SRC
This is specialized for Coq files (hence the ~coq~ language in the
~wrap-coq~ function, the ~.v~ extension in the ~fetch~ function, and
the default value for ~end~ matching the syntax ending definitions in
Coq). To use it, you need to:
- set the ~coqfiles~ variable to where your source files reside;
- call the function using lines of the form
#+BEGIN_SRC org
,#+call: fetchsrc(f="JsSyntax", s="Inductive expr :=", e="^ *$", b=1) :results drawer :post wrap-coq(text=*this*)
#+END_SRC
In this example, we look inside the file ~JsSyntax.v~ in ~coqfiles~,
search for a line matching ~Inductive expr :=~, and include the
fragment until the first line consisting only of white space,
excluded (as ~b=1~).
I use drawers to store the results to avoid a bug leading to
duplication during export when the code has already been evaluated in
the buffer (see [[http://thread.gmane.org/gmane.emacs.orgmode/79520][this thread]] for a description of the problem). This
has been fixed in recent versions of org-mode, so alternative
approaches are possible.
** Babel
*** How do I preview LaTeX fragments when in a LaTeX source block?
When editing =LaTeX= source blocks, you may want to preview LaTeX fragments
just like in an Org-mode buffer. You can do this by using the usual
keybinding =C-c C-x C-l= after loading this snipped:
#+BEGIN_SRC emacs-lisp
(define-key org-src-mode-map "\C-c\C-x\C-l" 'org-edit-preview-latex-fragment)
(defun org-edit-preview-latex-fragment ()
"Write latex fragment from source to parent buffer and preview it."
(interactive)
(org-src-in-org-buffer (org-preview-latex-fragment)))
#+END_SRC
Thanks to Sebastian Hofer for sharing this.
* Hacking Org: Working with Org-mode and other Emacs Packages.
** How to ediff folded Org files
A rather often quip among Org users is when looking at chages with
ediff. Ediff tends to fold the Org buffers when comparing. This can
be very inconvenient when trying to determine what changed. A recent
discussion on the mailing list led to a [[http://article.gmane.org/gmane.emacs.orgmode/75222][neat solution]] from Ratish
Punnoose.
** org-remember-anything
#+INDEX: Remember!Anything
[[http://www.emacswiki.org/cgi-bin/wiki/Anything][Anything]] users may find the snippet below interesting:
#+BEGIN_SRC emacs-lisp
(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))))))
#+END_SRC
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 templates, so that you are out of keys to assign those to.
** Org-mode and saveplace.el
Fix a problem with =saveplace.el= putting you back in a folded position:
#+BEGIN_SRC emacs-lisp
(add-hook 'org-mode-hook
(lambda ()
(when (outline-invisible-p)
(save-excursion
(outline-previous-visible-heading 1)
(org-show-subtree)))))
#+END_SRC
** Using ido-mode for org-refile (and archiving via refile)
First set up ido-mode, for example using:
#+BEGIN_SRC emacs-lisp
; use ido mode for completion
(setq ido-everywhere t)
(setq ido-enable-flex-matching t)
(setq ido-max-directory-size 100000)
(ido-mode (quote both))
#+END_SRC
Now to enable it in org-mode, use the following:
#+BEGIN_SRC emacs-lisp
(setq org-completion-use-ido t)
(setq org-refile-use-outline-path nil)
(setq org-refile-allow-creating-parent-nodes 'confirm)
#+END_SRC
The last line enables the creation of nodes on the fly.
If you refile into files that are not in your agenda file list, you can add them as target like this (replace file1\_done, etc with your files):
#+BEGIN_SRC emacs-lisp
(setq org-refile-targets '((org-agenda-files :maxlevel . 5) (("~/org/file1_done" "~/org/file2_done") :maxlevel . 5) ))
#+END_SRC
For refiling it is often not useful to include targets that have a DONE state. It's easy to remove them by using the verify-refile-target hook.
#+BEGIN_SRC emacs-lisp
; Exclude DONE state tasks from refile targets; taken from http://doc.norang.ca/org-mode.html
; added check to only include headlines, e.g. line must have at least one child
(defun my/verify-refile-target ()
"Exclude todo keywords with a DONE state from refile targets"
(or (not (member (nth 2 (org-heading-components)) org-done-keywords)))
(save-excursion (org-goto-first-child))
)
(setq org-refile-target-verify-function 'my/verify-refile-target)
#+END_SRC
Now when looking for a refile target, you can use the full power of ido to find them. Ctrl-R can be used to switch between different options that ido offers.
** Using ido-completing-read to find attachments
#+INDEX: Attachment!ido completion
-- Matt Lundin.
Org-attach is great for quickly linking files to a project. But if you
use org-attach extensively you might find yourself wanting to browse
all the files you've attached to org headlines. This is not easy to do
manually, since the directories containing the files are not human
readable (i.e., they are based on automatically generated ids). Here's
some code to browse those files using ido (obviously, you need to be
using ido):
#+BEGIN_SRC emacs-lisp
(load-library "find-lisp")
;; Adapted from http://www.emacswiki.org/emacs/RecentFiles
(defun my-ido-find-org-attach ()
"Find files in org-attachment directory"
(interactive)
(let* ((enable-recursive-minibuffers t)
(files (find-lisp-find-files org-attach-directory "."))
(file-assoc-list
(mapcar (lambda (x)
(cons (file-name-nondirectory x)
x))
files))
(filename-list
(remove-duplicates (mapcar #'car file-assoc-list)
:test #'string=))
(filename (ido-completing-read "Org attachments: " filename-list nil t))
(longname (cdr (assoc filename file-assoc-list))))
(ido-set-current-directory
(if (file-directory-p longname)
longname
(file-name-directory longname)))
(setq ido-exit 'refresh
ido-text-init ido-text
ido-rotate-temp t)
(exit-minibuffer)))
(add-hook 'ido-setup-hook 'ido-my-keys)
(defun ido-my-keys ()
"Add my keybindings for ido."
(define-key ido-completion-map (kbd "C-;") 'my-ido-find-org-attach))
#+END_SRC
To browse your org attachments using ido fuzzy matching and/or the
completion buffer, invoke ido-find-file as usual (=C-x C-f=) and then
press =C-;=.
** Link to Gnus messages by Message-Id
#+INDEX: Link!Gnus message by Message-Id
In a [[http://thread.gmane.org/gmane.emacs.orgmode/8860][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 [[http://www.emacswiki.org/cgi-bin/wiki/FindMailByMessageId][an Emacs Wiki
article]].
#+BEGIN_SRC emacs-lisp
;; 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 "")
(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)))
#+END_SRC
** Store link to a message when sending in Gnus
#+INDEX: Link!Store link to a message when sending in Gnus
Ulf Stegemann came up with this solution (see his [[http://www.mail-archive.com/emacs-orgmode@gnu.org/msg33278.html][original message]]):
#+BEGIN_SRC emacs-lisp
(defun ulf-message-send-and-org-gnus-store-link (&optional arg)
"Send message with `message-send-and-exit' and store org link to message copy.
If multiple groups appear in the Gcc header, the link refers to
the copy in the last group."
(interactive "P")
(save-excursion
(save-restriction
(message-narrow-to-headers)
(let ((gcc (car (last
(message-unquote-tokens
(message-tokenize-header
(mail-fetch-field "gcc" nil t) " ,")))))
(buf (current-buffer))
(message-kill-buffer-on-exit nil)
id to from subject desc link newsgroup xarchive)
(message-send-and-exit arg)
(or
;; gcc group found ...
(and gcc
(save-current-buffer
(progn (set-buffer buf)
(setq id (org-remove-angle-brackets
(mail-fetch-field "Message-ID")))
(setq to (mail-fetch-field "To"))
(setq from (mail-fetch-field "From"))
(setq subject (mail-fetch-field "Subject"))))
(org-store-link-props :type "gnus" :from from :subject subject
:message-id id :group gcc :to to)
(setq desc (org-email-link-description))
(setq link (org-gnus-article-link
gcc newsgroup id xarchive))
(setq org-stored-links
(cons (list link desc) org-stored-links)))
;; no gcc group found ...
(message "Can not create Org link: No Gcc header found."))))))
(define-key message-mode-map [(control c) (control meta c)]
'ulf-message-send-and-org-gnus-store-link)
#+END_SRC
** Link to visit a file and run occur
#+INDEX: Link!Visit a file and run occur
Add the following bit of code to your startup (after loading org),
and you can then use links like =occur:my-file.txt#regex= to open a
file and run occur with the regex on it.
#+BEGIN_SRC emacs-lisp
(defun org-occur-open (uri)
"Visit the file specified by URI, and run `occur' on the fragment
\(anything after the first '#') in the uri."
(let ((list (split-string uri "#")))
(org-open-file (car list) t)
(occur (mapconcat 'identity (cdr list) "#"))))
(org-add-link-type "occur" 'org-occur-open)
#+END_SRC
** Send html messages and attachments with Wanderlust
-- David Maus
/Note/: The module [[file:org-contrib/org-mime.org][Org-mime]] in Org's contrib directory provides
similar functionality for both Wanderlust and Gnus. The hack below is
still somewhat different: It allows you to toggle sending of html
messages within Wanderlust transparently. I.e. html markup of the
message body is created right before sending starts.
*** Send HTML message
Putting the code below in your .emacs adds following four functions:
- dmj/wl-send-html-message
Function that does the job: Convert everything between "--text
follows this line--" and first mime entity (read: attachment) or
end of buffer into html markup using `org-export-region-as-html'
and replaces original body with a multipart MIME entity with the
plain text version of body and the html markup version. Thus a
recipient that prefers html messages can see the html markup,
recipients that prefer or depend on plain text can see the plain
text.
Cannot be called interactively: It is hooked into SEMI's
`mime-edit-translate-hook' if message should be HTML message.
- dmj/wl-send-html-message-draft-init
Cannot be called interactively: It is hooked into WL's
`wl-mail-setup-hook' and provides a buffer local variable to
toggle.
- dmj/wl-send-html-message-draft-maybe
Cannot be called interactively: It is hooked into WL's
`wl-draft-send-hook' and hooks `dmj/wl-send-html-message' into
`mime-edit-translate-hook' depending on whether HTML message is
toggled on or off
- dmj/wl-send-html-message-toggle
Toggles sending of HTML message. If toggled on, the letters
"HTML" appear in the mode line.
Call it interactively! Or bind it to a key in `wl-draft-mode'.
If you have to send HTML messages regularly you can set a global
variable `dmj/wl-send-html-message-toggled-p' to the string "HTML" to
toggle on sending HTML message by default.
The image [[http://s11.directupload.net/file/u/15851/48ru5wl3.png][here]] shows an example of how the HTML message looks like in
Google's web front end. As you can see you have the whole markup of
Org at your service: *bold*, /italics/, tables, lists...
So even if you feel uncomfortable with sending HTML messages at least
you send HTML that looks quite good.
#+BEGIN_SRC emacs-lisp
(defun dmj/wl-send-html-message ()
"Send message as html message.
Convert body of message to html using
`org-export-region-as-html'."
(require 'org)
(save-excursion
(let (beg end html text)
(goto-char (point-min))
(re-search-forward "^--text follows this line--$")
;; move to beginning of next line
(beginning-of-line 2)
(setq beg (point))
(if (not (re-search-forward "^--\\[\\[" nil t))
(setq end (point-max))
;; line up
(end-of-line 0)
(setq end (point)))
;; grab body
(setq text (buffer-substring-no-properties beg end))
;; convert to html
(with-temp-buffer
(org-mode)
(insert text)
;; handle signature
(when (re-search-backward "^-- \n" nil t)
;; preserve link breaks in signature
(insert "\n#+BEGIN_VERSE\n")
(goto-char (point-max))
(insert "\n#+END_VERSE\n")
;; grab html
(setq html (org-export-region-as-html
(point-min) (point-max) t 'string))))
(delete-region beg end)
(insert
(concat
"--" "<>-{\n"
"--" "[[text/plain]]\n" text
"--" "[[text/html]]\n" html
"--" "}-<>\n")))))
(defun dmj/wl-send-html-message-toggle ()
"Toggle sending of html message."
(interactive)
(setq dmj/wl-send-html-message-toggled-p
(if dmj/wl-send-html-message-toggled-p
nil "HTML"))
(message "Sending html message toggled %s"
(if dmj/wl-send-html-message-toggled-p
"on" "off")))
(defun dmj/wl-send-html-message-draft-init ()
"Create buffer local settings for maybe sending html message."
(unless (boundp 'dmj/wl-send-html-message-toggled-p)
(setq dmj/wl-send-html-message-toggled-p nil))
(make-variable-buffer-local 'dmj/wl-send-html-message-toggled-p)
(add-to-list 'global-mode-string
'(:eval (if (eq major-mode 'wl-draft-mode)
dmj/wl-send-html-message-toggled-p))))
(defun dmj/wl-send-html-message-maybe ()
"Maybe send this message as html message.
If buffer local variable `dmj/wl-send-html-message-toggled-p' is
non-nil, add `dmj/wl-send-html-message' to
`mime-edit-translate-hook'."
(if dmj/wl-send-html-message-toggled-p
(add-hook 'mime-edit-translate-hook 'dmj/wl-send-html-message)
(remove-hook 'mime-edit-translate-hook 'dmj/wl-send-html-message)))
(add-hook 'wl-draft-reedit-hook 'dmj/wl-send-html-message-draft-init)
(add-hook 'wl-mail-setup-hook 'dmj/wl-send-html-message-draft-init)
(add-hook 'wl-draft-send-hook 'dmj/wl-send-html-message-maybe)
#+END_SRC
*** Attach HTML of region or subtree
Instead of sending a complete HTML message you might only send parts
of an Org file as HTML for the poor souls who are plagued with
non-proportional fonts in their mail program that messes up pretty
ASCII tables.
This short function does the trick: It exports region or subtree to
HTML, prefixes it with a MIME entity delimiter and pushes to killring
and clipboard. If a region is active, it uses the region, the
complete subtree otherwise.
#+BEGIN_SRC emacs-lisp
(defun dmj/org-export-region-as-html-attachment (beg end arg)
"Export region between BEG and END as html attachment.
If BEG and END are not set, use current subtree. Region or
subtree is exported to html without header and footer, prefixed
with a mime entity string and pushed to clipboard and killring.
When called with prefix, mime entity is not marked as
attachment."
(interactive "r\nP")
(save-excursion
(let* ((beg (if (region-active-p) (region-beginning)
(progn
(org-back-to-heading)
(point))))
(end (if (region-active-p) (region-end)
(progn
(org-end-of-subtree)
(point))))
(html (concat "--[[text/html"
(if arg "" "\nContent-Disposition: attachment")
"]]\n"
(org-export-region-as-html beg end t 'string))))
(when (fboundp 'x-set-selection)
(ignore-errors (x-set-selection 'PRIMARY html))
(ignore-errors (x-set-selection 'CLIPBOARD html)))
(message "html export done, pushed to kill ring and clipboard"))))
#+END_SRC
*** Adopting for Gnus
The whole magic lies in the special strings that mark a HTML
attachment. So you might just have to find out what these special
strings are in message-mode and modify the functions accordingly.
** Add sunrise/sunset times to the agenda.
#+INDEX: Agenda!Diary s-expressions
-- Nick Dokos
The diary package provides the function =diary-sunrise-sunset= which can be used
in a diary s-expression in some agenda file like this:
#+BEGIN_SRC org
%%(diary-sunrise-sunset)
#+END_SRC
Seb Vauban asked if it is possible to put sunrise and sunset in
separate lines. Here is a hack to do that. It adds two functions (they
have to be available before the agenda is shown, so I add them early
in my org-config file which is sourced from .emacs, but you'll have to
suit yourself here) that just parse the output of
diary-sunrise-sunset, instead of doing the right thing which would be
to take advantage of the data structures that diary/solar.el provides.
In short, a hack - so perfectly suited for inclusion here :-)
The functions (and latitude/longitude settings which you have to modify for
your location) are as follows:
#+BEGIN_SRC emacs-lisp
(setq calendar-latitude 48.2)
(setq calendar-longitude 16.4)
(setq calendar-location-name "Vienna, Austria")
(autoload 'solar-sunrise-sunset "solar.el")
(autoload 'solar-time-string "solar.el")
(defun diary-sunrise ()
"Local time of sunrise as a diary entry.
The diary entry can contain `%s' which will be replaced with
`calendar-location-name'."
(let ((l (solar-sunrise-sunset date)))
(when (car l)
(concat
(if (string= entry "")
"Sunrise"
(format entry (eval calendar-location-name))) " "
(solar-time-string (caar l) nil)))))
(defun diary-sunset ()
"Local time of sunset as a diary entry.
The diary entry can contain `%s' which will be replaced with
`calendar-location-name'."
(let ((l (solar-sunrise-sunset date)))
(when (cadr l)
(concat
(if (string= entry "")
"Sunset"
(format entry (eval calendar-location-name))) " "
(solar-time-string (caadr l) nil)))))
#+END_SRC
You also need to add a couple of diary s-expressions in one of your agenda
files:
#+BEGIN_SRC org
%%(diary-sunrise)Sunrise in %s
%%(diary-sunset)
#+END_SRC
This will show sunrise with the location and sunset without it.
The thread on the mailing list that started this can be found [[http://thread.gmane.org/gmane.emacs.orgmode/38723Here%20is%20a%20pointer%20to%20the%20thread%20on%20the%20mailing%20list][here]].
In comparison to the version posted on the mailing list, this one
gets rid of the timezone information and can show the location.
** Add lunar phases to the agenda.
#+INDEX: Agenda!Diary s-expressions
-- Rüdiger
Emacs comes with =lunar.el= to display the lunar phases (=M-x lunar-phases=).
This can be used to display lunar phases in the agenda display with the
following function:
#+BEGIN_SRC emacs-lisp
(require 'cl-lib)
(org-no-warnings (defvar date))
(defun org-lunar-phases ()
"Show lunar phase in Agenda buffer."
(require 'lunar)
(let* ((phase-list (lunar-phase-list (nth 0 date) (nth 2 date)))
(phase (cl-find-if (lambda (phase) (equal (car phase) date))
phase-list)))
(when phase
(setq ret (concat (lunar-phase-name (nth 2 phase)) " "
(substring (nth 1 phase) 0 5))))))
#+END_SRC
Add the following line to an agenda file:
#+BEGIN_SRC org
,* Lunar phase
,#+CATEGORY: Lunar
%%(org-lunar-phases)
#+END_SRC
This should display an entry on new moon, first/last quarter moon, and on full
moon. You can customize the entries by customizing =lunar-phase-names=.
E.g., to add Unicode symbols:
#+BEGIN_SRC emacs-lisp
(setq lunar-phase-names
'("● New Moon" ; Unicode symbol: 🌑 Use full circle as fallback
"☽ First Quarter Moon"
"○ Full Moon" ; Unicode symbol: 🌕 Use empty circle as fallback
"☾ Last Quarter Moon"))
#+END_SRC
Unicode 6 even provides symbols for the Moon with nice faces. But those
symbols are currently barely supported in fonts.
See [[https://en.wikipedia.org/wiki/Astronomical_symbols#Moon][Astronomical symbols on Wikipedia]].
** Export BBDB contacts to org-contacts.el
#+INDEX: Address Book!BBDB to org-contacts
Try this tool by Wes Hardaker:
[[http://www.hardakers.net/code/bbdb-to-org-contacts/]]
** Calculating date differences - how to write a simple elisp function
#+INDEX: Timestamp!date calculations
#+INDEX: Elisp!technique
Alexander Wingård asked how to calculate the number of days between a
time stamp in his org file and today (see
[[http://thread.gmane.org/gmane.emacs.orgmode/46881]]). Although the
resulting answer is probably not of general interest, the method might
be useful to a budding Elisp programmer.
Alexander started from an already existing org function,
=org-evaluate-time-range=. When this function is called in the context
of a time range (two time stamps separated by "=--="), it calculates the
number of days between the two dates and outputs the result in Emacs's
echo area. What he wanted was a similar function that, when called from
the context of a single time stamp, would calculate the number of days
between the date in the time stamp and today. The result should go to
the same place: Emacs's echo area.
The solution presented in the mail thread is as follows:
#+BEGIN_SRC emacs-lisp
(defun aw/org-evaluate-time-range (&optional to-buffer)
(interactive)
(if (org-at-date-range-p t)
(org-evaluate-time-range to-buffer)
;; otherwise, make a time range in a temp buffer and run o-e-t-r there
(let ((headline (buffer-substring (point-at-bol) (point-at-eol))))
(with-temp-buffer
(insert headline)
(goto-char (point-at-bol))
(re-search-forward org-ts-regexp (point-at-eol) t)
(if (not (org-at-timestamp-p t))
(error "No timestamp here"))
(goto-char (match-beginning 0))
(org-insert-time-stamp (current-time) nil nil)
(insert "--")
(org-evaluate-time-range to-buffer)))))
#+END_SRC
The function assumes that point is on some line with some time stamp
(or a date range) in it. Note that =org-evaluate-time-range= does not care
whether the first date is earlier than the second: it will always output
the number of days between the earlier date and the later date.
As stated before, the function itself is of limited interest (although
it satisfied Alexander's need).The *method* used might be of wider
interest however, so here is a short explanation.
The idea is that we want =org-evaluate-time-range= to do all the
heavy lifting, but that function requires that it be in a date-range
context. So the function first checks whether it's in a date range
context already: if so, it calls =org-evaluate-time-range= directly
to do the work. The trick now is to arrange things so we can call this
same function in the case where we do *not* have a date range
context. In that case, we manufacture one: we create a temporary
buffer, copy the line with the purported time stamp to the temp
buffer, find the time stamp (signal an error if no time stamp is
found) and insert a new time stamp with the current time before the
existing time stamp, followed by "=--=": voilà, we now have a time range
on which we can apply our old friend =org-evaluate-time-range= to
produce the answer. Because of the above-mentioned property
of =org-evaluate-time-range=, it does not matter if the existing
time stamp is earlier or later than the current time: the correct
number of days is output.
Note that at the end of the call to =with-temp-buffer=, the temporary
buffer goes away. It was just used as a scratch pad for the function
to do some figuring.
The idea of using a temp buffer as a scratch pad has wide
applicability in Emacs programming. The rest of the work is knowing
enough about facilities provided by Emacs (e.g. regexp searching) and
by Org (e.g. checking for time stamps and generating a time stamp) so
that you don't reinvent the wheel, and impedance-matching between the
various pieces.
** ibuffer and org files
Neil Smithline posted this snippet to let you browse org files with
=ibuffer=:
#+BEGIN_SRC emacs-lisp
(require 'ibuffer)
(defun org-ibuffer ()
"Open an `ibuffer' window showing only `org-mode' buffers."
(interactive)
(ibuffer nil "*Org Buffers*" '((used-mode . org-mode))))
#+END_SRC
** Enable org-mode links in other modes
Sean O'Halpin wrote a minor mode for this, please check it [[https://github.com/seanohalpin/org-link-minor-mode][here]].
See the relevant discussion [[http://thread.gmane.org/gmane.emacs.orgmode/58715/focus%3D58794][here]].
** poporg.el: edit comments in org-mode
[[https://github.com/QBobWatson/poporg/blob/master/poporg.el][poporg.el]] is a library by François Pinard which lets you edit comments
and strings from your code using a separate org-mode buffer.
** Convert a .csv file to an Org-mode table
Nicolas Richard has a [[http://article.gmane.org/gmane.emacs.orgmode/65456][nice recipe]] using the pcsv library ([[http://marmalade-repo.org/packages/pcsv][available]] from
the Marmelade ELPA repository):
#+BEGIN_SRC emacs-lisp
(defun yf/lisp-table-to-org-table (table &optional function)
"Convert a lisp table to `org-mode' syntax, applying FUNCTION to each of its elements.
The elements should not have any more newlines in them after
applying FUNCTION ; the default converts them to spaces. Return
value is a string containg the unaligned `org-mode' table."
(unless (functionp function)
(setq function (lambda (x) (replace-regexp-in-string "\n" " " x))))
(mapconcat (lambda (x) ; x is a line.
(concat "| " (mapconcat function x " | ") " |"))
table "\n"))
(defun yf/csv-to-table (beg end)
"Convert a csv file to an `org-mode' table."
(interactive "r")
(require 'pcsv)
(insert (yf/lisp-table-to-org-table (pcsv-parse-region beg end)))
(delete-region beg end)
(org-table-align))
#+END_SRC
* Hacking Org: Working with Org-mode and External Programs.
** Use Org-mode with Screen [Andrew Hyatt]
#+INDEX: Link!to screen session
"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]]
#+BEGIN_SRC emacs-lisp
(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.
#+END_SRC
** Org Agenda + Appt + Zenity
#+INDEX: Appointment!reminders
#+INDEX: Appt!Zenity
Russell Adams posted this setup [[http://article.gmane.org/gmane.emacs.orgmode/5806][on the list]]. It makes sure your agenda
appointments are known by Emacs, and it displays warnings in a [[http://live.gnome.org/Zenity][zenity]]
popup window.
#+BEGIN_SRC emacs-lisp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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)))
#+END_SRC
** Org and appointment notifications on Mac OS 10.8
Sarah Bagby [[http://mid.gmane.org/EA76104A-9ACD-4141-8D33-2E4D810D9B5A@geol.ucsb.edu][posted some code]] on how to get appointments notifications on
Mac OS 10.8 with [[https://github.com/alloy/terminal-notifier][terminal-notifier]].
** Org-Mode + gnome-osd
#+INDEX: Appointment!reminders
#+INDEX: Appt!gnome-osd
Richard Riley uses gnome-osd in interaction with Org-Mode to display
appointments. You can look at the code on the [[http://www.emacswiki.org/emacs-en/OrgMode-OSD][emacswiki]].
** txt2org convert text data to org-mode tables
From Eric Schulte
I often find it useful to generate Org-mode tables on the command line
from tab-separated data. The following awk script makes this easy to
do. Text data is read from STDIN on a pipe and any command line
arguments are interpreted as rows at which to insert hlines.
Here are two usage examples.
1. running the following
: $ cat < max_nf){ max_nf = NF; };
for(f=1; f<=NF; f++){
if(length($f) > lengths[f]){ lengths[f] = length($f); };
row[NR][f]=$f; } }
END {
hline_str="|"
for(f=1; f<=max_nf; f++){
for(i=0; i -i -nH "
(when context
(concat "-C" (number-to-string context)))
" -e ")))
(lgrep search "*org*" "/home/matt/org/")))
(global-set-key (kbd "") 'my-org-grep)
#+END_SRC
** Automatic screenshot insertion
#+INDEX: Link!screenshot
Suggested by Russell Adams
#+BEGIN_SRC emacs-lisp
(defun my-org-screenshot ()
"Take a screenshot into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
(interactive)
(setq filename
(concat
(make-temp-name
(concat (buffer-file-name)
"_"
(format-time-string "%Y%m%d_%H%M%S_")) ) ".png"))
(call-process "import" nil nil nil filename)
(insert (concat "[[" filename "]]"))
(org-display-inline-images))
#+END_SRC
** Capture invitations/appointments from MS Exchange emails
#+INDEX: Appointment!MS Exchange
Dirk-Jan C.Binnema [[http://article.gmane.org/gmane.emacs.orgmode/27684/][provided]] code to do this. Please check
[[file:code/elisp/org-exchange-capture.el][org-exchange-capture.el]]
** Audio/video file playback within org mode
#+INDEX: Link!audio/video
Paul Sexton provided code that makes =file:= links to audio or video files
(MP3, WAV, OGG, AVI, MPG, et cetera) play those files using the [[https://github.com/dbrock/bongo][Bongo]] Emacs
media player library. The user can pause, skip forward and backward in the
track, and so on from without leaving Emacs. Links can also contain a time
after a double colon -- when this is present, playback will begin at that
position in the track.
See the file [[file:code/elisp/org-player.el][org-player.el]]
** Under X11 Keep a window with the current agenda items at all time
#+INDEX: Agenda!dedicated window
I struggle to keep (in emacs) a window with the agenda at all times.
For a long time I have wanted a sticky window that keeps this
information, and then use my window manager to place it and remove its
decorations (I can also force its placement in the stack: top always,
for example).
I wrote a small program in qt that simply monitors an HTML file and
displays it. Nothing more. It does the work for me, and maybe somebody
else will find it useful. It relies on exporting the agenda as HTML
every time the org file is saved, and then this little program
displays the html file. The window manager is responsible of removing
decorations, making it sticky, and placing it in same place always.
Here is a screenshot (see window to the bottom right). The decorations
are removed by the window manager:
[[http://turingmachine.org/hacking/org-mode/orgdisplay.png]]
Here is the code. As I said, very, very simple, but maybe somebody will
find if useful.
[[http://turingmachine.org/hacking/org-mode/]]
--daniel german
** Script (thru procmail) to output emails to an Org file
#+INDEX: Conversion!email to org file
Tycho Garen sent [[http://comments.gmane.org/gmane.emacs.orgmode/44773][this]]:
: I've [...] created some procmail and shell glue that takes emails and
: inserts them into an org-file so that I can capture stuff on the go using
: the email program.
Everything is documented [[http://tychoish.com/code/org-mail/][here]].
** Save File With Different Format for Headings (fileconversion)
#+INDEX: Conversion!fileconversion
Using hooks and on the fly
- When writing a buffer to the file: Replace the leading stars from
headings with a file char.
- When reading a file into the buffer: Replace the file chars with
leading stars for headings.
To change the file format just add or remove the keyword in the
~#+STARTUP:~ line in the Org buffer and save.
Now you can also change to Fundamental mode to see how the file looks
like on the level of the file, can go back to Org mode, reenter Org
mode or change to any other major mode and the conversion gets done
whenever necessary.
*** Headings Without Leading Stars (hidestarsfile and nbspstarsfile)
#+INDEX: Conversion!fileconversion hidestarsfile
This is like "a cleaner outline view":
[[http://orgmode.org/manual/Clean-view.html]]
Example of the *file content* first with leading stars as usual and
below without leading stars through ~#+STARTUP: odd hidestars
hidestarsfile~:
#+BEGIN_SRC org
,#+STARTUP: odd hidestars
[...]
,***** TODO section
,******* subsection
,********* subsubsec
- bla bla
,***** section
- bla bla
,******* subsection
#+END_SRC
#+BEGIN_SRC org
,#+STARTUP: odd hidestars hidestarsfile
[...]
,* TODO section
,* subsection
,* subsubsec
- bla bla
,* section
- bla bla
,* subsection
#+END_SRC
The latter is convenient for better human readability when an Org file,
additionally to Emacs, is read with a file viewer or, for smaller edits,
with an editor not capable of the Org file format.
~hidestarsfile~ is a hack and can not become part of the Org core:
- An Org file with ~hidestarsfile~ can not contain list items with a
star as bullet due to the syntax conflict at read time. Mark
E. Shoulson suggested to use the non-breaking space which is now
implemented in fileconversion as ~nbspstarsfile~ as an alternative
for ~hidestarsfile~. Although I don't recommend it because an editor
like typically e. g. Emacs may render the non-breaking space
differently from the space ~0x20~.
- An Org file with ~hidestarsfile~ can almost not be edited with an
Org mode without added functionality of hidestarsfile as long as the
file is not converted back.
*** Headings in Markdown Format (markdownstarsfile)
#+INDEX: Conversion!fileconversion markdownstarsfile
Together with ~oddeven~ you can use ~markdownstarsfile~ to be readable
or even basically editable with Markdown (does not make much sense
with ~odd~, see ~org-convert-to-odd-levels~ and
~org-convert-to-oddeven-levels~ for how to convert).
Example of the *file content*:
#+BEGIN_SRC org
,#+STARTUP: oddeven markdownstarsfile
# section level 1
1. first item of numbered list (same format in Org and Markdown)
## section level 2
- first item of unordered list (same format in Org and Markdown)
### section level 3
+ first item of unordered list (same format in Org and Markdown)
#### section level 4
,* first item of unordered list (same format in Org and Markdown)
,* avoid this item type to be compatible with Org hidestarsfile
#+END_SRC
An Org file with ~markdownstarsfile~ can not contain code comment
lines prefixed with ~#~, even not when within source blocks.
*** emacs-lisp code
#+INDEX: Conversion!fileconversion emacs-lisp code
#+BEGIN_SRC emacs-lisp
;; - fileconversion version 0.10
;; - DISCLAIMER: Make a backup of your Org files before trying
;; `f-org-fileconv-*'. It is recommended to use a version control
;; system like git and to review and commit the changes in the Org
;; files regularly.
;; - Supported "#+STARTUP:" formats: "hidestarsfile",
;; "nbspstarsfile", "markdownstarsfile".
;; Design summary: fileconversion is a round robin of two states linked by
;; two actions:
;; - State `v-org-fileconv-level-org-p' is nil: The level is "file"
;; (encoded).
;; - Action `f-org-fileconv-decode': Replace file char with "*".
;; - State `v-org-fileconv-level-org-p' is non-nil: The level is "Org"
;; (decoded).
;; - Action `f-org-fileconv-encode': Replace "*" with file char.
;;
;; Naming convention of prefix:
;; - f-[...]: "my function", instead of the unspecific prefix `my-*'.
;; - v-[...]: "my variable", instead of the unspecific prefix `my-*'.
(defvar v-org-fileconv-level-org-p nil
"Whether level of buffer is Org or only file.
nil: level is file (encoded), non-nil: level is Org (decoded).")
(make-variable-buffer-local 'v-org-fileconv-level-org-p)
;; Survive a change of major mode that does `kill-all-local-variables', e.
;; g. when reentering Org mode through "C-c C-c" on a #+STARTUP: line.
(put 'v-org-fileconv-level-org-p 'permanent-local t)
;; * Callback `f-org-fileconv-org-mode-beg' before `org-mode'
(defadvice org-mode (before org-mode-advice-before-fileconv)
(f-org-fileconv-org-mode-beg))
(ad-activate 'org-mode)
(defun f-org-fileconv-org-mode-beg ()
;; - Reason to test `buffer-file-name': Only when converting really
;; from/to an Org _file_, not e. g. for a temp Org buffer unrelated to a
;; file.
;; - No `message' to not wipe a possible "File mode specification error:".
;; - `f-org-fileconv-decode' in org-mode-hook would be too late for
;; performance reasons, see
;; http://lists.gnu.org/archive/html/emacs-orgmode/2013-11/msg00920.html
(when (buffer-file-name) (f-org-fileconv-decode)))
;; * Callback `f-org-fileconv-org-mode-end' after `org-mode'
(add-hook 'org-mode-hook 'f-org-fileconv-org-mode-end
nil ; _Prepend_ to hook to have it first.
nil) ; Hook addition global.
(defun f-org-fileconv-org-mode-end ()
;; - Reason to test `buffer-file-name': only when converting really
;; from/to an Org _file_, not e. g. for a temp Org buffer unrelated to a
;; file.
;; - No `message' to not wipe a possible "File mode specification error:".
(when (buffer-file-name)
;; - Adding this to `change-major-mode-hook' or "defadvice before" of
;; org-mode would be too early and already trigger during find-file.
;; - Argument 4: t to limit hook addition to buffer locally, this way
;; and as required the hook addition will disappear when the major
;; mode of the buffer changes.
(add-hook 'change-major-mode-hook 'f-org-fileconv-encode nil t)
(add-hook 'before-save-hook 'f-org-fileconv-encode nil t)
(add-hook 'after-save-hook 'f-org-fileconv-decode nil t)))
(defun f-org-fileconv-re ()
"Check whether there is a #+STARTUP: line for fileconversion.
If found then return the expressions required for the conversion."
(save-excursion
(goto-char (point-min)) ; `beginning-of-buffer' is not allowed.
(let (re-list (count 0))
(while (re-search-forward "^[ \t]*#\\+STARTUP:" nil t)
;; #+STARTUP: hidestarsfile
(when (string-match-p "\\bhidestarsfile\\b" (thing-at-point 'line))
;; Exclude e. g.:
;; - Line starting with star for bold emphasis.
;; - Line of stars to underline section title in loosely quoted
;; ASCII style (star at end of line).
(setq re-list '("\\(\\* \\)" ; common-re
?\ )) ; file-char
(setq count (1+ count)))
;; #+STARTUP: nbspstarsfile
(when (string-match-p "\\bnbspstarsfile\\b" (thing-at-point 'line))
(setq re-list '("\\(\\* \\)" ; common-re
?\xa0)) ; file-char non-breaking space
(setq count (1+ count)))
;; #+STARTUP: markdownstarsfile
(when (string-match-p "\\bmarkdownstarsfile\\b"
(thing-at-point 'line))
;; Exclude e. g. "#STARTUP:".
(setq re-list '("\\( \\)" ; common-re
?#)) ; file-char
(setq count (1+ count))))
(when (> count 1) (error "More than one fileconversion found."))
re-list)))
(defun f-org-fileconv-decode ()
"In headings replace file char with '*'."
(let ((re-list (f-org-fileconv-re)))
(when (and re-list (not v-org-fileconv-level-org-p))
;; No `save-excursion' to be able to keep point in case of error.
(let* ((common-re (nth 0 re-list))
(file-char (nth 1 re-list))
(file-re (concat "^" (string file-char) "+" common-re))
(org-re (concat "^\\*+" common-re))
len
(p (point)))
(goto-char (point-min)) ; `beginning-of-buffer' is not allowed.
;; Syntax check.
(when (re-search-forward org-re nil t)
(goto-char (match-beginning 0))
(org-reveal)
(error "Org fileconversion decode: Syntax conflict at point."))
(goto-char (point-min)) ; `beginning-of-buffer' is not allowed.
;; Substitution.
(with-silent-modifications
(while (re-search-forward file-re nil t)
(goto-char (match-beginning 0))
;; Faster than a lisp call of insert and delete on each single
;; char.
(setq len (- (match-beginning 1) (match-beginning 0)))
(insert-char ?* len)
(delete-char len)))
(goto-char p))))
;; Notes for ediff when only one file has fileconversion:
;; - The changes to the buffer with fileconversion until here are
;; not regarded by `ediff-files' because the first call to diff is
;; made with the bare files directly. Only `ediff-update-diffs'
;; and `ediff-buffers' write the decoded buffers to temp files and
;; then call diff with them.
;; - Workarounds (choose one):
;; - After ediff-files first do a "!" (ediff-update-diffs) in the
;; "*Ediff Control Panel*".
;; - Instead of using `ediff-files' first open the files and then
;; run `ediff-buffers' (better for e. g. a script that takes two
;; files as arguments and uses "emacs --eval").
;; The level is Org most of all when no fileconversion is in effect.
(setq v-org-fileconv-level-org-p t))
(defun f-org-fileconv-encode ()
"In headings replace '*' with file char."
(let ((re-list (f-org-fileconv-re)))
(when (and re-list v-org-fileconv-level-org-p)
;; No `save-excursion' to be able to keep point in case of error.
(let* ((common-re (nth 0 re-list))
(file-char (nth 1 re-list))
(file-re (concat "^" (string file-char) "+" common-re))
(org-re (concat "^\\*+" common-re))
len
(p (point)))
(goto-char (point-min)) ; `beginning-of-buffer' is not allowed.
;; Syntax check.
(when (re-search-forward file-re nil t)
(goto-char (match-beginning 0))
(org-reveal)
(error "Org fileconversion encode: Syntax conflict at point."))
(goto-char (point-min)) ; `beginning-of-buffer' is not allowed.
;; Substitution.
(with-silent-modifications
(while (re-search-forward org-re nil t)
(goto-char (match-beginning 0))
;; Faster than a lisp call of insert and delete on each single
;; char.
(setq len (- (match-beginning 1) (match-beginning 0)))
(insert-char file-char len)
(delete-char len)))
(goto-char p)
(setq v-org-fileconv-level-org-p nil))))
nil) ; For the hook.
#+END_SRC
Michael Brand
** Meaningful diff for org files in a git repository
#+INDEX: git!diff org files
Since most diff utilities are primarily meant for source code, it is
difficult to read diffs of text files like ~.org~ files easily. If you
version your org directory with a SCM like git you will know what I
mean. However for git, there is a way around. You can use
=gitattributes= to define a custom diff driver for org files. Then a
regular expression can be used to configure how the diff driver
recognises a "function".
Put the following in your =/.gitattributes=.
: *.org diff=org
Then put the following lines in =/.git/config=
: [diff "org"]
: xfuncname = "^(\\*+ [a-zA-Z0-9]+.+)$"
This will let you see diffs for org files with each hunk identified by
the unmodified headline closest to the changes. After the
configuration a diff should look something like the example below.
#+BEGIN_EXAMPLE
diff --git a/org-hacks.org b/org-hacks.org
index a0672ea..92a08f7 100644
--- a/org-hacks.org
+++ b/org-hacks.org
@@ -2495,6 +2495,22 @@ ** Script (thru procmail) to output emails to an Org file
Everything is documented [[http://tychoish.com/code/org-mail/][here]].
+** Meaningful diff for org files in a git repository
+
+Since most diff utilities are primarily meant for source code, it is
+difficult to read diffs of text files like ~.org~ files easily. If you
+version your org directory with a SCM like git you will know what I
+mean. However for git, there is a way around. You can use
+=gitattributes= to define a custom diff driver for org files. Then a
+regular expression can be used to configure how the diff driver
+recognises a "function".
+
+Put the following in your =/.gitattributes=.
+: *.org diff=org
+Then put the following lines in =/.git/config=
+: [diff "org"]
+: xfuncname = "^(\\*+ [a-zA-Z0-9]+.+)$"
+
,* Musings
,** Cooking? Brewing?
#+END_EXAMPLE
** Opening devonthink links
John Wiegley wrote [[https://github.com/jwiegley/dot-emacs/blob/master/lisp/org-devonthink.el][org-devonthink.el]], which lets you handle devonthink
links from org-mode.
** Memacs - Org-mode collecting meta-data from the disk and cloud
Karl Voit designed Memacs ([[https://en.wikipedia.org/wiki/Memex][Memex]] and Emacs) which is a collection of
modules that are able to get meta-data from different kind of
sources. Memacs then generates output files containing meta-data in
Org-mode format. Those files a most likely integrated as ~*.org_archive~
files in your agenda.
This way, you can get a pretty decent overview of your (digital) life:
- file name timestamps ([[https://en.wikipedia.org/wiki/Iso_date][ISO 8601]]; like "2013-10-11 Product Demonstration.odp")
- emails (IMAP, POP, Maildir, mbox)
- RSS feeds (blog updates, ... *lots* of possibilities there!)
- version system commits (SVN, git)
- calendar (iCal, CSV)
- text messages from your phone (Android)
- phone calls (Android)
- photographs (EXIF)
- bank accounts ([[http://easybank.at][easybank]])
- usenet postings (slrn, mbox, ...)
- XML (a sub-set of easy-to-parse XML files can be parsed with minimal
effort)
General idea: you set up the module(s) you would like to use once and
they are running in the background. As long as the data source does
not change, you should not have to worry about the module again.
It is hard to explain the vast amount of (small) benefits you get once
you have set up your Memacs modules.
There is [[http://arxiv.org/abs/1304.1332][a whitepaper which describes Memacs]] and its implications.
Memacs is [[https://github.com/novoid/Memacs][hosted on github]] and is written in Python.
You can use Memacs to write your own Memacs module: an example module
demonstrates how to write modules with very low effort. Please
consider a pull request on github so that other people can use your
module as well!
[[https://github.com/novoid/twitter-json_to_orgmode][Twitter JSON to Org-mode]] generates Memacs-like output files for
[[https://blog.twitter.com/2012/your-twitter-archive][Twitter export archives]] (JSON) but is independent of Memacs.
* Musings
** Cooking? Brewing?
#+INDEX: beer!brewing
#+INDEX: cooking!conversions
See [[http://article.gmane.org/gmane.emacs.orgmode/44981][this message]] from Erik Hetzner:
It currently does metric/english conversion, and a few other tricks.
Basically I just use calc’s units code. I think scaling recipes, or
turning percentages into weights would be pretty easy.
[[https://gitorious.org/org-cook/org-cook]]
There is also, for those interested:
[[https://gitorious.org/org-brew/org-brew]]
for brewing beer. This is again, mostly just calc functions, including
hydrometer correction, abv calculation, priming sugar for a given CO_2
volume, etc. More integration with org-mode should be possible: for
instance it would be nice to be able to use a lookup table (of ingredients)
to calculate target original gravity, IBUs, etc.
# Emacs 24.2.50.1 (Org mode 8.2.10)