52 KiB
Phundrak’s Spacemacs User Configuration
- User Initialization
- User Configuration
User Initialization
While Emacs and especially Spacemacs loads, I want it to initialize some elements and load some packages. First of all, I want it to load my private Emacs config file:
(load "~/.emacs.d/private/private_emacs.el")
Then, I want a couple of requires:
(require 'org-id)
(require 'package)
(require 'ox-latex)
(require 'ox-publish)
I also want to load what’s in icons-in-terminal
so I can use them in various
packages in Emacs:
(add-to-list 'load-path "~/.local/share/icons-in-terminal/")
I would also like to enable the setup of flycheck for Rust when Flycheck is loaded:
(add-hook 'flycheck-mode-hook #'flycheck-rust-setup)
By default, Flyspell should be disabled and only enabled manually.
(flyspell-mode 0)
Finally, here is a quick workaround for Tramp, sometimes it cannot connect to my hosts if I don’t have this code snippet.
(setq tramp-ssh-controlmaster-options
"-o ControlMaster=auto -o ControlPath='tramp.%%C' -o ControlPersist=no")
User Configuration
ASM configuration
The first thing I will set with my ASM configuration is where the reference PDF is located.
(setq x86-lookup-pdf "~/Documents/code/asm/Intelx86/325383-sdm-vol-2abcd.pdf")
I will also modify what the comment character is, from a ;
to a #
:
(setq asm-comment-char ?\#)
C/C++
As the C/C++ syntax is checked by flycheck, let’s make sure we are using the latest standard available, that is C++17 and C17, from Clang.
(add-hook 'c-mode-hook
(lambda ()
(setq flycheck-clang-language-standard "c17")))
(add-hook 'c++-mode-hook
(lambda ()
(setq flycheck-clang-language-standard "c++17")))
Custom functions
In this section, I will put my various custom functions that do not fit in other sections and which are more oriented towards general usage throughout Emacs and in Elisp code.
Almost all of my code snippets will be prefixed by either my name or the name of the package or layer they are part of, unless they are an explicit overwrite of a function that already exists.
phundrak/fill-paragraph
This function was created in order to bind to another keyboard shortcut the
already existing C-u M-q
which I cannot type with evil-mode unless I’m in
insert mode.
(defun phundrak/fill-paragraph ()
(interactive)
(let* ((current-prefix-arg 4))
(call-interactively 'fill-paragraph)))
terminal-here-default-terminal-command
This function is actually an overwrite of the default one which apparently
does not work on my machine. This function is called by
terminal-here-launch
and spawns an external terminal emulator in the
directory emacs was in when the terminal was invoked. I simply point out to
this function the name of my terminal emulator. Here is the code:
(defun terminal-here-default-terminal-command (_dir)
'("st"))
Dart configuration
For Dart, I mainly declared some custom shortcuts bound to dart-mode
related to flutter, so nothing too exciting here. Some prefix are declared in
order to avoid the shortcuts in helm to show up as just custom
.
(spacemacs/declare-prefix-for-mode 'dart-mode "o" "user-defined")
(spacemacs/declare-prefix-for-mode 'dart-mode "of" "flutter")
(spacemacs/declare-prefix-for-mode 'dart-mode "ofr" "flutter-run")
Now, for the shortcuts themselves:
(spacemacs/set-leader-keys-for-major-mode 'dart-mode
"ofH" 'flutter-hot-restart
"ofh" 'flutter-hot-reload
"ofq" 'flutter-quit
"ofr" (lambda () (interactive) (flutter-run "-v"))
"ofs" 'flutter-screenshot)
Dired
When it comes to dired, I chose do modify some elements on how things are sorted and shown, but there isn’t much configuration. First, I want to always copy folders in a recursive way, no questions asked.
(setq dired-recursive-copies 'always)
Also, when I have two Dired buffers opened side by side, I generally want them to interact, for example if I want to move something around. So, let’s tell Emacs that:
(setq dired-dwim-target t)
Finally, let’s tell Dired how to sort the elements to be displayed: directories first, non-hidden first.
(setq dired-listing-switches "-ahl --group-directories-first")
By the way, let’s enable org-download
when we are in a Dired buffer:
(add-hook 'dired-mode-hook 'org-download-enable)
Emacs Lisp
Here will be stored my configuration directly related to Emacs Lisp, including some functions or default modes.
Enable eldoc-mode
by default
By default, if some Elisp code is opened, I want to enable eldoc-mode
so I
can easily get some documentation on the symbols in the source code. This is
done via the use of hooks.
(add-hook 'prog-mode-hook 'eldoc-mode)
phundrak/write-to-buffer
I was very surprised when I discovered no such function exists in Elisp. This function basically writes a string into a buffer, and optionally switches the user to the buffer. Here is the code for that function:
(defun write-to-buffer (input-string outputbuf &optional switchbuf)
"Writes `input-string' to the specified `output-buffer'. If
`switch-buffer' is non-nil, the active buffer will switch to the
output buffer; otherwise, it will take the user back to their
initial buffer. Works with `input-string' as a string or a list
of strings."
(let ((oldbuf (current-buffer)))
(switch-to-buffer outputbuf)
(cond ((char-or-string-p input-string) (insert input-string))
((listp input-string) (dolist (elem input-string)
(insert (format "%s\n" elem)))))
(if switchbuf
(switch-to-buffer oldbuf))))
Eshell
Eshell is a built-in shell available from Emacs which I use almost as often as Fish. Some adjustments are necessary for making this shell usable for me.
Environment variables
Some environment variables need to be correctly set so Eshell can correctly
work. The first environment variable to be set is the PATH
, as I have a
couple of directories where executables are located. Let’s add them to our
path.
(setenv "PATH"
(concat
(getenv "HOME") "/.pub-cache/bin"
":" (getenv "HOME") "/.local/bin"
":" (getenv "HOME") "/go/bin"
":" (getenv "HOME") "/.cargo/bin"
":" (getenv "HOME") "/.gem/ruby/2.6.0/bin"
":" (getenv "PATH")))
I would also like to set two environment variables related to Dart
development: the DART_SDK
and ANDROID_HOME
variables.
(setenv "DART_SDK" "/opt/dart-sdk/bin")
(setenv "ANDROID_HOME" (concat (getenv "HOME") "/Android/Sdk/"))
Finally, I’d like to add a custom directory to the PKG_CONFIG_PATH
:
(setenv "PKG_CONFIG_PATH" (concat
"/usr/local/lib/pkgconfig/" ":"
(getenv "PKG_CONFIG_PATH")))
Custom functions
When I’m in Eshell, sometimes I wish to open multiple files at once in
Emacs. For this, when I have several arguments for find-file
, I want to be
able to open them all at once. Let’s modify find-file
like so:
(defadvice find-file (around find-files activate)
"Also find all files within a list of files. This even works recursively."
(if (listp filename)
(loop for f in filename do (find-file f wildcards))
ad-do-it))
I also want to be able to have multiple instances of Eshell opened at once.
For that, I declared the function eshell-new
that does exactly that.
(defun eshell-new()
"Open a new instance of eshell."
(interactive)
(eshell 'N))
Aliases
Just like most shells, it is possible to declare in Eshell aliases. First, I
would like to be able to use open
to open files in Emacs:
(defalias 'open 'find-file)
I also have openo
which allows me to perform the same action, but in
another window:
(defalias 'openo 'find-file-other-window)
The function yes-or-no-p
is also aliased to y-or-n-p
so I only have to
answer by y
or n
instead of typing yes
or no
.
(defalias 'yes-or-no-p 'y-or-n-p)
For some ease of use, I’ll also declare list-buffers
as an alias of
ibuffer
.
(defalias 'list-buffers 'ibuffer)
Visual commands
With Eshell, some commands don’t work very well, especially commands that create a TUI. So, let’s declare them as visual commands or subcommands:
(setq eshell-visual-commands
'("fish" "zsh" "bash" "tmux" "htop" "top" "vim" "bat" "nano")
eshell-visual-subcommands
'("git" "log" "l" "diff" "show"))
Eshell theme
As with most shells, again, it is possible to customize the appearance of the Eshell prompt. First, we need to declare a macro so we can set a face with properties:
(defmacro with-face (str &rest properties)
`(propertize ,str 'face (list ,@properties)))
Now, let’s declare a function that will abbreviate the current pwd
fish-shell style.
(defun eshell/abbr-pwd ()
(let ((home (getenv "HOME"))
(path (eshell/pwd)))
(cond
((string-equal home path) "~")
((f-ancestor-of? home path) (concat "~/" (f-relative path home)))
(path))))
Now, let’s declare our prompt:
(defun eshell/my-prompt ()
(let ((header-bg "#161616"))
(concat
(with-face (eshell/abbr-pwd) :foreground "#008700")
"\n"
(if (= (user-uid) 0)
(with-face "➜" :foreground "red")
(with-face "➜" :foreground "#2345ba"))
" ")))
Now, let’s declare our prompt regexp and our prompt functions:
(setq eshell-prompt-regexp "^[^#$\n]*[#$] "
eshell-prompt-function 'eshell/my-prompt)
Finally, let’s declare the theme of our shell:
(eshell-git-prompt-use-theme 'powerline)
File extensions
Sometimes, Emacs doesn’t recognize or misrecognizes some extensions, resulting in a wrong mode set for said file. Let’s fix that by associating the extension with the desired mode:
(dolist (e '(("xml" . web-mode)
("xinp" . web-mode)
("aiml" . web-mode)
("C" . c++-mode)
("dconf" . conf-mode)
("yy" . bison-mode)
("ll" . flex-mode)
("s" . asm-mode)
("pl" . prolog-mode)
("l" . scheme-mode)
("vs" . glsl-mode)
("fs" . glsl-mode)))
(push (cons (concat "\\."
(car e)
"\\'") (cdr e))
auto-mode-alist))
We also have a couple of extensions which should all be in conf-unix-mode
,
let’s indicate that to Emacs:
(dolist (e '("service" "timer" "target" "mount" "automount"
"slice" "socket" "path" "netdev" "network"
"link"))
(push (cons (concat "\\." e "\\'") 'conf-unix-mode)
auto-mode-alist))
Gnus
Here comes my Gnus configuration. Gnus is an email client I use daily to read, manage, answer to and forward messages I receive by email.
Shortcuts
Some shortcuts needed to be redefined in order for Evil to work well with Gnus. Here is first the declaration of a prefix:
(spacemacs/declare-prefix "og" "gnus")
And here are said shortcuts. As described above in the shortcuts chapter,
these Spacemacs shortcuts are invoked with the SPC
leader key.
(spacemacs/set-leader-keys
"ogD" 'turn-on-gnus-dired-mode
"ogd" 'gnus-summary-delete-article
"ogf" 'gnus-summary-mail-forward
"ogo" 'my-gnus-group-list-subscribed-groups
"ogr" 'gnus-summary-insert-new-articles
"ogs" 'message-send-and-exit)
Hooks
To sort by topics my different mailboxes and folders, I use the
gnus-topic-mode
minor mode. To get it active by default, I use the
following hook to activate it:
(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)
Mail account configuration
This section will be tangled in ~/.gnus.el
.
I only use one email account with Gnus: lucien@phundrak.com
. Here is how I
configured it:
(setq gnus-secondary-select-methods '((nnimap "lucien@phundrak.com"
(nnimap-address "mail.phundrak.com")
(nnimap-server-port 143)
(nnimap-stream starttls)))
message-send-mail-function 'smtpmail-send-it
smtpmail-smtp-server "mail.phundrak.com"
smtpmail-stream-type 'starttls
smtpmail-smtp-service 587
gnus-message-archive-method '(nnimap "mail.phundrak.com")
gnus-message-archive-group "Sent"
nnml-directory "~/Mails"
message-directory "~/Mails"
gnus-fetch-old-headers 'some
mm-discouraged-alternatives '("text/html" "text/richtext"))
General options
This section will be tangled in ~/.gnus.el
.
I want to use at one point the Emacs Application Framework which is set to be able one day to render Gnus emails, but for now I am using w3m to render HTML emails I receive.
(setq mm-text-html-renderer 'w3m)
I also want Gnus to use the cache in case I need to navigate my emails offline:
(setq gnus-use-cache t)
Let’s set a quick organization of the Gnus folders, the format in which sent messages should be saved, and the typology of Gnus’ topics:
(eval-after-load 'gnus-topic
'(progn
(setq gnus-message-archive-group '((format-time-string "sent.%Y")))
(setq gnus-topic-topology '(("Gnus" visible)
(("lucien@phundrak.com" visible nil nil))))
(setq gnus-topic-alist '(("lucien@phundrak.com" ; the key of the topic
"nnimap+lucien@phundrak.com:INBOX"
"nnimap+lucien@phundrak.com:Sent"
"nnimap+lucien@phundrak.com:Drafts")
("Gnus")))))
Visual configuration
This section will be tangled in ~/.gnus.el
.
I get it that it used to be a good option with 4/3 screens, but frankly opening an email at the bottom of the frame instead of the side of the frame does not look good anymore. So, let’s fix that:
(gnus-add-configuration
'(article (horizontal 1.0 (summary .4 point) (article 1.0))))
LSP
When it comes to the LSP layer, there are some options which are not enabled
by default that I want to use, especially some modes I want to take advantage
of. This is why I enable first the lsp-treemacs-sync-mode
so treemacs is
LSP aware:
(lsp-treemacs-sync-mode 1)
I also enable some layers related to dap
, the Debug Adapter Protocol, which
works really nicely with LSP. Let’s enable Dap’s modes:
(dap-mode 1)
(dap-ui-mode 1)
(dap-tooltip-mode 1)
Finally, I also want the documentation tooltip to show up when the cursor is above a documented piece of code or symbol. Let’s enable that too:
(tooltip-mode 1)
Miscellaneous
I have a lot of variables that need to be set but don’t fall in any other category, so I’ll collect them here.
I have this regexp for detecting paragraphs.
(setq paragraph-start "\f\\|[ \t]*$\\|[ \t]*[-+*] ")
Evil
As a user of Evil, I’m sometimes pissed when I accidentally press C-u
and
it gets me to the top of the document. So, let’s disable it:
(setq evil-want-C-u-scroll nil)
Default modes
Some buffers sometimes won’t have a default mode at all, such as the
*scratch*
buffer. In any vanilla configuration, they will then default to
text-mode
. I personally prefer org-mode
to be my default mode, so let’s
set it so!
(setq edit-server-default-major-mode 'org-mode)
I also want to have by default some aggressive indentation in my source files. Let’s enable that:
(global-aggressive-indent-mode 1)
However, I do not wish to see it activated for Dart mode, so let’s exclude it:
(add-to-list 'aggressive-indent-excluded-modes 'dart-mode)
Hooks
I also have some hooks I use for enabling some major and minor modes. The first one here allows the execution of the deletion of trailing space each time I save a file.
(add-hook 'before-save-hook 'delete-trailing-whitespace)
I also want to always be in visual-line-mode
so Emacs soft-wraps lines
that are too long for the buffer they are displayed in.
(add-hook 'prog-mode-hook 'visual-line-mode)
I also want for some non-programming modes to enable a hard-limit in terms
of how many characters can fit on one line. The modes that benefit from that
are message-mode
, org-mode
, text-mode
and markdown-mode
.
(mapc (lambda (x)
(add-hook x 'auto-fill-mode)
(add-hook x 'visual-line-mode))
'(message-mode-hook
org-mode-hook
text-mode-hook
markdown-mode-hook))
Pinentry
Pinentry should use the loopback
mode when communicating with GnuPG. Let’s
set it so:
(setq epa-pinentry-mode 'loopback)
Prettified symbols
Just because it is pleasing to the eye, some symbols in source code get prettified into simpler symbols. Here is the list of symbols that are to be prettified. You can see in the corresponding comment what symbol will be displayed.
(setq prettify-symbols-alist '(("lambda" . 955) ; λ
("->" . 8594) ; →
("<->" . 8596) ; ↔
("<-" . 8592) ; ←
("=>" . 8658) ; ⇒
("<=>" . 8860) ; ⇔
("<=" . 8656) ; ⇐
("mapc" . 8614) ; ↦
("map" . 8614) ; ↦
(">>" . 187) ; »
("<<" . 171) ; «
))
Twittering mode
For twittering-mode
, a Twitter major mode for Emacs, I want to encrypt my
data using a master password, which I do thanks to this option:
(setq twittering-use-master-password t)
Wttr.in cities
Thanks to the wttrin package, I can get the weather forecast in Emacs for a couple of cities. I just need to specify them to Emacs like so:
(setq wttrin-default-cities '("Aubervilliers" "Paris" "Lyon" "Nonières"
"Saint Agrève"))
Nov-mode
nov-mode
is the mode used in the Epub reader. Here I will write a little
function that I will call through a hook each time I’m opening a new EPUB
file.
(defun my-nov-font-setup ()
(face-remap-add-relative 'variable-pitch :family "Charis SIL"
:size 16
:height 1.0))
Let’s bind this function to the nov-mode
hook. By the way, we’ll also
enable the visual-line-mode
here, just in case.
(mapc (lambda (mode)
(add-hook 'nov-mode-hook mode))
'('my-nov-font-setup 'visual-line-mode))
Let’s also set the maximum length of the lines in nov-mode
:
(setq nov-text-width 80)
Python
Emacs throws me an error about the python interpreter, let’s silence it:
(setq python-shell-completion-native-disabled-interpreters '("python"))
Org-mode
Org-mode is probably one of the best if not the best Emacs feature I have ever discovered. It is awesome for writing documents, regardless of the format you need it to be exported to, for agenda management, and for literary programming, such as with this document.
(with-eval-after-load 'org
;; configuration goes here
)
Custom org-mode functions
We begin with a couple of custom functions that I use in my org-mode files.
Custom and unique headings ID
The first ones are dedicated to provide org-mode headings a fixed and unique ID that won’t change over time. This code was taken from https://writequit.org/articles/emacs-org-mode-generate-ids.html. The first function’s job is to create these unique IDs
(defun eos/org-id-new (&optional prefix)
"Create a new globally unique ID.
An ID consists of two parts separated by a colon:
- a prefix
- a unique part that will be created according to
`org-id-method'.
PREFIX can specify the prefix, the default is given by the
variable `org-id-prefix'. However, if PREFIX is the symbol
`none', don't use any prefix even if `org-id-prefix' specifies
one.
So a typical ID could look like \"Org-4nd91V40HI\"."
(let* ((prefix (if (eq prefix 'none)
""
(concat (or prefix org-id-prefix)
"-"))) unique)
(if (equal prefix "-")
(setq prefix ""))
(cond
((memq org-id-method
'(uuidgen uuid))
(setq unique (org-trim (shell-command-to-string org-id-uuid-program)))
(unless (org-uuidgen-p unique)
(setq unique (org-id-uuid))))
((eq org-id-method 'org)
(let* ((etime (org-reverse-string (org-id-time-to-b36)))
(postfix (if org-id-include-domain
(progn
(require 'message)
(concat "@"
(message-make-fqdn))))))
(setq unique (concat etime postfix))))
(t (error "Invalid `org-id-method'")))
(concat prefix unique)))
Now, let’s see the function that will be used to get the custom id of a heading at point. If the function does not detect any custom ID, then one should be created and inserted.
(defun eos/org-custom-id-get (&optional pom create prefix)
"Get the CUSTOM_ID property of the entry at point-or-marker POM.
If POM is nil, refer to the entry at point. If the entry does
not have an CUSTOM_ID, the function returns nil. However, when
CREATE is non nil, create a CUSTOM_ID if none is present
already. PREFIX will be passed through to `eos/org-id-new'. In
any case, the CUSTOM_ID of the entry is returned."
(interactive)
(org-with-point-at pom
(let ((id (org-entry-get nil "CUSTOM_ID")))
(cond
((and id
(stringp id)
(string-match "\\S-" id)) id)
(create (setq id (eos/org-id-new (concat prefix "h")))
(org-entry-put pom "CUSTOM_ID" id)
(org-id-add-location id
(buffer-file-name (buffer-base-buffer)))
id)))))
Finally, this is the function that gets called on file saves. If the
function detects auto-id:t
among the org options in the #+OPTIONS:
header, then the above function is called.
(defun eos/org-add-ids-to-headlines-in-file ()
"Add CUSTOM_ID properties to all headlines in the current
file which do not already have one. Only adds ids if the
`auto-id' option is set to `t' in the file somewhere. ie,
,#+OPTIONS: auto-id:t"
(interactive)
(save-excursion
(widen)
(goto-char (point-min))
(when (re-search-forward "^#\\+OPTIONS:.*auto-id:t"
(point-max)
t)
(org-map-entries (lambda ()
(eos/org-custom-id-get (point)
'create))))))
Let’s add a hook to the above function so it is called automatically on save, and only in read-write functions.
(add-hook 'org-mode-hook
(lambda ()
(add-hook 'before-save-hook
(lambda ()
(when (and (eq major-mode 'org-mode)
(eq buffer-read-only nil))
(eos/org-add-ids-to-headlines-in-file))))))
Org babel languages
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:
(org-babel-do-load-languages
'org-babel-load-languages
'((C . t)
(dot . t)
(emacs-lisp . t)
(gnuplot . t)
(latex . t)
(makefile . t)
(python . t)
(R . t)
(sass . t)
(scheme . t)
(shell . t)))
Scheme requires a default implementation for geiser:
(setq geiser-default-implementation 'racket)
By the way, I wish to see source code behave the same way in the source blocks as in their own major mode. Let’s tell Emacs so:
(setq org-src-tab-acts-natively t)
Org variables
User information
Some variables about myself need to be set so Org-mode knows what information to include in exported files.
(setq user-full-name "Lucien Cartier-Tilet"
user-real-login-name "Lucien Cartier-Tilet"
user-login-name "phundrak"
user-mail-address "lucien@phundrak.com")
Visual settings
Visually, I prefer to hide the markers of macros, so let’s do that:
(setq org-hide-macro-markers t)
Miscellaneous
When creating a link to an Org flie, I want to create an ID only if the link is created interactively, and only if there is no custom ID already created.
(setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)
Org files exports
When it comes to exports, I want the LaTeX and PDF exports to be done with XeLaTeX only. This implies the modification of the following variable:
(setq org-latex-compiler "xelatex")
I also want to get by default minted
for LaTeX listings so I can have
syntax highlights:
(setq org-latex-listings 'minted)
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. I also added two default
packages, minted
and xeCJK
for syntax highlighting and Japanese (and
additionally Chinese and Korean) support.
(setq org-latex-default-packages-alist '(("" "graphicx" t)
("T1" "fontspec" t ("pdflatex"))
("" "longtable" nil)
("" "wrapfig" nil)
("" "rotating" nil)
("normalem" "ulem" t)
("" "amsmath" t)
("" "textcomp" t)
("" "amssymb" t)
("" "capt-of" nil)
("" "minted" nil)
("" "xeCJK" nil)
("" "hyperref" nil)))
By the way, reference links in LaTeX should be written in this format:
(setq org-export-latex-hyperref-format "\\ref{%s}")
When it comes to the export itself, the latex file needs to be processed several times through XeLaTeX.
(setq org-latex-pdf-process
'("xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
For Reveal.JS exports, I need to set where to find the framework by default:
(setq org-reveal-root "file:///home/phundrak/fromGIT/reveal.js")
I also 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. So, let’s disable it:
(setq org-use-sub-superscripts (quote {}))
On HTML exports, Org-mode tries to include a validation link for the exported HTML. Let’s disable that since I never use it.
(setq org-html-validation-link nil)
Custom LaTeX formats
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:
'("conlang"
"\\documentclass{book}"
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
And here is the declaration of the beamer
class:
`("beamer"
,(concat "\\documentclass[presentation]{beamer}\n"
"[DEFAULT-PACKAGES]"
"[PACKAGES]"
"[EXTRA]\n")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
Both these classes have to be added to org-latex-classes
like so:
(eval-after-load "ox-latex"
;; update the list of LaTeX classes and associated header (encoding, etc.)
;; and structure
'(add-to-list 'org-latex-classes
<<org-latex-class-conlang>>
<<org-latex-class-beamer>>
))
Org agenda
One awesome feature of Org mode is the agenda. By default, my agendas are
stored in ~/org
.
(setq org-agenda-files (list "~/org"))
I also have a custom command in Org agenda to mark some tasks as daily
tasks, with the :DAILY:
tag:
(setq org-agenda-custom-commands '(("h" "Daily habits"
((agenda ""))
((org-agenda-show-log t)
(org-agenda-ndays 7)
(org-agenda-log-mode-items '(state))
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'notregexp
":DAILY:"))))))
By the way, let’s also add all TODO.org files in Org-agenda with Org-projectile:
(with-eval-after-load 'org-agenda
(require 'org-projectile)
(mapcar #'(lambda (file)
(when (file-exists-p file)
(push file org-agenda-files)))
(org-projectile-todo-files)))
Org journal
I also occasionally use Org journal. All my files are stored in
~/org/journal
, as set below:
(setq org-journal-dir "~/org/journal/")
The default prefix for org journals is the following:
(setq org-journal-date-prefix "#+TITLE: ")
The timestamp will be set following the ISO 8601 format:
(setq org-journal-file-format "%Y-%m-%d")
Org projects
Another great features of Org-mode is the Org projects that allow the user to easily publish a bunch of org files to a remote location. Here is the current declaration of my projects, which will be detailed later:
(setq org-publish-project-alist
'(
<<org-proj-config-html>>
<<org-proj-config-static>>
<<org-proj-config>>
<<org-proj-lang-html>>
<<org-proj-lang-pdf>>
<<org-proj-lang-static>>
<<org-proj-lang>>))
Configuration website
("config-website-org"
:base-directory "~/org/config-website/"
:base-extension "org"
:exclude "\\./\\(CONTRIB\\|head\\|temp\\|svg-ink\\).*"
:publishing-directory "/ssh:Naro:~/www/phundrak.com/www/config"
:recursive t
:language "fr"
:publishing-function org-html-publish-to-html
:headline-levels 5
:auto-sitemap t
:auto-preamble t)
And lastly, we have the component for all the static files needed to run the website:
("config-website-static"
:base-directory "~/org/config-website/"
:base-extension "css\\|scss\\|dart\\|js\\|png\\|jpg\\|gif\\|svg\\|jpeg\\|ttf\\|woff\\|txt\\|epub\\|html"
:publishing-directory "/ssh:Naro:~/www/phundrak.com/www/config"
:recursive t
:language "fr"
:publishing-function org-publish-attachment)
The project is then defined like so:
("config-website"
:components ("config-website-org"
"config-website-static"))
Linguistics website
In my case, I only have my linguistics website, made out of three projects. The first component is the one generating the HTML files from the org files.
("langue-phundrak-com-org"
:base-directory "~/Documents/conlanging/web/"
:base-extension "org"
:exclude "\\./\\(CONTRIB\\|README\\|head\\|temp\\|svg-ink\\).*"
:publishing-directory "/ssh:Naro:~/www/phundrak.com/langue-phundrak-com/web"
:recursive t
:language "fr"
:publishing-function org-html-publish-to-html
:headline-levels 5
:auto-sitemap t
:auto-preamble t)
We also have the component for the LaTeX and PDF part of the website:
("langue-phundrak-com-pdf"
:base-directory "~/Documents/conlanging/web/"
:base-extension "org"
:exclude "\\./\\(CONTRIB\\|README\\|index\\|head\\|temp\\|svg-ink\\).*"
:publishing-directory "/ssh:Naro:~/www/phundrak.com/langue-phundrak-com/web"
:recursive t
:language "fr"
:publishing-function org-latex-publish-to-pdf
:headline-levels 5
:auto-preamble t)
And lastly, we have the component for all the static files needed to run the website:
("langue-phundrak-com-static"
:base-directory "~/Documents/conlanging/web/"
:base-extension "css\\|scss\\|dart\\|js\\|png\\|jpg\\|gif\\|svg\\|jpeg\\|ttf\\|woff\\|txt\\|epub"
:publishing-directory "/ssh:Naro:~/www/phundrak.com/langue-phundrak-com/web"
:recursive t
:language "fr"
:publishing-function org-publish-attachment)
The project is then defined like so:
("langue-phundrak-com"
:components ("langue-phundrak-com-org"
"langue-phundrak-com-static"
"langue-phundrak-com-pdf"))
Rust
The first thing I need to set for my Rust setup is the path to racer
.
(setq racer-cmd "~/.cargo/bin/racer")
Now, I also need to point to racer where the source code of Rust is located so I can get some documentation.
(setq racer-rust-src-path "~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src")
Finally, I wish to enable electric-pair-mode
and indent-guide-mode
for
Rust files, so let’s enable that through the use of a hook:
(add-hook 'rust-mode-hook
'(lambda ()
(local-set-key (kbd "TAB") #'company-indent-or-complete-common)
(electric-pair-mode 1)
(indent-guide-mode 1)))
Scheme
The Scheme configuration will be very short, I just need to tell Emacs the name of the interpreter since it is not the default one:
(setq geiser-chicken-binary "chicken-csi")
Shortcuts
As you will see, I defined A LOT of custom shortcuts. First, I have some shortcuts defined the vanilla Emacs way:
(global-set-key (kbd "C-x C-b") 'ibuffer)
(global-set-key (kbd "S-C-<left>") 'shrink-window-horizontally)
(global-set-key (kbd "S-C-<right>") 'enlarge-window-horizontally)
(global-set-key (kbd "S-C-<down>") 'shrink-window)
(global-set-key (kbd "S-C-<up>") 'enlarge-window)
(global-set-key (kbd "C-x <up>") 'windmove-up)
(global-set-key (kbd "C-x <down>") 'windmove-down)
(global-set-key (kbd "C-x <right>") 'windmove-right)
(global-set-key (kbd "C-x <left>") 'windmove-left)
(global-set-key (kbd "C-<prior>") 'previous-buffer)
(global-set-key (kbd "C-<next>") 'next-buffer)
(global-set-key (kbd "M-»") 'end-of-buffer)
(global-set-key (kbd "M-«") 'beginning-of-buffer)
(global-set-key (kbd "<XF86HomePage>") 'spacemacs/home)
(global-set-key (kbd "<XF86Open>") 'helm-find-files)
(global-set-key (kbd "<XF86Close>") 'kill-this-buffer)
(global-set-key (kbd "<XF86Save>") 'save-buffer)
(global-set-key (kbd "<C-tab>") 'evil-close-fold)
(global-set-key (kbd "<S-C-tab>") 'evil-close-folds)
(global-set-key (kbd "<C-iso-lefttab>") 'evil-open-fold)
These shortcuts can be called as-is, that is, typing C-x C-b
will call
ibuffer
.
Now, I also have some Spacemacs shortcuts, defined in a way they can be used
seamlessly with Evil. First, let’s declare some prefixes in order to avoid
seeing lots of custom
in helm:
(spacemacs/declare-prefix "o" "custom")
(spacemacs/declare-prefix "oa" "applications")
(spacemacs/declare-prefix "oB" "byte-compile .emacs.d")
(spacemacs/declare-prefix "oc" "comments")
(spacemacs/declare-prefix "of" "files")
(spacemacs/declare-prefix "ofb" ".local/bin sources")
(spacemacs/declare-prefix "ofe" "spacemacs.org")
(spacemacs/declare-prefix "off" "fish config")
(spacemacs/declare-prefix "ofi" "i3 config")
(spacemacs/declare-prefix "ofp" "polybar config")
(spacemacs/declare-prefix "ofr" "yadm README")
(spacemacs/declare-prefix "oi" "insert")
(spacemacs/declare-prefix "oii" "invisible space")
(spacemacs/declare-prefix "om" "multiple-cursors")
(spacemacs/declare-prefix "oo" "org-mode")
(spacemacs/declare-prefix "ooi" "custom IDs")
(spacemacs/declare-prefix "oos" "structure")
(spacemacs/declare-prefix "oot" "tables")
(spacemacs/declare-prefix "oott" "toggle width")
(spacemacs/declare-prefix "oote" "expand")
(spacemacs/declare-prefix "oots" "shrink")
(spacemacs/declare-prefix "or" "external command")
(spacemacs/declare-prefix "ot" "toggle")
(spacemacs/declare-prefix "ow" "writeroom")
(spacemacs/declare-prefix "ox" "text")
Now, onto the shortcuts:
(spacemacs/set-leader-keys
"oac" 'calc
"oaC" 'calendar
"oae" 'eww
"oaw" 'wttrin
"oB" (lambda () (byte-recompile-directory (expand-file-name "~/.emacs.d") 0))
"ob" 'fancy-battery-mode
"occ" 'outorg-copy-edits-and-exit
"oce" 'outorg-edit-as-org
"oco" 'outline-minor-mode
"od" 'elcord-mode
"oF" 'flycheck-mode
"ofb" (lambda () (interactive) (find-file "~/.local/bin/README.org"))
"ofe" (lambda () (interactive) (find-file "~/spacemacs.org"))
"off" (lambda () (interactive) (find-file "~/.config/fish/README.org"))
"ofi" (lambda () (interactive) (find-file "~/.config/i3/README.org"))
"ofp" (lambda () (interactive) (find-file "~/.config/polybar/config##yadm.j2"))
"ofr" (lambda () (interactive) (find-file "~/README.org"))
"ofo" 'find-file-at-point
"oii" (lambda () (interactive) (insert ""))
"ome" 'mc/edit-lines
"omn" 'mc/mark-next-like-this
"omp" 'mc/mark-previous-like-this
"oma" 'mc/mark-all-like-this
"ooi" 'eos/org-add-ids-to-headlines-in-file
"oos" 'org-insert-structure-template
"ooT" 'org-sidebar-tree
"oott" 'org-table-toggle-column-width
"oote" 'org-table-expand
"oots" 'org-table-shrink
"oow" 'org-pomodoro
"owi" 'writeroom-increase-width
"or" 'helm-run-external-command
"os" 'prettify-symbols-mode
"oti" 'toggle-input-method
"otI" 'set-input-method
"owd" 'writeroom-decrease-width
"oxf" 'phundrak/fill-paragraph)
You can notice they all begin with o
. This is actually a userspace, and I
know these shortcuts won’t conflict with any other packages. These shortcuts,
like a lot of Spacemacs shortcuts, can be called with the use of the leader
key, in my case SPC
. So, if I want to call the calculator, I will type SPC
o a c
.