To confirm your changes to the Psimacs configuration click the link below. CONFIRM CHANGES
To clear user customizations made via the emacs customize GUI, click the link below. DELETE CUSTOMIZATIONS
(require 'bind-key)
(defun psimacs-regen-conf ()
"Deletes the compiled psimacs.elc file, regenerating at next startup"
(interactive)
(delete-file
(expand-file-name
(locate-user-emacs-file "psimacs.elc"))))
(defun psimacs-remove-user-cust ()
"Deletes the custom.el file, resetting user customizations"
(interactive)
(delete-file
(expand-file-name
(concat user-emacs-directory ".cache/custom.el"))))
Disables emacs default start screen, since we’re using dashboard instead.
(custom-set-variables
'(inhibit-startup-screen t))
Disables blinking cursor, the tool-bar, and the menu-bar. Disables the scroll-bar on graphical systems as well.
(blink-cursor-mode 0)
(tool-bar-mode 0)
(menu-bar-mode 0)
(if (display-graphic-p)
(scroll-bar-mode 0))
On terminal displays, set the menu color scheme manually.
(if (not (display-graphic-p))
(set-face-background 'tty-menu-selected-face nil "color-208"))
Binds display-battery-mode to C-c <f12>.
(global-set-key (kbd "C-c <f12>") 'display-battery-mode)
Sets the default font and size. The commented out selections are all high quality programming fonts. Source Code Pro is available in most major Linux distro repositories, the others you may have to install yourself.
(add-to-list 'default-frame-alist '(font . "Fira Code-13"))
; (add-to-list 'default-frame-alist '(font . "Hack-13"))
; (add-to-list 'default-frame-alist '(font . "Source Code Pro-13"))
; (add-to-list 'default-frame-alist '(font . "Hasklig-13"))
(global-set-key (kbd "<f11>") 'toggle-frame-fullscreen)
When a user manually installs a package with package.el, or customizes variables/faces via gui Emacs saves the customizations with autogenerated elisp. Usually it happens in the init file, but we dont want that as init.el is under source control. So we move it to .cache/custom.el so user specified configuration is ignored by git. The defun disables saving enabled packages through list-package, since we do that with use-package instead.
(setq custom-file
(expand-file-name
(concat user-emacs-directory ".cache/custom.el")))
(defun package--save-selected-packages (&rest opt) nil)
Sets the location for backup files to the OS temp file directory. On Unix, this directory is located at /tmp.
(setq backup-directory-alist
`((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
`((".*" ,temporary-file-directory t)))
Sets up global auto-pairing of parentheses, quotes, brackets etc.
(use-package electric-pair-mode
:hook
(after-init . electric-pair-mode)
(after-init . show-paren-mode))
Global line numbers on all programming, text, and org buffers.
(use-package display-line-numbers-mode
:hook
(prog-mode . display-line-numbers-mode)
(text-mode . display-line-numbers-mode)
(conf-mode . display-line-numbers-mode)
(org-mode . display-line-numbers-mode))
Sets default tab indent to be three space characters.
(setq-default indent-tabs-mode nil)
(setq-default tab-width 3)
Disables the alert bell completely.
(setq ring-bell-function 'ignore)
(setq bookmark-default-file
(expand-file-name (locate-user-emacs-file ".cache/bookmarks")))
Installs external packages, and configures both baseline and external packages. Packages are updated weekly but this can be configured. Currently defaulting to MELPA, but older packages from melpa-stable can be installed by pinning with use-package. The various packages are grouped by their purpose.
The basic package manager setup is done in the init.el file to ensure that it loads before org-mode. This is necessary so that Org Mode is ready to be used without restarting Emacs after a package update.
All-the-icons provides icons that themes can use to replace indicators with appropriate icons, for example a branching logo for vcs status.
(use-package all-the-icons :straight t)
(use-package all-the-icons-dired :straight t
:hook (dired-mode . all-the-icons-dired-mode))
(use-package all-the-icons-ivy-rich :straight t :after counsel
:init (all-the-icons-ivy-rich-mode 1)
:config
(setcdr (assq t ivy-format-functions-alist) #'ivy-format-function-line))
(use-package treemacs-all-the-icons :straight t
:after treemacs all-the-icons
:config
(treemacs-load-theme "all-the-icons"))
Doom-themes and doom-modeline are beautiful theme frameworks that give Emacs a modern, snazzy look. I prefer the doom-vibrant theme but this can be easily changed in the load-theme declaration of doom.
(use-package doom-themes :straight t
:config (load-theme 'doom-vibrant t)
(doom-themes-org-config)
:custom-face (org-block ((t (:background "#1B1D26"))))
(org-block-begin-line ((t (:background "#1B1D26"))))
(org-block-end-line ((t (:background "#1B1D26"))))
(hl-line ((t (:background "#1F2228")))))
Modeline from Doom, has some problems in tty with all-the-icons.
(use-package doom-modeline :straight t
:hook (after-init . doom-modeline-mode)
:config
(setq doom-modeline-height 35)
(setq find-file-visit-truename t)
(setq doom-modeline-unicode-fallback t))
Spacemacs theme is a nice alternative to the doom themes, but I personally prefer doom-vibrant.
(custom-set-variables '(spacemacs-theme-custom-colors
'((comment-bg . nil))))
(use-package spacemacs-theme :straight t
:defer t
:init (load-theme 'spacemacs-dark t)
:custom-face (fringe ((t (:background "#212026")))))
(add-hook 'text-mode-hook 'hl-line-mode)
(add-hook 'prog-mode-hook 'hl-line-mode)
(setq psimacs-default-fringe '(2 . 2))
(setq psimacs-debug-fringe '(4 . 1))
(fringe-mode psimacs-default-fringe)
Dashboard is a start page for Emacs that keeps a list of recent files and displays upcoming entries in the org-agenda.
(use-package dashboard :straight t
:config
(dashboard-setup-startup-hook)
(setq dashboard-banner-logo-title "Welcome to GNU Emacs")
(setq recentf-save-file
(expand-file-name (locate-user-emacs-file ".cache/recentf")))
(setq dashboard-set-footer nil)
(setq dashboard-startup-banner 'logo)
(setq dashboard-set-heading-icons t)
(setq dashboard-set-file-icons t)
(setq dashboard-center-content t)
(setq dashboard-items '((projects . 5)
(recents . 5)
(bookmarks . 5)
(agenda . 5))))
Centaur-tabs brings browser-like tabs to Emacs. I personally dont get much use out of them but I must admit they are snazzy.
(use-package centaur-tabs :straight t
:config
(centaur-tabs-headline-match)
(setq centaur-tabs-set-icons t)
:bind
("C-<tab>" . centaur-tabs-forward)
("C-c <tab>" . centaur-tabs-mode)
:custom-face
(centaur-tabs-unselected
((t (:foreground "dim grey" :background "#2a2e38")))))
Another neat visual package I personally dont get much use out of. Treemacs is a project/file explorer sidebar similar to many IDEs. The two other packages provide integration with magit and projectile.
(use-package treemacs :straight t :defer t
:config
(treemacs-git-mode 'deferred)
(setq treemacs-width 30)
:bind
("C-c t" . treemacs))
(use-package treemacs-magit :straight t
:after treemacs magit)
(use-package treemacs-projectile :straight t
:after treemacs projectile)
For those of us who think a small bar style cursor is superior to the block.
(use-package bar-cursor :straight t
:config (bar-cursor-mode t))
Puts indentation guide vertical lines into source code files.
(use-package highlight-indent-guides :straight t
:config
(setq highlight-indent-guides-method 'character)
:hook
(prog-mode . highlight-indent-guides-mode))
Highlights uncommitted & unsaved lines in the lefthand fringe
(use-package diff-hl :straight t
:config (global-diff-hl-mode)
:hook (prog-mode . diff-hl-flydiff-mode)
(fundemental-mode . diff-hl-flydiff-mode)
(conf-mode . diff-hl-flydiff-mode))
Colorizes matching parentheses for easier parsing by humans.
(use-package rainbow-delimiters :straight t
:hook
(emacs-lisp-mode . rainbow-delimiters-mode)
(racket-mode . rainbow-delimiters-mode)
(racket-repl-mode . rainbow-delimiters-mode)
(scheme-mode . rainbow-delimiters-mode)
(lisp-mode . rainbow-delimiters-mode)
(sly-mode . rainbow-delimiters-mode)
(clojure-mode . rainbow-delimiters-mode)
(clojurescript-mode . rainbow-delimiters-mode)
(cider-repl-mode . rainbow-delimiters-mode))
Customizes various packages to use a single popup window framework
(use-package posframe :straight t)
(use-package company-posframe :straight t
:hook (company-mode . company-posframe-mode))
Ivy is a regex based replacement for the emacs C-f and M-x commands that saves many keystrokes with its predictive abilities.
(use-package ivy :straight t :diminish
:config (ivy-mode t)
(setq ivy-use-selectable-prompt t))
(use-package ivy-rich :straight t :after counsel
:init (ivy-rich-mode 1))
Add support for using ivy instead of dedicated buffer for xref (jump to definition) results.
(use-package ivy-xref :straight t
:init
(when (>= emacs-major-version 27)
(setq xref-show-definitions-function #'ivy-xref-show-defs))
(setq xref-show-xrefs-function #'ivy-xref-show-xrefs))
Counsel-mode replaces many built in Emacs interactive functions with better defaults. It is developed to work well with ivy & swiper, and they are all actually part of the same project. By turning on counsel mode globally in the use-package block, you replace the emacs commands with their counsel equivalents.
(use-package counsel :straight t :diminish
:config (counsel-mode t))
(use-package counsel-tramp :straight t :after counsel)
Swiper is a package for searching through buffers. It is similar to the built in isearch, and in my configuration I replaced the C-s keybinding with swiper.
(use-package swiper :straight t :diminish
:bind ("C-s" . swiper-isearch) ("C-r" . swiper-isearch-backward)
:custom-face
(swiper-line-face
((t (:foreground "#1c1f24" :background "dim gray")))))
Ripgrep emacs package is a magit-like frontend to the grep replacement “rg”.
(use-package rg :straight t
:config (rg-enable-default-bindings))
A better kind of flymake, Interfaces well with LSP.
(use-package flycheck :straight t
; :hook (after-init . global-flycheck-mode)
:hook
(rustic-mode . flycheck-mode)
(c++-mode . flycheck-mode)
(c-mode . flycheck-mode)
(go-mode . flycheck-mode)
(emacs-lisp-mode . flycheck-mode)
(python-mode . flycheck-mode)
:config
(add-to-list 'display-buffer-alist
`(,(rx bos "*Flycheck errors*" eos)
(display-buffer-reuse-window
display-buffer-in-side-window)
(side . bottom)
(reusable-frames . visible)
(window-height . 0.20))))
Hydra is a temporary situational keymapping package, useful to define temporary keymaps for debugging, quick navigation, etc. It can optionally provide a keymap cheat sheet in the mini-buffer.
(use-package hydra :straight t)
God-mode is a vi-like modal editing system for emacs. When God-mode is enabled, emacs interprets <some keystroke> as <C-some keystroke>. It does not have vi-like bindings, it instead uses emacs keybindings in a modal system. For example pressing n moves the cursor downwards like C-n would outside of God-mode. I have God-mode bound to escape.
(use-package god-mode :straight t
:bind ("<escape>" . god-mode-all)
:config (setq god-exempt-major-modes nil)
(setq god-exempt-predicates nil))
I am currently toying with using evil mode, but with insert mode mapped to default emacs keybindings.
Might want to try the packages below too:
- evil-tutor
- evil-magit
- evil-org
- evil-space
- evil-ediff
(use-package evil :straight t
:config
(setq evil-emacs-state-modes nil)
(setq evil-insert-state-modes nil)
(setq evil-motion-state-modes nil)
;(setq evil-default-state 'evil-emacs-state)
(define-key evil-normal-state-map "i" 'evil-emacs-state)
(define-key evil-normal-state-map "\C-z" 'evil-insert-state)
(define-key evil-emacs-state-map [escape] 'evil-normal-state)
(evil-mode 1))
- DISABLED
I am also currently toying with creating my own custom modal keymap via Ryo. I basically just want vim nav keys along with some emacs commands without their prefix.
(use-package ryo-modal :straight t
:commands ryo-modal-mode
:bind ("<escape>" . ryo-modal-mode)
:config
(ryo-modal-keys
;;("," ryo-modal-repeat)
;;("q" ryo-modal-mode)
;;("h" backward-char)
;;("j" next-line)
;;("k" previous-line)
;;("l" forward-char)
("n" next-line)
("m" previous-line)
("s" swiper-isearch)
("a" beginning-of-line)
("e" end-of-line)
("f" forward-char)
("b" backward-char)
("k" kill-line)
("y" yank)
("/" undo)
("c" "C-c")
("<SPC>" set-mark-command)
("w" kill-region))
(ryo-modal-keys
;; First argument to ryo-modal-keys may be a list of keywords.
;; These keywords will be applied to all keybindings.
(:norepeat t)
("0" "M-0")
("1" "M-1")
("2" "M-2")
("3" "M-3")
("4" "M-4")
("5" "M-5")
("6" "M-6")
("7" "M-7")
("8" "M-8")
("9" "M-9")
(":" "M-x")
("x" "C-x")
("C-x f" "C-x C-f")))
Tramp is an emacs built-in function for editing files on remote systems. It treats remote file systems, or different users on the same system, as a single logical system.
(use-package tramp
:config (setq tramp-default-method "ssh")
(setq tramp-persistency-file-name
(expand-file-name
(locate-user-emacs-file ".cache/tramp")))
(add-to-list 'tramp-remote-path 'tramp-own-remote-path))
Emacs’s built in shell is an underrated feature, probably in part due to its less than attractive default appearance. This section installs an external package for a toggle-able popup terminal bound to f12. On top of this, I made some of my own customizations in the psishell package. Most of these are visual changes, but a few minor aliases and custom functions can be found in there as well.
(use-package eshell)
(use-package psishell
:hook
(after-init . psiprompt-initialize)
(eshell-mode . setup-eshell-ivy-completion))
(use-package aweshell :straight
(:host github :repo "manateelazycat/aweshell"))
(use-package eshell-toggle :straight t :defer t
:custom
(eshell-toggle-size-fraction 3)
(eshell-toggle-use-projectile-root t)
(eshell-toggle-run-command nil)
(eshell-toggle-init-function #'eshell-toggle-init-eshell)
:bind
("<f12>" . eshell-toggle))
(use-package dired-hacks-utils :straight t)
(use-package dired-rainbow :straight t)
(use-package dired-filetype-face :straight t
:config (require 'dired-filetype-face))
(use-package dired-subtree :straight t
:bind (:map dired-mode-map
("i" . dired-subtree-insert)
(";" . dired-subtree-remove)
("<tab>" . dired-subtree-toggle)
("<backtab>" . dired-subtree-cycle)))
(use-package dired-git :straight t
:hook (dired-mode . dired-git-mode))
Used by Emacs internal web browsers to store cookies, session info, history, etc.
(use-package url
:config
(setq url-configuration-directory
(expand-file-name (locate-user-emacs-file ".cache/url"))))
Emacs must be compiled with module support to use libvterm, so disabled by default.
(use-package vterm :straight t)
Magit is a powerful git front-end for emacs that exposes most of git’s functions without dumbing them down. They can be called from eshell which is extremely cool. I currently cant remember why I set the transient-values file to the projectile cache.
(use-package magit :straight t
:config
(setq transient-values-file
(expand-file-name
(locate-user-emacs-file ".cache/projectile-cache")))
(setq transient-history-file
(expand-file-name
(locate-user-emacs-file ".cache/projectile-cache"))))
Projectile is a project management system that lets other packages like LSP automatically detect project roots. It is aware of version control which means LSP & dap are also aware of version control.
(use-package projectile :straight t
:config
(setq projectile-cache-file
(expand-file-name
(locate-user-emacs-file ".cache/projectile-cache")))
(setq projectile-known-projects-file
(expand-file-name
(locate-user-emacs-file ".cache/projectile-bookmarks.eld"))))
(use-package project :straight t)
Custom theme elements for org mode. Attribute setting lines can be disabled if you prefer a single global font size in org-mode. Org-bullets can be removed if you prefer asterisk’s over bullets for org headings. Heading-based indentation can be disabled by removing the org-indent-mode hook.
(use-package org-bullets :straight t
:hook
(org-mode . org-bullets-mode)
(org-mode . org-indent-mode)
:config
(set-face-attribute 'org-level-1 nil :height 1.4)
(set-face-attribute 'org-level-2 nil :height 1.25)
(set-face-attribute 'org-document-title nil :height 1.5)
(setq org-id-locations-file
(expand-file-name
(concat user-emacs-directory ".cache/org-id-locations"))))
Org Babel language configuration. Eventually planning to make this configurable outside of the elisp code.
(org-babel-do-load-languages
'org-babel-load-languages
'((python . t)
(shell . t)
(C . t)
(makefile . t)
(octave . t)
(matlab . t)
(lisp . t)))
(use-package ob-http :straight t
:config
(append '((http . t)) org-babel-load-languages))
Use four space indentation and Stroustrup formatting for C and C++ buffers.
(use-package cc-mode
:config
(setq-default c-basic-offset 4)
(setq c-default-style "stroustrup"))
Anaconda mode provides general python running/debugging support on top of emacs default python-mode. Pyvenv provides a nice way to switch between different virtual environments inside of emacs. Overall my python setup is relatively untested, and more granular configuration might make it easier to work with.
(use-package anaconda-mode :straight t
:hook python-mode
:config
(setq anaconda-mode-installation-directory
(expand-file-name
(locate-user-emacs-file ".cache/anaconda-mode"))))
(use-package pyvenv :straight t)
Go syntax highlighting & snippets. Additional support for semantic auto-completion and debugging is provided by lsp and dap elsewhere.
(use-package go-mode :straight t
:hook (go-mode . lsp))
(use-package go-snippets :straight t
:after yasnippet)
Rust syntax highlighting and LSP autocompletion. Rust-mode is provided by the rust project. Rustic is a third party, more actively developed Rust configuration for emacs. Note: Must install rust-src component from rustup for completion and lsp-ui documentation to work correctly.
(use-package rustic :straight t
:config
(setq rustic-flycheck-setup-mode-line-p nil))
Common Lisp support via the absolutely awesome SLIME environment. Requires a bit of setup, documented on slimes website Here. I chose the debian default sblc binary location for inferior-lisp-program, point it to wherever you have your common lisp implementation installed.
(use-package slime :straight t :defer
:config
; (setq inferior-lisp-program "sbcl")
(add-to-list 'slime-contribs 'slime-fancy)
(defun gerbil-scheme-start-swank (file encoding)
(format "%S\n\n" `(begin (import (ecraven gerbil-swank)) (start-swank ,file))))
(setq slime-lisp-implementations
(cons '(gerbil-scheme ("gxi" "-:d-" "--lang" "r7rs")
:init gerbil-scheme-start-swank
:env "GERBIL_LOADPATH=/home/hdjones/src/r7rs-swank/")
slime-lisp-implementations)))
(use-package slime-company :straight t :after slime company)
(use-package sly :straight t
:config
(setq org-babel-lisp-eval-fn #'sly-eval)
(setq inferior-lisp-program "sbcl"))
Scheme support, specifically geared towards racket. A SLIME-like interface to racket is provided by racket-mode. A possible implementation independent solution would be geiser.
(use-package geiser-guile :straight t)
(use-package racket-mode :straight t
:config
(add-to-list 'auto-mode-alist '("\\.rkt\\'" . racket-mode))
(setq racket-show-functions '(racket-show-pseudo-tooltip))
:hook
(racket-mode . racket-smart-open-bracket-mode)
(racket-repl-mode . racket-smart-open-bracket-mode)
(racket-mode . racket-xp-mode))
(use-package ob-racket
:straight
(:host github :repo "DEADB17/ob-racket")
:config
(append '((racket . t) (scribble . t)) org-babel-load-languages))
(use-package paredit :straight t)
Clojure support provided by CIDER and LSP.
(use-package clojure-mode :straight t
:hook
(clojure-mode . lsp)
(clojurescript-mode . lsp)
(clojurec-mode . lsp))
(use-package cider :straight t)
Enables Emacs’ built-in support for MATLAB. The matlab-shell-command variable can be changed if matlab is installed in a nonstandard location and/or is not in the users $PATH environmental variable. This approach is reportedy specific to Unix-like OS’s and a different method has to be used on Win32.
(use-package matlab-mode :straight t
:config
(setq matlab-indent-function t)
(setq matlab-shell-command "matlab")
:defer t)
Enables Emacs built-in octave support. This is sorta mutually exlusive with the matlab mode at the moment, probably just the way I have it configured. The –line-editing argument is a workaround for a bug where QT plot windows refuse to close.
(use-package octave
:hook
(octave-mode . (lambda () (abbrev-mode 1) (auto-fill-mode 1)
(if (eq window-system 'x) (font-lock-mode 1))))
:config
(add-to-list 'auto-mode-alist '("\\.m$" . octave-mode))
(setq inferior-octave-startup-args '("-i" "--line-editing")))
Provides a mode for editing Nix configuration files.
(use-package nix-mode :straight t)
(use-package nix-buffer :straight t
:config
(nix-buffer-update-directory-name
(expand-file-name
(locate-user-emacs-file ".cache/nix-buffer"))))
Languages for interacting with the Ethereum Virtual Machine
(use-package solidity-mode :straight t)
(use-package company-solidity :straight t)
(use-package solidity-flycheck :straight t)
(use-package vyper-mode :straight t)
(use-package systemd :straight t)
Provides a mode for yaml files
(use-package yaml-mode :straight t)
(use-package protobuf-mode :straight t)
Support for Podman/Docker container tech, including relevant file types.
(use-package docker :straight t)
(use-package dockerfile-mode :straight t)
(use-package docker-compose-mode :straight t)
(use-package direnv :straight t
:config (direnv-mode))
Yasnippet provides auto-complete code snippets that can be made/enabled on a language specific basis.
(use-package yasnippet :straight t
:config
(push (locate-user-emacs-file "psimacs/snippets") yas-snippet-dirs)
(yas-global-mode 1))
(use-package yasnippet-snippets :straight t)
Company acts as an intellisense-like autocomplete front end for the various language specific completion engines in emacs. Company-box provides logos for different kinds of completions that make it easier to visually parse the completion list.
(use-package company :straight t :diminish
:config
(global-company-mode t)
(setq company-tooltip-maximum-width 100))
(use-package company-box :straight t
:after company
:diminish
:hook (company-mode . company-box-mode))
The Language Server Protocol is an editor-agnostic code parsing/analysis protocol that editors can use to communicate with code completion engines. The lsp-mode Emacs package is an implementation of this protocol. Origami is an Emacs package that provides code folding, and lsp-origami provides origami with language specific code folding configuration.
Later on, I will move the C and C++ specific LSP configuration out into a different configuration area. The clangd executable should be configurable later as well.
(use-package lsp-mode :straight t
:hook (c-mode . lsp) (c++-mode . lsp)
:commands lsp
:config
(setq lsp-prefer-flymake nil)
(setq lsp-lens-enable t)
(setq lsp-clients-clangd-executable "clangd")
(setq lsp-session-file (expand-file-name
(locate-user-emacs-file ".cache/lsp-session"))))
(use-package lsp-ui :straight t
:hook (lsp-mode . lsp-ui-mode)
:config (setq lsp-ui-peek-always-show t)
:bind ("M-+" . lsp-ui-peek-find-definitions))
(use-package origami :straight t
:config (global-origami-mode)
:bind ("C-c f" . origami-forward-toggle-node))
(use-package lsp-origami :straight t)
IDE-like debugging support is provided by the dap-mode package. For now, the dap languages are specified here in the use-package declaration.
(use-package dap-mode :straight t
:hook
(c-mode . dap-mode)
(c++-mode . dap-mode)
(rustic-mode . dap-mode)
(go-mode . dap-mode)
:config
(setq dap-auto-configure-features '(locals controls tooltip))
(setq dap-breakpoints-file
(expand-file-name (locate-user-emacs-file ".cache/dap-breakpoints")))
:bind
(:map dap-mode-map
("<f5>" . dap-debug)
("C-<f5>" . dap-hydra)))
(use-package dap-gdb-lldb)
(use-package dap-go)
Meson and Ninja are modern analogues to Autotools & Make respectively.
(use-package meson-mode :straight t)
(use-package ninja-mode :straight t)
(use-package cmake-mode :straight t)