aboutsummaryrefslogtreecommitdiff
path: root/.emacs.d
diff options
context:
space:
mode:
Diffstat (limited to '.emacs.d')
-rw-r--r--.emacs.d/.gitignore5
-rw-r--r--.emacs.d/README.org94
-rw-r--r--.emacs.d/custom.el24
-rw-r--r--.emacs.d/gtkrc5
-rw-r--r--.emacs.d/init.el22
-rw-r--r--.emacs.d/init.org2349
-rw-r--r--.emacs.d/lisp/README.md18
-rw-r--r--.emacs.d/lisp/g.el134
-rw-r--r--.emacs.d/org-templates/README.org22
-rw-r--r--.emacs.d/org-templates/article-full.org20
-rw-r--r--.emacs.d/org-templates/article.org20
-rw-r--r--.emacs.d/org.css66
-rwxr-xr-x.emacs.d/pre-push79
-rw-r--r--.emacs.d/snippets/org-mode/header8
-rwxr-xr-x.emacs.d/test-startup.sh22
15 files changed, 2888 insertions, 0 deletions
diff --git a/.emacs.d/.gitignore b/.emacs.d/.gitignore
new file mode 100644
index 0000000..3406897
--- /dev/null
+++ b/.emacs.d/.gitignore
@@ -0,0 +1,5 @@
+*.html
+lisp/*.elc
+org-templates/*.pdf
+org-templates/*.tex
+org-templates/auto \ No newline at end of file
diff --git a/.emacs.d/README.org b/.emacs.d/README.org
new file mode 100644
index 0000000..517908a
--- /dev/null
+++ b/.emacs.d/README.org
@@ -0,0 +1,94 @@
+#+TITLE: GNU Emacs configuration
+#+AUTHOR: Miquel Sabaté Solà
+#+EMAIL: mikisabate@gmail.com
+
+* About this
+
+I'm following a literate programming approach for my GNU Emacs
+configuration. The basic workflow is that on the first run the =init.el= file
+will replace itself with a tangled (=org-babel=) version of itself. Therefore,
+all changes should go into the =init.org= file. Moreover, I've added a function
+that is executed on save which generates and compiles new versions of the
+=init.el= file.
+
+I run GNU Emacs in daemon mode, but I don't use systemd for that. Instead, in
+I'm using the =-a= argument of =emacsclient= with an empty string. This
+instructs =emacsclient= to spawn a new server if there isn't one already. This
+means that the first time around it will take some time, but in the next time
+everything will be alright.
+
+=Supported versions=: GNU Emacs 25.x and 26.x.
+
+* Dependencies
+
+First of all, install the [[https://github.com/mssola/soria][soria]] color theme. This should already be handled by
+the install script. Then make sure to install the following:
+
+- =calibre=: a markdown to HTML converter.
+- =spell= for spell checking.
+- A LaTeX to PDF converter for exporting org files to PDF. In openSUSE this is
+ fixed by installing the =texlive-pdftex= package.
+- =mu= and =mu4e= for email. This should be installed from my [[https://build.opensuse.org/package/show/home:mssola/mu][OBS]] project.
+
+Last but not least, to get a proper Go environment you need to install the
+following:
+
+#+BEGIN_SRC sh
+go get -u golang.org/x/tools/cmd/goimports
+go get -u github.com/rogpeppe/godef
+go get -u github.com/dougm/goflymake
+go get -u github.com/nsf/gocode
+#+END_SRC
+
+* Developing
+
+I've added a git =pre-push= hook which syncs the =init.html= and the =org.css=
+files into my personal server.
+
+* Installing
+
+The installation process of my GNU Emacs configuration should already be handled
+by the =install.sh= script that can be found in the root of this project. If you
+want to do it manually:
+
+- Create the =~/.emacs.d= directory if it has not been created yet.
+- Copy the =init.el= into the =~/.emacs.d= directory. This is the only file that
+ should be copied instead of linked because it will get replaced on the first run
+ by =org-babel=.
+- Link the =init.org=, =custom.el= and =gtkrc= files into the =~/.emacs.d=
+ directory.
+- Create the =~/.emacs.d/lisp= subdirectory and link the =lisp/g.el= file there.
+- Clone the [[https://github.com/mssola/soria][soria]] project and link the =soria-theme.el= file into the
+ =~/.emacs.d= directory.
+
+* Credits
+
+I've built this file by simply scavenging from other people's emacs.d/dotfiles
+repositories. I have taken lots of pieces from here and there, but most notably:
+
+- [[https://github.com/ereslibre/dotfiles][@ereslibre]]
+- [[https://github.com/dmacvicar/dotfiles][@dmacvicar]]
+- [[https://github.com/bbatsov/emacs.d][@bbatsov]]
+- [[https://github.com/aaronbieber/dotfiles][@aaronbieber]]
+- [[https://github.com/purcell/emacs.d][@purcell]]
+- [[https://github.com/sachac/emacs.d][@sachac]] ([[http://pages.sachachua.com/.emacs.d/Sacha.html][HTML version]])
+- [[https://github.com/larstvei/dot-emacs][@larstvei]]
+
+* License
+
+#+BEGIN_SRC text
+ Copyright (C) 2014-2019 Miquel Sabaté Solà <mikisabate@gmail.com>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+#+END_SRC
diff --git a/.emacs.d/custom.el b/.emacs.d/custom.el
new file mode 100644
index 0000000..be16428
--- /dev/null
+++ b/.emacs.d/custom.el
@@ -0,0 +1,24 @@
+(custom-set-variables
+ ;; custom-set-variables was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ '(ansi-color-names-vector
+ ["#1c1c1c" "#d78787" "#b9dc92" "#ffffaf" "#87afd7" "#875f87" "#dfafdf" "#d0d0d0"])
+ '(custom-safe-themes
+ (quote
+ ("44c996124982462f61fa04eeccb9e3661fbe995489eacd3b0f289e37aed29c98" "613d432fab88d34f9a4451bdbe714a31749de6c5a4d9d0bf0929399ad50f1ac6" "03f4de3e9d5df2d34dc4085ea2fe4906edf6377bf02eef7eb3430b97155c1398" "c2ea64b5a0d8042da7ff3979fc03e5cc13fc1e4bc839c5ab464f69c2dada0804" "1c79d160e207fcd2193beaf95bf25d55e15f3237f6943cc04f516e7ef600bdd7" "6a32c414a3d1a493d534a28e7814a4d6055bc607bbf45d57196cd6ee9215461b" "da9b51d7ba5c03589a7cb74f0da136cf4c9b2fdc6c58e48d78f077c8ccca39a9" "6a068d53e7b2bf41ac4a3874ea296b78c3f90cd1fd44d1769812c4c578313539" "8ebd5ccdc11c1e53647c9efc153dbcf0b00a61a519825d2698ce065913cecd35" "7e69e41a60afea0bea1e5f7a89416466db331ec45cbafe47ebec694411c997b8" "3762f105d8ea307cec0ee7cc36dcbce1ab0009ca1ae448fd07e8e8e65647431f" "75080b8936556e23444bd76fcfc042e484a50a403ccb7f36fd190c21f7bf8941" "e2669e7d32201debd97395277167b6a1d93606b9445ebce01b9f878eb980e200" "92eb47cefb2f03abaaaa52c60a0b89845361577c2201d3399d19b944828505f4" "62c1fac02f61eaad07bf39fd461f5c78ee3424ba87a1f5fe91b1bea25475f327" "62f08bc59e1ac24e6df5b5b01fea2da24f2fec201b285ccda9991b7052a3a46a" "ce1c38b72f45eed22f3dfaf7f3f0df4b0b6ed975cc5d2012fb1aad13e8055840" "e8b0224a3bd5da096120bf19c976a29cfe67af41bfe73171348bfe99ee0da62d" "ad1c0d9498ad9344082d47e3a1bb6b75f0d004e0ae8361613b0c9963b23fbb4d" "8e6f5b61626315a98a6b38acfe966800777bf6a1841aa2b812b471772cc17114" "5869e98ef7446c9e2283e5788c0f6e2790676bdb52e9e1e112bb74e2415733c4" "5a3f33eefbcf2a3098bafd22d7ad44358e66c3e844797e7bf9ef552a08dfeb6f" default)))
+ '(delete-selection-mode nil)
+ '(electric-indent-mode t)
+ '(magit-commit-arguments (quote ("--all" "--verbose" "--signoff")))
+ '(magit-log-arguments (quote ("--graph" "--color" "--decorate" "-n256")))
+ '(markdown-command "/usr/bin/markdown-calibre")
+ '(package-selected-packages
+ (quote
+ (py-autopep8 elpy inf-ruby move-text git-timemachine debbugs async-await request emojify auctex diminish bats-mode bool-flip salt-mode flycheck-rust rust-playground rust-mode vue-mode coffee-mode json-reformat erc-hl-nicks emoji-cheat-sheet-plus helm-circe htmlize cmake-mode websocket markdown-mode go-mode magit evil-leader evil helm projectile org-eldoc evil-commentary yasnippet yaml-mode which-key web-mode wc-mode use-package terraform-mode smart-tabs-mode slim-mode scss-mode rainbow-delimiters php-mode org-evil olivetti mu4e-alert mmm-jinja2 markdown-preview-mode helm-projectile helm-ag go-eldoc go-add-tags flycheck evil-surround evil-org evil-numbers evil-mu4e evil-magit evil-args dockerfile-mode disable-mouse default-text-scale crux cmake-font-lock ag))))
+(custom-set-faces
+ ;; custom-set-faces was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ )
diff --git a/.emacs.d/gtkrc b/.emacs.d/gtkrc
new file mode 100644
index 0000000..19d2109
--- /dev/null
+++ b/.emacs.d/gtkrc
@@ -0,0 +1,5 @@
+style "emacsfont"
+{
+ font_name = "Droid Sans Mono Dotted for Powerline 10"
+}
+widget "*" style "emacsfont"
diff --git a/.emacs.d/init.el b/.emacs.d/init.el
new file mode 100644
index 0000000..4129a5c
--- /dev/null
+++ b/.emacs.d/init.el
@@ -0,0 +1,22 @@
+;; This file replaces itself with the actual configuration at first run.
+;; Idea and file taken from https://github.com/larstvei/dot-emacs.
+;;
+;; NOTE DO NOT MODIFY THIS FILE. All changes should go into init.org
+
+;; We can't tangle without org!
+(require 'org)
+
+;; Follow symlinks
+(setq vc-follow-symlinks t)
+
+;; Open the configuration
+(find-file (concat user-emacs-directory "init.org"))
+
+;; Tangle it
+(org-babel-tangle)
+
+;; Load it
+(load-file (concat user-emacs-directory "init.el"))
+
+;; Finally byte-compile it
+(byte-compile-file (concat user-emacs-directory "init.el"))
diff --git a/.emacs.d/init.org b/.emacs.d/init.org
new file mode 100644
index 0000000..66ed281
--- /dev/null
+++ b/.emacs.d/init.org
@@ -0,0 +1,2349 @@
+#+TITLE: mssola's GNU Emacs configuration
+#+AUTHOR: Miquel Sabaté Solà
+#+EMAIL: mikisabate@gmail.com
+#+BABEL: :cache yes
+#+PROPERTY: header-args :tangle ~/.emacs.d/init.el
+
+* Preface
+
+This is my attempt of getting my configuration organized with literate
+programming and =org-babel=. I took the workflow I'm following from [[https://github.com/larstvei][@larstvei]].
+The idea is that the =init.el= file will replace itself on the first execution
+with the tangled version of this file. This first version will also be
+byte-compiled. This means that all changes are to be made on the =init.org=
+file *always*. The initial contents of the =init.el= are:
+
+#+BEGIN_SRC elisp :tangle no
+;; We can't tangle without org!
+(require 'org)
+
+;; Follow symlinks
+(setq vc-follow-symlinks t)
+
+;; Open the configuration
+(find-file (concat user-emacs-directory "init.org"))
+
+;; Tangle it
+(org-babel-tangle)
+
+;; Load it
+(load-file (concat user-emacs-directory "init.el"))
+
+;; Finally byte-compile it
+(byte-compile-file (concat user-emacs-directory "init.el"))
+#+END_SRC
+
+There is no reason to track the init.el file, and no reason to change this
+file. In order to ensure this, make sure to apply the following command after
+cloning:
+
+#+BEGIN_SRC sh :tangle no
+git update-index --assume-unchanged emacs/init.el
+#+END_SRC
+
+Moreover, in order to avoid manually tangling and compiling the =init.org= file
+on each change, the following function is provided:
+
+#+BEGIN_SRC elisp
+(defun tangle-init ()
+ "If the current buffer is 'init.org' the code-blocks are
+ tangled, and the tangled file is compiled. Morever, an init.html is generated."
+
+ (when (or (equal (buffer-file-name)
+ (expand-file-name (concat user-emacs-directory "init.org")))
+ (string-suffix-p "dotfiles/emacs/init.org" (buffer-file-name)))
+
+ ;; Avoid running hooks when tangling
+ (let ((prog-mode-hook nil))
+ (org-babel-tangle)
+ (byte-compile-file (concat user-emacs-directory "init.el")))))
+
+(add-hook 'after-save-hook 'tangle-init)
+#+END_SRC
+
+* Introduction
+
+I'm using GNU Emacs 26, but everything should be working in GNU Emacs 24. There
+are some exceptions to this (e.g. webkit support), but these cases are
+individually handled.
+
+#+BEGIN_SRC elisp
+ (unless (>= emacs-major-version 25)
+ (error "Don't be a cheap bastard and upgrade to at least GNU Emacs 25"))
+#+END_SRC
+
+Temporarily reduce garbage collection so startup time is lower. Idea taken from
+[[https://github.com/purcell][@purcell]].
+
+#+BEGIN_SRC elisp
+ (defconst mssola-initial-gc-cons-threshold gc-cons-threshold
+ "Initial value of `gc-cons-threshold' at start-up time.")
+ (setq gc-cons-threshold (* 1024 1024 1024))
+ (add-hook 'after-init-hook
+ (lambda () (setq gc-cons-threshold mssola-initial-gc-cons-threshold)))
+#+END_SRC
+
+User name and email.
+
+#+BEGIN_SRC elisp
+(setq user-full-name "Miquel Sabaté Solà"
+ user-mail-address "mikisabate@gmail.com")
+#+END_SRC
+
+* Lisp packages
+** Custom packages
+
+Compile the =g.el= script and bind it to @@html:<kbd>M-g</kbd>@@.
+
+#+BEGIN_SRC elisp
+(if (file-exists-p (concat user-emacs-directory "lisp/g.elc"))
+ (load-file (concat user-emacs-directory "lisp/g.elc"))
+ (byte-compile-file (concat user-emacs-directory "lisp/g.el") t))
+(global-set-key (kbd "M-g") 'g)
+#+END_SRC
+
+** use-package
+
+Initialize package.
+
+#+BEGIN_SRC elisp
+(require 'package)
+
+(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")
+
+(add-to-list 'package-archives
+ '("melpa" . "http://melpa.milkbox.net/packages/") t)
+(add-to-list 'package-archives
+ '("melpa-stable" . "https://stable.melpa.org/packages/") t)
+
+(package-initialize)
+#+END_SRC
+
+I'm using use-package to handle my installed packages. I don't know if it's
+the best option or what because I haven't tested all the package managers
+for Emacs out there. After trying some custom functions to handle
+package-install, I decided on use-package because I feel more well-organized.
+
+#+BEGIN_SRC elisp
+(unless (package-installed-p 'use-package)
+ (package-refresh-contents)
+ (package-install 'use-package))
+
+(require 'use-package)
+#+END_SRC
+
+Some =use-package= calls require =diminish.el= to be available. So, let's
+require it here on the very top.
+
+#+BEGIN_SRC elisp
+(use-package diminish
+ :ensure t)
+#+END_SRC
+
+* General
+
+** GUI
+
+I like a minimalistic GUI. Because of this, almost all GUI elements have been
+disabled or tweaked in some custom way.
+
+The frame title is "<login>: <path>". If we are not editing a file, then the
+name of the buffer is displayed (e.g. "mssola: *scratch*").
+
+#+BEGIN_SRC elisp
+ (setq frame-title-format
+ '((:eval
+ (concat (user-real-login-name) ": "
+ (if (buffer-file-name)
+ (abbreviate-file-name (buffer-file-name))
+ "%b")))))
+#+END_SRC
+
+Disable the menu, scroll and tool bars. At the same time, enable line and column
+modes.
+
+#+BEGIN_SRC elisp
+ (menu-bar-mode -1)
+ (when (fboundp 'set-scroll-bar-mode)
+ (set-scroll-bar-mode nil))
+ (when (fboundp 'tool-bar-mode)
+ (tool-bar-mode -1))
+ (when (fboundp 'tooltip-mode)
+ (tooltip-mode 0))
+
+ (line-number-mode 1)
+ (column-number-mode 1)
+
+ ;; Nice scrolling
+ (setq scroll-margin 0
+ scroll-conservatively 100000
+ scroll-preserve-screen-position 1)
+#+END_SRC
+
+Relative line numbers support is builtin since GNU Emacs 26.1:
+
+#+BEGIN_SRC elisp
+(if (>= emacs-major-version 26)
+ (progn
+ (add-hook 'prog-mode-hook 'display-line-numbers-mode)
+ (setq display-line-numbers-type 'relative)
+ (global-set-key (kbd "C-c L") 'display-line-numbers-mode)))
+#+END_SRC
+
+** Basic editing configuration
+
+Use UTF-8 *always*.
+
+#+BEGIN_SRC elisp
+ (prefer-coding-system 'utf-8)
+ (set-default-coding-systems 'utf-8)
+ (set-terminal-coding-system 'utf-8)
+ (set-keyboard-coding-system 'utf-8)
+ (set-language-environment 'utf-8)
+#+END_SRC
+
+Some editing tweaks like tabs vs spaces, maximum column width, etc.
+
+#+BEGIN_SRC elisp
+ ;; Emacs modes typically provide a standard means to change the indentation
+ ;; width (e.g. c-basic-offset). Moreover, even though I prefer tabs over space,
+ ;; for most coding conventions this is not the case (e.g. ruby). For this
+ ;; reason, I will disable them by default and enabled them back for each
+ ;; specific case (e.g. C). I'm also using the smart-tabs-mode package, see
+ ;; below in the languages section.
+ (setq-default indent-tabs-mode nil)
+ (setq-default tab-width 4)
+
+ ;; Maximum 80 columns.
+ (setq-default fill-column 80)
+ (setq-default auto-fill-function 'do-auto-fill)
+
+ ;; Do not break lines
+ (set-default 'truncate-lines t)
+
+ ;; Delete the selection with a keypress.
+ (delete-selection-mode t)
+
+ ;; Remove whitespaces at the end of line
+ (add-hook 'before-save-hook 'delete-trailing-whitespace)
+
+ ;; Cursor
+ (blink-cursor-mode 0)
+ (global-hl-line-mode -1)
+ (show-paren-mode 1)
+#+END_SRC
+
+** Font and theme
+
+I'm using "Droid Sans Mono" simply because I've grown used to it.
+
+#+BEGIN_SRC elisp
+(defconst mssola-font
+ (if (string= system-type "darwin")
+ "Droid Sans Mono-12"
+ "Droid Sans Mono Dotted for Powerline-10")
+ "The font to be used.")
+
+(set-frame-font mssola-font)
+(add-to-list 'default-frame-alist `(font . ,mssola-font))
+
+; Emacs in daemon mode does not like `set-face-attribute` because this is only
+; applied if there is a frame in place, which doesn't happen when starting the
+; daemon. Thus, we should call that after the frame has been created (e.g. by
+; emacsclient).
+; See: https://lists.gnu.org/archive/html/help-gnu-emacs/2015-03/msg00016.html
+(add-hook 'after-make-frame-functions-hook
+ (lambda ()
+ (set-face-attribute 'default t :font mssola-font)))
+#+END_SRC
+
+I've hacked my own theme called [[https://github.com/mssola/soria][soria]]. This theme combines the vim theme
+[[http://www.vim.org/scripts/script.php?script_id=2140][xoria256]] with the [[http://opensuse.github.io/branding-guidelines/][openSUSE branding guidelines]].
+
+#+BEGIN_SRC elisp
+ (load-theme 'soria t)
+#+END_SRC
+
+When hacking your own theme, sometimes you want to know what face is the one
+that you see on the screen right now. This function from [[https://github.com/thblt/DotFiles][@thblt]] allows me to
+get exactly that:
+
+#+BEGIN_SRC elisp
+(defun mssola-face-at-point (pos)
+ "Writes a message with the name of the face at the current point. The POS
+ argument contains the current position of the cursor."
+
+ (interactive "d")
+
+ (let ((face (or (get-char-property (point) 'read-face-name)
+ (get-char-property (point) 'face))))
+ (if face (message "Face: %s" face) (message "No face at %d" pos))))
+
+(global-set-key (kbd "C-c f") 'mssola-face-at-point)
+#+END_SRC
+
+** General global key bindings
+
+Use kill-this-buffer instead of kill-buffer.
+
+#+BEGIN_SRC elisp
+ (global-set-key (kbd "C-x k") 'kill-this-buffer)
+#+END_SRC
+
+Disable C-z. It will later on be picked up by Evil's config as the escape
+sequence. This is here to make sure that it will be disabled even if Evil
+cannot be loaded due to some error.
+
+#+BEGIN_SRC elisp
+ (global-unset-key (kbd "C-z"))
+#+END_SRC
+
+Also disable the =C-x i= binding, since I've never used the default behavior,
+and it will be used as a prefix for inferior modes (e.g. /ielm/).
+
+#+BEGIN_SRC elisp
+ (global-unset-key (kbd "C-x i"))
+#+END_SRC
+
+Disable all the Fn keys.
+
+#+BEGIN_SRC elisp
+ (dotimes (i 12)
+ (global-unset-key (kbd (format "<f%d>" (+ i 1)))))
+#+END_SRC
+
+Disable overwrite-mode.
+
+#+BEGIN_SRC elisp
+ (define-key global-map [(insert)] nil)
+#+END_SRC
+
+Kill GNU Emacs by hitting =C-x r q= (mnemonic /Really quit/).
+
+#+BEGIN_SRC elisp
+ (global-set-key (kbd "C-x r q") 'kill-emacs)
+#+END_SRC
+
+** Others
+
+Revert buffers automatically when underlying files are changed externally.
+
+#+BEGIN_SRC elisp
+ (global-auto-revert-mode t)
+#+END_SRC
+
+Follow symlinks.
+
+#+BEGIN_SRC elisp
+ (setq vc-follow-symlinks t)
+#+END_SRC
+
+Remove the initial message from the scratch buffer.
+
+#+BEGIN_SRC elisp
+ (setq initial-scratch-message nil)
+#+END_SRC
+
+Never kill the scratch buffer, bury it instead.
+
+#+BEGIN_SRC elisp
+(defadvice kill-buffer (around kill-buffer-around-advice activate)
+ (let ((buffer-to-kill (ad-get-arg 0)))
+ (if (equal buffer-to-kill "*scratch*")
+ (bury-buffer)
+ ad-do-it)))
+
+(defadvice kill-this-buffer (around kill-buffer-around-advice activate)
+ (let ((buffer-to-kill (ad-get-arg 0)))
+ (if (equal buffer-to-kill "*scratch*")
+ (bury-buffer)
+ ad-do-it)))
+#+END_SRC
+
+No backups
+
+#+BEGIN_SRC elisp
+ (setq-default make-backup-files nil)
+ (setq-default auto-save-default nil)
+#+END_SRC
+
+But at least save the list of recently open files.
+
+#+BEGIN_SRC elisp
+(require 'recentf)
+
+(recentf-mode 1)
+(global-set-key "\C-x\ \C-r" 'recentf-open-files)
+
+; Save the list every 5 minutes
+(run-at-time nil (* 5 60) 'recentf-save-list)
+#+END_SRC
+
+No welcome screen
+
+#+BEGIN_SRC elisp
+ (setq-default inhibit-startup-message t)
+#+END_SRC
+
+Enable y/n answers
+
+#+BEGIN_SRC elisp
+ (fset 'yes-or-no-p 'y-or-n-p)
+#+END_SRC
+
+Let flyspell be performant.
+
+#+BEGIN_SRC elisp
+ (defvar flyspell-issue-message-flag nil)
+#+END_SRC
+
+Save custom-variables somewhere else.
+
+#+BEGIN_SRC elisp
+ (setq custom-file (expand-file-name "custom.el" user-emacs-directory))
+ (if (file-exists-p custom-file)
+ (load custom-file))
+#+END_SRC
+
+Disable audio notifications.
+
+#+BEGIN_SRC elisp
+(setq ring-bell-function 'ignore)
+#+END_SRC
+
+* Calendar
+
+We catalans start our weeks on Monday.
+
+#+BEGIN_SRC elisp
+ (defvar calendar-week-start-day 1)
+#+END_SRC
+
+Global key binding.
+
+#+BEGIN_SRC elisp
+ (global-set-key (kbd "M-c") 'calendar)
+#+END_SRC
+
+Fix some stuff for evil mode.
+
+#+BEGIN_SRC elisp
+(with-eval-after-load "calendar"
+ (with-eval-after-load "evil"
+ (evil-set-initial-state 'calendar-mode 'normal)
+ (evil-define-key 'normal calendar-mode-map
+ "j" 'calendar-forward-week
+ "k" 'calendar-backward-week
+ "b" 'calendar-backward-day
+ "h" 'calendar-backward-day
+ "l" 'calendar-forward-day
+ "w" 'calendar-forward-day
+ "q" 'calendar-exit
+ "\C-h" 'evil-window-left
+ "\C-l" 'evil-window-right
+ "\C-j" 'evil-window-down
+ "\C-k" 'evil-window-up
+ "\C-n" 'calendar-scroll-left-three-months
+ "\C-p" 'calendar-scroll-right-three-months)))
+#+END_SRC
+
+* General purpose defuns
+
+I want to read the latest news. That's why I define a function that downloads
+the =NEWS= file from the git server and then opens it in a buffer.
+
+#+BEGIN_SRC elisp
+ (defun mssola-view-emacs-latest-news ()
+ "Allow users to fetch the latest Emacs' NEWS file."
+ (interactive)
+
+ (url-copy-file
+ "http://git.savannah.gnu.org/cgit/emacs.git/plain/etc/NEWS"
+ "/tmp/emacs-news" t)
+
+ (find-file-read-only "/tmp/emacs-news" t))
+#+END_SRC
+
+Sometimes I want to debug my initialization time.
+
+#+BEGIN_SRC elisp
+ (defun emacs-init-time ()
+ "Redefine the `emacs-init-time' function so it is more detailed.
+ Idea taken from @purcell."
+
+ (interactive)
+ (let ((init-time
+ (float-time (time-subtract after-init-time before-init-time))))
+ (message "%.3fs" init-time)))
+#+END_SRC
+
+* Project
+
+First of all, load the silver searcher, which is a convenient and fast searcher.
+Ayo silver!
+
+#+BEGIN_SRC elisp
+ (use-package ag
+ :ensure t
+ :config
+
+ ; Avoid some disagreements between ag and evil.
+ (with-eval-after-load 'evil
+ (add-hook 'ag-mode-hook
+ (lambda ()
+ (define-key ag-mode-map (kbd "n") 'evil-search-next)
+ (define-key ag-mode-map (kbd "N") 'evil-search-previous)
+ (define-key ag-mode-map (kbd "gg") 'evil-goto-first-line))))
+ (setq ag-reuse-buffers t)
+ (setq ag-reuse-window t))
+#+END_SRC
+
+Then, for keeping up with my projects I use the Projectile + Helm combination.
+
+#+BEGIN_SRC elisp
+ (use-package projectile
+ :ensure t
+ :config
+ (projectile-mode 1))
+
+ (use-package helm
+ :ensure t
+ :config
+ (setq projectile-completion-system 'helm)
+
+ ; Allow the search pattern to be on the header. Taken from this Reddit thread:
+ ; https://www.reddit.com/r/emacs/comments/3asbyn/new_and_very_useful_helm_feature_enter_search/
+ (setq helm-echo-input-in-header-line t)
+
+ (defun helm-hide-minibuffer-maybe ()
+ "Hide the minibuffer if we are in a Helm session"
+
+ (when (with-helm-buffer helm-echo-input-in-header-line)
+ (let ((ov (make-overlay (point-min) (point-max) nil nil t)))
+ (overlay-put ov 'window (selected-window))
+ (overlay-put ov 'face (let ((bg-color (face-background 'default nil)))
+ `(:background ,bg-color :foreground ,bg-color)))
+ (setq-local cursor-type nil))))
+
+ (add-hook 'helm-minibuffer-set-up-hook 'helm-hide-minibuffer-maybe)
+ (setq helm-split-window-inside-p t)
+
+ ; Preview files with tab
+ (define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action)
+
+ ; Show available options
+ (define-key helm-map (kbd "C-a") 'helm-select-action)
+
+ ; Some vim-like bindings
+ (define-key helm-map (kbd "C-j") 'helm-next-line)
+ (define-key helm-map (kbd "C-k") 'helm-previous-line)
+
+ (global-set-key (kbd "M-x") 'helm-M-x)
+
+ (use-package helm-ag
+ :ensure t))
+
+ (use-package helm-projectile
+ :ensure t
+ :config
+ (helm-projectile-on)
+
+ ; Define M-p as a way to quickly list all the available projects.
+ (with-eval-after-load 'evil
+ (define-key evil-normal-state-map (kbd "M-p")
+ 'helm-projectile-switch-project)))
+#+END_SRC
+
+I use @@html:<kbd>C-p</kbd>@@ as the binding for listing relevant files. This
+binding works either by using =helm-projectile= or the regular =helm-find=
+function. As a final touch, this binding also works for listing channels in ERC
+buffers.
+
+#+BEGIN_SRC elisp
+(defun mssola-erc-helm-buffer-list ()
+ "Returns a list with the ERC buffers."
+ (mapcar 'buffer-name (erc-buffer-list)))
+
+(defconst mssola-helm-source-erc-channel-list
+ '((name . "ERC Channels")
+ (candidates . mssola-erc-helm-buffer-list)
+ (action . switch-to-buffer)))
+
+(defun mssola-erc-helm-switch-buffer ()
+ "Use helm to select an active ERC buffer."
+
+ (interactive)
+
+ (helm :sources '(mssola-helm-source-erc-channel-list)
+ :buffer "*helm-erc-channels*"))
+
+(defun mssola-find-file ()
+ "Call the proper Helm function for finding files."
+
+ (interactive)
+
+ (if (string= major-mode "erc-mode")
+ (mssola-erc-helm-switch-buffer)
+ (condition-case nil
+ (helm-projectile-find-file)
+ (error
+ (helm-find-files nil)))))
+
+(with-eval-after-load 'evil
+ (define-key evil-normal-state-map (kbd "C-p") 'mssola-find-file))
+#+END_SRC
+
+Similarly, =helm-ag= has two functions for applying =ag= on the project. I'm
+binding to @@html:<kbd>,a</kbd>@@ a function that calls to the proper function.
+
+#+BEGIN_SRC elisp
+ (defun mssola-helm-ag ()
+ "Call the right ag command for helm-ag."
+
+ (interactive)
+
+ (condition-case nil
+ (helm-ag-project-root)
+ (error (helm-ag))))
+
+ (with-eval-after-load 'evil-leader
+ (evil-leader/set-key "a" 'mssola-helm-ag))
+#+END_SRC
+
+* Edit
+
+In this section I define some useful packages for editing. First of all, one of
+the coolest packages out there is =undo-tree=. It allows you to navigate through
+the undo history in a tree (because GNU Emacs is cool and keeps track of undo
+actions in a tree structure instead of in a stack). This package is included in
+recent versions of GNU Emacs.
+
+#+BEGIN_SRC elisp
+(with-eval-after-load 'undo-tree
+ (global-undo-tree-mode 1)
+
+ (setq undo-tree-visualizer-diff t
+ undo-tree-visualizer-timestamps t
+ undo-tree-visualizer-relative-timestamps t)
+
+ (require 'diminish)
+ (diminish 'undo-tree-mode))
+#+END_SRC
+
+Another important package is =flycheck=, which is an on-the-fly syntax checking
+extension. This works with lots of languages with proper glue code.
+
+#+BEGIN_SRC elisp
+(use-package let-alist
+ :ensure t)
+
+(use-package flycheck
+ :ensure t
+ :diminish
+ :config
+ (add-hook 'after-init-hook 'global-flycheck-mode)
+
+ ;; Only show the errors buffer if it isn't there and if I'm saving the
+ ;; buffer.
+ (setq flycheck-emacs-lisp-load-path 'inherit)
+ (setq flycheck-check-syntax-automatically '(mode-enabled save))
+ (setq flycheck-display-errors-function
+ #'flycheck-display-error-messages-unless-error-list))
+#+END_SRC
+
+A recurring issue in speeches and presentations is that when showing something
+with your editor, you have to increase/decrease the fonts. I use the
+=default-text-scale= package for this.
+
+#+BEGIN_SRC elisp
+ (use-package default-text-scale
+ :ensure t
+ :config
+ (global-set-key (kbd "C-+") 'default-text-scale-increase)
+ (global-set-key (kbd "C--") 'default-text-scale-decrease))
+#+END_SRC
+
+Some languages use some delimiters a lot (e.g. lisp languages and
+parenthesis). For this reason I'm using the =rainbow-delimiters= package, which
+properly highlights each level in a different way (provided that your theme
+supports it).
+
+#+BEGIN_SRC elisp
+ (use-package rainbow-delimiters
+ :ensure t)
+#+END_SRC
+
+Enable =electric-pair-mode=, which automatically closes pairs like brackets:
+
+#+BEGIN_SRC elisp
+(electric-pair-mode 1)
+#+END_SRC
+
+I never use the mouse.
+
+#+BEGIN_SRC elisp
+(use-package disable-mouse
+ :ensure t
+ :config
+ (global-disable-mouse-mode)
+ (setq global-disable-mouse-mode-lighter ""))
+#+END_SRC
+
+Sometimes you begin typing a prefix, but then you forget the following
+chord. For this reason =which-key= was created. It will show the available
+commands for the current chord as a list.
+
+#+BEGIN_SRC elisp
+(use-package which-key
+ :ensure t
+ :diminish which-key-mode
+ :config
+ (which-key-mode))
+#+END_SRC
+
+For some modes it is important to count the number of words in the text. For
+this, we have =wc-mode=.
+
+#+BEGIN_SRC elisp
+ (use-package wc-mode
+ :ensure t)
+#+END_SRC
+
+Editing files as root is a bit of a pain because usually the root user doesn't
+have the same configuration as the current one, and attempting to do so can be
+messy. So, instead of that, we could advice the =find-file= function so if the
+file is not writable by the current user, then GNU Emacs will ask for editing
+this same file as root:
+
+#+BEGIN_SRC elisp
+(defadvice find-file (after find-file-sudo activate)
+ "Find file as root if necessary."
+ (if (and buffer-file-name
+ (not (file-writable-p buffer-file-name)))
+ (if (yes-or-no-p "Do you want to edit this file as root?")
+ (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name)))))
+#+END_SRC
+
+=YASnippet= allows people to define shortcuts for writing some common blocks.
+Moreover, it comes with a set of builtin snippets already. Since I don't
+remember some of these snippets, I've mapped @@html:<kbd>, h</kbd>@@ to
+=yas-describe-tables=, which shows the available snippets in another buffer.
+
+#+BEGIN_SRC elisp
+(use-package yasnippet
+ :ensure t
+ :diminish yas-minor-mode
+ :init (yas-global-mode)
+ :config
+ (yas-global-mode 1))
+#+END_SRC
+
+=bool-flip= is a very simple utility that toggles truthy/falsey values.
+
+#+BEGIN_SRC elisp
+(use-package bool-flip
+ :ensure t
+ :config
+ (global-set-key (kbd "C-c b") 'bool-flip-do-flip))
+#+END_SRC
+
+=move-text= is a small package that allows you to move lines with a
+keybinding. This might be feasible with Evil mode, but still this might help
+when you want to move lines and keep the default registry empty:
+
+#+BEGIN_SRC elisp
+(use-package move-text
+ :ensure t
+ :bind
+ (("M-k" . move-text-up)
+ ("M-j" . move-text-down)))
+#+END_SRC
+
+* Dired
+
+I use dired mode mainly for attaching document into emails. That being said,
+whenever I use it, I want basic evil movement.
+
+#+BEGIN_SRC elisp
+ (with-eval-after-load 'evil
+ (evil-add-hjkl-bindings dired-mode-map 'normal
+ (kbd "w") 'evil-forward-word-begin))
+#+END_SRC
+
+I also extend =dired= with some handy tweaks.
+
+#+BEGIN_SRC elisp
+(setq directory-free-space-args "-Pkh"
+ dired-dwim-target t
+ dired-omit-mode nil
+ dired-recursive-copies 'always
+ dired-recursive-deletes 'always
+ delete-old-versions t)
+#+END_SRC
+
+And now instruct dired mode how to attach files when using mu4e. This is taken
+from the [[https://www.djcbsoftware.nl/code/mu/mu4e/Dired.html#Dired][mu4e documentation]], and it's available by typing
+@@html:<kbd>C-c RET C-a</kbd>@@.
+
+#+BEGIN_SRC elisp
+ (require 'gnus-dired)
+
+ ;; Make the `gnus-dired-mail-buffers' function also work on message-mode derived
+ ;; modes, such as mu4e-compose-mode.
+ (defun gnus-dired-mail-buffers ()
+ "Return a list of active message buffers."
+
+ (let (buffers)
+ (save-current-buffer
+ (dolist (buffer (buffer-list t))
+ (set-buffer buffer)
+ (when (and (derived-mode-p 'message-mode)
+ (null message-sent-message-via))
+ (push (buffer-name buffer) buffers))))
+ (nreverse buffers)))
+
+ (setq gnus-dired-mail-mode 'mu4e-user-agent)
+ (add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode)
+#+END_SRC
+
+* Evil
+
+Forgive me, [[https://stallman.org/saint.html][Father]], for I have sinned. I've been exposed to modal editing
+through Vim, and that has changed how I view editing for the foreseeable future.
+Because of this, I use Evil. The following blocks include some heavy-lifting so
+Evil and GNU Emacs work without hitting each other, and it also includes some
+Evil extensions.
+
+First of all, let's define a function that will be called whenever Evil is loaded.
+
+#+BEGIN_SRC elisp
+(defun mssola-evil ()
+ "Configure evil mode."
+
+ ; We can safely remap <C-u> because the counting will be handled a-la Vim.
+ (define-key evil-normal-state-map (kbd "C-u") 'evil-scroll-up)
+
+ ; Make window navigation easier.
+ (define-key evil-normal-state-map (kbd "C-j") 'evil-window-down)
+ (define-key evil-normal-state-map (kbd "C-k") 'evil-window-up)
+ (define-key evil-normal-state-map (kbd "C-l") 'evil-window-right)
+ (define-key evil-normal-state-map (kbd "C-h") 'evil-window-left)
+
+ ; The window navigation tweaks effectively wipe out the help prefix, which
+ ; is bad. Fortunately we can workaround this by providing "M-h" as the new
+ ; help prefix. This prefix is only used in emacs mode to mark lines, which is
+ ; something already handled by Evil.
+ (define-key global-map (kbd "M-h") 'help-command)
+ (fset 'help-command help-map)
+
+ ; Go back to Emacs' bindings on beginning/end of line.
+ (eval-after-load "evil-maps"
+ (dolist (map '(evil-motion-state-map
+ evil-insert-state-map
+ evil-emacs-state-map))
+ (define-key (eval map) "\C-a" 'crux-move-beginning-of-line)
+ (define-key (eval map) "\C-e" 'end-of-line)))
+
+ ; I store macros on the <q> register for convenience, so I used to use the
+ ; <C-q> combo to execute this macro in Vim. In Emacs though, this combo is
+ ; reserved to a rather useful function, and I'd like to keep it that way. So,
+ ; now the mapping is set to <C-2> (mnemonic: where the @ symbol is). Moreover,
+ ; it's applied as many times as specified by the numeric prefix argument.
+ (define-key evil-normal-state-map (kbd "C-2")
+ (lambda (n)
+ (interactive "p")
+ (evil-execute-macro n "@q")))
+
+ ; C-s: switch to normal mode and save the buffer. I know :)
+ (define-key evil-normal-state-map (kbd "C-s") 'save-buffer)
+ (define-key evil-insert-state-map (kbd "C-s")
+ (lambda () (interactive) (save-buffer) (evil-force-normal-state))))
+#+END_SRC
+
+Now make sure that Evil is installed, and call the relevant configuration functions.
+
+#+BEGIN_SRC elisp
+(use-package evil
+ :ensure t
+ :config
+ (add-hook 'evil-mode-hook 'mssola-evil)
+ (evil-mode 1)
+
+ ;; C-z is unused and it's close to my beloved C-c. Since I don't want to mess
+ ;; with one of the most sacred Emacs prefixes, I'm moving to C-z.
+ (define-key key-translation-map (kbd "C-z") [escape])
+ (define-key evil-operator-state-map (kbd "C-z") 'keyboard-quit)
+
+ ;; Use the proper initial evil state for the following modes.
+ (evil-set-initial-state 'help-mode 'normal)
+ (evil-set-initial-state 'debugger-mode 'normal)
+ (evil-set-initial-state 'describe-mode 'normal)
+ (evil-set-initial-state 'Buffer-menu-mode 'normal)
+#+END_SRC
+
+If Evil was properly loaded, then make sure that the following Evil-related
+packages are installed and configured as well. I start by defining the
+=evil-leader= package, which brings the @@html:<kbd>leader</kbd>@@ feature from
+Vim into Evil.
+
+#+BEGIN_SRC elisp
+ (use-package evil-leader
+ :ensure t
+ :config
+ (global-evil-leader-mode)
+ (evil-leader/set-leader ",")
+ (setq evil-leader/in-all-states 1)
+ (evil-leader/set-key
+ "c" 'delete-window
+ "k" 'kill-buffer-and-window
+ "v" 'split-window-right
+ "V" (lambda () (interactive) (split-window-right) (other-window 1))
+ "f" 'flycheck-list-errors))
+#+END_SRC
+
+Another handy Vim plugin that has made it into Evil is =evil-surround=, which
+defines a new text object for surrounding characters (e.g. change a string from
+having double quotes with single quotes in a single command).
+
+#+BEGIN_SRC elisp
+ (use-package evil-surround
+ :ensure t
+ :config
+ (global-evil-surround-mode 1))
+#+END_SRC
+
+Next is another Vim plugin that has been ported to Evil: =evil-commentary=. This
+package defines a new motion for comments, which is bound to
+@@html:<kbd>gc</kbd>@@. So, for example, @@html:<kbd>gcc</kbd>@@ will comment
+the current line, regardless of the programming language.
+
+#+BEGIN_SRC elisp
+ (use-package evil-commentary
+ :ensure t
+ :config
+ (evil-commentary-mode t))
+#+END_SRC
+
+Another cool package is =evil-args= which defines the argument text object. This
+text object can be targeted with the =a= character, and we can move backward and
+forward through arguments with @@html:<kbd>H</kbd>@@ and @@html:<kbd>L</kbd>@@
+respectively.
+
+#+BEGIN_SRC elisp
+ (use-package evil-args
+ :ensure t
+ :config
+ ; Configuration taken from the documentation of evil-args.
+
+ ;; Bind evil-args text objects
+ (define-key evil-inner-text-objects-map "a" 'evil-inner-arg)
+ (define-key evil-outer-text-objects-map "a" 'evil-outer-arg)
+
+ ;; Bind evil-forward/backward-args
+ (define-key evil-normal-state-map "L" 'evil-forward-arg)
+ (define-key evil-normal-state-map "H" 'evil-backward-arg)
+ (define-key evil-motion-state-map "L" 'evil-forward-arg)
+ (define-key evil-motion-state-map "H" 'evil-backward-arg))
+#+END_SRC
+
+Last but not least, =evil-numbers= brings a couple of bindings available to Vim
+into Evil: @@html:<kbd>C-c +</kbd>@@ for increasing a number, and
+@@html:<kbd>C-c -</kbd>@@ for decreasing it.
+
+#+BEGIN_SRC elisp
+ (use-package evil-numbers
+ :ensure t
+ :config
+ (define-key evil-normal-state-map (kbd "C-c +") 'evil-numbers/inc-at-pt)
+ (define-key evil-normal-state-map (kbd "C-c -") 'evil-numbers/dec-at-pt)))
+#+END_SRC
+
+* Git
+
+A git porcelain for GNU Emacs. Even if I'm still using the git CLI, it's
+certainly useful for some common tasks (I guess that I still need some learning).
+
+#+BEGIN_SRC elisp
+(use-package magit
+ :ensure t
+ :config
+#+END_SRC
+
+Set some global key bindings for Magit.
+
+#+BEGIN_SRC elisp
+(global-set-key (kbd "C-x g") 'magit-status)
+(global-set-key (kbd "C-c l") 'magit-log-buffer-file)
+#+END_SRC
+
+And repair some key bindings from Evil mode.
+
+#+BEGIN_SRC elisp
+ (with-eval-after-load 'evil
+ (use-package evil-magit
+ :ensure t
+ :config
+
+ ; The magit + evil-magit combo messes up some chords, let's fix this.
+ (evil-define-key 'normal magit-mode-map
+ "\C-h" 'evil-window-left
+ "\C-l" 'evil-window-right
+ "\C-j" 'evil-window-down
+ "\C-k" 'evil-window-up))))
+#+END_SRC
+
+=git-timemachine= is a package that goes hand-in-hand with Magit, and it
+provides a very easy way to go through the history of a file (while providing
+ways of jumping into Magit):
+
+#+BEGIN_SRC elisp
+(use-package git-timemachine
+ :ensure t
+ :bind (("C-x t m" . git-timemachine-toggle)))
+#+END_SRC
+
+* Email
+
+I use [[http://www.djcbsoftware.nl/code/mu/][mu]] and [[http://www.djcbsoftware.nl/code/mu/mu4e.html][mu4e]] to manage my email. The configuration for this has been taken
+mainly from the documentation, plus some cool remarks on Reddit. This
+configuration makes quite some assumptions. Read the =emacs/README.org= file as
+provided in my [[https://github.com/mssola/dotfiles][dotfiles]] project to get more details.
+
+I'm using an RPM that I've built on [[https://build.opensuse.org/package/show/home:mssola/mu][OBS]] which installs mu4e globally.
+
+#+BEGIN_SRC elisp
+(unless (file-directory-p "/usr/share/emacs/site-lisp/mu4e")
+ (message "Skipping mu4e because it's not installed."))
+
+(when (file-directory-p "/usr/share/emacs/site-lisp/mu4e")
+ (add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")
+ (require 'mu4e)
+
+ (when (featurep 'mu4e)
+#+END_SRC
+
+Set =mu4e= as the default user agent. This will be picked up by =compose-mail=.
+
+#+BEGIN_SRC elisp
+(setq mail-user-agent 'mu4e-user-agent)
+#+END_SRC
+
+Diferent SMTP options that will be used for each context.
+
+#+BEGIN_SRC elisp
+ (setq message-send-mail-function 'smtpmail-send-it
+ mu4e-maildir (expand-file-name "~/.mail")
+ starttls-use-gnutls t)
+#+END_SRC
+
+After that, I am defining some functions that will be used in various parts of
+the configuration.
+
+#+BEGIN_SRC elisp
+(defun mssola-smtp (server port)
+ "Set SMTP variables depending on the given SERVER and PORT."
+
+ (require 'smtpmail)
+
+ (setq smtpmail-starttls-credentials '((server port nil nil))
+ smtpmail-auth-credentials (expand-file-name "~/.authinfo.gpg")
+ smtpmail-default-smtp-server server
+ smtpmail-smtp-server server
+ message-send-mail-function 'smtpmail-send-it
+ smtpmail-smtp-service port))
+
+; https://www.reddit.com/r/emacs/comments/47t9ec/share_your_mu4econtext_configs/d0fsih6
+(defun mu4e-message-maildir-matches (msg rx)
+ "Returns true if the maildir of MSG matches the given regexp RX."
+
+ (when rx
+ (if (listp rx)
+ ;; if rx is a list, try each one for a match
+ (or (mu4e-message-maildir-matches msg (car rx))
+ (mu4e-message-maildir-matches msg (cdr rx)))
+ ;; not a list, check rx
+ (string-match rx (mu4e-message-field msg :maildir)))))
+
+(defun suse-refile-folder (key)
+ "Returns the refile folder for the given SUSE account in the KEY arg"
+
+ (if (string= key "susecom")
+ (setq archives-dir "/Arxiu/")
+ (setq archives-dir "/Archives/"))
+ (concat "/" key archives-dir
+ (format-time-string "%Y" (current-time))))
+#+END_SRC
+
+Depending on the context, it's better a signature or another:
+
+#+BEGIN_SRC elisp
+(defun mssola-mu4e-signature (key)
+ "Returns a string containing the mail signature for the given KEY."
+
+ (if (string= key "ajuntament")
+ (concat
+ "Miquel Sabaté Solà,\n"
+ "Regidor de Joventut, Participació ciutadana i Transparència\n"
+ "\n"
+ "Ajuntament de Capellades\n"
+ "Carrer de Ramon Godó, 9, 08786 - Capellades\n"
+ "Tel. 93 801 10 01 – mòbil 677 12 72 07\n"
+ "sabatesm@capellades.cat\n")
+ (concat
+ "Miquel Sabaté Solà,\n"
+ "PGP: 4096R / 1BA5 3C7A C93D CA2A CFDF DA97 96BE 8C6F D89D 6565\n")))
+#+END_SRC
+
+Now it's time to define the different contexts that I have. Defining contexts
+this way is relatively new (since mu 0.9.16).
+
+#+BEGIN_SRC elisp
+(setq mu4e-contexts
+ `(
+ ;; GMail
+ ,(make-mu4e-context
+ :name "gmail"
+ :enter-func (lambda ()
+ (mu4e-message "Switching to gmail.com")
+ (setq mu4e-compose-signature (mssola-mu4e-signature "gmail"))
+ (setq mu4e-sent-messages-behavior 'delete)
+ (mssola-smtp "smtp.gmail.com" 587))
+ :match-func (lambda (msg)
+ (when msg
+ (mu4e-message-maildir-matches msg "^/gmail")))
+ :vars '(
+ (user-mail-address . "mikisabate@gmail.com")
+ (mu4e-reply-to-address . "mikisabate@gmail.com")
+ (mu4e-drafts-folder . "/gmail/Drafts")
+ (mu4e-sent-folder . "/gmail/Sent")
+ (mu4e-refile-folder . "/gmail/All")
+ (mu4e-trash-folder . "/gmail/Trash")))
+
+ ;; City hall
+ ,(make-mu4e-context
+ :name "ajuntament"
+ :enter-func (lambda ()
+ (mu4e-message "Switching to mail.diba.cat")
+ (setq mu4e-compose-signature (mssola-mu4e-signature "ajuntament"))
+ (setq mu4e-sent-messages-behavior 'sent)
+ (mssola-smtp "mail.diba.cat" 587)
+ (setq smtpmail-local-domain "capellades.cat"))
+ :match-func (lambda (msg)
+ (when msg
+ (mu4e-message-maildir-matches msg "^/ajuntament")))
+ :vars '(
+ (user-mail-address . "sabatesm@capellades.cat")
+ (mu4e-reply-to-address . "sabatesm@capellades.cat")
+ (mu4e-drafts-folder . "/ajuntament/Esborranys")
+ (mu4e-sent-folder . "/ajuntament/Elements enviats")
+ (mu4e-refile-folder . "/ajuntament/Arxiu")
+ (mu4e-trash-folder . "/ajuntament/Elements suprimits")))
+
+ ;; suse.com
+ ,(make-mu4e-context
+ :name "comsuse"
+ :enter-func (lambda ()
+ (mu4e-message "Switching to suse.com")
+ (setq mu4e-compose-signature (mssola-mu4e-signature "comsuse"))
+ (setq mu4e-sent-messages-behavior 'sent)
+ (mssola-smtp "smtp.office365.com" 587))
+ :match-func (lambda (msg)
+ (when msg
+ (mu4e-message-maildir-matches msg "^/susecom")))
+ :vars `(
+ (user-mail-address . "msabate@suse.com")
+ (mu4e-reply-to-address . "msabate@suse.com")
+ (mu4e-drafts-folder . "/susecom/Esborranys")
+ (mu4e-sent-folder . "/susecom/Elements enviats")
+ (mu4e-refile-folder . ,(suse-refile-folder "susecom"))
+ (mu4e-trash-folder . "/susecom/Elements suprimits")))
+
+ ;; suse.de
+ ,(make-mu4e-context
+ :name "desuse"
+ :enter-func (lambda ()
+ (mu4e-message "Switching to suse.de")
+ (setq mu4e-compose-signature (mssola-mu4e-signature "desuse"))
+ (setq mu4e-sent-messages-behavior 'sent)
+ (mssola-smtp "imap.suse.de" 587))
+ :match-func (lambda (msg)
+ (when msg
+ (mu4e-message-maildir-matches msg "^/susede")))
+ :vars `(
+ (user-mail-address . "msabate@suse.de")
+ (mu4e-reply-to-address . "msabate@suse.de")
+ (mu4e-drafts-folder . "/susede/Drafts")
+ (mu4e-sent-folder . "/susede/Sent")
+ (mu4e-refile-folder . ,(suse-refile-folder "susede"))
+ (mu4e-trash-folder . "/susede/Trash")))))
+#+END_SRC
+
+If mu4e cannot figure things out, ask me.
+
+#+BEGIN_SRC elisp
+ (setq mu4e-context-policy 'ask)
+ (setq mu4e-compose-context-policy 'ask)
+#+END_SRC
+
+Fill the =mu4e-user-mail-address-list= variable with the contexts.
+
+#+BEGIN_SRC elisp
+ (setq mu4e-user-mail-address-list
+ (delq nil
+ (mapcar (lambda (context)
+ (when (mu4e-context-vars context)
+ (cdr (assq 'user-mail-address
+ (mu4e-context-vars context)))))
+ mu4e-contexts)))
+#+END_SRC
+
+Setting my bookmarks
+
+#+BEGIN_SRC elisp
+(setq mu4e-bookmarks
+ '(("maildir:/gmail/inbox OR maildir:/susecom/inbox OR maildir:/susede/inbox OR maildir:/ajuntament/inbox" "Inbox Folders" ?n)
+ ("maildir:/gmail/Sent OR maildir:/susecom/Elements\\ enviats OR maildir:/susede/Sent OR maildir:/ajuntament/Elements\\ enviats" "Sent Folders" ?s)
+ ("flag:unread AND NOT flag:trashed" "Unread messages" ?u)
+ ("date:today..now" "Today's messages" ?t)))
+#+END_SRC
+
+Sign outgoing emails always.
+
+#+BEGIN_SRC elisp
+ (add-hook 'message-send-hook 'mml-secure-message-sign-pgpmime)
+#+END_SRC
+
+To avoid UID clashes. See [[http://pragmaticemacs.com/emacs/fixing-duplicate-uid-errors-when-using-mbsync-and-mu4e/][this]].
+
+#+BEGIN_SRC elisp
+ (setq mu4e-change-filenames-when-moving t)
+#+END_SRC
+
+Miscellaneous settings.
+
+#+BEGIN_SRC elisp
+(setq mu4e-html2text-command "w3m -T text/html"
+ mu4e-attachment-dir "~/Downloads"
+ mu4e-headers-date-format "%Y-%m-%d %H:%M"
+ message-citation-line-format "%N @ %Y-%m-%d %H:%M %Z:\n"
+ message-citation-line-function 'message-insert-formatted-citation-line
+ message-kill-buffer-on-exit t
+ mu4e-get-mail-command "mbsync -aqV"
+ mu4e-update-interval 600
+ mu4e-compose-dont-reply-to-self t
+ mu4e-compose-format-flowed t
+ mu4e-view-show-addresses t
+ mu4e-headers-skip-duplicates t
+ mu4e-headers-include-related t
+ mu4e-headers-auto-update t)
+#+END_SRC
+
+The headers to show in the headers list a pair of a field and its width,
+with `nil' meaning 'unlimited' (better only use that for the last field.
+These are the defaults:
+
+#+BEGIN_SRC elisp
+ (setq mu4e-headers-fields
+ '( (:date . 18)
+ (:mailing-list . 15)
+ (:from-or-to . 20)
+ (:subject . nil)))
+#+END_SRC
+
+Add as a header action to toggle gnus mode for the view mode. I'm doing this
+because this is way better to visualize attached .eml emails.
+
+#+BEGIN_SRC elisp
+(defun mssola-toggle-gnus-mode (msg)
+ "Toggle gnus on view mode from now on."
+ (if mu4e-view-use-gnus
+ (setq mu4e-view-use-gnus nil)
+ (setq mu4e-view-use-gnus t)))
+
+(add-to-list 'mu4e-headers-actions
+ '("gnus mode toggle" . mssola-toggle-gnus-mode) t)
+#+END_SRC
+
+Show images
+
+#+BEGIN_SRC elisp
+ (setq mu4e-view-show-images t
+ mu4e-view-image-max-width 800)
+
+ ; Use imagemagick, if available
+ (when (fboundp 'imagemagick-register-types)
+ (imagemagick-register-types))
+#+END_SRC
+
+Correct some key bindings that are screwed up by =evil-mode=:
+
+#+BEGIN_SRC elisp
+(evil-define-key 'normal mu4e-view-mode-map
+ ";" 'mu4e-context-switch
+ "e" 'mu4e-view-save-attachment
+ "F" 'mu4e-compose-forward)
+#+END_SRC
+
+As of 0.9.18 and GNU Emacs 25, the =mu4e-action-with-xwidget= can be used to
+render an HTML message with Webkit.
+
+#+BEGIN_SRC elisp
+ (if (>= emacs-major-version 25)
+ (add-to-list 'mu4e-view-actions
+ '("webkit" . mu4e-action-view-with-xwidget)))
+#+END_SRC
+
+Look for =mu4e-msg2pdf= in the exec path. The reason for this is that the OBS
+package installs mu's =toys= into the exec path, but =mu4e= doesn't really count
+on it.
+
+#+BEGIN_SRC elisp
+ (let ((exec (locate-file "msg2pdf" exec-path exec-suffixes)))
+ (if exec
+ (setq mu4e-msg2pdf exec)))
+#+END_SRC
+
+Adding hooks for composing and viewing messages.
+
+#+BEGIN_SRC elisp
+ (defun mssola-compose-mode ()
+ "My settings for message composition."
+
+ ; If we are composing an email from scratch, it's more convenient to be in
+ ; insert mode. Otherwise start with normal mode.
+ (with-eval-after-load 'evil
+ (if mu4e-compose-parent-message
+ (evil-set-initial-state 'mu4e-compose-mode 'normal)
+ (evil-set-initial-state 'mu4e-compose-mode 'insert)))
+
+ ; Guess hard newlines
+ (use-hard-newlines t 'guess)
+
+ ; So it's easy to encrypt/decrypt emails.
+ (epa-mail-mode)
+
+ ; Spellz
+ (flyspell-mode))
+
+ (add-hook 'mu4e-compose-mode-hook 'mssola-compose-mode)
+
+ ; I want to read messages in the format that the sender used. I'm also
+ ; enabling epa-mail-mode, so it's easy to decrypt received emails.
+ (add-hook 'mu4e-view-mode-hook
+ (lambda ()
+ (epa-mail-mode)
+ (visual-line-mode 1)))
+#+END_SRC
+
+I want desktop notifications when receiving email.
+
+#+BEGIN_SRC elisp
+ (use-package mu4e-alert
+ :ensure t
+ :config
+
+ ; Notify me for unread emails from my inbox.
+ (mu4e-alert-set-default-style 'libnotify)
+ (add-hook 'after-init-hook #'mu4e-alert-enable-notifications)
+ (add-hook 'after-init-hook #'mu4e-alert-enable-mode-line-display)
+ (setq mu4e-alert-interesting-mail-query
+ (concat
+ "(maildir:/gmail/inbox OR maildir:/susecom/inbox OR maildir:/susede/inbox OR maildir:/ajuntament/inbox) "
+ "AND flag:unread AND NOT flag:trashed"))
+ (setq mu4e-alert-email-notification-types '(count)))
+
+ ; Evil mode in mu4e
+ (with-eval-after-load 'evil
+ (use-package evil-mu4e
+ :ensure t
+ :config
+
+ ; Idea taken from evil-mu4e.el
+ (defvar mssola-evil-mu4e-mode-map-bindings
+ `((,evil-mu4e-state mu4e-headers-mode-map "\C-u" evil-scroll-up)
+ (,evil-mu4e-state mu4e-main-mode-map "\C-u" evil-scroll-up)
+ (,evil-mu4e-state mu4e-view-mode-map "h" evil-backward-char)))
+
+ (dolist (binding mssola-evil-mu4e-mode-map-bindings)
+ (evil-define-key
+ (nth 0 binding) (nth 1 binding) (nth 2 binding) (nth 3 binding)))))
+#+END_SRC
+
+And finally define a proper shortcut.
+
+#+BEGIN_SRC elisp
+ ; The trailing parenthesis closes the "(when (featurep 'mu4e)" statement from
+ ; the very beginning.
+ (global-set-key (kbd "C-c m") 'mu4e)))
+#+END_SRC
+
+* org
+
+** TODO org template for creating "article" and similar stuff
+
+[[http://orgmode.org/][org mode]] is an incredible tool that keeps me organized: TODOs, notes, agenda,
+etc. Moreover, it's built in GNU Emacs:
+
+#+BEGIN_SRC elisp
+(require 'org)
+#+END_SRC
+
+** General settings
+
+First of all, let me define some helper functions.
+
+#+BEGIN_SRC elisp
+ (defun mssola-org-skip-if-priority (priority &optional subtree)
+ "Skip an agenda item if it has a priority of PRIORITY.
+ PRIORITY may be one of the characters ?A, ?B, or ?C.
+ Skips the current entry unless SUBTREE is not nil. This function has been
+ copied from @aaronbieber."
+
+ (let ((end (if subtree (save-excursion (org-end-of-subtree t))
+ (save-excursion (progn (outline-next-heading) (1- (point))))))
+ (pri-value (* 1000 (- org-lowest-priority priority)))
+ (pri-current (org-get-priority (thing-at-point 'line t))))
+ (if (= pri-value pri-current)
+ end
+ nil)))
+
+ (defun mssola-org-skip-if-not-closed-in-day (time &optional subtree)
+ "Skip entries that were not closed in the given TIME.
+ Skip the current entry unless SUBTREE is not nil, in which case skip
+ the entire subtree. Idea taken from @aaronbieber"
+
+ (let ((end (if subtree (save-excursion (org-end-of-subtree t))
+ (save-excursion (progn (outline-next-heading) (1- (point))))))
+ (day-prefix (format-time-string "%Y-%m-%d" time)))
+
+ (if (save-excursion
+ (and (re-search-forward org-closed-time-regexp end t)
+ (string= (substring (match-string-no-properties 1) 0 10) day-prefix)))
+ nil
+ end)))
+#+END_SRC
+
+Some general UI settings for org mode.
+
+#+BEGIN_SRC elisp
+(setq org-src-tab-acts-natively t
+ org-confirm-babel-evaluate nil
+ org-edit-src-content-indentation 0)
+
+(setq org-todo-keywords
+ '((sequence "TODO(t)" "|" "DONE(d!)")
+ (sequence "IDEA(i)" "WORKING(w)" "|" "USED(u@/!)" "DISCARDED(x@/!)")))
+
+(setq org-todo-keyword-faces
+ '(("TODO" . org-todo)
+ ("IDEA" . font-lock-constant-face)
+ ("WORKING" . font-lock-constant-face)
+ ("DONE" . org-done)
+ ("USED" . org-done)
+ ("DISCARDED" . org-done)))
+#+END_SRC
+
+Logging settings.
+
+#+BEGIN_SRC elisp
+ (setq org-log-done t)
+ (setq org-log-redeadline (quote time))
+ (setq org-log-reschedule (quote time))
+#+END_SRC
+
+Where org files reside.
+
+#+BEGIN_SRC elisp
+ (setq org-agenda-files '("~/org/"))
+#+END_SRC
+
+** Publishing
+
+In order to publish files into HTML, I would like to have =htmlize= installed.
+This package allows org to export to HTML in a better way (e.g. allowing code
+blocks to be converted into HTML as well, so we can properly colorize it).
+
+#+BEGIN_SRC elisp
+(use-package htmlize
+ :ensure t)
+#+END_SRC
+
+And now let's set all the related settings.
+
+#+BEGIN_SRC elisp
+(setq org-src-fontify-natively t
+ org-html-include-timestamps nil
+ org-html-toplevel-hlevel 2
+ org-html-htmlize-output-type 'css
+ org-export-with-section-numbers nil
+ org-export-with-sub-superscripts nil
+ org-export-htmlize-output-type 'css)
+#+END_SRC
+
+Make sure to use the proper template when exporting to ODT:
+
+#+BEGIN_SRC elisp
+(setq org-odt-styles-file "~/Documents/Templates/mssola.ott")
+#+END_SRC
+
+Sometimes it's useful to export to LaTeX. That is, when you are simply writing a
+quick document that will end up being converted into LaTeX and finally into PDF:
+
+#+BEGIN_SRC elisp
+(require 'ox-latex)
+
+(unless (boundp 'org-latex-classes)
+ (setq org-latex-classes nil))
+
+(add-to-list 'org-latex-classes
+ '("article"
+ "\\documentclass{article}"
+ ("\\section{%s}" . "\\section*{%s}")
+ ("\\subsection{%s}" . "\\subsection*{%s}")
+ ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
+ ("\\paragraph{%s}" . "\\paragraph*{%s}")
+ ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
+#+END_SRC
+
+You can also export org documents to man pages. In order to do so, you have to
+perform this first:
+
+#+BEGIN_SRC elisp
+(require 'ox-man)
+#+END_SRC
+
+Setup a function to toggle =org-publish-current-file= on save:
+
+#+BEGIN_SRC elisp
+(defun toggle-org-publish-current-file-on-save ()
+ (interactive)
+ (if (memq 'org-publish-current-file after-save-hook)
+ (progn
+ (remove-hook 'after-save-hook 'org-publish-current-file t)
+ (message "Disabled org-publish-current-file for current buffer..."))
+ (add-hook 'after-save-hook 'org-publish-current-file nil t)
+ (message "Enabled org-publish-current-file for current buffer...")))
+#+END_SRC
+
+Also hide the "Footnotes: " title on footnotes:
+
+#+BEGIN_SRC elisp
+(setq org-html-footnotes-section "<div id=\"footnotes\">
+<!-- Hack: %s -->
+<div id=\"text-footnotes\">
+%s
+</div>
+</div>")
+#+END_SRC
+
+Last but not least, some handy shortcuts:
+
+#+BEGIN_SRC elisp
+(with-eval-after-load "org"
+ (define-key org-mode-map (kbd "<f1>") 'org-latex-export-to-pdf)
+ (define-key org-mode-map (kbd "<f2>") 'org-odt-export-to-odt))
+#+END_SRC
+
+** Agenda
+
+Custom commands for =org-agenda=.
+
+#+BEGIN_SRC elisp
+ (setq org-agenda-custom-commands
+ '(("p" "Printed agenda"
+ ; Daily agenda with a 2-weeks deadline warning. Tasks are
+ ; represented as [ ] items.
+ ((agenda ""
+ ((org-agenda-ndays 1)
+ (org-deadline-warning-days 14)
+ (org-agenda-todo-keyword-format "[ ]")
+ (org-agenda-scheduled-leaders '("" ""))))
+
+ ; Display a "High Priority" list of tasks on top.
+ (tags "PRIORITY=\"A\""
+ ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
+ (org-agenda-sorting-strategy '(tag-up priority-down))
+ (org-agenda-todo-keyword-format "")
+ (org-agenda-overriding-header "\nHigh priority\n--------------\n")))
+
+
+ ; All tasks except those already listed as high priority or
+ ; ideas. Scheduled and deadlines are also ignored here.
+ (alltodo ""
+ ((org-agenda-skip-function '(or (mssola-org-skip-if-priority ?A)
+ (org-agenda-skip-entry-if 'todo '("IDEA" "WORKING"))
+ (org-agenda-skip-if nil '(scheduled deadline))))
+ (org-agenda-sorting-strategy '(tag-up priority-down))
+ (org-agenda-todo-keyword-format "")
+ (org-agenda-overriding-header "\nAll tasks\n----------\n")))
+
+ ; List of ideas.
+ (todo "IDEA"
+ ((org-agenda-overriding-header "\nIdeas\n------\n")
+ (org-agenda-todo-keyword-format ""))))
+
+ ((org-agenda-compact-blocks t)
+ (org-agenda-remove-tags t)))
+
+ ; List of done items. Useful for standups, review meetings, weekly
+ ; reports, etc.
+ ("d" "Done items"
+ ; First show the items done yesterday. Useful for standups.
+ ((todo "DONE"
+ ((org-agenda-overriding-header "Done yesterday\n---------------\n")
+ (org-agenda-skip-function
+ '(mssola-org-skip-if-not-closed-in-day
+ (time-subtract (current-time) (seconds-to-time 86400))))
+ (org-agenda-todo-keyword-format "")))
+
+ ; Then show what I've done today.
+ (todo "DONE"
+ ((org-agenda-overriding-header "\nDone today\n-----------\n")
+ (org-agenda-skip-function
+ '(mssola-org-skip-if-not-closed-in-day
+ (current-time)))
+ (org-agenda-todo-keyword-format "")))
+
+ ; Finally show what I've been doing in the past 15 days. Useful for
+ ; review meetings and weekly reports.
+ (todo "DONE"
+ ((org-agenda-start-day "-15d")
+ (org-agenda-span 15)
+ (org-agenda-start-on-weekday nil)
+ (org-agenda-todo-keyword-format "")
+ (org-agenda-scheduled-leaders '("" ""))
+ (org-agenda-overriding-header "\nDone during the past 15 days\n-----------------------------\n"))))
+
+ ((org-agenda-compact-blocks t)
+ (org-agenda-remove-tags t)))))
+#+END_SRC
+
+The prefix for the different kinds of types being used.
+
+#+BEGIN_SRC elisp
+ (setq org-agenda-prefix-format '((agenda . "%t%s")
+ (tags . "%c:%s")
+ (todo . "%c:%t%s")))
+#+END_SRC
+
+Set up a key binding for org-agenda.
+
+#+BEGIN_SRC elisp
+(global-set-key (kbd "C-c a") 'org-agenda)
+#+END_SRC
+
+** Capture
+
+Set the default notes file and the key binding.
+
+#+BEGIN_SRC elisp
+(setq org-default-notes-file (concat org-directory "/notes.org"))
+(define-key global-map "\C-cc" 'org-capture)
+#+END_SRC
+
+And finally set =org-capture-templates=.
+
+#+BEGIN_SRC elisp
+(setq org-capture-templates
+ `(("t" "todo" entry (file "") "* TODO %?\n%U\n")
+ ("i" "idea" entry (file "") "* %? :IDEA:\n%U\n%a\n")))
+#+END_SRC
+
+** Publish project
+
+I write blog posts with org-mode. Here's the trick:
+
+#+BEGIN_SRC elisp
+(setq org-publish-project-alist
+ '(("org-mssola"
+ ;; Path to your org files.
+ :base-directory "~/src/mssola/jo/org/"
+ :base-extension "org"
+
+ ;; Path to your Jekyll project.
+ :publishing-directory "~/src/mssola/jo/_i18n"
+ :recursive t
+ :publishing-function org-html-publish-to-html
+ :headline-levels 4
+ :html-extension "html"
+ :body-only t ;; Only export section between <body> </body>
+ )
+
+ ("mssola" :components ("org-mssola"))))
+#+END_SRC
+
+** Other
+
+Insert a <kbd></kbd> value in org mode. See this [[http://emacs.stackexchange.com/questions/2206/i-want-to-have-the-kbd-tags-for-my-blog-written-in-org-mode][StackExchange answer]].
+
+#+BEGIN_SRC elisp
+(defun endless/insert-key (key)
+ "Ask for a key then insert its description.
+Will work on both org-mode and any mode that accepts plain html."
+ (interactive "kType key sequence: ")
+ (let* ((is-org-mode (derived-mode-p 'org-mode))
+ (tag (if is-org-mode
+ "@@html:<kbd>%s</kbd>@@"
+ "<kbd>%s</kbd>")))
+ (if (null (equal key "\r"))
+ (insert
+ (format tag (help-key-description key nil)))
+ (insert (format tag ""))
+ (forward-char (if is-org-mode -8 -6)))))
+
+(define-key org-mode-map "\C-ck" #'endless/insert-key)
+#+END_SRC
+
+Define profiles.
+
+#+BEGIN_SRC elisp
+;; Variables
+
+(defvar mssola-org-profiles
+ '(("minimal" . mssola-org-minimal)
+ ("monthly" . mssola-org-monthly))
+ "Defined profiles for organization matters.")
+
+(defvar mssola-org-default-profile "minimal"
+ "The default profile for mssola-org.")
+
+;; Profiles
+
+(defun mssola-org-minimal ()
+ "Load a minimal set of files."
+ (find-file (concat (file-name-as-directory org-directory) "setmana.org")))
+
+(defun mssola-org-monthly ()
+ "Load a set of files useful for monthly planning."
+ (find-file (concat (file-name-as-directory org-directory) "setmana.org"))
+ (split-window-right)
+ (windmove-right)
+ (find-file (concat (file-name-as-directory org-directory) "any.org"))
+ (windmove-left))
+
+;; Functions
+
+(defun mssola-org (&optional profile)
+ "Setup a frame for organizational matters.
+PROFILE is the profile to be picked when given. If it's not given, then the
+user will be prompted to provide it."
+ (interactive)
+
+ (delete-other-windows)
+ (unless profile
+ (setq profile (completing-read "Give me the profile: "
+ (mapcar 'car mssola-org-profiles) nil t)))
+ (funcall (cdr (assoc profile mssola-org-profiles))))
+
+(defun mssola-org-default ()
+ "Setup a frame for organizational matters given a default profile has been set."
+ (interactive)
+
+ (mssola-org mssola-org-default-profile))
+
+(define-key global-map (kbd "C-c C-o") #'mssola-org-default)
+(define-key global-map (kbd "C-c M-o") #'mssola-org)
+#+END_SRC
+
+** TODO shortcut for making an org link, and transforming a link into a proper org link
+** TODO make it work with evil
+** TODO Proper keybindings for quick access.
+
+** TODO shortcuts for stuff like: create something urgent for today
+
+* IRC
+
+I'm using [[https://www.gnu.org/software/emacs/manual/html_mono/erc.html][ERC]] for IRC.
+
+#+BEGIN_SRC elisp
+(use-package erc
+ :config
+#+END_SRC
+
+First of all, let's add some basic modules.
+
+#+BEGIN_SRC elisp
+ (dolist (mod '(autojoin track truncate))
+ (add-to-list 'erc-modules mod))
+#+END_SRC
+
+Setting up basic stuff.
+
+#+BEGIN_SRC elisp
+ (setq erc-hide-list '("PART")
+ erc-prompt (lambda () (concat (buffer-name) ">"))
+ erc-track-exclude-types '("JOIN" "NICK" "PART" "QUIT" "MODE")
+ erc-server-coding-system '(utf-8 . utf-8)
+ erc-kill-buffer-on-part t
+ erc-kill-queries-on-quit t
+ erc-kill-server-buffer-on-quit t
+ erc-fill-column 100
+ erc-fill-prefix ""
+ erc-timestamp-format "[%H:%M] "
+ erc-insert-timestamp-function 'erc-insert-timestamp-left
+ erc-insert-away-timestamp-function 'erc-insert-timestamp-left
+ erc-hide-timestamps nil
+ erc-whowas-on-nosuchnick t
+ erc-public-away-p nil
+ erc-echo-notice-always-hook '(erc-echo-notice-in-minibuffer)
+ erc-auto-set-away nil
+ erc-autoaway-message "%i seconds out..."
+ erc-away-nickname "msabate"
+ erc-enable-logging t
+ erc-query-on-unjoined-chan-privmsg t)
+#+END_SRC
+
+Let's log messages whenever I receive/send them. The other option is to only do
+that on =/quit= or =/part=, but it's better to be safe than sorry.
+
+#+BEGIN_SRC elisp
+ (require 'erc-log)
+ (erc-log-enable)
+
+ (setq erc-log-channels-directory "~/.emacs.d/erc"
+ erc-save-buffer-on-part nil
+ erc-save-queries-on-quit nil
+ erc-log-write-after-send t
+ erc-log-write-after-insert t)
+#+END_SRC
+
+Servers and channels to auto-join.
+
+#+BEGIN_SRC elisp
+ (setq erc-autojoin-channels-alist
+ '(("irc.freenode.net" "#gnu" "#emacs")
+ ("irc.nue.suse.com" "#suse" "#docker")))
+#+END_SRC
+
+Use the =erc-hl-nicks= package, so highlight support for nicknames is better.
+
+#+BEGIN_SRC elisp
+(use-package erc-hl-nicks
+ :ensure t
+ :init
+ (with-eval-after-load 'erc
+ (add-to-list 'erc-modules 'hl-nicks)))
+#+END_SRC
+
+I want to have a desktop notification whenever someone mentions my name. For
+this, I'm using the =erc-notifications= package which is built in ERC since
+GNU Emacs 24.3.
+
+#+BEGIN_SRC elisp
+(with-eval-after-load 'erc
+ (setq erc-notifications-icon
+ (concat
+ "/usr/share/emacs/"
+ (format "%s.%s" emacs-major-version emacs-minor-version)
+ "/etc/images/icons/hicolor/24x24/apps/emacs.png"))
+ (add-to-list 'erc-modules 'notifications))
+#+END_SRC
+
+At this point, we can safely update all the loaded ERC modules.
+
+#+BEGIN_SRC elisp
+ (add-hook 'erc-connect-pre-hook
+ (lambda (x) (erc-update-modules)))
+#+END_SRC
+
+Start some modules which won't do it by default. Moreover, according to the [[https://www.emacswiki.org/emacs/ErcFilling][wiki]]
+=auto-fill-mode= should be disabled if I'm using =erc-fill-mode=.
+
+#+BEGIN_SRC elisp
+ (add-hook 'erc-mode-hook
+ '(lambda ()
+ (erc-track-mode t)
+ (auto-fill-mode -1)
+ (erc-log-mode 1)
+ (erc-autojoin-mode 1)))
+#+END_SRC
+
+And now define a function to connect to both IRC servers.
+
+#+BEGIN_SRC elisp
+ (defun mssola-erc ()
+ "Join pre-specified servers and channels."
+
+ (interactive)
+
+ (erc :server "irc.freenode.net" :port 6667 :nick "mssola")
+ (erc-tls :server "irc.nue.suse.com" :port 6697 :nick "mssola"))
+
+ (global-set-key (kbd "C-c i") 'mssola-erc))
+#+END_SRC
+
+* Languages
+
+** General
+
+First of all, define a function that identifies some warning keywords
+(e.g. TODO). This function can then be applied to the proper mode.
+
+#+BEGIN_SRC elisp
+ (defun warnings-mode-hook ()
+ "Hook for enabling the warning face on strings with a warning prefix."
+
+ (font-lock-add-keywords nil
+ '(("\\(XXX\\|FIXME\\|TODO\\|HACK\\|NOTE\\|BUG\\)"
+ 1 font-lock-warning-face prepend))))
+#+END_SRC
+
+Text mode is not a programming language, but it's used quite often in this
+context too. In this case, I want spell check and =wc-mode= activated.
+
+#+BEGIN_SRC elisp
+ (add-hook 'text-mode-hook
+ (lambda ()
+ (flyspell-mode 1)
+ (wc-mode 1)))
+#+END_SRC
+
+** Shell
+
+#+BEGIN_SRC elisp
+(use-package bats-mode
+ :ensure t)
+#+END_SRC
+
+** Lisp
+
+Emacs lisp needs =rainbow-delimiters=, so the amount of parenthesis is less
+confusing. Moreover, I'm also enabling =eldoc-mode= and the aforementioned
+=warnings-mode-hook=.
+
+#+BEGIN_SRC elisp
+ (add-hook 'emacs-lisp-mode-hook
+ (lambda ()
+ (eldoc-mode 1)
+ (warnings-mode-hook)
+ (rainbow-delimiters-mode 1)
+ ; https://github.com/jhenahan/emacs.d/blob/master/emacs-init.org#emacs-lisp
+ (setq mode-name "ξ")))
+#+END_SRC
+
+Configure =ielm= with the proper ELisp utilities:
+
+#+BEGIN_SRC elisp
+(use-package ielm
+ :config
+ (add-hook 'ielm-mode-hook #'eldoc-mode)
+ (add-hook 'ielm-mode-hook #'rainbow-delimiters-mode)
+ (global-set-key (kbd "C-x i e") 'ielm)
+ (global-set-key (kbd "C-x i l") 'ielm))
+#+END_SRC
+
+** C and C++
+
+C and C++ only require the =warnings-mode-hook= function, spell checking for the
+comments and the usage of tabs instead of spaces.
+
+#+BEGIN_SRC elisp
+; Note that C-common includes languages with a similar syntax of C.
+(add-hook 'c-mode-common-hook 'warnings-mode-hook)
+(add-hook 'c-mode-common-hook (lambda() (flyspell-prog-mode)))
+
+;; C
+(add-hook 'c-mode-hook
+ (lambda () (setq indent-tabs-mode t)))
+
+;; C++
+(add-hook 'c++-mode-hook
+ (lambda () (setq indent-tabs-mode t)))
+#+END_SRC
+
+CMake for y'all.
+
+#+BEGIN_SRC elisp
+ (use-package cmake-mode
+ :ensure t
+ :config
+
+ (setq auto-mode-alist
+ (append
+ '(("CMakeLists\\.txt\\'" . cmake-mode))
+ '(("\\.cmake\\'" . cmake-mode))
+ auto-mode-alist))
+
+ (use-package cmake-font-lock
+ :ensure t
+ :config
+
+ (add-hook 'cmake-mode-hook 'cmake-font-lock-activate)
+ (add-hook 'yaml-mode-hook 'warnings-mode-hook)))
+#+END_SRC
+
+** Ruby
+
+Include warning keywords in Ruby and do not automatically include the encoding
+magic comment:
+
+#+BEGIN_SRC elisp
+(use-package ruby-mode
+ :config
+ (setq ruby-insert-encoding-magic-comment nil)
+ (add-hook 'ruby-mode-hook #'subword-mode)
+ (add-hook 'ruby-mode-hook 'warnings-mode-hook))
+#+END_SRC
+
+And give me an IRB instance:
+
+#+BEGIN_SRC elisp
+(use-package inf-ruby
+ :ensure t
+ :config
+ (add-hook 'ruby-mode-hook #'inf-ruby-minor-mode)
+ (global-set-key (kbd "C-x i r") 'inf-ruby))
+#+END_SRC
+
+** Go
+
+And now my Go configuration. This includes stuff like the usage of =goimports=,
+=gofmt= on save, among many other useful things.
+
+#+BEGIN_SRC elisp
+ (defun mssola-go-mode ()
+ "My configuration for Go mode."
+
+ ; Use goimports instead of go-fmt
+ (setq gofmt-command "goimports")
+
+ ; Call Gofmt before saving
+ (add-hook 'before-save-hook 'gofmt-before-save)
+
+ ; Integration flycheck with Go
+ (add-to-list 'load-path
+ (concat (getenv "GOPATH") "/src/github.com/dougm/goflymake"))
+ (require 'go-flycheck)
+
+ (setq indent-tabs-mode t)
+ (flyspell-prog-mode)
+
+ ; eldoc support
+ (use-package go-eldoc
+ :ensure t
+ :config
+ (require 'go-eldoc)))
+
+ ;; Go
+ (use-package go-mode
+ :ensure t
+ :pin melpa-stable
+ :config
+
+ (add-hook 'go-mode-hook 'warnings-mode-hook)
+ (add-hook 'go-mode-hook 'go-eldoc-setup)
+ (add-hook 'go-mode-hook 'mssola-go-mode))
+#+END_SRC
+
+** Python
+
+Install =elpy= as the environment for Python support:
+
+#+BEGIN_SRC elisp
+(use-package elpy
+ :ensure t
+ :config
+ (advice-add 'python-mode :before 'elpy-enable)
+ (when (require 'flycheck nil t)
+ (setq elpy-modules (delq 'elpy-module-flymake elpy-modules))
+ (add-hook 'elpy-mode-hook 'flycheck-mode)))
+#+END_SRC
+
+Automatically use =autopep8= on save:
+
+#+BEGIN_SRC elisp
+(use-package py-autopep8
+ :ensure t
+ :config
+ (add-hook 'elpy-mode-hook 'py-autopep8-enable-on-save))
+#+END_SRC
+
+** Rust
+
+Install =rust-mode= and add some hooks to make it friendlier.
+
+#+BEGIN_SRC elisp
+(use-package rust-mode
+ :ensure t
+ :config
+
+ (add-hook 'before-save-hook
+ #'(lambda ()
+ (when (eq major-mode 'rust-mode)
+ (rust-format-buffer))))
+
+ (use-package flycheck-rust
+ :ensure t
+ :config
+
+ (add-hook 'flycheck-mode-hook #'flycheck-rust-setup)))
+#+END_SRC
+
+** Tabs vs spaces
+
+Tabs or spaces? [[https://www.emacswiki.org/emacs/TabsSpacesBoth][Both]]. The =smart-tabs-mode= has the philosophy of: tabs for
+indentation, spaces for alignment. This is only applied in languages where I'm
+usings tabs for indentation (C, C++ and Go).
+
+#+BEGIN_SRC elisp
+ (use-package smart-tabs-mode
+ :ensure t
+ :config
+ (smart-tabs-add-language-support golang go-mode-hook
+ ((c-indent-line . c-basic-offset)
+ (c-indent-region . c-basic-offset)))
+ (smart-tabs-insinuate 'c 'c++ 'golang))
+#+END_SRC
+
+** Inferior markup languages.
+
+#+BEGIN_SRC elisp
+ ;; Markdown mode with preview mode in the browser.
+ (use-package markdown-mode
+ :ensure t
+ :config
+
+ ; This is the one that I got from openSUSE.
+ (custom-set-variables
+ '(markdown-command "/usr/bin/markdown-calibre"))
+
+ ; Preview mode does its things through websockets, so it's a requirement.
+ ; After that, we can safely require it.
+ (use-package websocket
+ :ensure t
+ :config
+ (use-package markdown-preview-mode
+ :ensure t)))
+
+ ; YAML
+ (use-package yaml-mode
+ :ensure t
+ :config
+
+ (add-hook 'yaml-mode-hook 'warnings-mode-hook))
+#+END_SRC
+
+** Web-related stuff.
+
+Slim and SCSS.
+
+#+BEGIN_SRC elisp
+(use-package slim-mode
+ :ensure t)
+
+(use-package scss-mode
+ :ensure t
+ :config
+
+ (setq scss-compile-at-save nil)
+ (add-hook 'yaml-mode-hook 'warnings-mode-hook))
+
+(use-package coffee-mode
+ :ensure t)
+#+END_SRC
+
+Languages specific for backend code like PHP, and =web-mode=, which provides a
+bundle of features which are interesting for web-related stuff.
+
+#+BEGIN_SRC elisp
+(use-package php-mode
+ :ensure t)
+
+(use-package web-mode
+ :ensure t
+ :config
+
+ (add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
+ (add-to-list 'auto-mode-alist '("\\.jinja\\'" . web-mode))
+ (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
+
+ (add-hook 'web-mode-hook
+ (lambda ()
+ (setq web-mode-markup-indent-offset 2)
+ (setq web-mode-css-indent-offset 2)
+ (setq web-mode-code-indent-offset 2)))
+
+ (add-hook 'js-mode-hook
+ (lambda ()
+ (setq js-indent-level 2)
+ (rainbow-delimiters-mode 1)))
+
+ (use-package vue-mode
+ :ensure t
+ :config
+ (setq mmm-submode-decoration-level 0))
+
+ ; React: treat it as a derived mode. Idea taken from spacemacs.
+ (define-derived-mode react-mode web-mode "react")
+ (add-to-list 'auto-mode-alist '("\\.jsx\\'" . react-mode))
+ (add-to-list 'auto-mode-alist '("\\.react.js\\'" . react-mode))
+
+ (add-hook 'react-mode-hook
+ (lambda ()
+ (yas-activate-extra-mode 'js-mode)
+ (web-mode-set-content-type "jsx")
+ (setq-local web-mode-enable-auto-quoting nil)
+ (rainbow-delimiters 1))))
+#+END_SRC
+
+The =json-reformat= package provides functions for reformatting JSON strings. It
+happens from time to time that I have to read JSON output from responses, and it
+can be frustrating without proper formatting.
+
+#+BEGIN_SRC elisp
+(use-package json-reformat
+ :ensure t)
+#+END_SRC
+
+** Devops
+
+Highlighting for Dockerfiles.
+
+#+BEGIN_SRC elisp
+ (use-package dockerfile-mode
+ :ensure t
+ :config
+
+ (add-to-list 'auto-mode-alist '("Dockerfile" . dockerfile-mode)))
+#+END_SRC
+
+Stuff from Hashicorp like terraform and HCL.
+
+#+BEGIN_SRC elisp
+(use-package terraform-mode
+ :ensure t
+ :config
+
+ (terraform-format-on-save-mode))
+
+(use-package hcl-mode
+ :ensure t)
+#+END_SRC
+
+#+BEGIN_SRC elisp
+(use-package salt-mode
+ :ensure t)
+#+END_SRC
+
+** Others
+
+The [[https;//github.com/mssola/soria][soria]] theme has the =soria-purple-identifiers= hook. This hook instructs
+the theme to use purple for identifiers instead of the default color. This is a
+remnant from my Vim times, and I only apply it to some languages (random
+criteria really).
+
+#+BEGIN_SRC elisp
+ (dolist (lang-hook '(ruby-mode-hook
+ php-mode-hook
+ perl-mode-hook
+ emacs-lisp-mode-hook))
+ (add-hook lang-hook 'soria-purple-identifiers))
+#+END_SRC
+
+** LaTeX
+
+Let's use [[https://www.gnu.org/software/auctex/][Auctex]] for LaTeX files.
+
+#+BEGIN_SRC elisp
+(use-package tex
+ :ensure auctex
+ :config
+ (setq TeX-auto-save t)
+ (setq TeX-parse-self t)
+ (setq-default TeX-master nil))
+#+END_SRC
+
+* WoMan
+
+=WoMan= is a package that is included inside of GNU Emacs by default, and that
+takes care of visualizing man pages. Let's properly setup Evil mode for this:
+
+#+BEGIN_SRC elisp
+(with-eval-after-load "evil"
+ (evil-set-initial-state 'woman-mode 'normal)
+ (evil-define-key 'normal woman-mode-map
+ "J" 'Man-next-section
+ "K" 'Man-previous-section
+ "\C-h" 'evil-window-left
+ "\C-l" 'evil-window-right
+ "\C-j" 'evil-window-down
+ "\C-k" 'evil-window-up
+ "\C-u" 'evil-scroll-up))
+#+END_SRC
+
+Finally, I want man pages to fill all the frame:
+
+#+BEGIN_SRC elisp
+(setq woman-fill-frame t)
+#+END_SRC
+
+Start =WoMan= as a subcommand of the help command:
+
+#+BEGIN_SRC elisp
+(define-key 'help-command (kbd "M-m") #'woman)
+#+END_SRC
+
+* Misc
+
+Install a set of useful functions from [[https://github.com/bbatsov][@bbatsov]]. The bindings are following
+Emacs style instead of being more Vim-like on purpose (I don't want to put
+too many things into my leader and these shortcuts look sensible to me).
+
+#+BEGIN_SRC elisp
+(use-package crux
+ :ensure t
+ :config
+
+ (global-set-key (kbd "C-c d") 'crux-delete-file-and-buffer)
+ (global-set-key (kbd "C-c r") 'crux-rename-file-and-buffer)
+ (global-set-key (kbd "C-c n") 'crux-cleanup-buffer-or-region)
+ (global-set-key (kbd "C-<backspace>") 'crux-kill-line-backwards)
+ (global-set-key [remap move-beginning-of-line] 'crux-move-beginning-of-line)
+ (global-set-key (kbd "C-c o") 'crux-open-with))
+#+END_SRC
+
+** Emojis
+
+Display emojis in buffer!
+
+#+BEGIN_SRC elisp
+(use-package emojify
+ :ensure t
+ :config
+
+ (add-hook 'after-init-hook #'global-emojify-mode)
+ (setq emojify-composed-text-p nil)
+ (setq emojify-emoji-styles '(unicode github)))
+#+END_SRC
+
+* Credits
+
+I've built this file by simply scavenging from other people's emacs.d/dotfiles
+repositories. I have taken lots of pieces from here and there, but most notably:
+
+- [[https://github.com/ereslibre/dotfiles][@ereslibre]]
+- [[https://github.com/dmacvicar/dotfiles][@dmacvicar]]
+- [[https://github.com/bbatsov/emacs.d][@bbatsov]]
+- [[https://github.com/aaronbieber/dotfiles][@aaronbieber]]
+- [[https://github.com/purcell/emacs.d][@purcell]]
+- [[https://github.com/sachac/.emacs.d][@sachac]] ([[http://pages.sachachua.com/.emacs.d/Sacha.html][HTML version]])
+- [[https://github.com/larstvei/dot-emacs][@larstvei]]
+
+* License
+
+#+BEGIN_SRC text :tangle no
+ Copyright (C) 2014-2019 Miquel Sabaté Solà <mikisabate@gmail.com>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+#+END_SRC
diff --git a/.emacs.d/lisp/README.md b/.emacs.d/lisp/README.md
new file mode 100644
index 0000000..64e6da0
--- /dev/null
+++ b/.emacs.d/lisp/README.md
@@ -0,0 +1,18 @@
+## GNU Emacs Modules written by Miquel Sabaté Solà
+
+This directory contains Lisp modules I've written.
+
+### g.el
+
+A port of my [g](https://github.com/mssola/g) script for GNU Emacs. This is not
+helpful all the time, but it does help whenever Projectile does not cover me.
+This module implements the following interactive functions:
+
+- `g`: allows users to jump through a shortcut. After performing the jump, the
+ user will be presented with the `dired` mode.
+- `g-add`: add a new shortcut that points to a valid path.
+- `g-remove`: remove an existing shortcut.
+- `g-list`: list all the available shortcuts.
+
+This module is completely compatible with the `g.sh` script, which means that
+they both can be run side by side without any problems.
diff --git a/.emacs.d/lisp/g.el b/.emacs.d/lisp/g.el
new file mode 100644
index 0000000..3a4660a
--- /dev/null
+++ b/.emacs.d/lisp/g.el
@@ -0,0 +1,134 @@
+;;; g.el --- Adding shortcuts to GNU Emacs
+
+;; Copyright (C) 2016-2019 Miquel Sabaté Solà <mikisabate@gmail.com>
+;;
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;; Author: Miquel Sabaté Solà <mikisabate@gmail.com>
+;; Version: 0.1
+;; URL: https://github.com/mssola/dotfiles/emacs/site-lisp/g.el
+
+;;; Commentary:
+;;
+;; This is a GNU Emacs port of my g.sh bash script that can be found here:
+;; https://github.com/mssola/g. This package can be seen as useless given the
+;; fantastic Helm + Projectile combo, but it still comes in handy when you want
+;; to edit:
+;; - A file which is in a project unknown to Projectile.
+;; - A file that does not really belong to a real project.
+
+;;; Code:
+
+(defvar g-file "~/.gfile"
+ "The path to the gfile.")
+
+;; Utils
+
+(defun g-read-file (file)
+ "Read the given FILE and return it as a list of lines."
+
+ (if (file-exists-p file)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (split-string (buffer-string) "\n" t))
+ ""))
+
+(defun g-write (shortcuts)
+ "Write the given SHORTCUTS into the gfile."
+
+ (let ((output ""))
+ (maphash (lambda (key value)
+ (setq output
+ (concat output (format "%s\n%s\n" key value))))
+ shortcuts)
+ (write-region output nil g-file)))
+
+(defun g-read ()
+ "Read all the shortcuts as defined by the gfile.
+The returned object is a hash table."
+
+ (let ((shortcuts (make-hash-table :test 'equal))
+ (list (g-read-file g-file)))
+
+ ; The format of the file is a bit special because it was meant to be easily
+ ; parseable by Bash. It consists of pairs of lines, where n is the key, and
+ ; n+1 is the value.
+ (dotimes (i (/ (length list) 2))
+ (let ((n (* i 2)))
+ (puthash
+ (nth n list)
+ (nth (+ n 1) list)
+ shortcuts)))
+ shortcuts))
+
+;; Interactive functions
+
+(defun g ()
+ "Go to the given directory with the supplied alias."
+
+ (interactive)
+
+ (if (file-exists-p g-file)
+ (progn
+ (let* ((shortcuts (g-read))
+ (alias (completing-read
+ "Give me the name: " shortcuts nil t)))
+ (find-file (gethash alias shortcuts))))
+ (message "Add a shortcut first!")))
+
+(defun g-list ()
+ "List all the available shortcuts."
+
+ (interactive)
+
+ (let ((output ""))
+ (maphash (lambda (key value)
+ (setq output
+ (concat output (format "%s => %s\n" key value))))
+ (g-read))
+ (message output)))
+
+(defun g-add ()
+ "Add a new shortcut."
+
+ (interactive)
+
+ (let ((shortcuts (g-read))
+ (to-create (read-string "Shortcut to create: ")))
+ (if (gethash to-create shortcuts)
+ (message "Error: shortcut already exists.")
+ (let ((path (read-file-name "Path: " nil nil t)))
+ (if (file-exists-p path)
+ (progn
+ (puthash to-create (file-truename path) shortcuts)
+ (g-write shortcuts))
+ (message "Error: given path does not exist."))))))
+
+(defun g-remove ()
+ "Remove an existing shortcut."
+
+ (interactive)
+
+ (if (file-exists-p g-file)
+ (progn
+ (let* ((shortcuts (g-read))
+ (alias (completing-read
+ "Give me the shortcut to remove: " shortcuts nil t)))
+ (remhash alias shortcuts)
+ (g-write shortcuts)))
+ (message "There are no shortcuts!")))
+
+(provide 'g)
+
+;;; g.el ends here
diff --git a/.emacs.d/org-templates/README.org b/.emacs.d/org-templates/README.org
new file mode 100644
index 0000000..b3cc271
--- /dev/null
+++ b/.emacs.d/org-templates/README.org
@@ -0,0 +1,22 @@
+* org
+
+Helper files that are included in some way or another into my =org= file.
+
+* License
+
+#+BEGIN_SRC text
+Copyright (C) 2019 Miquel Sabaté Solà <mikisabate@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+#+END_SRC
diff --git a/.emacs.d/org-templates/article-full.org b/.emacs.d/org-templates/article-full.org
new file mode 100644
index 0000000..839e1d8
--- /dev/null
+++ b/.emacs.d/org-templates/article-full.org
@@ -0,0 +1,20 @@
+#+AUTHOR: Miquel Sabaté Solà
+#+DESCRIPTION:
+#+KEYWORDS:
+#+LANGUAGE: ca
+
+#+OPTIONS: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline
+#+OPTIONS: author:t c:nil creator:nil d:(not LOGBOOK) date:t title:t e:t
+#+OPTIONS: email:nil f:t inline:t num:t p:nil pri:nil stat:t tags:nil
+#+OPTIONS: tasks:t tex:t timestamp:t toc:t todo:t |:t
+
+#+LaTeX_CLASS_OPTIONS: [catalan,a4paper,12pt]
+#+LATEX_HEADER: \usepackage{babel}
+#+LATEX_HEADER: \usepackage[a4paper, portrait, margin=1in]{geometry}
+#+LATEX_HEADER: \renewcommand{\baselinestretch}{1.5}
+#+LATEX_HEADER: \usepackage{newtxtext,newtxmath}
+
+#+LATEX_HEADER: \usepackage{xcolor}
+#+LATEX_HEADER: \hypersetup{colorlinks=false, pdfborderstyle={/S/U/W 1}, urlbordercolor=gray, pdfborder=0 0 1}
+
+#+SELECT_TAGS: export
diff --git a/.emacs.d/org-templates/article.org b/.emacs.d/org-templates/article.org
new file mode 100644
index 0000000..463ec2f
--- /dev/null
+++ b/.emacs.d/org-templates/article.org
@@ -0,0 +1,20 @@
+#+AUTHOR: Miquel Sabaté Solà
+#+DESCRIPTION:
+#+KEYWORDS:
+#+LANGUAGE: ca
+
+#+OPTIONS: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline
+#+OPTIONS: author:nil c:nil creator:nil d:(not LOGBOOK) date:nil title:nil e:t
+#+OPTIONS: email:nil f:t inline:t num:t p:nil pri:nil stat:t tags:nil
+#+OPTIONS: tasks:t tex:t timestamp:t toc:nil todo:t |:t
+
+#+LaTeX_CLASS_OPTIONS: [a4paper, 12pt]
+#+LATEX_HEADER: \usepackage[a4paper, portrait, margin=1in]{geometry}
+#+LATEX_HEADER: \renewcommand{\baselinestretch}{1.5}
+#+LATEX_HEADER: \usepackage{newtxtext,newtxmath}
+#+LATEX_HEADER: \usepackage[catalan]{babel}
+
+#+LATEX_HEADER: \usepackage{xcolor}
+#+LATEX_HEADER: \hypersetup{colorlinks=false, pdfborderstyle={/S/U/W 1}, urlbordercolor=gray, pdfborder=0 0 1}
+
+#+SELECT_TAGS: export
diff --git a/.emacs.d/org.css b/.emacs.d/org.css
new file mode 100644
index 0000000..98110e5
--- /dev/null
+++ b/.emacs.d/org.css
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017-2019 Miquel Sabaté Solà <mikisabate@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This file tries to mimick what we have in the soria theme. That being said,
+ * the HTML exporter of org-mode is not perfect, so there's tons of stuff that
+ * are not highlighted in the same way as in GNU Emacs. Anyways, the colors are
+ * as follows:
+ *
+ * soria-purple "#dfafdf"
+ * soria-darkpurple "#875f87"
+ * soria-white "#d0d0d0"
+ * soria-darkgray "#1c1c1c"
+ * soria-brightgreen "#81c13b"
+ * soria-green "#b9dc92"
+ * soria-darkgreen "#2f5361"
+ * soria-gray "#808080"
+ * soria-linegray "#3a3a3a"
+ * soria-statusgray "#4e4e4e"
+ * soria-statusncgray "#b2b2b2"
+ * soria-black "#000000"
+ * soria-whitest "#eeeeee"
+ * soria-yellow "#ffffaf"
+ * soria-orange "#d7af87"
+ * soria-redpastel "#d78787"
+ * soria-blue "#87afd7"
+ */
+
+.org-src-container pre {
+ color: #d0d0d0;
+ background-color: #1c1c1c;
+ border-left: 0px;
+}
+
+.org-warning { color: #b9dc92; }
+.org-keyword { color: #87afd7; }
+.org-function-name { color: #87afd7; }
+.org-builtin { color: #87afd7; }
+.org-constant { color: #ffffaf; }
+.org-string { color: #ffffaf; }
+.org-doc { color: #808080; }
+.org-comment { color: #808080; }
+.org-comment-delimiter { color: #808080; }
+.org-rainbow-delimiters-depth-1 { color: #81c13b; }
+.org-rainbow-delimiters-depth-2 { color: #d78787; }
+.org-rainbow-delimiters-depth-3 { color: #d7af87; }
+.org-rainbow-delimiters-depth-4 { color: #87afd7; }
+.org-rainbow-delimiters-depth-5 { color: #d0d0d0; }
+.org-rainbow-delimiters-depth-6 { color: #d0d0d0; }
+.org-rainbow-delimiters-depth-7 { color: #d0d0d0; }
+.org-rainbow-delimiters-depth-8 { color: #d0d0d0; }
+.org-rainbow-delimiters-depth-9 { color: #d0d0d0; }
diff --git a/.emacs.d/pre-push b/.emacs.d/pre-push
new file mode 100755
index 0000000..dcc8dce
--- /dev/null
+++ b/.emacs.d/pre-push
@@ -0,0 +1,79 @@
+#!/bin/sh
+# Copyright (C) 2017-2019 Miquel Sabaté Solà <mikisabate@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Most of the code is taken from the default pre-push.sample file.
+
+# From the documentation, if the foreign ref does not yet exist the
+# <remote SHA1> will be 40 0.
+z40=0000000000000000000000000000000000000000
+
+# The path where the files are to be stored on the server.
+__mssola_remote_path=/home/mssola/static
+
+# Safely join paths.
+__mssola_join_path() {
+ local IFS="/"; echo "$*";
+}
+
+# This function does the actual syncing. It takes one argument, which is the
+# file to be synced. Note that this function assumes that the given file is
+# under the "emacs" directory.
+__mssola_sync_cheato() {
+ path=$(realpath .)
+
+ src=$(__mssola_join_path $path "emacs" $1)
+ dst=$(__mssola_join_path "cheato.mssola.com:$__mssola_remote_path" $1)
+
+ echo "Syncing $(__mssola_join_path emacs $1)"
+ rsync $src $dst
+}
+
+# Copy the files that I want to my server.
+__mssola_sync() {
+ __mssola_sync_cheato "init.html"
+ __mssola_sync_cheato "org.css"
+}
+
+# This block iterates through all the given info provided by git. If there is
+# a change on a GNU Emacs file, then it needs to by synced with my server.
+while read local_ref local_sha remote_ref remote_sha
+do
+ if [ "$local_sha" = $z40 ]
+ then
+ # Handle delete
+ :
+ else
+ if [ "$remote_sha" = $z40 ]
+ then
+ # New branch, examine all commits
+ range="$local_sha"
+ else
+ # Update to existing branch, examine new commits
+ range="$remote_sha..$local_sha"
+ fi
+
+ # Commits afecting GNU Emacs are prefixed with "emacs: ". It's a
+ # convention that I always follow.
+ commit=`git rev-list -n 1 --grep '^emacs:' "$range"`
+ if [ -n "$commit" ]
+ then
+ #__mssola_sync
+ exit 0
+ fi
+ fi
+done
+
+exit 0
diff --git a/.emacs.d/snippets/org-mode/header b/.emacs.d/snippets/org-mode/header
new file mode 100644
index 0000000..a3f7fca
--- /dev/null
+++ b/.emacs.d/snippets/org-mode/header
@@ -0,0 +1,8 @@
+# -*- mode: snippet -*-
+#name : header
+# --
+#+TITLE: ${1:<title>}
+#+AUTHOR: `(user-full-name)`
+#+EMAIL: `user-mail-address`
+
+* $0 \ No newline at end of file
diff --git a/.emacs.d/test-startup.sh b/.emacs.d/test-startup.sh
new file mode 100755
index 0000000..d8f3547
--- /dev/null
+++ b/.emacs.d/test-startup.sh
@@ -0,0 +1,22 @@
+#!/bin/sh -ex
+# Kindly taken from: https://github.com/purcell/emacs.d
+
+if [ -n "$TRAVIS" ]; then
+ # We still need to have an .emacs.d directory, so emacs-async (dependency of
+ # some other package) is happy.
+ export HOME=$PWD/..
+ ln -s emacs ../.emacs.d
+fi
+
+echo "Attempting startup..."
+
+${EMACS:=emacs} -nw --batch \
+ --eval '(let ((debug-on-error t)
+ (url-show-status nil)
+ (user-emacs-directory default-directory)
+ (package-user-dir (expand-file-name (concat "elpa-" emacs-version)))
+ (custom-theme-directory default-directory)
+ (user-init-file (expand-file-name "init.el")))
+ (load-file user-init-file)
+ (run-hooks (quote after-init-hook)))'
+echo "Startup successful"