emacs-config/config.org

2205 lines
86 KiB
Org Mode
Raw Normal View History

#+TITLE: Doom Emacs Configuration
#+AUTHOR: tecosaur
#+PROPERTY: header-args:emacs-lisp :tangle yes :cache yes :results silent :comments link
#+HTML_HEAD: <link rel='shortcut icon' type='image/png' href='https://www.gnu.org/software/emacs/favicon.png'>
#+BEGIN_QUOTE
Let us change our traditional attitude to the construction of programs:
Instead of imagining that our main task is to instruct a computer what to do,
let us concentrate rather on explaining to human beings what we want a
computer to do. --- Donald Knuth
#+END_QUOTE
2020-01-20 18:08:07 +00:00
* Intro
Customising an editor can be very rewarding ... until you have to leave it.
For years I have been looking for ways to avoid this pain.
2020-02-03 18:16:07 +00:00
Then I discovered [[https://github.com/cknadler/vim-anywhere][vim-anywhere]], and found that it had an emacs companion,[[https://github.com/zachcurry/emacs-anywhere][
2020-01-20 18:08:07 +00:00
emacs-anywhere]]. To me, this looked most attractive.
Separately, online I have seen the following statement enough times I think it's a catchphrase
#+BEGIN_QUOTE
Redditor1: I just discovered this thing, isn't it cool.
Redditor2: Oh, there's an emacs mode for that.
#+END_QUOTE
I tried out the =spacemacs= distribution a bit, but it wasn't quite to my liking.
Then I heard about =doom emacs= and thought I may as well give that a try.
TLDR; it's great.
Now I've discovered the wonders of literate programming, and am becoming more
settled by the day. This is my config.
* Rudimentary configuration
2020-02-03 05:28:15 +00:00
Make this file run (slightly) faster with lexical binding (see [[https://nullprogram.com/blog/2016/12/22/][this blog post]]
for more info).
#+BEGIN_SRC emacs-lisp
;;; config.el -*- lexical-binding: t; -*-
#+END_SRC
** Personal Information
It's useful to have some basic personal information
#+BEGIN_SRC emacs-lisp
(setq user-full-name "tecosaur"
user-mail-address "tecosaur@gmail.com")
#+END_SRC
Apparently this is used by ~GPG~, and all sorts of other things.
** Better defaults
*** Simple settings
Browsing the web and seeing [[https://github.com/angrybacon/dotemacs/blob/master/dotemacs.org#use-better-defaults][angrybacon/dotemacs]] and comparing with the values
shown by =SPC h v= and selecting what I thought looks good, I've ended up adding the following:
#+BEGIN_SRC emacs-lisp
(setq-default
delete-by-moving-to-trash t ; Delete files to trash
tab-width 4 ; Set width for tabs
uniquify-buffer-name-style 'forward ; Uniquify buffer names
window-combination-resize t ; take new window space from all other windows (not just current)
x-stretch-cursor t) ; Stretch cursor to the glyph width
2020-02-02 18:21:19 +00:00
(setq undo-limit 80000000 ; Raise undo-limit to 80Mb
2020-03-04 15:27:08 +00:00
evil-want-fine-undo t ; By default while in insert all changes are one big blob. Be more granular
auto-save-default t ; Nobody likes to loose work, I certainly don't
inhibit-compacting-font-caches t) ; When there are lots of glyphs, keep them in memory
(delete-selection-mode 1) ; Replace selection when inserting text
(display-time-mode 1) ; Enable time in the mode-line
2020-01-09 18:04:48 +00:00
(display-battery-mode 1) ; On laptops it's nice to know how much power you have
(global-subword-mode 1) ; Iterate through CamelCase words
#+END_SRC
*** Fullscreen
I also like the idea of fullscreen-ing when opened by ~emacs~ or the ~.desktop~ file.
#+BEGIN_SRC emacs-lisp
(if (eq initial-window-system 'x) ; if started by emacs command or desktop file
(toggle-frame-maximized)
(toggle-frame-fullscreen))
#+END_SRC
*** Auto-customisations
By default changes made via a customisation interface are added to =init.el=.
I prefer the idea of using a separate file for this. We just need to change a
setting, and load it if it exists.
#+BEGIN_SRC emacs-lisp
2020-02-26 12:50:01 +00:00
(setq-default custom-file (expand-file-name ".custom.el" doom-private-dir))
(when (file-exists-p custom-file)
(load custom-file))
#+END_SRC
*** Windows
I find it rather handy to be asked which buffer I want to see after splitting
the window. Let's make that happen.
First, we'll enter the new window
#+BEGIN_SRC emacs-lisp
(setq evil-vsplit-window-right t
evil-split-window-below t)
#+END_SRC
Then, we'll pull up ~ivy~
#+BEGIN_SRC emacs-lisp
(defadvice! prompt-for-buffer (&rest _)
:after '(evil-window-split evil-window-vsplit)
2020-02-09 15:16:25 +00:00
(+ivy/switch-buffer))
#+END_SRC
2020-01-29 12:46:48 +00:00
*** Buffer defaults
I'd much rather have my new buffers in ~org-mode~ than ~fundamental-mode~, hence
#+BEGIN_SRC emacs-lisp
;; (setq-default major-mode 'org-mode)
2020-01-29 12:46:48 +00:00
#+END_SRC
For some reason this + the mixed pitch hook causes issues with hydra and so I'll
just need to resort to =SPC b o= for now.
** Doom configuration
*** Visual Settings
**** Font Face
'Fira Code' is nice, and 'Overpass' makes for a nice sans companion. We just need to
fiddle with the font sizes a tad so that they visually match.
#+BEGIN_SRC emacs-lisp
2020-01-29 12:37:14 +00:00
(setq doom-font (font-spec :family "Fira Code" :size 22)
2020-01-09 17:52:29 +00:00
doom-big-font (font-spec :family "Fira Code" :size 36)
2020-01-29 12:37:14 +00:00
doom-variable-pitch-font (font-spec :family "Overpass" :size 24))
#+END_SRC
**** Theme
~doom-one~ is nice and all, but I find the ~vibrant~ variant nicer.
#+BEGIN_SRC emacs-lisp
(setq doom-theme 'doom-vibrant)
#+END_SRC
However, by default ~red~ text is used in the ~modeline~, so let's make that orange
so I don't feel like something's gone /wrong/ when editing files.
#+BEGIN_SRC emacs-lisp
(custom-set-faces!
'(doom-modeline-buffer-modified :foreground "orange"))
#+END_SRC
**** Miscellaneous
Relative line numbers are fantastic for knowing how far away line numbers are,
then =ESC 12 <UP>= gets you exactly where you think.
#+BEGIN_SRC emacs-lisp
(setq display-line-numbers-type 'relative)
#+END_SRC
2020-02-06 17:11:35 +00:00
I'd like some slightly nicer default buffer names
#+BEGIN_SRC emacs-lisp
(setq doom-fallback-buffer-name "► Doom"
+doom-dashboard-name "► Doom")
#+END_SRC
There's a bug with the modeline in insert mode for org documents ([[https://github.com/seagle0128/doom-modeline/issues/300][issue]]), so
2020-02-09 00:12:19 +00:00
#+BEGIN_SRC emacs-lisp
(custom-set-faces! '(doom-modeline-evil-insert-state :weight bold :foreground "#339CDB"))
2020-02-09 00:12:19 +00:00
#+END_SRC
*** Some helper macros
There are a few handy macros added by doom, namely
- ~load!~ for loading external ~.el~ files relative to this one
- ~use-package~ for configuring packages
- ~add-load-path!~ for adding directories to the ~load-path~ where ~emacs~ looks when
you load packages with ~require~ or ~use-package~
- ~map~ for binding new keys
To find more,
** Other things
*** Editor interaction
**** Mouse buttons
#+BEGIN_SRC emacs-lisp
(map! :n [mouse-8] #'better-jumper-jump-backward
:n [mouse-9] #'better-jumper-jump-forward)
#+END_SRC
2020-02-06 15:31:44 +00:00
*** Window title
I'd like to have just the buffer name, then if applicable the project folder
#+BEGIN_SRC emacs-lisp
(setq frame-title-format
'(""
"%b"
(:eval
(let ((project-name (projectile-project-name)))
(unless (string= "-" project-name)
2020-02-16 05:23:19 +00:00
(format (if (buffer-modified-p) " ◉ %s" "  ●  %s") project-name))))))
2020-02-06 15:31:44 +00:00
#+END_SRC
2020-03-27 04:20:42 +00:00
*** Splash screen
Emacs can render an image as the splash screen, and [[https://github.com/MarioRicalde][@MarioRicalde]] came up with a
cracker! He's also provided me with a nice emacs-style /E/, which is good for
smaller windows. *@MarioRicalde* you have my sincere thanks, you're great!
[[file:misc/splash-images/blackhole-lines.svg]]
By incrementally stripping away the outer layers of the logo one can obtain
quite a nice resizing effect.
2020-03-27 04:20:42 +00:00
#+BEGIN_SRC emacs-lisp
(defvar fancy-splash-image-template
(expand-file-name "misc/splash-images/blackhole-lines-template.svg" doom-private-dir)
"Default template svg used for the splash image, with substitutions from ")
(defvar fancy-splash-image-nil
(expand-file-name "misc/splash-images/transparent-pixel.png" doom-private-dir)
"An image to use at minimum size, usually a transparent pixel")
(setq fancy-splash-sizes
`((:height 500 :min-height 50 :padding (0 . 2) :template ,(expand-file-name "misc/splash-images/blackhole-lines-0.svg" doom-private-dir))
(:height 440 :min-height 42 :padding (1 . 4) :template ,(expand-file-name "misc/splash-images/blackhole-lines-0.svg" doom-private-dir))
(:height 400 :min-height 38 :padding (1 . 4) :template ,(expand-file-name "misc/splash-images/blackhole-lines-1.svg" doom-private-dir))
(:height 350 :min-height 36 :padding (1 . 3) :template ,(expand-file-name "misc/splash-images/blackhole-lines-2.svg" doom-private-dir))
(:height 300 :min-height 34 :padding (1 . 3) :template ,(expand-file-name "misc/splash-images/blackhole-lines-3.svg" doom-private-dir))
(:height 250 :min-height 32 :padding (1 . 2) :template ,(expand-file-name "misc/splash-images/blackhole-lines-4.svg" doom-private-dir))
(:height 200 :min-height 30 :padding (1 . 2) :template ,(expand-file-name "misc/splash-images/blackhole-lines-5.svg" doom-private-dir))
(:height 100 :min-height 24 :padding (1 . 2) :template ,(expand-file-name "misc/splash-images/emacs-e-template.svg" doom-private-dir))
(:height 0 :min-height 0 :padding (0 . 0) :file ,fancy-splash-image-nil)))
(defvar fancy-splash-sizes
`((:height 500 :min-height 50 :padding (0 . 2))
(:height 440 :min-height 42 :padding (1 . 4))
(:height 330 :min-height 35 :padding (1 . 3))
(:height 200 :min-height 30 :padding (1 . 2))
(:height 0 :min-height 0 :padding (0 . 0) :file ,fancy-splash-image-nil))
"list of plists with the following properties
:height the height of the image
:min-height minimum `frame-height' for image
:padding `+doom-dashboard-banner-padding' to apply
:template non-default template file
:file file to use instead of template")
(defvar fancy-splash-template-colours
'(("$colour1" . keywords) ("$colour2" . type) ("$colour3" . base5) ("$colour4" . base8))
"list of colour-replacement alists of the form (\"$placeholder\" . 'theme-colour) which applied the template")
(unless (file-exists-p (expand-file-name "theme-splashes" doom-cache-dir))
(make-directory (expand-file-name "theme-splashes" doom-cache-dir) t))
(defun fancy-splash-filename (theme-name height)
(expand-file-name (concat (file-name-as-directory "theme-splashes")
(symbol-name doom-theme)
"-" (number-to-string height) ".svg")
doom-cache-dir))
(defun fancy-splash-clear-cache ()
"Delete all cached fancy splash images"
(interactive)
(delete-directory (expand-file-name "theme-splashes" doom-cache-dir) t)
(message "Cache cleared!"))
(defun fancy-splash-generate-image (template height)
"Read TEMPLATE and create an image if HEIGHT with colour substitutions as ;described by `fancy-splash-template-colours' for the current theme"
(with-temp-buffer
(insert-file-contents template)
(re-search-forward "$height" nil t)
(replace-match (number-to-string height) nil nil)
(dolist (substitution fancy-splash-template-colours)
(beginning-of-buffer)
(while (re-search-forward (car substitution) nil t)
(replace-match (doom-color (cdr substitution)) nil nil)))
2020-03-28 04:18:03 +00:00
(write-region nil nil
(fancy-splash-filename (symbol-name doom-theme) height) nil nil)))
(defun fancy-splash-generate-images ()
"Perform `fancy-splash-generate-image' in bulk"
(dolist (size fancy-splash-sizes)
(unless (plist-get size :file)
(fancy-splash-generate-image (or (plist-get size :file)
(plist-get size :template)
fancy-splash-image-template)
(plist-get size :height)))))
(defun ensure-theme-splash-images-exist (&optional height)
(unless (file-exists-p (fancy-splash-filename
(symbol-name doom-theme)
(or height
(plist-get (car fancy-splash-sizes) :height))))
(fancy-splash-generate-images)))
(defun get-appropriate-splash ()
(let ((height (frame-height)))
(cl-some (lambda (size) (when (>= height (plist-get size :min-height)) size))
fancy-splash-sizes)))
(setq fancy-splash-last-size nil)
(setq fancy-splash-last-theme nil)
2020-03-27 04:20:42 +00:00
(defun set-appropriate-splash (&optional frame)
(let ((appropriate-image (get-appropriate-splash)))
(unless (and (equal appropriate-image fancy-splash-last-size)
(equal doom-theme fancy-splash-last-theme)))
(unless (plist-get appropriate-image :file)
(ensure-theme-splash-images-exist (plist-get appropriate-image :height)))
(setq fancy-splash-image
(or (plist-get appropriate-image :file)
(fancy-splash-filename (symbol-name doom-theme) (plist-get appropriate-image :height))))
(setq +doom-dashboard-banner-padding (plist-get appropriate-image :padding))
(setq fancy-splash-last-size appropriate-image)
(setq fancy-splash-last-theme doom-theme)
(+doom-dashboard-reload)))
2020-03-27 04:20:42 +00:00
(add-hook 'window-size-change-functions #'set-appropriate-splash)
(add-hook 'doom-load-theme-hook #'set-appropriate-splash)
2020-03-27 04:20:42 +00:00
#+END_SRC
2020-02-16 05:12:36 +00:00
*** Systemd daemon
For running a systemd service for a emacs server I have the following
#+BEGIN_SRC systemd :tangle ~/.config/systemd/user/emacs.service
[Unit]
Description=Emacs server daemon
Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/
[Service]
Type=forking
ExecStart=/usr/bin/emacs --daemon
ExecStop=/usr/bin/emacsclient --eval "(progn (setq kill-emacs-hook nil) (kill emacs))"
Environment=SSH_AUTH_SOCK=%t/keyring/ssh
Restart=on-failure
[Install]
WantedBy=default.target
#+END_SRC
which is then enabled by
#+BEGIN_SRC sh :tangle no
systemctl --user enable emacs.service
#+END_SRC
* Package loading
:PROPERTIES:
2020-04-10 04:31:36 +00:00
:header-args:emacs-lisp: :tangle "packages.el" :comments link
:END:
This file shouldn't be byte compiled.
#+BEGIN_SRC emacs-lisp :tangle "packages.el"
;; -*- no-byte-compile: t; -*-
#+END_SRC
** Loading instructions
:PROPERTIES:
2020-03-23 02:59:27 +00:00
:header-args:emacs-lisp: :tangle no
:END:
This is where you install packages, by declaring them with the ~package!~
macro, then running ~doom refresh~ on the command line. You'll need to
restart Emacs for your changes to take effect! Or at least, run =M-x doom/reload=.
WARNING: Don't disable core packages listed in ~~/.emacs.d/core/packages.el~.
Doom requires these, and disabling them may have terrible side effects.
*** Packages in MELPA/ELPA/emacsmirror
To install ~some-package~ from MELPA, ELPA or emacsmirror:
#+BEGIN_SRC emacs-lisp
(package! some-package)
#+END_SRC
*** Packages from git repositories
To install a package directly from a particular repo, you'll need to specify
a ~:recipe~. You'll find documentation on what ~:recipe~ accepts [[https://github.com/raxod502/straight.el#the-recipe-format][here]]:
#+BEGIN_SRC emacs-lisp
(package! another-package
:recipe (:host github :repo "username/repo"))
#+END_SRC
If the package you are trying to install does not contain a ~PACKAGENAME.el~
file, or is located in a subdirectory of the repo, you'll need to specify
~:files~ in the ~:recipe~:
#+BEGIN_SRC emacs-lisp
(package! this-package
:recipe (:host github :repo "username/repo"
:files ("some-file.el" "src/lisp/*.el")))
#+END_SRC
2020-01-09 18:00:50 +00:00
*** Disabling built-in packages
If you'd like to disable a package included with Doom, for whatever reason,
you can do so here with the ~:disable~ property:
#+BEGIN_SRC emacs-lisp
(package! builtin-package :disable t)
#+END_SRC
You can override the recipe of a built in package without having to specify
all the properties for ~:recipe~. These will inherit the rest of its recipe
from Doom or MELPA/ELPA/Emacsmirror:
#+BEGIN_SRC emacs-lisp
(package! builtin-package :recipe (:nonrecursive t))
(package! builtin-package-2 :recipe (:repo "myfork/package"))
#+END_SRC
Specify a ~:branch~ to install a package from a particular branch or tag.
This is required for some packages whose default branch isn't 'master' (which
our package manager can't deal with; see [[https://github.com/raxod502/straight.el/issues/279][raxod502/straight.el#279]])
#+BEGIN_SRC emacs-lisp
(package! builtin-package :recipe (:branch "develop"))
#+END_SRC
*** Updating all pins in file
2020-04-10 04:31:36 +00:00
#+BEGIN_SRC emacs-lisp :tangle yes
(defun +doom/update-all-pinned-package-form ()
"Call `doom/update-pinned-package-form' on every package! statement in the buffer"
(interactive)
(beginning-of-buffer)
(let ((progress 0) (total (how-many "package!")) (updated 0))
(while (search-forward "package!" nil t)
(setq progress (1+ progress))
(forward-char) ;; move cursor to package name "package! |name"
(message (format "Re-pinning package: %s/%s (%s)" progress total (current-word)))
(backward-char)
(evil-scroll-line-to-center (line-number-at-pos))
(redisplay)
(if (s-contains-p "Updated" (condition-case nil
(doom/update-pinned-package-form)
(user-error "")))
(setq updated (1+ updated)))
(search-forward "package!" nil t)) ;; because of cursor-moving done
(message (format "%s packages updated" updated))))
#+END_SRC
2020-02-16 06:13:35 +00:00
** General packages
*** Auto-complete
#+BEGIN_SRC emacs-lisp
(package! company-tabnine ; tab9 autocomplete
:recipe (:host github :repo "TommyX12/company-tabnine"
2020-04-09 17:16:13 +00:00
:files ("company-tabnine.el" "fetch-binaries.sh")) :pin "e986a4ad0d")
#+END_SRC
*** Prettification
~prettify-mode~ is nice and all, but adding substitutions is a little verbose.
This helps with that.
#+BEGIN_SRC emacs-lisp
(package! prettify-utils ; simplify messing with prettify-mode
2020-04-09 17:16:13 +00:00
:recipe (:host github :repo "Ilazki/prettify-utils.el") :pin "8b783d316c")
#+END_SRC
2020-01-20 18:08:53 +00:00
*** Window management
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! rotate :pin "091b5ac4fc")
2020-01-20 18:08:53 +00:00
#+END_SRC
*** Fun
Sometimes one just wants a little fun.
XKCD comics are fun.
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! xkcd :pin "66e928706f")
2020-01-20 18:08:53 +00:00
#+END_SRC
Every so often, you want everyone else to /know/ that you're typing, or just to
amuse oneself. Introducing: typewriter sounds!
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! selectric-mode :pin "bb9e66678f")
2020-01-20 18:08:53 +00:00
#+END_SRC
Hey, let's get the weather in here while we're at it.
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! wttrin :pin "df5427ce2a")
2020-01-20 18:08:53 +00:00
#+END_SRC
Why not flash words on the screen. Why not --- hey, it could be fun.
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! spray :pin "00638bc916")
2020-01-20 18:08:53 +00:00
#+END_SRC
With all our fancy emacs themes, my terminal is missing out!
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! theme-magic :pin "844c4311bd")
2020-01-20 18:08:53 +00:00
#+END_SRC
2020-04-09 17:15:17 +00:00
What's even the point of using Emacs unless you're constantly telling everyone
about it?
#+BEGIN_SRC emacs-lisp
(package! elcord :pin "94b0afb9ba")
#+END_SRC
2020-01-20 18:08:53 +00:00
*** Other
**** Flyspell-lazy
2020-01-09 18:01:52 +00:00
To alleviate some [[Flyspell][issues with flyspell]]
#+BEGIN_SRC emacs-lisp
(package! flyspell-lazy)
#+END_SRC
2020-02-03 04:57:08 +00:00
**** CalcTeX
This is a nice extension to ~calc~
#+BEGIN_SRC emacs-lisp
(package! calctex :recipe (:host github :repo "johnbcoughlin/calctex"
2020-04-09 17:16:13 +00:00
:files ("*.el")) :pin "542b628eb4")
2020-02-03 04:57:08 +00:00
#+END_SRC
2020-02-16 06:13:35 +00:00
**** ESS
View dataframes better with
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! ess-view :pin "d4e5a340b7")
2020-02-16 06:13:35 +00:00
#+END_SRC
** Language packages
*** Systemd
2020-02-03 04:57:08 +00:00
For editing systemd unit files
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! systemd :pin "51c148e09a")
2020-02-03 04:57:08 +00:00
#+END_SRC
2020-02-16 06:13:35 +00:00
*** Org Mode
**** Improve agenda/capture
The agenda is nice, but a souped up version is nicer.
#+BEGIN_SRC emacs-lisp
(package! org-super-agenda :pin "dd0d104c26")
#+END_SRC
2020-04-12 05:49:54 +00:00
**** Visuals
2020-02-16 06:13:35 +00:00
Org tables aren't the prettiest thing to look at. This package is supposed to
redraw them in the buffer with box-drawing characters. Sounds like an
improvement to me! Just need to get it working...
2020-02-03 04:57:08 +00:00
#+BEGIN_SRC emacs-lisp
2020-02-16 06:13:35 +00:00
(package! org-pretty-table-mode
2020-04-09 17:16:13 +00:00
:recipe (:host github :repo "Fuco1/org-pretty-table") :pin "88380f865a")
2020-02-16 06:13:35 +00:00
#+END_SRC
2020-04-12 05:49:54 +00:00
For automatically toggling LaTeX fragment previews there's this nice package
#+BEGIN_SRC emacs-lisp
(package! org-fragtog :pin "8eca8084cc")
#+END_SRC
~org-superstar-mode~ seems better than ~org-bullets~, so let's switch to that
instead. Since we're making stuff look nicer we may as well make priorities and
tags prettier as well :)
#+BEGIN_SRC emacs-lisp
(package! org-bullets :disable t :pin "767f55feb5")
(package! org-superstar
:recipe (:host github :repo "integral-dw/org-superstar-mode")
:pin "4659cfc120")
(package! org-fancy-priorities :pin "819bb993b7")
(package! org-pretty-tags :pin "40fd72f3e7")
#+END_SRC
**** Extra functionality
2020-02-16 06:13:35 +00:00
Because of the /[[https://github.com/commonmark/commonmark-spec/wiki/markdown-flavors][lovely variety in markdown implementations]]/ there isn't actually
such a thing a standard table spec ... or standard anything really. Because
~org-md~ is a goody-two-shoes, it just uses HTML for all these non-standardised
elements (a lot of them). So ~ox-gfm~ is handy for exporting markdown with all the
features that GitHub has. Initialised in [[Exporting to GFM]].
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! ox-gfm :pin "99f93011b0")
2020-02-16 06:13:35 +00:00
#+END_SRC
2020-02-26 11:05:41 +00:00
Now and then citations need to happen
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! org-ref :pin "5bb9be2232")
2020-02-26 11:05:41 +00:00
#+END_SRC
2020-02-16 06:13:35 +00:00
Came across this and ... it's cool
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! org-graph-view :recipe (:host github :repo "alphapapa/org-graph-view") :pin "13314338d7")
2020-02-03 04:57:08 +00:00
#+END_SRC
I *need* this in my life. It take a URL to a recipe from a common site, and
inserts an org-ified version at point. Isn't that just great.
#+BEGIN_SRC emacs-lisp
2020-04-09 17:16:13 +00:00
(package! org-chef :pin "67f50aa2a2")
#+END_SRC
* Package configuration
** Abbrev mode
Thanks to [[https://emacs.stackexchange.com/questions/45462/use-a-single-abbrev-table-for-multiple-modes/45476#45476][use a single abbrev-table for multiple modes? - Emacs Stack Exchange]] I
have the following.
#+BEGIN_SRC emacs-lisp
(use-package abbrev
:init
(setq-default abbrev-mode t)
;; a hook funtion that sets the abbrev-table to org-mode-abbrev-table
;; whenever the major mode is a text mode
(defun tec/set-text-mode-abbrev-table ()
(if (derived-mode-p 'text-mode)
(setq local-abbrev-table org-mode-abbrev-table)))
:commands abbrev-mode
:hook
(abbrev-mode . tec/set-text-mode-abbrev-table)
:config
(setq abbrev-file-name (expand-file-name "abbrev.el" doom-private-dir))
(setq save-abbrevs 'silently))
#+END_SRC
** Centaur Tabs
We want to make the tabs a nice, comfy size (~36~), with icons. The modifier
marker is nice, but the particular default Unicode one causes a lag spike, so
let's just switch to an ~o~, which still looks decent but doesn't cause any
issues.
A 'active-bar' is nice, so let's have one of those. If we have it ~under~ needs us to
turn on ~x-underline-at-decent~ though. For some reason this didn't seem to work
inside the ~(after! ... )~ block ¯\_(ツ)_/¯.
Then let's change the font to a sans serif, but the default one doesn't fit too
well somehow, so let's switch to 'P22 Underground Book'; it looks much nicer.
#+BEGIN_SRC emacs-lisp
(after! centaur-tabs
2020-04-09 18:29:06 +00:00
(centaur-tabs-mode -1)
(setq centaur-tabs-height 36
centaur-tabs-set-icons t
centaur-tabs-modified-marker "o"
2020-01-09 18:02:20 +00:00
centaur-tabs-close-button "×"
centaur-tabs-set-bar 'above)
centaur-tabs-gray-out-icons 'buffer
(centaur-tabs-change-fonts "P22 Underground Book" 160))
;; (setq x-underline-at-descent-line t)
#+END_SRC
** Company
It's nice to have completions almost all the time, in my opinion. Key strokes
are just waiting to be saved!
#+BEGIN_SRC emacs-lisp
(after! company
(setq company-idle-delay 0.5
company-minimum-prefix-length 2)
2020-02-26 12:49:02 +00:00
(setq company-show-numbers t)
(add-hook 'evil-normal-state-entry-hook #'company-abort)) ;; make aborting less annoying.
#+END_SRC
Now, the improvements from ~precident~ are mostly from remembering history, so
let's improve that memory.
#+BEGIN_SRC emacs-lisp
(setq-default history-length 1000)
(setq-default prescient-history-length 1000)
#+END_SRC
*** Plain Text
~ispell~ is nice, let's have it in ~text~, ~markdown~, and ~GFM~.
#+BEGIN_SRC emacs-lisp
(set-company-backend! '(text-mode
markdown-mode
gfm-mode)
'(:seperate company-ispell
company-files
company-yasnippet))
#+END_SRC
2020-03-19 09:00:06 +00:00
We then configure the dictionary we're using in [[*ispell][ispell]].
*** ESS
~company-dabbrev-code~ is nice. Let's have it.
#+BEGIN_SRC emacs-lisp
(set-company-backend! 'ess-r-mode '(company-R-args company-R-objects company-dabbrev-code :separate))
#+END_SRC
** [[https://github.com/zachcurry/emacs-anywhere][Emacs Anywhere]] configuration
2020-02-06 17:11:58 +00:00
# NB: install with curl -fsSL https://raw.github.com/zachcurry/emacs-anywhere/master/install | bash
It's nice to recognise GitHub (so we can use ~GFM~), and other apps which we know
take markdown
#+BEGIN_SRC emacs-lisp
(defun markdown-window-p (window-title)
"Judges from WINDOW-TITLE whether the current window likes markdown"
(string-match-p (rx (or "Stack Exchange" "Stack Overflow"
"Pull Request" "Issue" "Discord"))
window-title))
#+END_SRC
When the window opens, we generally want text so let's use a nice sans serif font,
a position the window below and to the left. Oh, and don't forget about checking
for ~GFM~, otherwise let's just use ~markdown~.
#+BEGIN_SRC emacs-lisp
(define-minor-mode emacs-anywhere-mode
"To tweak the current buffer for some emacs-anywhere considerations"
:init-value nil
:keymap (list
;; Finish edit, but be smart in org mode
(cons (kbd "C-c C-c") (lambda! (if (and (eq major-mode 'org-mode)
(org-in-src-block-p))
(org-ctrl-c-ctrl-c)
(delete-frame))))
;; Abort edit. emacs-anywhere saves the current edit for next time.
(cons (kbd "C-c C-k") (lambda! (setq ea-on nil)
(delete-frame))))
(when emacs-anywhere-mode
2020-03-24 04:45:07 +00:00
;; line breaking
(turn-off-auto-fill)
(visual-line-mode t)
;; DEL/C-SPC to clear (first keystroke only)
(set-transient-map (let ((keymap (make-sparse-keymap)))
(define-key keymap (kbd "DEL") (lambda! (delete-region (point-min) (point-max))))
(define-key keymap (kbd "C-SPC") (lambda! (delete-region (point-min) (point-max))))
keymap))
;; disable tabs
(when (bound-and-true-p centaur-tabs-mode)
(centaur-tabs-local-mode t))))
(defun ea-popup-handler (app-name window-title x y w h)
(interactive)
(set-frame-size (selected-frame) 80 12)
;; position the frame near the mouse
(let* ((mousepos (split-string (shell-command-to-string "xdotool getmouselocation | sed -E \"s/ screen:0 window:[^ ]*|x:|y://g\"")))
(mouse-x (- (string-to-number (nth 0 mousepos)) 100))
(mouse-y (- (string-to-number (nth 1 mousepos)) 50)))
(set-frame-position (selected-frame) mouse-x mouse-y))
(set-frame-name (concat "Quick Edit ∷ " ea-app-name " — "
(truncate-string-to-width
(string-trim
(string-trim-right window-title
(format "-[A-Za-z0-9 ]*%s" ea-app-name))
"[\s-]+" "[\s-]+")
45 nil nil "…")))
(message "window-title: %s" window-title)
;; set major mode
(cond
((markdown-window-p window-title) (gfm-mode))
(t (org-mode)) ; default major mode
)
(when (gui-get-selection 'PRIMARY) (insert (gui-get-selection 'PRIMARY)))
(evil-insert-state) ; start in insert
(emacs-anywhere-mode 1))
(add-hook 'ea-popup-hook 'ea-popup-handler)
#+END_SRC
** Flyspell
At one point, typing became noticably laggy, Profiling revealed
~flyspell-post-command-hook~ was responsible for 47% of CPU cycles by itself!
So I'm going to make use of ~flyspell-lazy~
#+BEGIN_SRC emacs-lisp
(after! flyspell (require 'flyspell-lazy) (flyspell-lazy-mode 1))
#+END_SRC
** Tramp
Let's try to make tramp handle prompts better
#+BEGIN_SRC emacs-lisp
(after! tramp
(setenv "SHELL" "/bin/bash")
(setq tramp-shell-prompt-pattern "\\(?:^\\| \\)[^]#$%>\n]*#?[]#$%>] *\\(\\[[0-9;]*[a-zA-Z] *\\)*")) ;; defult + 
#+END_SRC
**** Troubleshooting
In case the remote shell is misbehaving, here are some things to try
***** Zsh
There are some escape code you don't want, let's make it behave more considerately.
#+BEGIN_SRC shell :eval no :tangle no
if [[ "$TERM" == "dumb" ]]; then
unset zle_bracketed_paste
unset zle
PS1='$ '
return
fi
#+END_SRC
2020-03-17 17:12:17 +00:00
** Treemacs
Quite often there are superfluous files I'm not that interested in. There's no
2020-03-23 03:00:23 +00:00
good reason for them to take up space. Let's add a mechanism to ignore them.
#+BEGIN_SRC emacs-lisp
(after! treemacs
(defvar treemacs-file-ignore-extensions '()
"File extension which `treemacs-ignore-filter' will ensure are ignored")
(defvar treemacs-file-ignore-globs '()
"Globs which will are transformed to `treemacs-file-ignore-regexps' which `treemacs-ignore-filter' will ensure are ignored")
(defvar treemacs-file-ignore-regexps '()
"RegExps to be tested to ignore files, generated from `treeemacs-file-ignore-globs'")
(defun treemacs-file-ignore-generate-regexps ()
"Generate `treemacs-file-ignore-regexps' from `treemacs-file-ignore-globs'"
(setq treemacs-file-ignore-regexps (mapcar 'dired-glob-regexp treemacs-file-ignore-globs)))
(if (equal treemacs-file-ignore-globs '()) nil (treemacs-file-ignore-generate-regexps))
(defun treemacs-ignore-filter (file full-path)
"Ignore files specified by `treemacs-file-ignore-extensions', and `treemacs-file-ignore-regexps'"
(or (member (file-name-extension file) treemacs-file-ignore-extensions)
(let ((ignore-file nil))
(dolist (regexp treemacs-file-ignore-regexps ignore-file)
(setq ignore-file (or ignore-file (if (string-match-p regexp full-path) t nil)))))))
(add-to-list 'treemacs-ignored-file-predicates #'treemacs-ignore-filter))
#+END_SRC
Now, we just identify the files in question.
2020-03-17 17:12:17 +00:00
#+BEGIN_SRC emacs-lisp
2020-03-18 16:48:47 +00:00
(setq treemacs-file-ignore-extensions '(;; LaTeX
"aux"
"ptc"
"fdb_latexmk"
"fls"
"synctex.gz"
"toc"
;; LaTeX - glossary
"glg"
"glo"
"gls"
"glsdefs"
"ist"
"acn"
"acr"
"alg"
;; LaTeX - pgfplots
"mw"
;; LaTeX - pdfx
"pdfa.xmpi"
))
(setq treemacs-file-ignore-globs '(;; LaTeX
"*/_minted-*"
;; AucTeX
"*/.auctex-auto"
"*/_region_.log"
2020-03-23 03:00:23 +00:00
"*/_region_.tex"))
#+END_SRC
2020-02-29 11:09:06 +00:00
** Miscellaneous
*** calc
Radians are just better
#+BEGIN_SRC emacs-lisp
2020-04-12 05:47:21 +00:00
(setq calc-angle-mode 'rad ;; radians are rad
calc-algebraic-mode t ;; allows '2*x instead of 'x<RET>2*
calc-symbolic-mode t) ;; keeps stuff like √2 irrational for as long as possible
(after! calctex
(setq calctex-format-latex-header (concat calctex-format-latex-header
"\n\\usepackage{arevmath}")))
(add-hook 'calc-mode-hook #'calctex-mode)
#+END_SRC
*** electric pair mode
We want this everywhere
#+BEGIN_SRC emacs-lisp
(electric-pair-mode t)
#+END_SRC
*** ispell
2020-03-19 09:00:06 +00:00
Let's get a nice big dictionary from [[http://app.aspell.net/create][SCOWL Custom List/Dictionary Creator]] with
the following configuration
- size :: 80 (huge)
- spellings :: British(-ise) and Australian
- spellling variants level :: 0
- diacritics :: keep
- extra lists :: hacker, roman numerals
#+BEGIN_SRC emacs-lisp
(setq ispell-dictionary "en_GBs_au_SCOWL_80_0_k_hr")
2020-03-19 09:00:06 +00:00
#+END_SRC
Oh, and by the way, if ~company-ispell-dictionary~ is ~nil~, then
2020-03-28 04:18:24 +00:00
~ispell-complete-word-dict~ is used instead, which once again when ~nil~ is
~ispell-alternate-dictionary~, which at the moment maps to a plaintext version of
the above.
2020-03-19 09:00:06 +00:00
It seems reasonable to want to keep an eye on my personal dict, let's have it
nearby (also means that if I change the 'main' dictionary I keep my addition).
#+BEGIN_SRC emacs-lisp
(setq ispell-personal-dictionary (expand-file-name ".hunspell_personal" doom-private-dir))
#+END_SRC
*** spray
Let's make this suit me slightly better.
#+BEGIN_SRC emacs-lisp
(setq spray-wpm 500
spray-height 700)
#+END_SRC
*** theme magic
Let's automatically update terminals on theme change
#+BEGIN_SRC emacs-lisp
(add-hook 'doom-load-theme-hook 'theme-magic-from-emacs)
#+END_SRC
*** wttrin
Set the default city. It's initially ~Taipei~ but I find the IP-locating that's
done perfectly acceptable, so let's make that happen.
2020-03-15 16:31:28 +00:00
#+BEGIN_SRC emacs-lisp
(setq wttrin-default-cities '(""))
2020-03-15 16:31:28 +00:00
#+END_SRC
2020-04-09 17:15:17 +00:00
*** elcord
#+BEGIN_SRC emacs-lisp
(setq elcord-use-major-mode-as-main-icon t)
#+END_SRC
* Language configuration
*** File Templates
For some file types, we overwrite defaults in the [[file:./snippets][snippets]] directory, others
need to have a template assigned.
#+BEGIN_SRC emacs-lisp
(set-file-template! "\\.tex$" :trigger "__" :mode 'latex-mode)
#+END_SRC
** Org Mode
*** System config
Org mode isn't recognised as it's own mime type by default, but that can easily
be changed with the following file. For system-wide changes try
~~/usr/share/mime/packages/org.xml~.
#+BEGIN_SRC xml :tangle ~/.local/share/mime/packages/org.xml
<?xml version="1.0" encoding="utf-8"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="text/org">
<comment>Emacs Org-mode File</comment>
<glob pattern="*.org"/>
<alias type="text/org"/>
</mime-type>
</mime-info>
#+END_SRC
What's nice is that Papirus [[https://github.com/PapirusDevelopmentTeam/papirus-icon-theme/commit/a10fb7f2423d5e30b9c4477416ccdc93c4f3849d][now]] has an icon for =text/org=.
One simply needs to refresh their mime database
2020-03-23 02:59:27 +00:00
#+BEGIN_SRC shell :results silent
update-mime-database ~/.local/share/mime
#+END_SRC
Then set emacs as the default editor
2020-03-23 02:59:27 +00:00
#+BEGIN_SRC shell :results silent
xdg-mime default emacs.desktop text/org
#+END_SRC
*** Behaviour
2020-03-23 11:07:40 +00:00
**** Tweaking defaults
#+BEGIN_SRC emacs-lisp
(setq org-directory "~/.org" ; let's put files here
org-use-property-inheritance t ; it's convenient to have properties inherited
org-log-done 'time ; having the time a item is done sounds convininet
org-list-allow-alphabetical t ; have a. A. a) A) list bullets
org-export-in-background t ; run export processes in external emacs process
org-catch-invisible-edits 'smart) ; try not to accidently do weird stuff in invisible regions
#+END_SRC
2020-03-23 11:07:40 +00:00
I also like the ~:comments~ header-argument, so let's make that a default.
#+BEGIN_SRC emacs-lisp
(setq org-babel-default-header-args '((:session . "none")
(:results . "replace")
(:exports . "code")
(:cache . "no")
(:noweb . "no")
(:hlines . "no")
(:tangle . "no")
(:comments . "link")))
#+END_SRC
**** Extra functionality
Let's also make creating an org buffer just that little bit easier.
#+BEGIN_SRC emacs-lisp
(evil-define-command evil-buffer-org-new (count file)
"Creates a new ORG buffer replacing the current window, optionally
editing a certain FILE"
:repeat nil
(interactive "P<f>")
(if file
(evil-edit file)
(let ((buffer (generate-new-buffer "*new org*")))
(set-window-buffer nil buffer)
(with-current-buffer buffer
(org-mode)))))
(map! :leader
(:prefix "b"
:desc "New empty ORG buffer" "o" #'evil-buffer-org-new))
#+END_SRC
2020-02-29 10:46:14 +00:00
I think it makes sense to have list bullets change with depth
#+BEGIN_SRC emacs-lisp
(setq org-list-demote-modify-bullet '(("+" . "-") ("-" . "+") ("*" . "+")))
#+END_SRC
2020-02-26 11:05:41 +00:00
Occasionally I want to cite something.
#+BEGIN_SRC emacs-lisp
(use-package! org-ref
2020-02-26 11:05:41 +00:00
:after org
:config
(setq org-ref-completion-library 'org-ref-ivy-cite))
#+END_SRC
It's also nice to be able to use ~cdlatex~.
#+BEGIN_SRC emacs-lisp
(after! org (add-hook 'org-mode-hook 'turn-on-org-cdlatex))
#+END_SRC
At some point in the future it could be good to investigate [[https://scripter.co/splitting-an-org-block-into-two/][splitting org blocks]].
Likewise [[https://archive.casouri.cat/note/2020/insert-math-symbol-in-emacs/][this]] looks good for symbols.
2020-03-23 03:01:31 +00:00
My spelling is atrocious, so let's get flycheck going.
#+BEGIN_SRC emacs-lisp
(after! org (add-hook 'org-mode-hook 'turn-on-flyspell))
#+END_SRC
**** Super agenda
#+BEGIN_SRC emacs-lisp
(use-package! org-super-agenda
:commands (org-super-agenda-mode))
(after! org-agenda
(org-super-agenda-mode))
(setq org-agenda-skip-scheduled-if-done t
org-agenda-skip-deadline-if-done t
org-agenda-include-deadlines t
org-agenda-block-separator nil
org-agenda-compact-blocks t)
(setq org-agenda-custom-commands
'(("o" "Overview"
((agenda "" ((org-agenda-span 'day)
(org-super-agenda-groups
'((:name "Today"
:time-grid t
:date today
:todo "TODAY"
:scheduled today
:order 1)))))
(alltodo "" ((org-agenda-overriding-header "")
(org-super-agenda-groups
'((:name "Next to do"
:todo "NEXT"
:order 1)
(:name "Important"
:tag "Important"
:priority "A"
:order 6)
(:name "Due Today"
:deadline today
:order 2)
(:name "Due Soon"
:deadline future
:order 8)
(:name "Overdue"
:deadline past
:face error
:order 7)
(:name "Assignments"
:tag "Assignment"
:order 10)
(:name "Issues"
:tag "Issue"
:order 12)
(:name "Projects"
:tag "Project"
:order 14)
(:name "Emacs"
:tag "Emacs"
:order 13)
(:name "Research"
:tag "Research"
:order 15)
(:name "To read"
:tag "Read"
:order 30)
(:name "Waiting"
:todo "WAITING"
:order 20)
(:name "Trivial"
:priority<= "E"
:tag ("Trivial" "Unimportant")
:todo ("SOMEDAY" )
:order 90)
(:discard (:tag ("Chore" "Routine" "Daily")))))))))))
#+END_SRC
**** Nicer headings
Thanks to alphapapa's [[https://github.com/alphapapa/unpackaged.el#export-to-html-with-useful-anchors][unpackaged.el]].
Unfortunately this currently seems to break some of the other modifications I've made.
#+BEGIN_SRC emacs-lisp :tangle no
(define-minor-mode unpackaged/org-export-html-with-useful-ids-mode
"Attempt to export Org as HTML with useful link IDs.
Instead of random IDs like \"#orga1b2c3\", use heading titles,
made unique when necessary."
:global t
(if unpackaged/org-export-html-with-useful-ids-mode
(advice-add #'org-export-get-reference :override #'unpackaged/org-export-get-reference)
(advice-remove #'org-export-get-reference #'unpackaged/org-export-get-reference)))
(defun unpackaged/org-export-get-reference (datum info)
"Like `org-export-get-reference', except uses heading titles instead of random numbers."
(let ((cache (plist-get info :internal-references)))
(or (car (rassq datum cache))
(let* ((crossrefs (plist-get info :crossrefs))
(cells (org-export-search-cells datum))
;; Preserve any pre-existing association between
;; a search cell and a reference, i.e., when some
;; previously published document referenced a location
;; within current file (see
;; `org-publish-resolve-external-link').
;;
;; However, there is no guarantee that search cells are
;; unique, e.g., there might be duplicate custom ID or
;; two headings with the same title in the file.
;;
;; As a consequence, before re-using any reference to
;; an element or object, we check that it doesn't refer
;; to a previous element or object.
(new (or (cl-some
(lambda (cell)
(let ((stored (cdr (assoc cell crossrefs))))
(when stored
(let ((old (org-export-format-reference stored)))
(and (not (assoc old cache)) stored)))))
cells)
(when (org-element-property :raw-value datum)
;; Heading with a title
(unpackaged/org-export-new-title-reference datum cache))
;; NOTE: This probably breaks some Org Export
;; feature, but if it does what I need, fine.
(org-export-format-reference
(org-export-new-reference cache))))
(reference-string new))
;; Cache contains both data already associated to
;; a reference and in-use internal references, so as to make
;; unique references.
(dolist (cell cells) (push (cons cell new) cache))
;; Retain a direct association between reference string and
;; DATUM since (1) not every object or element can be given
;; a search cell (2) it permits quick lookup.
(push (cons reference-string datum) cache)
(plist-put info :internal-references cache)
reference-string))))
(defun unpackaged/org-export-new-title-reference (datum cache)
"Return new reference for DATUM that is unique in CACHE."
(cl-macrolet ((inc-suffixf (place)
`(progn
(string-match (rx bos
(minimal-match (group (1+ anything)))
(optional "--" (group (1+ digit)))
eos)
,place)
;; HACK: `s1' instead of a gensym.
(-let* (((s1 suffix) (list (match-string 1 ,place)
(match-string 2 ,place)))
(suffix (if suffix
(string-to-number suffix)
0)))
(setf ,place (format "%s--%s" s1 (cl-incf suffix)))))))
(let* ((title (org-element-property :raw-value datum))
(ref (url-hexify-string (substring-no-properties title)))
(parent (org-element-property :parent datum)))
(while (--any (equal ref (car it))
cache)
;; Title not unique: make it so.
(if parent
;; Append ancestor title.
(setf title (concat (org-element-property :raw-value parent)
"--" title)
ref (url-hexify-string (substring-no-properties title))
parent (org-element-property :parent parent))
;; No more ancestors: add and increment a number.
(inc-suffixf ref)))
ref)))
#+END_SRC
**** Nicer ~org-return~
Once again, from [[https://github.com/alphapapa/unpackaged.el#org-return-dwim][unpackaged.el]]
#+BEGIN_SRC emacs-lisp
(after! org
(defun unpackaged/org-element-descendant-of (type element)
"Return non-nil if ELEMENT is a descendant of TYPE.
TYPE should be an element type, like `item' or `paragraph'.
ELEMENT should be a list like that returned by `org-element-context'."
;; MAYBE: Use `org-element-lineage'.
(when-let* ((parent (org-element-property :parent element)))
(or (eq type (car parent))
(unpackaged/org-element-descendant-of type parent))))
;;;###autoload
(defun unpackaged/org-return-dwim (&optional default)
"A helpful replacement for `org-return-indent'. With prefix, call `org-return-indent'.
On headings, move point to position after entry content. In
lists, insert a new item or end the list, with checkbox if
appropriate. In tables, insert a new row or end the table."
;; Inspired by John Kitchin: http://kitchingroup.cheme.cmu.edu/blog/2017/04/09/A-better-return-in-org-mode/
(interactive "P")
(if default
(org-return t)
(cond
;; Act depending on context around point.
;; NOTE: I prefer RET to not follow links, but by uncommenting this block, links will be
;; followed.
;; ((eq 'link (car (org-element-context)))
;; ;; Link: Open it.
;; (org-open-at-point-global))
((org-at-heading-p)
;; Heading: Move to position after entry content.
;; NOTE: This is probably the most interesting feature of this function.
(let ((heading-start (org-entry-beginning-position)))
(goto-char (org-entry-end-position))
(cond ((and (org-at-heading-p)
(= heading-start (org-entry-beginning-position)))
;; Entry ends on its heading; add newline after
(end-of-line)
(insert "\n\n"))
(t
;; Entry ends after its heading; back up
(forward-line -1)
(end-of-line)
(when (org-at-heading-p)
;; At the same heading
(forward-line)
(insert "\n")
(forward-line -1))
;; FIXME: looking-back is supposed to be called with more arguments.
(while (not (looking-back (rx (repeat 3 (seq (optional blank) "\n")))))
(insert "\n"))
(forward-line -1)))))
((org-at-item-checkbox-p)
;; Checkbox: Insert new item with checkbox.
(org-insert-todo-heading nil))
((org-in-item-p)
;; Plain list. Yes, this gets a little complicated...
(let ((context (org-element-context)))
(if (or (eq 'plain-list (car context)) ; First item in list
(and (eq 'item (car context))
(not (eq (org-element-property :contents-begin context)
(org-element-property :contents-end context))))
(unpackaged/org-element-descendant-of 'item context)) ; Element in list item, e.g. a link
;; Non-empty item: Add new item.
(org-insert-item)
;; Empty item: Close the list.
;; TODO: Do this with org functions rather than operating on the text. Can't seem to find the right function.
(delete-region (line-beginning-position) (line-end-position))
(insert "\n"))))
((when (fboundp 'org-inlinetask-in-task-p)
(org-inlinetask-in-task-p))
;; Inline task: Don't insert a new heading.
(org-return t))
((org-at-table-p)
(cond ((save-excursion
(beginning-of-line)
;; See `org-table-next-field'.
(cl-loop with end = (line-end-position)
for cell = (org-element-table-cell-parser)
always (equal (org-element-property :contents-begin cell)
(org-element-property :contents-end cell))
while (re-search-forward "|" end t)))
;; Empty row: end the table.
(delete-region (line-beginning-position) (line-end-position))
(org-return t))
(t
;; Non-empty row: call `org-return-indent'.
(org-return t))))
(t
;; All other cases: call `org-return-indent'.
(org-return t)))))
(advice-add #'org-return-indent :override #'unpackaged/org-return-dwim))
#+END_SRC
*** Visuals
**** In editor
***** Font Display
Mixed pitch is great. As is ~+org-pretty-mode~, let's use them.
#+BEGIN_SRC emacs-lisp
(add-hook! 'org-mode-hook #'+org-pretty-mode #'mixed-pitch-mode)
#+END_SRC
2020-01-09 17:58:01 +00:00
Earlier I loaded the ~org-pretty-table~ package, let's enable it everywhere!
#+BEGIN_SRC emacs-lisp
(setq global-org-pretty-table-mode t)
#+END_SRC
2020-03-14 15:30:49 +00:00
Let's make headings a bit bigger
#+BEGIN_SRC emacs-lisp
(custom-set-faces!
'(outline-1 :weight extra-bold :height 1.2)
'(outline-2 :weight bold :height 1.12)
'(outline-3 :weight bold :height 1.1)
'(outline-4 :weight semi-bold :height 1.08)
'(outline-5 :weight semi-bold :height 1.05)
'(outline-6 :weight semi-bold :height 1.02)
'(outline-8 :weight semi-bold)
'(outline-9 :weight semi-bold))
#+END_SRC
***** Symbols
2020-01-09 17:58:01 +00:00
It's also nice to change the character used for collapsed items (by default ~…~),
I think ~▾~ is better for indicating 'collapsed section'.
and add an extra ~org-bullet~ to the default list of four.
I've also added some fun alternatives, just commented out.
#+BEGIN_SRC emacs-lisp
(use-package! org-superstar ; "prettier" bullets
:hook (org-mode . org-superstar-mode))
(use-package org-fancy-priorities
:diminish
:defines org-fancy-priorities-list
:hook (org-mode . org-fancy-priorities-mode)
:config
(unless (char-displayable-p ?❗)
(setq org-fancy-priorities-list '("HIGH" "MID" "LOW" "OPTIONAL"))))
(after! org
(use-package org-pretty-tags
:config
(setq org-pretty-tags-surrogate-strings
'(("uni" . "🎓")))
(org-pretty-tags-global-mode)))
(after! org
(setq org-ellipsis " ▾ "
org-superstar-headline-bullets-list '("◉" "○" "✸" "✿" "✤" "✜" "◆" "▶")
2020-04-12 05:50:29 +00:00
org-fancy-priorities-list '((?A . "⚑") ;; ASAP
(?B . "⬆") ;; High
(?C . "■") ;; Medium
(?D . "⬇") ;; Low
(?E . "❓")) ;; Optional
org-priority-faces '((?A . all-the-icons-red)
(?B . all-the-icons-orange)
(?C . all-the-icons-yellow)
(?D . all-the-icons-green)
(?E . all-the-icons-blue))
org-priority-highest ?A
2020-04-12 05:50:29 +00:00
org-priority-lowest ?E
;; org-superstar-headline-bullets-list '("" "Ⅱ" "Ⅲ" "Ⅳ" "" "Ⅵ" "Ⅶ" "Ⅷ" "Ⅸ" "")
))
2020-01-09 17:58:01 +00:00
#+END_SRC
It's also nice to make use of the unicode characters for check boxes, and other commands.
#+BEGIN_SRC emacs-lisp
(after! org
(appendq! +pretty-code-symbols
2020-01-29 13:20:41 +00:00
'(:checkbox "☐"
:pending "◼"
:checkedbox "☑"
:results "🠶"
:property "☸"
2020-03-01 13:14:06 +00:00
:properties "⚙"
:end "∎"
:options "⌥"
2020-01-29 13:20:41 +00:00
:title "𝙏"
:author "𝘼"
:date "𝘿"
2020-01-09 17:58:01 +00:00
:begin_quote ""
2020-01-29 13:20:41 +00:00
:end_quote ""
:em_dash "—"))
2020-01-09 17:58:01 +00:00
(set-pretty-symbols! 'org-mode
:merge t
2020-01-29 13:20:41 +00:00
:checkbox "[ ]"
:pending "[-]"
:checkedbox "[X]"
:results "#+RESULTS:"
:property "#+PROPERTY:"
2020-03-01 13:14:06 +00:00
:property ":PROPERTIES:"
:end ":END:"
2020-03-04 15:27:37 +00:00
:options "#+OPTIONS:"
2020-01-29 13:20:41 +00:00
:title "#+TITLE:"
:author "#+AUTHOR:"
:date "#+DATE:"
2020-01-09 17:58:01 +00:00
:begin_quote "#+BEGIN_QUOTE"
2020-01-29 13:20:41 +00:00
:end_quote "#+END_QUOTE"
:em_dash "---")
2020-01-09 17:58:01 +00:00
)
(plist-put +pretty-code-symbols :name "⁍") ; or could be good?
#+END_SRC
2020-02-16 08:13:17 +00:00
We also like ~org-fragtog~, and that wants a hook.
#+BEGIN_SRC emacs-lisp
(add-hook 'org-mode-hook 'org-fragtog-mode)
#+END_SRC
2020-02-03 05:01:57 +00:00
***** LaTeX Fragments
It's nice to customise the look of LaTeX fragments so they fit better in the
text --- like this \(\sqrt{\beta^2+3}-\sum_{\phi=1}^\infty \frac{x^\phi-1}{\Gamma(a)}\). Let's start by adding a sans font.
2020-02-03 05:01:57 +00:00
#+BEGIN_SRC emacs-lisp
(setq org-format-latex-header "\\documentclass{article}
\\usepackage[usenames]{color}
\\usepackage[T1]{fontenc}
\\usepackage{mathtools}
\\usepackage{textcomp,amssymb}
2020-02-26 11:05:41 +00:00
\\usepackage[makeroom]{cancel}
2020-02-03 05:01:57 +00:00
\\pagestyle{empty} % do not remove
% The settings below are copied from fullpage.sty
\\setlength{\\textwidth}{\\paperwidth}
\\addtolength{\\textwidth}{-3cm}
\\setlength{\\oddsidemargin}{1.5cm}
\\addtolength{\\oddsidemargin}{-2.54cm}
\\setlength{\\evensidemargin}{\\oddsidemargin}
\\setlength{\\textheight}{\\paperheight}
\\addtolength{\\textheight}{-\\headheight}
\\addtolength{\\textheight}{-\\headsep}
\\addtolength{\\textheight}{-\\footskip}
\\addtolength{\\textheight}{-3cm}
\\setlength{\\topmargin}{1.5cm}
\\addtolength{\\topmargin}{-2.54cm}
% my custom stuff
2020-02-09 00:36:59 +00:00
\\usepackage{arev}
2020-02-03 05:01:57 +00:00
\\usepackage{arevmath}")
#+END_SRC
We can either render from a ~dvi~ or ~pdf~ file, so let's benchmark ~latex~ and
~pdflatex~.
| ~latex~ time | ~pdflatex~ time |
|------------+---------------|
| 135±2 ms | 215±3 ms |
2020-02-03 05:01:57 +00:00
On the rendering side, there are two ~.dvi~-to-image convertors which I am
interested in: ~dvipng~ and ~dvisvgm~. Then with the a ~.pdf~ we have ~pdf2svg~.
For inline preview we care about speed, while for exporting we care about file
size and preffer a vector graphic.
Using the above latex expression and benchmarking lead to the following results:
| ~dvipng~ time | ~dvisvgm~ time | ~pdf2svg~ time |
|-------------+--------------+--------------|
| 89±2 ms | 178±2 ms | 12±2 ms |
Now let's combine this to see what's best
| Tool chain | Total time | Resultant file size |
|--------------------+------------+---------------------|
| ~latex~ + ~dvipng~ | 226±2 ms | 7 KiB |
| ~latex~ + ~dvisvgm~ | 392±4 ms | 8 KiB |
| ~pdflatex~ + ~pdf2svg~ | 230±2 ms | 16 KiB |
2020-02-03 05:01:57 +00:00
So, let's use ~dvipng~ for previewing LaTeX fragments in-emacs, but ~dvisvgm~ for [[
Exporting to HTML][LaTeX Rendering]].
/Unfortunately: it seems that svg sizing is annoying ATM, so let's actually not do this right now./
2020-02-03 05:01:57 +00:00
As well as having a sans font, there are a few other tweaks which can make them
look better. Namely making sure that the colours switch when the theme does.
2020-02-03 05:01:57 +00:00
#+BEGIN_SRC emacs-lisp
(after! org
;; make background of fragments transparent
;; (let ((dvipng--plist (alist-get 'dvipng org-preview-latex-process-alist)))
;; (plist-put dvipng--plist :use-xcolor t)
;; (plist-put dvipng--plist :image-converter '("dvipng -D %D -bg 'transparent' -T tight -o %O %f")))
2020-02-09 15:14:21 +00:00
(add-hook! 'doom-load-theme-hook
(defun +org-refresh-latex-background ()
(plist-put! org-format-latex-options
:background
(face-attribute (or (cadr (assq 'default face-remapping-alist))
'default)
:background nil t))))
2020-02-03 05:01:57 +00:00
)
#+END_SRC
It'd be nice to make ~mhchem~ equations able to be rendered.
NB: This doesn't work at the moment.
#+BEGIN_SRC emacs-lisp
(after! org
(add-to-list 'org-latex-regexps '("\\ce" "^\\\\ce{\\(?:[^\000{}]\\|{[^\000}]+?}\\)}" 0 nil)))
#+END_SRC
***** Stolen from [[https://github.com/jkitchin/scimax][scimax]] (semi-working right now)
I want fragment justification
#+BEGIN_SRC emacs-lisp
(after! org
(defun scimax-org-latex-fragment-justify (justification)
"Justify the latex fragment at point with JUSTIFICATION.
JUSTIFICATION is a symbol for 'left, 'center or 'right."
(interactive
(list (intern-soft
(completing-read "Justification (left): " '(left center right)
nil t nil nil 'left))))
(let* ((ov (ov-at))
(beg (ov-beg ov))
(end (ov-end ov))
(shift (- beg (line-beginning-position)))
(img (overlay-get ov 'display))
(img (and (and img (consp img) (eq (car img) 'image)
(image-type-available-p (plist-get (cdr img) :type)))
img))
space-left offset)
(when (and img
;; This means the equation is at the start of the line
(= beg (line-beginning-position))
(or
(string= "" (s-trim (buffer-substring end (line-end-position))))
(eq 'latex-environment (car (org-element-context)))))
(setq space-left (- (window-max-chars-per-line) (car (image-size img)))
offset (floor (cond
((eq justification 'center)
(- (/ space-left 2) shift))
((eq justification 'right)
(- space-left shift))
(t
0))))
(when (>= offset 0)
(overlay-put ov 'before-string (make-string offset ?\ ))))))
(defun scimax-org-latex-fragment-justify-advice (beg end image imagetype)
"After advice function to justify fragments."
(scimax-org-latex-fragment-justify (or (plist-get org-format-latex-options :justify) 'left)))
(defun scimax-toggle-latex-fragment-justification ()
"Toggle if LaTeX fragment justification options can be used."
(interactive)
(if (not (get 'scimax-org-latex-fragment-justify-advice 'enabled))
(progn
(advice-add 'org--format-latex-make-overlay :after 'scimax-org-latex-fragment-justify-advice)
(put 'scimax-org-latex-fragment-justify-advice 'enabled t)
(message "Latex fragment justification enabled"))
(advice-remove 'org--format-latex-make-overlay 'scimax-org-latex-fragment-justify-advice)
(put 'scimax-org-latex-fragment-justify-advice 'enabled nil)
(message "Latex fragment justification disabled"))))
#+END_SRC
There's also this lovely equation numbering stuff I'll nick
#+BEGIN_SRC emacs-lisp
;; Numbered equations all have (1) as the number for fragments with vanilla
;; org-mode. This code injects the correct numbers into the previews so they
;; look good.
(after! org
(defun scimax-org-renumber-environment (orig-func &rest args)
"A function to inject numbers in LaTeX fragment previews."
(let ((results '())
(counter -1)
(numberp))
(setq results (loop for (begin . env) in
(org-element-map (org-element-parse-buffer) 'latex-environment
(lambda (env)
(cons
(org-element-property :begin env)
(org-element-property :value env))))
collect
(cond
((and (string-match "\\\\begin{equation}" env)
(not (string-match "\\\\tag{" env)))
(incf counter)
(cons begin counter))
((string-match "\\\\begin{align}" env)
(prog2
(incf counter)
(cons begin counter)
(with-temp-buffer
(insert env)
(goto-char (point-min))
;; \\ is used for a new line. Each one leads to a number
(incf counter (count-matches "\\\\$"))
;; unless there are nonumbers.
(goto-char (point-min))
(decf counter (count-matches "\\nonumber")))))
(t
(cons begin nil)))))
(when (setq numberp (cdr (assoc (point) results)))
(setf (car args)
(concat
(format "\\setcounter{equation}{%s}\n" numberp)
(car args)))))
(apply orig-func args))
(defun scimax-toggle-latex-equation-numbering ()
"Toggle whether LaTeX fragments are numbered."
(interactive)
(if (not (get 'scimax-org-renumber-environment 'enabled))
(progn
(advice-add 'org-create-formula-image :around #'scimax-org-renumber-environment)
(put 'scimax-org-renumber-environment 'enabled t)
(message "Latex numbering enabled"))
(advice-remove 'org-create-formula-image #'scimax-org-renumber-environment)
(put 'scimax-org-renumber-environment 'enabled nil)
(message "Latex numbering disabled.")))
(advice-add 'org-create-formula-image :around #'scimax-org-renumber-environment)
(put 'scimax-org-renumber-environment 'enabled t))
#+END_SRC
**** Exporting (general)
#+BEGIN_SRC emacs-lisp
(after! org (setq org-export-headline-levels 5)) ; I like nesting
#+END_SRC
**** Exporting to HTML
***** Custom CSS/JS
There is a fantastic exporter config ([[https://github.com/fniessen/org-html-themes][fniessen/org-html-themes]]) which we can
setup to be used with all our org files. Since most of the syntax highlighting
colours from our [[Theme]] gets used, we benefit from customising the code block style.
#+NAME: orgHtmlStyle
#+BEGIN_SRC web :exports none :tangle no
<link rel='stylesheet' type='text/css' href='https://fniessen.github.io/org-html-themes/styles/readtheorg/css/htmlize.css'/>
<link rel='stylesheet' type='text/css' href='https://fniessen.github.io/org-html-themes/styles/readtheorg/css/readtheorg.css'/>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js'></script>
<script type='text/javascript' src='https://fniessen.github.io/org-html-themes/styles/lib/js/jquery.stickytableheaders.min.js'></script>
<script type='text/javascript' src='https://fniessen.github.io/org-html-themes/styles/readtheorg/js/readtheorg.js'></script>
<style>
pre.src {
background-color: var(--theme-bg);
color: var(--theme-fg);
scrollbar-color:#bbb6#9992;
scrollbar-width: thin;
margin: 0;
border: none;
}
div.org-src-container {
border-radius: 12px;
overflow: hidden;
margin-bottom: 24px;
margin-top: 1px;
border: 1px solid#e1e4e5;
}
pre.src::before {
background-color:#6666;
top: 8px;
border: none;
border-radius: 5px;
line-height: 1;
border: 2px solid var(--theme-bg);
opacity: 0;
transition: opacity 200ms;
}
pre.src:hover::before { opacity: 1; }
pre.src:active::before { opacity: 0; }
pre.example {
border-radius: 12px;
background: var(--theme-bg-alt);
color: var(--theme-fg);
}
code {
border-radius: 5px;
background:#e8e8e8;
font-size: 80%;
}
kbd {
display: inline-block;
padding: 3px 5px;
font: 80% SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;
line-height: normal;
line-height: 10px;
color:#444d56;
vertical-align: middle;
background-color:#fafbfc;
border: 1px solid#d1d5da;
border-radius: 3px;
box-shadow: inset 0 -1px 0#d1d5da;
}
table {
max-width: 100%;
overflow-x: auto;
display: block;
border-top: none;
}
a {
text-decoration: none;
background-image: linear-gradient(#d8dce9, #d8dce9);
background-position: 0% 100%;
background-repeat: no-repeat;
background-size: 0% 2px;
transition: background-size .3s;
}
\#table-of-contents a {
background-image: none;
}
a:hover, a:focus {
background-size: 100% 2px;
}
a[href^='#'] { font-variant-numeric: oldstyle-nums; }
a[href^='#']:visited { color:#3091d1; }
li .checkbox {
display: inline-block;
width: 0.9em;
height: 0.9em;
border-radius: 3px;
margin: 3px;
top: 4px;
position: relative;
}
2020-01-20 18:11:50 +00:00
li.on > .checkbox { background: var(--theme-green); box-shadow: 0 0 2px var(--theme-green); }
li.trans > .checkbox { background: var(--theme-orange); box-shadow: 0 0 2px var(--theme-orange); }
li.off > .checkbox { background: var(--theme-red); box-shadow: 0 0 2px var(--theme-red); }
li.on > .checkbox::after {
content: '';
height: 0.45em;
width: 0.225em;
-webkit-transform-origin: left top;
transform-origin: left top;
transform: scaleX(-1) rotate(135deg);
border-right: 2.8px solid#fff;
border-top: 2.8px solid#fff;
opacity: 0.9;
left: 0.10em;
top: 0.45em;
position: absolute;
}
2020-01-20 18:11:50 +00:00
li.trans > .checkbox::after {
content: '';
font-weight: bold;
font-size: 1.6em;
position: absolute;
top: 0.23em;
left: 0.09em;
width: 0.35em;
height: 0.12em;
background:#fff;
opacity: 0.9;
border-radius: 0.1em;
}
2020-01-20 18:11:50 +00:00
li.off > .checkbox::after {
content: '✖';
color:#fff;
opacity: 0.9;
position: relative;
top: -0.40rem;
left: 0.17em;
font-size: 0.75em;
}
span.timestamp {
color: #003280;
background: #647CFF44;
border-radius: 3px;
line-height: 1.25;
}
\#table-of-contents { overflow-y: auto; }
blockquote p { margin: 8px 0px 16px 0px; }
\#postamble .date { color: var(--theme-green); }
::-webkit-scrollbar { width: 10px; height: 8px; }
::-webkit-scrollbar-track { background:#9992; }
::-webkit-scrollbar-thumb { background:#ccc; border-radius: 10px; }
::-webkit-scrollbar-thumb:hover { background:#888; }
</style>
#+END_SRC
#+NAME: orgHtmlScript
We also want to make the background and foreground colours of the ~<pre>~ blocks
match out theme (they don't by default), so I scraped some code from ~emacs.stackexchange~.
#+BEGIN_SRC emacs-lisp :noweb yes
(defun my-org-inline-css-hook (exporter)
"Insert custom inline css to automatically set the
background of code to whatever theme I'm using's background"
(when (eq exporter 'html)
(setq
org-html-head-extra
(concat
org-html-head-extra
(format "
<style type=\"text/css\">
:root {
--theme-bg: %s;
--theme-bg-alt: %s;
--theme-base0: %s;
--theme-base1: %s;
--theme-base2: %s;
--theme-base3: %s;
--theme-base4: %s;
--theme-base5: %s;
--theme-base6: %s;
--theme-base7: %s;
--theme-base8: %s;
--theme-fg: %s;
--theme-fg-alt: %s;
--theme-grey: %s;
--theme-red: %s;
--theme-orange: %s;
--theme-green: %s;
--theme-teal: %s;
--theme-yellow: %s;
--theme-blue: %s;
--theme-dark-blue: %s;
--theme-magenta: %s;
--theme-violet: %s;
--theme-cyan: %s;
--theme-dark-cyan: %s;
}
</style>"
(doom-color 'bg)
(doom-color 'bg-alt)
(doom-color 'base0)
(doom-color 'base1)
(doom-color 'base2)
(doom-color 'base3)
(doom-color 'base4)
(doom-color 'base5)
(doom-color 'base6)
(doom-color 'base7)
(doom-color 'base8)
(doom-color 'fg)
(doom-color 'fg-alt)
(doom-color 'grey)
(doom-color 'red)
(doom-color 'orange)
(doom-color 'green)
(doom-color 'teal)
(doom-color 'yellow)
(doom-color 'blue)
(doom-color 'dark-blue)
(doom-color 'magenta)
(doom-color 'violet)
(doom-color 'cyan)
(doom-color 'dark-cyan))
"
<<orgHtmlStyle>>
"
))))
(add-hook 'org-export-before-processing-hook 'my-org-inline-css-hook)
#+END_SRC
***** Make verbatim different to code
Since we have =verbatim= and ~code~, let's use =verbatim= for key strokes.
#+BEGIN_SRC emacs-lisp
(setq org-html-text-markup-alist
'((bold . "<b>%s</b>")
(code . "<code>%s</code>")
(italic . "<i>%s</i>")
(strike-through . "<del>%s</del>")
(underline . "<span class=\"underline\">%s</span>")
(verbatim . "<kbd>%s</kbd>")))
#+END_SRC
***** Change checkbox type
We also want to use HTML checkboxes, however we want to get a bit fancier than default
#+BEGIN_SRC emacs-lisp
(after! org
(appendq! org-html-checkbox-types '((html-span .
((on . "<span class='checkbox'></span>")
(off . "<span class='checkbox'></span>")
(trans . "<span class='checkbox'></span>")))))
(setq org-html-checkbox-type 'html-span))
#+END_SRC
- [ ] I'm yet to do this
- [-] Work in progress
- [X] This is done
2020-02-03 05:01:57 +00:00
***** LaTeX Rendering
On the maths side of things, I consider ~dvisvgm~ to be a rather compelling
option. However this isn't sized very well at the moment.
#+BEGIN_SRC emacs-lisp
;; (setq-default org-html-with-latex `dvisvgm)
#+END_SRC
**** Exporting to LaTeX
I like automatically using spaced small caps for acronyms. For strings I want to
be unaffected lest's use ~;~ as a prefix to prevent the transformation --- i.e.
~;JFK~ (as one would want for two-letter geographic locations and names).
#+BEGIN_SRC emacs-lisp
;; TODO make this /only/ apply to text (i.e. not URL)
(after! org
(defun tec/org-export-latex-filter-acronym (text backend info)
(when (org-export-derived-backend-p backend 'latex)
(let ((case-fold-search nil))
(replace-regexp-in-string
";?\\b[A-Z][A-Z]+s?"
(lambda (all-caps-str)
; only \acr if str doesn't start with ";"
(if (equal (aref all-caps-str 0) 59) (substring all-caps-str 1)
(if (equal (aref all-caps-str (- (length all-caps-str) 1)) ?s)
(concat "\\textls*[70]{\\textsc{" (s-downcase (substring all-caps-str 0 -1)) "}\\protect\\scalebox{.91}[.84]{s}}")
(concat "\\textls*[70]{\\textsc{" (s-downcase all-caps-str) "}}"))))
text t t))))
(add-to-list 'org-export-filter-plain-text-functions
'tec/org-export-latex-filter-acronym)
(add-to-list 'org-export-filter-headline-functions
'tec/org-export-latex-filter-acronym))
#+END_SRC
Now for a few more adjustments.
#+BEGIN_SRC emacs-lisp
2020-03-23 03:01:56 +00:00
(after! ox-latex
(add-to-list 'org-latex-classes
'("fancy-article"
2020-03-23 03:01:56 +00:00
"\\documentclass{scrartcl}\n\
\\usepackage[T1]{fontenc}\n\
\\usepackage[osf,largesc,helvratio=0.9]{newpxtext}\n\
\\usepackage[scale=0.92]{sourcecodepro}\n\
\\usepackage[varbb]{newpxmath}\n\
\\usepackage[activate={true,nocompatibility},final,tracking=true,kerning=true,spacing=true,factor=2000]{microtype}\n\
\\usepackage{xcolor}\n\
\\setlength{\\parskip}{\\baselineskip}\n\
\\setlength{\\parindent}{0pt}"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
(add-to-list 'org-latex-classes
'("blank"
"[NO-DEFAULT-PACKAGES]
[NO-PACKAGES]
[EXTRA]"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
2020-02-29 11:09:06 +00:00
(add-to-list 'org-latex-classes
2020-02-26 11:05:41 +00:00
'("bmc-article"
"\\documentclass[article,code,maths]{bmc}
[NO-DEFAULT-PACKAGES]
[NO-PACKAGES]
[EXTRA]"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
2020-02-29 11:09:06 +00:00
(add-to-list 'org-latex-classes
2020-02-26 11:05:41 +00:00
'("bmc"
"\\documentclass[code,maths]{bmc}
[NO-DEFAULT-PACKAGES]
[NO-PACKAGES]
[EXTRA]"
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
2020-03-23 03:01:56 +00:00
(setq org-latex-default-class "fancy-article")
2020-02-29 11:09:06 +00:00
(add-to-list 'org-latex-packages-alist '("" "minted"))
(setq org-latex-listings 'minted)
2020-03-01 13:22:15 +00:00
(setq org-latex-minted-options
'(("frame" "lines")
("fontsize" "\\scriptsize")
("linenos" "")
("breakanywhere" "true")
("breakautoindent" "true")
("breaklines" "true")
("autogobble" "true")
("obeytabs" "true")
("python3" "true")
("breakbefore" "\\\\\\.+")
("breakafter" "\\,")
("style" "autumn")
("breaksymbol" "\\tiny\\ensuremath{\\hookrightarrow}")
("breakanywheresymbolpre" "\\,\\footnotesize\\ensuremath{{}_{\\rfloor}}")
("breakbeforesymbolpre" "\\,\\footnotesize\\ensuremath{{}_{\\rfloor}}")
("breakaftersymbolpre" "\\,\\footnotesize\\ensuremath{{}_{\\rfloor}}")))
2020-03-23 03:01:56 +00:00
(setq org-latex-hyperref-template "\\hypersetup{
pdfauthor={%a},
pdftitle={%t},
pdfkeywords={%k},
pdfsubject={%d},
pdfcreator={%c},
pdflang={%L},
breaklinks=true,
colorlinks=true,
linkcolor=,
urlcolor=blue!70!green,
citecolor=green!60!blue\n}
\\urlstyle{same}\n")
2020-02-29 11:09:06 +00:00
(setq org-latex-pdf-process
'("latexmk -shell-escape -interaction=nonstopmode -f -pdf -output-directory=%o %f")))
#+END_SRC
2020-01-20 18:15:09 +00:00
**** Exporting to Beamer
It's nice to use a different theme
#+BEGIN_SRC emacs-lisp
(setq org-beamer-theme "[progressbar=foot]metropolis")
#+END_SRC
Then customise it a bit
#+BEGIN_SRC emacs-lisp
#+END_SRC
And I think that it's natural to divide a presentation into sections, e.g.
Introduction, Overview... so let's set bump up the headline level that becomes a
frame from ~1~ to ~2~.
#+BEGIN_SRC emacs-lisp
(setq org-beamer-frame-level 2)
2020-01-20 18:17:20 +00:00
#+END_SRC
**** Exporting to GFM
We just need to load ~ox-gfm~ for org-mode documents
#+BEGIN_SRC emacs-lisp
(eval-after-load "org"
'(require 'ox-gfm nil t))
#+END_SRC
2020-01-09 18:02:54 +00:00
*** Babel
2020-02-09 03:06:01 +00:00
Doom lazy-loads babel languages, with is lovely.
We need to tell babel to use python3. Who uses python2 anymore anyway? And why
2020-01-20 18:17:00 +00:00
doesn't ~python~ refer to the latest version!?
#+BEGIN_SRC emacs-lisp
(setq org-babel-python-command "python3")
#+END_SRC
We also like autocompletion here
#+BEGIN_SRC emacs-lisp
(defun tec-org-python ()
(if (eq major-mode 'python-mode)
(progn (anaconda-mode t)
(company-mode t)))
)
(add-hook 'org-src-mode-hook 'tec-org-python)
#+END_SRC
2020-01-09 18:03:18 +00:00
*** ESS
We don't want ~R~ evaluation to hang the editor, hence
#+BEGIN_SRC emacs-lisp
(setq ess-eval-visibly 'nowait)
#+END_SRC
2020-01-09 18:03:42 +00:00
Syntax highlighting is nice, so let's turn all of that on
#+BEGIN_SRC emacs-lisp
(setq ess-R-font-lock-keywords '((ess-R-fl-keyword:keywords . t)
(ess-R-fl-keyword:constants . t)
(ess-R-fl-keyword:modifiers . t)
(ess-R-fl-keyword:fun-defs . t)
(ess-R-fl-keyword:assign-ops . t)
(ess-R-fl-keyword:%op% . t)
(ess-fl-keyword:fun-calls . t)
(ess-fl-keyword:numbers . t)
(ess-fl-keyword:operators . t)
(ess-fl-keyword:delimiters . t)
(ess-fl-keyword:= . t)
(ess-R-fl-keyword:F&T . t)))
#+END_SRC
** LaTeX
2020-03-23 03:12:19 +00:00
*** To-be-implemented ideas
- Paste image from clipboard
+ Determine first folder in ~graphicspath~ if applicable
+ Ask for file name
+ Use ~xclip~ to save file to graphics folder, or current directory (whichever applies)
#+BEGIN_SRC shell :eval no
command -v xclip >/dev/null 2>&1 || { echo >&1 "no xclip"; exit 1; }
if
xclip -selection clipboard -target image/png -o >/dev/null 2>&1
then
xclip -selection clipboard -target image/png -o >$1 2>/dev/null
echo $1
else
echo "no image"
fi
#+END_SRC
+ Insert figure, with filled in details as a result (activate =yasnippet= with
filename as variable maybe?)
2020-04-09 18:06:28 +00:00
*** Compilation
#+BEGIN_SRC emacs-lisp
(setq TeX-save-query nil
TeX-show-compilation t
TeX-command-extra-options "-shell-escape")
(after! latex
(add-to-list 'TeX-command-list '("XeLaTeX" "%`xelatex%(mode)%' %t" TeX-run-TeX nil t)))
#+END_SRC
*** Snippet value
For use in the new-file template, let's set out a nice preamble we may want to use.
#+NAME: latex-nice-preable
#+BEGIN_SRC latex :tangle no
\\usepackage[pdfa,unicode=true,hidelinks]{hyperref}
\\usepackage[dvipsnames,svgnames,table,hyperref]{xcolor}
\\renewcommand{\\UrlFont}{\\ttfamily\\small}
\\usepackage[a-2b]{pdfx} % why not be archival
\\usepackage[T1]{fontenc}
\\usepackage[osf,helvratio=0.9]{newpxtext} % pallatino
\\usepackage[scale=0.92]{sourcecodepro}
\\usepackage[varbb]{newpxmath}
\\usepackage{mathtools}
\\usepackage{amssymb}
\\usepackage[activate={true,nocompatibility},final,tracking=true,kerning=true,spacing=true,factor=2000]{microtype}
% microtype makes text look nicer
\\usepackage{graphicx} % include graphics
\\usepackage{grffile} % fix allowed graphicx filenames
\\usepackage{booktabs} % nice table rules
#+END_SRC
Then let's bind the content to a function, and define some nice helpers.
#+BEGIN_SRC emacs-lisp :noweb yes
(setq tec/yas-latex-template-preamble "
<<latex-nice-preable>>
")
(defun tec/yas-latex-get-class-choice ()
"Prompt user for LaTeX class choice"
(setq tec/yas-latex-class-choice (ivy-read "Select document class: " '("article" "scrartcl" "bmc") :def "bmc")))
(defun tec/yas-latex-preamble-if ()
"Based on class choice prompt for insertion of default preamble"
(if (equal tec/yas-latex-class-choice "bmc") 'nil
(eq (read-char-choice "Include default preamble? [Type y/n]" '(?y ?n)) ?y)))
#+END_SRC
2020-03-14 16:26:06 +00:00
*** Editor visuals
2020-03-23 03:06:55 +00:00
Once again, /all hail mixed pitch mode!/
#+BEGIN_SRC emacs-lisp
(add-hook 'LaTeX-mode-hook #'mixed-pitch-mode)
#+END_SRC
2020-03-14 16:26:06 +00:00
Let's enhance ~TeX-fold-math~ a bit
#+BEGIN_SRC emacs-lisp
2020-04-09 18:28:04 +00:00
(after! latex
(setcar (assoc "⋆" LaTeX-fold-math-spec-list) "★")) ;; make \star bigger
2020-03-14 16:26:06 +00:00
(setq TeX-fold-math-spec-list
2020-04-09 18:06:28 +00:00
`(;; missing/better symbols
2020-03-14 16:26:06 +00:00
("≤" ("le"))
("≥" ("ge"))
("≠" ("ne"))
;; conviniance shorts
("" ("left"))
("" ("right"))
;; private macros
("" ("RR"))
("" ("NN"))
("" ("ZZ"))
("" ("QQ"))
("" ("CC"))
("" ("PP"))
("" ("HH"))
("𝔼" ("EE"))
("𝑑" ("dd"))
2020-03-16 13:28:37 +00:00
;; known commands
2020-03-14 16:26:06 +00:00
("" ("phantom"))
2020-03-30 05:43:51 +00:00
("❪{1}{2}❫" ("frac"))
2020-04-09 18:06:28 +00:00
(,(lambda (arg) (concat "√" (TeX-fold-parenthesize-as-neccesary arg))) ("sqrt"))
(,(lambda (arg) (concat "⭡" (TeX-fold-parenthesize-as-neccesary arg))) ("vec"))
2020-03-14 16:26:06 +00:00
("{1}" ("text"))
2020-03-16 13:28:37 +00:00
;; private commands
2020-03-14 16:26:06 +00:00
("|{1}|" ("abs"))
("‖{1}‖" ("norm"))
("⌊{1}⌋" ("floor"))
("⌈{1}⌉" ("ceil"))
("⌊{1}⌉" ("round"))
2020-03-30 05:43:51 +00:00
("𝑑{1}/𝑑{2}" ("dv"))
("∂{1}/∂{2}" ("pdv"))
;; fancification
("{1}" ("mathrm"))
2020-04-09 18:06:28 +00:00
(,(lambda (word) (string-offset-roman-chars 119743 word)) ("mathbf"))
(,(lambda (word) (string-offset-roman-chars 119951 word)) ("mathcal"))
(,(lambda (word) (string-offset-roman-chars 120003 word)) ("mathfrak"))
(,(lambda (word) (string-offset-roman-chars 120055 word)) ("mathbb"))
(,(lambda (word) (string-offset-roman-chars 120159 word)) ("mathsf"))
(,(lambda (word) (string-offset-roman-chars 120367 word)) ("mathtt"))
2020-03-16 13:28:37 +00:00
)
TeX-fold-macro-spec-list
'(
;; as the defaults
("[f]" ("footnote" "marginpar"))
("[c]" ("cite"))
("[l]" ("label"))
("[r]" ("ref" "pageref" "eqref"))
("[i]" ("index" "glossary"))
("..." ("dots"))
("{1}" ("emph" "textit" "textsl" "textmd" "textrm" "textsf" "texttt"
"textbf" "textsc" "textup"))
;; tweaked defaults
("©" ("copyright"))
("®" ("textregistered"))
("™" ("texttrademark"))
("[1]:||►" ("item"))
("❡❡ {1}" ("part" "part*"))
("❡ {1}" ("chapter" "chapter*"))
("§ {1}" ("section" "section*"))
("§§ {1}" ("subsection" "subsection*"))
("§§§ {1}" ("subsubsection" "subsubsection*"))
("¶ {1}" ("paragraph" "paragraph*"))
("¶¶ {1}" ("subparagraph" "subparagraph*"))
;; extra
("⬖ {1}" ("begin"))
("⬗ {1}" ("end"))
2020-03-14 16:26:06 +00:00
))
2020-03-30 05:43:51 +00:00
(defun string-offset-roman-chars (offset word)
"Shift the codepoint of each charachter in WORD by OFFSET with an extra -6 shift if the letter is lowercase"
(apply 'string
(mapcar (lambda (c) (+ (if (>= c 97) (- c 6) c) offset)) word)))
2020-04-09 18:06:28 +00:00
(defun TeX-fold-parenthesize-as-neccesary (tokens &optional suppress-left suppress-right)
"Add ❪ ❫ parenthesis as if multiple LaTeX tokens appear to be present"
(if (string-match-p "^\\\\?\\w+$" tokens) tokens
(concat (if suppress-left "" "❪")
tokens
(if suppress-right "" "❫"))))
2020-03-14 16:26:06 +00:00
#+END_SRC
2020-03-15 16:19:17 +00:00
Some local keybindings to make life a bit easier
#+BEGIN_SRC emacs-lisp
(after! tex
(map!
:map LaTeX-mode-map
:ei [C-return] #'LaTeX-insert-item
;; normal stuff here
:localleader
:desc "View" "v" #'TeX-view)
2020-03-15 16:19:17 +00:00
(setq TeX-electric-math '("\\(" . "")))
#+END_SRC
2020-03-14 16:26:06 +00:00
Maths deliminators can be de-emphasised a bit
#+BEGIN_SRC emacs-lisp
;; Making \( \) less visible
(defface unimportant-latex-face
'((t
2020-03-15 16:19:17 +00:00
:inherit font-lock-comment-face :family "Overpass" :weight light))
2020-03-14 16:26:06 +00:00
"Face used to make \\(\\), \\[\\] less visible."
:group 'LaTeX-math)
(font-lock-add-keywords
'latex-mode
`((,(rx (and "\\" (any "()[]"))) 0 'unimportant-latex-face prepend))
'end)
(font-lock-add-keywords
'latex-mode
`((,"\\\\[[:word:]]+" 0 'font-lock-keyword-face prepend))
'end)
#+END_SRC
And enable shell escape for the preview
#+BEGIN_SRC emacs-lisp
(setq preview-LaTeX-command '("%`%l \"\\nonstopmode\\nofiles\
\\PassOptionsToPackage{" ("," . preview-required-option-list) "}{preview}\
\\AtBeginDocument{\\ifx\\ifPreview\\undefined"
preview-default-preamble "\\fi}\"%' \"\\detokenize{\" %t \"}\""))
#+END_SRC
2020-03-15 16:19:17 +00:00
*** CDLaTeX
The symbols and modifies are very nice by default, but could do with a bit of
fleshing out. Let's change the prefix to a key which is similarly rarely used,
but more convinient, like =;=.
#+BEGIN_SRC emacs-lisp
(after! cdlatex
(setq ;; cdlatex-math-symbol-prefix ?\; ;; doesn't work at the moment :(
cdlatex-math-symbol-alist
'( ;; adding missing functions to 3rd level symbols
(?_ ("\\downarrow" "" "\\inf"))
(?^ ("\\uparrow" "" "\\sup"))
(?k ("\\kappa" "" "\\ker"))
(?m ("\\mu" "" "\\lim"))
(?c ("" "\\circ" "\\cos"))
(?d ("\\delta" "\\partial" "\\dim"))
(?D ("\\Delta" "\\nabla" "\\deg"))
;; no idea why \Phi isnt on 'F' in first place, \phi is on 'f'.
(?F ("\\Phi"))
;; now just conveniance
(?. ("\\cdot" "\\dots"))
(?: ("\\vdots" "\\ddots"))
(?* ("\\times" "\\star" "\\ast")))
cdlatex-math-modify-alist
'( ;; my own stuff
(?B "\\mathbb" nil t nil nil)
(?a "\\abs" nil t nil nil))))
2020-03-15 16:19:17 +00:00
#+END_SRC
*** SyncTeX
#+BEGIN_SRC emacs-lisp
(after! tex
(add-to-list 'TeX-view-program-list '("Evince" "evince %o"))
(add-to-list 'TeX-view-program-selection '(output-pdf "Evince")))
#+END_SRC
2020-01-09 18:03:42 +00:00
** R
*** Editor Visuals
#+BEGIN_SRC emacs-lisp
(after! ess-r-mode
(appendq! +pretty-code-symbols
2020-02-03 05:03:39 +00:00
'(:assign "⟵"
:multiply "×"))
2020-01-09 18:03:42 +00:00
(set-pretty-symbols! 'ess-r-mode
;; Functional
:def "function"
;; Types
:null "NULL"
:true "TRUE"
:false "FALSE"
:int "int"
:floar "float"
:bool "bool"
;; Flow
:not "!"
:and "&&" :or "||"
:for "for"
:in "%in%"
:return "return"
;; Other
2020-02-03 05:03:39 +00:00
:assign "<-"
:multiply "%*%"))
2020-01-09 18:03:42 +00:00
#+END_SRC
2020-02-03 05:04:00 +00:00
** hledger
~ledger-mode~ is great and all, but ~hledger~ seems to be more actively maintained.
For example, from 2018--2020, the most prolific contributor to ~ledger~ produced
31 commits. For ~hledger~ this statistic is 1800 commits. In addition, over the
last decade, ~ledger~ seems to have lost steam, while ~hledger~ seems as actively
developed as ever. From this basic comparison ~hledger~ looks to have a more
promising outlook. It also has a few extra nicities that ~ledger~ doesn't, but is
2020-02-17 08:16:56 +00:00
a little slower (~haskell~ vs. ~c++~).
2020-02-03 05:04:00 +00:00
Since this uses the same format, and ~ledger-mode~ is well integrated into emacs,
2020-02-17 08:16:56 +00:00
and produced by John Wiegley --- author of ~ledger~ and current Emacs maintainer
2020-02-03 05:04:00 +00:00
--- using this seems like a good idea. Thankfully we can, with a little modification.
#+BEGIN_SRC emacs-lisp
(setq ledger-mode-should-check-version nil
ledger-report-links-in-register nil
ledger-binary-path "hledger")
#+END_SRC
** Markdown
Let's use mixed pitch, because it's great
#+BEGIN_SRC emacs-lisp
(add-hook! (gfm-mode markdown-mode) #'mixed-pitch-mode)
#+END_SRC
Most of the time when I write markdown, it's going into some app/website which
will do it's own line wrapping, hence we /only/ want to use visual line wrapping. No hard stuff.
#+BEGIN_SRC emacs-lisp
(add-hook! (gfm-mode markdown-mode) #'visual-line-mode #'turn-off-auto-fill)
#+END_SRC
2020-02-03 05:04:00 +00:00
** Beancount
2020-02-14 17:25:59 +00:00
The [[https://bitbucket.org/blais/beancount/src/tip/editors/emacs/beancount.el][beancount package]] online has been put into ~./lisp~, we just need to load and
enable it for ~.beancount~ files.
2020-02-03 05:04:00 +00:00
#+BEGIN_SRC emacs-lisp
(use-package! beancount
2020-03-18 16:49:23 +00:00
:load-path "~/.config/doom/lisp"
:mode ("\\.beancount\\'" . beancount-mode)
:config
(setq beancount-electric-currency t)
2020-03-18 16:49:23 +00:00
(defun beancount-bal ()
"Run bean-report bal."
(interactive)
(let ((compilation-read-command nil))
(beancount--run "bean-report"
(file-relative-name buffer-file-name) "bal")))
;; TODO make the following *work*
:bind (:map beancount-mode-map ("S-RET" . #'beancount-align-to-previous-number)))
2020-02-03 05:04:00 +00:00
#+END_SRC
# Local variables:
# eval: (add-hook 'after-save-hook 'org-html-export-to-html t t)
# end: