Skip to content

Latest commit

 

History

History
565 lines (427 loc) · 13.6 KB

config.org

File metadata and controls

565 lines (427 loc) · 13.6 KB

Emacs Configuration

Package Management

Use Package

Install packages by default when configured with use-package.

(setq use-package-always-ensure t)

Macro to use to configure built-in features, rather than packages that do not need to be installed

(defmacro use-feature (name &rest args)
  "`use-package' with package installation (`ensure') disabled."
  (declare (indent defun))
  `(use-package ,name
     :ensure nil
     ,@args))

Base Settings

General

Don’t worry about lockfiles

(setq create-lockfiles nil)

Customization Saving

Do not save customizations in init.el, instead save them in a temporary file that will be discarded. As a result, any customizations made in a session will not be persisted across sessions.

(setq custom-file (expand-file-name
                   (format "custom-%d-%d.el" (emacs-pid) (random))
                   temporary-file-directory))

No Littering

Move all common files typically written to the user-emacs-directory to the var and etc subdirectories so that they can be included in .gitignore

(use-package no-littering
  :ensure (:wait t))

Minibuffer

Support opening new minibuffers from inside existing minibuffers.

(setq enable-recursive-minibuffers t)

Do not allow the cursor in the minibuffer prompt.

(setq minibuffer-prompt-properties
      '(read-only t cursor-intangible t face minibuffer-prompt))

(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)

Save History

Command and other menu history is saved.

(use-feature savehist
  :init
  (savehist-mode))

Backup and Auto-Save

Put backup files and auto-save files in var directory, rather than alongside the original files

(setq backup-directory-alist `(("." . ,(no-littering-expand-var-file-name "backup/"))))

