#+Title: Yay-Evil distro by Ian Y.E. Pan #+Author: Ian Y.E. Pan #+Date: 2019 Welcome! This Emacs "distro" is based on my personal Emacs configuration (on GNU Emacs 26.3). It's unopinionated and was created for general use in mind. The package settings are grouped in a logical manner, and I've documented as detailed as possible what each code snippet does in this file. * Settings without corresponding packages Clean up the UI and enhance some basic defaults defined in "C Source Code". The variable ~ian/indent-width~ controls the default indentation across various programming modes. The default is 4, you can change this variable to 2 or any other indentation width you prefer, and the change will be made across all programming language modes including C, C++, Java, Python etc. (Exception: JavaScript defaults to 2-space indent, you can still set it to any other indentation width you prefer in the ~web-mode~ section.) #+BEGIN_SRC emacs-lisp (use-package emacs :preface (defvar ian/indent-width 4) ; change this value to your preferred width :config (setq frame-title-format '("Yay-Evil") ; Yayyyyy Evil! ring-bell-function 'ignore ; minimize distraction frame-resize-pixelwise t default-directory "~/") (tool-bar-mode -1) (menu-bar-mode -1) ;; better scrolling experience (setq scroll-margin 0 scroll-conservatively 101 ; > 100 scroll-preserve-screen-position t auto-window-vscroll nil) ;; Always use spaces for indentation (setq-default indent-tabs-mode nil tab-width ian/indent-width) ;; Omit default startup screen (setq inhibit-startup-screen t)) ;; The Emacs default split doesn't seem too intuitive for most users. (use-package emacs :ensure nil :preface (defun ian/split-and-follow-horizontally () "Split window below." (interactive) (split-window-below) (other-window 1)) (defun ian/split-and-follow-vertically () "Split window right." (interactive) (split-window-right) (other-window 1)) :config (global-set-key (kbd "C-x 2") #'ian/split-and-follow-horizontally) (global-set-key (kbd "C-x 3") #'ian/split-and-follow-vertically)) #+END_SRC * Configuration for built-in packages Since we're using use-package as our package management system, we might as well try to organize under the same syntax as much as possible to keep the configuration consistent. The option ~use-package-always-ensure~ is turned on in ~init.el~, so we'll add ~:ensure nil~ when configuring the built-in packages. #+END_SRC ** Modernize selection behavior Replace the active region just by typing text, just like modern editors. #+BEGIN_SRC emacs-lisp (use-package delsel :ensure nil :config (delete-selection-mode +1)) #+END_SRC ** Disable scroll-bar #+BEGIN_SRC emacs-lisp (use-package scroll-bar :ensure nil :config (scroll-bar-mode -1)) #+END_SRC ** Enable column numbers #+BEGIN_SRC emacs-lisp (use-package simple :ensure nil :config (column-number-mode +1)) #+END_SRC ** File-related tweaks Don't bother confirming killing processes and don't let backup~ files scatter around. #+BEGIN_SRC emacs-lisp (use-package files :ensure nil :config (setq confirm-kill-processes nil create-lockfiles nil ; don't create .# files (crashes 'npm start') make-backup-files nil)) #+END_SRC ** Automatically refreshes the buffer for changes outside of Emacs Auto refreshes every 2 seconds. Don't forget to refresh the version control status as well. #+BEGIN_SRC emacs-lisp (use-package autorevert :ensure nil :config (global-auto-revert-mode +1) (setq auto-revert-interval 2 auto-revert-check-vc-info t global-auto-revert-non-file-buffers t auto-revert-verbose nil)) #+END_SRC ** Eldoc: documentation in the mini-buffer Slightly shorten eldoc display delay. #+BEGIN_SRC emacs-lisp (use-package eldoc :ensure nil :diminish eldoc-mode :config (setq eldoc-idle-delay 0.4)) #+END_SRC ** Indentation improvement For Java and C/C++, change the formatting style from GNU (the default) to the more standard K&R. Here we also set the indentation width of C, C++, Java, and Python to the preferred value defined in ~ian/indent-width~ (all languages default to 4, except JavaScript, which is 2, as controlled in ~web-mode~). Of course, you can change the value depending on the language as well. #+BEGIN_SRC emacs-lisp ;; C, C++, and Java (use-package cc-vars :ensure nil :config (setq-default c-basic-offset ian/indent-width) (setq c-default-style '((java-mode . "java") (awk-mode . "awk") (other . "k&r")))) ;; Python (both v2 and v3) (use-package python :ensure nil :config (setq python-indent-offset ian/indent-width)) #+END_SRC ** Mouse wheel (track-pad) scroll speed By default, the scrolling is way too fast to be precise and helpful, let's tune it down a little bit. #+BEGIN_SRC emacs-lisp (use-package mwheel :ensure nil :config (setq mouse-wheel-scroll-amount '(2 ((shift) . 1)) mouse-wheel-progressive-speed nil)) #+END_SRC ** Show matching parentheses Reduce the highlight delay to instantly. #+BEGIN_SRC emacs-lisp (use-package paren :ensure nil :init (setq show-paren-delay 0) :config (show-paren-mode +1)) #+END_SRC ** Setting up some frame defaults Maximize the frame by default on start-up. Set the font to size 12. #+BEGIN_SRC emacs-lisp (use-package frame :preface (defun ian/set-default-font () (interactive) (when (member "Consolas" (font-family-list)) (set-face-attribute 'default nil :family "Consolas")) (set-face-attribute 'default nil :height 120 :weight 'normal)) :ensure nil :config (setq initial-frame-alist '((fullscreen . maximized))) (ian/set-default-font)) #+END_SRC ** Ediff tweaks Enter ediff with side-by-side buffers to better compare the differences. #+BEGIN_SRC emacs-lisp (use-package ediff :ensure nil :config (setq ediff-window-setup-function #'ediff-setup-windows-plain) (setq ediff-split-window-function #'split-window-horizontally)) #+END_SRC ** Auto-pairing quotes and parentheses etc. Electric-pair-mode has improved quite a bit in recent Emacs versions. No longer need an extra package for this. It also takes care of the new-line-and-push-brace feature. #+BEGIN_SRC emacs-lisp (use-package elec-pair :ensure nil :hook (prog-mode . electric-pair-mode)) #+END_SRC ** Clean up whitespace on save #+BEGIN_SRC emacs-lisp (use-package whitespace :ensure nil :hook (before-save . whitespace-cleanup)) #+END_SRC ** Dired tweaks Delete intermediate buffers when navigating through dired. #+begin_src emacs-lisp (use-package dired :ensure nil :config (setq delete-by-moving-to-trash t) (eval-after-load "dired" #'(lambda () (put 'dired-find-alternate-file 'disabled nil) (define-key dired-mode-map (kbd "RET") #'dired-find-alternate-file)))) #+end_src ** Dump custom-set-variables to a garbage file and don't load it #+BEGIN_SRC emacs-lisp (use-package cus-edit :ensure nil :config (setq custom-file (concat user-emacs-directory "to-be-dumped.el"))) #+END_SRC * Third-party packages Many Emacsers love having tons of packages -- and that's absolutely fine! However, one of the goals of the Yay-Evil distro is to provide an essential-only foundation for users to build upon. Therefore, only the most important packages and/or lightweight improvements will be included here. For example, completion frameworks like Ivy or Helm are considered heavy by many, yet the built-in Ido serves almost the same purpose. The only arguably opinionated package is probably Evil, but you probably saw that coming from the distro name, didn't you ;) ? If you prefer the default keybindings, simply disable the section that controls the Evil behaviors. Normally, we need to add ~:ensure t~ to tell ~use-package~ to download packages when it's not available. But since we've added ~use-package-always-ensure~ in ~init.el~, we can omit it. ** GUI enhancements *** Load custom theme #+BEGIN_SRC emacs-lisp (add-to-list 'custom-theme-load-path (concat user-emacs-directory "themes/")) (load-theme 'wilmersdorf t) ; an orginal theme created by me. #+END_SRC *** Dashboard welcome page #+BEGIN_SRC emacs-lisp (use-package dashboard :config (dashboard-setup-startup-hook) (setq dashboard-startup-banner 'logo dashboard-banner-logo-title "Yay Evil!" dashboard-items nil dashboard-set-footer nil)) #+END_SRC *** Syntax highlighting Lightweight syntax highlighting improvement for numbers and escape sequences (e.g. ~\n, \t~). #+BEGIN_SRC emacs-lisp (use-package highlight-numbers :hook (prog-mode . highlight-numbers-mode)) (use-package highlight-escape-sequences :hook (prog-mode . hes-mode)) #+END_SRC ** Vi keybindings I personally find Vi(m) bindings to be the most efficient way of editing text (especially code). I also changed the default ~:q~ and ~:wq~ to be killing current buffer, instead of killing the frame or subsequently killing Emacs. #+BEGIN_SRC emacs-lisp (use-package evil :diminish undo-tree-mode :init (setq evil-want-C-u-scroll t evil-want-keybinding nil evil-shift-width ian/indent-width) :hook (after-init . evil-mode) :preface (defun ian/save-and-kill-this-buffer () (interactive) (save-buffer) (kill-this-buffer)) :config (with-eval-after-load 'evil-maps ; avoid conflict with company tooltip selection (define-key evil-insert-state-map (kbd "C-n") nil) (define-key evil-insert-state-map (kbd "C-p") nil)) (evil-ex-define-cmd "q" #'kill-this-buffer) (evil-ex-define-cmd "wq" #'ian/save-and-kill-this-buffer)) #+END_SRC Evil-collection covers more parts of Emacs that the original Evil doesn't support (e.g. Packages buffer, eshell, calendar etc.) #+BEGIN_SRC emacs-lisp (use-package evil-collection :after evil :config (setq evil-collection-company-use-tng nil) (evil-collection-init)) #+END_SRC Emulates tpope's vim commentary package (Use ~gcc~ to comment out a line, ~gc~ to comment out the target of a motion (for example, ~gcap~ to comment out a paragraph), ~gc~ in visual mode to comment out the selection etc.) #+BEGIN_SRC emacs-lisp (use-package evil-commentary :after evil :diminish :config (evil-commentary-mode +1)) #+END_SRC ** Git Integration Tell magit to automatically put us in vi-insert-mode when committing a change. #+BEGIN_SRC emacs-lisp (use-package magit :bind ("C-x g" . magit-status) :config (add-hook 'with-editor-mode-hook #'evil-insert-state)) #+END_SRC ** Searching/sorting enhancements & project management *** Ido, ido-vertical, ido-ubiquitous and fuzzy matching Selecting buffers/files with great efficiency. In my opinion, Ido is enough to replace Ivy/Counsel and Helm. We install ido-vertical to get a better view of the available options (use ~C-n~, ~C-p~ or arrow keys to navigate). Ido-ubiquitous (from the ~ido-completing-read+~ package) provides us ido-like completions in describing functions and variables etc. Fuzzy matching is a nice feature and we have flx-ido for that purpose. #+BEGIN_SRC emacs-lisp (use-package ido :config (ido-mode +1) (setq ido-everywhere t ido-enable-flex-matching t)) (use-package ido-vertical-mode :config (ido-vertical-mode +1) (setq ido-vertical-define-keys 'C-n-C-p-up-and-down)) (use-package ido-completing-read+ :config (ido-ubiquitous-mode +1)) (use-package flx-ido :config (flx-ido-mode +1)) #+END_SRC ** Programming language support and utilities *** Company for auto-completion Use ~C-n~ and ~C-p~ to navigate the tooltip. #+BEGIN_SRC emacs-lisp (use-package company :diminish company-mode :hook (prog-mode . company-mode) :config (setq company-minimum-prefix-length 1 company-idle-delay 0.1 company-selection-wrap-around t company-tooltip-align-annotations t company-frontends '(company-pseudo-tooltip-frontend ; show tooltip even for single candidate company-echo-metadata-frontend)) (define-key company-active-map (kbd "C-n") 'company-select-next) (define-key company-active-map (kbd "C-p") 'company-select-previous)) #+END_SRC *** Flycheck A modern on-the-fly syntax checking extension -- absolute essential #+BEGIN_SRC emacs-lisp (use-package flycheck :config (global-flycheck-mode +1)) #+END_SRC *** Org Mode Some minimal org mode tweaks: org-bullets gives our headings (h1, h2, h3...) a more visually pleasing look. #+BEGIN_SRC emacs-lisp (use-package org :hook ((org-mode . visual-line-mode) (org-mode . org-indent-mode))) (use-package org-bullets :hook (org-mode . org-bullets-mode)) #+END_SRC *** Useful major modes Markdown mode and Web mode, the latter covers our usages of HTML/CSS/JS/JSX/TS/TSX/JSON. #+BEGIN_SRC emacs-lisp (use-package markdown-mode :hook (markdown-mode . visual-line-mode)) (use-package web-mode :mode (("\\.html?\\'" . web-mode) ("\\.css\\'" . web-mode) ("\\.jsx?\\'" . web-mode) ("\\.tsx?\\'" . web-mode) ("\\.json\\'" . web-mode)) :config (setq web-mode-markup-indent-offset 2) ; HTML (setq web-mode-css-indent-offset 2) ; CSS (setq web-mode-code-indent-offset 2) ; JS/JSX/TS/TSX (setq web-mode-content-types-alist '(("jsx" . "\\.js[x]?\\'")))) #+END_SRC ** Miscellaneous *** Diminish minor modes The diminish package is used to hide unimportant minor modes in the modeline. It provides the ~:diminish~ keyword we've been using in other use-package declarations. #+BEGIN_SRC emacs-lisp (use-package diminish :demand t) #+END_SRC *** Which-key Provides us with hints on available keystroke combinations. #+BEGIN_SRC emacs-lisp (use-package which-key :diminish which-key-mode :config (which-key-mode +1) (setq which-key-idle-delay 0.4 which-key-idle-secondary-delay 0.4)) #+END_SRC *** Configure PATH on macOS #+BEGIN_SRC emacs-lisp (use-package exec-path-from-shell :config (when (memq window-system '(mac ns x)) (exec-path-from-shell-initialize))) #+END_SRC