Skip to content

Latest commit

 

History

History
280 lines (213 loc) · 10.6 KB

config.org

File metadata and controls

280 lines (213 loc) · 10.6 KB

Emacs Configuration

Preface

This configuration borrows heavily from Emacs From Scratch. This file, the one you’re looking at, generates init.el which can be loaded by Emacs at startup. It took a bit to bootstrap it, but once it was working cleanly, then it could be used to edit itself.

;; NOTE: init.el is now generated from config.org.  Please edit that file
;;       and init.el will be generated automatically when saving!

Startup Performance

;; The default is 800 kilobytes.  Measured in bytes.
(setq gc-cons-threshold (* 50 1000 1000))

(defun efs/display-startup-time ()
  (message "Emacs loaded in %s with %d garbage collections."
           (format "%.2f seconds"
                   (float-time
                     (time-subtract after-init-time before-init-time)))
           gcs-done))

(add-hook 'emacs-startup-hook #'efs/display-startup-time)

Table of Contents

Package System Setup

Emacs has a built in package manager but it doesn’t make it easy to automatically install packages on a new system the first time you pull down your configuration. use-package is a really helpful package used in this configuration to make it a lot easier to automate the installation and configuration of everything else we use.

;; Initialize package sources
(require 'package)

(setq package-archives '(("melpa-stable" . "https://melpa.org/packages/")))

;; Set directory where ELisp Packages are to be installed. Normally this
;; defaults to <user-emacs-directory>/elpa/, but this pollutes the
;; configuration(s). Plus, it opens up the possibility for different
;; configurations to share the same packages.
(setq package-user-dir "~/elpa")
;; For 'package' to work properly, it needs to be able to find the GPG keys as
;; well. The default value is <user-emacs-directory>/elpa/gnupg.
(setq package-gnupghome-dir "~/elpa/gnupg")

(package-initialize)

;; bootstrap use-package
(setq package-enable-at-startup nil)
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

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

;; Silently add ':ensure t' to all instances of use-package macro. use-package
;; will attempt to download any package that isn't already present.
(setq use-package-always-ensure t)

General Setup

Keep Folders Clean

We use the no-littering package to keep folders where we edit files and the Emacs configuration folder clean! It knows about a wide variety of variables for built in Emacs features as well as those from community packages so it can be much easier than finding and setting these variables yourself.

tldr: It puts everything into a var/ or etc/ sub-directory.

;; NOTE: If you want to move everything out of the ~/.emacs.d folder
;; reliably, set `user-emacs-directory` before loading no-littering!
;(setq user-emacs-directory "~/.cache/emacs")

(use-package no-littering)

House-Keeping

In general, I try to avoid Emacs’ Easy Customization Interface. Rather, I put any customizations here, in my config file. Set the custom-file path to null and the problem goes away.

;; Don't load or store any customizations
(setq custom-file null-device)

Automatic Package Updates

The auto-package-update package helps us keep our Emacs packages up to date! It will prompt you after a certain number of days either at startup or at a specific time of day to remind you to update your packages.

You can also use M-x auto-package-update-now to update right now!

(use-package auto-package-update
  :custom
  (auto-package-update-interval 7)
  (auto-package-update-prompt-before-update t)
  (auto-package-update-hide-results t)
  :config
  (auto-package-update-maybe)
  (auto-package-update-at-time "09:00"))

User Interface

Basic UI Configuration

This section configures basic UI settings that remove unneeded elements to make Emacs look a lot more minimal and modern. If you’re just getting started in Emacs, the menu bar might be helpful so you can remove the (menu-bar-mode -1) line if you’d like to still see that.

(setq inhibit-startup-screen t)   ; Go straight to *scratch* if no file is given
(setq visible-bell t)             ; Set up the visible bell instead of audible 'ding'
(menu-bar-mode -1)                ; Disable the menu bar
(column-number-mode)              ; Show column position of the cursor as well as the row like this: (R, C)
(show-paren-mode t)               ; Always highlight opposite parenthesis
(defalias 'yes-or-no-p 'y-or-n-p) ; Always Use `y-or-n-p', Never `yes-or-no-p'

;; Turn on line numbers for all modes...
(global-display-line-numbers-mode t)
;; ... except these modes.
(dolist (mode '(org-mode-hook
                term-mode-hook
                shell-mode-hook
                ;; treemacs-mode-hook
                eshell-mode-hook))
  (add-hook mode (lambda () (display-line-numbers-mode 0))))

This stuff seems relevant only to GUI Emacs

;; (tool-bar-mode -1)          ; Disable the toolbar
;; (tooltip-mode -1)           ; Disable tooltips
;; (scroll-bar-mode -1)        ; Disable visible scrollbar
;; (set-fringe-mode 10)        ; Give some breathing room

;; ;; Set frame transparency
;; (set-frame-parameter (selected-frame) 'alpha efs/frame-transparency)
;; (add-to-list 'default-frame-alist `(alpha . ,efs/frame-transparency))
;; ;; Always begin in fullscreen
;; (set-frame-parameter (selected-frame) 'fullscreen 'maximized)
;; (add-to-list 'default-frame-alist '(fullscreen . maximized))

Keybinding Configuration

Evil - extensible vi layer for Emacs

This configuration uses evil-mode for a Vi-like modal editing experience. It emulates the main features of Vim, and provides facilities for writing custom extensions.

(use-package evil
  :ensure t
  :init
  ;; The following solves the issue where TAB doesn't map to org-cycle in emacs
  ;; -nw. It is necessary for this to occur *before* (require 'evil). See:
  ;; https://stackoverflow.com/questions/22878668/emacs-org-mode-evil-mode-tab-key-not-working
  (setq evil-want-C-i-jump nil)
  :config
  (evil-mode 1)
  ;; 'Emacs way' to quite Insert mode
  (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)

  ;; Use visual line motions even outside of visual-line-mode buffers
  (evil-global-set-key 'motion "j" 'evil-next-visual-line)
  (evil-global-set-key 'motion "k" 'evil-previous-visual-line))

evil-surround

https://github.com/emacs-evil/evil-surround

(use-package evil-surround
  :after evil
  :config
  (global-evil-surround-mode 1))

evil-nerd-commenter

https://github.com/redguardtoo/evil-nerd-commenter

(use-package evil-nerd-commenter
  :after evil
  :config
  (evilnc-default-hotkeys nil t) ; default keybindings in Evil only, not Emacs
  )

evil-matchit

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

https://github.com/redguardtoo/evil-matchit

(use-package evil-matchit
  :after evil
  :config
  (global-evil-matchit-mode 1))

UI Configuration

Color Theme

I picked a theme that was better than the default for terminal usage.

(load-theme 'tango-dark)

Which Key

which-key is a useful UI panel that appears when you start pressing any key binding in Emacs to offer you all possible completions for the prefix. For example, if you press C-c (hold control and press the letter c), a panel will appear at the bottom of the frame displaying all of the bindings under that prefix and which command they run. This is very useful for learning the possible key bindings in the mode of your current buffer.

(use-package which-key
  :defer 5 ; defer [N] causes package to be loaded -- if not already -- after N seconds of idle time.
  :diminish which-key-mode ; reduce clutter on the mode-line
  :config
  (which-key-mode) ; enable minor mode after loading
  )

Assistants - Control the outside from within

Magit

(use-package magit)

RipGrep

(use-package rg)

Development

Languages

IDE

Org Mode

toc-org (Table of Contents for Org-mode)

toc-org helps you to have an up-to-date table of contents in org files without exporting (useful primarily for readme files on GitHub).

(use-package toc-org
  :ensure t
  :commands toc-org-enable
  :init (add-hook 'org-mode-hook 'toc-org-enable))

Auto-tangle Configuration Files

This snippet adds a hook to org-mode buffers so that efs/org-babel-tangle-config gets executed each time such a buffer gets saved. This function checks to see if the file being saved is the Emacs.org file you’re looking at right now, and if so, automatically exports the configuration here to the associated output files. https://youtu.be/kkqVTDbfYp4?t=1371

;; Automatically tangle our Emacs.org config file when we save it
(defun efs/org-babel-tangle-config ()
  (when (string-equal (file-name-directory (buffer-file-name))
                      (expand-file-name user-emacs-directory))
    ;; Dynamic scoping to the rescue
    (let ((org-confirm-babel-evaluate nil))
      (org-babel-tangle))))

(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'efs/org-babel-tangle-config)))