diff options
Diffstat (limited to 'emacs')
| -rw-r--r-- | emacs/README.org | 39 | ||||
| -rw-r--r-- | emacs/custom.el | 23 | ||||
| -rw-r--r-- | emacs/init.el | 109 | ||||
| -rw-r--r-- | emacs/init.org | 1547 | ||||
| -rw-r--r-- | emacs/settings/defuns.el | 62 | ||||
| -rw-r--r-- | emacs/settings/init-calendar.el | 45 | ||||
| -rw-r--r-- | emacs/settings/init-dired.el | 49 | ||||
| -rw-r--r-- | emacs/settings/init-edit.el | 109 | ||||
| -rw-r--r-- | emacs/settings/init-evil.el | 161 | ||||
| -rw-r--r-- | emacs/settings/init-general.el | 142 | ||||
| -rw-r--r-- | emacs/settings/init-lang.el | 214 | ||||
| -rw-r--r-- | emacs/settings/init-magit.el | 56 | ||||
| -rw-r--r-- | emacs/settings/init-misc.el | 34 | ||||
| -rw-r--r-- | emacs/settings/init-mu4e.el | 262 | ||||
| -rw-r--r-- | emacs/settings/init-org.el | 168 | ||||
| -rw-r--r-- | emacs/settings/init-project.el | 116 |
16 files changed, 1622 insertions, 1514 deletions
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 |