(add-hook 'elpaca-after-init-hook
          (lambda ()
            (setq auto-save-list-file-prefix (no-littering-expand-var-file-name "auto-save/sessions/")
                  auto-save-file-name-transforms `((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))))

When paths are too long, there can be errors when auto-save and backup filenames are generated. This uses a consistent hash, rather than the full path to generate the filenames. This is taken from Doom Emacs.

(defun c/make-auto-save-file-name-hashed (fn)
  "Compress the auto-save file name so paths don't get too long."
  (let ((buffer-file-name
         (if (or (null buffer-file-name)
                 (find-file-name-handler buffer-file-name 'make-auto-save-file-name))
             buffer-file-name
           (sha1 buffer-file-name))))
    (funcall fn)))
(advice-add #'make-auto-save-file-name :around #'c/make-auto-save-file-name-hashed)

(defun c/make-backup-file-name-hashed (fn file)
  "A few places use the backup file name so paths don't get too long."
  (let ((alist backup-directory-alist)
        backup-directory)
    (while alist
      (let ((elt (car alist)))
        (if (string-match (car elt) file)
            (setq backup-directory (cdr elt) alist nil)
          (setq alist (cdr alist)))))
    (let ((file (funcall fn file)))
      (if (or (null backup-directory)
              (not (file-name-absolute-p backup-directory)))
          file
        (expand-file-name (sha1 (file-name-nondirectory file))
                          (file-name-directory file))))))
(advice-add #'make-backup-file-name-1 :around #'c/make-backup-file-name-hashed)

Autofill

Set default width of fill mode to 80 columns.

(setq-default fill-column 80)

Indentation

Two space indentation by default.

(setq-default indent-tabs-mode nil
              tab-width 2
              smie-indent-basic 2)

Org Mode Settings

Start Folded

Start an org file with all headers collapsed

(setq org-startup-folded t)

Assistance

Which Key

Which-key is a minor mode for Emacs that displays the key bindings following your currently entered incomplete command (a prefix) in a popup.

(use-feature which-key
  :init
  (which-key-mode))

Helpful

Helpful is an alternative to the built-in Emacs help that provides much more contextual information.

(use-package helpful
  :bind (
         ;; Remap standard commands
         ([remap describe-function] . #'helpful-callable)
         ([remap describe-command] . #'helpful-command)
         ([remap describe-variable] . #'helpful-variable)
         ([remap describe-symbol] . #'helpful-symbol)
         ([remap describe-key] . #'helpful-key)))

User Interface

Font Size

(use-feature emacs
  :bind (("s-=" . #'global-text-scale-adjust)
         ("s--" . #'global-text-scale-adjust)
         ("s-0" . #'global-text-scale-adjust)
         ("C-=" . #'text-scale-adjust)
         ("C--" . #'text-scale-adjust)
         ("C-0" . #'text-scale-adjust))

  :preface
  (defvar presentation-mode-font-size 21)
  (defun presentation-mode ()
    "Increase the font size for presentation."
    (interactive)
    (let* ((current-font-size (/ (face-attribute 'default :height) 10))
           (new-font-size
            (if (not (eq current-font-size presentation-mode-font-size))
                presentation-mode-font-size
              c/monospace-font-size)))
      (set-face-attribute 'default nil :height (* new-font-size 10))
      (set-face-attribute 'variable-pitch nil :height (* new-font-size 10))
      (redisplay 'force))))

Tab Bar

(use-feature tab-bar
  :bind (("s-t" . #'tab-new)
         ("s-w" . #'tab-close)
         ("s-T" . #'tab-undo))

  :config
  (setq tab-bar-show t
        tab-bar-new-tab-choice t
        tab-bar-new-button nil
        tab-bar-close-button-show nil
        tab-bar-new-tab-to 'rightmost
        ;; If this is the default (t) the name format function below causes
        ;; emacs to hang on boot since commit ca3763af5cc2758ec71700029558e6ecc4379ea9
        tab-bar-auto-width nil))

Modern Tab Styling

(use-package modern-tab-bar
  :after tab-bar
  :ensure (modern-tab-bar :host github :repo "aaronjensen/emacs-modern-tab-bar" :protocol ssh)
  :init
  (modern-tab-bar-mode))

Completion Menu (Vertico)

Vertico provides a performant and minimalistic vertical completion UI based on the default completion system.

(use-package vertico
  :init
  (vertico-mode))

Completion Menu Annotations (Marginalia)

Marginalia adds annotations to minibuffer completions.

(use-package marginalia
  :bind (:map minibuffer-local-map ("M-A" . marginalia-cycle))

  :init
  (marginalia-mode))

Consult

Consult provides search and navigation commands based on the Emacs completion function completing-read.

(use-package consult
  :bind (("C-x b" . consult-buffer)))

Completion Style (Orderless)

The orderless completion style allows typing parts of what is being matched, separated by spaces. For example, “som thi” will match “this-is-some-thing”.

(use-package orderless
  :init
  (setq completion-styles '(orderless basic)
        completion-category-defaults nil
        completion-category-overrides '((file (styles partial-completion)))))

Completion at Point (Corfu/Cape/Ripgrep)

Completion at Point Function Configuration

Add :capf and :compdef to use-package

(use-package compdef
  :ensure (:wait t))

Inline Completion (Corfu)

(use-package corfu
  :bind
  (:map corfu-map
        ("TAB" . corfu-next)
        ([tab] . corfu-next)
        ("S-TAB" . corfu-previous)
        ([backtab] . corfu-previous)
        ("C-n" . nil)
        ("C-p" . nil)
        ([remap next-line] . nil)
        ([remap previous-line] . nil)
        ([remap move-end-of-line] . nil)
        ([remap move-beginning-of-line] . nil)
        ("\r" . nil)
        ("<escape>" . corfu-quit))

  :init
  ;; Tab will trigger completion if it does not need to indent
  (setq tab-always-indent 'complete)

  ;; Disable text-mode ispell completion at point function
  (setq text-mode-ispell-word-completion nil)

  ;; TAB-and-Go customizations
  (setq
   ;; Enable cycling for `corfu-next/previous'
   corfu-cycle t
   corfu-preselect 'prompt)

  ;; Auto completion
  (setq
   corfu-auto t
   corfu-auto-prefix 2
   corfu-auto-delay 0.1)

  :config
  (corfu-history-mode))

Cape Completion at Point Functions

(use-package cape
  :config
  (setq cape-dabbrev-check-other-buffers nil))

Ripgrep Completion-at-Point Functions

(use-package ripgrep-capf
  :after cape
  :ensure (:host github :repo "aaronjensen/ripgrep-capf" :protocol ssh)

  :init
  (defalias 'capf-dabbrev-ripgrep (cape-capf-super #'cape-dabbrev #'ripgrep-capf)))

Acting on Completions (Embark)

(use-package embark
  :bind (:map
         vertico-map
         ("C-c C-o" . #'embark-export)
         ("C-c C-c" . #'embark-act)
         ("C-c C-e" . #'c/embark-export-wgrep))

  :preface
  (defvar c/embark-export-wgrep nil)
  (defun c/embark-export-wgrep ()
    "Embark export then wgrep"
    (interactive)
    (setq c/embark-export-wgrep t)
    (command-execute #'embark-export)))

(use-package embark-consult
  :config
  (declare-function wgrep-change-to-wgrep-mode "ext:wgrep")

  (defun c/embark-export-grep-wgrep (&rest _)
    "Start wgrep when indicated"
    (when c/embark-export-wgrep
      (setq c/embark-export-wgrep nil)
      (when (eq major-mode 'grep-mode)
        (wgrep-change-to-wgrep-mode))))

  (advice-add #'embark-consult-export-grep :after #'c/embark-export-grep-wgrep))

Text Editing

Spell Checking (Flyspell)

(use-feature flyspell
  :hook ((org-mode git-commit-mode markdown-mode) . flyspell-mode)

  :config
  (setq flyspell-issue-message-flag nil
        flyspell-issue-welcome-flag nil))

Editing Search Results (wgrep)

Edit the grep buffer and store in the file buffer

(use-package wgrep
  :config
  (setq wgrep-auto-save-buffer t))

Projects

Tree Viewer (Treemacs)

Tree layout file explorer

(use-package treemacs
  :bind ("s-b" . #'treemacs)
  :config
  (treemacs-follow-mode))

Allow Treemacs buffers to be unique inside the active tab instead of the default frame-based buffer scope

(use-package treemacs-tab-bar
  :after (treemacs)
  :demand t
  :config
  (treemacs-set-scope-type 'Tabs))

Workspaces (Tabspaces)

(use-package tabspaces
  :after consult

  :init
  (setq tabspaces-session-file (no-littering-expand-var-file-name "tabsession.el")
        tabspaces-project-switch-commands #'project-find-file)

  (tabspaces-mode)

  :config
  (consult-customize consult--source-buffer :hidden t :default nil)
  ;; set consult-workspace buffer list
  (defvar consult--source-workspace
    (list :name "Workspace Buffers"
          :narrow ?w
          :history 'buffer-name-history
          :category 'buffer
          :state #'consult--buffer-state
          :default t
          :items (lambda () (consult--buffer-query
                             :predicate #'tabspaces--local-buffer-p
                             :sort 'visibility
                             :as #'buffer-name)))

    "Set workspace buffer list for consult-buffer.")
  (add-to-list 'consult-buffer-sources 'consult--source-workspace))

File Types

Shell

(use-feature shell
  :config
  (setq sh-basic-offset 2))

Markdown

(use-package markdown-mode
  :config
  (add-hook 'markdown-mode #'visual-line-mode)
  (add-hook 'markdown-mode #'visual-wrap-prefix-mode)

  (setq markdown-list-indent-width 2))

Ruby

(use-feature ruby-mode
  :hook (ruby-mode . corfu-mode)
  :capf capf-dabbrev-ripgrep

  :config
  (setq ruby-block-indent nil
        ruby-method-call-indent nil
        ruby-method-params-indent nil
        ruby-after-operator-indent nil
        ruby-bracketed-args-indent nil))

Programming

Go To Definition (Dumb Jump)

Find potential definitions of a function of variable under point

(use-package dumb-jump
  :init
  (add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
  (setq xref-show-definitions-function #'xref-show-definitions-completing-read)

  (setq dumb-jump-force-searcher 'rg))

Verion Control

Magit

(use-package magit)

Install latest version of transient, as the version included in Emacs is not recent enough.

(use-package transient)

Terminal

Terminal Emulator (vterm)

(use-package vterm
  :init
  (setq vterm-always-compile-module t
        ;; Defaults to 0.1. Decreasing this greatly impacts performance of
        ;; rendering large batches of text.
        vterm-timer-delay 0.06))

Toggle

(use-package vterm-toggle
  :bind (("s-i" . vterm-toggle)))

Startup Time

(add-hook 'after-init-hook
          (lambda ()
            (let ((inhibit-message t))
              (message "Emacs init time: %s" (emacs-init-time)))))