Skip to content

Latest commit

 

History

History
724 lines (719 loc) · 25 KB

config.org

File metadata and controls

724 lines (719 loc) · 25 KB

My confiuration

Table of Content

Introduction

Lexical Binding

Enabling lexical binding improves performance.

;;; init.el --- -*- lexical-binding: t -*-

Private configuration

First of all, we load the private config that you have to set yourself, in your own private.el. You have to set up the user mail address and elfeed feeds.

(load "~/.emacs.d/private.el")

Performance 1

We disable the garbage collector at launch time to improve performances.

(setq gc-cons-threshold most-positive-fixnum
      gc-cons-percentage 0.6)

After startup, we set it back to a 16MB threshold.

(add-hook 'emacs-startup-hook
  (lambda ()
    (setq gc-cons-threshold 16777216
          gc-cons-percentage 0.1)))

Package management

We add the melpa package archive which contains most of emacs packages.

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
(setenv "PATH" (concat (getenv "PATH") (concat (concat ":" (getenv "HOME")) "/go/bin")))

The use-package package provides an easier way to configure and install package, we load it since it’s already installed as a git submodule.

(add-to-list 'load-path "~/.emacs.d/use-package")
(require 'use-package)

Then we tell use-package to check if a package is installed and install it if it’s not unless we told it not to.

(require 'use-package-ensure)
(setq use-package-always-ensure t)

The use-package-ensure-system-package provides a use-package extension to check and install system dependencies.

(use-package use-package-ensure-system-package)

The auto-package-update package provides automatic updates with use-package. We tell it to only update packages after 5 seconds in idle.

(use-package auto-package-update
  :defer 5
  :config
  (setq auto-package-update-delete-old-versions t)
  (setq auto-package-update-hide-results t)
  (auto-package-update-maybe))

Security

First, make emacs verify all TLS connections.

(setq tls-checktrust t
      gnutls-verify-error t)

Then, we give emacs the location of certificates.

(let ((trustfile "/etc/ssl/certs/ca-certificates.crt"))
  (setq tls-program
      `(,(format  "gnutls-cli --x509cafile %s -p %%p %%h" trustfile)
        ,(format "openssl s_client -connect %%h:%%p -CAfile %s -no_ssl2 -ign_eof"
                 trustfile)))
  (setq gnutls-trustfiles (list trustfile)))

Miscellaneous

Switch to utf-8 encoding.

(set-default-coding-systems 'utf-8)

Use y/n prompts instead of yes/no ones.

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

Aesthetic changes

Theme

Install doom themes, enable italic and bold fonts and enable the nord theme. And enable org-mode’s fontification.

(use-package doom-themes
  :config
  (setq doom-themes-enable-bold t
        doom-themes-enable-italic t)
  (load-theme 'doom-nord t)
  (doom-themes-visual-bell-config)
  (doom-themes-org-config))

Bar

The mood-line package provides a doom-modeline inspired bar, based on the original emacs bar. We also add time in the bar.

(use-package mood-line
  :config
  (mood-line-mode)
  (display-time-mode))

Patch

The ‘⚑’ character, used for issues by the bar, doesn’t work well with the font I use. So we use the el-patch package which allows to patch the bar.

(use-package el-patch)

(el-patch-feature mood-line)
(with-eval-after-load 'mood-line
  (el-patch-defun mood-line--update-flycheck-segment (&optional status)
    "Update `mood-line--flycheck-text' against the reported flycheck STATUS."
    (setq mood-line--flycheck-text
        (pcase status
          ('finished (if flycheck-current-errors
                         (let-alist (flycheck-count-errors flycheck-current-errors)
                           (let ((sum (+ (or .error 0) (or .warning 0))))
                             (propertize (concat
                                          (el-patch-swap "⚑ Issues: " "Issues: ")
                                          (number-to-string sum)
                                          "  ")
                                         'face (if .error
                                                   'mood-line-status-error
                                                 'mood-line-status-warning))))
                       (propertize "✔ Good  " 'face 'mood-line-status-success)))
          ('running (propertize "Δ Checking  " 'face 'mood-line-status-info))
          ('errored (propertize "✖ Error  " 'face 'mood-line-status-error))
          ('interrupted (propertize "⏸ Paused  " 'face 'mood-line-status-neutral))
          ('no-checker "")))))

Dashboard

We use the emacs-dashboard package which displays a nice home page with recent files, agenda items and projects.

(use-package dashboard
  :custom
  (dashboard-show-shortcuts nil)
  (dashboard-items '((recents . 20)
                     (agenda . 5)
                     (projects . 8)))
  :config
  (global-page-break-lines-mode)
  (dashboard-setup-startup-hook))

To get dashboard when using emacsclient -c, we need the following line:

(setq initial-buffer-choice (lambda () (get-buffer "*dashboard*")))

Miscellaneous

Font

I like the scientifica font, you can use another font format, however I’ve had problems with this font in other formats.

(set-frame-font
 "-HBnP-scientifica-normal-normal-normal-*-11-*-*-*-*-0-iso10646-1")

However, this won’t work with emacsclient -c so we need this:

(add-to-list 'default-frame-alist
             '(font . "-HBnP-scientifica-normal-normal-normal-*-11-*-*-*-*-0-iso10646-1"))

By default variable-pitch uses a different font.

(custom-set-faces
 '(variable-pitch ((t nil)))
 '(fixed-pitch    ((t nil))))

Redundant UI elements

We disable unuseful UI elements.

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

Line numbers

Enable line numbers in programming modes and org-mode.

(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(add-hook 'org-mode-hook  'display-line-numbers-mode)

Completion

Ivy

The ivy package provides a completion engine. We set a higher minibuffer than default.

(use-package ivy
  :config
  (ivy-mode 1)
  :custom
  (ivy-height 20))

Swiper

The swiper package provides an isearch alternative using ivy.

(use-package swiper 
  :commands (swiper))

Counsel

The counsel package provides alternative commands for emacs builtin ones which uses ivy.

(use-package counsel
  :after (ivy)
  :defer t
  :config
  (counsel-mode 1)
  (setq ivy-initial-inputs-alist nil))

Prescient

We use the prescient completion backend. We activate the persist option which allows history between different emacs sessions.

(use-package prescient
  :after (ivy)
  :config (prescient-persist-mode 1))

We install the ivy backend of prescient.

(use-package ivy-prescient
  :after (ivy prescient)
  :config (ivy-prescient-mode 1))

Programming

Common

Projectile

We use the projectile package to get good project completion and tooling.

(use-package projectile
  :commands (project-find-file)
  :custom
  (projectile-completion-system 'ivy))

Parentheses

We use electric pair mode to get the corresponding delimiters when we type one. For instance ‘(’ will also add a ‘)’.

(electric-pair-mode 1)

We use the rainbow-delimiters package to get matching parentheses and brackets of same colour.

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

Tabulation

Set up the tabulation width and the default style in c.

(setq tab-width 8
      electric-indent-inhibit t
      c-default-style "bsd"
      c-basic-offset tab-width)

Make backspace delete a full tab instead of a space at a time.

(setq backward-delete-char-untabify-method 'hungry)

Only use tabs in c mode, and use spaces in other programming languages.

(add-hook 'emacs-lisp-mode-hook '(lambda () (setq indent-tabs-mode nil)))
(add-hook 'tuareg-mode-hook     '(lambda () (setq indent-tabs-mode nil)))
(add-hook 'org-mode-hook        '(lambda () (setq indent-tabs-mode nil)))
(add-hook 'c-mode-hook          '(lambda () (setq indent-tabs-mode t)))

The smart tabs package allows us to use tabs for code blocks and spaces to align things like tables and arguments, so we enable it in c mode.

(use-package smart-tabs-mode
  :config
  (smart-tabs-insinuate 'c))

Flycheck

The flycheck package provides on the fly syntax cheking. We enable it in all buffers. The hook makes flycheck stop complaining about package presentation when checking a emacs-lisp block from org-mode. We also change the way error are represented, replacing the wave by a straight underline.

(use-package flycheck
  :custom-face
  (flycheck-info    ((t (:underline "#A3BE8C"))))
  (flycheck-error   ((t (:underline "#BF616A"))))
  (flycheck-warning ((t (:underline "#EBCB8B"))))
  :init (global-flycheck-mode)
  :hook
  (org-src-mode . (lambda ()
      (setq-local flycheck-disabled-checkers
                  '(emacs-lisp-checkdoc)))))

Replace flycheck’s default fringe with a bitmap arrow.

(define-fringe-bitmap 'flycheck-error-bmp 
  (vector #b10000000
          #b11000000
          #b11100000
          #b11110000
          #b11100000
          #b11000000
          #b10000000)
  nil nil 'center)
(flycheck-redefine-standard-error-levels nil 'flycheck-error-bmp)

Company

The company package provides in buffer auto-completion. We tell it to start completing from the first character and provide keybindings to move in suggestions without moving from the home row. We activate it in programming modes and in org-mode.

(use-package company
  :hook
  ((prog-mode org-mode) . company-mode)
  :bind
  (:map company-active-map
  ("<tab>" . 'company-complete-selection)
  ("M-l"   . 'company-complete-common)
  ("M-j"   . 'company-select-next)
  ("M-k"   . 'company-select-previous))
  :custom
  (company-idle-delay 0.1)
  (company-minimum-prefix-length 1))

We use the prescient integration with company to get better sorted auto-completion.

(use-package company-prescient
  :after (company prescient)
  :config (company-prescient-mode))

Languages

C

Irony

The irony-mode package provides auto-completion and syntax checking for C/C++ based on libclang. So it needs to be installed using irony-install-server. Of course we only enable it in c mode.

(use-package irony
  :hook
  (c-mode     . irony-mode)
  (irony-mode . irony-cdb-autosetup-compile-options))

To get syntax checking with irony we use the flycheck-irony backend of flycheck which we load after flycheck and irony and enable it when flycheck is enabled.

(use-package flycheck-irony
  :after (flycheck irony)
  :hook (flycheck-mode . flycheck-irony-setup))

To get auto-completion with irony we use the company-irony backend of company.

(use-package company-irony
  :after (irony company)
  :config
  (add-to-list 'company-backends 'company-irony))

We also use the company-irony-c-headers of company to get completion of headers file.

(use-package company-irony-c-headers
  :after (irony company)
  :config (add-to-list 'company-backends 'company-irony-c-headers))

We can get documentation from c files using the irony backend of eldoc.

(use-package irony-eldoc
  :after (irony)
  :hook (irony-mode . irony-eldoc))

We define a function to use uncrustify on the local buffer.

(defun uncrustify ()
  "Use uncrustify on the current buffer."
  (interactive)
  (let ((save-point (point)))
    (shell-command-on-region
     (point-min)
     (point-max)
     "uncrustify -c ~/.uncrustify.cfg"
     (current-buffer)
     t
     "*uncrustify error buffer"
     nil)
    (goto-char save-point)))

We add summon this function when saving a c file.

(defun uncrustify-on-save ()
  "Unable uncrustify on save on the local buffer"
  (interactive)
  (add-hook 'before-save-hook 'uncrustify nil t))

;(add-hook 'c-mode-hook 'uncrustify-on-save)

CMake

The cmake-font-lock package provides advanced syntax highlighting for CMake files.

(use-package cmake-font-lock
  :mode ("\\.cmake\\'||CMakeLists.txt"))

Ocaml

The tuareg package provides a REPL, syntax highlighting and a debugger. We tell it to align patterns in pattern matching.

(use-package tuareg
  :custom
  (tuareg-match-patterns-aligned t)
  :mode ("\\.ml\\'" . tuareg-mode))

The merlin package provides auto-completion, syntax-checking and type annotations for ocaml. We use with tuareg and add it to the list of company backends, so we load it after these packages.

(use-package merlin
  :after (tuareg company)
  :config
  (add-to-list 'company-backends 'merlin-company-backend)
  :hook
  ((caml-mode tuareg-mode) . merlin-mode))

We can get documentation from ocaml files using the merlin backend of eldoc.

(use-package merlin-eldoc
  :hook ((tuareg-mode caml-mode) . merlin-eldoc-setup)
  :custom
  (eldoc-echo-area-use-multiline-p t)
  (merlin-eldoc-max-lines 6))

By default merlin uses flymake, however we use flycheck, so we disable its internal error reporting mechanism and replace it by a one which uses flycheck.

(use-package flycheck-ocaml
  :after (merlin flycheck)
  :config
  (setq merlin-error-after-save nil)
  (flycheck-ocaml-setup))

Common Lisp

The SLIME package provides Common Lisp IDE features.

The slime-company package a company backend for the SLIME package.

;  (use-package sly)

Org

Unable auto fill in org mode to make paragraphs of 80 lines automaticlly. We only load the emacs-lisp backend of literate programming with org-mode.

(use-package org
  :defer t
  :custom 
  (fill-column 80)
  :hook 
  (org-mode . auto-fill-mode)
  :config
  (org-babel-do-load-languages
    'org-babel-load-languages
    '((emacs-lisp . t))))

The toc-org auto generates table of contents on the first outline with a :TOC: tag, so we turn it in org files and load it after org-mode.

(use-package toc-org 
  :after (org)
  :hook (org-mode . toc-org-enable))

Git

Magit

The magit package provides a wrapper upon most of often used git commands.

(use-package magit
  :commands (magit-commit magit-push magit-status magit-pull))

Git gutter

The git-gutter and git-gutter-fringe packages provide a nice visual indicator in the fringe to see which lines are modified, added or deleted and not commited yet.

(use-package git-gutter
  :hook ((prog-mode org-mode) . git-gutter-mode))

(use-package git-gutter-fringe)

Provides a nice bitmap fringe for git-gutter.

(setq-default fringes-outside-margins t)
(define-fringe-bitmap 'git-gutter-fr:added
  (vector #b11100000)
  nil nil '(center repeated))
(define-fringe-bitmap 'git-gutter-fr:modified
  (vector #b11100000)
  nil nil '(center repeated))
(define-fringe-bitmap 'git-gutter-fr:deleted
  (vector #b10000000
          #b11000000
          #b11100000
          #b11110000)
  nil nil 'bottom)

Media

Elfeed

Elfeed is a feed reader supporting Atom and RSS feeds. Feeds are set in the private.el file in a list named elfeed-feeds. We only load the package when the elfeed command is called, and update feeds every time we open it. We also tell that elfeed needs curl.

(use-package elfeed
  :ensure-system-package (curl)
  :config (elfeed-update)
  :commands (elfeed))

Notmuch

First of all, we create a function to update the mail box, by downloading and indexing new emails using notmuch and offlineimap. We also tag each email sent by the user with a special tag.

(defun update-mail ()
  "Update offlineimap and notmuch."
  (interactive)
  (start-process-shell-command 
   "offlineimap"
   "offlineimap"
   "offlineimap -o && notmuch new")
  (start-process-shell-command
   "notmuch"
   "notmuch"
   (concat "notmuch tag +sent -- from:" user-mail-address)))

Notmuch is an email-client. We only load the package when the notmuch command is called. You need to install the notmuch and notmuch-emacs packages with your package manager. We tell use-package not to install notmuch since it’s already installed by the package manager. We also tell emacs which commands to use to send email - the smtp server has to be configured in private.el. We tell that notmuch needs gnutls-cli and notmuch.

(use-package notmuch 
;;  :custom-face
;;  (widget-field
;;   ((t
;;     (:box
;;      (:line-width
;;      (1 . 1)
;;       :color nil :style none)
;;      :foreground "#ECEFF4" :background "#242832"))))
  :config (update-mail)
  :ensure nil
  :commands (notmuch notmuch-mua-new-mail)
  :ensure-system-package 
  ((gnutls-cli . gnutls-bin)
    notmuch offlineimap)
  :custom 
  (notmuch-show-logo nil)
  (message-send-mail-function 'smtpmail-send-it)
  (mail-send-mail-function 'smtpmail-send-it)
  (message-auto-save-directory "~/.mail/draft")
  (message-kill-buffer-on-exit t)
  (message-directory "~/.mail"))

Eww

We set eww as the default web browser to use. We also customize a bit the look so it looks more coherent with the rest of the configuration.

(use-package eww
  :ensure nil
  :commands (eww)
  :custom-face
  (eww-form-submit ((t (:inherit custom-button))))
  (eww-valid-certificate ((t (:weight bold :foreground "#A3BE8C"))))
  (eww-form-text
   ((t
     (:box
      (:line-width
       (1 . 1)
       :color nil :style none)
      :foreground "#ECEFF4" :background "#242832"))))
  :custom (browse-url-browser-function 'eww-browse-url))

Keybindings

Evil

The Evil package provides emulation for the main features of Vim.

(use-package evil
  :init
  (setq evil-want-keybinding nil)
  :config
  (evil-mode 1))

The Evil Collection package provides Vim emulation for packages not covered by Evil. We already modified company keybindings so we disable evil’ one.

(use-package evil-collection
  :after (evil)
  :custom (evil-collection-company-use-tng nil)
  :config
  (evil-collection-init))

The undo-tree package provides a more traditional undo system without loosing information about past states of the buffer. Enable persistent buffer undo.

(use-package undo-tree
  :custom
  (undo-tree-auto-save-history t)
  (undo-limit 10000)
  :after (evil)
  :config
  (global-undo-tree-mode))

Avy

The avy package provides a way to move in the buffer using a char-based decision tree.

(use-package avy)

Anzu

The anzu package provides search information for various modes in the mode line.

(use-package anzu
  :config (global-anzu-mode)
  :custom-face
  (anzu-mode-line ((t (:foreground "#EBCB8B")))))

General

The general package provides an easy way to bind keys and integrates well with evil.

(use-package general
  :after (evil))

We define some keybindings for often used commands. They all start with the prefix space, à la spacemacs. We need to use the keymap override otherwise evil would bind the space key.

(general-define-key
  :prefix "SPC"
  :states 'normal
  :keymaps 'override
  "SPC" 'projectile-find-file
  "sb"  'swiper
  "ff"  'find-file
  "bb"  'counsel-switch-buffer
  "fr"  'counsel-recentf
  "kl"  'counsel-flycheck
  "cr"  'comment-region
  "cc"  'comment-line
  "gc"  'magit-commit
  "gp"  'magit-push
  "gs"  'magit-status
  "al"  'avy-goto-line
  "ac"  'avy-goto-char-2
  "aw"  'avy-goto-word-1
  "at"  'avy-goto-char-timer
  "ml"  'notmuch
  "mk"  'notmuch-mua-new-mail
  "mf"  'elfeed
  "p"   'projectile-command-map)

We add some key bindings to edit source blocks in org-mode.

(general-define-key
 :prefix "SPC"
 :states 'normal
 :keymaps '(org-mode-map)
 "cf" 'org-edit-special)

(general-define-key
 :prefix "SPC"
 :states 'normal
 :keymaps '(org-src-mode-map)
 "cf" 'org-edit-src-exit)

Then we add keybindings for message-mode.

(general-define-key
 :prefix "SPC"
 :states 'normal
 :keymaps '(message-mode-map notmuch-message-mode-map)
 "ms" 'message-send-and-exit)

Finally, we add some keys for full sized keyboards.

(general-define-key
  "<next>"  '(lambda ()
              (interactive)
              (next-line 40))
  "<prior>" '(lambda ()
              (interactive)
              (previous-line 40)))