My emacs configuration
This file is split in 8 categories:
- Conventions Here we will document the semantics, design choices and structure that we will use throughout the file
- Installation Instructions to install on your system
- Manual Fixes Solutions to various problems/bugs
- Visual Here we load our themes and cursor shape and eye-candy in general
- EXWM Configuration for when we use the Emacs X Window Manager
- UI Changes Functions and packages that change or add functionality to the UI
- Window Management Configuration for managing EMACS windows
- Text editor Configuration for editing plain text formats
The file conf.el generated by org-babel-load-file is made by tangling so we can disable a file/subree/source block by setting ‘tangle’ to ‘no’ either in the file’s/subtree’s properties or in the header of the source block.
We can use this to easily disable parts of the configuration (e.g. to disable exwm)
Basically we need to initialize and refresh the contents of the package manager, make sure we have use-package and org-mode installed. After that we use org-babel-load-file to load the configuration stored in this file.
If you are reading this using org-mode you should be able to install by following the links.
Create init.el(Backs up your current init.el as init.el.bk)
;; Sample init.el
(require 'package)
(setq package-archives '(("elpa" . "https://elpa.gnu.org/packages/")
("melpa" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")))
(package-initialize)
(let ((usep? (require 'use-package nil 'noerror)))
;; we reload the archives syncronously for the first time
;; in order to fetch the packages
(package-refresh-contents usep?)
(when (not usep?)
(package-install 'use-package)))
(require 'use-package)
(use-package org-plus-contrib
:ensure t
:defer t)
(require 'org)
(org-babel-load-file
(expand-file-name "conf.org" user-emacs-directory))
Finally, this file must be saved as /<user-emacs-directory>/conf.org Copy to my emacs directory(Backs up your current conf.org as conf.org.bk)
Fixes for various problems are to be documented here. Writing the solution in emacs lisp makes sure that it is platform independant
Upgrading from org-mode 8.XX to 9.XX messes up with the evaluation of source blocks You will need to recompile the elisp files and restart emacs. Eval the sexp below(C-x C-e) to do so.
(byte-recompile-directory (file-name-directory (locate-library "org")) 0 t)
(use-package doom-themes
:ensure t
:config (load-theme 'doom-city-lights t))
(set 'light-theme 'doom-solarized-light)
(set 'dark-theme 'doom-city-lights)
(use-package powerline
:ensure t
:config
(powerline-center-theme))
(setq light/dark-theme-setting-state 0)
(defun light/dark-toggle (&optional set-state)
(interactive "P")
(if set-state
(if (or (= set-state 0) (= set-state 1))
(setq light/dark-theme-setting-state set-state)
(error "Invalid state `%s' should be 0 or 1"))
(setq light/dark-theme-setting-state (- 1 light/dark-theme-setting-state)))
(if (= light/dark-theme-setting-state 1)
(progn
(disable-theme dark-theme)
(load-theme light-theme t))
(progn
(disable-theme light-theme)
(load-theme dark-theme t)))
(powerline-center-theme))
Set the font to something nice
(set-face-attribute 'default nil
:width 'expanded
:height 120
:weight 'normal
:stipple nil
:font "Anonymous Pro")
(setq-default cursor-type 'bar)
(use-package beacon
:ensure t
:config
(beacon-mode t))
(use-package exwm
:ensure t)
(require 'exwm-config)
(exwm-config-default)
(require 'exwm-systemtray)
(exwm-systemtray-enable)
(use-package dmenu
:ensure t
:bind ("s-d" . dmenu))
(global-set-key (kbd "s-<return>") (lambda ()
(interactive)
(ansi-term shell-file-name)))
(global-set-key (kbd "s-b")
(lambda ()
(interactive)
(start-process "Firefox" nil "firefox")))
General tweaks to the UI
(use-package ido
:ensure t
:config
(ido-mode t)
(ido-everywhere t))
(use-package smex
:ensure t
:init
:config
(smex-initialize)
:bind
( "M-x" . smex)
( "M-X" . smex-major-mode-commands)
( "C-c M-x" . execute-extended-command))
(use-package ido-vertical-mode
:ensure t
:config
(ido-vertical-mode 1)
(setq ido-vertical-define-keys 'C-n-and-C-p-only))
(use-package flx-ido
:ensure t
:init
:config
(flx-ido-mode t)
(setq ido-use-faces nil)
:bind )
We just make sure hydra is loaded and ready and we’ll configure heads in the appropriate sub-sections
(use-package hydra
:ensure t)
Emacs winow management Not to be confused with X windows which is EXWM’s job
The winmove-C-c-move-* functions allow us to overwrite then with extra functionality
(use-package windmove
:ensure t
:bind (("C-c h" . windmove-C-c-move-left)
("C-c j" . windmove-C-c-move-down)
("C-c k" . windmove-C-c-move-up)
("C-c l" . windmove-C-c-move-right)))
(require 'windmove)
(require 'hydra)
(defhydra hydra-windmove
(:pre (setq-default cursor-type 'box)
:post (setq-default cursor-type 'bar))
"Switch windows with vi-like keybindings"
("h" windmove-left)
("j" windmove-down)
("k" windmove-up)
("l" windmove-right)
("0" delete-window)
("1" delete-other-windows)
("2" split-window-below)
("3" split-window-right)
("y" shrink-window-horizontally)
("o" enlarge-window-horizontally)
("u" shrink-window)
("i" enlarge-window)
("ESC" nil "quit"))
(defun windmove-C-c-move-left ()
"Move left and call the function `hydra-windmove/body' interface
\\[windmove-C-c-move-left]"
(interactive)
(windmove-left)
(hydra-windmove/body))
(defun windmove-C-c-move-down ()
"Move down and call the function `hydra-windmove/body' interface
\\[windmove-C-c-move-left]"
(interactive)
(windmove-down)
(hydra-windmove/body))
(defun windmove-C-c-move-up ()
"Move up and call the function `hydra-windmove/body' interface
\\[windmove-C-c-move-left]"
(interactive)
(windmove-up)
(hydra-windmove/body))
(defun windmove-C-c-move-right ()
"Move right and call the function `hydra-windmove/body' interface
\\[windmove-C-c-move-left]"
(interactive)
(windmove-right)
(hydra-windmove/body))
If there is a prefix argument call shell-command so that we don’t move the point while the command is executing else call async-shell-command
(defun my-shell-command (&optional p)
(interactive "P")
(if p
(call-interactively 'shell-command)
(call-interactively 'async-shell-command)))
(global-set-key (kbd "M-!") 'my-shell-command)
(use-package yasnippet
:ensure t
:config
(setq yas-snippet-dirs '("~/.emacs.d/yasnippet-snippets/snippets/"))
(yas-global-mode t))
(use-package undo-tree
:ensure t
:config (setq-default undo-tree-mode t)
:bind ("C-x /" . undo-tree-visualize))
(use-package nlinum
:ensure t
:config
(setq nlinum-format "%6d")
(global-nlinum-mode))
(use-package avy
:ensure t
:init
:config
(setq avy-keys (number-sequence ?a ?z)
avy-timeout-seconds 0.5)
:bind
("C-c g j" . avy-goto-char-timer)
("C-c g l" . avy-goto-line))
(use-package company
:ensure t
:init
:config (add-hook 'after-init-hook 'global-company-mode)
:bind )
(use-package flycheck
:ensure t)
(use-package god-mode
:ensure t
:init
:config
:bind ("ESC M-g" . 'god-mode-all))
(use-package autopair
:ensure t
:init
:config
(autopair-global-mode t)
(setq
autopair-autowrap t
autopair-blink t
autopair-skip-whitespace t)
:bind )
(electric-pair-mode t)
Visit Config
(defun conf-edit ()
(interactive)
(find-file (expand-file-name "conf.org" user-emacs-directory)))
;; Store this file in register c
;; Open with C-x r j c
(set-register ?c `(file . ,(expand-file-name "conf.org" user-emacs-directory)))
(defun region-reduce-radius (dr)
(interactive "nReduce raduis by: ")
"Shorten the region by 2*DR while mainaining the center"
(let ((beg (region-beginning))
(end (region-end)))
(deactivate-mark)
(push-mark (+ beg dr) t t)
(goto-char (- end dr))
(activate-mark)))
(global-set-key (kbd "C-c r r") 'region-reduce-radius)
(defun my-kill-word ()
(interactive)
(when (= (char-syntax (char-before)) (string-to-char "w"))
(backward-word))
(kill-word 1))
(global-set-key (kbd "C-c w") 'my-kill-word)
We’ll use this to calculate a character’s pair
(defun get-pair-of (char)
(car (cdr (electric-pair-syntax-info char))))
(defun my-change-inside (open)
"Vim-like change inside that accepts the opening character as OPEN"
(interactive "cChar: ")
(let ((close (get-pair-of open)))
(when close
(search-forward (char-to-string open))
(backward-char)
(mark-sexp)
(kill-region (+ (region-beginning) 1) (- (region-end) 1))
(forward-char))))
(global-set-key (kbd "C-c i") 'my-change-inside)
The opposite of change-inside: changes the pair surrounding the balanced expression e.g. “foo” -> (foo) -> [foo]
(defun my-change-outside (p1 p2)
"Switch p1 to p2 as the pair of a balanced sexp
replacing the pair with a space deletes the pair"
(interactive "cChange \ncTo")
(let ((^p1 (get-pair-of p1))
(^p2 (get-pair-of p2)))
(when (and ^p1 (or ^p2 (= p2 (string-to-char " "))))
(search-forward (char-to-string p1))
(backward-char)
(mark-sexp)
(delete-char 1)
(if (not (= p2 (string-to-char " "))) (insert p2))
(goto-char (- (region-end) 1))
(delete-char 1)
(if (not (= p2 (string-to-char " ")))(insert ^p2)))))
(global-set-key (kbd "C-c o") 'my-change-outside)
(global-prettify-symbols-mode t)
(use-package auctex
:ensure t
:defer t)
(setq global-org-keymap (make-sparse-keymap))
(define-key global-org-keymap (kbd "a") 'org-agenda)
(define-key global-org-keymap (kbd "l") 'org-store-link)
(define-key global-org-keymap (kbd "c") 'org-capture)
(global-set-key (kbd "ESC M-o") global-org-keymap)
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(python . t)
(shell . t)))
(use-package org-bullets
:ensure t)
(add-hook 'org-mode-hook 'org-bullets-mode)
Note: Exporting to latex requires a latex installation
We will configure latex preview to work with unicode fonts First we use a backend that supports fontspec
(require 'ox)
(setq org-preview-latex-process-alist
'((dvipng
:programs ("latex" "dvipng")
:description "dvi > png"
:message "you need to install the programs: xelatex and dvipng."
:image-input-type "xdv"
:image-output-type "png"
:image-size-adjust (1.0 . 1.0)
:latex-compiler ("latex -interaction nonstopmode -no-pdf -output-directory %o %f")
:image-converter ("dvipng -fg %F -bg %B -D %D -T tight -o %O %f"))
(dvisvgm
:programs ("xelatex" "dvisvgm")
:description "dvi > svg"
:message "you need to install the programs: xelatex and dvisvgm."
:use-xcolor t
:image-input-type "xdv"
:image-output-type "svg"
:image-size-adjust (1.7 . 1.5)
:latex-compiler ("xelatex -interaction nonstopmode -no-pdf -output-directory %o %f")
:image-converter ("dvisvgm %f -n -b min -c %S -o %O"))
(imagemagick
:programs ("latex" "convert")
:description "pdf > png"
:message "you need to install the programs: xelatex and imagemagick."
:use-xcolor t
:image-input-type "pdf"
:image-output-type "png"
:image-size-adjust (1.0 . 1.0)
:latex-compiler ("xelatex -interaction nonstopmode -output-directory %o %f")
:image-converter ("convert -density %D -trim -antialias %f -quality 100 %O"))))
(setq org-preview-latex-default-process 'dvisvgm)
Then well add a unicode font in our default headers
(setq org-format-latex-header
"
\\documentclass{article}
\\usepackage[usenames]{color}
[PACKAGES]
[DEFAULT-PACKAGES]
\\setmainfont{DejaVu Serif Bold}
\\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}
")
(plist-put org-format-latex-options :scale 2)
Use xelatex to render unicode characters
(setq org-latex-pdf-process
'("xelatex -interaction nonstopmode -output-directory %o %f"
"xelatex -interaction nonstopmode -output-directory %o %f"
"xelatex -interaction nonstopmode -output-directory %o %f"))
Add default latex packages
;; for unicode fonts
(add-to-list 'org-latex-packages-alist '("" "fontspec" t))
(add-to-list 'org-latex-packages-alist '("" "unicode-math" t))
Configure document classes and use a reasonable font Some helper functions first
;; default format string for class header
(setq org-helper-class-generator-default-format-str
"\\documentclass[%dpt]{%s}
[DEFAULT-PACKAGES]
[PACKAGES]
\\setmainfont{%s}
%s
[EXTRA]")
;; handles the formating of a class header
(defun org-helper-create-latex-class-header
(name &optional font size extra-headers format-string)
"Creates the document-class header for a given class"
(format (if format-string format-string org-helper-class-generator-default-format-str)
(if size size 11)
name
(if font font "DejaVu Serif")
(if extra-headers extra-headers "")))
;; We'll use this to create all our document classes for LaTeX export
(defun org-helper-create-class (name section-alist &optional font size extra-headers header-format-string)
"Helper function to create document classes"
(append (list name)
(list
(org-helper-create-latex-class-header
name font size extra-headers header-format-string))
section-alist))
Then define the document classes
(setq org-latex-classes
(list (org-helper-create-class
"article"
'(("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
(org-helper-create-class
"report"
'(("\\part{%s}" . "\\part*{%s}")
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")))
(org-helper-create-class
"book"
'(("\\part{%s}" . "\\part*{%s}")
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")))))
(use-package magit
:ensure t
:init
:config
:bind )
(use-package projectile
:ensure t)
We will use Irony mode and Rtags for completion This requires clang and llvm
After installing the package run M-x rtags-install to install the daemon
(use-package rtags
:ensure t
:config
(rtags-start-process-unless-running))
(use-package company-rtags
:ensure t)
(add-to-list 'company-backends 'company-rtags)
(use-package flycheck-rtags
:ensure t)
(use-package irony
:ensure t
:config
(add-hook 'c-mode-hook 'irony-mode))
(unless (file-exists-p
(expand-file-name "irony-server"
(concat irony-server-install-prefix "bin/")))
(irony-install-server))
(use-package company-irony
:ensure t
:config
(add-to-list 'company-backends 'company-irony))
(use-package flycheck-irony
:ensure t
:config
(add-hook 'flycheck-mode-hook 'flycheck-irony-setup))