vyorkin / emacs.d

My Emacs config

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Emacs configuration file

Credits

Inspired by freetonik’s setup.

Warnings

This config is not intended to be used by anyone other than me. I would not recommend using this configuration as-is.

Setup

Prerequisites

Install bear:

sudo apt-get install bear

Install wordnet, for example on Ubuntu:

sudo apt install wordnet

Install eslint_d eslint server, it is used as flycheck-javascript-eslint-executable:

npm i -g eslint_d

Install pdf-tools:

M-x pdf-tools-install RET

Check if pdf-tools are working:

M-x pdf-info-check-epdfinfo RET

Clone the repo:

git clone --recurse-submodules -j8 --depth=1 https://github.com/vyorkin/emacs.d

Make a backup of your old .emacs.d:

mv ~/.emacs.d ~/.emacs.d-bak
  • Symlink init.org to ~/.emacs.d/init.org
  • Symlink init.el to ~/.emacs.d/init.el
ln -sf $(pwd)/init.org ~/.emacs.d/init.org
ln -sf $(pwd)/init.el ~/.emacs.d/init.el

On the first run Emacs will install some packages. It’s best to restart Emacs after that process is done for the first time.

There is no reason to track the init.el that is generated; by running the following command git will not bother tracking it:

git update-index --assume-unchanged init.el

If one wishes to make changes to the repo-version of init.el start tracking again with:

git update-index --no-assume-unchanged init.el

When this configuration is loaded for the first time, the init.el is the file that is loaded. It looks like this:

