aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <msabate@suse.com>2017-01-13 17:30:28 +0100
committerMiquel Sabaté Solà <msabate@suse.com>2017-01-13 17:30:28 +0100
commit8b4b59dbf19f2affc3eaaf69d3cc38efeede3981 (patch)
treef6c0c3f215f18aebab7294c8c2bf0002aeec2f5f
parent2aa031d0a09882408e29de0f7ed67f1843d0b9f6 (diff)
downloaddotfiles-8b4b59dbf19f2affc3eaaf69d3cc38efeede3981.tar.gz
dotfiles-8b4b59dbf19f2affc3eaaf69d3cc38efeede3981.zip
emacs: literate programming
Everything has been moved into an org file. Signed-off-by: Miquel Sabaté Solà <msabate@suse.com>
-rw-r--r--README.md19
-rw-r--r--emacs/README.org39
-rw-r--r--emacs/custom.el23
-rw-r--r--emacs/init.el109
-rw-r--r--emacs/init.org1547
-rw-r--r--emacs/settings/defuns.el62
-rw-r--r--emacs/settings/init-calendar.el45
-rw-r--r--emacs/settings/init-dired.el49
-rw-r--r--emacs/settings/init-edit.el109
-rw-r--r--emacs/settings/init-evil.el161
-rw-r--r--emacs/settings/init-general.el142
-rw-r--r--emacs/settings/init-lang.el214
-rw-r--r--emacs/settings/init-magit.el56
-rw-r--r--emacs/settings/init-misc.el34
-rw-r--r--emacs/settings/init-mu4e.el262
-rw-r--r--emacs/settings/init-org.el168
-rw-r--r--emacs/settings/init-project.el116
-rwxr-xr-xinstall.sh6
18 files changed, 1629 insertions, 1532 deletions
diff --git a/README.md b/README.md
index 93d22ce..1272b1b 100644
--- a/README.md
+++ b/README.md
@@ -10,24 +10,7 @@ And that's about it. Use this at your own risk ;)
## GNU Emacs
-**NOTE**: these instructions are outdated, I'll update them whenever I can.
-
-For the configuration of Emacs I'm trying out using symlinks instead of copying
-files into the right places. For this reason, for now I'm not providing an
-automatical way to install everything (this is left to be done in the near
-future). The `emacs/init.el` and `emacs/gtkrc` files should be symlinked into
-`~/.emacs.d`.
-
-I run GNU Emacs in daemon mode, but I don't use systemd for that. Instead, in
-the `i3/config` file you'll see that I'm using `-a ""` as an argument of
-`emacsclient`. 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.
-
-Last but not least, I'm using my customized `soria` color theme. This theme is
-unfortunately not available in any way other than Github. Therefore, you should
-clone it yourself in https://github.com/mssola/soria, and add it into
-the `~/.emacs.d` directory.
+See [emacs/README.org](emacs/README.org).
## Runtime dependencies
diff --git a/emacs/README.org b/emacs/README.org
new file mode 100644
index 0000000..3563f76
--- /dev/null
+++ b/emacs/README.org
@@ -0,0 +1,39 @@
+* My GNU Emacs configuration
+
+** TODO these instructions are outdated, I'll update them whenever I can.
+
+For the configuration of Emacs I'm trying out using symlinks instead of copying
+files into the right places. For this reason, for now I'm not providing an
+automatical way to install everything (this is left to be done in the near
+future). The `emacs/init.el` and `emacs/gtkrc` files should be symlinked into
+`~/.emacs.d`.
+
+I run GNU Emacs in daemon mode, but I don't use systemd for that. Instead, in
+the `i3/config` file you'll see that I'm using `-a ""` as an argument of
+`emacsclient`. 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.
+
+Last but not least, I'm using my customized `soria` color theme. This theme is
+unfortunately not available in any way other than Github. Therefore, you should
+clone it yourself in https://github.com/mssola/soria, and add it into
+the `~/.emacs.d` directory.
+
+** License
+
+#+BEGIN_SRC text
+ Copyright (C) 2014-2017 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/custom.el b/emacs/custom.el
new file mode 100644
index 0000000..1905a1d
--- /dev/null
+++ b/emacs/custom.el
@@ -0,0 +1,23 @@
+(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
+ ("5a3f33eefbcf2a3098bafd22d7ad44358e66c3e844797e7bf9ef552a08dfeb6f" default)))
+ '(delete-selection-mode nil)
+ '(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
+ (cmake-mode websocket markdown-mode go-mode magit evil-leader evil helm projectile writeroom-mode org-eldoc evil-commentary circe 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 expand-region 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/init.el b/emacs/init.el
index 42c8f52..589e48a 100644
--- a/emacs/init.el
+++ b/emacs/init.el
@@ -1,102 +1,19 @@
-;;; init.el --- My Emacs configuration
-
-;; Copyright (C) 2016-2017 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.
+;; This file replaces itself with the actual configuration at first run.
+;; Idea and file taken from https://github.com/larstvei/dot-emacs.
;;
-;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-;;
-;; This is my personal Emacs configuration. I wouldn't expect much to be
-;; honest :)
-
-;;; 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:
-;; - @ereslibre: https://github.com/ereslibre/dotfiles
-;; - @dmacvicar: https://github.com/dmacvicar/dotfiles
-;; - @bbatsov: https://github.com/bbatsov/emacs.d
-;; - @aaronbieber: https://github.com/aaronbieber/dotfiles
-;; - @purcell: https://github.com/purcell/emacs.d
-
-;;; Code:
-
-;;; Preface
-
-;; I'm using GNU Emacs 25, 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.
-(unless (>= emacs-major-version 24)
- (error "Don't be a cheap bastard and upgrade to at least GNU Emacs 24"))
-
-;; Temporarily reduce garbage collection so startup time is lower. Idea taken
-;; from @purcell.
-(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)))
-
-;;; User name and email.
-
-(setq user-full-name "Miquel Sabaté Solà"
- user-mail-address "mikisabate@gmail.com")
-
-;;; Basic configuration
-
-(add-to-list 'load-path (expand-file-name "settings" user-emacs-directory))
-
-(require 'init-general)
-(require 'init-calendar)
-(require 'defuns)
-
-;;; Custom Lisp
-
-(byte-compile-file (concat user-emacs-directory "lisp/g.el") t)
-(global-set-key (kbd "M-g") 'g)
-
-;;; Initialize package and use-package.
-
-(require 'package)
-
-(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)
+;; NOTE DO NOT MODIFY THIS FILE. All changes should go into init.org
-(package-initialize)
+;; We can't tangle without org!
+(require 'org)
-;; 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.
-(unless (package-installed-p 'use-package)
- (package-refresh-contents)
- (package-install 'use-package))
+;; Open the configuration
+(find-file (concat user-emacs-directory "init.org"))
-;; And load the configuration for all the packages being used.
+;; Tangle it
+(org-babel-tangle)
-(require 'init-project)
-(require 'init-edit)
-(require 'init-misc)
-(require 'init-dired)
-(require 'init-evil)
-(require 'init-magit)
-(require 'init-mu4e)
-(require 'init-org)
-(require 'init-lang)
+;; Load it
+(load-file (concat user-emacs-directory "init.el"))
-(provide 'init)
-;;; init.el ends here
+;; Finally byte-compile it
+(byte-compile-file (concat user-emacs-directory "init.el"))
diff --git a/emacs/init.org b/emacs/init.org
new file mode 100644
index 0000000..4410d27
--- /dev/null
+++ b/emacs/init.org
@@ -0,0 +1,1547 @@
+#+TITLE: mssola's GNU Emacs configuration
+#+AUTHOR: Miquel Sabaté Solà
+#+BABEL: :cache yes
+#+PROPERTY: header-args :tangle init.el
+
+* Preface
+<<sec: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)
+
+ ;; 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. 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."
+
+ (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 25, 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 24)
+ (error "Don't be a cheap bastard and upgrade to at least GNU Emacs 24"))
+#+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
+
+* 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
+
+** 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 elisp
+
+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
+ (set-frame-font "Droid Sans Mono Dotted for Powerline-10")
+ (add-to-list 'default-frame-alist '(font . "Droid Sans Mono Dotted for Powerline-10"))
+
+ ; 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 "Droid Sans Mono Dotted for Powerline-10")))
+#+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
+
+** 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
+
+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
+
+** 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)))
+#+END_SRC
+
+No backups
+
+#+BEGIN_SRC elisp
+ (setq-default make-backup-files nil)
+ (setq-default auto-save-default nil)
+#+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
+
+* 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 "C-c c") 'calendar)
+#+END_SRC
+
+Fix some stuff for evil mode.
+
+#+BEGIN_SRC elisp
+ (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
+
+* Lisp packages
+** Custom packages
+
+Compile the =g.el= script and bind it to <kbd>M-g</kbd>.
+
+#+BEGIN_SRC elisp
+ (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)
+
+ (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))
+#+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)
+ (setq projectile-mode-line
+ '(:eval (format " %s" (projectile-project-name)))))
+
+ (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-in-side-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)
+
+ (use-package helm-ag
+ :ensure t))
+
+ (use-package helm-projectile
+ :ensure t
+ :config
+ (helm-projectile-on))
+#+END_SRC
+
+Finally, I've added a couple of bindings in evil mode. First of all, I want
+<kbd>C-p</kbd> to use the proper function for finding files.
+
+#+BEGIN_SRC elisp
+ (defun mssola-find-file ()
+ "Call the proper Helm function for finding files."
+
+ (interactive)
+
+ (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 <kbd>leader-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)
+ (setq undo-tree-visualizer-timestamps t)
+ (with-eval-after-load 'evil-leader
+ (evil-leader/set-key
+ "u" 'undo-tree-visualize)))
+#+END_SRC
+
+Another important package is =flycheck=, which is a 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
+ :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
+
+I never use the mouse.
+
+#+BEGIN_SRC elisp
+ (use-package disable-mouse
+ :ensure t
+ :config
+ (global-disable-mouse-mode))
+#+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)
+#+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
+
+Next on the list, we have =writeroom-mode=. I honestly don't use this package
+that often, but it's cool to have a distraction-free screen from time to time.
+
+#+BEGIN_SRC elisp
+ (use-package writeroom-mode
+ :ensure t)
+#+END_SRC
+
+Finally, we have =expand-region=. This is an extension that is based on a Vim
+one, which expands the region of selection with a single key chord. Even if evil
+covers most of my uses, it's convenient to have this tool anyways.
+
+#+BEGIN_SRC elisp
+ (use-package expand-region
+ :ensure t
+ :config
+
+ ; Set C-e as the expand command (mnemonic: expand). This command will
+ ; supercede the evil binding for "move one line", which I never use anyways.
+ (global-set-key (kbd "\C-e") 'er/expand-region)
+ (with-eval-after-load 'evil
+ (define-key evil-normal-state-map (kbd "\C-e") 'er/expand-region)
+ (define-key evil-visual-state-map (kbd "\C-e") 'er/expand-region)))
+
+ (defun er/add-text-mode-expansions ()
+ "This way we can also expand the region into paragraphs & pages in text mode.
+ Directly taken from: https://github.com/magnars/expand-region.el."
+
+ (make-variable-buffer-local 'er/try-expand-list)
+ (setq er/try-expand-list (append
+ er/try-expand-list
+ '(mark-paragraph
+ mark-page))))
+
+ (add-hook 'text-mode-hook 'er/add-text-mode-expansions)
+#+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
+
+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
+<kbd>C-c</kbd><kbd>RET</kbd><kbd>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. As I said in the [[:preface][Preface]], 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 block
+includes some heavy-lifting so Evil and GNU Emacs work without hitting each
+other, and it also includes some Evil extensions.
+
+#+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)
+
+ ; Helm + Projectile shortcuts.
+ (with-eval-after-load 'helm-projectile
+ (define-key evil-normal-state-map (kbd "M-p")
+ 'helm-projectile-switch-project))
+
+ ; I use the Super key in combination with j & k to move around i3. Let's unset
+ ; M- combos for these two fellows for whenever I misstype them.
+ (global-unset-key (kbd "M-j"))
+ (global-unset-key (kbd "M-k"))
+
+ ; both this function and the subsequent lines about [escape] are taken from
+ ; @aaronbieber configuration.
+ (defun minibuffer-keyboard-quit ()
+ "Abort recursive edit.
+ In Delete Selection mode, if the mark is active, just deactivate it;
+ then it takes a second \\[keyboard-quit] to abort the minibuffer."
+ (interactive)
+ (if (and delete-selection-mode transient-mark-mode mark-active)
+ (setq deactivate-mark t)
+ (when (get-buffer "*Completions*") (delete-windows-on "*Completions*"))
+ (abort-recursive-edit)))
+
+ ;; Make escape quit everything, whenever possible.
+ (define-key evil-normal-state-map [escape] 'keyboard-quit)
+ (define-key evil-visual-state-map [escape] 'keyboard-quit)
+ (define-key minibuffer-local-map [escape] 'minibuffer-keyboard-quit)
+ (define-key minibuffer-local-ns-map [escape] 'minibuffer-keyboard-quit)
+ (define-key minibuffer-local-completion-map [escape] 'minibuffer-keyboard-quit)
+ (define-key minibuffer-local-must-match-map [escape] 'minibuffer-keyboard-quit)
+ (define-key minibuffer-local-isearch-map [escape] 'minibuffer-keyboard-quit)
+
+ ; 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))))
+
+ (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)
+ (set-quit-char "C-z")
+
+ ;; 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)
+
+ (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
+ "," 'back-to-indentation
+ "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
+ "e" 'eval-last-sexp
+ "b" 'view-buffer
+ "o" 'browse-url-at-point))
+
+ (use-package evil-surround
+ :ensure t
+ :config
+ (global-evil-surround-mode 1))
+
+ (use-package evil-commentary
+ :ensure t
+ :config
+ (evil-commentary-mode t))
+
+ (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))
+
+ (use-package evil-numbers
+ :ensure t
+ :config
+ (define-key evil-normal-state-map (kbd "C-a") 'evil-numbers/inc-at-pt)
+ (define-key evil-normal-state-map (kbd "C-c -") 'evil-numbers/dec-at-pt)))
+#+END_SRC
+
+* Magit
+
+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
+
+ ; Proper initial states.
+ (with-eval-after-load 'evil
+ (add-hook 'git-commit-mode-hook 'evil-insert-state)
+ (evil-set-initial-state 'magit-log-edit-mode 'insert))
+
+ ; When showing the status, hide the usually-redundant "branch" section and
+ ; show the rest.
+ (add-hook 'magit-section-set-visibility-hook
+ '(lambda (section)
+ (if (string= (magit-section-type section) "branch")
+ 'hide
+ 'show)))
+
+ (with-eval-after-load 'evil-leader
+ (evil-leader/set-key "s" 'magit-status)
+
+ (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
+ "\M-p" 'helm-projectile-switch-project))))
+#+END_SRC
+
+* mu4e
+
+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 =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
+ (add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")
+ (require 'mu4e)
+
+ (when (featurep 'mu4e)
+#+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
+ smtpmail-smtp-service port))
+
+ ;; Define the different accounts that I'm using. This is only available since
+ ;; mu 0.9.16.
+
+ ; https://www.reddit.com/r/emacs/comments/47t9ec/share_your_mu4econtext_configs/d0fsih6
+ (defun mu4e-message-maildir-matches (msg 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"
+ (concat "/" key "/Archives/"
+ (format-time-string "%Y" (current-time))))
+#+END_SRC
+
+Now it's time to define the different contexts that I have. Defining contexts
+this way is relatively new (since mu 0.16).
+
+#+BEGIN_SRC elisp
+ (setq mu4e-contexts
+ `(
+ ;; GMail
+ ,(make-mu4e-context
+ :name "gmail"
+ :enter-func (lambda ()
+ (mu4e-message "Switching to gmail.com")
+ (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")))
+
+ ;; suse.com
+ ,(make-mu4e-context
+ :name "comsuse"
+ :enter-func (lambda ()
+ (mu4e-message "Switching to suse.com")
+ (mssola-smtp "smtp.novell.com" 25))
+ :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/Drafts")
+ (mu4e-sent-folder . "/susecom/Sent")
+ (mu4e-refile-folder . ,(suse-refile-folder "susecom"))
+ (mu4e-trash-folder . "/susecom/Trash")))
+
+ ;; suse.de
+ ,(make-mu4e-context
+ :name "desuse"
+ :enter-func (lambda ()
+ (mu4e-message "Switching to suse.de")
+ (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" "Inbox Folders" ?n)
+ ("flag:unread AND NOT flag:trashed" "Unread messages" ?u)
+ ("date:today..now" "Today's messages" ?t)))
+#+END_SRC
+
+The following signature looks alright regardless of whether the client supports
+format=flowed or not.
+
+#+BEGIN_SRC elisp
+ (setq mu4e-compose-signature
+ (concat
+ "Miquel Sabaté Solà,\n"
+ "PGP: 4096R / 1BA5 3C7A C93D CA2A CFDF DA97 96BE 8C6F D89D 6565\n"))
+#+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-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
+
+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
+
+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 that 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) "
+ "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
+
+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-fontify-natively t
+ 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
+
+Loggins 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
+
+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
+
+** 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.
+
+* Languages
+
+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\\)"
+ 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
+
+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
+
+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
+
+Include warning keywords in Ruby.
+
+#+BEGIN_SRC elisp
+ (add-hook 'ruby-mode-hook 'warnings-mode-hook)
+#+END_SRC
+
+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)
+
+ (evil-leader/set-key
+ "." 'godef-jump-other-window)
+
+ (setq indent-tabs-mode t)
+ (flyspell-prog-mode)
+
+ ; eldoc support
+ (use-package go-eldoc
+ :ensure t
+ :config
+ (require 'go-eldoc))
+
+ (use-package go-add-tags
+ :ensure t
+ :config
+ (evil-leader/set-key "t" 'go-add-tags)))
+
+ ;; 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
+
+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.
+
+#+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 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))))
+#+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
+
+Some devops stuff, like Docker, terraform, etc. I have salt-mode disabled for
+now because it's buggy, but I still have hope.
+
+#+BEGIN_SRC elisp
+ (use-package dockerfile-mode
+ :ensure t
+ :config
+
+ (add-to-list 'auto-mode-alist '("Dockerfile\\'" . dockerfile-mode)))
+
+ (use-package terraform-mode
+ :ensure t
+ :config
+
+ (terraform-format-on-save-mode))
+
+ (use-package hcl-mode
+ :ensure t)
+
+ ;(use-package salt-mode
+ ;:ensure t)
+#+END_SRC
+
+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
+
+Last but not least, =YASnippet=. This package allows people to define shortcuts
+for writing some common blocks.
+
+#+BEGIN_SRC elisp
+ (use-package yasnippet
+ :ensure t
+ :config
+ (yas-reload-all)
+ (add-hook 'prog-mode-hook #'yas-minor-mode))
+#+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
+ :bind (("C-c d" . crux-delete-file-and-buffer)
+ ("C-c r" . crux-rename-file-and-buffer)
+ ("C-c i" . crux-find-user-init-file)
+ ("C-c o" . crux-open-with)))
+#+END_SRC
diff --git a/emacs/settings/defuns.el b/emacs/settings/defuns.el
deleted file mode 100644
index 3d33533..0000000
--- a/emacs/settings/defuns.el
+++ /dev/null
@@ -1,62 +0,0 @@
-;;; defuns.el --- Small utility functions
-
-;; Copyright (C) 2016-2017 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/>.
-
-;;; Commentary:
-;;
-;; Small utility functions
-
-;;; Code:
-
-(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))
-
-(defun mssola-cleanup-workspace ()
- "Cleanup the current workspace by killing all buffers and windows.
-The user will end up in the *scratch* buffer."
-
- (interactive)
- (when (y-or-n-p "Are you sure that you want to cleanup your workspace? ")
- (delete-other-windows)
- (switch-to-buffer "*scratch*")
-
- ; Code taken from 'crux-kill-other-buffers in the crux package by
- ; @bbatsov. It's the same but the confirmation has been removed since we are
- ; already asking for permission before.
- (seq-each
- #'kill-buffer
- (delete (current-buffer) (seq-filter #'buffer-file-name (buffer-list))))))
-
-(global-set-key (kbd "C-c a") 'mssola-cleanup-workspace)
-
-(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)))
-
-(provide 'defuns)
-;;; defuns.el ends here
diff --git a/emacs/settings/init-calendar.el b/emacs/settings/init-calendar.el
deleted file mode 100644
index 3d94354..0000000
--- a/emacs/settings/init-calendar.el
+++ /dev/null
@@ -1,45 +0,0 @@
-;;; init-calendar.el --- Configuration for Calendar mode
-
-;; Copyright (C) 2016-2017 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/>.
-
-;;; Commentary:
-;;
-;; Set Monday as the initial day and set Evil bindings.
-
-;;; Code:
-
-(defvar calendar-week-start-day 1)
-(global-set-key (kbd "C-c c") '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))
-
-(provide 'init-calendar)
-;;; init-calendar.el ends here
diff --git a/emacs/settings/init-dired.el b/emacs/settings/init-dired.el
deleted file mode 100644
index 55271aa..0000000
--- a/emacs/settings/init-dired.el
+++ /dev/null
@@ -1,49 +0,0 @@
-;;; init-dired.el --- Dired mode configuration
-
-;; Copyright (C) 2017 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.
-
-;;; Commentary:
-;;
-;; Set of settings for dired mode.
-
-; Add basic evil movement.
-(with-eval-after-load 'evil
- (evil-add-hjkl-bindings dired-mode-map 'normal
- (kbd "w") 'evil-forward-word-begin))
-
-; Allow dired mode to attach files to mu4e. Taken from:
-; https://www.djcbsoftware.nl/code/mu/mu4e/Dired.html#Dired.
-; With this, you will need to type C-c RET C-a, in order to attach the file
-; pointed by the cursor.
-
-(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)
-
-(provide 'init-dired)
-;;; init-dired.el ends here
diff --git a/emacs/settings/init-edit.el b/emacs/settings/init-edit.el
deleted file mode 100644
index 4bb1602..0000000
--- a/emacs/settings/init-edit.el
+++ /dev/null
@@ -1,109 +0,0 @@
-;;; init-edit.el --- Packages for improving the editing experience
-
-;; Copyright (C) 2016-2017 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.
-
-;;; Commentary:
-;;
-;; Set of packages for improving the editing experience.
-
-;;; Code:
-
-(require 'use-package)
-
-;; Disable overwrite-mode.
-(define-key global-map [(insert)] nil)
-
-;; undo-tree
-
-(global-undo-tree-mode 1)
-(setq undo-tree-visualizer-diff t)
-(setq undo-tree-visualizer-timestamps t)
-(with-eval-after-load 'evil-leader
- (evil-leader/set-key
- "u" 'undo-tree-visualize))
-
-;; Flycheck
-
-(use-package let-alist
- :ensure t)
-
-(use-package flycheck
- :ensure t
- :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))
-
-;; Let's increase fonts with C-+ and C--
-
-(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))
-
-;; We will add this manually to the desired modes.
-(use-package rainbow-delimiters
- :ensure t)
-
-;; Disable all mouse interactions
-(use-package disable-mouse
- :ensure t
- :config
- (global-disable-mouse-mode))
-
-;; Shows a popup with the available commands for the current chords. Helpful
-;; when you don't remember a specific combination.
-(use-package which-key
- :ensure t)
-
-;; Install wc-mode, which counts the number of words in the current buffer.
-(use-package wc-mode
- :ensure t)
-
-;; Distraction-free writing for GNU Emacs.
-(use-package writeroom-mode
- :ensure t)
-
-; Even though this is not entirely needed because Evil already covers most of
-; it, sometimes it's convenient to use it.
-(use-package expand-region
- :ensure t
- :config
-
- ; Set C-e as the expand command (mnemonic: expand). This command will
- ; supercede the evil binding for "move one line", which I never use anyways.
- (global-set-key (kbd "\C-e") 'er/expand-region)
- (with-eval-after-load 'evil
- (define-key evil-normal-state-map (kbd "\C-e") 'er/expand-region)
- (define-key evil-visual-state-map (kbd "\C-e") 'er/expand-region)))
-
-(defun er/add-text-mode-expansions ()
- "This way we can also expand the region into paragraphs & pages in text mode.
-Directly taken from: https://github.com/magnars/expand-region.el."
-
- (make-variable-buffer-local 'er/try-expand-list)
- (setq er/try-expand-list (append
- er/try-expand-list
- '(mark-paragraph
- mark-page))))
-
-(add-hook 'text-mode-hook 'er/add-text-mode-expansions)
-
-(provide 'init-edit)
-;;; init-edit.el ends here
diff --git a/emacs/settings/init-evil.el b/emacs/settings/init-evil.el
deleted file mode 100644
index c8e0906..0000000
--- a/emacs/settings/init-evil.el
+++ /dev/null
@@ -1,161 +0,0 @@
-;;; init-evil.el --- Evil configuration
-
-;; Copyright (C) 2016-2017 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/>.
-
-;;; Commentary:
-;;
-;; All the configuration related to Evil mode. This file tackles *only* Evil
-;; itself, not the configuration from other packages that provide evil bindings.
-
-;;; Code:
-
-(require 'use-package)
-
-(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)
-
- ; Helm + Projectile shortcuts.
- (with-eval-after-load 'helm-projectile
- (define-key evil-normal-state-map (kbd "M-p")
- 'helm-projectile-switch-project))
-
- ; I use the Super key in combination with j & k to move around i3. Let's unset
- ; M- combos for these two fellows for whenever I misstype them.
- (global-unset-key (kbd "M-j"))
- (global-unset-key (kbd "M-k"))
-
- ; both this function and the subsequent lines about [escape] are taken from
- ; @aaronbieber configuration.
- (defun minibuffer-keyboard-quit ()
- "Abort recursive edit.
-In Delete Selection mode, if the mark is active, just deactivate it;
-then it takes a second \\[keyboard-quit] to abort the minibuffer."
- (interactive)
- (if (and delete-selection-mode transient-mark-mode mark-active)
- (setq deactivate-mark t)
- (when (get-buffer "*Completions*") (delete-windows-on "*Completions*"))
- (abort-recursive-edit)))
-
- ;; Make escape quit everything, whenever possible.
- (define-key evil-normal-state-map [escape] 'keyboard-quit)
- (define-key evil-visual-state-map [escape] 'keyboard-quit)
- (define-key minibuffer-local-map [escape] 'minibuffer-keyboard-quit)
- (define-key minibuffer-local-ns-map [escape] 'minibuffer-keyboard-quit)
- (define-key minibuffer-local-completion-map [escape] 'minibuffer-keyboard-quit)
- (define-key minibuffer-local-must-match-map [escape] 'minibuffer-keyboard-quit)
- (define-key minibuffer-local-isearch-map [escape] 'minibuffer-keyboard-quit)
-
- ; 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))))
-
-(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)
- (set-quit-char "C-z")
-
- ;; 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)
-
- (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
- "," 'back-to-indentation
- "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
- "e" 'eval-last-sexp
- "b" 'view-buffer
- "o" 'browse-url-at-point))
-
- (use-package evil-surround
- :ensure t
- :config
- (global-evil-surround-mode 1))
-
- (use-package evil-commentary
- :ensure t
- :config
- (evil-commentary-mode t))
-
- (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))
-
- (use-package evil-numbers
- :ensure t
- :config
- (define-key evil-normal-state-map (kbd "C-a") 'evil-numbers/inc-at-pt)
- (define-key evil-normal-state-map (kbd "C-c -") 'evil-numbers/dec-at-pt)))
-
-
-(provide 'init-evil)
-;;; init-evil.el ends here
diff --git a/emacs/settings/init-general.el b/emacs/settings/init-general.el
deleted file mode 100644
index 3b76b96..0000000
--- a/emacs/settings/init-general.el
+++ /dev/null
@@ -1,142 +0,0 @@
-;;; init-general.el --- Basic general configuration
-
-;; Copyright (C) 2016-2017 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/>.
-
-;;; Commentary:
-;;
-;; General stuff like better defaults, appearance, basic editing, etc.
-
-;;; Code:
-
-;; UTF-8 *always*.
-(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)
-
-;; No welcome screen
-(setq-default inhibit-startup-message t)
-
-;; Enable y/n answers
-(fset 'yes-or-no-p 'y-or-n-p)
-
-;; 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*").
-(setq frame-title-format
- '((:eval
- (concat (user-real-login-name) ": "
- (if (buffer-file-name)
- (abbreviate-file-name (buffer-file-name))
- "%b")))))
-
-;; 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)
-
-;; Delete the selection with a keypress.
-(delete-selection-mode t)
-
-;; Revert buffers automatically when underlying files are changed externally
-(global-auto-revert-mode t)
-
-;; Do not break lines
-(set-default 'truncate-lines t)
-
-;; No backups
-(setq-default make-backup-files nil)
-(setq-default auto-save-default nil)
-
-;; Nice scrolling
-(setq scroll-margin 0
- scroll-conservatively 100000
- scroll-preserve-screen-position 1)
-
-;; Remove whitespaces at the end of line
-(add-hook 'before-save-hook 'delete-trailing-whitespace)
-
-;; Graphical interface tweaks
-(menu-bar-mode -1)
-(when (fboundp 'set-scroll-bar-mode)
- (set-scroll-bar-mode nil))
-(when (fboundp 'tool-bar-mode)
- (tool-bar-mode -1))
-
-;; Lines and columns
-(line-number-mode 1)
-(column-number-mode 1)
-
-;; Cursor
-(blink-cursor-mode 0)
-(global-hl-line-mode -1)
-(show-paren-mode 1)
-
-;; Follow symlinks
-(setq vc-follow-symlinks t)
-
-;; Default font
-
-(set-frame-font "Droid Sans Mono Dotted for Powerline-10")
-(add-to-list 'default-frame-alist '(font . "Droid Sans Mono Dotted for Powerline-10"))
-
-; 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 "Droid Sans Mono Dotted for Powerline-10")))
-
-; Use kill-this-buffer instead of kill-buffer
-(global-set-key (kbd "C-x k") 'kill-this-buffer)
-
-;; 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.
-(global-unset-key (kbd "C-z"))
-
-;; Disable all the Fn keys.
-(dotimes (i 12)
- (global-unset-key (kbd (format "<f%d>" (+ i 1)))))
-
-;; Let flyspell be performant.
-(defvar flyspell-issue-message-flag nil)
-
-; Kill Emacs. Sometimes useful when you have a server-client setup and you want
-; to *really* evaluate everything from scratch.
-(global-set-key (kbd "C-c k") 'kill-emacs)
-
-; Save custom-variables somewhere else.
-
-(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
-(if (file-exists-p custom-file)
- (load custom-file))
-
-;; Default theme
-(load-theme 'soria t)
-
-(provide 'init-general)
-;;; init-general.el ends here
diff --git a/emacs/settings/init-lang.el b/emacs/settings/init-lang.el
deleted file mode 100644
index aa983cf..0000000
--- a/emacs/settings/init-lang.el
+++ /dev/null
@@ -1,214 +0,0 @@
-;;; init-lang.el --- Settings for all programming languages
-
-;; Copyright (C) 2016-2017 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.
-
-;;; Commentary:
-;;
-;; Settings for all programming languages.
-
-;;; Code:
-
-(require 'use-package)
-
-(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\\)"
- 1 font-lock-warning-face prepend))))
-
-;; Text mode.
-(add-hook 'text-mode-hook
- (lambda ()
- (flyspell-mode 1)
- (wc-mode 1)))
-
-;; Emacs Lisp mode
-(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 "ξ")))
-
-;; C-common (it 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)))
-
-;; Ruby mode
-(add-hook 'ruby-mode-hook 'warnings-mode-hook)
-
-(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)
-
- (evil-leader/set-key
- "." 'godef-jump-other-window)
-
- (setq indent-tabs-mode t)
- (flyspell-prog-mode)
-
- ; eldoc support
- (use-package go-eldoc
- :ensure t
- :config
- (require 'go-eldoc))
-
- (use-package go-add-tags
- :ensure t
- :config
- (evil-leader/set-key "t" 'go-add-tags)))
-
-;; 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))
-
-;; Smart tabs
-(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))
-
-;; 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)))
-
-; Slim
-(use-package slim-mode
- :ensure t)
-
-; YAML
-(use-package yaml-mode
- :ensure t
- :config
-
- (add-hook 'yaml-mode-hook 'warnings-mode-hook))
-
-; SASS/SCSS
-(use-package scss-mode
- :ensure t
- :config
-
- (setq scss-compile-at-save nil)
- (add-hook 'yaml-mode-hook 'warnings-mode-hook))
-
-; Apply purple function identifiers to all these languages.
-(dolist (lang-hook '(ruby-mode-hook
- php-mode-hook
- perl-mode-hook
- emacs-lisp-mode-hook))
- (add-hook lang-hook 'soria-purple-identifiers))
-
-;; YASnippet
-(use-package yasnippet
- :ensure t
- :config
- (yas-reload-all)
- (add-hook 'prog-mode-hook #'yas-minor-mode))
-
-;; CMake
-(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)))
-
-(use-package dockerfile-mode
- :ensure t
- :config
-
- (add-to-list 'auto-mode-alist '("Dockerfile\\'" . dockerfile-mode)))
-
-(use-package terraform-mode
- :ensure t
- :config
-
- (terraform-format-on-save-mode))
-
-(use-package hcl-mode
- :ensure t)
-
-;(use-package salt-mode
- ;:ensure t)
-
-(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))))
-
-(provide 'init-lang)
-;;; init-lang.el ends here
diff --git a/emacs/settings/init-magit.el b/emacs/settings/init-magit.el
deleted file mode 100644
index f07ba52..0000000
--- a/emacs/settings/init-magit.el
+++ /dev/null
@@ -1,56 +0,0 @@
-;;; init-magit.el --- Magit configuration
-
-;; Copyright (C) 2016-2017 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.
-
-;;; Commentary:
-;;
-;; Magit configuration
-
-;;; Code:
-
-(require 'use-package)
-
-(use-package magit
- :ensure t
- :config
-
- ; Proper initial states.
- (with-eval-after-load 'evil
- (add-hook 'git-commit-mode-hook 'evil-insert-state)
- (evil-set-initial-state 'magit-log-edit-mode 'insert))
-
- ; When showing the status, hide the usually-redundant "branch" section and
- ; show the rest.
- (add-hook 'magit-section-set-visibility-hook
- '(lambda (section)
- (if (string= (magit-section-type section) "branch")
- 'hide
- 'show)))
-
- (with-eval-after-load 'evil-leader
- (evil-leader/set-key "s" 'magit-status)
-
- (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
- "\M-p" 'helm-projectile-switch-project))))
-
-(provide 'init-magit)
-;;; init-magit.el ends here
diff --git a/emacs/settings/init-misc.el b/emacs/settings/init-misc.el
deleted file mode 100644
index 04eb84a..0000000
--- a/emacs/settings/init-misc.el
+++ /dev/null
@@ -1,34 +0,0 @@
-;;; init-misc.el --- Miscellaneous packages
-
-;; Copyright (C) 2016-2017 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.
-
-;;; Commentary:
-;;
-;; Set of packages for improving the editing experience.
-
-;;; Code:
-
-(require 'use-package)
-
-;; Install a set of useful functions from @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).
-(use-package crux
- :ensure t
- :bind (("C-c d" . crux-delete-file-and-buffer)
- ("C-c r" . crux-rename-file-and-buffer)
- ("C-c i" . crux-find-user-init-file)
- ("C-c o" . crux-open-with)))
-
-(provide 'init-misc)
-;;; init-misc.el ends here
diff --git a/emacs/settings/init-mu4e.el b/emacs/settings/init-mu4e.el
deleted file mode 100644
index f0256a9..0000000
--- a/emacs/settings/init-mu4e.el
+++ /dev/null
@@ -1,262 +0,0 @@
-;;; init-mu4e.el --- Configuration for mu4e
-
-;; Copyright (C) 2016-2017 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.
-
-;;; Commentary:
-;;
-;; Configuration for mu4e. This configuration makes quite some assumptions.
-;; Read the `emacs/README.md` file as provided in my `dotfiles` project to
-;; get more details.
-
-;;; Code:
-
-; I'm using an RPM that I've built on OBS which installs mu4e globally. See:
-; https://build.opensuse.org/package/show/home:mssola/mu
-(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")
-(require 'mu4e)
-
-(when (featurep 'mu4e)
- ;; Diferent SMTP options that will be used for each context.
-
- (setq message-send-mail-function 'smtpmail-send-it
- mu4e-maildir (expand-file-name "~/.mail")
- starttls-use-gnutls t)
-
- (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
- smtpmail-smtp-service port))
-
- ;; Define the different accounts that I'm using. This is only available since
- ;; mu 0.9.16.
-
- ; https://www.reddit.com/r/emacs/comments/47t9ec/share_your_mu4econtext_configs/d0fsih6
- (defun mu4e-message-maildir-matches (msg 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"
- (concat "/" key "/Archives/"
- (format-time-string "%Y" (current-time))))
-
- (setq mu4e-contexts
- `(
- ;; GMail
- ,(make-mu4e-context
- :name "gmail"
- :enter-func (lambda ()
- (mu4e-message "Switching to gmail.com")
- (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")))
-
- ;; suse.com
- ,(make-mu4e-context
- :name "comsuse"
- :enter-func (lambda ()
- (mu4e-message "Switching to suse.com")
- (mssola-smtp "smtp.novell.com" 25))
- :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/Drafts")
- (mu4e-sent-folder . "/susecom/Sent")
- (mu4e-refile-folder . ,(suse-refile-folder "susecom"))
- (mu4e-trash-folder . "/susecom/Trash")))
-
- ;; suse.de
- ,(make-mu4e-context
- :name "desuse"
- :enter-func (lambda ()
- (mu4e-message "Switching to suse.de")
- (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")))))
-
- ; If mu4e cannot figure things out, ask me.
- (setq mu4e-context-policy 'ask)
- (setq mu4e-compose-context-policy 'ask)
-
- ; Fill the `mu4e-user-mail-address-list' variable with the contexts.
- (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)))
-
- ; Setting my bookmarks
- (setq mu4e-bookmarks
- '(("maildir:/gmail/inbox OR maildir:/susecom/inbox OR maildir:/susede/inbox" "Inbox Folders" ?n)
- ("flag:unread AND NOT flag:trashed" "Unread messages" ?u)
- ("date:today..now" "Today's messages" ?t)))
-
- ; Signature. This signature looks alright regardless of whether the client
- ; supports format=flowed or not.
- (setq mu4e-compose-signature
- (concat
- "Miquel Sabaté Solà,\n"
- "PGP: 4096R / 1BA5 3C7A C93D CA2A CFDF DA97 96BE 8C6F D89D 6565\n"))
-
- ; Sign outgoing emails always.
- (add-hook 'message-send-hook 'mml-secure-message-sign-pgpmime)
-
- ;; To avoid UID clashes. See:
- ;; http://pragmaticemacs.com/emacs/fixing-duplicate-uid-errors-when-using-mbsync-and-mu4e/
- (setq mu4e-change-filenames-when-moving t)
-
- ; Miscellaneous settings.
- (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-headers-skip-duplicates t
- mu4e-headers-include-related t
- mu4e-headers-auto-update t)
-
- ;; 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:
- (setq mu4e-headers-fields
- '( (:date . 18)
- (:mailing-list . 15)
- (:from-or-to . 20)
- (:subject . nil)))
-
- ; Show images
- (setq mu4e-view-show-images t
- mu4e-view-image-max-width 800)
-
- ; Use imagemagick, if available
- (when (fboundp 'imagemagick-register-types)
- (imagemagick-register-types))
-
- ; As of 0.9.18 and GNU Emacs 25, the mu4e-action-with-xwidget can be used to
- ; render an HTML message with Webkit.
- (if (>= emacs-major-version 25)
- (add-to-list 'mu4e-view-actions
- '("webkit" . mu4e-action-view-with-xwidget)))
-
- ; Look for mu4e-msg2pdf in the exec path.
- (let ((exec (locate-file "msg2pdf" exec-path exec-suffixes)))
- (if exec
- (setq mu4e-msg2pdf exec)))
-
- ;; Addings hooks for composing and viewing messages.
-
- (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)))
-
- ;; Helper packages.
-
- ; Desktop notifications
- (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) "
- "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)))))
-
- ; Define a proper shortcut.
- (global-set-key (kbd "C-c m") 'mu4e))
-
-(provide 'init-mu4e)
-;;; init-mu4e.el ends here
diff --git a/emacs/settings/init-org.el b/emacs/settings/init-org.el
deleted file mode 100644
index 16cb0ec..0000000
--- a/emacs/settings/init-org.el
+++ /dev/null
@@ -1,168 +0,0 @@
-;;; init-org.el --- Configuration for mu4e
-
-;; Copyright (C) 2016-2017 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.
-
-;;; Commentary:
-;;
-;; Configuration for org mode.
-
-;;; Code:
-
-(require 'org)
-
-;; Helper functions.
-
-(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)))
-
-;; General org config.
-
-;; TODO: wc mode in org-mode
-
-;; TODO: shortcut for making an org link, and transforming a link into a proper
-;; org link
-
-(with-eval-after-load 'evil
- ; TODO: doesn't work
- (define-key global-map (kbd "M-h") 'help-command)
- (fset 'help-command help-map))
-
-; TODO: this might overlap some existing keybindings
-;(global-set-key "\C-cl" 'org-store-link)
-;(global-set-key "\C-ca" 'org-agenda)
-;(global-set-key "\C-cb" 'org-iswitchb)
-
-(setq org-src-fontify-natively t)
-
-(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)))
-
-; Logging
-(setq org-log-done t)
-(setq org-log-redeadline (quote time))
-(setq org-log-reschedule (quote time))
-
-;; org-agenda
-
-(setq org-agenda-files '("~/org/"))
-
-(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)))))
-
-; The prefix for the different kinds of types being used.
-(setq org-agenda-prefix-format '((agenda . "%t%s")
- (tags . "%c:%s")
- (todo . "%c:%t%s")))
-
-(provide 'init-org)
-;;; init-org.el ends here
diff --git a/emacs/settings/init-project.el b/emacs/settings/init-project.el
deleted file mode 100644
index 038ea96..0000000
--- a/emacs/settings/init-project.el
+++ /dev/null
@@ -1,116 +0,0 @@
-;;; init-project.el --- Packages for interacting with projects
-
-;; Copyright (C) 2016-2017 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.
-
-;;; Commentary:
-;;
-;; Set of packages and their configurations for managing projects inside of
-;; GNU Emacs.
-
-;;; Code:
-
-(require 'use-package)
-
-;;; Ayo silver!
-
-(use-package ag
- :ensure t
- :config
-
- (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))
-
-;;; Projectile & Helm
-
-(use-package projectile
- :ensure t
- :config
- (projectile-mode 1)
- (setq projectile-mode-line
- '(:eval (format " %s" (projectile-project-name)))))
-
-(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-in-side-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)
-
- (use-package helm-ag
- :ensure t))
-
-(use-package helm-projectile
- :ensure t
- :config
- (helm-projectile-on))
-
-;;; Finally setup the bindings for Evil mode
-
-(defun mssola-helm-ag ()
- "Call the right ag command for helm-ag."
-
- (interactive)
-
- (condition-case nil
- (helm-ag-project-root)
- (error (helm-ag))))
-
-(defun mssola-find-file ()
- "Call the proper Helm function for finding files."
-
- (interactive)
-
- (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))
-
-(with-eval-after-load 'evil-leader
- (evil-leader/set-key "a" 'mssola-helm-ag))
-
-(provide 'init-project)
-;;; init-project.el ends here
diff --git a/install.sh b/install.sh
index e913112..3b54e07 100755
--- a/install.sh
+++ b/install.sh
@@ -57,6 +57,12 @@ cp -rf vim $HOME/.vim
cp vimrc $HOME/.vimrc
vim +PluginInstall +qall
+# GNU Emacs
+rm -rf $HOME/.emacs.d
+cp emacs/custom.el $HOME/.emacs.d/custom.el
+cp emacs/init.el $HOME/.emacs.d/init.el
+ln -s emacs/init.org $HOME/.emacs.d/init.org
+
# Wipe out weechat config and install it again
rm -rf $HOME/.weechat
cp -r weechat $HOME/.weechat