dotfiles/.emacs.d/config.org
2024-02-04 17:49:53 -08:00

16 KiB

General Configuration

General configuration is configuration of vanilla Emacs. This includes making Emacs more minimal.

Disable Error Bell

Disable error bell and visual bell. Visual bell would be nice on Linux, but on mac it is just annoying so I removed it temp.

  (setq ring-bell-function 'ignore)
  (setq visual-bell nil)

Disable Dialog Box

Disables the dialog prompting box and instead prompts the user in the minibuffer.

(setq use-dialog-box nil)

Relocate Custom File

Change location of custom file. This will stop custom from appending to the config file.

  (setq custom-file "~/.emacs.d/custom.el")
  (unless (file-exists-p custom-file)
      (make-empty-file custom-file))
  (load custom-file)

Move Backup File

This moves the backup files so that Emacs doesn't clutter up directories with backup files.

(setq backup-directory-alist '(("." . "~/.emacs.d/backups/")))

White Space

Various configuration relating to white-space.

  (setq-default electric-ident-inhibit t) ; Stop indentation of the previous line.

Tabs/Spaces

Disable tabs and replace them with a custom number of spaces.

  (setq-default indent-tabs-mode nil) ; Use spaces instead of tabs.
  (setq-default tab-width 4)
  (setq-default evil-shift-width tab-width)

  ; C Indentation
  (setq-default c-basic-offset 4)

  ; Yara Indentation
  (setq-default yara-indent-offset 4)
  (setq-default yara-indent-section 4)

Visualizing White Space

Add a nice visualization for tabs and spaces. This can be helpful to identify which is which quickly to avoid submitting poorly spaced code.

  (global-whitespace-mode)
  (setq whitespace-global-modes '(not org-mode dired-mode erc-mode))
  (setq whitespace-style '(face tabs spaces tab-mark space-mark trailing))
  (custom-set-faces
    '(whitespace-tab ((t (:foreground "#384551"))))
    '(whitespace-space ((t (:foreground "#384551")))))


  (setq whitespace-display-mappings
    '((tab-mark 9 [187 9] [92 9])
      (space-mark 32 [183] [46])))

SSH Remoting with Tramp

Below are a few configuration changes to avoid TRAMP freezes when attempting to SSH into another system with more complex config files.

(setq tramp-remote-shell "/bin/sh")
(setq tramp-remote-shell-login "-l")
(setq tramp-remote-shell-args "-c")

Package Manager

Emacs and packages. Pretty much a requirement.

Setup package

Initialize package and setup package archives. This lets you install packages from other archives such as melpa.

  (require 'package)

  (setq package-archives '(("melpa" . "https://melpa.org/packages/")
                           ("org" . "https://orgmode.org/elpa/")
                           ("elpa" . "https://elpa.gnu.org/packages/")))

  (package-initialize)
  (unless package-archive-contents
    (package-refresh-contents))

Use-package

Install use package for easier installation of other packages.

  (unless (package-installed-p 'use-package)
    (package-install 'use-package))

  (require 'use-package)
  (setq use-package-always-ensure t)
  (setq use-package-compute-statistics t)

Cosmetic

Packages that change the look of Emacs in some way.

Cosmetic Configuration

Disable the useless features that make Emacs bloated.

  ; Disable startup message
  (setq inhibit-startup-message t)

  (scroll-bar-mode -1)   ; Disable scrollbar
  (tool-bar-mode -1)     ; Disable toolbar
  (tooltip-mode -1)      ; Disable tooltips
  (menu-bar-mode -1)     ; Disable menu-bar
  (set-fringe-mode 10)   ; Add gaps on left and right
  (setq scroll-margin 4) ; Scroll as cursor reaches bottom/top of page.

Change font

Pretty self explanatory.

  (defun jm/set-font-faces ()
      (set-face-attribute 'default nil :font "Fira Code Retina" :height 140))

Adding a fix for fonts when running Emacs as a daemon.

  (if (daemonp)
      (add-hook 'after-make-frame-functions
                (lambda (frame)
                  (with-selected-frame frame
                    (jm/set-font-faces))))
    (jm/set-font-faces))

Doom Modeline

Use doom modeline to make the modeline look nicer.

    (use-package all-the-icons) ; requirement
    (use-package doom-modeline
      :init (doom-modeline-mode 1)
      :config
      (setq doom-modeline-height 45)
      (display-time))

In order to avoid missing icons, you should also install the package all-the-icons-install-fonts through the Emacs command line.

Doom Themes

Install doom themes for better themes.

  (use-package doom-themes
    :init (load-theme 'doom-city-lights t))

Rainbow Delimiters

Colors parenthesis for better lisp syntax highlighting.

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

Line Numbers

This adds relative line numbers while excluding certain modes.

  ; Disable line numbers for certain modes
  (dolist (mode '(org-mode-hook
                  erc-mode-hook
                  term-mode-hook
                  vterm-mode-hook
                  shell-mode-hook
                  eshell-mode-hook))
    (add-hook mode (lambda () (display-line-numbers-mode 0))))

  ; Enable relative line numbers
  (setq-default display-line-numbers-type 'visual)
  (global-display-line-numbers-mode t)

Keybindings

Contains the configuration for any keybindings or packages relating to keybindings.

General Configurations

Remap quit command to make it easier to rescue a buffer. With this function, escape will be used instead of C-g.

(global-set-key (kbd "<escape>") 'keyboard-escape-quit)

Which-key

Lists all possible keybindings off of prefix.

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

General

General allows you to setup a prefix key easily. This makes it really easy to setup a bunch of keybindings with ease.

  (use-package general
    :config
    (general-create-definer jm/leader-keys
      :keymaps '(normal insert visual emacs)
      :prefix "SPC"
      :global-prefix "C-SPC")

    (jm/leader-keys
     ; Emacs related keybindings
     "r" '(rename-buffer :which-key "Rename buffer")
     "er" '((lambda () (interactive) (load-file "~/.emacs")) :which-key "Reload emacs config")
     "es" '(eshell :which-key "Open eshell terminal")))

Evil

Evil is a package that adds vim keybindings to Emacs.

  ;; Setup vim keybindings with evil
  (use-package evil
    :init
    (setq evil-want-integration t)
    (setq evil-want-keybinding nil) ; replaced with evil collection
    (setq evil-want-C-u-scroll t)
    (setq evil-want-C-i-jump nil)
    :config
    (evil-mode 1)
    (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
    (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join)

    ; Use visual line motions even outside of visual-line-mode buffers.
    (evil-global-set-key 'motion "j" 'evil-next-visual-line)
    (evil-global-set-key 'motion "k" 'evil-previous-visual-line)

    ; Modify which modes use vim keybindings.
    (evil-set-initial-state 'messages-buffer-mode 'normal)
    (evil-set-initial-state 'dashboard-mode 'normal))

Evil Collection

Evil collection is a package that replaces the bad evil-want-keybinding keybindings.

  (use-package evil-collection
    :after evil
    :config (evil-collection-init))

Undo-Tree

Undo tree's use is self explanatory. While the built-in Emacs undo system is fine for me, undo-tree is required as it fixes an issue with evil where you can't redo.

  ; Fix vim redo with undo tree
  (use-package undo-tree
    :after evil
    :config
    (evil-set-undo-system 'undo-tree)
    (setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo")))
    (global-undo-tree-mode 1))

Other Packages

This is a list of installed packages not included in any other category.

Perspective

Perspective is a package to help with managing buffers. It allows for multiple workspaces or perspectives which each contain their own sub list of buffers.

(use-package perspective
  :bind (("C-x b" . persp-switch-to-buffer*)
         ("C-x k" . persp-kill-buffer*))
  :custom (persp-mode-prefix-key (kbd "C-x w"))
  :init (persp-mode))

Projectile

Projectile is a package for managing various projects in emacs. It adds functionality to let you interact with various projects such as quickly searching filenames, switching between all projects, grepping all files, etc.

(use-package projectile
  :bind-keymap
  ("C-x p" . projectile-command-map)
  :config
  (projectile-mode +1))

Vertico

Vertico is a package that implements a drop-down like menu in the mini buffer allowing for much better searching.

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

When installing Vertico, the documentation mentions a few other packages that add some nice features that would come by default with something like ivy. I've added some descriptions of these below:

  • savehist - One feature of Vertico that is really helpful is it's seamless integration with the built-in emacs package, savehist, to save command history when navigating.
  • marginalia - Similar to the definition of marginalia, this emacs package implements descriptions besides each option in Vertico completion. Some examples of this would be definitions for Elisp functions, more verbose file information, etc.
  • orderless - By default, Vertico starts its completion from the start of the search the same way as default emacs completion. The orderless package changes this by implementing a nicer completion that searches for any similar options based on the provided search terms.
(use-package savehist
  :init
  (savehist-mode))

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

(use-package orderless
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles basic partial-completion)))))

Helpful

Helpful is a package that improves the builtin Emacs help menus. The config below installs helpful and sets the keybindings to call helpful functions instead of the default emacs help.

(use-package helpful
  :bind (("C-h f" . #'helpful-callable)
         ("C-h v" . #'helpful-variable)
         ("C-h k" . #'helpful-key)
         ("C-h x" . #'helpful-command)))

Magit

Magit adds several features to Emacs that make using git easier.

(use-package magit
  :config
  (jm/leader-keys "gc" 'magit-clone))

Dashboard

The Emacs dashboard package provides a nice dashboard when first starting up emacs.

;; Fix for when emacs is run as a daemon

(use-package dashboard
  :init
  (setq initial-buffer-choice (lambda () (dashboard-open))
        dashboard-icon-type 'all-the-icons
        dashboard-set-file-icons t
        dashboard-set-heading-icons t
        dashboard-projects-backend 'project-el
        dashboard-items '((projects . 5)
                          (recents . 5)
                          (agenda . 5)))
  :config
  (dashboard-setup-startup-hook))

MacOS Environment Fix

When using emacs on MacOS, the environment variables are not synced properly and therefore require a separate package to fix this. In this case, this package is the exec-path-from-shell.

(use-package exec-path-from-shell
  :config (exec-path-from-shell-initialize))

Builtin Package Config

Dired

Dired is a built-in package in Emacs that allows for basic file navigation. While it serves its purpose, vanilla dired is far from a good file navigator. With some basic customization however, this can be changed.

  (use-package dired
    :ensure nil ; Melpa won't be able to find this package.
    :commands (dired dired-jump)
    :bind (("C-x C-j" . dired-jump))
    :custom ((dired-listing-switches "-ahgo"))
    :config
    (evil-collection-define-key 'normal 'dired-mode-map
      "h" 'dired-single-up-directory
      "l" 'dired-single-buffer))

Dired Single

Vanilla dired opens a new buffer for every new directory it visits. When managing files, this will quickly fill up resulting in a ridiculous number of buffers. Though, single dired fixes this problem by instead modifying the current buffer when navigating through files.

  (use-package dired-single :after dired)

All the Icons Dired

all-the-icons-dired is a dired plugin that adds icons to each of the files.

  (use-package all-the-icons-dired
    :after dired
    :hook dired-mode)

Hide Dotfiles

This hides all dotfiles in dired with the keybinding H.

(use-package dired-hide-dotfiles
  :hook dired-mode
  :config
  (evil-collection-define-key 'normal 'dired-mode-map
    "H" 'dired-hide-dotfiles-mode))

ERC

ERC is a builtin package that adds IRC chatting functionality to emacs.

(use-package erc
  :ensure nil
  :config
  (setq erc-nick "random936"
        erc-track-exclude-types '("JOIN" "NICK" "PART" "QUIT" "353")
        erc-autojoin-channels-alist '((".*\.libera\.chat" "#emacs" "#gentoo" "#systemcrafters"))
        erc-fill-column 120
        erc-fill-function 'erc-fill-static
        erc-fill-static-center 20
        erc-kill-buffer-on-part t
        erc-kill-queries-on-quit t
        erc-kill-server-buffer-on-quit t)

  ;; Fix for perspective.el not adding ERC buffers to active perspective.
  (add-hook 'erc-join-hook (lambda (&rest args)
                             (persp-add-buffer (current-buffer))))

  (jm/leader-keys 
    "cc" '(erc-tls :which-key "Connect to IRC over TLS")
    "cb" '(erc-switch-to-buffer :which-key "Switch IRC buffers")))

To highlight each nickname with a different color, I can use the erc-hl-nicks package. I can also use the erc-image package to render images sent by other users over IRC.

(use-package erc-hl-nicks
  :after erc
  :config (add-to-list 'erc-modules 'hl-nicks))

(use-package erc-image
  :after erc
  :config
  (setq erc-image-inline-rescale 300)
  (add-to-list 'erc-modules 'image))

Import Other Files

This is the section to include imports from other files.

  (defun jm/load-config-if-exists (file-path)
    (if (file-exists-p file-path)
        (org-babel-load-file file-path)
      (warn (concat "Failed to load config: " file-path))))

  (jm/load-config-if-exists "~/.emacs.d/org.org") ; Org-mode
  (jm/load-config-if-exists "~/.emacs.d/lsp.org") ; Language Server Protocol
  (jm/load-config-if-exists "~/.emacs.d/terminal.org") ; Emacs Terminal
  (jm/load-config-if-exists "~/.emacs.d/functions.org") ; Personal Elisp Functions
  (jm/load-config-if-exists "~/.emacs.d/email.org") ; Mu4e/SMTP Config

  ;; Load EXWM configuration if environment variable set.
  (let ((exwm-org-file "~/.emacs.d/exwm.org"))
    (when (and (file-exists-p exwm-org-file) (getenv "USING_EXWM"))
      (org-babel-load-file exwm-org-file)))