alexforsale's literate Emacs configuration
Table of Contents
This repository is my personal Emacs configuration. In case you don't know what Emacs is, I won't be the one explaining. To me Emacs is crucial and should exists in all of my machines, including the proprietary ones. In fact, this repository is the first one that I clone into my new machines (with my dotfiles being the second one).
The Goal
I used to blindly copying and pasting every snippets of Emacs configuration I found over the internet. The result usually is me having to mix and match them into one configuration, which is fine until it broke, and I start from scratch again and the cycle repeats.
Keep it simple
If the default configuration for a certain package is enough, don't add more.
Reproducible
This configuration should be usable in many systems.
This configuration is for me, not for anyone else
It's good if anyone who stumble into this repository find it useful, but the priority is to make it useful for me now. I'm trying to stop adding configuration that someday would be useful.
Editor first, IDE second
I'm not a programmer, I use Emacs mainly for editing files, tasks management, note-taking.
Documented
- List every external packages needed for this configuration
Mnemonic keybindings
Try setting a sensible keybindings, especially for external packages. Don't mess with the default keybindings if possible.
Use org-mode
This way I don't have to separate each configurations into a separate modules.
- Use
noweb
1
I also learned that tangling too many codeblocks took a while. Now I use
noweb
, the output will only be one fileconfig.el
. init.el
andconfig.el
init.el is for the essential configurations, everything else goes to config.el.
Evil
evil
external
Mostly copied from doom or the official documentation2.
1: (use-package evil 2: :ensure t 3: :demand t 4: :preface 5: (customize-set-variable 'evil-want-keybinding nil) 6: (customize-set-variable 'evil-want-integration t) 7: (customize-set-variable 'evil-undo-system 'undo-redo) 8: (customize-set-variable 'evil-want-C-i-jump nil) ;; fix TAB in terminal org-mode 9: (customize-set-variable 'evil-want-C-u-scroll t) ;; move universal arg to <leader> u 10: (customize-set-variable 'evil-want-C-u-delete t) ;; delete back to indentation in insert state 11: (customize-set-variable 'evil-want-C-g-bindings t) 12: :custom 13: (evil-undo-system #'undo-redo) 14: (evil-search-module 'evil-search) 15: (evil-ex-search-vim-style-regexp t) 16: (evil-ex-interactive-search-highlight 'selected-window) 17: (evil-kbd-macro-suppress-motion-error t) 18: (evil-visual-update-x-selection-p nil) 19: :config 20: (setq evil-normal-state-cursor 'box 21: evil-insert-state-cursor 'bar 22: evil-visual-state-cursor 'hollow) 23: (evil-select-search-module 'evil-search-module 'evil-search) 24: (evil-mode 1) 25: (with-eval-after-load 'eldoc 26: (eldoc-add-command 'evil-normal-state 27: 'evil-insert 28: 'evil-change 29: 'evil-delete 30: 'evil-replace)))
evil-collection
external
For parts of Emacs not covered by Evil3.
1: (use-package evil-collection 2: :ensure t 3: :after evil 4: :init 5: (evil-collection-init) 6: :custom 7: (evil-collection-setup-minibuffer t) 8: (evil-collection-calendar-want-org-bindings t))
Variables and helper functions
Identity
1: (setq user-mail-address "alexforsale@yahoo.com" 2: user-full-name "Kristian Alexander P")
+config/user-modules-directory
This variable is needed in order for Emacs to locate this configuration files.
1: (defvar +config/user-modules-directory (expand-file-name "modules/" user-emacs-directory) 2: "User modules directory.")
add module directory to load-path
1: (when (file-directory-p +config/user-modules-directory) 2: (add-to-list 'load-path +config/user-modules-directory))
merge-list-to-list
function
This function is just a wrapper to easily merge lists.
1: ;;; From https://emacs.stackexchange.com/questions/38008/adding-many-items-to-a-list/68048#68048 2: (defun merge-list-to-list (dst src) 3: "Merges content of the 2nd list with the 1st one" 4: (set dst 5: (append (eval dst) src)))
define +config/org-directory
variable
1: (when (file-directory-p (expand-file-name "Sync/org" (getenv "HOME"))) 2: (customize-set-variable '+config/org-directory (expand-file-name "Sync/org" (getenv "HOME"))))
Keybindings
general.el
Keybindings in Emacs is always been my struggle, my brain isn't big enough to memorize all the default keybindings (though over the years my fingers started to memorize some of them). At first I started using hydra, it's a wonderful package for customized keybindings. But configuring them feels like a chore, considering I'm still working my way on finding my own comfort in keybindings.
1: (use-package general 2: :ensure t 3: :init 4: (general-evil-setup t) 5: (general-auto-unbind-keys) 6: :config 7: (general-override-mode) 8: (general-create-definer +config/leader-key 9: :keymaps 'override 10: :states '(insert emacs normal hybrid motion visual operator) 11: :prefix "SPC" 12: :non-normal-prefix "C-c SPC") 13: (general-create-definer +config/local-leader 14: :keymaps 'override 15: :states '(emacs normal hybrid motion visual operator) 16: :prefix "SPC m" 17: :non-normal-prefix "C-c SPC m" 18: "" '(:ignore t :which-key (lambda (arg) `(,(cadr (split-string (car arg) " ")) . ,(replace-regexp-in-string "-mode$" "" (symbol-name major-mode)))))) 19: ;; useful macro 20: (defmacro +config/leader-menu! (name infix-key &rest body) 21: "Create a definer NAME `+config/leader-NAME' wrapping `+config/leader-key'. 22: Create prefix map: `+config/leader-NAME-map'. Prefix bindings in BODY with INFIX-KEY." 23: (declare (indent 2)) 24: `(progn 25: (general-create-definer ,(intern (concat "+config/leader-" name)) 26: :wrapping +config/leader-key 27: :prefix-map (quote ,(intern (concat "+config/leader-" name "-map"))) 28: :infix ,infix-key 29: :wk-full-keys nil 30: "" '(:ignore t :which-key ,name)) 31: (,(intern (concat "+config/leader-" name)) 32: ,@body))))
What I'm doing before is setting the general keybindings inside their respective use-package declarations. So in org-roam, I set a general keybinding. The problem with this is, if the package is deferred (with the keyword :defer t
), the keybindings won't show.
I prefer to have the keybindings inside the use-package declaration, this way if I decided not to use the package(s), their custom keybindings will also be removed. The other way for this is to use the :demand t
keyword, with the down side of having a longer initialization time.
Packages keybindings
- First level menu
1: ;; First level menu 2: (+config/leader-menu! "activities" "C-a") 3: (+config/leader-menu! "buffer" "b") 4: (+config/leader-menu! "files" "f") 5: (+config/leader-menu! "find" "gf") 6: (+config/leader-menu! "go" "g") 7: (+config/leader-menu! "insert" "i") 8: (+config/leader-menu! "mail" "M-m") 9: (+config/leader-menu! "mark" "m") 10: (+config/leader-menu! "notes" "n") 11: (+config/leader-menu! "open" "o") 12: (+config/leader-menu! "quit" "q") 13: (+config/leader-menu! "register" "gr") 14: (+config/leader-menu! "tree" "t") 15: (+config/leader-menu! "tab" "t TAB") 16: (+config/leader-menu! "vterm" "tv") 17: (+config/leader-menu! "window" "w")
- First level keybinding
1: ;; keybindings 2: (+config/leader-key 3: ";" 'pp-eval-expression 4: ":" 'execute-extended-command 5: "^" '(subword-capitalize :wk "Capitalize subword") 6: "u" 'universal-argument)
- buffer
1: ;; buffer 2: (+config/leader-buffer 3: "[" '(previous-buffer :wk "previous buffer") 4: "]" '(next-buffer :wk "next buffer") 5: "TAB" '((lambda () (interactive) (switch-to-buffer nil)) :wk "other-buffer") 6: "b" '(switch-to-buffer :wk "switch to buffer") 7: "s" '(basic-save-buffer :wk "save buffer") 8: "c" '(clone-indirect-buffer :wk "clone buffer") 9: "C" '(clone-indirect-buffer-other-window :wk "clone buffer other window") 10: "d" '(kill-current-buffer :wk "kill current buffer") 11: "i" 'ibuffer 12: "k" '(kill-buffer :wk "kill buffer") 13: "l" '(evil-switch-to-windows-last-buffer :wk "Switch to last open buffer") 14: "m" '((lambda () (interactive) (switch-to-buffer "*Messages*")) :wk "switch to messages buffer") 15: "n" '(next-buffer :wk "next buffer") 16: "N" '(evil-buffer-new :wk "New unnamed buffer") 17: "p" '(previous-buffer :wk "previous buffer") 18: "o" '((lambda () (interactive) (switch-to-buffer nil)) :wk "other-buffer") 19: "r" '(revert-buffer-quick :wk "revert buffer") 20: "R" '(rename-buffer :wk "rename buffer") 21: "x" '((lambda () (interactive) (switch-to-buffer "*scratch*")) :wk "switch to scratch buffer") 22: "z" '(bury-buffer :wk "bury buffer"))
- Editing
smartparens
1: (with-eval-after-load 'smartparens 2: (general-nvmap 3: :keymaps 'smartparens-mode-map 4: "<" 'sp-backward-barf-sexp 5: "C-<" 'sp-backward-slurp-sexp 6: ">" 'sp-forward-slurp-sexp 7: "C->" 'sp-forward-barf-sexp) 8: (general-define-key 9: :keymaps 'smartparens-mode-map 10: "M-DEL" 'sp-unwrap-sexp))
- dired
1: (general-nvmap 2: 'dired-mode-map 3: "g$" 'dired-hide-subdir 4: "g?" 'dired-summary 5: "gG" 'dired-do-chgrp 6: "gj" 'dired-next-dirline 7: "gk" 'dired-prev-dirline 8: "go" 'dired-view-file 9: "gO" 'dired-find-file-other-window 10: "gy" 'dired-show-file-type)
- files
1: ;; files 2: (+config/leader-files 3: "D" 'dired 4: "d" 'dired-jump 5: "f" '(find-file :wk "find file") 6: "F" '(find-file-other-frame :wk "find file other frame") 7: "k" 'delete-frame 8: "r" 'recentf 9: "S" '(write-file :wk "save file") 10: "s" '(save-buffer :wk "save buffer") 11: "w" '(find-file-other-window :wk "find file other window"))
- find
1: ;; find 2: (+config/leader-find 3: "g" 'grep 4: "r" '(rgrep :wk "recursive grep"))
- help
1: ;; help 2: (+config/leader-key 3: "h" (general-simulate-key "C-h" 4: :state '(normal visual) 5: :name general-SPC-h-simulates-C-h 6: :docstring "Simulates C-h in normal and visual mode." 7: :which-key "Help"))
- insert
1: ;; insert 2: (+config/leader-insert 3: "u" '(insert-char :wk "insert character"))
- mark
1: ;; mark 2: (+config/leader-mark 3: "m" '(bookmark-set :wk "set bookmark") 4: "b" '(bookmark-jump :wk "jump to bookmark") 5: "B" '(bookmark-jump-other-window :wk "jump to bookmark other window") 6: "C-c b" '(bookmark-jump-other-frame :wk "jump to bookmark other frame") 7: "c" '(consult-bookmark :wk "consult bookmark") ;; require `consult' package 8: "l" '(bookmark-bmenu-list :wk "list bookmarks") 9: "L" '(bookmark-load :wk "load bookmark") 10: "d" '(bookmark-delete :wk "delete bookmark") 11: "D" '(bookmark-delete-all :wk "delete all bookmarks") 12: "s" '(bookmark-save :wk "save bookmark") 13: "r" '(bookmark-rename :wk "rename bookmark"))
- open
1: ;; open 2: (+config/leader-open 3: "i" '((lambda () (interactive) (find-file user-init-file)) :wk "open Emacs configuration file"))
org-mode
1: (general-define-key 2: :keymaps 'override 3: "C-c l" '(org-store-link :wk "Store link") 4: "C-c a" '(org-agenda :wk "Org Agenda") 5: "C-c c" '(org-capture :wk "Org Capture") 6: "C-c C-s" 'org-schedule) 7: 8: (+config/leader-notes 9: "a" 'org-agenda 10: "c" 'org-capture 11: "C" 'org-capture-goto-last-stored 12: "r" 'org-refile-goto-last-stored) 13: 14: ;; (+config/local-leader 15: ;; :major-modes 'org-mode 16: ;; :keymaps 'org-mode-map 17: ;; "a" '(:ignore t :wk "action") 18: ;; "s" '(:ignore t :wk "search")) 19: 20: (+config/local-leader 21: :keymaps 'org-mode-map 22: "C-a" 'org-attach 23: "C-b" 'org-backward-heading-same-level 24: "C-c" 'org-ctrl-c-ctrl-c 25: "C-d" 'org-deadline 26: "C-e" 'org-export-dispatch 27: "C-f" 'org-forward-heading-same-level 28: "C-j" 'org-goto 29: "C-k" 'org-kill-note-or-show-branches 30: "C-l" 'org-insert-link 31: "C-n" 'org-next-visible-heading 32: "C-o" 'org-open-at-point 33: "C-p" 'org-previous-visible-heading 34: "C-q" 'org-set-tags-command 35: "C-r" 'org-fold-reveal 36: "C-s" 'org-schedule 37: "C-t" 'org-todo 38: "C-w" 'org-refile 39: "C-y" 'org-evaluate-time-range 40: "C-z" 'org-add-note 41: "M-b" 'org-previous-block 42: "M-f" 'org-next-block 43: "M-l" 'org-insert-last-stored-link 44: "M-w" 'org-refile-copy 45: "C-^" 'org-up-element 46: "C-_" 'org-down-element 47: "C-<" 'org-promote-subtree 48: "C->" 'org-demote-subtree 49: "C-," 'org-insert-structure-template 50: "C-*" 'org-list-make-subtree 51: "{" 'org-table-toggle-formula-debugger 52: "}" 'org-table-toggle-coordinate-overlays 53: "`" 'org-table-edit-field 54: "\\" 'org-match-sparse-tree 55: "^" 'org-sort 56: "[" 'org-agenda-file-to-front 57: "]" 'org-remove-file 58: "@" 'org-mark-subtree 59: "?" 'org-table-field-info 60: "=" 'org-table-eval-formula 61: ">" 'org-goto-calendar 62: "+" 'org-table-sum 63: "<" 'org-date-from-calendar 64: ";" 'org-toggle-comment 65: ":" 'org-toggle-fixed-width 66: "/" 'org-sparse-tree 67: "," 'org-priority 68: "." 'org-timestamp 69: "*" 'org-ctrl-c-star 70: "-" 'org-ctrl-c-minus 71: "#" 'org-update-statistics-cookies 72: "$" 'org-archive-subtree 73: "%" 'org-mark-ring-push 74: "'" 'org-edit-special 75: "TAB" '(org-clock-in :wk "clock-in") 76: "!" '(org-reload :wk "reload org") 77: "[" '(org-mark-ring-goto :wk "Jump to previous position in the mark ring") 78: "b" '(:ignore t :wk "buffer") 79: "bs" '(org-save-all-org-buffers :wk "save all org buffer") 80: "f" '(:ignore t :wk "files") 81: "fs" '(org-save-all-org-buffers :wk "save all org buffer") 82: "s" '(org-schedule :wk "org schedule") 83: "i" '(:ignore t :wk "insert") 84: "id" '(org-insert-drawer :wk "insert drawer") 85: "i@" '(org-cite-insert :wk "insert citation") 86: "if" '(org-footnote-action :wk "footnote") 87: "i C-f" '(org-emphasize :wk "insert emphasize") 88: "il" '(org-insert-link :wk "insert link") 89: "iD" '(org-deadline :wk "insert deadline") 90: "is" '(org-schedule :wk "insert schedule") 91: "ip" '(org-set-property :wk "insert property") 92: "it" '(org-insert-time-stamp :wk "insert time-stamp at point"))
- quit
1: ;; quit 2: (+config/leader-quit 3: "q" '(save-buffers-kill-terminal :wk "quit and save") 4: "R" '(restart-emacs :wk "restart Emacs"))
- register
1: ;; register 2: (+config/leader-register 3: ;; "#" '(consult-register :wk "consult-register") ;; require `consult' package 4: "+" '(increment-register :wk "augment content of register") 5: "C-@" '(point-to-register :wk "store current point to register") 6: "C-SPC" '(point-to-register :wk "store current point to register") 7: "M-w" '(copy-rectangle-as-kill :wk "copy region-rectangle and save") 8: "SPC" '(point-to-register :wk "store current point to register") 9: "c" '(clear-rectangle :wk "blank out region-rectangle") 10: "d" '(delete-rectangle :wk "delete region-rectangle") 11: "f" '(frameset-to-register :wk "store frameset to register") 12: "g" '(insert-register :wk "insert register") 13: "i" '(insert-register :wk "insert register") 14: "j" '(jump-to-register :wk "jump to register") 15: "k" '(kill-rectangle :wk "cut rectangle into killed-rectangle") 16: "l" '(bookmark-bmenu-list :wk "display existing bookmarks") 17: "m" '(bookmark-set :wk "set bookmark") 18: "M" '(bookmark-set-no-overwrite :wk "set bookmark no overwrite") 19: "n" '(number-to-register :wk "store a number in a register") 20: "N" '(rectangle-number-lines :wk "insert number in front of region-rectangle") 21: "o" '(open-rectangle :wk "blank out region-rectangle") 22: "r" '(copy-rectangle-to-register :wk "copy rectangle-region to register") 23: "s" '(copy-to-register :wk "copy region to register") 24: "t" '(string-rectangle :wk "replace rectangle with string") 25: "x" '(copy-to-register :wk "copy region to register") 26: "w" '(window-configuration-to-register :wk "store window configuration to register") 27: "y" '(yank-rectangle :wk "yank last killed rectangle with upper left corner at point"))
- window
1: ;; window 2: (+config/leader-window 3: "C-o" '(delete-other-windows :wk "delete other windows") 4: "[" '(evil-window-left :wk "left window") 5: "]" '(evil-window-right :wk "right window") 6: "+" '(enlarge-window :wk "enlarge window") 7: "-" '(shrink-window :wk "shrink window") 8: "}" '(enlarge-window-horizontally :wk "enlarge window horizontally") 9: "{" '(shrink-window-horizontally :wk "shrink window horizontally") 10: "+" 'evil-window-increase-height 11: "-" 'evil-window-decrease-height 12: ":" 'evil-ex 13: "<" 'evil-window-decrease-width 14: "=" 'balance-windows 15: ">" 'evil-window-increase-height 16: "_" 'evil-window-set-height 17: "b" 'evil-window-bottom-right 18: "c" 'evil-window-delete 19: "d" '(delete-window :wk "delete window") 20: "h" 'evil-window-left 21: "f" '(ffap-other-window :wk "ffap other window") 22: "j" 'evil-window-down 23: "k" 'evil-window-up 24: "l" 'evil-window-right 25: "n" 'evil-window-new 26: "p" 'evil-window-mru 27: "q" 'evil-quit 28: "r" 'evil-window-rotate-downwards 29: "R" 'evil-window-rotate-upwards 30: "s" 'evil-window-split 31: "T" '(tear-off-window :wk "tear off window") 32: "t" 'evil-window-top-left 33: "u" 'winner-undo 34: "v" 'evil-window-vsplit 35: "w" '(other-window :wk "other window") 36: "W" 'evil-window-prev 37: "x" 'evil-window-exchange 38: "|" 'evil-window-set-width 39: "<left>" 'evil-window-left 40: "<right>" 'evil-window-right 41: "<down>" 'evil-window-down 42: "<up>" 'evil-win-up)
UI
I suppose here is the most external packages used.
Doom themes and modelines
doom-themes
external
A megapack of themes for GNU Emacs4. I'm not the kind of guy who enjoys ricing, I look every once in a while for a nice colorscheme and then I just stick it everywhere else. Been a solarized fans most of the time, now I'm trying nord.
1: (use-package doom-themes 2: :ensure t 3: :demand t 4: :config 5: ;; Global settings (defaults) 6: (setq doom-themes-enable-bold t ; if nil, bold is universally disabled 7: doom-themes-enable-italic t) ; if nil, italics is universally disabled 8: (load-theme 'doom-nord t) 9: 10: ;; Enable flashing mode-line on errors 11: (doom-themes-visual-bell-config) 12: ;; Enable custom neotree theme (all-the-icons must be installed!) 13: ;; (doom-themes-neotree-config) 14: ;; or for treemacs users 15: (setq doom-themes-treemacs-theme "doom-atom") ; use "doom-colors" for less minimal icon theme 16: (doom-themes-treemacs-config) 17: ;; Corrects (and improves) org-mode's native fontification. 18: (doom-themes-org-config))
doom-modeline
external
A fancy and fast mode-line inspired by minimalism design5. I'm using their themes, why not the modeline as well? I used mostly the default settings apart from project detection and indent info for showing the current indentation style (useful when editing yaml files).
1: (use-package doom-modeline 2: :ensure 3: :init 4: (doom-modeline-mode 1) 5: :config 6: (setq doom-modeline-project-detection 'projectile 7: doom-modeline-indent-info t))
modus-vivendi
disabled
I use this theme when I'm not using any external theme.
1: (use-package custom 2: :ensure nil 3: :init 4: (load-theme 'modus-vivendi t))
ace-window
external
(use-package ace-window :ensure :config (setq aw-keys '(?q ?w ?e ?r ?t ?a ?s ?d ?f ?z ?x ?c ?v) aw-background nil aw-frame-size 2) (custom-set-faces '(aw-leading-char-face ((t (:inherit ace-jump-face-foreground :height 4.0))))) :bind ([remap other-window] . ace-window))
all-the-icons
external
A utility package to collect various Icon Fonts and propertize them within Emacs6.
1: (use-package all-the-icons 2: :ensure 3: :if (display-graphic-p))
This needs a manual intervention from the user to install the fonts (by running the all-the-icons-install-fonts
command).
dashboard
external
An extensible emacs dashboard7.
My sole reason for using dashboard is to avoid seeing an empty scratch buffer each time I opened a new Emacs frame.
1: ;; use-package with package.el: 2: (use-package dashboard 3: :ensure t 4: :demand t 5: :init 6: (setq dashboard-set-heading-icons t 7: dashboard-icon-type 'all-the-icons) 8: (setq dashboard-heading-icons '((recents . "history") 9: (bookmarks . "bookmark") 10: (agenda . "calendar") 11: (projects . "rocket") 12: (registers . "database"))) 13: :custom 14: (initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))) 15: (dashboard-startup-banner 'logo) 16: (dashboard-set-heading-icons t) 17: (dashboard-set-file-icons t) 18: (dashboard-display-icons-p t) 19: (dashboard-icon-type 'nerd-icons) 20: (dashboard-projects-switch-function 'projectile-persp-switch-project) 21: (dashboard-week-agenda t) 22: (dashboard-filter-agenda-entry nil) 23: (dashboard-startup-banner 'logo) 24: (dashboard-center-content t) 25: (dashboard-vertically-center-content t) 26: (dashboard-agenda-sort-strategy 27: '(todo-state-up time-down priority-down todo-state-down time-up priority-up)) 28: (dashboard-navigation-cycle t) 29: (dashboard-banner-logo-title nil) 30: (dashboard-set-heading-icons t) 31: (dashboard-set-footer nil) 32: (dashboard-projects-backend 'projectile) 33: (dashboard-display-icons-p t) 34: (dashboard-items '((recents . 3) 35: (bookmarks . 2) 36: (projects . 5) 37: (agenda . 8) 38: (registers . 2))) 39: :config 40: (dashboard-setup-startup-hook))
which-key
external
Emacs package that displays available keybindings in popup8. This is one of the top Emacs packages that I must have in my configuration.
1: (use-package which-key 2: :ensure 3: :demand t 4: :custom 5: (which-key-lighter "") 6: (which-key-sort-order #'which-key-key-order-alpha) 7: (which-key-sort-uppercase-first nil) 8: (which-key-add-column-padding 1) 9: (which-key-max-display-columns nil) 10: (which-key-min-display-lines 6) 11: (which-key-compute-remaps t) 12: (which-key-side-window-slot -10) 13: (which-key-separator " → ") 14: (which-key-allow-evil-operators t) 15: (which-key-use-C-h-commands t) 16: (which-key-show-remaining-keys t) 17: (which-key-show-prefix 'bottom) 18: :config 19: (which-key-mode) 20: (which-key-setup-side-window-bottom) 21: (which-key-setup-minibuffer) 22: (define-key which-key-mode-map (kbd "C-x <f5>") 'which-key-C-h-dispatch))
Fonts
1: (set-face-attribute 'default nil :family "Iosevka Nerd Font Mono") 2: (set-face-attribute 'variable-pitch nil :family "Iosevka Nerd Font Mono")
rainbow-mode
, rainbow-identifiers
, and rainbow-delimiters
external
Making Emacs more colourful.
1: (use-package rainbow-mode 2: :ensure 3: :hook (prog-mode . rainbow-mode)) 4: 5: (use-package rainbow-identifiers 6: :ensure 7: :hook (prog-mode . rainbow-identifiers-mode)) 8: 9: (use-package rainbow-delimiters 10: :ensure 11: :hook (prog-mode . rainbow-delimiters-mode))
helpful
external
Since Emacs is a self-documenting editor9. It's certainly nice to have a more contextual help buffers.
Figure 2: Helpful will also show the source code when available
Figure 3: more prettier docstring
Figure 4: helpful will also display any keybindings related
1: (use-package helpful 2: :ensure 3: :bind 4: ("C-h f" . helpful-function) 5: ([remap describe-symbol] . helpful-symbol) 6: ([remap describe-variable] . helpful-variable) 7: ([remap describe-command] . helpful-command) 8: ([remap describe-key] . helpful-key) 9: :custom 10: (helpful-max-buffers 2) 11: :config 12: (with-eval-after-load 'general 13: (general-define-key 14: "C-h F" 'helpful-function 15: :keymaps 'prog-mode-map 16: "C-c C-d" 'helpful-at-point) 17: (general-nvmap 18: :keymaps 'prog-mode-map 19: "K" '(helpful-at-point :wk "helpful at point") 20: "gr" '(helpful-update :wk "update"))))
hl-line
Enable line highlighting in all buffers.
1: (use-package hl-line 2: :config 3: (global-hl-line-mode 1))
nerd-icons
external
(use-package nerd-icons :ensure t :custom ;; The Nerd Font you want to use in GUI ;; "Symbols Nerd Font Mono" is the default and is recommended ;; but you can use any other Nerd Font if you want (nerd-icons-font-family "Symbols Nerd Font Mono"))
nerd-fonts
external
This package still not available at Melpa, so I have to clone it as a submodule.
in archlinux, these fonts is conveniently grouped in nerd-fonts, which is needed for this and the nerd-icons
package.
1: (when (file-directory-p (expand-file-name "site-lisp/nerd-fonts" user-emacs-directory)) 2: (add-to-list 'load-path (expand-file-name "site-lisp/nerd-fonts" user-emacs-directory))) 3: 4: (use-package nerd-fonts)
paren
1: (use-package paren 2: :config 3: (show-paren-mode 1) 4: :custom 5: (show-paren-style 'mixed))
Builtins
base
Usually configuration that defined at the C source code.
1: (use-package emacs 2: :ensure nil 3: :init 4: ;; Add prompt indicator to `completing-read-multiple'. 5: ;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma. 6: (defun crm-indicator (args) 7: (cons (format "[CRM%s] %s" 8: (replace-regexp-in-string 9: "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" "" 10: crm-separator) 11: (car args)) 12: (cdr args))) 13: (advice-add #'completing-read-multiple :filter-args #'crm-indicator) 14: ;; Do not allow the cursor in the minibuffer prompt 15: (setq minibuffer-prompt-properties 16: '(read-only t cursor-intangible t face minibuffer-prompt)) 17: (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) 18: ;; Emacs 28: Hide commands in M-x which do not work in the current mode. 19: ;; Vertico commands are hidden in normal buffers. 20: (setq read-extended-command-predicate 21: #'command-completion-default-include-p 22: tab-always-indent 'complete) 23: ;; Enable recursive minibuffers 24: (setq enable-recursive-minibuffers t) 25: :custom 26: (read-buffer-completion-ignore-case t) 27: (use-short-answers t) 28: (use-dialog-box-p nil) 29: (window-resize-pixelwise t) 30: (frame-resize-pixelwise t) 31: (ring-bell-function #'ignore) 32: (scroll-preserve-screen-position t) 33: (scroll-conservatively 101) 34: (fast-but-imprecise-scrolling t) 35: (truncate-partial-width-windows nil) 36: (fill-column 80) 37: (enable-recursive-minibuffers t) 38: (use-file-dialog nil) 39: (create-lockfiles nil) 40: (delete-by-moving-to-trash t) 41: (inhibit-startup-screen t) 42: :config 43: (setq completion-ignore-case t 44: load-prefer-newer t 45: auto-window-vscroll nil 46: inhibit-compacting-font-caches t 47: redisplay-skip-fontification-on-input t) 48: (set-default 'indicate-empty-lines t) 49: (setq-default x-stretch-cursor t))
files
Usually configurations related to file manipulations.
(use-package files :config (defun full-auto-save () (interactive) (save-excursion (dolist (buf (buffer-list)) (set-buffer buf) (if (and (buffer-file-name) (buffer-modified-p)) (basic-save-buffer))))) (add-hook 'auto-save-hook 'full-auto-save) (nconc auto-mode-alist '(("/LICENSE\\'" . text-mode) ("\\.log\\'" . text-mode) ("rc\\'" . conf-mode) ("\\.\\(?:hex\\|nes\\)\\'" . hexl-mode))) :custom (confirm-kill-emacs #'yes-or-no-p) ; confirm when exiting (confirm-kill-processes nil) ; don't confirm killing processes (revert-without-query (list ".")) (find-file-visit-truename t) ; `find-file' will visit the actual file (version-control t) (backup-by-copying t) (delete-old-versions t) (kept-new-versions 6) (kept-old-versions 2) (auto-save-include-big-deletions t) (auto-save-list-file-prefix (expand-file-name ".autosave/" user-emacs-directory)) (backup-directory-alist `(("." . ,(expand-file-name ".backup" user-emacs-directory)))) (auto-mode-case-fold nil) (require-final-newline t))
saveplace
1: (use-package saveplace 2: :init 3: (save-place-mode 1) 4: :custom 5: (save-place-file (expand-file-name "places" user-emacs-directory)))
autorevert
1: (use-package autorevert 2: :init 3: (global-auto-revert-mode 1) 4: :custom 5: (auto-revert-interval 60) 6: (global-auto-revert-non-file-buffers t) 7: (auto-revert-verbose nil) 8: (auto-revert-stop-on-user-input t))
savehist
1: (use-package savehist 2: :init 3: (savehist-mode 1) 4: :custom 5: (savehist-file (expand-file-name "history" user-emacs-directory)) 6: (savehist-coding-system 'utf-8) 7: (savehist-additional-variables 8: '(evil-jumps-history 9: kill-ring 10: register-alist 11: mark-ring 12: global-mark-ring 13: search-ring 14: regexp-search-ring)))
recentf
1: (use-package recentf 2: :bind ("C-c f" . recentf) 3: :custom 4: (recentf-max-saved-items 250) 5: (recentf-max-menu-items 300) 6: (recentf-exclude 7: `("/elpa/" ;; ignore all files in elpa directory 8: "recentf" ;; remove the recentf load file 9: ".*?autoloads.el$" 10: "treemacs-persist" 11: "company-statistics-cache.el" ;; ignore company cache file 12: "/intero/" ;; ignore script files generated by intero 13: "/journal/" ;; ignore daily journal files 14: ".gitignore" ;; ignore `.gitignore' files in projects 15: "/tmp/" ;; ignore temporary files 16: "NEWS" ;; don't include the NEWS file for recentf 17: "bookmarks" "bmk-bmenu" ;; ignore bookmarks file in .emacs.d 18: "loaddefs.el" 19: "^/\\(?:ssh\\|su\\|sudo\\)?:" ;; ignore tramp/ssh files 20: (concat "^" (regexp-quote (or (getenv "XDG_RUNTIME_DIR")))))))
server
(use-package server :config (unless (server-running-p) (server-start)) (require 'org-protocol))
prog-mode
1: (use-package prog-mode 2: :hook ((prog-mode . prettify-symbols-mode) 3: (prog-mode . visual-line-mode) 4: ;; (prog-mode . (lambda () (electric-pair-mode 1))) 5: ) 6: :config 7: (setq prettify-symbols-alist 8: '(("|>" . "▷") 9: ("<|" . "◁") 10: ("->>" . "↠ ") 11: ("->" . "→ ") 12: ("<-" . "← ") 13: ("=>" . "⇒"))))
bookmark
1: (use-package bookmark 2: :custom 3: (bookmark-save-flag 1) 4: (bookmark-default-file (expand-file-name ".bookmark" user-emacs-directory)))
tramp
1: (use-package tramp 2: :custom 3: (tramp-backup-directory-alist backup-directory-alist) 4: (tramp-auto-save-directory (expand-file-name ".tramp-autosave/" user-emacs-directory)))
epg-config
1: (use-package epg-config 2: :custom 3: (epg-pinentry-mode 'loopback))
simple
1: (use-package simple 2: :custom 3: (save-interprogram-paste-before-kill t) 4: (shift-select-mode nil) 5: (kill-do-not-save-duplicates t) 6: (shift-select-mode nil) 7: (set-mark-command-repeat-pop t) 8: (indent-tabs-mode nil) 9: (column-number-mode t) 10: (idle-update-delay 1.0) 11: :config 12: (with-eval-after-load 'evil 13: (evil-set-initial-state #'message-mode 'insert)))
vc-hooks
By default visiting / opening symlinked file will ask if we want to visit the actual file.
1: (use-package vc-hooks 2: :ensure nil 3: :custom 4: (vc-follow-symlinks t))
Completions
Vertico frameworks
I call this framework since usually these packages are what people use together, though they work fine separately.
vertico
- Basic configuration
1: (use-package vertico 2: :ensure 3: :init 4: (vertico-mode) 5: ;; Different scroll margin 6: ;; (setq vertico-scroll-margin 0) 7: ;; Show more candidates 8: ;; (setq vertico-count 20) 9: ;; Grow and shrink the Vertico minibuffer 10: ;; (setq vertico-resize t) 11: ;; Optionally enable cycling for `vertico-next' and `vertico-previous'. 12: (setq vertico-cycle t) 13: ) 14: 15: ;; A few more useful configurations... 16: (use-package emacs 17: :init 18: ;; Add prompt indicator to `completing-read-multiple'. 19: ;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma. 20: (defun crm-indicator (args) 21: (cons (format "[CRM%s] %s" 22: (replace-regexp-in-string 23: "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" "" 24: crm-separator) 25: (car args)) 26: (cdr args))) 27: (advice-add #'completing-read-multiple :filter-args #'crm-indicator) 28: ;; Do not allow the cursor in the minibuffer prompt 29: (setq minibuffer-prompt-properties 30: '(read-only t cursor-intangible t face minibuffer-prompt)) 31: (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) 32: ;; Support opening new minibuffers from inside existing minibuffers. 33: (setq enable-recursive-minibuffers t) 34: ;; Emacs 28 and newer: Hide commands in M-x which do not work in the current 35: ;; mode. Vertico commands are hidden in normal buffers. This setting is 36: ;; useful beyond Vertico. 37: (setq read-extended-command-predicate #'command-completion-default-include-p))
- Extensions
vertico-directory
1: (use-package vertico-directory 2: :after vertico 3: :ensure nil 4: ;; More convenient directory navigation commands 5: :bind (:map vertico-map 6: ("RET" . vertico-directory-enter) 7: ("DEL" . vertico-directory-delete-char) 8: ("M-DEL" . vertico-directory-delete-word)) 9: ;; Tidy shadowed file names 10: :hook (rfn-eshadow-update-overlay . vertico-directory-tidy))
vertico-quick
1: (use-package vertico-quick 2: :after vertico 3: :ensure nil 4: :bind (:map vertico-map 5: ("M-q" . vertico-quick-insert) 6: ("C-q" . vertico-quick-exit)))
- Basic configuration
marginalia
1: ;; Enable rich annotations using the Marginalia package 2: (use-package marginalia 3: :ensure 4: :bind (:map minibuffer-local-map 5: ("M-A" . marginalia-cycle)) 6: :init 7: (marginalia-mode))
corfu
consult
- Basic Configuration
1: (use-package consult 2: :ensure 3: :hook (completion-list-mode . consult-preview-at-point-mode) 4: :init 5: ;; Optionally configure the register formatting. This improves the register 6: ;; preview for `consult-register', `consult-register-load', 7: ;; `consult-register-store' and the Emacs built-ins. 8: (setq register-preview-delay 0.5 9: register-preview-function #'consult-register-format) 10: ;; Optionally tweak the register preview window. 11: ;; This adds thin lines, sorting and hides the mode line of the window. 12: (advice-add #'register-preview :override #'consult-register-window) 13: ;; Use Consult to select xref locations with preview 14: (setq xref-show-xrefs-function #'consult-xref 15: xref-show-definitions-function #'consult-xref) 16: ;; Configure other variables and modes in the :config section, 17: ;; after lazily loading the package. 18: :config 19: ;; Optionally configure preview. The default value 20: ;; is 'any, such that any key triggers the preview. 21: ;; (setq consult-preview-key 'any) 22: ;; (setq consult-preview-key "M-.") 23: ;; (setq consult-preview-key '("S-<down>" "S-<up>")) 24: ;; For some commands and buffer sources it is useful to configure the 25: ;; :preview-key on a per-command basis using the `consult-customize' macro. 26: (consult-customize 27: consult-theme :preview-key '(:debounce 0.2 any) 28: consult-ripgrep consult-git-grep consult-grep 29: consult-bookmark consult-recent-file consult-xref 30: consult--source-bookmark consult--source-file-register 31: consult--source-recent-file consult--source-project-recent-file 32: ;; :preview-key "M-." 33: :preview-key '(:debounce 0.4 any)) 34: ;; Optionally configure the narrowing key. 35: ;; Both < and C-+ work reasonably well. 36: (setq consult-narrow-key "<") ;; "C-+" 37: ;; Optionally make narrowing help available in the minibuffer. 38: ;; You may want to use `embark-prefix-help-command' or which-key instead. 39: ;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help) 40: ;; By default `consult-project-function' uses `project-root' from project.el. 41: ;; Optionally configure a different project root function. 42: ;;;; 1. project.el (the default) 43: ;; (setq consult-project-function #'consult--default-project--function) 44: ;;;; 2. vc.el (vc-root-dir) 45: ;; (setq consult-project-function (lambda (_) (vc-root-dir))) 46: ;;;; 3. locate-dominating-file 47: ;; (setq consult-project-function (lambda (_) (locate-dominating-file "." ".git"))) 48: ;;;; 4. projectile.el (projectile-project-root) 49: ;; (autoload 'projectile-project-root "projectile") 50: ;; (setq consult-project-function (lambda (_) (projectile-project-root))) 51: ;;;; 5. No project support 52: ;; (setq consult-project-function nil)) 53: ) 54:
orderless
- Basic Configuration
1: (use-package orderless 2: :ensure 3: :init 4: ;; Configure a custom style dispatcher (see the Consult wiki) 5: ;; (setq orderless-style-dispatchers '(+orderless-consult-dispatch orderless-affix-dispatch) 6: ;; orderless-component-separator #'orderless-escapable-split-on-space) 7: (setq completion-styles '(orderless basic) 8: completion-category-defaults nil 9: completion-category-overrides '((file (styles partial-completion)))))
- Basic Configuration
nerd-icons-corfu
1: (use-package nerd-icons-corfu 2: :ensure 3: :config 4: (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter) 5: (setq nerd-icons-corfu-mapping 6: '((array :style "cod" :icon "symbol_array" :face font-lock-type-face) 7: (boolean :style "cod" :icon "symbol_boolean" :face font-lock-builtin-face) 8: ;; ... 9: (t :style "cod" :icon "code" :face font-lock-warning-face))))
nerd-icons-completion
1: (use-package nerd-icons-completion 2: :ensure 3: :hook (marginalia-mode . nerd-icons-completion-marginalia-setup) 4: :config 5: (nerd-icons-completion-mode))
Shells
eshell
A shell-like command interpreter implemented in Emacs Lisp.
1: (use-package eshell 2: :ensure nil 3: :custom 4: (eshell-history-size 10000) 5: (eshell-hist-ignore-dups t) 6: (eshell-buffer-maximum-lines 10000) 7: (eshell-scroll-to-bottom-on-input t) 8: (eshell-destroy-buffer-when-process-dies t) 9: (eshell-prompt-regexp "^[^\)]*[\)] "))
eshell-syntax-highlighting
1: (use-package eshell-syntax-highlighting 2: :ensure 3: :defer t 4: :after eshell 5: :config 6: (eshell-syntax-highlighting-global-mode +1))
esh-autosuggest
1: (use-package esh-autosuggest 2: :defer t 3: :hook (eshell-mode . esh-autosuggest-mode) 4: ;; If you have use-package-hook-name-suffix set to nil, uncomment and use the 5: ;; line below instead: 6: ;; :hook (eshell-mode-hook . esh-autosuggest-mode) 7: :ensure t)
sh-script
1: (use-package sh-script 2: :mode ("\\.bats\\'" . sh-mode) 3: :mode ("\\.\\(?:zunit\\|env\\)\\'" . sh-mode) 4: :mode ("/bspwmrc\\'" . sh-mode) 5: :hook (sh-mode-local-vars . lsp-deferred) 6: :hook (sh-mode-local-vars . tree-sitter-mode) 7: :config 8: (with-eval-after-load 'lsp 9: (add-hook 'sh-mode-hook #'lsp-deferred) 10: (add-hook 'shell-mode-hook #'lsp-deferred) 11: (add-hook 'sh-mode-local-vars-hook #'lsp-deferred)) 12: (with-eval-after-load 'rainbow-delimiters 13: (add-hook 'sh-mode #'rainbow-delimiters-mode)) 14: ;; recognize function names with dashes in them 15: (setq sh-indent-after-continuation 'always) 16: (add-to-list 'sh-imenu-generic-expression 17: '(sh (nil "^\\s-*function\\s-+\\([[:alpha:]_-][[:alnum:]_-]*\\)\\s-*\\(?:()\\)?" 1) 18: (nil "^\\s-*\\([[:alpha:]_-][[:alnum:]_-]*\\)\\s-*()" 1))) 19: (with-eval-after-load 'smartparens 20: (sp-local-pair 'sh-mode "`" "`" :unless '(sp-point-before-word-p sp-point-before-same-p))))
vterm
1: (use-package vterm 2: :ensure 3: :defer t 4: :commands vterm-mode 5: :config 6: (add-hook 'vterm-mode-hook 7: (lambda () 8: (setq-local global-hl-line-mode nil) 9: (setq-local hscroll-margin 0))) 10: (setq vterm-kill-buffer-on-exit t) 11: :general 12: (+config/leader-menu! "vterm" 13: "tv" 14: "RET" 'vterm-toggle 15: "v" 'vterm))
multi-vterm
1: (use-package multi-vterm 2: :ensure 3: :defer t 4: :after vterm 5: :general 6: (general-iemap 7: :keymaps 'vterm-mode-map 8: "C-SPC" '(:ignore t :wk "multi vterm") 9: "C-SPC a" '(multi-vterm :wk "new vterm buffer") 10: "C-SPC n" '(multi-vterm-next :wk "next vterm buffer") 11: "C-SPC p" '(multi-vterm-prev :wk "previous vterm buffer")))
vterm-toggle
disabled
1: (use-package vterm-toggle 2: :ensure 3: :defer t 4: :after vterm 5: :commands vterm-toggle 6: :bind 7: (:map vterm-mode-map 8: ("C-<return>" . vterm-toggle-insert-cd)) 9: :config 10: (setq vterm-toggle-fullscreen-p nil) 11: (add-to-list 'display-buffer-alist 12: '((lambda (buffer-or-name _) 13: (let ((buffer (get-buffer buffer-or-name))) 14: (with-current-buffer buffer 15: (or (equal major-mode 'vterm-mode) 16: (string-prefix-p vterm-buffer-name (buffer-name buffer)))))) 17: (display-buffer-reuse-window display-buffer-at-bottom) 18: ;;(display-buffer-reuse-window display-buffer-in-direction) 19: ;;display-buffer-in-direction/direction/dedicated is added in emacs27 20: ;;(direction . bottom) 21: (dedicated . t) ;dedicated is supported in emacs27 22: (reusable-frames . visible) 23: (window-height . 0.4))))
bash-completion
disabled
1: (use-package bash-completion 2: :ensure 3: :defer t 4: :config 5: (bash-completion-setup) 6: :hook 7: (shell-dynamic-complete-function bash-completion-dynamic-complete))
Editing
select
1: (use-package select 2: :custom 3: (select-enable-clipboard t))
transient-mark-mode
Highlight region.
1: (transient-mark-mode 1)
delete-selection-mode
When enabled, typed text replaces the selection if the selection is active. Otherwise, typed text is just inserted at point regardless of any selection.
1: (delete-selection-mode 1)
subword
1: (use-package subword 2: :init 3: (global-subword-mode 1))
text-mode
1: (use-package text-mode 2: :ensure nil 3: :hook (text-mode . visual-line-mode) 4: :config 5: (setq-default sentence-end-double-space nil))
ws-butler
(use-package ws-butler :ensure :hook (prog-mode . ws-butler-mode))
smartparens
I still have a mixed feeling for this package, but it still easier to configure than the builtin electric-pair-mode. Also, should this be in the Lisp section?
1: ;; smartparens 2: (use-package smartparens 3: :ensure 4: :demand t 5: :init 6: (smartparens-global-mode) 7: :config 8: ;; smartparens recognizes `slime-mrepl-mode', but not `sly-mrepl-mode', so... 9: (add-to-list 'sp-lisp-modes 'sly-mrepl-mode) 10: (require 'smartparens-config) 11: (add-hook 'eval-expression-minibuffer-setup-hook #'smartparens-mode) 12: ;; Overlays are too distracting and not terribly helpful. show-parens does 13: ;; this for us already (and is faster), so... 14: (setq sp-highlight-pair-overlay nil 15: sp-highlight-wrap-overlay nil 16: sp-highlight-wrap-tag-overlay nil) 17: (show-smartparens-global-mode 1) 18: (smartparens-global-mode 1) 19: ;; Fix usage of ' in Lisp modes 20: ;; THANKS: https://github.com/Fuco1/smartparens/issues/286#issuecomment-32324743 21: ;; (eval) is used as a hack to quiet Flycheck errors about (sp-with-modes) 22: (eval 23: '(sp-with-modes sp-lisp-modes 24: ;; disable ', it's the quote character! 25: (sp-local-pair "'" nil :actions nil) 26: ;; also only use the pseudo-quote inside strings where it serve as 27: ;; hyperlink. 28: (sp-local-pair "`" "'" :when '(sp-in-string-p sp-in-comment-p)) 29: (sp-local-pair "`" nil 30: :skip-match (lambda (ms mb me) 31: (cond 32: ((equal ms "'") 33: (or (sp--org-skip-markup ms mb me) 34: (not (sp-point-in-string-or-comment)))) 35: (t (not (sp-point-in-string-or-comment)))))))) 36: (sp-with-modes '(html-mode sgml-mode nxml-mode web-mode) 37: (sp-local-pair "<" ">")) 38: 39: (defun sp--markdown-skip-asterisk (ms mb me) 40: (save-excursion 41: (goto-char mb) 42: (save-match-data (looking-at "^\\* ")))) 43: 44: (sp-with-modes 'markdown-mode 45: (sp-local-pair "*" "*" 46: :unless '(sp-point-after-word-p sp-point-at-bol-p) 47: :skip-match 'sp--markdown-skip-asterisk) 48: (sp-local-pair "**" "**") 49: (sp-local-pair "_" "_" :unless '(sp-point-after-word-p))) 50: 51: ;;; org-mode 52: (defun sp--org-skip-asterisk (ms mb me) 53: (or (and (= (line-beginning-position) mb) 54: (eq 32 (char-after (1+ mb)))) 55: (and (= (1+ (line-beginning-position)) me) 56: (eq 32 (char-after me))))) 57: (defun sp--org-inside-LaTeX (id action context) 58: (org-inside-LaTeX-fragment-p)) 59: (sp-with-modes 'org-mode 60: (sp-local-pair "*" "*" 61: :unless '(sp-point-after-word-p sp--org-inside-LaTeX sp-point-at-bol-p) 62: :skip-match 'sp--org-skip-asterisk) 63: (sp-local-pair "/" "/" :unless '(sp-point-after-word-p sp--org-inside-LaTeX)) 64: (sp-local-pair "~" "~" :unless '(sp-point-after-word-p sp--org-inside-LaTeX)) 65: (sp-local-pair "=" "=" :unless '(sp-point-after-word-p sp--org-inside-LaTeX)) 66: (sp-local-pair "\\[" "\\]")) 67: 68: ;; haskell 69: (add-to-list 'sp-no-reindent-after-kill-modes 'haskell-mode) 70: 71: ;; You're likely writing lisp in the minibuffer, therefore, disable these 72: ;; quote pairs, which lisps doesn't use for strings: 73: (sp-local-pair '(minibuffer-mode minibuffer-inactive-mode) "'" nil :actions nil) 74: (sp-local-pair '(minibuffer-mode minibuffer-inactive-mode) "`" nil :actions nil) 75: )
The keybinding I got from the example configuration messes up my evil-mode. I have them commented for now.
IDE stuffs
magit
external
1: (use-package magit 2: :ensure 3: :demand t 4: :config 5: (evil-set-initial-state #'git-commit-mode 'insert) 6: :custom 7: (magit-revision-show-gravatars '("^Author: " . "^Commit: ")) 8: (magit-diff-refine-hunk 'all) 9: (magit-log-arguments '("-n100" "--graph" "--decorate")) 10: :general 11: (+config/leader-go 12: "g" 'magit-status))
projectile
external
A project interaction library for Emacs, with little external dependency as possible.
1: (use-package projectile 2: :ensure t 3: :demand t 4: :bind (([remap evil-jump-to-tag] . projectile-find-tag) 5: ([remap find-tag] . projectile-find-tag)) 6: :hook (dired-before-readin . projectile-track-known-projects-find-file-hook) 7: :custom 8: (projectile-cache-file (expand-file-name ".projects" user-emacs-directory)) 9: (projectile-auto-discover nil) 10: (projectile-enable-caching (not noninteractive)) 11: (projectile-globally-ignored-files '("DS_Store" "TAGS")) 12: (projectile-globally-ignored-file-suffixes '(".elc" ".pyc" ".o")) 13: (projectile-kill-buffers-filter 'kill-only-files) 14: (projectile-known-projects-file (expand-file-name ".projectile_projects.eld" user-emacs-directory)) 15: (projectile-ignored-projects '("~/")) 16: (projectile-project-root-files-bottom-up 17: (append '(".projectile" ".project" ".git") 18: (when (executable-find "hg") 19: '(".hg")) 20: (when (executable-find "bzr") 21: '(".bzr")))) 22: (projectile-project-root-files-top-down-recurring '("Makefile")) 23: (compilation-buffer-name-function #'projectile-compilation-buffer-name) 24: (compilation-save-buffers-predicate #'projectile-current-project-buffer-p) 25: (projectile-git-submodule-command nil) 26: (projectile-indexing-method 'hybrid) 27: :config 28: (projectile-mode +1) 29: (put 'projectile-git-submodule-command 'initial-value projectile-git-submodule-command) 30: :general 31: (+config/leader-key 32: "SPC" 'projectile-find-file 33: "p" '(:keymap projectile-command-map :package projectile :wk "projectile")))
diff-hl
external
1: (use-package diff-hl 2: :ensure 3: :hook (find-file . diff-hl-mode) 4: :hook (vc-dir-mode . diff-hl-dir-mode) 5: :hook (dired-mode . diff-hl-dired-mode) 6: :hook (diff-hl-mode . diff-hl-flydiff-mode) 7: :hook (diff-hl-mode . diff-hl-show-hunk-mouse-mode) 8: :hook (magit-pre-refresh-hook . diff-hl-magit-pre-refresh) 9: :hook (magit-post-refresh-hook . diff-hl-magit-post-refresh) 10: :init 11: (global-diff-hl-mode) 12: :custom 13: (vc-git-diff-switches '("--histogram") 14: diff-hl-flydiff-delay 0.5 15: diff-hl-show-staged-changes nil) 16: :config 17: (when (featurep 'flycheck) 18: (setq flycheck-indication-mode 'right-fringe)))
perspective
external
Useful when I'm working on several projectile projects at once. With each perspective having their own separate buffer list.
1: (use-package perspective 2: :ensure 3: :config 4: (setq persp-initial-frame-name "Main" 5: persp-suppress-no-prefix-key-warning t) 6: (if (featurep 'no-littering) 7: (setq persp-state-default-file (expand-file-name ".perspective-state" no-littering-var-directory)) 8: (setq persp-state-default-file (expand-file-name ".perspective-state" user-emacs-directory))) 9: (global-set-key [remap switch-to-buffer] #'persp-switch-to-buffer*) 10: (when (featurep 'consult) 11: (require 'consult) 12: (unless (boundp 'persp-consult-source) 13: (defvar persp-consult-source 14: (list :name "Perspective" 15: :narrow ?s 16: :category 'buffer 17: :state #'consult--buffer-state 18: :history 'buffer-name-history 19: :default t 20: :items 21: #'(lambda () (consult--buffer-query :sort 'visibility 22: :predicate '(lambda (buf) (persp-is-current-buffer buf t)) 23: :as #'buffer-name))))) 24: (consult-customize consult--source-buffer :hidden t :default nil) 25: (add-to-list 'consult-buffer-sources persp-consult-source)) 26: :init 27: (customize-set-variable 'persp-mode-prefix-key (kbd "C-c TAB")) 28: (unless (equal persp-mode t) 29: (persp-mode 1)) 30: :bind (([remap switch-to-buffer] . persp-switch-to-buffer*) 31: ([remap kill-buffer] . persp-kill-buffer*)) 32: :hook (kill-emacs . persp-state-save) 33: :general 34: (general-def 35: :keymaps 'perspective-map 36: "TAB" '(persp-switch-last :wk "switch to last perspective") 37: "P" 'projectile-persp-switch-project) 38: (+config/leader-key 39: "TAB" (general-simulate-key "C-c TAB" 40: :state '(normal visual) 41: :name general-SPC-h-simulates-C-c-TAB 42: :docstring "Simulates C-c TAB in normal and visual mode." 43: :which-key "Perspective")) 44: (+config/leader-key 45: "C-x" '(persp-switch-to-scratch-buffer :wk "switch to scratch buffer")))
persp-projectile
external
1: (use-package persp-projectile 2: :ensure t 3: :after perspective 4: :commands projectile-persp-switch-project 5: :general 6: (general-def 7: :keymaps 'perspective-map 8: "P" 'projectile-persp-switch-project))
git-link
external
1: (use-package git-link 2: :demand 3: :ensure 4: :commands (git-link git-link-commit git-link-homepage) 5: :general 6: (+config/leader-go 7: "G" '(:ignore t :wk "git") 8: "Gl" 'git-link 9: "Gh" 'git-link-homepage 10: "Gc" 'git-link-commit))
git-messenger
external
1: (use-package git-messenger 2: :ensure 3: :config 4: (with-eval-after-load 'general 5: (+config/leader-go 6: "Gm" 'git-messenger:popup-message)) 7: :custom 8: ;; Enable magit-show-commit instead of pop-to-buffer 9: (git-messenger:use-magit-popup t) 10: (git-messenger:show-detail t))
git-timemachine
external
1: (use-package git-timemachine 2: :ensure 3: :after magit 4: :general 5: (+config/leader-go 6: "Gt" 'git-timemachine-toggle))
org-project-capture
external
1: (use-package org-project-capture 2: :bind (("C-c n p" . org-project-capture-project-todo-completing-read)) 3: :ensure t 4: :config 5: (progn 6: (setq org-project-capture-backend 7: (make-instance 'org-project-capture-projectile-backend)) ; Replace with your backend of choice 8: (setq org-project-capture-projects-file (expand-file-name "projects.org" org-directory)) 9: (org-project-capture-single-file)))
lsp
external
- Basic configuration
- LSP
1: (use-package lsp-mode 2: :ensure 3: :init 4: (setq lsp-keymap-prefix "C-c C-l") 5: (defun my/orderless-dispatch-flex-first (_pattern index _total) 6: (and (eq index 0) 'orderless-flex)) 7: (defun my/lsp-mode-setup-completion () 8: (setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults)) 9: '(orderless))) 10: (add-hook 'orderless-style-dispatchers #'my/orderless-dispatch-flex-first nil 'local) 11: (when (featurep 'cape) 12: (setq-local completion-at-point-functions (list (cape-capf-buster #'lsp-completion-at-point)))) 13: :hook 14: (lsp-mode . lsp-enable-which-key-integration) 15: (lsp-completion-mode . my/lsp-mode-setup-completion) 16: ((c-mode c++-mode xml-mode python-mode 17: yaml-mode toml-mode python-mode-local-vars 18: lua-mode jinja2-mode 19: json-mode html-mode 20: web-mode html-mode-local-vars-hook 21: web-mode-local-vars-hook nxml-mode-local-vars-hook 22: scss-mode-local-vars css-mode-local-vars 23: less-css-mode-local-vars css-mode 24: typescript-mode javascript-mode 25: js2-mode typescript-tsx-mode) . lsp-deferred) 26: :config 27: (setq lsp-toml-command 28: (if (file-exists-p (expand-file-name ".cargo/bin/taplo" "~")) 29: (expand-file-name ".cargo/bin/taplo" "~") 30: "taplo") 31: lsp-rust-rls-server-command "rls" 32: lsp-eldoc-render-all t 33: lsp-enable-snippet nil 34: lsp-enable-indentation nil 35: lsp-prefer-flymake nil 36: lsp-keep-workspace-alive nil 37: lsp-modeline-code-actions-segments '(count icon name)) 38: (when (featurep 'exwm) 39: (advice-add #'corfu--make-frame :around 40: (defun +corfu--make-frame-a (oldfun &rest args) 41: (cl-letf (((symbol-function #'frame-parent) 42: (lambda (frame) 43: (or (frame-parameter frame 'parent-frame) 44: exwm-workspace--current)))) 45: (apply oldfun args)) 46: (when exwm--connection 47: (set-frame-parameter corfu--frame 'parent-frame nil)))) 48: 49: (advice-add #'corfu--popup-redirect-focus :override 50: (defun +corfu--popup-redirect-focus-a () 51: (redirect-frame-focus corfu--frame 52: (or (frame-parent corfu--frame) 53: exwm-workspace--current))))) 54: :custom 55: (lsp-completion-provider :none) 56: :general 57: (+config/leader-key 58: :keymaps 'lsp-mode-map 59: "l" (general-simulate-key "C-c C-l" 60: :name general-SPC-l-simulates-C-c-C-l 61: :docstring "Simulates C-c C-l" 62: :which-key "LSP")))
lsp-ui
1: (use-package lsp-ui 2: :ensure 3: :defer t 4: :hook (lsp-mode . lsp-ui-mode) 5: :init 6: (setq lsp-ui-sideline-enable t 7: lsp-ui-sideline-update-mode 'line 8: lsp-ui-sideline-show-code-actions t 9: lsp-ui-sideline-show-hover t 10: lsp-ui-doc-enable t 11: lsp-ui-doc-include-signature t 12: lsp-ui-doc-show-with-cursor t 13: lsp-eldoc-enable-hover nil ; Disable eldoc displays in minibuffer 14: lsp-ui-doc-position 'at-point 15: lsp-ui-imenu-enable t 16: lsp-ui-sideline-ignore-duplicate t 17: lsp-ui-peek-enable t) 18: :config 19: (define-key lsp-ui-mode-map [remap xref-find-definitions] #'lsp-ui-peek-find-definitions) 20: (define-key lsp-ui-mode-map [remap xref-find-references] #'lsp-ui-peek-find-references) 21: (add-to-list 'lsp-language-id-configuration '(jinja2-mode . "jinja2") t) 22: (add-to-list 'lsp-language-id-configuration '("\\.js2$" . "jinja2") t) 23: :general 24: (general-define-key 25: :keymaps '(lsp-ui-mode-map) 26: [remap xref-find-definitions] 'lsp-ui-peek-find-definitions 27: [remap xref-find-references] 'lsp-ui-peek-find-references 28: "M-." 'lsp-ui-peek-find-definitions 29: "M-?" 'lsp-ui-peek-find-references))
consult-lsp
1: (use-package consult-lsp 2: :ensure 3: :after consult lsp 4: :bind 5: (:map lsp-mode-map 6: ([remap xref-find-apropos] . consult-lsp-symbols)))
- LSP
org-mode
org-mode
1: (use-package org 2: :commands org-tempo 3: :preface 4: (if (not +config/org-directory) 5: (cond 6: ((file-directory-p 7: (expand-file-name "Dropbox/org" (getenv "HOME"))) 8: (setq org-directory (expand-file-name "Dropbox/org" (getenv "HOME")))) 9: ((file-directory-p 10: (expand-file-name "Sync/org" (getenv "HOME"))) 11: (setq org-directory (expand-file-name "Sync/org" (getenv "HOME")))) 12: ((file-directory-p 13: (expand-file-name "Documents/google-drive/org" (getenv "HOME"))) 14: (setq org-directory (expand-file-name "Documents/google-drive/org" (getenv "HOME"))))) 15: (customize-set-variable 'org-directory +config/org-directory)) 16: :hook ((org-mode . org-indent-mode) 17: (org-mode . +config/org-prettify-symbols)) 18: :config 19: (global-set-key (kbd "C-c l") #'org-store-link) 20: (global-set-key (kbd "C-c a") #'org-agenda) 21: (global-set-key (kbd "C-c c") #'org-capture) 22: (when(file-directory-p (expand-file-name "braindump/org" org-directory)) 23: (customize-set-variable '+config/org-roam-directory 24: (expand-file-name "braindump/org" org-directory))) 25: (when (file-directory-p (expand-file-name "alexforsale.github.io" org-directory)) 26: (customize-set-variable '+config/blog-directory 27: (expand-file-name "alexforsale.github.io" org-directory))) 28: (modify-syntax-entry ?= "$" org-mode-syntax-table) 29: (modify-syntax-entry ?~ "$" org-mode-syntax-table) 30: (modify-syntax-entry ?_ "$" org-mode-syntax-table) 31: (modify-syntax-entry ?+ "$" org-mode-syntax-table) 32: (modify-syntax-entry ?/ "$" org-mode-syntax-table) 33: (modify-syntax-entry ?* "$" org-mode-syntax-table) 34: (add-to-list 'org-modules 'org-tempo t) 35: (add-to-list 'org-structure-template-alist '("sh" . "src sh")) 36: (add-to-list 'org-structure-template-alist '("co" . "src conf")) 37: (add-to-list 'org-structure-template-alist '("lisp" . "src lisp")) 38: (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) 39: (add-to-list 'org-structure-template-alist '("sc" . "src scheme")) 40: (add-to-list 'org-structure-template-alist '("ts" . "src typescript")) 41: (add-to-list 'org-structure-template-alist '("py" . "src python")) 42: (add-to-list 'org-structure-template-alist '("go" . "src go")) 43: (add-to-list 'org-structure-template-alist '("yaml" . "src yaml")) 44: (add-to-list 'org-structure-template-alist '("js" . "src js")) 45: (add-to-list 'org-structure-template-alist '("json" . "src json")) 46: (add-to-list 'org-structure-template-alist '("n" . "note")) 47: (org-babel-do-load-languages 48: 'org-babel-load-languages 49: '((emacs-lisp . t) 50: (awk . t) 51: (C . t) 52: (css . t) 53: (calc . t) 54: ;; (ditaa . t) ; needs the `ditaa' package 55: ;; (diagrams . t) ; `ob-diagrams' 56: ;; (dot . t ) ; `graphviz' 57: (screen . t) 58: (haskell . t) 59: (java . t) 60: (js . t) 61: (latex . t) 62: (lisp . t) 63: (lua . t) 64: (org . t) 65: (perl . t) 66: (plantuml . t) 67: (python .t) 68: (ruby . t) 69: (shell . t) 70: (sed . t) 71: (scheme . t) 72: (sql . t) 73: (sqlite . t))) 74: (setq-default org-use-sub-superscripts '{}) 75: (add-to-list 'org-babel-tangle-lang-exts '("js" . "js")) 76: (defun +config/org-prettify-symbols () 77: (push '("[ ]" . "☐") prettify-symbols-alist) 78: (push '("[X]" . "☑") prettify-symbols-alist) 79: (prettify-symbols-mode)) 80: :custom 81: (org-replace-disputed-keys t) 82: (org-indirect-buffer-display 'current-window) 83: (org-enforce-todo-dependencies t) 84: (org-fontify-whole-heading-line t) 85: (org-return-follows-link t) 86: (org-mouse-1-follows-link t) 87: (org-image-actual-width nil) 88: (org-adapt-indentation nil) 89: (org-startup-indented t) 90: (org-link-descriptive nil) 91: (org-log-done 'time) 92: (org-log-refile 'time) 93: (org-log-redeadline 'time) 94: (org-log-reschedule 'time) 95: (org-log-into-drawer t) 96: (org-clone-delete-id t) 97: (org-default-notes-file (expand-file-name "notes.org" org-directory)) 98: (org-insert-heading-respect-content nil) 99: (org-pretty-entities t) 100: (org-use-property-inheritance t) 101: (org-priority-highest ?A) 102: (org-priority-lowest ?D) 103: (org-priority-default ?B) 104: (org-todo-keywords 105: '((sequence 106: "TODO(t!)" ; A task that needs doing & is ready to do 107: "NEXT(n!)" ; Tasks that can be delayed 108: "PROG(p!)" ; A task that is in progress 109: "WAIT(w!)" ; Something external is holding up this task 110: "HOLD(h!)" ; This task is paused/on hold because of me 111: "|" 112: "DONE(d!)" ; Task successfully completed 113: "DELEGATED(l!)" ; Task is delegated 114: "KILL(k!)") ; Task was cancelled, aborted or is no longer applicable 115: )) 116: (org-todo-keyword-faces 117: '(("PROG" . (:foreground "#5e81ac" :weight bold)) 118: ("WAIT" . (:foreground "#ebcb8b" :weight bold)) 119: ("HOLD" . (:foreground "#d08770" :weight bold)) 120: ("NEXT" . (:foreground "#81a1c1" :weight bold)) 121: ("DELEGATED" . "#8fbcbb") 122: ("KILL" . "#a3be8c"))))
org-faces
1: (use-package org-faces 2: :custom 3: (org-fontify-quote-and-verse-blocks t))
org-archive
1: (use-package org-archive 2: :after org 3: :custom 4: (org-archive-tag "archive") 5: (org-archive-subtree-save-file-p t) 6: (org-archive-mark-done t) 7: (org-archive-reversed-order t) 8: (org-archive-location (concat (expand-file-name "archives.org" org-directory) "::datetree/* Archived Tasks")))
org-capture
1: (use-package org-capture 2: :after org 3: :demand t 4: :config 5: (org-capture-put :kill-buffer t) 6: (setq org-capture-templates ;; this is the default from `doom'. 7: `(("i" "Inbox - Goes Here first!" entry 8: (file+headline ,(expand-file-name "inbox.org" org-directory) "Inbox") 9: "** %?\n%i\n%a" :prepend t) 10: ("r" "Request" entry (file+headline ,(expand-file-name "inbox.org" org-directory) "Request") 11: (file ,(expand-file-name "request.template" org-directory))) 12: ("l" "Links" entry 13: (file+headline ,(expand-file-name "links.org" org-directory) "Links")))))
org-refile
1: (use-package org-refile 2: :after org 3: :hook (org-after-refile-insert . save-buffer) 4: :custom 5: (org-refile-targets 6: `((,(expand-file-name "projects.org" org-directory) :maxlevel . 1) 7: (,(expand-file-name "routines.org" org-directory) :maxlevel . 1) 8: (,(expand-file-name "personal.org" org-directory) :maxlevel . 1))) 9: (org-refile-use-outline-path 'file) 10: (org-outline-path-complete-in-steps nil))
org-fold
1: (use-package org-fold 2: :after org org-contrib 3: :custom 4: (org-catch-invisible-edits 'smart))
org-id
1: (use-package org-id 2: :after org 3: :custom 4: (org-id-locations-file-relative t) 5: (org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id))
org-num
1: (use-package org-num 2: :after org 3: :custom 4: (org-num-face '(:inherit org-special-keyword :underline nil :weight bold)) 5: (org-num-skip-tags '("noexport" "nonum")))
org-crypt
1: (use-package org-crypt ; built-in 2: :after org 3: :commands org-encrypt-entries org-encrypt-entry org-decrypt-entries org-decrypt-entry 4: ;;:hook (org-reveal-start . org-decrypt-entry) 5: :preface 6: ;; org-crypt falls back to CRYPTKEY property then `epa-file-encrypt-to', which 7: ;; is a better default than the empty string `org-crypt-key' defaults to. 8: (defvar org-crypt-key nil) 9: (with-eval-after-load 'org 10: (add-to-list 'org-tags-exclude-from-inheritance "crypt")))
org-attach
1: (use-package org-attach 2: :after org 3: :commands (org-attach-new 4: org-attach-open 5: org-attach-open-in-emacs 6: org-attach-reveal-in-emacs 7: org-attach-url 8: org-attach-set-directory 9: org-attach-sync) 10: :config 11: (unless org-attach-id-dir 12: (setq-default org-attach-id-dir (expand-file-name ".attach/" org-directory))) 13: (with-eval-after-load 'projectile 14: (add-to-list 'projectile-globally-ignored-directories org-attach-id-dir)) 15: :custom 16: (org-attach-auto-tag nil))
org-agenda
1: (use-package org-agenda 2: :after org 3: :custom 4: (org-agenda-files (list (concat org-directory "/"))) 5: (org-agenda-file-regexp "\\`[^.].*\\.org\\|[0-9]+$\\'") 6: (org-agenda-include-inactive-timestamps t) 7: (org-agenda-window-setup 'only-window) 8: (org-stuck-projects '("+{project*}-killed-Archives/-DONE-KILL-DELEGATED" 9: ("TODO" "NEXT" "IDEA" "PROG") 10: nil "")) 11: :config 12: (with-eval-after-load 'evil 13: (evil-set-initial-state #'org-agenda-mode 'normal)) 14: (setq org-agenda-custom-commands 15: `(("w" "Work Agenda and all TODOs" 16: ((agenda "" 17: ((org-agenda-span 1) 18: (org-agenda-start-on-weekday t) 19: (org-agenda-block-separator nil) 20: (org-agenda-use-time-grid t) 21: (org-agenda-day-face-function (lambda (date) 'org-agenda-date)) 22: (org-agenda-format-date "%A %-e %B %Y") 23: (org-agenda-overriding-header "\nToday\n"))) 24: (tags-todo "TODO=\"TODO\"|\"NEXT\"" 25: ((org-agenda-block-separator nil) 26: (org-agenda-skip-function '(org-agenda-skip-if-todo 'nottodo 'done)) 27: (org-agenda-use-time-grid nil) 28: (org-agenda-overriding-header "\nIncomplete\n"))) 29: (agenda "" 30: ((org-agenda-span 7) 31: (org-agenda-start-on-weekday 1) 32: (org-agenda-block-separator nil) 33: (org-agenda-use-time-grid nil) 34: (org-agenda-overriding-header "\nWeekly\n")))) 35: ((org-agenda-tag-filter-preset '("-personal" "-home")))) 36: ("h" "Home Agenda and all personal TODOs" 37: ((agenda "" 38: ((org-agenda-span 1) 39: (org-agenda-start-on-weekday t) 40: (org-agenda-block-separator nil) 41: (org-agenda-use-time-grid t) 42: (org-agenda-day-face-function (lambda (date) 'org-agenda-date)) 43: (org-agenda-format-date "%A %-e %B %Y") 44: (org-agenda-overriding-header "\nToday\n"))) 45: (tags-todo "TODO=\"TODO\"|\"NEXT\"" 46: ((org-agenda-block-separator nil) 47: (org-agenda-skip-function '(org-agenda-skip-if-todo 'nottodo 'done)) 48: (org-agenda-use-time-grid nil) 49: (org-agenda-overriding-header "\nIncomplete\n"))) 50: (agenda "" 51: ((org-agenda-span 7) 52: (org-agenda-start-on-weekday 1) 53: (org-agenda-block-separator nil) 54: (org-agenda-use-time-grid nil) 55: (org-agenda-overriding-header "\nWeekly\n")))) 56: ((org-agenda-tag-filter-preset '("+personal")))))))
org-clock
1: (use-package org-clock 2: :after org 3: :commands org-clock-save 4: :hook (kill-emacs . org-clock-save) 5: :custom 6: (org-persist 'history) 7: (org-clock-in-resume t) 8: (org-clock-out-remove-zero-time-clocks t) 9: (org-clock-history-length 20) 10: (org-show-notification-handler "notify-send") 11: (org-agenda-skip-scheduled-if-deadline-is-shown t) 12: :config 13: (org-clock-persistence-insinuate))
org-timer
1: (use-package org-timer 2: :config 3: (setq org-timer-format "Timer :: %s"))
org-eldoc
1: (use-package org-eldoc 2: :after org org-contrib 3: :config 4: (puthash "org" #'ignore org-eldoc-local-functions-cache) 5: (puthash "plantuml" #'ignore org-eldoc-local-functions-cache) 6: (puthash "python" #'python-eldoc-function org-eldoc-local-functions-cache) 7: :custom 8: (org-eldoc-breadcrumb-separator " → "))
org-superstar
external
1: (use-package org-superstar 2: :ensure 3: :hook (org-mode . org-superstar-mode) 4: :custom 5: (org-superstar-leading-bullet ?\s) 6: (org-superstar-leading-fallback ?\s) 7: (org-hide-leading-stars nil) 8: (org-indent-mode-turns-on-hiding-stars nil) 9: (org-superstar-todo-bullet-alist 10: '(("TODO" . 9744) 11: ("[ ]" . 9744) 12: ("DONE" . 9745) 13: ("[X]" . 9745))) 14: :config 15: (org-superstar-configure-like-org-bullets))
org-fancy-priority
external
1: (use-package org-fancy-priorities ; priority icons 2: :ensure 3: :defer t 4: :hook (org-mode . org-fancy-priorities-mode) 5: :hook (org-agenda-mode . org-fancy-priorities-mode) 6: :custom 7: (org-fancy-priorities-list '("⚡" "⬆" "⬇" "☕")))
org-modern
external
(use-package org-modern :ensure t :demand t :config (set-face-attribute 'org-modern-symbol nil :family "Iosevka Nerd Font") (setq ;; Edit settings org-auto-align-tags nil org-tags-column 0 org-fold-catch-invisible-edits 'show-and-error org-special-ctrl-a/e t org-insert-heading-respect-content t ;; Org styling, hide markup etc. org-hide-emphasis-markers nil ; set to nil for easier editing org-ellipsis "…" ;; Agenda styling org-agenda-tags-column 0 org-agenda-block-separator ?─ org-agenda-time-grid '((daily today require-timed) (800 1000 1200 1400 1600 1800 2000) " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄") org-agenda-current-time-string "◀── now ─────────────────────────────────────────────────") (global-org-modern-mode))
Other Tools
make-mode
1: (use-package make-mode 2: :config 3: (add-hook 'makefile-mode-hook 'indent-tabs-mode))
executable
1: (use-package executable 2: :hook 3: (after-save . executable-make-buffer-file-executable-if-script-p))
pinentry
1: (use-package pinentry 2: :ensure 3: :defer t 4: :config 5: (pinentry-start))
pass
1: (use-package password-store 2: :ensure 3: :defer t 4: :config 5: (setq password-store-password-length 12)) 6: 7: (use-package password-store-otp 8: :ensure 9: :defer t 10: :after password-store) 11: 12: (use-package pass 13: :ensure 14: :defer t) 15: 16: (use-package auth-source-pass 17: :init 18: (auth-source-pass-enable))
rg
Packaged as ripgrep
in archlinux. The :if
keyword won't load this if the executable not found.
1: (use-package rg 2: :if (executable-find "rg") 3: :ensure 4: :defer t)
Dired
Stands for Directory Editor (I guess), is a builtin file manager for Emacs.
dired
1: (use-package dired 2: :commands dired-jump 3: :init 4: (setq dired-dwim-target t ; guess a default target directory 5: dired-hide-details-hide-symlink-targets nil ; don't hide symbolic link targets 6: dired-auto-revert-buffer #'dired-buffer-stale-p ; revert stale only 7: dired-recursive-copies 'always ; always copy recursively 8: dired-recursive-deletes 'top ; ask only for top-level 9: dired-create-destination-dirs 'ask 10: dired-clean-confirm-killing-deleted-buffers nil))
image-dired
1: (use-package image-dired 2: :config 3: (setq image-dired-thumb-size 150))
dired-x
1: (use-package dired-x 2: :hook (dired-mode . dired-omit-mode) 3: :config 4: (setq dired-omit-files 5: (concat dired-omit-files 6: "\\|^\\.DS_Store\\'" 7: "\\|^\\.project\\(?:ile\\)?\\'" 8: "\\|^\\.\\(?:svn\\|git\\)\\'" 9: "\\|^\\.ccls-cache\\'" 10: "\\|\\(?:\\.js\\)?\\.meta\\'" 11: "\\|\\.\\(?:elc\\|o\\|pyo\\|swp\\|class\\)\\'")) 12: ;; Disable the prompt about whether I want to kill the Dired buffer for a 13: ;; deleted directory. Of course I do! 14: (setq dired-clean-confirm-killing-deleted-buffers nil) 15: (let ((cmd "xdg-open")) 16: (setq dired-guess-shell-alist-user 17: `(("\\.\\(?:docx\\|pdf\\|djvu\\|eps\\)\\'" ,cmd) 18: ("\\.\\(?:jpe?g\\|png\\|gif\\|xpm\\)\\'" ,cmd) 19: ("\\.\\(?:xcf\\)\\'" ,cmd) 20: ("\\.csv\\'" ,cmd) 21: ("\\.tex\\'" ,cmd) 22: ("\\.\\(?:mp4\\|mkv\\|avi\\|flv\\|rm\\|rmvb\\|ogv\\)\\(?:\\.part\\)?\\'" ,cmd) 23: ("\\.\\(?:mp3\\|flac\\)\\'" ,cmd) 24: ("\\.html?\\'" ,cmd) 25: ("\\.md\\'" ,cmd)))))
fd-dired
external
Needs an external package fd
, or fd-find
1: (use-package fd-dired 2: :ensure 3: :if (executable-find "fd") 4: :defer t 5: :init 6: (global-set-key [remap find-dired] #'fd-dired))
dired-git-info
1: (use-package dired-git-info 2: :ensure 3: :defer t 4: ;; :hook 5: ;; (dired-after-readin . dired-git-info-auto-enable) 6: :config 7: ;; (setq +dired--git-info-p (bound-and-true-p dired-git-info-mode)) 8: ;; (when +dired--git-info-p 9: ;; (dired-git-info-mode -1)) 10: (setq dgi-auto-hide-details-p nil))
dired-aux
1: (use-package dired-aux 2: :config 3: (setq dired-create-destination-dirs 'ask 4: dired-vc-rename-file t))
dired-rsync
1: (use-package dired-rsync 2: :ensure 3: :defer t)
diredfl
1: (use-package diredfl 2: :ensure 3: :defer t 4: :hook (dired-mode . diredfl-global-mode))
TODO Treemacs
treemacs
1: (use-package treemacs 2: :ensure 3: :hook ((treemacs-mode . (lambda () (hs-minor-mode -1)))) 4: :config 5: (setq treemacs-hide-gitignored-files-mode t 6: treemacs-no-png-images t 7: treemacs-silent-refresh t 8: treemacs-sorting 'mod-time-desc 9: treemacs-python-executable (executable-find "python3") 10: treemacs-collapse-dirs (if treemacs-python-executable 3 0) 11: treemacs-deferred-git-apply-delay 0.5 12: treemacs-directory-name-transformer #'identity 13: treemacs-display-in-side-window t 14: treemacs-eldoc-display 'simple 15: treemacs-file-event-delay 2000 16: treemacs-file-extension-regex treemacs-last-period-regex-value 17: treemacs-file-follow-delay 0.2 18: treemacs-file-name-transformer #'identity 19: treemacs-follow-after-init t 20: treemacs-expand-after-init t 21: treemacs-find-workspace-method 'find-for-file-or-pick-first 22: treemacs-git-command-pipe "" 23: treemacs-goto-tag-strategy 'refetch-index 24: treemacs-header-scroll-indicators '(nil . "^^^^^^") 25: treemacs-hide-dot-git-directory t 26: treemacs-indentation 2 27: treemacs-indentation-string " " 28: treemacs-is-never-other-window nil 29: treemacs-max-git-entries 5000 30: treemacs-missing-project-action 'ask 31: treemacs-move-forward-on-expand nil 32: treemacs-no-delete-other-windows t 33: treemacs-project-follow-cleanup nil 34: treemacs-persist-file (expand-file-name ".cache/treemacs-persist" user-emacs-directory) 35: treemacs-position 'left 36: treemacs-read-string-input 'from-child-frame 37: treemacs-recenter-distance 0.1 38: treemacs-recenter-after-file-follow nil 39: treemacs-recenter-after-tag-follow nil 40: treemacs-recenter-after-project-jump 'always 41: treemacs-recenter-after-project-expand 'on-distance 42: treemacs-litter-directories '("/node_modules" "/.venv" "/.cask") 43: treemacs-project-follow-into-home nil 44: treemacs-show-cursor nil 45: treemacs-show-hidden-files t 46: treemacs-silent-filewatch t 47: treemacs-select-when-already-in-treemacs 'move-back 48: treemacs-space-between-root-nodes t 49: treemacs-tag-follow-cleanup t 50: treemacs-tag-follow-delay 1.5 51: treemacs-text-scale nil 52: treemacs-user-mode-line-format nil 53: treemacs-user-header-line-format nil 54: treemacs-wide-toggle-width 70 55: treemacs-width 35 56: treemacs-width-increment 1 57: treemacs-width-is-initially-locked t 58: treemacs-workspace-switch-cleanup nil) 59: (treemacs-peek-mode 1) 60: (treemacs-filewatch-mode t) 61: (treemacs-follow-mode t) 62: (treemacs-fringe-indicator-mode 'always) 63: (when treemacs-python-executable 64: (treemacs-git-commit-diff-mode t)) 65: (pcase (cons (not (null (executable-find "git"))) 66: (not (null treemacs-python-executable))) 67: (`(t . t) 68: (treemacs-git-mode 'deferred)) 69: (`(t . _) 70: (treemacs-git-mode 'simple))) 71: :bind 72: (:map global-map 73: ("M-0" . treemacs-select-window) 74: ("C-x t 1" . treemacs-delete-other-windows) 75: ("C-x t t" . treemacs) 76: ("C-x t d" . treemacs-select-directory) 77: ("C-x t B" . treemacs-bookmark) 78: ("C-x t C-t" . treemacs-find-file) 79: ("C-x t M-t" . treemacs-find-tag)) 80: :general 81: (+config/leader-tree 82: "t" 'treemacs 83: "p" 'treemacs-add-and-display-current-project-exclusively) 84: 85: (general-define-key 86: :keymaps 'treemacs-mode-map 87: "[mouse-1]" 'treemacs-single-click-expand-action) 88: 89: (general-nvmap 90: :keymaps 'treemacs-mode-map 91: "gr" '(treemacs-refresh :wk "refresh tree") 92: "zm" '(:ignore t :wk "move") 93: "zmf" '(treemacs-move-file :wk "move file") 94: "zmd" '(treemacs-move-project-down :wk "move project down") 95: "zmu" '(treemacs-move-project-up :wk "move project up") 96: "zr" '(:ignore t :wk "rename") 97: "zrf" '(treemacs-rename-file :wk "rename file") 98: "zrp" '(treemacs-rename-project :wk "rename project") 99: "zrw" '(treemacs-rename-workspace :wk "rename workspace") 100: "zc" '(:ignore t :wk "create/clean") 101: "zcC" '(treemacs-cleanup-litter :wk "cleanup litter") 102: "zcd" '(treemacs-create-dir :wk "create directory") 103: "zcf" '(treemacs-create-file :wk "create file") 104: "zd" '(treemacs-delete-file :wk "delete file")))
treemacs-projectile
1: (use-package treemacs-projectile 2: :ensure 3: :after treemacs)
treemacs-icons-dired
1: (use-package treemacs-icons-dired 2: :ensure 3: :after treemacs 4: :hook (dired-mode . treemacs-icons-dired-enable-once))
treemacs-magit
1: (use-package treemacs-magit 2: :ensure 3: :after treemacs magit)
treemacs-evil
1: (use-package treemacs-evil 2: :ensure 3: :after treemacs evil)
lsp-treemacs
1: (use-package lsp-treemacs 2: :ensure 3: :after treemacs lsp 4: :config 5: (lsp-treemacs-sync-mode 1) 6: :general 7: (general-define-key 8: :keymaps 'treemacs-mode-map 9: "S" 'lsp-treemacs-symbols 10: "X" 'lsp-treemacs-errors-list 11: "Y" 'lsp-treemacs-call-hierarchy))
treemacs-perspective
1: (use-package treemacs-perspective 2: :ensure 3: :after treemacs perspective 4: :config 5: (treemacs-set-scope-type 'Perspectives))
treemacs-tab-bar
1: (use-package treemacs-tab-bar 2: :ensure 3: :after treemacs)
treemacs-nerd-icons
1: (use-package treemacs-nerd-icons 2: :ensure 3: :after treemacs 4: :config 5: (treemacs-load-theme "nerd-icons"))
notmuch
external
1: (use-package notmuch 2: :ensure 3: :if (executable-find "notmuch") 4: :defer t 5: :commands (notmuch) 6: :hook 7: (message-setup . mml-secure-sign-pgpmime) 8: :config 9: (global-set-key (kbd "<XF86Mail>") 'notmuch) 10: (setq notmuch-fcc-dirs nil 11: notmuch-search-result-format 12: '(("date" . "%12s ") 13: ("count" . "%-7s ") 14: ("authors" . "%-30s ") 15: ("subject" . "%-72s ") 16: ("tags" . "(%s)")) 17: notmuch-tag-formats 18: '(("unread" 19: (propertize tag 'face 'notmuch-tag-unread)) 20: ("flagged" 21: (propertize tag 'face 'notmuch-tag-flagged) 22: (notmuch-tag-format-image-data tag 23: (notmuch-tag-star-icon)))) 24: notmuch-tagging-keys 25: '(("a" notmuch-archive-tags "Archive") 26: ("u" notmuch-show-mark-read-tags "Mark read") 27: ("f" ("+flagged") "Flag") 28: ("s" ("+spam" "-inbox") "Mark as spam") 29: ("d" ("+deleted" "-inbox") "Delete")) 30: notmuch-saved-searches 31: '((:name "flagged" :query "tag:flagged" :key "f") 32: (:name "sent" :query "tag:sent" :key "s") 33: (:name "drafts" :query "tag:draft" :key "d") 34: (:name "all mail" :query "*" :key "a") 35: (:name "unread" :query "tag:unread" :key "u") 36: (:name "zum" :query "tag:zum" :key "z") 37: (:name "mkn" :query "tag:mkn" :key "c") 38: (:name "gmail" :query "tag:gmail" :key "g") 39: (:name "hotmail" :query "tag:hotmail" :key "h") 40: (:name "yahoo" :query "tag:yahoo" :key "h") 41: (:name "ymail" :query "tag:ymail" :key "m") 42: (:name "Today" 43: :query "date:today AND NOT tag:spam AND NOT tag:bulk" 44: :key "T" 45: :search-type 'tree 46: :sort-order 'newest-first) 47: (:name "This Week" 48: :query "date:weeks AND NOT tag:spam AND NOT tag:bulk" 49: :key "W" 50: :search-type 'tree 51: :sort-order 'newest-first) 52: (:name "This Month" 53: :query "date:months AND NOT tag:spam AND NOT tag:bulk" 54: :key "M" 55: :search-type 'tree 56: :sort-order 'newest-first) 57: (:name "flagged" 58: :query "tag:flagged AND NOT tag:spam AND NOT tag:bulk" 59: :key "f" 60: :search-type 'tree 61: :sort-order 'newest-first) 62: (:name "spam" :query "tag:spam")) 63: notmuch-archive-tags '("-inbox" "-unread")) 64: (setq-default notmuch-search-oldest-first nil) 65: (if (executable-find "gpg2") 66: (setq notmuch-crypto-gpg-program "gpg2") 67: (setq notmuch-crypto-gpg-program "gpg")) 68: (setq notmuch-crypto-process-mime t 69: mml-secure-openpgp-sign-with-sender t) 70: (define-key notmuch-show-mode-map "S" 71: (lambda () 72: "Mark message as spam" 73: (interactive) 74: (notmuch-show-tag (list +spam -new)))) 75: :general 76: (+config/leader-menu! "mail" "M-m" 77: "m" '(notmuch :wk "Notmuch Mail")) 78: 79: (+config/leader-mail 80: "m" '(notmuch :wk "open notmuch mail") 81: "M" '(compose-mail :wk "new mail")) 82: 83: (general-nmap 'notmuch-common-keymap 84: "gr" 'notmuch-refresh-this-buffer 85: "gR" 'notmuch-poll-and-refresh-this-buffer))
notmuch-indicator
external
1: (use-package notmuch-indicator 2: :ensure 3: :config 4: (setq notmuch-indicator-args 5: '((:terms "tag:unread and tag:inbox" :label "U" :label-face success))) 6: (notmuch-indicator-mode))
consult-notmuch
external
1: (use-package consult-notmuch 2: :ensure 3: :after consult 4: :config 5: (add-to-list 'consult-buffer-sources 'consult-notmuch-buffer-source))
ol-notmuch
external
1: (use-package ol-notmuch 2: :ensure)
notmuch-maildir
external
1: (use-package notmuch-maildir 2: :ensure 3: :config 4: (notmuch-maildir-inject-section))
message
1: (use-package message 2: :custom 3: (message-directory (expand-file-name ".mail" (getenv "HOME"))) 4: (message-sendmail-envelope-from 'header))
sendmail
1: (use-package sendmail 2: :custom 3: (mail-specify-envelope-from t) 4: (mail-envelope-from 'header) 5: (send-mail-function 'sendmail-send-it) 6: (sendmail-program (executable-find "msmtp")))
Programming languages
Lisp
lispy
1: (use-package lispy 2: :ensure 3: :hook ((emacs-lisp-mode . lispy-mode) 4: (lisp-mode . lispy-mode) 5: (scheme-mode . lispy-mode) 6: (geiser-mode . lispy-mode)))
lispyville
1: (use-package lispyville 2: :ensure 3: :hook (lispy-mode . lispyville-mode))
- Emacs-lisp
elisp-mode
1: (when (locate-library "aggressive-indent") 2: (add-hook 'lisp-mode-hook #'aggressive-indent-mode) 3: (add-hook 'clojure-mode-hook #'aggressive-indent-mode) 4: (add-hook 'scheme-mode-hook #'aggressive-indent-mode)) 5: 6: ;;;; emacs-lisp -n 7: (use-package elisp-mode 8: :diminish emacs-lisp-mode 9: :diminish elisp-mode 10: :diminish outline-minor-mode 11: :diminish lisp-data-mode 12: :mode ("\\.Cask\\'" . emacs-lisp-mode) 13: :ensure nil 14: :hook (emacs-lisp-mode . (lambda () 15: (outline-minor-mode) 16: (rainbow-delimiters-mode))))
ielm
1: (use-package ielm 2: :ensure nil 3: ;;:hook (ielm-mode . (turn-on-smartparens-mode)) 4: :config 5: (setq ielm-font-lock-keywords 6: (append '(("\\(^\\*\\*\\*[^*]+\\*\\*\\*\\)\\(.*$\\)" 7: (1 font-lock-comment-face) 8: (2 font-lock-constant-face))) 9: (when (require 'highlight-numbers nil t) 10: (highlight-numbers--get-regexp-for-mode 'emacs-lisp-mode)) 11: (cl-loop for (matcher . match-highlights) 12: in (append lisp-el-font-lock-keywords-2 13: lisp-cl-font-lock-keywords-2) 14: collect 15: `((lambda (limit) 16: (when ,(if (symbolp matcher) 17: `(,matcher limit) 18: `(re-search-forward ,matcher limit t)) 19: ;; Only highlight matches after the prompt 20: (> (match-beginning 0) (car comint-last-prompt)) 21: ;; Make sure we're not in a comment or string 22: (let ((state (syntax-ppss))) 23: (not (or (nth 3 state) 24: (nth 4 state)))))) 25: ,@match-highlights)))))
macrostep
external
1: (use-package macrostep 2: :ensure 3: :defer t 4: :bind (:map emacs-lisp-mode-map 5: ("C-c e" . macrostep-expand)))
- Common lisp
1: ;;;; common-lisp 2: (when (file-directory-p (expand-file-name "site-lisp/sly-stepper" user-emacs-directory)) 3: (add-to-list 'load-path (expand-file-name "site-lisp/sly-stepper" user-emacs-directory))) 4: (when (file-directory-p (expand-file-name "site-lisp/sly-quicklisp" user-emacs-directory)) 5: (add-to-list 'load-path (expand-file-name "site-lisp/sly-quicklisp" user-emacs-directory))) 6: (when (file-directory-p (expand-file-name "site-lisp/sly-macrostep" user-emacs-directory)) 7: (add-to-list 'load-path (expand-file-name "site-lisp/sly-macrostep" user-emacs-directory))) 8: 9: (defvar inferior-lisp-program "sbcl") 10: (when (executable-find "ros") 11: (setq inferior-lisp-program "ros -Q run")) 12: 13: (add-hook 'lisp-mode-hook #'rainbow-delimiters-mode)
- clojure
cider
external
1: ;;;; clojure 2: (use-package cider 3: :ensure 4: :defer t)
clj-refactor
external
1: (use-package clj-refactor 2: :ensure 3: :defer t 4: :hook (clojure-mode . +config/clojure-mode-hook) 5: :config 6: (defun +config/clojure-mode-hook () 7: (clj-refactor-mode 1) 8: ;; This choice of keybinding leaves cider-macroexpand-1 unbound 9: (cljr-add-keybindings-with-prefix "C-c r")))
- Scheme
geiser
external
1: ;;;; scheme 2: (use-package geiser 3: :ensure 4: :defer t 5: :diminish geiser-autodoc-mode 6: ;; :hook (geiser-repl-mode . turn-on-smartparens-strict-mode) 7: :init 8: (setq geiser-autodoc-identifier-format "%s → %s" 9: geiser-repl-per-project-p t 10: geiser-repl-history-filename (concat user-emacs-directory "geiser-history")))
geiser-guile
external
1: (use-package geiser-guile 2: :ensure 3: :defer t 4: :config 5: (let ((nonguix-path (expand-file-name "Projects/guix/nonguix" 6: (getenv "HOME"))) 7: (personal-path (expand-file-name "Projects/guix/devel/src" 8: (getenv "HOME")))) 9: (when (file-directory-p nonguix-path) 10: (add-to-list 'geiser-guile-load-path nonguix-path)) 11: (when (file-directory-p personal-path) 12: (add-to-list 'geiser-guile-load-path personal-path))))
macrostep-geiser
external
1: (use-package macrostep-geiser 2: :ensure 3: :defer t 4: :after geiser-mode geiser-repl 5: :hook ((geiser-mode geiser-repl-mode) . macrostep-geiser-setup) 6: :bind (:map geiser-mode-map 7: ("C-c e" . macrostep-expand)))
C and C++
cc-mode
builtin
1: (use-package cc-mode 2: :mode ("\\.mm\\'" . objc-mode) 3: :mode ("\\.h\\'" . +cc-c-c++-objc-mode) 4: :hook (c-mode-common . rainbow-delimiters-mode) 5: ;; :hook (c++-mode-local-vars . c++-ts-mode) 6: ;; :hook (c-mode-common . c-ts-base-mode) 7: ;; :hook (cmake-mode-local-vars . cmake-ts-mode) 8: :config 9: (setq c-basic-offset tab-width 10: c-backspace-function #'delete-backward-char) 11: (with-eval-after-load 'ffap 12: (add-to-list 'ffap-alist '(c-mode . ffap-c-mode))))
XML
YAML
yaml-mode
external
1: (use-package yaml-mode 2: :ensure 3: :config 4: (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) 5: (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode)) 6: (setq tab-width 2) 7: ;; (when (treesit-available-p) 8: ;; (add-to-list 'major-mode-remap-alist '(yaml-mode . yaml-ts-mode))) 9: :hook 10: ((yaml-mode . (lambda () 11: (define-key yaml-mode-map "\C-m" 'newline-and-indent))) 12: (yaml-mode . (lambda () 13: (run-hooks 'prog-mode-hook)))))
TOML
toml-mode
external
1: (use-package toml-mode 2: :ensure 3: :mode 4: ("\\.toml\\'" . toml-mode) 5: :config 6: ;; (when (treesit-available-p) 7: ;; (add-to-list 'major-mode-remap-alist '(toml-mode . toml-ts-mode))) 8: (with-eval-after-load 'lsp-mode 9: (setq lsp-toml-command (executable-find "taplo"))) 10: (add-to-list 'lsp-language-id-configuration '("\\.toml$" . "toml")))
Lua
Jinja2
jinja2-mode
external
1: (use-package jinja2-mode 2: :ensure 3: :defer t 4: :config 5: ;; The default behavior is to reindent the whole buffer on save. This is 6: ;; disruptive and imposing. There are indentation commands available; the user 7: ;; can decide when they want their code reindented. 8: (setq jinja2-enable-indent-on-save nil) 9: (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) 10: (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode)))
Web
web-mode
external
1: (defun +config/django-web-mode () 2: "Set web-engine to django if `manage.py' detected in `projectile-project-root'." 3: (if (projectile-project-p) 4: (if (file-exists-p (concat (projectile-project-root) "manage.py")) 5: (web-mode-set-engine "django")))) 6: 7: (defun +config/web-mode-fix-js-comment () 8: "Fix comment handling in `web-mode' for JavaScript (from `doom')." 9: (when (member web-mode-content-type '("javascript" "jsx")) 10: ;; For some reason the default is to insert HTML comments even 11: ;; in JavaScript. 12: (setq-local comment-start "//") 13: (setq-local comment-end "") 14: ;; Needed since otherwise the default value generated by 15: ;; `comment-normalize-vars' will key off the syntax and think 16: ;; that a single "/" starts a comment, which completely borks 17: ;; auto-fill. 18: (setq-local comment-start-skip "// *"))) 19: 20: (use-package web-mode 21: :ensure 22: :defer t 23: :mode "\\.[px]?html?\\'" 24: :mode "\\.\\(?:tpl\\|blade\\)\\(?:\\.php\\)?\\'" 25: :mode "\\.erb\\'" 26: :mode "\\.[lh]?eex\\'" 27: :mode "\\.jsp\\'" 28: :mode "\\.as[cp]x\\'" 29: :mode "\\.ejs\\'" 30: :mode "\\.hbs\\'" 31: :mode "\\.mustache\\'" 32: :mode "\\.svelte\\'" 33: :mode "\\.twig\\'" 34: :mode "\\.jinja2?\\'" 35: :mode "\\.eco\\'" 36: :mode "wp-content/themes/.+/.+\\.php\\'" 37: :mode "templates/.+\\.php\\'" 38: :init 39: ;; If the user has installed `vue-mode' then, by appending this to 40: ;; `auto-mode-alist' rather than prepending it, its autoload will have 41: ;; priority over this one. 42: (add-to-list 'auto-mode-alist '("\\.vue\\'" . web-mode) 'append) 43: :mode "\\.vue\\'" 44: :config 45: (setq web-mode-markup-indent-offset 2 46: web-mode-enable-auto-closing t 47: web-mode-auto-close-style 1 48: web-mode-css-indent-offset 2 49: web-mode-code-indent-offset 2 50: web-mode-enable-auto-pairing nil 51: web-mode-enable-block-face t 52: web-mode-enable-comment-interpolation t 53: web-mode-enable-heredoc-fontification t 54: web-mode-enable-css-colorization t 55: web-mode-enable-part-face t 56: web-mode-enable-current-element-highlight t 57: web-mode-enable-current-column-highlight t 58: web-mode-style-padding 1 59: web-mode-script-padding 1 60: web-mode-block-padding 0 61: web-mode-comment-style 2 62: web-mode-enable-curly-brace-indentation t 63: web-mode-enable-auto-quoting nil 64: web-mode-engines-alist 65: '(("php" . "\\.phtml\\'") 66: ("blade" . "\\.blade\\'") 67: ("elixir" . "\\.eex\\'") 68: ("phoenix" . "\\.[lh]eex\\'"))) 69: ;; web-mode-extra-auto-pairs 70: ;; '(("erb" . (("beg" "end"))) 71: ;; ("php" . (("beg" "end"))))) 72: (with-eval-after-load 'smartparens 73: (sp-local-pair 'web-mode "<" nil :actions :rem) 74: (sp-local-pair 'web-mode "{%" " %}") 75: (sp-local-pair 'web-mode "{{" " }}") 76: (sp-local-pair 'web-mode "<!--" " -->") 77: ) 78: (defun +config/web-mode-hook () 79: "Hooks for Web mode." 80: (local-set-key (kbd "RET") 'newline-and-indent)) 81: ;; Use // instead of /* as the default comment delimited in JS 82: (with-eval-after-load 'web-mode 83: (setf (alist-get "javascript" web-mode-comment-formats nil nil #'equal) 84: "//")) 85: :hook ((html-mode-local-vars-hook 86: mhtml-mode-local-vars-hook) . tree-sitter) 87: :hook (web-mode . +config/django-web-mode) 88: :general 89: (general-nvmap 90: :keymaps 'web-mode-map 91: "gn" 'web-mode-navigate) 92: (general-vmap 93: :keymaps 'web-mode-map 94: "gs" 'web-mode-surround))
emmet-mode
external
1: (use-package emmet-mode 2: :ensure 3: :defer t 4: :hook (css-mode web-mode html-mode haml-mode nxml-mode rjsx-mode reason-mode) 5: :config 6: (when (require 'yasnippet nil t) 7: (add-hook 'emmet-mode-hook #'yas-minor-mode-on)) 8: (setq emmet-move-cursor-between-quotes t) 9: :general 10: (general-vmap 11: :keymaps 'emmet-mode-keymap 12: "TAB" 'emmet-wrap-with-markup) 13: (general-def 14: :keymaps 'emmet-mode-keymap 15: "M-E" 'emmet-expand-line))
skewer-mode
external
1: (use-package skewer-mode 2: :ensure 3: :defer t 4: :hook ((web-mode . skewer-html-mode) 5: (js2-mode . skewer-mode)))
lsp-tailwindcss
external
1: (use-package lsp-tailwindcss 2: :ensure 3: :init 4: (setq lsp-tailwindcss-add-on-mode t))
sass-mode
external
1: (use-package sass-mode 2: :ensure 3: :defer t 4: :hook (scss-mode . rainbow-mode))
css-eldoc
external
1: (use-package css-eldoc 2: :ensure 3: :defer t 4: :commands turn-on-css-eldoc 5: ;;add a hook if you want always to see the selector options in the minibuffer 6: :config 7: (add-hook 'css-mode-hook 'turn-on-css-eldoc) 8: (add-hook 'scss-mode-hook 'turn-on-css-eldoc))
com-css-sort
external
1: (use-package com-css-sort 2: :ensure 3: :defer t 4: :commands (com-css-sort com-css-sort-attributes-block com-css-sort-attributes-document) 5: :config 6: (setq com-css-sort-sort-type 'alphabetic-sort))
css-mode
1: (use-package css-mode 2: :hook ((css-mode 3: stylus-mode) . rainbow-mode) 4: :hook (css-mode-local-vars . tree-sitter) 5: :config 6: (with-eval-after-load 'skewer-mode 7: (add-hook 'css-mode-hook 'skewer-css-mode)))
javascript
1: (defvar +javascript-npm-conf (make-hash-table :test 'equal)) 2: 3: ;;;###autoload 4: (defun +javascript-npm-conf (&optional project-root refresh-p) 5: "Retrieves an alist of this project's 'package.json'. If REFRESH-P is non-nil 6: ignore the cache." 7: (let ((project-root (or project-root (doom-project-root)))) 8: (or (and (not refresh-p) 9: (gethash project-root +javascript-npm-conf)) 10: (let ((package-file (expand-file-name "package.json" project-root))) 11: (when-let (json (and (file-exists-p package-file) 12: (require 'json) 13: (json-read-file package-file))) 14: (puthash project-root json +javascript-npm-conf)))))) 15: 16: ;;;###autoload 17: (defun +javascript-npm-dep-p (packages &optional project-root refresh-p) 18: (when-let (data (and (bound-and-true-p +javascript-npm-mode) 19: (+javascript-npm-conf project-root refresh-p))) 20: (let ((deps (append (cdr (assq 'dependencies data)) 21: (cdr (assq 'devDependencies data))))) 22: (cond ((listp packages) 23: (funcall (if (eq (car packages) 'and) 24: #'cl-every 25: #'cl-some) 26: (lambda (pkg) (assq pkg deps)) 27: (if (listp packages) packages (list packages)))) 28: ((symbolp packages) 29: (assq packages deps)) 30: (t (error "Expected a package symbol or list, got %s" packages)))))) 31: 32: ;;;###autoload 33: (defun +javascript-add-npm-path-h () 34: "Add node_modules/.bin to `exec-path'." 35: (when-let ((search-directory (or (doom-project-root) default-directory)) 36: (node-modules-parent (locate-dominating-file search-directory "node_modules/")) 37: (node-modules-dir (expand-file-name "node_modules/.bin/" node-modules-parent))) 38: (make-local-variable 'exec-path) 39: (add-to-list 'exec-path node-modules-dir) 40: (doom-log ":lang:javascript: add %s to $PATH" (expand-file-name "node_modules/" node-modules-parent)))) 41: 42: 43: ;; 44: ;; Commands 45: 46: ;;;###autoload 47: (defun +javascript/open-repl () 48: "Open a Javascript REPL. Meaning either `skewer-repl', if any of the 49: skewer-*-mode's are enabled, or `nodejs-repl' otherwise." 50: (interactive) 51: (call-interactively 52: (if (and (featurep 'skewer-mode) 53: (or (bound-and-true-p skewer-mode) 54: (bound-and-true-p skewer-css-mode) 55: (bound-and-true-p skewer-html-mode))) 56: #'skewer-repl 57: #'nodejs-repl)) 58: (current-buffer)) 59: 60: ;;;###autoload 61: (defun +javascript/skewer-this-buffer () 62: "Toggle a globalized skewer-mode, attaching an external browser (once), 63: initiating an internal httpd server (once) and enabling the appropriate 64: skewer-mode for the current buffer. 65: 66: Run this for any buffer you want to skewer." 67: (interactive) 68: (when (bound-and-true-p impatient-mode) 69: (error "Skewer-mode isn't compatible with impatient mode")) 70: (require 'skewer-mode) 71: (unless (process-status "httpd") 72: (run-skewer)) 73: (pcase major-mode 74: ((or 'css-mode 'scss-mode 'less-css-mode) 75: (unless (bound-and-true-p skewer-css-mode) 76: (skewer-css-mode +1))) 77: ((or 'web-mode 'html-mode) 78: (unless (bound-and-true-p skewer-html-mode) 79: (skewer-html-mode +1))) 80: ('js2-mode 81: (unless (bound-and-true-p skewer-mode) 82: (skewer-mode +1))) 83: (_ (error "Invalid mode %s" major-mode)))) 84: 85: ;;;###autoload 86: (defun +javascript/skewer-cleanup () 87: "Disable skewer-mode globally and disable the httpd server." 88: (interactive) 89: (when (process-status "httpd") 90: (httpd-stop)) 91: (dolist (buf (buffer-list)) 92: (with-current-buffer buf 93: (if (bound-and-true-p skewer-mode) 94: (skewer-mode -1)) 95: (if (bound-and-true-p skewer-css-mode) 96: (skewer-css-mode -1)) 97: (if (bound-and-true-p skewer-html-mode) 98: (skewer-html-mode -1))))) 99: 100: ;; 101: ;; Hooks 102: 103: ;;;###autoload 104: (defun +javascript-cleanup-tide-processes-h () 105: "Clean up dangling tsserver processes if there are no more buffers with 106: `tide-mode' active that belong to that server's project." 107: (when tide-mode 108: (unless (cl-loop with project-name = (tide-project-name) 109: for buf in (delq (current-buffer) (buffer-list)) 110: if (and (buffer-local-value 'tide-mode buf) 111: (with-current-buffer buf 112: (string= (tide-project-name) project-name))) 113: return buf) 114: (kill-process (tide-current-server))))) 115: 116: ;; 117: ;; Advice 118: 119: ;;;###autoload 120: (defun +javascript-tide-project-root-a () 121: "Resolve to `doom-project-root' if `tide-project-root' fails." 122: (or tide-project-root 123: (or (locate-dominating-file default-directory "tsconfig.json") 124: (locate-dominating-file default-directory "jsconfig.json")))) 125: 126: (with-eval-after-load 'projectile 127: (add-to-list 'projectile-globally-ignored-directories "^node_modules$") 128: (add-to-list 'projectile-globally-ignored-directories "^flow-typed$"))
js2-mode
external
1: (use-package js2-mode 2: :ensure 3: :defer t 4: :interpreter ("node" . js2-mode) 5: :hook (js2-mode . rainbow-delimiters-mode) 6: :hook (js2-mode . js2-imenu-extras-mode) 7: :hook (js2-mode . (lambda () (push '("function" . ?ƒ) prettify-symbols-alist))) 8: :config 9: (with-eval-after-load 'skewer-mode 10: (add-hook 'js2-mode 'skewer-mode)) 11: (setq-default js2-basic-indent 2 12: js2-basic-offset 2 13: js2-auto-indent-p t 14: js2-cleanup-whitespace t 15: js2-enter-indents-newline t 16: js2-indent-on-enter-key t 17: js2-global-externs (list "window" "module" "require" "buster" "sinon" "assert" "refute" "setTimeout" "clearTimeout" "setInterval" "clearInterval" "location" "__dirname" "console" "JSON" "jQuery" "$")))
js2-refactor
external
1: (use-package js2-refactor 2: :ensure 3: :defer t 4: :hook (js2-mode . js2-refactor-mode) 5: :init 6: (js2r-add-keybindings-with-prefix "C-c C-r") 7: :config 8: (setq js2-skip-preprocessor-directives t) 9: :general 10: (general-nvmap 11: :keymap 'js2-refactor-mode-map 12: "zr" (general-simulate-key "C-c C-r" 13: :name general-z-r-simulates-C-c-C-r 14: :docstring "Simulates C-c C-r" 15: :which-key "JS2 Refactor")))
rjsx-mode
external
1: (use-package rjsx-mode 2: :ensure 3: :defer t 4: :mode "\\.[mc]?js\\'" 5: :mode "\\.es6\\'" 6: :mode "\\.pac\\'" 7: :hook (rjsx-mode . rainbow-delimiters-mode) 8: :hook (rjsx-mode . rainbow-mode) 9: :bind (([remap comment-dwim ] . rjsx-comment-dwim)) 10: :init 11: (with-eval-after-load 'compilation 12: (add-to-list 'compilation-error-regexp-alist 'node) 13: (add-to-list 'compilation-error-regexp-alist-alist '(node "^[[:blank:]]*at \\(.*(\\|\\)\\(.+?\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\)" 14: 2 3 4))) 15: :config 16: (with-eval-after-load 'compilation 17: (add-to-list 'compilation-error-regexp-alist 'node) 18: (add-to-list 'compilation-error-regexp-alist-alist 19: '(node "^[[:blank:]]*at \\(.*(\\|\\)\\(.+?\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\)" 20: 2 3 4))) 21: (setq js-chain-indent t 22: ;; These have become standard in the JS community 23: js2-basic-offset 2 24: ;; Don't mishighlight shebang lines 25: js2-skip-preprocessor-directives t 26: ;; let flycheck handle this 27: js2-mode-show-parse-errors nil 28: js2-mode-show-strict-warnings nil 29: ;; Flycheck provides these features, so disable them: conflicting with 30: ;; the eslint settings. 31: js2-strict-missing-semi-warning nil 32: ;; maximum fontification 33: js2-highlight-level 3 34: js2-idle-timer-delay 0.15) 35: :general 36: (general-nvmap 37: :keymaps 'rjsx-mode-map 38: "'" 'rjsx-jump-tag 39: "gj" 'rjsx-jump-closing-tag 40: "gk" 'rjsx-jump-opening-tag 41: "gr" 'rjsx-rename-tag-at-point 42: "z>" 'rjsx-electric-gt 43: "z<" 'rjsx-electric-lt))
xref-js2
external
1: (use-package xref-js2 2: :ensure 3: :defer t 4: :if (executable-find "ag") ; silver-searcher 5: :config 6: (add-hook 'js2-mode-hook (lambda () 7: (add-hook 'xref-backend-functions #'xref-js2-xref-backend nil t))))
typescript-mode
external
1: (use-package typescript-mode 2: :ensure 3: :defer t 4: :hook (typescript-mode . rainbow-delimiters-mode) 5: :hook (typescript-tsx-mode . rainbow-delimiters-mode) 6: :hook (typescript-mode . (lambda () (setq comment-line-break-function #'js2-line-break 7: typescript-indent-level (or (and (bound-and-true-p tide-mode) 8: (plist-get (tide-tsfmt-options) :indentSize)) 9: typescript-indent-level) 10: emmet-expand-jsx-className? t))) 11: :init 12: (add-to-list 'auto-mode-alist 13: (cons "\\.tsx\\'" #'typescript-mode)) 14: (with-eval-after-load 'flycheck 15: (flycheck-add-mode 'javascript-eslint 'web-mode) 16: (flycheck-add-mode 'javascript-eslint 'typescript-mode) 17: (flycheck-add-mode 'javascript-eslint 'typescript-tsx-mode) 18: (flycheck-add-mode 'typescript-tslint 'typescript-tsx-mode)) 19: (defun +javascript-disable-tide-checkers-h () 20: (add-to-list 'flycheck-disabled-checkers 'javascript-jshint) 21: (add-to-list 'flycheck-disabled-checkers 'tsx-tide) 22: (add-to-list 'flycheck-disabled-checkers 'jsx-tide)) 23: (add-hook 'typescript-tsx-mode-hook #'+javascript-disable-tide-checkers-h) 24: :config 25: (when (fboundp 'web-mode) 26: (define-derived-mode typescript-tsx-mode web-mode "TypeScript-TSX")) 27: (autoload 'js2-line-break "js2-mode" nil t))
tide
external
1: (use-package tide 2: :ensure 3: :defer t 4: :hook (tide-mode . tide-hl-identifier-mode) 5: :config 6: (setq tide-completion-detailed t 7: tide-always-show-documentation t 8: tide-server-max-response-length 524288 9: tide-completion-setup-company-backend nil) 10: (add-hook 'tide-mode-hook (lambda () (add-hook 'kill-buffer-hook #'+javascript-cleanup-tide-processes-h nil 'local))))
npm-mode
external
1: (use-package npm-mode 2: :ensure 3: :defer t)
nodejs-repl
external
1: (use-package nodejs-repl 2: :ensure 3: :defer t)
Latex
auctex
1: (use-package auctex 2: :ensure nil 3: :mode (("\\.tex\\'" . latex-mode) 4: ("\\.latex\\'" . latex-mode)) 5: :commands (latex-mode LaTeX-mode plain-tex-mode) 6: :init 7: (progn 8: (add-hook 'LaTeX-mode-hook #'LaTeX-preview-setup) 9: (add-hook 'LaTeX-mode-hook #'flyspell-mode) 10: (add-hook 'LaTeX-mode-hook #'turn-on-reftex) 11: (setq-default TeX-engine 'xetex) 12: (setq TeX-auto-save nil 13: TeX-parse-self nil 14: TeX-save-query nil 15: TeX-PDF-mode t) 16: (setq-default TeX-master nil)))
preview
1: (use-package preview 2: :ensure nil 3: :after auctex 4: :commands LaTeX-preview-setup 5: :init 6: (progn 7: (setq-default preview-scale 1.4 8: preview-scale-function '(lambda () (* (/ 10.0 (preview-document-pt)) preview-scale)))))
reftex
1: (use-package reftex 2: :ensure nil 3: :commands turn-on-reftex 4: :init 5: (setq reftex-plug-into-AUCTeX t))
bibtex
1: (use-package bibtex 2: :config 3: (setq bibtex-autokey-year-length 4 4: bibtex-autokey-name-year-separator "-" 5: bibtex-autokey-year-title-separator "-" 6: bibtex-autokey-titleword-separator "-" 7: bibtex-autokey-titlewords 2 8: bibtex-autokey-titlewords-stretch 1 9: bibtex-autokey-titleword-length 5))
LaTex
1: ;; Auto-fill for LaTeX 2: (defun lem-latex-auto-fill () 3: "Turn on auto-fill for LaTeX mode." 4: (turn-on-auto-fill) 5: (set-fill-column 80) 6: (setq default-justification 'left)) 7: (add-hook 'LaTeX-mode-hook #'lem-latex-auto-fill) 8: 9: ;; Compilation command 10: (add-hook 'LaTeX-mode-hook (lambda () (setq compile-command "latexmk -pdflatex=xelatex -f -pdf %f"))) 11: 12: ;; Prevent ispell from verifying some LaTeX commands 13: ;; http://stat.genopole.cnrs.fr/dw/~jchiquet/fr/latex/emacslatex 14: (defvar lem-ispell-tex-skip-alists 15: '("cite" "nocite" 16: "includegraphics" 17: "author" "affil" 18: "ref" "eqref" "pageref" 19: "label")) 20: (setq ispell-tex-skip-alists 21: (list 22: (append (car ispell-tex-skip-alists) 23: (mapcar #'(lambda (cmd) (list (concat "\\\\" cmd) 'ispell-tex-arg-end)) lem-ispell-tex-skip-alists)) 24: (cadr ispell-tex-skip-alists))) 25: 26: ;; Indentation with align-current in LaTeX environments 27: (defvar lem-LaTeX-align-environments '("tabular" "tabular*")) 28: (add-hook 'LaTeX-mode-hook 29: (lambda () 30: (require 'align) 31: (setq LaTeX-indent-environment-list 32: ;; For each item in the list... 33: (mapcar (lambda (item) 34: ;; The car is an environment 35: (let ((env (car item))) 36: ;; If this environment is in our list... 37: (if (member env lem-LaTeX-align-environments) 38: ;; ...then replace this item with a correct one 39: (list env 'align-current) 40: ;; else leave it alone 41: item))) 42: LaTeX-indent-environment-list)))) 43: 44: ;; Use dvipdfmx to convert DVI files to PDF in AUCTeX 45: (eval-after-load 'tex 46: '(add-to-list 'TeX-command-list 47: '("DVI to PDF" "dvipdfmx %d" TeX-run-command t t) t)) 48: 49: ;; SyncTeX (http://www.emacswiki.org/emacs/AUCTeX#toc19) 50: (defun synctex/un-urlify (fname-or-url) 51: "A trivial function that replaces a prefix of file:/// with just /." 52: (if (string= (substring fname-or-url 0 8) "file:///") 53: (substring fname-or-url 7) 54: fname-or-url))
Markdown external
- Basic Configuration
1: (use-package markdown-mode 2: :ensure) 3: 4: (use-package markdown-ts-mode 5: :ensure 6: :init 7: (add-to-list 'major-mode-remap-alist '(markdown-mode . markdown-ts-mode))) 8: 9: (use-package poly-markdown 10: :ensure 11: :init :mode 12: (("README\\.md\\'" . gfm-mode) 13: ("\\.md$" . markdown-ts-mode) 14: ("\\.markdown$" . markdown-ts-mode))) 15: 16: (use-package edit-indirect 17: :ensure 18: :after markdown-mode)
Python
python
builtin
1: (use-package python 2: :mode ("[./]flake8\\'" . conf-mode) 3: :mode ("/Pipfile\\'" . conf-mode) 4: :hook ((python-mode . lsp-deferred) 5: (python-mode . lsp-ui-mode) 6: (python-mode . lsp-ui-doc-mode) 7: ;; (python-mode . guess-style-guess-tab-mode) 8: (python-mode-local-vars . (lambda () 9: (lsp-deferred) 10: (tree-sitter)))) 11: :config 12: (if (executable-find "ipython") 13: (setq python-interpreter (executable-find "ipython")) 14: (setq python-interpreter (executable-find "python3"))) 15: (when (featurep 'projectile) 16: (add-to-list 'projectile-globally-ignored-directories "^\\.venv$")) 17: (let ((directories `("/usr/bin/" "/usr/local/bin/" "/opt/bin" ,(expand-file-name ".local/bin/" (getenv "HOME"))))) 18: (dolist (directory directories) (when (file-directory-p directory)(add-to-list 'python-shell-exec-path directory)))) 19: (setq python-indent-guess-indent-offset nil 20: python-shell-completion-native-enable nil 21: python-shell-exec-path (list "/usr/bin/" "/usr/local/bin" (expand-file-name ".local/bin/" (getenv "HOME"))) 22: python-indent-guess-indent-offset-verbose nil) 23: (when (featurep 'lsp-mode) 24: (setq lsp-pylsp-plugins-rope-completion-enabled t ; needs python-rope package 25: lsp-pylsp-plugins-mccabe-enabled t ; needs python-mccabe package 26: lsp-ruff-lsp-python-path (executable-find "python3") 27: ) 28: (when (executable-find "black") 29: (setq lsp-pylsp-plugins-black-enabled t)) 30: (when (executable-find "autopep8") 31: (setq lsp-pylsp-plugins-autopep8-enabled t)) 32: (when (executable-find "flake8") 33: (setq lsp-pylsp-plugins-flake8-enabled t)) 34: (when (executable-find "pycodestyle") 35: (setq lsp-pylsp-plugins-pycodestyle-enabled t)) 36: (when (executable-find "pydocstyle") 37: (setq lsp-pylsp-plugins-pydocstyle-enabled t)) 38: (when (executable-find "pylint") 39: (setq lsp-pylsp-plugins-pylint-enabled t)) 40: (when (executable-find "pyflakes") 41: (setq lsp-pylsp-plugins-pyflakes-enabled t)) 42: (when (executable-find "yapf") 43: (setq lsp-pylsp-plugins-yapf-enabled t))) 44: (when (featurep 'flycheck) 45: (setq flycheck-python-mypy-executable (executable-find "mypy") 46: flycheck-python-flake8-executable (executable-find "flake8") 47: flycheck-python-pylint-executable (executable-find "pylint") 48: flycheck-python-pyright-executable (executable-find "pyright"))) 49: :general 50: (+config/local-leader 51: :keymaps 'python-mode-map 52: "d" '(:ignore t :wk "doc")))
pydoc
external
1: (use-package pydoc 2: :ensure 3: :general 4: (general-def 5: :keymaps 'python-mode-map 6: "C-c C-d" 'pydoc-at-point-no-jedi))
ob-ipython
1: (use-package ob-ipython 2: :ensure 3: :defer t 4: :init 5: (setq ob-ipython-resources-dir ".ob-ipython-resrc") 6: (with-eval-after-load 'org-src 7: (add-to-list 'org-src-lang-modes '("ipython" . python))) 8: (with-eval-after-load 'ob-async 9: (add-to-list 'ob-async-no-async-languages-alist "ipython")))
pip-requirements
external
1: (use-package pip-requirements 2: :ensure 3: :defer t 4: :config 5: (add-hook 'pip-requirements-mode-hook #'pip-requirements-auto-complete-setup))
inferior-python-mode
1: (use-package inferior-python-mode 2: :ensure nil 3: ;;:hook (inferior-python-mode . hide-mode-line-mode) 4: :config 5: (+config/local-leader 6: :keymaps 'python-mode-map 7: "r" '(run-python :wk "run python")))
lsp-pyright
external
1: (use-package lsp-pyright 2: :ensure 3: :after lsp-mode 4: :hook (python-mode . (lambda () 5: (lsp-deferred) 6: (lsp-ui-mode) 7: (lsp-ui-doc-mode))) 8: :config 9: (setq lsp-pyright-python-executable-cmd 10: (if (executable-find "python3") 11: (executable-find "python3") 12: "python")))
python-docstring
external
1: (use-package python-docstring 2: :ensure 3: :diminish 4: :hook (python-mode . python-docstring-mode) 5: :general 6: (+config/local-leader 7: :keymaps 'python-mode-map 8: "dq" 'python-docstring-fill))
pipenv
external
1: (use-package pipenv 2: :ensure 3: :diminish 4: :after python 5: :commands pipenv-project-p 6: :hook (python-mode . pipenv-mode) 7: :init 8: (setq pipenv-projectile-after-switch-function 9: #'pipenv-projectile-after-switch-extended 10: pipenv-executable (executable-find "pipenv")) 11: :general 12: (+config/local-leader 13: :keymaps 'python-mode-map 14: "p" '(:keymap pipenv-command-map :package pipenv :wk "pipenv")))
pyvenv
external
1: (use-package pyvenv 2: :ensure t 3: :config 4: (pyvenv-mode t) 5: ;; Set correct Python interpreter 6: (setq pyvenv-post-activate-hooks 7: (list (lambda () 8: (setq python-shell-interpreter (concat pyvenv-virtual-env ".venv/bin/python3"))))) 9: (setq pyvenv-post-deactivate-hooks 10: (list (lambda () 11: (setq python-shell-interpreter "python3")))))
flycheck-pycheckers
external
1: (use-package flycheck-pycheckers 2: :ensure 3: :after flycheck 4: :config 5: (with-eval-after-load 'flycheck 6: (add-hook 'flycheck-mode-hook #'flycheck-pycheckers-setup)))
ein
external
1: (use-package ein 2: :ensure t)
Rust
rust-mode
1: ;;;###autoload 2: (defun +rust-cargo-project-p () 3: "Return t if this is a cargo project." 4: (locate-dominating-file buffer-file-name "Cargo.toml")) 5: 6: ;;; Custom Cargo commands 7: 8: (autoload 'rustic-run-cargo-command "rustic-cargo") 9: ;;;###autoload 10: (defun +rust/cargo-audit () 11: "Run 'cargo audit' for the current project." 12: (interactive) 13: (rustic-run-cargo-command "cargo audit")) 14: 15: (with-eval-after-load 'projectile 16: (add-to-list 'projectile-project-root-files "Cargo.toml")) 17: 18: (use-package rust-mode)
rustic
external
1: (use-package rustic 2: :ensure 3: :mode ("\\.rs$" . rustic-mode) 4: :init 5: (with-eval-after-load 'rustic-flycheck 6: (remove-hook 'rustic-mode-hook #'flycheck-mode) 7: (remove-hook 'rustic-mode-hook #'flymake-mode-off) 8: (remove-hook 'flycheck-mode-hook #'rustic-flycheck-setup)) 9: (with-eval-after-load 'org-src 10: (defalias 'org-babel-execute:rust #'org-babel-execute:rustic)) 11: :config 12: (add-hook 'rustic-mode-hook #'rainbow-delimiters-mode) 13: (setq rustic-indent-method-chain t 14: rustic-lsp-client 'lsp-mode) 15: (add-hook 'rustic-mode-local-vars-hook #'rustic-setup-lsp 'append) 16: (add-hook 'rustic-mode-local-vars-hook #'flycheck-mode) 17: ;; (add-hook 'rustic-mode-local-vars-hook #'tree-sitter! 'append) 18: (with-eval-after-load 'lsp 19: (setq lsp-rust-analyzer-display-parameter-hints t)))
flycheck-rust
external
1: (use-package flycheck-rust 2: :ensure 3: :after flycheck 4: :config 5: (with-eval-after-load 'rustic 6: (add-hook 'flycheck-mode-hook #'flycheck-rust-setup)))
Ansible
ansible
external
1: (use-package ansible 2: :ensure 3: :defer t 4: :if (executable-find "ansible") 5: :ensure 6: :commands ansible-auto-decrypt-encrypt 7: :hook (ansible . 'ansible-auto-decrypt-encrypt) 8: :init 9: (put 'ansible-vault-password-file 'safe-local-variable #'stringp) 10: :config 11: (setq ansible-section-face 'font-lock-variable-name-face 12: ansible-task-label-face 'font-lock-doc-face) 13: :general 14: (+config/local-leader 15: :keymaps 'yaml-mode-map 16: "a" '(:ignore t :wk ansible) 17: "ad" 'ansible-decrypt-buffer 18: "ae" 'ansible-encrypt-buffer))
ansible-doc
external
1: (use-package ansible-doc 2: :after ansible 3: :ensure 4: :hook (yaml-mode . ansible-doc-mode) 5: :config 6: (when (featurep 'evil) 7: (evil-set-initial-state '(ansible-doc-module-mode) 'emacs)))
Perl
Haskell
haskell-mode
external
1: (use-package haskell-mode 2: :ensure t 3: :defer t 4: :init 5: (setq flymake-allowed-file-name-masks nil) 6: :custom 7: (haskell-process-load-or-reload-prompt t) 8: (haskell-process-auto-import-loaded-modules t) 9: (haskell-process-log t) 10: (haskell-tags-on-save t))
- lsp-haskell external
(use-package lsp-haskell :ensure t :defer t :after lsp)
The Configuration
early-init.el
- GC Threshold
A common way of speeding up Emacs startup. The variable
gc-cons-threshold
is the number of bytes consing between garbage collection. Garbage collection can happen atuomatically once this many bytes have been allocated since the last garbage collection. Here I set this to a variablemost-positive-fixnum
which value is set automatically.most-positive-fixnum
2305843009213693951
1: (setq gc-cons-threshold most-positive-fixnum 2: gc-cons-percentage 0.6)
The
gc-cons-percentage
default to 0.1, is the portion of the heap used for allocation.I set the value differently when Emacs is starting up, by setting this variable into
emacs-startup-hook
that runs after Emacs loaded the init files.1: (add-hook 'emacs-startup-hook 2: (lambda () 3: (setq gc-cons-threshold (* 16 1024 1024) ; 16mb 4: gc-cons-percentage 0.1)))
- Language
Set UTF-8 as the default coding system
1: (set-language-environment "UTF-8")
- Set initial frame
Here I disable the menu-bar, tool-bar and vertical scroll bar.
1: (push '(menu-bar-lines . 0) default-frame-alist) 2: (push '(tool-bar-lines . 0) default-frame-alist) 3: (push '(vertical-scroll-bars) default-frame-alist)
- Define the location of
custom-file
The
custom-file
is used to save customization settings for future use.1: (customize-set-variable 'custom-file (expand-file-name "custom.el" user-emacs-directory)) 2: (when (file-exists-p custom-file) 3: (load custom-file))
- Setup
package
Now much more simpler since
[[https://github.com/jwiegley/use-package][use-package]]
is built into Emacs.1: (require 'package) 2: ;; Add `melpa` to `package-archives`. 3: (add-to-list 'package-archives 4: '("melpa" . "https://melpa.org/packages/")) 5: ;; gnu-devel 6: (add-to-list 'package-archives '("gnu-devel" . "https://elpa.gnu.org/devel/")) 7: (setq package-quickstart t)
use-package
1: (require 'use-package) 2: 3: (custom-set-variables 4: '(use-package-enable-imenu-support t) 5: '(use-package-always-defer nil) 6: '(use-package-verbose nil) 7: '(use-package-check-before-init t) 8: '(use-package-compute-statistics t))
use-package-ignore-unknown-keywords
is set tot
to avoid error signaling, since I'm also usegeneral.el
that uses a:general
keyword inuse-package
.use-package-enable-imenu-support
to makeimenu
to see ause-package
declarations.use-package-check-before-init
to haveuse-package
check the package existence before executing the:init
block.
init.el
- Tangle this org-file
This file is already added in my git repositories for initial Emacs loading. But I also include it here to make sure there's no changes made.
1: (require 'ob-tangle) 2: 3: (when (file-exists-p (expand-file-name "index.org" user-emacs-directory)) 4: (org-babel-tangle-file (expand-file-name "index.org" user-emacs-directory))) 5: 6: (require 'config (expand-file-name "config.el" user-emacs-directory))
config.el
- The configuration
1: ;; Variables, and helper functions 2: (setq user-mail-address "alexforsale@yahoo.com" 3: user-full-name "Kristian Alexander P") 4: (defvar +config/user-modules-directory (expand-file-name "modules/" user-emacs-directory) 5: "User modules directory.") 6: (when (file-directory-p +config/user-modules-directory) 7: (add-to-list 'load-path +config/user-modules-directory)) 8: ;;; From https://emacs.stackexchange.com/questions/38008/adding-many-items-to-a-list/68048#68048 9: (defun merge-list-to-list (dst src) 10: "Merges content of the 2nd list with the 1st one" 11: (set dst 12: (append (eval dst) src))) 13: (when (file-directory-p (expand-file-name "Sync/org" (getenv "HOME"))) 14: (customize-set-variable '+config/org-directory (expand-file-name "Sync/org" (getenv "HOME")))) 15: ;; keybindings 16: (use-package general 17: :ensure t 18: :init 19: (general-evil-setup t) 20: (general-auto-unbind-keys) 21: :config 22: (general-override-mode) 23: (general-create-definer +config/leader-key 24: :keymaps 'override 25: :states '(insert emacs normal hybrid motion visual operator) 26: :prefix "SPC" 27: :non-normal-prefix "C-c SPC") 28: (general-create-definer +config/local-leader 29: :keymaps 'override 30: :states '(emacs normal hybrid motion visual operator) 31: :prefix "SPC m" 32: :non-normal-prefix "C-c SPC m" 33: "" '(:ignore t :which-key (lambda (arg) `(,(cadr (split-string (car arg) " ")) . ,(replace-regexp-in-string "-mode$" "" (symbol-name major-mode)))))) 34: ;; useful macro 35: (defmacro +config/leader-menu! (name infix-key &rest body) 36: "Create a definer NAME `+config/leader-NAME' wrapping `+config/leader-key'. 37: Create prefix map: `+config/leader-NAME-map'. Prefix bindings in BODY with INFIX-KEY." 38: (declare (indent 2)) 39: `(progn 40: (general-create-definer ,(intern (concat "+config/leader-" name)) 41: :wrapping +config/leader-key 42: :prefix-map (quote ,(intern (concat "+config/leader-" name "-map"))) 43: :infix ,infix-key 44: :wk-full-keys nil 45: "" '(:ignore t :which-key ,name)) 46: (,(intern (concat "+config/leader-" name)) 47: ,@body)))) 48: ;; First level menu 49: (+config/leader-menu! "activities" "C-a") 50: (+config/leader-menu! "buffer" "b") 51: (+config/leader-menu! "files" "f") 52: (+config/leader-menu! "find" "gf") 53: (+config/leader-menu! "go" "g") 54: (+config/leader-menu! "insert" "i") 55: (+config/leader-menu! "mail" "M-m") 56: (+config/leader-menu! "mark" "m") 57: (+config/leader-menu! "notes" "n") 58: (+config/leader-menu! "open" "o") 59: (+config/leader-menu! "quit" "q") 60: (+config/leader-menu! "register" "gr") 61: (+config/leader-menu! "tree" "t") 62: (+config/leader-menu! "tab" "t TAB") 63: (+config/leader-menu! "vterm" "tv") 64: (+config/leader-menu! "window" "w") 65: ;; keybindings 66: (+config/leader-key 67: ";" 'pp-eval-expression 68: ":" 'execute-extended-command 69: "^" '(subword-capitalize :wk "Capitalize subword") 70: "u" 'universal-argument) 71: ;; buffer 72: (+config/leader-buffer 73: "[" '(previous-buffer :wk "previous buffer") 74: "]" '(next-buffer :wk "next buffer") 75: "TAB" '((lambda () (interactive) (switch-to-buffer nil)) :wk "other-buffer") 76: "b" '(switch-to-buffer :wk "switch to buffer") 77: "s" '(basic-save-buffer :wk "save buffer") 78: "c" '(clone-indirect-buffer :wk "clone buffer") 79: "C" '(clone-indirect-buffer-other-window :wk "clone buffer other window") 80: "d" '(kill-current-buffer :wk "kill current buffer") 81: "i" 'ibuffer 82: "k" '(kill-buffer :wk "kill buffer") 83: "l" '(evil-switch-to-windows-last-buffer :wk "Switch to last open buffer") 84: "m" '((lambda () (interactive) (switch-to-buffer "*Messages*")) :wk "switch to messages buffer") 85: "n" '(next-buffer :wk "next buffer") 86: "N" '(evil-buffer-new :wk "New unnamed buffer") 87: "p" '(previous-buffer :wk "previous buffer") 88: "o" '((lambda () (interactive) (switch-to-buffer nil)) :wk "other-buffer") 89: "r" '(revert-buffer-quick :wk "revert buffer") 90: "R" '(rename-buffer :wk "rename buffer") 91: "x" '((lambda () (interactive) (switch-to-buffer "*scratch*")) :wk "switch to scratch buffer") 92: "z" '(bury-buffer :wk "bury buffer")) 93: (with-eval-after-load 'smartparens 94: (general-nvmap 95: :keymaps 'smartparens-mode-map 96: "<" 'sp-backward-barf-sexp 97: "C-<" 'sp-backward-slurp-sexp 98: ">" 'sp-forward-slurp-sexp 99: "C->" 'sp-forward-barf-sexp) 100: (general-define-key 101: :keymaps 'smartparens-mode-map 102: "M-DEL" 'sp-unwrap-sexp)) 103: (general-nvmap 104: 'dired-mode-map 105: "g$" 'dired-hide-subdir 106: "g?" 'dired-summary 107: "gG" 'dired-do-chgrp 108: "gj" 'dired-next-dirline 109: "gk" 'dired-prev-dirline 110: "go" 'dired-view-file 111: "gO" 'dired-find-file-other-window 112: "gy" 'dired-show-file-type) 113: ;; files 114: (+config/leader-files 115: "D" 'dired 116: "d" 'dired-jump 117: "f" '(find-file :wk "find file") 118: "F" '(find-file-other-frame :wk "find file other frame") 119: "k" 'delete-frame 120: "r" 'recentf 121: "S" '(write-file :wk "save file") 122: "s" '(save-buffer :wk "save buffer") 123: "w" '(find-file-other-window :wk "find file other window")) 124: ;; find 125: (+config/leader-find 126: "g" 'grep 127: "r" '(rgrep :wk "recursive grep")) 128: ;; help 129: (+config/leader-key 130: "h" (general-simulate-key "C-h" 131: :state '(normal visual) 132: :name general-SPC-h-simulates-C-h 133: :docstring "Simulates C-h in normal and visual mode." 134: :which-key "Help")) 135: ;; insert 136: (+config/leader-insert 137: "u" '(insert-char :wk "insert character")) 138: ;; mark 139: (+config/leader-mark 140: "m" '(bookmark-set :wk "set bookmark") 141: "b" '(bookmark-jump :wk "jump to bookmark") 142: "B" '(bookmark-jump-other-window :wk "jump to bookmark other window") 143: "C-c b" '(bookmark-jump-other-frame :wk "jump to bookmark other frame") 144: "c" '(consult-bookmark :wk "consult bookmark") ;; require `consult' package 145: "l" '(bookmark-bmenu-list :wk "list bookmarks") 146: "L" '(bookmark-load :wk "load bookmark") 147: "d" '(bookmark-delete :wk "delete bookmark") 148: "D" '(bookmark-delete-all :wk "delete all bookmarks") 149: "s" '(bookmark-save :wk "save bookmark") 150: "r" '(bookmark-rename :wk "rename bookmark")) 151: ;; open 152: (+config/leader-open 153: "i" '((lambda () (interactive) (find-file user-init-file)) :wk "open Emacs configuration file")) 154: (general-define-key 155: :keymaps 'override 156: "C-c l" '(org-store-link :wk "Store link") 157: "C-c a" '(org-agenda :wk "Org Agenda") 158: "C-c c" '(org-capture :wk "Org Capture") 159: "C-c C-s" 'org-schedule) 160: 161: (+config/leader-notes 162: "a" 'org-agenda 163: "c" 'org-capture 164: "C" 'org-capture-goto-last-stored 165: "r" 'org-refile-goto-last-stored) 166: 167: ;; (+config/local-leader 168: ;; :major-modes 'org-mode 169: ;; :keymaps 'org-mode-map 170: ;; "a" '(:ignore t :wk "action") 171: ;; "s" '(:ignore t :wk "search")) 172: 173: (+config/local-leader 174: :keymaps 'org-mode-map 175: "C-a" 'org-attach 176: "C-b" 'org-backward-heading-same-level 177: "C-c" 'org-ctrl-c-ctrl-c 178: "C-d" 'org-deadline 179: "C-e" 'org-export-dispatch 180: "C-f" 'org-forward-heading-same-level 181: "C-j" 'org-goto 182: "C-k" 'org-kill-note-or-show-branches 183: "C-l" 'org-insert-link 184: "C-n" 'org-next-visible-heading 185: "C-o" 'org-open-at-point 186: "C-p" 'org-previous-visible-heading 187: "C-q" 'org-set-tags-command 188: "C-r" 'org-fold-reveal 189: "C-s" 'org-schedule 190: "C-t" 'org-todo 191: "C-w" 'org-refile 192: "C-y" 'org-evaluate-time-range 193: "C-z" 'org-add-note 194: "M-b" 'org-previous-block 195: "M-f" 'org-next-block 196: "M-l" 'org-insert-last-stored-link 197: "M-w" 'org-refile-copy 198: "C-^" 'org-up-element 199: "C-_" 'org-down-element 200: "C-<" 'org-promote-subtree 201: "C->" 'org-demote-subtree 202: "C-," 'org-insert-structure-template 203: "C-*" 'org-list-make-subtree 204: "{" 'org-table-toggle-formula-debugger 205: "}" 'org-table-toggle-coordinate-overlays 206: "`" 'org-table-edit-field 207: "\\" 'org-match-sparse-tree 208: "^" 'org-sort 209: "[" 'org-agenda-file-to-front 210: "]" 'org-remove-file 211: "@" 'org-mark-subtree 212: "?" 'org-table-field-info 213: "=" 'org-table-eval-formula 214: ">" 'org-goto-calendar 215: "+" 'org-table-sum 216: "<" 'org-date-from-calendar 217: ";" 'org-toggle-comment 218: ":" 'org-toggle-fixed-width 219: "/" 'org-sparse-tree 220: "," 'org-priority 221: "." 'org-timestamp 222: "*" 'org-ctrl-c-star 223: "-" 'org-ctrl-c-minus 224: "#" 'org-update-statistics-cookies 225: "$" 'org-archive-subtree 226: "%" 'org-mark-ring-push 227: "'" 'org-edit-special 228: "TAB" '(org-clock-in :wk "clock-in") 229: "!" '(org-reload :wk "reload org") 230: "[" '(org-mark-ring-goto :wk "Jump to previous position in the mark ring") 231: "b" '(:ignore t :wk "buffer") 232: "bs" '(org-save-all-org-buffers :wk "save all org buffer") 233: "f" '(:ignore t :wk "files") 234: "fs" '(org-save-all-org-buffers :wk "save all org buffer") 235: "s" '(org-schedule :wk "org schedule") 236: "i" '(:ignore t :wk "insert") 237: "id" '(org-insert-drawer :wk "insert drawer") 238: "i@" '(org-cite-insert :wk "insert citation") 239: "if" '(org-footnote-action :wk "footnote") 240: "i C-f" '(org-emphasize :wk "insert emphasize") 241: "il" '(org-insert-link :wk "insert link") 242: "iD" '(org-deadline :wk "insert deadline") 243: "is" '(org-schedule :wk "insert schedule") 244: "ip" '(org-set-property :wk "insert property") 245: "it" '(org-insert-time-stamp :wk "insert time-stamp at point")) 246: ;; quit 247: (+config/leader-quit 248: "q" '(save-buffers-kill-terminal :wk "quit and save") 249: "R" '(restart-emacs :wk "restart Emacs")) 250: ;; register 251: (+config/leader-register 252: ;; "#" '(consult-register :wk "consult-register") ;; require `consult' package 253: "+" '(increment-register :wk "augment content of register") 254: "C-@" '(point-to-register :wk "store current point to register") 255: "C-SPC" '(point-to-register :wk "store current point to register") 256: "M-w" '(copy-rectangle-as-kill :wk "copy region-rectangle and save") 257: "SPC" '(point-to-register :wk "store current point to register") 258: "c" '(clear-rectangle :wk "blank out region-rectangle") 259: "d" '(delete-rectangle :wk "delete region-rectangle") 260: "f" '(frameset-to-register :wk "store frameset to register") 261: "g" '(insert-register :wk "insert register") 262: "i" '(insert-register :wk "insert register") 263: "j" '(jump-to-register :wk "jump to register") 264: "k" '(kill-rectangle :wk "cut rectangle into killed-rectangle") 265: "l" '(bookmark-bmenu-list :wk "display existing bookmarks") 266: "m" '(bookmark-set :wk "set bookmark") 267: "M" '(bookmark-set-no-overwrite :wk "set bookmark no overwrite") 268: "n" '(number-to-register :wk "store a number in a register") 269: "N" '(rectangle-number-lines :wk "insert number in front of region-rectangle") 270: "o" '(open-rectangle :wk "blank out region-rectangle") 271: "r" '(copy-rectangle-to-register :wk "copy rectangle-region to register") 272: "s" '(copy-to-register :wk "copy region to register") 273: "t" '(string-rectangle :wk "replace rectangle with string") 274: "x" '(copy-to-register :wk "copy region to register") 275: "w" '(window-configuration-to-register :wk "store window configuration to register") 276: "y" '(yank-rectangle :wk "yank last killed rectangle with upper left corner at point")) 277: ;; window 278: (+config/leader-window 279: "C-o" '(delete-other-windows :wk "delete other windows") 280: "[" '(evil-window-left :wk "left window") 281: "]" '(evil-window-right :wk "right window") 282: "+" '(enlarge-window :wk "enlarge window") 283: "-" '(shrink-window :wk "shrink window") 284: "}" '(enlarge-window-horizontally :wk "enlarge window horizontally") 285: "{" '(shrink-window-horizontally :wk "shrink window horizontally") 286: "+" 'evil-window-increase-height 287: "-" 'evil-window-decrease-height 288: ":" 'evil-ex 289: "<" 'evil-window-decrease-width 290: "=" 'balance-windows 291: ">" 'evil-window-increase-height 292: "_" 'evil-window-set-height 293: "b" 'evil-window-bottom-right 294: "c" 'evil-window-delete 295: "d" '(delete-window :wk "delete window") 296: "h" 'evil-window-left 297: "f" '(ffap-other-window :wk "ffap other window") 298: "j" 'evil-window-down 299: "k" 'evil-window-up 300: "l" 'evil-window-right 301: "n" 'evil-window-new 302: "p" 'evil-window-mru 303: "q" 'evil-quit 304: "r" 'evil-window-rotate-downwards 305: "R" 'evil-window-rotate-upwards 306: "s" 'evil-window-split 307: "T" '(tear-off-window :wk "tear off window") 308: "t" 'evil-window-top-left 309: "u" 'winner-undo 310: "v" 'evil-window-vsplit 311: "w" '(other-window :wk "other window") 312: "W" 'evil-window-prev 313: "x" 'evil-window-exchange 314: "|" 'evil-window-set-width 315: "<left>" 'evil-window-left 316: "<right>" 'evil-window-right 317: "<down>" 'evil-window-down 318: "<up>" 'evil-win-up) 319: (provide 'config-keybindings) 320: ;;; config-keybindings.el ends.here 321: ;; evil 322: (use-package evil 323: :ensure t 324: :demand t 325: :preface 326: (customize-set-variable 'evil-want-keybinding nil) 327: (customize-set-variable 'evil-want-integration t) 328: (customize-set-variable 'evil-undo-system 'undo-redo) 329: (customize-set-variable 'evil-want-C-i-jump nil) ;; fix TAB in terminal org-mode 330: (customize-set-variable 'evil-want-C-u-scroll t) ;; move universal arg to <leader> u 331: (customize-set-variable 'evil-want-C-u-delete t) ;; delete back to indentation in insert state 332: (customize-set-variable 'evil-want-C-g-bindings t) 333: :custom 334: (evil-undo-system #'undo-redo) 335: (evil-search-module 'evil-search) 336: (evil-ex-search-vim-style-regexp t) 337: (evil-ex-interactive-search-highlight 'selected-window) 338: (evil-kbd-macro-suppress-motion-error t) 339: (evil-visual-update-x-selection-p nil) 340: :config 341: (setq evil-normal-state-cursor 'box 342: evil-insert-state-cursor 'bar 343: evil-visual-state-cursor 'hollow) 344: (evil-select-search-module 'evil-search-module 'evil-search) 345: (evil-mode 1) 346: (with-eval-after-load 'eldoc 347: (eldoc-add-command 'evil-normal-state 348: 'evil-insert 349: 'evil-change 350: 'evil-delete 351: 'evil-replace))) 352: (use-package evil-collection 353: :ensure t 354: :after evil 355: :init 356: (evil-collection-init) 357: :custom 358: (evil-collection-setup-minibuffer t) 359: (evil-collection-calendar-want-org-bindings t)) 360: ;; UI 361: (use-package ace-window 362: :ensure 363: :config 364: (setq aw-keys '(?q ?w ?e ?r ?t ?a ?s ?d ?f ?z ?x ?c ?v) 365: aw-background nil 366: aw-frame-size 2) 367: (custom-set-faces 368: '(aw-leading-char-face 369: ((t (:inherit ace-jump-face-foreground :height 4.0))))) 370: :bind ([remap other-window] . ace-window)) 371: (use-package doom-themes 372: :ensure t 373: :demand t 374: :config 375: ;; Global settings (defaults) 376: (setq doom-themes-enable-bold t ; if nil, bold is universally disabled 377: doom-themes-enable-italic t) ; if nil, italics is universally disabled 378: (load-theme 'doom-nord t) 379: 380: ;; Enable flashing mode-line on errors 381: (doom-themes-visual-bell-config) 382: ;; Enable custom neotree theme (all-the-icons must be installed!) 383: ;; (doom-themes-neotree-config) 384: ;; or for treemacs users 385: (setq doom-themes-treemacs-theme "doom-atom") ; use "doom-colors" for less minimal icon theme 386: (doom-themes-treemacs-config) 387: ;; Corrects (and improves) org-mode's native fontification. 388: (doom-themes-org-config)) 389: (use-package doom-modeline 390: :ensure 391: :init 392: (doom-modeline-mode 1) 393: :config 394: (setq doom-modeline-project-detection 'projectile 395: doom-modeline-indent-info t)) 396: ;; use-package with package.el: 397: (use-package dashboard 398: :ensure t 399: :demand t 400: :init 401: (setq dashboard-set-heading-icons t 402: dashboard-icon-type 'all-the-icons) 403: (setq dashboard-heading-icons '((recents . "history") 404: (bookmarks . "bookmark") 405: (agenda . "calendar") 406: (projects . "rocket") 407: (registers . "database"))) 408: :custom 409: (initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))) 410: (dashboard-startup-banner 'logo) 411: (dashboard-set-heading-icons t) 412: (dashboard-set-file-icons t) 413: (dashboard-display-icons-p t) 414: (dashboard-icon-type 'nerd-icons) 415: (dashboard-projects-switch-function 'projectile-persp-switch-project) 416: (dashboard-week-agenda t) 417: (dashboard-filter-agenda-entry nil) 418: (dashboard-startup-banner 'logo) 419: (dashboard-center-content t) 420: (dashboard-vertically-center-content t) 421: (dashboard-agenda-sort-strategy 422: '(todo-state-up time-down priority-down todo-state-down time-up priority-up)) 423: (dashboard-navigation-cycle t) 424: (dashboard-banner-logo-title nil) 425: (dashboard-set-heading-icons t) 426: (dashboard-set-footer nil) 427: (dashboard-projects-backend 'projectile) 428: (dashboard-display-icons-p t) 429: (dashboard-items '((recents . 3) 430: (bookmarks . 2) 431: (projects . 5) 432: (agenda . 8) 433: (registers . 2))) 434: :config 435: (dashboard-setup-startup-hook)) 436: (use-package all-the-icons 437: :ensure 438: :if (display-graphic-p)) 439: (use-package which-key 440: :ensure 441: :demand t 442: :custom 443: (which-key-lighter "") 444: (which-key-sort-order #'which-key-key-order-alpha) 445: (which-key-sort-uppercase-first nil) 446: (which-key-add-column-padding 1) 447: (which-key-max-display-columns nil) 448: (which-key-min-display-lines 6) 449: (which-key-compute-remaps t) 450: (which-key-side-window-slot -10) 451: (which-key-separator " → ") 452: (which-key-allow-evil-operators t) 453: (which-key-use-C-h-commands t) 454: (which-key-show-remaining-keys t) 455: (which-key-show-prefix 'bottom) 456: :config 457: (which-key-mode) 458: (which-key-setup-side-window-bottom) 459: (which-key-setup-minibuffer) 460: (define-key which-key-mode-map (kbd "C-x <f5>") 'which-key-C-h-dispatch)) 461: (set-face-attribute 'default nil :family "Iosevka Nerd Font Mono") 462: (set-face-attribute 'variable-pitch nil :family "Iosevka Nerd Font Mono") 463: (use-package font-core 464: :init 465: (global-font-lock-mode t)) 466: (use-package rainbow-mode 467: :ensure 468: :hook (prog-mode . rainbow-mode)) 469: 470: (use-package rainbow-identifiers 471: :ensure 472: :hook (prog-mode . rainbow-identifiers-mode)) 473: 474: (use-package rainbow-delimiters 475: :ensure 476: :hook (prog-mode . rainbow-delimiters-mode)) 477: (use-package helpful 478: :ensure 479: :bind 480: ("C-h f" . helpful-function) 481: ([remap describe-symbol] . helpful-symbol) 482: ([remap describe-variable] . helpful-variable) 483: ([remap describe-command] . helpful-command) 484: ([remap describe-key] . helpful-key) 485: :custom 486: (helpful-max-buffers 2) 487: :config 488: (with-eval-after-load 'general 489: (general-define-key 490: "C-h F" 'helpful-function 491: :keymaps 'prog-mode-map 492: "C-c C-d" 'helpful-at-point) 493: (general-nvmap 494: :keymaps 'prog-mode-map 495: "K" '(helpful-at-point :wk "helpful at point") 496: "gr" '(helpful-update :wk "update")))) 497: (use-package hl-line 498: :config 499: (global-hl-line-mode 1)) 500: (use-package nerd-icons 501: :ensure t 502: :custom 503: ;; The Nerd Font you want to use in GUI 504: ;; "Symbols Nerd Font Mono" is the default and is recommended 505: ;; but you can use any other Nerd Font if you want 506: (nerd-icons-font-family "Symbols Nerd Font Mono")) 507: (when (file-directory-p (expand-file-name "site-lisp/nerd-fonts" user-emacs-directory)) 508: (add-to-list 'load-path (expand-file-name "site-lisp/nerd-fonts" user-emacs-directory))) 509: 510: (use-package nerd-fonts) 511: (use-package paren 512: :config 513: (show-paren-mode 1) 514: :custom 515: (show-paren-style 'mixed)) 516: ;; builtins 517: (use-package emacs 518: :ensure nil 519: :init 520: ;; Add prompt indicator to `completing-read-multiple'. 521: ;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma. 522: (defun crm-indicator (args) 523: (cons (format "[CRM%s] %s" 524: (replace-regexp-in-string 525: "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" "" 526: crm-separator) 527: (car args)) 528: (cdr args))) 529: (advice-add #'completing-read-multiple :filter-args #'crm-indicator) 530: ;; Do not allow the cursor in the minibuffer prompt 531: (setq minibuffer-prompt-properties 532: '(read-only t cursor-intangible t face minibuffer-prompt)) 533: (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) 534: ;; Emacs 28: Hide commands in M-x which do not work in the current mode. 535: ;; Vertico commands are hidden in normal buffers. 536: (setq read-extended-command-predicate 537: #'command-completion-default-include-p 538: tab-always-indent 'complete) 539: ;; Enable recursive minibuffers 540: (setq enable-recursive-minibuffers t) 541: :custom 542: (read-buffer-completion-ignore-case t) 543: (use-short-answers t) 544: (use-dialog-box-p nil) 545: (window-resize-pixelwise t) 546: (frame-resize-pixelwise t) 547: (ring-bell-function #'ignore) 548: (scroll-preserve-screen-position t) 549: (scroll-conservatively 101) 550: (fast-but-imprecise-scrolling t) 551: (truncate-partial-width-windows nil) 552: (fill-column 80) 553: (enable-recursive-minibuffers t) 554: (use-file-dialog nil) 555: (create-lockfiles nil) 556: (delete-by-moving-to-trash t) 557: (inhibit-startup-screen t) 558: :config 559: (setq completion-ignore-case t 560: load-prefer-newer t 561: auto-window-vscroll nil 562: inhibit-compacting-font-caches t 563: redisplay-skip-fontification-on-input t) 564: (set-default 'indicate-empty-lines t) 565: (setq-default x-stretch-cursor t)) 566: (use-package files 567: :config 568: (defun full-auto-save () 569: (interactive) 570: (save-excursion 571: (dolist (buf (buffer-list)) 572: (set-buffer buf) 573: (if (and (buffer-file-name) (buffer-modified-p)) 574: (basic-save-buffer))))) 575: (add-hook 'auto-save-hook 'full-auto-save) 576: (nconc 577: auto-mode-alist 578: '(("/LICENSE\\'" . text-mode) 579: ("\\.log\\'" . text-mode) 580: ("rc\\'" . conf-mode) 581: ("\\.\\(?:hex\\|nes\\)\\'" . hexl-mode))) 582: :custom 583: (confirm-kill-emacs #'yes-or-no-p) ; confirm when exiting 584: (confirm-kill-processes nil) ; don't confirm killing processes 585: (revert-without-query (list ".")) 586: (find-file-visit-truename t) ; `find-file' will visit the actual file 587: (version-control t) 588: (backup-by-copying t) 589: (delete-old-versions t) 590: (kept-new-versions 6) 591: (kept-old-versions 2) 592: (auto-save-include-big-deletions t) 593: (auto-save-list-file-prefix (expand-file-name ".autosave/" user-emacs-directory)) 594: (backup-directory-alist `(("." . ,(expand-file-name ".backup" user-emacs-directory)))) 595: (auto-mode-case-fold nil) 596: (require-final-newline t)) 597: (use-package saveplace 598: :init 599: (save-place-mode 1) 600: :custom 601: (save-place-file (expand-file-name "places" user-emacs-directory))) 602: (use-package autorevert 603: :init 604: (global-auto-revert-mode 1) 605: :custom 606: (auto-revert-interval 60) 607: (global-auto-revert-non-file-buffers t) 608: (auto-revert-verbose nil) 609: (auto-revert-stop-on-user-input t)) 610: (use-package savehist 611: :init 612: (savehist-mode 1) 613: :custom 614: (savehist-file (expand-file-name "history" user-emacs-directory)) 615: (savehist-coding-system 'utf-8) 616: (savehist-additional-variables 617: '(evil-jumps-history 618: kill-ring 619: register-alist 620: mark-ring 621: global-mark-ring 622: search-ring 623: regexp-search-ring))) 624: (use-package recentf 625: :bind ("C-c f" . recentf) 626: :custom 627: (recentf-max-saved-items 250) 628: (recentf-max-menu-items 300) 629: (recentf-exclude 630: `("/elpa/" ;; ignore all files in elpa directory 631: "recentf" ;; remove the recentf load file 632: ".*?autoloads.el$" 633: "treemacs-persist" 634: "company-statistics-cache.el" ;; ignore company cache file 635: "/intero/" ;; ignore script files generated by intero 636: "/journal/" ;; ignore daily journal files 637: ".gitignore" ;; ignore `.gitignore' files in projects 638: "/tmp/" ;; ignore temporary files 639: "NEWS" ;; don't include the NEWS file for recentf 640: "bookmarks" "bmk-bmenu" ;; ignore bookmarks file in .emacs.d 641: "loaddefs.el" 642: "^/\\(?:ssh\\|su\\|sudo\\)?:" ;; ignore tramp/ssh files 643: (concat "^" (regexp-quote (or (getenv "XDG_RUNTIME_DIR"))))))) 644: (use-package server 645: :config 646: (unless (server-running-p) 647: (server-start)) 648: (require 'org-protocol)) 649: (use-package prog-mode 650: :hook ((prog-mode . prettify-symbols-mode) 651: (prog-mode . visual-line-mode) 652: ;; (prog-mode . (lambda () (electric-pair-mode 1))) 653: ) 654: :config 655: (setq prettify-symbols-alist 656: '(("|>" . "▷") 657: ("<|" . "◁") 658: ("->>" . "↠ ") 659: ("->" . "→ ") 660: ("<-" . "← ") 661: ("=>" . "⇒")))) 662: (use-package bookmark 663: :custom 664: (bookmark-save-flag 1) 665: (bookmark-default-file (expand-file-name ".bookmark" user-emacs-directory))) 666: (use-package tramp 667: :custom 668: (tramp-backup-directory-alist backup-directory-alist) 669: (tramp-auto-save-directory (expand-file-name ".tramp-autosave/" user-emacs-directory))) 670: (use-package epg-config 671: :custom 672: (epg-pinentry-mode 'loopback)) 673: (use-package simple 674: :custom 675: (save-interprogram-paste-before-kill t) 676: (shift-select-mode nil) 677: (kill-do-not-save-duplicates t) 678: (shift-select-mode nil) 679: (set-mark-command-repeat-pop t) 680: (indent-tabs-mode nil) 681: (column-number-mode t) 682: (idle-update-delay 1.0) 683: :config 684: (with-eval-after-load 'evil 685: (evil-set-initial-state #'message-mode 'insert))) 686: ;; completion 687: (use-package vertico 688: :ensure 689: :init 690: (vertico-mode) 691: ;; Different scroll margin 692: ;; (setq vertico-scroll-margin 0) 693: ;; Show more candidates 694: ;; (setq vertico-count 20) 695: ;; Grow and shrink the Vertico minibuffer 696: ;; (setq vertico-resize t) 697: ;; Optionally enable cycling for `vertico-next' and `vertico-previous'. 698: (setq vertico-cycle t) 699: ) 700: 701: ;; A few more useful configurations... 702: (use-package emacs 703: :init 704: ;; Add prompt indicator to `completing-read-multiple'. 705: ;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma. 706: (defun crm-indicator (args) 707: (cons (format "[CRM%s] %s" 708: (replace-regexp-in-string 709: "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" "" 710: crm-separator) 711: (car args)) 712: (cdr args))) 713: (advice-add #'completing-read-multiple :filter-args #'crm-indicator) 714: ;; Do not allow the cursor in the minibuffer prompt 715: (setq minibuffer-prompt-properties 716: '(read-only t cursor-intangible t face minibuffer-prompt)) 717: (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) 718: ;; Support opening new minibuffers from inside existing minibuffers. 719: (setq enable-recursive-minibuffers t) 720: ;; Emacs 28 and newer: Hide commands in M-x which do not work in the current 721: ;; mode. Vertico commands are hidden in normal buffers. This setting is 722: ;; useful beyond Vertico. 723: (setq read-extended-command-predicate #'command-completion-default-include-p)) 724: (use-package vertico-directory 725: :after vertico 726: :ensure nil 727: ;; More convenient directory navigation commands 728: :bind (:map vertico-map 729: ("RET" . vertico-directory-enter) 730: ("DEL" . vertico-directory-delete-char) 731: ("M-DEL" . vertico-directory-delete-word)) 732: ;; Tidy shadowed file names 733: :hook (rfn-eshadow-update-overlay . vertico-directory-tidy)) 734: (use-package vertico-quick 735: :after vertico 736: :ensure nil 737: :bind (:map vertico-map 738: ("M-q" . vertico-quick-insert) 739: ("C-q" . vertico-quick-exit))) 740: ;; Enable rich annotations using the Marginalia package 741: (use-package marginalia 742: :ensure 743: :bind (:map minibuffer-local-map 744: ("M-A" . marginalia-cycle)) 745: :init 746: (marginalia-mode)) 747: (use-package corfu 748: :ensure 749: :custom 750: (corfu-cycle t) 751: (corfu-auto t) 752: (corfu-quit-no-match 'separator) 753: (corfu-preselect 'prompt) 754: (completion-cycle-threshold 3) 755: :init 756: (global-corfu-mode)) 757: (use-package consult 758: :ensure 759: :hook (completion-list-mode . consult-preview-at-point-mode) 760: :init 761: ;; Optionally configure the register formatting. This improves the register 762: ;; preview for `consult-register', `consult-register-load', 763: ;; `consult-register-store' and the Emacs built-ins. 764: (setq register-preview-delay 0.5 765: register-preview-function #'consult-register-format) 766: ;; Optionally tweak the register preview window. 767: ;; This adds thin lines, sorting and hides the mode line of the window. 768: (advice-add #'register-preview :override #'consult-register-window) 769: ;; Use Consult to select xref locations with preview 770: (setq xref-show-xrefs-function #'consult-xref 771: xref-show-definitions-function #'consult-xref) 772: ;; Configure other variables and modes in the :config section, 773: ;; after lazily loading the package. 774: :config 775: ;; Optionally configure preview. The default value 776: ;; is 'any, such that any key triggers the preview. 777: ;; (setq consult-preview-key 'any) 778: ;; (setq consult-preview-key "M-.") 779: ;; (setq consult-preview-key '("S-<down>" "S-<up>")) 780: ;; For some commands and buffer sources it is useful to configure the 781: ;; :preview-key on a per-command basis using the `consult-customize' macro. 782: (consult-customize 783: consult-theme :preview-key '(:debounce 0.2 any) 784: consult-ripgrep consult-git-grep consult-grep 785: consult-bookmark consult-recent-file consult-xref 786: consult--source-bookmark consult--source-file-register 787: consult--source-recent-file consult--source-project-recent-file 788: ;; :preview-key "M-." 789: :preview-key '(:debounce 0.4 any)) 790: ;; Optionally configure the narrowing key. 791: ;; Both < and C-+ work reasonably well. 792: (setq consult-narrow-key "<") ;; "C-+" 793: ;; Optionally make narrowing help available in the minibuffer. 794: ;; You may want to use `embark-prefix-help-command' or which-key instead. 795: ;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help) 796: ;; By default `consult-project-function' uses `project-root' from project.el. 797: ;; Optionally configure a different project root function. 798: ;;;; 1. project.el (the default) 799: ;; (setq consult-project-function #'consult--default-project--function) 800: ;;;; 2. vc.el (vc-root-dir) 801: ;; (setq consult-project-function (lambda (_) (vc-root-dir))) 802: ;;;; 3. locate-dominating-file 803: ;; (setq consult-project-function (lambda (_) (locate-dominating-file "." ".git"))) 804: ;;;; 4. projectile.el (projectile-project-root) 805: ;; (autoload 'projectile-project-root "projectile") 806: ;; (setq consult-project-function (lambda (_) (projectile-project-root))) 807: ;;;; 5. No project support 808: ;; (setq consult-project-function nil)) 809: ) 810: 811: (use-package orderless 812: :ensure 813: :init 814: ;; Configure a custom style dispatcher (see the Consult wiki) 815: ;; (setq orderless-style-dispatchers '(+orderless-consult-dispatch orderless-affix-dispatch) 816: ;; orderless-component-separator #'orderless-escapable-split-on-space) 817: (setq completion-styles '(orderless basic) 818: completion-category-defaults nil 819: completion-category-overrides '((file (styles partial-completion))))) 820: (use-package nerd-icons-corfu 821: :ensure 822: :config 823: (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter) 824: (setq nerd-icons-corfu-mapping 825: '((array :style "cod" :icon "symbol_array" :face font-lock-type-face) 826: (boolean :style "cod" :icon "symbol_boolean" :face font-lock-builtin-face) 827: ;; ... 828: (t :style "cod" :icon "code" :face font-lock-warning-face)))) 829: (use-package nerd-icons-completion 830: :ensure 831: :hook (marginalia-mode . nerd-icons-completion-marginalia-setup) 832: :config 833: (nerd-icons-completion-mode)) 834: ;; shells 835: (use-package eshell 836: :ensure nil 837: :custom 838: (eshell-history-size 10000) 839: (eshell-hist-ignore-dups t) 840: (eshell-buffer-maximum-lines 10000) 841: (eshell-scroll-to-bottom-on-input t) 842: (eshell-destroy-buffer-when-process-dies t) 843: (eshell-prompt-regexp "^[^\)]*[\)] ")) 844: (use-package eshell-syntax-highlighting 845: :ensure 846: :defer t 847: :after eshell 848: :config 849: (eshell-syntax-highlighting-global-mode +1)) 850: (use-package esh-autosuggest 851: :defer t 852: :hook (eshell-mode . esh-autosuggest-mode) 853: ;; If you have use-package-hook-name-suffix set to nil, uncomment and use the 854: ;; line below instead: 855: ;; :hook (eshell-mode-hook . esh-autosuggest-mode) 856: :ensure t) 857: (use-package sh-script 858: :mode ("\\.bats\\'" . sh-mode) 859: :mode ("\\.\\(?:zunit\\|env\\)\\'" . sh-mode) 860: :mode ("/bspwmrc\\'" . sh-mode) 861: :hook (sh-mode-local-vars . lsp-deferred) 862: :hook (sh-mode-local-vars . tree-sitter-mode) 863: :config 864: (with-eval-after-load 'lsp 865: (add-hook 'sh-mode-hook #'lsp-deferred) 866: (add-hook 'shell-mode-hook #'lsp-deferred) 867: (add-hook 'sh-mode-local-vars-hook #'lsp-deferred)) 868: (with-eval-after-load 'rainbow-delimiters 869: (add-hook 'sh-mode #'rainbow-delimiters-mode)) 870: ;; recognize function names with dashes in them 871: (setq sh-indent-after-continuation 'always) 872: (add-to-list 'sh-imenu-generic-expression 873: '(sh (nil "^\\s-*function\\s-+\\([[:alpha:]_-][[:alnum:]_-]*\\)\\s-*\\(?:()\\)?" 1) 874: (nil "^\\s-*\\([[:alpha:]_-][[:alnum:]_-]*\\)\\s-*()" 1))) 875: (with-eval-after-load 'smartparens 876: (sp-local-pair 'sh-mode "`" "`" :unless '(sp-point-before-word-p sp-point-before-same-p)))) 877: (use-package vterm 878: :ensure 879: :defer t 880: :commands vterm-mode 881: :config 882: (add-hook 'vterm-mode-hook 883: (lambda () 884: (setq-local global-hl-line-mode nil) 885: (setq-local hscroll-margin 0))) 886: (setq vterm-kill-buffer-on-exit t) 887: :general 888: (+config/leader-menu! "vterm" 889: "tv" 890: "RET" 'vterm-toggle 891: "v" 'vterm)) 892: (use-package multi-vterm 893: :ensure 894: :defer t 895: :after vterm 896: :general 897: (general-iemap 898: :keymaps 'vterm-mode-map 899: "C-SPC" '(:ignore t :wk "multi vterm") 900: "C-SPC a" '(multi-vterm :wk "new vterm buffer") 901: "C-SPC n" '(multi-vterm-next :wk "next vterm buffer") 902: "C-SPC p" '(multi-vterm-prev :wk "previous vterm buffer"))) 903: (use-package vterm-toggle 904: :ensure 905: :defer t 906: :after vterm 907: :commands vterm-toggle 908: :bind 909: (:map vterm-mode-map 910: ("C-<return>" . vterm-toggle-insert-cd)) 911: :config 912: (setq vterm-toggle-fullscreen-p nil) 913: (add-to-list 'display-buffer-alist 914: '((lambda (buffer-or-name _) 915: (let ((buffer (get-buffer buffer-or-name))) 916: (with-current-buffer buffer 917: (or (equal major-mode 'vterm-mode) 918: (string-prefix-p vterm-buffer-name (buffer-name buffer)))))) 919: (display-buffer-reuse-window display-buffer-at-bottom) 920: ;;(display-buffer-reuse-window display-buffer-in-direction) 921: ;;display-buffer-in-direction/direction/dedicated is added in emacs27 922: ;;(direction . bottom) 923: (dedicated . t) ;dedicated is supported in emacs27 924: (reusable-frames . visible) 925: (window-height . 0.4)))) 926: (use-package bash-completion 927: :ensure 928: :defer t 929: :config 930: (bash-completion-setup) 931: :hook 932: (shell-dynamic-complete-function bash-completion-dynamic-complete)) 933: ;; editing 934: (use-package select 935: :custom 936: (select-enable-clipboard t)) 937: (transient-mark-mode 1) 938: (delete-selection-mode 1) 939: (use-package subword 940: :init 941: (global-subword-mode 1)) 942: (use-package text-mode 943: :ensure nil 944: :hook (text-mode . visual-line-mode) 945: :config 946: (setq-default sentence-end-double-space nil)) 947: (use-package ws-butler 948: :ensure 949: :hook (prog-mode . ws-butler-mode)) 950: ;; smartparens 951: (use-package smartparens 952: :ensure 953: :demand t 954: :init 955: (smartparens-global-mode) 956: :config 957: ;; smartparens recognizes `slime-mrepl-mode', but not `sly-mrepl-mode', so... 958: (add-to-list 'sp-lisp-modes 'sly-mrepl-mode) 959: (require 'smartparens-config) 960: (add-hook 'eval-expression-minibuffer-setup-hook #'smartparens-mode) 961: ;; Overlays are too distracting and not terribly helpful. show-parens does 962: ;; this for us already (and is faster), so... 963: (setq sp-highlight-pair-overlay nil 964: sp-highlight-wrap-overlay nil 965: sp-highlight-wrap-tag-overlay nil) 966: (show-smartparens-global-mode 1) 967: (smartparens-global-mode 1) 968: ;; Fix usage of ' in Lisp modes 969: ;; THANKS: https://github.com/Fuco1/smartparens/issues/286#issuecomment-32324743 970: ;; (eval) is used as a hack to quiet Flycheck errors about (sp-with-modes) 971: (eval 972: '(sp-with-modes sp-lisp-modes 973: ;; disable ', it's the quote character! 974: (sp-local-pair "'" nil :actions nil) 975: ;; also only use the pseudo-quote inside strings where it serve as 976: ;; hyperlink. 977: (sp-local-pair "`" "'" :when '(sp-in-string-p sp-in-comment-p)) 978: (sp-local-pair "`" nil 979: :skip-match (lambda (ms mb me) 980: (cond 981: ((equal ms "'") 982: (or (sp--org-skip-markup ms mb me) 983: (not (sp-point-in-string-or-comment)))) 984: (t (not (sp-point-in-string-or-comment)))))))) 985: (sp-with-modes '(html-mode sgml-mode nxml-mode web-mode) 986: (sp-local-pair "<" ">")) 987: 988: (defun sp--markdown-skip-asterisk (ms mb me) 989: (save-excursion 990: (goto-char mb) 991: (save-match-data (looking-at "^\\* ")))) 992: 993: (sp-with-modes 'markdown-mode 994: (sp-local-pair "*" "*" 995: :unless '(sp-point-after-word-p sp-point-at-bol-p) 996: :skip-match 'sp--markdown-skip-asterisk) 997: (sp-local-pair "**" "**") 998: (sp-local-pair "_" "_" :unless '(sp-point-after-word-p))) 999: 1000: ;;; org-mode 1001: (defun sp--org-skip-asterisk (ms mb me) 1002: (or (and (= (line-beginning-position) mb) 1003: (eq 32 (char-after (1+ mb)))) 1004: (and (= (1+ (line-beginning-position)) me) 1005: (eq 32 (char-after me))))) 1006: (defun sp--org-inside-LaTeX (id action context) 1007: (org-inside-LaTeX-fragment-p)) 1008: (sp-with-modes 'org-mode 1009: (sp-local-pair "*" "*" 1010: :unless '(sp-point-after-word-p sp--org-inside-LaTeX sp-point-at-bol-p) 1011: :skip-match 'sp--org-skip-asterisk) 1012: (sp-local-pair "/" "/" :unless '(sp-point-after-word-p sp--org-inside-LaTeX)) 1013: (sp-local-pair "~" "~" :unless '(sp-point-after-word-p sp--org-inside-LaTeX)) 1014: (sp-local-pair "=" "=" :unless '(sp-point-after-word-p sp--org-inside-LaTeX)) 1015: (sp-local-pair "\\[" "\\]")) 1016: 1017: ;; haskell 1018: (add-to-list 'sp-no-reindent-after-kill-modes 'haskell-mode) 1019: 1020: ;; You're likely writing lisp in the minibuffer, therefore, disable these 1021: ;; quote pairs, which lisps doesn't use for strings: 1022: (sp-local-pair '(minibuffer-mode minibuffer-inactive-mode) "'" nil :actions nil) 1023: (sp-local-pair '(minibuffer-mode minibuffer-inactive-mode) "`" nil :actions nil) 1024: ) 1025: ;; IDE stuffs 1026: ;; org-mode 1027: (use-package org 1028: :commands org-tempo 1029: :preface 1030: (if (not +config/org-directory) 1031: (cond 1032: ((file-directory-p 1033: (expand-file-name "Dropbox/org" (getenv "HOME"))) 1034: (setq org-directory (expand-file-name "Dropbox/org" (getenv "HOME")))) 1035: ((file-directory-p 1036: (expand-file-name "Sync/org" (getenv "HOME"))) 1037: (setq org-directory (expand-file-name "Sync/org" (getenv "HOME")))) 1038: ((file-directory-p 1039: (expand-file-name "Documents/google-drive/org" (getenv "HOME"))) 1040: (setq org-directory (expand-file-name "Documents/google-drive/org" (getenv "HOME"))))) 1041: (customize-set-variable 'org-directory +config/org-directory)) 1042: :hook ((org-mode . org-indent-mode) 1043: (org-mode . +config/org-prettify-symbols)) 1044: :config 1045: (global-set-key (kbd "C-c l") #'org-store-link) 1046: (global-set-key (kbd "C-c a") #'org-agenda) 1047: (global-set-key (kbd "C-c c") #'org-capture) 1048: (when(file-directory-p (expand-file-name "braindump/org" org-directory)) 1049: (customize-set-variable '+config/org-roam-directory 1050: (expand-file-name "braindump/org" org-directory))) 1051: (when (file-directory-p (expand-file-name "alexforsale.github.io" org-directory)) 1052: (customize-set-variable '+config/blog-directory 1053: (expand-file-name "alexforsale.github.io" org-directory))) 1054: (modify-syntax-entry ?= "$" org-mode-syntax-table) 1055: (modify-syntax-entry ?~ "$" org-mode-syntax-table) 1056: (modify-syntax-entry ?_ "$" org-mode-syntax-table) 1057: (modify-syntax-entry ?+ "$" org-mode-syntax-table) 1058: (modify-syntax-entry ?/ "$" org-mode-syntax-table) 1059: (modify-syntax-entry ?* "$" org-mode-syntax-table) 1060: (add-to-list 'org-modules 'org-tempo t) 1061: (add-to-list 'org-structure-template-alist '("sh" . "src sh")) 1062: (add-to-list 'org-structure-template-alist '("co" . "src conf")) 1063: (add-to-list 'org-structure-template-alist '("lisp" . "src lisp")) 1064: (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) 1065: (add-to-list 'org-structure-template-alist '("sc" . "src scheme")) 1066: (add-to-list 'org-structure-template-alist '("ts" . "src typescript")) 1067: (add-to-list 'org-structure-template-alist '("py" . "src python")) 1068: (add-to-list 'org-structure-template-alist '("go" . "src go")) 1069: (add-to-list 'org-structure-template-alist '("yaml" . "src yaml")) 1070: (add-to-list 'org-structure-template-alist '("js" . "src js")) 1071: (add-to-list 'org-structure-template-alist '("json" . "src json")) 1072: (add-to-list 'org-structure-template-alist '("n" . "note")) 1073: (org-babel-do-load-languages 1074: 'org-babel-load-languages 1075: '((emacs-lisp . t) 1076: (awk . t) 1077: (C . t) 1078: (css . t) 1079: (calc . t) 1080: ;; (ditaa . t) ; needs the `ditaa' package 1081: ;; (diagrams . t) ; `ob-diagrams' 1082: ;; (dot . t ) ; `graphviz' 1083: (screen . t) 1084: (haskell . t) 1085: (java . t) 1086: (js . t) 1087: (latex . t) 1088: (lisp . t) 1089: (lua . t) 1090: (org . t) 1091: (perl . t) 1092: (plantuml . t) 1093: (python .t) 1094: (ruby . t) 1095: (shell . t) 1096: (sed . t) 1097: (scheme . t) 1098: (sql . t) 1099: (sqlite . t))) 1100: (setq-default org-use-sub-superscripts '{}) 1101: (add-to-list 'org-babel-tangle-lang-exts '("js" . "js")) 1102: (defun +config/org-prettify-symbols () 1103: (push '("[ ]" . "☐") prettify-symbols-alist) 1104: (push '("[X]" . "☑") prettify-symbols-alist) 1105: (prettify-symbols-mode)) 1106: :custom 1107: (org-replace-disputed-keys t) 1108: (org-indirect-buffer-display 'current-window) 1109: (org-enforce-todo-dependencies t) 1110: (org-fontify-whole-heading-line t) 1111: (org-return-follows-link t) 1112: (org-mouse-1-follows-link t) 1113: (org-image-actual-width nil) 1114: (org-adapt-indentation nil) 1115: (org-startup-indented t) 1116: (org-link-descriptive nil) 1117: (org-log-done 'time) 1118: (org-log-refile 'time) 1119: (org-log-redeadline 'time) 1120: (org-log-reschedule 'time) 1121: (org-log-into-drawer t) 1122: (org-clone-delete-id t) 1123: (org-default-notes-file (expand-file-name "notes.org" org-directory)) 1124: (org-insert-heading-respect-content nil) 1125: (org-pretty-entities t) 1126: (org-use-property-inheritance t) 1127: (org-priority-highest ?A) 1128: (org-priority-lowest ?D) 1129: (org-priority-default ?B) 1130: (org-todo-keywords 1131: '((sequence 1132: "TODO(t!)" ; A task that needs doing & is ready to do 1133: "NEXT(n!)" ; Tasks that can be delayed 1134: "PROG(p!)" ; A task that is in progress 1135: "WAIT(w!)" ; Something external is holding up this task 1136: "HOLD(h!)" ; This task is paused/on hold because of me 1137: "|" 1138: "DONE(d!)" ; Task successfully completed 1139: "DELEGATED(l!)" ; Task is delegated 1140: "KILL(k!)") ; Task was cancelled, aborted or is no longer applicable 1141: )) 1142: (org-todo-keyword-faces 1143: '(("PROG" . (:foreground "#5e81ac" :weight bold)) 1144: ("WAIT" . (:foreground "#ebcb8b" :weight bold)) 1145: ("HOLD" . (:foreground "#d08770" :weight bold)) 1146: ("NEXT" . (:foreground "#81a1c1" :weight bold)) 1147: ("DELEGATED" . "#8fbcbb") 1148: ("KILL" . "#a3be8c")))) 1149: (use-package org-faces 1150: :custom 1151: (org-fontify-quote-and-verse-blocks t)) 1152: (use-package org-archive 1153: :after org 1154: :custom 1155: (org-archive-tag "archive") 1156: (org-archive-subtree-save-file-p t) 1157: (org-archive-mark-done t) 1158: (org-archive-reversed-order t) 1159: (org-archive-location (concat (expand-file-name "archives.org" org-directory) "::datetree/* Archived Tasks"))) 1160: (use-package org-capture 1161: :after org 1162: :demand t 1163: :config 1164: (org-capture-put :kill-buffer t) 1165: (setq org-capture-templates ;; this is the default from `doom'. 1166: `(("i" "Inbox - Goes Here first!" entry 1167: (file+headline ,(expand-file-name "inbox.org" org-directory) "Inbox") 1168: "** %?\n%i\n%a" :prepend t) 1169: ("r" "Request" entry (file+headline ,(expand-file-name "inbox.org" org-directory) "Request") 1170: (file ,(expand-file-name "request.template" org-directory))) 1171: ("l" "Links" entry 1172: (file+headline ,(expand-file-name "links.org" org-directory) "Links"))))) 1173: (use-package org-refile 1174: :after org 1175: :hook (org-after-refile-insert . save-buffer) 1176: :custom 1177: (org-refile-targets 1178: `((,(expand-file-name "projects.org" org-directory) :maxlevel . 1) 1179: (,(expand-file-name "routines.org" org-directory) :maxlevel . 1) 1180: (,(expand-file-name "personal.org" org-directory) :maxlevel . 1))) 1181: (org-refile-use-outline-path 'file) 1182: (org-outline-path-complete-in-steps nil)) 1183: (use-package org-num 1184: :after org 1185: :custom 1186: (org-num-face '(:inherit org-special-keyword :underline nil :weight bold)) 1187: (org-num-skip-tags '("noexport" "nonum"))) 1188: (use-package org-fold 1189: :after org org-contrib 1190: :custom 1191: (org-catch-invisible-edits 'smart)) 1192: (use-package org-id 1193: :after org 1194: :custom 1195: (org-id-locations-file-relative t) 1196: (org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)) 1197: (use-package org-crypt ; built-in 1198: :after org 1199: :commands org-encrypt-entries org-encrypt-entry org-decrypt-entries org-decrypt-entry 1200: ;;:hook (org-reveal-start . org-decrypt-entry) 1201: :preface 1202: ;; org-crypt falls back to CRYPTKEY property then `epa-file-encrypt-to', which 1203: ;; is a better default than the empty string `org-crypt-key' defaults to. 1204: (defvar org-crypt-key nil) 1205: (with-eval-after-load 'org 1206: (add-to-list 'org-tags-exclude-from-inheritance "crypt"))) 1207: (use-package org-attach 1208: :after org 1209: :commands (org-attach-new 1210: org-attach-open 1211: org-attach-open-in-emacs 1212: org-attach-reveal-in-emacs 1213: org-attach-url 1214: org-attach-set-directory 1215: org-attach-sync) 1216: :config 1217: (unless org-attach-id-dir 1218: (setq-default org-attach-id-dir (expand-file-name ".attach/" org-directory))) 1219: (with-eval-after-load 'projectile 1220: (add-to-list 'projectile-globally-ignored-directories org-attach-id-dir)) 1221: :custom 1222: (org-attach-auto-tag nil)) 1223: (use-package org-clock 1224: :after org 1225: :commands org-clock-save 1226: :hook (kill-emacs . org-clock-save) 1227: :custom 1228: (org-persist 'history) 1229: (org-clock-in-resume t) 1230: (org-clock-out-remove-zero-time-clocks t) 1231: (org-clock-history-length 20) 1232: (org-show-notification-handler "notify-send") 1233: (org-agenda-skip-scheduled-if-deadline-is-shown t) 1234: :config 1235: (org-clock-persistence-insinuate)) 1236: (use-package org-agenda 1237: :after org 1238: :custom 1239: (org-agenda-files (list (concat org-directory "/"))) 1240: (org-agenda-file-regexp "\\`[^.].*\\.org\\|[0-9]+$\\'") 1241: (org-agenda-include-inactive-timestamps t) 1242: (org-agenda-window-setup 'only-window) 1243: (org-stuck-projects '("+{project*}-killed-Archives/-DONE-KILL-DELEGATED" 1244: ("TODO" "NEXT" "IDEA" "PROG") 1245: nil "")) 1246: :config 1247: (with-eval-after-load 'evil 1248: (evil-set-initial-state #'org-agenda-mode 'normal)) 1249: (setq org-agenda-custom-commands 1250: `(("w" "Work Agenda and all TODOs" 1251: ((agenda "" 1252: ((org-agenda-span 1) 1253: (org-agenda-start-on-weekday t) 1254: (org-agenda-block-separator nil) 1255: (org-agenda-use-time-grid t) 1256: (org-agenda-day-face-function (lambda (date) 'org-agenda-date)) 1257: (org-agenda-format-date "%A %-e %B %Y") 1258: (org-agenda-overriding-header "\nToday\n"))) 1259: (tags-todo "TODO=\"TODO\"|\"NEXT\"" 1260: ((org-agenda-block-separator nil) 1261: (org-agenda-skip-function '(org-agenda-skip-if-todo 'nottodo 'done)) 1262: (org-agenda-use-time-grid nil) 1263: (org-agenda-overriding-header "\nIncomplete\n"))) 1264: (agenda "" 1265: ((org-agenda-span 7) 1266: (org-agenda-start-on-weekday 1) 1267: (org-agenda-block-separator nil) 1268: (org-agenda-use-time-grid nil) 1269: (org-agenda-overriding-header "\nWeekly\n")))) 1270: ((org-agenda-tag-filter-preset '("-personal" "-home")))) 1271: ("h" "Home Agenda and all personal TODOs" 1272: ((agenda "" 1273: ((org-agenda-span 1) 1274: (org-agenda-start-on-weekday t) 1275: (org-agenda-block-separator nil) 1276: (org-agenda-use-time-grid t) 1277: (org-agenda-day-face-function (lambda (date) 'org-agenda-date)) 1278: (org-agenda-format-date "%A %-e %B %Y") 1279: (org-agenda-overriding-header "\nToday\n"))) 1280: (tags-todo "TODO=\"TODO\"|\"NEXT\"" 1281: ((org-agenda-block-separator nil) 1282: (org-agenda-skip-function '(org-agenda-skip-if-todo 'nottodo 'done)) 1283: (org-agenda-use-time-grid nil) 1284: (org-agenda-overriding-header "\nIncomplete\n"))) 1285: (agenda "" 1286: ((org-agenda-span 7) 1287: (org-agenda-start-on-weekday 1) 1288: (org-agenda-block-separator nil) 1289: (org-agenda-use-time-grid nil) 1290: (org-agenda-overriding-header "\nWeekly\n")))) 1291: ((org-agenda-tag-filter-preset '("+personal"))))))) 1292: (use-package org-timer 1293: :config 1294: (setq org-timer-format "Timer :: %s")) 1295: (use-package org-eldoc 1296: :after org org-contrib 1297: :config 1298: (puthash "org" #'ignore org-eldoc-local-functions-cache) 1299: (puthash "plantuml" #'ignore org-eldoc-local-functions-cache) 1300: (puthash "python" #'python-eldoc-function org-eldoc-local-functions-cache) 1301: :custom 1302: (org-eldoc-breadcrumb-separator " → ")) 1303: (use-package org-superstar 1304: :ensure 1305: :hook (org-mode . org-superstar-mode) 1306: :custom 1307: (org-superstar-leading-bullet ?\s) 1308: (org-superstar-leading-fallback ?\s) 1309: (org-hide-leading-stars nil) 1310: (org-indent-mode-turns-on-hiding-stars nil) 1311: (org-superstar-todo-bullet-alist 1312: '(("TODO" . 9744) 1313: ("[ ]" . 9744) 1314: ("DONE" . 9745) 1315: ("[X]" . 9745))) 1316: :config 1317: (org-superstar-configure-like-org-bullets)) 1318: (use-package org-fancy-priorities ; priority icons 1319: :ensure 1320: :defer t 1321: :hook (org-mode . org-fancy-priorities-mode) 1322: :hook (org-agenda-mode . org-fancy-priorities-mode) 1323: :custom 1324: (org-fancy-priorities-list '("⚡" "⬆" "⬇" "☕"))) 1325: (use-package org-modern 1326: :ensure t 1327: :demand t 1328: :config 1329: (set-face-attribute 'org-modern-symbol nil :family "Iosevka Nerd Font") 1330: (setq 1331: ;; Edit settings 1332: org-auto-align-tags nil 1333: org-tags-column 0 1334: org-fold-catch-invisible-edits 'show-and-error 1335: org-special-ctrl-a/e t 1336: org-insert-heading-respect-content t 1337: ;; Org styling, hide markup etc. 1338: org-hide-emphasis-markers nil ; set to nil for easier editing 1339: org-ellipsis "…" 1340: ;; Agenda styling 1341: org-agenda-tags-column 0 1342: org-agenda-block-separator ?─ 1343: org-agenda-time-grid 1344: '((daily today require-timed) 1345: (800 1000 1200 1400 1600 1800 2000) 1346: " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄") 1347: org-agenda-current-time-string 1348: "◀── now ─────────────────────────────────────────────────") 1349: (global-org-modern-mode)) 1350: ;; tools 1351: (use-package make-mode 1352: :config 1353: (add-hook 'makefile-mode-hook 'indent-tabs-mode)) 1354: (use-package executable 1355: :hook 1356: (after-save . executable-make-buffer-file-executable-if-script-p)) 1357: (use-package pinentry 1358: :ensure 1359: :defer t 1360: :config 1361: (pinentry-start)) 1362: (use-package password-store 1363: :ensure 1364: :defer t 1365: :config 1366: (setq password-store-password-length 12)) 1367: 1368: (use-package password-store-otp 1369: :ensure 1370: :defer t 1371: :after password-store) 1372: 1373: (use-package pass 1374: :ensure 1375: :defer t) 1376: 1377: (use-package auth-source-pass 1378: :init 1379: (auth-source-pass-enable)) 1380: (use-package rg 1381: :if (executable-find "rg") 1382: :ensure 1383: :defer t) 1384: ;; dired 1385: (use-package dired 1386: :commands dired-jump 1387: :init 1388: (setq dired-dwim-target t ; guess a default target directory 1389: dired-hide-details-hide-symlink-targets nil ; don't hide symbolic link targets 1390: dired-auto-revert-buffer #'dired-buffer-stale-p ; revert stale only 1391: dired-recursive-copies 'always ; always copy recursively 1392: dired-recursive-deletes 'top ; ask only for top-level 1393: dired-create-destination-dirs 'ask 1394: dired-clean-confirm-killing-deleted-buffers nil)) 1395: (use-package image-dired 1396: :config 1397: (setq image-dired-thumb-size 150)) 1398: (use-package dired-x 1399: :hook (dired-mode . dired-omit-mode) 1400: :config 1401: (setq dired-omit-files 1402: (concat dired-omit-files 1403: "\\|^\\.DS_Store\\'" 1404: "\\|^\\.project\\(?:ile\\)?\\'" 1405: "\\|^\\.\\(?:svn\\|git\\)\\'" 1406: "\\|^\\.ccls-cache\\'" 1407: "\\|\\(?:\\.js\\)?\\.meta\\'" 1408: "\\|\\.\\(?:elc\\|o\\|pyo\\|swp\\|class\\)\\'")) 1409: ;; Disable the prompt about whether I want to kill the Dired buffer for a 1410: ;; deleted directory. Of course I do! 1411: (setq dired-clean-confirm-killing-deleted-buffers nil) 1412: (let ((cmd "xdg-open")) 1413: (setq dired-guess-shell-alist-user 1414: `(("\\.\\(?:docx\\|pdf\\|djvu\\|eps\\)\\'" ,cmd) 1415: ("\\.\\(?:jpe?g\\|png\\|gif\\|xpm\\)\\'" ,cmd) 1416: ("\\.\\(?:xcf\\)\\'" ,cmd) 1417: ("\\.csv\\'" ,cmd) 1418: ("\\.tex\\'" ,cmd) 1419: ("\\.\\(?:mp4\\|mkv\\|avi\\|flv\\|rm\\|rmvb\\|ogv\\)\\(?:\\.part\\)?\\'" ,cmd) 1420: ("\\.\\(?:mp3\\|flac\\)\\'" ,cmd) 1421: ("\\.html?\\'" ,cmd) 1422: ("\\.md\\'" ,cmd))))) 1423: (use-package fd-dired 1424: :ensure 1425: :if (executable-find "fd") 1426: :defer t 1427: :init 1428: (global-set-key [remap find-dired] #'fd-dired)) 1429: (use-package dired-git-info 1430: :ensure 1431: :defer t 1432: ;; :hook 1433: ;; (dired-after-readin . dired-git-info-auto-enable) 1434: :config 1435: ;; (setq +dired--git-info-p (bound-and-true-p dired-git-info-mode)) 1436: ;; (when +dired--git-info-p 1437: ;; (dired-git-info-mode -1)) 1438: (setq dgi-auto-hide-details-p nil)) 1439: (use-package dired-aux 1440: :config 1441: (setq dired-create-destination-dirs 'ask 1442: dired-vc-rename-file t)) 1443: (use-package dired-rsync 1444: :ensure 1445: :defer t) 1446: (use-package diredfl 1447: :ensure 1448: :defer t 1449: :hook (dired-mode . diredfl-global-mode)) 1450: ;; treemacs 1451: (use-package treemacs 1452: :ensure 1453: :hook ((treemacs-mode . (lambda () (hs-minor-mode -1)))) 1454: :config 1455: (setq treemacs-hide-gitignored-files-mode t 1456: treemacs-no-png-images t 1457: treemacs-silent-refresh t 1458: treemacs-sorting 'mod-time-desc 1459: treemacs-python-executable (executable-find "python3") 1460: treemacs-collapse-dirs (if treemacs-python-executable 3 0) 1461: treemacs-deferred-git-apply-delay 0.5 1462: treemacs-directory-name-transformer #'identity 1463: treemacs-display-in-side-window t 1464: treemacs-eldoc-display 'simple 1465: treemacs-file-event-delay 2000 1466: treemacs-file-extension-regex treemacs-last-period-regex-value 1467: treemacs-file-follow-delay 0.2 1468: treemacs-file-name-transformer #'identity 1469: treemacs-follow-after-init t 1470: treemacs-expand-after-init t 1471: treemacs-find-workspace-method 'find-for-file-or-pick-first 1472: treemacs-git-command-pipe "" 1473: treemacs-goto-tag-strategy 'refetch-index 1474: treemacs-header-scroll-indicators '(nil . "^^^^^^") 1475: treemacs-hide-dot-git-directory t 1476: treemacs-indentation 2 1477: treemacs-indentation-string " " 1478: treemacs-is-never-other-window nil 1479: treemacs-max-git-entries 5000 1480: treemacs-missing-project-action 'ask 1481: treemacs-move-forward-on-expand nil 1482: treemacs-no-delete-other-windows t 1483: treemacs-project-follow-cleanup nil 1484: treemacs-persist-file (expand-file-name ".cache/treemacs-persist" user-emacs-directory) 1485: treemacs-position 'left 1486: treemacs-read-string-input 'from-child-frame 1487: treemacs-recenter-distance 0.1 1488: treemacs-recenter-after-file-follow nil 1489: treemacs-recenter-after-tag-follow nil 1490: treemacs-recenter-after-project-jump 'always 1491: treemacs-recenter-after-project-expand 'on-distance 1492: treemacs-litter-directories '("/node_modules" "/.venv" "/.cask") 1493: treemacs-project-follow-into-home nil 1494: treemacs-show-cursor nil 1495: treemacs-show-hidden-files t 1496: treemacs-silent-filewatch t 1497: treemacs-select-when-already-in-treemacs 'move-back 1498: treemacs-space-between-root-nodes t 1499: treemacs-tag-follow-cleanup t 1500: treemacs-tag-follow-delay 1.5 1501: treemacs-text-scale nil 1502: treemacs-user-mode-line-format nil 1503: treemacs-user-header-line-format nil 1504: treemacs-wide-toggle-width 70 1505: treemacs-width 35 1506: treemacs-width-increment 1 1507: treemacs-width-is-initially-locked t 1508: treemacs-workspace-switch-cleanup nil) 1509: (treemacs-peek-mode 1) 1510: (treemacs-filewatch-mode t) 1511: (treemacs-follow-mode t) 1512: (treemacs-fringe-indicator-mode 'always) 1513: (when treemacs-python-executable 1514: (treemacs-git-commit-diff-mode t)) 1515: (pcase (cons (not (null (executable-find "git"))) 1516: (not (null treemacs-python-executable))) 1517: (`(t . t) 1518: (treemacs-git-mode 'deferred)) 1519: (`(t . _) 1520: (treemacs-git-mode 'simple))) 1521: :bind 1522: (:map global-map 1523: ("M-0" . treemacs-select-window) 1524: ("C-x t 1" . treemacs-delete-other-windows) 1525: ("C-x t t" . treemacs) 1526: ("C-x t d" . treemacs-select-directory) 1527: ("C-x t B" . treemacs-bookmark) 1528: ("C-x t C-t" . treemacs-find-file) 1529: ("C-x t M-t" . treemacs-find-tag)) 1530: :general 1531: (+config/leader-tree 1532: "t" 'treemacs 1533: "p" 'treemacs-add-and-display-current-project-exclusively) 1534: 1535: (general-define-key 1536: :keymaps 'treemacs-mode-map 1537: "[mouse-1]" 'treemacs-single-click-expand-action) 1538: 1539: (general-nvmap 1540: :keymaps 'treemacs-mode-map 1541: "gr" '(treemacs-refresh :wk "refresh tree") 1542: "zm" '(:ignore t :wk "move") 1543: "zmf" '(treemacs-move-file :wk "move file") 1544: "zmd" '(treemacs-move-project-down :wk "move project down") 1545: "zmu" '(treemacs-move-project-up :wk "move project up") 1546: "zr" '(:ignore t :wk "rename") 1547: "zrf" '(treemacs-rename-file :wk "rename file") 1548: "zrp" '(treemacs-rename-project :wk "rename project") 1549: "zrw" '(treemacs-rename-workspace :wk "rename workspace") 1550: "zc" '(:ignore t :wk "create/clean") 1551: "zcC" '(treemacs-cleanup-litter :wk "cleanup litter") 1552: "zcd" '(treemacs-create-dir :wk "create directory") 1553: "zcf" '(treemacs-create-file :wk "create file") 1554: "zd" '(treemacs-delete-file :wk "delete file"))) 1555: (use-package treemacs-projectile 1556: :ensure 1557: :after treemacs) 1558: (use-package treemacs-icons-dired 1559: :ensure 1560: :after treemacs 1561: :hook (dired-mode . treemacs-icons-dired-enable-once)) 1562: (use-package treemacs-magit 1563: :ensure 1564: :after treemacs magit) 1565: (use-package treemacs-evil 1566: :ensure 1567: :after treemacs evil) 1568: (use-package lsp-treemacs 1569: :ensure 1570: :after treemacs lsp 1571: :config 1572: (lsp-treemacs-sync-mode 1) 1573: :general 1574: (general-define-key 1575: :keymaps 'treemacs-mode-map 1576: "S" 'lsp-treemacs-symbols 1577: "X" 'lsp-treemacs-errors-list 1578: "Y" 'lsp-treemacs-call-hierarchy)) 1579: (use-package treemacs-perspective 1580: :ensure 1581: :after treemacs perspective 1582: :config 1583: (treemacs-set-scope-type 'Perspectives)) 1584: (use-package treemacs-tab-bar 1585: :ensure 1586: :after treemacs) 1587: (use-package treemacs-nerd-icons 1588: :ensure 1589: :after treemacs 1590: :config 1591: (treemacs-load-theme "nerd-icons")) 1592: ;; mail 1593: (use-package notmuch 1594: :ensure 1595: :if (executable-find "notmuch") 1596: :defer t 1597: :commands (notmuch) 1598: :hook 1599: (message-setup . mml-secure-sign-pgpmime) 1600: :config 1601: (global-set-key (kbd "<XF86Mail>") 'notmuch) 1602: (setq notmuch-fcc-dirs nil 1603: notmuch-search-result-format 1604: '(("date" . "%12s ") 1605: ("count" . "%-7s ") 1606: ("authors" . "%-30s ") 1607: ("subject" . "%-72s ") 1608: ("tags" . "(%s)")) 1609: notmuch-tag-formats 1610: '(("unread" 1611: (propertize tag 'face 'notmuch-tag-unread)) 1612: ("flagged" 1613: (propertize tag 'face 'notmuch-tag-flagged) 1614: (notmuch-tag-format-image-data tag 1615: (notmuch-tag-star-icon)))) 1616: notmuch-tagging-keys 1617: '(("a" notmuch-archive-tags "Archive") 1618: ("u" notmuch-show-mark-read-tags "Mark read") 1619: ("f" ("+flagged") "Flag") 1620: ("s" ("+spam" "-inbox") "Mark as spam") 1621: ("d" ("+deleted" "-inbox") "Delete")) 1622: notmuch-saved-searches 1623: '((:name "flagged" :query "tag:flagged" :key "f") 1624: (:name "sent" :query "tag:sent" :key "s") 1625: (:name "drafts" :query "tag:draft" :key "d") 1626: (:name "all mail" :query "*" :key "a") 1627: (:name "unread" :query "tag:unread" :key "u") 1628: (:name "zum" :query "tag:zum" :key "z") 1629: (:name "mkn" :query "tag:mkn" :key "c") 1630: (:name "gmail" :query "tag:gmail" :key "g") 1631: (:name "hotmail" :query "tag:hotmail" :key "h") 1632: (:name "yahoo" :query "tag:yahoo" :key "h") 1633: (:name "ymail" :query "tag:ymail" :key "m") 1634: (:name "Today" 1635: :query "date:today AND NOT tag:spam AND NOT tag:bulk" 1636: :key "T" 1637: :search-type 'tree 1638: :sort-order 'newest-first) 1639: (:name "This Week" 1640: :query "date:weeks AND NOT tag:spam AND NOT tag:bulk" 1641: :key "W" 1642: :search-type 'tree 1643: :sort-order 'newest-first) 1644: (:name "This Month" 1645: :query "date:months AND NOT tag:spam AND NOT tag:bulk" 1646: :key "M" 1647: :search-type 'tree 1648: :sort-order 'newest-first) 1649: (:name "flagged" 1650: :query "tag:flagged AND NOT tag:spam AND NOT tag:bulk" 1651: :key "f" 1652: :search-type 'tree 1653: :sort-order 'newest-first) 1654: (:name "spam" :query "tag:spam")) 1655: notmuch-archive-tags '("-inbox" "-unread")) 1656: (setq-default notmuch-search-oldest-first nil) 1657: (if (executable-find "gpg2") 1658: (setq notmuch-crypto-gpg-program "gpg2") 1659: (setq notmuch-crypto-gpg-program "gpg")) 1660: (setq notmuch-crypto-process-mime t 1661: mml-secure-openpgp-sign-with-sender t) 1662: (define-key notmuch-show-mode-map "S" 1663: (lambda () 1664: "Mark message as spam" 1665: (interactive) 1666: (notmuch-show-tag (list +spam -new)))) 1667: :general 1668: (+config/leader-menu! "mail" "M-m" 1669: "m" '(notmuch :wk "Notmuch Mail")) 1670: 1671: (+config/leader-mail 1672: "m" '(notmuch :wk "open notmuch mail") 1673: "M" '(compose-mail :wk "new mail")) 1674: 1675: (general-nmap 'notmuch-common-keymap 1676: "gr" 'notmuch-refresh-this-buffer 1677: "gR" 'notmuch-poll-and-refresh-this-buffer)) 1678: (use-package notmuch-indicator 1679: :ensure 1680: :config 1681: (setq notmuch-indicator-args 1682: '((:terms "tag:unread and tag:inbox" :label "U" :label-face success))) 1683: (notmuch-indicator-mode)) 1684: (use-package consult-notmuch 1685: :ensure 1686: :after consult 1687: :config 1688: (add-to-list 'consult-buffer-sources 'consult-notmuch-buffer-source)) 1689: (use-package ol-notmuch 1690: :ensure) 1691: (use-package notmuch-maildir 1692: :ensure 1693: :config 1694: (notmuch-maildir-inject-section)) 1695: (use-package message 1696: :custom 1697: (message-directory (expand-file-name ".mail" (getenv "HOME"))) 1698: (message-sendmail-envelope-from 'header)) 1699: (use-package sendmail 1700: :custom 1701: (mail-specify-envelope-from t) 1702: (mail-envelope-from 'header) 1703: (send-mail-function 'sendmail-send-it) 1704: (sendmail-program (executable-find "msmtp"))) 1705: ;; programming 1706: ;; (use-package lispy 1707: ;; :ensure 1708: ;; :hook ((emacs-lisp-mode . lispy-mode) 1709: ;; (lisp-mode . lispy-mode) 1710: ;; (scheme-mode . lispy-mode) 1711: ;; (geiser-mode . lispy-mode))) 1712: ;; (use-package lispyville 1713: ;; :ensure 1714: ;; :hook (lispy-mode . lispyville-mode)) 1715: (when (locate-library "aggressive-indent") 1716: (add-hook 'lisp-mode-hook #'aggressive-indent-mode) 1717: (add-hook 'clojure-mode-hook #'aggressive-indent-mode) 1718: (add-hook 'scheme-mode-hook #'aggressive-indent-mode)) 1719: 1720: ;;;; emacs-lisp -n 1721: (use-package elisp-mode 1722: :diminish emacs-lisp-mode 1723: :diminish elisp-mode 1724: :diminish outline-minor-mode 1725: :diminish lisp-data-mode 1726: :mode ("\\.Cask\\'" . emacs-lisp-mode) 1727: :ensure nil 1728: :hook (emacs-lisp-mode . (lambda () 1729: (outline-minor-mode) 1730: (rainbow-delimiters-mode)))) 1731: (use-package ielm 1732: :ensure nil 1733: ;;:hook (ielm-mode . (turn-on-smartparens-mode)) 1734: :config 1735: (setq ielm-font-lock-keywords 1736: (append '(("\\(^\\*\\*\\*[^*]+\\*\\*\\*\\)\\(.*$\\)" 1737: (1 font-lock-comment-face) 1738: (2 font-lock-constant-face))) 1739: (when (require 'highlight-numbers nil t) 1740: (highlight-numbers--get-regexp-for-mode 'emacs-lisp-mode)) 1741: (cl-loop for (matcher . match-highlights) 1742: in (append lisp-el-font-lock-keywords-2 1743: lisp-cl-font-lock-keywords-2) 1744: collect 1745: `((lambda (limit) 1746: (when ,(if (symbolp matcher) 1747: `(,matcher limit) 1748: `(re-search-forward ,matcher limit t)) 1749: ;; Only highlight matches after the prompt 1750: (> (match-beginning 0) (car comint-last-prompt)) 1751: ;; Make sure we're not in a comment or string 1752: (let ((state (syntax-ppss))) 1753: (not (or (nth 3 state) 1754: (nth 4 state)))))) 1755: ,@match-highlights))))) 1756: (use-package macrostep 1757: :ensure 1758: :defer t 1759: :bind (:map emacs-lisp-mode-map 1760: ("C-c e" . macrostep-expand))) 1761: ;;;; common-lisp 1762: (when (file-directory-p (expand-file-name "site-lisp/sly-stepper" user-emacs-directory)) 1763: (add-to-list 'load-path (expand-file-name "site-lisp/sly-stepper" user-emacs-directory))) 1764: (when (file-directory-p (expand-file-name "site-lisp/sly-quicklisp" user-emacs-directory)) 1765: (add-to-list 'load-path (expand-file-name "site-lisp/sly-quicklisp" user-emacs-directory))) 1766: (when (file-directory-p (expand-file-name "site-lisp/sly-macrostep" user-emacs-directory)) 1767: (add-to-list 'load-path (expand-file-name "site-lisp/sly-macrostep" user-emacs-directory))) 1768: 1769: (defvar inferior-lisp-program "sbcl") 1770: (when (executable-find "ros") 1771: (setq inferior-lisp-program "ros -Q run")) 1772: 1773: (add-hook 'lisp-mode-hook #'rainbow-delimiters-mode) 1774: (use-package sly 1775: :ensure 1776: :commands sly-autoloads 1777: :hook ((lisp-mode-local-vars . rainbow-delimiters-mode) 1778: (lisp-mode . sly-editing-mode)) 1779: :config 1780: (require 'sly-autoloads)) 1781: ;;;; clojure 1782: (use-package cider 1783: :ensure 1784: :defer t) 1785: (use-package clj-refactor 1786: :ensure 1787: :defer t 1788: :hook (clojure-mode . +config/clojure-mode-hook) 1789: :config 1790: (defun +config/clojure-mode-hook () 1791: (clj-refactor-mode 1) 1792: ;; This choice of keybinding leaves cider-macroexpand-1 unbound 1793: (cljr-add-keybindings-with-prefix "C-c r"))) 1794: ;;;; scheme 1795: (use-package geiser 1796: :ensure 1797: :defer t 1798: :diminish geiser-autodoc-mode 1799: ;; :hook (geiser-repl-mode . turn-on-smartparens-strict-mode) 1800: :init 1801: (setq geiser-autodoc-identifier-format "%s → %s" 1802: geiser-repl-per-project-p t 1803: geiser-repl-history-filename (concat user-emacs-directory "geiser-history"))) 1804: (use-package geiser-guile 1805: :ensure 1806: :defer t 1807: :config 1808: (let ((nonguix-path (expand-file-name "Projects/guix/nonguix" 1809: (getenv "HOME"))) 1810: (personal-path (expand-file-name "Projects/guix/devel/src" 1811: (getenv "HOME")))) 1812: (when (file-directory-p nonguix-path) 1813: (add-to-list 'geiser-guile-load-path nonguix-path)) 1814: (when (file-directory-p personal-path) 1815: (add-to-list 'geiser-guile-load-path personal-path)))) 1816: 1817: (use-package cc-mode 1818: :mode ("\\.mm\\'" . objc-mode) 1819: :mode ("\\.h\\'" . +cc-c-c++-objc-mode) 1820: :hook (c-mode-common . rainbow-delimiters-mode) 1821: ;; :hook (c++-mode-local-vars . c++-ts-mode) 1822: ;; :hook (c-mode-common . c-ts-base-mode) 1823: ;; :hook (cmake-mode-local-vars . cmake-ts-mode) 1824: :config 1825: (setq c-basic-offset tab-width 1826: c-backspace-function #'delete-backward-char) 1827: (with-eval-after-load 'ffap 1828: (add-to-list 'ffap-alist '(c-mode . ffap-c-mode)))) 1829: (use-package nxml-mode 1830: :mode "\\.p\\(?:list\\|om\\)\\'" ; plist, pom 1831: :mode "\\.xs\\(?:d\\|lt\\)\\'" ; xslt, xsd 1832: :mode "\\.rss\\'" 1833: :config 1834: (setq nxml-slash-auto-complete-flag t 1835: nxml-auto-insert-xml-declaration-flag t)) 1836: (use-package yaml-mode 1837: :ensure 1838: :config 1839: (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) 1840: (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode)) 1841: (setq tab-width 2) 1842: ;; (when (treesit-available-p) 1843: ;; (add-to-list 'major-mode-remap-alist '(yaml-mode . yaml-ts-mode))) 1844: :hook 1845: ((yaml-mode . (lambda () 1846: (define-key yaml-mode-map "\C-m" 'newline-and-indent))) 1847: (yaml-mode . (lambda () 1848: (run-hooks 'prog-mode-hook))))) 1849: (use-package toml-mode 1850: :ensure 1851: :mode 1852: ("\\.toml\\'" . toml-mode) 1853: :config 1854: ;; (when (treesit-available-p) 1855: ;; (add-to-list 'major-mode-remap-alist '(toml-mode . toml-ts-mode))) 1856: (with-eval-after-load 'lsp-mode 1857: (setq lsp-toml-command (executable-find "taplo"))) 1858: (add-to-list 'lsp-language-id-configuration '("\\.toml$" . "toml"))) 1859: (use-package lua-mode 1860: :ensure 1861: :defer t 1862: :config 1863: (with-eval-after-load 'lsp-mode 1864: (setq lsp-lua-hint-enable t 1865: lsp-lua-hint-set-type t))) 1866: (use-package jinja2-mode 1867: :ensure 1868: :defer t 1869: :config 1870: ;; The default behavior is to reindent the whole buffer on save. This is 1871: ;; disruptive and imposing. There are indentation commands available; the user 1872: ;; can decide when they want their code reindented. 1873: (setq jinja2-enable-indent-on-save nil) 1874: (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) 1875: (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode))) 1876: (use-package json-mode 1877: :ensure) 1878: (defun +config/django-web-mode () 1879: "Set web-engine to django if `manage.py' detected in `projectile-project-root'." 1880: (if (projectile-project-p) 1881: (if (file-exists-p (concat (projectile-project-root) "manage.py")) 1882: (web-mode-set-engine "django")))) 1883: 1884: (defun +config/web-mode-fix-js-comment () 1885: "Fix comment handling in `web-mode' for JavaScript (from `doom')." 1886: (when (member web-mode-content-type '("javascript" "jsx")) 1887: ;; For some reason the default is to insert HTML comments even 1888: ;; in JavaScript. 1889: (setq-local comment-start "//") 1890: (setq-local comment-end "") 1891: ;; Needed since otherwise the default value generated by 1892: ;; `comment-normalize-vars' will key off the syntax and think 1893: ;; that a single "/" starts a comment, which completely borks 1894: ;; auto-fill. 1895: (setq-local comment-start-skip "// *"))) 1896: 1897: (use-package web-mode 1898: :ensure 1899: :defer t 1900: :mode "\\.[px]?html?\\'" 1901: :mode "\\.\\(?:tpl\\|blade\\)\\(?:\\.php\\)?\\'" 1902: :mode "\\.erb\\'" 1903: :mode "\\.[lh]?eex\\'" 1904: :mode "\\.jsp\\'" 1905: :mode "\\.as[cp]x\\'" 1906: :mode "\\.ejs\\'" 1907: :mode "\\.hbs\\'" 1908: :mode "\\.mustache\\'" 1909: :mode "\\.svelte\\'" 1910: :mode "\\.twig\\'" 1911: :mode "\\.jinja2?\\'" 1912: :mode "\\.eco\\'" 1913: :mode "wp-content/themes/.+/.+\\.php\\'" 1914: :mode "templates/.+\\.php\\'" 1915: :init 1916: ;; If the user has installed `vue-mode' then, by appending this to 1917: ;; `auto-mode-alist' rather than prepending it, its autoload will have 1918: ;; priority over this one. 1919: (add-to-list 'auto-mode-alist '("\\.vue\\'" . web-mode) 'append) 1920: :mode "\\.vue\\'" 1921: :config 1922: (setq web-mode-markup-indent-offset 2 1923: web-mode-enable-auto-closing t 1924: web-mode-auto-close-style 1 1925: web-mode-css-indent-offset 2 1926: web-mode-code-indent-offset 2 1927: web-mode-enable-auto-pairing nil 1928: web-mode-enable-block-face t 1929: web-mode-enable-comment-interpolation t 1930: web-mode-enable-heredoc-fontification t 1931: web-mode-enable-css-colorization t 1932: web-mode-enable-part-face t 1933: web-mode-enable-current-element-highlight t 1934: web-mode-enable-current-column-highlight t 1935: web-mode-style-padding 1 1936: web-mode-script-padding 1 1937: web-mode-block-padding 0 1938: web-mode-comment-style 2 1939: web-mode-enable-curly-brace-indentation t 1940: web-mode-enable-auto-quoting nil 1941: web-mode-engines-alist 1942: '(("php" . "\\.phtml\\'") 1943: ("blade" . "\\.blade\\'") 1944: ("elixir" . "\\.eex\\'") 1945: ("phoenix" . "\\.[lh]eex\\'"))) 1946: ;; web-mode-extra-auto-pairs 1947: ;; '(("erb" . (("beg" "end"))) 1948: ;; ("php" . (("beg" "end"))))) 1949: (with-eval-after-load 'smartparens 1950: (sp-local-pair 'web-mode "<" nil :actions :rem) 1951: (sp-local-pair 'web-mode "{%" " %}") 1952: (sp-local-pair 'web-mode "{{" " }}") 1953: (sp-local-pair 'web-mode "<!--" " -->") 1954: ) 1955: (defun +config/web-mode-hook () 1956: "Hooks for Web mode." 1957: (local-set-key (kbd "RET") 'newline-and-indent)) 1958: ;; Use // instead of /* as the default comment delimited in JS 1959: (with-eval-after-load 'web-mode 1960: (setf (alist-get "javascript" web-mode-comment-formats nil nil #'equal) 1961: "//")) 1962: :hook ((html-mode-local-vars-hook 1963: mhtml-mode-local-vars-hook) . tree-sitter) 1964: :hook (web-mode . +config/django-web-mode) 1965: :general 1966: (general-nvmap 1967: :keymaps 'web-mode-map 1968: "gn" 'web-mode-navigate) 1969: (general-vmap 1970: :keymaps 'web-mode-map 1971: "gs" 'web-mode-surround)) 1972: (use-package emmet-mode 1973: :ensure 1974: :defer t 1975: :hook (css-mode web-mode html-mode haml-mode nxml-mode rjsx-mode reason-mode) 1976: :config 1977: (when (require 'yasnippet nil t) 1978: (add-hook 'emmet-mode-hook #'yas-minor-mode-on)) 1979: (setq emmet-move-cursor-between-quotes t) 1980: :general 1981: (general-vmap 1982: :keymaps 'emmet-mode-keymap 1983: "TAB" 'emmet-wrap-with-markup) 1984: (general-def 1985: :keymaps 'emmet-mode-keymap 1986: "M-E" 'emmet-expand-line)) 1987: (use-package skewer-mode 1988: :ensure 1989: :defer t 1990: :hook ((web-mode . skewer-html-mode) 1991: (js2-mode . skewer-mode))) 1992: (use-package lsp-tailwindcss 1993: :ensure 1994: :init 1995: (setq lsp-tailwindcss-add-on-mode t)) 1996: (use-package sass-mode 1997: :ensure 1998: :defer t 1999: :hook (scss-mode . rainbow-mode)) 2000: (use-package css-eldoc 2001: :ensure 2002: :defer t 2003: :commands turn-on-css-eldoc 2004: ;;add a hook if you want always to see the selector options in the minibuffer 2005: :config 2006: (add-hook 'css-mode-hook 'turn-on-css-eldoc) 2007: (add-hook 'scss-mode-hook 'turn-on-css-eldoc)) 2008: 2009: 2010: (defvar +javascript-npm-conf (make-hash-table :test 'equal)) 2011: 2012: ;;;###autoload 2013: (defun +javascript-npm-conf (&optional project-root refresh-p) 2014: "Retrieves an alist of this project's 'package.json'. If REFRESH-P is non-nil 2015: ignore the cache." 2016: (let ((project-root (or project-root (doom-project-root)))) 2017: (or (and (not refresh-p) 2018: (gethash project-root +javascript-npm-conf)) 2019: (let ((package-file (expand-file-name "package.json" project-root))) 2020: (when-let (json (and (file-exists-p package-file) 2021: (require 'json) 2022: (json-read-file package-file))) 2023: (puthash project-root json +javascript-npm-conf)))))) 2024: 2025: ;;;###autoload 2026: (defun +javascript-npm-dep-p (packages &optional project-root refresh-p) 2027: (when-let (data (and (bound-and-true-p +javascript-npm-mode) 2028: (+javascript-npm-conf project-root refresh-p))) 2029: (let ((deps (append (cdr (assq 'dependencies data)) 2030: (cdr (assq 'devDependencies data))))) 2031: (cond ((listp packages) 2032: (funcall (if (eq (car packages) 'and) 2033: #'cl-every 2034: #'cl-some) 2035: (lambda (pkg) (assq pkg deps)) 2036: (if (listp packages) packages (list packages)))) 2037: ((symbolp packages) 2038: (assq packages deps)) 2039: (t (error "Expected a package symbol or list, got %s" packages)))))) 2040: 2041: ;;;###autoload 2042: (defun +javascript-add-npm-path-h () 2043: "Add node_modules/.bin to `exec-path'." 2044: (when-let ((search-directory (or (doom-project-root) default-directory)) 2045: (node-modules-parent (locate-dominating-file search-directory "node_modules/")) 2046: (node-modules-dir (expand-file-name "node_modules/.bin/" node-modules-parent))) 2047: (make-local-variable 'exec-path) 2048: (add-to-list 'exec-path node-modules-dir) 2049: (doom-log ":lang:javascript: add %s to $PATH" (expand-file-name "node_modules/" node-modules-parent)))) 2050: 2051: 2052: ;; 2053: ;; Commands 2054: 2055: ;;;###autoload 2056: (defun +javascript/open-repl () 2057: "Open a Javascript REPL. Meaning either `skewer-repl', if any of the 2058: skewer-*-mode's are enabled, or `nodejs-repl' otherwise." 2059: (interactive) 2060: (call-interactively 2061: (if (and (featurep 'skewer-mode) 2062: (or (bound-and-true-p skewer-mode) 2063: (bound-and-true-p skewer-css-mode) 2064: (bound-and-true-p skewer-html-mode))) 2065: #'skewer-repl 2066: #'nodejs-repl)) 2067: (current-buffer)) 2068: 2069: ;;;###autoload 2070: (defun +javascript/skewer-this-buffer () 2071: "Toggle a globalized skewer-mode, attaching an external browser (once), 2072: initiating an internal httpd server (once) and enabling the appropriate 2073: skewer-mode for the current buffer. 2074: 2075: Run this for any buffer you want to skewer." 2076: (interactive) 2077: (when (bound-and-true-p impatient-mode) 2078: (error "Skewer-mode isn't compatible with impatient mode")) 2079: (require 'skewer-mode) 2080: (unless (process-status "httpd") 2081: (run-skewer)) 2082: (pcase major-mode 2083: ((or 'css-mode 'scss-mode 'less-css-mode) 2084: (unless (bound-and-true-p skewer-css-mode) 2085: (skewer-css-mode +1))) 2086: ((or 'web-mode 'html-mode) 2087: (unless (bound-and-true-p skewer-html-mode) 2088: (skewer-html-mode +1))) 2089: ('js2-mode 2090: (unless (bound-and-true-p skewer-mode) 2091: (skewer-mode +1))) 2092: (_ (error "Invalid mode %s" major-mode)))) 2093: 2094: ;;;###autoload 2095: (defun +javascript/skewer-cleanup () 2096: "Disable skewer-mode globally and disable the httpd server." 2097: (interactive) 2098: (when (process-status "httpd") 2099: (httpd-stop)) 2100: (dolist (buf (buffer-list)) 2101: (with-current-buffer buf 2102: (if (bound-and-true-p skewer-mode) 2103: (skewer-mode -1)) 2104: (if (bound-and-true-p skewer-css-mode) 2105: (skewer-css-mode -1)) 2106: (if (bound-and-true-p skewer-html-mode) 2107: (skewer-html-mode -1))))) 2108: 2109: ;; 2110: ;; Hooks 2111: 2112: ;;;###autoload 2113: (defun +javascript-cleanup-tide-processes-h () 2114: "Clean up dangling tsserver processes if there are no more buffers with 2115: `tide-mode' active that belong to that server's project." 2116: (when tide-mode 2117: (unless (cl-loop with project-name = (tide-project-name) 2118: for buf in (delq (current-buffer) (buffer-list)) 2119: if (and (buffer-local-value 'tide-mode buf) 2120: (with-current-buffer buf 2121: (string= (tide-project-name) project-name))) 2122: return buf) 2123: (kill-process (tide-current-server))))) 2124: 2125: ;; 2126: ;; Advice 2127: 2128: ;;;###autoload 2129: (defun +javascript-tide-project-root-a () 2130: "Resolve to `doom-project-root' if `tide-project-root' fails." 2131: (or tide-project-root 2132: (or (locate-dominating-file default-directory "tsconfig.json") 2133: (locate-dominating-file default-directory "jsconfig.json")))) 2134: 2135: (with-eval-after-load 'projectile 2136: (add-to-list 'projectile-globally-ignored-directories "^node_modules$") 2137: (add-to-list 'projectile-globally-ignored-directories "^flow-typed$")) 2138: (use-package js2-mode 2139: :ensure 2140: :defer t 2141: :interpreter ("node" . js2-mode) 2142: :hook (js2-mode . rainbow-delimiters-mode) 2143: :hook (js2-mode . js2-imenu-extras-mode) 2144: :hook (js2-mode . (lambda () (push '("function" . ?ƒ) prettify-symbols-alist))) 2145: :config 2146: (with-eval-after-load 'skewer-mode 2147: (add-hook 'js2-mode 'skewer-mode)) 2148: (setq-default js2-basic-indent 2 2149: js2-basic-offset 2 2150: js2-auto-indent-p t 2151: js2-cleanup-whitespace t 2152: js2-enter-indents-newline t 2153: js2-indent-on-enter-key t 2154: js2-global-externs (list "window" "module" "require" "buster" "sinon" "assert" "refute" "setTimeout" "clearTimeout" "setInterval" "clearInterval" "location" "__dirname" "console" "JSON" "jQuery" "$"))) 2155: (use-package xref-js2 2156: :ensure 2157: :defer t 2158: :if (executable-find "ag") ; silver-searcher 2159: :config 2160: (add-hook 'js2-mode-hook (lambda () 2161: (add-hook 'xref-backend-functions #'xref-js2-xref-backend nil t)))) 2162: (use-package js2-refactor 2163: :ensure 2164: :defer t 2165: :hook (js2-mode . js2-refactor-mode) 2166: :init 2167: (js2r-add-keybindings-with-prefix "C-c C-r") 2168: :config 2169: (setq js2-skip-preprocessor-directives t) 2170: :general 2171: (general-nvmap 2172: :keymap 'js2-refactor-mode-map 2173: "zr" (general-simulate-key "C-c C-r" 2174: :name general-z-r-simulates-C-c-C-r 2175: :docstring "Simulates C-c C-r" 2176: :which-key "JS2 Refactor"))) 2177: (use-package rjsx-mode 2178: :ensure 2179: :defer t 2180: :mode "\\.[mc]?js\\'" 2181: :mode "\\.es6\\'" 2182: :mode "\\.pac\\'" 2183: :hook (rjsx-mode . rainbow-delimiters-mode) 2184: :hook (rjsx-mode . rainbow-mode) 2185: :bind (([remap comment-dwim ] . rjsx-comment-dwim)) 2186: :init 2187: (with-eval-after-load 'compilation 2188: (add-to-list 'compilation-error-regexp-alist 'node) 2189: (add-to-list 'compilation-error-regexp-alist-alist '(node "^[[:blank:]]*at \\(.*(\\|\\)\\(.+?\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\)" 2190: 2 3 4))) 2191: :config 2192: (with-eval-after-load 'compilation 2193: (add-to-list 'compilation-error-regexp-alist 'node) 2194: (add-to-list 'compilation-error-regexp-alist-alist 2195: '(node "^[[:blank:]]*at \\(.*(\\|\\)\\(.+?\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\)" 2196: 2 3 4))) 2197: (setq js-chain-indent t 2198: ;; These have become standard in the JS community 2199: js2-basic-offset 2 2200: ;; Don't mishighlight shebang lines 2201: js2-skip-preprocessor-directives t 2202: ;; let flycheck handle this 2203: js2-mode-show-parse-errors nil 2204: js2-mode-show-strict-warnings nil 2205: ;; Flycheck provides these features, so disable them: conflicting with 2206: ;; the eslint settings. 2207: js2-strict-missing-semi-warning nil 2208: ;; maximum fontification 2209: js2-highlight-level 3 2210: js2-idle-timer-delay 0.15) 2211: :general 2212: (general-nvmap 2213: :keymaps 'rjsx-mode-map 2214: "'" 'rjsx-jump-tag 2215: "gj" 'rjsx-jump-closing-tag 2216: "gk" 'rjsx-jump-opening-tag 2217: "gr" 'rjsx-rename-tag-at-point 2218: "z>" 'rjsx-electric-gt 2219: "z<" 'rjsx-electric-lt)) 2220: (use-package typescript-mode 2221: :ensure 2222: :defer t 2223: :hook (typescript-mode . rainbow-delimiters-mode) 2224: :hook (typescript-tsx-mode . rainbow-delimiters-mode) 2225: :hook (typescript-mode . (lambda () (setq comment-line-break-function #'js2-line-break 2226: typescript-indent-level (or (and (bound-and-true-p tide-mode) 2227: (plist-get (tide-tsfmt-options) :indentSize)) 2228: typescript-indent-level) 2229: emmet-expand-jsx-className? t))) 2230: :init 2231: (add-to-list 'auto-mode-alist 2232: (cons "\\.tsx\\'" #'typescript-mode)) 2233: (with-eval-after-load 'flycheck 2234: (flycheck-add-mode 'javascript-eslint 'web-mode) 2235: (flycheck-add-mode 'javascript-eslint 'typescript-mode) 2236: (flycheck-add-mode 'javascript-eslint 'typescript-tsx-mode) 2237: (flycheck-add-mode 'typescript-tslint 'typescript-tsx-mode)) 2238: (defun +javascript-disable-tide-checkers-h () 2239: (add-to-list 'flycheck-disabled-checkers 'javascript-jshint) 2240: (add-to-list 'flycheck-disabled-checkers 'tsx-tide) 2241: (add-to-list 'flycheck-disabled-checkers 'jsx-tide)) 2242: (add-hook 'typescript-tsx-mode-hook #'+javascript-disable-tide-checkers-h) 2243: :config 2244: (when (fboundp 'web-mode) 2245: (define-derived-mode typescript-tsx-mode web-mode "TypeScript-TSX")) 2246: (autoload 'js2-line-break "js2-mode" nil t)) 2247: (use-package tide 2248: :ensure 2249: :defer t 2250: :hook (tide-mode . tide-hl-identifier-mode) 2251: :config 2252: (setq tide-completion-detailed t 2253: tide-always-show-documentation t 2254: tide-server-max-response-length 524288 2255: tide-completion-setup-company-backend nil) 2256: (add-hook 'tide-mode-hook (lambda () (add-hook 'kill-buffer-hook #'+javascript-cleanup-tide-processes-h nil 'local)))) 2257: (use-package npm-mode 2258: :ensure 2259: :defer t) 2260: (use-package nodejs-repl 2261: :ensure 2262: :defer t) 2263: (use-package auctex 2264: :ensure nil 2265: :mode (("\\.tex\\'" . latex-mode) 2266: ("\\.latex\\'" . latex-mode)) 2267: :commands (latex-mode LaTeX-mode plain-tex-mode) 2268: :init 2269: (progn 2270: (add-hook 'LaTeX-mode-hook #'LaTeX-preview-setup) 2271: (add-hook 'LaTeX-mode-hook #'flyspell-mode) 2272: (add-hook 'LaTeX-mode-hook #'turn-on-reftex) 2273: (setq-default TeX-engine 'xetex) 2274: (setq TeX-auto-save nil 2275: TeX-parse-self nil 2276: TeX-save-query nil 2277: TeX-PDF-mode t) 2278: (setq-default TeX-master nil))) 2279: (use-package preview 2280: :ensure nil 2281: :after auctex 2282: :commands LaTeX-preview-setup 2283: :init 2284: (progn 2285: (setq-default preview-scale 1.4 2286: preview-scale-function '(lambda () (* (/ 10.0 (preview-document-pt)) preview-scale))))) 2287: (use-package reftex 2288: :ensure nil 2289: :commands turn-on-reftex 2290: :init 2291: (setq reftex-plug-into-AUCTeX t)) 2292: (use-package bibtex 2293: :config 2294: (setq bibtex-autokey-year-length 4 2295: bibtex-autokey-name-year-separator "-" 2296: bibtex-autokey-year-title-separator "-" 2297: bibtex-autokey-titleword-separator "-" 2298: bibtex-autokey-titlewords 2 2299: bibtex-autokey-titlewords-stretch 1 2300: bibtex-autokey-titleword-length 5)) 2301: ;; Auto-fill for LaTeX 2302: (defun lem-latex-auto-fill () 2303: "Turn on auto-fill for LaTeX mode." 2304: (turn-on-auto-fill) 2305: (set-fill-column 80) 2306: (setq default-justification 'left)) 2307: (add-hook 'LaTeX-mode-hook #'lem-latex-auto-fill) 2308: 2309: ;; Compilation command 2310: (add-hook 'LaTeX-mode-hook (lambda () (setq compile-command "latexmk -pdflatex=xelatex -f -pdf %f"))) 2311: 2312: ;; Prevent ispell from verifying some LaTeX commands 2313: ;; http://stat.genopole.cnrs.fr/dw/~jchiquet/fr/latex/emacslatex 2314: (defvar lem-ispell-tex-skip-alists 2315: '("cite" "nocite" 2316: "includegraphics" 2317: "author" "affil" 2318: "ref" "eqref" "pageref" 2319: "label")) 2320: (setq ispell-tex-skip-alists 2321: (list 2322: (append (car ispell-tex-skip-alists) 2323: (mapcar #'(lambda (cmd) (list (concat "\\\\" cmd) 'ispell-tex-arg-end)) lem-ispell-tex-skip-alists)) 2324: (cadr ispell-tex-skip-alists))) 2325: 2326: ;; Indentation with align-current in LaTeX environments 2327: (defvar lem-LaTeX-align-environments '("tabular" "tabular*")) 2328: (add-hook 'LaTeX-mode-hook 2329: (lambda () 2330: (require 'align) 2331: (setq LaTeX-indent-environment-list 2332: ;; For each item in the list... 2333: (mapcar (lambda (item) 2334: ;; The car is an environment 2335: (let ((env (car item))) 2336: ;; If this environment is in our list... 2337: (if (member env lem-LaTeX-align-environments) 2338: ;; ...then replace this item with a correct one 2339: (list env 'align-current) 2340: ;; else leave it alone 2341: item))) 2342: LaTeX-indent-environment-list)))) 2343: 2344: ;; Use dvipdfmx to convert DVI files to PDF in AUCTeX 2345: (eval-after-load 'tex 2346: '(add-to-list 'TeX-command-list 2347: '("DVI to PDF" "dvipdfmx %d" TeX-run-command t t) t)) 2348: 2349: ;; SyncTeX (http://www.emacswiki.org/emacs/AUCTeX#toc19) 2350: (defun synctex/un-urlify (fname-or-url) 2351: "A trivial function that replaces a prefix of file:/// with just /." 2352: (if (string= (substring fname-or-url 0 8) "file:///") 2353: (substring fname-or-url 7) 2354: fname-or-url)) 2355: (use-package markdown-mode 2356: :ensure) 2357: 2358: (use-package markdown-ts-mode 2359: :ensure 2360: :init 2361: (add-to-list 'major-mode-remap-alist '(markdown-mode . markdown-ts-mode))) 2362: 2363: (use-package poly-markdown 2364: :ensure 2365: :init :mode 2366: (("README\\.md\\'" . gfm-mode) 2367: ("\\.md$" . markdown-ts-mode) 2368: ("\\.markdown$" . markdown-ts-mode))) 2369: 2370: (use-package edit-indirect 2371: :ensure 2372: :after markdown-mode) 2373: (use-package python 2374: :mode ("[./]flake8\\'" . conf-mode) 2375: :mode ("/Pipfile\\'" . conf-mode) 2376: :hook ((python-mode . lsp-deferred) 2377: (python-mode . lsp-ui-mode) 2378: (python-mode . lsp-ui-doc-mode) 2379: ;; (python-mode . guess-style-guess-tab-mode) 2380: (python-mode-local-vars . (lambda () 2381: (lsp-deferred) 2382: (tree-sitter)))) 2383: :config 2384: (if (executable-find "ipython") 2385: (setq python-interpreter (executable-find "ipython")) 2386: (setq python-interpreter (executable-find "python3"))) 2387: (when (featurep 'projectile) 2388: (add-to-list 'projectile-globally-ignored-directories "^\\.venv$")) 2389: (let ((directories `("/usr/bin/" "/usr/local/bin/" "/opt/bin" ,(expand-file-name ".local/bin/" (getenv "HOME"))))) 2390: (dolist (directory directories) (when (file-directory-p directory)(add-to-list 'python-shell-exec-path directory)))) 2391: (setq python-indent-guess-indent-offset nil 2392: python-shell-completion-native-enable nil 2393: python-shell-exec-path (list "/usr/bin/" "/usr/local/bin" (expand-file-name ".local/bin/" (getenv "HOME"))) 2394: python-indent-guess-indent-offset-verbose nil) 2395: (when (featurep 'lsp-mode) 2396: (setq lsp-pylsp-plugins-rope-completion-enabled t ; needs python-rope package 2397: lsp-pylsp-plugins-mccabe-enabled t ; needs python-mccabe package 2398: lsp-ruff-lsp-python-path (executable-find "python3") 2399: ) 2400: (when (executable-find "black") 2401: (setq lsp-pylsp-plugins-black-enabled t)) 2402: (when (executable-find "autopep8") 2403: (setq lsp-pylsp-plugins-autopep8-enabled t)) 2404: (when (executable-find "flake8") 2405: (setq lsp-pylsp-plugins-flake8-enabled t)) 2406: (when (executable-find "pycodestyle") 2407: (setq lsp-pylsp-plugins-pycodestyle-enabled t)) 2408: (when (executable-find "pydocstyle") 2409: (setq lsp-pylsp-plugins-pydocstyle-enabled t)) 2410: (when (executable-find "pylint") 2411: (setq lsp-pylsp-plugins-pylint-enabled t)) 2412: (when (executable-find "pyflakes") 2413: (setq lsp-pylsp-plugins-pyflakes-enabled t)) 2414: (when (executable-find "yapf") 2415: (setq lsp-pylsp-plugins-yapf-enabled t))) 2416: (when (featurep 'flycheck) 2417: (setq flycheck-python-mypy-executable (executable-find "mypy") 2418: flycheck-python-flake8-executable (executable-find "flake8") 2419: flycheck-python-pylint-executable (executable-find "pylint") 2420: flycheck-python-pyright-executable (executable-find "pyright"))) 2421: :general 2422: (+config/local-leader 2423: :keymaps 'python-mode-map 2424: "d" '(:ignore t :wk "doc"))) 2425: 2426: (use-package ob-ipython 2427: :ensure 2428: :defer t 2429: :init 2430: (setq ob-ipython-resources-dir ".ob-ipython-resrc") 2431: (with-eval-after-load 'org-src 2432: (add-to-list 'org-src-lang-modes '("ipython" . python))) 2433: (with-eval-after-load 'ob-async 2434: (add-to-list 'ob-async-no-async-languages-alist "ipython"))) 2435: (use-package pip-requirements 2436: :ensure 2437: :defer t 2438: :config 2439: (add-hook 'pip-requirements-mode-hook #'pip-requirements-auto-complete-setup)) 2440: 2441: (use-package lsp-pyright 2442: :ensure 2443: :after lsp-mode 2444: :hook (python-mode . (lambda () 2445: (lsp-deferred) 2446: (lsp-ui-mode) 2447: (lsp-ui-doc-mode))) 2448: :config 2449: (setq lsp-pyright-python-executable-cmd 2450: (if (executable-find "python3") 2451: (executable-find "python3") 2452: "python"))) 2453: (use-package python-docstring 2454: :ensure 2455: :diminish 2456: :hook (python-mode . python-docstring-mode) 2457: :general 2458: (+config/local-leader 2459: :keymaps 'python-mode-map 2460: "dq" 'python-docstring-fill)) 2461: (use-package pipenv 2462: :ensure 2463: :diminish 2464: :after python 2465: :commands pipenv-project-p 2466: :hook (python-mode . pipenv-mode) 2467: :init 2468: (setq pipenv-projectile-after-switch-function 2469: #'pipenv-projectile-after-switch-extended 2470: pipenv-executable (executable-find "pipenv")) 2471: :general 2472: (+config/local-leader 2473: :keymaps 'python-mode-map 2474: "p" '(:keymap pipenv-command-map :package pipenv :wk "pipenv"))) 2475: 2476: 2477: (use-package ein 2478: :ensure t) 2479: ;;;###autoload 2480: (defun +rust-cargo-project-p () 2481: "Return t if this is a cargo project." 2482: (locate-dominating-file buffer-file-name "Cargo.toml")) 2483: 2484: ;;; Custom Cargo commands 2485: 2486: (autoload 'rustic-run-cargo-command "rustic-cargo") 2487: ;;;###autoload 2488: (defun +rust/cargo-audit () 2489: "Run 'cargo audit' for the current project." 2490: (interactive) 2491: (rustic-run-cargo-command "cargo audit")) 2492: 2493: (with-eval-after-load 'projectile 2494: (add-to-list 'projectile-project-root-files "Cargo.toml")) 2495: 2496: (use-package rust-mode) 2497: (use-package rustic 2498: :ensure 2499: :mode ("\\.rs$" . rustic-mode) 2500: :init 2501: (with-eval-after-load 'rustic-flycheck 2502: (remove-hook 'rustic-mode-hook #'flycheck-mode) 2503: (remove-hook 'rustic-mode-hook #'flymake-mode-off) 2504: (remove-hook 'flycheck-mode-hook #'rustic-flycheck-setup)) 2505: (with-eval-after-load 'org-src 2506: (defalias 'org-babel-execute:rust #'org-babel-execute:rustic)) 2507: :config 2508: (add-hook 'rustic-mode-hook #'rainbow-delimiters-mode) 2509: (setq rustic-indent-method-chain t 2510: rustic-lsp-client 'lsp-mode) 2511: (add-hook 'rustic-mode-local-vars-hook #'rustic-setup-lsp 'append) 2512: (add-hook 'rustic-mode-local-vars-hook #'flycheck-mode) 2513: ;; (add-hook 'rustic-mode-local-vars-hook #'tree-sitter! 'append) 2514: (with-eval-after-load 'lsp 2515: (setq lsp-rust-analyzer-display-parameter-hints t))) 2516: (use-package flycheck-rust 2517: :ensure 2518: :after flycheck 2519: :config 2520: (with-eval-after-load 'rustic 2521: (add-hook 'flycheck-mode-hook #'flycheck-rust-setup))) 2522: (use-package ansible 2523: :ensure 2524: :defer t 2525: :if (executable-find "ansible") 2526: :ensure 2527: :commands ansible-auto-decrypt-encrypt 2528: :hook (ansible . 'ansible-auto-decrypt-encrypt) 2529: :init 2530: (put 'ansible-vault-password-file 'safe-local-variable #'stringp) 2531: :config 2532: (setq ansible-section-face 'font-lock-variable-name-face 2533: ansible-task-label-face 'font-lock-doc-face) 2534: :general 2535: (+config/local-leader 2536: :keymaps 'yaml-mode-map 2537: "a" '(:ignore t :wk ansible) 2538: "ad" 'ansible-decrypt-buffer 2539: "ae" 'ansible-encrypt-buffer)) 2540: (use-package ansible-doc 2541: :after ansible 2542: :ensure 2543: :hook (yaml-mode . ansible-doc-mode) 2544: :config 2545: (when (featurep 'evil) 2546: (evil-set-initial-state '(ansible-doc-module-mode) 'emacs))) 2547: (use-package cperl-mode 2548: :ensure 2549: :defer t 2550: :mode ("\\.\\([pP][Llm]\\|al\\)\\'" . cperl-mode)) 2551: (use-package haskell-mode 2552: :ensure t 2553: :defer t 2554: :init 2555: (setq flymake-allowed-file-name-masks nil) 2556: :custom 2557: (haskell-process-load-or-reload-prompt t) 2558: (haskell-process-auto-import-loaded-modules t) 2559: (haskell-process-log t) 2560: (haskell-tags-on-save t)) 2561: (use-package lsp-haskell 2562: :ensure t 2563: :defer t 2564: :after lsp) 2565: (use-package magit 2566: :ensure 2567: :demand t 2568: :config 2569: (evil-set-initial-state #'git-commit-mode 'insert) 2570: :custom 2571: (magit-revision-show-gravatars '("^Author: " . "^Commit: ")) 2572: (magit-diff-refine-hunk 'all) 2573: (magit-log-arguments '("-n100" "--graph" "--decorate")) 2574: :general 2575: (+config/leader-go 2576: "g" 'magit-status)) 2577: (use-package projectile 2578: :ensure t 2579: :demand t 2580: :bind (([remap evil-jump-to-tag] . projectile-find-tag) 2581: ([remap find-tag] . projectile-find-tag)) 2582: :hook (dired-before-readin . projectile-track-known-projects-find-file-hook) 2583: :custom 2584: (projectile-cache-file (expand-file-name ".projects" user-emacs-directory)) 2585: (projectile-auto-discover nil) 2586: (projectile-enable-caching (not noninteractive)) 2587: (projectile-globally-ignored-files '("DS_Store" "TAGS")) 2588: (projectile-globally-ignored-file-suffixes '(".elc" ".pyc" ".o")) 2589: (projectile-kill-buffers-filter 'kill-only-files) 2590: (projectile-known-projects-file (expand-file-name ".projectile_projects.eld" user-emacs-directory)) 2591: (projectile-ignored-projects '("~/")) 2592: (projectile-project-root-files-bottom-up 2593: (append '(".projectile" ".project" ".git") 2594: (when (executable-find "hg") 2595: '(".hg")) 2596: (when (executable-find "bzr") 2597: '(".bzr")))) 2598: (projectile-project-root-files-top-down-recurring '("Makefile")) 2599: (compilation-buffer-name-function #'projectile-compilation-buffer-name) 2600: (compilation-save-buffers-predicate #'projectile-current-project-buffer-p) 2601: (projectile-git-submodule-command nil) 2602: (projectile-indexing-method 'hybrid) 2603: :config 2604: (projectile-mode +1) 2605: (put 'projectile-git-submodule-command 'initial-value projectile-git-submodule-command) 2606: :general 2607: (+config/leader-key 2608: "SPC" 'projectile-find-file 2609: "p" '(:keymap projectile-command-map :package projectile :wk "projectile"))) 2610: (use-package diff-hl 2611: :ensure 2612: :hook (find-file . diff-hl-mode) 2613: :hook (vc-dir-mode . diff-hl-dir-mode) 2614: :hook (dired-mode . diff-hl-dired-mode) 2615: :hook (diff-hl-mode . diff-hl-flydiff-mode) 2616: :hook (diff-hl-mode . diff-hl-show-hunk-mouse-mode) 2617: :hook (magit-pre-refresh-hook . diff-hl-magit-pre-refresh) 2618: :hook (magit-post-refresh-hook . diff-hl-magit-post-refresh) 2619: :init 2620: (global-diff-hl-mode) 2621: :custom 2622: (vc-git-diff-switches '("--histogram") 2623: diff-hl-flydiff-delay 0.5 2624: diff-hl-show-staged-changes nil) 2625: :config 2626: (when (featurep 'flycheck) 2627: (setq flycheck-indication-mode 'right-fringe))) 2628: (use-package perspective 2629: :ensure 2630: :config 2631: (setq persp-initial-frame-name "Main" 2632: persp-suppress-no-prefix-key-warning t) 2633: (if (featurep 'no-littering) 2634: (setq persp-state-default-file (expand-file-name ".perspective-state" no-littering-var-directory)) 2635: (setq persp-state-default-file (expand-file-name ".perspective-state" user-emacs-directory))) 2636: (global-set-key [remap switch-to-buffer] #'persp-switch-to-buffer*) 2637: (when (featurep 'consult) 2638: (require 'consult) 2639: (unless (boundp 'persp-consult-source) 2640: (defvar persp-consult-source 2641: (list :name "Perspective" 2642: :narrow ?s 2643: :category 'buffer 2644: :state #'consult--buffer-state 2645: :history 'buffer-name-history 2646: :default t 2647: :items 2648: #'(lambda () (consult--buffer-query :sort 'visibility 2649: :predicate '(lambda (buf) (persp-is-current-buffer buf t)) 2650: :as #'buffer-name))))) 2651: (consult-customize consult--source-buffer :hidden t :default nil) 2652: (add-to-list 'consult-buffer-sources persp-consult-source)) 2653: :init 2654: (customize-set-variable 'persp-mode-prefix-key (kbd "C-c TAB")) 2655: (unless (equal persp-mode t) 2656: (persp-mode 1)) 2657: :bind (([remap switch-to-buffer] . persp-switch-to-buffer*) 2658: ([remap kill-buffer] . persp-kill-buffer*)) 2659: :hook (kill-emacs . persp-state-save) 2660: :general 2661: (general-def 2662: :keymaps 'perspective-map 2663: "TAB" '(persp-switch-last :wk "switch to last perspective") 2664: "P" 'projectile-persp-switch-project) 2665: (+config/leader-key 2666: "TAB" (general-simulate-key "C-c TAB" 2667: :state '(normal visual) 2668: :name general-SPC-h-simulates-C-c-TAB 2669: :docstring "Simulates C-c TAB in normal and visual mode." 2670: :which-key "Perspective")) 2671: (+config/leader-key 2672: "C-x" '(persp-switch-to-scratch-buffer :wk "switch to scratch buffer"))) 2673: (use-package persp-projectile 2674: :ensure t 2675: :after perspective 2676: :commands projectile-persp-switch-project 2677: :general 2678: (general-def 2679: :keymaps 'perspective-map 2680: "P" 'projectile-persp-switch-project)) 2681: (use-package git-link 2682: :demand 2683: :ensure 2684: :commands (git-link git-link-commit git-link-homepage) 2685: :general 2686: (+config/leader-go 2687: "G" '(:ignore t :wk "git") 2688: "Gl" 'git-link 2689: "Gh" 'git-link-homepage 2690: "Gc" 'git-link-commit)) 2691: (use-package git-messenger 2692: :ensure 2693: :config 2694: (with-eval-after-load 'general 2695: (+config/leader-go 2696: "Gm" 'git-messenger:popup-message)) 2697: :custom 2698: ;; Enable magit-show-commit instead of pop-to-buffer 2699: (git-messenger:use-magit-popup t) 2700: (git-messenger:show-detail t)) 2701: (use-package git-timemachine 2702: :ensure 2703: :after magit 2704: :general 2705: (+config/leader-go 2706: "Gt" 'git-timemachine-toggle)) 2707: (use-package org-project-capture 2708: :bind (("C-c n p" . org-project-capture-project-todo-completing-read)) 2709: :ensure t 2710: :config 2711: (progn 2712: (setq org-project-capture-backend 2713: (make-instance 'org-project-capture-projectile-backend)) ; Replace with your backend of choice 2714: (setq org-project-capture-projects-file (expand-file-name "projects.org" org-directory)) 2715: (org-project-capture-single-file))) 2716: (use-package lsp-mode 2717: :ensure 2718: :init 2719: (setq lsp-keymap-prefix "C-c C-l") 2720: (defun my/orderless-dispatch-flex-first (_pattern index _total) 2721: (and (eq index 0) 'orderless-flex)) 2722: (defun my/lsp-mode-setup-completion () 2723: (setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults)) 2724: '(orderless))) 2725: (add-hook 'orderless-style-dispatchers #'my/orderless-dispatch-flex-first nil 'local) 2726: (when (featurep 'cape) 2727: (setq-local completion-at-point-functions (list (cape-capf-buster #'lsp-completion-at-point)))) 2728: :hook 2729: (lsp-mode . lsp-enable-which-key-integration) 2730: (lsp-completion-mode . my/lsp-mode-setup-completion) 2731: ((c-mode c++-mode xml-mode python-mode 2732: yaml-mode toml-mode python-mode-local-vars 2733: lua-mode jinja2-mode 2734: json-mode html-mode 2735: web-mode html-mode-local-vars-hook 2736: web-mode-local-vars-hook nxml-mode-local-vars-hook 2737: scss-mode-local-vars css-mode-local-vars 2738: less-css-mode-local-vars css-mode 2739: typescript-mode javascript-mode 2740: js2-mode typescript-tsx-mode) . lsp-deferred) 2741: :config 2742: (setq lsp-toml-command 2743: (if (file-exists-p (expand-file-name ".cargo/bin/taplo" "~")) 2744: (expand-file-name ".cargo/bin/taplo" "~") 2745: "taplo") 2746: lsp-rust-rls-server-command "rls" 2747: lsp-eldoc-render-all t 2748: lsp-enable-snippet nil 2749: lsp-enable-indentation nil 2750: lsp-prefer-flymake nil 2751: lsp-keep-workspace-alive nil 2752: lsp-modeline-code-actions-segments '(count icon name)) 2753: (when (featurep 'exwm) 2754: (advice-add #'corfu--make-frame :around 2755: (defun +corfu--make-frame-a (oldfun &rest args) 2756: (cl-letf (((symbol-function #'frame-parent) 2757: (lambda (frame) 2758: (or (frame-parameter frame 'parent-frame) 2759: exwm-workspace--current)))) 2760: (apply oldfun args)) 2761: (when exwm--connection 2762: (set-frame-parameter corfu--frame 'parent-frame nil)))) 2763: 2764: (advice-add #'corfu--popup-redirect-focus :override 2765: (defun +corfu--popup-redirect-focus-a () 2766: (redirect-frame-focus corfu--frame 2767: (or (frame-parent corfu--frame) 2768: exwm-workspace--current))))) 2769: :custom 2770: (lsp-completion-provider :none) 2771: :general 2772: (+config/leader-key 2773: :keymaps 'lsp-mode-map 2774: "l" (general-simulate-key "C-c C-l" 2775: :name general-SPC-l-simulates-C-c-C-l 2776: :docstring "Simulates C-c C-l" 2777: :which-key "LSP"))) 2778: (use-package lsp-ui 2779: :ensure 2780: :defer t 2781: :hook (lsp-mode . lsp-ui-mode) 2782: :init 2783: (setq lsp-ui-sideline-enable t 2784: lsp-ui-sideline-update-mode 'line 2785: lsp-ui-sideline-show-code-actions t 2786: lsp-ui-sideline-show-hover t 2787: lsp-ui-doc-enable t 2788: lsp-ui-doc-include-signature t 2789: lsp-ui-doc-show-with-cursor t 2790: lsp-eldoc-enable-hover nil ; Disable eldoc displays in minibuffer 2791: lsp-ui-doc-position 'at-point 2792: lsp-ui-imenu-enable t 2793: lsp-ui-sideline-ignore-duplicate t 2794: lsp-ui-peek-enable t) 2795: :config 2796: (define-key lsp-ui-mode-map [remap xref-find-definitions] #'lsp-ui-peek-find-definitions) 2797: (define-key lsp-ui-mode-map [remap xref-find-references] #'lsp-ui-peek-find-references) 2798: (add-to-list 'lsp-language-id-configuration '(jinja2-mode . "jinja2") t) 2799: (add-to-list 'lsp-language-id-configuration '("\\.js2$" . "jinja2") t) 2800: :general 2801: (general-define-key 2802: :keymaps '(lsp-ui-mode-map) 2803: [remap xref-find-definitions] 'lsp-ui-peek-find-definitions 2804: [remap xref-find-references] 'lsp-ui-peek-find-references 2805: "M-." 'lsp-ui-peek-find-definitions 2806: "M-?" 'lsp-ui-peek-find-references)) 2807: (use-package consult-lsp 2808: :ensure 2809: :after consult lsp 2810: :bind 2811: (:map lsp-mode-map 2812: ([remap xref-find-apropos] . consult-lsp-symbols)))