Skip to content

Latest commit

 

History

History
500 lines (462 loc) · 18.5 KB

emacs.org

File metadata and controls

500 lines (462 loc) · 18.5 KB

Emacs configuration

Speed up initialization

Raising garbage collection limit, seting file-name-handler-alist to nil (because regular expressions are expensive), and avoiding resizing the frame based on the font size.

Then we set a hook to set the gc and file-name-handler-alist back to their original values after init

;; -*- lexical-binding: t -*-
(setq gc-cons-threshold most-positive-fixnum
      frame-inhibit-implied-resize t)
(push '(menu-bar-lines . 0) default-frame-alist)
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)
(advice-add #'x-apply-session-resources :override #'ignore)

Set up font

(defvar bb-font-family "Iosevka SS01")
(defvar bb-font-size 130)
(set-face-attribute 'default nil
  :family bb-font-family
  :height bb-font-size
  :width 'normal
  :weight 'normal)

(set-face-attribute 'line-number-current-line nil
  :family bb-font-family
  :height bb-font-size
  :width 'expanded
  :weight 'normal
  :inverse-video nil)

Set up normal init

(defvar default-file-name-handler-alist file-name-handler-alist)
(setq gc-cons-threshold most-positive-fixnum
      gc-cons-percentage 0.6
      file-name-handler-alist nil
      frame-inhibit-implied-resize t)
(add-hook 'after-init-hook #'(lambda () (setq gc-cons-threshold 16777216
                                         gc-cons-percentage 0.1
                                         file-name-handler-alist default-file-name-handler-alist)))

Store all backups and autosaves in the temp dir

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

Move our custom file to a location consistent with our other files (and source it)

(setq custom-file "~/.config/emacs/custom.el")
(load custom-file 'noerror)

Load the other files in our set up

(load "~/.config/emacs/init_core.el")
(load "~/.config/emacs/init_editing.el")
(load "~/.config/emacs/init_ui.el")
(load "~/.config/emacs/init_programming.el")

Enable some nice programming features in in prog-mode

(add-hook 'prog-mode-hook (function(lambda ()
  (prettify-symbols-mode 1)
  (show-paren-mode 1)
  (global-hl-line-mode 1)
  (display-line-numbers-mode)
  (add-hook 'before-save-hook 'delete-trailing-whitespace nil t)))
)

Set some variables (explained inline)

(setq initial-scratch-message ""                     ; disable the scratch message
      inhibit-startup-message t                      ; disable the startup screen
      scroll-conservatively 101                      ; move window one line at a time when point approaches edge
      scroll-margin 5                                ; start scrolling 5 lines from edge
      visible-bell t                                 ; Audible bell is cancer, but visible bell works okay
      ad-redefinition-action 'accept                 ; Tell emacs we're okay with functions being given advice
      vc-follow-symlinks t                           ; Follow symlinks to vcs controlled files
      select-enable-clipboard t                      ; copy actions copy to clipboard
      select-enable-primary t                        ; copy actions also copy to primary
      mouse-drag-copy-region t                       ; highlighting a section causes it to get copied (linux default behavior)
      prettify-symbols-unprettify-at-point t         ; unprettify symbols when the point hits them so we can edit them
)
(setq-default fill-column 80                         ; in fill-mode, what column do we wrap at?
              truncate-lines t                       ; disable line wrapping
              indent-tabs-mode nil                   ; use spaces over tabs everywhere
              tab-width 2                            ; but when encountering a tab, how large is it?
              tab-stop-list (number-sequence 3 120 2); and what are the tabstop points when shifting?
)
(global-unset-key (kbd "C-x C-c"))                   ; Stop killing windows by fatfingering this

Don’t make me type ‘yes’ or ‘no’, even if it’s important

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

Auto-require some basic packages outside of use-package/straight.el

(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 5))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
  (url-retrieve-synchronously
   "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
   'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))

(straight-use-package 'use-package)
(setq straight-use-package-by-default t)

esup

for debugging startup times :)

(use-package esup)

Make sure that we have our exec-path correct

(use-package exec-path-from-shell
  :if (memq window-system '(mac ns))
  :init (setq exec-path-from-shell-check-startup-files nil
              exec-path-from-shell-shell-name "/opt/local/bin/zsh")
  :config (exec-path-from-shell-initialize))

Theme!

(use-package doom-themes
  :config
    (load-theme 'doom-nord t)
    (doom-themes-visual-bell-config)
    (doom-themes-org-config))

(use-package doom-modeline
  :init (setq doom-modeline-env-version nil)
  :config (doom-modeline-mode))

Undo Tree

(use-package undo-tree :config (global-undo-tree-mode))

Set up evil and plugins

Instantiate a default leader key

This key is just left of space on my Preonic. Since I don’t use that keyboard everywhere, I use my desktop’s hostname to determine if I should set prefix differently

(defvar bb-default-leader-key "<SPC>")
(if (string= (system-name) "tia-bxb-d01.ctisl.gtri.org") (setq bb-default-leader-key "<XF86TouchpadOff>"))

And now Evil itself

Set up evil, but defer JUUUUUST a bit, since it’s pretty slow

(use-package evil-leader
    :config
    (evil-leader/set-leader bb-default-leader-key)
    (global-evil-leader-mode))

(use-package evil
    :demand t
    :after (evil-leader undo-tree)
    :defer 0.1
    :custom (evil-undo-system 'undo-tree)
    :config
    (evil-mode 1))

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

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

Ivy + Swiper + Counsel (for filtering and search)

Ivy replaces completing-read functions. Counsel extends existing functions to use ivy (outside of completing-read)

(use-package ivy :config (ivy-mode))
(use-package counsel :config (counsel-mode))

Set up Company as completion framework

(use-package company
  :delight company-mode
  :config
    (setq company-tooltip-limit 20
          company-tooltip-align-annotations t)
    (global-company-mode 1)
)

Ripgrep for searching

(use-package ripgrep)

Make folding work okay

Still haven’t found a great folding library for emacs. Origami.el will have to do for now

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

projectile and perspective: So that we can jump around easily

(use-package perspective
  :config
    (persp-mode))

(use-package persp-projectile
    :straight (persp-projectile
               :host github
               :repo "bbatsov/persp-projectile")
    :commands (projectile-persp-switch-project)
    :init (evil-leader/set-key "p" 'projectile-persp-switch-project))

(use-package projectile
  :delight projectile-mode
  :commands (projectile-switch-project projectile-find-file projectile-mode)
  :after evil-leader
  :init
    (setq projectile-completion-system 'ivy
          projectile-require-project-root nil
          projectile-git-command "fd . --print0 --color never"
          projectile-indexing-method 'alien
          projectile-project-search-path '("~/code"))
  :config
    (projectile-mode))

(use-package counsel-projectile
  :after projectile
  :config
    (setq counsel-projectile-rg-initial-input '(ivy-thing-at-point))
    (evil-define-key 'normal 'global (kbd "<leader>b") 'counsel-projectile)
    (evil-leader/set-key
        "b" 'counsel-projectile
        evil-leader/leader 'counsel-projectile
        "/" 'counsel-projectile-rg))

Set up integration with Git

(use-package git-gutter
  :hook (prog-mode . git-gutter-mode)
  :init (setq git-gutter:update-interval 2))
(use-package magit
  :commands (magit-status)
  :hook (after-save . magit-after-save-refresh-status)
  :defer 5
  :init
    (evil-leader/set-key "g" 'magit)
    (setq magit-popup-show-common-commands nil
          magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1))
(use-package evil-magit
  :after magit
  :init
    (setq evil-magit-want-horizontal-movement nil))

Setup Direnv so we can properly change environements :)

(use-package direnv
  :config (direnv-mode))

Discover and respect editorconfig settings

(use-package editorconfig
  :config (editorconfig-mode 1))

Highlight colors in HTML/CSS/files

(use-package rainbow-mode)

Highlight nested brackets differently in bracketized languages

(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))

Highlight TODO notes using fic-mode

(use-package fic-mode
  :commands (fic-mode)
  :init (setq fic-highlighted-words '("FIXME" "TODO" "BUG" "NOTE"))
  :hook (prog-mode . fic-mode))

lsp, for some later languages

(use-package flycheck
  :config
    (setq flycheck-highlighting-mode nil
          flycheck-indication-mode 'left-margin
    )
    (global-flycheck-mode)
    (add-to-list 'display-buffer-alist
      `(,(rx bos "*Flycheck errors*" eos)
         (display-buffer-reuse-window display-buffer-in-side-window)
         (side . bottom)
         (resulable-frames . visible)
         (window-height . 15)))
   :hook (flycheck-mode . flycheck-set-indication-mode))

(use-package treemacs)
(use-package treemacs-projectile)
(use-package treemacs-evil)
(use-package which-key
  :config (which-key-mode 1))
(use-package lsp-mode
  :config
  (defun bb/lsp-setup()
    (setq lsp-idle-delay 0.5
          lsp-enable-symbol-highlighting nil
          lsp-enable-snippet nil  ;; Not supported by company capf, which is the recommended company backend
          lsp-pyls-configuration-sources ["flake8"]
          ;; enable things we want!
          lsp-pyls-plugins-flake8-enabled t
          lsp-pyls-plugins-pydocstyle-enabled t
          ;; and now disable stuff we don't want
          lsp-pyls-plugins-pycodestyle-enabled nil
          lsp-pyls-plugins-mccabe-enabled nil
          lsp-pyls-plugins-pyflakes-enabled nil
          lsp-pyls-plugins-autopep8-enabled nil

     )

    (lsp-register-custom-settings
     '(("pyls.plugins.pyls_black.enabled" t t)
       ("pyls.plugins.pyls_isort.enabled" t t))))
  :hook
  ((python-mode . lsp)
   (reason-mode . lsp)
   (lsp-mode . lsp-enable-which-key-integration)
   (lsp-before-initialize . bb/lsp-setup)))

(use-package lsp-ui
  :config
  (defun bb/lsp-ui-setup ()
    (lsp-headerline-breadcrumb-mode 1)
    (setq lsp-ui-sideline-enable t
          lsp-ui-sideline-delay 0.5
          lsp-ui-sideline-ignore-duplicate t
          lsp-ui-doc-delay 1
          lsp-eldoc-enable-hover t
          lsp-signature-doc-lines 2
          lsp-signature-auto-activate t
          lsp-ui-doc-position 'top
          lsp-ui-doc-alignment 'window))
  :commands lsp-ui-mode
  :hook ((lsp-before-initialize . bb/lsp-ui-setup))
   :bind (:map evil-normal-state-map
               ("gd" . lsp-ui-peek-find-definitions)
               ("gr" . lsp-ui-peek-find-references))
               ("C-e" . flycheck-next-error))
(use-package lsp-treemacs
  :config
    (defun bb/lsp-treemacs-setup ()
      (setq lsp-treemacs-symbols-position-params `((side . right) (slot . 2) (window-width . 35))))
  :hook ((lsp-ui-mode . lsp-treemacs-sync-mode)
         (lsp-treemacs-sync-mode . bb/lsp-treemacs-setup)))

Javascript

(use-package web-mode
  :mode (".jsx?$" ".html$" ".css$")
  :init
    (setq web-mode-markup-indent-offset 2
          web-mode-code-indent-offset 2
          web-mode-css-indent-offset 2
          web-mode-attr-indent-offset 2
          web-mode-enable-css-colorization t
          web-mode-enable-current-column-highlight t
          web-mode-enable-auto-quoting nil
    ))

Lua

(use-package lua-mode
  :mode (".lua$"))

Reason

I also suggest (and use, but don’t automate the install of) ocaml-lsp. It works well (much better, at the time of writing, than Reason-LS).

Still TODO: disable lsp-enable-symbol-highlighting For reason buffers. Ocaml-lsp highlights the entire statement rather than a single identifier, as in pyls. This gets old really fast.

(use-package reason-mode
  :mode ("\\.rei?'")
  :init (setq refmt-command 'opam)
)

YAML

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

Markdown

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

Org mode!

Rather important: We use this to tangle this very file (though 24+ ships a good enough version to do so)

(setq agenda-path "/ssh:bryan@bryan-bennett.com:~bryan/synced/agenda.org")
(use-package org
  :defer t
  :mode ("\\.org$" . org-mode)
  :bind (("C-c l" . org-store-link)
          ("C-c c" . org-capture)
          ("C-c a" . org-agenda)
          ("C-c o" . (lambda () (interactive) (find-file agenda-path)))
          :map org-mode-map
            ;; ("C-h" . org-delete-backward-char)
            ("C-c !" . org-time-stamp-inactive))
  :config
    (setq org-agenda-files '(agenda-path)
          org-capture-templates '(
            ("t"
             "Todo - Personal"
             entry
             (file+olp agenda-path "Agenda" "Personal"))
            ("T"
             "Todo - Work"
             entry
             (file+olp agenda-path "Agenda" "Work"))
            ("g"
             "Grocery Item"
             checkitem
             (file+olp agenda-path "Purchases" "Groceries"))
            ("p"
             "Purchase - Personal"
             checkitem
             (file+olp agenda-path "Purchases" "Personal"))
            ("P"
             "Purchase - Shared"
             checkitem
             (file+olp agenda-path "Purchases" "Shared"))
            ("r"
             "Recipe (to Try)"
             entry
             (file+olp agenda-path "Purchases" "Shared")
             "* [[%^{url?}][%^{title?}]]"
            )
          )
    )
)

VTerm (For an embedded terminal in emacs)

(use-package vterm
    :config
      (when (memq window-system '(mac ns)) (setq vterm-shell "/opt/local/bin/zsh"))
      (setq vterm-kill-buffer-on-exit t
              vterm-copy-exclude-prompt t)
      (evil-set-initial-state 'vterm-mode 'insert)

      (defun bb-vterm-exit-close-window (buffer event_desc)
          "Kill the containing window when a vterm process exits"
          (when buffer
          (delete-window (get-buffer-window buffer))))

      (add-hook 'vterm-exit-functions 'bb-vterm-exit-close-window)
      (defun shell-here ()
          "Opens up a new shell in the directory associated with the
          current buffer's file. The eshell is renamed to match that
          directory to make multiple eshell windows easier."
          (interactive)
          (let* ((parent (if (buffer-file-name)
                              (file-name-directory (buffer-file-name))
                          default-directory))
                  (height (/ (window-total-height) 3))
                  (name   (car (last (split-string parent "/" t)))))
          (split-window-vertically (- height))
          (other-window 1)
          (vterm)
          (rename-buffer (concat "*vterm: " name "*"))))
      (evil-leader/set-key "!" 'shell-here))