Skip to content

Latest commit

 

History

History
2080 lines (1677 loc) · 66.7 KB

README.org

File metadata and controls

2080 lines (1677 loc) · 66.7 KB

My Emacs Config

Introduction

The idea of generating an emacs config file using org-mode is taken from Harry Schwartz’s talk about org-mode. When Emacs starts, all the elisp code blocks from this file are parsed and used to generate the config. This is done through org-babel. Babel is Org-mode’s ability to execute source code within org-mode documents.

To use this config file, you need to evaluate this file on startup. This can be done writing this line (org-babel-load-file "~/.my-emacs/README.org") into your init.el.

NOTE: This file assumes that your org-mode config file is located into ~/.my-emacs/README.org.

Basic Emacs Setup

My information

Relevant personal information that Emacs needs.

(setq user-full-name "Daniel Laguna"
    user-mail-address "[email protected]"
    calendar-latitude 40.33
    calendar-longitude -3.76
    calendar-location-name "Madrid, Spain")

Adding MELPA

MELPA is the main package repository for Emacs. There are more repositories and you are able to add more than one. But make sure you are using HTTPS!!.

;; Set up the package manager and repositories
(require 'package)

(add-to-list 'package-archives '("MELPA" . "https://melpa.org/packages/"))
(add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/"))

(setq package-enable-at-startup nil)
(package-initialize)

Install use-package

Emacs has a built-in package manager that makes easy to install packages. use-package makes things easier though. As a consequence, I need to write less emacs-lisp code, and along with org-mode, it makes easier the maintenance of a configuration file.

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(eval-when-compile
  (require 'use-package))

Set where is the emacs configuration repository

This variable defines where this repository is located in your filesystem, as this variable is used later in the configuration. So yes, is where your Emacs configuration lives, so change it to where you store your conf files.

(setq conf-dir "~/.my-emacs/")

TAB

<TAB> key run indentation in most of the major mode. Sometimes, I want to <TAB> behaves as inserting a tab character. I can do this typing C-q-<TAB> but I don’t like the default widht so I change it to 4. Also, I want to try white spaces indentation so I deactivated the tab based indentation.

(setq-default tab-width 4)

(global-set-key (kbd "C-c w") 'whitespace-mode)
(add-hook 'prog-mode-hook (lambda () (interactive) (setq show-trailing-whitespace 1)))

(setq-default indent-tabs-mode nil)

Set window title to buffer name

With this option the window title will be as the filename or like the name of the unsaved buffer. Handy when you want to classify *Emacs Anywhere* unsaved buffers and set as floating panes within i3.

(setq frame-title-format '("%b"))

Disable yes-or-no messages

There are different types of confirmation prompts in Emacs. One of them forces you to write yes and the other one only to press y, so I disable the first type.

(fset 'yes-or-no-p 'y-or-n-p)

Disabling the default startup message

I prefer to have a scratch buffer ready when booting up with org-mode running

(setq inhibit-splash-screen t
      initial-scratch-message nil
      initial-major-mode 'org-mode)

Disable the warning when killing a buffer with process

When a buffer has an associated process, Emacs will prompt you when trying to kill it asking for confirmation. I preferred to disable this behaviour.

(setq kill-buffer-query-functions
      (remq 'process-kill-buffer-query-function
             kill-buffer-query-functions))

Fix scroll

Setting this values will force one-line scrolling everywhere (mouse and keyboard), resulting most of the times in a smoother scrolling than the actual smooth scolling.

(setq scroll-step            1
      scroll-conservatively  10000
      mouse-wheel-scroll-amount '(1 ((shift) . 1))
      mouse-wheel-progressive-speed nil
      mouse-wheel-follow-mouse 't)

Wrap lines

Setting this value, the lines will wrap in all buffers when collapsing.

(global-visual-line-mode t)

Set the backups folder

Backups are always fancy. But emacs, blows up all my project folders with swarms of #foo# files. That’s why I set them to a backup folder and stop them from polluting everywhere.

(setq backup-directory-alist '(("." . "~/.emacs.d/backup"))
      backup-by-copying t
      version-control t
      delete-old-versions t
      kept-new-versions 20
      kept-old-versions 5)

Auto-fill comments

For our comments (only comments, not code) to be automatically filled in programming modes, we can use this function:

(defun comment-auto-fill ()
  (setq-local comment-auto-fill-only-comments t)
  (auto-fill-mode 1))

(add-hook 'prog-mode-hook 'comment-auto-fill)

Increase or decrease font size across all buffers

Extracted from a file in Steve Purcell’s Emacs configuration, it is possible to use this functions to increase or decrease the text scale in all Emacs. Specially useful for presentations, demos and other shows alike.

(defun font-name-replace-size (font-name new-size)
  (let ((parts (split-string font-name "-")))
    (setcar (nthcdr 7 parts) (format "%d" new-size))
    (mapconcat 'identity parts "-")))

(defun increment-default-font-height (delta)
  "Adjust the default font height by DELTA on every frame.
The pixel size of the frame is kept (approximately) the same.
DELTA should be a multiple of 10, in the units used by the
:height face attribute."
  (let* ((new-height (+ (face-attribute 'default :height) delta))
         (new-point-height (/ new-height 10)))
    (dolist (f (frame-list))
      (with-selected-frame f
        ;; Latest 'set-frame-font supports a "frames" arg, but
        ;; we cater to Emacs 23 by looping instead.
        (set-frame-font (font-name-replace-size (face-font 'default)
                                                new-point-height)
                        t)))
    (set-face-attribute 'default nil :height new-height)
    (message "default font size is now %d" new-point-height)))

(defun increase-default-font-height ()
  (interactive)
  (increment-default-font-height 10))

(defun decrease-default-font-height ()
  (interactive)
  (increment-default-font-height -10))

(global-set-key (kbd "C-M-=") 'increase-default-font-height)
(global-set-key (kbd "C-M--") 'decrease-default-font-height)

Add functions to determine system

One liner functions to know in which system we are running.

(defun system-is-mac ()
  (interactive)
  (string-equal system-type "darwin"))

(defun system-is-linux ()
  (interactive)
  (string-equal system-type "gnu/linux"))

(defun system-is-chip ()
  (interactive)
  (string-equal system-name "chip"))

(defun system-is-windows ()
  (interactive)
  (or (string-equal system-name "windows-nt")
      (string-equal system-name "cygwin")))

Tramp configuration

The Transparent Remote Access, Multiple Protocols enables editing remote files using different protocols. It’s very easy to use because the user doen not have to worry about anything.

I only had one problem with it. TRAMP doesn’t recognized the remote shell prompt because the server used a customised prompt, so TRAMP hangs with the message ”Waiting for prompts from remote shell”. This is easy to fix adding .* to the tramp-shell-prompt-pattern variable as said in emacs wiki.

(setq tramp-shell-prompt-pattern "\\(?:^\\|\r\\)[^]#$%>\n]*#?[]#$%>].* *\\(^[\\[[0-9;]*[a-zA-Z] *\\)*")

Esc key as C-g

(global-set-key (kbd "<escape>") 'keyboard-escape-quit)

Define keybindings to eval-buffer on init and open README.org

Really loving this emacs org-mode configuration. It was easier to reload the configuration on the fly: M-x eval-buffer RET. However the buffer to evalute is not this one, but .emacs.d/init.el. That’s whu it’s probably a better idea to define a new keybinding that automatically reloads that buffer.

(defun reload-emacs-configuration ()
  "Reload the configuration"
  (interactive)
  (load "~/.emacs.d/init.el"))

(defun open-emacs-configuration ()
  "Open the configuration.org file in buffer"
  (interactive)
  (find-file (concat conf-dir "README.org")))

(global-set-key (kbd "C-c c r") 'reload-emacs-configuration)
(global-set-key (kbd "C-c c o") 'open-emacs-configuration)

Scroll in the compilation buffer

It’s really annoying to not have the last part of the output in the screen when compiling. This automatically scrolls the buffer for you as the output is printed.

(setq compilation-scroll-output t)

Add other keybindings

In this section goes all these keybindings that don’t really fit anywhere else.

;(global-set-key (kbd "C-c b") 'bookmark-jump)

Emacs GUI

Disabling GUI bars

The Emacs GUI client has this tools bars that I don’t like too much. I prefer a clean layout with the simple mode-line and without a scroll-bar, as if it were Vim.

(tool-bar-mode -1)
(menu-bar-mode -1)
(scroll-bar-mode -1)

Setting default font

I used Monaco or Dejavu Sans for years and I really liked. Even this last year I tried Source Code Pro that I liked too. This time I want to give a try to something different as Fantasque Sans Mono. As the author describe it is a programming font designed with functionality in mind, and with some wibbly-wobbly handwriting-like fuzziness that makes it unassumingly cool.

In order to set the font globally in Emacs run the following.

(set-face-attribute 'default nil :font "Fantasque Sans Mono 11")
(set-frame-font "Fantasque Sans Mono 11" nil t)

The font is not set when Emacs runs in daemon mode. Call add a callback in after-make-frame-functions. This functions are called when a new frame is created.

(defun set-custom-font (frame)
  (interactive)
  (set-face-attribute 'default frame
                      :font "Fantasque Sans Mono 11")
  (set-face-attribute 'variable-pitch frame
                      :font "Fantasque Sans Mono 11")
  (set-face-attribute 'fixed-pitch frame
                      :font "Fantasque Sans Mono 11")
  (set-face-attribute 'tooltip frame
                      :font "Fantasque Sans Mono 11"))

(add-to-list 'after-make-frame-functions 'set-custom-font t)

Highlight changed and uncommited lines

Use the git-gutter-fringe package for that. I have it activated for prog-mode and org-mode.

(use-package git-gutter-fringe
  :ensure t
  :config

  (add-hook 'prog-mode-hook 'git-gutter-mode)
  (add-hook 'org-mode-hook  'git-gutter-mode))

Setting solarized theme

I’ve been using grubvox dark theme for a long time on vim and in my firsts steps with emacs. But, I’ve always been in love with solarized-light. On my opinion, solarized doesn’t looks pretty on vim. But looks sexy on emacs.

(use-package solarized-theme
  :ensure t
  :init
  (setq solarized-use-variable-pitch nil)
  (setq solarized-scale-org-headlines nil)
  :config
  (load-theme 'solarized-light t)
  (set-face-attribute 'org-block nil :background "#f9f2d9"))

Disable splitting frames to creating frames

This functionality is to be used along i3wm in order to delegate window management to i3 completely. There is also a couple of functions that must be overriden in order to make everything work seamlessly.

;; Fix quit-window definitions to get rid of buffers
(defun quit-window-dwim (&optional args)
  "`delete-frame' if closing a single window, else `quit-window'."
  (interactive)
  (if (one-window-p)
      (delete-frame)
    (quit-window args)))

(defun running-i3 ()
  (string-match-p
   (regexp-quote "i3")
   (shell-command-to-string "echo $DESKTOP_SESSION")))

(defun set-up-i3 ()
  (interactive)
  (setq-default pop-up-frames 'graphic-only
                magit-bury-buffer-function 'quit-window-dwim
                magit-commit-show-diff nil)
  (substitute-key-definition 'quit-window 'quit-window-dwim
                             global-map)
  (substitute-key-definition 'quit-window 'quit-window-dwim
                             help-mode-map)
  (substitute-key-definition 'quit-window 'quit-window-dwim
                             Buffer-menu-mode-map)
  (message "Configuration for i3 applied"))

(when (running-i3)
  (set-up-i3))

This last line checks up if i3 is running and sets everything up (duh), but when Emacs is started as a daemon in systemd or before actually running i3, this check will fail. My solution is to run emacsclient -e “(set-up-i3)” in my i3 configuration, so that i3 is the one actually telling the Emacs daemon to get the proper settings.

Mode-line configuration

These two packages developed by Jonas Bernoulli, provide a beautiful and simple mode-line that shows all the information in a beautiful and minimalistic way. The general mode-lin aesthetics and distribution is provided by moody, while minions hide all the minor modes and provides an on-click menu to show them. So, I don’t need anymore the delight package to hide all the actually active minor modes.

(use-package minions
  :ensure t
  :config

  (setq minions-mode-line-lighter "[+]")
  (minions-mode))

(use-package moody
  :ensure t
  :config

  (setq x-underline-at-descent-line t
        column-number-mode t)

  (moody-replace-mode-line-buffer-identification)
  (moody-replace-vc-mode)

  (let ((line (face-attribute 'mode-line :underline)))
    (set-face-attribute 'mode-line          nil :overline   line)
    (set-face-attribute 'mode-line-inactive nil :overline   line)
    (set-face-attribute 'mode-line-inactive nil :underline  line)
    (set-face-attribute 'mode-line          nil :box        nil)
    (set-face-attribute 'mode-line-inactive nil :box        nil)
    (set-face-attribute 'mode-line-inactive nil :background "#f9f2d9")))

Highlight matching parenthesis

As the title says, this mode highlight matching parenthesis under the cursor

(setq show-paren-delay 0)
(show-paren-mode 1)

Programming Modes

company

Company is a text completion framework for Emacs. The name stands for “complete anything”. It uses pluggable back-ends and front-ends to retrieve and display completion candidates.

Add company-tng-frontend if you like YCM Vim completion :P

(use-package company
  :ensure t
  :config
    (setq company-tooltip-align-annotations t)
    (eval-after-load 'company
      '(progn
        (add-hook 'prog-mode-hook 'company-mode)
        (add-to-list 'company-frontends 'company-tng-frontend)
        (define-key company-active-map (kbd "TAB") 'company-complete-common-or-cycle)
        (define-key company-active-map [tab] 'company-complete-common-or-cycle)
        (define-key company-active-map (kbd "S-TAB") 'company-select-previous)
        (define-key company-active-map (kbd "<backtab>") 'company-select-previous)

        (define-key company-mode-map (kbd "C-<SPC>") 'company-complete))))

With company-flx we add fuzzy matching to company. But it seems only work with company-capf backend.

(use-package company-flx
  :ensure t
  :config
    (eval-after-load 'company
      (company-flx-mode +1)))

C/C++

I’ve been using NeoVim with YouCompleteMe for C/C++ development. But, I want to change my default text editor to emacs. So, this section sums up my research on C/C++ related emacs packages.

First of all lets set the indentation mode to the one you are used to. Personally I prefer the one Stroustrup follows.

(add-hook 'c++-mode-hook (lambda () (c-set-style "stroustrup")))

cmake-mode

This package provides syntax highlight in CMakeLists.txt files and completions via company-cmake backend. Very useful when creating the CMake files.

(use-package cmake-mode
  :ensure t)

ggtags

Provides an emacs frontend to GNU Global source code tagging system. You have to generate the tags database calling gtags on top of the project.

(use-package ggtags
  :ensure t
  :hook (c++-mode . ggtags-mode)
  :bind (:map ggtags-mode-map
         ("C-c g s" . ggtags-find-other-symbol)
         ("C-c g h" . ggtags-view-tag-history)
         ("C-c g r" . ggtags-find-reference)
         ("C-c g f" . ggtags-find-file)
         ("C-c g c" . ggtags-create-tags)
         ("C-c g u" . ggtags-update-tags)
         ("M-," . pop-tag-mark))
  :config

  (setq-local imenu-create-index-function #'ggtags-build-imenu-index))

Header completion with company-c-headers

This backend provides header completion from system headers #include <header> and user provided per project #include "header".

In order to say where the backend have to look for the headers, you have to add the system paths to the list company-c-headers-path-system. And also per project to the list company-c-headers-path-user.

(use-package company-c-headers
  :ensure t
  :config

  (add-to-list 'company-c-headers-path-system '"/usr/include/c++/8.2.1/")
  (add-to-list 'company-backends 'company-c-headers))

semantic minor mode

This package provides language-aware editing commands base on source code parsers.

(require 'semantic)

(global-semanticdb-minor-mode)
(global-semantic-idle-scheduler-mode)

;(add-hook 'c++-mode-hook (lambda () (semantic-mode)))

irony

(use-package irony
  :ensure t
  :config

  (add-hook 'c++-mode-hook 'irony-mode)
  (add-hook 'c-mode-hook 'irony-mode)
  (add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options))
(use-package company-irony
  :ensure t
  :config

  (eval-after-load 'company
    '(add-to-list 'company-backends 'company-irony)))

Python

In order to use ipython as default interpreter set these lines below.

(setq python-shell-interpreter "ipython"
      python-shell-interpreter-args "--simple-prompt -i")

I’ve set a global tab-width in basic emacs setup. But it seems not working in python-mode.

(add-hook 'python-mode-hook
      (lambda ()
        (setq tab-width 4)))

Regular Python configuration

elpy provides IDE-kind functionality for Emacs. Right now is the best python package I tried for emacs. It comes with flymake as default syntax checker though. I deactivated it in favor of flycheck.

(use-package elpy
  :ensure t
  :config

  (elpy-enable)
  (remove-hook 'elpy-modules 'elpy-module-flymake)

  (add-hook 'elpy-mode-hook (lambda () (highlight-indentation-mode -1))))

Package for Python docstrings

This package adds some nice features like automatic creation of docstrings and highlighting in them. There is also another package for better highlight and indentation of the comments.

(use-package sphinx-doc
  :ensure t
  :hook (python-mode . sphinx-doc-mode))

(use-package python-docstring
  :ensure t
  :config (setq python-docstring-sentence-end-double-space nil)
  :hook (python-mode . python-docstring-mode))

Jupyter Notebook

EIN provides a client for IPython and Jupyter notebooks inside emacs. This allows use all the emacs features inside the notebooks.

(use-package ein
  :ensure t
  :hook (ein:notebook-multilang-mode
         . (lambda () (ws-butler-mode -1) (visual-line-mode)))
  :custom-face
  (ein:cell-input-area ((t (:background "#f9f2d9")))))

Cython

I am very curious about Cython, until now I have been using C++ boost library in order to write my Python wrappers around C/C++ code. Cython provides a variant of Python syntax such as optional static type declarations (this is not the same as mypy) that provides speed improvements when the code is compiled. Therefore, all the Cython code you write is compiled to .c files and then a C compiler compiles it to a shared library .so which can be imported directly into the normal CPython interpreter.

In order to be able to compile Cython code you will need to write a distutils/setuptools setup.py file. You can read about how to do it here.

The next lines are just some emacs packages that will help you to write your Cython code.

(use-package cython-mode
  :ensure t)

(use-package flycheck-cython
  :ensure t)

Emacs Lisp and Lisp

It is time to learn something about Lisp and Emacs Lisp. I feel comfortable using Emacs, but I want to be able to write my own functions. Let’s set up some sort of configuration that let me develop in this language.

ParEdit is a minor mode for performing structured editing of S-expression data. Will keep your parentheses balanced. You will never mess around again deleting matching parenthesis by mistake. Also add the evil flavor to workaround evil modifier commands.

(use-package paredit
  :ensure t
  :hook ((emacs-lisp-mode . paredit-mode)
         (lisp-mode . paredit-mode)))

(use-package evil-paredit
  :ensure t
  :hook ((emacs-lisp-mode . evil-paredit-mode)
         (lisp-mode . evil-paredit-mode)))

Web development

This is not my target but sometimes I have to deal with some web development. I found this web-mode package that makes easier the web development with emacs. This mode will be major mode activated for HTML and Javascript files.

(use-package web-mode
  :ensure t
  :hook (html-mode . web-mode))

Javascript, Typescript and React

This package is useful in order to check the syntax and help you while you write Javascript code. In Emacs 27 j2-mode supports React .jsx so is activated as a minor mode when web-mode or js-mode are activated.

(use-package js2-mode
  :ensure t
  :hook ((web-mode js-mode) . js2-minor-mode)
  :config (setq js-indent-level 2))
(use-package typescript-mode
  :ensure t
  :config

  (add-to-list 'auto-mode-alist '("\\.tsx?\\'" . typescript-mode)))

Tide stands for TypeScript Interactive Development Environment for Emacs. Provides completion, linting and formatting for JavaScript, TypeScript and JSX. Needs the tide server as a dependency and a jsconfig.json file per project. Check the tide repository for more info.

(use-package tide
  :ensure t
  :after (js2-mode company flycheck)
  :hook ((js2-minor-mode . tide-setup)
         (js2-minor-mode . tide-hl-identifier-mode))

  :config
  (flycheck-add-next-checker 'javascript-eslint 'javascript-tide 'append))

Docker files

Spotify created a mayor mode that provides syntax highlighting as well as the ability to build the image directly from the buffer with C-c C-b.

Also you can specify the image name in the file itself as in org-mode File-Local Variables.

## -*- docker-image-name: "your-image-name-here" -*-
(use-package docker
  :ensure t
  :init (setq helm-command-prefix-key "C-x M-h")
  :bind ("C-x c" . docker))

(use-package dockerfile-mode
  :ensure t
  :config

  (add-to-list 'auto-mode-alist '("Dockerfile\\'" . dockerfile-mode)))

(use-package docker-tramp
  :ensure t)

Also docker-compose-mode provides syntax highlighting and completions for docker-compose files using company as backend.

(use-package docker-compose-mode
  :ensure t
  :hook (docker-compose-mode . company-mode))

LaTeX

This configuration tries to mimic a WYSIWYG editor in Emacs.

AUCTeX

Provides features in order to edit, compile and view TeX files in Emacs. You will need to install it from the repositories of your distribution.

In order to get support for many other LaTeX packages you have to enable document parsing. If you also use \include you also should make AUCTeX aware of the multi-file document structure. Each time you open a new file AUCTeX will ask you for a master file.

(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq-default TeX-master nil)
(setq LaTeX-electric-left-right-brace t)
(setq TeX-source-correlate-mode t)
(setq TeX-view-program-selection '(((output-dvi has-no-display-manager) "dvi2tty")
                                   ((output-dvi style-pstricks) "dvips and gv")
                                   (output-dvi "xdvi")
                                   (output-pdf "PDF Tools")
                                   (output-html "xdg-open")))

Formating functions

Basic keybindings in order to format text.

(add-hook  'LaTeX-mode-hook
           (lambda ()
             (local-set-key (kbd "C-c f") 'TeX-font)))

Auto revert for pdf-tools

Autorevert poll the file system every auto-revert-interval seconds. Furthermore is possible to send an event which will revert the PDF buffer after the TeX compilation has finished.

(add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer)

Enable flyspell in TeX files

(add-hook 'LaTeX-mode-hook 'flyspell-mode)
(add-hook 'LaTeX-mode-hook 'flyspell-buffer)

Enable auto-fill for TeX edition

(add-hook 'LaTeX-mode-hook 'auto-fill-mode)

Adding company support for TeX

Add the backend enable auto-completion for LaTeX files.

(use-package company-auctex
  :ensure t
  :hook (LaTeX-mode . company-mode)
  :config

  (company-auctex-init))

hideshow

This minor mode provides selectively folding for code and comment blocks. Blocks are defined per mayor mode. It cames pre-configured with default mayor modes like c-mode, c++mode..

You can configure this minor mode and enable it in different mayor modes with this config. This issue explains how to configure for nxml-mode.

(use-package hideshow
  :ensure t
  :bind ("C-c h" . hs-toggle-hiding)
  :config
  (add-to-list 'hs-special-modes-alist
             '(nxml-mode
               "<!--\\|<[^/>]*[^/]>"
               "-->\\|</[^/>]*[^/]>"

               "<!--"
               nxml-forward-element
               nil))
)

(add-hook 'nxml-mode-hook 'hs-minor-mode)
(add-hook 'python-mode-hook 'hs-minor-mode)

WIP

These source blocks needs to be moved to its corresponding sections.

(use-package org-autolist
  :ensure t
  :config (add-hook 'org-mode-hook (lambda () (org-autolist-mode))))

(use-package org-bullets
  :ensure t)
  ;:config
  ;(progn
  ;  (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
  ;  (setq org-bullets-bullet-list
  ;        '("\u25c9" "\u25ce" "\u25cb" "\u25cb" "\u25cb" "\u25cb"))))

Org-mode

Enable auto-fill-mode

This conf enables 80 characters auto filling per line inside org-mode. I believe that 80 character per line enhances the readability of a text file.

If you want a visual behaviour inside emacs instead into the raw text file check visual-fill-column.

(add-hook 'org-mode-hook 'auto-fill-mode)
(setq-default fill-column 79)

Set the directory

Set the path of the org directory

(setq org-directory "~/Drive/org/")

Setting up the agenda

I’m triying to use the org agenda in order to organize all my workflow tasks. So in this section there are some agenda useful configurations.

First, I’m defining where are my agenda files. I like to have it synced with Google Drive, in order to have always ready a back up. Also org can handle multiple agenda files, so you can add more files or folder to the list.

(setq org-agenda-files (list "~/Drive/org/agenda.org"))

As I said, I’m planning keep track of my tasks on the agenda. Thus I need to add some workflow states to the default TODO | DONE defined on Emacs

(setq org-todo-keywords
      '((sequence "TODO(t)" "IN-PROGRESS(p)" "WAITING(w)" "|" "DONE(d)" "CANCELED(c)")))

Also setting this keybinding allows me take quick looks to the agenda by week.

(global-set-key (kbd "C-c t a") 'org-agenda-list)

In order to add items to the agenda from anywhere in Emacs, we need to use org-capture. When you call it, a split will prompt asking you to select a template to use in order to add the task. By default, there are not templates, so lets define one along with a keybinging to call it.

(setq org-capture-templates
      '(("a" "My TODO task format." entry
         (file "agenda.org")
         "* TODO %?
SCHEDULED: %t")))

(defun my-org-task-capture ()
  "Capture a task with my default template."
  (interactive)
  (org-capture nil "a"))

(global-set-key (kbd "C-c c c") 'my-org-task-capture)

Also, I want an easy way to add tasks from the agenda view. So lets bound the c key to the default capture command. In addition, pressing C-u c will open the default org-capture dialog prompting the different capture types.

The key binding is set in Agenda key bindings section.

(defun my-org-agenda-capture (&optional vanilla)
  "Capture a task in agenda mode, using the date at point.

If VANILLA is non-nil, run the standard `org-capture'."
  (interactive "P")
  (if vanilla
      (org-capture)
    (let ((org-overriding-default-time (org-get-cursor-date)))
      (org-capture nil "a"))))

Finally, I want to see my daily agenda as I defined in my custom view in the section Agenda custom commands. So, as I take quick looks to the daily agenda the S-SPC binding fits perfect.

(defun my-pop-to-org-agenda (&optional split)
  "Visit the org agenda, in the current window or a SPLIT."
  (interactive "P")
  (org-agenda nil "d")
  (when (not split)
    (delete-other-windows)))

(global-set-key (kbd "S-SPC") 'my-pop-to-org-agenda)

Below these lines, there are some tweaks that I’ve found for the agenda.

Performing a text search (”s” selection from org-agenda) include all the text from the file list in org agenda.

(setq org-agenda-text-search-extra-files '(agenda-archives))

This option force you to mark all child tasks as DONE before you can mark the parent as DONE.

(setq org-enforce-todo-dependencies t)

This one insert a timestamp on the task when it was marked as done. Very useful in order to maintain a log of when the tasks are done. Also the same idea, but for logging how many the times a deadline or an scheduled date was changed.

(setq org-log-done (quote time))
(setq org-log-redeadline (quote time))
(setq org-log-reschedule (quote time))

Agenda key bindings

In this section are all the key bindings related to the agenda mode. They need to be evaluated after the org-agenda-mode was loaded, otherwise Emacs would fail to evaluate them.

  • Rebind the k and j keys to move up and down as in evil-mode.
(eval-after-load 'org-agenda
  '(progn
     (define-key org-agenda-mode-map "j" 'org-agenda-next-item)
     (define-key org-agenda-mode-map "k" 'org-agenda-previous-item)
     (define-key org-agenda-mode-map "c" 'my-org-agenda-capture)))

Agenda custom commands

This custom commands are intended to define my custom view of the agenda. All the ideas are inspired on this Aaron Bieber blog entry.

The defined agenda view shows the tasks for today, along with the high priority and all that aren’t scheduled for any date.

(defun my-org-skip-subtree-if-priority (priority)
  "Skip an agenda subtree if it has a priority of PRIORITY.

PRIORITY may be one of the characters ?A, ?B, or ?C."
  (let ((subtree-end (save-excursion (org-end-of-subtree t)))
        (pri-value (* 1000 (- org-lowest-priority priority)))
        (pri-current (org-get-priority (thing-at-point 'line t))))
    (if (= pri-value pri-current)
        subtree-end
      nil)))

(defun my-org-skip-subtree-if-habit ()
  "Skip an agenda entry if it has a STYLE property equal to \"habit\"."
  (let ((subtree-end (save-excursion (org-end-of-subtree t))))
    (if (string= (org-entry-get nil "STYLE") "habit")
        subtree-end
      nil)))

(setq org-agenda-custom-commands
      '(("d" "Daily agenda and all TODOs"
         ((tags "PRIORITY=\"A\""
                ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
                 (org-agenda-overriding-header "High-priority unfinished tasks:")))
          (agenda "" ((org-agenda-span 1)))
          (alltodo ""
                   ((org-agenda-skip-function '(or (my-org-skip-subtree-if-habit)
                                                   (my-org-skip-subtree-if-priority ?A)
                                                   (org-agenda-skip-if nil '(scheduled deadline))))
                    (org-agenda-overriding-header "ALL normal priority tasks:")))))))

evil integration with org-mode

I’m very used to Vim, that’s why I use evil-mode. But, it doesn’t have a default integration with org-mode. That’s where evil-org package helps defining some useful keybindings for a Vim key-map fan.

(use-package evil-org
  :ensure t
  :hook (org-mode . evil-org-mode))

Native TAB in source blocks

By default TAB keystroke doesn’t indent in org source blocks. Typing C-q-<TAB> I can force a native TAB but I prefer this option that makes TAB work as if the keystroke was issued in the code’s major mode.

(setq org-src-tab-acts-natively t)

org-ref

This is an org-mode module to handle citations, cross-references and bibliographies.

We require the packages and set the default for the bibliography notes, the main .bib bibliography and the directory where the PDFs can be downloaded to.

(use-package org-ref
  :ensure t
  :config

  (setq org-src-preserve-indentation t)

  (setq org-latex-default-packages-alist
    (-remove-item
     '("" "hyperref" nil)
     org-latex-default-packages-alist))

  (add-to-list 'org-latex-default-packages-alist '("" "natbib" "") t)
  (add-to-list 'org-latex-default-packages-alist
           '("linktocpage,pdfstartview=FitH,colorlinks,linkcolor=black,anchorcolor=black,citecolor=black,filecolor=blue,menucolor=black,urlcolor=blue"
         "hyperref" nil)
           t)

  (progn
    (setq org-ref-bibliography-notes "~/Drive/org/bibliography/notes.org"
          org-ref-default-bibliography '("~/Drive/org/bibliography/main.bib")
          org-ref-pdf-directory "~/Drive/org/bibliography/pdfs"
          org-latex-pdf-process
          '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
            "bibtex %b"
            "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
            "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f")))

  (setq bibtex-autokey-year-length 4
      bibtex-autokey-name-year-separator "-"
      bibtex-autokey-year-title-separator "-"
      bibtex-autokey-titleword-separator "-"
      bibtex-autokey-titlewords 2
      bibtex-autokey-titlewords-stretch 1
      bibtex-autokey-titleword-length 5))

This enable the use of native org-mode labels in org-ref links, instead the label:org-ref style.

(setq org-latex-prefer-user-labels t)

IEEE export

For class assignments and who-knows-what in the future, I was able to integrate a IEEE Conference template in org-mode export via Latex. To use it, just include the IEEEtran class in your org file. It has not been thoroughly tested, but its headers, index, abstract and general aesthetic works perfectly out of the box.

(add-to-list 'org-latex-classes
             '("IEEEtran" "\\documentclass[11pt]{IEEEtran}"
               ("\\section{%s}" . "\\section*{%s}")
               ("\\subsection{%s}" . "\\subsection*{%s}")
               ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
               ("\\paragraph{%s}" . "\\paragraph*{%s}")
               ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             t)

Beamer export

We need to manually enable the export to Beamer option

(use-package ox-beamer)

Custom ellipsis

Custom ellipsis to use in the org-mode heading outline.

(setq org-ellipsis " \u2935")

Prettify symbols

This setting will prettify latex symbols like (x_{subscript}) and superscripts (x^{superscript}). As a consequence, they will appear in org as visual symbols.

(setq-default org-pretty-entities t)

org-download

Thanks to org-download you are able to drag and drop images to Emacs org-mode. There are several sources image cames from: From browser, file system, remote address using org-download-yank or a screenshot using org-download-screenshot.

(require 'org-download)

(add-hook 'dired-mode-hook 'org-download-enable)

Use syntax highlight in source blocks

When writing source code on a block, if this variable is enabled it will use the same syntax highlight as the mode supposed to deal with it.

(setq org-src-fontify-natively t)

Source syntax highlight in latex exports

Using org-mode latex export you can get syntax highlighting in pdf using the minted package, wich uses Python pygments package. This snippet was taken from Joon’s Blog. Issue cache=false.

(require 'ox-latex)
(add-to-list 'org-latex-packages-alist '("cache=false" "minted"))
(setq org-latex-listings 'minted)

Auto cleanup latex intermediary files

I hate all this intermediary files that latex creates. Just blow up all my directories. So, I’ve found a solution in this emacs stack exchange question.

(setq org-latex-logfiles-extensions (quote ("lof" "lot" "tex~" "aux" "idx" "log" "out" "toc" "nav" "snm" "vrb" "dvi" "fdb_latexmk" "blg" "brf" "fls" "entoc" "ps" "spl" "bbl")))

Time tracking: Clocking

I’ve recently discovered this feature and is awesome. It enables time tracking for tasks inside an agenda file.

C-c C-x C-i Starts the clock on the current time C-c C-x C-o Stops the current active clock

With this option all the CLOCKS will be grouped into a :CLOCKING: entry

(setq org-clock-into-drawer t)

Disable lisp flycheck checker in org-src-mode

I receive an annoying warning all the time from flycheck when I try to edit lisp snippets. The checker treats them as a lisp package, but they are just snippets. With the next snippet you can deactivate this warnings in every snippet edited in org-mode.

(defun disable-flycheck-in-org-src-block ()
  (setq-local flycheck-disabled-checkers '(emacs-lisp-checkdoc)))

(add-hook 'org-src-mode-hook 'disable-flycheck-in-org-src-block)

Other major modes

Evil mode

I’m very used to Vim and prefer its keybindings over the Emacs ones. Evil-mode provides keybindings and emulates the main features of Vim.

This configuration enables leader key function and highlihgt persistence on searches.

(use-package evil
  :ensure t
  :init
  (setq evil-want-keybinding nil)  ;; Needed by evil-collection
  :config

  (evil-mode 1)

  ;; Evil key bindings
  (define-key evil-motion-state-map "j" 'evil-next-visual-line)
  (define-key evil-motion-state-map "k" 'evil-previous-visual-line)

  (use-package evil-leader
    :ensure t
    :config
    (global-evil-leader-mode)

    (evil-leader/set-leader "<SPC>")
    (evil-leader/set-key
      "<SPC>" 'evil-search-highlight-persist-remove-all
      "i" 'counsel-imenu))

  (use-package evil-search-highlight-persist
   :ensure t
   :config
   (global-evil-search-highlight-persist t))

    ;; Add these evil keybindings in Emacs mode
    (evil-add-hjkl-bindings occur-mode-map 'emacs
    (kbd "/")       'evil-search-forward
    (kbd "n")       'evil-search-next
    (kbd "N")       'evil-search-previous
    (kbd "C-d")     'evil-scroll-down
    (kbd "C-u")     'evil-scroll-up
    (kbd "C-w C-w") 'other-window))

This package adds a collection of Evil bindings that Evil does not cover by default.

(use-package evil-collection
  :ensure t
  :after evil
  :config
  (evil-collection-init))

Disable the evil-repeat-pop-next and other commands that I don’t use.

(eval-after-load "evil-maps"
  '(progn
     (define-key evil-normal-state-map "\M-." nil)
     (define-key evil-motion-state-map "(" nil)
     (define-key evil-motion-state-map ")" nil)))

mu4e

mu is a simple command line tool for searching through emails. It’s a cute little tool and is especially nice for allowing you to quickly check for any new email without leaving the terminal. However, you need to have an offline copy of the messages where mu can search. This is done through offlineimap. You can find how is configured in my dotfiles repository.

mu4e is the Emacs email client included with mu. It provides functionality to search over the offline copy of my emails, move them around, and send/reply to different mail servers.

For sending mail using SMTP, mu4e uses smtpmail in order to establish the connection to the SMTP server. The authentication is done using auth-source library.

As Gregory J Stein points, offlineimap won’t sync the messages sended to the trash marked with the T label, which happens whenever you delete a message with d. The workaround is the last function defined in the below snippet.

Activating org-mu4e you will be able to capture links or queries to your emails and then use it as links into your org-mode files. Very handy if you want to store emails into the agenda file.

(use-package mu4e
  :load-path "/usr/share/emacs/site-lisp/mu4e"
  :demand t
  :bind (("C-c m" . mu4e))
  :hook (mu4e-compose-mode . flyspell-mode)
  :config

  (require 'org-mu4e)
  (require 'shr)

  ;; Set mu4e as default mail user agent
  (setq mail-user-agent 'mu4e-user-agent)

  ;; Set the default Maildir folders
  (setq mu4e-maildir "~/.maildir"
        mu4e-sent-folder "/fastmail/Sent"
        mu4e-drafts-folder "/fastmail/Drafts"
        mu4e-trash-folder "/fastmail/Trash"
        mu4e-refile-folder "/fastmail/Archive"
        mu4e-completing-read-function 'ivy-completing-read
        mu4e-confirm-quit nil
        mu4e-kill-buffer-on-exit t
        smtpmail-stream-type 'ssl
        smtpmail-smtp-server "smtp.fastmail.com"
        smtpmail-smtp-service 465)

  (setq send-mail-function 'smtpmail-send-it
        message-send-mail-function 'smtpmail-send-it)

  (setq	mu4e-view-date-format "%a %e %b %Y %T"
        mu4e-headers-date-format "%d/%m/%Y"
        mu4e-headers-time-format "%T"
        mu4e-view-prefer-html t
        shr-use-colors nil
        shr-use-fonts nil
        shr-width 79)

  (setq mu4e-bookmarks
        '((:name "Unread messages"
           :query "flag:unread AND NOT flag:trashed AND NOT maildir:/fastmail/Spam AND NOT maildir:/fastmail/Trash"
           :key ?u)
          (:name "Today's messages"
           :query "date:today..now"
           :key ?t)
          (:name "Last 7 days"
           :query "date:7d..now"
           :key ?w)
          (:name "Inbox"
           :query "maildir:/fastmail/INBOX"
           :key ?i)
          (:name "Banking"
           :query "maildir:/fastmail/Banking"
           :key ?b)
          (:name "Jobs"
           :query "maildir:/fastmail/Jobs"
           :key ?j)
          (:name "Neerlandes"
           :query "maildir:/fastmail/Neerlandes"
           :key ?n)
          (:name "NLGov"
           :query "maildir:/fastmail/NLGov"
           :key ?g)
          (:name "Transport"
           :query "maildir:/fastmail/Transport"
           :key ?t))))

As I use evil-mode, lets enable vim-like keystrokes inside mu4e.

(use-package evil-mu4e
  :ensure t)

Thanks to mu4e-alert whenever you call mu4e-alert-enable-mode-line-display, your modeline will be updated to include a little envelope icon and the current count of unread messages.

(use-package mu4e-alert
  :ensure t
  :after mu4e
  :hook ((after-init . mu4e-alert-enable-mode-line-display)
         (after-init . mu4e-alert-enable-notifications))
  :config

  (mu4e-alert-set-default-style 'libnotify)
  (setq mu4e-alert-interesting-mail-query
        "flag:unread AND NOT flag:trashed AND NOT maildir:/fastmail/Spam AND NOT maildir:/fastmail/Trash")

  (setq mu4e-alert-modeline-formatter
        'mu4e-alert-custom-mode-line-formatter)

  (defun mu4e-alert-custom-mode-line-formatter (mail-count)
    "Custom formatter used to get the string to be displayed in the
mode-line.Uses Font Awesome mail icon to have a more visual icon
in the display.  MAIL-COUNT is the count of mails for which the
string is to displayed"
    (when (not (zerop mail-count))
      (concat " "
              (propertize
               ""
               ;; 'display (when (display-graphic-p)
               ;;            display-time-mail-icon)
               'face display-time-mail-face
               'help-echo (concat (if (= mail-count 1)
                                      "You have an unread email"
                                    (format "You have %s unread emails" mail-count))
                                  "\nClick here to view "
                                  (if (= mail-count 1) "it" "them"))
               'mouse-face 'mode-line-highlight
               'keymap '(mode-line keymap
                                   (mouse-1 . mu4e-alert-view-unread-mails)
                                   (mouse-2 . mu4e-alert-view-unread-mails)
                                   (mouse-3 . mu4e-alert-view-unread-mails)))
              (if (zerop mail-count)
                  " "
                (format " [%d] " mail-count))))))

Also, I define a custom function so that updating the mail is possible just by pinging the Emacs daemon. I have this function called as a post-hook every time the offlineimap is called.

(defun update-mail-in-server ()
  "Check for mail and update the mode line icon."
  (interactive)
  (mu4e-update-mail-and-index t)
  (mu4e-alert-enable-mode-line-display)
  ;; Clear echo area in 2 seconds after update
  (run-with-timer 2 nil (lambda () (message nil))))

org-mime is a package that enables HTML email writing using org-mode on Emacs side.

(use-package org-mime
  :ensure t
  :after org
  :hook (org-ctrl-c-ctrl-c . htmlize-org-mail)
  :config

  (setq-default composing-html-mail nil)

    (defun compose-org-mail ()
    "Create a new org scratch buffer to compose an HTML mail."
    (interactive)
    (let ((draft-buffer (generate-new-buffer "*org-draft*")))
      (with-current-buffer draft-buffer
        (org-mode)
        (insert "?header")
        (yas/expand))
      (display-buffer draft-buffer nil t)
      (setq composing-html-mail t)))

  (defun htmlize-org-mail ()
    "When in an org mail, htmlize it."
    (interactive)
    (when composing-html-mail
      (setq composing-html-mail nil)
      (org-mime-org-buffer-htmlize))))

markdown-mode

Since my change to Emacs I tend to set aside Markdown, thus writing my markup documents in org-mode. However, once in a while, I still have to write in this markup language. This bare minimal configuration will help to write those documents.

(use-package markdown-mode
  :ensure t
  :after flyspell
  :hook ((markdown-mode . auto-fill-mode)
         (markdown-mode . flyspell-mode)))

csv-mode

This mode allows markup and alignment of or .csv files. Due to some files are too big, this configuration comes with a function to only align the visible part of the file.

(use-package csv-mode
  :ensure t
  :config

  (setq csv-align-padding 2)

  (defun csv-align-visible ()
    "Align only visible entries in csv-mode"
    (interactive)
    (csv-align-fields nil
                      (window-start (selected-window))
                      (window-end (selected-window)))
    (message "Aligned visible fields only. Press C-c C-w to align again."))

  :bind (:map csv-mode-map ("C-c C-w" . 'csv-align-visible))
  :hook (csv-mode . csv-align-visible))

restclient-mode

This mode lets you explore and test HTTP REST webservices from plain text. Evaluate the requests with C-c C-c and display the results as a pretty-printed XML or JSON.

(use-package restclient
  :hook (restclient-mode . company-mode)
  :ensure t)

Thanks to ob-restclient is possible to provide support on org-babel and add snippets with requests in your org-mode files.

(use-package ob-restclient
  :ensure t
  :config

  (org-babel-do-load-languages
   'org-babel-load-languages '((restclient . t))))

Auto-completion for HTTP methods and headers in restclient-mode is provided by company-restclient

(use-package company-restclient
  :ensure t
  :after company
  :config (add-to-list 'company-backends 'company-restclient))

Packages & Tools

which-key

A useful package that displays the possible key combinations when you start a new key command.

(use-package which-key
  :ensure t
  :config (which-key-mode))

Add icons with all-the-icons

This package comes with a set of icons for Emacs. You have to install them with all-the-icons-install-fonts

(use-package all-the-icons
  :ensure t)

Add emojis to emacs

emojify will display emojis as images, so your emacs should be compiled with support for PNG images in order to display it properly. But if you have installed an emoji font is also a good idea to turn on the unicode display of emojis.

(use-package emojify
  :ensure t
  :hook (after-init . global-emojify-mode)
  :config

  (setq emojify-emoji-styles '(unicode github)))

dired

This is the default Emacs system directory. It’s super useful, specially when I’m in some OS where I don’t feel very confortable :P Dired allows you navigation through the filesystem using a text buffer. That’s very useful because if you press C-x C-q in the dired buffer it turns into a writeable buffer so you can edit files or directories as a regular textfile. Setting to true dired-dwin-target enables the dired Do What I Mean behaviour. With that, if you try to rename a file with a second buffer open, it will asume that you want to move it there. Same with copy and other operations.

In this video you can see a reference of what you can do with dired mode.

(use-package dired
  :hook (dired-mode . dired-hide-details-mode)
  :config
  (setq dired-dwim-target t))

(use-package all-the-icons-dired
    :ensure t
    :hook (dired-mode . all-the-icons-dired-mode))

(use-package dired-sidebar
  :ensure t
  :bind (("C-c s" . dired-sidebar-toggle-sidebar)))

In order to tell dired to sort the folders first, you have to write your own sorting function.

(defun mydired-sort ()
  "Sort dired listings with directories first."
  (save-excursion
    (let (buffer-read-only)
      (forward-line 2) ;; beyond dir. header
      (sort-regexp-fields t "^.*$" "[ ]*." (point) (point-max)))
    (set-buffer-modified-p nil)))

(defadvice dired-readin
  (after dired-after-updating-hook first () activate)
  "Sort dired listings with directories first before adding marks."
  (mydired-sort))

Move buffers around

There’s no fast way to swap buffers location in Emacs by default. To do it, a good option is to use buffer-move package and use these key bindings.

(use-package buffer-move
  :ensure t
  :bind (("C-x w <up>"    . buf-move-up)
         ("C-x w <down>"  . buf-move-down)
         ("C-x w <left>"  . buf-move-left)
         ("C-x w <right>" . buf-move-right)
         ("C-x w k"       . buf-move-up)
         ("C-x w j"       . buf-move-down)
         ("C-x w h"       . buf-move-left)
         ("C-x w l"       . buf-move-right)))

Relative margin line numbers

This setting enables the margin line numbers with the relative number mode.

(use-package nlinum-relative
  :ensure t
  :hook (prog-mode . nlinum-relative-mode)
  :config

  (nlinum-relative-setup-evil)
  (setq nlinum-relative-redisplay-delay 0))

Zsh like completion

zlc provides Zsh like completion for the default minibuffer.

;; Zsh Tab completion for minibuffer
(use-package zlc
  :ensure t
  :config
  (zlc-mode t))

Environment variables

Emacs doesn’t look to my user environment variables. Therefore, I can’t get python completion working with my own modules because it doesn’t look for my $PYTHONPATH. exec-path-from-shell is an Emacs library to ensure variables inside Emacs look the same as in the user’s shell. By default it sets the user $MANPATH and $PATH. Also you can copy other environment variables by customizing exec-path-from-shell-variables or by calling exec-path-from-shell-copy-env.

(use-package exec-path-from-shell
  :ensure t
  :config

  (add-to-list 'exec-path-from-shell-variables '"PYTHONPATH")
  (add-to-list 'exec-path-from-shell-variables '"GTAGSLIBPATH")
  (exec-path-from-shell-initialize))

Spell checking

Emacs comes with ispell a very useful spell checker if you use emacs to write notes or documents as I do. ispell needs a completion tool to review the text. I’ve installed hunspell in my Arch Linux laptop.

I set spanish as default language for spell checking because is my native language. But, I can use M-x ispell-change-dictionary if I want to change the spell checking language.

The last two lines prevents ispell to check inside org source blocks and sections.

(use-package flyspell
  :ensure t
  :hook (org-mode .(lambda() (setq ispell-parser 'tex)))
  :config

  (when (executable-find "aspell")
    (setq ispell-program-name "aspell"
          ispell-dictionary "american"))

  (set-face-underline 'flyspell-incorrect
                      '(:color "#dc322f" :style line))
  (set-face-underline 'flyspell-duplicate
                      '(:color "#e5aa00" :style line))

  (add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:"))
  (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC")))

Enable the spell checking in buffers with the following major modes.

(add-hook 'org-mode-hook 'flyspell-mode)

ivy

ivy is a minimalistic completion engine. It supports fuzzy matching. But I don’t like this behaviour on swiper search engine. So, I deactivated setting the default regexp builder with (swiper . ivy--regex-plus).

(use-package ivy
  :ensure t
  :demand t
  :config

  (ivy-mode)
  (setq ivy-use-virtual-buffers t
        ivy-count-format "%d/%d ")

  (setq ivy-wrap t)

  ; Fuzzy mode
  (setq ivy-re-builders-alist
        '((swiper . ivy--regex-plus) ; No Fuzzy matchin for swiper
          (t      . ivy--regex-fuzzy)))

  (setq ivy-initial-inputs-alist nil)

  :bind (("C-s" . swiper)
         :map ivy-minibuffer-map
         ("RET" . ivy-alt-done)
         ("C-j" . ivy-next-line)
         ("C-k" . ivy-previous-line)))

Also, this alternative package complement ivy

(use-package ivy-rich
  :ensure t
  :demand t
  :config (ivy-rich-mode))

counsel is a collection of Ivy-enhanced versions of common Emacs commands. So, enhances the emacs user experience ;)

(use-package counsel
  :ensure t
  :after ivy
  :demand t
  :config

  (counsel-mode)
  (setcdr (assoc 'counsel-M-x ivy-initial-inputs-alist) "")

  ;; Remove all the initial input in all commands
  ;;(setq ivy-initial-inputs-alist nil)
  )

swiper is an Ivy-enhanced alternative to isearch

(use-package swiper
  :ensure t
  :demand t)

projectile

Enables different tools and functions to deal with files related to a project. It works out of the box, since it will detect your VCS files automatically and set it as the root of the project. If it doesn’t, you can just create an empty .projectile file in the root of your project.

I have it configured to ignore all files that has not been staged in the project.

(use-package projectile
  :ensure t
  :config

  (projectile-global-mode t)
  (setq projectile-use-git-grep t)
  (setq projectile-indexing-method 'hybrid) ; alien method is faster but only
                                        ; work with .gitinore and not
                                        ; .projectile file

  (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map))

Also, the counsel-projectile extension adds integration with ivy.

(use-package counsel-projectile
  :ensure t
  :config (counsel-projectile-mode t))

flycheck

Flycheck brings on-the-fly syntax checking for different languages. It comes already with support for a lot of languages and can also use other packages as backend.

(use-package flycheck
  :ensure t
  :hook (prog-mode . flycheck-mode)
  :config

  (setq flycheck-python-mypy-ini "~/.config/mypy/config")

  (set-face-underline 'flycheck-error '(:color "Red1" :style line))
  (set-face-underline 'flycheck-warning '(:color "#e5aa00" :style line))
  (set-face-underline 'flycheck-info '(:color "#268bd2" :style line)))

smartparens

Auto-close parenthesis and other characters. Very useful in prog-mode.

(use-package smartparens
  :ensure t
  :config

  (add-hook 'prog-mode-hook #'smartparens-mode)
  (sp-pair "{" nil :post-handlers '(("||\n[i]" "RET"))))

Smooth scrolling

This package keeps the cursor away from the top and bottom of the current buffer’s window in order to keep lines of context around the point visible as much as possible.

; Smooth scrolling on file limits
(use-package smooth-scrolling
  :ensure t
  :config
  (smooth-scrolling-mode 1))

Clipboard integration

simple-clip enables clipboard system integration from emacs.

; SimpleClip Super+C Super+X Super+V
(use-package simpleclip
  :ensure t
  :config
  (simpleclip-mode 1))

PDF Tools

(use-package pdf-tools
  :ensure t
  :config

  (pdf-tools-install))

There’s a conflict between evil-mode and pdf-view-mode. evil cause that pdf display keeps blinking. xuhdev gives a solution to deal with this conflict.

(evil-set-initial-state 'pdf-view-mode 'emacs)
(add-hook 'pdf-view-mode-hook
  (lambda ()
    (set (make-local-variable 'evil-emacs-state-cursor) (list nil))))

Magit

Magit is an interface to VCS Git implemented as an emacs package.

(use-package magit
  :ensure t
  :hook (git-commit-mode . (lambda () (setq-local fill-column 72)))
  :bind (("C-x g" . magit-status))
  :config

  (setq magit-section-initial-visibility-alist '((unpushed . show)))
  (git-commit-turn-on-auto-fill)

  (when (running-i3)
    (setq-default magit-bury-buffer-function 'quit-window-dwim
                  magit-commit-show-diff nil)))

(use-package evil-magit
  :ensure t)

(use-package magit-lfs
  :ensure t)

(use-package magit-todos
  :ensure t
  :config

  (magit-todos-mode))

gitlab-ci-mode

This major mode provides syntax highlighting and completion for keywords and special variables in .gitlab-ci.yml files.

(use-package gitlab-ci-mode
  :ensure t
  :hook ((gitlab-ci-mode . flycheck)
         (gitlab-ci-mode . company-mode)))

Furthermore if you want the Flycheck integration with the linter included in gitlab-ci-mode you should install the next package.

(use-package gitlab-ci-mode-flycheck
  :ensure t
  :after flycheck gitlab-ci-mode
  :init
  (gitlab-ci-mode-flycheck-enable))

ivy-bibtex

I was using helm with org-ref in order to manage my bibliography. But this package allow you to search and manage your BibTeX bibliography using the minimalism of ivy.

In order to store the pdfs BibTeX assumes that the name of a pdf consist of the reference key plus suffix .pdf.

(use-package ivy-bibtex
  :ensure t
  :config

  ;; ivy-bibtex requires ivy's `ivy--regex-ignore-order` regex builder, which
  ;; ignores the order of regexp tokens when searching for matching candidates.
  (add-to-list 'ivy-re-builders-alist '(ivy-bibtex . ivy--regex-ignore-order))

  (setq ivy-bibtex-default-action 'ivy-bibtex-insert-citation)

  ;; Library configuration
  (setq bibtex-completion-library-path '("~/Drive/org/bibliography/pdfs/"))
  (setq bibtex-completion-bibliography '("~/Drive/org/bibliography/main.bib"))
  (setq bibtex-completion-notes-path "~/Drive/org/bibliography/notes/")

  (global-set-key (kbd "C-c b") 'ivy-bibtex))

By default emacs is used to open the pdf files using DocView or PDF Tools. With the next snippet you will be able to open the documents as default with p and with an external tool bounded to P.

(defun bibtex-completion-open-pdf-external (keys &optional fallback-action)
  (let ((bibtex-completion-pdf-open-function
         (lambda (fpath) (start-process "evince" "*helm-bibtex-evince*" "/usr/bin/evince" fpath))))
    (bibtex-completion-open-pdf keys fallback-action)))

(ivy-bibtex-ivify-action bibtex-completion-open-pdf-external ivy-bibtex-open-pdf-external)


(ivy-add-actions
 'ivy-bibtex
 '(("P" ivy-bibtex-open-pdf-external "Open PDF file in Evince viewer (if present)")))

View Large Files

VLF minor mode allows viewing, editing, searching and comparing large files in emacs. It divides the file on several batches and takes care of all the operations for you allowing to edite smoothly the contents of the file.

(use-package vlf
  :ensure t)

yasnippets

This package is a template system for Emacs. It allows to type and abbreviation and automatically expand it into function templates using TAB. All the snippets I use are located into the /snippets folder of this repository.

(use-package yasnippet
  :ensure t
  :config

  (add-to-list 'yas-snippet-dirs (concat conf-dir "snippets"))
  (yas-global-mode 1)
  (advice-add 'yas--auto-fill-wrapper :override #'ignore))

rainbow-delimiters

This package turns parenthesis into color pairs, which enhances your visual parenthesis matching skills.

(use-package rainbow-delimiters
  :ensure t
  :hook (prog-mode . rainbow-delimiters-mode))

emacs-libvterm

I tried different packages in order to use a virtual terminal inside emacs, but none of them convinced me so that’s why once again I’m trying a new one. emacs-libvterm provides a bridge to libvterm to display a terminal inside an emacs buffer.

I’m very used to vim keybindings but I never got used to have it on the terminal. Deactivate it with the next command.

(use-package vterm
  :ensure t
  :bind (("C-c v" . vterm)
         ("C-c 4 v" . vterm-other-window))
  :config

  (evil-set-initial-state 'vterm-mode 'emacs))

SQL mode

Emacs come with a built-in sql-mode that interacts with different databases. Configuration is pretty straightforward. This link describes how to configure it.

(setq sql-postgres-login-params
      '((user :default "postgres")
        (database :default "postgres")
        (server :default "localhost")
        (port :default 5432)))

(add-hook 'sql-interactive-mode-hook
          (lambda ()
            (toggle-truncate-lines t)))

(evil-set-initial-state 'sql-interactive-mode 'emacs)

Literate Calc Mode

Display inline calc results as overlays in markup modes as org-mode. It is possible to activate a minor mode literate-calc-minor-mode and use the overlays.

(use-package literate-calc-mode
  :hook (org-mode . literate-calc-minor-mode)
  :ensure t)

Acknowledgments

  • Thanks to Diego Vicente. He discovered me Emacs and org-mode. Also, many aspects of my Emacs file are inspired by his config file.