Skip to content

Latest commit

 

History

History
411 lines (398 loc) · 14.2 KB

config.org

File metadata and controls

411 lines (398 loc) · 14.2 KB

Yay-Evil distro by Ian Y.E. Pan

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.)

(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))

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.

Modernize selection behavior

Replace the active region just by typing text, just like modern editors.

(use-package delsel
  :ensure nil
  :config (delete-selection-mode +1))

Disable scroll-bar

(use-package scroll-bar
  :ensure nil
  :config (scroll-bar-mode -1))

Enable column numbers

(use-package simple
  :ensure nil
  :config (column-number-mode +1))

File-related tweaks

Don’t bother confirming killing processes and don’t let backup~ files scatter around.

(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))

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.

(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))

Eldoc: documentation in the mini-buffer

Slightly shorten eldoc display delay.

(use-package eldoc
  :ensure nil
  :diminish eldoc-mode
  :config
  (setq eldoc-idle-delay 0.4))

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.

;; 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))

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.

(use-package mwheel
  :ensure nil
  :config (setq mouse-wheel-scroll-amount '(2 ((shift) . 1))
                mouse-wheel-progressive-speed nil))

Show matching parentheses

Reduce the highlight delay to instantly.

(use-package paren
  :ensure nil
  :init (setq show-paren-delay 0)
  :config (show-paren-mode +1))

Setting up some frame defaults

Maximize the frame by default on start-up. Set the font to size 12.

(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))

Ediff tweaks

Enter ediff with side-by-side buffers to better compare the differences.

(use-package ediff
  :ensure nil
  :config
  (setq ediff-window-setup-function #'ediff-setup-windows-plain)
  (setq ediff-split-window-function #'split-window-horizontally))

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.

(use-package elec-pair
  :ensure nil
  :hook (prog-mode . electric-pair-mode))

Clean up whitespace on save

(use-package whitespace
  :ensure nil
  :hook (before-save . whitespace-cleanup))

Dired tweaks

Delete intermediate buffers when navigating through dired.

(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))))

Dump custom-set-variables to a garbage file and don’t load it

(use-package cus-edit
  :ensure nil
  :config
  (setq custom-file (concat user-emacs-directory "to-be-dumped.el")))

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

(add-to-list 'custom-theme-load-path (concat user-emacs-directory "themes/"))
(load-theme 'wilmersdorf t) ; an orginal theme created by me.

Dashboard welcome page

(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))

Syntax highlighting

Lightweight syntax highlighting improvement for numbers and escape sequences (e.g. \n, \t).

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

(use-package highlight-escape-sequences
  :hook (prog-mode . hes-mode))

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.

(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))

Evil-collection covers more parts of Emacs that the original Evil doesn’t support (e.g. Packages buffer, eshell, calendar etc.)

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

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.)

(use-package evil-commentary
  :after evil
  :diminish
  :config (evil-commentary-mode +1))

Git Integration

Tell magit to automatically put us in vi-insert-mode when committing a change.

(use-package magit
  :bind ("C-x g" . magit-status)
  :config (add-hook 'with-editor-mode-hook #'evil-insert-state))

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.

(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))

Programming language support and utilities

Company for auto-completion

Use C-n and C-p to navigate the tooltip.

(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))

Flycheck

A modern on-the-fly syntax checking extension – absolute essential

(use-package flycheck :config (global-flycheck-mode +1))

Org Mode

Some minimal org mode tweaks: org-bullets gives our headings (h1, h2, h3…) a more visually pleasing look.

(use-package org
  :hook ((org-mode . visual-line-mode)
         (org-mode . org-indent-mode)))

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

Useful major modes

Markdown mode and Web mode, the latter covers our usages of HTML/CSS/JS/JSX/TS/TSX/JSON.

(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]?\\'"))))

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.

(use-package diminish
  :demand t)

Which-key

Provides us with hints on available keystroke combinations.

(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))

Configure PATH on macOS

(use-package exec-path-from-shell
  :config (when (memq window-system '(mac ns x))
            (exec-path-from-shell-initialize)))