(setq package-enable-at-startup nil)
(when (fboundp 'startup-redirect-eln-cache)
(startup-redirect-eln-cache
(convert-standard-filename
(expand-file-name "var/eln-cache/" user-emacs-directory))))
;;; -*- lexical-binding: t -*-
;; NOTE: init.el is now generated from Emacs.org. Please edit that file
;; in Emacs and init.el will be generated automatically!
(setq gc-cons-threshold 200000000)
(setq native-comp-async-report-warnings-errors nil)
(setq warning-minimum-level :error)
(defun me/display-startup-time ()
(message "Emacs loaded in %s with %d garbage collections."
(format "%.2f seconds"
(float-time
(time-subtract after-init-time before-init-time)))
gcs-done))
(add-hook 'emacs-startup-hook #'me/display-startup-time)
(when (fboundp 'horizontal-scroll-bar-mode)
(horizontal-scroll-bar-mode -1))
(when (fboundp 'scroll-bar-mode)
(scroll-bar-mode -1))
(when (fboundp 'tool-bar-mode)
(tool-bar-mode -1))
(when (fboundp 'tooltip-mode)
(tooltip-mode -1))
(when (fboundp 'menu-bar-mode)
(menu-bar-mode -1))
(when (fboundp 'set-fringe-mode)
(set-fringe-mode 10))
(set-frame-parameter (selected-frame) 'fullscreen 'maximized)
(add-to-list 'default-frame-alist '(fullscreen . maximized))
(defconst IS-MAC (eq system-type 'darwin)
"If the host is running MacOS return true")
(defconst IS-LINUX (eq system-type 'gnu/linux)
"If the host is running Linux return true")
(defconst IS-WINDOWS (memq system-type '(cygwin windows-nt ms-dos))
"If the host is running Windows return true")
(defconst IS-BSD (or IS-MAC (eq system-type 'berkeley-unix))
"If the host is running BSD return true")
(setq straight-use-package-by-default t)
(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)
The auto-package-update package helps us keep our Emacs packages up to date! It will prompt you after a certain number of days either at startup or at a specific time of day to remind you to update your packages.
You can also use M-x auto-package-update-now
to update right now!
(use-package auto-package-update
:custom
(auto-package-update-interval 7)
(auto-package-update-prompt-before-update nil)
(auto-package-update-hide-results t)
:config
(auto-package-update-maybe)
(auto-package-update-at-time "09:00"))
(use-package no-littering
:demand t
:config
(setq auto-save-file-name-transforms
`((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))
(setq custom-file (no-littering-expand-etc-file-name "custom.el")))
(use-package general
:demand t
:config
(progn
(general-evil-setup t)
(general-auto-unbind-keys)
(general-create-definer leader-map
:keymaps 'override
:states '(insert emacs normal hybrid motion visual operator)
:global-prefix "C-c"
:non-normal-prefix "M-SPC"
:prefix "SPC")
(general-create-definer local-leader-map
:keymaps 'override
:states '(insert emacs normal hybrid motion visual operator)
:global-prefix "C-c m"
:non-normal-prefix "M-SPC m"
:prefix "SPC m")))
(use-package emacs
:demand t
:straight nil
:preface
;; Fonts and Text ;;
(defvar me/default-font-size 160)
(defvar me/default-variable-font-size 160)
(defun me/reset-text-size ()
(interactive)
(text-scale-set 0))
;; Transparency ;;
(defvar me/frame-transparency '(95 . 95))
;; Buffers ;;
(defun me/alternate-buffer ()
"Go to previous buffer"
(interactive)
(switch-to-buffer (other-buffer)))
(defun me/set-default-line-length-to (line-length)
"Set the default line length to LINE-LENGTH."
(setq-default fill-column line-length))
;; Saving ;;
(defun me/save-all-unsaved ()
"Save all unsaved files. no ask."
(interactive)
(save-some-buffers t))
;; Utility ;;
(defun me/create-dir-if-not-exists ()
"Offer to create directory when it doesn't exist"
(when buffer-file-name
(let ((dir (file-name-directory buffer-file-name)))
(when (and (not (file-exists-p dir))
(y-or-n-p (format "Directory %s does not exist. Create it?" dir)))
(make-directory dir t)))))
(defun me/open-config ()
"Open configuration file"
(interactive)
(find-file (expand-file-name (concat user-emacs-directory "README.org"))))
(defun me/reload-emacs-config ()
(interactive)
(load-file (expand-file-name (concat user-emacs-directory "init.el"))))
;; Scrolling
(defun me/scroll-half-page (direction)
"Scrolls half page up if `direction' is non-nil, otherwise will scroll half page down."
(let ((opos (cdr (nth 6 (posn-at-point)))))
;; opos = original position line relative to window
(move-to-window-line nil) ;; Move cursor to middle line
(if direction
(recenter-top-bottom -1) ;; Current line becomes last
(recenter-top-bottom 0)) ;; Current line becomes first
(move-to-window-line opos))) ;; Restore cursor/point position
(defun me/scroll-half-page-down ()
"Scrolls exactly half page down keeping cursor/point position."
(interactive)
(me/scroll-half-page nil))
(defun me/scroll-half-page-up ()
"Scrolls exactly half page up keeping cursor/point position."
(interactive)
(me/scroll-half-page t))
(defun me/buffer-to-side-window ()
"Place the current buffer in the side window at the bottom."
(interactive)
(let ((buf (current-buffer)))
(display-buffer-in-side-window
buf '((window-height . 0.25)
(side . bottom)
(slot . -1)
(window-parameters . (no-delete-other-windows . t))))
(delete-window)))
(defun me/quit-window-force ()
(interactive)
(quit-window t))
:config
(progn
;; Startup ;;
(setq inhibit-startup-message t)
(setq initial-scratch-message nil)
;; Bells and Ringers ;;
(setq visible-bell nil)
(setq ring-bell-function 'ignore)
;; History and persistence ;;
(require 'recentf)
(add-to-list 'recentf-exclude no-littering-var-directory)
(add-to-list 'recentf-exclude no-littering-etc-directory)
(setq recentf-max-menu-items 40)
(setq recentf-max-saved-items 250)
(setq save-interprogram-paste-before-kill t)
(setq initial-buffer-choice nil)
;; (require 'desktop)
;; (customize-set-variable 'desktop-save 't)
;; (desktop-save-mode 1)
(recentf-mode 1)
(with-eval-after-load 'no-littering
(add-to-list 'recentf-exclude no-littering-etc-directory)
(add-to-list 'recentf-exclude no-littering-var-directory))
(save-place-mode 1)
(winner-mode 1)
(global-auto-revert-mode t)
;; Completion ;;
(setq read-file-name-completion-ignore-case t
read-buffer-completion-ignore-case t
completion-ignore-case t
completion-cycle-threshold 2
tab-always-indent t
tab-width 4)
(setq-default indent-tabs-mode nil)
(electric-pair-mode t)
;; Use `consult-completion-in-region' if Vertico is enabled.
;; Otherwise use the default `completion--in-region' function.
;; (setq completion-in-region-function
;; (lambda (&rest args)
;; (apply (if vertico-mode
;; #'consult-completion-in-region
;; #'completion--in-region)
;; args)))
;; Emacs 28: Hide commands in M-x which do not work in the current mode.
;; Vertico commands are hidden in normal buffers.
(setq read-extended-command-predicate
#'command-completion-default-include-p)
;; Minibuffer ;;
;; 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)
(general-def minibuffer-local-map
"C-S-p" 'yank)
;; Enable recursive minibuffers
(setq enable-recursive-minibuffers t)
;; File Encoding ;;
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(set-file-name-coding-system 'utf-8)
(set-clipboard-coding-system 'utf-8)
(set-buffer-file-coding-system 'utf-8)
;; Fonts ;;
(cond (IS-MAC (setq me/default-font-size 200) (setq me/default-variable-font-size 200))
(IS-WINDOWS (setq me/default-font-size 90) (setq me/default-variable-font-size 90)))
(set-face-attribute 'default nil :font "MonoLisa Custom" :height me/default-font-size)
(set-face-attribute 'fixed-pitch nil :font "MonoLisa Custom" :height me/default-font-size)
(set-face-attribute 'variable-pitch nil :font "Cantarell" :height me/default-variable-font-size :weight 'regular)
(global-font-lock-mode t)
;; Transparency ;;
(set-frame-parameter (selected-frame) 'alpha me/frame-transparency)
(add-to-list 'default-frame-alist `(alpha . ,me/frame-transparency))
;; Loading ;;
(setq load-prefer-newer t)
;; Saving ;;
;; Auto save
(setq after-focus-change-function 'me/save-all-unsaved)
(add-hook 'focus-out-hook 'me/save-all-unsaved)
;; Remove whitespace on save
(add-hook 'before-save-hook 'delete-trailing-whitespace)
;; Make file executable if it's a script on save
(add-hook 'after-save-hook
'executable-make-buffer-file-executable-if-script-p)
;; Create directory if it doesn't exist
(add-hook 'before-save-hook 'me/create-dir-if-not-exists)
;; Version Control ;;
(setq vc-follow-symlinks t)
;; Directories ;;
(setq default-directory "~/")
;; Prog Mode ;;
(add-hook 'prog-mode-hook 'subword-mode)
;; Formatting ;;
(setq sentence-end-double-space nil)
;; (me/set-default-line-length-to 80)
;; Behavior ;;
(setq require-final-newline t)
(setq show-paren-delay 0.0)
(global-set-key [remap quit-window] #'me/quit-window-force)
;; Confirmations
(setq confirm-kill-emacs 'y-or-n-p)
(fset 'yes-or-no-p 'y-or-n-p)
;; Modes
(transient-mark-mode 1)
(delete-selection-mode 1)
(show-paren-mode 1)
(column-number-mode 0)
;; Line Numbers
;; Disable line numbers for some modes
(dolist (mode '(org-mode-hook
term-mode-hook
shell-mode-hook
treemacs-mode-hook
eshell-mode-hook
vterm-mode-hook
dired-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode 0))))
(global-display-line-numbers-mode 1)
;; Frames
(setq ns-pop-up-frames nil)
;; Windows
;; Attempt to always use the same window size and stop resizing stuff weirdly
(customize-set-variable 'display-buffer-base-action
'((display-buffer-reuse-window display-buffer-same-window)
(reusable-frames . t)))
(customize-set-variable 'even-window-sizes nil)
(setq resize-mini-windows t)
;; Mouse
(setq mouse-yank-at-point t)
;; Apropos
(setq apropos-do-all t)
;; Tab bar ;;
;; (tab-bar-mode t)
;; (customize-set-variable 'tab-bar-new-tab-choice '"*scratch*")
;; (customize-set-variable 'tab-bar-show 't)
;; Mac OS ;;
(when IS-MAC
(setq mac-command-modifier 'control
mac-option-modifier 'meta
mac-control-modifier 'super
mac-right-command-modifier 'control
mac-right-option-modifier 'meta
ns-function-modifier 'hyper))
;; Keybindings ;;
;; Prefixes
(leader-map
"" '(nil :which-key "my lieutenant general prefix")
"b" '(:ignore t :wk "buffers")
"D" '(:ignore t :wk "debug")
"e" '(:ignore t :wk "edit")
"o" '(:ignore t :wk "org")
"f" '(:ignore t :wk "files")
"fe" '(:ignore t :wk "emacs")
"g" '(:ignore t :wk "git")
"s" '(:ignore t :wk "search")
"x" '(:ignore t :wk "execute")
"T" '(:ignore t :wk "toggles"))
(local-leader-map
"" '(nil :which-key "major mode"))
;; Sim Keys
(leader-map
"," (general-simulate-key "C-c")
"C" (general-simulate-key "C-x")
"M" (general-simulate-key "C-c C-x"))
;; Maps
(leader-map
"h" '(:keymap help-map :wk "help"))
;; Base
(leader-map
";" 'execute-extended-command
":" 'eval-expression
"O" 'other-window-prefix
"X" '((lambda () (interactive) (switch-to-buffer "*scratch*")) :wk "scratch")
"br" 'rename-buffer
"bd" 'bury-buffer
"bp" 'me/alternate-buffer
"bk" 'kill-this-buffer
"bK" 'kill-some-buffers
"B" 'ibuffer
"ea" 'align-regexp
"eA" 'align
"er" 'query-replace
"fB" 'bookmark-set
"ff" 'find-file
"fs" 'save-buffer
"fd" 'dired
"fS" 'me/save-all-unsaved
"fee" 'me/open-config
"fer" 'me/reload-emacs-config
"feq" 'save-buffers-kill-emacs
"feQ" 'kill-emacs
"xp" 'check-parens
"xe" 'eval-last-sexp
"xb" 'eval-buffer)
(leader-map "C-h" '(which-key-C-h-dispatch :wk t))
(local-leader-map "C-h" '(which-key-C-h-dispatch :wk t))
(general-def
"C-v" 'me/scroll-half-page-down
"M-v" 'me/scroll-half-page-up)
;; Remaps
(general-def with-editor-mode-map
[remap save-buffer] 'with-editor-finish)
))
(use-package ediff
:straight nil
:config
(progn
(setq ediff-diff-options "")
(setq ediff-custom-diff-options "-u")
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
(setq ediff-split-window-function 'split-window-vertically)))
(use-package smerge-mode
:straight nil
:init (setq smerge-command-prefix "")
:config
(progn
(with-eval-after-load 'hydra
(defhydra hydra/smerge
(:color pink :hint nil :post (smerge-auto-leave))
"
^Move^ ^Keep^ ^Diff^ ^Other^
^^-----------^^-------------------^^---------------------^^-------
_n_ext _b_ase _<_: upper/base _C_ombine
_p_rev _u_pper _=_: upper/lower _r_esolve
^^ _l_ower _>_: base/lower _k_ill current
^^ _a_ll _R_efine
^^ _RET_: current _E_diff
"
("n" smerge-next)
("p" smerge-prev)
("b" smerge-keep-base)
("u" smerge-keep-upper)
("l" smerge-keep-lower)
("a" smerge-keep-all)
("RET" smerge-keep-current)
("\C-m" smerge-keep-current)
("<" smerge-diff-base-upper)
("=" smerge-diff-upper-lower)
(">" smerge-diff-base-lower)
("R" smerge-refine)
("E" smerge-ediff)
("C" smerge-combine-with-next)
("r" smerge-resolve)
("k" smerge-kill-current)
("q" nil "cancel" :color blue))
(with-eval-after-load 'general
(leader-map smerge-mode-map
"gm" 'hydra/smerge/body)))))
(use-package dired
:straight nil
:commands (dired dired-jump)
:preface
:general
(general-def
"C-x C-j" 'dired-jump)
:custom ((dired-listing-switches "-agho --group-directories-first"))
:hook (dired-mode . dired-hide-details-mode)
:config
(general-def '(motion visual normal emacs) dired-mode-map
"l" 'dired-open-file
"L" 'dired-view-file
"h" 'dired-up-directory)
(setq dired-dwim-target t)
(setq dired-kill-when-opening-new-dired-buffer t)
;; MacOS ;;
(when IS-MAC
(setq dired-use-ls-dired t
insert-directory-program "/opt/homebrew/bin/gls"
dired-listing-switches "-aBhl --group-directories-first")))
(use-package dired-single
:commands (dired dired-jump))
(use-package all-the-icons-dired
:after all-the-icons
:hook (dired-mode . all-the-icons-dired-mode))
(use-package dired-open
:commands (dired dired-jump)
:config
(setq dired-open-extensions '(("png" . "feh")
("mkv" . "mpv"))))
(use-package dired-hide-dotfiles
;;:hook (dired-mode . dired-hide-dotfiles-mode)
:config
(with-eval-after-load 'evil-collection
(evil-collection-define-key 'normal 'dired-mode-map
"C-S-h" 'dired-hide-dotfiles-mode)))
(use-package doom-themes
:init
(load-theme 'doom-tokyo-night t)
:config
(progn
(setq doom-themes-enable-bold t
doom-themes-enable-italic t)
(setq doom-themes-treemacs-theme "doom-tokyo-night")
(with-eval-after-load 'treemacs
(doom-themes-treemacs-config))
(with-eval-after-load 'org
(doom-themes-org-config))))
(use-package solaire-mode
:config
(solaire-global-mode))
(use-package exec-path-from-shell
:if IS-MAC
:config
(exec-path-from-shell-initialize))
(use-package dash
:commands (global-dash-fontify-mode)
:init (global-dash-fontify-mode)
:config (dash-register-info-lookup))
The long lost Emacs string manipulation library.
(use-package s)
(use-package posframe
:demand t)
(use-package which-key
:init (which-key-mode)
:diminish which-key-mode
:after evil
:demand t
:config
(progn
(setq which-key-allow-evil-operators t)
(setq which-key-sort-order 'which-key-key-order-alpha)
(setq which-key-use-C-h-commands nil)
(setq which-key-idle-delay 0.5)))
(use-package evil
:demand t
:preface
(defun me/evil-record-macro ()
(interactive)
(if buffer-read-only
(quit-window)
(call-interactively 'evil-record-macro)))
(defun me/save-and-kill-this-buffer ()
(interactive)
(save-buffer)
(kill-this-buffer))
:init
(progn
(setq evil-want-integration t
evil-want-keybinding nil
evil-want-C-u-scroll t
evil-want-C-i-jump t
evil-respect-visual-line-mode t
evil-undo-system 'undo-tree))
:config
(progn
(evil-mode 1)
(evil-set-initial-state 'messages-buffer-mode 'normal)
(evil-set-initial-state 'dashboard-mode 'normal)
(with-eval-after-load 'general
(imap "C-n" nil
"C-p" nil)
(nmap "R" 'evil-replace-state
"q" 'me/evil-record-macro
"g ?" 'nil
"gu" 'universal-argument
"gw" 'other-window-prefix)
(imap "C-g" 'evil-normal-state
"C-u" 'universal-argument)
(vmap "gu" 'universal-argument)
(mmap "j" 'evil-next-visual-line
"k" 'evil-previous-visual-line
"L" 'evil-end-of-line-or-visual-line
"H" 'evil-first-non-blank-of-visual-line
"gu" 'universal-argument)
(setq me/window-map (cons 'keymap evil-window-map))
(general-def me/window-map
"u" 'winner-undo
"U" 'winner-redo
"f" 'other-frame)
(leader-map "w" '(:keymap me/window-map :wk "windows"))
(evil-ex-define-cmd "q" #'kill-this-buffer)
(evil-ex-define-cmd "wq" #'me/save-and-kill-this-buffer)
(imap "j"
(general-key-dispatch 'self-insert-command
:timeout 0.15
"k" 'evil-normal-state)))))
(use-package evil-collection
:after evil
:diminish evil-collection-unimpaired-mode
:config
(evil-collection-init)
(with-eval-after-load 'general
(nmap
"go" 'evil-collection-unimpaired-insert-newline-below
"gO" 'evil-collection-unimpaired-insert-newline-above
"gp" 'evil-collection-unimpaired-paste-below
"gP" 'evil-collection-unimpaired-paste-above)))
(use-package evil-org
:after org
:config
(progn
(add-hook 'org-mode-hook 'evil-org-mode)
(add-hook 'evil-org-mode-hook
(lambda () (evil-org-set-key-theme)))))
(use-package evil-commentary
:after evil
:config
(evil-commentary-mode))
(use-package evil-nerd-commenter
:after evil
:config
(evilnc-default-hotkeys nil t))
(use-package evil-matchit
:after evil
:config
(global-evil-matchit-mode 1))
(use-package evil-goggles
:after evil
:config
(progn
(setq evil-goggles-pulse t)
(setq evil-goggles-duration 0.4)
(setq evil-goggles-blocking-duration 0.1)
(evil-goggles-mode)
(evil-goggles-use-diff-faces)))
(use-package evil-surround
:after evil
:config
(global-evil-surround-mode 1))
(use-package evil-owl
:config
(setq evil-owl-display-method 'posframe
evil-owl-extra-posframe-args '(:width 50 :height 20)
evil-owl-max-string-length 50)
(evil-owl-mode))
(use-package evil-mc
:after evil
:config
(progn
(evil-define-local-var evil-mc-custom-paused nil
"Paused functionality when there are multiple cursors active.")
(defun evil-mc-pause-smartchr-for-mode (mode)
"Temporarily disables the smartchr keys for MODE."
(let ((m-mode (if (atom mode) mode (car mode)))
(s-mode (if (atom mode) mode (cdr mode))))
(let ((init (intern (concat "smartchr/init-" (symbol-name s-mode))))
(undo (intern (concat "smartchr/undo-" (symbol-name s-mode)))))
(when (eq major-mode m-mode)
(funcall undo)
(push `(lambda () (,init)) evil-mc-custom-paused)))))
(defun evil-mc-before-cursors-setup-hook ()
"Hook to run before any cursor is created.
Can be used to temporarily disable any functionality that doesn't
play well with `evil-mc'."
(mapc 'evil-mc-pause-smartchr-for-mode
'(web-mode js2-mode java-mode (enh-ruby-mode . ruby-mode) css-mode))
(when (boundp 'whitespace-cleanup-disabled)
(setq whitespace-cleanup-disabled t)
(push (lambda () (setq whitespace-cleanup-disabled nil)) evil-mc-custom-paused)))
(defun evil-mc-after-cursors-teardown-hook ()
"Hook to run after all cursors are deleted."
(dolist (fn evil-mc-custom-paused) (funcall fn))
(setq evil-mc-custom-paused nil))
(add-hook 'evil-mc-before-cursors-created 'evil-mc-before-cursors-setup-hook)
(add-hook 'evil-mc-after-cursors-deleted 'evil-mc-after-cursors-teardown-hook)
(defvar evil-mc-mode-line-prefix "ⓜ"
"Override of the default mode line string for `evil-mc-mode'.")
(global-evil-mc-mode 1)))
(use-package undo-tree
:diminish undo-tree-mode
:init
(global-undo-tree-mode)
:config
(mmap "U" 'undo-tree-visualize))
(use-package projectile
:ensure t
:init
(setq projectile-project-search-path '("~/Code/"))
(projectile-mode +1)
:config
(progn
(leader-map
"p" '(:keymap projectile-command-map :wk "projects"))
(with-eval-after-load 'consult
(general-def projectile-command-map
"b" 'consult-project-buffer))))
(use-package avy
:after evil
:config
(progn
(general-def :states '(normal visual motion)
"gf" 'avy-goto-char-timer
"gF" 'avy-resume)
(general-def :states '(normal visual motion insert emacs)
"C-f" 'avy-goto-char-timer
"C-S-f" 'avy-resume)
(setq avy-timeout-seconds 0.2)))
NOTE: The first time you load your configuration on a new machine, you’ll need to run `M-x all-the-icons-install-fonts` so that mode line icons display correctly.
(use-package all-the-icons)
(use-package all-the-icons-completion
:after (all-the-icons marginalia)
:hook (marginalia-mode . all-the-icons-completion-marginalia-setup)
:init
(all-the-icons-completion-mode))
(use-package all-the-icons-dired
:after all-the-icons)
(use-package vertico
:init (vertico-mode)
:config
(progn
(general-def vertico-map
"C-d" 'vertico-scroll-up
"C-u" 'vertico-scroll-down
"C-v" 'vertico-scroll-up
"M-v" 'vertico-scroll-down
"C-j" 'vertico-next
"C-J" 'vertico-next-group
"C-k" 'vertico-previous
"C-K" 'vertico-previous-group
"M-RET" 'minibuffer-force-complete-and-exit
"M-TAB" 'minibuffer-complete
"C-RET" 'vertico-exit-input
"C-<return>" 'vertico-exit-input)
(advice-add #'vertico--format-candidate :around
(lambda (orig cand prefix suffix index _start)
(setq cand (funcall orig cand prefix suffix index _start))
(concat
(if (= vertico--index index)
(propertize "» " 'face 'vertico-current)
" ")
cand)))))
(use-package vertico-directory
:after vertico
:straight nil
:load-path "straight/repos/vertico/extensions/"
:bind
(:map vertico-map
("RET" . vertico-directory-enter)
("DEL" . vertico-directory-delete-char)
("M-DEL" . vertico-directory-delete-word))
:hook (rfn-eshadow-update-overlay . vertico-directory-tidy))
(use-package vertico-posframe
:disabled t
:config
(setq vertico-posframe-truncate-lines nil)
(setq vertico-posframe-min-width 80)
(setq vertico-posframe-poshandler 'posframe-poshandler-window-top-center)
(vertico-posframe-mode))
(use-package savehist
:init
(savehist-mode))
(use-package consult
:general
(leader-map
"SPC" 'consult-buffer
"so" 'consult-outline
"sm" 'consult-mark
"sl" 'consult-line
"sL" 'consult-line-multi
"sM" 'consult-global-map
"sr" 'consult-ripgrep
"fF" 'consult-recent-file
"fb" 'consult-bookmark
"bb" 'consult-buffer
"bo" 'consult-buffer-other-window
"bf" 'consult-buffer-other-frame
"bm" 'consult-mode-command
"bh" 'consult-history
"xc" 'consult-complex-command
"xk" 'consult-kmacro)
(general-def
"C-x b" 'consult-buffer
"C-x 4 b" 'consult-buffer-other-window
"C-x 5 b" 'consult-buffer-other-frame
"C-x M-:" 'consult-complex-command
"C-x r b" 'consult-bookmark
"C-x p b" 'consult-project-buffer
"M-#" 'consult-register-load
"M-'" 'consult-register-store
"C-M-#" 'consult-register
"M-y" 'consult-yank-pop
"<help> a" 'consult-apropos
"M-g e" 'consult-compile-error
"M-g f" 'consult-flymake
"M-g g" 'consult-goto-line
"M-g M-g" 'consult-goto-line
"M-g o" 'consult-outline
"M-g m" 'consult-mark
"M-g k" 'consult-global-mark
"M-g i" 'consult-imenu
"M-g I" 'consult-imenu-multi
"M-s d" 'consult-find
"M-s D" 'consult-locate
"M-s g" 'consult-grep
"M-s G" 'consult-git-grep
"M-s r" 'consult-ripgrep
"M-s L" 'consult-line-multi
"M-s m" 'consult-multi-occur
"M-s k" 'consult-keep-lines
"M-s u" 'consult-focus-lines
"M-s e" 'consult-isearch-history)
(general-def
"C-s" 'consult-line
"C-S-s" 'consult-line-multi)
(general-def isearch-mode-map
"M-e" 'consult-isearch-history
"M-s e" 'consult-isearch-history
"C-s" 'consult-line
"C-S-s" 'consult-line-multi)
(general-def minibuffer-local-map
"M-s" 'consult-history
"M-r" 'consult-history)
:init
;; Optionally configure the register formatting. This improves the register
;; preview for `consult-register', `consult-register-load',
;; `consult-register-store' and the Emacs built-ins.
(setq register-preview-delay 0.5
register-preview-function #'consult-register-format)
;; Optionally tweak the register preview window.
;; This adds thin lines, sorting and hides the mode line of the window.
(advice-add #'register-preview :override #'consult-register-window)
;; Use Consult to select xref locations with preview
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
:config
(progn
(consult-customize
consult-theme
:preview-key '(:debounce 0.2 any)
consult-ripgrep consult-git-grep consult-grep
consult-bookmark consult-recent-file consult-xref
consult--source-bookmark consult--source-recent-file
consult--source-project-recent-file
:preview-key (kbd "M-."))
(defvar-local consult-toggle-preview-orig nil)
(defun consult-toggle-preview ()
"Command to enable/disable preview."
(interactive)
(if consult-toggle-preview-orig
(setq consult--preview-function consult-toggle-preview-orig
consult-toggle-preview-orig nil)
(setq consult-toggle-preview-orig consult--preview-function
consult--preview-function #'ignore)))
(general-def vertico-map
"M-p" 'consult-toggle-preview)
(setq consult-narrow-key "<")
(setq completion-in-region-function
(lambda (&rest args)
(apply (if vertico-mode
#'consult-completion-in-region
#'completion--in-region)
args)))))
(use-package orderless
:config
(defvar +orderless-dispatch-alist
'((?% . char-fold-to-regexp)
(?! . orderless-without-literal)
(?`. orderless-initialism)
(?= . orderless-literal)
(?~ . orderless-flex)))
;; Recognizes the following patterns:
;; * ~flex flex~
;; * =literal literal=
;; * %char-fold char-fold%
;; * `initialism initialism`
;; * !without-literal without-literal!
;; * .ext (file extension)
;; * regexp$ (regexp matching at end)
(defun +orderless-dispatch (pattern index _total)
(cond
;; Ensure that $ works with Consult commands, which add disambiguation suffixes
((string-suffix-p "$" pattern)
`(orderless-regexp . ,(concat (substring pattern 0 -1) "[\x200000-\x300000]*$")))
;; File extensions
((and
;; Completing filename or eshell
(or minibuffer-completing-file-name
(derived-mode-p 'eshell-mode))
;; File extension
(string-match-p "\\`\\.." pattern))
`(orderless-regexp . ,(concat "\\." (substring pattern 1) "[\x200000-\x300000]*$")))
;; Ignore single !
((string= "!" pattern) `(orderless-literal . ""))
;; Prefix and suffix
((if-let (x (assq (aref pattern 0) +orderless-dispatch-alist))
(cons (cdr x) (substring pattern 1))
(when-let (x (assq (aref pattern (1- (length pattern))) +orderless-dispatch-alist))
(cons (cdr x) (substring pattern 0 -1)))))))
;; Define orderless style with initialism by default
(orderless-define-completion-style +orderless-with-initialism
(orderless-matching-styles '(orderless-initialism orderless-literal orderless-regexp)))
;; You may want to combine the `orderless` style with `substring` and/or `basic`.
;; There are many details to consider, but the following configurations all work well.
;; Personally I (@minad) use option 3 currently. Also note that you may want to configure
;; special styles for special completion categories, e.g., partial-completion for files.
;;
;; 1. (setq completion-styles '(orderless))
;; This configuration results in a very coherent completion experience,
;; since orderless is used always and exclusively. But it may not work
;; in all scenarios. Prefix expansion with TAB is not possible.
;;
;; 2. (setq completion-styles '(substring orderless))
;; By trying substring before orderless, TAB expansion is possible.
;; The downside is that you can observe the switch from substring to orderless
;; during completion, less coherent.
;;
;; 3. (setq completion-styles '(orderless basic))
;; Certain dynamic completion tables (completion-table-dynamic)
;; do not work properly with orderless. One can add basic as a fallback.
;; Basic will only be used when orderless fails, which happens only for
;; these special tables.
;;
;; 4. (setq completion-styles '(substring orderless basic))
;; Combine substring, orderless and basic.
;;
(setq completion-styles '(orderless basic)
completion-category-defaults nil
;;; Enable partial-completion for files.
;;; Either give orderless precedence or partial-completion.
;;; Note that completion-category-overrides is not really an override,
;;; but rather prepended to the default completion-styles.
;; completion-category-overrides '((file (styles orderless partial-completion))) ;; orderless is tried first
completion-category-overrides '((file (styles partial-completion)) ;; partial-completion is tried first
(consult-multi (styles orderless+initialism))
;; enable initialism by default for symbols
(command (styles +orderless-with-initialism))
(variable (styles +orderless-with-initialism))
(symbol (styles +orderless-with-initialism)))
orderless-component-separator #'orderless-escapable-split-on-space ;; allow escaping space with backslash!
orderless-style-dispatchers '(+orderless-dispatch)))
(use-package marginalia
:bind (("M-A" . marginalia-cycle)
:map minibuffer-local-map
("M-A" . marginalia-cycle))
:custom
(marginalia-max-relative-age 0)
(marginalia-align 'left)
:init
(marginalia-mode)
:config
(add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup))
(use-package embark
:general
(general-def
"C-," 'embark-act
"C-;" 'embark-dwim
"C-h B" 'embark-bindings)
:init
;; Optionally replace the key help with a completing-read interface
(setq prefix-help-command #'embark-prefix-help-command)
:config
;; Hide the mode line of the Embark live/completions buffers
(add-to-list 'display-buffer-alist
'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
nil
(window-parameters (mode-line-format . none))))
(defun +embark-live-vertico ()
"Shrink Vertico minibuffer when `embark-live' is active."
(when-let (win (and (string-prefix-p "*Embark Live" (buffer-name))
(active-minibuffer-window)))
(with-selected-window win
(when (and (bound-and-true-p vertico--input)
(fboundp 'vertico-multiform-unobtrusive))
(vertico-multiform-unobtrusive)))))
(add-hook 'embark-collect-mode-hook #'+embark-live-vertico))
(use-package embark-consult
:after (embark consult)
:demand t ; only necessary if you have the hook below
;; if you want to have consult previews as you move around an
;; auto-updating embark collect buffer
:hook
(embark-collect-mode . consult-preview-at-point-mode))
(use-package company
:delight
:config
(imap company-active-map
"TAB" 'company-complete-common-or-cycle
"C-d" 'company-show-doc-buffer
"<backtab>" '(lambda () (interactive) (company-complete-common-or-cycle -1)))
(imap text-mode-map
"C-." 'company-complete)
(imap prog-mode-map
"C-." 'company-complete)
(setq completion-at-point-functions '(company-complete))
(with-eval-after-load 'orderless
(setq orderless-component-separator "[ !]")
(defun just-one-face (fn &rest args)
(let ((orderless-match-faces [completions-common-part]))
(apply fn args)))
(advice-add 'company-capf--candidates :around #'just-one-face))
(setq company-require-match nil)
(setq company-tooltip-limit 5)
(setq company-show-numbers t)
(setq company-selection-wrap-around t)
(setq company-dabbrev-downcase nil)
(setq company-idle-delay 0.2)
(setq company-echo-delay 0)
(setq company-backends '(company-capf
company-keywords
company-semantic
company-elisp
company-files
company-dabbrev
company-etags
company-cmake
company-ispell
company-yasnippet))
(global-company-mode))
(use-package company-posframe
:config
;; (push '(company-posframe-mode . nil)
;; desktop-minor-mode-table)
(setq company-tooltip-minimum-width 40)
(company-posframe-mode 1))
(use-package prescient)
(use-package company-prescient
:after (company prescient)
:config
(company-prescient-mode))
(use-package helpful
:after evil
:demand t
:commands (helpful-callable helpful-variable helpful-command helpful-key helpful-at-point)
:bind
("H-d" . helpful-at-point)
([remap describe-function] . helpful-function)
([remap describe-command] . helpful-command)
([remap describe-variable] . helpful-variable)
([remap describe-key] . helpful-key)
(:map evil-motion-state-map
("K" . helpful-at-point))
:config
(general-def '(normal motion) helpful-mode-map
"q" 'kill-this-buffer)
(leader-map
"bH" 'helpful-kill-buffers))
(use-package hydra
:config
(progn
(defhydra me/hydra-evil-windows (:hint nil
:pre (winner-mode 1)
:post (redraw-display))
"
Movement & RESIZE^^^^
^ ^ _k_ ^ ^ _f__d_ file/dired _o_nly win ^Move _C-k_
_h_ ^✜^ _l_ _b__B_ buffer/alt _x_ Delete this win ^_C-w_ _C-j_
^ ^ _j_ ^ ^ _u_ _r_ undo/redo _s_plit _v_ertically ^_C-h_ _C-l_"
;; For some reason the evil
;; commands behave better than
;; the emacs ones
("j" evil-window-down)
("k" evil-window-up)
("l" evil-window-right)
("h" evil-window-left)
("J" evil-window-increase-height)
("K" evil-window-decrease-height)
("L" evil-window-increase-width)
("H" evil-window-decrease-width)
("u" winner-undo)
("r" (progn (winner-undo) (setq this-command 'winner-undo)))
("d" dired :color blue)
("f" find-file)
("b" consult-buffer :color blue)
("B" me/alternate-buffer)
("o" delete-other-windows :color blue)
("x" delete-window)
("s" split-window-horizontally)
("v" split-window-vertically)
("C-w" evil-window-next :color blue)
("C-k" evil-window-move-very-top :color blue)
("C-j" evil-window-move-very-bottom :color blue)
("C-h" evil-window-move-far-left :color blue)
("C-l" evil-window-move-far-right :color blue)
("SPC" balance-windows :color blue))
(leader-map "W" 'me/hydra-evil-windows/body)))
(use-package origami
:config
(global-origami-mode))
(use-package org
:demand t
:preface
;; Functions ;;
(defun me/org-mode-initial-setup ()
(setq org-indent-mode-turns-on-hiding-stars t)
(setq org-tags-column 0)
(setq org-indent-indentation-per-level 2)
(org-indent-mode)
(variable-pitch-mode 1)
(visual-line-mode 1))
(defun me/org-babel-tangle-config ()
(when (string-equal (file-name-directory (buffer-file-name))
(expand-file-name user-emacs-directory))
;; Dynamic scoping to the rescue
(let ((org-confirm-babel-evaluate nil))
(org-babel-tangle))))
;; Files ;;
(defconst me/org-emacs-config-file (concat user-emacs-directory "README.org"))
:config
(progn
;; Keybinds ;;
;; Org Mode Keybinds
(general-unbind org-mode-map
"C-c ?" nil)
(local-leader-map org-mode-map
"p" 'org-set-property
"s" '(:ignore t :wk "search")
"T" '(:ignore t :wk "tables")
"Ti" 'org-table-field-info
"i" '(:ignore t :wk "insert")
"it" 'org-set-tags-command
"is" 'org-insert-structure-template
"e" '(:ignore t :wk "edit")
"es" 'org-sort
"sm" 'org-match-sparse-tree
"sM" 'org-tags-sparse-tree
"st" 'org-sparse-tree)
(general-def '(motion normal) org-mode-map
"gt" 'org-toggle-heading
"gT" 'org-ctrl-c-minus)
(defun me/org-insert-subheading ()
(interactive)
(progn
(call-interactively #'org-insert-subheading)
(call-interactively #'evil-insert-state)))
(general-def '(motion normal) org-mode-map
"M-RET" #'me/org-insert-subheading
"M-<return>" #'me/org-insert-subheading)
;; Consult
(with-eval-after-load 'consult
(local-leader-map org-mode-map
"so" 'consult-outline
"ss" 'consult-org-heading)
(leader-map org-mode-map
"ss" 'consult-org-heading))
;; Org Src Keybinds
(general-def org-src-mode-map
[remap save-buffer] 'org-edit-src-exit)
(local-leader-map org-src-mode-map
"s" 'org-edit-src-exit)
;; Hooks ;;
(add-hook 'org-mode-hook 'me/org-mode-initial-setup)
(add-hook 'org-src-mode-hook 'evil-normalize-keymaps)
;; Visuals ;;
(setq org-ellipsis " ▼ ")
(setq org-pretty-entities t)
(setq org-fontify-todo-headline t)
;; Source Editing ;;
(setq org-edit-src-turn-on-auto-save t)
(setq org-src-window-setup 'current-window)
(push '("conf-unix" . conf-unix) org-src-lang-modes)
;; Fix coming out of src editing into insert mode
(defun me/org-edit-special ()
(interactive)
(progn
(call-interactively #'evil-normal-state)
(call-interactively #'org-edit-special)))
(general-def org-mode-map
[remap org-edit-special] #'me/org-edit-special)
;; Fonts ;;
;; Replace list hyphen with dot
(font-lock-add-keywords 'org-mode
'(("^ *\\([-]\\) "
(0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))
(dolist (face '((org-level-1 . 1.2)
(org-level-2 . 1.1)
(org-level-3 . 1.05)
(org-level-4 . 1.0)
(org-level-5 . 1.0)
(org-level-6 . 1.0)
(org-level-7 . 1.0)
(org-level-8 . 1.0))))
;; Ensure that anything that should be fixed-pitch in Org files appears that way
(set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch)
(set-face-attribute 'org-table nil :inherit 'fixed-pitch)
(set-face-attribute 'org-formula nil :inherit 'fixed-pitch)
(set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch)
(set-face-attribute 'line-number nil :inherit 'fixed-pitch)
(set-face-attribute 'line-number-current-line nil :inherit 'fixed-pitch)
(set-face-attribute 'org-hide nil :inherit 'fixed-pitch)
;; Open links in current window
(setf (cdr (assoc 'file org-link-frame-setup)) 'find-file)
(setq org-cycle-separator-lines 0)
;; Babel ;;
(setq org-confirm-babel-evaluate nil)
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)))
;; Automatically tangle our Emacs.org config file when we save it
(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'me/org-babel-tangle-config)))))
(use-package org-contrib
:after org)
(use-package org-modern
:after org
:init
(setq org-auto-align-tags nil
org-tags-column 0
org-catch-invisible-edits 'show-and-error
org-insert-heading-respect-content t)
:config
(set-face-attribute 'org-modern-symbol nil :family "Fira Code Retina")
(setq org-modern-checkbox nil)
(setq org-modern-keyword "‣")
(global-org-modern-mode))
(use-package visual-fill-column
:preface
(defun me/org-mode-visual-fill ()
(setq visual-fill-column-width 100
visual-fill-column-center-text t)
(visual-fill-column-mode 1))
:hook (org-mode . me/org-mode-visual-fill))
(use-package magit
:general
(leader-map
"gs" 'magit-status
"gS" 'magit-status-here)
:custom
(magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)
:config
(progn
(defun me/magit-quit ()
(interactive)
(magit-mode-bury-buffer t))
(general-def magit-mode-map
[remap magit-mode-bury-buffer] #'me/magit-quit)
(add-hook 'with-editor-mode-hook #'evil-insert-state)))
;; NOTE: Make sure to configure a GitHub token before using this package!
;; - https://magit.vc/manual/forge/Token-Creation.html#Token-Creation
;; - https://magit.vc/manual/ghub/Getting-Started.html#Getting-Started
(use-package forge
:after magit
:init
(setq forge-add-default-bindings t)
(setq auth-sources '("~/.authinfo")))
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode))
(use-package format-all
:hook (prog-mode . format-all-mode)
:general (leader-map "=" 'format-all-buffer))
(use-package yasnippet)
(use-package treemacs
:general
(leader-map
"Tt" 'treemacs)
:init
(setq treemacs-width 20)
)
(use-package treemacs-evil
:after (treemacs evil)
:straight nil
:load-path "straight/repos/treemacs/src/extra")
(use-package treemacs-all-the-icons
:after (treemacs magit)
:straight nil
:load-path "straight/repos/treemacs/src/extra")
(use-package treemacs-all-the-icons
:after (treemacs all-the-icons)
:straight nil
:load-path "straight/repos/treemacs/src/extra")
(use-package treemacs-perspective
:after (treemacs perspective)
:straight nil
:load-path "straight/repos/treemacs/src/extra")
(use-package treemacs-projectile
:after (treemacs projectile)
:straight nil
:load-path "straight/repos/treemacs/src/extra")
(use-package xref
:straight nil
:config
(with-eval-after-load 'evil
(mmap xref--xref-buffer-mode-map
"<backtab" #'xref-prev-group
"<return" #'xref-goto-xref
"<tab>" #'xref-next-group)))
(use-package lsp-mode
:hook
((js-mode ; ts-ls (tsserver wrapper)
js-jsx-mode ; ts-ls (tsserver wrapper)
typescript-mode ; ts-ls (tsserver wrapper)
web-mode ; ts-ls/HTML/CSS
) . lsp-deferred)
;; (lsp-completion-mode . me/lsp-mode-setup-completion)
:commands lsp
;; only corfu
;; :custom (lsp-completion-provider :none)
:init
(setq lsp-keymap-prefix "C-l")
:config
(lsp-enable-which-key-integration t)
(local-leader-map prog-mode-map
"l" (general-simulate-key "C-l"))
(setq lsp-restart 'auto-restart)
;;(setq lsp-enable-symbol-highlighting nil)
;;(setq lsp-enable-on-type-formatting nil)
;;(setq lsp-signature-auto-activate nil)
(setq lsp-eldoc-enable-hover nil)
(setq lsp-signature-render-documentation nil)
(setq lsp-modeline-code-actions-enable nil)
(setq lsp-modeline-diagnostics-enable nil)
(setq lsp-headerline-breadcrumb-enable t)
(setq lsp-semantic-tokens-enable t)
(setq lsp-enable-folding t)
(setq lsp-enable-imenu t)
(setq lsp-enable-snippet t)
(setq lsp-enable-indentation nil)
(setq-default lsp-enable-relative-indentation nil)
(setq read-process-output-max (* 1024 1024)) ;; 1MB
(setq lsp-idle-delay 0.5))
(use-package lsp-ui
:commands lsp-ui-mode
:config
(general-def lsp-ui-doc-mode-map
"<f5>" 'lsp-ui-doc-focus-frame)
(general-def lsp-ui-doc-frame-mode-map
"<f6>" 'lsp-ui-doc-unfocus-frame)
(setq lsp-ui-doc-position 'at-point)
(setq lsp-ui-doc-max-height 80)
(setq lsp-ui-doc-alignment 'window)
(setq lsp-ui-doc-enable t)
(setq lsp-ui-doc-header t)
(set-face-attribute 'lsp-ui-doc-header nil :foreground (face-foreground 'default) :background (face-background 'default))
(setq lsp-ui-doc-max-width 50)
(setq lsp-ui-doc-include-signature t)
(setq lsp-ui-doc-show-with-cursor t)
(setq lsp-ui-doc-delay 0.5)
(setq lsp-ui-doc-border (face-foreground 'default))
(setq lsp-ui-sideline-mode nil)
(setq lsp-ui-sideline-show-code-actions nil)
(setq lsp-ui-sideline-delay 0.05))
(use-package lsp-treemacs
:after (perspective lsp treemacs)
:config
(lsp-treemacs-sync-mode 1))
(use-package flymake
:straight nil
:custom
(flymake-fringe-indicator-position nil))
(use-package tree-sitter
:config
(global-tree-sitter-mode)
(add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode))
(use-package tree-sitter-langs)
(use-package tree-sitter-indent)
(use-package dap-mode
:after lsp
:config
(progn
(dap-auto-configure-mode)
(require 'dap-node)
(dap-node-setup)))
(use-package yaml-mode)
(use-package json-mode)
(use-package markdown-mode
:mode ("\\.md\\'" . markdown-mode)
:custom (markdown-wiki-link-search-type '(sub-directories parent-directories))
:init
(setq markdown-link-space-sub-char " ")
(setq markdown-wiki-link-alias-first nil)
(setq markdown-fontify-code-blocks-natively t)
(setq markdown-enable-wiki-links t)
(setq markdown-wiki-link-fontify-missing t))
(use-package obsidian
:ensure t
:demand t
:config
(progn
(leader-map
"c" 'obsidian-capture
"os" 'obsidian-search
"oj" 'obsidian-jump
"ot" 'obsidian-tag-find)
(leader-map obsidian-mode-map
"ol" 'obsidian-insert-wikilink
"oL" 'obsidian-insert-link
"oo" 'obsidian-follow-link-at-point)
(general-def obsidian-mode-map
"C-c C-o" 'obsidian-follow-link-at-point
"C-c C-l" 'obsidian-insert-wikilink)
(obsidian-specify-path "~/Documents/BrendOS")
(global-obsidian-mode t))
:custom
;; This directory will be used for `obsidian-capture' if set.
(obsidian-inbox-directory "• Encounters/• Unsorted"))
(use-package vterm
:commands vterm
:general (leader-map "`" 'vterm)
:config
(progn
(setq vterm-buffer-name-string "vterm %s")
(setq vterm-shell "fish")
(setq vterm-max-scrollback 10000)))
(use-package perspective
:defer nil
:demand t
:init
(setq persp-initial-frame-name "config")
(setq persp-show-modestring nil)
(setq persp-state-default-file (no-littering-expand-var-file-name "persp/auto-save"))
(setq persp-suppress-no-prefix-key-warning t)
(persp-mode)
(when (file-exists-p persp-state-default-file)
(persp-state-load persp-state-default-file))
:custom
(persp-sort 'access)
:config
(progn
(defun me/persp-state-save ()
(let ((dir-name (no-littering-expand-var-file-name "persp/")))
(when (not (file-exists-p dir-name))
(make-directory dir-name t)))
(persp-state-save))
(add-hook 'kill-emacs-hook 'me/persp-state-save)
(general-def perspective-map
"t" 'persp-switch
"b" 'persp-ibuffer)
(leader-map
"P" '(:keymap perspective-map :wk "perspectives")
"C-TAB" 'persp-last
"TAB" 'persp-switch)
(with-eval-after-load 'consult
(consult-customize consult--source-buffer :hidden t :default nil)
(add-to-list 'consult-buffer-sources persp-consult-source))))
(use-package doom-modeline
:init
(doom-modeline-mode 1)
(setq doom-modeline-bar-width 1
doom-modeline-minor-modes nil
doom-modeline-buffer-file-name-style 'auto
doom-modeline-minor-modes nil
doom-modeline-modal-icon t
doom-modeline-persp-name t
doom-modeline-display-default-persp-name t
doom-modeline-persp-icon nil
doom-modeline-buffer-encoding nil)
:config
;; This configuration to is fix a bug where certain windows would not display
;; their full content due to the overlapping modeline
(advice-add #'fit-window-to-buffer :before (lambda (&rest _) (redisplay t))))
For some reason they only support persp-mode
and not perspective
(with-eval-after-load 'perspective
(progn
;; First remove the advice and hooks
(general-remove-hook (list 'persp-renamed-functions 'persp-activated-functions 'find-file-hook 'buffer-list-update-hook) #'doom-modeline-update-persp-name)
(advice-remove #'lv-message #'doom-modeline-update-persp-name)
;; New function for updating persp name
(defun me/doom-modeline-update-persp-name (&rest _)
"Update perspective name in mode-line."
(setq doom-modeline--persp-name
(when (and doom-modeline-persp-name)
(let* ((persp (persp-current-name))
(face (if (and persp)
'doom-modeline-persp-buffer-not-in-persp
'doom-modeline-persp-name))
(icon (doom-modeline-icon 'material "folder" "🖿" "#"
:face `(:inherit ,face :slant normal)
:height 1.1
:v-adjust -0.225)))
(when (or doom-modeline-display-default-persp-name)
(concat doom-modeline-spc
(propertize (concat (and doom-modeline-persp-icon
(concat icon doom-modeline-vspc))
(propertize persp 'face face))
'mouse-face 'doom-modeline-highlight)
doom-modeline-spc))))))
;; Initialize
(me/doom-modeline-update-persp-name)
;; Add hooks
(general-add-hook (list 'persp-switch-hook 'persp-activated-hook 'persp-after-rename-hook 'persp-state-after-save-hook 'find-file-hook 'buffer-list-update-hook) #'me/doom-modeline-update-persp-name)
(advice-add #'lv-message :after #'doom-modeline-update-persp-name)))
((nil . ((eval git-auto-commit-mode 1))))