dotfiles/.emacs.d/config.org
2023-12-15 19:00:54 -08:00

508 lines
14 KiB
Org Mode

* 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.
#+begin_src emacs-lisp
(setq ring-bell-function 'ignore)
(setq visual-bell nil)
#+end_src
** Disable Dialog Box
Disables the dialog prompting box and instead prompts the user in the minibuffer.
#+begin_src emacs-lisp
(setq use-dialog-box nil)
#+end_src
** Relocate Custom File
Change location of custom file. This will stop *custom* from appending to the config file.
#+begin_src emacs-lisp
(setq custom-file "~/.emacs.d/custom.el")
(unless (file-exists-p custom-file)
(make-empty-file custom-file))
(load custom-file)
#+end_src
** Move Backup File
This moves the backup files so that Emacs doesn't clutter up directories with backup files.
#+begin_src emacs-lisp
(setq backup-directory-alist '(("." . "~/.emacs.d/backups/")))
#+end_src
** Time Startup
This function times the startup to tell you how long it took for the Emacs config to load.
#+begin_src emacs-lisp
(defun jm/display-startup-time ()
(message "Emacs loaded in %.2f seconds with %d garbage collections."
(float-time (time-subtract after-init-time before-init-time))
gcs-done))
(add-hook 'emacs-startup-hook 'jm/display-startup-time)
#+end_src
** White Space
Various configuration relating to white-space.
#+begin_src emacs-lisp
(setq-default electric-ident-inhibit t) ; Stop indentation of the previous line.
#+end_src
*** Tabs/Spaces
Disable tabs and replace them with a custom number of spaces.
#+begin_src emacs-lisp
(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)
#+end_src
*** 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.
#+begin_src emacs-lisp
(global-whitespace-mode)
(setq whitespace-global-modes '(not org-mode dired-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])))
#+end_src
** 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.
#+begin_src emacs-lisp
(setq tramp-remote-shell "/bin/sh")
(setq tramp-remote-shell-login "-l")
(setq tramp-remote-shell-args "-c")
#+end_src
* General Packages
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 [[https://melpa.org/][melpa]].
#+begin_src emacs-lisp
(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))
#+end_src
** Use-package
Install use package for easier installation of other packages.
#+begin_src emacs-lisp
(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)
#+end_src
** Installed Packages
This is a list of installed packages not included in any other category.
*** Command Log Mode
Command Log Mode creates a window that logs all commands and corresponding keybindings.
#+begin_src emacs-lisp
(use-package command-log-mode
:defer t
:config (global-command-log-mode))
#+end_src
*** Magit
*Magit* adds several features to Emacs that make using git easier.
#+begin_src emacs-lisp
(use-package magit)
#+end_src
*** Helpful
*Helpful* is a package that improves the builtin Emacs help menus.
#+begin_src emacs-lisp
(use-package helpful
:config ; Set keybindings to call helpful instead of the default emacs help.
(global-set-key (kbd "C-h f") #'helpful-callable)
(global-set-key (kbd "C-h v") #'helpful-variable)
(global-set-key (kbd "C-h k") #'helpful-key)
(global-set-key (kbd "C-h x") #'helpful-command)
;; Lookup the current symbol at point. C-c C-d is a common keybinding for this in lisp modes.
(global-set-key (kbd "C-c C-d") #'helpful-at-point)
;; Look up *F*unctions (excludes macros).
(global-set-key (kbd "C-h F") #'helpful-function))
#+end_src
*** 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.
#+begin_src emacs-lisp
(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))
#+end_src
* Cosmetic
Packages that change the look of Emacs in some way.
** Cosmetic Configuration
Disable the useless features that make Emacs bloated.
#+begin_src emacs-lisp
; 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.
#+end_src
*** Change font
Pretty self explanatory.
#+begin_src emacs-lisp
(defun jm/set-font-faces ()
(set-face-attribute 'default nil :font "Fira Code Retina" :height 140))
#+end_src
Adding a fix for fonts when running Emacs as a daemon.
#+begin_src emacs-lisp
(if (daemonp)
(add-hook 'after-make-frame-functions
(lambda (frame)
(with-selected-frame frame
(jm/set-font-faces))))
(jm/set-font-faces))
#+end_src
** Doom Modeline
Use doom modeline to make the modeline look nicer.
#+begin_src emacs-lisp
(use-package all-the-icons) ; requirement
(use-package doom-modeline
:init (doom-modeline-mode 1)
:config
(setq doom-modeline-height 45)
(display-time))
#+end_src
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.
#+begin_src emacs-lisp
(use-package doom-themes
:init (load-theme 'doom-city-lights t))
#+end_src
** Rainbow Delimiters
Colors parenthesis for better lisp syntax highlighting.
#+begin_src emacs-lisp
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode))
#+end_src
** Line Numbers
This adds relative line numbers while excluding certain modes.
#+begin_src emacs-lisp
; Disable line numbers for certain modes
(dolist (mode '(org-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)
#+end_src
* Auto-completion
Packages associated with Emacs auto-completion. This does not include auto-completion from language servers just the auto-completion of commands etc.
** Vertico
Vertico is a package that implements a drop-down like menu in the mini buffer allowing for much better searching.
#+begin_src emacs-lisp
(use-package vertico
:init
(vertico-mode))
#+end_src
One feature of Vertico that is really helpful is that it works with another built-in emacs package, ~savehist~, to save directory history when navigating with Vertico.
#+begin_src emacs-lisp
(use-package savehist
:init
(savehist-mode))
#+end_src
One last feature I will also add is the ~marginalia~ package which adds some nice /footnotes/ to the command information. This can be extra helpful when looking up Elisp functions for example.
#+begin_src emacs-lisp
(use-package marginalia
:after vertico
:init
(marginalia-mode))
#+end_src
* 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*.
#+begin_src emacs-lisp
(global-set-key (kbd "<escape>") 'keyboard-escape-quit)
#+end_src
** Packages
*** Which-key
Lists all possible keybindings off of prefix.
#+begin_src emacs-lisp
(use-package which-key
:init (which-key-mode)
:diminish which-key-mode)
#+end_src
*** General
General allows you to setup a prefix key easily. This makes it really easy to setup a bunch of keybindings with ease.
#+begin_src emacs-lisp
(use-package general
:config
(general-create-definer jm/leader-keys
:keymaps '(normal insert visual emacs)
:prefix "SPC"
:global-prefix "C-SPC")
(jm/leader-keys
; Example of a keybinding should be changed later
"t" '(counsel-load-theme :which-key "Choose theme")
"v" '(vterm :which-key "Open vterm terminal")
"r" '(rename-buffer :which-key "Rename buffer")
; Org mode related keybindings
"oa" '(org-agenda :which-key "Org agenda")
; Emacs related keybindings
"er" '((lambda () (interactive) (load-file "~/.emacs")) :which-key "Reload emacs config")
"es" '(eshell :which-key "Open eshell terminal")))
#+end_src
*** Evil
Evil is a package that adds vim keybindings to Emacs.
#+begin_src emacs-lisp
;; 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))
#+end_src
**** Evil Collection
Evil collection is a package that replaces the bad ~evil-want-keybinding~ keybindings.
#+begin_src emacs-lisp
(use-package evil-collection
:after evil
:config (evil-collection-init))
#+end_src
**** 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.
#+begin_src emacs-lisp
; 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))
#+end_src
*** Hydra
Hydra is a package that implements a way to execute the same commands in quick succession.
#+begin_src emacs-lisp
(use-package hydra :defer)
#+end_src
Setup easy changing of font size. This implements a zooming system to make text smaller or bigger quickly.
#+begin_src emacs-lisp
(defhydra hydra-zoom (:timeout 4)
("j" text-scale-increase "in")
("k" text-scale-decrease "out")
("f" nil "finished" :exit t))
#+end_src
This keybinding needs to be added to general to give it a prefix.
#+begin_src emacs-lisp
(jm/leader-keys
"z" '(hydra-zoom/body :which-key "scale-text"))
#+end_src
* 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.
#+begin_src emacs-lisp
(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))
#+end_src
** 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.
#+begin_src emacs-lisp
(use-package dired-single :after dired)
#+end_src
** All the Icons Dired
~all-the-icons-dired~ is a dired plugin that adds icons to each of the files.
#+begin_src emacs-lisp
(use-package all-the-icons-dired
:after dired
:hook (dired-mode . all-the-icons-dired-mode))
#+end_src
** Hide Dotfiles
This hides all dotfiles in dired with the keybinding ~H~.
#+begin_src emacs-lisp
(use-package dired-hide-dotfiles
:hook (dired-mode . dired-hide-dotfiles-mode)
:config
(evil-collection-define-key 'normal 'dired-mode-map
"H" 'dired-hide-dotfiles-mode))
#+end_src
* Import Other Files
This is the section to include imports from other files.
#+begin_src emacs-lisp
(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)))
#+end_src