;; We can't tangle without org!
(require 'org)
;; Open the configuration
(find-file (concat user-emacs-directory "init.org"))
;; Tangle it
(org-babel-tangle)
;; Load it
(load-file (concat user-emacs-directory "init.el"))
;; Finally byte-compile it
(byte-compile-file (concat user-emacs-directory "init.el"))

Check this init.org and run M-x all-the-icons-install-fonts if all-the-icons package is enabled.

Known issues

This is a known issue with emacs 28:

Eager macro-expansion failure: (wrong-number-of-arguments (3 . 4) 2) [2 times]
define-obsolete-variable-alias: Wrong number of arguments: (3 . 4), 2

There a number of PRs that fixes it as of 14/02/2021. Update packages after some time to see if it is fixed.

Startup timer

(add-hook 'emacs-startup-hook
  (lambda ()
    (message
     "Emacs ready in %s with %d GC's."
     (format
      "%.2f seconds"
      (float-time (time-subtract after-init-time before-init-time)))
     gcs-done)))

Config

Intro

Lexical binding for the init-file is needed, it can be specified in the header. This is the first line of the actual configuration.

;;; -*- lexical-binding: t -*-

Make startup faster by reducing the frequency of garbage collection. The default is 800 kilobytes. Measured in bytes. These are the first lines of the actual configuration.

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

In noninteractive sessions, prioritize non-byte-compiled source files to prevent the use of stale byte-code.

(setq load-prefer-newer noninteractive)

Non-nil means enter debugger if an error is signaled.

(setq debug-on-error t)

Customization

Let’s keep all customizations in one place.

Location

Location name and coordinates.

(defvar my/lat 55.84)
(defvar my/lon 37.34)
(defvar my/location "Moscow, RU")

Utils

Utility functions.

(defun my/emacs-path (path)
  "Expands `path` with Emacs home directory."
  (expand-file-name path user-emacs-directory))

(defun my/tmp-path (path)
  "Expand `path` with Emacs temporary directory."
  (my/emacs-path (format "tmp/%s" path)))

(defun my/lisp-path (path)
  "Expand `path` with Emacs `/lisp` directory."
  (my/emacs-path (format "lisp/%s" path)))

Auto-tangling (disabled)

I don’t use auto-tangling since I don’t want to tangle every time I save my init.org. Instead I call org-babel-tangle manually once at the very end of making changes.

Tangle and compile this file on save automatically:

(defun tangle-init ()
  "If the current buffer is 'init.org' the code-blocks are
tangled, and the tangled file is compiled."
  (when (equal (buffer-file-name)
               (file-truename (concat user-emacs-directory "init.org")))
    ;; Avoid running hooks when tangling.
    (let ((prog-mode-hook nil))
      (org-babel-tangle)
      (byte-compile-file (concat user-emacs-directory "init.el")))))

(add-hook 'after-save-hook 'tangle-init)

Package management

Init

Initialize package and add package archives.

(require 'package)

Tangle the following line if you have TLS-related issues:

(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")
;; Try to uncomment this if you have TLS-related issues
;; (setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")

(let* ((no-ssl (and (memq system-type '(windows-nt ms-dos))
                    (not (gnutls-available-p))))
    (proto (if no-ssl "http" "https")))
    (add-to-list 'package-archives (cons "melpa" (concat proto "://melpa.org/packages/")) t))

It is ok to use both package-initialize and use-package for a well behaved package: package-initialize will not load the whole package, but only autoload functions selected by the package author.

(package-initialize)

Use-package

Install

Install use-package.

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

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

Config

Install missing packages automatically if not already present on the system and be less verbose.

(setq
 use-package-always-ensure t
 use-package-verbose nil)

Statistics gathering (disabled)

Enable tangling and run the M-x use-package-report command to see the results. Read the docs for more info.

(use-package-compute-statistics)

Quelpa

Setup quelpa.

(if (require 'quelpa nil t)
  ;; Prevent quelpa from doing anyting that requires network connection.
  (setq
   quelpa-update-melpa-p nil    ; Don't update MELPA git repo
   quelpa-checkout-melpa-p nil  ; Don't clone MELPA git repo
   quelpa-upgrade-p nil         ; Don't try to update packages automatically
   quelpa-self-upgrade-p nil)   ; Don't upgrade quelpa automatically

(unless (package-installed-p 'quelpa)
  (with-temp-buffer
    (url-insert-file-contents "https://github.com/quelpa/quelpa/raw/master/quelpa.el")
    (eval-buffer)
    ;; Comment/uncomment line below to disable/enable quelpa auto-upgrade.
    (quelpa-self-upgrade))))

Install use-package and the quelpa handler.

(quelpa
 '(quelpa-use-package
   :fetcher github
   :repo "quelpa/quelpa-use-package"))
(require 'quelpa-use-package)

Advice setting :ensure nil for use-package + quelpa.

(quelpa-use-package-activate-advice)

Use-package plugins

All credit to a13.

Works as :custom keyword, but instead of a value takes update function or the second (the first is the original one) argument to the default updater.

(use-package use-package-custom-update
 :quelpa
 (use-package-custom-update
   :repo "a13/use-package-custom-update"
   :fetcher github
   :version original))

:secret keyword for use-package.

(use-package use-package-secrets
 :custom
 (use-package-secrets-directories '("~/.emacs.d/secrets"))
 :quelpa
 (use-package-secrets
   :repo "a13/use-package-secrets"
   :fetcher github
   :version original))

System shell env

Pass system shell environment to Emacs. This is important primarily for shell inside Emacs, but also things like Org mode export to Tex PDF don’t work, since it relies on running external command pdflatex, which is loaded from PATH. Also this is required for use-package-ensure-system-package extension.

(use-package exec-path-from-shell
 :commands
 (exec-path-from-shell-copy-envs
  exec-path-from-shell-initialize)
 :init
 (setq exec-path-from-shell-check-startup-files nil)
 :config
 (exec-path-from-shell-copy-envs '("WAKATIME_API_KEY"))
 (when (memq window-system '(mac ns x))
   (exec-path-from-shell-initialize)))

Warnings

Decrease the obsolete warnings annoyance level.

(setq byte-compile-warnings '(not obsolete))

This helps to get rid of functions might not be defined at runtime warnings. See this issue for details.

(eval-when-compile
  (setq use-package-expand-minimally byte-compile-current-file))

Suppress ad-handle-definition warnings.

(setq ad-redefinition-action 'accept)

Defaults

Backups & lock files

Don’t create lock files.

(setq create-lockfiles nil)

I don’t care about auto save and backup files. Also I don’t like distracting alarms.

(setq
 make-backup-files nil        ; disable backup files
 auto-save-list-file-name nil ; disable .saves files
 auto-save-default nil        ; disable auto saving
 ring-bell-function 'ignore)  ; turn off alarms completely

Performance

Disable bidirectional text for a tiny performance boost.

(setq-default bidi-display-reordering nil)

Update UI less frequently (disabled).

(setq
 idle-update-delay 2
 jit-lock-defer-time 0
 jit-lock-stealth-time 0.2
 jit-lock-stealth-verbose nil)

Misc

Use y/n instead of yes/no.

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

Don’t prompt for non existent name when creating new buffers.

(setq-default confirm-nonexistent-file-or-buffer t)

Enable recentf-mode and remember a lot of files.

(setq
 recentf-auto-cleanup 'never
 recentf-max-menu-items 0
 recentf-max-saved-items 300
 recentf-filename-handlers '(file-truename abbreviate-file-name))

(recentf-mode 1)

Automatically save place in each file.

(setq
 save-place-forget-unreadable-files t
 save-place-limit 400)

(save-place-mode 1)

Location

Set the location name and coordinates.

(setq
 calendar-location-name my/location
 calendar-latitude my/lat
 calendar-longitude my/lon)

Builtin

Imports

(require 'color)

Files

On save/write file:

  • Automatically delete trailing whitespace.
  • Silently put a newline at the end of file if there isn’t already one there.
(use-package files
  :ensure nil
  :preface
  (defun my/files/setup ()
    (add-hook 'before-save-hook 'delete-trailing-whitespace))
  :commands
  (generate-new-buffer
   executable-find
   file-name-base
   file-name-extension)
  :custom
  (require-final-newline t)
  :hook
  (prog-mode . my/files/setup))

Reverting

Diminish autorevert mode.

(use-package autorevert
 :ensure nil
 :custom
 ;; Don't generate any messages whenever a buffer is reverted
 (auto-revert-verbose nil)
 ;; Operate only on file-visiting buffers
 (global-auto-revert-non-file-buffers t)
 :diminish auto-revert-mode)

Uniquify

The forward buffer name style includes part of the file’s directory name at the beginning of the buffer name. Using this method, buffers visiting the files /u/rms/tmp/Makefile and /usr/projects/hooy/Makefile would be named ‘tmp/Makefile’ and ‘hooy/Makefile’.

(use-package uniquify
 :ensure nil
 :custom
 ;; use "foo/bar/qux"
 (uniquify-buffer-name-style 'forward))

History

Many editors (e.g. Vim) have the feature of saving minibuffer history to an external file after exit. This package provides the same feature in Emacs. When set up, it saves recorded minibuffer histories to a file (~/.emacs-history by default).

(use-package savehist
  :ensure nil
  :custom
  (savehist-additional-variables
   '(kill-ring
     ;; search entries
     search-ring
     regexp-search-ring))
  ;; save every minute
  (savehist-autosave-interval 60)
  (savehist-save-minibuffer-history t)
  :init
  (savehist-mode 1))

Frame

  • Disable blinking cursor.
  • Disable suspending on C-z.
(use-package frame
 :ensure nil
 :config
 (blink-cursor-mode 0)
 :bind
 ("C-z" . nil))

Delsel

C-c C-g always quits minibuffer.

(use-package delsel
 :ensure nil
 :bind
 ("C-c C-g" . minibuffer-keyboard-quit))

Simple

(use-package simple
  :ensure nil
  :diminish
  ((visual-line-mode . "")
   (auto-fill-function . ""))
  :bind
  ;; remap ctrl-w/ctrl-h
  (("C-c h" . help-command)
   ("C-x C-k" . kill-region)
   ("C-h" . delete-backward-char)))

VC hooks

(use-package vc-hooks
  :ensure nil
  :config
  (setq
   vc-follow-symlinks t
   vc-make-backup-files nil))

Prog mode

Prettify symbols.

(use-package prog-mode
 :ensure nil
 :commands
 (global-prettify-symbols-mode)
 :init
 (setq prettify-symbols-unprettify-at-point 'right-edge)
 :config
 ;; convert certain words into symbols, e.g. lambda becomes λ.
 (global-prettify-symbols-mode t))

IBuffer

Use the ibuffer in place of the default list-buffers command. This provides tremendous amount of additional functionality in terms of filtering, grouping, and acting upon the listed buffers. Also, it opens the list of buffers in the same window.

(use-package ibuffer
 :ensure nil
 :bind
 ;; Set all global list-buffers bindings to use ibuffer
 ([remap list-buffers] . ibuffer))

Mule

(use-package mule
 :commands
 (set-terminal-coding-system)
 :ensure nil
 :config
 (prefer-coding-system 'utf-8)
 (set-terminal-coding-system 'utf-8)
 (set-language-environment "UTF-8"))

ETags

Setup Emacs tags.

(use-package etags
 :ensure nil
 :custom
 ;; Don't add a new tags to the current list.
 ;; Always start a new list.
 (tags-add-tables nil))

Man

(use-package man
 :ensure nil
 :custom-face
 (Man-overstrike ((t (:inherit font-lock-type-face :bold t))))
 (Man-underline ((t (:inherit font-lock-keyword-face :underline t)))))

Calendar

(use-package calendar
 :ensure nil
 :custom
 (calendar-week-start-day 1))

Face remap

(use-package face-remap
 :commands
 (buffer-face-mode-face
  face-remap-add-relative
  buffer-face-mode)
 :ensure nil
 :diminish buffer-face-mode)

CC mode

Note that “.m” conflicts with mercury-mode.

(use-package cc-mode
 :ensure nil
 :config
 ;; (add-to-list 'auto-mode-alist '("\\.m\\'" . objc-mode))
 (add-to-list 'auto-mode-alist '("\\.mm\\'" . objc-mode)))

Compile

Kill compilation process before starting another, save all buffers on compile, scroll to the first compilation error automatically.

(use-package compile
  :custom
  (compilation-always-kill t)
  (compilation-ask-about-save nil)
  (compilation-scroll-output t)
  :init
  (make-variable-buffer-local 'compile-command)
  (put 'compile-command 'safe-local-variable 'stringp))

Shell

Hide the “Indentation setup for shell type sh” message in the minibuffer.

(advice-add
 'sh-set-shell :around
 (lambda (orig-fun &rest args)
   (let ((inhibit-message t))
     (apply orig-fun args))))

Libraries

async

Simple library for asynchronous processing in Emacs.

(use-package async
  :demand t
  :config
  (autoload 'dired-async-mode "dired-async.el" nil t)
  (dired-async-mode 1)
  (async-bytecomp-package-mode 1))

alert

A Growl-like alerts notifier for Emacs.

(use-package alert)

UI

Basics

(setq
 inhibit-startup-screen t ; Don't show splash screen
 use-dialog-box nil       ; Disable dialog boxes
 use-file-dialog nil)     ; Disable file dialog

Titlebar

Make titlebar transparent.

(when (memq window-system '(mac ns))
  (add-to-list 'default-frame-alist '(ns-appearance . dark)) ;; {light, dark}
  (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t)))

Scroll

More procedural scrolling.

(setq
 auto-window-vscroll nil
 hscroll-margin 5
 hscroll-step 5
 scroll-conservatively 101
 scroll-margin 0
 scroll-preserve-screen-position t)

(setq-default
 scroll-down-aggressively 0.01
 scroll-up-aggressively 0.01)

UI elements

Hide toolbar and scrollbars.

(tool-bar-mode -1)
(scroll-bar-mode -1)
(when (fboundp 'horizontal-scroll-bar-mode)
  (horizontal-scroll-bar-mode -1))

I generally prefer to hide the menu bar, but doing this on OS X simply makes it update unreliably in GUI frames, so we make an exception.

(if (eq system-type 'darwin)
    (add-hook 'after-make-frame-functions
              (lambda (frame)
                (set-frame-parameter frame 'menu-bar-lines
                                     (if (display-graphic-p frame) 1 0))))
  (when (fboundp 'menu-bar-mode)
    (menu-bar-mode -1)))

Don’t blink matching paren, it’s too distracting.

(setq-default blink-matching-paren nil)

Cursor

Hide cursor in inactive windows.

(setq-default cursor-in-non-selected-windows nil)
  • Display vertical bar cursor with default width.
  • Draw block cursor as wide as the glyph under it.
(setq-default
 cursor-type 'bar
 x-stretch-cursor t)

Show full path in the title bar.

(setq-default frame-title-format "%b (%f)")

Don’t implicitly resize the frame’s display area in order to preserve the number of columns or lines the frame displays when changing font, menu bar, tool bar, internal borders, fringes or scroll bars. Read this for more info.

(setq-default frame-inhibit-implied-resize t)

Fringe

Set fringe size.

(fringe-mode '(12 . 12))

Setup fringes on both sides and display an indicator for buffer boundaries on the left side. Display fringes outside margins to have the padding on the inside.

(setq-default
 fringes-outside-margins t
 left-fringe-width 8
 right-fringe-width 8
 indicate-buffer-boundaries 'left)

Remove continuation arrow on right fringe.

(setq-default
 fringe-indicator-alist
 (delq (assq 'continuation fringe-indicator-alist) fringe-indicator-alist))

Window-divider

Hide the window-divider (a line separating windows).

(when (boundp 'window-divider-mode)
  (setq window-divider-default-places t
        window-divider-default-bottom-width 0
        window-divider-default-right-width 0)
  (window-divider-mode +1))

Line-spacing

Non-zero values for line-spacing can mess up ansi-term and co, so we zero it explicitly in those cases.

(add-hook
 'term-mode-hook
 (lambda () (setq line-spacing 0)))

Highlight parens.

(setq show-paren-style 'parenthesis)
(show-paren-mode 1)

Treat an Emacs region much like a typical text selection outside of Emacs.

(setq delete-selection-mode t)

Set left and right margins for every window.

(setq-default
 left-margin-width 1
 right-margin-width 1)

Startup

Start maximized (disabled).

(toggle-frame-maximized)

Mode line

Turn-off tooltips on cursor hover-over.

(setq mode-line-default-help-echo nil)

Display only line and column in a mode-line.

(setq
 mode-line-position
 '((line-number-mode ("%l" (column-number-mode ":%c")))))

Time

(use-package time
  :ensure nil
  :custom
  (display-time-default-load-average nil)
  (display-time-24hr-format t)
  :config
  (display-time-mode t))

Font

Font faces

Font faces configuration.

(use-package faces
  :ensure nil
  :custom
  (face-font-family-alternatives
   '(("JetBrains Mono" "Hack" "Consolas" "Monaco" "Monospace")))
  :init
  (set-face-attribute
   'default nil
   :family (caar face-font-family-alternatives)
   :weight 'regular
   :height 120
   :width 'semi-condensed)
  (set-fontset-font
   "fontset-default"
   'cyrillic
   (font-spec :registry "iso10646-1" :script 'cyrillic)))

Font lock

Try to speed-up font-lock-mode.

(setq
 font-lock-maximum-decoration
 '((c-mode . 2) (c++-mode . 1) (t . 1)))

(setq font-lock-support-mode 'jit-lock-mode)
(setq
 jit-lock-stealth-time 16
 jit-lock-defer-contextually t
 jit-lock-stealth-nice 0.5)

Editor

Customizations

I don’t use the customizations UI. Anyway, I keep those automated customizations in a separate file. The 'noerror argument passed to load prevents errors if the file doesn’t exist.

(setq custom-file (my/emacs-path "custom.el"))
(load custom-file 'noerror)

Basics

Some basic things.

(setq
 ;; sentences should end in one space
 sentence-end-double-space nil
 ;; empty scratch buffer
 initial-scratch-message nil
 ;; show keystrokes right away,
 ;; don't show the message in the scratch buffer
 echo-keystrokes 0.1
 ;; disable native fullscreen support
 ns-use-native-fullscreen nil)

Minibuffer

Give some more room to the minibuffer.

(setq
 max-mini-window-height 0.3
 resize-mini-windows 'grow-only)

Enable recursive minibuffers and keep the point out of the minibuffer.

(setq
 ;; allow minibuffer commands in the minibuffer
 enable-recursive-minibuffers t
 ;; keep the point out of the minibuffer
 minibuffer-prompt-properties
 '(read-only t point-entered minibuffer-avoid-prompt face minibuffer-prompt))

Auto executable scripts.

(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)

Tabs & spaces

  • Use spaces instead of tabs everywhere.
  • One tab is 2 spaces.
(setq-default
 indent-tabs-mode nil
 tab-width 2)

Display line and column numbers in the mode-line.

(setq
  line-number-mode t
  column-number-mode t)

Line wrapping

Long lines will show a continuation character in the right margin at the window’s edge to indicate that one can scroll to see the rest.

(setq-default truncate-lines t)

Break line at N characters.

(setq-default fill-column 64)

Enable automatic line breaking for all text mode buffers.

(add-hook 'text-mode-hook 'turn-on-auto-fill)

Always wrap lines.

;; (global-visual-line-mode)

Benchmarking

Usage:

  • M-x benchmark-init/show-durations-tabulated

M-x benchmark-init/show-durations-tree

;; Disabled, see: https://github.com/dholm/benchmark-init-el/issues/15
(use-package benchmark-init
 :hook
 ;; To disable collection of benchmark data after init is done.
 (after-init . benchmark-init/deactivate))

Theme

Base-16 themes

(use-package base16-theme
  :config
  ;; (load-theme 'base16-default-dark t)
  ;; (load-theme 'base16-grayscale-dark t)
  ;; (load-theme 'base16-grayscale-light t)
  ;; (load-theme 'base16-gruvbox-light-hard t)
  ;; (load-theme 'base16-material-palenight t) ;; ****
  ;; (load-theme 'base16-rebecca t)
  ;; (load-theme 'base16-pop t)
  ;; (load-theme 'base16-tomorrow-night t)
  ;; (load-theme 'base16-twilight t)
  ;; (load-theme 'base16-irblack t)

base16-chalk + customizations.

(load-theme 'base16-chalk t)
(custom-set-faces
 '(proof-queue-face ((t (:foreground "#eee"))))
 '(proof-declaration-name-face ((t (:foreground "#55aaff"))))
 '(company-coq-comment-h1-face ((t (:size 1.5))))
 '(proof-locked-face ((t (:background "#252525"))))
 '(proof-mouse-highlight-face  ((t (:background "#555" :foreground "#fff")))))

base16-black-metal + customizations.

(load-theme 'base16-black-metal t) ;; ***
(custom-set-faces
 '(proof-queue-face ((t (:foreground "#eee"))))
 '(company-coq-comment-h1-face ((t (:size 1.5))))
 '(font-lock-comment-face ((t (:foreground "#999"))))
 '(proof-locked-face ((t (:background "#151515"))))
 '(proof-mouse-highlight-face  ((t (:background "#555" :foreground "#fff")))))

base16-one-light + customizations.

(load-theme 'base16-one-light t)
(custom-set-faces
 '(proof-queue-face ((t (:foreground "#f0f0f0"))))
 '(proof-locked-face ((t (:background "#faebd7" :foreground "#4a473d"))))
 '(proof-locked-face ((t (:background "#faebd7" ))))
 '(proof-mouse-highlight-face  ((t (:background "#555" :foreground "#fff")))))
)

Customizations for vimish-fold and base16-grayscale-dark theme.

(eval-after-load 'vimish-fold
 (custom-set-faces
  '(vimish-fold-mouse-face ((t (:box (:line-width 1 :color "#555")))))
  '(vimish-fold-overlay ((t (:box (:line-width 1 :color "#222")))))))

Doom themes

See the screenshots.

(use-package doom-themes
 :init
 (setq
  doom-themes-enable-bold nil
  doom-themes-enable-italic nil)
 :config
 (load-theme 'doom-dracula t)
 (load-theme 'doom-challenger-deep t)
 ;; Enable flashing mode-line on errors
 (doom-themes-visual-bell-config)
 (doom-themes-neotree-config)
 ;; Corrects (and improves) org-mode's native fontification
 (doom-themes-org-config)
 (load-theme 'doom-dracula)
)

Apropospriate theme

(use-package apropospriate-theme
 :config
 (load-theme 'apropospriate-dark))

Nord theme

(use-package nord-theme)

Zero dark theme

(use-package zerodark-theme
  :config
  (load-theme 'zerodark t nil)
  (zerodark-setup-modeline-format)
  ;; Customizations
  (with-eval-after-load 'idle-highlight-mode
    ;; (set-face-background 'idle-highlight "#c51060")
    (set-face-foreground 'idle-highlight "#999")
    (set-face-background 'idle-highlight "#222"))

  (with-eval-after-load 'company))
(with-eval-after-load 'proof-general
    (custom-set-faces
     '(proof-queue-face ((t (:foreground "#eee"))))
     '(proof-locked-face ((t (:background "#001800" :foreground "#aaccbb"))))
     '(proof-locked-face ((t (:background "#0d3360" ))))
     '(proof-mouse-highlight-face  ((t (:background "#555" :foreground "#fff"))))))

Lor theme

Just another Tango theme based on linux.org.ru colors.

(use-package lor-theme
 :ensure nil
 :custom-face
 (variable-pitch ((t (:family "Serif"))))
 (fixed-pitch ((t (:family "Monospace"))))
 :config
 (load-theme 'lor)
 :quelpa
 (lor-theme :repo "a13/lor-theme" :fetcher github :version original))

Sorcery

(use-package sorcery-theme)

Other themes

(use-package dracula-theme :defer t)
(use-package gotham-theme :defer t)
(use-package sublime-themes :defer t)
(use-package color-theme-modern :defer t)
(use-package twilight-theme :defer t)
(use-package gruber-darker-theme :defer t)
(use-package monokai-theme :defer t)
(use-package faff-theme :defer t)
(use-package badwolf-theme :defer t)
(use-package boron-theme :defer t)
(use-package bliss-theme :defer t)
(use-package busybee-theme :defer t)
(use-package color-theme-sanityinc-tomorrow :defer t)
(use-package badger-theme :defer t)
(use-package atom-one-dark-theme :defer t)
(use-package zenburn-theme :defer t)
(use-package hemisu-theme :defer t)
(use-package paganini-theme :defer t)
(use-package yoshi-theme :defer t)
(use-package rebecca-theme :defer t) ;; *****
(use-package moe-theme :defer t)
(use-package arjen-grey-theme :defer t)
(use-package darkmine-theme :defer t)
(use-package flatland-theme :defer t)
(use-package tao-theme :defer t)
(use-package liso-theme :defer t)
(use-package jazz-theme :defer t)
(use-package material-theme :defer t)
(use-package challenger-deep-theme :defer t) ;; ***
(use-package ample-theme
  :disabled
  :init
  (progn
    (load-theme 'ample t t)
    (load-theme 'ample-flat t t)
    (load-theme 'ample-light t t)
    (enable-theme 'ample-flat))
  :defer t)
(use-package cyberpunk-theme :defer t)
(use-package phoenix-dark-mono-theme :defer t) ;; *** (like grayscale-dark)
(use-package phoenix-dark-pink-theme :defer t) ;; **
(use-package cyberpunk-theme :defer t)
(use-package blackboard-theme :defer t) ;; ***
(use-package mustard-theme :defer t) ;; ****
(use-package labburn-theme :defer t) ;; *****
(use-package green-phosphor-theme :defer t) ;; *****
(use-package exotica-theme :defer t) ;; **
(use-package lush-theme :defer t) ;; ****

Theme changer (disabled)

Sunrise/sunset theme changer. Given a location and day/night color themes, this file provides a change-theme function that selects the appropriate theme based on whether it is day or night. It will continue to change themes at sunrise and sunset.

(use-package theme-changer
  :config
  (change-theme 'base16-gruvbox-light-hard 'labburn))

Kurecolor

A collection of color tools aimed at those working with (normal 6 digit) hex color codes, useful for CSS, Emacs themes, etc. etc.

Features include interactive step modification of hue, sat, val on hex colors. Color conversion algorithms, for 6 digit hex colors, hsv, rgb, cssrgb. Get/set h s v values from/for a color.

It’s recommend you use this in conjunction with rainbow-mode, for instant feedback on color changes.

See the kurecolor github for more info.

(use-package kurecolor)

Key bindings

Variables

Use SPC as a “leader” key and C-SPC as a second leader (I call it “leader+” here).

(defvar my/leader "SPC")
(defvar my/leader+ "C-SPC")

General package

(use-package general
 :config

Basic keybindings

(general-define-key
 "C-h" 'windmove-left
 "C-l" 'windmove-right
 "C-k" 'windmove-up
 "C-j" 'windmove-down
 "C-c C-k" 'kill-region)

MacOS keybindings

(when (eq system-type 'darwin)
  (general-define-key
   "s-<backspace>" 'kill-whole-line
   "M-S-<backspace>" 'kill-word
   ;; Use Super for movement and selection just like in macOS
   "s-<right>" (kbd "C-e")
   "S-s-<right>" (kbd "C-S-e")
   "s-<left>" (kbd "M-m")
   "S-s-<left>" (kbd "M-S-m")
   "s-<up>" 'beginning-of-buffer
   "s-<down>" 'end-of-buffer
   ;; Basic things you should expect from macOS
   "s-a" 'mark-whole-buffer       ; select all
   "s-s" 'save-buffer             ; save
   "s-S" 'write-file              ; save as
   "s-q" 'save-buffers-kill-emacs ; quit
   ;; Go to other windows easily with one keystroke
   ;; s-something instead of C-x something
   "s-o" (kbd "C-x o")
   "s-w" (kbd "C-x 0") ; just like close tab in a web browser
   "s-W" (kbd "C-x 1") ; close others with shift
   ;; Move between windows with Control-Command-Arrow and
   ;; with Cmd just like in iTerm
   "s-[" 'windmove-left   ; Cmd+[ go to left window
   "s-]" 'windmove-right  ; Cmd+] go to right window
   "s-{" 'windmove-up     ; Cmd+Shift+[ go to upper window
   "<s-}>" 'windmove-down ; Ctrl+Shift+[ go to down window
   ;; Prev/next buffer
   "s-<" 'previous-buffer
   "s->" 'next-buffer))

Evil keybindings

Setup

Set up some basic equivalents for vim mapping functions. This creates global key definition functions for the evil states.

(general-evil-setup t)

Basic

Swap : and ; to make colon commands easier to type in Emacs.

(nmap
 ";" 'evil-ex
 ":" 'evil-repeat-find-char)

Remap 0 for convenience.

(nmap 'messages-buffer-mode-map
  "0" 'evil-digit-argument-or-evil-beginning-of-line)

Process menu

(nmap 'process-menu-mode-map
  "M-d" 'process-menu-delete-process
  "q" 'kill-buffer-and-window)

Leader-prefixed

(nmap
  :prefix my/leader

Window splitting.

"v" 'split-window-horizontally
"s" 'split-window-vertically

XRef.

"@" 'xref-find-definitions
"#" 'xref-find-references

Evaluation.

"E e" 'eval-expression
"E l" 'eval-last-sexp

Help.

"h k" 'describe-key-briefly
"h K" 'describe-key
"h M" 'describe-mode
"h m" 'info-display-manual)

Profiling.

"P s" 'profiler-start
"P S" 'profiler-stop
"P r" 'profiler-report

Others.

"p" 'list-processes
"\\" 'widen
)

Behavior

Garbage collection

Enforce a sneaky Garbage Collection strategy to minimize GC interference with the activity. During normal use a high GC threshold is set. When idling GC is immediately triggered and a low threshold is set.

A more detailed explanation of the rationale behind this can be found at: http://akrl.sdf.org/.

(use-package gcmh
  :config
  (gcmh-mode 1))

Server

Start server if one isn’t already running.

(use-package server
  :ensure nil
  :commands server-running-p
  :preface
  (defun my/server-ensure-running (frame)
    "Ensure server is running when launching FRAME."
    (with-selected-frame frame
      (unless (server-running-p)
        (server-start))))
  :init
  (add-hook 'after-make-frame-functions #'my/server-ensure-running))

Trashing

(setq
  delete-by-moving-to-trash t
  trash-directory (my/emacs-path "trash"))

Buffer

Hide async shell command buffers.

(cl-pushnew
 '("^*Async Shell Command*" . (display-buffer-no-window))
 display-buffer-alist
 :test #'equal)

Always display pop up buffers at the bottom and regard all star buffers as such buffers. (Not always that useful)

(let ((rule
       `(,(rx bos "*" (one-or-more anything) "*" (optional "<" (one-or-more anything) ">") eos)
         (display-buffer-reuse-window
          display-buffer-in-side-window)
         (reusable-frames . visible)
         (side . bottom)
         (window-height . 0.4))))
  (cl-pushnew rule display-buffer-alist :test #'equal))

Visual fill column

Wrap lines according to fill-column in visual-line-mode.

(use-package visual-fill-column
  :custom
  (visual-fill-column-center-text t))

Clipboard (disabled)

Make emacs kill ring and system clipboard independent. Currenly untangled.

(use-package simpleclip
 :disabled
 :after general
 :config
 (simpleclip-mode 1)
 (nmap
   "s-c" 'simpleclip-copy
   "s-v" 'simpleclip-paste)
 (imap
   "s-c" 'simpleclip-copy
   "s-v" 'simpleclip-paste))

Copy as

Allows to copy buffer locations as GitHub/Slack/JIRA/HipChat/etc formatted code.

(use-package copy-as-format
 :after general
 :config
 (vmap
   :prefix "C-c f"
   "f" 'copy-as-format
   "a" 'copy-as-format-asciidoc
   "b" 'copy-as-format-bitbucket
   "d" 'copy-as-format-disqus
   "g" 'copy-as-format-github
   "l" 'copy-as-format-gitlab
   "h" 'copy-as-format-html
   "j" 'copy-as-format-jira
   "m" 'copy-as-format-markdown
   "w" 'copy-as-format-mediawiki
   "o" 'copy-as-format-org-mode
   "p" 'copy-as-format-pod
   "r" 'copy-as-format-rst
   "s" 'copy-as-format-slack))

Posframe

Pop a posframe (a child-frame) at point.

(use-package posframe
  :custom
  (posframe-mouse-banish nil))

Extra whitespace trimming

Unobtrusively trim extraneous whitespace only in lines edited.

(use-package ws-butler
 :hook
 (prog-mode . ws-butler-mode)
 :diminish ws-butler-mode)

Aggressive indent (disabled)

Emacs minor mode that keeps your code always indented. More reliable than electric-indent-mode. More info in the package repository.

(use-package aggressive-indent
 :hook
 ((emacs-lisp-mode css-mode c++-mode) . aggressive-indent-mode)
 :config
 ;; Prevent lines jumping around in c++-mode when you haven't typed the ";" yet
 (add-to-list
  'aggressive-indent-dont-indent-if
  '(and
    (derived-mode-p 'c++-mode)
    (null (string-match
           "\\([;{}]\\|\\b\\(if\\|for\\|while\\)\\b\\)"
           (thing-at-point 'line))))))

Auto-save buffers (disabled)

Save buffers when they lose focus.

(use-package super-save
 :config
 (super-save-mode +1)
 :diminish)

Auto read-only

Automatically make the buffer-file to read-only based on buffer-file-name. For example, it can protect library code provided by third parties.

(use-package auto-read-only
 :config
 (auto-read-only-mode 1)
 ;; Automatically make the init.el read-only because it is a
 ;; generated file.
 (add-to-list 'auto-read-only-file-regexps "~/.emacs.d/init.el"))

Zoom

text-scale-increase and text-scale-decrease doesn’t play well with company-mode (suggestions popup alignment issue). You can find some more info here.

frame-fns and frame-cmds are dependencies of zoom-frm.

(use-package frame-fns
 :demand t
 :quelpa (frame-fns :fetcher github :repo "emacsmirror/frame-fns"))
(use-package frame-cmds
 :demand t
 :quelpa (frame-cmds :fetcher github :repo "emacsmirror/frame-cmds"))

(use-package zoom-frm
 :after (frame-fns frame-cmds)
 :quelpa (zoom-frm :fetcher github :repo "emacsmirror/zoom-frm")
 :config
 (nmap
   "C-=" 'zoom-frm-in
   "C--" 'zoom-frm-out
   "<s-triple-wheel-up>" 'zoom-frm-in
   "<s-triple-wheel-down>" 'zoom-frm-out))

Fixed and automatic balanced window layout for Emacs. TL;DR: Zooms current pane.

(use-package zoom
 :custom
 (zoom-size '(0.8 . 0.8))
 (zoom-ignored-major-modes '(dired-mode pomidor-mode))
 (zoom-ignored-buffer-name-regexps '("^*calc"))
 (zoom-ignore-predicates '((lambda () (> (count-lines (point-min) (point-max)) 20)))))

Transparency

Allows easily change Emacs transparency. See the package repo for more info.

(use-package seethru
 :demand t
 :commands
 (seethru)
 :config
 (seethru 100)
 ;; C-c 8, C-c 9
 (seethru-recommended-keybinds))

Go to last change

Go to last change in a current buffer.

(use-package goto-chg
 :after general
 :config
 (nmap
   :prefix my/leader
   "." 'goto-last-change
   "," 'goto-last-change-reverse)
 ;; Additional keybindings for macOS
 (when (eq system-type 'darwin)
   (nmap
     "s-." 'goto-last-change
     "s-," 'goto-last-change-reverse)))

Fullframe

Makes it possible to advice commands to execute fullscreen, restoring the window setup when exiting.

(use-package fullframe
 :config
 (fullframe list-packages quit-window)
 (fullframe package-list-packages quit-window))

Folding

Vim-like text folding for Emacs.

(use-package vimish-fold
 :after evil
 :commands
 (vimish-fold-global-mode)
 :init
 (setq
  vimish-fold-blank-fold-header "<...>"
  vimish-fold-indication-mode 'right-fringe)
 :config
 (vimish-fold-global-mode 1))

Which key

Key bindings are provided by evil-collection.

(use-package which-key
 :diminish which-key-mode
 :init
 (setq
  which-key-idle-delay 1.0
  which-key-sort-order 'which-key-prefix-then-key-order-reverse
  ;; Hack to make this work with Evil
  which-key-show-operator-state-maps t
  which-key-prefix-prefix ""
  which-key-side-window-max-width 0.5
  which-key-popup-type 'side-window
  which-key-side-window-location 'bottom)
 :config
 (which-key-mode)
 (with-eval-after-load 'evil-collection
   (add-to-list 'evil-collection-mode-list 'while-key)))

Free keys

Show free bindings in current buffer. To use, call the command M-x free-keys. See the package repo for more info.

(use-package free-keys)

VLF

Large file support. This can view/edit/search and compare large files.

(use-package vlf)

Sudo edit

Utilities for opening files with sudo.

(use-package sudo-edit)

Try

Allows you to try out Emacs packages without installing them.

(use-package try)

Restart

(use-package restart-emacs
 :after general
 :demand t
 :config
 (nmap
   :prefix my/leader
   "Z" 'restart-emacs))

Appearance

Customization

Define an interactive function for customizing appearance.

(defun my/customize-appearance ()
  (interactive)
  ;; set the background or vertical border to the main area background color
  (set-face-background 'vertical-border (face-background 'default))
  ;; set the foreground and background of the vertical-border face to
  ;; the same value so there is no line up the middle
  (set-face-foreground 'vertical-border (face-background 'vertical-border))
  ;; set the fringe colors to whatever is the background color
  (set-face-attribute
   'fringe nil
   :foreground (face-foreground 'default)
   :background (face-background 'default))

  ;; Comment/uncomment the lines below to
  ;; set the highlight color for selected text:

  ;; (set-face-attribute 'region nil :foreground "#fff")
  ;; (set-face-attribute 'region nil :background "#282828")

  ;; Comment/uncomment the line below to
  ;; set the highlight color and foreground color for matching search results:

  ;; (set-face-attribute 'lazy-highlight nil :foreground "black" :background "#ffd700")
  )

Required for emacsclient.

(if (display-graphic-p)
    (my/customize-appearance)
  (add-hook
   'after-make-frame-functions
   (lambda (frame)
     (when (display-graphic-p frame)
       (with-selected-frame frame
         (my/customize-appearance))))))

Page break lines (disabled)

Display ugly ^L page breaks as tidy horizontal lines. Currently disabled, becuase it makes the scrolling slow.

(use-package page-break-lines
 :init
 (global-page-break-lines-mode 1)
 :diminish page-break-lines-mode)

Rainbow delimiters

rainbow-delimiters is a “rainbow parentheses”-like mode which highlights delimiters such as parentheses, brackets or braces according to their depth. Each successive level is highlighted in a different color. This makes it easy to spot matching delimiters, orient yourself in the code, and tell which statements are at a given depth.

(use-package rainbow-delimiters
 :commands
 (rainbow-delimiters-unmatched-face)
 :config
 ;; Pastels
 (set-face-attribute 'rainbow-delimiters-depth-1-face nil :foreground "#78c5d6")
 (set-face-attribute 'rainbow-delimiters-depth-2-face nil :foreground "#bf62a6")
 (set-face-attribute 'rainbow-delimiters-depth-3-face nil :foreground "#459ba8")
 (set-face-attribute 'rainbow-delimiters-depth-4-face nil :foreground "#e868a2")
 (set-face-attribute 'rainbow-delimiters-depth-5-face nil :foreground "#79c267")
 (set-face-attribute 'rainbow-delimiters-depth-6-face nil :foreground "#f28c33")
 (set-face-attribute 'rainbow-delimiters-depth-7-face nil :foreground "#c5d647")
 (set-face-attribute 'rainbow-delimiters-depth-8-face nil :foreground "#f5d63d")
 (set-face-attribute 'rainbow-delimiters-depth-9-face nil :foreground "#78c5d6")
 ;; Make unmatched parens stand out more
 (set-face-attribute
  'rainbow-delimiters-unmatched-face nil
   :foreground 'unspecified
   :inherit 'show-paren-mismatch
   :strike-through t)
 (set-face-foreground 'rainbow-delimiters-unmatched-face "magenta")
 :hook
 (prog-mode . rainbow-delimiters-mode)
 :diminish rainbow-delimiters-mode)

Rainbow identifiers

Rainbow identifier highlighting.

(use-package rainbow-identifiers
 :hook
 (prog-mode . rainbow-identifiers-mode)
 :diminish rainbow-identifiers-mode)

Rainbow mode (disabled)

This minor mode sets background color to strings that match color.

Disabled because it highlights things like #define MACROS.

(use-package rainbow-mode
 :diminish rainbow-mode
 :hook prog-mode
 :config
 (nmap
   :prefix my/leader
   "t r" 'rainbow-mode))

Idle highlight mode

Basically its the same as highlight-thing but seems to be smarter and less distracting.

(use-package idle-highlight-mode
 :custom
 (idle-highlight-idle-time 0.5)
 :hook
 (prog-mode . idle-highlight-mode)
 :config
 (nmap
   :prefix my/leader
   "t H" 'idle-highlight-mode))

Line highlight

Provides a local minor mode (toggled by M-x hl-line-mode) and a global minor mode (toggled by M-x global-hl-line-mode) to highlight, on a suitable terminal, the line on which point is.

(use-package hl-line
  :custom
  ;; Only highlight in selected window
  (hl-line-sticky-flag nil)
  (global-hl-line-sticky-flag nil)
  :config
  (set-face-background 'hl-line "#151515")
  (global-hl-line-mode)
  (nmap
    :prefix my/leader
    "t l" 'global-hl-line-mode))

Column highlight (slow)

Library required for the col-hightlight package.

(use-package vline
  :quelpa
  (vline :fetcher github :repo "emacsmirror/vline"))

This package highlights the current column. When you move the cursor, the highlighting follows (tracks the cursor), as long as the highlighting stays on.

(use-package col-highlight
  :after (vline)
  :quelpa
  (col-highlight :fetcher github :repo "emacsmirror/col-highlight")
  ;; :hook
  ;; (prog-mode . column-highlight-mode)
  :config
  (set-face-background 'col-highlight "#151515")
  (nmap
    :prefix my/leader
    "t c" 'column-highlight-mode))

Column marker

With this library you can highlight a column (vertical line) of text. In fact, you can highlight any number of such columns – 3 such highlight column markers are provided by default, but you can easily define more.

(use-package column-marker
  :quelpa
  (column-marker :fetcher github :repo "emacsmirror/column-marker"))

Hightlight todos

Highlights TODO and similar keywords in comments and strings. See the package repository for more info.

(use-package hl-todo
 :config
 (global-hl-todo-mode))

Highlight indentation (slow)

Provides two minor modes highlight-indentation-mode and highlight-indentation-current-column-mode:

  • highlight-indentation-mode - displays guidelines indentation (space indentation only).
  • highlight-indentation-current-column-mode - displays guidelines for the current-point indentation (space indentation only).

See the package repository for more info.

(use-package highlight-indentation
 :after general
 ;; :hook
 ;; (yaml-mode . highlight-indentation-mode)
 ;; (haskell-mode . highlight-indentation-mode)
 ;; (prog-mode . highlight-indentation-current-column-mode)
 :config
 ;; theme: zerodark
 ;; (set-face-background 'highlight-indentation-face "#24282f")
 ;; (set-face-background 'highlight-indentation-current-column-face "#22252c")
 ;; theme: grayscale dark
 (set-face-background 'highlight-indentation-face "#151515")
 (set-face-background 'highlight-indentation-current-column-face "#121212")
 (nmap
   :prefix my/leader
   "t i" 'highlight-indentation-mode
   "t I" 'highlight-indentation-current-column-mode)
 :diminish
 (highlight-indentation-mode
  highlight-indentation-current-column-mode))

Highlight leading spaces (disabled)

Highlight leading spaces that are part of the indentation. See the package repo for more info.

Breaks syntax highlighting.

(use-package highlight-leading-spaces
 :custom-face
 (highlight-leading-spaces ((t (:foreground "#2a2a2a"))))
 :config
 (nmap
   :prefix my/leader
   "t s" 'highlight-leading-spaces-mode))

Highlight numbers (disabled)

Minor mode that highlights numeric literals in source code.

(use-package highlight-numbers
 :hook
 (prog-mode . highlight-numbers-mode))

VI Tilde fringe (disabled)

Display tildes on empty lines in the Emacs fringe a la Vi. See the package repo for more info.

(use-package vi-tilde-fringe
 :config
 (global-vi-tilde-fringe-mode)
 :diminish vi-tilde-fringe-mode)

Fill column (disabled)

I keep it disabled, because it is too slow.

(use-package fill-column-indicator
 :config
 (setq fci-rule-column 120)
 (setq fci-rule-color "#141414")
 (setq fill-column 80))

All the icons

A utility package to collect various Icon Fonts and propertize them within Emacs.

Don’t forget to run M-x all-the-icons-install-fonts.

Disabled, it slows down dired.

(use-package all-the-icons
 :config
 (setq
   all-the-icons-mode-icon-alist
   `(,@all-the-icons-mode-icon-alist
     (package-menu-mode all-the-icons-octicon "package" :v-adjust 0.0)
     (jabber-chat-mode all-the-icons-material "chat" :v-adjust 0.0)
     (jabber-roster-mode all-the-icons-material "contacts" :v-adjust 0.0)
     (telega-chat-mode all-the-icons-fileicon "telegram" :v-adjust 0.0
                       :face all-the-icons-blue-alt)
     (telega-root-mode all-the-icons-material "contacts" :v-adjust 0.0))))

Emojify (disabled)

Add emoji support. This is useful when working with HTML.

(use-package emojify
 :hook
 (text-mode . emojify-mode))

Mode line

Simple-modeline (disabled)

(use-package simple-modeline
 ;; TODO: https://github.com/melpa/melpa/pull/6818
 :quelpa
 (simple-modeline :fetcher github :repo "gexplorer/simple-modeline")
  :hook (after-init . simple-modeline-mode))

Telephone-line (macos-only)

(use-package telephone-line
  :if (eq system-type 'darwin)
  :custom
  (telephone-line-primary-left-separator 'telephone-line-flat)
  (telephone-line-primary-right-separator 'telephone-line-flat)
  (telephone-line-secondary-left-separator 'telephone-line-flat)
  (telephone-line-secondary-right-separator 'telephone-line-flat)
  :init
  (setq
   telephone-line-lhs
   '((evil . (telephone-line-evil-tag-segment))
     (accent . (telephone-line-vc-segment
                telephone-line-erc-modified-channels-segment
                telephone-line-process-segment))
     (nil . (telephone-line-minor-mode-segment
             telephone-line-buffer-segment))))
  (setq
   telephone-line-rhs
   '((nil . (telephone-line-misc-info-segment))
     (accent . (telephone-line-major-mode-segment))
     (evil . (telephone-line-airline-position-segment))))
  :config
  :hook (after-init . telephone-line-mode))

Mood-line (disabled)

A minimal mode-line configuration that aims to replicate some of the features of the doom-modeline package.

(use-package mood-line
 :hook
 (after-init . mood-line-mode))

Spaceline (disabled)

A very cool mode line that I used previously.

(use-package spaceline
 :init
 (setq
  powerline-default-separator 'bar
  spaceline-highlight-face-func 'spaceline-highlight-face-evil-state)
 :config
 (require 'spaceline-config)
 (spaceline-spacemacs-theme))

Flycheck color (disabled)

Colors the mode-line according to the Flycheck state of the current buffer.

(use-package flycheck-color-mode-line
  :after (flycheck)
  :commands
  (flycheck-color-mode-line-mode)
  :hook
  (flycheck-mode . flycheck-color-mode-line-mode))

Indent info (disabled)

Display information about the current indentation settings.

(use-package indent-info
  :custom
  (indent-info-prefix " ")
  (indent-info-suffix " ")
  :config
  (global-indent-info-mode 1))

Moody + minions (gnu/linux-only)

Another option is moody + minions as an attractive minimalist mode line replacement.

Minions is a minor-mode menu for the mode line. This menu is intended as a replacement for the incomplete yet wide list of enabled minor-modes that is displayed in the mode line by default.

(use-package minions
 :if (eq system-type 'gnu/linux)
 :config
 (setq minions-mode-line-lighter "[+]")
 (minions-mode 1))

Provides utilities for displaying elements of the mode line as tabs and ribbons. It also provides replacements for a few built-in elements.

(use-package moody
 :if (eq system-type 'gnu/linux)
 :config
 (moody-replace-mode-line-buffer-identification)
 (moody-replace-vc-mode)
 (setq-default
  x-underline-at-descent-line t
  column-number-mode t))

Hide mode line

Support hiding the mode line, this can be useful for different modes displaying documents or presentation.

TODO: Fix this issue.

(use-package hide-mode-line
 :config
 (add-hook 'completion-list-mode-hook #'hide-mode-line-mode)
 (nmap
   :prefix my/leader
   "t m" 'global-hide-mode-line-mode))

Beacon

Visualizes cursor position. Slows down font-lock-mode significanly.

(use-package beacon
 :after (general)
 :demand t
 :commands (beacon-mode)
 :custom
 (beacon-size 12)
 (beacon-blink-delay 0.0)
 (beacon-blink-duration 0.5)
 (beacon-color "#ffd700")
 (beacon-blink-when-window-scrolls nil)
 (beacon-dont-blink-commands nil)
 :config
 (nmap
   :prefix my/leader
   "t b" 'beacon-mode)
 :diminish beacon-mode)

Evil

Main

(use-package evil
 :preface
 (defvar my/evil/esc-hook '(t)
   "A hook run after ESC is pressed in normal mode
   (invoked by `evil-force-normal-state').
   If a hook returns non-nil, all hooks after it are ignored.")
 (defun my/evil/attach-esc-hook ()
   "Run all escape hooks, if any returns non-nil, then stop there"
   (run-hook-with-args-until-success 'my/evil/esc-hook))
 :init
 (setq
  ;; Undo system Evil should use. If equal to ‘undo-tree’ or
  ;; ‘undo-fu’, those packages must be installed. If equal to
  ;; ‘undo-tree’, ‘undo-tree-mode’ must also be activated. If
  ;; equal to ‘undo-redo’, Evil uses commands natively available
  ;; in Emacs 28
  evil-undo-system 'undo-redo
  ;; evil-collection assumes evil-want-keybinding is set to nil
  ;; and evil-want-integration is set to t before loading evil
  ;; and evil-collection
  evil-want-keybinding nil
  evil-want-integration t
  ;; Restore missing C-u in evil so it scrolls up (like in Vim).
  ;; Otherwise C-u applies a prefix argument.
  evil-want-C-u-scroll t
  ;; C-w deletes a word in Insert state.
  evil-want-C-w-delete t
  ;; All changes made during insert state, including a possible
  ;; delete after a change operation, are collected in a single
  ;; undo step
  evil-want-fine-undo "no"
  ;; Inclusive visual character selection which ends at the
  ;; beginning or end of a line is turned into an exclusive
  ;; selection. Thus if the selected (inclusive) range ends at
  ;; the beginning of a line it is changed to not include the
  ;; first character of that line, and if the selected range
  ;; ends at the end of a line it is changed to not include the
  ;; newline character of that line
  evil-want-visual-char-semi-exclusive t
  ;; ‘Y’ yanks to the end of the line
  evil-want-Y-yank-to-eol t
  ;; Meaning which characters in a pattern are magic.
  ;; The meaning of those values is the same as in Vim
  evil-magic t
  ;; If non-nil abbrevs will be expanded when leaving insert
  ;; state like in Vim, if ‘abbrev-mode’ is on
  evil-want-abbrev-expand-on-insert-exit nil
  ;; Signal the current state in the echo area
  evil-echo-state t
  ;; The = operator converts between leading tabs and spaces.
  ;; Whether tabs are converted to spaces or vice versa depends
  ;; on the value of ‘indent-tabs-mode’
  evil-indent-convert-tabs t
  ;; Vim-style backslash codes are supported in search patterns
  evil-ex-search-vim-style-regexp t
  ;; Substitute patterns are global by default
  evil-ex-substitute-global t
  ;; Column range for ex commands
  evil-ex-visual-char-range t
  ;; Use evil interactive search module instead of isearch
  evil-search-module 'evil-search
  ;; If nil then * and # search for words otherwise for symbols
  evil-symbol-word-search t
  ;; Don't use emacs mode for ibuffer
  ;; evil-emacs-state-modes (delq 'ibuffer-mode evil-emacs-state-modes)
  ;; Cursors
  evil-default-cursor (face-background 'cursor nil t)
  evil-normal-state-cursor 'box
  evil-emacs-state-cursor `(,(face-foreground 'warning) box)
  evil-insert-state-cursor 'bar
  evil-visual-state-cursor 'box)
 :config
 ;; Enable evil-mode globally,
 ;; good for ex-vimmers like me
 (evil-mode t)
 ;; Special
 (evil-make-overriding-map special-mode-map 'normal)
 ;; Compilation
 (evil-set-initial-state 'compilation-mode 'normal)
 ;; Occur
 (evil-make-overriding-map occur-mode-map 'normal)
 (evil-set-initial-state 'occur-mode 'normal)
 (advice-add 'evil-force-normal-state :after 'my/evil/attach-esc-hook)
 ;; Unbind  evil-paste-pop and evil-paste-pop-next
 ;; which breaks evil-mc
 (with-eval-after-load 'evil-maps
   (define-key evil-normal-state-map (kbd "C-n") nil)
   (define-key evil-normal-state-map (kbd "C-p") nil)))

Evil collection

A collection of Evil bindings for the parts of Emacs that Evil does not cover properly by default.

(use-package evil-collection
  :init
  (setq
   ;; If you don't need everything - uncomment and add everything you want
   ;; evil-collection-mode-list '()

   ;; Don't enable vim key bindings in minibuffer
   ;; its a default setting, just want it to be explicitly stated here
   evil-collection-setup-minibuffer nil)
  :config
  (evil-collection-init)
  (nmap
    "C-M-l" 'evil-window-increase-width
    "C-M-h" 'evil-window-decrease-width
    "C-M-k" 'evil-window-increase-height
    "C-M-j" 'evil-window-decrease-height))

Multiple cursors

Provides multiple cursors functionality for Emacs when used with evil-mode.

(use-package evil-mc
 :after (general evil)
 :demand t
 :commands
 ;; Enable evil-mc mode for all buffers
 (global-evil-mc-mode)
 :preface
 (defun my/evil-mc/esc ()
   "Clear evil-mc cursors and restore state."
   (when (evil-mc-has-cursors-p)
     (evil-mc-undo-all-cursors)
     (evil-mc-resume-cursors)
     t))
 :config
 (global-evil-mc-mode 1)
 (add-hook 'my/evil/esc-hook 'my/evil-mc/esc)
 (mmap
   "C-n" 'evil-mc-make-and-goto-next-match)
 (when (eq system-type 'darwin)
   ;; Unbind isearch commands
   (unbind-key "s-d")
   (unbind-key "s-g")
   (mmap
     "s-d" 'evil-mc-make-and-goto-next-match
     "s-D" 'evil-mc-make-all-cursors))
 :diminish evil-mc-mode)

Matchit

Vim matchit.vim by Benji Fisher is ported into Emacs.

Press “%” to jump between matched tags in Emacs. For example, in HTML “<div>” and “</div>” are a pair of tags. Many modern languages are supported.

(use-package evil-matchit
 :after evil
 :demand t
 :commands
 (evilmi-jump-items
  evilmi-text-object
  global-evil-matchit-mode)
 :config
 (global-evil-matchit-mode 1))

Smartparens

(use-package evil-smartparens
  :after (smartparens)
  :config
  (add-hook 'smartparens-enabled-hook #'evil-smartparens-mode))

String inflection

Evil operator to cycle text objects through camelCase, kebab-case, snake_case and UPPER_CASE.

The keybinding is g~. For example, try using g~io.

(use-package evil-string-inflection)

Surround

This package emulates surround.vim by Tim Pope. The functionality is wrapped into a minor mode.

This package uses Evil as its vi layer.

(use-package evil-surround
 :after evil
 :demand t
 :commands
 (global-evil-surround-mode
   evil-surround-edit
   evil-Surround-edit
   evil-surround-region)
 :config
 (global-evil-surround-mode 1))

Visualstar

This is a port of one of the many visual-star plugins for Vim to work with evil-mode.

(use-package evil-visualstar
 :after evil
 :commands
 (global-evil-visualstar-mode
   evil-visualstar/begin-search
   evil-visualstar/begin-search-forward
   evil-visualstar/begin-search-backward)
 :config
 (global-evil-visualstar-mode))

Vimish fold

Adds standard vim keybindings of zf and zd to create and delete folds (via vimish-fold) respectively. Also hooks into evil so the usual vim keybindings for fold toggling (za), opening (zo), closing (zc) etc all work as expected with vimish-fold.

Finally, also supports navigation between folds using zj and zk.

(use-package evil-vimish-fold
  :after (evil vimish-fold)
  :commands
  (evil-vimish-fold-mode)
  :config
  (evil-vimish-fold-mode 1)
  :hook
  (prog-mode . evil-vimish-fold-mode)
  (text-mode . evil-vimish-fold-mode)
  :diminish evil-vimish-fold-mode)

Commentary

Comments stuff out. A port of vim-commentary.

(use-package evil-commentary
 :after evil
 :demand t
 :commands
 (evil-commentary-mode
  evil-commentary-yank
  evil-commentary-line)
 :config (evil-commentary-mode)
 :diminish evil-commentary-mode)

Numbers

  • Increment / Decrement binary, octal, decimal and hex literals
  • Works like C-a~/~C-x in vim, i.e. searches for number up to eol and then increments or decrements and keep zero padding up (unlike in vim)
  • When a region is active, as in evil’s visual mode, all the numbers within that region will be incremented/decremented (unlike in vim)
(use-package evil-numbers
  :after (evil general)
  :demand t
  :config
  (nmap
    "C-c =" 'evil-numbers/inc-at-pt
    "C-c -" 'evil-numbers/dec-at-pt))

Bookmarks

Most of the keybindings are set by the evil-collection package.

(use-package bookmark
  :after general
  :init
  (setq
   bookmark-version-control t
   bookmark-save-flag 1)
  :config
  ;; Uncomment if you prefer going straight to bookmarks on Emacs startup.
  ;; (bookmark-bmenu-list)
  ;; (switch-to-buffer "*Bookmark List*")
  (nmap
    :prefix my/leader
    "b" 'bookmark-set))

Completion

Company

Some of the key bindings are provided by the evil-collection.

(use-package company
 :after (lsp-mode)
 :preface
 (defun my/company-mode/setup-faces ()
   "Style company-mode nicely"
   (interactive)
   (let* ((bg (face-attribute 'default :background))
          (bg-light (color-lighten-name bg 2))
          (bg-lighter (color-lighten-name bg 5))
          (bg-lightest (color-lighten-name bg 10))
          (ac (face-attribute 'match :foreground)))
     (custom-set-faces
      `(company-tooltip
        ((t (:inherit default :background ,bg-light))))
      `(company-scrollbar-bg ((t (:background ,bg-lightest))))
      `(company-scrollbar-fg ((t (:background ,bg-lighter))))
      `(company-tooltip-selection
        ((t (:inherit font-lock-function-name-face))))
      `(company-tooltip-common
        ((t (:inherit font-lock-constant-face))))
      `(company-preview-common
        ((t (:foreground ,ac :background ,bg-lightest)))))))
 :hook
 ((lsp-mode org-mode) . company-mode)
 ;; NOTE: Uncomment to use company-mode in all buffers
 ;; (after-init . global-company-mode)
 :custom
 ;; Disable in org
 ;; (company-global-modes '(not org-mode))
 (company-dabbrev-ignore-case nil)
 (company-dabbrev-code-ignore-case nil)
 (company-dabbrev-downcase nil)
 (company-idle-delay 0.2 "adjust this setting according to your typing speed")
 (company-minimum-prefix-length 1)
 (company-tooltip-align-annotations t)

 :config
 (my/company-mode/setup-faces)
 (unbind-key "C-SPC")
 (imap
  "C-SPC" 'company-complete
  "M-SPC" 'company-complete)
 (general-define-key
  :keymaps 'company-active-map
  "C-j" 'company-select-next-or-abort
  "C-k" 'company-select-previous-or-abort
  "C-o" 'company-other-backend
  "C-f" 'company-abort
  "C-d" 'company-show-doc-buffer
  "C-w" 'backward-kill-word)
 :diminish company-mode)

Company quickhelp

(use-package company-quickhelp
 :after company
 :custom
 (company-quickhelp-delay 3)
 :config
 (general-define-key
  :keymaps 'company-active-map
  "C-c h" 'company-quickhelp-manual-begin))

Flycheck

Mode

On-the-fly syntax checking for GNU Emacs. See the flycheck.org for more info.

(use-package flycheck
  :after (general)
  :demand t
  :commands
  (global-flycheck-mode)
  :init
  (setq-default
   flycheck-disabled-checkers
   '(emacs-lisp-checkdoc
     javascript-jshint
     haskell-stack-ghc
     haskell-ghc
     haskell-hlint))
  (setq
   flycheck-highlighting-mode 'lines
   flycheck-indication-mode 'left-fringe
   flycheck-mode-line-prefix "fly"
   flycheck-javascript-eslint-executable "eslint_d")
  :config
  (global-flycheck-mode 1)
  (nmap
    :prefix my/leader
    "t e" 'flycheck-mode
    "e e" 'flycheck-list-errors
    "e c" 'flycheck-clear
    "e i" 'flycheck-manual
    "e C" 'flycheck-compile
    "e n" 'flycheck-next-error
    "e p" 'flycheck-previous-error
    "e b" 'flycheck-buffer
    "e s" 'flycheck-select-checker
    "e v" 'flycheck-verify-setup
    "e V" 'flycheck-verify-checker)
  ;; Make the error list display like similar lists in contemporary IDEs
  ;; like VisualStudio, Eclipse, etc.
  (add-to-list
   'display-buffer-alist
   `(,(rx bos "*errors*" eos)
     ;; (display-buffer-reuse-window
     ;;  display-buffer-in-side-window)
     (side . bottom)
     (reusable-frames . visible)
     (window-height . 0.33)))
  (unbind-key "C-j" flycheck-error-list-mode-map)
  :diminish flycheck-mode)

Flycheck indicator

An Emacs minor-mode to get a fancy mode line indicator for Flycheck.

(use-package flycheck-indicator
  :hook (flycheck-mode . flycheck-indicator-mode))

Posframe (disabled)

Displays flycheck error messages via posframe. I prefer to enable it manually, when needed.

(use-package flycheck-posframe
  :after (flycheck)
  :config
  (flycheck-posframe-configure-pretty-defaults)
  (add-to-list
   'flycheck-posframe-inhibit-functions
   #'(lambda () (bound-and-true-p company-backend)))
  (setq flycheck-posframe-border-width 1)
  (set-face-attribute 'flycheck-posframe-background-face nil :inherit nil :background "#111")
  (set-face-attribute 'flycheck-posframe-error-face nil :inherit nil :foreground "red")
  (set-face-attribute 'flycheck-posframe-warning-face nil :foreground "skyblue")
  (set-face-attribute 'flycheck-posframe-info-face nil :foreground "white")
  :custom-face (flycheck-posframe-border-face ((t (:foreground "#353535"))))
  ;; :hook
  ;; (flycheck-mode . flycheck-posframe-mode)
)

Proselint (disabled)

Add prose linting to Flycheck. Depends on the proselint command line tool.

TODO: Find a way to disable it in code regions.

(with-eval-after-load 'flycheck
  (flycheck-define-checker proselint
    "A linter for prose."
    :command ("proselint" source-inplace)
    :error-patterns
    ((warning line-start (file-name) ":" line ":" column ": "
              (id (one-or-more (not (any " "))))
              (message) line-end))
    :modes (text-mode markdown-mode gfm-mode))
  (add-to-list 'flycheck-checkers 'proselint))

Flyspell

Enables on-the-fly spell checking in Emacs by the means of a minor mode.

TODO: Cycle through different languages

(use-package flyspell
  :ensure nil
  :after (general ispell)
  :custom
  (flyspell-delay 1)
  (flyspell-always-use-popup t)
  :init
  (setq
   flyspell-use-meta-tab nil
   flyspell-mode-line-string ""
   flyspell-auto-correct-binding (kbd ""))
  :hook
  (;; Don’t check comments, thats too annoying
   ;; (prog-mode . flyspell-prog-mode)
   ;; Might be slow in large org-files
   (org-mode . (lambda () (flyspell-mode -1)))
   ((gfm-mode text-mode git-commit-mode) . flyspell-mode))
  :config
  (unbind-key "C-." flyspell-mode-map)
  (nmap
    :prefix my/leader
    "t f" 'flyspell-mode)
  (nmap
    "C-c i b" 'flyspell-buffer
    "C-c i f" 'flyspell-mode))

Dictionary

Powerthesaurus

Powerthesaurus integration for Emacs.

(use-package powerthesaurus
 :after general
 :config
 (nmap
   :prefix my/leader
   "L" 'powerthesaurus-lookup-word-at-point))

If you got the error in process filter chances are the wordnik.com is down, try again later ;)

Define word

Display the definition of word at point in Emacs.

(use-package define-word
 :after general
 :config
 (nmap
   :prefix my/leader
   "D" 'define-word-at-point))

Wordnut

Interface to WordNet lexical database. Uses wn (wordnet) for searching local wordnet db; injects results into *WordNut* buffer.

(use-package wordnut
  :if (executable-find "wordnet")
  :config
  (nmap
    :prefix my/leader
    "d" 'wordnut-lookup-current-word))

Synosaurus (disabled)

(use-package synosaurus
 :after (general)
 :config
 (nmap
  :prefix my/leader
  "; ;" 'synosaurus-lookup
  "; '" 'synosaurus-choose-and-replace))

Dired

Constants (file extensions)

(defconst my/dired-html-files-extensions
  '("htm" "html" "xhtml" "phtml" "haml"
    "asp" "aspx" "xaml" "php" "jsp")
  "HTML files extensions")
(defconst my/dired-styles-files-extensions
  '("css" "sass" "scss" "less")
  "Styles files extensions")
(defconst my/dired-xml-files-extensions
  '("xml" "xsd" "xsl" "xslt" "wsdl")
  "XML files extensions")
(defconst my/dired-document-files-extensions
  '("doc" "docx" "ppt" "pptx" "xls" "xlsx"
    "csv" "rtf" "djvu" "epub""wps" "pdf" "texi" "tex"
    "odt" "ott" "odp" "otp" "ods" "ots"
    "odg" "otg")
  "Document files extensions")
(defconst my/dired-text-files-extensions
  '("txt" "md" "org" "ini" "conf" "rc" "vim" "vimrc" "exrc")
  "Text files extensions")
(defconst my/dired-sh-files-extensions
  '("sh" "bash" "zsh" "fish" "csh" "ksh"
    "awk" "ps1" "psm1" "psd1" "bat" "cmd")
  "Shell files extensions")
(defconst my/dired-source-files-extensions
  '("py" "c" "cc" "cpp" "cxx" "c++" "h" "hpp" "hxx" "h++"
    "java" "pl" "rb" "el" "pl" "pm" "l" "jl" "f90" "f95"
    "R" "php" "hs" "purs" "coffee" "ts" "js" "json" "m" "mm"
    "ml" "asm" "vb" "ex" "exs" "erl" "go" "clj" "cljs"
    "sql" "yml" "yaml" "toml" "rs" "idr" "cs" "mk" "make" "swift"
    "rake" "lua")
  "Source files extensions")
(defconst my/dired-compressed-files-extensions
  '("zip" "bz2" "tgz" "txz" "gz" "xz" "z" "Z"
    "war" "ear" "rar" "sar" "xpi" "apk" "tar" "7z"
    "gzip" "001" "ace" "lz"
    "lzma" "bzip2" "cab" "jar" "iso")
  "Compressed files extensions")
(defconst my/dired-image-files-extensions
  '("bmp" "jpg" "jpeg" "gif" "png" "tiff"
    "ico" "svg" "psd" "pcd" "raw" "exif"
    "BMP" "JPG" "PNG")
  "Image files extensions")
(defconst my/dired-audio-files-extensions
  '("mp3" "MP3" "ogg" "OGG" "flac" "FLAC" "wav" "WAV")
  "Dired Audio files extensions")
(defconst my/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")
(defconst my/dired-misc-files-extensions
  '("DS_Store" "projectile" "cache" "elc" "dat" "meta")
  "Misc files extensions")

Dired

Setup dired.

(use-package dired
 :after general
 :ensure nil
 :custom
 ;; Do not bind C-x C-j since it's used by jabber.el
 (dired-bind-jump nil)
 :init
 ;; Prevents dired from creating an annoying popup
 ;; when dired-find-alternate-file is called
 (setq
  ;; If there is a dired buffer displayed in the next window,
  ;; use its current directory
  dired-dwim-target t
  dired-omit-verbose nil
  ;; human readable filesize
  dired-listing-switches "-ahlv"
  ;; recursive copy & delete
  dired-recursive-deletes 'always
  dired-recursive-copies 'always)
 (setq
  dired-garbage-files-regexp
  "\\.\\(?:aux\\|out\\|bak\\|dvi\\|log\\|orig\\|rej\\|toc\\|class\\)\\'")
 ;; Enable omit mode
 ;; (setq-default dired-omit-mode t)
 ;; Hide autosave files
 ;; (setq-default dired-omit-files "^\\.?#")
 ;; Uncomment the line below if you want to hide dot files
 ;; (setq-default dired-omit-files (concat dired-omit-files "\\|^\\.[^\\.]"))
 (setq
  dired-omit-extensions
  '("CVS" "RCS" ".o" "~" ".bin" ".lbin" ".fasl" ".ufsl" ".a" ".ln" ".blg"
    ".bbl" ".elc" ".lof" ".glo" ".idx" ".aux" ".glob" ".vo"
    ".lot" ".fmt" ".tfm" ".class" ".DS_Store"
    ".fas" ".lib" ".x86f" ".sparcf" ".lo" ".la" ".toc" ".aux" ".cp" ".fn"
    ".ky" ".pg" ".tp" ".vr" ".cps" ".fns" ".kys" ".pgs" ".tps" ".vrs"
    ".idx" ".lof" ".lot" ".glo" ".blg" ".bbl" ".cp" ".cps" ".fn" ".fns"
    ".ky" ".kys" ".pg" ".pgs" ".tp" ".tps" ".vr" ".vrs" ".gv" ".gv.pdf"))
 ;; macOS ls command doesn't support "--dired" option
 (when (string= system-type "darwin")
   (setq dired-use-ls-dired nil))
 :config
 (put 'dired-find-alternate-file 'disabled nil)
 (nmap
   :prefix my/leader
   "j" 'dired-jump)
 (nmap 'dired-mode-map
   "gg" 'evil-goto-first-line
   "G" 'evil-goto-line
   "b" 'bookmark-set)
 :hook
 (dired-mode . dired-hide-details-mode)
 (dired-mode . hl-line-mode)
 :diminish dired-mode)

Dired hide dotfiles

Allows to easily show/hide dotfiles.

(use-package dired-hide-dotfiles
 :config
 (nmap 'dired-mode-map
   "." 'dired-hide-dotfiles-mode)
 :hook
 (dired-mode . dired-hide-dotfiles-mode))

Dired fl

Extra Emacs font lock rules for a more colourful dired. See the package repo for more info.

(use-package diredfl
 :after dired
 :hook
 (dired-mode . diredfl-mode))

Dired rsync

Adds a single command dired-rsync which allows the user to copy marked files in a dired buffer via rsync. This is useful, especially for large files, because the copy happens in the background and doesn’t lock up Emacs. It is also more efficient than using tramps own encoding methods for moving data between systems.

(use-package dired-rsync
 :config
 (nmap 'dired-mode-map
   "r" 'dired-rsync))

Dired launch

Launch an external application from dired.

(use-package dired-launch
 :hook
 (dired-mode . dired-launch-mode)
 :init
 ;; Use xdg-open as the default launcher
 (setq dired-launch-default-launcher '("xdg-open"))
 :config
 (nmap 'dired-launch-mode-map
   "l" 'dired-launch-command))

Dired+

Setup dired+.

(use-package dired+
 :after dired
 :quelpa
 (dired+ :fetcher github :repo "emacsmirror/dired-plus")
 :commands
 (dired-read-dir-and-switches)
 :init
 (setq
  diredp-hide-details-initially-flag nil
  diredp-hide-details-propagate-flag nil))

Dired hacks.

Collection of useful dired additions.

Prerequisites

First, we need to install some dired hacks dependencies.

(use-package dash)
(use-package dired-hacks-utils
 :after dired
 :demand t)

Filter

The filtering system is designed after ibuffer: every dired buffer has associated “filter stack” where user can push filters (predicates). These filters are by default logically “anded”, meaning, only the files satsifying all the predicates are shown.

(use-package dired-filter
 :after dired
 :hook
 (dired-mode . dired-filter-group-mode)
 :init
 (setq
  dired-filter-keep-expanded-subtrees nil
  dired-filter-group-saved-groups
  '(("default"
     ("video" (extension "mkv" "avi" "mp4" "webm"))
     ("archives" (extension "zip" "rar" "gz" "bz2" "tar"))
     ("pdf" (extension "pdf"))
     ("tex" (extension "tex" "bib"))
     ("js" (extension "js"))
     ("ts" (extension "ts"))
     ("json" (extension "json"))
     ("styles" (extension "css" "scss" "sass" "less"))
     ("html" (extension "html"))
     ("haskell" (extension "hs"))
     ("idris" (extension "idr"))
     ("purescript" (extension "purs"))
     ("c/c++"
      (extension
       "c" "cc" "cpp" "cxx" "c++"
       "h" "hpp" "hxx" "h++"))
     ("org" (extension "org"))
     ("lisp" (extension "el"))
     ("word" (extension "docx" "doc"))
     ("excel" (extension "xlsx" "xls"))
     ("text" (extension "txt"))
     ("svg" (extension "svg"))
     ("shell"
      (extension
       "sh" "bash" "zsh" "fish" "csh" "ksh"
       "awk" "ps1" "psm1" "psd1" "bat" "cmd"))
     ("audio"
      (extension
       "mp3" "ogg" "flac" "wav"))
     ("img"
      (extension
       "bmp" "jpg" "jpeg" "gif" "png" "tiff"
       "ico" "svg" "psd" "pcd" "raw" "exif")))))
 (nmap 'dired-mode-map
   "/" 'dired-filter-map
   "C-c C-t" 'dired-filter-group-toggle-header
   "C-c C-g" 'dired-filter-group-mode))

Avfs

(use-package dired-avfs
 :after (dired dired-hack-utils))

Open

(use-package dired-open
 :after (dired dired-hack-utils))

Narrow

(use-package dired-narrow
 :after (general dired dired-hack-utils)
 :config
 (nmap 'dired-mode-map
   "," 'dired-narrow))

Peep dired

Peep at files in another window from dired buffers.

(use-package peep-dired
 :after (dired general)
 :preface
 (defconst my/peep-dired/ignored-extensions
   (append
    my/dired-document-files-extensions
    my/dired-compressed-files-extensions
    my/dired-image-files-extensions
    my/dired-audio-files-extensions
    my/dired-video-files-extensions
    my/dired-misc-files-extensions))
 :hook
 (peep-dired . evil-normalize-keymaps)
 :init
 (setq
  peep-dired-ignored-extensions my/peep-dired/ignored-extensions
  peep-dired-cleanup-on-disable t
  peep-dired-enable-on-directories t)
 :config
 (nmap 'dired-mode-map
   "C-c C-v" 'peep-dired)
 (general-define-key
  :states '(normal)
  :keymaps 'peep-dired-mode-map
  "j" 'peep-dired-next-file
  "k" 'peep-dired-prev-file))

Icons (disabled)

Disabled, slows down dired.

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

Navigation

Treemacs

Mode

A tree layout file explorer for Emacs.

(use-package treemacs
  :defer t
  :after (general)
  :init
  (with-eval-after-load 'winum
    (define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
  :config
  (progn
    (setq treemacs-no-png-images t)

    ;; The default width and height of the icons is 22 pixels.
    (treemacs-resize-icons 14)

    (treemacs-follow-mode t)
    (treemacs-filewatch-mode t)
    (treemacs-fringe-indicator-mode 'always)
    (pcase (cons (not (null (executable-find "git")))
                 (not (null treemacs-python-executable)))
      (`(t . t)
       (treemacs-git-mode 'deferred))
      (`(t . _)
       (treemacs-git-mode 'simple))))
  (nmap
    :prefix my/leader
    "r" 'treemacs-select-window
    "q" 'treemacs))

Evil

Evil mode compatibility.

(use-package treemacs-evil
  :after (treemacs evil))

Projectile

(use-package treemacs-projectile
  :after (treemacs projectile))

Magit

(use-package treemacs-magit
  :after (treemacs magit))

Icons (disabled)

Treemacs icons for dired. Code is based on all-the-icons-dired.el.

(use-package treemacs-icons-dired
  :after (treemacs dired)
  :config (treemacs-icons-dired-mode))

Persp (disabled)

(use-package treemacs-persp    ;; treemacs-perspective if you use perspective.el vs. persp-mode
  :after (treemacs persp-mode) ;; or perspective vs. persp-mode
  :config (treemacs-set-scope-type 'Perspectives))

Ace window

Quickly switch between windows (splits).

When there are two windows, ace-window will call other-window. If there are more, each window will have the first character of its window label highlighted at the upper left of the window.

See the package repo for more info.

(use-package ace-window
 :custom
 (aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l) "Use home row for selecting.")
 (aw-scope 'frame "Highlight only current frame.")
 :config
 (nmap
   :prefix my/leader
   "w" 'ace-window))

Windows

Winner

Undo/redo window layout (split pane) config.

(use-package winner
 :demand t
 :init
 (setq
  winner-dont-bind-my-keys t
  winner-boring-buffers
  '("*Completions*"
    "*Compile-Log*"
    "*inferior-lisp*"
    "*Fuzzy Completions*"
    "*Apropos*"
    "*Help*"
    "*cvs*"
    "*Buffer List*"
    "*Ibuffer*"
    "*esh command on file*"))
 :config
 (winner-mode 1)
 :config
 (nmap
   :prefix my/leader
   "U" 'winner-undo
   "R" 'winner-redo)
 (when (eq system-type 'darwin)
   (general-define-key
    "C-s-[" 'winner-undo
    "C-s-]" 'winner-redo)))

Transpose frame

Provides some interactive functions which allows users to transpose windows arrangement in currently selected frame.

(use-package transpose-frame
  :config
  (nmap
    "C-M-SPC" 'transpose-frame
    "C-M-u" 'flip-frame
    "C-M-i" 'flip-frame
    "C-M-y" 'flop-frame
    "C-M-o" 'flop-frame))

Zoom

Zoom a window to display as a single window temporarily.

(use-package zoom-window
  :custom
  (zoom-window-mode-line-color "#000000")
  :config
  (nmap
    :prefix my/leader
    "RET" 'zoom-window-zoom))

Expand region

Increases the selected region by semantic units.

(use-package expand-region
 :after (general)
 :config
 (vmap
   "v" 'er/expand-region)
 (when (eq system-type 'darwin)
   (vmap
     "s-'" 'er/expand-region)))

Ivy

Setup ivy.

(use-package ivy
  :preface
  (defun my/ivy/switch-buffer-occur ()
    "Occur function for `ivy-switch-buffer' using `ibuffer'."
    (ibuffer nil (buffer-name) (list (cons 'name ivy--old-re))))
  :commands
  (ivy-mode ivy-set-occur)
  :custom
  (ivy-count-format "%d/%d " "Show anzu-like counter")
  :custom-face
  ;; (ivy-current-match ((t (:inherit 'hl-line))))
  ;; TODO: Make this theme-dependent (use :inherit)
  (ivy-current-match ((t (:background "#333333" :foreground "#fff"))))
  :init
  (setq
   ;; Enable bookmarks and recentf
   ;; (add 'recentf-mode' and bookmarks to 'ivy-switch-buffer')
   ivy-use-virtual-buffers t
   ;; Display full buffer name
   ivy-virtual-abbreviate 'full
   ;; Number of result lines to display
   ivy-height 12
   ;; Current input becomes selectable as a candidate
   ;; solves the issue of creating a file or
   ;; a directory `foo` when a file `foobar` already exists
   ;; another way is to use C-M-j
   ivy-use-selectable-prompt t
   ;; Wrap around ivy results
   ivy-wrap t
   ;; Omit ^ at the beginning of regexp
   ivy-initial-inputs-alist nil)
  :config
  (ivy-mode 1)
  ;; Enable fuzzy searching everywhere except:
  ;; - Switching buffers with Ivy
  ;; - Swiper
  ;; - Counsel projectile (find-file)
  (setq
   ivy-re-builders-alist
   '((swiper . ivy--regex-plus)
     (swiper-isearch . regexp-quote)
     (ivy-switch-buffer . ivy--regex-plus)
     (counsel-projectile-find-file . ivy--regex-plus)))
  (ivy-set-occur 'ivy-switch-buffer 'my/ivy/switch-buffer-occur)
  (nmap
    :prefix my/leader
    "b" 'ivy-switch-buffer)
  (nmap
    "C-c v" 'ivy-push-view
    "C-c V" 'ivy-pop-view)
  (when (eq system-type 'darwin)
    (general-define-key
     "s-b" 'ivy-switch-buffer
     "M-s-b" 'ivy-resume))
  (general-define-key
   :keymaps 'ivy-minibuffer-map
   "C-t" 'ivy-toggle-fuzzy
   "C-j" 'ivy-next-line
   "C-k" 'ivy-previous-line
   "C-n" 'ivy-next-history-element
   "C-p" 'ivy-previous-history-element
   "<C-return>" 'ivy-immediate-done
   "C-l" 'ivy-immediate-done
   "C-w" 'ivy-backward-kill-word)
  :diminish ivy-mode)

Ivy posframe (disabled)

It doesn’t work with evil-mode.

(use-package ivy-posframe
  :after (posframe)
  :config
  (setq ivy-posframe-height-alist
        '((swiper . 20)
          (t. 20)))

  (setq
   ivy-posframe-display-functions-alist
   '((swiper . nil)
     (counsel-bookmark . ivy-posframe-display-at-frame-center)
     (counsel-find-file . ivy-posframe-display-at-frame-center)
     (counsel-git-grep . ivy-posframe-display-at-frame-center)
     (counsel-package . ivy-posframe-display-at-frame-center)
     (counsel-load-theme . ivy-posframe-display-at-frame-center)
     (counsel-rg . ivy-posframe-display-at-frame-center)
     (counsel-fzf . ivy-posframe-display-at-frame-center)
     (counsel-imenu . ivy-posframe-display-at-frame-center)
     (counsel-describe-variable . ivy-posframe-display-at-frame-center)
     (counsel-describe-face . ivy-posframe-display-at-frame-center)
     (counsel-describe-function . ivy-posframe-display-at-frame-center)
     (counsel-unicode-char . ivy-posframe-display-at-frame-top-center)
     (counsel-ace-link . ivy-posframe-display-at-frame-top-center)
     (complete-symbol . ivy-posframe-display-at-point)
     (counsel-M-x . ivy-posframe-display-at-frame-center)
     (t . ivy-posframe-display)))
  (ivy-posframe-mode 1))

Ivy icons (disabled)

(use-package all-the-icons-ivy
 :after (ivy projectile)
 :commands
 (all-the-icons-ivy-setup)
 :custom
 (all-the-icons-ivy-buffer-commands '() "Don't use for buffers.")
 (all-the-icons-ivy-file-commands
  '(counsel-find-file
    counsel-file-jump
    counsel-recentf
    counsel-projectile-find-file
    counsel-projectile-find-dir) "Prettify more commands.")
 :config
 (all-the-icons-ivy-setup))

Rich

More friendly interface for ivy. Here is the package repo.

(use-package ivy-rich
 :after ivy
 :commands
 ivy-rich-mode
 :init
 (setq
  ;; To abbreviate paths using abbreviate-file-name
  ;; (e.g. replace “/home/username” with “~”)
  ivy-rich-path-style 'abbrev)
 :config
 (ivy-rich-mode 1))

Xref

Use Ivy as the interface to select from xref candidates.

(use-package ivy-xref
 :init
  ;; xref initialization is different in Emacs 27 - there are two different
  ;; variables which can be set rather than just one
  (when (>= emacs-major-version 27)
    (setq xref-show-definitions-function #'ivy-xref-show-defs))
  ;; Necessary in Emacs <27. In Emacs 27 it will affect all xref-based
  ;; commands other than xref-find-definitions (e.g. project-find-regexp)
  ;; as well
  (setq xref-show-xrefs-function #'ivy-xref-show-xrefs))

Flyspell correct

(use-package flyspell-correct-ivy
 :after (general flyspell ivy)
 :demand t
 :init
 (setq flyspell-correct-interface 'flyspell-correct-ivy)
 :config
 (nmap 'flyspell-mode-map
   "C-;" 'flyspell-correct-next))

IBuffer VC

Lets you:

  • Group your buffers by their parent vc root directory
  • See the VC status of the associated files
  • Sort buffers by their VC status
  • Display buffer filenames that are relative to their VC root
(use-package ibuffer-vc
  :custom
  (ibuffer-formats
   '((mark modified read-only vc-status-mini " "
           (name 18 18 :left :elide)
           " "
           (size 9 -1 :right)
           " "
           (mode 16 16 :left :elide)
           " "
           filename-and-process)) "include vc status info")
  :hook
  (ibuffer . (lambda ()
               (ibuffer-vc-set-filter-groups-by-vc-root)
               (unless (eq ibuffer-sorting-mode 'alphabetic)
                 (ibuffer-do-sort-by-alphabetic)))))

FZF

(use-package fzf)

Counsel

Setup counsel.

(use-package counsel
 :after general
 :init
 ;; Much faster than grep
 (setq
  counsel-git-cmd "rg --files"
  ;; Truncate all lines that are longer than 120 characters
  counsel-grep-base-command
  "rg -i -M 120 --no-heading --line-number --color never %s .")
 :config
 (nmap
   "C-f" 'counsel-imenu)
 (imap
   "C-," 'counsel-unicode-char)
 (nmap
   :prefix my/leader
   "f" 'counsel-rg
   "F" 'counsel-fzf
   "h v" 'counsel-describe-variable
   "h f" 'counsel-describe-function
   "h F" 'counsel-describe-face)
 (when (eq system-type 'darwin)
   (nmap
     "s-f" 'counsel-rg))
 (nmap
   "M-x" 'counsel-M-x)
 (nmap
   :prefix "C-x"
   "C-r" 'find-file
   "C-f" 'counsel-find-file
   "C-g" 'counsel-git-grep
   "p" 'counsel-package)
 (nmap
   :prefix my/leader
   my/leader 'counsel-M-x
   "T" 'counsel-load-theme
   "J" 'counsel-bookmark))

Ace link

Package for selecting a link to jump to.

(use-package ace-link
 :after (counsel)
 :commands
 (ace-link-setup-default)
 :config
 (nmap
   "C-c C-l" 'counsel-ace-link)
 :config
 (ace-link-setup-default))

Counsel etags

(use-package counsel-etags
  :after (general counsel)
  :init
  ;; Don't ask before rereading the TAGS files if they have changed
  (setq tags-revert-without-query t)
  ;; Don't warn when TAGS files are large
  (setq large-file-warning-threshold nil)
  ;; (setq counsel-etags-extra-tags-files '("./codex.tags"))
  ;; Use a custom command to update tags
  ;; (setq counsel-etags-update-tags-backend
  ;;       (lambda (src-dir) (shell-command "make tags")))
  :config
  (nmap
    "C-]" 'counsel-etags-find-tag-at-point)
  :init
  (add-hook 'prog-mode-hook
    (lambda ()
      (add-hook 'after-save-hook
        'counsel-etags-virtual-update-tags 'append 'local)))
  :config
  ;; (with-eval-after-load 'counsel-etags
  ;;   (push "TAGS" counsel-etags-ignore-filenames)
  ;;   (push "build" counsel-etags-ignore-directories))
  (setq counsel-etags-update-interval 60))

Counsel ffdata

Access your Firefox bookmarks and history in Emacs.

(use-package counsel-ffdata
 :after (general)
 :config
 (nmap
  :prefix my/leader
  "1" 'counsel-ffdata-firefox-history
  "2" 'counsel-ffdata-firefox-bookmarks))

Swiper

Ivy-enhanced alternative to isearch.

(use-package swiper
  :after general
  :init
  ;; Recenter after swiper is finished
  (setq swiper-action-recenter t)
  :config
  (general-define-key
   :keymaps 'swiper-map
   "C-r" 'swiper-query-replace)
  (general-define-key
   :keymaps 'ivy-mode-map
   "C-k" 'ivy-previous-line)
  (nmap
    "C-s" 'swiper))

Dumb jump

Dumb Jump is an Emacs “jump to definition” package with support for 40+ programming languages that favors “just working”.

(use-package dumb-jump
 :custom
 (dumb-jump-selector 'ivy)
 (dumb-jump-prefer-searcher 'ag)
 (nmap
   "C-c C-j" 'dumb-jump-go))

Avy

(use-package avy
 :config
 (mmap
   :prefix "C-c j"
   "c" 'avy-goto-char
   "w" 'avy-goto-word-1
   "l" 'avy-goto-line))

Avy zap (disabled)

Zap to char using `avy’. Disabled: I have no idea what it is doing.

(use-package avy-zap
 :bind
 ([remap zap-to-char] . avy-zap-to-char))

Avy flycheck

Jump to and fix syntax errors using flycheck with avy interface.

(use-package avy-flycheck
 :after (general avy flycheck)
 :commands
 avy-flycheck-setup
 :init
 (setq avy-flycheck-style 'pre)
 :config
 (avy-flycheck-setup)
 (nmap
   :prefix my/leader
   "n e" 'avy-flycheck-goto-error))

Tmux integration

Seamlessly navigate between Emacs and Tmux splits. See the package repo for more info.

(use-package navigate
 :quelpa
 (navigate :fetcher github :repo "keith/evil-tmux-navigator")
 :config
 (require 'navigate))

Projectile

Setup

(use-package projectile
 :after (general ivy)
 :init
 ;; Projectile requires this setting for ivy completion
 (setq
  projectile-indexing-method 'alien
  projectile-completion-system 'ivy
  ;; Useful for very large projects
  projectile-enable-caching t
  projectile-sort-order 'recently-active
  projectile-mode-line nil
  projectile-use-git-grep t
  projectile-file-exists-remote-cache-expire (* 10 60)
  projectile-file-exists-local-cache-expire (* 5 60)
  projectile-require-project-root nil
  projectile-globally-ignored-directories
  '(".git" ".svn" ".hg" "_darcs"
    "out" "output" "repl"
    "dist" "dist-newstyle"
    ".vagrant"
    "project" "target" "compiled" ".bundle"
    "*build" "jar"
    "venv" ".virtualenv"
    "*__pycache__*" "*.egg-info"
    ".tox" ".cache" ".cabal-sandbox" ".stack-work"
    ".emacs.d" "elpa" "site-lisp"
    "bin" "eclipse-bin" ".ensime_cache" ".idea"
    ".eunit" ".bzr"
    "vendor" "uploads" "assets"
    "node_modules" "bower_components"
    "_build" ".psci_modules" ".pulp-cache")
  projectile-globally-ignored-files
  '(".DS_Store" "TAGS" ".nrepl-port" "*.gz" "*.pyc" ".purs-repl"
    "*.jar" "*.tar.gz" "*.tgz" "*.zip" "package-lock.json"))
 :config
 ;; Use projectile everywhere
 (projectile-mode)
 ;; Remove the mode name for projectile-mode, but show the project name
 ;; :delight '(:eval (concat " " (projectile-project-name)))
 (nmap
   :prefix my/leader
   "!" 'projectile-run-async-shell-command-in-root
   "DEL" 'projectile-invalidate-cache)
 (nmap
   "C-SPC SPC" 'projectile-commander)
 :diminish projectile-mode)

Counsel

Projectile replacements.

(use-package counsel-projectile
 :after (counsel projectile general)
 :config
 (nmap
   "C-q" 'counsel-projectile-find-file
   "C-a" 'counsel-projectile-switch-to-buffer
   "C-p" 'counsel-projectile-switch-project))

Git

With editor

Makes it easy to use the Emacsclient as the $EDITOR of child processes, making sure they know how to call home. For remote processes a substitute is provided, which communicates with Emacs on standard output instead of using a socket as the Emacsclient does.

(use-package with-editor
 :config
 (nmap 'with-editor-mode-map
   ;; it closes the Magit's git-commit window
   ;; instead of switching to evil-normal-state
   ;; [escape] 'with-editor-cancel
   "RET" 'with-editor-finish)
 (evil-set-initial-state 'with-editor-mode 'insert))

Git messenger

Popup commit message for current line.

(use-package git-messenger
  :config
  (nmap
    :prefix my/leader
    "g m" 'git-messenger:popup-message))

Magit

(use-package magit
  :demand t
  :custom
  (magit-log-buffer-file-locked t)
  (magit-refs-show-commit-count 'all)
  (magit-save-repository-buffers 'dontask)
  (git-messenger:use-magit-popup t)
  :config
  ;; Unset pager as it is not supported properly inside emacs
  (setenv "GIT_PAGER" "")
  (nmap
    :prefix my/leader
    "g s" 'magit-status
    "g S" 'magit-stash
    "g l" 'magit-log
    "g B" 'magit-blame
    "g p" 'magit-pull
    "g P" 'magit-push
    "g b c" 'magit-branch-checkout
    "g b n" 'magit-branch-create
    "g c c" 'magit-commit-create
    "g c a" 'magit-commit-amend
    "g d d" 'magit-diff
    "g d f" 'magit-diff-buffer-file))

Magit todos (disabled)

Might be slow.

(use-package magit-todos
 :after (magit general)
 :commands
 (magit-todos-mode)
 :config
 (magit-todos-mode)
 (nmap
   :prefix my/leader
   "/" 'magit-todos-list))

Forge

Forge allows you to work with Git forges—such as Github and Gitlab—from the comfort of Magit and the rest of Emacs.

See the announcement and the manual for more info.

(use-package forge)

Git gutter

(use-package git-gutter
 :after (general)
 :demand t
 :commands
 (global-git-gutter-mode)
 :config
 ;; (global-git-gutter-mode)
 ;; (git-gutter:linum-setup)
 (custom-set-variables
  '(git-gutter:update-interval 2)
  '(git-gutter:modified-sign "*")
  '(git-gutter:added-sign "+")
  '(git-gutter:deleted-sign "-")
  '(git-gutter:hide-gutter nil))
 (set-face-foreground 'git-gutter:modified "#da8548")
 (set-face-foreground 'git-gutter:added "#98be65")
 (set-face-foreground 'git-gutter:deleted "#ff6c6b")
 (nmap
   :prefix my/leader
   "t g" 'git-gutter-mode)
 :diminish git-gutter-mode)

Time machine

Step through historic versions of git controlled file.

(use-package git-timemachine
  :config
  (nmap
    :prefix my/leader
    "g t" 'git-timemachine))

Syntactic modes

(use-package git-modes)

Gist

Broken

(use-package gist
 :after general
 :config
 (nmap
   :prefix my/leader
   "G l" 'gist-list
   "G b" 'gist-buffer
   "G B" 'gist-buffer-private
   "G r" 'gist-region
   "G R" 'gist-region-private))

Shell

Pager

Make less work inside Emacs shells. But disable it as the default pager.

(setenv "LESS" "--dumb --prompt=s")
(setenv "PAGER" "")

Eshell

(use-package eshell
  :ensure nil
  ;; :config
  ;; (unbind-key "C-j" eshell-mode-map)
  ;; (unbind-key "C-k" eshell-mode-map)
)

EM-smart (disabled)

(use-package em-smart
 :ensure nil
 :config
 (eshell-smart-initialize)
 :custom
 (eshell-where-to-jump 'begin)
 (eshell-review-quick-commands nil)
 (eshell-smart-space-goes-to-end t))

Esh help

(use-package esh-help
 :commands
 (setup-esh-help-eldoc)
 :config
 (setup-esh-help-eldoc))

Esh autosuggest

(use-package esh-autosuggest
 :hook (eshell-mode . esh-autosuggest-mode))
(use-package eshell-prompt-extras
 :after esh-opt
 :commands
 (epe-theme-dakrone)
 :custom
 (eshell-prompt-function #'epe-theme-dakrone))

Fringe status

Command execution status indicator in the fringe.

(use-package eshell-fringe-status
  :hook
  (eshell-mode . eshell-fringe-status-mode))

EShell toggle

(use-package eshell-toggle
 :after (general)
 :custom
 (eshell-toggle-use-projectile-root t)
 (eshell-toggle-run-command nil)
 :config
 (nmap
   :prefix my/leader
   "\\" 'eshell-toggle))

SSH

Formatting

Prettier

(use-package prettier
 :config
 (add-hook 'after-init-hook #'global-prettier-mode))

Snippets

Yasnippet

(use-package yasnippet
  :demand t
  :init
  (setq
   yas-wrap-around-region t
   yas-indent-line t)
  :config
  (yas-global-mode 1)
  (nmap
    :prefix my/leader
    "y i" 'yas-insert-snippet
    "y n" 'yas-new-snippet
    "y v" 'yas-visit-snippet-file
    "y r" 'yas-reload-all)
  (imap
    "C-l" 'yas-insert-snippet)
  :diminish yas-minor-mode)
(use-package ivy-yasnippet
 :config
 (imap
   "C-s" 'ivy-yasnippet))
(use-package auto-yasnippet
 :after (general yasnippet)
 :config
 (nmap
   :prefix my/leader
   "y c" 'aya-create
   "y e" 'aya-expand
   "y o" 'aya-open-line))

Yasnippet snippets

A collection of yasnippet snippets for many languages.

(use-package yasnippet-snippets)

Yatemplate

Simple file templates for Emacs with YASnippet.

(use-package yatemplate
  :init
  (yatemplate-fill-alist))

Org

Main

Setup

(use-package org
  :after (general counsel visual-fill-column)
  :preface
  (defun my/org/setup ()
    (interactive)
    ;; Center content
    (setq visual-fill-column-width 100
          visual-fill-column-center-text t)
    (visual-fill-column-mode 1)
    ;; Wrap text
    (visual-line-mode 1)
    ;; Replace list hyphen with dot
    (font-lock-add-keywords 'org-mode
                            '(("^ *\\([-]\\) "
                                (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) ""))))))
    ;; Use noticeable faces for heading levels
    (dolist (face '((org-level-1 . 1.4)
                    (org-level-2 . 1.2)
                    (org-level-3 . 1.0)
                    (org-level-4 . 1.0)
                    (org-level-5 . 1.0)
                    (org-level-6 . 1.0)
                    (org-level-7 . 1.0)
                    (org-level-8 . 1.0)))
      (set-face-attribute (car face) nil :font "JetBrains Mono" :weight 'regular :height (cdr face))))
  :mode ("\\.org\\'" . org-mode)
  :hook (org-mode . my/org/setup)
  :commands
  (org-babel-do-load-languages)
  :init

Config

Visually indent sections. This looks better for smaller files. Also, startup folded and disallow editing invisible areas.

(setq org-startup-indented t)
(setq org-startup-folded t)
(setq org-catch-invisible-edits 'error)

Show inline images when loading a new Org file.

(setq org-startup-with-inline-images t)

This feature came to Org in version 8. It lets you type “normal quotes” in the org buffer, as opposed to “this latex stuff”, and will transform them on export so that your HTML/text output looks nice and your latex export looks nice!

(setq org-export-with-smart-quotes t)

Forces to mark all child tasks as DONE before you can mark the parent as DONE.

(setq org-enforce-todo-dependencies t)

Allows displaying UTF-8 chars like \alpha.

(setq org-pretty-entities t)

Insert an annotation in a task when it is marked as done including a timestamp of when exactly that happened.

(setq org-log-done 'time)

Insert annotations when you change the deadline of a task, which will note the previous deadline date and when it was changed.

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

Same as above, but for the scheduled dates.

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

Hide leading stars.

(setq org-hide-leading-stars t)

Use syntax highlighting in source blocks while editing.

(setq org-src-fontify-natively t)

Noticeable ellipsis. Others:

, , , , , , ,

(setq org-ellipsis "")

Keep org files in Dropbox. And all of those files should be in included agenda.

(setq
 org-directory "~/Dropbox/org"
 org-agenda-files '("~/Dropbox/org/"))

Refile targets should include files and down to 9 levels into them.

(setq
 org-refile-targets
 (quote ((nil :maxlevel . 9)
  (org-agenda-files :maxlevel . 9))))

And inside those code blocks indentation should be correct depending on the source language used and have code highlighting.

(setq org-src-tab-acts-natively t)
(setq org-src-preserve-indentation t)
(setq org-src-fontify-natively t)

State changes for todos and also notes should go into a Logbook drawer:

(setq org-log-into-drawer t)

Open URLs in Firefox.

(setq
 org-file-apps
 (quote
  ((auto-mode . emacs)
   ("\\.mm\\'" . default)
   ("\\.x?html?\\'" . "google-chrome %s")
   ("\\.pdf\\'" . default))))

Custom capture templates.

(setq
 org-capture-templates
 '(("t" "todo" entry (file "todo.org") "* TODO %^{task name}\n%u\n%a\n")
   ("n" "note" entry (file "notes.org") "* %^{heading} %t %^g\n  %?\n")
   ("j" "journal" entry (file "journal.org") "* %U - %^{heading}\n  %?")))

I keep my links in links.org, export them to HTML and access them via browser. This makes the HTML file automatically on every save.

(defun org-mode-export-links ()
  "Export links document to HTML automatically when links.org is changed"
  (when (equal (buffer-file-name) "~/Dropbox/org/links.org")
    (progn
      (org-html-export-to-html)
      (alert "HTML exported" :severity 'trivial :title "ORG"))))

(add-hook 'after-save-hook 'org-mode-export-links)

Set TODO priorities.

(setq
 org-highest-priority ?A
 org-lowest-priority ?C
 org-default-priority ?B)

Set default task sequence/lifecycle, colors and triggers.

(setq
  org-todo-keywords
  '((sequence "TODO" "IN-PROGRESS" "WAITING" "HOLD" "|" "DONE" "CANCELLED"))
  org-todo-keyword-faces
  '(("TODO" :foreground "magenta2" :weight bold)
    ("IN-PROGRESS" :foreground "dodger blue" :weight bold)
    ("WAITING" :foreground "orange" :weight bold)
    ("DONE" :foreground "forest green" :weight bold)
    ("HOLD" :foreground "magenta" :weight bold)
    ("CANCELLED" :foreground "forest green" :weight bold)
    ("BUG" :foreground "red" :weight bold)
    ("UNTESTED" . "purple"))
  org-todo-state-tags-triggers
  '(("CANCELLED" ("CANCELLED" . t))
    ("WAITING" ("WAITING" . t))
    ("HOLD" ("WAITING") ("HOLD" . t))
    (done ("WAITING") ("HOLD"))
    ("TODO" ("WAITING") ("CANCELLED") ("HOLD"))
    ("IN-PROGRESS" ("WAITING") ("CANCELLED") ("HOLD"))
    ("DONE" ("WAITING") ("CANCELLED") ("HOLD"))))

Do not dim blocked tasks.

(setq org-agenda-dim-blocked-tasks nil)

Compact the block agenda view.

(setq org-agenda-compact-blocks t)

Hide DONE items.

(setq
 org-agenda-skip-scheduled-if-done t
 org-agenda-skip-deadline-if-done t)

Set a 30 day span, instead of a week view.

(setq
 org-agenda-start-day "-3d"
 org-agenda-span 30)

Omit empty days in the agenda.

(setq org-agenda-show-all-dates nil)

Disable pre-warnings.

(setq org-deadline-warning-days 0)

Hide the time grid by default.

(setq org-agenda-use-time-grid nil)

Make the agenda schedule prettier.

(setq
 org-agenda-prefix-format
 '((agenda . " %i %-12t% s %b\n")
   (timeline . "  % s")
   (todo . " %i %-12:c")
   (tags . " %i %-12:c")
   (search . " %i %-12:c")))

Next comes the :config section.

:config
(require 'org)

Makes inline latex previews bigger.

(setq
 org-format-latex-options
 (plist-put org-format-latex-options :scale 1.7))

Keybindings

Fix moving between windows.

(nmap 'org-mode-map
 "C-k" 'windmove-up
 "C-j" 'windmove-down)

Other useful keybindings.

(nmap
  :prefix my/leader
  "t L" 'org-toggle-link-display
  "o" 'org-todo-list
  "O" 'counsel-org-goto-all
  "c" 'counsel-org-capture
  "k" 'org-narrow-to-subtree)
(mmap 'org-agenda-mode-map
  "C-c C-l" 'org-agenda-log-mode)
:delight "org")

Evil

Supplemental evil-mode keybindings to emacs org-mode. See the repo for keybindings cheatsheet.

;; See: https://github.com/Somelauw/evil-org-mode/issues/93#issuecomment-950306532
(fset 'evil-redirect-digit-argument 'ignore)

(use-package evil-org
 :after (general org)
 :commands
 (evil-org-set-key-theme evil-org-agenda-set-keys)
 :preface
 (defun my/evil-org/setup ()
   (evil-org-mode)
   (evil-org-set-key-theme '(textobjects insert navigation additional shift todo heading calendar))
   (evil-org-agenda-set-keys))
 :hook
 (org-mode . my/evil-org/setup)
 :config
 ;; (add-to-list 'evil-digit-bound-motions 'evil-org-beginning-of-line)
 ;; (evil-define-key 'motion 'evil-org-mode
 ;;   (kbd "0") 'evil-org-beginning-of-line)
 (require 'evil-org-agenda)
 :diminish evil-org-mode)

Bullets

org-superstar

Prettify headings and plain lists in Org mode. This package is a direct descendant of org-bullets, with most of the code base completely rewritten.

(use-package org-superstar
 :after (org)
 :config
 (org-superstar-configure-like-org-bullets)
 :hook
 (org-mode . org-superstar-mode))

org-bullets (disabled)

I use org-superstart instead, so it is currently disabled.

(use-package org-bullets
 :after org
 :hook
 (org-mode . org-bullets-mode))

Sticky-header

Show off-screen Org heading at top of window.

(use-package org-sticky-header
:after (org)
:hook
(org-mode . org-sticky-header-mode))

Cliplink

Paste links from clipboard and automatically fetch title.

(use-package org-cliplink
  :config
  (nmap 'org-mode-map
    :prefix my/leader
    "L" 'org-cliplink))

Orgroam

A plain-text personal knowledge management system.

(use-package org-roam
;; TODO: Why do we have to use "demand" here?
:demand t
:after (org general)
:preface
(defun my/org-roam/node-insert-immediate (arg &rest args)
  (interactive "P")
  (let ((args (cons arg args))
        (org-roam-capture-templates (list (append (car org-roam-capture-templates)
                                                  '(:immediate-finish t)))))
    (apply #'org-roam-node-insert args)))
(defun my/org-roam/filter-by-tag (tag-name)
  (lambda (node)
    (member tag-name (org-roam-node-tags node))))
(defun my/org-roam/list-notes-by-tag (tag-name)
  (mapcar #'org-roam-node-file
          (seq-filter
           (my/org-roam/filter-by-tag tag-name)
           (org-roam-node-list))))
(defun my/org-roam/refresh-agenda-list ()
  (interactive)
  (setq org-agenda-files (my/org-roam/list-notes-by-tag "agenda")))
(defun my/org-roam/setup ()
 (my/org-roam/refresh-agenda-list))
:custom
(org-roam-directory "~/projects/personal/braindump/org")
(org-roam-capture-templates
 '(("d" "default" plain "%?"
     :target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
     :unnarrowed t)
   ("b" "book notes" plain
    "\n* Source\n\nAuthor: %^{Author}\nTitle: ${title}\nYear: %^{Year}\n\n* Summary\n\n%?"
    :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
    :unnarrowed t)
   ("p" "project" plain "* Goals\n\n%?\n\n* Tasks\n\n** TODO Add initial tasks\n\n* Dates\n\n"
    :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+category: ${title}\n#+filetags: project agenda")
    :unnarrowed t)))
:init
(setq org-roam-v2-ack t)
(setq org-roam-dailies-directory "journal/")
(setq org-roam-dailies-capture-templates
      '(("d" "default" entry
         "* %<%H:%M> %?"
         :target (file+head+olp "%<%Y-%m-%d>.org"
                                "#+title: %<%Y-%m-%d>\n" ("Journal")))))
:config
(my/org-roam/setup)
;; Ensure the keymap is available
(require 'org-roam-dailies)
(org-roam-setup)
(org-roam-db-autosync-mode)
(nmap
  :prefix my/leader
  "n l" 'org-roam-buffer-toggle
  "n f" 'org-roam-node-find
  "n i" 'org-roam-node-insert
  "n j" 'org-roam-dailies-capture-today
  "n k" 'org-roam-dailies-capture-tomorrow
  "n h" 'org-roam-dailies-capture-yesterday
  "n d" 'org-roam-dailies-goto-today
  "n y" 'org-roam-dailies-goto-yesterday
  "n t" 'org-roam-dailies-goto-tomorrow
  "n D" 'org-roam-dailies-goto-date
  "n ," 'org-roam-dailies-goto-previous-note
  "n ." 'org-roam-dailies-goto-next-note))

Pandoc exporter

(use-package ox-pandoc)

Blogging with hugo

Install ox-hugo and enable auto export.

(use-package ox-hugo
  :after (ox org-capture)
  :commands (org-hugo-slug)
  :custom
  (org-hugo-delete-trailing-ws nil)
  :config
  ;; Define variable to get rid of 'reference to free variable' warnings.
  (defun my/org-hugo/new-subtree-post ()
    "Returns `org-capture' template string for new blog post.
     See `org-capture-templates' for more information."
    (let*
        ;; Prompt to enter the post title
        ((title (read-from-minibuffer "Post Title: "))
         (lang (read-from-minibuffer "Lang code (e.g. ru-ru): "))
         (date (format-time-string (org-time-stamp-format :long :inactive) (org-current-time)))
         (fname (concat (org-hugo-slug title) "." lang)))
      (mapconcat
       #'identity
       `(
         ,(concat "* TODO " title)
         ":PROPERTIES:"
         ,(concat ":EXPORT_FILE_NAME: " fname)
         ,(concat ":EXPORT_DATE: " date) ;Enter current date and time
         ":END:"
         "%?\n") ; Place the cursor here finally
       "\n")))
  ;; org-capture template to quickly create posts and generate slugs.
  (add-to-list
   'org-capture-templates
   '("b"
     "blog post"
     entry
     (file "~/projects/personal/blog/content-org/posts.org")
     (function my/org-hugo/new-subtree-post)))

  (with-eval-after-load 'ox-hugo
   (add-to-list 'org-hugo-special-block-type-properties '("mermaid" . (:raw t)))))

Slim HTML export (disabled)

slimhtml is an emacs org mode export backend. It is a set of transcoders for common org elements which outputs minimal HTML.

(use-package htmlize)
(use-package ox-slimhtml)

(defun org-html-export-as-slimhtml
(&optional async subtreep visible-only body-only ext-plist)
  (interactive)
  (org-export-to-buffer 'slimhtml "*slimhtml*"
    async subtreep visible-only body-only ext-plist (lambda () (html-mode))))

(eval-after-load 'org
  `(define-key org-mode-map
     (kbd "s-O")
     (lambda ()
       (interactive)
       (org-html-export-as-slimhtml nil nil nil t)
       (with-no-warnings (mark-whole-buffer))
       ;; TODO: I don't use simpleclip, so need to update this
       ;; (simplecmlip-copy (point-min) (point-max))
       (delete-window))))

Org Download (disabled)

Drag and drop images to org files.

(use-package org-download
  :config
  ;; Org-download creates links, but I need to change the path
  ;; for my blog. This simple hook runs on every save.
  (defun org-mode-blog-fix-org-downloaded-image-paths ()
    (when (equal (buffer-file-name) "~/projects/personal/blog/content-org/blog.org")
      (progn
        (while (re-search-forward "file:../static" nil t)
          (replace-match "file:"))
        (while (re-search-backward "file:../static" nil t)
          (replace-match "file:")))))

  (add-hook 'after-save-hook 'org-mode-blog-fix-org-downloaded-image-paths)
  :hook
  (dired-mode-hook . org-download-enable))

LSP

Mode

Setup lsp-mode. Here is how to diagnose the performance problems.

(use-package lsp-mode
  :after (general projectile)
  :commands (lsp)
  :custom
  ;; Uncomment to inspect communication between client and the server
  (lsp-print-io t)
  (lsp-prefer-flymake nil)
  (setq lsp-headerline-breadcrumb-enable t)
  ;; Determines how often lsp-mode will refresh the highlights, lenses, links, etc while you type.
  (lsp-idle-delay 0.5)
  ;; Make sure the logging is switched off
  (lsp-log-io nil)
  (lsp-completion-provider :capf)

  ;; Display all of the info returned by document/onHover.
  (lsp-eldoc-render-all nil)

  ;; What to use when checking on-save: "check" is default, I prefer "clippy"
  (lsp-rust-analyzer-cargo-watch-command "clippy")
  (lsp-rust-analyzer-diagnostics-disabled ["unresolved-proc-macro"])

  ;; enable / disable the hints as you prefer:
  (lsp-rust-analyzer-server-display-inlay-hints nil)
  (lsp-rust-analyzer-display-lifetime-elision-hints-enable "skip_trivial")
  (lsp-rust-analyzer-display-chaining-hints t)
  (lsp-rust-analyzer-display-lifetime-elision-hints-use-parameter-names nil)
  (lsp-rust-analyzer-display-closure-return-type-hints t)
  (lsp-rust-analyzer-display-parameter-hints nil)
  (lsp-rust-analyzer-display-reborrow-hints nil)
  :config
  (dolist (dir '("vendor")) (push dir lsp-file-watch-ignored))
  (nmap
    :prefix my/leader
    "l r" 'lsp-restart-workspace
    "l f" 'lsp-format-buffer
    "l l" 'lsp-execute-code-action
    "l s" 'lsp-rust-analyzer-status
    "l d" 'lsp-describe-thing-at-point)
  :hook
  (lsp-mode . lsp-lens-mode)
  (lsp-mode . lsp-enable-which-key-integration)
  (c-mode . lsp)
  (c++-mode . lsp)
  :delight "lsp")

LSP UI

(use-package lsp-ui
  :after (lsp-mode)
  :commands (lsp-ui-mode general)
  :config
  (add-hook 'lsp-mode-hook 'lsp-ui-mode)
  (add-hook 'lsp-after-open-hook 'lsp-enable-imenu)
  (add-hook 'lsp-ui-doc-frame-hook
    (lambda (frame _w)
      (set-face-attribute 'default frame :font "JetBrains Mono" :height 12)))
  (set-face-attribute 'lsp-ui-sideline-global nil :font "JetBrains Mono" :height 0.6)
  (set-face-attribute 'lsp-ui-sideline-code-action nil :font "JetBrains Mono" :height 0.6)
  (setq
   ;; Show side line (e.g. code actions hits)
   lsp-ui-sideline-enable t
   lsp-ui-sideline-show-hover t
   lsp-ui-sideline-delay 0.5
   lsp-ui-peek-always-show t
   lsp-ui-sideline-actions-icon nil
   ;; Show hover messages in sideline
   lsp-ui-show-hover t
   ;; Show code actions in sideline
   lsp-ui-show-code-actions t
   lsp-enable-completion-at-point t
   lsp-ui-doc-position 'at-point
   lsp-ui-doc-header nil
   lsp-ui-doc-enable nil
   lsp-ui-doc-delay 0.25
   lsp-ui-doc-use-webkit nil
   lsp-ui-doc-include-signature t
   lsp-ui-doc-border "#222"
   lsp-ui-peek-fontify nil
   lsp-ui-peek-expand-function (lambda (xs) (mapcar #'car xs)))
  (nmap 'lsp-ui-mode-map
    :prefix my/leader
    "=" 'lsp-ui-sideline-apply-code-actions)
  (nmap 'haskell-mode-map
    :prefix my/leader
    "i" 'lsp-ui-doc-focus-frame
    "I" 'lsp-ui-imenu
    "t d" 'lsp-ui-doc-mode
    "t s" 'lsp-ui-sideline-mode)
  (general-def 'lsp-ui-peek-mode-map
    "h" 'lsp-ui-peek--select-next-file
    "l" 'lsp-ui-peek--select-prev-file
    "j" 'lsp-ui-peek--select-next
    "k" 'lsp-ui-peek--select-prev))

Company LSP

(use-package company-lsp
 :after (lsp-mode company)
 ;; It is not on MELPA yet:
 ;; https://github.com/tigersoldier/company-lsp/issues/147
 :quelpa
 (company-lsp :fetcher github :repo "tigersoldier/company-lsp")
 :commands (company-lsp)
 :init
 (setq
  ;; Don't filter results on the client side
  company-transformers nil
  company-lsp-cache-candidates 'auto
  ;; Fetch completion candidates asynchronously.
  company-lsp-async t
  ;; Enable snippet expansion on completion
  company-lsp-enable-snippet t)
 :config
 (push 'company-lsp company-backends))

Treemacs

(use-package lsp-treemacs
 :after (general)
 :commands lsp-treemacs-errors-list
 :config
 ;; Enable bidirectional synchronization of lsp workspace
 ;; folders and treemacs projects
 (lsp-treemacs-sync-mode 1)
 (nmap
   :prefix my/leader
   "m s" 'lsp-treemacs-symbols
   "m r" 'lsp-treemacs-references
   "m i" 'lsp-treemacs-implementations
   "m c" 'lsp-treemacs-call-hierarchy
   "m t" 'lsp-treemacs-type-hierarchy
   "m e" 'lsp-treemacs-errors-list))

Ivy

Provides an interactive ivy interface to the workspace symbol functionality offered by lsp-mode.

(use-package lsp-ivy)

Makefile

Emacs helpers to run things from makefiles.

  • Interactively selecting a make target and running it. Bound to C-c C-e in makefile-mode when makefile-executor-mode is enabled.
  • Re-running the last execution. We usually run things in Makefiles many times after all! Bound to C-c C-c in makefile-mode when makefile-executor-mode is enabled.
  • Running a makefile target in a dedicated buffer. Useful when starting services and other long-running things! Bound to C-c C-d in makefile-mode when makefile-executor-mode is enabled.
  • Calculation of variables et.c.; $(BINARY) will show up as what it evaluates to.
  • If projectile is installed, execution from any buffer in a project. If more than one Makefile is found, an interactive prompt for one is shown. This is added to the projectile-commander on the m key.
(use-package makefile-executor
  :config
  (add-hook 'makefile-mode-hook 'makefile-executor-mode))

RFC

(use-package rfc-mode
 :custom
  rfc-mode-directory (my/emacs-path "rfc"))

Smartparens (disabled)

Minor mode for Emacs that deals with parens pairs and tries to be smart about it.

(use-package smartparens
 :commands
 (smartparens-mode
  sp-with-modes
  sp-local-pair
  sp-pair)
 :hook
 ((conf-mode text-mode prog-mode) . smartparens-mode)
 :config
 (use-package smartparens-config
  :ensure nil
  :demand t)
 (sp-local-pair 'minibuffer-inactive-mode "'" nil :actions nil)
 (general-define-key
  :keymaps 'sp-keymap
  "M-F" 'sp-forward-symbol
  "M-B" 'sp-backward-symbol
  "C-M-k" 'sp-kill-sexp
  "C-M-w" 'sp-copy-sexp
  "C-M-t" 'sp-transpose-sexp
  "M-<left>" 'sp-forward-slurp-sexp
  "C-M-<left>" 'sp-forward-barf-sexp
  "M-<right>" 'sp-backward-slurp-sexp
  "C-M-<right>" 'sp-backward-barf-sexp
  "M-D" 'sp-splice-sexp
  "C-M-[" 'sp-select-previous-thing
  "C-M-]" 'sp-select-next-thing
  "C-c s u" 'sp-up-sexp
  "C-c s d" 'sp-down-sexp
  "C-c s t" 'sp-prefix-tag-object
  "C-c s p" 'sp-prefix-pair-object
  "C-c s c" 'sp-convolute-sexp
  "C-c s a" 'sp-absorb-sexp
  "C-c s e" 'sp-emit-sexp
  "C-c s p" 'sp-add-to-previous-sexp
  "C-c s n" 'sp-add-to-next-sexp
  "C-c s j" 'sp-join-sexp
  "C-c s s" 'sp-split-sexp
  "C-c s (" 'sp-wrap-round
  "C-c s [" 'sp-wrap-square
  "C-c s {" 'sp-wrap-curly)
 :diminish smartparens-mode)

Help

Helpful

See the package repo for more info.

(use-package helpful
 :config
 (nmap
   :prefix my/leader
   "H h" 'helpful-at-point
   "H f" 'helpful-callable
   "H F" 'helpful-function
   "H v" 'helpful-variable
   "H c" 'helpful-command
   "H k" 'helpful-key))

Devdocs

Allows to easily search the DevDocs documentation.

(use-package devdocs
  :config
  (nmap
    :prefix my/leader
    "h h" 'devdocs-search))

MMM

Provides a minor mode that allows Multiple Major Modes to coexist in one buffer.

(use-package mmm-mode
  :after (haskell-mode)
  :preface
  (defun my/mmm-mode/setup ()
    ;; go into mmm minor mode when class is given
    (make-local-variable 'mmm-global-mode)
    (setq mmm-global-mode 'true))
  :init
  (setq mmm-submode-decoration-level 1)
  :hook
  (haskell-mode . my/mmm-mode/setup)
  :config

Styles for Literate Haskell. Read here for more info.

(mmm-add-classes
 '((literate-haskell-bird
    :submode text-mode
    :front "^[^>]"
    :include-front true
    :back "^>\\|$")
   (literate-haskell-latex
    :submode literate-haskell-mode
    :front "^\\\\begin{code}"
    :front-offset (end-of-line 1)
    :back "^\\\\end{code}"
    :include-back nil
    :back-offset (beginning-of-line -1))))
(setq mmm-submode-decoration-level 0)

Re-fontify sub-mode portions when idle. The manual command for this is mmm-parse-buffer. If you don’t do this, then syntax highlighting won’t work for new regions of Haskell code in the \begin{code}...\end{code} blocks.

(setq mmm-parse-when-idle 't))

Languages

Lisp

(use-package lisp-mode
  :ensure nil
  :config
  (put 'use-package 'lisp-indent-function 1)
  (put 'add-hook 'lisp-indent-function 1)
  (put :map 'lisp-indent-function 1))

Emacs Lisp

Mode

(use-package elisp-mode
  :after (general company smartparens)
  :ensure nil
  :preface
  (defun my/emacs-lisp-prettify-symbols-setup ()
    "Prettify `emacs-lisp-mode' specific symbols."
    (dolist (symbol '(("defun"    . )
                      ("defmacro" . )
                      ("defvar"   . )
                      ("defconst" . "ν_")))
      (cl-pushnew symbol prettify-symbols-alist :test #'equal)))
  :config
  (nmap 'emacs-lisp-mode-map
    "M-." 'find-function-at-point
    "M-," 'find-variable-at-point)
  (add-to-list 'company-backends 'company-elisp)
  (sp-with-modes 'emacs-lisp-mode
    (sp-local-pair "'" nil :actions nil))
  :hook
  (emacs-lisp-mode . my/emacs-lisp-prettify-symbols-setup))

Refs

(use-package elisp-refs
  :after elisp-mode)

Macrostep

(use-package macrostep
 :after elisp-mode
 :demand t
 :commands macrostep-expand
 :mode ("\\*.el\\'" . emacs-lisp-mode)
 :config
 ;; support Macrostep in Evil mode
 (general-define-key
  :keymaps 'macrostep-keymap
  "q" 'macrostep-collapse-all
  "e" 'macrostep-expand)
 (nmap
   :keymaps 'emacs-lisp-mode-map
   :prefix my/leader
   "m e" 'macrostep-expand))

Highlight

(use-package highlight-defined
 :custom
 (highlight-defined-face-use-itself t)
 :hook
 (emacs-lisp-mode . highlight-defined-mode))
(use-package highlight-quoted
 :hook
 (emacs-lisp-mode . highlight-quoted-mode))
(use-package highlight-sexp
  :quelpa
  (highlight-sexp :repo "daimrod/highlight-sexp" :fetcher github :version original)
  :hook
  (emacs-lisp-mode . highlight-sexp-mode)
  (lisp-mode . highlight-sexp-mode))

Prism package disperses lisp forms (and other languages) into a spectrum of color by depth.

I’ve disabled it for now because of error:

is Error (use-package): prism/:catch: Wrong number of arguments: (3 . 3), 0

(use-package anaphora)
(use-package prism
  :after (anaphora)
  :quelpa (prism :fetcher github :repo "alphapapa/prism.el"))

Evaluation Result OverlayS for Emacs Lisp.

(use-package eros
 :hook
 (emacs-lisp-mode . eros-mode))
(use-package ipretty
  :defer t
  :commands
  (ipretty-mode)
  :config
  (ipretty-mode 1))

Hide package namespace in your emacs-lisp code. For example, it changes whatever-mode to :mode.

(use-package nameless
 :hook
 (emacs-lisp-mode . nameless-mode)
 :custom
 (nameless-global-aliases '())
 (nameless-private-prefix t)
 :config
 (nmap 'emacs-lisp-mode-map
   :prefix my/leader
   "t n" 'nameless-mode))

Improve readability of escape characters in regular expressions.

(use-package easy-escape
  :diminish easy-escape-minor-mode
  :hook
  (emacs-lisp-mode . easy-escape-minor-mode))

Package lint

A linting library for elisp package metadata.

(use-package package-lint)

Flycheck checker for elisp package metadata.

(use-package flycheck-package
 :defer t
 :after flycheck
 (flycheck-package-setup))

Suggest

Discover functions.

(use-package suggest
  :preface
  (defun my/suggest-popup ()
    "Open suggest as a popup."
    (interactive)
    (let* ((window (selected-window))
           (dedicated-flag (window-dedicated-p window)))
      (set-window-dedicated-p window t)
      (suggest)
      (set-window-dedicated-p window dedicated-flag)))
  :config
  (nmap 'emacs-lisp-mode-map
    :prefix my/leader
    "E s" 'my/suggest-popup))

Haskell

Hasklig (ligatures)

(use-package hasklig-mode
  :commands
  (hasklig-mode)
  :delight "hl")

Mode

(use-package haskell-mode
  :after
  (general company eldoc)
  ;; :quelpa
  ;; (haskell-mode :fetcher github :repo "haskell/haskell-mode")
  :mode
  (("\\.hs\\(-boot\\)?\\'" . haskell-mode)
   ("\\.hcr\\'" . haskell-core-mode)
   ("\\.lhs\\'" . literate-haskell-mode)
   ("\\.cabal\\'" . haskell-cabal-mode)
   ("\\.x\\'" . prog-mode))
  :commands
  (haskell-compile-cabal-build-command
   haskell-interactive-mode-map)
  :preface
  (defun my/display-ctrl-D-as-space ()
    "Display `^D' as newline."
    (interactive)
    (setq buffer-display-table (make-display-table))
    (aset buffer-display-table ?\^D [?\ ]))
  (defun my/haskell-mode/setup ()
    (interactive)
    ;; (setq buffer-face-mode-face '(:family "Hasklig"))
    (buffer-face-mode)
    ;; Treat symbol (e.g. "_") as a word
    (defalias 'forward-evil-word 'forward-evil-symbol)
    ;; (subword-mode 1)
    ;; (eldoc-overlay-mode)       ; annoying
    ;; (haskell-indentation-mode) ; hi2 FTW
    ;; Affects/breaks haskell-indentation-mode
    ;; (setq-local evil-auto-indent nil)
    (with-current-buffer (get-buffer-create "*haskell-process-log*")
      (my/display-ctrl-D-as-space))
    ;; (hasklig-mode)
    (haskell-doc-mode)
    (haskell-collapse-mode)
    (haskell-decl-scan-mode)
    (electric-layout-mode)
    (electric-pair-local-mode)
    (electric-indent-local-mode)
    ;; There are some tools that dont't work with unicode symbols
    ;; I (sometimes) use Hasklig instead
    ;; (turn-on-haskell-unicode-input-method)
    (face-remap-add-relative 'font-lock-doc-face 'font-lock-comment-face))
  (defvar my/haskell-process-use-ghci nil)
  (defvar my/haskell-build-command-use-make nil)
  (defun my/haskell-mode/toggle-build-command ()
    "Toggle the build command"
    (interactive)
    (if my/haskell-build-command-use-make
        (progn
          (setq haskell-compile-cabal-build-command "cd %s && cabal new-build")
          (alert "Setting build command to:\n cabal new-build" :severity 'normal :title "Haskell"))
      (progn
        (setq haskell-compile-cabal-build-command "cd %s && make build")
        (alert "Setting build command to:\n make build" :severity 'normal :title "Haskell"))))
  (defun my/haskell-mode/toggle-process-type ()
    "Toggle GHCi process between cabal and ghci"
    (interactive)
    (if my/haskell-process-use-ghci
        (progn
          ;; You could set it to "cabal-repl" if
          ;; you're using the old cabal workflow
          (setq haskell-process-type 'cabal-new-repl)
          (setq my/haskell-process-use-ghci nil)
          (alert "Using cabal new-repl" :severity 'normal :title "Haskell"))
      (progn
        (setq haskell-process-type 'stack-ghci)
        (setq my/haskell-process-use-ghci t)
        (alert "Using stack ghci" :severity 'normal :title "Haskell"))))
  (defun my/haskell-mode/show-process-log ()
    "Display *haskell-process-log* buffer in other window"
    (interactive)
    (switch-to-buffer-other-window "*haskell-process-log*"))
  :hook
  (haskell-mode . my/haskell-mode/setup)
  :custom
  ;; Enable debug logging to *haskell-process-log* buffer
  (haskell-process-log t)
  ;; Don't generate tags via hasktags after saving
  (haskell-tags-on-save nil)
  ;; Don't run stylish-haskell on the buffer before saving.
  ;; It just inserts a bunch of spaces at the end of the line for no reason
  (haskell-stylish-on-save nil)
  ;; Suggest to add import statements using Hoogle as a backend
  (haskell-process-suggest-hoogle-imports t)
  ;; Suggest to add import statements using Hayoo as a backend
  (haskell-process-suggest-hayoo-imports t)
  ;; Replace SVG image text with actual images
  (haskell-svg-render-images t)
  ;; Don't eliminate the context part in a Haskell type
  (haskell-doc-chop-off-context nil)
  ;; Suggest removing import lines as warned by GHC
  (haskell-process-suggest-haskell-docs-imports t)
  ;; Search for the types of global functions by loading the files
  (haskell-doc-show-global-types t)
  ;; Don't show debugging tips when starting the process
  (haskell-process-show-debug-tips nil)
  ;; Don’t suggest removing import lines as warned by GHC
  ;; It is too annoying, sometimes I want to keep unused imports
  (haskell-process-suggest-remove-import-lines nil)
  ;; Don't suggest adding packages to .cabal file
  (haskell-process-suggest-add-package nil)
  ;; Don't suggest restarting the f*****g process
  (haskell-process-suggest-restart nil)
  ;; Don't suggest adding the OverloadedStrings extensions
  (haskell-process-suggest-overloaded-strings nil)
  ;; Auto import the modules reported by GHC to have been loaded
  (haskell-process-auto-import-loaded-modules t)
  ;; Show things like type info instead of printing to the message area
  ;; haskell-process-use-presentation-mode t
  ;; Don't popup errors in a separate buffer
  (haskell-interactive-popup-errors nil)
  ;; Make haskell-process-log look better
  (haskell-process-args-ghci '("-ferror-spans" "-fhide-source-paths"))
  (haskell-process-args-cabal-repl '("--ghc-options=-ferror-spans -fhide-source-paths"))
  (haskell-process-args-stack-ghci '("--ghci-options=-ferror-spans" "--no-build" "--no-load"))
  (haskell-process-args-cabal-new-repl '("--ghc-options=-ferror-spans -fhide-source-paths"))
  ;; Use "cabal new-repl" as the inferior haskell process
  (haskell-process-type 'cabal-new-repl)
  ;; haskell-process-args-stack-ghci '("--ghci-options=-ferror-spans")
  ;; haskell-compile-cabal-build-command "stack build --no-library-profiling"
  (haskell-compile-cabal-build-command "cd %s && cabal new-build")
  :config
  (add-to-list
   'electric-layout-rules
   '((?\{) (?\} . around)))
  (add-to-list
   'electric-layout-rules
   '((?\[) (?\] . around)))
  ;; Common key bindings
  (nmap '(haskell-mode-map haskell-cabal-mode-map haskell-interactive-mode-map)
    "C-c C-b" 'haskell-compile
    "C-c C-k" 'haskell-interactive-mode-kill
    "C-c C-r" 'haskell-process-restart
    "C-c C-d" 'haskell-cabal-add-dependency
    "C-c C-l" 'haskell-interactive-mode-clear
    "C-c C-h" 'haskell-hoogle
    "C-c SPC" 'haskell-session-change-target
    "C-c C-c" 'my/haskell-mode/show-process-log)
  (nmap '(haskell-mode-map haskell-cabal-mode-map)
    "C-c C-j" 'haskell-interactive-switch)
  (nmap '(haskell-mode-map haskell-interactive-mode-map)
    "C-c c v" 'haskell-cabal-visit-file
    "C-c c b" 'haskell-process-cabal-build
    "C-c c r" 'haskell-process-cabal)
  (nmap 'haskell-compilation-mode-map
    "C-k" 'windmove-up ;; bind it back
    "M-k" 'compilation-previous-error
    "M-j" 'compilation-next-error)
  (nmap 'haskell-mode-map
    "C-c T" 'my/haskell-mode/toggle-process-type
    "C-c b" 'my/haskell-mode/toggle-build-command
    "C-c H" 'haskell-hayoo
    "C-c C-m" 'haskell-auto-insert-module-template
    "C-c ." 'haskell-hide-toggle
    "C-c C-o" 'haskell-process-load-file
    "C-c C-SPC" 'haskell-interactive-copy-to-prompt
    "C-c C-f" 'haskell-mode-stylish-buffer
    "C-c C-t" 'haskell-process-do-type
    "C-c C-i" 'haskell-process-do-info
    ;; Hit it repeatedly to jump between groups of imports
    "C-c C-u" 'haskell-navigate-imports)
  (require 'haskell-interactive-mode)
  (unbind-key "C-j" haskell-interactive-mode-map)
  (nmap 'haskell-interactive-mode-map
    "C-c C-j" 'haskell-interactive-switch-back)
  (imap 'haskell-interactive-mode-map
    "C-c C-l" 'haskell-interactive-mode-clear)
  :delight "hs")

Literate Haskell

Remove the hard-coded literate-haskell-mode activation for .lhs files that haskell-mode comes with. In exchange, enable LaTeX mode whenever we open up a .lhs file. Using mmm-mode, we will activate haskell-mode in the code sections.

(setq
 auto-mode-alist
 (remove
  (rassoc 'literate-haskell-mode auto-mode-alist)
  auto-mode-alist))

(add-to-list 'auto-mode-alist '("\\.lhs$" . latex-mode))

Happy

Emacs major mode for editing Happy filles.

(use-package happy-mode
  :after (mmm-mode)
  :quelpa (happy-mode :fetcher github :repo "sergv/happy-mode"))

Hi2 (disabled)

(use-package hi2
 :after haskell-mode
 :init
 (setq
  hi2-layout-offset 2
  hi2-left-offset 2
  hi2-where-post-offset 2)
 :config
 (put 'hi2-where-post-offset 'safe-local-variable 'numberp)
 (put 'hi2-left-offset 'safe-local-variable 'numberp)
 (put 'hi2-layout-offset 'safe-local-variable 'numberp)
 (imap
   'hi2-mode-map
   "<tab>" 'hi2-indent-line)
 :diminish hi2-mode)

Hindent (disabled)

Bear in mind that it doesn’t support unicode syntax so all your cool unicode operators will be replaced.

(use-package hindent
 :after (general haskell-mode)
 :hook
 (haskell-mode . hindent-mode)
 :config
 ;; "r " - reformat
 (vmap 'haskell-mode-map
   "C-c r" 'hindent-reformat-region)
 (nmap 'haskell-mode-map
   "C-c r" 'hindent-reformat-buffer
   "C-c R" 'hindent-reformat-decl)
 :diminish hindent-mode)

Ghcid (disabled)

My first attempt to get ghcid working inside Emacs. It works, but I still prefer to run it from inside the terminal.

(use-package ghcid
  :after (haskell-mode)
  :quelpa
  (ghcid :fetcher url :url "https://raw.githubusercontent.com/vyorkin/ghcid/nixos-bash/plugins/emacs/ghcid.el")
  :preface
  (defun my/ghcid/show-buffer ()
    (interactive)
    (show-buffer (ghcid-buffer-name)))
  (defun my/ghcid/set-arget (ghcid-targ &optional ghcid-test-targ)
    (interactive
     (list
      (completing-read
       "ghcid target: "
       (map 'list
            (lambda (targ)
              (format "%s:%s" (projectile-project-name) targ))
            (haskell-cabal-enum-targets)))
      (completing-read
       "ghcid --test target: " '("--test=main" "--test=Main.main" nil))))
    (setq ghcid-target ghcid-targ)
    (ghcid-kill)
    (ghcid))
  :custom
  ;; :config (setq-local default-directory projectile-project-root)
  (ghcid-target "")
  :config
  (nmap 'haskell-mode-map
    :prefix my/leader
    "#" 'ghcid
    "$" 'ghcid-stop
    "@" 'my/ghcid/set-arget
    "%" 'my/ghcid/show-buffer))

Ormolu

Formats Haskell source code using ormolu.

(use-package ormolu
  :quelpa
  (ormolu
   :fetcher github
   :repo "vyorkin/ormolu.el")
  :custom
  (ormolu-reformat-buffer-on-save nil)
  :config
  (nmap 'haskell-mode-map
    "C-c r" 'ormolu-format-buffer))

Company-cabal

Company-mode completion back-end for haskell-cabal-mode.

(use-package company-cabal
 :after (haskell-mode company)
 :config
 (add-to-list 'company-backends 'company-cabal))

Liquid types (disabled)

Currenly untangled because I don’t always use LH.

(use-package liquid-types
  :after
  (haskell-mode flycheck)
  :config
  (require 'liquid-types)

Configure flycheck-liquidhs.

(add-hook 'haskell-mode-hook
  '(lambda () (flycheck-select-checker 'haskell-liquid)))
(add-hook 'literate-haskell-mode-hook
  '(lambda () (flycheck-select-checker 'haskell-liquid)))

Toggle minor mode on entering Haskell mode. Currently disabled, too.

(add-hook 'haskell-mode-hook
  '(lambda () (liquid-types-mode)))
(add-hook 'literate-haskell-mode-hook
  '(lambda () (liquid-types-mode)))
:delight "lh")

Hasky-stack

Interface to the Stack Haskell development tool.

(use-package hasky-stack
 :after (general haskell-mode)
 :config
 (nmap 'haskell-mode-map
   :prefix my/leader
   "h s" 'hasky-stack-execute
   "h n" 'hasky-stack-new))

Hasky-extensions

Toggle Haskell language extensions from Emacs.

(use-package hasky-extensions
 :after (general haskell-mode hasky-stack)
 :config
 (nmap 'haskell-mode-map
   :prefix my/leader
   "h e" 'hasky-extensions
   "h d" 'hasky-extensions-browse-docs))

PureScript

Mode

The PureScript mode.

(use-package purescript-mode
 :after (general files)
 :if (executable-find "purs")
 :preface
 (defun my/purescript-emmet ()
   (interactive)
   (let ((start (point))
         (end (save-excursion (beginning-of-line-text) (point))))
     (call-process-region start end "purescript-emmet" t t)))
 :config
 ;; Not needed when installing from melpa
 ;; (require 'purescript-mode-autoloads)
 (imap 'purescript-mode-map
   "C-c C-e" 'my/purescript-emmet))

A new, simple purescript mode for cheap syntax highlighting.

New Mode (disabled)

(use-package purescript-mode
 :quelpa (purescript-mode :fetcher github :repo "justinwoo/new-purescript-mode"))

PSC IDE

(use-package psc-ide
 :after (general purescript-mode)
 :quelpa
 (psc-ide
   :repo "purescript-emacs/psc-ide-emacs"
   :commit "230101a3d56c9e062c3ce2bf9a4dc077e5607cc0"
   :fetcher github)
 :commands (psc-ide-mode)
 :preface
 (defun my/psc-ide/setup ()
   (setq-local evil-auto-indent nil)
   (psc-ide-mode)
   (turn-on-purescript-unicode-input-method)
   (turn-on-purescript-indentation))
 :hook
 (purescript-mode . my/psc-ide/setup)
 :init
 ;; use the psc-ide server that is
 ;; relative to npm bin directory
 (setq psc-ide-use-npm-bin t)
 :config
 (general-define-key
  :states 'normal
  :keymaps 'psc-ide-mode-map
  "C-t" 'psc-ide-goto-definition
  "C-]" 'psc-ide-goto-definition
  "g d" 'psc-ide-goto-definition)
 :delight "psc-ide")

PSCI (disabled)

A major mode to try and improve the purescript repl experience within emacs.

(use-package psci
 :disabled
 :after (purescript-mode)
 :hook
 (purescript-mode . inferior-psci-mode)
 :delight "psci")

Idris

Idris syntax highlighting, compiler-supported editing, interactive REPL and more things for Emacs.

(use-package idris-mode
  :custom
  (idris-repl-banner-functions '(idris-repl-text-banner))
  (idris-repl-prompt-style 'short)
  :config
  (idris-define-evil-keys)
  (nmap 'idris-mode-map
    "C-c C-h" 'idris-type-search
    "C-c h"   'idris-apropos
    "C-c SPC" 'idris-add-clause
    "C-c C-o" 'idris-load-file
    "C-c C-i" 'idris-info-show
    "C-c C-f" 'idris-list-holes
    "C-c C-j" 'idris-repl))

Agda (disabled)

(use-package agda2-mode
  :demand t
  :load-path "lisp/agda/src/data/emacs-mode"
  :config
  (nmap 'agda2-mode-map
    "gd" 'agda2-goto-definition-keyboard
    "C-c C-SPC" 'agda2-give))

ATS/ATS2 (disabled)

Mode

ATS2 mode.

(use-package ats-mode
  :load-path "lisp")

Flycheck.

(use-package flycheck-ats2
 :after (ats-mode))

Nix

Mode

An emacs major mode for editing nix expressions.

(use-package nix-mode
  :after (general)
  :mode ("\\.nix\\'" "\\.nix.in\\'")
  :config
  (nmap 'nix-mode-map
    "C-c r" 'nix-format-buffer)
  :delight "nix")

Drv mode

A major mode for viewing Nix derivations (.drv files).

(use-package nix-drv-mode
  :ensure nix-mode
  :mode "\\.drv\\'")

Shell (disabled)

(use-package nix-shell
  :ensure nix-mode
  :commands (nix-shell-unpack nix-shell-configure nix-shell-build))

REPL

(use-package nix-repl
  :ensure nix-mode
  :commands (nix-repl))

Update fetch

Command for updating fetch declarations in place.

(use-package nix-update
  :config
  (nmap 'nix-mode-map
    :prefix my/leader
    "n u" 'nix-update-fetch))

Company

Company backend for NixOS options.

(use-package company-nixos-options
  :after (company)
  :commands (company-nixos-options)
  :config
  (add-to-list 'company-backends 'company-nixos-options))

Sandbox

(use-package nix-sandbox)

Flycheck (todo)

TODO: https://github.com/travisbhartwell/nix-emacs#flycheck

Ocaml

Env

(defvar my/opam-config/share (string-trim-right (shell-command-to-string "opam config var share")))

Tuareg

Tuareg is an Emacs OCaml mode.

Provides:

  • Syntax highlighting.
  • REPL (aka toplevel).
  • OCaml debugger within Emacs.

Usage:

  • Start the OCaml REPL with M-x run-ocaml.
  • Run the OCaml debugger with M-x ocamldebug FILE.
(use-package tuareg
  :demand t
  :mode
  (("\\.ml[ily]?$" . tuareg-mode)
   ("\\.mly$" . tuareg-menhir)
   ("\\.topml$" . tuareg-mode)
   ("\\.atd$" . tuareg-mode))
  :init
  (setq tuareg-match-patterns-aligned t)
  :hook
  (caml-mode . tuareg-mode)
  :delight "ocaml")

Smartparens

(with-eval-after-load 'smartparens
  (sp-local-pair 'tuareg-mode "'" nil :actions nil)
  (sp-local-pair 'tuareg-mode "`" nil :actions nil))

Merlin

Context sensitive completion for OCaml. Provides modern IDE features. Implements a minor-mode that is supposed to be used on top of tuareg-mode.

See the package repo for more info.

(use-package merlin
  :after (company tuareg)
  :demand t
  :init
  ;; Disable merlin's own error checking
  ;; We'll use flycheck-ocaml for that
  (setq
   ;; merlin-command "/run/current-system/sw/bin/ocamlmerlin"
   merlin-error-after-save nil
   merlin-completion-with-doc t)
  :config
  (add-to-list 'company-backends 'merlin-company-backend)
  (nmap 'merlin-mode-map
    "C-t" 'merlin-locate
    "C-]" 'merlin-locate
    "C-[" 'merlin-pop-stack
    "g d" 'merlin-locate)
  (nmap 'merlin-mode-map
    :prefix my/leader
    "3" 'merlin-occurrences
    "4" 'merlin-jump
    "5" 'merlin-document
    "9" 'merlin-locate-ident
    "0" 'merlin-iedit-occurrences)
  :hook
  ((tuareg-mode caml-mode) . merlin-mode))

Merlin eldoc (disabled)

Automatically (without using keybindings) provide information for the value under point in OCaml and ReasonML files.

(use-package merlin-eldoc
  :after (merlin)
  :custom
  (eldoc-echo-area-use-multiline-p t)   ; Use multiple lines when necessary
  (merlin-eldoc-max-lines 8)            ; But not more than 8
  (merlin-eldoc-type-verbosity 'min)    ; Don't display verbose types
  (merlin-eldoc-function-arguments t)   ; Show function arguments
  (merlin-eldoc-doc nil)                ; Don't show the documentation
  (merlin-eldoc-occurrences t)          ; Highlight occurences
  :config
  (nmap 'merlin-mode-map
    :prefix my/leader
    "m p" 'merlin-eldoc-jump-to-prev-occurrence
    "m n" 'merlin-eldoc-jump-to-next-occurrence)
  :hook
  ((tuareg-mode reason-mode) . merlin-eldoc-setup))

Customizations for merlin-eldoc

(with-eval-after-load 'merlin-eldoc
  (custom-set-faces
   (set-face-background 'merlin-eldoc-occurrences-face "#111")))

Utop

https://github.com/diml/utop#integration-with-emacs

(use-package utop
  :after (tuareg)
  :commands
  (utop-command)
  :config
  ;; (setq utop-command "opam config exec utop -- -emacs")
  (setq utop-command "opam config exec -- dune utop . -- -emacs")
  (autoload 'utop-minor-mode "utop" "Minor mode for utop" t)
  (nmap 'merlin-mode-map
    "C-c C-j" 'utop
    "C-c C-o" 'utop-eval-buffer)
  (nmap 'utop-mode-map
    "C-c C-j" 'utop
    "C-c C-SPC" 'utop-eval-phrase)
  :hook
  ((tuareg-mode reason-mode) . utop-minor-mode))

Formatting (disabled)

Auto-formatter for OCaml code.

(use-package ocamlformat
  :after (tuareg)
  :load-path (lambda () (concat my/opam-config/share "emacs/site-lisp"))
  :preface
  (defun my/deactivate-ocamlformat ()
    (interactive)
    (setq ocamlformat-enable 'disable))
  (defun my/activate-ocamlformat ()
    (interactive)
    (setq ocamlformat-enable 'enable))
  :custom
  (ocamlformat-show-errors 'echo)
  (ocamlformat-enable 'enable)
  :config
  (add-hook 'tuareg-mode-hook
    (lambda ()
      (general-define-key
       :states '(normal)
       :keymaps 'tuareg-mode-map
       "C-c r" 'ocamlformat)))

  :hook ((before-save . 'ocamlformat-before-save)))

ocp-indent is disabled, I use ocamlformat instead

(use-package ocp-indent
  :after (tuareg)
  :config
  (nmap 'tuareg-mode-map
    "C-c r" 'ocp-indent-buffer))

Dune

A composable build system for OCaml.

(use-package dune)

Flycheck

OCaml support for Flycheck using Merlin.

(use-package flycheck-ocaml
 :after (flycheck merlin)
 :demand t
 :commands
 (flycheck-ocaml-setup)
 :config
 ;; Enable flycheck checker
 (flycheck-ocaml-setup))

Coq

This configuration relies on the Proof General to be cloned here: /.emacs.d/lisp/PG. See the Proof General docs for more info.

(use-package proof-general
  :custom
  (proof-delete-empty-windows t)
  ;; (proof-three-window-mode-policy 'smart)
  ;; see: https://github.com/ProofGeneral/PG/issues/404
  (proof-shrink-windows-tofit nil)
  :delight "coq")

IDE extensions for Proof General’s Coq mode: prettification, autocompletion, snippets, outlines, code folding, jumping to definition, integrated help, etc.

(use-package company-coq
  :after (proof-site)
  :preface
  (defun my/company-coq/setup ()
    (interactive)
    (setq buffer-face-mode-face '(:family "JetBrains Mono"))
    (setq-local
     prettify-symbols-alist
     '((":=" . ?≜)
       ("Proof." . ?∵)
       ("Qed." . ?■)
       ("Defined." . ?□)
       ("Alpha" . ) ("Beta" . ) ("Gamma" . )
       ("Delta" . ) ("Epsilon" . ) ("Zeta" . )
       ("Eta" . ) ("Theta" . ) ("Iota" . )
       ("Kappa" . ) ("Lambda" . ) ("Mu" . )
       ("Nu" . ) ("Xi" . ) ("Omicron" . )
       ("Pi" . ) ("Rho" . ) ("Sigma" . )
       ("Tau" . ) ("Upsilon" . ) ("Phi" . )
       ("Chi" . ) ("Psi" . ) ("Omega" . )
       ("alpha" . ) ("beta" . ) ("gamma" . )
       ("delta" . ) ("epsilon" . ) ("zeta" . )
       ("eta" . ) ("theta" . ) ("iota" . )
       ("kappa" . ) ("lambda" . ) ("mu" . )
       ("nu" . ) ("xi" . ) ("omicron" . ?ο)
       ("pi" . ) ("rho" . ) ("sigma" . )
       ("tau" . ) ("upsilon" . ) ("phi" . )
       ("chi" . ) ("psi" . ) ("omega" . )))
    (sp-local-pair 'coq-mode "'" nil :actions nil))
  :commands (company-coq-mode)
  :hook
  (coq-mode . company-coq-mode)
  (coq-mode . my/company-coq/setup)
  :init
  (setq
   ;; Enable autocompletion for theorem names and
   ;; symbols defined in the libraries we load
   company-coq-live-on-the-edge t
   company-coq-disabled-features '()
  ;; Disable symbol prettification
   company-coq-disabled-features '(prettify-symbols)
   company-coq-dynamic-autocompletion t)
  :config
  (nmap 'coq-mode-map
    "C-C C-t" 'coq-About)
  (nmap 'coq-mode-map
    :prefix my/leader
    "3" 'coq-SearchAbout
    "4" 'coq-Print
    "5" 'coq-LocateNotation
    "6" 'coq-LocateConstant
    "7" 'coq-Inspect
    "8" 'coq-About
    "9" 'coq-Show
    "0" 'coq-Check)
  (nmap 'coq-mode-map
    "g d" 'company-coq-jump-to-definition))

Lean (disabled)

Emacs mode for the Lean theorem prover. Keybindings: https://github.com/leanprover/lean-mode#key-bindings-and-commands

(use-package lean-mode)

Minizinc

(use-package minizinc-mode
  :mode
  ("\\.mzn\\'"))

TLA+

(use-package tla-mode
  :quelpa
  (tla-mode :fetcher github :repo "ratish-punnoose/tla-mode")
  :mode "\.tla$")
(use-package polymode)

(use-package tla-pcal-mode
  :after (polymode)
  :quelpa
  (tla-pcal-mode :fetcher github :repo "mrc/tla-tools"))

SML

(use-package sml-mode
  :quelpa (sml-mode :fetcher github :repo "emacsmirror/sml-mode")
  :mode "\\.sml$"
  :custom
  (sml-indent-level 2)
  :config
  (nmap 'sml-mode-map
    "C-c C-o" 'sml-prog-proc-load-file
    "C-c C-j" 'sml-prog-proc-switch-to))

Scheme

(use-package geiser
 :after general)

(use-package scheme
 :ensure nil
 :after (geiser)
 :preface
 (defun my/scheme/setup ()
   (geiser-mode t))
 :hook
 (scheme-mode . my/scheme/setup))

(use-package quack
 :after (scheme)
 :config
 (setq
  ;; use emacs-style fontification
  quack-fontify-style 'emacs))

Racket

(use-package faceup)
(use-package racket-mode
 :after
 (general
  smartparens
  org
  faceup
  geiser)
 :if (executable-find "racket")
 :mode ("\\.rkt[dl]?\\'" . racket-mode)
 :interpreter ("racket" . racket-mode)
 :hook
 (racket-mode . smartparens-mode)
 :init
 (setq
  geiser-scheme-implementation 'racket
  racket-smart-open-bracket-enable t)
 :config
 (add-to-list 'org-babel-load-languages '(racket . t))
 (sp-local-pair 'racket-mode "'" nil :actions nil)
 (sp-local-pair 'racket-mode "`" nil :actions nil))

Clojure

(use-package clojure-mode
 :after (general company org)
 :defer 1
 :commands
 (define-clojure-indent
  put-clojure-indent)
 :mode
 (("\\.clj\\'" . clojure-mode)
  ("\\.edn\\'" . clojure-mode)
  ("\\.boot\\'" . clojure-mode)
  ("\\.cljs.*\\'" . clojure-mode))
 :init
 (setq inferior-lisp-program "lein repl")
 :config
 (add-to-list 'org-babel-load-languages '(clojure . t))
 (nmap 'clojure-mode-map
   :prefix my/leader
   "C s" 'cider-start-http-server
   "C r" 'cider-refresh
   "C u" 'cider-user-ns
   "C R" 'cider-restart)
 (define-clojure-indent (fact 1))
 (define-clojure-indent (facts 1)))
(use-package clojure-mode-extra-font-locking
 :after (clojure-mode)
 :defer 1
 :init
 (font-lock-add-keywords
  nil
  '(("(\\(facts?\\)"
     (1 font-lock-keyword-face))
    ("(\\(background?\\)"
     (1 font-lock-keyword-face)))))
(use-package cider
 :after (clojure-mode)
 :defer 1
 :commands (cider-mode)
 :custom
 (cider-repl-result-prefix ";; => ")
 :init
 (setq
  ;; go right to the REPL buffer when it's finished connecting
  cider-repl-pop-to-buffer-on-connect t
  ;; when there's a cider error, show its buffer and switch to it
  cider-show-error-buffer t
  cider-auto-select-error-buffer t
  cider-repl-history-file "~/.emacs.d/cider-history"
  cider-repl-wrap-history t)
 :hook
 (clojure-mode . clojure-mode))
(use-package kibit-helper
 :defer 1)
(use-package flycheck-clojure
  :after (flycheck clojure-mode)
  :defer 1
  :commands
  (flycheck-clojure-setup)
  :config
  (eval-after-load 'flycheck '(flycheck-clojure-setup)))

Scala

Mode

Enable scala-mode for highlighting, indentation and motion commands.

(use-package scala-mode
 :after (general)
 :if (executable-find "scala")
 :interpreter
 ("scala" . scala-mode)
 :hook
  (scala-mode . lsp))

Sbt

Enable ==sbt-mode= for executing sbt commands.

(use-package sbt-mode
  :commands sbt-start sbt-command
  :config
  ;; WORKAROUND: https://github.com/ensime/emacs-sbt-mode/issues/31
  ;; allows using SPACE when in the minibuffer
  (substitute-key-definition
   'minibuffer-complete-word
   'self-insert-command
   minibuffer-local-completion-map)
   ;; sbt-supershell kills sbt-mode:  https://github.com/hvesalai/emacs-sbt-mode/issues/152
   (setq sbt:program-options '("-Dsbt.supershell=false"))
)

LSP

Add metals backend for lsp-mode.

(use-package lsp-metals
  :config (setq lsp-metals-treeview-show-when-views-received t))

Kotlin

(use-package kotlin-mode)
(use-package flycheck-kotlin
 :after (kotlin-mode flycheck)
 :commands
 (flycheck-kotlin-setup)
 :config
 (flycheck-kotlin-setup))

Rust

rustic

Rust development environment for Emacs.

(use-package rustic
 :after (lsp-mode)
 :preface
 (defun my/rustic/setup ()
  ;; So that run C-c C-c C-r works without having to confirm,
  ;; but don't try to save rust buffers that are not file visiting.
  ;; Once https://github.com/brotzeit/rustic/issues/253 has been
  ;; resolved this should no longer be necessary
  (when buffer-file-name
    (setq-local buffer-save-without-query t))
  (setq lsp-ui-sideline-enable nil))
  :config
  (setq rustic-format-on-save t)

  ;; uncomment for less flashiness
  ;; (setq lsp-eldoc-hook nil)
  ;; (setq lsp-enable-symbol-highlighting nil)
  ;; (setq lsp-signature-auto-activate nil)

  (nmap 'rustic-mode-map
   "C-c R" 'rustic-cargo-fmt
   "C-c r" 'rustic-format-buffer)
  :hook
  (rustic-mode . my/rustic/setup))

rust-mode (disabled)

(use-package rust-mode
 :after (company general)
 :if (executable-find "rustc")
 :commands (rust-mode)
 :config
 ;; enable rust-mode for .lalrpop files
 (add-to-list 'auto-mode-alist '("\\.lalrpop\\'" . rust-mode))
 (general-define-key
  :keymaps 'rust-mode-map
  "TAB" 'company-indent-or-complete-common
  "C-c C-b" 'rust-compile
  "C-c <tab>" 'rust-format-buffer))

racer (disabled)

Some of key bindings are provided by ==evil-collection=.

(use-package racer
 :after rust-mode
 :demand t
 :commands racer-mode
 :hook
 ((racer-mode . eldoc-mode)
  (racer-mode . company-mode)
  (rust-mode . racer-mode)))

cargo (disabled)

(use-package cargo
 :after (general rust-mode)
 :config
 (nmap 'rust-mode-map
   :prefix my/leader
   "c ." 'cargo-process-repeat
   "c c" 'cargo-process-clean
   "c b" 'cargo-process-build
   "c c" 'cargo-process-check
   "c d" 'cargo-process-doc
   "c e" 'cargo-process-bench
   "c f" 'cargo-process-current-test
   "c f" 'cargo-process-fmt
   "c i" 'cargo-process-init
   "c n" 'cargo-process-new
   "c o" 'cargo-process-current-file-tests
   "c s" 'cargo-process-search
   "c u" 'cargo-process-update
   "c x" 'cargo-process-run
   "c X" 'cargo-process-run-example
   "t" 'cargo-process-test))

company-racer (disabled)

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

flycheck-rust (disabled)

(use-package flycheck-rust
  :config
  (with-eval-after-load 'rust-mode
    (add-hook 'flycheck-mode-hook #'flycheck-rust-setup)))

Prolog

(use-package prolog
 :ensure nil
 :preface
 (defun my/mercury-mode/setup ()
   (electric-indent-mode -1))
 :commands
 (prolog-mode mercury-mode)
 :hook
 (mercury-mode . my/mercury-mode/setup)
 :mode
 (("\\.pl\\'" . prolog-mode)
  ("\\.m\\'" . mercury-mode))
 :init
 (setq prolog-system 'swi))

TODO: add https://github.com/flycheck/flycheck-mercury

Dhall

(use-package dhall-mode
 :custom
 (dhall-format-at-save t)
 :mode "\\.dhall\\'")

Terraform

Mode

(use-package terraform-mode
 :hook (terraform-mode . terraform-format-on-save-mode))

Company

(use-package company-terraform
 :after (terraform company)
 :commands
 (company-terraform-init)
 :config
 (company-terraform-init))

SQL

(use-package format-sql
 :after (general)
 :config
 (vmap 'sql-mode-map
   "C-c R" 'format-sql-region)
 (nmap 'sql-mode-map
   "C-c r" 'format-sql-buffer))
(use-package sqlup-mode
  :after (general)
  :hook
  ;; capitalize keywords in SQL mode
  ;; capitalize keywords in an interactive session (e.g. psql)
  ((sql-mode sql-interactive-mode) . sqlup-mode)
  :config
  (add-to-list 'sqlup-blacklist "name")
  (add-to-list 'sqlup-blacklist "public")
  (add-to-list 'sqlup-blacklist "state")
  (nmap
    :keymaps '(sql-mode-map sql-interactive-mode-map)
    :prefix my/leader
    "S u" 'sqlup-capitalize-keywords-in-region
    "S U" 'sqlup-capitalize-keywords-in-buffer))

Json

(use-package json-mode
  :mode "\\.bowerrc$")

Allows to display any JSON document as a tree. Doesn’t work, see: DamienCassou/json-navigator#22

(use-package json-navigator)

Reformat tool for JSON.

(use-package json-reformat)

Yaml

(use-package yaml-mode
 :config
 :delight "yaml")
(use-package flycheck-yamllint
 :after (flycheck yaml-mode)
 :commands
 (flycheck-yamllint-setup)
 :config
 (flycheck-yamllint-setup))

Toml

(use-package toml-mode)

Protobuf

(use-package protobuf-mode)

Emmet

(use-package emmet-mode
 :after (general sgml-mode)
 :defer 1
 :commands
 emmet-mode
 :hook
 ((sgml-mode ; auto-start on any markup modes
   css-mode  ; enable css abbreviation
   html-mode
   jade-mode) . emmet-mode)
 :config
 (imap
   "C-x C-o" 'emmet-expand-line)
 :delight "emmet")

Python

(use-package python-mode
 :preface
 (defun my/python-mode/setup ()
   (mapc (lambda (pair) (push pair prettify-symbols-alist))
         '(("def" . "𝒇")
           ("class" . "𝑪")
           ("and" . "")
           ("or" . "")
           ("not" . "")
           ("in" . "")
           ("not in" . "")
           ("return" . "")
           ("yield" . "")
           ("for" . "")
           ("!=" . "")
           ("==" . "")
           (">=" . "")
           ("<=" . "")
           ("[]" . "")
           ("=" . ""))))
 :hook
 (python-mode . my/python-mode/setup))

Ruby

(use-package inf-ruby
 :hook
 ;; automatically switch from common ruby compilation modes
 ;; to interact with a debugger
 (compilation-filter . inf-ruby-auto-enter)
 ;; required to use binding.pry or byebug
 (after-init . inf-ruby-switch-setup))
(use-package robe
 :after (company)
 :hook
 (ruby-mode . robe-mode)
 :config
 (add-to-list 'company-backends 'company-robe)
 :delight "robe")
(use-package rubocop
 :after (robe)
 :hook
 (ruby-mode . rubocop-mode)
 :delight "rcop")
(use-package bundler
 :after general
 :config
 (nmap 'ruby-mode-map
   :prefix my/leader
   "b i" 'bundle-install
   "b c" 'bundle-console
   "b o" 'bundle-outdated
   "b u" 'bundle-update
   "b e" 'bundle-exec))
(use-package rbenv
 :commands
 (global-rbenv-mode)
 :preface
 (defun my/rbenv/modeline (current-ruby)
   (append
    '(" ruby [")
    (list (propertize current-ruby 'face 'rbenv-active-ruby-face))
    '("]")))
 :hook
 (ruby-mode . rbenv-use-corresponding)
 :init
 (setq rbenv-modeline-function 'my/rbenv/modeline)
 :config
 (global-rbenv-mode)
 (nmap 'ruby-mode-map
   :prefix "C-c R"
   "c" 'rbenv-use-corresponding
   "u" 'rbenv-use))
(use-package rake
 :after (general projectile)
 :init
 (setq rake-completion-system projectile-completion-system)
 :config
 (nmap 'ruby-mode-map
   :prefix my/leader
   "r" 'rake))
(use-package rspec-mode)
(use-package projectile-rails
 :after projectile
 :commands
 (projectile-rails-global-mode)
 :init
 (setq
  projectile-rails-vanilla-command "bin/rails"
  projectile-rails-spring-command "bin/spring"
  projectile-rails-zeus-command "bin/zeus")
 :config
 (projectile-rails-global-mode)
 :diminish)

PHP

(use-package php-mode
  :mode "\\.\\(php\\|inc\\)$")

Java

(use-package gradle-mode
  :hook ((java-mode kotlin-mode) . gradle-mode))
(use-package javadoc-lookup)

Web

Mode

(use-package web-mode
  :after (tide)
  :preface
  (defun my/web-mode/setup ()
    (interactive)
    (when (string-equal "tsx" (file-name-extension buffer-file-name))
      (setup-tide-mode)))
  :mode
  (("\\.html?\\'" . web-mode)
   ("\\.html\\.erb\\'" . web-mode)
   ("\\.erb\\'" . web-mode)
   ("\\.djhtml\\'" . web-mode)
   ("\\.tsx\\'" . web-mode)
   ("\\.jsx\\'" . web-mode)
   ("\\.mustache\\'" . web-mode)
   ("\\.jinja\\'" . web-mode)

   ("\\.css\\'" . web-mode)
   ("\\.scss\\'" . web-mode)

   ("\\.[agj]sp\\'" . web-mode)
   ("\\.as[cp]x\\'" . web-mode)
   ("\\.as\\'" . web-mode)

   ("\\.phtml\\'" . web-mode)
   ("\\.tpl\\.php\\'" . web-mode)
   ("\\.php\\'" . web-mode))

  :init
  (setq
   ;; indent HTML automatically
   web-mode-indent-style 2
   ;; offsets
   web-mode-markup-indent-offset 2
   web-mode-css-indent-offset 2
   web-mode-code-indent-offset 2

   web-mode-engines-alist
   '(("\\.jinja\\'"  . "django")
     ("php" . "\\.php[3-5]?"))

   web-mode-enable-auto-pairing t
   web-mode-enable-css-colorization t
   web-mode-enable-current-element-highlight t
   web-mode-enable-current-column-highlight nil)
  :config
  (flycheck-add-mode 'javascript-eslint 'web-mode)
  :hook
  (web-mode . my/web-mode/setup))

Cakecrumbs

Display current path for HTML/XML/CSS.

(use-package cakecrumbs
  :config
  (cakecrumbs-auto-setup))

Company

(use-package company-web
 :after company
 :demand t)

Styling

CSS mode

(use-package css-mode)

Counsel CSS

(use-package counsel-css
  :after counsel
)

SCSS mode

(use-package scss-mode
 :config
 :delight "scss")

Go

(use-package go-mode
  :after (company flycheck)
  :if (executable-find "go")
  :preface
  (defun my/go-mode/setup ()
    (add-hook 'before-save-hook 'gofmt-before-save)
    (add-hook 'go-mode-hook 'flycheck-mode)
    (setq-default)
    (setq standard-indent 8)
    (setq tab-width 8)
    (setq indent-tabs-mode 1))
  :mode "\\.go\\'"
  :hook
  (go-mode . my/go-mode/setup))
(use-package company-go
 :after (company go-mode)
 :hook
 (go-mode . company-mode)
 :config
 (add-to-list 'company-backends 'company-go))
(use-package go-stacktracer)

(use-package go-add-tags)

(use-package go-eldoc
  :hook
  (go-mode . go-eldoc-setup))

(use-package go-gopath)

(use-package gotest)

(use-package go-playground)

TypeScript

TypeScript mode.

(use-package typescript-mode
  :preface
  (defun my/typescript-mode/setup ()
    ;; The error messages produced by tsc when its pretty flag
    ;; is turned on include ANSI color escapes, which by default
    ;; compilation-mode does not interpret. In order to get the
    ;; escapes parsed we do the following:
    (require 'ansi-color)
    (defun colorize-compilation-buffer ()
      (ansi-color-apply-on-region compilation-filter-start (point-max)))
    (add-hook 'compilation-filter-hook 'colorize-compilation-buffer))
  :custom
  (typescript-indent-level 2)
  :hook
  (typescript-mode . my/typescript-mode/setup))

TypeScript IDE.

(use-package tide
  :after (typescript-mode flycheck company)
  :preface
  (defun my/tide/setup ()
    (interactive)
    (tide-setup)
    (flycheck-mode +1)
    (eldoc-mode +1)
    (tide-hl-identifier-mode +1)
    (company-mode +1))
  :custom
  (tide-format-options
   '(:indentSize 2 :tabSize 2 :indentStyle 2))
  :config
  (flycheck-add-next-checker 'javascript-eslint 'jsx-tide 'append)
  (nmap tide-mode-map
    :prefix my/leader
    "0" 'tide-jsdoc-template)
  :hook
  ((typescript-mode . my/tide/setup)
   (before-save . tide-format-before-save)))

TypeScript REPL.

(use-package ts-comint
  :custom
  (ts-comint-program-command "ts-node"))

JavaScript

tern

(use-package tern
 :commands
 (tern-mode)
 :config
 ;; Enable js completion between <script>...</script> etc
 (defadvice company-tern (before web-mode-set-up-ac-sources activate)
   "Set `tern-mode' based on current language before running company-tern."
   (message "advice")
   (if (equal major-mode 'web-mode)
       (let ((web-mode-cur-language (web-mode-language-at-pos)))
         (if (or (string= web-mode-cur-language "javascript")
                 (string= web-mode-cur-language "jsx"))
             (unless tern-mode (tern-mode))
           (if tern-mode (tern-mode -1)))))))

npm

(use-package npm-mode
 :commands
 (npm-mode npm-global-mode)
 :config
 (npm-global-mode)
 :diminish npm-mode)

js2

(use-package js2-mode
 :init
 ;; indent step is 2 spaces
 (setq-default js2-basic-offset 2)
 (setq-default js-indent-level 2)
 (setq
  ;; configure indentation
  js2-enter-indents-newline t
  js2-auto-indent-p t
  ;; Idle timeout before reparsing buffer
  js2-idle-timer-delay 0.5
  ;; disable error parsing in favor of Flycheck
  js2-strict-missing-semi-warning nil)
 :commands js2-mode
 :config
 (add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
 :delight "js2")

eslintd-fix

A very fast JS linter and fixer.

(use-package eslintd-fix
 :hook
 (tide-mode . eslintd-fix-mode))

xref-js2

Jump to references/definitions using ag & js2-mode’s AST. See the repo for details.

(use-package xref-js2
 :preface
 (defun my/xref-js2/add-backend ()
   (add-hook 'xref-backend-functions
             'xref-js2-xref-backend nil t))
 :hook
 (js2-mode . my/xref-js2/add-backend)
 :config
 (unbind-key "M-." js2-mode-map))

js2-refactor

A JavaScript refactoring library.

(use-package js2-refactor
 :commands
(js2r-add-keybindings-with-prefix)
 :hook
 (js2-mode . js2-refactor-mode)
 :config
 ;; enable minor mode for js refactoring
 ;; see: https://github.com/magnars/js2-refactor.el#refactorings
 (js2r-add-keybindings-with-prefix "C-c C-j"))

prettier

(use-package prettier-js
 :hook
 ((js2-mode-hook web-mode-hook) . prettier-js-mode)
 :delight "pr")

GraphQL

(use-package graphql-mode
 :mode "\\.graphql\\'"
 :custom
 (graphql-url "http://localhost:8000/api/graphql/query"))

Vue

(use-package vue-mode)

Elm

(use-package elm-mode
  :custom
  (elm-format-on-save t)
  (elm-package-json "elm.json")
  (elm-tags-exclude-elm-stuff nil)
  (elm-tags-on-save t))
(use-package flycheck-elm
 :after (elm-mode flycheck)
 :hook
 (flycheck-mode . flycheck-elm-setup))

Nginx

(use-package nginx-mode)

D

(use-package d-mode)

C/C++

Syntax highlighting

Syntax highlighting support for “Modern C++” - until C++20 and Technical Specification. This package aims to provide a simple highlight of the C++ language without dependency.

(use-package modern-cpp-font-lock
  :config
  (modern-c++-font-lock-global-mode t))

Preprocessor highlighting (disabled)

Highlight C-style preprocessor directives in Emacs.

(use-package preproc-font-lock
  :config
  (preproc-font-lock-global-mode 1))

CMake

GLSL

(use-package glsl-mode)

(use-package company-glsl)

Solidity

A simple language mode for the Solidity language.

(use-package solidity-mode
 :custom
 (solidity-comment-style 'slash))

(use-package solidity-flycheck
 :custom
 (solidity-solc-path "~/.npm-packages/bin/solcjs")
 (solidity-solium-path "~/.npm-packages/bin/solium")
 (solidity-flycheck-solc-checker-active nil)
 (solidity-flycheck-solium-checker-active nil))

Kconfig

(use-package kconfig-mode)

Bison (disabled)

Conflicts with happy-mode, so make sure to manually enable the happy-mode when working with .y parser files.

(use-package bison-mode)

Octave

(use-package octave
 :after general
 :ensure nil
 ;; Overlaps with mercury-mode
 :mode ("\\.octave\\'" . octave-mode))
(use-package cmake-mode
  :mode (("\\.cmake\\'" . cmake-mode)
         ("\\CMakeLists.txt$" . cmake-mode)))

(use-package cmake-font-lock
  :config
  (autoload 'cmake-font-lock-activate "cmake-font-lock" nil t)
  (add-hook 'cmake-mode-hook 'cmake-font-lock-activate))

(use-package eldoc-cmake
  :hook (cmake-mode . eldoc-cmake-enable))

Latex

(use-package tex
 :demand t
 ; Issues with aucstex in MacOs
 :ensure auctex
 :config
 (setq-default TeX-engine 'luatex)
 (setq-default TeX-PDF-mode t)
 (setq-default TeX-master nil)
 (setq TeX-view-program-selection '((output-pdf "PDF Tools")))
 (setq reftex-plug-into-AUCTeX t)
 (setq reftex-bibliography-commands '("bibliography" "nobibliography" "addbibresource"))
 (setq reftex-use-external-file-finders t)
 (setq reftex-external-file-finders
       '(("tex" . "kpsewhich -format=.tex %f")
         ("bib" . "kpsewhich -format=.bib %f")))
 (setq reftex-insert-label-flags '("s" "sft" "e"))
 (setq TeX-electric-sub-and-superscrip t)
 (setq TeX-electric-math (cons "\\(" "\\)"))
 :hook
 ((LaTeX-mode . visual-line-mode)
  (LaTeX-mode . turn-on-auto-fill)
  (LaTeX-mode . flyspell-mode)
  (LaTeX-mode . LaTeX-math-mode)
  (LaTeX-mode . turn-on-reftex)
  (TeX-after-compilation-finished-functions
    . TeX-revert-document-buffer)))

(use-package auctex-latexmk
  :hook (LaTeX-mode . auctex-latexmk-setup))

Add company mode support. This package provides completion back-ends for math unicode symbols and latex tags.

(use-package company-math
 :config
 (add-to-list 'company-backends 'company-math-symbols-latex)
 (add-to-list 'company-backends 'company-math-symbols-unicode))

Pug

(use-package pug-mode)

Jade

(use-package jade-mode)

Haml

(use-package haml-mode)

Slim

(use-package slim-mode
 :delight "slim")

Lua

(use-package lua-mode
  :preface
  (defun my/lua-prettify-symbols-setup ()
    (dolist (symbol '(("~="  . (?\s (Br . Bl) ?\s (Bc . Bc) ?≠))
                      ("function"  . )
                      ("math.huge" . ?∞)))
      (cl-pushnew symbol prettify-symbols-alist :test #'equal)))
  :mode "\\.lua\\'"
  :custom
  (lua-documentation-function 'eww)
  :init
  (setq lua-indent-level 2)
  :hook
  (lua-mode . my/lua-prettify-symbols-setup))

(use-package lua-block
  :after (lua-mode)
  :quelpa
  (lua-block
   :fetcher url
   :url "http://www.emacswiki.org/emacs/download/lua-block.el")
  :init
  (autoload 'lua-block-mode "lua-block" nil t)
  :delight "lb")

Forth

(use-package forth-mode)

Arduino

(use-package arduino-mode
  :init
  ;; TODO: irony-arduino-includes-options
  ;; see https://github.com/yuutayamada/company-arduino/issues/5
  ;; TODO: https://github.com/yuutayamada/company-arduino/issues/6
  :config
  ;; Activate irony-mode on arduino-mode
  (add-hook 'arduino-mode-hook 'irony-mode)
  (nmap
    :prefix my/leader
    "a v" 'arduino-verify
    "a u" 'arduino-upload
    "a i" 'arduino-install-library
    "a m" 'arduino-menu
    "a n" 'arduino-sketch-new
    "a b" 'arduino-install-boards
    "a s" 'arduino-serial-monitor))
(use-package company-arduino
  :after (irony company company-irony company-c-headers)
  :config
  ;; Add arduino's include options to irony-mode's variable
  (add-hook 'irony-mode-hook 'company-arduino-turn-on)
  ;; Configuration for company-c-headers.el
  ;; The `company-arduino-append-include-dirs' function appends
  ;; Arduino's include directories to the default directories
  ;; if `default-directory' is inside `company-arduino-home'. Otherwise
  ;; just returns the default directories.
  ;; Please change the default include directories accordingly.
  (defun my-company-c-headers-get-system-path ()
    "Return the system include path for the current buffer."
    (let ((default '("/usr/include/" "/usr/local/include/")))
      (company-arduino-append-include-dirs default t)))
  (setq company-c-headers-path-system 'my-company-c-headers-get-system-path))

Robots.txt

(use-package robots-txt-mode)

Dotenv

(use-package dotenv-mode
 :config
 (add-to-list 'auto-mode-alist '("\\.env\\..*\\'" . dotenv-mode)))

CSV

(use-package csv-mode
  :mode "\\.[Cc][Ss][Vv]$"
  :init
  (setq
   ;; default separators for CSV files.
   csv-separators '("," ";" "|" " " "\t")
   ;; number of lines to consider part of header.
   csv-header-lines 1))

Api blueprint

(use-package apib-mode
  :after general
  :config
  (nmap 'apib-mode-map
    :prefix my/leader
    "z p" 'apib-parse           ; Parse the API Blueprint
    "z v" 'apib-validate        ; Validate the API Blueprint
    "z j" 'apib-get-json        ; Print all generated JSON bodies
    "z s" 'apib-get-json-schema ; Print all generated JSON Schemas
    ))

NASM

(use-package nasm-mode)

IASM

(use-package iasm-mode)

BNF

(use-package bnf-mode
 :mode "\\.bnf\\'")

CUDA

(use-package cuda-mode
  :mode
  (("\\.cu\\'" . cuda-mode)
   ("\\.cuh\\'" . cuda-mode)))

APL

(use-package gnu-apl-mode)
(use-package dyalog-mode)

Ansible

(use-package ansible)

DAP

Use the Debug Adapter Protocol for running tests and debugging.

(use-package dap-mode
  :config
  (require 'dap-cpptools)
  (dap-mode 1)
  (dap-ui-mode 1)
  (add-hook 'dap-stopped-hook
    (lambda (arg) (call-interactively #'dap-hydra)))
  :hook
  (lsp-mode . dap-mode)
  (lsp-mode . dap-ui-mode))

GDB

When gdb debugging, show the many windows (stack trace, break points, etc).

(use-package gdb-mi
  :ensure nil
  :commands (gdb-many-windows)
  :hook
  (gdb . gdb-many-windows))

Coverage

Test coverage overlay. Highlights untested lines.

(use-package coverlay
  :preface
  (defun my/coverlay-mode-enable ()
    "Turn on `coverlay-mode'."
    (coverlay-minor-mode 1)
    (when (and (buffer-file-name) (not (bound-and-true-p coverlay--loaded-filepath)))
      (let* ((coverage-file
              (concat
               (locate-dominating-file (file-name-directory (buffer-file-name)) "coverage")
               "coverage"
               "/lcov.info")))
        (when (file-exists-p coverage-file)
          (coverlay-watch-file coverage-file)))))
  :custom
  (coverlay:mark-tested-lines nil)
  :diminish coverlay-minor-mode)

Quickrun

Run command quickly.

(use-package quickrun
  :preface
  (defun my/display-ctrl-M-as-newline ()
    "Display `^M' as newline."
    (interactive)
    (setq buffer-display-table (make-display-table))
    (aset buffer-display-table ?\^M [?\n]))
  :hook
  (quickrun--mode . my/display-ctrl-M-as-newline)
  :config
  (nmap
    :prefix my/leader
    "i q" 'quickrun
    "i r" 'quickrun-region
    "i a" 'quickrun-autorun-mode))

Docker

Emacs integration for Docker. Supports docker containers, images, volumes, networks, docker-machine and docker-compose.

(use-package docker
 :diminish docker-mode
 :config
 (nmap
   :prefix my/leader
   "d" 'docker))
(use-package docker-compose-mode)

Kubernetes

(use-package timonier
 :after general
 :init
 (setq timonier-k8s-proxy "http://localhost:8001"))

HTTP

(use-package restclient
 :mode
 ("\\.http\\'" . restclient-mode))
(use-package restclient-test
 :hook
 (restclient-mode-hook . restclient-test-mode))
(use-package ob-restclient
 :after (org restclient)
 :init
 (org-babel-do-load-languages
  'org-babel-load-languages
  '((restclient . t))))
(use-package company-restclient
 :after (company restclient)
 :custom-update
 (company-backends '(company-restclient)))

Statistics

SLOC

(use-package sloc
  :quelpa (sloc :fetcher github :repo "leoliu/sloc.el"))

Uptimes (disabled)

Provides a simple system for tracking and displaying the uptimes of Emacs sessions.

(use-package uptimes)

Keyfreq (disabled)

Measure how many time you execute commands. The following blog post explains this in details.

(use-package keyfreq
 :commands
 (keyfreq-mode keyfreq-autosave-mode)
 :config
 (keyfreq-mode 1)
 (keyfreq-autosave-mode 1))

Wakatime (disabled)

Setup wakatime.

(use-package wakatime-mode
 :init
 (setq
  wakatime-api-key (getenv "WAKATIME_API_KEY")
  wakatime-cli-path "/run/current-system/sw/bin/wakatime")
 :config
 (global-wakatime-mode)
 :diminish wakatime-mode)

Hydra

Install

Install hydra.

(use-package hydra
 :config

Text scale

Define hydra for text scaling.

(defhydra hydra-zoom ()
  "
 ^Zoom^
───────────────────────────────────
"
  ("=" text-scale-increase nil)
  ("k" text-scale-increase "in")
  ("j" text-scale-decrease "out")
  ("+" text-scale-increase "in")
  ("-" text-scale-decrease "out")
  ("0" (text-scale-set 0) "remove"))

Window management

Define window management hydra.

(defhydra hydra-window ()
  "
Movement^^      ^Split^            ^Resize^
────────────────────────────────────────────────────
_h_ ←          _v_ertical          _H_ X←
_j_ ↓          _s_ horizontal      _J_ X↓
_k_ ↑          _U_ undo            _K_ X↑
_l_ →          _R_ reset           _L_ X→
_f_ollow       _d_lt Other
_SPC_ cancel   _o_nly this
"
  ("h" windmove-left)
  ("j" windmove-down)
  ("k" windmove-up)
  ("l" windmove-right)

  ("H" evil-window-increase-width)
  ("J" evil-window-increase-height)
  ("K" evil-window-decrease-height)
  ("L" evil-window-decrease-width)

  ("f" follow-mode)
  ("v"
   (lambda ()
     (interactive)
     (split-window-right)
     (windmove-right))
   )
  ("s"
   (lambda ()
     (interactive)
     (split-window-below)
     (windmove-down))
   )
  ("d" delete-window)
  ("o" delete-other-windows)
  ("i" ace-maximize-window)
  ("U"
   (progn
     (winner-undo)
     (setq this-command 'winner-undo))
   )
  ("R" winner-redo)
  ("SPC" nil))

Rectangle

(defhydra hydra-rectangle ()
  "
^Rectangle^
───────────────────
_m_: mark region
_k_: kill region
_y_: yank region
  "
  ("m" rectangle-mark-mode nil)
  ("y" yank-rectangle nil)
  ("k" kill-rectangle nil)

  ("l" forward-char)
  ("h" backward-char)
  ("j" next-line)
  ("k" previous-line)
  ("0" move-beginning-of-line)
  ("$" move-end-of-line))

Flycheck

(defhydra hydra-flycheck (:color blue)
  "
  ^
  ^Flycheck^          ^Errors^            ^Checker^
  ^────────^──────────^──────^────────────^───────^─────
  _M_ manual          _<_ previous        _?_ describe
  _v_ verify setup    _>_ next            _d_ disable
  ^^                  _f_ check           _m_ mode
  ^^                  _l_ list            _s_ select
  ^^                  ^^                  ^^
  "
  ("<" flycheck-previous-error :color pink)
  (">" flycheck-next-error :color pink)
  ("?" flycheck-describe-checker)
  ("M" flycheck-manual)
  ("d" flycheck-disable-checker)
  ("f" flycheck-buffer)
  ("l" flycheck-list-errors)
  ("m" flycheck-mode)
  ("s" flycheck-select-checker)
  ("v" flycheck-verify-setup))

Yasnippet

(defhydra hydra-yasnippet (:color blue :hint nil)
  "
^YASnippets^
───────────────────────
_i_: insert snippet
_v_: visit snippet files
_n_: new
_r_: reload all
  "
  ("i" yas-insert-snippet)
  ("v" yas-visit-snippet-file :color blue)
  ("n" yas-new-snippet)
  ("r" yas-reload-all))

Macro

(defhydra hydra-macro ()
  "
^Macro^
────────────────────────────
_j_: create new macro
_k_: end creation of new macro
_e_: execute last macro
_n_: insert Counter
  "
  ("j" kmacro-start-macro :color blue)
  ("k" kmacro-end-macro :colocr blue)
  ("e" kmacro-end-or-call-macro-repeat)
  ("n" kmacro-insert-counter))

Org

Base

(defhydra hydra-org/base ()
  "
^Org base^
───────────────
_s_: store link
_l_: insert link

_r_: refile
_t_: insert tag
"
  ("s" org-store-link nil :color blue)
  ("l" org-insert-link nil :color blue)
  ("r" org-refile nil :color blue)
  ("t" org-set-tags-command nil :color blue))

Link

(defhydra hydra-org/link ()
  "
^Org link^
────────────────────────────────────────────────────────
_i_ backward slurp     _o_ forward slurp    _n_ next link
_j_ backward barf      _k_ forward barf     _p_ previous link
"
  ("i" org-link-edit-backward-slurp)
  ("o" org-link-edit-forward-slurp)
  ("j" org-link-edit-backward-barf)
  ("k" org-link-edit-forward-barf)
  ("n" org-next-link)
  ("p" org-previous-link))

Table

(defhydra hydra-org/table ()
  "
^Org table^
──────────────────────────────────────────────────────────
_r_ recalculate     _w_ wrap region      _c_ toggle coordinates
_i_ iterate table   _t_ transpose        _D_ toggle debugger
_B_ iterate buffer  _E_ export table     _d_ edit field
_e_ eval formula    _s_ sort lines       ^^
"
  ("E" org-table-export :color blue)
  ("s" org-table-sort-lines)
  ("d" org-table-edit-field)
  ("e" org-table-eval-formula)
  ("r" org-table-recalculate)
  ("i" org-table-iterate)
  ("B" org-table-iterate-buffer-tables)
  ("w" org-table-wrap-region)
  ("D" org-table-toggle-formula-debugger)
  ("t" org-table-transpose-table-at-point)
  ("c" org-table-toggle-coordinate-overlays :color blue))

Babel

(defhydra hydra-org/babel ()
  "
^Org babel^
────────────────────────────────────────────────
_n_ next       _i_ info           _I_ insert header
_p_ prev       _c_ check          _e_ examplify region
_h_ goto head  _E_ expand         ^^
^^             _s_ split          ^^
^^             _r_ remove result  ^^
"
  ("i" org-babel-view-src-block-info)
  ("I" org-babel-insert-header-arg)
  ("c" org-babel-check-src-block :color blue)
  ("s" org-babel-demarcate-block :color blue)
  ("n" org-babel-next-src-block)
  ("p" org-babel-previous-src-block)
  ("E" org-babel-expand-src-block :color blue)
  ("e" org-babel-examplify-region :color blue)
  ("r" org-babel-remove-result :color blue)
  ("h" org-babel-goto-src-block-head))

Help

(defhydra hydra-help ()
  "
^Help^
────────────────────────────
_f_: callable
_F_: function
_v_: variable
_c_: command
_k_: key
_m_: mode
_l_: view lossage
_M_: view messages
"
  ("M" view-echo-area-messages :color blue)
  ("f" helpful-callable :color blue)
  ("F" helpful-function :color blue)
  ("v" helpful-variable :color blue)
  ("c" helpful-command :color blue)
  ("k" helpful-key :color blue)
  ("m" describe-mode :color blue)
  ("l" view-lossage :color blue))

Packages

(defhydra hydra-packages ()
  "
^Packages^
─────────────────
_l_: list
_r_: refresh
_d_: delete
_e_: describe
_i_: install
_f_: install file
"
  ("l" package-list-packages)
  ("r" package-refresh-contents)
  ("d" package-delete)
  ("i" package-install)
  ("f" package-install-file)
  ("e" describe-package))

Search online

(defhydra hydra-search-online ()
  "
  ^
^Search Online^
────────────────────────────────────────────────────────
_g_: google         _y_: youtube           _t_: twitter
_t_: translate      _u_: urban dictionary  _m_: melpa
_w_: wikipedia      _h_: hoogle            _M_: google maps
_s_: stack overflow _H_: hackage           _i_: google images
_G_: github         _p_: pursuit           _d_: duckduckgo
  "
  ("g" engine/search-google)
  ("t" engine/search-google-translate)
  ("w" engine/search-wikipedia)
  ("S" engine/search-stack-overflow)
  ("G" engine/search-github)
  ("y" engine/search-youtube)
  ("u" engine/search-urban-dictionary)
  ("h" engine/search-hoogle)
  ("H" engine/search-hackage)
  ("p" engine/search-pursuit)
  ("r" engine/search-rust-docs)
  ("s" engine/search-substrate)
  ("m" engine/search-melpa)
  ("T" engine/search-twitter)
  ("M" engine/search-google-maps)
  ("i" engine/search-google-images)
  ("d" engine/search-duckduckgo))

Key bindings

(nmap
  :prefix my/leader+
  "f" 'hydra-flycheck/body
  "h" 'hydra-help/body
  "o o" 'hydra-org/base/body
  "o l" 'hydra-org/link/body
  "o t" 'hydra-org/table/body
  "o b" 'hydra-org/babel/body
  "r" 'hydra-rectangle/body
  "m" 'hydra-macro/body
  "p" 'hydra-packages/body
  "C-SPC" 'hydra-search-online/body
  "S" 'hydra-yasnippet/body
  "t" 'hydra-zoom/body
  "w" 'hydra-window/body))

Calendar

(use-package calfw-org)
(use-package calfw
 :demand t
 :config
 (require 'calfw-org)

 ;; Nicer Unicode characters
 (setq
   cfw:fchar-junction ?╋
   cfw:fchar-vertical-line ?┃
   cfw:fchar-horizontal-line ?━
   cfw:fchar-left-junction ?┣
   cfw:fchar-right-junction ?┫
   cfw:fchar-top-junction ?┯
   cfw:fchar-top-left-corner ?┏
   cfw:fchar-top-right-corner ?┓))

Reading

PDF

Emacs support library for PDF files. You should run the following command manually:

M-x pdf-tools-install RET

To check if everything is ok:

M-x pdf-info-check-epdfinfo RET
(use-package pdf-tools
 :mode ("\\.pdf\\'" . pdf-view-mode)
 :commands
 (pdf-tools-install)
 :config
 (pdf-tools-install)
 (setq-default pdf-view-display-size 'fit-width))

Djvu

(use-package djvu)

EPUB

Major mode for reading EPUB’s in Emacs.

(use-package nov
  :preface
  (defun my/nov-delayed-render-setup ()
    (run-with-idle-timer 0.2 nil 'nov-render-document))
  (defun my/nov-fringes-setup ()
    "Hide the fringes for `nov-mode'."
    (set-window-fringes (get-buffer-window) 0 0 nil))
  :mode
  ("\\.epub$" . nov-mode)
  :hook
  (nov-mode . my/nov-delayed-render-setup)
  (nov-mode . my/nov-fringes-setup))

Translation

This package allows to translate the strings using Google Translate service directly from Emacs.

(use-package google-translate
 :after (general)
 :demand t
 :init
 (setq google-translate-default-source-language "en")
 (setq google-translate-default-target-language "ru")
 :config
 (require 'google-translate-default-ui)
 (nmap
  :prefix "C-c"
  "t" 'google-translate-at-point
  "q" 'google-translate-query-translate))

Telega

GNU Emacs telegram client (unofficial).

(use-package telega)

Tools

Net utils

(use-package net-utils
 :config
 (nmap
   :prefix my/leader
   "N p" 'ping
   "N i" 'ifconfig
   "N w" 'iwconfig
   "N n" 'netstat
   "N a" 'arp
   "N r" 'route
   "N h" 'nslookup-host
   "N d" 'dig
   "N s" 'smbclient))

IX

(use-package ix
 :after general
 :config
 (nmap
   :prefix my/leader
   "G i i" 'ix
   "G i b" 'ix-browse
   "G i d" 'ix-delete))

Direnv

Provides =direnv= integration for Emacs.

(use-package direnv
 :demand t
 :custom
 (direnv-always-show-summary t)
 :config
 (direnv-mode))

carbon-now-sh

(use-package carbon-now-sh
  :config
  (vmap 'prog-mode
    "C-c c" 'carbon-now-sh))

Search

Engine mode

(use-package engine-mode
 :config
 (engine-mode t)
 (engine/set-keymap-prefix (kbd "C-SPC C-SPC"))
 (defengine amazon
   "http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=%s")
 (defengine duckduckgo
   "https://duckduckgo.com/?q=%s"
   :keybinding "d")
 (defengine github
   "https://github.com/search?q=%s&type=Code"
   :keybinding "G")
 (defengine google
   "http://www.google.com/search?ie=utf-8&oe=utf-8&q=%s"
   :keybinding "g")
 (defengine google-images
   "http://www.google.com/images?hl=en&source=hp&biw=1440&bih=795&gbv=2&aq=f&aqi=&aql=&oq=&q=%s"
   :keybinding "i")
 (defengine google-maps
   "http://maps.google.com/maps?q=%s"
   :docstring "Mappin' it up."
   :keybinding "M")
 (defengine melpa
   "https://melpa.org/#/?q=%s"
   :docstring "Searching on melpa"
    :keybinding "m")
 (defengine project-gutenberg
   "http://www.gutenberg.org/ebooks/search/?query=%s")
 (defengine rfcs
   "http://pretty-rfc.herokuapp.com/search?q=%s")
 (defengine stack-overflow
   "https://stackoverflow.com/search?q=%s"
   :keybinding "S"
   :docstring "Search Stack Overlow")
 (defengine substrate
   "https://paritytech.github.io/substrate/master/sc_service/index.html?search=%s"
   :keybinding "s"
   :docstring "Search Substrate")
 (defengine rust-docs
   "https://doc.rust-lang.org/nightly/core/index.html?search=%s"
   :keybinding "r"
   :docstring "Search Rust docs")
 (defengine google-translate
   "https://translate.google.com/#view=home&op=translate&sl=en&tl=ru&text=%s"
   :keybinding "t")
 (defengine twitter
   "https://twitter.com/search?q=%s"
   :keybinding "T")
 (defengine wikipedia
   "http://www.wikipedia.org/search-redirect.php?language=en&go=Go&search=%s"
   :keybinding "w"
   :docstring "Searchin' the wikis.")
 (defengine pursuit
   "https://pursuit.purescript.org/search?q=%s"
   :keybinding "p")
 (defengine hoogle
   "https://www.haskell.org/hoogle/?hoogle=%s"
   :keybinding "h")
 (defengine hackage
   "https://hackage.haskell.org/packages/search?terms=%s"
   :keybinding "H")
 (defengine hayoo
   "http://hayoo.fh-wedel.de/?query=%s")
 (defengine wiktionary
   "https://www.wikipedia.org/search-redirect.php?family=wiktionary&language=en&go=Go&search=%s")
 (defengine wolfram-alpha
   "http://www.wolframalpha.com/input/?i=%s")
 (defengine urban-dictionary
   "https://www.urbandictionary.com/define.php?term=%s"
   :keybinding "u")
 (defengine youtube
   "http://www.youtube.com/results?aq=f&oq=&search_query=%s"
   :keybinding "y"))

Counsel web

(use-package counsel-web
 :after (general counsel)
 :quelpa
 (counsel-web :fetcher github :repo "mnewt/counsel-web")
 :custom
 (counsel-web-search-action 'browse-url)
 (counsel-web-suggest-function 'counsel-web-suggest--google)
 (counsel-web-search-function 'counsel-web-search--google)
 :config
 (nmap
  :prefix my/leader
  "S" 'counsel-web-suggest))

Google this (disabled)

I use engine-mode instead.

(use-package google-this
 :diminish google-this-mode
 :config
 (google-this-mode 1)
 (nmap
   :prefix my/leader
   "G" google-this-mode-submap))

Stack exchange

(use-package sx
 :config
 (nmap
   :prefix my/leader
   "' q" 'sx-tab-all-questions
   "' i" 'sx-inbox
   "' o" 'sx-open-link
   "' u" 'sx-tab-unanswered-my-tags
   "' a" 'sx-ask
   "' s" 'sx-search))

Delight

(use-package delight
 :config
 (delight
  '((emacs-lisp-mode "elisp" :major)
    (ruby-mode "ruby" :major)
    (elixir-mode "ex" elixir)
    (alchemist-mode "al" alchemist)
    (alchemist-hex-mode "alhex" alchemist)
    (alchemist-test-mode "altest" alchemist)
    (rust-mode "rs" rust)
    (purescript-mode "purs" purescript)
    (javascript-mode "js" js)
    (eldoc-mode "eldoc" eldoc)
    (outline-minor-mode "outl" outline)
    ;; (hi-lock-mode "hi" hi-lock)
    (subword-mode "sw" subword))))

Google this

I use engine-mode instead.

(use-package google-this
 :diminish google-this-mode
 :config
 (google-this-mode 1)
 (nmap
   :prefix my/leader
   "G" google-this-mode-submap))

Stack exchange

(use-package sx
 :config
 (nmap
   :prefix my/leader
   "' q" 'sx-tab-all-questions
   "' i" 'sx-inbox
   "' o" 'sx-open-link
   "' u" 'sx-tab-unanswered-my-tags
   "' a" 'sx-ask
   "' s" 'sx-search))

Diminish

Hide minor modes to save space.

(use-package diminish
 :config
 (diminish 'abbrev-mode)
 (diminish 'auto-fill-function)
 (with-eval-after-load 'face-remap (diminish 'buffer-face-mode))
 (with-eval-after-load 'with-editor (diminish 'with-editor-mode))
 (eval-after-load "purescript-indentation" '(diminish 'purescript-indentation-mode))
 (eval-after-load "dired" '(diminish 'dired-omit-mode))
 (eval-after-load "hideshow" '(diminish 'hs-minor-mode))
 (eval-after-load "eldoc" '(diminish 'eldoc-mode))
 (eval-after-load "hi-lock" '(diminish 'hi-lock-mode)))

Finalize

Set the frequency of garbage collections to big number (100mb) like most of the popular starter kits like Spacemacs/Doom/Prelude, etc do:

(setq gc-cons-threshold 100000000) ;; 100mb

Increase the amount of data which Emacs reads from the process. Again the emacs default is too low 4k considering that the some of the language server responses are in 800k - 3M range.

(setq read-process-output-max (* 1024 1024)) ;; 1mb

About

My Emacs config


Languages

Language:Emacs Lisp 100.0%