1
0
mirror of https://github.com/Foltik/dotfiles synced 2024-11-28 05:27:06 -05:00
dotfiles/lain/.emacs.d/sandbox.org
2019-02-10 11:54:41 -05:00

24 KiB
Raw Blame History

Packaging

Package.el

Package.el is the built-in package manager in Emacs. This is where the fun begins.

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

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.

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

Custom Keywords

A few useful :keyword macros that extend the vanilla use-package functionality.

:company
  (defun use-package-company-normalize (name keyword args)
    "Normalize the KEYWORD with NAME :company with arguments ARGS into a list of pairs for the handler."
    (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
              "<symbol> or "
              "(<symbol or list of symbols> . <symbol or function>) 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))))

  ;;;###autoload
  (defun use-package-company-handler (name _keyword args rest state)
    "Generate a function and hook from each pair in NAME ARGS for the keyword with NAME :company, appending the forms to the use-package declaration specified by REST and STATE."
    (use-package-concat
     (use-package-process-keywords name rest state)
     (mapcan
      (lambda (def)
        (let ((modes (car def))
              (backend (cdr def))
              (fun (intern (concat "use-package-company-add-" (symbol-name (cdr def))))))
          (when backend
            (append
             `((defun ,fun ()
                 (setq-local company-backends
                             (append company-backends '(,backend)))))
             (mapcar
              (lambda (mode)
                `(add-hook
                  ',(derived-mode-hook-name mode)
                  #',fun))
              (if (use-package-non-nil-symbolp modes) (list modes) modes))))))
      (use-package-normalize-commands args))))

  (defalias 'use-package-normalize/:company 'use-package-company-normalize)
  (defalias 'use-package-handler/:company 'use-package-company-handler)
  (defalias 'use-package-autoloads/:company 'use-package-autoloads-mode)

  (setq use-package-keywords
    (let ((idx (+ 1 (cl-position :hook use-package-keywords))))
      (append
        (seq-subseq use-package-keywords 0 idx)
        (list :company)
        (nthcdr idx use-package-keywords))))

Keybinds

which-key

which-key displays a popup in the minibuffer that shows keybindings following incomplete commands.

  (use-package which-key
    :diminish
    :config
    (which-key-mode))

General

General is an excellent keybind manager that adds tons of useful macros. Also set up a leader key and prefixes, like \ in Vim.

  (use-package general
    :config
    (general-create-definer jf-leader-def
      :keymaps 'override
      :states '(normal insert emacs)
      :prefix "SPC"
      :non-normal-prefix "M-SPC")

    (defun jf-create-wk-prefix (desc)
      "Helper for creating which-key prefix descriptions.
  Bind to a key with general to make which-key show DESC
  as the prefix's description"
      `(:ignore t :wk ,desc))

    (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 ',(jf-create-wk-prefix name)))))
            definitions)))

    (jf-create-definers
     (("a" . "apps")
      ("b" . "buffers")
      ("f" . "files")
      ("g" . "git")
      ("h" . "help")
      ("m" . "major")
      ("o" . "org")
      ("p" . "projects")
      ("w" . "windows"))))

Vim Emulation

Evil

Evil is pretty much the entirety of Vim in Emacs.

  (use-package evil
    :diminish undo-tree-mode

    :init
    (setq evil-want-integration t)
    (setq evil-want-keybinding nil)

    (defun jf-window-split ()
      (interactive)
      (evil-window-split)
      (evil-window-down 1))
    (defun jf-window-vsplit ()
      (interactive)
      (evil-window-vsplit)
      (evil-window-right 1))

    :config
    (evil-mode t)

    (jf-windows-def
     "-" #'jf-window-split
     "=" #'jf-window-vsplit
     "b" #'balance-windows
     "H" #'evil-window-far-left
     "J" #'evil-window-bottom
     "K" #'evil-window-top
     "L" #'evil-window-far-right
     "h" #'evil-window-left
     "j" #'evil-window-right
     "k" #'evil-window-down
     "l" #'evil-window-right
     "o" #'other-frame))

Evil Collection

Evil Collection adds Evil bindings for all the parts of Emacs that Evil doesn't cover properly by default.

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

Evil Extensions

Avy

An enhanced version of f in Vim.

  (use-package avy
    :general
    (:keymaps 'override
      :states 'normal
      "C-f" 'avy-goto-char-in-line
      "C-F" 'avy-goto-char))

evil-surround

Use S and a delimiter to surround in visual mode.

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

Emacs

Defaults

Configuration Editing

Add functions for editing and reloading the Emacs config files.

  (defun jf-edit-config ()
    (interactive)
    (find-file jf-config-file))

  (defun jf-edit-init ()
    (interactive)
    (find-file jf-init-file))

  (defun jf-reload-config ()
    (interactive)
    (org-babel-load-file jf-config-file))

  (jf-files-def
    "e"  (jf-create-wk-prefix "emacs files")
    "ec" #'jf-edit-config
    "ei" #'jf-edit-init
    "er" #'jf-reload-config)

Add to Load Path

Create and add a folder to the load path for local lisp files. The folder itself and all descendants will be added to the path. These packages will take precedence over other libraries with the same name.

  (unless (file-exists-p jf-load-path)
    (make-directory jf-load-path))

  (let ((default-directory jf-load-path))
    (setq load-path
          (append
           (let ((load-path (copy-sequence load-path)))
             (append
              (copy-sequence (normal-top-level-add-to-load-path '(".")))
              (normal-top-level-add-subdirs-to-load-path)))
           load-path)))

File Not Found Functions

Offer to create parent folders when a file is opened Offer to create nonexistant parent directories.

  (defun jf-create-nonexistant-directories ()
    (let ((parent-directory (file-name-directory buffer-file-name)))
      (when (and (not (file-exists-p parent-directory))
                (y-or-n-p (format "Directory `%s' does not exist. Create it?" parent-directory)))
        (make-directory parent-directory t)))) ; last argument specifies to behave like `mkdir -p'

  (add-to-list 'find-file-not-found-functions #'jf-create-nonexistant-directories)

Customize Location

Make changes in M-x customize go somewhere other than being schlunked into init.el.

  (setq custom-file (concat user-emacs-directory "_customize.el"))
  (load custom-file t)

Disable Bell

Shut up, emacs.

  (setq ring-bell-function #'ignore)

Shorter Prompts

Make yes-or-no prompts ask for y-or-n instead. Saves loads of time™.

  (defalias 'yes-or-no-p #'y-or-n-p)

Move Backup Files

By default, emacs gunks up every folder with file~ backups and #file# lockfiles. Schlunk them all in /tmp instead.

  (setq backup-directory-alist
        `((".*" . ,temporary-file-directory)))
  (setq auto-save-file-name-transforms
        `((".*" ,temporary-file-directory t)))

Nicer Scrolling

Keep the cursor away from the edges when scrolling, rather than hitting the bottom and scrolling a metric boatload off the screen.

  (require 'smooth-scrolling)

Secure auth-source

GPG encrypt stored auth tokens from auth-source instead of storing them in plaintext.

  (setq auth-sources '("~/.emacs.d/authinfo.gpg"))

Use UTF-8

Pleeeease default to UTF-8, Emacs.

  (setq locale-coding-system 'utf-8)
  (set-terminal-coding-system 'utf-8)
  (set-keyboard-coding-system 'utf-8)
  (set-selection-coding-system 'utf-8)
  (prefer-coding-system 'utf-8)

Trash when Deleting

Don't permanently delete stuff unless asked.

  (setq delete-by-moving-to-trash t)

Open Compressed Files

…automatically.

  (setq auto-compression-mode t)

Save Minibuffer History

  (savehist-mode 1)
  (setq history-length 1000)

Double Spaces

Why sentences would need double spaces to end I do not know.

  (set-default 'sentence-end-double-space nil)

Eval Print Level

Print more stuff when running C-x C-e or (eval-last-sexp)

  (setq eval-expression-print-level 100)

UI

Font

Engage a nice coding font.

  (add-to-list 'default-frame-alist '(font . "Fira Code 12"))
  (set-face-attribute 'default t :font "Fira Code 12")

Menu Bar

Disable the useless cruft at the top of the screen.

  (menu-bar-mode -1)
  (tool-bar-mode -1)
  (scroll-bar-mode -1)

Modeline

Diminish

Adds support for :diminish in use-package declarations, which hides a mode from the modeline.

(use-package diminish)
Column Number

Show line and column numbers in the modeline.

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

Line Numbers

Use the default emacs relative line numbers, but switch to absolute lines when in insert mode.

  (use-package nlinum-relative
    :config
    (nlinum-relative-setup-evil)
    :hook (prog-mode . nlinum-relative-mode))

Show Matching Parens

Shows matching parenthesis

(require 'paren)
(setq show-paren-delay 0)
(show-paren-mode)

Themes

pywal

Fancy dynamic color scheme generation from desktop wallpapers. Requires additional setup on the machine itself.

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

spacemacs

This theme is pretty fancy and has lots of supported modes.

  (unless (package-installed-p 'spacemacs-theme)
    (package-install 'spacemacs-theme))

  (defun jf-theme-spacemacs ()
    (load-theme 'spacemacs-dark))

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.

(set-frame-parameter (selected-frame) 'alpha 85)
(add-to-list 'default-frame-alist '(alpha . 85))

Helpers

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

Communication

Web

Tools

Programming

Formatting

Indentation

Set some sane defaults

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

Define some useful helper functions

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

Smart Parentheses

smartparens handles parens for languages that aren't lispy, and paredit handles the rest. Keybinds in M-x sp-cheat-sheet.

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

Smart Parentheses Modes

Picks a suitable parenthesis editing mode for the current major mode when entering any prog-mode.

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

ws-butler

Unobtrusively cleans up whitespace before EOLs as you edit, stopping the noisy commits generated from blanket trimming entire files.

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

pretty-mode

Redisplay parts of the Emacs buffer as pretty symbols.

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

prettify-symbols-mode

Built into emacs since 24.1

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

Column 80 Highlight

Add a hotkey for highlighting column 80 and activate it in prog-mode

(use-package fill-column-indicator
    :init
    (setq fci-rule-use-dashes t)
    (setq fci-rule-column 80)
    :general)

Checkers

Flycheck

Flycheck does syntax highlighting in a few languages

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

Completion

Company

company auto-completes stuff in the buffer, company-quickhelp shows documentation popups when idling on a completion candidate.

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

Snippets

Yasnippet adds support for custom snippets

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

Debugging

Realgud

Realgud is a modular frontend for many debuggers

(use-package realgud
    :commands 
    (realgud:gdb 
     realgud:lldb 
     realgud:node-inspect 
     realgud:pdb 
     realgud:trepan3k))

RMSBolt

(use-package rmsbolt
    :commands rmsbolt-mode)

Git

magit

It's magic git! Keybinds here

  (use-package magit
      :general)

It's evil magic git!

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

forge

Magic GitHub facilities for git forges such as GitHub and GitLab!

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

Projects

Projectile provides project-level features like make shortcuts and file switching

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

Tools

Languages

Fish

Beter editing of scripts for the fish shell

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

Markdown

(use-package markdown-mode
    :mode "\\.md\\'")

Python

Jedi for autocompletion sources

(use-package company-jedi
    :company python-mode)

Javascript

js2-mode improves the default js mode. Keybindings in this file.

(use-package js2-mode
    :mode "\\.js\\'"
    :interpreter "node")

Web-dev

Web-mode should give everything you need for a web-dev major mode. Company integration is done with company-web

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

JSON

Just an enhanced json mode

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

YAML

Enhanced yaml mode

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

Arch PKGBUILD

For editing PKGBUILD files

(use-package pkgbuild-mode
    :mode ".*PKGBUILD\\'")

LaTeX

AUCTeX

AUCTeX is a major mode for editing tex, CDLaTeX adds some minor niceities to it. company-auctex for completion.

(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)))
cdlatex
Environment
(setq foltz-cdlatex-envs nil)
Commands
(setq foltz-cdlatex-commands nil)
Math Symbols
(setq foltz-cdlatex-symbols
  '((?I ("\\infty"))))
cdlatex

cdlatex adds better TeX-specific template expansions and other niceties.

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

Rust

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

C/C++

Irony

Irony handles enhanced C/C++ operations powered by clang company-irony for company integration

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