diff options
| author | Aryadev Chavali <aryadev@aryadevchavali.com> | 2023-09-29 22:30:58 +0100 | 
|---|---|---|
| committer | Aryadev Chavali <aryadev@aryadevchavali.com> | 2023-09-29 22:30:58 +0100 | 
| commit | a0a5b2e05d3beae7ed3d5ed14b6b65bbc811c7a9 (patch) | |
| tree | b0482444d66b598c13aa47636306aa42986de8d2 /Emacs/.config/emacs/core.org | |
| parent | cc25dcf8121c7a0431f5fc1f27675b1229818041 (diff) | |
| download | dotfiles-a0a5b2e05d3beae7ed3d5ed14b6b65bbc811c7a9.tar.gz dotfiles-a0a5b2e05d3beae7ed3d5ed14b6b65bbc811c7a9.tar.bz2 dotfiles-a0a5b2e05d3beae7ed3d5ed14b6b65bbc811c7a9.zip  | |
(Emacs)~config->app,core
The two largest sections of my config are separated into their own
files now.  Does increase init time, but I just can't handle how big
this thing is.  It'll be a bit nicer to look at and manage with
separate files.
Diffstat (limited to 'Emacs/.config/emacs/core.org')
| -rw-r--r-- | Emacs/.config/emacs/core.org | 738 | 
1 files changed, 738 insertions, 0 deletions
diff --git a/Emacs/.config/emacs/core.org b/Emacs/.config/emacs/core.org new file mode 100644 index 0000000..687b226 --- /dev/null +++ b/Emacs/.config/emacs/core.org @@ -0,0 +1,738 @@ +#+title: Core packages +#+author: Aryadev Chavali +#+description: The core components of my configuration +#+date: 2023-09-29 +#+property: header-args:emacs-lisp :tangle core.el :comments link :results none +#+options: toc:nil +#+startup: noindent + +Packages that are absolutely necessary for the rest of the +configuration.  These yield core functionality such as keybinding, +modal editing, completion, auto typing to name a few. +* General +General provides a great solution for binding keys.  It has evil and +use-package support so it fits nicely into configuration.  In this +case, I define a "definer" for the "LEADER" keys.  Leader is bound to +~SPC~ and it's functionally equivalent to the doom/spacemacs leader. +Local leader is bound to ~SPC ,~ and it's similar to doom/spacemacs +leader but doesn't try to fully assimilate the local-leader map, +instead just picking stuff I think is useful.  This forces me to learn +only as many bindings as I find necessary; no more, no less. + +I also define prefix leaders for differing applications.  These are +quite self explanatory by their name and provide a nice way to +visualise all bindings under a specific heading just by searching the +code. +#+begin_src emacs-lisp +(use-package general +  :straight t +  :demand t +  :config +  ;; General which key definitions for leaders +  (general-def +    :states '(normal motion) +    "SPC"   'nil +    "\\"    '(nil :which-key "Local leader") +    "SPC c" '(nil :which-key "Code") +    "SPC f" '(nil :which-key "File") +    "SPC t" '(nil :which-key "Shell") +    "SPC m" '(nil :which-key "Toggle modes") +    "SPC a" '(nil :which-key "Applications") +    "SPC s" '(nil :which-key "Search") +    "SPC b" '(nil :which-key "Buffers") +    "SPC q" '(nil :which-key "Quit/Literate") +    "SPC i" '(nil :which-key "Insert") +    "SPC d" '(nil :which-key "Directories")) + +  (general-create-definer leader +    :states '(normal motion) +    :keymaps 'override +    :prefix "SPC") + +  (general-create-definer local-leader +    :states '(normal motion) +    :prefix "\\") + +  (general-create-definer code-leader +    :states '(normal motion) +    :keymaps 'override +    :prefix "SPC c") + +  (general-create-definer file-leader +    :states '(normal motion) +    :keymaps 'override +    :prefix "SPC f") + +  (general-create-definer shell-leader +    :states '(normal motion) +    :keymaps 'override +    :prefix "SPC t") + +  (general-create-definer mode-leader +    :states '(normal motion) +    :keymaps 'override +    :prefix "SPC m") + +  (general-create-definer app-leader +    :states '(normal motion) +    :keymaps 'override +    :prefix "SPC a") + +  (general-create-definer search-leader +    :states '(normal motion) +    :keymaps 'override +    :prefix "SPC s") + +  (general-create-definer buffer-leader +    :states '(normal motion) +    :keymaps 'override +    :prefix "SPC b") + +  (general-create-definer quit-leader +    :states '(normal motion) +    :keymaps 'override +    :prefix "SPC q") + +  (general-create-definer insert-leader +    :states '(normal motion) +    :keymaps 'override +    :prefix "SPC i") + +  (general-create-definer dir-leader +    :states '(normal motion) +    :keymaps 'override +    :prefix "SPC d") + +  (general-create-definer general-nmmap +    :states '(normal motion)) + +  (defalias 'nmmap #'general-nmmap) + +  (general-evil-setup t)) +#+end_src +** Some binds in Emacs +Some bindings that I couldn't fit elsewhere easily. +#+begin_src emacs-lisp +(use-package emacs +  :straight nil +  :general +  (general-def +    "C-x d" #'delete-frame) + +  (nmmap +    "C--" #'text-scale-decrease +    "C-=" #'text-scale-increase) + +  (leader +    "SPC" '(execute-extended-command :which-key "M-x") +    "'"   '(browse-url-emacs :which-key "Open url in Emacs") +    ";"   'eval-expression +    ":"   `(,(proc (interactive) (switch-to-buffer "*scratch*")) +            :which-key "Switch to *scratch*") +    "!"   '(async-shell-command :which-key "Async shell command") +    "h" '(help-command :which-key "Help")) + +  (mode-leader +    "t" #'+oreo/switch-theme) + +  (code-leader +    "F" `(,(proc (interactive) (find-file "~/Code/")) +          :which-key "Open ~/Code/")) + +  (file-leader +    "f" #'find-file +    "F" #'find-file-other-frame +    "s" #'save-buffer +    "p" `(,(proc (interactive) +                 (find-file (concat user-emacs-directory "config.org"))) +          :which-key "Open config.org")) + +  (quit-leader +    "q" #'save-buffers-kill-terminal +    "c" #'+literate/compile-config +    "l" #'+literate/load-config +    "d" #'delete-frame) + +  (search-leader "i" #'imenu)) +#+end_src +* Evil +My editor journey started off with Vim rather than Emacs, so my brain +has imprinted on its style.  Thankfully Emacs is super extensible so +there exists a package (more of a supreme system) for porting Vim's +modal editing style to Emacs, called Evil (Emacs Vi Layer). + +However there are a lot of packages in Vim that provide greater +functionality, for example 'vim-surround'.  Emacs, by default, has +these capabilities but there are further packages which integrate them +into Evil. +** Evil core +Setup the evil package, with some opinionated keybindings: +- Switch ~evil-upcase~ and ~evil-downcase~ because I use ~evil-upcase~ +  more +- Switch ~evil-goto-mark~ and ~evil-goto-mark-line~ as I'd rather have +  the global one closer to the home row +- Use 'T' character as an action for transposing objects +#+begin_src emacs-lisp +(use-package evil +  :demand t +  :hook (after-init-hook . evil-mode) +  :general +  (leader +    "w"  '(evil-window-map :which-key "Window") +    "wd" #'delete-frame) + +  (nmmap +    "TAB" #'evil-jump-item +    "r"   #'evil-replace-state +    "zC"  #'hs-hide-level +    "zO" #'hs-show-all +    "'"   #'evil-goto-mark +    "`"   #'evil-goto-mark-line +    "C-w" #'evil-window-map +    "gu"  #'evil-upcase +    "gU"  #'evil-downcase +    "T"   nil) + +  (nmmap +    :infix "T" +    "w" #'transpose-words +    "c" #'transpose-chars +    "s" #'transpose-sentences +    "p" #'transpose-paragraphs +    "e" #'transpose-sexps +    "l" #'transpose-lines) +  :init +  (setq evil-want-keybinding nil +        evil-split-window-below t +        evil-vsplit-window-right t +        evil-want-abbrev-expand-on-insert-exit t +        evil-undo-system #'undo-tree) +  :config +  (fset #'evil-window-vsplit #'make-frame)) +#+end_src +** Evil surround +Evil surround is a port for vim-surround. +#+begin_src emacs-lisp +(use-package evil-surround +  :after evil +  :config +  (global-evil-surround-mode)) +#+end_src +** Evil commentary +Allows generalised commenting of objects easily. +#+begin_src emacs-lisp +(use-package evil-commentary +  :after evil +  :config +  (evil-commentary-mode)) +#+end_src +** Evil multi cursor +Setup for multi cursors in Evil mode.  Don't let evil-mc setup it's own +keymap because it uses 'gr' as its prefix, which I don't like. +#+begin_src emacs-lisp +(use-package evil-mc +  :after evil +  :init +  (defvar evil-mc-key-map (make-sparse-keymap)) +  :general +  (nmap +    :infix "gz" +    "q" #'evil-mc-undo-all-cursors +    "d" #'evil-mc-make-and-goto-next-match +    "j" #'evil-mc-make-cursor-move-next-line +    "k" #'evil-mc-make-cursor-move-prev-line +    "j" #'evil-mc-make-cursor-move-next-line +    "m" #'evil-mc-make-all-cursors +    "z" #'evil-mc-make-cursor-here +    "r" #'evil-mc-resume-cursors +    "s" #'evil-mc-pause-cursors +    "u" #'evil-mc-undo-last-added-cursor) +  :config +  ;; (evil-mc-define-vars) +  ;; (evil-mc-initialize-vars) +  ;; (add-hook 'evil-mc-before-cursors-created #'evil-mc-pause-incompatible-modes) +  ;; (add-hook 'evil-mc-before-cursors-created #'evil-mc-initialize-active-state) +  ;; (add-hook 'evil-mc-after-cursors-deleted  #'evil-mc-teardown-active-state) +  ;; (add-hook 'evil-mc-after-cursors-deleted  #'evil-mc-resume-incompatible-modes) +  ;; (advice-add #'evil-mc-initialize-hooks :override #'ignore) +  ;; (advice-add #'evil-mc-teardown-hooks :override #'evil-mc-initialize-vars) +  ;; (advice-add #'evil-mc-initialize-active-state :before #'turn-on-evil-mc-mode) +  ;; (advice-add #'evil-mc-teardown-active-state :after #'turn-off-evil-mc-mode) +  ;; (add-hook 'evil-insert-state-entry-hook #'evil-mc-resume-cursors) +  (global-evil-mc-mode)) +#+end_src + +** Evil collection +Provides a community based set of keybindings for most modes in +Emacs.  I don't necessarily like all my modes having these bindings +though, as I may disagree with some.  So I use it in a mode to mode basis. +#+begin_src emacs-lisp +(use-package evil-collection +  :after evil) +#+end_src +* Completion +Emacs is a text based interface.  Completion is its bread and butter +in providing good user experience.  By default Emacs provides +'completions-list' which produces a buffer of options which can be +searched and selected.  We can take this further though! + +Ido and Icomplete are packages distributed with Emacs to provide +greater completion interfaces.  They utilise the minibuffer to create +a more interactive experience, allowing incremental searches and +option selection. + +Ivy and Helm provide more modern interfaces, though Helm is quite +heavy.  Ivy, on the other hand, provides an interface similar to Ido +with less clutter and better customisation options. +** Ivy +Ivy is a completion framework for Emacs, and my preferred one.  It has +a great set of features with little to no pain with setting up. +*** Ivy Core +Setup for ivy, in preparation for counsel.  Turn on ivy-mode just +after init. + +Setup vim-like bindings for the minibuffer ("M-(j|k)" for down|up the +selection list). +#+begin_src emacs-lisp +(use-package ivy +  :defer t +  :hook (after-init-hook . ivy-mode) +  :general +  (general-def +    :keymaps 'ivy-minibuffer-map +    "C-j"    #'ivy-yank-symbol +    "M-j"    #'ivy-next-line-or-history +    "M-k"    #'ivy-previous-line-or-history +    "C-SPC"  #'ivy-occur) +  (general-def +    :keymaps  'ivy-switch-buffer-map +    "M-j"     #'ivy-next-line-or-history +    "M-k"     #'ivy-previous-line-or-history) +  (nmap +    :keymaps '(ivy-occur-mode-map ivy-occur-grep-mode-map) +    "RET"    #'ivy-occur-press-and-switch +    "J"      #'ivy-occur-press +    "gr"     #'ivy-occur-revert-buffer +    "q"      #'quit-window +    "D"      #'ivy-occur-delete-candidate +    "W"      #'ivy-wgrep-change-to-wgrep-mode +    "{"      #'compilation-previous-file +    "}"      #'compilation-next-file) +  :init +  (with-eval-after-load "evil" +    (evil-set-initial-state 'ivy-occur-mode 'normal) +    (evil-set-initial-state 'ivy-occur-grep-mode 'normal)) +  (with-eval-after-load "amx" +    (setq amx-backend 'ivy)) + +  (setq ivy-height 10 +        ivy-wrap t +        ivy-fixed-height-minibuffer t +        ivy-use-virtual-buffers nil +        ivy-virtual-abbreviate 'full +        ivy-on-del-error-function #'ignore +        ivy-use-selectable-prompt t) +  :config +  (require 'counsel nil t)) +#+end_src +*** Counsel +Setup for counsel.  Load after ivy and helpful. +#+begin_src emacs-lisp +(use-package counsel +  :defer t +  :general +  (search-leader +    "s" #'counsel-grep-or-swiper +    "r" #'counsel-rg) +  (file-leader +    "r" #'counsel-recentf) +  (insert-leader +    "c" #'counsel-unicode-char) +  (general-def +    [remap describe-bindings]        #'counsel-descbinds +    [remap load-theme]               #'counsel-load-theme) +  :config +  (setq ivy-initial-inputs-alist '((org-insert-link . "^")) +        counsel-describe-function-function #'helpful-callable +        counsel-describe-variable-function #'helpful-variable +        counsel-grep-swiper-limit 1500000 +        ivy-re-builders-alist '((swiper . ivy--regex-plus) +                                (counsel-grep-or-swiper . ivy--regex-plus) +                                (counsel-rg . ivy--regex-plus) +                                (t . ivy--regex-ignore-order))) +  (counsel-mode)) +#+end_src +*** WIP Ivy posframe +:PROPERTIES: +:header-args:emacs-lisp: :tangle no +:END: +This makes ivy minibuffer windows use child frames. +Very nice eyecandy, but can get kinda annoying. +#+begin_src emacs-lisp +(use-package ivy-posframe +  :hook (ivy-mode-hook . ivy-posframe-mode) +  :straight t +  :init +  (setq ivy-posframe-parameters +        '((left-fringe      . 0) +          (right-fringe     . 0) +          (background-color . "grey7"))) + +  (setq ivy-posframe-display-functions-alist +        '((t . ivy-posframe-display-at-window-center)))) +#+end_src +*** WIP Counsel etags +:PROPERTIES: +:header-args:emacs-lisp: :tangle no +:END: +Counsel etags allows me to search generated tag files for tags.  I +already have a function defined to generate the tags, so it's just +searching them which I find to be a bit of a hassle, and where this +package comes in. + +This has been replaced by [[*xref][xref]] which is inbuilt. +#+begin_src emacs-lisp +(use-package counsel-etags +  :after counsel +  :general +  (search-leader +    "t" #'counsel-etags-find-tag)) +#+end_src +** WIP Ido +:PROPERTIES: +:header-args:emacs-lisp: :tangle no +:END: +Ido is a very old completion package that still works great to this +day.  Though it is limited in its scope (and may thus be called a +completion add-on rather than a full on framework), it is still a very +powerful package.  With the use of ido-completing-read+, it may be used +similarly to a fully fledged completion framework. + +#+begin_src emacs-lisp +(use-package ido +  :demand t +  :general +  (general-def +    :keymaps '(ido-buffer-completion-map +               ido-file-completion-map +               ido-file-dir-completion-map +               ido-common-completion-map) +    (kbd "M-j")   #'ido-next-match +    (kbd "M-k")   #'ido-prev-match +    (kbd "C-x o") #'evil-window-up) +  :init +  (setq ido-decorations +        (list "{" "}" " \n" " ..." "[" "]" " [No match]" " [Matched]" +              " [Not readable]" " [Too big]" " [Confirm]") +        completion-styles '(flex partial-completion intials emacs22)) +  (setq-default ido-enable-flex-matching t +                ido-enable-dot-prefix t +                ido-enable-regexp nil) +  (with-eval-after-load "magit" +    (setq magit-completing-read-function 'magit-ido-completing-read)) +  :config +  (ido-mode) +  (ido-everywhere)) +#+end_src +*** Ido ubiquitous +Ido completing-read+ is a package that extends the ido package to work +with more text based functions. +#+begin_src emacs-lisp +(use-package ido-completing-read+ +  :after ido +  :config +  (ido-ubiquitous-mode +1)) +#+end_src +** Amx +Amx is a fork of Smex that works to enhance the +execute-extended-command interface.  It also provides support for ido +or ivy (though I'm likely to use ido here) and allows you to switch +between them. + +It provides a lot of niceties such as presenting the key bind when +looking for a command. + +#+begin_src emacs-lisp +(use-package amx +  :config +  (amx-mode)) +#+end_src +** Orderless +Orderless sorting method for completion, probably one of the best +things ever. +#+begin_src emacs-lisp +(use-package orderless +  :after (ivy ido) +  :config +  (setf (alist-get t ivy-re-builders-alist) 'orderless-ivy-re-builder)) +#+end_src +** Completions-list +In case I ever use the completions list, some basic commands to look +around. +#+begin_src emacs-lisp +(use-package simple +  :straight nil +  :general +  (nmmap +    :keymaps 'completion-list-mode-map +    "l"   #'next-completion +    "h"   #'previous-completion +    "ESC" #'delete-completion-window +    "q"   #'quit-window +    "RET" #'choose-completion) +  :config +  (with-eval-after-load "evil" +    (setq evil-emacs-state-modes (cl-remove-if +                                  #'(lambda (x) (eq 'completions-list-mode x)) +                                  evil-emacs-state-modes)) +    (add-to-list 'evil-normal-state-modes 'completions-list-mode))) +#+end_src +** Company +Company is the auto complete system I use.  I don't like having heavy +setups for company as it only makes it slower to use.  In this case, +just setup some evil binds for company. +#+begin_src emacs-lisp +(use-package company +  :straight t +  :hook +  (prog-mode-hook   . company-mode) +  (eshell-mode-hook . company-mode) +  :general +  (imap +    "C-SPC" #'company-complete) +  (general-def +    :states '(normal insert) +    "M-j" #'company-select-next +    "M-k" #'company-select-previous)) +#+end_src +* Pretty symbols +Prettify symbols mode allows for users to declare 'symbols' that +replace text within certain modes.  Though this may seem like useless +eye candy, it has aided my comprehension and speed of recognition +(recognising symbols is easier than words). + +Essentially a use-package keyword which makes declaring pretty symbols +for language modes incredibly easy.  Checkout my [[C/C++][C/C++]] configuration +for an example. +#+begin_src emacs-lisp +(use-package prog-mode +  :straight nil +  :init +  (setq prettify-symbols-unprettify-at-point t) +  :config +  (with-eval-after-load "use-package-core" +    (add-to-list 'use-package-keywords ':pretty) +    (defun use-package-normalize/:pretty (_name-symbol _keyword args) +      args) + +    (defun use-package-handler/:pretty (name _keyword args rest state) +      (use-package-concat +       (use-package-process-keywords name rest state) +       (mapcar +        #'(lambda (arg) +            (let ((mode (car arg)) +                  (rest (cdr arg))) +              `(add-hook +                ',mode +                #'(lambda nil +                    (setq prettify-symbols-alist ',rest) +                    (prettify-symbols-mode))))) +        args))))) +#+end_src + +Here's a collection of keywords and possible associated symbols for +any prog language of choice.  Mostly for reference and copying. +#+begin_example +("null"   . "Ø") +("list"   . "ℓ") +("string" . "𝕊") +("true"   . "⊤") +("false"  . "⊥") +("char"   . "ℂ") +("int"    . "ℤ") +("float"  . "ℝ") +("!"      . "¬") +("&&"     . "∧") +("||"      . "∨") +("for"    . "∀") +("return" . "⟼") +("print"  . "ℙ") +("lambda" . "λ") +#+end_example +* Window management +Emacs' default window management is quite bad, eating other windows on +a whim and not particularly caring for the current window setup. +Thankfully you can change this via the ~display-buffer-alist~ which +matches buffer names with how the window for the buffer should be +displayed.  I add a use-package keyword to make ~display-buffer-alist~ +records within use-package. + +I have no idea whether it's optimal AT ALL, but it works for me. +#+begin_src emacs-lisp +(use-package window +  :straight nil +  :general +  (buffer-leader +    "b" #'switch-to-buffer +    "d" #'kill-current-buffer +    "K" #'kill-buffer +    "j" #'next-buffer +    "k" #'previous-buffer +    "D" '(+oreo/clean-buffer-list :which-key "Kill most buffers")) +  :init +  (with-eval-after-load "use-package-core" +    (add-to-list 'use-package-keywords ':display) +    (defun use-package-normalize/:display (_name-symbol _keyword args) +      args) + +    (defun use-package-handler/:display (name _keyword args rest state) +      (use-package-concat +       (use-package-process-keywords name rest state) +       (mapcar +        #'(lambda (arg) +            `(add-to-list 'display-buffer-alist +                          ',arg)) +        args))))) +#+end_src +** Some display records +Using the ~:display~ keyword, setup up some ~display-buffer-alist~ +records.  This is mostly for packages that aren't really configured +(like [[info:woman][woman]]) or packages that were configured before +(like [[Ivy][Ivy]]). +#+begin_src emacs-lisp +(use-package window +  :straight nil +  :defer t +  :display +  ("\\*Process List\\*" +   (display-buffer-at-bottom) +   (window-height . 0.25)) + +  ("\\*\\(Ido \\)?Completions\\*" +   (display-buffer-in-side-window) +   (window-height . 0.25) +   (side . bottom)) + +  ("\\*ivy-occur.*" +   (display-buffer-at-bottom) +   (window-height . 0.25)) + +  ("\\*Async Shell Command\\*" +   (display-buffer-at-bottom) +   (window-height . 0.25))) +#+end_src +* Auto typing +Snippets are a pretty nice way of automatically inserting code.  Emacs +provides a ton of packages by default to do this, but there are great +packages to install as well. + +Abbrevs and skeletons make up a popular solution within Emacs default. +Abbrevs are for simple expressions wherein the only input is the key, +and the output is some Elisp function.  They provide a lot of inbuilt +functionality and are quite useful.  Skeletons, on the other hand, are +for higher level insertions + +The popular external solution is Yasnippet.  Yasnippet is a great +package for snippets, which I use heavily in programming and org-mode. +I setup here the global mode for yasnippet and a collection of +snippets for ease of use. +** Abbrevs +Just define a few abbrevs for various date-time operations.  Also +define a macro that will assume a function for the expansion, helping +with abstracting a few things away. +#+begin_src emacs-lisp +(use-package abbrev +  :straight nil +  :hook +  (prog-mode-hook . abbrev-mode) +  (text-mode-hook . abbrev-mode) +  :init +  (defmacro +abbrev/define-abbrevs (abbrev-table &rest abbrevs) +    `(progn +       ,@(mapcar #'(lambda (abbrev) +                     `(define-abbrev +                        ,abbrev-table +                        ,(car abbrev) +                        "" +                        (proc (insert ,(cadr abbrev))))) +                 abbrevs))) +  (setq save-abbrevs nil) +  :config +  (+abbrev/define-abbrevs +   global-abbrev-table +   ("sdate" +    (format-time-string "%Y-%m-%d" (current-time))) +   ("stime" +    (format-time-string "%H:%M:%S" (current-time))) +   ("sday" +    (format-time-string "%A" (current-time))) +   ("smon" +    (format-time-string "%B" (current-time))))) +#+end_src +** WIP Skeletons +:PROPERTIES: +:header-args:emacs-lisp: :tangle no +:END: +Defines a macro for generating a skeleton + abbrev for a given mode. +Doesn't sanitise inputs because I assume callers are /rational/ actors +who would *only* use this for their top level Emacs config. + +Honestly didn't find much use for this currently, so disabled. +#+begin_src emacs-lisp +(use-package skeleton +  :straight nil +  :after abbrev +  :config +  (defmacro +autotyping/gen-skeleton-abbrev (mode abbrev &rest skeleton) +    (let* ((table          (intern (concat (symbol-name mode) "-abbrev-table"))) +           (skeleton-name  (intern (concat "+skeleton/" (symbol-name mode) "/" abbrev)))) +      `(progn +         (define-skeleton +           ,skeleton-name +           "" +           ,@skeleton) +         (define-abbrev ,table +           ,abbrev +           "" +           ',skeleton-name))))) +#+end_src +** Auto insert +Allows inserting text immediately upon creating a new buffer with a +given name.  Supports skeletons for inserting text.  To make it easier +for later systems to define their own auto inserts, I define a +~use-package~ keyword ~auto-insert~ which allows one to define an +entry for ~auto-insert-alist~. +#+begin_src emacs-lisp +(use-package autoinsert +  :straight nil +  :demand t +  :hook (after-init-hook . auto-insert-mode) +  :config +  (with-eval-after-load "use-package-core" +    (add-to-list 'use-package-keywords ':auto-insert) +    (defun use-package-normalize/:auto-insert (_name-symbol _keyword args) +      args) +    (defun use-package-handler/:auto-insert (name _keyword args rest state) +      (use-package-concat +       (use-package-process-keywords name rest state) +       (mapcar +        #'(lambda (arg) +            `(add-to-list +              'auto-insert-alist +              ',arg)) +        args))))) +#+end_src +** Yasnippet default +Look at the snippets [[file:../.config/yasnippet/snippets/][folder]] +for all snippets I've got. +#+begin_src emacs-lisp +(use-package yasnippet +  :defer t +  :hook +  (prog-mode-hook . yas-minor-mode) +  :general +  (insert-leader +    "i" #'yas-insert-snippet) +  :config +  (yas-load-directory (no-littering-expand-etc-file-name "yasnippet/snippets"))) +#+end_src  | 
