+ (progn
+ (mapc #'disable-theme custom-enabled-themes)
+ (load-theme 'tangomod t)
+ (sml/apply-theme 'light)))
+
+(defun amin/dark ()
+ "Load dark theme(s)."
+ (interactive)
+ (progn
+ (mapc #'disable-theme custom-enabled-themes)
+ (load-theme 'tangomod-dark t)
+ (sml/apply-theme 'dark)))
+
+(amin--leader-keys
+ "t" '(:ignore t :wk "theme")
+ "t d" 'amin/dark
+ "t l" 'amin/light)
+#+end_src
+
+** [[https://github.com/bbatsov/crux][crux]]
+
+#+begin_src emacs-lisp
+(use-package crux
+ :defer 1
+ :general
+ (amin--leader-keys
+ "b K" 'crux-kill-other-buffers
+ "c d" 'crux-duplicate-current-line-or-region
+ "c D" 'crux-duplicate-and-comment-current-line-or-region
+ "f c" 'crux-copy-file-preserve-attributes
+ "f d" 'crux-delete-file-and-buffer
+ "f r" 'crux-rename-file-and-buffer)
+ :bind (("C-c d" . crux-duplicate-current-line-or-region)
+ ("C-c D" . crux-duplicate-and-comment-current-line-or-region)
+ ("C-S-j" . crux-top-join-line)
+ ("C-c j" . crux-top-join-line)))
+#+end_src
+
+** [[https://github.com/alezost/mwim.el][mwim]]
+
+#+begin_src emacs-lisp
+(use-package mwim
+ :general
+ (:states '(normal visual)
+ "0" 'mwim-beginning-of-code-or-line
+ "$" 'mwim-end-of-code-or-line)
+ :bind (("C-a" . mwim-beginning-of-code-or-line)
+ ("C-e" . mwim-end-of-code-or-line)
+ ("<home>" . mwim-beginning-of-line-or-code)
+ ("<end>" . mwim-end-of-line-or-code)))
+#+end_src
+
+** projectile
+
+#+begin_src emacs-lisp
+(use-package projectile
+ :defer 2
+ :bind-keymap ("C-c p" . projectile-command-map)
+ :config
+ (projectile-mode)
+
+ (defun my-projectile-invalidate-cache (&rest _args)
+ ;; ignore the args to `magit-checkout'
+ (projectile-invalidate-cache nil))
+
+ (eval-after-load 'magit-branch
+ '(progn
+ (advice-add 'magit-checkout
+ :after #'my-projectile-invalidate-cache)
+ (advice-add 'magit-branch-and-checkout
+ :after #'my-projectile-invalidate-cache))))
+#+end_src
+
+** [[https://github.com/Wilfred/helpful][helpful]]
+
+#+begin_src emacs-lisp
+(use-package helpful
+ :defer 1
+ :general
+ (amin--leader-keys
+ "h h" '(:ignore t :wk "helpful")
+ "h h c" 'helpful-command
+ "h h f" 'helpful-callable ; helpful-function
+ "h h v" 'helpful-variable
+ "h h k" 'helpful-key
+ "h h p" 'helpful-at-point))
+#+end_src
+
+** [[https://github.com/knu/shell-toggle.el][shell-toggle]]
+
+#+begin_src emacs-lisp
+(use-package shell-toggle
+ :after eshell
+ :general (amin--leader-keys "a s" 'amin/shell-toggle)
+ :bind ("C-c e" . amin/shell-toggle)
+ :config
+ (defun amin/shell-toggle (make-cd)
+ "Toggle between the shell buffer and whatever buffer you are editing.
+With a prefix argument MAKE-CD also insert a \"cd DIR\" command
+into the shell, where DIR is the directory of the current buffer.
+
+When called in the shell buffer returns you to the buffer you were editing
+before calling this the first time.
+
+Options: `shell-toggle-goto-eob'"
+ (interactive "P")
+ ;; Try to decide on one of three possibilities:
+ ;; If not in shell-buffer, switch to it.
+ ;; If in shell-buffer, return to state before going to the shell-buffer
+ (if (eq (current-buffer) shell-toggle-shell-buffer)
+ (shell-toggle-buffer-return-from-shell)
+ (progn
+ (shell-toggle-buffer-goto-shell make-cd)
+ (if shell-toggle-full-screen-window-only (delete-other-windows)))))
+
+ ;; override to split horizontally instead
+ (defun shell-toggle-buffer-switch-to-other-window ()
+ "Switch to other window.
+If the current window is the only window in the current frame,
+create a new window and switch to it.
+
+\(This is less intrusive to the current window configuration than
+`switch-buffer-other-window')"
+ (let ((this-window (selected-window)))
+ (other-window 1)
+ ;; If we did not switch window then we only have one window and need to
+ ;; create a new one.
+ (if (eq this-window (selected-window))
+ (progn
+ (split-window-horizontally)
+ (other-window 1)))))
+
+ :custom
+ (shell-toggle-launch-shell 'shell-toggle-eshell))
+#+end_src
+
+** [[https://github.com/EricCrosson/unkillable-scratch][unkillable-scratch]]
+
+Make =*scratch*= and =*Messages*= unkillable.
+
+#+begin_src emacs-lisp
+(use-package unkillable-scratch
+ :defer 3
+ :config
+ (unkillable-scratch 1)
+ :custom
+ (unkillable-buffers '("^\\*scratch\\*$" "^\\*Messages\\*$")))
+#+end_src
+
+** [[https://github.com/davep/boxquote.el][boxquote.el]]
+
+#+begin_example
+,----
+| make pretty boxed quotes like this
+`----
+#+end_example
+
+#+begin_src emacs-lisp
+(use-package boxquote
+ :defer 3
+ :bind
+ (:prefix-map amin--boxquote-prefix-map
+ :prefix "C-c q"
+ ("b" . boxquote-buffer)
+ ("B" . boxquote-insert-buffer)
+ ("d" . boxquote-defun)
+ ("F" . boxquote-insert-file)
+ ("hf" . boxquote-describe-function)
+ ("hk" . boxquote-describe-key)
+ ("hv" . boxquote-describe-variable)
+ ("hw" . boxquote-where-is)
+ ("k" . boxquote-kill)
+ ("p" . boxquote-paragraph)
+ ("q" . boxquote-boxquote)
+ ("r" . boxquote-region)
+ ("s" . boxquote-shell-command)
+ ("t" . boxquote-text)
+ ("T" . boxquote-title)
+ ("u" . boxquote-unbox)
+ ("U" . boxquote-unbox-region)
+ ("y" . boxquote-yank)
+ ("M-q" . boxquote-fill-paragraph)
+ ("M-w" . boxquote-kill-ring-save)))
+#+end_src
+
+Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
+
+** COMMENT [[https://github.com/DarthFennec/highlight-indent-guides][highlight-indent-guides]] :ARCHIVE:
+
+#+begin_src emacs-lisp
+(use-package highlight-indent-guides
+ :defer 3
+ :hook ((prog-mode . highlight-indent-guides-mode)
+ ;; (org-mode . highlight-indent-guides-mode)
+ )
+ :config
+ (setq highlight-indent-guides-character ?\|)
+ (setq highlight-indent-guides-auto-enabled nil)
+ (setq highlight-indent-guides-method 'character)
+ (setq highlight-indent-guides-responsive 'top)
+ (set-face-foreground 'highlight-indent-guides-character-face "gainsboro")
+ (set-face-foreground 'highlight-indent-guides-top-character-face "grey40")) ; grey13 is nice too
+#+end_src
+
+** pdf-tools
+
+#+begin_src emacs-lisp
+(use-package pdf-tools
+ :defer t
+ :magic ("%PDF" . pdf-view-mode)
+ :config
+ (setq pdf-view-resize-factor 1.05)
+ (pdf-tools-install)
+ :bind
+ (:map pdf-view-mode-map
+ ("C-s" . isearch-forward)
+ ("C-r" . isearch-backward)
+ ("j" . pdf-view-next-line-or-next-page)
+ ("k" . pdf-view-previous-line-or-previous-page)
+ ("h" . image-backward-hscroll)
+ ("l" . image-forward-hscroll)))
+#+end_src
+
+** anzu
+
+#+begin_src emacs-lisp
+(use-package anzu)
+#+end_src
+
+** typo.el
+
+#+begin_src emacs-lisp
+(use-package typo
+ :defer 2
+ :config
+ (typo-global-mode 1)
+ :hook (text-mode . typo-mode))
+#+end_src
+
+** slack
+
+Hopefully temporary.
+
+#+begin_src emacs-lisp
+(use-package slack
+ :commands (slack-start)
+ :init
+ (eval-when-compile ; silence the byte-compiler
+ (defvar url-http-data nil)
+ (defvar url-http-extra-headers nil)
+ (defvar url-http-method nil)
+ (defvar url-callback-function nil)
+ (defvar url-callback-arguments nil)
+ (defvar oauth--token-data nil))
+ (setq slack-buffer-emojify t
+ slack-prefer-current-team t)
+ :config
+ (slack-register-team
+ :name "uw-apv"
+ :default t
+ :client-id uw-apv-client-id
+ :client-secret uw-apv-client-secret
+ :token uw-apv-token
+ :subscribed-channels '(general)
+ :full-and-display-names t)
+ (slack-register-team
+ :name "watform"
+ :default nil
+ :client-id watform-client-id
+ :client-secret watform-client-secret
+ :token watform-token
+ :subscribed-channels '(general)
+ :full-and-display-names t)
+ (add-to-list 'swiper-font-lock-exclude 'slack-message-buffer-mode t)
+ (setq lui-time-stamp-format "[%Y-%m-%d %H:%M:%S]"
+ lui-time-stamp-only-when-changed-p t
+ lui-time-stamp-position 'right)
+ :bind
+ (("C-c s s" . slack-start)
+ ("C-c s u" . slack-select-unread-rooms)
+ ("C-c s b" . slack-select-rooms)
+ ("C-c s t" . slack-change-current-team)
+ ("C-c s c" . slack-ws-close)
+ :map slack-mode-map
+ ("M-p" . slack-buffer-goto-prev-message)
+ ("M-n" . slack-buffer-goto-next-message)
+ ("C-c e" . slack-message-edit)
+ ("C-c k" . slack-message-delete)
+ ("C-c C-k" . slack-channel-leave)
+ ("C-c r a" . slack-message-add-reaction)
+ ("C-c r r" . slack-message-remove-reaction)
+ ("C-c r s" . slack-message-show-reaction-users)
+ ("C-c p l" . slack-room-pins-list)
+ ("C-c p a" . slack-message-pins-add)
+ ("C-c p r" . slack-message-pins-remove)
+ ("@" . slack-message-embed-mention)
+ ("#" . slack-message-embed-channel)))
+
+(use-package alert
+ :commands (alert)
+ :init
+ (setq alert-default-style 'notifier))
+#+end_src
+
+** hl-todo
+
+#+begin_src emacs-lisp
+(use-package hl-todo
+ :defer 4
+ :config
+ (global-hl-todo-mode))
+#+end_src
+
+** shrink-path
+
+#+begin_src emacs-lisp
+(use-package shrink-path
+ :after eshell
+ :config
+ (setq eshell-prompt-regexp "\\(.*\n\\)*λ "
+ eshell-prompt-function #'+eshell/prompt)
+
+ (defun +eshell/prompt ()
+ (let ((base/dir (shrink-path-prompt default-directory)))
+ (concat (propertize (car base/dir)
+ 'face 'font-lock-comment-face)
+ (propertize (cdr base/dir)
+ 'face 'font-lock-constant-face)
+ (propertize (+eshell--current-git-branch)
+ 'face 'font-lock-function-name-face)
+ "\n"
+ (propertize "λ" 'face 'eshell-prompt-face)
+ ;; needed for the input text to not have prompt face
+ (propertize " " 'face 'default))))
+
+ (defun +eshell--current-git-branch ()
+ (let ((branch (car (loop for match in (split-string (shell-command-to-string "git branch") "\n")
+ when (string-match "^\*" match)
+ collect match))))
+ (if (not (eq branch nil))
+ (concat " " (substring branch 2))
+ ""))))
+#+end_src
+
+** magithub
+
+For when I /have to/ use GH.
+
+#+begin_src emacs-lisp
+(use-package magithub
+ :after magit
+ :config
+ (magithub-feature-autoinject t)
+ (setq magithub-clone-default-directory "~/src/git"))
+#+end_src