* Packaging ** Package.el [[http://wikemacs.org/wiki/Package.el][Package.el]] is the built-in package manager in Emacs. This is where the fun begins. #+BEGIN_SRC emacs-lisp (require 'package) (setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/") ("melpa" . "https://melpa.org/packages/") ("melpa-stable" . "https://stable.melpa.org/packages/") ("marmalade" . "https://marmalade-repo.org/packages/") ("org" . "https://orgmode.org/elpa/"))) (setq package-enable-at-startup nil) (package-initialize) #+END_SRC ** use-package [[https://github.com/jwiegley/use-package][use-package]] is a nifty macro that interfaces with =Package.el=, keeping package-specific configuration all in once place. It's pretty much the basis of this entire config. #+BEGIN_SRC emacs-lisp (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (eval-when-compile (require 'use-package)) (setq use-package-compute-statistics t) (setq use-package-always-ensure t) (setq use-package-always-pin "melpa") (setq use-package-verbose t) #+END_SRC *** Custom Keywords A few useful =:keyword= macros that extend the vanilla =use-package= functionality. **** Helpers Define some helpers for bootstrapping the custom keywords. #+BEGIN_SRC emacs-lisp (defun foltz-add-use-package-keyword (keyword deferring) "Add a KEYWORD, which may imply DEFERRING, to the use-package keyword list." (setq use-package-keywords (let ((idx (+ 1 (cl-position :hook use-package-keywords)))) (append (seq-subseq use-package-keywords 0 idx) (list keyword) (nthcdr idx use-package-keywords)))) (when deferring (setq use-package-deferring-keywords (append use-package-deferring-keywords (list keyword))))) #+END_SRC **** :company #+BEGIN_SRC emacs-lisp (defun use-package-normalize/:company (name keyword args) (use-package-as-one (symbol-name keyword) args (lambda (label arg) (unless (or (consp arg) (use-package-non-nil-symbolp arg)) (use-package-error (concat label " or " "( . ) or " "a list of these"))) (use-package-normalize-pairs (lambda (k) (or (use-package-non-nil-symbolp k) (and (consp k) (not (cdr (last k))) (seq-every-p 'use-package-non-nil-symbolp k)))) #'use-package-recognize-function name label arg)))) (defun use-package-handler/:company (name keyword args rest state) (use-package-concat (use-package-process-keywords name rest state) (mapcan (lambda (def) (let ((modes (car def)) (backend (cdr def)) (fun (intern (concat "jf-company-add-" (symbol-name (cdr def)))))) (when backend (append `((defun ,fun () (let ((backend ,(append (list backend) '(:with company-yasnippet)))) (unless (member backend company-backends) (add-to-list 'company-backends backend))))) (mapcar (lambda (mode) `(add-hook ',(intern (concat (symbol-name mode) use-package-hook-name-suffix)) #',fun)) (if (use-package-non-nil-symbolp modes) (list modes) modes)))))) (use-package-normalize-commands args)))) (defalias 'use-package-autoloads/:company 'use-package-autoloads-mode) (foltz-add-use-package-keyword :company nil) #+END_SRC * Keybinds ** which-key [[https://github.com/justbur/emacs-which-key][which-key]] displays a popup in the minibuffer that shows keybindings following incomplete commands. #+BEGIN_SRC emacs-lisp (use-package which-key :diminish :config (which-key-mode)) #+END_SRC ** General [[https://github.com/noctuid/general.el][General]] is an excellent keybind manager that adds *tons* of useful macros. #+BEGIN_SRC emacs-lisp (use-package general) #+END_SRC ** Leaders Create a leader key, =SPC=, like =\= in vim. Different button presses after the leader bring you to different options. #+BEGIN_SRC emacs-lisp (general-create-definer jf-leader-def :keymaps 'override :states '(normal insert emacs) :prefix "SPC" :non-normal-prefix "M-SPC") (defmacro jf-create-definers (definitions) "A wrapper for general-create-definer. For every pair in DEFINITIONS, creates a leader with name jf-NAME-def and keybind SPC KEY or M-SPC KEY in normal mode." `(progn ,@(mapcan (lambda (def) (let ((key (car def)) (name (cdr def))) `((general-create-definer ,(intern (concat "jf-" name "-def")) :keymaps 'override :states '(normal insert emacs) :prefix ,(concat "SPC " key) :non-normal-prefix ,(concat "M-SPC " key)) (jf-leader-def ,key '(:ignore t :wk ,name))))) definitions))) (jf-create-definers (("b" . "buffers") ("f" . "files") ("g" . "git") ("h" . "help") ("o" . "org") ("p" . "projects") ("w" . "windows"))) #+END_SRC * Vim Emulation ** Evil [[https://github.com/emacs-evil/evil][Evil]] is pretty much the entirety of Vim in Emacs. #+BEGIN_SRC emacs-lisp (use-package evil :diminish undo-tree-mode :init (setq evil-want-integration t) (setq evil-want-keybinding nil) (defun foltz-window-split () (interactive) (evil-window-split) (evil-window-down 1)) (defun foltz-window-vsplit () (interactive) (evil-window-vsplit) (evil-window-right 1)) :config (evil-mode t)) #+END_SRC ** Evil Collection [[https://github.com/emacs-evil/evil-collection][Evil Collection]] adds Evil bindings for all the parts of Emacs that Evil doesn't cover properly by default. #+BEGIN_SRC emacs-lisp (use-package evil-collection :after evil :config (evil-collection-init '(calendar cmake-mode company custom debug dired doc-view elisp-mode elisp-refs eshell eval-sexp-fu flycheck flymake grep help ibuffer image image-dired info ivy js2-mode log-view man neotree python racer realgud which-key))) #+END_SRC ** Evil Extensions *** evil-surround Use =S= and a delimiter to surround in visual mode. #+BEGIN_SRC emacs-lisp (use-package evil-surround :after evil :diminish :config (global-evil-surround-mode 1)) #+END_SRC * Emacs ** Defaults *** Customize Make changes in =M-x customize= go somewhere other than being schlunked into =init.el=. #+BEGIN_SRC emacs-lisp (setq custom-file (concat user-emacs-directory "_customize.el")) (load custom-file t) #+END_SRC *** Bell Shut up, emacs. #+BEGIN_SRC emacs-lisp (setq ring-bell-function #'ignore) #+END_SRC *** Prompts Make =yes-or-no= prompts ask for =y-or-n= instead. Saves loads of timeā„¢. #+BEGIN_SRC emacs-lisp (defalias 'yes-or-no-p #'y-or-n-p) #+END_SRC *** Backup Files By default, emacs gunks up every folder with =file~= backups and =#file#= lockfiles. Schlunk them all in =/tmp= instead. #+BEGIN_SRC emacs-lisp (setq backup-directory-alist `((".*" . ,temporary-file-directory))) (setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t))) #+END_SRC *** Scrolling #+BEGIN_SRC emacs-lisp (setq scroll-conservatively 100) ;; don't scroll a metric boatload when bottom is hit #+END_SRC *** auth-source GPG encrypt stored auth tokens from [[https://www.gnu.org/software/emacs/manual/html_mono/auth.html][auth-source]] instead of storing them in plaintext. #+BEGIN_SRC emacs-lisp (setq auth-sources '("~/.emacs.d/authinfo.gpg")) #+END_SRC ** UI *** Font Engage a nice coding font. #+BEGIN_SRC emacs-lisp (add-to-list 'default-frame-alist '(font . "Fira Code 12")) (set-face-attribute 'default t :font "Fira Code 12") #+END_SRC *** Menu Bar Disable the useless cruft at the top of the screen. #+BEGIN_SRC emacs-lisp (menu-bar-mode -1) (tool-bar-mode -1) (scroll-bar-mode -1) #+END_SRC *** Modeline **** Diminish Adds support for =:diminish= in use-package declarations, which hides a mode from the modeline. #+BEGIN_SRC emacs-lisp (use-package diminish) #+END_SRC **** Column Number Show the column number in the modeline. #+BEGIN_SRC emacs-lisp (setq column-number-mode t) #+END_SRC *** Line Numbers Use the default emacs relative line numbers, but switch to absolute lines when in insert mode. #+BEGIN_SRC emacs-lisp (use-package nlinum-relative :config (nlinum-relative-setup-evil) :hook (prog-mode . nlinum-relative-mode)) #+END_SRC *** Show Matching Parens Shows matching parenthesis #+BEGIN_SRC emacs-lisp (require 'paren) (setq show-paren-delay 0) (show-paren-mode) #+END_SRC ** Themes *** pywal Fancy dynamic color scheme generation from desktop wallpapers. Requires additional setup on the machine itself. #+BEGIN_SRC emacs-lisp (defvar jf-theme-pywal-path "~/.cache/wal/colors.el" "Path to the colorscheme generated by pywal.") (defun jf-theme-pywal () (load-file jf-theme-pywal-path)) (when (eq 'jf-theme 'jf-theme-pywal) (require 'filenotify) (file-notify-add-watch jf-theme-pywal-path '(change) #'jf-theme-pywal)) #+END_SRC *** spacemacs This theme is pretty fancy and has lots of supported modes. #+BEGIN_SRC emacs-lisp (unless (package-installed-p 'spacemacs-theme) (package-install 'spacemacs-theme)) (defun jf-theme-spacemacs () (load-theme 'spacemacs-dark)) #+END_SRC *** Transparency Sets the window's transparency, to better admire choice wallpapers. The first number in the alpha section applies when the window is active, the second when it's inactive. #+BEGIN_SRC emacs-lisp (set-frame-parameter (selected-frame) 'alpha 85) (add-to-list 'default-frame-alist '(alpha . 85)) #+END_SRC *** Helpers #+BEGIN_SRC emacs-lisp (defvar jf-theme #'jf-theme-pywal "Theme function to call.") (defun jf-apply-theme () "Apply the current theme as set by jf-theme." (funcall jf-theme)) (jf-apply-theme) #+END_SRC * Communication * Web * Tools * Programming ** Formatting *** Indentation Set some *sane* defaults #+BEGIN_SRC emacs-lisp (setq foltz-tab-width 4) (setq-default python-indent-offset foltz-tab-width) (setq-default evil-shift-width foltz-tab-width) (setq-default c-basic-offset foltz-tab-width) ; Disable annoying electric indent of previous lines (setq-default electric-indent-inhibit t) ; Eat the whole tab when I press backspace (setq backward-delete-char-untabify-method 'hungry) #+END_SRC Define some *useful* helper functions #+BEGIN_SRC emacs-lisp (defun foltz-indent-tabs () (interactive) (setq tab-width foltz-tab-width) (local-set-key (kbd "") 'tab'to-tab-stop) (setq indent-tabs-mode t)) (defun foltz-indent-spaces (num-spaces) (interactive) (setq tab-width num-spaces) (setq indent-tabs-mode nil)) (defun foltz-indent-2-spaces () (foltz-indent-spaces 2)) (defun foltz-indent-4-spaces () (foltz-indent-spaces 4)) (defun foltz-indent-8-spaces () (foltz-indent-spaces 8)) (foltz-indent-4-spaces) (setq whitespace-style '(face tabs tab-mark trailing)) (custom-set-faces '(whitespace-tab ((t (:foreground "#636363"))))) (setq whitespace-display-mappings '((tab-mark 9 [124 9] [92 9]))) (add-hook 'prog-mode-hook #'whitespace-mode) #+END_SRC *** Smart Parentheses smartparens handles parens for languages that aren't lispy, and paredit handles the rest. Keybinds in =M-x sp-cheat-sheet=. #+BEGIN_SRC emacs-lisp (use-package paredit :diminish :commands enable-paredit-mode) (use-package smartparens :diminish :commands smartparens-strict-mode :config (require 'smartparens-config)) (use-package evil-smartparens :hook (smartparens-enabled . evil-smartparens-mode)) #+END_SRC *** Smart Parentheses Modes Picks a suitable parenthesis editing mode for the current major mode when entering any prog-mode. #+BEGIN_SRC emacs-lisp (defun foltz-paren-mode () (if (member major-mode '(emacs-lisp-mode lisp-mode lisp-interaction-mode scheme-mode)) (enable-paredit-mode) (smartparens-strict-mode))) (add-hook 'prog-mode-hook #'foltz-paren-mode) #+END_SRC *** ws-butler Unobtrusively cleans up whitespace before EOLs as you edit, stopping the noisy commits generated from blanket trimming entire files. #+BEGIN_SRC emacs-lisp (use-package ws-butler :hook (prog-mode . ws-butler-mode)) #+END_SRC *** pretty-mode [[https://github.com/pretty-mode/pretty-mode][Redisplay parts of the Emacs buffer as pretty symbols.]] #+BEGIN_SRC emacs-lisp (use-package pretty-mode :hook (prog-mode . pretty-mode) :config (pretty-deactivate-groups '(:equality :sub-and-superscripts)) (pretty-activate-groups '(:greek :arithmetic-nary :ordering :ordering-double :ordering-triple :arrows :arrows-twoheaded :punctuation :logic :sets))) #+END_SRC *** prettify-symbols-mode Built into emacs since 24.1 #+BEGIN_SRC emacs-lisp (add-hook 'python-mode-hook 'prettify-symbols-mode) (add-hook 'python-mode-hook (lambda () (mapc (lambda (pair) (push pair prettify-symbols-alist)) '(;; Syntax ("in" . #x2208) ("not in" . #x2209) ("return" . #x27fc) ("yield" . #x27fb) ("for" . #x2200) ;; Base Types ("int" . #x2124) ("float" . #x211d) ("str" . #x1d54a) ("True" . #x1d54b) ("False" . #x1d53d))))) #+END_SRC *** Column 80 Highlight Add a hotkey for highlighting column 80 and activate it in =prog-mode= #+BEGIN_SRC emacs-lisp (use-package fill-column-indicator :init (setq fci-rule-use-dashes t) (setq fci-rule-column 80) :general) #+END_SRC ** Checkers *** Flycheck Flycheck does syntax highlighting in a few languages #+BEGIN_SRC emacs-lisp (use-package flycheck :hook (prog-mode . flycheck-mode)) #+END_SRC ** Completion *** Company company auto-completes stuff in the buffer, company-quickhelp shows documentation popups when idling on a completion candidate. #+BEGIN_SRC emacs-lisp (use-package company :defer t :hook ((prog-mode cdlatex-mode) . company-mode) :general (:keymaps 'company-active-map "C-SPC" 'company-abort) :custom (company-maximum-prefix-length 2) (company-idle-delay 0.2 "Decrease idle delay")) (use-package company-quickhelp :after company :hook (company-mode . company-quickhelp-mode)) #+END_SRC ** Snippets Yasnippet adds support for custom snippets #+BEGIN_SRC emacs-lisp (use-package yasnippet :commands yas-minor-mode :hook (prog-mode . yas-minor-mode) :custom (yas-snippet-dirs '("~/.emacs.d/snippets" "~/.emacs.d/elpa/yasnippet-snippets-0.6/snippets"))) ;;;(use-package yasnippet-snippets) #+END_SRC ** Debugging *** Realgud [[https://github.com/realgud/realgud][Realgud]] is a modular frontend for many debuggers #+BEGIN_SRC emacs-lisp (use-package realgud :commands (realgud:gdb realgud:lldb realgud:node-inspect realgud:pdb realgud:trepan3k)) #+END_SRC *** RMSBolt #+BEGIN_SRC emacs-lisp (use-package rmsbolt :commands rmsbolt-mode) #+END_SRC ** Git *** magit It's magic git! Keybinds [[https://github.com/emacs-evil/evil-magit][here]] #+BEGIN_SRC emacs-lisp (use-package magit :general) #+END_SRC It's *evil* magic git! #+BEGIN_SRC emacs-lisp (use-package evil-magit :after (evil magit)) #+END_SRC *** forge Magic GitHub facilities for git forges such as GitHub and GitLab! #+BEGIN_SRC emacs-lisp (use-package forge :after magit :init (setq foltz-forge-hosts '(("git.lcsr.rutgers.edu" "git.lcsr.rutgers.edu/api/v4" "git.lcsr.rutgers.edu" forge-gitlab-repository))) :config (setq forge-alist (append forge-alist foltz-forge-hosts))) #+END_SRC ** Projects Projectile provides project-level features like make shortcuts and file switching #+BEGIN_SRC emacs-lisp (use-package projectile :init (defun foltz-projectile-neotree () "Open NeoTree in the project root" (interactive) (let ((project-dir (projectile-project-root)) (file-name (buffer-file-name))) (neotree-toggle) (if project-dir (if (neo-global--window-exists-p) (progn (neotree-dir project-dir) (neotree-find file-name)))))) (defun foltz-projectile-discover-projects (directory) "Add projects in dir to projectile cache" (interactive (list (read-directory-name "Starting directory: "))) (let ((subdirs (directory-files directory t))) (mapcar (lambda (dir) (when (and (file-directory-p dir) (not (member (file-name-nondirectory dir) '(".." ".")))) (let ((default-directory dir) (projectile-cached-project-root dir)) (when (projectile-project-p) (projectile-add-known-project (projectile-project-root)))))) subdirs))) :config (projectile-mode 1) (foltz-projectile-discover-projects "~/Documents/dev") :general (:keymaps 'projectile-command-map "t" 'foltz-projectile-neotree) :custom (projectile-completion-system 'ivy) (projectile-project-search-path '("~/Documents/dev"))) #+END_SRC ** Tools ** Languages *** Fish Beter editing of scripts for the fish shell #+BEGIN_SRC emacs-lisp (use-package fish-mode :mode "\\.fish\\'") #+END_SRC *** Markdown #+BEGIN_SRC emacs-lisp (use-package markdown-mode :mode "\\.md\\'") #+END_SRC *** Python Jedi for autocompletion sources #+BEGIN_SRC emacs-lisp (use-package company-jedi :company python-mode) #+END_SRC *** Javascript [[https://github.com/mooz/js2-mode][js2-mode]] improves the default js mode. Keybindings in [[https://github.com/emacs-evil/evil-collection/blob/master/evil-collection-js2-mode.el][this file]]. #+BEGIN_SRC emacs-lisp (use-package js2-mode :mode "\\.js\\'" :interpreter "node") #+END_SRC *** Web-dev Web-mode should give everything you need for a web-dev major mode. Company integration is done with company-web #+BEGIN_SRC emacs-lisp (use-package web-mode :mode ("\\.html\\'" "\\.php\\'" "\\.blade\\.") :custom (web-mode-code-indent-offset 4) (web-mode-indent-style 4)) (use-package company-web :company web-mode) #+END_SRC *** JSON Just an enhanced json mode #+BEGIN_SRC emacs-lisp (use-package json-mode :mode "\\.json\\'") #+END_SRC *** YAML Enhanced yaml mode #+BEGIN_SRC emacs-lisp (use-package yaml-mode :mode "\\.yaml\\'") #+END_SRC *** Arch PKGBUILD For editing PKGBUILD files #+BEGIN_SRC emacs-lisp (use-package pkgbuild-mode :mode ".*PKGBUILD\\'") #+END_SRC *** LaTeX **** AUCTeX AUCTeX is a major mode for editing tex, CDLaTeX adds some minor niceities to it. company-auctex for completion. #+BEGIN_SRC emacs-lisp (use-package tex :defer t :ensure auctex :general :custom (TeX-auto-save t)) (use-package company-auctex :company LaTeX-mode) (use-package company-math :company ((TeX-mode . company-math-symbols-latex) (TeX-mode . company-math-symbols-unicode) (TeX-mode . company-latex-commands))) #+END_SRC **** cdlatex ***** Environment #+BEGIN_SRC emacs-lisp (setq foltz-cdlatex-envs nil) #+END_SRC ***** Commands #+BEGIN_SRC emacs-lisp (setq foltz-cdlatex-commands nil) #+END_SRC ***** Math Symbols #+BEGIN_SRC emacs-lisp (setq foltz-cdlatex-symbols '((?I ("\\infty")))) #+END_SRC ***** cdlatex cdlatex adds better TeX-specific template expansions and other niceties. #+BEGIN_SRC emacs-lisp (use-package cdlatex :hook (LaTeX-mode . cdlatex-mode) :custom (cdlatex-env-alist foltz-cdlatex-envs) (cdlatex-command-alist foltz-cdlatex-commands) (cdlatex-math-symbol-alist foltz-cdlatex-symbols)) #+END_SRC *** Rust #+BEGIN_SRC emacs-lisp (use-package rust-mode :mode "\\.rs\\'" :general) (use-package flycheck-rust :hook (rust-mode . flycheck-rust-setup)) (use-package racer :hook ((rust-mode . racer-mode) (rust-mode . eldoc-mode)) :custom (racer-cmd "~/.cargo/bin/racer") (racer-rust-src-path "~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src")) (use-package cargo :hook (rust-mode . cargo-minor-mode) :general) #+END_SRC *** C/C++ **** Irony Irony handles enhanced C/C++ operations powered by clang company-irony for company integration #+BEGIN_SRC emacs-lisp (use-package irony :after counsel :hook ((c++-mode . irony-mode) (c-mode . irony-mode) (irony-mode . irony-cdb-autosetup-compile-options))) (use-package company-irony :company irony-mode) (use-package company-irony-c-headers :company irony-mode) (use-package flycheck-irony :hook (irony-mode . flycheck-irony-setup)) #+END_SRC **** Hotkeys #+BEGIN_SRC emacs-lisp #+END_SRC