53 KiB
Emacs — Packages — Org Mode
- Org-mode
Org-mode
(mapconcat (lambda (line)
(let* ((key (nth 0 line))
(function (nth 1 line))
(comment (or (nth 2 line) ""))
(package (or (nth 3 line) "")))
(format "\"%s%s\" %s"
prefix
key
(if (string= "" comment)
(if (member function '("" "nil")) "nil" (concat "#'" function))
(format "'(%s :wk %s%s)"
(if (member function '("" "nil")) ":ignore t" function)
(if (member function '("none" "nil")) "t" (concat "\"" comment "\""))
(if (string-blank-p package) "" (concat ":package " package)))))))
table
"\n")
Since recently, in order to make org-cite
compile properly, we need
the citeproc
package, a citation processor.
(use-package citeproc
:after (org)
:defer t
:straight (:build t))
Org is the main reason I am using Emacs. It is an extremely powerful tool when you want to write anything that is not necessarily primarily programming-related, though it absolutely can be! Org can be a replacement for anything similar to LibreOffice Writer, LibreOffice Calc, and LibreOffice Impress. It is a much more powerful (and older) version of Markdown which can be exported to LaTeX and HTML at least, rendering writing web pages and technical, scientific documents much simpler than writing manually HTML and LaTeX code, especially when a single document source is meant to be exported for both formats. And since org is an Emacs package, that also means it can be greatly extended however we like!
(use-package org
:straight t
:defer t
:after engrave-faces
:commands (orgtbl-mode)
:hook ((org-mode . visual-line-mode)
(org-mode . org-num-mode))
:custom-face
(org-macro ((t (:foreground "#b48ead"))))
:init
(auto-fill-mode -1)
:config
<<org-hydra-babel>>
(require 'ox-beamer)
(require 'org-protocol)
(setq org-hide-leading-stars nil
org-hide-macro-markers t
org-ellipsis " ⤵"
org-image-actual-width 600
org-redisplay-inline-images t
org-display-inline-images t
org-startup-with-inline-images "inlineimages"
org-pretty-entities t
org-fontify-whole-heading-line t
org-fontify-done-headline t
org-fontify-quote-and-verse-blocks t
org-startup-indented t
org-startup-align-all-tables t
org-use-property-inheritance t
org-list-allow-alphabetical t
org-M-RET-may-split-line nil
org-src-window-setup 'split-window-below
org-src-fontify-natively t
org-src-tab-acts-natively t
org-src-preserve-indentation t
org-log-done 'time
org-directory "~/org"
org-default-notes-file (expand-file-name "notes.org" org-directory))
(with-eval-after-load 'oc
(setq org-cite-global-bibliography '("~/org/bibliography/references.bib")))
<<org-agenda-files>>
<<org-behavior-electric>>
<<org-capture-target-files>>
<<org-capture-templates>>
<<org-create-emphasis-functions()>>
<<org-babel-load-languages>>
<<org-use-sub-superscripts>>
<<org-latex-compiler>>
<<org-latex-src-block-backend>>
<<org-latex-default-packages>>
<<org-export-latex-hyperref-format>>
<<org-latex-pdf-process>>
<<org-latex-logfiles-add-extensions>>
<<org-re-reveal>>
<<org-html-validation>>
<<org-latex-classes>>
<<org-publish-projects>>
<<org-mode-visual-prettify-symbols>>
:general
(phundrak/evil
:keymaps 'org-mode-map
:packages 'org
"RET" 'org-open-at-point)
(phundrak/major-leader-key
:keymaps 'org-mode-map
:packages 'org
<<general-keybindings-gen(table=org-keybinds-various)>>
<<general-keybindings-gen(table=org-keybinds-babel)>>
<<general-keybindings-gen(table=org-keybinds-dates)>>
<<general-keybindings-gen(table=org-keybinds-insert)>>
<<general-keybindings-gen(table=org-keybinds-jump)>>
<<general-keybindings-gen(table=org-keybinds-tables)>>
<<general-keybindings-gen(table=org-keybinds-toggles)>>)
<<org-capture-keybinds>>
(phundrak/major-leader-key
:packages 'org
:keymaps 'org-src-mode-map
"'" #'org-edit-src-exit
"k" #'org-edit-src-abort))
The main feature from evil-org
that I love is how easy it is to modify
some keybindings for keyboards layouts that do not have hjkl
, such as
the bépo layout (or Dvorak or Colemak if you are into that). But it
also adds a ton of default keybindings which are just much more
comfortable than the default ones you get with evil and org naked.
(use-package evil-org
:straight (:build t)
:after (org)
:hook (org-mode . evil-org-mode)
:config
(setq-default evil-org-movement-bindings
'((up . "s")
(down . "t")
(left . "c")
(right . "r")))
(evil-org-set-key-theme '(textobjects navigation calendar additional shift operators))
(require 'evil-org-agenda)
(evil-org-agenda-set-keys))
This package is a small package I’ve written that helps me when writing conlanging documents, with features such as creating syntax trees, converting translitterated text to its native script, etc…
(use-package conlanging
:straight (conlanging :build t
:type git
:repo "https://labs.phundrak.com/phundrak/conlanging.el")
:after org
:defer t)
Since very recently, the contrib/lisp/
directory of org moved out of
the main repository to this repository. On the other hand,
contrib/scripts/
moved to the worg repository, but I don’t need
it. The main reason I want org-contrib
is due to ox-extra
that allow
the usage of the :ignore:
tag in org.
(use-package org-contrib
:after (org)
:defer t
:straight (:build t)
:init
(require 'ox-extra)
(ox-extras-activate '(latex-header-blocks ignore-headlines)))
Agenda
(setq org-agenda-files (list "~/org/agenda" "~/org/notes.org"))
(use-package org-caldav
:straight (:build t)
:defer t
:config
(setq org-caldav-url "https://nextcloud.phundrak.com/remote.php/dav/calendars/phundrak"
org-icalendar-timezone "Europe/Paris"
org-caldav-calendars
`((:calendar-id "personal" :files ("~/org/agenda/private.org")
:inbox "~/org/agenda/private.org")
(:calendar-id "contact_birthdays" :files ("~/org/agenda/birthdays.org")
:inbox "~/org/agenda/birthdays.org"))))
Babel
One of the amazing features of org-mode is its literary programming capacities by running code blocks from within Org-mode itself. But for that, only a couple of languages are supported directly by Org-mode itself, and they need to be activated. Here are the languages I activated in my Org-mode configuration:
C |
emacs-lisp |
gnuplot |
latex |
makefile |
plantuml |
python |
sass |
shell |
sql |
'((C . t) (emacs-lisp . t) (gnuplot . t) (latex . t) (makefile . t) (plantuml . t) (python . t) (sass . t) (shell . t) (sql . t))
The corresponding code is as follows:
(org-babel-do-load-languages
'org-babel-load-languages
<<org-babel-languages-gen()>>)
Some languages can run asynchronously with the help of ob-async
.
(use-package ob-async
:straight (:build t)
:defer t
:after (org ob))
A package I use from time to time is ob-latex-as-png
which allows me
to easily convert a LaTeX snippet into a PNG, regardless of the
exporter I use afterwards. Its installation is pretty simple:
(use-package ob-latex-as-png
:after org
:straight (:build t))
A nice thing to have when working with REST APIs is to have a REST client. Even better if it can work inside org-mode!
(use-package ob-restclient
:straight (:build t)
:defer t
:after (org ob)
:init
(add-to-list 'org-babel-load-languages '(restclient . t)))
Behavior
A useful package I like is toc-org
which creates automatically a table
of contents. My main usage for this however is not just to create a
table of content of my files to quickly jump around my file (I have
counsel-org-goto
for that), but it is for creating table of contents
for org files that will be hosted and viewable on GitHub.
(use-package toc-org
:after (org markdown-mode)
:straight (:build t)
:init
(add-to-list 'org-tag-alist '("TOC" . ?T))
:hook (org-mode . toc-org-enable)
:hook (markdown-mode . toc-org-enable))
electric-mode
also bothers me a lot when editing org files, so let’s deactivate it:
(add-hook 'org-mode-hook (lambda ()
(interactive)
(electric-indent-local-mode -1)))
As explained in my blog post, org-mode is terrible with coming up with meaningful IDs for its headings. I actually wrote a package for this!
(use-package org-unique-id
:straight (org-unique-id :build t
:type git
:host github
:repo "Phundrak/org-unique-id")
:defer t
:after org
:init (add-hook 'before-save-hook #'org-unique-id-maybe))
Capture
Org capture is an amazing tool for taking quick notes, be it simple text, links, resources, or reminders. They are all organised is specified org files which are described below.
(defvar org-conlanging-file "~/org/conlanging.org")
(defvar org-notes-file "~/org/notes.org")
(defvar org-journal-file "~/org/journal.org")
(defvar org-linguistics-file "~/org/linguistics.org")
(defvar org-novel-file "~/org/novel.org")
(defvar org-agenda-file "~/org/agenda/private.org")
(defvar org-school-file "~/org/agenda/school.org")
(defvar org-worldbuilding-file "~/org/worldbuilding.org")
Let me describe a keybind to invoke org-capture from anywhere within Emacs.
(phundrak/leader-key
:packages 'org
:infix "o"
"" '(:ignore t :which-key "org")
"c" #'org-capture)
When org-capture
is invoked, it will ask which template we wish to
use. In the table /phundrak/config.phundrak.com/src/commit/ce1daa64669fe4967d939fc61948c7808b2922a6/docs/emacs/packages/org-capture-shortcuts-table, the key column
represents which keychord we need to hit, titled with name, we need to
hit in order to use the template, inserted in the designated file in
the manner described by insertion mode.
Shortcut | Name | Title | Insertion mode | file | template |
---|---|---|---|---|---|
e | |||||
ew | Write Email | Emails | file+headline | org-default-notes-file | email.orgcaptmpl |
j | Journal | file+datetree | org-journal-file | journal.orgcaptmpl | |
l | Link | ||||
ll | General | file+headline | org-default-notes-file | link.orgcaptmpl | |
ly | YouTube | file+headline | org-default-notes-file | youtube.orgcaptmpl | |
L | Protocol Link | Link | file+headline | org-default-notes-file | protocol-link.orgcaptmpl |
n | Notes | ||||
nc | Conlanging | Note | file+headline | org-conlanging-file | notes.orgcaptmpl |
nn | General | file+headline | org-default-notes-file | notes.orgcaptmpl | |
nN | Novel | Note | file+headline | org-novel-notes-file | notes.orgcaptmpl |
nq | Quote | file+headline | org-default-notes-file | notes-quote.orgcaptmpl | |
nw | Worldbuilding | Note | file+headline | org-wordbuilding-file | notes.orgcaptmpl |
N | Novel | ||||
Ni | Ideas | file+headline | org-novel-notes-file | notes.orgcaptmpl | |
p | Protocol | Link | file+headline | org-default-notes-file | protocol.orgcaptmpl |
r | Resources | ||||
rc | Conlanging | Resources | file+headline | org-conlanging-file | resource.orgcaptmpl |
re | Emacs | file+headline | org-default-notes-file | resource.orgcaptmpl | |
ri | Informatique | file+headline | org-default-notes-file | resource.orgcaptmpl | |
rl | Linguistics | file+headline | org-default-notes-file | resource.orgcaptmpl | |
rL | Linux | file+headline | org-default-notes-file | resource.orgcaptmpl | |
rw | Worldbuilding | Resources | file+headline | org-wordbuilding-file | resource.orgcaptmpl |
t | Tasks | ||||
tb | Birthday | file+headline | org-private-agenda-file | birthday.orgcaptmpl | |
te | Event | file+headline | org-private-agenda-file | event.orgcaptmpl | |
th | Health | file+headline | org-private-agenda-file | health.orgcaptmpl | |
ti | Informatique | file+headline | org-private-agenda-file | informatique.orgcaptmpl |
All templates can be found in my dotfiles’ repository.
(mapconcat (lambda (entry)
(let ((key (nth 0 entry))
(name (nth 1 entry))
(title (nth 2 entry))
(ins-mode (nth 3 entry))
(file (nth 4 entry))
(template (nth 5 entry)))
(if (string= "" ins-mode)
(format "%S" `(,key ,name))
(format "(\"%s\" \"%s\" entry\n %S\n %S)"
key name
`(,(intern ins-mode) ,(intern file) ,(if (string= "file+datetree" ins-mode)
(intern "")
(if (string= title "")
name
title)))
`(file ,(concat "~/org/capture/" template))))))
entries
"\n")
("e" "Email") ("ew" "Write Email" entry (file+headline org-default-notes-file "Emails") (file "~/org/capture/email.orgcaptmpl")) ("j" "Journal" entry (file+datetree org-journal-file ##) (file "~/org/capture/journal.orgcaptmpl")) ("l" "Link") ("ll" "General" entry (file+headline org-default-notes-file "General") (file "~/org/capture/link.orgcaptmpl")) ("ly" "YouTube" entry (file+headline org-default-notes-file "YouTube") (file "~/org/capture/youtube.orgcaptmpl")) ("L" "Protocol Link" entry (file+headline org-default-notes-file "Link") (file "~/org/capture/protocol-link.orgcaptmpl")) ("n" "Notes") ("nc" "Conlanging" entry (file+headline org-conlanging-file "Note") (file "~/org/capture/notes.orgcaptmpl")) ("nn" "General" entry (file+headline org-default-notes-file "General") (file "~/org/capture/notes.orgcaptmpl")) ("nN" "Novel" entry (file+headline org-novel-notes-file "Note") (file "~/org/capture/notes.orgcaptmpl")) ("nq" "Quote" entry (file+headline org-default-notes-file "Quote") (file "~/org/capture/notes-quote.orgcaptmpl")) ("nw" "Worldbuilding" entry (file+headline org-wordbuilding-file "Note") (file "~/org/capture/notes.orgcaptmpl")) ("N" "Novel") ("Ni" "Ideas" entry (file+headline org-novel-notes-file "Ideas") (file "~/org/capture/notes.orgcaptmpl")) ("p" "Protocol" entry (file+headline org-default-notes-file "Link") (file "~/org/capture/protocol.orgcaptmpl")) ("r" "Resources") ("rc" "Conlanging" entry (file+headline org-conlanging-file "Resources") (file "~/org/capture/resource.orgcaptmpl")) ("re" "Emacs" entry (file+headline org-default-notes-file "Emacs") (file "~/org/capture/resource.orgcaptmpl")) ("ri" "Informatique" entry (file+headline org-default-notes-file "Informatique") (file "~/org/capture/resource.orgcaptmpl")) ("rl" "Linguistics" entry (file+headline org-default-notes-file "Linguistics") (file "~/org/capture/resource.orgcaptmpl")) ("rL" "Linux" entry (file+headline org-default-notes-file "Linux") (file "~/org/capture/resource.orgcaptmpl")) ("rw" "Worldbuilding" entry (file+headline org-wordbuilding-file "Resources") (file "~/org/capture/resource.orgcaptmpl")) ("t" "Tasks") ("tb" "Birthday" entry (file+headline org-private-agenda-file "Birthday") (file "~/org/capture/birthday.orgcaptmpl")) ("te" "Event" entry (file+headline org-private-agenda-file "Event") (file "~/org/capture/event.orgcaptmpl")) ("th" "Health" entry (file+headline org-private-agenda-file "Health") (file "~/org/capture/health.orgcaptmpl")) ("ti" "Informatique" entry (file+headline org-private-agenda-file "Informatique") (file "~/org/capture/informatique.orgcaptmpl"))
The capture templates are set like so:
(setq org-capture-templates
'(
<<org-capture-shortcuts-gen()>>))
Custom functions
Emphasize text
Sometimes, I want to emphasize some text in my org-mode documents. It’s very possible to just go to the beginning of the chosen text, add the marker, then go to the end of the text than needs emphasis and add another marker, and I’m sure most people are fine with that. But I also like being able to select a region and hit a keybind to emphasize it that way. The table /phundrak/config.phundrak.com/src/commit/ce1daa64669fe4967d939fc61948c7808b2922a6/docs/emacs/packages/org-emphasis-character lists the emphasis characters in org-mode, their role, and the character code of each emphasis character. From that, creating functions that emphasize a selected text is quite easy.
Emphasis | Character | Character code |
---|---|---|
bold | * |
42 |
italic | / |
47 |
underline | _ |
95 |
verbatim | = |
61 |
code | ~ |
126 |
strike-through | + |
43 |
(mapconcat (lambda (emphasis)
(let ((type (car emphasis))
(code (nth 2 emphasis)))
(format "(defun org-emphasize-%s ()
\"Emphasize as %s the current region.\"
(interactive)
(org-emphasize %s))"
type
type
code)))
emphasis-list
"\n")
(defun org-emphasize-bold ()
"Emphasize as bold the current region."
(interactive)
(org-emphasize 42))
(defun org-emphasize-italic ()
"Emphasize as italic the current region."
(interactive)
(org-emphasize 47))
(defun org-emphasize-underline ()
"Emphasize as underline the current region."
(interactive)
(org-emphasize 95))
(defun org-emphasize-verbatim ()
"Emphasize as verbatim the current region."
(interactive)
(org-emphasize 61))
(defun org-emphasize-code ()
"Emphasize as code the current region."
(interactive)
(org-emphasize 126))
(defun org-emphasize-strike-through ()
"Emphasize as strike-through the current region."
(interactive)
(org-emphasize 43))
You can find the keybinds for these functions here.
phundrak/toggle-org-src-window-split
(defun phundrak/toggle-org-src-window-split ()
"This function allows the user to toggle the behavior of
`org-edit-src-code'. If the variable `org-src-window-setup' has
the value `split-window-right', then it will be changed to
`split-window-below'. Otherwise, it will be set back to
`split-window-right'"
(interactive)
(if (equal org-src-window-setup 'split-window-right)
(setq org-src-window-setup 'split-window-below)
(setq org-src-window-setup 'split-window-right))
(message "Org-src buffers will now split %s"
(if (equal org-src-window-setup 'split-window-right)
"vertically"
"horizontally")))
Exporters
I want to disable by default behaviour of ^
and _
for only one
character, making it compulsory to use instead ^{}
and _{}
respectively. This is due to my frequent usage of the underscore in my
org files as a regular character and not a markup one, especially when
describing phonetics evolution. So, let’s disable it:
(setq org-use-sub-superscripts (quote {}))
Epub
A backend for exporting files through org I like is ox-epub
which, as
you can guess, exports org files to the Epub format.
(use-package ox-epub
:after (org ox)
:straight (:build t))
Gemini
Gemini is a lightweight protocol for creating lightweight websites
that are basically text-only websites with maybe some images. I’m
currently maintaining my own fork of Justin Abrahms’ ox-gemini
which
fixes two issues I had with the original package.
(use-package ox-gemini
:defer t
:straight (ox-gemini :build t
:fork (:type git
:host nil
:repo "https://labs.phundrak.com/phundrak/ox-gemini"))
:after (ox org))
HTML
On HTML exports, Org-mode tries to include a validation link for the exported HTML. Let’s disable that since I never use it.
(setq org-html-validation-link nil)
This package allows for live-previewing the HTML export of an org buffer in an XWidget Webkit browser window. But when testing it, it’s not great for large org files, I should keep its usage for smaller org files.
(use-package preview-org-html-mode
:defer t
:after (org)
:straight (preview-org-html-mode :build t
:type git
:host github
:repo "jakebox/preview-org-html-mode")
:general
(phundrak/major-leader-key
:keymaps 'org-mode-map
:packages 'preview-org-html-mode
:infix "P"
"" '(:ignore t :which-key "preview")
"h" #'preview-org-html-mode
"r" #'preview-org-html-refresh
"p" #'preview-org-html-pop-window-to-frame)
:config
(setq preview-org-html-refresh-configuration 'save))
Hugo
I manage my blog with Hugo. Although it natively supports the org format, it’s not great compared to its markdown support. So, instead, let’s directly export our org files as markdown files and let Hugo do the rest of the job for us!
(use-package ox-hugo
:defer t
:after ox
:straight t)
I also have a function for publishing my blog once I exported my
articles with ox-hugo
. It will compile blog into a public/
directory
and copy its content over to my remote server.
(defun phundrak/blog-publish ()
"Publish my blog through Hugo to my remote server."
(interactive)
(let* ((default-directory (expand-file-name "~/org/blog"))
(public-path (concat default-directory "/public"))
(target-path "/rsync:Tilo:/home/phundrak/www/phundrak.com/blog"))
(compile "hugo")
(let ((files (mapcar (lambda (file)
(f-relative file public-path))
(f-files public-path nil t))))
(dolist (file files)
(copy-file (concat public-path "/" file)
(concat target-path "/" file)
t nil t)))))
LaTeX
When it comes to exports, I want the LaTeX and PDF exports to be done with XeTeX only. I also want LaTeX exports to use my labels rather than org-generated labels.
(setq org-latex-compiler "xelatex"
org-latex-prefer-user-labels t)
A new backend that was introduced in org-mode for LaTeX source block
coloring is engraved
.
(use-package engrave-faces
:straight (:build t))
(require 'engrave-faces)
(setq org-latex-src-block-backend 'engraved)
The default packages break my LaTeX exports: for some reason, images
are not loaded and exported in PDFs, so I needed to redefine the
default packages excluding the one that broke my exports; namely, I
need to remove inputenc
, fontenc
and grffile
. I also added some
default packages:
cleveref
for better references to various elements.svg
for inserting SVG files in PDF outputsbooktabs
for nicer tables- and
tabularx
for tabulars with adjustable columns
(dolist (package '(("AUTO" "inputenc" t ("pdflatex"))
("T1" "fontenc" t ("pdflatex"))
("" "grffile" t)))
(delete package org-latex-default-packages-alist))
(dolist (package '(("AUTO" "babel" nil ("pdflatex"))
("AUTO" "polyglossia" nil ("xelatex" "lualatex"))
("capitalize" "cleveref")
("" "booktabs")
("" "tabularx")))
(add-to-list 'org-latex-default-packages-alist package t))
(setq org-latex-reference-command "\\cref{%s}")
By the way, reference links in LaTeX should be written in this format,
since we are using cleveref
:
(setq org-export-latex-hyperref-format "\\ref{%s}")
Tectonic is awesome for processing LaTeX documents! Look how simple it is!
(setq org-latex-pdf-process
'("tectonic -Z shell-escape --synctex --outdir=%o %f"))
Finally, org-mode is supposed to automatically clean logfiles after it exports an org file to LaTeX. However, it misses a few, so I need to add their extension like so:
(dolist (ext '("bbl" "lot"))
(add-to-list 'org-latex-logfiles-extensions ext t))
Reveal.js
(use-package org-re-reveal
:defer t
:after org
:straight (:build t)
:init
(add-hook 'org-mode-hook (lambda () (require 'org-re-reveal)))
:config
(setq org-re-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js"
org-re-reveal-revealjs-version "4"))
SSH Config
Yet another exporter I enjoy is ox-ssh
with which I manage my
$HOME/.ssh/config
file. You won’t find my org file for managing my
servers on my repos though.
(use-package ox-ssh
:after (ox org)
:straight (:build t))
Keybindings
Be prepared, I have a lot of keybindings for org-mode! They are all
prefixed with a comma ,
in normal mode.
Key chord | Function | Description |
---|---|---|
RET | org-ctrl-c-ret | |
* | org-ctrl-c-star | |
, | org-ctrl-c-ctrl-c | |
' | org-edit-special | |
- | org-ctrl-c-minus | |
a | org-agenda | |
c | org-capture | |
C | org-columns | |
e | org-export-dispatch | |
l | org-store-link | |
p | org-priority | |
r | org-reload |
I then have a couple of babel-related functions.
Key chord | Function | Description |
---|---|---|
b | nil | babel |
b. | org-babel-transient/body | |
bb | org-babel-execute-buffer | |
bc | org-babel-check-src-block | |
bC | org-babel-tangle-clean | |
be | org-babel-execute-maybe | |
bf | org-babel-tangle-file | |
bn | org-babel-next-src-block | |
bo | org-babel-open-src-block-result | |
bp | org-babel-previous-src-block | |
br | org-babel-remove-result-one-or-many | |
bR | org-babel-goto-named-result | |
bt | org-babel-tangle | |
bi | org-babel-view-src-block-info |
The org-babel-transient
hydra allows me to quickly navigate between
code blocks and interact with them. This code block was inspired by
one you can find in Spacemacs.
(defhydra org-babel-transient ()
"
^Navigate^ ^Interact
^^^^^^^^^^^------------------------------------------
[_t_/_s_] navigate src blocs [_x_] execute src block
[_g_]^^ goto named block [_'_] edit src block
[_z_]^^ recenter screen [_q_] quit
"
("q" nil :exit t)
("t" org-babel-next-src-block)
("s" org-babel-previous-src-block)
("g" org-babel-goto-named-src-block)
("z" recenter-top-bottom)
("x" org-babel-execute-maybe)
("'" org-edit-special :exit t))
We next have keybindings related to org-mode’s agenda capabilities. We can schedule a todo header for some dates, or set a deadline.
Key chord | Function | Description |
---|---|---|
d | nil | dates |
dd | org-deadline | |
ds | org-schedule | |
dt | org-time-stamp | |
dT | org-time-stamp-inactive |
Let’s now define some keybinds for inserting stuff in our org buffer:
Key chord | Function | Description |
---|---|---|
i | nil | insert |
ib | org-insert-structure-template | |
id | org-insert-drawer | |
ie | nil | emphasis |
ieb | org-emphasize-bold | |
iec | org-emphasize-code | |
iei | org-emphasize-italic | |
ies | org-emphasize-strike-through | |
ieu | org-emphasize-underline | |
iev | org-emphasize-verbatim | |
iE | org-set-effort | |
if | org-footnote-new | |
ih | org-insert-heading | |
iH | counsel-org-link | |
ii | org-insert-item | |
il | org-insert-link | |
in | org-add-note | |
ip | org-set-property | |
is | org-insert-subheading | |
it | org-set-tags-command |
There isn’t a lot of stuff I can jump to yet, but there’s still some:
Key chord | Function | Description |
---|---|---|
j | nil | jump |
ja | counsel-org-goto-all | |
jh | counsel-org-goto |
Tables get a bit more love:
Key chord | Function | Description |
---|---|---|
t | nil | tables |
tc | org-table-move-column-left | |
tt | org-table-move-row-down | |
ts | org-table-move-row-up | |
tr | org-table-move-column-right | |
ta | org-table-align | |
te | org-table-eval-formula | |
tf | org-table-field-info | |
tF | org-table-edit-formulas | |
th | org-table-convert | |
tl | org-table-recalculate | |
tp | org-plot/gnuplot | |
tS | org-table-sort-lines | |
tw | org-table-wrap-region | |
tx | org-table-shrink | |
tN | org-table-create-with-table.el | |
td | nil | delete |
tdc | org-table-delete-column | |
tdr | org-table-kill-row | |
ti | nil | insert |
tic | org-table-insert-column | |
tih | org-table-insert-hline | |
tir | org-table-insert-row | |
tiH | org-table-hline-and-move | |
tt | nil | toggle |
ttf | org-table-toggle-formula-debugger | |
tto | org-table-toggle-coordinate-overlays |
Finally, let’s make enabling and disabling stuff accessible:
Key chord | Function | Description |
---|---|---|
T | nil | toggle |
Tc | org-toggle-checkbox | |
Ti | org-toggle-inline-images | |
Tl | org-latex-preview | |
Tn | org-num-mode | |
Ts | phundrak/toggle-org-src-window-split | |
Tt | org-show-todo-tree | |
TT | org-todo |
LaTeX formats
I currently have two custom formats for my Org-mode exports: one for
general use (initially for my conlanging files, hence its conlang
name), and one for beamer exports.
Below is the declaration of the conlang
LaTeX class:
'("conlang"
"\\documentclass{book}"
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
And here is the declaration of the beamer
class:
`("beamer"
,(concat "\\documentclass[presentation]{beamer}\n"
"[DEFAULT-PACKAGES]"
"[PACKAGES]"
"[EXTRA]\n")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
Both these classes have to be added to org-latex-classes
like so:
(eval-after-load "ox-latex"
'(progn
(add-to-list 'org-latex-classes
<<org-latex-class-conlang>>)
(add-to-list 'org-latex-classes
<<org-latex-class-beamer>>)))
Projects
Another great features of Org-mode is the Org projects that allow the user to easily publish a bunch of org files to a remote location. Here is the current declaration of my projects, which will be detailed later:
<<org-proj-config-setup>>
(setq org-publish-project-alist
`(<<org-proj-config-html>>
<<org-proj-config-static>>
<<org-proj-config>>))
Configuration website
This is my configuration for exporting my dotfiles to my website in a web format only. No PDFs or anything, just HTML. Please note that I do not use that often anymore, I much prefer the automatic script that I have which deploys through my Drone instance my website on git pushes.
And before we get into the actual configuration, I would like to introduce a couple of variables. This is a bit more verbose than if I declared everything manually, but now I can change all three values at the same time without a hasle.
(defvar phundrak//projects-config-target
"/ssh:Tilo:~/www/phundrak.com/config"
"Points to where exported files for config.phundrak.com should be put.")
(defvar phundrak//projects-config-source
"~/org/config/"
"Points to where the sources for config.phundrak.com are.")
(defvar phundrak//projects-config-language
"en"
"Language of the website config.phundrak.com.")
(defvar phundrak//projects-config-recursive
t
"Defines whether subdirectories should be parsed for config.phundrak.com.")
Now, here is my configuration. In this snippet, my org files located in my source directory get exported in the HTML format and published to my target directory on my remote server through RSYNC via TRAMP. A sitemap is automatically generated, which comes in handy with the online sitemap that is available through the navigation bar.
("config-website-html"
:base-directory ,phundrak//projects-config-source
:base-extension "org"
:publishing-directory ,phundrak//projects-config-target
:recursive ,phundrak//projects-config-recursive
:language ,phundrak//projects-config-language
:publishing-function org-html-publish-to-html
:headline-levels 5
:auto-sitemap t
:auto-preamble t)
We also have the component for all the static files needed to run the website (mostly images tbh).
("config-website-static"
:base-directory ,phundrak//projects-config-source
:base-extension "png\\|jpg\\|gif\\|webp\\|svg\\|jpeg\\|ttf\\|woff\\|txt\\|epub\\|md"
:publishing-directory ,phundrak//projects-config-target
:recursive ,phundrak//projects-config-recursive
:language ,phundrak//projects-config-language
:publishing-function org-publish-attachment)
The project is then defined like so:
("config-website"
:components ("config-website-org"
"config-website-static"))
Org-roam
After hearing about it for so many years and thinking I really should install it one day, 2023 is finally the year I installed org-roam! For those unaware of it, org-roam is a Zettelkasten-style knowledge management system based on org-mode.
(use-package org-roam
:straight (:build t)
:defer t
:custom
(org-roam-directory (expand-file-name "org/roam/" (getenv "HOME")))
(org-roam-completion-everywhere t)
:config
(org-roam-db-autosync-mode 1)
:general
(phundrak/leader-key
:packages '(org org-roam)
:infix "o"
"r" '(:ignore t :which-key "roam")
"rb" '(org-mark-ring-goto :which-key "back")
"rB" #'org-roam-buffer-toggle
"rn" '(:ignore t :which-key "nodes")
"rnf" #'org-roam-node-find
"rni" #'org-roam-node-insert
"rno" #'org-roam-node-open
"rnr" #'org-roam-node-random
"rnv" #'org-roam-node-visit
"rs" '(:ignore t :which-key "sync")
"rsa" #'org-roam-db-autosync-mode
"rsc" #'org-roam-db-clear-all
"rsd" #'org-roam-db-diagnose-node
"rss" #'org-roam-db-sync
"ru" '(:ignore t :which-key "ui")
"rua" #'org-roam-ui-add-to-local-graph
"ruo" #'org-roam-ui-open)
(phundrak/major-leader-key
:keymaps 'org-mode-map
:packages '(org org-roam)
"h" #'org-id-get-create
"r" '(:ignore t :which-key "roam")
"ra" '(:ignore t :which-key "alias")
"raa" #'org-roam-alias-add
"rar" #'org-roam-alias-remove))
(use-package org-roam-ui
:straight (:build t)
:defer t
:after org-roam
:config
(setq org-roam-ui-sync-theme t
org-roam-ui-follow t
org-roam-ui-update-on-save t
org-roam-ui-open-on-start t))
Org-ref and Bibtex configuration
(use-package reftex
:commands turn-on-reftex
:init (setq reftex-default-bibliography "~/org/bibliography/references.bib"
reftex-plug-into-AUCTeX t))
(use-package org-ref
;; :after (org ox-bibtex pdf-tools)
:after org
:defer t
:straight (:build t)
:custom-face
(org-ref-cite-face ((t (:weight bold))))
:init
(setq org-ref-completion-library 'org-ref-ivy-cite
org-latex-logfiles-extensions '("lof" "lot" "aux" "idx" "out" "log" "fbd_latexmk"
"toc" "nav" "snm" "vrb" "dvi" "blg" "brf" "bflsb"
"entoc" "ps" "spl" "bbl" "pygtex" "pygstyle"))
(add-hook 'org-mode-hook (lambda () (require 'org-ref)))
:config
(setq bibtex-completion-pdf-field "file"
bibtex-completion-notes-path "~/org/bibliography/notes/"
bibtex-completion-bibliography "~/org/bibliography/references.bib"
bibtex-completion-library-path "~/org/bibliography/bibtex-pdfs/"
bibtex-completion-pdf-symbol "⌘"
bibtex-completion-notes-symbol "✎")
:general
(phundrak/evil
:keymaps 'bibtex-mode-map
:packages 'org-ref
"C-t" #'org-ref-bibtex-next-entry
"C-s" #'org-ref-bibtex-previous-entry
"gt" #'org-ref-bibtex-next-entry
"gs" #'org-ref-bibtex-previous-entry)
(phundrak/major-leader-key
:keymaps '(bibtex-mode-map)
:packages 'org-ref
;; Navigation
"t" #'org-ref-bibtex-next-entry
"s" #'org-ref-bibtex-previous-entry
;; Open
"b" #'org-ref-open-in-browser
"n" #'org-ref-open-bibtex-notes
"p" #'org-ref-open-bibtex-pdf
;; Misc
"h" #'org-ref-bibtex-hydra/body
"i" #'org-ref-bibtex-hydra/org-ref-bibtex-new-entry/body-and-exit
"s" #'org-ref-sort-bibtex-entry
"l" '(:ignore t :which-key "lookup")
"la" #'arxiv-add-bibtex-entry
"lA" #'arxiv-get-pdf-add-bibtex-entry
"ld" #'doi-utils-add-bibtex-entry-from-doi
"li" #'isbn-to-bibtex
"lp" #'pubmed-insert-bibtex-from-pmid)
(phundrak/major-leader-key
:keymaps 'org-mode-map
:pakages 'org-ref
"ic" #'org-ref-insert-link
"iL" #'org-ref-insert-ref-link
"ir" #'org-ref-insert-link-hydra/body
"iB" #'org-ref-bibtex-hydra/body))
(use-package ivy-bibtex
:defer t
:straight (:build t)
:config
(setq bibtex-completion-pdf-open-function #'find-file)
:general
(phundrak/leader-key
:keymaps '(bibtex-mode-map)
:packages 'ivy-bibtex
"m" #'ivy-bibtex))
Org-present
org-present
allows its user to create presentations through org-mode
,
which is really nice! However, most of my configuration will be stolen
from Daviwil’s with minor changes.
(defun my/org-present-prepare-slide ()
(org-overview)
(org-show-entry)
(org-show-children)
(org-present-hide-cursor))
(defun my/org-present-init ()
(setq header-line-format " ")
(org-display-inline-images)
(my/org-present-prepare-slide))
(defun my/org-present-quit ()
(setq header-line-format nil)
(org-present-small)
(org-present-show-cursor))
(defun my/org-present-prev ()
(interactive)
(org-present-prev)
(my/org-present-prepare-slide))
(defun my/org-present-next ()
(interactive)
(org-present-next)
(my/org-present-prepare-slide))
(use-package org-present
:after org
:defer t
:straight (:build t)
:general
(phundrak/major-leader-key
:packages 'org-present
:keymaps 'org-mode-map
"P" #'org-present)
(phundrak/evil
:states 'normal
:packages 'org-present
:keymaps 'org-present-mode-keymap
"+" #'org-present-big
"-" #'org-present-small
"<" #'org-present-beginning
">" #'org-present-end
"«" #'org-present-beginning
"»" #'org-present-end
"c" #'org-present-hide-cursor
"C" #'org-present-show-cursor
"n" #'org-present-next
"p" #'org-present-prev
"r" #'org-present-read-only
"w" #'org-present-read-write
"q" #'org-present-quit)
:hook ((org-present-mode . my/org-present-init)
(org-present-mode-quit . my/org-present-quit)))
Tangle config org files on save
Something really, really useful is tangling all my configuration files on save. For this, a dedicated function will do the trick.
(defun my/tangle-config-file ()
(when (and (eq major-mode 'org-mode)
(f-ancestor-of-p (f-full "~/.nosync/org/config") default-directory))
(org-babel-tangle)))
(add-hook 'after-save-hook #'my/tangle-config-file)
Visual Configuration
While most modes of Emacs are dedicated to development, and therefore
are much more comfortable with a fixed-pitch font, more literary modes
such as org-mode are much more enjoyable if you have a variable pitch
font enabled. BUT, these modes can also require some fixed-pitch fonts
for some elements of the buffer, such as code blocks with
org-mode. mixed-pitch
comes to the rescue!
(use-package mixed-pitch
:after org
:straight (:build t)
:hook
(org-mode . mixed-pitch-mode)
(emms-browser-mode . mixed-pitch-mode)
(emms-playlist-mode . mixed-pitch-mode)
:config
(add-hook 'org-agenda-mode-hook (lambda () (mixed-pitch-mode -1))))
I have an issue with org-mode’s emphasis markers: I find them ugly. I
can of course hide them if I simply set org-hide-emphasis-markers
to
t
, but it makes editing hard since I never know whether I am before or
after the emphasis marker when editing near the beginning/end of an
emphasized region. org-appear
fixes this issue so that it shows the
emphasis markers only when the cursor is in the emphasized region,
otherwise they will remain hidden! Very cool!
(use-package org-appear
:after org
:straight (:build t)
:hook (org-mode . org-appear-mode)
:config
(setq org-appear-autoemphasis t
org-hide-emphasis-markers t
org-appear-autolinks t
org-appear-autoentities t
org-appear-autosubmarkers t)
(run-at-time nil nil #'org-appear--set-elements))
Similarly, LaTeX fragments previews are nice and all, but if I have my cursor on it, I want to see the LaTeX source code and modify it, not just the generated image!
(use-package org-fragtog
:defer t
:after org
:straight (:build t)
:hook (org-mode . org-fragtog-mode))
Org-modern modernizes a bit the appearance of org buffers, including
tables, source blocks, and tags, and it applies settings similar to
org-superstar
which I used to use.
(use-package org-modern
:straight (:build t)
:after org
:defer t
:custom (org-modern-table nil)
:hook (org-mode . org-modern-mode)
:hook (org-agenda-finalize . org-modern-agenda))
org-fancy-priorities
change the priority of an org element such as #A
to anything user-defined. Let’s all-the-iconify this!
(use-package org-fancy-priorities
:after (org all-the-icons)
:straight (:build t)
:hook (org-mode . org-fancy-priorities-mode)
:hook (org-agenda-mode . org-fancy-priorities-mode)
:config
(setq org-fancy-priorities-list `(,(all-the-icons-faicon "flag" :height 1.1 :v-adjust 0.0)
,(all-the-icons-faicon "arrow-up" :height 1.1 :v-adjust 0.0)
,(all-the-icons-faicon "square" :height 1.1 :v-adjust 0.0))))
Org Outline Tree is a better way of managing my org files’ outline.
(use-package org-ol-tree
:after (org avy)
:defer t
:straight (org-ol-tree :build t
:host github
:type git
:repo "Townk/org-ol-tree")
:general
(phundrak/major-leader-key
:packages 'org-ol-tree
:keymaps 'org-mode-map
"O" #'org-ol-tree))
(add-hook 'org-mode-hook
(lambda ()
(dolist (pair '(("[ ]" . ?☐)
("[X]" . ?☑)
("[-]" . ?❍)
("#+title:" . ?📕)
("#+TITLE:" . ?📕)
("#+author:" . ?✎)
("#+AUTHOR:" . ?✎)
("#+email:" . ?📧)
("#+EMAIL:" . ?📧)
("#+include" . ?⭳)
("#+INCLUDE" . ?⭳)
("#+begin_src" . ?λ)
("#+BEGIN_SRC" . ?λ)
("#+end_src" . ?λ)
("#+END_SRC" . ?λ)))
(add-to-list 'prettify-symbols-alist pair))
(prettify-symbols-mode)))
Misc
org-tree-slide
is a presentation tool for org-mode.
(use-package org-tree-slide
:defer t
:after org
:straight (:build t)
:config
(setq org-tree-slide-skip-done nil)
:general
(phundrak/evil
:keymaps 'org-mode-map
:packages 'org-tree-slide
"<f8>" #'org-tree-slide-mode)
(phundrak/major-leader-key
:keymaps 'org-tree-slide-mode-map
:packages 'org-tree-slide
"d" (lambda () (interactive (setq org-tree-slide-skip-done (not org-tree-slide-skip-done))))
"p" #'org-tree-slide-move-next-tree
"n" #'org-tree-slide-move-previous-tree
"t" #'org-tree-slide-move-next-tree
"s" #'org-tree-slide-move-previous-tree
"u" #'org-tree-slide-content))
org-roll
is a simple package for tabletop RPGs for rolling dice.
(use-package org-roll
:defer t
:after org
:straight (:build t :type git :host github :repo "zaeph/org-roll"))