1400 lines
53 KiB
Org Mode
1400 lines
53 KiB
Org Mode
|
#+title: Emacs — Packages — Org Mode
|
|||
|
#+setupfile: ../../headers
|
|||
|
#+property: header-args:emacs-lisp :mkdirp yes :lexical t :exports code
|
|||
|
#+property: header-args:emacs-lisp+ :tangle ~/.config/emacs/lisp/org.el
|
|||
|
#+property: header-args:emacs-lisp+ :mkdirp yes :noweb no-export
|
|||
|
|
|||
|
* Org-mode
|
|||
|
#+name: general-keybindings-gen
|
|||
|
#+header: :tangle no :exports none :results value :cache yes
|
|||
|
#+begin_src emacs-lisp :var table=org-keybinds-babel prefix=""
|
|||
|
(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")
|
|||
|
#+end_src
|
|||
|
|
|||
|
Since recently, in order to make ~org-cite~ compile properly, we need
|
|||
|
the ~citeproc~ package, a citation processor.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package citeproc
|
|||
|
:after (org)
|
|||
|
:defer t
|
|||
|
:straight (:build t))
|
|||
|
#+end_src
|
|||
|
|
|||
|
Org is the main reason I am using Emacs. It is an extremely powerfu
|
|||
|
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!
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
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.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
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…
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package conlanging
|
|||
|
:straight (conlanging :build t
|
|||
|
:type git
|
|||
|
:repo "https://labs.phundrak.com/phundrak/conlanging.el")
|
|||
|
:after org
|
|||
|
:defer t)
|
|||
|
#+end_src
|
|||
|
|
|||
|
Since very recently, the ~contrib/lisp/~ directory of org moved out of
|
|||
|
the main repository to [[https://git.sr.ht/~bzg/org-contrib][this repository]]. On the other hand,
|
|||
|
~contrib/scripts/~ moved to [[https://code.orgmode.org/bzg/worg/src/master/code][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.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package org-contrib
|
|||
|
:after (org)
|
|||
|
:defer t
|
|||
|
:straight (:build t)
|
|||
|
:init
|
|||
|
(require 'ox-extra)
|
|||
|
(ox-extras-activate '(latex-header-blocks ignore-headlines)))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** Agenda
|
|||
|
#+name: org-agenda-files
|
|||
|
#+begin_src emacs-lisp :tangle no
|
|||
|
(setq org-agenda-files (list "~/org/agenda" "~/org/notes.org"))
|
|||
|
#+end_src
|
|||
|
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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"))))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** 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:
|
|||
|
#+NAME: org-babel-languages-table
|
|||
|
| C |
|
|||
|
| emacs-lisp |
|
|||
|
| gnuplot |
|
|||
|
| latex |
|
|||
|
| makefile |
|
|||
|
| plantuml |
|
|||
|
| python |
|
|||
|
| sass |
|
|||
|
| shell |
|
|||
|
| sql |
|
|||
|
|
|||
|
#+NAME: org-babel-languages-gen
|
|||
|
#+header: :cache yes :results replace
|
|||
|
#+header: :var languages=org-babel-languages-table[,0]
|
|||
|
#+BEGIN_SRC emacs-lisp :exports none :tangle no
|
|||
|
(format "'(%s)"
|
|||
|
(mapconcat (lambda ($language)
|
|||
|
(format "(%s . t)" $language))
|
|||
|
languages
|
|||
|
"\n "))
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
#+RESULTS[b0a5bea13e6ba99525ad166ea5538e74ba4c6ddc]: org-babel-languages-gen
|
|||
|
#+begin_example
|
|||
|
'((C . t)
|
|||
|
(emacs-lisp . t)
|
|||
|
(gnuplot . t)
|
|||
|
(latex . t)
|
|||
|
(makefile . t)
|
|||
|
(plantuml . t)
|
|||
|
(python . t)
|
|||
|
(sass . t)
|
|||
|
(shell . t)
|
|||
|
(sql . t))
|
|||
|
#+end_example
|
|||
|
|
|||
|
The corresponding code is as follows:
|
|||
|
#+NAME: org-babel-load-languages
|
|||
|
#+BEGIN_SRC emacs-lisp :noweb yes :tangle no
|
|||
|
(org-babel-do-load-languages
|
|||
|
'org-babel-load-languages
|
|||
|
<<org-babel-languages-gen()>>)
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
Some languages can run asynchronously with the help of ~ob-async~.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package ob-async
|
|||
|
:straight (:build t)
|
|||
|
:defer t
|
|||
|
:after (org ob))
|
|||
|
#+end_src
|
|||
|
|
|||
|
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:
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package ob-latex-as-png
|
|||
|
:after org
|
|||
|
:straight (:build t))
|
|||
|
#+end_src
|
|||
|
|
|||
|
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!
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package ob-restclient
|
|||
|
:straight (:build t)
|
|||
|
:defer t
|
|||
|
:after (org ob)
|
|||
|
:init
|
|||
|
(add-to-list 'org-babel-load-languages '(restclient . t)))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** 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.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
~electric-mode~ also bothers me a lot when editing org files, so let’s deactivate it:
|
|||
|
#+name: org-behavior-electric
|
|||
|
#+begin_src emacs-lisp :tangle no
|
|||
|
(add-hook 'org-mode-hook (lambda ()
|
|||
|
(interactive)
|
|||
|
(electric-indent-local-mode -1)))
|
|||
|
#+end_src
|
|||
|
|
|||
|
As explained in my [[https://blog.phundrak.com/better-custom-ids-orgmode/][blog post]], org-mode is terrible with coming up with
|
|||
|
meaningful IDs for its headings. I actually wrote a package for this!
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** 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.
|
|||
|
#+name: org-capture-target-files
|
|||
|
#+begin_src emacs-lisp :tangle no
|
|||
|
(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")
|
|||
|
#+end_src
|
|||
|
|
|||
|
Let me describe a keybind to invoke org-capture from anywhere within
|
|||
|
Emacs.
|
|||
|
#+name: org-capture-keybinds
|
|||
|
#+begin_src emacs-lisp :tangle no
|
|||
|
(phundrak/leader-key
|
|||
|
:packages 'org
|
|||
|
:infix "o"
|
|||
|
"" '(:ignore t :which-key "org")
|
|||
|
"c" #'org-capture)
|
|||
|
#+end_src
|
|||
|
|
|||
|
When ~org-capture~ is invoked, it will ask which template we wish to
|
|||
|
use. In the table [[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/.
|
|||
|
#+name: org-capture-shortcuts-table
|
|||
|
| Shortcut | Name | Title | Insertion mode | file | template |
|
|||
|
|----------+---------------+-----------+----------------+-------------------------+--------------------------|
|
|||
|
| e | Email | | | | |
|
|||
|
| 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 [[https://labs.phundrak.com/phundrak/dotfiles/src/branch/master/org/capture][in my dotfiles’ repository]].
|
|||
|
|
|||
|
#+name: org-capture-shortcuts-gen
|
|||
|
#+header: :exports none :cache yes :tangle no
|
|||
|
#+begin_src emacs-lisp :var entries=org-capture-shortcuts-table
|
|||
|
(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")
|
|||
|
#+end_src
|
|||
|
|
|||
|
#+RESULTS[9f565c3dd73becfad0a99c0cfaf4521762334b40]: org-capture-shortcuts-gen
|
|||
|
#+begin_example
|
|||
|
("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"))
|
|||
|
#+end_example
|
|||
|
|
|||
|
The capture templates are set like so:
|
|||
|
#+name: org-capture-templates
|
|||
|
#+begin_src emacs-lisp :tangle no :results silent
|
|||
|
(setq org-capture-templates
|
|||
|
'(
|
|||
|
<<org-capture-shortcuts-gen()>>))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** 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 begining 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 [[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.
|
|||
|
|
|||
|
#+name: org-emphasis-character
|
|||
|
| Emphasis | Character | Character code |
|
|||
|
|----------------+-----------+----------------|
|
|||
|
| bold | ~*~ | 42 |
|
|||
|
| italic | ~/~ | 47 |
|
|||
|
| underline | ~_~ | 95 |
|
|||
|
| verbatim | ~=~ | 61 |
|
|||
|
| code | ~~~ | 126 |
|
|||
|
| strike-through | ~+~ | 43 |
|
|||
|
|
|||
|
#+name: org-create-emphasis-functions
|
|||
|
#+header: :tangle no :exports results :cache yes
|
|||
|
#+header: :wrap "src emacs-lisp :tangle no :exports code"
|
|||
|
#+begin_src emacs-lisp :var emphasis-list=org-emphasis-character
|
|||
|
(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")
|
|||
|
#+end_src
|
|||
|
|
|||
|
#+RESULTS[dbd10cce4ae05a046838214784f0f4c16765e728]: org-create-emphasis-functions
|
|||
|
#+begin_src emacs-lisp :tangle no :exports code
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
You can find the keybinds for these functions [[file:./org#keybindings][here]].
|
|||
|
|
|||
|
*** ~phundrak/toggle-org-src-window-split~
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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")))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** Exporters
|
|||
|
I want to disable by default behavior 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:
|
|||
|
#+NAME: org-use-sub-superscripts
|
|||
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|||
|
(setq org-use-sub-superscripts (quote {}))
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
*** Epub
|
|||
|
A backend for exporting files through org I like is ~ox-epub~ which, as
|
|||
|
you can guess, exports org files to the [[https://www.w3.org/publishing/epub32/][Epub format]].
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package ox-epub
|
|||
|
:after (org ox)
|
|||
|
:straight (:build t))
|
|||
|
#+end_src
|
|||
|
|
|||
|
*** 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.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package ox-gemini
|
|||
|
:defer t
|
|||
|
:straight (ox-gemini :build t
|
|||
|
:fork (:repo "https://labs.phundrak.com/phundrak/ox-gemini"))
|
|||
|
:after (ox org))
|
|||
|
#+end_src
|
|||
|
|
|||
|
*** 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.
|
|||
|
#+NAME: org-html-validation
|
|||
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|||
|
(setq org-html-validation-link nil)
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
#+begin_src emacs-lisp
|
|||
|
;; (use-package htmlize
|
|||
|
;; :defer t
|
|||
|
;; :straight (:build t))
|
|||
|
#+end_src
|
|||
|
|
|||
|
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.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
*** Hugo
|
|||
|
I manage [[https://blog.phundrak.com][my blog]] with [[https://gohugo.io/][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!
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package ox-hugo
|
|||
|
:defer t
|
|||
|
:after ox
|
|||
|
:straight t)
|
|||
|
#+end_src
|
|||
|
|
|||
|
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.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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)))))
|
|||
|
#+end_src
|
|||
|
|
|||
|
*** 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.
|
|||
|
#+NAME: org-latex-compiler
|
|||
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|||
|
(setq org-latex-compiler "xelatex"
|
|||
|
org-latex-prefer-user-labels t)
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
A new backend that was introduced in org-mode for LaTeX source block
|
|||
|
coloring is ~engraved~.
|
|||
|
#+BEGIN_SRC emacs-lisp
|
|||
|
(use-package engrave-faces
|
|||
|
:straight (:build t))
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
#+name: org-latex-src-block-backend
|
|||
|
#+begin_src emacs-lisp :tangle no
|
|||
|
(require 'engrave-faces)
|
|||
|
(setq org-latex-src-block-backend 'engraved)
|
|||
|
#+end_src
|
|||
|
|
|||
|
The default packages break my LaTeX exports: for some reasons, images
|
|||
|
are not loaded and exported in PDFs, so I needed to redifine 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 outputs
|
|||
|
- ~booktabs~ for nicer tables
|
|||
|
- and ~tabularx~ for tabulars with adjustable columns
|
|||
|
#+NAME: org-latex-default-packages
|
|||
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|||
|
(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}")
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
By the way, reference links in LaTeX should be written in this format,
|
|||
|
since we are using ~cleveref~:
|
|||
|
#+NAME: org-export-latex-hyperref-format
|
|||
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|||
|
(setq org-export-latex-hyperref-format "\\ref{%s}")
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
[[https://tectonic-typesetting.github.io/en-US/][Tectonic]] is awesome for processing LaTeX documents! Look how simple it
|
|||
|
is!
|
|||
|
#+NAME: org-latex-pdf-process
|
|||
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|||
|
(setq org-latex-pdf-process
|
|||
|
'("tectonic -Z shell-escape --synctex --outdir=%o %f"))
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
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:
|
|||
|
#+name: org-latex-logfiles-add-extensions
|
|||
|
#+begin_src emacs-lisp :tangle no
|
|||
|
(dolist (ext '("bbl" "lot"))
|
|||
|
(add-to-list 'org-latex-logfiles-extensions ext t))
|
|||
|
#+end_src
|
|||
|
|
|||
|
*** Reveal.js
|
|||
|
#+NAME: org-re-reveal
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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"))
|
|||
|
#+end_src
|
|||
|
|
|||
|
*** SSH Config
|
|||
|
Yet another exporter I enjoy is [[https://github.com/dantecatalfamo/ox-ssh][~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.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package ox-ssh
|
|||
|
:after (ox org)
|
|||
|
:straight (:build t))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** Keybindings
|
|||
|
Be prepared, I have a lot of keybindings for org-mode! They are all
|
|||
|
prefixed with a comma ~,~ in normal mode.
|
|||
|
#+name: org-keybinds-various
|
|||
|
| 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.
|
|||
|
#+name: org-keybinds-babel
|
|||
|
| 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.
|
|||
|
#+name: org-hydra-babel
|
|||
|
#+begin_src emacs-lisp :tangle no
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
We next have keybindings related to org-mode’s agenda capabilities. We
|
|||
|
can schedule a todo header for some dates, or set a deadline.
|
|||
|
#+name: org-keybinds-dates
|
|||
|
| 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:
|
|||
|
#+name: org-keybinds-insert
|
|||
|
| 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:
|
|||
|
#+name: org-keybinds-jump
|
|||
|
| Key chord | Function | Description |
|
|||
|
|-----------+----------------------+-------------|
|
|||
|
| j | nil | jump |
|
|||
|
| ja | counsel-org-goto-all | |
|
|||
|
| jh | counsel-org-goto | |
|
|||
|
|
|||
|
Tables get a bit more love:
|
|||
|
#+name: org-keybinds-tables
|
|||
|
| 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:
|
|||
|
#+name: org-keybinds-toggles
|
|||
|
| 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
|
|||
|
:PROPERTIES:
|
|||
|
:header-args:emacs-lisp: :tangle no :exports code :results silent
|
|||
|
:END:
|
|||
|
I currently have two custom formats for my Org-mode exports: one for general use
|
|||
|
(initialy for my conlanging files, hence its ~conlang~ name), and one for beamer
|
|||
|
exports.
|
|||
|
|
|||
|
Below is the declaration of the ~conlang~ LaTeX class:
|
|||
|
#+NAME: org-latex-class-conlang
|
|||
|
#+BEGIN_SRC emacs-lisp
|
|||
|
'("conlang"
|
|||
|
"\\documentclass{book}"
|
|||
|
("\\chapter{%s}" . "\\chapter*{%s}")
|
|||
|
("\\section{%s}" . "\\section*{%s}")
|
|||
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|||
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
And here is the declaration of the ~beamer~ class:
|
|||
|
#+NAME: org-latex-class-beamer
|
|||
|
#+BEGIN_SRC emacs-lisp
|
|||
|
`("beamer"
|
|||
|
,(concat "\\documentclass[presentation]{beamer}\n"
|
|||
|
"[DEFAULT-PACKAGES]"
|
|||
|
"[PACKAGES]"
|
|||
|
"[EXTRA]\n")
|
|||
|
("\\section{%s}" . "\\section*{%s}")
|
|||
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|||
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
Both these classes have to be added to ~org-latex-classes~ like so:
|
|||
|
#+NAME: org-latex-classes
|
|||
|
#+BEGIN_SRC emacs-lisp :noweb yes
|
|||
|
(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>>)))
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
** Projects
|
|||
|
:PROPERTIES:
|
|||
|
:header-args:emacs-lisp: :tangle no :exports code :results silent
|
|||
|
:END:
|
|||
|
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:
|
|||
|
#+NAME: org-publish-projects
|
|||
|
#+BEGIN_SRC emacs-lisp :noweb yes :noweb-prefix no
|
|||
|
<<org-proj-config-setup>>
|
|||
|
(setq org-publish-project-alist
|
|||
|
`(<<org-proj-config-html>>
|
|||
|
<<org-proj-config-static>>
|
|||
|
<<org-proj-config>>))
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
*** 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.
|
|||
|
#+NAME: org-proj-config-setup
|
|||
|
#+BEGIN_SRC emacs-lisp
|
|||
|
(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.")
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
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.
|
|||
|
#+NAME: org-proj-config-html
|
|||
|
#+BEGIN_SRC emacs-lisp
|
|||
|
("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)
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
We also have the component for all the static files needed to run the website
|
|||
|
(mostly images tbh).
|
|||
|
#+NAME: org-proj-config-static
|
|||
|
#+BEGIN_SRC emacs-lisp
|
|||
|
("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)
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
The project is then defined like so:
|
|||
|
#+NAME: org-proj-config
|
|||
|
#+BEGIN_SRC emacs-lisp
|
|||
|
("config-website"
|
|||
|
:components ("config-website-org"
|
|||
|
"config-website-static"))
|
|||
|
#+END_SRC
|
|||
|
|
|||
|
** 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.
|
|||
|
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** Org-ref and Bibtex configuration
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package reftex
|
|||
|
:commands turn-on-reftex
|
|||
|
:init (setq reftex-default-bibliography "~/org/bibliography/references.bib"
|
|||
|
reftex-plug-into-AUCTeX t))
|
|||
|
#+end_src
|
|||
|
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** 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
|
|||
|
[[https://config.daviwil.com/emacs#org-present][from Daviwil’s]] with minor changes.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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)))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** 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!
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))))
|
|||
|
#+end_src
|
|||
|
|
|||
|
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!
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
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!
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package org-fragtog
|
|||
|
:defer t
|
|||
|
:after org
|
|||
|
:straight (:build t)
|
|||
|
:hook (org-mode . org-fragtog-mode))
|
|||
|
#+end_src
|
|||
|
|
|||
|
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.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package org-modern
|
|||
|
:straight (:build t)
|
|||
|
:after org
|
|||
|
:defer t
|
|||
|
:hook (org-mode . org-modern-mode)
|
|||
|
:hook (org-agenda-finalize . org-modern-agenda))
|
|||
|
#+end_src
|
|||
|
|
|||
|
~org-fancy-priorities~ change the priority of an org element such as ~#A~
|
|||
|
to anything user-defined. Let’s all-the-iconify this!
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))))
|
|||
|
#+end_src
|
|||
|
|
|||
|
/Org Outline Tree/ is a better way of managing my org files’ outline.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
#+name: org-mode-visual-prettify-symbols
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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)))
|
|||
|
#+end_src
|
|||
|
|
|||
|
** Misc
|
|||
|
~org-tree-slide~ is a presentation tool for org-mode.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(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))
|
|||
|
#+end_src
|
|||
|
|
|||
|
~org-roll~ is a simple package for tabletop RPGs for rolling dice.
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package org-roll
|
|||
|
:defer t
|
|||
|
:after org
|
|||
|
:straight (:build t :type git :host github :repo "zaeph/org-roll"))
|
|||
|
#+end_src
|