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