Emacs configuration file

Table des matières

This is my emacs configuration file. It is under version control and available, among other configurations, at this repository: https://github.com/seblemaguer/dotfiles

This configuration relies mainly on melpa and repository named "local-melpa". This local-melpa repository is corresponding to the branch "personal" of my fork of melpa (see here: https://github.com/seblemaguer/melpa/tree/personal )

1 Prerequisite

This part focusing on some baseline prerequisites before the main configuration part

1.1 Daemon mode

First start a server as it is going to be the 99% of my use of emacs.


1.2 Packages

This section is configuring the bootstrap packages (enhancing use-package and support quelpa)

1.2.1 Global

This section focuses on the package management configuration.

We want to be able to have 4 things:

  • Adapt the system package manager (for archlinux tool trizen) + enable use-package-ensure-system-package
(use-package system-packages
    :ensure t
    (setq system-packages-supported-package-managers
            (trizen .
                    ((default-sudo . nil)
                     (install . "trizen -S")
                     (search . "trizen -Ss")
                     (uninstall . "trizen -Rns")
                     (update . "trizen -Syu")
                     (clean-cache . "trizen -Sc")
                     (log . "cat /var/log/trizen.log")
                     (get-info . "trizen -Qi")
                     (get-info-remote . "trizen -Si")
                     (list-files-provided-by . "trizen -Ql")
                     (verify-all-packages . "trizen -Qkk")
                     (verify-all-dependencies . "trizen -Dk")
                     (remove-orphaned . "trizen -Rns $(trizen -Qtdq)")
                     (list-installed-packages . "trizen -Qe")
                     (list-installed-packages-all . "trizen -Q")
                     (list-dependencies-of . "trizen -Qi")
                     (noconfirm . "--noconfirm")))

          system-packages-use-sudo nil
          system-packages-package-manager 'trizen)

(use-package use-package-ensure-system-package
  :ensure t)
  • Use an enhanced package list visualizer (paradox)
(use-package paradox
  :ensure t
  :defer t
  (setq paradox-spinner-type 'progress-bar
        paradox-execute-asynchronously t))
  • Dealing with key-chord support
(use-package use-package-chords
  :ensure t
  :config (key-chord-mode 1))
(defun package-upgrade-all ()
  "Upgrade all packages automatically without showing *Packages* buffer."
  (let (upgrades)
    (cl-flet ((get-version (name where)
                (let ((pkg (cadr (assq name where))))
                  (when pkg
                    (package-desc-version pkg)))))
      (dolist (package (mapcar #'car package-alist))
        (let ((in-archive (get-version package package-archive-contents)))
          (when (and in-archive
                     (version-list-< (get-version package package-alist)
            (push (cadr (assq package package-archive-contents))
    (if upgrades
        (when (yes-or-no-p
               (message "Upgrade %d package%s (%s)? "
                        (length upgrades)
                        (if (= (length upgrades) 1) "" "s")
                        (mapconcat #'package-desc-full-name upgrades ", ")))
            (dolist (package-desc upgrades)
              (let ((old-package (cadr (assq (package-desc-name package-desc)
                (package-install package-desc)
                (package-delete  old-package)))))
      (message "All packages are up to date"))))

1.2.2 Quelpa

Quelpa is super useful for developer package management. Adding the adaptation for the use-package makes it configuration file proof.

(use-package quelpa-use-package
    :ensure t
    (setq quelpa-update-melpa-p nil))

2 Global

This section is about configuring global emacs helpers which are not specific to a dedicated language (or filetype) but are useful for any edition use-case in emacs.

2.1 Undo

In order to have a better and more visual control of undoing, I use undo-tree.

(use-package undo-tree
  :ensure quelpa
  :quelpa (undo-tree :fetcher git :url "http://www.dr-qubit.org/git/undo-tree.git")
  :defer t

  (setq undo-tree-visualizer-timestamps nil
        undo-tree-visualizer-diff t)


2.2 Minor-mode activation

I use some minor modes based on some filetypes. This package is an helper which facilitates these activations.

(use-package auto-minor-mode
  :ensure t
  :defer t)

2.3 Helpers

I define here some global helpers used either in the rest of the file, either available to use at runtime

2.3.1 Authentification

Easy use wrapper around auth-* authentification emacs utils

(defun* my:auth-source-get-passwd (&rest spec &allow-other-keys)
  (let ((founds (apply 'auth-source-search spec)))
    (when founds
      (funcall (plist-get (nth 0 founds) :secret)))))

(defun* my:auth-source-get-user (&rest spec &allow-other-keys)
  (let ((founds (apply 'auth-source-search spec)))
    (when founds
      (plist-get (nth 0 founds) :user))))

2.3.2 Editing as root

Defining a simple helper to edit file as root using tramp

(defun edit-current-file-as-root ()
  "Edit the file that is associated with the current buffer as root"
  (if (buffer-file-name)
        (setq file (concat "/sudo:localhost:" (buffer-file-name)))
        (find-file file))
    (message "Current buffer does not have an associated file.")))

2.4 TODO Accent problem

(load-library "iso-transl")

2.5 TODO Message buffer

The main idea here is to add a timestamp to the messages as it helps to understand the sequence of problems. For now the advice is not activated as it causes some problems.

(defvar debug-messages nil)

(defun current-time-microseconds ()
  (let* ((nowtime (current-time))
         (now-ms (nth 2 nowtime)))
    (concat (format-time-string "[%Y-%m-%d %T" nowtime) (format ".%d] " now-ms))))

(defadvice message (before who-said-that activate)
  "Find out who said that thing. and say so."
  (let ((trace nil) (n 1) (frame nil))
    (when debug-messages
          (while (setq frame (backtrace-frame n))
            (setq n     (1+ n)
                  trace (cons (cadr frame) trace)) )

          (ad-set-arg 0 (concat (format-time-string "[%Y-%m-%d %T %Z] ") "<<%S>>:\n" (ad-get-arg 0)))
          (ad-set-args 1 (cons trace (ad-get-args 1)))))))

2.6 Encoding

Define the global encoding as utf-8 english US related. Of course, it is possible de locally change this information per buffer.

(setq system-time-locale "en_US.utf8")
(prefer-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)

2.7 Folding

In order to have a unify folding support, I use origami in couple with hydra. The advantage of hydra is to see all the alternatives more easily. Also inspire from https://github.com/Schnouki/dotfiles/blob/master/emacs/init-20-dev.el

(use-package origami
  :ensure quelpa
  :quelpa (origami :repo "seblemaguer/origami.el" :fetcher github)
  (origami-show-fold-header t)

  (origami-fold-replacement-face ((t (:inherit magit-diff-context-highlight))))
  (origami-fold-fringe-face ((t (:inherit magit-diff-context-highlight))))

  (defhydra origami-hydra (:color blue :hint none)
      _:_: recursively toggle node       _a_: toggle all nodes    _t_: toggle node
      _o_: show only current node        _u_: undo                _r_: redo
      _R_: reset
    (":" origami-recursively-toggle-node)
    ("a" origami-toggle-all-nodes)
    ("t" origami-toggle-node)
    ("o" origami-show-only-node)
    ("u" origami-undo)
    ("r" origami-redo)
    ("R" origami-reset))

  :bind (:map origami-mode-map
              ("C-:" . origami-hydra/body))
  (face-spec-reset-face 'origami-fold-header-face))

2.8 Edition

This section is dedicated to hacks and helpers to facilitate global edition.

2.8.1 Edit simultanously multiple region

Sometimes it can be useful to edit multiple region at once. To do that, I use iedit.

(use-package iedit
  :ensure t
  (delete-selection-mode t))

2.8.2 Alignment

I defined this helper to as I like to align equations based on the equal sign.

(defun align-to-equals (begin end)
  "Align region to equal signs"
   (interactive "r")
   (align-regexp begin end "\\(\\s-*\\)=" 1 1 ))

2.9 Recent file

Opening recent files is always an easy and fast shortcut. Some files should be ignored though. That leads to this configuration

(use-package recentf
  (recentf-mode 1)


  ;; Increase limit
  (setq recentf-max-menu-items 100)

  ;; Emacs
  (add-to-list 'recentf-exclude (format "%s/.orhc-bibtex-cache" (getenv "HOME")))
  (add-to-list 'recentf-exclude (format "%s/configuration/emacs\\.d/\\(?!\\(main.*\\)\\)" (getenv "HOME")))
  (add-to-list 'recentf-exclude (format "%s/\\.emacs\\.d/.*" (getenv "HOME")))

  ;; Some caches
  (add-to-list 'recentf-exclude (format "%s/\\.ido\\.last" (getenv "HOME")))
  (add-to-list 'recentf-exclude (format "%s/\\.recentf" (getenv "HOME")))

  ;; elfeed
  (add-to-list 'recentf-exclude (format "%s/\\.elfeed/.*" (getenv "HOME")))
  (add-to-list 'recentf-exclude (format "%s/Dropbox/emacs/elfeed/.*" (getenv "HOME")))

  ;; Org-mode organisation
  (add-to-list 'recentf-exclude (format "%s/Dropbox/org/organisation/.*" (getenv "HOME")))

  ;; Org/todo/calendars
  (add-to-list 'recentf-exclude ".*todo.org")
  (add-to-list 'recentf-exclude (format "%s/Calendars/.*" (getenv "HOME")))

  ;; Maildir
  (add-to-list 'recentf-exclude (format "%s/maildir.*" (getenv "HOME"))))

2.10 Backup files

This section is dedicated to deal with backups. The main logic is to exlude some specific files (either because of they are sensitive, either because they are just results of a process). For the other ones, I want to have an easy way to navigate in it.

2.10.1 Global backup configuration

This the global backup configuration. For that I adapted a little bit the wonderful snapshot-timemachine package.

(use-package snapshot-timemachine
  :ensure t

  ;; Default Backup directory
  (defvar backup-directory "~/.emacs.d/backups/")
  (setq backup-directory-alist `((".*" . ,backup-directory)))

  (when (not (file-exists-p backup-directory))
    (make-directory backup-directory t))

  ;; Auto-save
  (defvar auto-save-directory "~/.emacs.d/auto-save/")
  (setq auto-save-file-name-transforms `((".*" ,auto-save-directory t)))

  (when (not (file-exists-p auto-save-directory))
    (make-directory auto-save-directory t))

  ;; Tramp backup
  (defvar tramp-backup-directory "~/.emacs.d/tramp-backups/")
  (setq tramp-backup-directory-alist `((".*" . ,tramp-backup-directory)))

  (when (not (file-exists-p tramp-backup-directory))
    (make-directory tramp-backup-directory t))

  (setq make-backup-files t               ; backup of a file the first time it is saved.
        backup-by-copying t               ; don't clobber symlinks
        version-control t                 ; version numbers for backup files
        delete-old-versions t             ; delete excess backup files silently
        delete-by-moving-to-trash t
        kept-old-versions 6               ; oldest versions to keep when a new numbered backup is made (default: 2)
        kept-new-versions 9               ; newest versions to keep when a new numbered backup is made (default: 2)
        auto-save-default t               ; auto-save every buffer that visits a file
        auto-save-timeout 20              ; number of seconds idle time before auto-save (default: 30)
        auto-save-interval 200            ; number of keystrokes between auto-saves (default: 300)


  (defun snapshot-timemachine-backup-finder (file)
    "Find snapshots of FILE in rsnapshot backups."
    (let* ((file (expand-file-name file))
           (file-adapted (replace-regexp-in-string "/" "!" file))
           (backup-files(directory-files backup-directory t (format "%s.*" file-adapted))))
      (seq-map-indexed (lambda (backup-file index)
                         (make-snapshot :id index
                                        :name (format "%d" index)
                                        :file backup-file
                                        :date (nth 5 (file-attributes backup-file))))

  (setq snapshot-timemachine-snapshot-finder #'snapshot-timemachine-backup-finder))

2.10.2 Sensitive mode

There are some files which are not desired to be backed up. This part goal is to setup this "avoiding saving" spécificities.

(define-minor-mode sensitive-mode
  "For sensitive files like password lists.
It disables backup creation and auto saving.

With no argument, this command toggles the mode.
Non-null prefix argument turns on the mode.
Null prefix argument turns off the mode."
  ;; The initial value.
  ;; The indicator for the mode line.
  " Sensitive"
  ;; The minor mode bindings.
  (if (symbol-value sensitive-mode)
        ;; disable backups
        (set (make-local-variable 'backup-inhibited) t)
        ;; disable auto-save
        (if auto-save-default
            (auto-save-mode -1)))
                                        ;resort to default value of backup-inhibited
    (kill-local-variable 'backup-inhibited)
                                        ;resort to default auto save setting
    (if auto-save-default
        (auto-save-mode 1))))

(add-to-list 'auto-minor-mode-alist '("\\.git/.*\\'" . sensitive-mode))
(add-to-list 'auto-minor-mode-alist '("emacs\\.d/.*\\'" . sensitive-mode))
(add-to-list 'auto-minor-mode-alist '("emacs\\.d/emms/.*\\'" . sensitive-mode))
(add-to-list 'auto-minor-mode-alist '("Calendars/.*.org\\'" . sensitive-mode))
(add-to-list 'auto-minor-mode-alist '("\\.gpg\\'" . sensitive-mode))

2.11 Copy/Pasted

Baseline configuration for copy/pasting

(setq mouse-drag-copy-region nil
      x-select-enable-primary nil
      x-select-enable-clipboard t
      select-active-regions t)

2.12 Spell

Configuration of the (fly) spelling for emacs. For spelling, I am using aspell.

(use-package flyspell
  :ensure t

  ;; Set programms
  (setq-default ispell-program-name "aspell")
  (setq-default ispell-list-command "--list")

  ;; Refresh flyspell after directory change
  (defun flyspell-buffer-after-pdict-save (&rest _)
  (advice-add 'ispell-pdict-save :after #'flyspell-buffer-after-pdict-save)

  ;; Popup
  (defun flyspell-emacs-popup-textual (event poss word)
    "A textual flyspell popup menu."
    (require 'popup)
    (let* ((corrects (if flyspell-sort-corrections
                         (sort (car (cdr (cdr poss))) 'string<)
                       (car (cdr (cdr poss)))))
           (cor-menu (if (consp corrects)
                         (mapcar (lambda (correct)
                                   (list correct correct))
           (affix (car (cdr (cdr (cdr poss)))))
           (base-menu  (let ((save (if (and (consp affix) show-affix-info)
                                        (list (concat "Save affix: " (car affix))
                                        '("Accept (session)" session)
                                        '("Accept (buffer)" buffer))
                                     '(("Save word" save)
                                       ("Accept (session)" session)
                                       ("Accept (buffer)" buffer)))))
                         (if (consp cor-menu)
                             (append cor-menu (cons "" save))
           (menu (mapcar
                  (lambda (arg) (if (consp arg) (car arg) arg))
      (cadr (assoc (popup-menu* menu :scroll-bar t) base-menu))))

  (defun flyspell-emacs-popup-choose (org-fun event poss word)
    (if (window-system)
        (funcall org-fun event poss word)
      (flyspell-emacs-popup-textual event poss word)))

  (eval-after-load "flyspell"
       (advice-add 'flyspell-emacs-popup :around #'flyspell-emacs-popup-choose)))

2.13 Fixme

To deal with the fixme, I relie on two part: fic-mode for the highlighting and occur for the listing.

(use-package fic-mode
  :commands fic-mode
  :ensure t
  :init (add-hook 'prog-mode-hook 'fic-mode)

  (defun fic-view-listing ()
    "Use occur to list related FIXME keywords"
    (occur "\\<\\(FIXME\\|WRITEME\\|WRITEME!\\|TODO\\|BUG\\):?"))

2.14 Minibuffer

Minibuffer configuration part. Nothing really outstanding, just the classical stuff.

(use-package minibuffer
  (setq read-file-name-completion-ignore-case t
        completion-ignore-case t
        resize-mini-windows t)
  (file-name-shadow-mode 1)

  (add-hook 'eval-expression-minibuffer-setup-hook #'eldoc-mode))

2.15 Buffers

Some buffer specificities configuration like how to deal with trailing whitespaces or the fill-column for example.

;; Open Large file
(use-package vlf
  :ensure t
  (require 'vlf-setup))

;; Delete trailing-whitespace
(add-hook 'before-save-hook 'delete-trailing-whitespace)

;; Unify the buffer name style
(eval-after-load "uniquify"
     (setq uniquify-buffer-name-style 'forward)))

;; Redefine fill-column as my screen is not 80 chars :D
(setq-default fill-column 100)

2.16 Productivity behavior

This part is dedicated to ensure productivity configuration. This involves mainly isolating, capturing and bibliography.

2.16.1 Dark room

Sometimes I just want to ignore everything except the current document. Darkroom is exactly designed for that

(use-package darkroom :ensure t)

2.16.2 ORG/Web tools

Org-web-tools is a nice package which allows to sniff a webpage and convert it into org-mode format. This is really useful to homogeneise documentation.

(use-package org-web-tools :ensure t)

2.16.3 Biblio

This part focus on bibliography/library configuration. The goal is to have a global configuration to organize read papers or "to read" papers. This is mainly based on https://codearsonist.com/reading-for-programmers

(use-package ivy-bibtex
  :ensure t
  (setq ivy-bibtex-bibliography "~/Dropbox/org/work/biblio/index.bib" ;; where your references are stored
        ivy-bibtex-library-path "~/Dropbox/org/work/biblio/lib/" ;; where your pdfs etc are stored
        ivy-bibtex-notes-path "~/Dropbox/org/work/biblio/index.org" ;; where your notes are stored
        bibtex-completion-bibliography "~/Dropbox/org/work/biblio/index.bib" ;; writing completion
        bibtex-completion-notes-path "~/Dropbox/org/work/biblio/index.org"))

(use-package org-ref
  :after org
  :ensure t
  (("uu"  . org-ref-cite-hydra/body))
  (setq org-ref-completion-library 'org-ref-ivy-cite
        org-ref-notes-directory "~/Dropbox/org/work/biblio"
        org-ref-bibliography-notes "~/Dropbox/org/work/biblio/index.org"
        org-ref-default-bibliography '("~/Dropbox/org/work/biblio/index.bib")
        org-ref-pdf-directory "~/Dropbox/org/work/biblio/lib/")

  (add-hook 'org-export-before-parsing-hook 'orcp-citeproc))

(use-package interleave
  :ensure t
  :bind ("C-x i" . interleave-mode)
  (setq interleave-split-direction 'horizontal
        interleave-split-lines 20
        interleave-disable-narrowing t))

2.16.4 Paper

As I write papers, it is useful to have some helper to start to have the inspiration.

(use-package academic-phrases :ensure t)
(use-package powerthesaurus :ensure t)

2.17 Process management

I want to have some services and processes managed directly in emacs. This services/processes are closely related to my emacs use and there have to be shutdown when emacs is stopping.

2.17.1 Services

The main use case (actually the only for now) is the imap notification system. To do so I use the couple prodigy (to start the process in emacs) and imapnotify to actually activate the push service. Internally, imapnotify is going to call emacsclient to notify the user about a new mail.

(use-package prodigy
  :ensure quelpa
  :quelpa (prodigy :fetcher github :repo "seblemaguer/prodigy.el" :branch "auto-start")

    :name "Saarland imap notify"
    :command "imapnotify"
    :args '("-c" "~/configuration/imapnotify/saarland.js")
    :tags '(work mail)
    :stop-signal 'sigterm
    :auto-start t
    :kill-process-buffer-on-stop t)

    :name "hikoseb imap notify"
    :command "imapnotify"
    :args '("-c" "~/configuration/imapnotify/hikoseb.js")
    :tags '(perso mail)
    :stop-signal 'sigterm
    :auto-start t
    :kill-process-buffer-on-stop t)

    :name "sebgmail imap notify"
    :command "imapnotify"
    :args '("-c" "~/configuration/imapnotify/sebgmail.js")
    :tags '(perso mail)
    :stop-signal 'sigterm
    :auto-start t
    :kill-process-buffer-on-stop t)

    :name "DFKI imap notify"
    :command "imapnotify"
    :args '("-c" "~/configuration/imapnotify/dfki.js")
    :tags '(work mail)
    :stop-signal 'sigterm
    :auto-start t
    :kill-process-buffer-on-stop t)

    :name "MMCI imap notify"
    :command "imapnotify"
    :args '("-c" "~/configuration/imapnotify/mmci.js")
    :tags '(work mail)
    :stop-signal 'sigterm
    :auto-start t
    :kill-process-buffer-on-stop t)


2.17.2 System daemons

With this package I can also manage my system services (tested on archlinux).

(use-package daemons :ensure t)

2.17.3 Background process configuration

Starting process in background is really nice to avoid being spammed. So let's make it available

(defun my-bpr-on-start (process)
  "Routine to allow colors in commint buffer"
  (set-process-filter process 'comint-output-filter))

(use-package bpr
  :ensure t
  :after projectile
  (setq bpr-colorize-output t
        bpr-close-after-success t
        bpr-use-projectile t
        bpr-process-mode #'comint-mode
        bpr-window-creator #'split-window-vertically
        bpr-on-start 'my-bpr-on-start))

2.18 Environment control helpers

I prefer to control some hardware using emacs directly. For now the keyboard, the screen and the sound.

2.18.1 desktop environment

Thanks to desktop environement, I can control the keyboard and the screen brightness.

(use-package desktop-environment
  :ensure t
  (setq desktop-environment-brightness-normal-increment "-inc 10"
        desktop-environment-brightness-normal-decrement "-dec 10"
        desktop-environment-brightness-small-increment "-inc 5"
        desktop-environment-brightness-small-decrement "-dec 5"
        desktop-environment-brightness-get-command "xbacklight -get"
        desktop-environment-brightness-set-command "xbacklight"

2.18.2 pulseaudio

Thanks to pulseaudio-control, I can control my soundcard.

(use-package pulseaudio-control
  :ensure t
  (setq pulseaudio-control--current-sink "@DEFAULT_SINK@"))

2.19 Language interaction (LSP)

LSP is a set of helper to interact with external "ide" tools and provide their functionalities into emacs. This has been proven useful, especially for java editing.

(use-package lsp-mode
  :ensure t
  :init (setq lsp-inhibit-message t
              lsp-eldoc-render-all nil
              lsp-highlight-symbol-at-point nil))

(use-package company-lsp
  :after  company
  :ensure t
  (setq company-lsp-enable-snippet t
        company-lsp-cache-candidates t))

(use-package lsp-ui
  :ensure t
  (setq lsp-ui-sideline-enable t
        lsp-ui-sideline-show-symbol t
        lsp-ui-sideline-show-hover t
        lsp-ui-sideline-show-code-actions t
        lsp-ui-sideline-update-mode 'point))

3 Completion

This part focuses on completion configuration. Language specific configurations are not done here but in the dedicate language configuration part. This section is just for global configuration.

3.1 Ivy/swipper/counsel

I do prefer vertical completion, which is why I use extensively Ivy and extensions.

(use-package ivy
  :ensure t
  (setq ivy-display-style 'fancy
        ivy-use-virtual-buffers t
        enable-recursive-minibuffers t
        ivy-use-selectable-prompt t))

(use-package counsel
  :ensure t
  (global-set-key (kbd "M-x") 'counsel-M-x)
  (global-set-key (kbd "C-x C-f") 'counsel-find-file))

3.2 Company

In order to have inline completion, really important for coding, I use company. However I adapted some facing attributes. Each language is also adding its backend when needed. Therefore, only global configuration here.

(use-package company
  :ensure t
  ;; Global
  (setq company-idle-delay 1
        company-minimum-prefix-length 1
        company-show-numbers t
        company-tooltip-limit 20)

  ;; Facing
  (unless (face-attribute 'company-tooltip :background)
    (set-face-attribute 'company-tooltip nil :background "black" :foreground "gray40")
    (set-face-attribute 'company-tooltip-selection nil :inherit 'company-tooltip :background "gray15")
    (set-face-attribute 'company-preview nil :background "black")
    (set-face-attribute 'company-preview-common nil :inherit 'company-preview :foreground "gray40")
    (set-face-attribute 'company-scrollbar-bg nil :inherit 'company-tooltip :background "gray20")
    (set-face-attribute 'company-scrollbar-fg nil :background "gray40"))

  ;; Default backends
  (setq company-backends '((company-files)))

  ;; Activating globally
  (global-company-mode t))

(use-package company-quickhelp
  :ensure t
  :after company
  (company-quickhelp-mode 1))

3.3 Helm

(use-package helm
  :ensure t
  (setq helm-scroll-amount 4 ; scroll 4 lines other window using M-<next>/M-<prior>
        helm-quick-update t ; do not display invisible candidates
        helm-idle-delay 0.01 ; be idle for this many seconds, before updating in delayed sources.
        helm-input-idle-delay 0.01 ; be idle for this many seconds, before updating candidate buffer
        helm-show-completion-display-function #'helm-show-completion-default-display-function
        helm-split-window-default-side 'below ;; open helm buffer in another window
        helm-split-window-inside-p t ;; open helm buffer inside current window, not occupy whole other window
        helm-candidate-number-limit 200 ; limit the number of displayed canidates
        helm-move-to-line-cycle-in-source nil ; move to end or beginning of source when reaching top or bottom of source.

3.4 Templating

I use templates for 2 use cases: the buffer edition and the file specific templates. Both are relying on yasnippet.

3.4.1 Edition templates

The default configuration of yasnippet consists of activating it and plugging it with company. Ivy-yasnippet is used for snippet discovery.

(use-package yasnippet
  :ensure t

  ;; Adding yasnippet support to company
  (add-to-list 'company-backends '(company-yasnippet))

  ;; Activate global

(use-package yasnippet-snippets
  :ensure t

(use-package ivy-yasnippet
  :ensure t)

3.4.2 Filetype templates

This part is using yatemplate (an over-layer of yasnippet) coupled with auto-insert to have a set of file type dedicated templates. The templates are available in third_parties/templates directory.

(use-package yatemplate
  :ensure t
  :after yasnippet

  ;; Define template directory
  (setq yatemplate-dir (concat config-basedir "/third_parties/templates"))

  ;; Coupling with auto-insert
  (setq auto-insert-alist nil)
  ;; (add-hook 'find-file-hook 'auto-insert)

4 Filetype

Now that we have achieved the global configuration, I am going to focus on the language specific configuration.

4.1 C/C++

C and C++ configuration is mainly relying on irony. Some minor adaptations, like the compilation part, are also integrated.

4.1.1 Irony main configuration

We just load irony add support for c derivative mode.

(use-package irony
  :ensure t
  :defer t
  :hook ((c-mode . irony-mode)
         (objc-mode . irony-mode)
         (c++-mode .irony-mode)))

4.1.2 Checking/documentation

(use-package flycheck-irony
  :ensure t
  :after (flycheck irony)
  :defer t)

(use-package irony-eldoc
  :ensure t
  :after (irony)
  :defer t)

4.1.3 Completion

For the completion, I am relying on company and irony. The configuration consists of add irony into company backend.

(use-package company-irony
  :ensure t
  :hook (irony-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-irony)))))

(use-package company-irony-c-headers
  :ensure t
  :hook (irony-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-irony-c-headers)))))

4.1.4 Adapt compilation

Sometimes, I don't want to have a makefile or any complicated project compilation. So I just use gcc/g++. Therefore, here, either there is a makefile and use it, either there is none and I use gcc/++ directly.

(add-hook 'c-mode-hook
          (lambda ()
            (unless (or (file-exists-p "Makefile") (boundp 'buffer-file-name))
              (set (make-local-variable 'compile-command)
                   (let ((file (file-name-nondirectory buffer-file-name)))
                     (concat "gcc -g -Wall -Wextra -o " (file-name-sans-extension file) " " file))))))

(add-hook 'c++-mode-hook
          (lambda ()
            (unless (file-exists-p "Makefile")
              (set (make-local-variable 'compile-command)
                   (let ((file (file-name-nondirectory buffer-file-name)))
                     (concat "g++ -g -Wall -Wextra -o " (file-name-sans-extension file) " " file))))))

4.1.5 C++ specificities

For C++, I use a dedicated font lock.

(use-package modern-cpp-font-lock :ensure t)

4.2 Configuration and log files

This part is dedicated to unix and more general configuration files as well as logs.

4.2.1 Default unix configuration

Config-general-mode is applied for all unix configuration files.

(use-package config-general-mode
  :ensure t
  :mode ("\\.conf$" "\\.*rc$"))

4.2.2 Authinfo

I developed a dedicated mode for syntax highlighting authinfo files. For now, it is not stable enough to be on melpa so I use quelpa.

(use-package authinfo-mode
  :ensure quelpa
  :quelpa (authinfo-mode :repo "seblemaguer/authinfo-mode" :fetcher github)
  :mode ("\\.authinfo\\(?:\\.gpg\\)\\'" . authinfo-mode))

4.2.3 Apache

(use-package apache-mode
  :ensure t
  :mode ("\\.htaccess\\'" "httpd\\.conf\\'" "srm\\.conf\\'"
         "access\\.conf\\'" "sites-\\(available\\|enabled\\)/"))

4.2.4 SSH configuration

(use-package ssh-config-mode
  :ensure t
  :mode ("/\\.ssh/config\\'" "/system/ssh\\'" "/sshd?_config\\'" "/known_hosts\\'" "/authorized_keys2?\\'")
  :hook (ssh-config-mode . turn-on-font-lock)

  (autoload 'ssh-config-mode "ssh-config-mode" t))

4.2.5 Logview

(use-package logview
  :ensure t
  :mode ("syslog\\(?:\\.[0-9]+\\)" "\\.log\\(?:\\.[0-9]+\\)?\\'"))

4.2.6 yaml

(use-package yaml-mode
  :ensure t
  :mode (".yaml$"))

(use-package yaml-tomato
  :ensure t)

4.2.7 vimrc

(use-package vimrc-mode
  :ensure t
  :mode ("^\\.vimrc\\'"))

4.3 CSS

(use-package scss
  :defer t
  :mode ("\\.scss\\'")
  (autoload 'scss-mode "scss-mode")
  (setq scss-compile-at-save 'nil))

4.4 CSV

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

  ;; Define separators
  (setq csv-separators '("," ";" ":" " ")))

  ;; Subpackages
(use-package csv-nav
  :ensure t
  :disabled t)

4.5 Cue

(use-package cue-mode
  :ensure quelpa
  :quelpa (cue-mode :repo "seblemaguer/cue-mode" :fetcher github)
  :mode ("\\.cue$"))

4.6 Graphviz

(use-package graphviz-dot-mode
  :ensure t
  (defvar default-tab-width nil)

  :mode ("\\.dot\\'"))

4.7 Java based

4.7.1 Global (lsp-java)

(use-package lsp-java
  :ensure t
  :requires (lsp-ui-flycheck lsp-ui-sideline)
  (java-mode . (lambda () (add-to-list (make-local-variable 'company-backends) 'company-lsp)))
  (java-mode . lsp-java-enable)
  (java-mode . flycheck-mode)
  (java-mode . (lambda () (lsp-ui-flycheck-enable t)))
  (java-mode . lsp-ui-sideline-mode)
  (setq lsp-java-save-action-organize-imports nil))

4.7.2 Snippets

(use-package java-snippets
  :ensure t)

4.7.3 Javadoc

(use-package javadoc-lookup
  :ensure t
  (when (file-exists-p "/usr/share/doc/openjdk-8-jdk/api")
    (javadoc-add-roots "/usr/share/doc/openjdk-8-jdk/api"))

  (javadoc-add-artifacts [org.lwjgl.lwjgl lwjgl "2.8.2"]
                         [com.nullprogram native-guide "0.2"]
                         [org.apache.commons commons-math3 "3.0"]
                         ;; [de.dfki.lt.jtok jtok-core "1.9.3"]

4.7.4 Groovy

  1. Global groovy
    (use-package groovy-mode
      :ensure t
      :mode ("\.groovy$" "\.gradle$")
      :interpreter ("gradle" "groovy")
      (autoload 'run-groovy "inf-groovy" "Run an inferior Groovy process")
      (autoload 'inf-groovy-keys "inf-groovy" "Set local key defs for inf-groovy in groovy-mode")
      ;; Some keys for
      (add-hook 'groovy-mode-hook
                '(lambda ()
    ;; Subpackages
    (use-package groovy-imports :ensure t)
  2. Gradle specificities
    (use-package flycheck-gradle
      :ensure t
      :defer t)

4.8 Latex

4.8.1 Global

(use-package tex-site
  :ensure auctex
  :defer t
  :after (tex latex)

  ;; Spelling
  (setq ispell-tex-skip-alists
           ;;("%\\[" . "%\\]") ; AMStex block comment...
           ;; All the standard LaTeX keywords from L. Lamport's guide:
           ;; \cite, \hspace, \hspace*, \hyphenation, \include, \includeonly
           ;; \input, \label, \nocite, \rule (in ispell - rest included here)
           ("\\\\addcontentsline"              ispell-tex-arg-end 2)
           ("\\\\add\\(tocontents\\|vspace\\)" ispell-tex-arg-end)
           ("\\\\\\([aA]lph\\|arabic\\)"   ispell-tex-arg-end)
           ("\\\\author"                         ispell-tex-arg-end)
           ;; New regexps here --- kjh
           ("\\\\\\(text\\|paren\\)cite" ispell-tex-arg-end)
           ("\\\\cite\\(t\\|p\\|year\\|yearpar\\)" ispell-tex-arg-end)
           ("\\\\bibliographystyle"                ispell-tex-arg-end)
           ("\\\\makebox"                  ispell-tex-arg-end 0)
           ("\\\\e?psfig"                  ispell-tex-arg-end)
           ("\\\\document\\(class\\|style\\)" .
            "\\\\begin[ \t\n]*{[ \t\n]*document[ \t\n]*}"))
           ;; delimited with \begin.  In ispell: displaymath, eqnarray,
           ;; eqnarray*, equation, minipage, picture, tabular,
           ;; tabular* (ispell)
           ("\\(figure\\|table\\)\\*?"     ispell-tex-arg-end 0)
           ("\\(equation\\|eqnarray\\)\\*?"     ispell-tex-arg-end 0)
           ("list"                                 ispell-tex-arg-end 2)
           ("program" . "\\\\end[ \t\n]*{[ \t\n]*program[ \t\n]*}")
           ("verbatim\\*?"."\\\\end[ \t\n]*{[ \t\n]*verbatim\\*?[ \t\n]*}")
           ("lstlisting\\*?"."\\\\end[ \t\n]*{[ \t\n]*lstlisting\\*?[ \t\n]*}"))))

  ;; Pdf activated by default
  (TeX-global-PDF-mode 1)

  ;; Diverse
  (setq-default TeX-master nil)
  (setq TeX-parse-self t
        TeX-auto-save t)

  ;; Filling
  (add-hook 'LaTeX-mode-hook 'turn-off-auto-fill)
  (add-hook 'LaTeX-mode-hook
            (lambda ()
              (TeX-fold-mode t)))

  ;; Minor helpers for comment and quotes
  (add-to-list 'LaTeX-verbatim-environments "comment")
  (setq TeX-open-quote "\enquote{"
        TeX-close-quote "}")

  ;; Indentation
  (setq LaTeX-indent-level 4
        LaTeX-item-indent 0
        TeX-brace-indent-level 4
        TeX-newline-function 'newline-and-indent)

  ;; Some usefull hooks
  (add-hook 'LaTeX-mode-hook 'flyspell-mode)
  (add-hook 'LaTeX-mode-hook 'LaTeX-math-mode)
  (add-hook 'LaTeX-mode-hook 'outline-minor-mode)

  (defadvice LaTeX-fill-region-as-paragraph (around LaTeX-sentence-filling)
    "Start each sentence on a new line."
    (let ((from (ad-get-arg 0))
          (to-marker (set-marker (make-marker) (ad-get-arg 1)))
      (while (< from (marker-position to-marker))
        ;; might have gone beyond to-marker --- use whichever is smaller:
        (ad-set-arg 1 (setq tmp-end (min (point) (marker-position to-marker))))
        (ad-set-arg 0 (setq from (point)))
        (unless (or
                 (looking-at "\\s *$"))
      (set-marker to-marker nil)))
  (ad-activate 'LaTeX-fill-region-as-paragraph)

  ;; PDF/Tex correlation
  (setq TeX-source-correlate-method 'synctex)
  (add-hook 'LaTeX-mode-hook 'TeX-source-correlate-mode)

  ;; Keys
  (define-key LaTeX-mode-map (kbd "C-c C-=") 'align-current))

4.8.2 Bibtex

(use-package bibtex
  :defer t
  (defun bibtex-generate-autokey ()
    (let* ((bibtex-autokey-names nil)
           (bibtex-autokey-year-length 2)
           (bibtex-autokey-name-separator "\0")
           (names (split-string (bibtex-autokey-get-names) "\0"))
           (year (bibtex-autokey-get-year))
           (name-char (cond ((= (length names) 1) 4)
                            ((= (length names) 2) 2)
                            (t 1)))
           (existing-keys (bibtex-parse-keys))
      (setq names (mapconcat (lambda (x)
                               (substring x 0 name-char))
      (setq key (format "%s%s" names year))
      (let ((ret key))
        (loop for c from ?a to ?z
              while (assoc ret existing-keys)
              do (setq ret (format "%s%c" key c)))

  (setq bibtex-align-at-equal-sign t
        bibtex-autokey-name-year-separator ""
        bibtex-autokey-year-title-separator ""
        bibtex-autokey-titleword-first-ignore '("the" "a" "if" "and" "an")
        bibtex-autokey-titleword-length 100
        bibtex-autokey-titlewords 1))

4.8.3 Completion

;; Completion
(setq TeX-auto-global (format "%s/auctex/style" generated-basedir))

(use-package company-auctex
  :ensure t
  (latex-mode . (company-auctex-init)))

(use-package company-bibtex
  :ensure t
  (latex-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-bibtex))))
  (org-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-bibtex)))))

(use-package company-reftex
  :ensure t
  (latex-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-reftex-labels company-reftex-citations))))
  (org-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-reftex-labels company-reftex-citations)))))

(use-package company-math
  :ensure t
  (latex-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-math-symbols-unicode))))
  (org-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-math-symbols-unicode)))))

4.8.4 Compilation

;; Escape mode
(defun TeX-toggle-escape nil
  "Toggle Shell Escape"
  (setq LaTeX-command
        (if (string= LaTeX-command "latex")
            "latex -shell-escape"
  (message (concat "shell escape "
                   (if (string= LaTeX-command "latex -shell-escape")

(use-package auctex-latexmk
  :ensure t
  (setq auctex-latexmk-inherit-TeX-PDF-mode t)

(setq TeX-show-compilation nil)

;; Redine TeX-output-mode to get the color !
(define-derived-mode TeX-output-mode TeX-special-mode "LaTeX Output"
  "Major mode for viewing TeX output.
  \\{TeX-output-mode-map} "
  :syntax-table nil
  (set (make-local-variable 'revert-buffer-function)

  (set (make-local-variable 'font-lock-defaults)
       '((("^!.*" . font-lock-warning-face) ; LaTeX error
          ("^-+$" . font-lock-builtin-face) ; latexmk divider
          ("^\\(?:Overfull\\|Underfull\\|Tight\\|Loose\\).*" . font-lock-builtin-face)
          ;; .....

  ;; special-mode makes it read-only which prevents input from TeX.
  (setq buffer-read-only nil))

4.8.5 Reftex

(use-package reftex
  :defer t
  (add-hook 'LaTeX-mode-hook 'turn-on-reftex)   ; with AUCTeX LaTeX mode
  (setq reftex-save-parse-info t
        reftex-enable-partial-scans t
        reftex-use-multiple-selection-buffers t
        reftex-plug-into-AUCTeX t
        reftex-vref-is-default t
        '((?\C-m . "\\cite[]{%l}")
          (?t . "\\textcite{%l}")
          (?a . "\\autocite[]{%l}")
          (?p . "\\parencite{%l}")
          (?f . "\\footcite[][]{%l}")
          (?F . "\\fullcite[]{%l}")
          (?x . "[]{%l}")
          (?X . "{%l}"))

        '(("cite" "[{")
          ("cites" "[{}]")
          ("footcite" "[{")
          ("footcites" "[{")
          ("parencite" "[{")
          ("textcite" "[{")
          ("fullcite" "[{")
          ("citetitle" "[{")
          ("citetitles" "[{")
          ("headlessfullcite" "[{"))

        reftex-cite-prompt-optional-args nil
        reftex-cite-cleanup-optional-args t))

4.8.6 Preview

(use-package latex-math-preview
  :ensure t
  (autoload 'LaTeX-preview-setup "preview")
  (setq preview-scale-function 1.2)
  (add-hook 'LaTeX-mode-hook 'LaTeX-preview-setup))

4.9 Ledger

(use-package ledger-mode
  :ensure t
  :defer t
  :mode ("\\.ledger$"))

(use-package flycheck-ledger
  :ensure t
  :after (flycheck ledger-mode))

4.10 TODO (E)Lisp

;; Disable checking doc
(use-package flycheck
  (setq-default flycheck-disabled-checkers '(emacs-lisp-checkdoc)))

;; Package lint
(use-package package-lint :ensure t)

;; Pretty print for lisp
(use-package ipretty :ensure t)

;; Completion
(use-package company
  :ensure t
  :hook (emacs-lisp-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-elisp)))))

4.11 Lua

(use-package lua-mode
  :ensure t)

(use-package company-lua
  :ensure t)

4.12 Matlab

(use-package matlab-load
  :ensure matlab-mode
  :mode ("\\.m\\'" . matlab-mode)

  ;; Command defines
  (setq matlab-shell-command-switches '("-nodesktop -nosplash")
        mlint-programs '("mlint" "glnxa64/mlint")))

4.13 Markdown

4.13.1 Global

(use-package markdown-mode
  :ensure t
  :mode ("\\.md$"))

(use-package markdown-mode+
  :ensure t
  :after markdown-mode
  :defer t)

4.13.2 Syntax highlight in block

(use-package polymode
  :ensure t
  (require 'poly-markdown))

4.14 PDF

4.14.1 Global

(use-package pdf-tools
  :ensure t
  :after hydra

  ;; Install what need to be installed !
  (pdf-tools-install t t t)
  ;; open pdfs scaled to fit page
  (setq-default pdf-view-display-size 'fit-page)
  ;; automatically annotate highlights
  (setq pdf-annot-activate-created-annotations t)
  ;; use normal isearch
  (define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward)
  ;; more fine-grained zooming
  (setq pdf-view-resize-factor 1.1)

  (add-hook 'pdf-view-mode-hook
            (lambda ()
              (cua-mode 0)

  (add-to-list 'auto-mode-alist (cons "\\.pdf$" 'pdf-view-mode))

  ;; Keys
  (bind-keys :map pdf-view-mode-map
             ("/" . hydra-pdftools/body)
             ("<s-spc>" .  pdf-view-scroll-down-or-next-page)
             ("g"  . pdf-view-first-page)
             ("G"  . pdf-view-last-page)
             ("l"  . image-forward-hscroll)
             ("h"  . image-backward-hscroll)
             ("j"  . pdf-view-next-page)
             ("k"  . pdf-view-previous-page)
             ("e"  . pdf-view-goto-page)
             ("u"  . pdf-view-revert-buffer)
             ("al" . pdf-annot-list-annotations)
             ("ad" . pdf-annot-delete)
             ("aa" . pdf-annot-attachment-dired)
             ("am" . pdf-annot-add-markup-annotation)
             ("at" . pdf-annot-add-text-annotation)
             ("y"  . pdf-view-kill-ring-save)
             ("i"  . pdf-misc-display-metadata)
             ("s"  . pdf-occur)
             ("b"  . pdf-view-set-slice-from-bounding-box)
             ("r"  . pdf-view-reset-slice))

  (defhydra hydra-pdftools (:color blue :hint nil)
      PDF tools

   Move  History   Scale/Fit                  Annotations     Search/Link     Do
     ^^_g_^^      _B_    ^↧^    _+_    ^ ^     _al_: list    _s_: search    _u_: revert buffer
     ^^^↑^^^      ^↑^    _H_    ^↑^  ↦ _W_ ↤   _am_: markup  _o_: outline   _i_: info
     ^^_p_^^      ^ ^    ^↥^    _0_    ^ ^     _at_: text    _F_: link      _d_: dark mode
     ^^^↑^^^      ^↓^  ╭─^─^─┐  ^↓^  ╭─^ ^─┐   _ad_: delete  _f_: search link
_h_ ←pag_e_→ _l_  _N_  │ _P_ │  _-_    _b_     _aa_: dired
     ^^^↓^^^      ^ ^  ╰─^─^─╯  ^ ^  ╰─^ ^─╯   _y_:  yank
     ^^_n_^^      ^ ^  _r_eset slice box
          ("\\" hydra-master/body "back")
          ("<ESC>" nil "quit")
          ("al" pdf-annot-list-annotations)
          ("ad" pdf-annot-delete)
          ("aa" pdf-annot-attachment-dired)
          ("am" pdf-annot-add-markup-annotation)
          ("at" pdf-annot-add-text-annotation)
          ("y"  pdf-view-kill-ring-save)
          ("+" pdf-view-enlarge :color red)
          ("-" pdf-view-shrink :color red)
          ("0" pdf-view-scale-reset)
          ("H" pdf-view-fit-height-to-window)
          ("W" pdf-view-fit-width-to-window)
          ("P" pdf-view-fit-page-to-window)
          ("n" pdf-view-next-page-command :color red)
          ("p" pdf-view-previous-page-command :color red)
          ("d" pdf-view-dark-minor-mode)
          ("b" pdf-view-set-slice-from-bounding-box)
          ("r" pdf-view-reset-slice)
          ("g" pdf-view-first-page)
          ("G" pdf-view-last-page)
          ("e" pdf-view-goto-page)
          ("o" pdf-outline)
          ("s" pdf-occur)
          ("i" pdf-misc-display-metadata)
          ("u" pdf-view-revert-buffer)
          ("F" pdf-links-action-perfom)
          ("f" pdf-links-isearch-link)
          ("B" pdf-history-backward :color red)
          ("N" pdf-history-forward :color red)
          ("l" image-forward-hscroll :color red)
          ("h" image-backward-hscroll :color red)))

4.14.2 Org specific

(use-package org-pdfview
  :ensure t

  (add-to-list 'org-file-apps
               '("\\.pdf\\'" . (lambda (file link) (org-pdfview-open link)))))

4.15 Perl

(use-package cperl-mode
  (defalias 'perl-mode 'cperl-mode)
  (cperl-set-style "BSD")

  ;; Documentation
  (setq cperl-lazy-help-time 2)

  ;; Folding
  (add-hook 'cperl-mode-hook 'hs-minor-mode)

  ;; Interactive shell
  (autoload 'run-perl "inf-perl" "Start perl interactive shell" t)

  ;; Debugger
  (autoload 'perldb-ui "perldb-ui" "perl debugger" t)

  ;; Executable perl
  (when (and buffer-file-name
             (not (string-match "\\.\\(pm\\|pod\\)$" (buffer-file-name))))
    (add-hook 'after-save-hook 'executable-chmod nil t))
  (set (make-local-variable 'compile-dwim-check-tools) nil))

4.16 Praat

(use-package praat-mode
  :mode ("\\.praat" "\\.[tT][Gg]"))

4.17 Python

4.17.1 Global configuration

(use-package python
  ("\\.py\\'" . python-mode)
  ("\\.wsgi$" . python-mode)

  (setq-default indent-tabs-mode nil)

  (setq python-indent-offset 4))

4.17.2 Anaconda configuration

(use-package anaconda-mode
  :ensure t
  :after python
  (python-mode . anaconda-mode)
  (python-mode . anaconda-eldoc-mode))

(use-package company-anaconda
  :ensure t
  :hook (python-mode . (lambda () (add-to-list (make-local-variable 'company-backends)'(company-anaconda :with company-capf)))))

4.17.3 Pipenv

(use-package pipenv
  :ensure t
  ((python-mode . pipenv-mode))

  (setq pipenv-projectile-after-switch-function

4.17.4 virtual environment

(use-package pyvenv
        :ensure t)

4.17.5 Interpreter configuration

(use-package ein
  :ensure t

  (setq ein:complete-on-dot -1)

   ((eq system-type 'darwin) (setq ein:console-args '("--gui=osx" "--matplotlib=osx" "--colors=Linux")))
   ((eq system-type 'gnu/linux) (setq ein:console-args '("--gui=gtk3" "--matplotlib=gtk3" "--colors=Linux"))))

  (setq ein:query-timeout 1000)

  (defun load-ein ()

4.17.6 Sphinx documentation

(use-package sphinx-doc
  :ensure t
  (add-hook 'python-mode-hook
            (lambda ()
              (sphinx-doc-mode t))))

4.18 R

4.18.1 ESS configuration

(use-package ess
  :ensure t)

(use-package ess-smart-underscore
  :ensure t
  :after ess)

(use-package ess-view
  :ensure t
  :after ess)

(use-package ess-R-data-view
  :ensure t
  :after ess)

4.18.2 Support drag & drop

(use-package extend-dnd
  :ensure t

4.18.3 completing

(use-package company-statistics
  :ensure t
  :after company
  :hook (after-init . company-statistics-mode))

4.19 Shell

(use-package company-shell
  :ensure t
  (eshell-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-shell company-shell-env company-fish-shell))))
  (sh-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-shell company-shell-env company-fish-shell))))

4.20 PlantUML

(use-package plantuml-mode
  :ensure t
  :after org
  :mode ("\\.plantuml\\'")
  (setq plantuml-jar-path "/opt/plantuml/plantuml.jar"
        org-plantuml-jar-path plantuml-jar-path))

4.21 Web configuration

4.21.1 Global web configuration

(use-package web-mode
  :ensure t
  ("\\.phtml\\'" "\\.tpl\\.php\\'" "\\.[agj]sp\\'" "\\.as[cp]x\\'"
  "\\.erb\\'" "\\.mustache\\'" "\\.djhtml\\'" "\\.html?\\'")

  (setq web-mode-markup-indent-offset 2
        web-mode-code-indent-offset 2
        web-mode-css-indent-offset 2

        web-mode-enable-auto-pairing t
        web-mode-enable-auto-expanding t
        web-mode-enable-css-colorization t)

  ;; Template
  (setq web-mode-engines-alist
        '(("php"    . "\\.phtml\\'")
          ("blade"  . "\\.blade\\."))


(use-package web-beautify
  :ensure t
  :commands (web-beautify-css

(use-package web-completion-data :ensure t)
(use-package web-mode-edit-element :ensure t)

4.21.2 EMMET

(use-package emmet-mode
  :ensure t
  :diminish (emmet-mode . "ε")
  :bind* (("C-)" . emmet-next-edit-point)
          ("C-(" . emmet-prev-edit-point))
  :commands (emmet-mode
  ((sgml-mode-hook . emmet-mode)
   (html-mode . emmet-mode)
   (web-mode . emmet-mode))
  (setq emmet-indentation 2
        emmet-move-cursor-between-quotes t))

4.21.3 Completion

(use-package company-web
  :ensure t
  :hook (web-mode . (lambda () (add-to-list (make-local-variable 'company-backends) '(company-web-html)))))

4.21.4 Javascript

  1. Global
    (use-package js2-mode
      :ensure t
      ;; Better imenu
      (add-hook 'js2-mode-hook #'js2-imenu-extras-mode))
    (use-package js2-refactor
      :ensure t
      :after (js2-mode hydra)
      (js2-mode . js2-refactor-mode)
      (js2r-add-keybindings-with-prefix "C-c C-r")
      (define-key js2-mode-map (kbd "C-k") #'js2r-kill)
      ;; js-mode (which js2 is based on) binds "M-." which conflicts with xref, so
      ;; unbind it.
      (define-key js-mode-map (kbd "M-.") nil)
      ;; Hydra / js2
      (defhydra js2-refactor-hydra (:color blue :hint nil)
      ^Functions^                    ^Variables^               ^Buffer^                      ^sexp^               ^Debugging^
      _lp_: Localize Parameter      _ev_: Extract variable   _wi_: Wrap buffer in IIFE    _k_:  js2 kill      _lt_: log this
      _ef_: Extract function        _iv_: Inline variable    _ig_: Inject global in IIFE  _ss_: split string  _dt_: debug this
      _ip_: Introduce parameter     _rv_: Rename variable    _ee_: Expand node at point   _sl_: forward slurp
      _em_: Extract method          _vt_: Var to this        _cc_: Contract node at point _ba_: forward barf
      _ao_: Arguments to object     _sv_: Split var decl.    _uw_: unwrap
      _tf_: Toggle fun exp and decl _ag_: Add var to globals
      _ta_: Toggle fun expr and =>  _ti_: Ternary to if
        ("ee" js2r-expand-node-at-point)
        ("cc" js2r-contract-node-at-point)
        ("ef" js2r-extract-function)
        ("em" js2r-extract-method)
        ("tf" js2r-toggle-function-expression-and-declaration)
        ("ta" js2r-toggle-arrow-function-and-expression)
        ("ip" js2r-introduce-parameter)
        ("lp" js2r-localize-parameter)
        ("wi" js2r-wrap-buffer-in-iife)
        ("ig" js2r-inject-global-in-iife)
        ("ag" js2r-add-to-globals-annotation)
        ("ev" js2r-extract-var)
        ("iv" js2r-inline-var)
        ("rv" js2r-rename-var)
        ("vt" js2r-var-to-this)
        ("ao" js2r-arguments-to-object)
        ("ti" js2r-ternary-to-if)
        ("sv" js2r-split-var-declaration)
        ("ss" js2r-split-string)
        ("uw" js2r-unwrap)
        ("lt" js2r-log-this)
        ("dt" js2r-debug-this)
        ("sl" js2r-forward-slurp)
        ("ba" js2r-forward-barf)
        ("k" js2r-kill)
        ("q" nil)))
    (use-package xref-js2
      :ensure t
      :after js2-mode
      (add-hook 'js2-mode-hook
                (lambda ()
                  (add-hook 'xref-backend-functions #'xref-js2-xref-backend nil t))))
    (use-package indium
      :ensure t
      :diminish indium-interaction-mode
      (setq indium-update-script-on-save t))
    ;; (setq indium-workspace-file (no-littering-expand-var-file-name "indium-workspaces.el"))))
    (use-package gulp-task-runner
      :commands (gulp))
    (use-package js-auto-beautify
      :ensure t)
    (use-package js-import
      :ensure t)
    (use-package company-tern
      :ensure t
      :after (company tern xref-js2)
      (js2-mode . tern-mode)
      (js2-mode . company-mode)
      (add-to-list 'company-backends 'company-tern)
      ;; Disable completion keybindings, as we use xref-js2 instead
      (define-key tern-mode-keymap (kbd "M-.") nil)
      (define-key tern-mode-keymap (kbd "M-,") nil)
      (setq company-tern-property-marker " <p>"
            company-tern-property-marker nil
            company-tern-meta-as-single-line t
            company-tooltip-align-annotations t))
  2. JSON
    (use-package json-mode
      :ensure t
    ;; Subpackage
    (use-package json-reformat :ensure t)
  3. AngularJS

    Extracted from https://github.com/zakame/emacs-for-javascript

    (use-package react-snippets
      :ensure t)
    (use-package angular-mode
      :ensure t
    (use-package angular-snippets
      :ensure t
      (eval-after-load "web-mode"
        '(bind-key "C-c C-d" 'ng-snip-show-docs-at-point web-mode-map)))
  4. Some helpers
    (defun grunt-serve ()
      "Spawns 'grunt serve' process"
      ;; Set dynamic config for process.
      ;; Variables below are applied only to particular process
      (let* ((bpr-scroll-direction 1) (bpr-show-progress nil))
        (bpr-spawn "$(npm bin)/grunt serve --color")

4.22 XML

(use-package nxml-mode
  :mode ("\\.xml$" . nxml-mode)
  :commands (pretty-print-xml-region)
  :defer t
  ;; Mapping xml to nxml
  (fset 'xml-mode 'nxml-mode)


  ;; Global configuration
  (setq nxml-child-indent 2
        nxml-auto-insert-xml-declaration-flag t
        nxml-slash-auto-complete-flag t
        nxml-bind-meta-tab-to-complete-flag t)

  ;; Outline hook
  (add-hook 'nxml-mode-hook
            (lambda ()
              (setq outline-regexp "^[ \t]*\<[a-zA-Z]+")))

  ;; Helper to format
  (defun pretty-print-xml-region (begin end)
  "Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this.  The function inserts linebreaks to separate tags that have
nothing but whitespace between them.  It then indents the markup
by using nxml's indentation rules."
  (interactive "r")
      (goto-char begin)
      (while (search-forward-regexp "\>[ \\t]*\<" nil t)
        (backward-char) (insert "\n"))
      (indent-region begin end))))

5 Org

5.1 Global part

(use-package org
  :ensure t
  :after flyspell

  ;; Global
  (setq org-startup-indented t
        org-enforce-todo-dependencies t
        org-cycle-separator-lines 2
        org-blank-before-new-entry '((heading) (plain-list-item . auto))
        org-insert-heading-respect-content nil
        org-reverse-note-order nil
        org-show-following-heading t
        org-show-hierarchy-above t
        org-show-siblings '((default))
        org-id-method 'uuidgen
        org-deadline-warning-days 30
        org-table-export-default-format "orgtbl-to-csv"
        org-src-window-setup 'other-window
        org-clone-delete-id t
        org-cycle-include-plain-lists t
        org-src-fontify-natively t
        org-hide-emphasis-markers t)

  ;; Activate spelling
  (add-hook 'org-mode 'flyspell-mode)
  (add-to-list 'ispell-skip-region-alist '("^#+begin_src" . "^#+end_src"))

  ;; TODO to sort
  (use-package ob-async :ensure t)
  (use-package org-checklist)
  (use-package ob-exp)
  (use-package ox-bibtex)
  (use-package org-protocol)
  (use-package org-dashboard :ensure t)

  ;; Todo part
  (setq org-todo-keywords '((sequence
                             "TODO(t)" "REVIEW(r)" "NEXT(N)" "STARTED(s)"
                             "WAITING(w)" "DELEGATED(e)" "MAYBE(m)" "|"
                             "DONE(d)" "NOTE(n)" "DEFERRED(f)" "CANCELLED(c@/!)"))

        org-todo-state-tags-triggers '(("CANCELLED" ("CANCELLED" . t))
                                       ("WAITING" ("WAITING" . t))
                                       ("HOLD" ("WAITING" . t) ("HOLD" . t))
                                       (done ("WAITING") ("HOLD"))
                                       ("TODO" ("WAITING") ("CANCELLED") ("HOLD"))
                                       ("IN PROGRESS" ("NEXT") ("WAITING") ("CANCELLED") ("HOLD"))
                                       ("NEXT" ("WAITING") ("CANCELLED") ("HOLD"))
                                       ("DONE" ("WAITING") ("CANCELLED") ("HOLD"))))

  ;; Priority definition
  (setq org-highest-priority ?A
        org-lowest-priority ?E
        org-default-priority ?C)

  ;; Archiving
  (setq org-archive-mark-done t
        org-log-done 'time
        org-archive-location "%s_archive::* Archived Tasks")

  ;; Refiling
  (setq org-refile-targets '((org-agenda-files . (:maxlevel . 3)))
        org-completion-use-ido nil
        org-refile-use-outline-path 'file
        org-outline-path-complete-in-steps nil
        org-refile-allow-creating-parent-nodes 'confirm))

5.2 Todo management - some helpers

Extracted from https://www.emacswiki.org/emacs/org-extension.el

(defun org-archive-all-done-item ()
  "Archive all item that have with prefix DONE."
    (goto-char (point-min))
    (if (search-forward-regexp "^[\\*]+ \\(DONE\\|CANCELLED\\)" nil t)
          (goto-char (point-min))
          (while (search-forward-regexp "^[\\*]+ \\(DONE\\|CANCELLED\\)" nil t)
          (message "Archive finished"))
      (message "No need to archive"))))

(defun org-clean-done-item ()
  "Delete all item that have with prefix DONE."
    (goto-char (point-min))
    (if (search-forward-regexp "^[\\*]+ \\(DONE\\|CANCELLED\\)" nil t)
          (goto-char (point-min))
          (while (search-forward-regexp "^[\\*]+ \\(DONE\\|CANCELLED\\)" nil t)
          (message "Cleaning DONE tasks finished"))
      (message "No need to clean"))))

5.3 Calendar / Agenda

5.3.1 Global

(use-package org-agenda
  :after (hydra org)

  ;; Todo part
  (setq org-agenda-files '())
  (when (file-exists-p "~/Dropbox/org/todo/todo.org")
    (setq org-agenda-files
          (append org-agenda-files '("~/Dropbox/org/todo/todo.org"))))

  (when (file-exists-p "~/Dropbox/org/organisation/bookmarks.org")
    (setq org-agenda-files
          (append org-agenda-files '("~/Dropbox/org/organisation/bookmarks.org"))))

  (when (file-exists-p "~/Calendars")
    (setq org-agenda-files
          (append org-agenda-files (directory-files "~/Calendars/" t "^.*\\.org$"))))

  ;; Deadline management
  (setq org-agenda-include-diary nil
        org-deadline-warning-days 7
        org-timeline-show-empty-dates t

        org-agenda-category-icon-alist `(
                                         ;; Tools / utils
                                         ("[Ee]macs" ,(format "%s/third_parties/icons/emacs24.png" config-basedir) nil nil :ascent center)
                                         ("[Oo]rg" ,(format "%s/third_parties/icons/org.png" config-basedir) nil nil :ascent center)
                                         ("^[Hh][Tt][Ss]$" ,(format "%s/third_parties/icons/hts.png" config-basedir) nil nil :ascent center)
                                         ("^[Mm]ary[tT]\\{2\\}[sS]$" ,(format "%s/third_parties/icons/marytts.png" config-basedir) nil nil :ascent center)
                                         ("^SFB$" ,(format "%s/third_parties/icons/sfb.png" config-basedir) nil nil :ascent center)
                                         ("[Ss]ystem" ,(format "%s/third_parties/icons/debian.png" config-basedir) nil nil :ascent center)
                                         ("[Tt]ools?" ,(format "%s/third_parties/icons/wrench.png" config-basedir) nil nil :ascent center)
                                         ("[Ex]pe\\(riment\\)s?" ,(format "%s/third_parties/icons/expes.png" config-basedir) nil nil :ascent center)

                                         ;; Admin / meeting
                                         ("[Aa]dmin" ,(format "%s/third_parties/icons/admin.png" config-basedir) nil nil :ascent center)
                                         ("[Mm]eeting" ,(format "%s/third_parties/icons/meeting.png" config-basedir) nil nil :ascent center)
                                         ("[Aa]ppointments?" ,(format "%s/third_parties/icons/appointment.png" config-basedir) nil nil :ascent center)
                                         ("[Vv]isitors" ,(format "%s/third_parties/icons/visitors.png" config-basedir) nil nil :ascent center)
                                         ("synsig" ,(format "%s/third_parties/icons/isca.png" config-basedir) nil nil :ascent center)
                                         ("\\([Tt]rip\\|[Dd]eplacement\\)" ,(format "%s/third_parties/icons/trip.png" config-basedir) nil nil :ascent center)
                                         ("Train" ,(format "%s/third_parties/icons/train.png" config-basedir) nil nil :ascent center)

                                         ;; Deadlines / dates
                                         ("\\([Pp]resentations?\\)" ,(format "%s/third_parties/icons/meeting.png" config-basedir) nil nil :ascent center)
                                         ("\\([Pp]apers?\\|[Bb]lio?\\|[Aa]rticles?\\)" ,(format "%s/third_parties/icons/book.png" config-basedir) nil nil :ascent center)
                                         ("[Mm]ails?" ,(format "%s/third_parties/icons/gnus.png" config-basedir) nil nil :ascent center)
                                         ("[Rr]eview?" ,(format "%s/third_parties/icons/review.png" config-basedir) nil nil :ascent center)

                                         ;; Personnal dates
                                         ("Medical" ,(format "%s/third_parties/icons/medical.png" config-basedir) nil nil :ascent center)
                                         ("\\(Party\\|Celeb\\)" ,(format "%s/third_parties/icons/party.png" config-basedir) nil nil :ascent center)
                                         ("Anniv" ,(format "%s/third_parties/icons/anniversary.png" config-basedir) nil nil :ascent center)
                                         ("\\([Hh]olidays\\|[Vv]acations?\\)" ,(format "%s/third_parties/icons/holidays.png" config-basedir) nil nil :ascent center)

                                         ;; Personnal diverse
                                         ("Music" ,(format "%s/third_parties/icons/music.png" config-basedir) nil nil :ascent center)
                                         ("Book" ,(format "%s/third_parties/icons/book.png" config-basedir) nil nil :ascent center)
                                         ("[Pp]rojects?" ,(format "%s/third_parties/icons/project.png" config-basedir) nil nil :ascent center)
                                         (".*" '(space . (:width (16)))))

        ;; Some commands
        org-agenda-custom-commands '(
                                     ("D" todo "DONE")

                                     ("w" "Work and administrative"
                                       (tags-todo "WORK")
                                       (tags-todo "OFFICE")
                                       (tags-todo "ADMIN")))

                                     ("p" "personnal"
                                       (tags-todo "PERSONNAL")))

                                     ("d" "Daily Action List"
                                      ((agenda "" ((org-agenda-ndays 1)
                                                    '((agenda time-up priority-down tag-up) ))
                                                   (org-deadline-warning-days 0)))))))

  ;; Agenda view shortcuts
  (define-key org-agenda-mode-map "v" 'hydra-org-agenda-view/body)

  (defun org-agenda-cts ()
    (let ((args (get-text-property
                 (min (1- (point-max)) (point))
      (nth 2 args)))

  (defhydra hydra-org-agenda-view (:color blue :hint none)
    _d_: ?d? day        _g_: time grid=?g? _a_: arch-trees
    _w_: ?w? week       _[_: inactive      _A_: arch-files
    _t_: ?t? fortnight  _f_: follow=?f?    _r_: report=?r?
    _m_: ?m? month      _e_: entry =?e?    _D_: diary=?D?
    _y_: ?y? year       _q_: quit          _L__l__c_: ?l?

    ("SPC" org-agenda-reset-view)
    ("d" org-agenda-day-view
     (if (eq 'day (org-agenda-cts))
         "[x]" "[ ]"))
    ("w" org-agenda-week-view
     (if (eq 'week (org-agenda-cts))
         "[x]" "[ ]"))
    ("t" org-agenda-fortnight-view
     (if (eq 'fortnight (org-agenda-cts))
         "[x]" "[ ]"))
    ("m" org-agenda-month-view
     (if (eq 'month (org-agenda-cts)) "[x]" "[ ]"))
    ("y" org-agenda-year-view
     (if (eq 'year (org-agenda-cts)) "[x]" "[ ]"))
    ("l" org-agenda-log-mode
     (format "% -3S" org-agenda-show-log))
    ("L" (org-agenda-log-mode '(4)))
    ("c" (org-agenda-log-mode 'clockcheck))
    ("f" org-agenda-follow-mode
     (format "% -3S" org-agenda-follow-mode))
    ("a" org-agenda-archives-mode)
    ("A" (org-agenda-archives-mode 'files))
    ("r" org-agenda-clockreport-mode
     (format "% -3S" org-agenda-clockreport-mode))
    ("e" org-agenda-entry-text-mode
     (format "% -3S" org-agenda-entry-text-mode))
    ("g" org-agenda-toggle-time-grid
     (format "% -3S" org-agenda-use-time-grid))
    ("D" org-agenda-toggle-diary
     (format "% -3S" org-agenda-include-diary))
    ("!" org-agenda-toggle-deadlines)
     (let ((org-agenda-include-inactive-timestamps t))
       (org-agenda-check-type t 'timeline 'agenda)
    ("q" (message "Abort") :exit t)))

;; Global shortcut to call org agenda
(global-set-key (kbd "<f12>") 'org-agenda)

5.3.2 Super agenda

(use-package org-super-agenda
  :ensure t
  :after (org org-agenda)
  (setq org-super-agenda-groups

        '((:name "Important tasks ":priority "A")
          (:name "SynSIG" :tag "SynSIG")
          (:auto-category t)

5.4 Capturing

5.4.1 Global

(use-package org-capture

  ;; Capture
  (setq org-capture-templates
        `(("b" "Adding book" entry
           (file+headline "~/Dropbox/org/todo/todo.org" "To read")
           (file ,(format "%s/third_parties/org-capture-templates/book.org" config-basedir)))

          ("L" "Bookmark" entry
           (file+olp "~/Dropbox/org/todo/todo.org" "To review" "Bookmarks")
           (file ,(format "%s/third_parties/org-capture-templates/bookmark.org" config-basedir)))

          ("m" "mail" entry
           (file+headline "~/Dropbox/org/todo/todo.org" "Mailing")
           (file ,(format "%s/third_parties/org-capture-templates/mail.org" config-basedir)))

          ("M" "MSP calendar" entry
           (file "~/Calendars/Calendar-MSP.org")
           (file ,(format "%s/third_parties/org-capture-templates/calendar.org" config-basedir)))

          ("P" "Personnal calendar" entry
           (file "~/Calendars/Calendar-Personal.org")
           (file ,(format "%s/third_parties/org-capture-templates/calendar.org" config-basedir)))

          ("r" "RSS" entry
           (file+olp "~/Dropbox/org/todo/todo.org" "To review" "RSS")
           (file ,(format "%s/third_parties/org-capture-templates/rss.org" config-basedir)))

          ("t" "ToDo Entry" entry
           (file+headline "~/Dropbox/org/todo/todo.org" "To sort")
           (file ,(format "%s/third_parties/org-capture-templates/default.org" config-basedir))
           :empty-lines-before 1)))

5.4.2 Cooking

(use-package org-chef
  :ensure t
  (add-to-list 'org-capture-templates
               '("c" "Cookbook" entry (file "~/Dropbox/recipes/cookbook.org")
                 :empty-lines 1)))

5.5 Editing

(setq org-list-allow-alphabetical t
      org-highlight-latex-and-related '(latex)
      org-ditaa-jar-path "/usr/share/ditaa/ditaa.jar"
      org-babel-results-keyword "results" ;; Display images directly in the buffer
      org-confirm-babel-evaluate nil
      org-startup-with-inline-images t)

(use-package org-notebook :ensure t)

;; Add languages
(use-package ob-ipython :ensure t)
(org-babel-do-load-languages 'org-babel-load-languages
                             '((emacs-lisp . t)
                               (dot . t)
                               (ditaa . t)
                               (R . t)
                               (ipython . t)
                               (ruby . t)
                               (gnuplot . t)
                               (clojure . t)
                               (shell . t)
                               (ledger . t)
                               (org . t)
                               (plantuml . t)
                               (latex . t)))

; Define specific modes for specific tools
(add-to-list 'org-src-lang-modes '("plantuml" . plantuml))
(add-to-list 'org-src-lang-modes '("dot" . graphviz-dot))

5.5.1 Block template

(use-package hydra :ensure t
  ;; Define the templates
  (setq org-structure-template-alist
        '(("s" "#+begin_src ?\n\n#+end_src" "<src lang=\"?\">\n\n</src>")
          ("e" "#+begin_example\n?\n#+end_example" "<example>\n?\n</example>")
          ("q" "#+begin_quote\n?\n#+end_quote" "<quote>\n?\n</quote>")
          ("v" "#+begin_verse\n?\n#+end_verse" "<verse>\n?\n/verse>")
          ("c" "#+begin_center\n?\n#+end_center" "<center>\n?\n/center>")
          ("l" "#+begin_export latex\n?\n#+end_export" "<literal style=\"latex\">\n?\n</literal>")
          ("L" "#+latex: " "<literal style=\"latex\">?</literal>")
          ("h" "#+begin_export html\n?\n#+end_exrt" "<literal style=\"html\">\n?\n</literal>")
          ("H" "#+html: " "<literal style=\"html\">?</literal>")
          ("a" "#+begin_export ascii\n?\n#+end_export")
          ("A" "#+ascii: ")
          ("i" "#+index: ?" "#+index: ?")
          ("I" "#+include: %file ?" "<include file=%file markup=\"?\">")))

  ;; Shortcuts
  (defun hot-expand (str &optional mod)
    "Expand org template."
    (let (text)
      (when (region-active-p)
        (setq text (buffer-substring (region-beginning) (region-end)))
        (delete-region (region-beginning) (region-end)))
      (insert str)
      (when mod (insert mod) (forward-line))
      (when text (insert text))))

  (defhydra hydra-org-template (:color blue :hint nil)
     Org template

 block               src block         structure
_c_: center        _s_: src         _L_: LATEX:
_q_: quote         _e_: emacs lisp  _i_: index:
_E_: example       _p_: python      _I_: INCLUDE:
_v_: verse         _P_: perl        _H_: HTML:
_a_: ascii         _u_: Plantuml    _A_: ASCII:
_l_: latex         _d_: ditaa
_h_: html          _S_: shell
    ("s" (hot-expand "<s"))
    ("E" (hot-expand "<e"))
    ("q" (hot-expand "<q"))
    ("v" (hot-expand "<v"))
    ("c" (hot-expand "<c"))
    ("l" (hot-expand "<l"))
    ("h" (hot-expand "<h"))
    ("a" (hot-expand "<a"))
    ("L" (hot-expand "<L"))
    ("i" (hot-expand "<i"))
    ("e" (hot-expand "<s" "emacs-lisp"))
    ("p" (hot-expand "<s" "python"))
    ("P" (hot-expand "<s" "perl"))
    ("S" (hot-expand "<s" "sh"))
    ("d" (hot-expand "<s" "ditaa :file CHANGE.png :cache yes"))
    ("u" (hot-expand "<s" "plantuml :file CHANGE.svg :cache yes"))
    ("I" (hot-expand "<I"))
    ("H" (hot-expand "<H"))
    ("A" (hot-expand "<A"))
    ("<" self-insert-command "ins")
    ("ESC" nil "quit"))

  (define-key org-mode-map "<"
    (lambda () (interactive)
      (if (or (region-active-p) (looking-back "^"))
        (self-insert-command 1)))))

5.5.2 Id generations

(use-package org-id+
  :ensure quelpa
  :quelpa (org-id+ :repo "seblemaguer/org-id-plus" :fetcher github))

5.6 Exporting

5.6.1 HTML

(use-package htmlize :ensure t)

(use-package ox-html
  :after ox
  :requires (htmlize)
  (setq org-html-xml-declaration '(("html" . "")
                                 ("was-html" . "<?xml version=\"1.0\" encoding=\"%s\"?>")
                                 ("php" . "<?php echo \"<?xml version=\\\"1.0\\\" encoding=\\\"%s\\\" ?>\"; ?>"))
      org-export-html-inline-images t
      org-export-with-sub-superscripts nil
      org-export-html-style-extra "<link rel=\"stylesheet\" href=\"org.css\" type=\"text/css\" />"
      org-export-html-style-include-default nil
      org-export-htmlize-output-type 'css ; Do not generate internal css formatting for HTML exports

  (defun endless/export-audio-link (path desc format)
    "Export org audio links to hmtl."
    (cl-case format
      (html (format "<audio src=\"%s\" controls>%s</audio>" path (or desc "")))))
  (org-add-link-type "audio" #'ignore #'endless/export-audio-link)

  (defun endless/export-video-link (path desc format)
    "Export org video links to hmtl."
    (cl-case format
      (html (format "<video controls src=\"%s\"></video>" path (or desc "")))))
  (org-add-link-type "video" #'ignore #'endless/export-video-link)

  (add-to-list 'org-file-apps '("\\.x?html?\\'" . "/usr/bin/vivaldi-stable %s")))

(use-package ox-reveal
  :ensure t
  :requires (ox-html htmlize))

5.6.2 LaTeX

(use-package ox-latex
  :after ox
  :defer t
  (setq org-latex-listings t
        org-export-with-LaTeX-fragments t
        org-latex-pdf-process (list "latexmk -shell-escape -bibtex -f -pdf %f")))

5.6.3 Beamer

(use-package ox-beamer
  :after ox
  (defun my-beamer-bold (contents backend info)
    (when (eq backend 'beamer)
      (replace-regexp-in-string "\\`\\\\[A-Za-z0-9]+" "\\\\textbf" contents)))
  (add-to-list 'org-export-filter-bold-functions 'my-beamer-bold))

5.6.4 Docbook

(setq org-export-docbook-xsl-fo-proc-command "fop %s %s"
      org-export-docbook-xslt-proc-command "xsltproc --output %s /usr/share/xml/docbook/stylesheet/nwalsh/fo/docbook.xsl %s")

5.6.5 Markdown

(use-package ox-gfm
    :ensure t
    :after ox
    :config (require 'ox-gfm))

5.6.6 Pandoc

(use-package ox-pandoc
  :ensure t
  :after ox
  :defer t
  ;; default options for all output formats
  (setq org-pandoc-options '((standalone . t))
        ;; cancel above settings only for 'docx' format
        org-pandoc-options-for-docx '((standalone . nil))
        ;; special settings for beamer-pdf and latex-pdf exporters
        org-pandoc-options-for-beamer-pdf '((pdf-engine . "xelatex"))
        org-pandoc-options-for-latex-pdf '((pdf-engine . "xelatex"))))

6 Documentation

6.1 Help

(use-package helpful :ensure t)

6.2 Apropos

(use-package apropos-fn+var
  :ensure t
  (setq apropos-do-all t))

6.3 Info

(use-package info-buffer :ensure t)
(use-package info+ :ensure t :disabled)

6.4 Man

(use-package man
  :ensure t
  (setq Man-notify-method 'pushy)
  (setq woman-manpath
          "/usr/share/man/" "/usr/local/man/" ;; System
          ,(format "%s/local/man" config-basedir) ;; Private environment

7 Shell

7.1 Global

The key configuration is mainly coming from https://github.com/jcf/emacs.d the rest is coming from http://www.modernemacs.com/post/custom-eshell/ with some adaptation

(use-package eshell
  (add-hook 'eshell-mode-hook
            (lambda ()
              (eshell/export "NODE_NO_READLINE=1")))

  (defmacro with-face (STR &rest PROPS)
    "Return STR propertized with PROPS."
    `(propertize ,STR 'face (list ,@PROPS)))

  (defmacro esh-section (NAME ICON FORM &rest PROPS)
    "Build eshell section NAME with ICON prepended to evaled FORM with PROPS."
    `(setq ,NAME
           (lambda () (when ,FORM
                        (-> ,ICON
                            (concat esh-section-delim ,FORM)
                            (with-face ,@PROPS))))))

  (defun esh-acc (acc x)
    "Accumulator for evaluating and concatenating esh-sections."
    (--if-let (funcall x)
        (if (s-blank? acc)
          (concat acc esh-sep it))

  (defun esh-prompt-func ()
    "Build `eshell-prompt-function'"
    (concat esh-header
            (-reduce-from 'esh-acc "" eshell-funcs)

  (esh-section esh-dir
               "\xf07c"  ;  (faicon folder)
               (abbreviate-file-name (eshell/pwd))
               '(:foreground "blue" :bold ultra-bold :underline t))

  (esh-section esh-git
               "\xe907"  ;  (git icon)
               '(:foreground "red"))

  (esh-section esh-python
               "\xe928"  ;  (python icon)

  (esh-section esh-clock
               "\xf017"  ;  (clock icon)
               (format-time-string "%H:%M" (current-time))
               '(:foreground "forest green"))

  ;; Below I implement a "prompt number" section
  (setq esh-prompt-num 0)
  (add-hook 'eshell-exit-hook (lambda () (setq esh-prompt-num 0)))
  (advice-add 'eshell-send-input :before
              (lambda (&rest args) (setq esh-prompt-num (incf esh-prompt-num))))

  (esh-section esh-num
               "\xf0c9"  ;  (list icon)
               (number-to-string esh-prompt-num)
               '(:foreground "brown"))

  (setq esh-sep " | " ; "  "  or " | " ;; Separator between esh-sections
        esh-section-delim " " ;; Separator between an esh-section icon and form
        esh-header "\n " ;; Eshell prompt header

        ;; Eshell prompt regexp and string. Unless you are varying the prompt by eg.
        ;; your login, these can be the same.
        eshell-prompt-regexp "[^└]└─> "
        eshell-prompt-string "└─> "

        eshell-funcs (list esh-dir esh-git esh-python esh-clock esh-num) ;; Choose which eshell-funcs to enable
        eshell-prompt-function 'esh-prompt-func ;; Enable the new eshell prompt

  (defun eshell-mode-some-config ()
    (define-key eshell-mode-map (kbd "M-p") 'helm-eshell-history)
    (eshell/export "NODE_NO_READLINE=1"))

  (add-hook 'eshell-mode-hook

  ;; If I ever want my own eshell/foo commands overwrite real commands ...
  (setq eshell-prefer-lisp-functions t)

  ;; Helpers
  (defun eshell/clear ()
    "Clear the eshell buffer."
    (let ((inhibit-read-only t))

  (defun clipboard/set (astring)
    "Copy a string to clipboard"
      (insert astring)
      (clipboard-kill-region (point-min) (point-max))))

  (defun eshell/copy-pwd ()
    "Copy current directory to clipboard "
    (clipboard/set (eshell/pwd)))

  (defun eshell/copy-fpath (fname)
    "Copy file name with full path to clipboard "
    (let ((fpath (concat (eshell/pwd) "/" fname)))
      (clipboard/set fpath)
      (concat "Copied path: " fpath)))

7.2 Status in the fringe

(use-package eshell-fringe-status
  :ensure t
  (add-hook 'eshell-mode-hook 'eshell-fringe-status-mode))

7.3 Some helpers

(defun eshell/clear ()
  "Clear the eshell buffer."
  (let ((inhibit-read-only t))

(defun clipboard/set (astring)
  "Copy a string to clipboard"
    (insert astring)
    (clipboard-kill-region (point-min) (point-max))))

(defun eshell/copy-pwd ()
  "Copy current directory to clipboard "
  (clipboard/set (eshell/pwd)))

(defun eshell/copy-fpath (fname)
  "Copy file name with full path to clipboard "
  (let ((fpath (concat (eshell/pwd) "/" fname)))
    (clipboard/set fpath)
    (concat "Copied path: " fpath)))

8 Compilation

8.1 TODO some requires to check

(require 'compile-)
(require 'compile)
(require 'compile+)

8.2 Flychecking

(use-package flycheck-stack
  :ensure t
  :after flycheck)

8.3 Gradle global support

(use-package gradle-mode
  :ensure quelpa
  :quelpa (gradle-mode :repo "seblemaguer/emacs-gradle-mode" :fetcher github)
  (setq gradle-gradlew-executable "./gradlew"
        gradle-use-gradlew t)

8.4 Compilation

(use-package winnow
  :ensure t
  (add-hook 'compilation-mode-hook 'winnow-mode)
  (add-hook 'ag-mode-hook 'winnow-mode))

9 Project management

9.1 Configuration projectile

The commands are based on http://endlessparentheses.com/improving-projectile-with-extra-commands.html?source=rss

  (use-package projectile
    :ensure t

    ;; Global configuration
    (setq projectile-switch-project-action 'neotree-projectile-action
          projectile-enable-caching t
          projectile-create-missing-test-files t
          projectile-switch-project-action #'projectile-commander
          projectile-ignored-project-function 'file-remote-p)

    ;; Defining some helpers
    (def-projectile-commander-method ?s
      "Open a *shell* buffer for the project."
      ;; This requires a snapshot version of Projectile.

    (def-projectile-commander-method ?c
      "Run `compile' in the project."
      (projectile-compile-project nil))

    (def-projectile-commander-method ?\C-?
      "Go back to project selection."

    ;; Keys
    (setq projectile-keymap-prefix (kbd "C-x p"))

    ;; Activate globally

9.2 Todos/projectile

(use-package org-projectile
  :ensure t
  :after org
  :after projectile
  (setq org-projectile-per-project-filepath "todo.org"
        (append org-agenda-files (org-projectile-todo-files))))

9.3 Completion

(use-package counsel-projectile
  :ensure t
  :after projectile)

10 Version control

10.1 Git

10.1.1 Magit

  1. Global
    (use-package magit
      :ensure t
      ;; Ignore recent commit
      (setq magit-status-sections-hook
      ;; Update visualization
      (setq pretty-magit-alist nil
            pretty-magit-prompt nil)
      (defmacro pretty-magit (WORD ICON PROPS &optional NO-PROMPT?)
        "Replace sanitized WORD with ICON, PROPS and by default add to prompts."
             (add-to-list 'pretty-magit-alist
                          (list (rx bow (group ,WORD (eval (if ,NO-PROMPT? "" ":"))))
                                ,ICON ',PROPS))
           (unless ,NO-PROMPT?
             (add-to-list 'pretty-magit-prompt (concat ,WORD ": ")))))
      ;; Operations
      (pretty-magit "add"   ? (:foreground "#375E97" :height 1.2) pretty-magit-prompt)
      (pretty-magit "fix"   ? (:foreground "#FB6542" :height 1.2) pretty-magit-prompt)
      (pretty-magit "clean" ? (:foreground "#FFBB00" :height 1.2) pretty-magit-prompt)
      (pretty-magit "doc."  ? (:foreground "#3F681C" :height 1.2) pretty-magit-prompt)
      ;; Meta information
      (pretty-magit "master"  ? (:box nil :height 1.2) t)
      (pretty-magit "origin"  ? (:box nil :height 1.2) t)
      (pretty-magit "upstream"  ? (:box nil :height 1.2) t)
      (defun add-magit-faces ()
        "Add face properties and compose symbols for buffer from pretty-magit."
          (--each pretty-magit-alist
            (-let (((rgx icon props) it))
                (goto-char (point-min))
                (while (search-forward-regexp rgx nil t)
                   (match-beginning 1) (match-end 1) icon)
                  (when props
                     (match-beginning 1) (match-end 1) props))))))))
      (advice-add 'magit-status :after 'add-magit-faces)
      (advice-add 'magit-refresh-buffer :after 'add-magit-faces)
      ;; Opening repo externally
      (defun parse-url (url)
        "convert a git remote location as a HTTP URL"
        (if (string-match "^http" url)
          (replace-regexp-in-string "\\(.*\\)@\\(.*\\):\\(.*\\)\\(\\.git?\\)"
      (defun magit-open-repo ()
        "open remote repo URL"
        (let ((url (magit-get "remote" "origin" "url")))
            (browse-url (parse-url url))
            (message "opening repo %s" url))))
      (add-hook 'magit-mode-hook
                (lambda ()
                  (local-set-key (kbd "o") 'magit-open-repo))))
  2. Diff
    (use-package magit-tbdiff
      :ensure t
      :after magit)
  3. Todo
    (use-package magit-todos
      :ensure t
      :commands (magit-todos-mode)
      :hook (magit-mode . magit-todos-mode)
      (setq magit-todos-recursive t
            magit-todos-depth 100)
      :custom (magit-todos-keywords (list "TODO" "FIXME")))

10.1.2 Git ignore

(use-package gitignore-mode
  :ensure t)

(use-package helm-gitignore
  :ensure t)

10.1.3 Config edition

(use-package gitconfig-mode
  :ensure t
  :defer t
  ("/\.gitconfig\'"    . gitconfig-mode)
  ("/vcs/gitconfig\'"    . gitconfig-mode))

10.1.4 Helpers for edition

(use-package git-commit
  :ensure t
  :defer t)

(use-package gitattributes-mode
  :ensure t
  :defer t)

10.1.5 Git prefix

(use-package git-msg-prefix
  :ensure t
  :defer t
  (setq git-msg-prefix-log-flags " --since='1 week ago' "
        git-msg-prefix-regex "^\\([^:]*: \\)"
        git-msg-prefix-input-method 'ivy-read)
  ;; (add-hook 'git-commit-mode-hook 'git-msg-prefix)

10.1.6 Commit navigation

(use-package git-timemachine :ensure t)

10.1.7 Send patch by email

(use-package gitpatch
  :ensure t
  (setq gitpatch-mail-attach-patch-key "C-c i"))

10.2 Mercurial

10.2.1 Monky

(use-package monky :ensure t)

10.2.2 Configuration

(use-package hgignore-mode :ensure t)
(use-package hgrc-mode :ensure t)

10.3 Providers

10.3.1 Github

;; Github api
(use-package gh :ensure t)
(use-package gh-md :ensure t)

;; Search on github
(use-package github-search :ensure t)

;; Mapping github with magit
(use-package ghub :ensure t)
(use-package ghub+ :ensure t)

(use-package magithub
  :ensure t
  :after (:all magit ghub ghub+)
  :config (magithub-feature-autoinject t))

10.3.2 Gist

(use-package gist :ensure t)

10.3.3 Gitlab

(use-package gitlab :ensure t)
(use-package glab :ensure t)
(use-package ivy-gitlab :ensure t)

10.3.4 Browsing at remote

(use-package browse-at-remote :ensure t)

10.4 Continuous building

(use-package travis
  :ensure t

  (defun show-my-travis-projects ()
    (travis-show-projects "seblemaguer")))

11 File/Directory management

11.1 Dired

11.1.1 Run associated application - define helpers

(defun dired-open-native ()
  "Open marked files (or the file the cursor is on) from dired."
  (let* ((files (dired-get-marked-files t current-prefix-arg))
         (n (length files)))
    (when (or (<= n 3)
              (y-or-n-p (format "Open %d files?" n)))
      (dolist (file files)
        (call-process "xdg-open" nil 0 nil file)))))

                                        ; The use of "gnome-open" here should probably be parameterized.
(defun dired-open-current-directory-in-GUI-file-manager ()
  "Open the current directory in native GUI file namanger
For those times when dired just wont do.
     "xdg-open .")))

11.1.2 Main configuration

(use-package dired

  ;; Adapt ls for mac
  (when (eq system-type 'darwin)
    (require 'ls-lisp)
    (setq ls-lisp-use-insert-directory-program t
          insert-directory-program "/usr/local/bin/gls"))

  ;; Omitting
  (setq-default dired-omit-files "^\\.[^.]+"
                dired-omit-mode t)

  ;; Adapt ls lisp format
  (if (boundp 'ls-lisp-ignore-case)
      (setq ls-lisp-ignore-case t))
  (if (boundp 'ls-lisp-dirs-first)
      (setq ls-lisp-dirs-first t))
  (if (boundp 'ls-lisp-use-localized-time-format)
      (setq ls-lisp-use-localized-time-format t))
  (if (boundp 'ls-lisp-format-time-list)
      (setq ls-lisp-format-time-list '("%Y-%m-%d %H:%M" "%Y-%m-%d %H:%M")))

  (put 'dired-find-alternate-file 'disabled nil)

  (setq dired-dwim-target t

        ;; Compression
        auto-compression-mode t

        ;; Recursive
        dired-recursive-deletes 'top
        dired-recursive-copies 'always

        ;; Details information
        dired-listing-switches "--group-directories-first -alh"
        dired-details-hidden-string "[...]")

  ;; Keys
  (define-key dired-mode-map (kbd "C-o") 'dired-omit-mode)
  (define-key dired-mode-map (kbd "<C-return>") 'dired-open-native)
  (define-key dired-mode-map (kbd "e") 'dired-open-externally)

  ;; Diff
  (defun ora-ediff-files ()
    (let ((files (dired-get-marked-files))
          (wnd (current-window-configuration)))
      (if (<= (length files) 2)
          (let ((file1 (car files))
                (file2 (if (cdr files)
                           (cadr files)
                          "file: "
            (if (file-newer-than-file-p file1 file2)
                (ediff-files file2 file1)
              (ediff-files file1 file2))
            (add-hook 'ediff-after-quit-hook-internal
                      (lambda ()
                        (setq ediff-after-quit-hook-internal nil)
                        (set-window-configuration wnd))))
        (error "no more than 2 files should be marked"))))
  (define-key dired-mode-map "E" 'ora-ediff-files)

11.1.3 peep-dired

(use-package peep-dired
  :ensure t
  (define-key dired-mode-map (kbd "P") 'peep-dired)

11.1.4 dired-narrow

(use-package dired-narrow
  :ensure t
  (define-key dired-mode-map (kbd "/") 'dired-narrow)

11.1.5 dired-single

(use-package dired-single
  :ensure t
  (define-key dired-mode-map [return] 'dired-single-buffer)
  (define-key dired-mode-map [mouse-1] 'dired-single-buffer-mouse)

11.1.6 dired-collapse

(use-package dired-collapse
  :ensure t
  (add-hook 'dired-mode-hook 'dired-collapse-mode))

11.1.7 dired-filter

(use-package dired-filter
  :ensure t
  (add-hook 'dired-mode-hook 'dired-filter-group-mode)

  (setq dired-filter-group-saved-groups
           ("Directories" (directory))
            (extension . "pdf"))
            (extension "tex" "bib"))
            (extension . "org"))
            (extension "zip" "rar" "gz" "bz2" "tar"))
            (extension "ogg" "flv" "mpg" "avi" "mp4" "mp3"))

11.1.8 dired-subtree

(use-package dired-subtree
  :ensure t
  (define-key dired-mode-map "i" 'dired-subtree-insert)
  (define-key dired-mode-map ";" 'dired-subtree-remove)

11.1.9 Dired / images

(use-package image-dired+
  :ensure t
  (setq auto-image-file-mode t)
  (eval-after-load 'image-dired+ '(image-diredx-async-mode 1)))

11.1.10 Async

(use-package async
  :ensure t
  :after dired

  (when (require 'dired-aux)
      (require 'dired-async))
    (dired-async-mode 1)))

11.1.11 Dired / Rsync

(use-package dired-rsync
  :defer t
  :ensure t
  (bind-key "C-c C-r" 'dired-rsync dired-mode-map))

11.1.12 Hydra

Hydra mapping for dired taken from https://github.com/abo-abo/hydra/wiki/Dired and adapted.

(defhydra hydra-dired (:hint nil :color pink)
_+_ mkdir          _v_iew           _m_ark             _(_ details        _i_nsert-subdir    wdired
_C_opy             _O_ view other   _U_nmark all       _)_ omit-mode      _$_ hide-subdir    C-x C-q : edit
_D_elete           _o_pen other     _u_nmark           _l_ redisplay      _w_ kill-subdir    C-c C-c : commit
_R_ename           _M_ chmod        _t_oggle           _g_ revert buf     _e_ ediff          C-c ESC : abort
_Y_ rel symlink    _G_ chgrp        _E_xtension mark   _s_ort             _=_ pdiff
_S_ymlink          ^ ^              _F_ind marked      _._ toggle hydra   \\ flyspell
_r_sync            ^ ^              ^ ^                ^ ^                _?_ summary
_z_ compress-file  _A_ find regexp
_Z_ compress       _Q_ repl regexp

T - tag prefix
  ("\\" dired-do-ispell)
  ("(" dired-hide-details-mode)
  (")" dired-omit-mode)
  ("+" dired-create-directory)
  ("=" diredp-ediff)         ;; smart diff
  ("?" dired-summary)
  ("$" diredp-hide-subdir-nomove)
  ("A" dired-do-find-regexp)
  ("C" dired-do-copy)        ;; Copy all marked files
  ("D" dired-do-delete)
  ("E" dired-mark-extension)
  ("e" dired-ediff-files)
  ("F" dired-do-find-marked-files)
  ("G" dired-do-chgrp)
  ("g" revert-buffer)        ;; read all directories again (refresh)
  ("i" dired-maybe-insert-subdir)
  ("l" dired-do-redisplay)   ;; relist the marked or singel directory
  ("M" dired-do-chmod)
  ("m" dired-mark)
  ("O" dired-display-file)
  ("o" dired-find-file-other-window)
  ("Q" dired-do-find-regexp-and-replace)
  ("R" dired-do-rename)
  ("r" dired-do-rsynch)
  ("S" dired-do-symlink)
  ("s" dired-sort-toggle-or-edit)
  ("t" dired-toggle-marks)
  ("U" dired-unmark-all-marks)
  ("u" dired-unmark)
  ("v" dired-view-file)      ;; q to exit, s to search, = gets line #
  ("w" dired-kill-subdir)
  ("Y" dired-do-relsymlink)
  ("z" diredp-compress-this-file)
  ("Z" dired-do-compress)
  ("q" nil)
  ("." nil :color blue))

(define-key dired-mode-map "." 'hydra-dired/body)

11.2 Images

(use-package image+
  :ensure t
  (add-hook 'image-mode-hook
            '(lambda ()
               (require 'image+)

  :bind (:map image-mode-map
              ("=" . imagex-sticky-zoom-in)
              ("-" . imagex-sticky-zoom-out)
              ("m" . imagex-sticky-maximize)
              ("g" . imagex-sticky-restore-original)
              ("S" . imagex-sticky-save-image)
              ("r" . imagex-sticky-rotate-right)
              ("l" . imagex-sticky-rotate-left)
              ("/" . imagex-sticky-binding/body))

    (defhydra imagex-sticky-binding () ;; global-map "C-x C-l")
    "Manipulating Image"
    ("+" imagex-sticky-zoom-in "zoom in")
    ("-" imagex-sticky-zoom-out "zoom out")
    ("M" imagex-sticky-maximize "maximize")
    ("O" imagex-sticky-restore-original "restore original")
    ("S" imagex-sticky-save-image "save file")
    ("r" imagex-sticky-rotate-right "rotate right")
    ("l" imagex-sticky-rotate-left "rotate left")))

11.3 Diff

11.3.1 Global

(use-package ediff
  (autoload 'diff-mode "diff-mode" "Diff major mode" t)
  (setq diff-switches "-u"
        ediff-auto-refine-limit (* 2 14000)
        ediff-window-setup-function 'ediff-setup-windows-plain
        (lambda (&optional arg)
          (if (> (frame-width) 160)
              (split-window-horizontally arg)
            (split-window-vertically arg)))))

11.3.2 Helpers for region diff

(defun diff-region ()
  "Select a region to compare"
  (when (use-region-p) ; there is a region
    (let (buf)
      (setq buf (get-buffer-create "*Diff-regionA*"))
        (set-buffer buf)
      (append-to-buffer buf (region-beginning) (region-end)))
  (message "Now select other region to compare and run `diff-region-now`"))

(defun diff-region-now ()
  "Compare current region with region already selected by `diff-region`"
  (when (use-region-p)
    (let (bufa bufb)
      (setq bufa (get-buffer-create "*Diff-regionA*"))
      (setq bufb (get-buffer-create "*Diff-regionB*"))
        (set-buffer bufb)
      (append-to-buffer bufb (region-beginning) (region-end))
      (ediff-buffers bufa bufb))

11.4 Tramp

;; Global configuration
(setq tramp-default-method "ssh")
(setq password-cache-expiry 60)
(setq tramp-auto-save-directory temporary-file-directory)

;; Debug
;;(setq tramp-verbose 9)
(setq tramp-debug-buffer nil)

11.5 Trash

;; Ask confirmation only once and move to trash
(setq dired-recursive-deletes 'always)
(setq delete-by-moving-to-trash t)

(defun empty-trash()
  "Command to empty the trash (for now gnome/linux specific)"
  (shell-command "rm -rf ~/.local/share/Trash/*"))

(defun open-trash-dir()
  "Command to open the trash dir"
  (find-file "~/.local/share/Trash/files"))

11.6 Treemacs

(use-package treemacs
  :ensure t
  :after hl-line-mode
  (setq treemacs-follow-after-init          t
        treemacs-width                      35
        treemacs-indentation                2
        treemacs-git-integration            t
        treemacs-collapse-dirs              3
        treemacs-silent-refresh             nil
        treemacs-change-root-without-asking nil
        treemacs-sorting                    'alphabetic-desc
        treemacs-show-hidden-files          t
        treemacs-never-persist              nil
        treemacs-is-never-other-window      nil
        treemacs-goto-tag-strategy          'refetch-index)

  (treemacs-follow-mode t)
  (treemacs-filewatch-mode t)
  (:map global-map
        ([f8]        . treemacs-toggle)))

(use-package treemacs-projectile
  :ensure t
  :after treemacs
  (setq treemacs-header-function #'treemacs-projectile-create-header))

12 Ibuffer

12.1 Filter

(defun my-own-ibuffer-hook ()
  (setq ibuffer-saved-filter-groups
         (cons "default"
                    (name . "^[*]scratch[*]$")
                    (name . "^[*]Messages[*]$")))

                    (name . "^[*]?[Cc]alendar.*$")
                    (name . "^diary$")
                    (mode . cfw:calendar-mode)
                    (mode . muse-mode)))

                   (filename . "/todo.org"))

                    (mode . emms-mode)
                    (mode . emms-browser-mode)
                    (mode . emms-playlist-mode)))

                    (name . "rss.org")
                    (name . "^[*]?[Ee]lfeed.*$")
                    (derived-mode . elfeed-search-mode)
                    (derived-mode . elfeed-show-mode)))

                    (derived-mode . apropos-mode)
                    (derived-mode . help-mode)
                    (derived-mode . Info-mode)))

                    (mode . message-mode)
                    (mode . bbdb-mode)
                    (mode . mail-mode)
                    (mode . notmuch-show-mode)
                    (mode . notmuch-search-mode)
                    (mode . notmuch-hello-mode)
                    (name . "^\.bbdb$")
                    (name . "^\.newsrc-dribble")))))


                 (("Dired" (mode . dired-mode))

                    (mode . sh-mode)))

                    (mode . tex-mode)
                    (mode . latex-mode)
                    (mode . bibtex-mode)
                    (mode . text-mode)))

                    (mode . matlab-mode)
                    (name . "^[*]MATLAB[*]$")
                    (mode . ess-mode)
                    (mode . iESS)))

                    (derived-mode . conf-mode)))

                    (mode . php-mode)
                    (mode . css-mode)
                    (mode . html-mode)
                    (mode . js2-mode)
                    (mode . scss-mode)
                    (mode . web-mode)))

                    (mode . emacs-lisp-mode)
                    (mode . c-mode)
                    (mode . cperl-mode)
                    (mode . python-mode)
                    (mode . c++-mode)
                    (mode . java-mode)
                    (mode . jde-mode)))

                    (mode . groovy-mode)
                    (derived-mode . makefile-mode)))

                    (mode . csv-mode)
                    (mode . json-mode)
                    (mode . nxml-mode)
                    (mode . ledger-mode)

                    (mode . org-mode)))

                    (mode . comint-mode)
                    (mode . eshell-mode)
                    (mode . term-mode)))

                    (name . "^[*]prodigy.*[*]$")))

                    (name ."^[*].*[*]$")))

12.2 Global

(use-package ibuffer
  :after hydra

  ;; Sub packages
  (use-package ibuffer-git :ensure t)
  (use-package ibuffer-tramp :ensure t)
  (use-package ibuffer-vc :ensure t)
  (use-package ibuffer-circe
    :ensure quelpa
    :quelpa (ibuffer-circe :repo "seblemaguer/ibuffer-circe" :fetcher github)
    :after circe
    :config (require 'circe))

  ;; Use human readable Size column instead of original one
  (define-ibuffer-column size-h
    (:name "Size" :inline t)
     ((> (buffer-size) 1000000) (format "%7.3fM" (/ (buffer-size) 1000000.0)))
     ((> (buffer-size) 1000) (format "%7.3fk" (/ (buffer-size) 1000.0)))
     (t (format "%8d" (buffer-size)))))

  ;; Modification time
  (defun get-modification-time-buffer(b)
    "Retrieve the savetime of the given buffer"
    (if (buffer-file-name b)
        (format-time-string "%Y-%m-%d %H:%M:%S"
                            (nth 5 (file-attributes (buffer-file-name b))))

  (define-ibuffer-column last-modification
    (:name "Last modification time" )
    (get-modification-time-buffer buffer))

  ;; Ibuffer entry format
  (setq ibuffer-formats
        '((mark modified read-only
                (name 30 30 :left :elide) " "
                (size-h 9 -1 :right) " "
                (mode 20 20 :left :elide) " "
                ;; (eproject 16 16 :left :elide)      " "
                (git-status 8 8 :left)" "
                (last-modification 30 30 :left :elide)  " "

  ;; Update
  (defadvice ibuffer-update (around ibuffer-preserve-prev-header activate)
    "Preserve line-header used before Ibuffer if it doesn't set one"
    (let ((prev-line-header header-line-format))
      (unless header-line-format
        (setq header-line-format prev-line-header))))

  (setq ibuffer-default-sorting-mode 'major-mode  ;; Sorting
        ibuffer-show-empty-filter-groups nil      ;; Ignore empty groups
        ibuffer-marked-char ?✓               ;; Change the marking symbol

  ;; Auto revert
  (add-hook 'ibuffer-mode-hook
            (lambda ()
              (ibuffer-switch-to-saved-filter-groups "default")
              (ibuffer-update nil t)))

  ;; Collapsing some buffer groups
  (setq mp/ibuffer-collapsed-groups
        (list "Calendar" "Todos"
              "Emms" "RSS/Podcast"
              "Temp" "Help" "*Tramp*"))

  (defadvice ibuffer (after collapse)
    (dolist (group mp/ibuffer-collapsed-groups)
        (goto-char 1)
        (when (search-forward (concat "[ " group " ]") (point-max) t)
            (move-beginning-of-line nil)
    (goto-char 1)
    (search-forward "[ " (point-max) t)
  (ad-activate 'ibuffer)

  ;; Keys
  (defhydra hydra-ibuffer-main (:color pink :hint nil)

 ^Navigation^     ^Mark^         ^Actions^          ^View^
  _k_:    ʌ     _m_: mark       _D_: delete        _g_: refresh
 _RET_: visit   _u_: unmark     _S_: save          _s_: sort
  _j_:    v     _*_: specific   _a_: all actions   _/_: filter
    ("j" ibuffer-forward-line)
    ("RET" ibuffer-visit-buffer :color blue)
    ("k" ibuffer-backward-line)

    ("m" ibuffer-mark-forward)
    ("u" ibuffer-unmark-forward)
    ("*" hydra-ibuffer-mark/body :color blue)

    ("D" ibuffer-do-delete)
    ("S" ibuffer-do-save)
    ("a" hydra-ibuffer-action/body :color blue)

    ("g" ibuffer-update)
    ("s" hydra-ibuffer-sort/body :color blue)
    ("/" hydra-ibuffer-filter/body :color blue)

    ("o" ibuffer-visit-buffer-other-window "other window" :color blue)
    ("q" ibuffer-quit "quit ibuffer" :color blue)
    ("." nil "toggle hydra" :color blue))

  (defhydra hydra-ibuffer-mark (:color teal :columns 5
                                       :after-exit (hydra-ibuffer-main/body))
    ("*" ibuffer-unmark-all "unmark all")
    ("M" ibuffer-mark-by-mode "mode")
    ("m" ibuffer-mark-modified-buffers "modified")
    ("u" ibuffer-mark-unsaved-buffers "unsaved")
    ("s" ibuffer-mark-special-buffers "special")
    ("r" ibuffer-mark-read-only-buffers "read-only")
    ("/" ibuffer-mark-dired-buffers "dired")
    ("e" ibuffer-mark-dissociated-buffers "dissociated")
    ("h" ibuffer-mark-help-buffers "help")
    ("z" ibuffer-mark-compressed-file-buffers "compressed")
    ("b" hydra-ibuffer-main/body "back" :color blue))

  (defhydra hydra-ibuffer-action (:color teal :columns 4
                                         (if (eq major-mode 'ibuffer-mode)
    ("A" ibuffer-do-view "view")
    ("E" ibuffer-do-eval "eval")
    ("F" ibuffer-do-shell-command-file "shell-command-file")
    ("I" ibuffer-do-query-replace-regexp "query-replace-regexp")
    ("H" ibuffer-do-view-other-frame "view-other-frame")
    ("N" ibuffer-do-shell-command-pipe-replace "shell-cmd-pipe-replace")
    ("M" ibuffer-do-toggle-modified "toggle-modified")
    ("O" ibuffer-do-occur "occur")
    ("P" ibuffer-do-print "print")
    ("Q" ibuffer-do-query-replace "query-replace")
    ("R" ibuffer-do-rename-uniquely "rename-uniquely")
    ("T" ibuffer-do-toggle-read-only "toggle-read-only")
    ("U" ibuffer-do-replace-regexp "replace-regexp")
    ("V" ibuffer-do-revert "revert")
    ("W" ibuffer-do-view-and-eval "view-and-eval")
    ("X" ibuffer-do-shell-command-pipe "shell-command-pipe")
    ("b" nil "back"))

  (defhydra hydra-ibuffer-sort (:color amaranth :columns 3)
    ("i" ibuffer-invert-sorting "invert")
    ("a" ibuffer-do-sort-by-alphabetic "alphabetic")
    ("v" ibuffer-do-sort-by-recency "recently used")
    ("s" ibuffer-do-sort-by-size "size")
    ("f" ibuffer-do-sort-by-filename/process "filename")
    ("m" ibuffer-do-sort-by-major-mode "mode")
    ("b" hydra-ibuffer-main/body "back" :color blue))

  (defhydra hydra-ibuffer-filter (:color amaranth :columns 4)
    ("m" ibuffer-filter-by-used-mode "mode")
    ("M" ibuffer-filter-by-derived-mode "derived mode")
    ("n" ibuffer-filter-by-name "name")
    ("c" ibuffer-filter-by-content "content")
    ("e" ibuffer-filter-by-predicate "predicate")
    ("f" ibuffer-filter-by-filename "filename")
    (">" ibuffer-filter-by-size-gt "size")
    ("<" ibuffer-filter-by-size-lt "size")
    ("/" ibuffer-filter-disable "disable")
    ("b" hydra-ibuffer-main/body "back" :color blue))

  (define-key ibuffer-mode-map "." 'hydra-ibuffer-main/body)

  ;; Global access
  (global-set-key (kbd "C-x C-b") 'ibuffer))

12.3 Helpers

(defun ibuffer-clean ()
  "Clean automatically created buffers"
  (ibuffer-unmark-all ?*)
  (ibuffer-mark-by-mode 'help-mode)
  (ibuffer-mark-by-mode 'magit-mode)
  (ibuffer-mark-by-mode 'occur-mode)
  (ibuffer-mark-by-mode 'grep-mode)
  (ibuffer-mark-by-mode 'dired-mode)
  (ibuffer-mark-by-mode 'completion-list-mode)
  (ibuffer-mark-by-mode 'compilation-mode)
  (ibuffer-mark-by-mode 'Man-mode)
  (ibuffer-mark-by-mode 'browse-kill-ring-mode)
  (ibuffer-mark-by-name-regexp "*anything*")
  (ibuffer-mark-by-name-regexp "*ESS*")
  (ibuffer-mark-by-name-regexp "*Shell Command Output*")
  (ibuffer-mark-by-name-regexp "*Compile-Log*")
  (ibuffer-mark-by-name-regexp "*vc-diff*")

13 Notification

13.1 Sauron

(use-package sauron
  :ensure t

  (setq sauron-separate-frame nil ;; The notification is on the same window ?
        sauron-sticky-frame t
        sauron-max-line-length nil ;; No max. length for the line
        sauron-modules '(sauron-org sauron-elfeed)) ;; reduced the default modules

13.2 Alert

(use-package alert
  :after sauron

  (defcustom alert-highlight-priorities
    '((urgent . 5)
      (high . 4)
      (moderate . 3)
      (normal . 2)
      (low . 1)
      (trivial . 0))
    "A mapping of alert severities onto Growl priority values."
    :type '(alist :key-type symbol :value-type integer)
    :group 'alert)

  (defvar alert-highlight-current-level 0)
  (defvar alert-highlight-threshold 1)

  (defun alert-adapt-mode-line (info)

    ;; First time => copy the current mode line face
    (when (<= alert-highlight-current-level alert-highlight-threshold)
      (copy-face 'mode-line 'backup-mode-line-face))

    ;; (message (format "%d >= (%d, %d, %s)"
    ;;               (cdr (assq (plist-get info :severity) alert-highlight-priorities))
    ;;               alert-highlight-current-level
    ;;               alert-highlight-threshold
    ;;               (cdr (assq (plist-get info :severity)
    ;;                          alert-severity-colors))))

    ;; Change the policy
    (when (and (> (cdr (assq (plist-get info :severity) alert-highlight-priorities))
               (> (cdr (assq (plist-get info :severity) alert-highlight-priorities))
        (set-face-attribute 'mode-line nil
                            :background (cdr (assq (plist-get info :severity)

    ;; Change current level if this one is upper
    (when (> (cdr (assq (plist-get info :severity) alert-highlight-priorities))
      (setq alert-highlight-current-level (cdr (assq (plist-get info :severity)

    ;; Print the message everytime !
    (alert-message-notify info)

    ;; Removers are optional.  Their job is to remove
    ;; the visual or auditory effect of the alert.
    :remover  #'alert-message-remove)

   :title "Mode-line alert"
   :notifier 'alert-adapt-mode-line)

  (setq alert-default-style 'mode-line-alert)

  ;; Link with sauron
  (add-hook 'sauron-event-added-functions 'sauron-alert-el-adapter)

  ;; Shortcuts part
  (defun sauron-alert-clear ()
      (when (> alert-highlight-current-level alert-highlight-threshold)
          (copy-face 'backup-mode-line-face 'mode-line)
          (setq alert-highlight-current-level 0)))

  (defun sauron-alert-toggle-hide-show ()
      (when (> alert-highlight-current-level alert-highlight-threshold)
          (copy-face 'backup-mode-line-face 'mode-line)
          (setq alert-highlight-current-level 0)))))

  ;; Shortcuts
  (global-set-key (kbd "<f7>") 'sauron-alert-toggle-hide-show)
  (global-set-key (kbd "C-<f7>") 'sauron-alert-clear))

14 System

14.1 Docker

(use-package docker :ensure t)
(use-package docker-api :ensure t)
(use-package docker-tramp :ensure t)
(use-package dockerfile-mode :ensure t)

14.2 SSH

(use-package ssh :ensure t)
(use-package ssh-deploy :ensure t)

14.3 Monitoring

(use-package symon
  :ensure t
  :defer t)

15 Internet/network

15.1 Globalize clickable url

;; Redefine the browser to add vivaldi
(use-package browse-url
  (defcustom browse-url-vivaldi-program
    (let ((candidates '("vivaldi" "vivaldi-stable")))
      (while (and candidates (not (executable-find (car candidates))))
        (setq candidates (cdr candidates)))
      (or (car candidates) "vivaldi"))
    "The name by which to invoke Vivaldi."
    :type 'string
    :version "25.3"
    :group 'browse-url)

  (defcustom browse-url-vivaldi-arguments nil
    "A list of strings to pass to Vivaldi as arguments."
    :type '(repeat (string :tag "Argument"))
    :version "25.3"
    :group 'browse-url)

  (defun browse-url-vivaldi (url &optional _new-window)
    "Ask the Vivaldi WWW browser to load URL.
Default to the URL around or before point.  The strings in
variable `browse-url-vivaldi-arguments' are also passed to
The optional argument NEW-WINDOW is not used."
    (interactive (browse-url-interactive-arg "URL: "))
    (setq url (browse-url-encode-url url))
    (let* ((process-environment (browse-url-process-environment)))
      (apply 'start-process
             (concat "vivaldi " url) nil
              (list url)))))

  (defun browse-url-default-browser (url &rest args)
    "Find a suitable browser and ask it to load URL.
Default to the URL around or before point.

When called interactively, if variable `browse-url-new-window-flag' is
non-nil, load the document in a new window, if possible, otherwise use
a random existing one.  A non-nil interactive prefix argument reverses
the effect of `browse-url-new-window-flag'.

When called non-interactively, optional second argument ARGS is used
instead of `browse-url-new-window-flag'."
      ((memq system-type '(windows-nt ms-dos cygwin))
      ((memq system-type '(darwin))
      ((browse-url-can-use-xdg-open) 'browse-url-xdg-open)
;;;    ((executable-find browse-url-gnome-moz-program) 'browse-url-gnome-moz)
      ((executable-find browse-url-mozilla-program) 'browse-url-mozilla)
      ((executable-find browse-url-firefox-program) 'browse-url-firefox)
      ((executable-find browse-url-chromium-program) 'browse-url-chromium)
      ((executable-find browse-url-vivaldi-program) 'browse-url-vivaldi)
;;;    ((executable-find browse-url-galeon-program) 'browse-url-galeon)
      ((executable-find browse-url-kde-program) 'browse-url-kde)
;;;    ((executable-find browse-url-netscape-program) 'browse-url-netscape)
;;;    ((executable-find browse-url-mosaic-program) 'browse-url-mosaic)
      ((executable-find browse-url-conkeror-program) 'browse-url-conkeror)
      ((executable-find browse-url-chrome-program) 'browse-url-chrome)
      ((executable-find browse-url-xterm-program) 'browse-url-text-xterm)
      ((locate-library "w3") 'browse-url-w3)
       (lambda (&rest _ignore) (error "No usable browser found"))))
     url args)))

;; Activate clickage everywhere
(use-package goto-addr
  (define-globalized-minor-mode global-goto-address-mode
    goto-address-mode goto-address-mode :group 'goto-address)


  (define-globalized-minor-mode global-goto-address-prog-mode
    goto-address-prog-mode goto-address-prog-mode :group 'goto-address))

15.2 Searching

15.2.1 Google

(use-package google :ensure t)
(use-package google-maps :ensure t)
(use-package google-translate :ensure t)

15.2.2 Youtube

(use-package ivy-youtube :ensure t)

15.2.3 Codesearch

(use-package counsel-codesearch :ensure t)

15.3 IRC

15.3.1 Global

(use-package circe
  :ensure t
  :bind ("<S-f2>" . circe-init)
  (add-hook 'circe-chat-mode-hook 'disable-global-facilities)


  ;; Defining the networks
  (setq circe-network-options
           :nick "slemaguer"
           :server-buffer-name "⇄ bitlbee"
           :nickserv-password my-irc-password
           :nickserv-mask "\\(bitlbee\\|root\\)!\\(bitlbee\\|root\\)@"
           :nickserv-identify-challenge "use the \x02identify\x02 command to identify yourself"
           :nickserv-identify-command "PRIVMSG NickServ :IDENTIFY {nick} {password}"
           :nickserv-identify-confirmation "Password accepted, settings and accounts loaded"
           :channels ("&bitlbee")
           :host "localhost"
           :service "6667")

           :tls t
           :nick "slemaguer"
           :channels (:after-auth "#limsi")
           :nickserv-password my-irc-password
           :server-buffer-name "⇄ freenode")

           :tls t
           :nick "seblemaguer"
           :sasl-username "seblemaguer"
           :sasl-password my-irc-password
           :server-buffer-name "⇄ gitter"
           :service "6667")

  ;; Completion
  (setq circe-use-cycle-completion t)

  ;; Spam information reduction
  (setq circe-reduce-lurker-spam t)

  ;; Tracking
  (setq lui-track-bar-behavior 'before-switch-to-buffer)

  ;; spell checking
  (add-hook 'circe-channel-mode-hook 'turn-on-flyspell)
  (setq lui-max-buffer-size 30000
        lui-flyspell-p t
        lui-flyspell-alist '(("limsi" "francais")
                             ("IvanaDidirkova" "francais")
                             ("." "american")))

  ;; Formatting

  (setq lui-time-stamp-position 'right-margin
        lui-time-stamp-format "%H:%M"
        lui-fill-type nil)

  (defun my-lui-setup ()
     fringes-outside-margins t
     right-margin-width 5
     word-wrap t
     wrap-prefix "    "))
  (add-hook 'lui-mode-hook 'my-lui-setup)

  ;; Connection
  (defun circe-network-connected-p (network)
    "Return non-nil if there's any Circe server-buffer whose
  `circe-server-netwok' is NETWORK."
    (catch 'return
      (dolist (buffer (circe-server-buffers))
        (with-current-buffer buffer
          (if (string= network circe-server-network)
              (throw 'return t))))))

   (defun circe-maybe-connect (network)
     "Connect to NETWORK, but ask user for confirmation if it's
  already been connected to."
     (interactive "sNetwork: ")
     (if (or (not (circe-network-connected-p network))
             (y-or-n-p (format "Already connected to %s, reconnect?" network)))
         (circe network)))

   (defun my-irc-password (server)
     "Return the password for the `SERVER'."
     (my:auth-source-get-passwd :host server))

   ;; Shortcut
   (defun circe-init ()
     "Connect to IRC"
     (if (circe-network-connected-p "bitlbee")
         (switch-to-buffer "&bitlbee")
         (circe-maybe-connect "Freenode")
         (circe-maybe-connect "bitlbee"))))

15.3.2 Logging

(use-package lui-logging
  :commands enable-lui-logging)

15.3.3 Autopasting

(use-package lui-autopaste
  :after circe
  (add-hook 'circe-channel-mode-hook 'enable-lui-autopaste)
  (defvar lui-autopaste-service-gist-url nil
    "The URL for the last gist.")

  (defun lui-autopaste-service-gist (text)
    "Paste TEXT to github using gist.el."
    ;; It's so great gist works with callbacks! It's so much fun to
    ;; work around that!
    (setq lui-autopaste-service-gist-url 'waiting)
      (insert text)
      (gist-region (point-min) (point-max) nil
                   (lambda (gist)
                     (when (eq lui-autopaste-service-gist-url
                       (setq lui-autopaste-service-gist-url
                             (oref gist :html-url))))))
    (let ((wait 0))
      (while (and (< wait 10)
                  (eq lui-autopaste-service-gist-url
        (sit-for 0.1 )
        (setq wait (1+ wait))))
    (if (eq lui-autopaste-service-gist-url 'waiting)
          (setq lui-autopaste-service-gist-url nil)
          (error "Couldn't create gist"))
      (prog1 lui-autopaste-service-gist-url
        (setq lui-autopaste-service-gist-url nil))))

  (setq lui-autopaste-function 'lui-autopaste-service-gist))

15.3.4 Some coloring

(use-package lui-irc-colors
  :after circe
  (add-to-list 'lui-pre-output-hook 'lui-irc-colors))

15.3.5 Notification

(use-package sauron-circe
  :ensure quelpa
  :quelpa (sauron-circe :repo "seblemaguer/sauron-circe" :fetcher github)
  :after sauron

15.4 Mail

15.4.1 TTLS

(use-package starttls
  (setq starttls-use-gnutls t
        starttls-gnutls-program "gnutls-cli"
        starttls-extra-arguments '("--insecure")
        auth-sources '("~/.authinfo.gpg")))

15.4.2 Message composition

(use-package message
  (add-hook 'message-mode-hook 'flyspell-mode)
  (add-hook 'message-setup-hook '(lambda () (footnote-mode t)))
  (add-hook 'message-mode-hook 'disable-global-facilities)

  (setq message-auto-save-directory nil
        message-citation-line-function 'message-insert-formatted-citation-line
        message-citation-line-format "Le %e %B %Y à %-H:%M %Z, %N a écrit :"
        message-sendmail-f-is-evil nil
        message-signature-file (format "%s/third_parties/mail/signature" config-basedir)
        message-fill-column 100)

15.4.3 Composing/Sending

(use-package smtpmail-multi
  :ensure t
  :after flyspell
  ;; :ensure-system-package msmtp

  (setq user-full-name "Sébastien Le Maguer"
          (sebgmail . ("seb.lemaguer@gmail.com"
                       nil nil nil))
          (coli . ("slemaguer"
                   nil nil nil))
          (mmci . ("lemaguer"
                   nil nil nil))

        '(("slemaguer@coli.uni-saarland.de" coli)
          ("lemaguer@mmci.uni-saarland.de" mmci)
          ("seb.lemaguer@gmail.com" sebgmail))

        smtpmail-multi-default-account 'coli
        message-send-mail-function 'smtpmail-multi-send-it
        mail-host-address "coli.uni-saarland.de"

        ;; Debug part
        smtpmail-debug-info nil
        smtpmail-debug-verbose nil)

15.4.4 notmuch

  1. Global configuration
    (use-package notmuch
      :ensure t
      :ensure-system-package notmuch
      :ensure-system-package isync
      (setq notmuch-search-oldest-first nil
            notmuch-print-mechanism 'notmuch-print-muttprint/evince
            notmuch-show-all-multipart/alternative-parts nil
            notmuch-crypto-process-mime t
            gnus-inhibit-images nil
            notmuch-always-prompt-for-sender t
            notmuch-show-indent-messages-width 2
            notmuch-fcc-dirs '(("slemaguer@coli.uni-saarland.de" . "Saarland/INBOX/.Sent")
                               ("lemaguer@mmci.uni-saarland.de" . "MMCI/Sent")
                               ("seb.lemaguer@gmail.com" . "SebGmail/Sent")
      ;; Hook for notmuch
      (defcustom notmuch-index-updated-hook nil
        "Normal hook run when notmuch index has been updated."
        :type 'hook
        :group 'notmuch)
      (defun notmuch-message-mark-sent ()
        "Mark all the message from any interesting sent folders as sent."
        (notmuch-tag "folder:Saarland/INBOX/.Sent or folder:*/Sent"
                     (notmuch-tag-change-list '("-inbox" "-unread" "+sent"))))
      (defun notmuch-update-index ()
        "Update the index (without sync.) and mark sent messages as sent"
        (run-hooks 'notmuch-index-updated-hook))
      (defun notmuch-update-index-and-refresh-buffer ()
        "Update the index and then refresh the current buffer"
      (defun notmuch-sync-and-update-index ()
        "Update the index after sync."
        (call-process "mbsync" nil t nil "-a")
      ;; Hello shortcuts
      (define-key notmuch-hello-mode-map "U" 'notmuch-sync-and-update-index)
      (define-key notmuch-hello-mode-map "g" 'notmuch-update-index-and-refresh-buffer)
      ;; Search shortcuts
      (define-key notmuch-search-mode-map "g" 'notmuch-update-index-and-refresh-buffer)
      (define-key notmuch-search-mode-map "d"
        (lambda ()
          "toggle deleted tag for thread"
          (if (member "deleted" (notmuch-search-get-tags))
              (notmuch-search-tag '("-deleted"))
            (notmuch-search-tag '("+deleted" "-inbox" "-unread")))))
      (define-key notmuch-search-mode-map "!"
        (lambda ()
          "toggle unread tag for thread"
          (if (member "unread" (notmuch-search-get-tags))
              (notmuch-search-tag '("-unread"))
            (notmuch-search-tag '("+unread")))))
      ;; Show shortcuts
      (define-key notmuch-show-mode-map "\C-c\C-o" 'browse-url-at-point)
      (define-key notmuch-show-mode-map "d"
        (lambda ()
          "toggle deleted tag for message"
          (if (member "deleted" (notmuch-show-get-tags))
              (notmuch-show-tag '("-deleted"))
            (notmuch-show-tag '("+deleted" "-inbox" "-unread")))))
      (global-set-key (kbd "<f2>") 'notmuch))
  2. Welcome
    1. Use-package start
      (use-package notmuch-hello
        :defer t
        (setq notmuch-hello-thousands-separator "." ;; Add a thousand separator
              notmuch-column-control 1.0) ;; don't display columns
    2. Saved searches
          ;; Research
          (setq notmuch-saved-searches '(
                                         ;; Quick helpers
                                         (:key "u" :name "unread" :query "tag:unread")
                                         (:key "t" :name "today" :query "date:today")
                                         (:key "f" :name "flagged" :query "tag:flagged")
                                         (:key "D" :name "Deleted" :query "tag:deleted")
                                         ;; Classic box
                                         (:key "i" :name "inbox" :query "tag:inbox")
                                         (:key "e" :name "sent" :query "tag:sent")
                                         (:key "d" :name "drafts" :query "tag:draft")
                                         ;; Folder
                                         (:key "p" :name "Saarland inbox" :query "folder:Saarland/INBOX")
                                         (:key "s" :name "SebGmail inbox" :query "folder:SebGmail/INBOX")
        (defun my-count-query (query)
            (insert query "\n")
            (unless (= (call-process-region (point-min) (point-max) notmuch-command
                                            t t nil "count" "--batch") 0)
              (notmuch-logged-error "notmuch count --batch failed"
                                    "Please check that the notmuch CLI is new enough to support `count
      --batch'. In general we recommend running matching versions of
      the CLI and emacs interface."))
            (goto-char (point-min))
            (let ((n (read (current-buffer))))
              (if (= n 0)
                (notmuch-hello-nice-number n)))))
        (defun my-notmuch-hello-query-insert (cnt query elem)
          (if cnt
              (let* ((str (format "%s" cnt))
                     (widget-push-button-prefix "")
                     (widget-push-button-suffix "")
                     (oldest-first (case (plist-get elem :sort-order)
                                     (newest-first nil)
                                     (oldest-first t)
                                     (otherwise notmuch-search-oldest-first))))
                (widget-create 'push-button
                               :notify #'notmuch-hello-widget-search
                               :notmuch-search-terms query
                               :notmuch-search-oldest-first oldest-first
                               :notmuch-search-type 'tree
                (widget-insert (make-string (- 8 (length str)) ? )))
            (widget-insert "        ")))
        (defun my-notmuch-hello-insert-searches ()
          "Insert the saved-searches section."
          (widget-insert (propertize "New     Total      Key  List\n" 'face 'my-notmuch-hello-header-face))
          (mapc (lambda (elem)
                  (when elem
                    (let* ((q_tot (plist-get elem :query))
                           (q_new (concat q_tot " AND tag:unread"))
                           (n_tot (my-count-query q_tot))
                           (n_new (my-count-query q_new)))
                      (my-notmuch-hello-query-insert n_new q_new elem)
                      (my-notmuch-hello-query-insert n_tot q_tot elem)
                      (widget-insert "   ")
                      (widget-insert (plist-get elem :key))
                      (widget-insert "    ")
                      (widget-insert (plist-get elem :name))
                      (widget-insert "\n"))))
    3. Recent searches
      (defun my-notmuch-hello-insert-recent-searches ()
        "Insert recent searches."
        (when notmuch-search-history
          (widget-insert "Recent searches:")
          (widget-insert "\n\n")
          (let ((start (point)))
            (loop for i from 1 to notmuch-hello-recent-searches-max
                  for search in notmuch-search-history do
                  (let ((widget-symbol (intern (format "notmuch-hello-search-%d" i))))
                    (set widget-symbol
                         (widget-create 'editable-field
                                        ;; Don't let the search boxes be
                                        ;; less than 8 characters wide.
                                        :size (max 8
                                                   (- (window-width)
                                                      ;; Leave some space
                                                      ;; at the start and
                                                      ;; end of the
                                                      ;; boxes.
                                                      (* 2 notmuch-hello-indent)
                                                      ;; 1 for the space
                                                      ;; before the `[del]'
                                                      ;; button. 5 for the
                                                      ;; `[del]' button.
                                                      1 5))
                                        :action (lambda (widget &rest ignore)
                                                  (notmuch-hello-search (widget-value widget)))
                    (widget-insert " ")
                    (widget-create 'push-button
                                   :notify (lambda (widget &rest ignore)
                                             (when (y-or-n-p "Are you sure you want to delete this search? ")
                                               (notmuch-hello-delete-search-from-history widget)))
                                   :notmuch-saved-search-widget widget-symbol
                  (widget-insert "\n"))
            (indent-rigidly start (point) notmuch-hello-indent))
    4. Header
      (defface my-notmuch-hello-header-face
        '((t :foreground "white"
             :background "#0088FC"
             :weight bold))
        "Font for the header in `my-notmuch-hello-insert-searches`."
        :group 'notmuch-faces)
    5. Generate welcome page
      (defun my-notmuch-hello-insert-separator ()
        (insert "\n\f\n"))
      ;; We add items later in reverse order with (add-to-list ...):
      (setq notmuch-hello-sections '())
      (add-to-list 'notmuch-hello-sections 'my-notmuch-hello-insert-recent-searches)
      (add-to-list 'notmuch-hello-sections 'my-notmuch-hello-insert-searches)
      ;; (add-to-list 'notmuch-hello-sections 'my-notmuch-hello-insert-separator)
      ;; (add-to-list 'notmuch-hello-sections 'notmuch-hello-insert-search)
      ;;(add-to-list 'notmuch-hello-sections 'my-notmuch-hello-insert-header)
      ;; this is the end of use-package notmuch:
      (add-hook 'notmuch-hello-refresh-hook
                (lambda ()
                  (whitespace-mode -1)
    6. End of use-package
  3. Notification
    (use-package sauron-notmuch
      :ensure quelpa
      :quelpa (sauron-notmuch :repo "seblemaguer/sauron-notmuch" :fetcher github)
      :after (sauron notmuch)
      ;; Define an important filter
      ;; (setq sauron-notmuch-important-filter "....")
      ;; Start
  4. Integration with org-mode
    (use-package org-notmuch)
  5. Reply/citation
    (use-package notmuch-mua
      :defer t
      (setq notmuch-mua-cite-function #'message-cite-original-without-signature)
  6. Interactive search
    (use-package counsel-notmuch :ensure t)

15.5 RSS

15.5.1 Global

(use-package elfeed
  :ensure t

  ;; Change the storage directory
  (setq elfeed-db-directory "~/Dropbox/emacs/elfeed")

  ;; Formatting dates
  (setq elfeed-search-date-format '("%Y-%m-%d %H:%M" 17 :left))

  ;; Hook
  (add-hook 'elfeed-new-entry-hook
            (elfeed-make-tagger :before "7 days ago"
                                :remove 'unread))

  ;; Shortcuts
  (global-set-key (kbd "<f9>")
                  (lambda ()
                    (elfeed-search-set-filter "+unread")
  (global-set-key (kbd "C-<f9>")
                  (lambda ()
                    (elfeed-search-set-filter "+unread +mustread")
  (global-set-key (kbd "S-<f9>")
                  (lambda ()
                    (elfeed-search-set-filter "+unread +emacs")

15.5.2 Org connection

(use-package elfeed-org
  :ensure t
  :after elfeed
  (when (file-exists-p "~/Dropbox/org/organisation/rss.org")
      (setq rmh-elfeed-org-files (list "~/Dropbox/org/organisation/rss.org"))
      (rmh-elfeed-org-process rmh-elfeed-org-files rmh-elfeed-org-tree-id)))


15.5.3 Youtube specificities

(use-package youtube-dl
  :ensure quelpa
  :quelpa (youtube-dl :repo "skeeto/youtube-dl-emacs" :fetcher github)
  :defer t
  :bind ("C-x y" . youtube-dl-list)
  (setq youtube-dl-directory "~/netshare")

  ;; FIXME: should be moved !
  (defun expose (function &rest args)
  "Return an interactive version of FUNCTION, 'exposing' it to the user."
  (lambda ()
    (apply function args)))

  (defun elfeed-show-youtube-dl ()
    "Download the current entry with youtube-dl."
    (pop-to-buffer (youtube-dl (elfeed-entry-link elfeed-show-entry))))

  (cl-defun elfeed-search-youtube-dl (&key slow)
    "Download the current entry with youtube-dl."
    (let ((entries (elfeed-search-selected)))
      (dolist (entry entries)
        (if (null (youtube-dl (elfeed-entry-link entry)
                              :title (elfeed-entry-title entry)
                              :slow slow))
            (message "Entry is not a YouTube link!")
          (message "Downloading %s" (elfeed-entry-title entry)))
        (elfeed-untag entry 'unread)
        (elfeed-search-update-entry entry)
        (unless (use-region-p) (forward-line)))))

  (defalias 'elfeed-search-youtube-dl-slow
    (expose #'elfeed-search-youtube-dl :slow t))

  (define-key elfeed-show-mode-map "d" 'elfeed-show-youtube-dl)
  (define-key elfeed-search-mode-map "d" 'elfeed-search-youtube-dl)
  (define-key elfeed-search-mode-map "D" 'elfeed-search-youtube-dl-slow)
  (define-key elfeed-search-mode-map "L" 'youtube-dl-list))

15.5.4 Notification part

(use-package sauron
  :ensure t
  (require 'sauron-elfeed)
  (cl-loop for feed in elfeed-feeds
           do (when (member 'mustread (cdr feed))
                (puthash (car feed) 3 sauron-elfeed-prio-hash))))

15.5.5 Helpers

(defun elfeed-mark-all-as-read ()

15.6 Stackexchange

(use-package sx
  :ensure t
  (bind-keys :prefix "C-c s"
             :prefix-map my-sx-map
             :prefix-docstring "Global keymap for SX."
             ("q" . sx-tab-all-questions)
             ("i" . sx-inbox)
             ("o" . sx-open-link)
             ("u" . sx-tab-unanswered-my-tags)
             ("a" . sx-ask)
             ("s" . sx-search)))

15.7 Reddit

(use-package md4rd
  :ensure t
  (defhydra md4rd-hydra (:color blue :hint none)
      _o_: open   _u_: upvote       _e_: expand all     _t_: toggle line
                _d_: downvote     _c_: collapse all
      ("u" md4rd-upvote)
      ("d" md4rd-downvote)
      ("o" md4rd-open)
      ("t" md4rd-widget-toggle-line)
      ("e" md4rd-widget-expand-all)
      ("c" md4rd-widget-collapse-all))

  :bind (:map md4rd-mode-map
              ("u" . md4rd-upvote)
              ("d" . md4rd-downvote)
              ("o" . md4rd-open)
              ("t" . md4rd-widget-toggle-line)
              ("e" . md4rd-widget-expand-all)
              ("c" . md4rd-widget-collapse-all)
              ("TAB" . widget-forward)
              ("<backtab>" . widget-backward)
              ("/" . md4rd-hydra/body))

  (setq md4rd-subs-active '(lisp+Common_Lisp emacs)))

15.8 github

(defun gh-issue-new-url (project title body)
  "Generate the github url based on the PROJECT for the base and as the parameters TITLE and BODY"
  (concat "https://github.com/"
          (url-hexify-string title)
          (url-hexify-string body)))

(defun gh-issue-new-browse (project title body)
  "Open the browser at the issue page"
  (browse-url (gh-issue-new-url project title body)))

(defun gh-issue-get-project ()
  "Get the project name based on the GH-PROJECT property"
  (org-entry-get (point) "GH-PROJECT" t))

(defun gh-issue-create ()
  "Create an issue based on the current entry of the org tree"
  (gh-issue-new-browse (gh-issue-get-project)
                       (org-get-heading t t)
                       (org-export-as 'gfm t)))

16 Music

16.1 Global

(use-package emms
  :ensure t


  ;; A minor macos adaptation
  (when (eq system-type 'darwin)
    (setq emms-source-file-gnu-find "/usr/local/bin/gfind"))

  ;; Some behaviour definition
  (setq later-do-interval 0.0001
        emms-directory "~/.emacs.d/emms"
        emms-playlist-buffer-name "*Music*"
        emms-source-file-default-directory (expand-file-name "~/Music")
        emms-source-file-directory-tree-function 'emms-source-file-directory-tree-find
        emms-show-format "NP: %s"
        emms-playlist-default-major-mode 'emms-playlist-mode
        emms-repeat-playlist t
        emms-mode-line-mode-line-function nil  ;; Don't want any info in the mode line
        emms-mode-line-titlebar-function 'emms-mode-line-playlist-current) ;; Put info in the titlebar

  ;; Define a list of radio/streams/...
  (add-to-list 'emms-stream-default-list '("Classic rock radio" "http://internetradio.salue.de:8000/classicrock.mp3" 1 url))

  ;; Visualisation activation/deactivation
  (emms-mode-line nil)
  ;; (emms-playing-time-disable-display)

  ;; Enable cache
  (when (fboundp 'emms-cache)
    (emms-cache 1))

  ;; Adapt track description format
  (defun track-description (track)
    "Return a description of the current TRACK."
    (if (and (emms-track-get track 'info-artist)
             (emms-track-get track 'info-title))
        (let ((pmin (emms-track-get track 'info-playing-time-min))
              (psec (emms-track-get track 'info-playing-time-sec))
              (ptot (emms-track-get track 'info-playing-time))
              (art  (emms-track-get track 'info-artist))
              (tit  (emms-track-get track 'info-title))
              (alb  (emms-track-get track 'info-album)))
          (cond ((and pmin psec) (format "%s - %s - %s [%02d:%02d]" art alb tit pmin psec))
                (ptot (format  "%s - %s - %s [%02d:%02d]" art alb tit (/ ptot 60) (% ptot 60)))
                (t (emms-track-simple-description track))))
      (emms-track-simple-description track)))
  (setq emms-track-description-function 'track-description)

  ;; Show the progress bar when seek (FIXME: is not working have to correct)
  ;; taken from http://emacs.stackexchange.com/questions/21747/emms-how-can-i-have-a-progress-bar?rq=1
  (defun chunyang-emms-indicate-seek (_sec)
    (let* ((total-playing-time (emms-track-get
           (elapsed/total (/ (* 100 emms-playing-time) total-playing-time)))
      (with-temp-message (format "[%-100s] %2d%%"
                                 (make-string elapsed/total ?=)
        (sit-for 2))))
  (add-hook 'emms-player-seeked-functions #'chunyang-emms-indicate-seek 'append)

  ;; Some shortcuts
  (global-set-key (kbd "<f5>") 'emms-browse-by-artist)
  (global-set-key (kbd "S-<f5>") 'emms-playlist-mode-go))

(use-package emms-info-libtag
  :after emms

  (setq emms-info-asynchronously nil
        emms-info-functions '(emms-info-libtag)))

16.2 MPV as a player

(use-package emms-player-simple-mpv
  :ensure t
  :after emms

  ;; Subpackages
  (use-package emms-player-simple-mpv-e.g.time-display)
  (use-package emms-player-simple-mpv-e.g.playlist-fname)
  (use-package emms-player-simple-mpv-e.g.hydra)
  (use-package emms-player-simple-mpv)
  (use-package emms-player-simple-mpv-control-functions)

  (define-emms-simple-player-mpv my-mpv '(file url streamlist playlist)
    (concat "\\`\\(http[s]?\\|mms\\)://\\|"
            (apply #'emms-player-simple-regexp
                   "aac" "pls" "m3u"
    "mpv" "--no-terminal" "--force-window=no" "--audio-display=no")

   'emms-player-my-mpv "." '(playlist)
   (lambda (track-name) (format "--playlist=%s" track-name)))

  (add-to-list 'emms-player-list 'emms-player-my-mpv))

16.3 Tagging using emms

I actually use this part for minor correction. The tags are done when abcde is converting the cd

(use-package emms-mark-ext :ensure t)

16.4 Browser

(use-package emms-browser
  :after emms
   "all-files" (emms-browser-filter-only-type 'file))
  (add-hook 'emms-browser-show-display-hook '(lambda () (hl-line-mode 1)))

  (setq emms-browser-info-artist-format "%i☢ %n"
        emms-browser-info-album-format "%i%cS [%y] %n"
        emms-browser-info-title-format "%i♪ %T. %t [%d]"
        emms-browser-playlist-info-album-format "%cS %a - %A : "
        emms-browser-playlist-info-title-format "%T. %t [%d]"))

17 Weather

(use-package wttrin
  :ensure t
  :commands (wttrin)
  (setq wttrin-default-cities '("Saarbrücken" "Lannion" "Sofia")))

18 Visual

18.1 Global theme

(use-package meacupla-theme
  :ensure quelpa
  :quelpa (meacupla-theme :repo "seblemaguer/meacupla-theme" :fetcher gitlab)
  (load-theme 'meacupla t))

18.2 Frame part

18.2.1 Title

(defun frame-title-format ()
  "Return frame title with current project name, where applicable."
  (let ((file buffer-file-name))
    (if file
        (if (and (bound-and-true-p projectile-mode)
             (format "[%s] " (projectile-project-name))
             (replace-regexp-in-string (format "^%s" (projectile-project-p)) "" (file-truename file)))
          (abbreviate-file-name file))

(when (display-graphic-p)
  (setq frame-title-format '((:eval (frame-title-format)))))

18.2.2 Remove unused part

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

18.3 Buffer

18.3.1 Org-mode

  1. Faces
    (use-package org
      :ensure t
      (setq org-todo-keyword-faces
            '(("TODO" :background "red1" :foreground "black" :weight bold :box (:line-width 2 :style released-button))
              ("REVIEW" :background "orange" :foreground "black" :weight bold :box (:line-width 2 :style released-button))
              ("NEXT" :background "red1" :foreground "black" :weight bold :box (:line-width 2 :style released-button))
              ("STARTED" :background "orange" :foreground "black" :weight bold :box (:line-width 2 :style released-button))
              ("WAITING" :background "yellow" :foreground "black" :weight bold :box (:line-width 2 :style released-button))
              ("DEFERRED" :background "gold" :foreground "black" :weight bold :box (:line-width 2 :style released-button))
              ("DELEGATED" :background "gold" :foreground "black" :weight bold :box (:line-width 2 :style released-button))
              ("MAYBE" :background "gray" :foreground "black" :weight bold :box (:line-width 2 :style released-button))
              ("DONE" :background "forest green" :weight bold :box (:line-width 2 :style released-button))
              ("CANCELLED" :background "lime green" :foreground "black" :weight bold :box (:line-width 2 :style released-button)))
              org-priority-faces '((?A . (:foreground "red" :weight bold))
                                   (?B . (:foreground "orange"  :weight bold))
                                   (?C . (:foreground "orange"))
                                   (?D . (:foreground "forest green"))
                                   (?E . (:foreground "forest green")))))
  2. Org-bullets
    (use-package org-bullets
      :ensure t
      (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))
  3. Fancy priority
    (use-package org-fancy-priorities
      :ensure t
      (add-hook 'org-agenda-mode-hook 'org-fancy-priorities-mode)
      (add-hook 'org-mode-hook 'org-fancy-priorities-mode)
      (setq org-fancy-priorities-list
            '((?A . "❗") (?B . "⬆") (?C . "⬇") (?D . "☕")
              (?1 . "⚡") (?2 . "⮬") (?3 . "⮮") (?4 . "☕")
              (?I . "Imaportant"))))

18.3.2 Highlight

(use-package volatile-highlights
  :ensure t
  (volatile-highlights-mode t))

(use-package hl-line+
  :ensure t
  (setq font-lock-maximum-decoration t)
  (setq font-lock-maximum-size nil)
  (global-font-lock-mode t)
  (transient-mark-mode t))

18.3.3 Indentation

(use-package indent-guide
  :ensure t
  :defer t)

18.3.4 Column/line

(use-package nlinum
  :ensure t
  :disabled t
  (line-number-mode t)
  (column-number-mode t)
  (global-nlinum-mode t)
  (size-indication-mode t))

(use-package nlinum-hl
  :ensure t
  :after nlinum
  :disabled t
  (add-hook 'nlinum-mode-hook (lambda () (setq nlinum-highlight-current-line t))))

(use-package fill-column-indicator
  :ensure t

  ;; Define a global mode but not sure I am going to use it
    global-fci-mode fci-mode
    (lambda ()
      (fci-mode 1))))

18.3.5 Paging

(use-package page-break-lines
  :ensure t
  :diminish page-break-lines-mode
  (global-page-break-lines-mode t))

18.3.6 Parenthesis

  1. Smart parents
    (use-package smartparens
      :ensure t
      :after circe
      ;; Activate smartparens globally
      (smartparens-global-mode t)
      (show-smartparens-global-mode t)
      ;; Activate smartparens in minibuffer
      (add-hook 'eval-expression-minibuffer-setup-hook #'smartparens-mode)
      ;; Do not pair simple quotes
      (sp-pair "'" nil :actions :rem))
  2. Rainbow delimiter
    (use-package rainbow-delimiters
      :ensure t
       '(rainbow-delimiters-mismatched-face ((t (:foreground "white" :background "red" :weight bold))))
       '(rainbow-delimiters-unmatched-face ((t (:foreground "white" :background "red" :weight bold))))
       ;; show parents (in case of rainbow failing !)
       '(show-paren-match ((t (:foreground "white" :background "green" :weight bold))))
       '(show-paren-mismatch ((t (:foreground "white" :background "red" :weight bold))))
      (add-hook 'prog-mode-hook #'rainbow-delimiters-mode))

18.3.7 Show current function

(which-func-mode 1)

18.3.8 Diff

(use-package diff-hl
  :ensure t
  (fringe-mode 10))

18.3.9 Faces/Colors

  1. Dired (using dired-rainbow)
    (use-package dired-rainbow
      :ensure t
      :defer t
      (eval-after-load 'dired '(require 'dired-rainbow))
      (defconst dired-audio-files-extensions
        '("mp3" "MP3" "ogg" "OGG" "flac" "FLAC" "wav" "WAV")
        "Dired Audio files extensions")
      (dired-rainbow-define audio "#329EE8" dired-audio-files-extensions)
      (defconst dired-video-files-extensions
        '("vob" "VOB" "mkv" "MKV" "mpe" "mpg" "MPG" "mp4" "MP4" "ts" "TS" "m2ts"
          "M2TS" "avi" "AVI" "mov" "MOV" "wmv" "asf" "m2v" "m4v" "mpeg" "MPEG" "tp")
        "Dired Video files extensions")
      (dired-rainbow-define video "#455AFC" dired-video-files-extensions)
      (dired-rainbow-define html "#4e9a06" ("htm" "html" "xhtml"))
      (dired-rainbow-define xml "DarkGreen" ("xml" "xsd" "xsl" "xslt" "wsdl"))
      (dired-rainbow-define document "#ce5c00" ("doc" "docx" "odt" "pdb" "pdf" "ps" "rtf" "djvu"))
      (dired-rainbow-define image "#ff4b4b" ("jpg" "png" "jpeg" "gif"))
      (dired-rainbow-define sourcefile "#3F82FD" ("el" "groovy" "gradle" "py" "c" "cc" "h" "java" "pl" "rb"))
      (dired-rainbow-define executable "#8cc4ff" ("exe" "msi"))
      (dired-rainbow-define compressed "#ad7fa8" ("zip" "bz2" "tgz" "txz" "gz" "xz" "z" "Z" "jar" "war" "ear" "rar" "sar" "xpi" "apk" "xz" "tar"))
      (dired-rainbow-define packaged "#e6a8df" ("deb" "rpm"))
      (dired-rainbow-define encrypted "LightBlue" ("gpg" "pgp"))
      (dired-rainbow-define-chmod executable-unix "Green" "-.*x.*")
      (dired-rainbow-define log (:inherit default :italic t) ".*\\.log")
  2. Elfeed
    (use-package elfeed
      ;; Adapt the faces
      (defface elfeed-must-read-face
        '((((class color) (background light)) (:foreground "#f00"))
          (((class color) (background dark))  (:foreground "#f00")))
        "Face used in search mode for titles."
        :group 'elfeed)
      (defface elfeed-emacs-face
        '((((class color) (background light)) (:foreground "#090"))
          (((class color) (background dark))  (:foreground "#090")))
        "Face used in search mode for titles."
        :group 'elfeed)
      (defface elfeed-news-face
        '((((class color) (background light)) (:foreground "#AAA"))
          (((class color) (background dark))  (:foreground "#AAA")))
        "Face used in search mode for titles."
        :group 'elfeed)
      (setq elfeed-search-face-alist
            '((unread elfeed-search-unread-title-face)
              (mustread elfeed-must-read-face)
              (news elfeed-news-face)
              (emacs elfeed-emacs-face)))
    (use-package youtube-dl
      (defface elfeed-youtube
        '((t :foreground "#f9f"))
        "Marks YouTube videos in Elfeed."
        :group 'elfeed)
      (push '(youtube elfeed-youtube) elfeed-search-face-alist))

18.3.10 Emoji

(use-package emojify
  :ensure t

  (use-package company-emoji
    :ensure t)

  (setq emojify-user-emojis
        '(("(heart)" . (("name" . "Heart")
                        ("image" . "~/.emacs.d/emojis/emojione-v2.2.6-22/2665.png")
                        ("style" . "github")))))

  ;; If emojify is already loaded refresh emoji data
  (when (featurep 'emojify)

(use-package flycheck-status-emoji
  :ensure t
  :after emojify)

18.3.11 Specific mode cleaning helper

(defun disable-global-facilities ()
  "Function to disable some utilities globally activated for current buffer"
  (smartparens-mode 0)
  ;; (nlinum-mode 0)

18.4 Icons

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

18.5 Fonts

(defun set-icon-fonts (CODE-FONT-ALIST)
  "Utility to associate many unicode points with specified fonts."
    (-let (((font . codes) it))
      (--each codes
        (set-fontset-font t `(,it . ,it) font)))))

(defun load-default-fonts ()

  (set-fontset-font "fontset-default" 'unicode "Dejavu Sans Mono")
  (set-face-font 'default "Inconsolata-11")

  ;; The icons you see are not the correct icons until this is evaluated!
      ;;                         
      #xf07c #xf0c9 #xf0c4 #xf0cb #xf017 #xf101)

      ;;    
      #xe907 #xe928)

      ;;                        
      #xf091 #xf059 #xf076 #xf075 #xf016 #xf00a)

      ;; 𝕊    ⨂      ∅      ⟻    ⟼     ⊙      𝕋       𝔽
      #x1d54a #x2a02 #x2205 #x27fb #x27fc #x2299 #x1d54b #x1d53d
      ;; 𝔹    𝔇       𝔗
      #x1d539 #x1d507 #x1d517))))

(defun load-fonts (frame)
  (select-frame frame)

(if (daemonp)
    (add-hook 'after-make-frame-functions #'load-fonts)

18.6 Mode line - spaceline

(use-package fancy-battery :ensure t)
(use-package spaceline-config :ensure spaceline)

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

  ;; Separator configuration
  (setq spaceline-all-the-icons-separator-type 'wave
        spaceline-separator-dir-left '(left . left)
        spaceline-separator-dir-right '(right . right)
        spaceline-minor-modes-separator " ")

  ;;Other configuration
  (setq spaceline-all-the-icons-icon-set-flycheck-slim 'dots
        spaceline-all-the-icons-icon-set-git-ahead 'commit
        spaceline-all-the-icons-flycheck-alternate t
        spaceline-all-the-icons-highlight-file-name t
        spaceline-highlight-face-func 'spaceline-highlight-face-modified)

  ;; Change this ugly orange color
  (set-face-attribute 'spaceline-unmodified nil :background "LightSkyBlue")

  ;; Info

  ;; Battery
  (add-hook 'after-init-hook #'fancy-battery-mode)
  (display-battery-mode -1)

  ;; Reduce projectile account
  (setq projectile-mode-line " P")



  ;; EMMS part
  (spaceline-define-segment all-the-icons-track
    "Show the current played track."

  ;; Circe specific part
  (spaceline-define-segment circe-track
    "Show the circe buffers with new messages. Requires `circe-track-mode' to be enabled."
    (if tracking-buffers
        (s-join " " (tracking-shorten tracking-buffers))))

  ;; Redfine linenum for pdf-view mode compatibility
  (spaceline-define-segment line-column
    "The current line and column numbers."
    (if (eq major-mode 'pdf-view-mode)
        (concat (number-to-string (pdf-view-current-page))
                (number-to-string (pdf-cache-number-of-pages)))

  ;; Redefine battery segment to add percentage

(spaceline-define-segment all-the-icons-battery-status
  "An `all-the-icons' segment to show the battery information"
  (let* ((charging?  (string= "AC" (cdr (assoc ?L fancy-battery-last-status))))
         (percent    (string-to-number (cdr (assoc ?p fancy-battery-last-status))))
         (time       (cdr (assoc ?t fancy-battery-last-status)))

           (charging? '((icon . "charging") (inherit . fancy-battery-charging) (height . 1.3) (raise . 0.0)))
           ((> percent 95) '((icon . "full") (inherit . fancy-battery-charging)))
           ((> percent 70) '((icon . "three-quarters")))
           ((> percent 30) '((icon . "half")))
           ((> percent 15) '((icon . "quarter") (inherit . fancy-battery-discharging)))
           (t '((icon . "empty") (inherit . fancy-battery-critical)))))

         (icon-set (if charging? 'alltheicon 'faicon))
         (icon-f   (all-the-icons--function-name icon-set))
         (family-f (all-the-icons--family-name icon-set))

         (icon-face `(:family ,(funcall family-f) :background ,(spaceline-all-the-icons--face-background default-face)))
         (text-face `(:height ,(spaceline-all-the-icons--height 0.9) :background ,(spaceline-all-the-icons--face-background default-face))))

    (let-alist icon-alist
      (setq icon-face (append `(:height ,(spaceline-all-the-icons--height (when .height .height))) icon-face))
      (if (not .inherit)
          (setq icon-face (append icon-face '(:inherit))
                text-face (append text-face '(:inherit)))
        (setq icon-face (append icon-face `(:inherit ,(macroexpand .inherit)))
              text-face (append text-face `(:inherit ,(macroexpand .inherit)))))

        (propertize (funcall icon-f (format "battery-%s" .icon))
                    'face icon-face
                    'display `(raise ,(or .raise 0.0)))
        (propertize (cond
                     (spaceline-all-the-icons-slim-render "")
                     (charging? (format " %s%%%% " percent))
                     (t (concat " " time " (" (format "%2d" percent) "%%" ")")))
                    'face text-face
                    'display '(raise 0.1)))
       'help-echo `(format "%s Remaining" ,time)
       'mouse-face (spaceline-all-the-icons--highlight))))

  :global-override fancy-battery-mode-line
  :when (and active (bound-and-true-p fancy-battery-mode)))

  ;; Redine the mode-line theme
  (defun spaceline-all-the-icons-theme (&rest additional-segments)
    "Install the `spaceline-ml-all-the-icons'.
Add ADDITIONAL-SEGMENTS to the end of the theme."
        ;; Azu
         :face mode-line
         :skip-alternate t)

        ;; Buffer information
         :face highlight-face
         :skip-alternate t

         :separator (spaceline-all-the-icons--separator spaceline-all-the-icons-secondary-separator " "))


        ;; Projectile / major mode
            all-the-icons-buffer-id) :separator ""))
         :face default-face)


        ;; ???
         :face highlight-face
         :separator (spaceline-all-the-icons--separator spaceline-all-the-icons-primary-separator " "))


        ;; VC/check/update informations
            all-the-icons-git-status) :separator " ")
            all-the-icons-flycheck-status-info) :separator " ")
         :face other-face
         :separator (spaceline-all-the-icons--separator spaceline-all-the-icons-secondary-separator " "))

        ;; Minor modes
         :tight t
         :face highlight-face
         :when spaceline-all-the-icons-minor-modes-p)

        ;; Which function
         :face powerline-active2
         :separator ""))

      `(((,@additional-segments) :when active :face powerline-active2)
        ((,@additional-segments) :when (not active) :face powerline-inactive2)

        ;; Wweather
         :face powerline-active2
         :separator (spaceline-all-the-icons--separator spaceline-all-the-icons-secondary-separator " "))

        ;; Music info
         :face powerline-active2)

         :separator " " :when active)


        ;; Time info
         :separator (spaceline-all-the-icons--separator spaceline-all-the-icons-primary-separator " ")
         :face default-face)))

    (setq-default mode-line-format spaceline-all-the-icons-theme))

  ;; Loading
  (spaceline-all-the-icons-theme 'circe-track))

19 Keys/shortcuts

19.1 Mac adaptation

(setq mac-option-modifier nil
      mac-command-modifier 'meta)

19.2 Main entry

  (defhydra hydra-main (:color teal :hint nil)
 Main helper

  Org. related          Help                Zooming        bookmarks          other helpers     completion
  _c_: org-capture        _f_: function doc.    _+_: zoom in     _B_: list bookmarks  _p_: prodigy        _y_: ivy-yasnippet
  _g_: org-web-get-url    _v_: variable doc.    _-_: zoom out    _b_: bookmark file   _m_: new mail

  _s_: list backups
  _S_: snapshot timemachine
    ("b" bookmark-set)
    ("B" list-bookmarks)
    ("c" org-capture)
    ("f" describe-function)
    ("g" org-web-tools-read-url-as-org)
    ("m" notmuch-mua-new-mail)
    ("p" prodigy)
    ("s" snapshot-timeline)
    ("S" snapshot-timemachine)
    ("v" describe-variable)
    ("y" ivy-yasnippet)
    ("+" text-scale-increase :color pink)
    ("-" text-scale-decrease :color pink)
    ("<ESC>" nil "quit" :color blue)
    ("q"   nil "cancel" :color blue))

  (global-set-key (kbd "<f1>") 'hydra-main/body)

19.3 Project/Version control

(defhydra hydra-projectile-other-window (:color teal)
  ("f"  projectile-find-file-other-window        "file")
  ("g"  projectile-find-file-dwim-other-window   "file dwim")
  ("d"  projectile-find-dir-other-window         "dir")
  ("b"  projectile-switch-to-buffer-other-window "buffer")
  ("q"  nil                                      "cancel" :color blue))

(defhydra hydra-projectile (:color teal :hint nil)
     PROJECTILE: %(projectile-project-root)

     Find File            Search/Tags          Buffers                Cache
_s-f_: file            _a_: ag                _i_: Ibuffer           _c_: cache clear
 _ff_: file dwim       _g_: update gtags      _b_: switch to buffer  _x_: remove known project
 _fd_: file curr dir   _o_: multi-occur     _s-k_: Kill all buffers  _X_: cleanup non-existing
  _r_: recent file                                               ^^^^_z_: cache current
  _d_: dir

  ("<ESC>" nil "quit")
  ("<" hydra-project/body "back")
  ("a"   projectile-ag)
  ("b"   projectile-switch-to-buffer)
  ("c"   projectile-invalidate-cache)
  ("d"   projectile-find-dir)
  ("s-f" projectile-find-file)
  ("ff"  projectile-find-file-dwim)
  ("fd"  projectile-find-file-in-directory)
  ("g"   ggtags-update-tags)
  ("s-g" ggtags-update-tags)
  ("i"   projectile-ibuffer)
  ("K"   projectile-kill-buffers)
  ("s-k" projectile-kill-buffers)
  ("m"   projectile-multi-occur)
  ("o"   projectile-multi-occur)
  ("s-p" projectile-switch-project "switch project")
  ("p"   projectile-switch-project)
  ("s"   projectile-switch-project)
  ("r"   projectile-recentf)
  ("x"   projectile-remove-known-project)
  ("X"   projectile-cleanup-known-projects)
  ("z"   projectile-cache-current-file)
  ("`"   hydra-projectile-other-window/body "other window" :color blue)
  ("q"   nil "cancel" :color blue))

(defhydra hydra-magit (:color teal :hint nil)
      Magit: %(magit-get \"remote\" \"origin\" \"url\")

 Status/Info      Remote          Operations
_s_: Status      _f_: Pull       _c_: commit
_l_: Log all     _p_: Push
_d_: Diff
_t_: timeline
  ("<ESC>" nil "quit")
  ("<" hydra-project/body "back")
  ("f" magit-pull)
  ("p" magit-push)
  ("c" magit-commit)
  ("d" magit-diff)
  ("l" magit-log-all)
  ("s" magit-status)
  ("t" git-timeline)
  ("q"   nil "cancel" :color blue))

(defhydra hydra-flycheck (:pre (progn (setq hydra-lv t) (flycheck-list-errors))
                               :post (progn (setq hydra-lv nil) (quit-windows-on "*Flycheck errors*"))
                               :color teal
                               :hint nil)
  ("f"  flycheck-error-list-set-filter                            "Filter")
  ("j"  flycheck-next-error                                       "Next")
  ("k"  flycheck-previous-error                                   "Previous")
  ("gg" flycheck-first-error                                      "First")
  ("G"  (progn (goto-char (point-max)) (flycheck-previous-error)) "Last")
  ("<" hydra-project/body "back")
  ("q"   nil "cancel" :color blue))

(defhydra hydra-project (:color teal :hint nil)
     Project/Source management

 Projects              Version control        On-the-fly
_d_: dash projects     _m_: magit             _f_: fixme listing
_p_: projectile        _t_: travis status     _F_: flycheck

  ("<ESC>" nil "quit")
  ("d"   org-dashboard-display)
  ("p"   hydra-projectile/body)
  ("f"   fic-view-listing)
  ("F"   hydra-flycheck/body)
  ("m"   hydra-magit/body)
  ("t"   show-my-travis-projects)
  ("q"   nil "cancel" :color blue))
(global-set-key (kbd "<f4>") 'hydra-project/body)

19.4 Shell/terminal

;; Function coming from here: http://www.howardism.org/Technical/Emacs/eshell-fun.html
(defun eshell-here ()
  "Opens up a new shell in the directory associated with the
current buffer's file. The eshell is renamed to match that
directory to make multiple eshell windows easier."
  (let* ((parent (if (buffer-file-name)
                     (file-name-directory (buffer-file-name))
         (height (/ (window-total-height) 3))
         (name   (car (last (split-string parent "/" t)))))
    (split-window-vertically (- height))
    (other-window 1)
    (if (get-buffer (concat "*eshell: " name "*"))
        (switch-to-buffer (concat "*eshell: " name "*"))
      (progn (eshell "new") (rename-buffer (concat "*eshell: " name "*"))))

(defhydra hydra-shell (:color teal :hint nil)

_p_: start (projectile)
_h_: start (here)
  ("p"      projectile-run-eshell)
  ("h"      eshell-here)
  ("<ESC>"  nil "quit" :color blue)
  ("q"      nil "cancel" :color blue))
(global-set-key (kbd "<f6>") 'hydra-shell/body)

19.5 Global keys

19.5.1 Compilation

(global-set-key (kbd "C-c C-c") 'compile)

(defhydra hydra-next-error (global-map "C-x")
Compilation errors:
_j_: next error        _h_: first error    _q_uit
_k_: previous error    _l_: last error
    ("`" next-error     nil)
    ("j" next-error     nil :bind nil)
    ("k" previous-error nil :bind nil)
    ("h" first-error    nil :bind nil)
    ("l" (condition-case err
             (while t
           (user-error nil))
     nil :bind nil)
    ("q" nil            nil :color blue))

19.5.2 Commenting

(global-set-key (kbd "C-c C-;") 'comment-region)
(global-set-key (kbd "C-c C-:") 'uncomment-region)

19.5.3 Buffers

(global-set-key (kbd "M-g") 'goto-line)
(global-set-key (kbd "M-G") 'what-line)

19.5.4 Windows

(global-set-key (kbd "C-c =") 'compare-windows)

19.5.5 Files

(global-set-key (kbd "C-x C-r") 'counsel-recentf)
(global-set-key (kbd "C-x C-d") 'dired)

(global-set-key [(control c) ?1] 'find-name-dired)
(global-set-key [(control c) ?2] 'find-grep-dired)
(global-set-key [(control c) ?3] 'grep-find)

19.5.6 Multimedia

(global-set-key (kbd "<XF86AudioPlay>") 'emms-pause)
(global-set-key (kbd "<XF86AudioStop>") 'emms-stop)
(global-set-key (kbd "<XF86AudioPrev>") 'emms-previous)
(global-set-key (kbd "<XF86AudioNext>") 'emms-next)

19.5.7 Mac key remapping

(global-set-key (kbd "<end>") 'move-end-of-line)
(global-set-key (kbd "<home>") 'move-beginning-of-line)

20 Finalization

20.1 Startup

(setq inhibit-startup-message t)
(setq find-file-suppress-same-file-warnings t)

20.2 Scratch

(use-package scratch-ext
  :ensure t
  :hook (after-init . scratch-ext-restore-last-scratch)
  ;; Org-mode + start folded buffer
  (setq initial-major-mode 'org-mode)
  (set-buffer (get-buffer-create "*scratch*"))
  (set (make-local-variable 'org-startup-folded) t))

Auteur: Sébastien Le Maguer

Created: 2018-08-24 Fri 13:46