1
0
mirror of https://github.com/Foltik/dotfiles synced 2024-11-24 12:26:05 -05:00
dotfiles/lain/.emacs.d/sandbox.org

21 KiB

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.

Helpers

Define some helpers for bootstrapping the custom keywords.

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

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

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.

  (use-package general)

Leaders

Create a leader key, SPC, like \ in vim. Different button presses after the leader bring you to different options.

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

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

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

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

Customize

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)

Bell

Shut up, emacs.

  (setq ring-bell-function #'ignore)

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)

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

Scrolling

(setq scroll-conservatively 100) ;; don't scroll a metric boatload when bottom is hit

auth-source

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

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

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 the column number in the modeline.

(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