configuration.org
Emacs configuration as Org file
Some of my configuration entries where borrowed from other people, see Acknowledgment section for a list.
Performances tweaks (part. 1, start)
Decrease the GC frequency by setting the threshold high for configuration loading. The threshold will be set lower at the end of the configuration to make each GC call faster for normal emacs use.
(setq gc-cons-threshold (* 60 1024 1024))
Personal information
Sets who I am
(setq user-full-name "Michaël Hauspie"
user-mail-address "michael.hauspie@univ-lille.fr"
calendar-latitude 50.60483
calendar-longitude 3.1464
calendar-location-name "Villeneuve d'Ascq, France")
Packages management
I use Elpa, Melpa and Org mode packages repository, thus I need to add them to the package-archives
list
(require 'package)
(add-to-list 'package-archives '("gnu" . "https://elpa.gnu.org/packages/") t)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/") t)
(package-initialize)
Then, to ensure that packages are installed and that I can launch
Emacs on a new computer and have it setup automatically, I use
use-package
.
(when (not (package-installed-p 'use-package))
(package-refresh-contents)
(package-install 'use-package))
If I use a package, I want to ensure that it is installed, so set ensure package by default
(require 'use-package-ensure)
(setq use-package-always-ensure t)
I like to keep things up to date, so I use auto-package-update
;; (use-package auto-package-update
;; :config
;; (setq auto-package-update-delete-old-versions t)
;; (setq auto-package-update-hide-results t)
;; (auto-package-update-maybe))
and I want to be sure that compiled versions of packages are up-to-date
(use-package auto-compile
:config (auto-compile-on-load-mode))
(setq load-prefer-newer t)
Global editing configuration
Default behavior
I use better-defaults to tweak some annoying Emacs default behaviors. The two most important beeing:
- use
ido
almost everywhere - put temporary files in a specific folder rather as
~
files everywhere
there is more to better-defaults
, be sure to have a look at its list
of changed behaviors. In particular, it switches the menu bar off and
I quite like have it around sometimes, so I re-enable it.
(use-package better-defaults)
;; I want menu bar
(menu-bar-mode t)
Ido is not set everywhere by better-defaults
and I really want it everywhere
(setq ido-enable-flex-matching t)
(setq ido-everywhere t)
As I often use Emacs on MacOS, I need the right option (alt) key to
behave as an option key and not an Emacs meta
key.
(when (eq system-type 'darwin)
(setq mac-right-option-modifier nil))
Allow pressing only y
instead of yes
for fast answer to yes or no question
;; Make the y or n suffice for a yes or no question
(fset 'yes-or-no-p 'y-or-n-p)
Editor tweaks
Save the place in the file when killing the buffer so that it reopens at the same spot later
(save-place-mode t)
Syntax highlighting everywhere
(global-font-lock-mode t)
(setq font-lock-maximum-decoration t)
Use 4 spaces as tab
(setq tab-width 4)
Allow cursor to top/bottom of file before signaling a scrolling error
(setq scroll-error-top-bottom t)
Replace selection as I type
(delete-selection-mode t)
When using C-k
, kill the whole line (including \n
)
(setq kill-whole-line t)
When moving the cursor up or down, remember when it was on a line end and keep it that way even if next line is longer or shorter
(setq track-eol t)
Automatically revert buffers if they change on disk. This prevent keeping an outdated buffer open and makes changes that will overwrite the newer file on disk. If the buffer was edited since the last save/revert, Emacs asks what to do.
(global-auto-revert-mode t)
;; kept for future use, I think I do not want that
;; (setq global-auto-revert-non-file-buffers nil)
Do not word wrap buffers, truncate long lines
;; Truncate lines (don't word wrap)
(setq truncate-lines t)
If a timestamp tag is present in the file, update it when saving
;; Time stamping
(setq time-stamp-active t ; do enable time-stamps
time-stamp-line-limit 70 ; check first 70 buffer lines for Time-stamp:
time-stamp-format "%Y-%02m-%02d %02H:%02M:%02S (%u)") ; date format
(add-hook 'write-file-hooks 'time-stamp)
Define a shortcut to re-indent all buffer. This saves the current point, marks whole buffer and call indent-region
(defun mh/indent-buffer()
(interactive)
(save-excursion
(indent-region (point-min) (point-max))))
(global-set-key (kbd "C-c i b") 'mh/indent-buffer)
Undo on steroids
Manage undo as a tree so that we can undo/redo more. Bound by default on C-x u
(use-package undo-tree
:config
(global-undo-tree-mode))
UI and visual tweaks
Changes to builtin visuals
I always display visual line where the cursor is and I like to have line numbers at the left of the buffer. I also have Emacs to show me matching parenthesis. Also do not show the welcome screen.
;; Do not show welcome screen
(setq inhibit-startup-screen t)
;; Highlight current line
(global-hl-line-mode t)
;; Show line number on the left hand side of the code Set line numbers
;; to alway be of the same same, even if we increase the font size
;; This is useful when I stream or do lecture where I need to increase
;; font. As linum does not change the width of the window it uses,
;; things gets messy if the line number font increases
(global-linum-mode t)
(set-face-attribute 'linum nil :height 110)
;; Show matching parenthesis
(show-paren-mode t)
;; Detailed window title
(setq-default frame-title-format (list "%65b %f"))
(setq-default icon-title-format (list "%b"))
Theme
(use-package color-theme-sanityinc-tomorrow
:config
(load-theme 'sanityinc-tomorrow-bright t)
)
Use Fira Code with ligature
(use-package fira-code-mode
:config
(global-fira-code-mode)
(setq fira-code-mode-enable-hex-literal nil)
)
Modeline
Use moody
for a nice looking bottom modeline
;; (use-package moody
;; :config
;; (setq x-underline-at-descent-line t
;; moody-mode-line-height 10)
;; (moody-replace-mode-line-buffer-identification)
;; (moody-replace-vc-mode))
Tweak how some modeline elements are displayed
;; Show line and column number in mode line
(column-number-mode t)
(line-number-mode t)
;; Show time in mode line
(setq display-time-24hr-format t)
(setq display-time-day-and-date t)
(display-time-mode t)
To not display all minor modes. eval-after-load
is there to
ensure that diminish is called only for modules that are installed
and loaded.
(use-package diminish
:config
(eval-after-load "company" '(diminish 'company-mode))
(eval-after-load "company-box" '(diminish 'company-box-mode))
(eval-after-load "undo-tree" '(diminish 'undo-tree-mode))
(eval-after-load "yasnippet" '(diminish 'yas-minor-mode))
(eval-after-load "which-key" '(diminish 'which-key-mode))
(diminish 'eldoc-mode)
)
Shortcut dynamic help buffer
When a key binding sequence is started and not finished, display possible next keys in the mini-buffer
(use-package which-key
:config
(which-key-mode t))
Winner mode for undo/redo buffer configuration
Enable winner mode globally. Then with C-c left
and C-c right
we can redo/undo the buffer configuration
(winner-mode t)
Org mode
This is one of the most important mode I use in Emacs. I use it to organize tasks, take meetings notes, write articles, lectures… I use org with contributed packages added.
Basics
(use-package org
;; :ensure org-plus-contrib
;; :ensure org-tempo
:custom
;; Tab keeps indenting in src blocks
(org-src-tab-acts-natively t)
;; IDO for completion when applicable
(org-completion-use-ido t)
;; hide emphasis markers
;; (org-hide-emphasis-markers t)
:config
;; (require 'org-tempo)
(add-hook 'org-mode-hook
'(lambda ()
(setq org-file-apps
'(("org" . emacs)
("rs" . emacs)
("c" . emacs)
("h" . emacs)
)))))
Add a shortcut to toggle display of emphasis characters
(defun org-toggle-emphasis ()
"Toggle hiding/showing of org emphasize markers."
(interactive)
(if org-hide-emphasis-markers
(set-variable 'org-hide-emphasis-markers nil)
(set-variable 'org-hide-emphasis-markers t)))
(define-key org-mode-map (kbd "C-c e") 'org-toggle-emphasis)
Use org-mode
for the initial scratch buffer
(setq initial-major-mode 'org-mode)
And set some keyboard shortcuts for links and agenda
(global-set-key (kbd "C-c l") 'org-store-link)
(global-set-key (kbd "C-c a") 'org-agenda)
(global-set-key (kbd "C-c c") 'org-capture)
Add shortcuts to quickly add code blocks using =C-,=
(add-to-list 'org-structure-template-alist
'("el" . "src emacs-lisp"))
Visuals
Use bullets instead of asterisks
(use-package org-bullets
:init
(add-hook 'org-mode-hook 'org-bullets-mode))
(set-face-foreground 'org-verbatim "orange1")
Task management
Record when a todo item was marked as done and enforce marking dependencies as done before being able to mark an item as done
(setq org-log-done 'time)
(setq org-enforce-todo-dependencies t)
(setq org-enforce-todo-checkbox-dependencies t)
Set default task completion states to TODO
, WAITING
and
DONE
. I use WAITING
when I can’t go further on a task because
I’m waiting for some inputs.
(setq org-todo-keywords
'((sequence "TODO" "WAITING" "|" "DONE")))
index and archive files
Index and archive are my main todo lists (index) and a list of archived (done) tasks.
(setq org-directory "~/documents/org")
(defun org-file-path (filename)
"Return the absolute address of an org file, given its relative name."
(concat (file-name-as-directory org-directory) filename))
(setq org-index-file (org-file-path "index.org"))
(setq org-archive-location
(concat (org-file-path "archive.org") "::* From %s"))
Then more specifics org files to add to the agenda list
(setq org-agenda-files (list org-index-file
"~/.emacs.d/configuration.org"
(org-file-path "work.org")
(org-file-path "archive.org"))) ; Just in case I forget to mark a subtask as done and archive the main one
Hitting C-c C-x C-s
will mark a todo as done and move it to an appropriate place in the archive.
(defun hrs/mark-done-and-archive ()
"Mark the state of an org-mode item as DONE and archive it."
(interactive)
(org-todo 'done)
(org-archive-subtree))
(define-key org-mode-map (kbd "C-c C-x C-s") 'hrs/mark-done-and-archive)
Agenda
The week should begin today, not last Monday for the agenda view
(setq org-agenda-start-on-weekday nil)
I want to see more days in the agenda view
(setq org-agenda-span 15)
Define a custom agenda view. I want my agenda with tasks that are scheduled or have a deadline, but also all other tasks that do not have a date scheduled or as deadline. This is for tasks that I will eventualy do later.
(setq org-agenda-custom-commands
'(("a" "Agenda"
(
(agenda "" ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))))
(alltodo "" ((org-agenda-skip-function '(org-agenda-skip-entry-if 'scheduled 'deadline 'todo 'done))))
))))
Capture
Define some capture template to be able to create tasks, or maybe other things later
(setq org-capture-templates
'(("f" "Finished book"
table-line (file "~/Documents/org/books-read.org")
"| %^{Title} | %^{Author} | %u |")
("t" "Todo"
entry
(file+headline org-index-file "Tâches")
"* TODO %?\n:PROPERTIES:\nCREATED: %u\n:END:\n")
("b" "Bookmarks"
table-line (file "~/Documents/org/bookmarks.org")
"| %^{prompt|rust|other} | %^{url} | %^{what}")
("c" "Cycling"
table-line (file "~/Documents/org/cycling.org")
"| %t | balade | %^{prompt|standard|électrique} | %^{Distance} |")
("w" "Cycling to work"
table-line (file "~/Documents/org/cycling.org")
"| %t | boulot | %^{prompt|électrique|standard} | 26.2 |")))
Tree slide
(use-package org-tree-slide
:config
(define-key org-mode-map (kbd "<f8>") 'org-tree-slide-mode)
)
Export configuration
I use org-mode
to export to LaTeX, (beamer and article) markdown and to HTML
using bootstrap template.
;; Add Beamer to export list
(require 'ox-beamer)
;; And markdown
(require 'ox-md)
;; some HTML slide export engines
(use-package ox-html5slide)
(use-package ox-impress-js)
(use-package ox-reveal)
(use-package ox-spectacle )
;; bootstrap html
(use-package ox-twbs)
So that code highlighting can be done using minted (which uses Pygments as an external tool), we need to change latex export commands.
;; Configure ox-latex to export source block using minted
;; Setting minted cache to false as cache seems to fail when changing the output-directory
(add-to-list 'org-latex-packages-alist '("cache=false" "minted"))
(setq org-latex-listings 'minted)
(setq org-latex-pdf-process
'("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
For HTML source code highlight, use htmlize
(use-package htmlize)
Source code evaluation
So that source code blocks can be evaluated inside org-mode
, we add
it to babel languages. org-babel
is what executes code and outputs
its result in your org file.
(use-package gnuplot)
(use-package gnuplot-mode)
(use-package ob-rust)
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(C . t)
(latex . t)
(gnuplot . t)
(dot . t)
(java . t)
(python . t)
(makefile . t)
(org . t)
(perl . t)
(sed . t)
(shell . t)
(rust . t)
))
Preserve indentation in source block (useful for makefiles to preserve tabs for example)
(setq org-src-preserve-indentation t)
Don’t ask before evaluating
(setq org-confirm-babel-evaluate nil)
Correctly associate dot
language with the correct major-mode inside org.
(use-package graphviz-dot-mode)
(add-to-list 'org-src-lang-modes '("dot" . graphviz-dot))
Make org mode correctly export quotes
(setq org-export-with-smart-quotes t)
Use python3
(setq org-babel-python-command "python3")
Completion setup
I use company mode for completion. It provides a visual completion list of what can be used to complete. It works with several backends such as LSP, with which it provides semantic completion for code editing.
First, install and configure company and enable it for
all buffers. I also set M-/
to trigger company-complete
(use-package company
:ensure company-lsp
:ensure company-box
:ensure company-php
:ensure company-web
:init
(global-company-mode t)
(global-set-key (kbd "M-/") 'company-complete)
;; Complete quite soon
:custom
(company-minimum-prefix-length 3)
(company-idle-delay 0.1)
)
Then, add backends and company tweaks.
company-box
adds icons to company complete list. It is useful when
completing symbols in source code.
(use-package company-box
:ensure frame-local
:hook (company-mode . company-box-mode))
Now some backends I use. Mainly lsp, php and web
related. company-lsp
is slow to start, so we force a defer loading
only when it’s needed.
(use-package company-php)
(use-package company-web)
(use-package company-lsp
:defer t)
Code navigation
Treemacs
I use Treemacs for code navigation. You can use it to define
projects (a project is a folder actually) from which you can easily
navigate. You can have several workspaces that are simply a list of
projects. I bind C-c t
to toggle treemacs panel.
(use-package treemacs
:custom
(treemacs--icon-size 16)
:bind ("C-c t" . treemacs-select-window)
)
Projectile
Projectile allows for easy file navigation inside
projects. Projects are automatically detected by projectile
whenever a .git
folder or a .projectile
file is in a foler.
Bind C-c p
as the prefix for projectile command keybinds.
(use-package projectile
:config
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
(projectile-mode t))
As I use treemacs
, adds treemacs-projectile
plugin
(use-package treemacs-projectile)
Snippets
I use yasnippet
for defining and using snippets for several modes. I
preload all snippets by AndreaCrotti (yasnippet-snippets
package).
(use-package yasnippet
:init
(yas-global-mode))
(use-package yasnippet-snippets)
Developpement
Here, I setup all packages for developping in several languages. This starts by configuring LSP which allow emacs to get semantic information from a language server dedicated to the programming language currently in use.
LSP
(use-package lsp-mode
:hook (
(c++-mode . lsp)
(python-mode . lsp)
(rust-mode . lsp)
(lsp-mode . lsp-enable-which-key-integration)
)
:config
(lsp-headerline-breadcrumb-mode t)
:commands lsp
)
For displaying more information directly in the buffer, I use lsp-ui
(use-package lsp-ui
:commands lsp-ui-mode)
LSP keybinds
(setq lsp-keymap-prefix "s-l")
Integration with treemacs
LSP can integrate with treemacs to display packages, class, symbols and such.
(use-package lsp-treemacs
:custom
(lsp-treemacs-sync-mode 1))
Flycheck
Flycheck allow synthax checking in the source code buffer. LSP uses flycheck if available to show code diagnosis.
(use-package flycheck)
For languages that do not have LSP yet, we can add some flycheck extensions
(use-package flycheck-perl6)
Language specific configuration
Rust
Install rust-mode
and set the rust language server to rust-analyzer
(use-package rust-mode
:custom
(lsp-rust-server 'rust-analyzer)
; (rust-format-on-save t)
)
For this to work, you need to install rust-analyzer
and rustmft
.
if [[ "$OSTYPE" =~ ^darwin ]]
then
echo "Installing for macos"
binary=rust-analyzer-mac
else
echo "Installing for linux"
binary=rust-analyzer-linux
fi
curl -L https://github.com/rust-analyzer/rust-analyzer/releases/latest/download/$binary -o ~/.cargo/bin/rust-analyzer
chmod +x ~/.cargo/bin/rust-analyzer
Adds cargo installed binaries to exec path
(setq exec-path (cons "~/.cargo/bin" exec-path))
Lua
Simply add lua-mode
(use-package lua-mode)
Docker
For dockerfiles and docker-compose files, install some docker packages
(use-package dockerfile-mode)
(use-package docker-compose-mode)
(use-package docker)
(use-package docker-api)
(use-package docker-cli)
(use-package docker-tramp)
Web
Add web-mode
, rainbow-mode
, simple-httpd
and impatient-mode
for web editing.
-
web-mode
is a major mode for web template editing. We associate the mode with web files -
rainbow-mode
colorizes color names in buffers -
simple-httpd
is an http server implemented inelisp
that can serve local directory and even remote directory if associated with tramp -
impatient-mode
serves buffers dynamically withsimple-httpd
. What you edit in emacs is immediatly visible on the web browser
(use-package web-mode
:config
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode))
)
(use-package rainbow-mode)
(use-package simple-httpd)
(use-package impatient-mode)
LaTeX
Enable reftex
whenever tex-mode
is activated
(add-hook 'latex-mode-hook 'reftex-mode)
Use auctex
for better experience editing latex files
(use-package auctex
:ensure auctex-latexmk
:defer t
)
If using macos, add mactex to exec-path
(when (eq system-type 'darwin)
(setq exec-path (cons "/Library/TeX/texbin" exec-path)))
Ningx configuration
A mode to edit nginx configuration files.
(use-package nginx-mode)
Magit
Magit is git porcelain inside emacs.
- Bind
C-x g
to pop up the magit status buffer - configure magit to automatically revert buffers that are opened if they are modified by a magit action (such as changing branch, merging…)
- Save buffers that visit a file that belongs to a repository if needed
(use-package magit
:config
(magit-auto-revert-mode t)
(magit-save-repository-buffers t)
:bind ("C-x g" . magit-status)
)
Protocol buffers
(use-package protobuf-mode)
Spell checking
First, set aspell
to be the spell checking program instead of ispell
(setq ispell-program-name "aspell")
Then define a command that will run flyspell on the buffer and activate it
(defun mh/spellcheck ()
(interactive)
(flyspell-mode t)
(flyspell-buffer)
)
And define a global binding to call it
(global-set-key (kbd "C-c s") 'mh/spellcheck)
Binding to fix a word then go to the next error. Special syntax
[?\C-\$]
is used to protect the $
sign
(defun mh/cycle-spellcheck ()
(interactive)
(flyspell-goto-next-error)
(ispell-word))
(global-set-key (kbd "C-$") 'mh/cycle-spellcheck)
Misc.
Adds /usr/local/bin
to Emacs exec-path
(setq exec-path (cons "/usr/local/bin" exec-path))
Starts Emacs server so that we can use emacsclient
for opening new
files.
(server-start)
A handy way of starting Emacs from the shell is then to call
emacsclient -a emacs ...
This will attempt to connect to Emacs server and run Emacs if the server is not started yet.
To check later
Try helm
Try mu4e
Performances tweaks (part. 2, profiling)
This configuration can make emacs being long to start, let’s profile a bit
This will print emacs start time as well as the count of GC calls
(add-hook 'emacs-startup-hook
(lambda ()
(message "Emacs ready in %s with %d garbage collections."
(format "%.2f seconds"
(float-time
(time-subtract after-init-time before-init-time)))
gcs-done)))
ESup is an emacs profiler
(use-package esup
:ensure t
;; To use MELPA Stable use ":pin mepla-stable",
:pin melpa
:commands (esup))
Performances tweaks (part. 3, the end)
Set GC threshold to something more reasonable for standard use.
(setq gc-cons-threshold (* 2 1024 1024))
Acknowledgment
I learned a great deal of how to use org-mode
for emacs
configuration from Harry R. Schwartz configuration files. He also gave
a great talk on emacs org-mode
. Parts of my configuration are
directly copied from his.
Alain M. Lafon also gave a great talk on how emacs can be played like an instrument.
A guide on how to speed up emacs starting time