Org-Mode
Org-mode might the emacs killer app. This file holds some extra settings which
were not set in the use-package
statement in init.el
.
TODO General settings
Some general settings for org. Clean up the use-package definition
(use-package org :init ; loaded before package is initialized ;; The background color of my org source code blocks needs to be defined before ;; org is loaded. (defface org-block-begin-line '((t (:foreground "#99968b" :background "#303030" :box (:style released-button) :extend t))) "Face used for the line delimiting the begin of source blocks.") (defface org-block-end-line '((t (:foreground "#99968b" :background "#303030" :box (:style released-button) :extend t))) "Face used for the line delimiting the end of source blocks.") :config (require 'org-tempo) (setq-default org-return-follows-link t org-image-actual-width '(800) org-highlight-latex-and-related '(latex script entities)) (add-hook 'org-mode-hook #'org-indent-mode) (add-hook 'org-mode-hook #'visual-line-mode) (add-hook 'org-mode-hook #'flyspell-mode) (set-face-attribute 'org-drawer nil :inherit 'font-lock-keyword-face) ;; change some keys to be a little more like LaTeX (defun do.org/insert-math () (interactive) (insert "\\(\\)") (backward-char 2)) (defun do.org/insert-today-inactive () "Insert today's date as inactive time stamp." (interactive) (org-insert-time-stamp (org-current-time) nil t)) (defun do.org/time-stamp-inactive () "Insert an inactive timestamp of the user's choosing." (interactive) (org-time-stamp nil t)) (defalias 'ts #'do.org/time-stamp-inactive) ;; non-breaking spaces <<do.org/non-breaking-spaces>> ;; fix `electric-pair-mode' <<do.org/fix-electric-pair>> :bind (("C-c l" . #'org-store-link) ("C-c t" . #'do.org/insert-today-inactive) :map org-mode-map ("$" . do.org/insert-math) ("~" . do.org/insert-nbsp))) (use-package org-contrib :ensure t)
fixing `electric-pair-mode'
(defun do.org/fix-electric-pair-fn () (setq-local electric-pair-inhibit-predicate `(lambda (c) (if (char-equal c ?<) t (,electric-pair-inhibit-predicate c))))) (add-hook 'org-mode-hook #'do.org/fix-electric-pair-fn)
Syntax highlighting in Code Blocks
Very important if your config file is a .org document… Also, add native
<tab>
behavior in source blocks.
(setq
org-src-fontify-natively t
org-src-tab-acts-natively t)
We also want this in LaTeX output!
(setq org-latex-listings 'minted)
Blogging
Define a small template for new blog posts. Use with <b TAB
this does not work anymore in org > 9.2…
(add-to-list 'org-structure-template-alist '("b" "#+TITLE: ? #+AUTHOR: Dennis Ogbe #+EMAIL: [email protected] #+DATE: #+STARTUP: showall #+STARTUP: inlineimages #+BEGIN_PREVIEW\n\n#+END_PREVIEW\n"))
HTML Export
For HTML output, we want to be able to set a custom stylesheet.
(setq org-html-htmlize-output-type 'css)
We need the htmlize
package for that
(use-package htmlize :ensure t :commands (htmlize-buffer htmlize-file htmlize-many-files htmlize-many-files-dired htmlize-region))
The following code reads some CSS and adds it as a string to the HTML header
that will be embedded in every .org
file that is exported.
When exporting an org-file to my blog, this variable will be overridden and
instead I will point to the relevant .css
files. For "standalone" HTML files,
I want to embed the CSS into the HTML header. The snippet below essentially
just sets the variable org-html-head
.
(defvar do.org.css/css-header-dir "~/repos/blog/res" "Directory containing the org css header files for HTML export.") (defvar do.org.css/css-header-files '("code.css" "main.css") "Filenames of CSS files in `do.org.css/css-header-dir' to be included in the HTML export header.") (let* ((css-dir (let* ((fullpath (file-name-as-directory (expand-file-name do.org.css/css-header-dir)))) (if (file-exists-p fullpath) fullpath nil))) (css-files do.org.css/css-header-files) (csstidy "csstidy") (csstidy-args " --template=highest --silent=true")) (if (and css-dir (executable-find csstidy)) (setq org-html-head (with-temp-buffer (insert "<style type=\"text/css\">\n") (dolist (file css-files) (let* ((fullpath (concat css-dir file))) (when (file-exists-p fullpath) (insert (shell-command-to-string (concat csstidy " " fullpath csstidy-args)))))) (insert "</style>") (buffer-string))) (message "Org config: Not setting `org-html-head'.")))
org-latex settings
For some reason, explained here, we need to run pdflatex with the
-shell-escape
flag. This is getting too complicated, so we're just going to
run latexmk from org.
(setq org-latex-pdf-process (list "latexmk -pdflatex='pdflatex -interaction nonstopmode' -shell-escape -pdf -bibtex -f %f")) (setq org-latex-with-hyperref "\\hypersetup{ colorlinks=true, citecolor=red, filecolor=blue, linkcolor=red, urlcolor=blue, pdfauthor={%a}, pdftitle={%t}, pdfkeywords={%k}, pdfsubject={%d}, pdfcreator={%c}, pdflang={%L}}\n") (setq org-latex-prefer-user-labels t)
If we want to export to a documentclass other than article
, we need to add
its structure to the following list. To use that class, we can then put the
following in the org-mode file header: #+LATEX_CLASS: <class>
. To add options
to the class, we add the following: #+LATEX_CLASS_OPTIONS: [op1, op2,...]
.
(require 'ox-latex) (add-to-list 'org-latex-classes '("IEEEtran" "\\documentclass{IEEEtran}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}")))
We add some templates for some common math environments
(add-to-list 'org-structure-template-alist '("prop" "#+begin_proposition ?\n\n#+end_proposition")) (add-to-list 'org-structure-template-alist '("thm" "#+begin_theorem ?\n\n#+end_theorem")) (add-to-list 'org-structure-template-alist '("lem" "#+begin_lemma ?\n\n#+end_lemma")) (add-to-list 'org-structure-template-alist '("pf" "#+begin_proof ?\n\n#+end_proof"))
Non-breaking spaces
Entering "~" in org-mode buffers enters a literal tilde character and not the non-breaking space that I usually want. To get around this, we can insert "non-breaking-space" org entity. Unfortunately, having \nbsp{}
littered around org-mode buffers is super ugly, so we use prettify-symbols-mode
to correct this eyesore.
This is straightforward, but the default behavior of prettify-symbols-mode
does not match occurrences like as\nbsp{}cite:citation
, where the space is butting up to other strings on both sides. So we have to fix that too.
(defun do.org/prettify-symbols-compose-predicate (start end _match) "Explicitly allow any occurrence of the non-breaking space to be composed." (let ((result (prettify-symbols-default-compose-p start end _match))) (or result (string-equal (buffer-substring start end) "\\nbsp{}")))) (defun do.org/prettify-symbols-setup () "Set up `prettify-symbols-mode' for `org-mode' buffers." (make-variable-buffer-local 'prettify-symbols-unprettify-at-point) (setq prettify-symbols-unprettify-at-point 'right-edge) (setq prettify-symbols-compose-predicate #'do.org/prettify-symbols-compose-predicate) (setq prettify-symbols-alist `(("\\nbsp{}" . ,(string-to-char "~")))) (prettify-symbols-mode 1)) (add-hook 'org-mode-hook #'do.org/prettify-symbols-setup) (defun do.org/insert-nbsp () "Bind this to the ~ (tilde) character to insert non-breaking spaces on `org-mode' for LaTeX export." (interactive) (insert "\\nbsp{}"))
Default Applications
Org opens PDFs by default in gv… change that to evince. Also open HTML in Chrome.
(let ((pdf-reader (if (boundp 'do.minimal/pdf-reader) do.minimal/pdf-reader "evince"))) (setq org-file-apps `((auto-mode . emacs) ("\\.x?html?\\'" . "firefox %s") ("\\.pdf\\'" . ,(concat pdf-reader " \"%s\"")) ("\\.pdf::\\([0-9]+\\)\\'" . ,(concat pdf-reader " \"%s\" -p %1")) ("\\.pdf.xoj" . "xournal %s"))))
org-babel
Babel lets the user run code inside an org-mode document. I feel like this can come in handy one day.
Active Babel languages
(org-babel-do-load-languages 'org-babel-load-languages '((python . t) (emacs-lisp . t) (matlab . t) (octave . t) (latex . t) (js . t) (shell . t) (C . t) (ditaa . t)))
org-babel settings
(setq org-babel-matlab-with-emacs-link nil) (setq org-confirm-babel-evaluate nil) (setq org-export-babel-evaluate t) ;;; display/update images in the buffer after I evaluate (add-hook 'org-babel-after-execute-hook 'org-display-inline-images 'append)
ditaa
Ditaa is a small tool that takes ASCII art and renders it as neat diagrams. Combined with org, I can sketch out ideas directly in an org buffer using the emacs Artist mode.
(setq org-ditaa-jar-path (concat initel-directory "random/ditaa/ditaa0_9.jar"))
Windmove and org-mode clashes
Make windmove (and framemove) play nice with org.
(add-hook 'org-shiftup-final-hook 'windmove-up) (add-hook 'org-shiftleft-final-hook 'windmove-left) (add-hook 'org-shiftdown-final-hook 'windmove-down) (add-hook 'org-shiftright-final-hook 'windmove-right)
YaSnippet and org
backtab
is already used in org-mode. Let's use C-<tab>
instead.
(define-key org-mode-map (kbd "C-<tab>") 'yas-expand)
org-download
(use-package org-download :ensure t :init (setq org-download-screenshot-method "xclip -selection clipboard -t image/png -o > %s") (setq org-download-method 'directory) (defalias 'insert-screenshot 'org-download-screenshot) :config (add-hook 'dired-mode-hook 'org-download-enable))
Execute a code block on startup
Sometimes I want to execute a code block in an org file as soon as it is started. This can be done as follows. We first need the following function.
(defun do.org/execute-startup-block () "Go to the startup block and execute it. It must be named 'do-org-startup-code'." (interactive) ;; only run this once. some modes (looking at you, org-ref) run ;; `hack-local-variables' again. we want our code to be executed only once on ;; buffer creation. (unless (bound-and-true-p do.org/startup-was-run-p) (org-babel-goto-named-src-block "do-org-startup-code") (let ((org-babel-after-execute-hook nil)) (org-babel-execute-src-block)) (org-global-cycle) (setq-local do.org/startup-was-run-p t)))
We can identify the code block to execute on startup by giving it the name do-org-startup-code, i.e., we add a #+NAME: do-org-startup-code
in the line before #+begin_src
.
Then to execute, we need to set the :eval
local variable to call our function, which visits the block and runs it. This might look like this:
FILENAME -*- mode: org; eval: (do.org/execute-startup-block) -*-
or the corresponding multiline comment form at the end of a file.