aboutsummaryrefslogtreecommitdiff
path: root/emacs/settings
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <msabate@suse.com>2016-11-17 12:50:00 +0100
committerMiquel Sabaté Solà <msabate@suse.com>2016-11-17 12:50:00 +0100
commit44a504dc3c8e6171dc066b2c19b7769525388896 (patch)
treedba04234c2268a094c6a1ce8d33e0abc24218788 /emacs/settings
parent3e5d6e81072b11c6d7a719cb3f3e484dc61d4c7e (diff)
downloaddotfiles-44a504dc3c8e6171dc066b2c19b7769525388896.tar.gz
dotfiles-44a504dc3c8e6171dc066b2c19b7769525388896.zip
emacs: split init.el into different files
The init.el was about to surpass the 1000 LoC threshold, and it was no longer easy to structure the code. Thus, I've moved the different pieces into new files. Signed-off-by: Miquel Sabaté Solà <msabate@suse.com>
Diffstat (limited to 'emacs/settings')
-rw-r--r--emacs/settings/defuns.el62
-rw-r--r--emacs/settings/init-calendar.el46
-rw-r--r--emacs/settings/init-edit.el89
-rw-r--r--emacs/settings/init-evil.el157
-rw-r--r--emacs/settings/init-general.el133
-rw-r--r--emacs/settings/init-lang.el193
-rw-r--r--emacs/settings/init-magit.el56
-rw-r--r--emacs/settings/init-misc.el34
-rw-r--r--emacs/settings/init-mu4e.el261
-rw-r--r--emacs/settings/init-project.el119
10 files changed, 1150 insertions, 0 deletions
diff --git a/emacs/settings/defuns.el b/emacs/settings/defuns.el
new file mode 100644
index 0000000..4de9573
--- /dev/null
+++ b/emacs/settings/defuns.el
@@ -0,0 +1,62 @@
+;;; defuns.el --- Small utility functions
+
+;; Copyright (C) 2016 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
new file mode 100644
index 0000000..a5b80c5
--- /dev/null
+++ b/emacs/settings/init-calendar.el
@@ -0,0 +1,46 @@
+;;; init-calendar.el --- Configuration for Calendar mode
+
+;; Copyright (C) 2016 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)
+
+(eval-after-load "evil"
+ '(progn
+ (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-edit.el b/emacs/settings/init-edit.el
new file mode 100644
index 0000000..5d8dd7f
--- /dev/null
+++ b/emacs/settings/init-edit.el
@@ -0,0 +1,89 @@
+;;; init-edit.el --- Packages for improving the editing experience
+
+;; Copyright (C) 2016 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)
+
+;; 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)
+
+; 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)
+ (eval-after-load 'evil
+ '(progn
+ (define-key evil-normal-state-map (kbd "\C-e") 'er/expand-region)
+ (define-key evil-visual-state-map (kbd "\C-e") 'er/expand-region))))
+
+; Directly taken from: https://github.com/magnars/expand-region.el. This way we
+; can also expand the region into paragraphs and pages in text mode.
+(defun er/add-text-mode-expansions ()
+ (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
new file mode 100644
index 0000000..d0e8e91
--- /dev/null
+++ b/emacs/settings/init-evil.el
@@ -0,0 +1,157 @@
+;;; init-evil.el --- Evil configuration
+
+;; Copyright (C) 2016 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.
+ (eval-after-load 'helm-projectile
+ '(progn
+ (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-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
new file mode 100644
index 0000000..33d8d67
--- /dev/null
+++ b/emacs/settings/init-general.el
@@ -0,0 +1,133 @@
+;;; init-general.el --- Basic general configuration
+
+;; Copyright (C) 2016 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")))
+
+;; 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)
+
+;; 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
new file mode 100644
index 0000000..e53b969
--- /dev/null
+++ b/emacs/settings/init-lang.el
@@ -0,0 +1,193 @@
+;;; init-lang.el --- Settings for all programming languages
+
+;; Copyright (C) 2016 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)))
+
+;; Emacs Lisp mode
+(add-hook 'emacs-lisp-mode-hook 'eldoc-mode)
+(add-hook 'emacs-lisp-mode-hook 'warnings-mode-hook)
+(add-hook 'emacs-lisp-mode-hook #'rainbow-delimiters-mode)
+
+;; 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)
+
+(provide 'init-lang)
+;;; init-lang.el ends here
diff --git a/emacs/settings/init-magit.el b/emacs/settings/init-magit.el
new file mode 100644
index 0000000..7ddbc3c
--- /dev/null
+++ b/emacs/settings/init-magit.el
@@ -0,0 +1,56 @@
+;;; init-magit.el --- Magit configuration
+
+;; Copyright (C) 2016 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.
+ (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)))
+
+ (eval-after-load 'evil-leader
+ '(progn
+ (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
new file mode 100644
index 0000000..1a2a64f
--- /dev/null
+++ b/emacs/settings/init-misc.el
@@ -0,0 +1,34 @@
+;;; init-misc.el --- Miscellaneous packages
+
+;; Copyright (C) 2016 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
new file mode 100644
index 0000000..b008af5
--- /dev/null
+++ b/emacs/settings/init-mu4e.el
@@ -0,0 +1,261 @@
+;;; init-mu4e.el --- Configuration for mu4e
+
+;; Copyright (C) 2016 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:
+
+;; TODO: sending emails is a bit screwed in my current setup...
+
+;; TODO: refile
+;;; http://comments.gmane.org/gmane.mail.mu.general/631
+;;; https://www.djcbsoftware.nl/code/mu/mu4e/Refiling-messages.html
+;;; https://www.djcbsoftware.nl/code/mu/mu4e/Smart-refiling.html
+;;; http://www.djcbsoftware.nl/code/mu/mu4e/Retrieval-and-indexing.html
+
+;; TODO: evil commands such as C-h, C-l
+;; TODO: remove whole thread ?
+;; TODO: signature below quote
+;; TODO: gmail flags
+;; TODO: msmtp
+
+; 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)
+ ; Define a proper shortcut.
+ (global-set-key (kbd "C-c m") '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-gmail-smtp ()
+ (require 'smtpmail)
+
+ (setq smtpmail-starttls-credentials
+ '(("smtp.gmail.com" 587 nil nil))
+ smtpmail-auth-credentials
+ (expand-file-name "~/.authinfo.gpg")
+ smtpmail-default-smtp-server "smtp.gmail.com"
+ smtpmail-smtp-server "smtp.gmail.com"
+ smtpmail-smtp-service 587))
+
+ (defun mssola-suse-smtp ()
+ (require 'smtpmail)
+
+ (setq smtpmail-starttls-credentials
+ '(("smtp.novell.com" 25 nil nil))
+ smtpmail-auth-credentials
+ (expand-file-name "~/.authinfo.gpg")
+ smtpmail-default-smtp-server "smtp.novell.com"
+ smtpmail-smtp-server "smtp.novell.com"
+ smtpmail-smtp-service 25))
+
+ ;; Define the different accounts that I'm using. This is only available since
+ ;; mu 0.9.16.
+
+ (setq mu4e-contexts
+ `(
+ ;; GMail
+ ,(make-mu4e-context
+ :name "gmail"
+ :enter-func (lambda ()
+ (mu4e-message "Switching to gmail.com")
+ (mssola-gmail-smtp))
+ :match-func (lambda (msg)
+ (when msg
+ (mu4e-message-contact-field-matches
+ msg :to "mikisabate@gmail.com")))
+ :vars '(
+ (user-mail-address . "mikisabate@gmail.com")
+ (user-full-name . "Miquel Sabaté Solà")
+ (mu4e-reply-to-address . "mikisabate@gmail.com")
+ (mu4e-drafts-folder . "/gmail/Drafts")
+ (mu4e-sent-folder . "/gmail/Sent")
+ (mu4e-trash-folder . "/gmail/Trash")))
+
+ ;; suse.com
+ ,(make-mu4e-context
+ :name "comsuse"
+ :enter-func (lambda ()
+ (mu4e-message "Switching to suse.com")
+ (mssola-suse-smtp))
+ :match-func (lambda (msg)
+ (when msg
+ (mu4e-message-contact-field-matches
+ msg :to "msabate@suse.com")))
+ :vars '(
+ (user-mail-address . "msabate@suse.com")
+ (user-full-name . "Miquel Sabaté Solà")
+ (mu4e-reply-to-address . "msabate@suse.com")
+ (mu4e-drafts-folder . "/susecom/Drafts")
+ (mu4e-sent-folder . "/susecom/Sent")
+ (mu4e-trash-folder . "/susecom/Trash")))
+
+ ;; suse.de
+ ,(make-mu4e-context
+ :name "desuse"
+ :enter-func (lambda ()
+ (mu4e-message "Switching to suse.de")
+ (mssola-suse-smtp))
+ :match-func (lambda (msg)
+ (when msg
+ (mu4e-message-contact-field-matches
+ msg :to "msabate@suse.de")))
+ :vars '(
+ (user-mail-address . "msabate@suse.de")
+ (user-full-name . "Miquel Sabaté Solà")
+ (mu4e-reply-to-address . "msabate@suse.de")
+ (mu4e-drafts-folder . "/susede/Drafts")
+ (mu4e-sent-folder . "/susede/Sent")
+ (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)))
+
+ ; Signature.
+ (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
+ (add-hook 'message-send-hook 'mml-secure-message-sign-pgpmime)
+
+ ; Don't save message to Sent Messages, mbsync will take care of that.
+ (setq mu4e-sent-messages-behavior 'delete)
+
+ ;; 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 120
+ mu4e-compose-dont-reply-to-self t
+ mu4e-headers-skip-duplicates t
+ mu4e-headers-include-related t
+ mu4e-headers-auto-update t)
+
+ ;; Setting up shortcuts that can be composed with mu4e commands. For
+ ;; example, in this setup, pressin `ji` will jump to the inbox, and `ma`
+ ;; will move an email to the `All Mail` folder.
+ (setq mu4e-maildir-shortcuts
+ '( ("/INBOX" . ?i)
+ ("/Sent" . ?s)
+ ("/Trash" . ?t)
+ ("/Drafts" . ?d)))
+
+ ;; 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))
+
+ ; Webkit support for viewing HTML emails. See the following discussion:
+ ; https://groups.google.com/forum/#!topic/mu-discuss/JqHEGycEyKI
+ (defun my-mu4e-action-view-with-xwidget (msg)
+ "View the body of the message inside xwidget-webkit."
+ (unless (fboundp 'xwidget-webkit-browse-url)
+ (mu4e-error "No xwidget support available"))
+ (let* ((html (mu4e-message-field msg :body-html))
+ (txt (mu4e-message-field msg :body-txt))
+ (tmpfile (format "%s%x.html" temporary-file-directory (random t))))
+ (unless (or html txt)
+ (mu4e-error "No body part for this message"))
+ (with-temp-buffer
+ ;; simplistic -- but note that it's only an example...
+ (insert (or html (concat "<pre>" txt "</pre>")))
+ (write-file tmpfile)
+ (xwidget-webkit-browse-url (concat "file://" tmpfile) t))))
+
+ (add-to-list 'mu4e-view-actions
+ '("xViewXWidget" . my-mu4e-action-view-with-xwidget) t)
+
+ ; Spell check
+ (add-hook 'mu4e-compose-mode-hook
+ (lambda ()
+ "My settings for message composition."
+ (set-fill-column 99999)
+ (flyspell-mode)))
+
+ ; Restore some of my evil config.
+ ; TODO: doesn't work
+ (dolist (imap '(mu4e-main-mode-map mu4e-headers-mode-map mu4e-view-mode-map))
+ (evil-define-key 'evil-mu4e-state imap
+ "\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))
+
+ ; Desktop notifications
+ (use-package mu4e-alert
+ :ensure t
+ :config
+
+ (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
+ "flag:unread AND NOT flag:trashed")
+ (setq mu4e-alert-email-notification-types '(count)))
+
+ ; Evil mode in mu4e
+ (eval-after-load 'evil
+ '(progn
+ (use-package evil-mu4e
+ :ensure t
+ :config))))
+
+(setq mu4e-update-interval 120)
+
+(provide 'init-mu4e)
+;;; init-mu4e.el ends here
diff --git a/emacs/settings/init-project.el b/emacs/settings/init-project.el
new file mode 100644
index 0000000..36b9199
--- /dev/null
+++ b/emacs/settings/init-project.el
@@ -0,0 +1,119 @@
+;;; init-project.el --- Packages for interacting with projects
+
+;; Copyright (C) 2016 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
+
+ (eval-after-load 'evil
+ '(progn
+ (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-global-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))))
+
+(eval-after-load 'evil
+ '(progn
+ (define-key evil-normal-state-map (kbd "C-p") 'mssola-find-file)))
+
+(eval-after-load 'evil-leader
+ '(progn
+ (evil-leader/set-key "a" 'mssola-helm-ag)))
+
+(provide 'init-project)
+;;; init-project.el ends here