alexforsale's literate Emacs configuration

Table of Contents

About

This is the configuration for Emacs, written in org-mode which allows me to create an actual configuration file (by tangling this one org file), automatically export it into HTML (and also publish it to my github page using github-action), and also makes it easier to maintain.

emacs.png Since this file in Emacs is considered to be a library, it should follow the convention. But this is not needed in the HTML exported file, so every heading with the name header or footer will be tagged with the noexport tag and won't show in the HTML page, it's' kind of repetitive anyway.

Me

1: (setq user-mail-address "alexforsale@yahoo.com"
2:       user-full-name "Kristian Alexander P")

Modules loading

Every top level heading in this file should be tangled to a separate file, this section will be tangled as ./config.el.

 1: (require 'config-variables (expand-file-name "modules/config-variables.el" user-emacs-directory) t)
 2: (require 'config-keybindings nil t)
 3: (require 'config-evil nil t)
 4: (require 'config-ui nil t)
 5: (require 'config-builtin nil t)
 6: (require 'config-completion nil t)
 7: (require 'config-shell nil t)
 8: (require 'config-editing nil t)
 9: (require 'config-project nil t)
10: (require 'config-org nil t)
11: (require 'config-tools nil t)
12: (require 'config-dired nil t)
13: (require 'config-treemacs nil t)
14: (require 'config-flycheck nil t)
15: (require 'config-mail nil t)
16: (require 'config-lisp nil t)
17: (require 'config-cc nil t)
18: (require 'config-xml nil t)
19: (require 'config-yaml nil t)
20: (require 'config-toml nil t)
21: (require 'config-lua nil t)
22: (require 'config-jinja2 nil t)
23: (require 'config-json nil t)
24: (require 'config-web nil t)
25: (require 'config-latex nil t)
26: (require 'config-markdown nil t)
27: (require 'config-python nil t)
28: (require 'config-rust nil t)
29: (require 'config-ansible nil t)
30: (require 'config-perl nil t)
31: (require 'config-haskell nil t)
32: (when (string= "exwm"
33:                (or (getenv "GDMSESSION")
34:                    (getenv "DESKTOP_SESSION")))
35:   (require 'config-exwm))

Since the load-path for the modules directory is defined in ./modules/config-variables.el, the first require line also state the location.

Early-init file

Customizations defined in this file (./early-init.el) takes effect earlier than the normal init file. Usually before the package systems and GUI is initialized.

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))

variables and functions

Keybindings

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.

general.el

(I think) is the keybindings used in doom, CMIIW it's been a while since I've used doomemacs.

general-keybinding-with-which-key.png More convenient key definitions in emacs1.

 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 "s-SPC")
13:   (general-create-definer +config/local-leader
14:     :keymaps 'override
15:     :states '(emacs normal hybrid motion visual operator)
16:     :prefix "m"
17:     :non-normal-prefix "s-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've found

    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: (general-nvmap
       2:   :keymaps 'smartparens-mode-map
       3:   "<" 'sp-backward-barf-sexp
       4:   "C-<" 'sp-backward-slurp-sexp
       5:   ">" 'sp-forward-slurp-sexp
       6:   "C->" 'sp-forward-barf-sexp)
       7: 
       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)
    

Evil

It's not like I hate the standard Emacs keychord, I actually used it for a while, and most of the shells default to Emacs key. But I have to admit, using vim keys allows me to type faster.

The main package

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-u-scroll t) ;; move universal arg to <leader> u
 9:   (customize-set-variable 'evil-want-C-u-delete t) ;; delete back to indentation in insert state
10:   (customize-set-variable 'evil-want-C-g-bindings t)
11:   :custom
12:   (evil-undo-system #'undo-redo)
13:   (evil-search-module 'evil-search)
14:   (evil-ex-search-vim-style-regexp t)
15:   (evil-ex-interactive-search-highlight 'selected-window)
16:   (evil-kbd-macro-suppress-motion-error t)
17:   (evil-visual-update-x-selection-p nil)
18:   :config
19:   (setq evil-normal-state-cursor 'box
20:         evil-insert-state-cursor 'bar
21:         evil-visual-state-cursor 'hollow)
22:   (evil-select-search-module 'evil-search-module 'evil-search)
23:   (evil-mode 1)
24:   (with-eval-after-load 'eldoc
25:     (eldoc-add-command 'evil-normal-state
26:                        'evil-insert
27:                        'evil-change
28:                        'evil-delete
29:                        'evil-replace))
30:   ;; (evil-set-leader '(normal visual) (kbd "SPC"))
31:   ;; (evil-set-leader '(normal visual) (kbd "C-c SPC") t)
32:   ;; set the universal arg
33:   ;; (evil-define-key '(normal visual) 'global (kbd "<leader>u") 'universal-argument)
34:   :general
35:   (+config/leader-go
36:     "'" '(:ignore t :wk "avy")
37:     "''" 'avy-resume
38:     "'c" 'evil-avy-goto-char
39:     "'l" 'evil-avy-goto-line
40:     "'w" 'evil-avy-goto-word-or-subword-1))

evil-collection

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)
 9:   :config
10:   (with-eval-after-load 'bookmark
11:     (evil-collection-bookmark-setup))
12:   (with-eval-after-load 'pass
13:     (evil-collection-pass-setup))
14:   (with-eval-after-load 'man
15:     (evil-collection-man-setup))
16:   (with-eval-after-load 'org
17:     (evil-collection-org-setup))
18:   (with-eval-after-load 'corfu
19:     (evil-collection-corfu-setup))
20:   (with-eval-after-load 'embark
21:     (evil-collection-embark-setup))
22:   (with-eval-after-load 'epa
23:     (evil-collection-epa-setup))
24:   (with-eval-after-load 'nov
25:     (evil-collection-nov-setup))
26:   (with-eval-after-load 'eww
27:     (evil-collection-eww-setup)))

evil-terminal-cursor-changer

Changing the cursor shape in terminal4.

1: (unless (display-graphic-p)
2:   (use-package evil-terminal-cursor-changer
3:     :ensure t
4:     :config
5:     (evil-terminal-cursor-changer-activate)))

evil-args

Motions and text objects for delimited arguments in Evil5.

 1: (use-package evil-args
 2:   :after evil
 3:   :ensure t
 4:   :hook (emacs-lisp-mode . +config/evil-args-lisp)
 5:   :config
 6:   (define-key evil-inner-text-objects-map "a" 'evil-inner-arg)
 7:   (define-key evil-outer-text-objects-map "a" 'evil-outer-arg)
 8:   (define-key evil-normal-state-map "L" 'evil-forward-arg)
 9:   (define-key evil-normal-state-map "H" 'evil-backward-arg)
10:   (define-key evil-motion-state-map "L" 'evil-forward-arg)
11:   (define-key evil-motion-state-map "H" 'evil-backward-arg)
12:   (define-key evil-normal-state-map "K" 'evil-jump-out-args)
13:   (defun +config/evil-args-lisp ()
14:     (setq-local evil-args-delimiters '(" "))))

evil-easymotion

⏩ A port of vim easymotion to Emacs' evil-mode6.

 1: (use-package evil-easymotion
 2:   :after evil
 3:   :ensure t
 4:   :demand t
 5:   :commands evilem-create evilem-default-keybindings
 6:   :config
 7:   (evilem-default-keybindings "gs")
 8:   (evilem-make-motion evilem-motion-search-next #'evil-ex-search-next
 9:                       :bind ((evil-ex-search-highlight-all nil)))
10:   (evilem-make-motion evilem-motion-search-previous #'evil-ex-search-previous
11:                       :bind ((evil-ex-search-highlight-all nil)))
12:   (evilem-make-motion evilem-motion-search-word-forward #'evil-ex-search-word-forward
13:                       :bind ((evil-ex-search-highlight-all nil)))
14:   (evilem-make-motion evilem-motion-search-word-backward #'evil-ex-search-word-backward
15:                       :bind ((evil-ex-search-highlight-all nil)))
16:   (put 'visible 'bounds-of-thing-at-point (lambda () (cons (window-start) (window-end))))
17:   (evilem-make-motion evilem-motion-forward-word-begin #'evil-forward-word-begin :scope 'visible)
18:   (evilem-make-motion evilem-motion-forward-WORD-begin #'evil-forward-WORD-begin :scope 'visible)
19:   (evilem-make-motion evilem-motion-forward-word-end #'evil-forward-word-end :scope 'visible)
20:   (evilem-make-motion evilem-motion-forward-WORD-end #'evil-forward-WORD-end :scope 'visible)
21:   (evilem-make-motion evilem-motion-backward-word-begin #'evil-backward-word-begin :scope 'visible)
22:   (evilem-make-motion evilem-motion-backward-WORD-begin #'evil-backward-WORD-begin :scope 'visible)
23:   (evilem-make-motion evilem-motion-backward-word-end #'evil-backward-word-end :scope 'visible)
24:   (evilem-make-motion evilem-motion-backward-WORD-end #'evil-backward-WORD-end :scope 'visible))

evil-surround

This package emulates surround.vim7.

1: (use-package evil-surround
2:   :after evil
3:   :ensure t
4:   :commands (global-evil-surround-mode
5:              evil-surround-edit
6:              evil-Surround-edit
7:              evil-surround-region)
8:   :config (global-evil-surround-mode 1))

evil-embrace

Evil integration ofembrace.el8.

 1: (use-package evil-embrace
 2:   :after evil evil-surround
 3:   :ensure t
 4:   :commands embrace-add-pair embrace-add-pair-regexp
 5:   :hook (LaTeX-mode . embrace-LaTeX-mode-hook)
 6:   :hook (org-mode . embrace-org-mode-hook)
 7:   :hook (ruby-mode . embrace-ruby-mode-hook)
 8:   :hook (emacs-lisp-mode . embrace-emacs-lisp-mode-hook)
 9:   :init
10:   (with-eval-after-load 'evil-surround
11:     (evil-embrace-enable-evil-surround-integration))
12:   :config
13:   (setq evil-embrace-show-help-p nil))

evil-traces

Some evil-ex command previews9.

1: (use-package evil-traces
2:   :ensure t
3:   :after evil-ex
4:   :config
5:   (evil-traces-mode))

evil-visualstar

Start a * or # search from the visual selection10.

 1: (use-package evil-visualstar
 2:   :after evil
 3:   :ensure t
 4:   :commands (evil-visualstar/begin-search
 5:              evil-visualstar/begin-search-forward
 6:              evil-visualstar/begin-search-backward)
 7:   :init
 8:   (evil-define-key* 'visual 'global
 9:     "*" #'evil-visualstar/begin-search-forward
10:     "#" #'evil-visualstar/begin-search-backward))

exato

🔖 EXATO: Evil XML Attributes Text Object11.

1: (use-package exato
2:   :ensure t
3:   :after evil
4:   :demand t
5:   :commands evil-outer-xml-attr evil-inner-xml-attr)

evil-multiedit

Multiple cursors for evil-mode, based on iedit12.

 1: (use-package evil-multiedit
 2:   :after evil
 3:   :ensure t
 4:   :demand t
 5:   :config
 6:   (evil-ex-define-cmd "ie[dit]" 'evil-multiedit-ex-match)
 7:   (evil-multiedit-mode)
 8:   (evil-multiedit-default-keybinds)
 9:   ;; (with-eval-after-load 'general
10:   ;;   (general-define-key
11:   ;;    :keymaps 'evil-multiedit-state-map
12:   ;;    "RET" 'evil-multiedit-toggle-or-restrict-region)
13:   ;;   (general-mmap
14:   ;;    :keymaps 'evil-motion-state-map
15:   ;;    "RET" 'evil-multiedit-toggle-or-restrict-region)
16:   ;;   (general-define-key
17:   ;;    :keymaps '(evil-multiedit-state-map evil-multiedit-insert-state-map)
18:   ;;    "C-n" 'evil-multiedit-next
19:   ;;    "C-p" 'evil-multiedit-prev)
20:   ;;   (general-vmap
21:   ;;    :keymaps 'evil-visual-state-map
22:   ;;    "R" 'evil-multiedit-match-all)
23:   ;;   (general-nmap
24:   ;;    :keymaps 'evil-normal-state-map
25:   ;;    "M-d" 'evil-multiedit-match-and-next
26:   ;;    "M-D" 'evil-multiedit-match-and-prev)
27:   ;;   (general-vmap
28:   ;;    :keymaps 'evil-visual-state-map
29:   ;;    "M-d" 'evil-multiedit-match-and-next
30:   ;;    "M-D" 'evil-multiedit-match-and-prev
31:   ;;    "C-M-D" 'evil-multiedit-restore)
32:   ;;   (general-iemap
33:   ;;    :keymaps 'evil-insert-state-map
34:   ;;    "M-d" 'evil-multiedit-toggle-marker-here))
35:   )

UI

which-key

Emacs package that displays available keybindings in popup13. 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))

nerd-icons

(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"))

all-the-icons

A utility package to collect various Icon Fonts and propertize them within Emacs14.

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).

doom-themes

A megapack of themes for GNU Emacs15. 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

A fancy and fast mode-line inspired by minimalism design16. I'm using their themes, why not the modeline as well?

1: (use-package doom-modeline
2:   :ensure
3:   :hook (after-init . doom-modeline-mode))

dashboard

An extensible emacs dashboard17.

emacs-dashboard.png

Figure 1: Emacs dashboard

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:   :config
 6:   (dashboard-setup-startup-hook)
 7:   (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))
 8:         ;;dashboard-banner-logo-title (format "Welcome, %s" user-full-name)
 9:         dashboard-items '((recents . 3)
10:                           (bookmarks . 2)
11:                           (projects . 5)
12:                           (agenda . 8)
13:                           (registers . 2))
14:         dashboard-projects-switch-function 'projectile-persp-switch-project
15:         dashboard-week-agenda t
16:         dashboard-filter-agenda-entry nil
17:         dashboard-startup-banner 'logo
18:         dashboard-center-content t
19:         dashboard-vertically-center-content t
20:         ;; dashboard-icon-type 'all-the-icons
21:         dashboard-display-icons-p t
22:         dashboard-set-heading-icons t
23:         dashboard-set-file-icons t
24:         dashboard-agenda-sort-strategy
25:         '(todo-state-up time-down priority-down todo-state-down time-up priority-up)
26:         ))

tab-bar   builtin disabled

Although I used Perspective more, there are some cases where it's easier with tabs. And the default UI for the tabs is not that great.

1: (use-package tab-bar
2:   :init
3:   (setq tab-bar-show 1
4:         tab-bar-close-button-show nil
5:         tab-bar-tab-hints t
6:         tab-bar-new-button-show nil
7:         tab-bar-separator " "
8:         tab-bar-auto-width nil
9:         tab-bar-position t))
 1: (use-package frame
 2:   :init
 3:   (blink-cursor-mode 1)
 4:   :config
 5:   (cond
 6:    ((find-font (font-spec :family "OverpassM Nerd Font Mono"))
 7:     (set-frame-font "OverpassM Nerd Font Mono 10" nil t))
 8:    ((find-font (font-spec :family "Ubuntu Mono"))
 9:     (set-frame-font "Ubuntu Mono 10" nil t))
10:    ((find-font (font-spec :family "Fira Code Retina"))
11:     (set-frame-font "Fira Code Retina 10" nil t))
12:    ((find-font (font-spec :family "Source Code Pro"))
13:     (set-frame-font "Source Code Pro 10" nil t))
14:    ((find-font (font-spec :family "DejaVu Sans Mono"))
15:     (set-frame-font "DejaVu Sans Mono 10" nil t))))

window   builtin disabled

1: (use-package window
2:   :config
3:   (setq split-width-threshold 160))

display-line-number   builtin disabled

1: (use-package display-line-numbers
2:   :init
3:   (setq display-line-numbers-type t)
4:   :hook (prog-mode . display-line-numbers-mode)
5:   :custom
6:   (display-line-numbers-grow-only t))

help-at-pt   builtin disabled

1: (use-package help-at-pt
2:   :custom
3:   (help-at-pt-display-when-idle t))

hidehow   builtin disabled

1: (use-package hideshow
2:   :hook (prog-mode . hs-minor-mode))

uniquify   builtin disabled

1: (use-package uniquify
2:   :ensure nil
3:   :config
4:   (setq uniquify-buffer-name-style 'forward
5:         uniquify-separator " • "
6:         uniquify-after-kill-buffer-p t
7:         uniquify-ignore-buffers-re "^\\*"))

speedbar   builtin disabled

 1: (use-package speedbar
 2:   :custom
 3:   (speedbar-use-images nil)
 4:   (speedbar-update-flag t)
 5:   (speedbar-frame-parameters '((name . "speedbar")
 6:                                (title . "speedbar")
 7:                                (minibuffer . nil)
 8:                                (border-width . 2)
 9:                                (menu-bar-lines . 0)
10:                                (tool-bar-lines . 0)
11:                                (unsplittable . t)
12:                                (left-fringe . 10)))
13:   :config
14:   (speedbar-add-supported-extension
15:    (list
16:   ;;;; General Lisp Languages
17:     ".cl"
18:     ".li?sp"
19:   ;;;; Lua/Fennel (Lisp that transpiles to lua)
20:     ".lua"
21:     ".fnl"
22:     ".fennel"
23:   ;;;; JVM languages (Java, Kotlin, Clojure)
24:     ".kt"
25:     ".mvn"
26:     ".gradle"
27:     ".properties"
28:     ".cljs?"
29:   ;;;; shellscript
30:     ".sh"
31:     ".bash"
32:   ;;;; Web Languages and Markup/Styling
33:     ".php"
34:     ".ts"
35:     ".html?"
36:     ".css"
37:     ".less"
38:     ".scss"
39:     ".sass"
40:   ;;;; Makefile
41:     "makefile"
42:     "MAKEFILE"
43:     "Makefile"
44:   ;;;; Data formats
45:     ".json"
46:     ".yaml"
47:     ".toml"
48:   ;;;; Notes and Markup
49:     ".md"
50:     ".markdown"
51:     ".org"
52:     ".txt"
53:     "README")))

winner   builtin disabled

1: (use-package winner
2:   :init
3:   (winner-mode 1))

time   builtin disabled

1: (use-package time
2:   :hook (after-init . display-time-mode)
3:   :config
4:   (when (file-directory-p (expand-file-name ".mail" (getenv "HOME")))
5:     (setq display-time-mail-directory (expand-file-name ".mail" (getenv "HOME"))))
6:   :custom
7:   (display-time-24hr-format t)
8:   (display-time-day-and-date t))

paren   builtin

1: (use-package paren
2:   :config
3:   (show-paren-mode 1)
4:   :custom
5:   (show-paren-style 'mixed))

hl-line   builtin

1: (use-package hl-line
2:   :config
3:   (global-hl-line-mode 1))

font-core   builtin

1: (use-package font-core
2:   :init
3:   (global-font-lock-mode t))

menu-bar, tool-bar, and scroll-bar   builtin

 1: (use-package menu-bar
 2:   :init
 3:   (menu-bar-mode -1))
 4: 
 5: (use-package tool-bar
 6:   :init
 7:   (tool-bar-mode -1))
 8: 
 9: (use-package scroll-bar
10:   :init
11:   (scroll-bar-mode -1))

xt-mouse   builtin disabled

1: (use-package xt-mouse
2:   :config
3:   (xterm-mouse-mode 1))

avy   builtin disabled

 1: (use-package avy
 2:   :after evil
 3:   :ensure ;; when `use-package-always-ensure' is nil
 4:   :bind
 5:   (([remap goto-char] . evil-avy-goto-char)
 6:    ([remap goto-line] . evil-avy-goto-line)
 7:    ("M-g l" . evil-avy-goto-line))
 8:   :config
 9:   ;; (evil-define-key 'normal 'global (kbd "<localleader>gc") 'evil-avy-goto-char)
10:   ;; (evil-define-key 'normal 'global (kbd "<localleader>gl") 'evil-avy-goto-line-below)
11:   ;; (evil-define-key 'normal 'global (kbd "<localleader>gL") 'evil-avy-goto-line-above)
12:   )

tabify   builtin

1: (use-package tabify
2:   :ensure nil
3:   :config
4:   (setq tabify-regexp "^\t* [ \t]+"))

rainbow-mode, rainbow-identifiers, and rainbow-delimiters

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))

nerd-fonts   disabled

This package still not available at Melpa, so I have to clone it as a submodule.

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)

helpful   disabled

Since Emacs is a self-documenting editor18. It's certainly nice to have a more contextual help buffers.

helpful_source.png

Figure 2: Helpful will also show the source code when available

helpful_docstring.png

Figure 3: more prettier docstring

helpful_bindings.png

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:   :config
10:   (with-eval-after-load 'general
11:     (general-define-key
12:      "C-h F" 'helpful-function
13:      :keymaps 'prog-mode-map
14:      "C-c C-d" 'helpful-at-point)
15:     (general-nvmap
16:       :keymaps 'prog-mode-map
17:       "K" '(helpful-at-point :wk "helpful at point")
18:       "gr" '(helpful-update :wk "update"))))

Builtin

I have these builtin packages loaded, I would like to investigate them one by one, gradually removing those I don't really need.

byte compilation   builtin

1: (use-package bytecomp
2:   :custom
3:   (byte-compile-warnings nil))

Base configuration   builtin

 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))

saveplace   builtin

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   builtin

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   builtin

 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)))

prog-mode   builtin

 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:           ("=>" . "⇒"))))

select   builtin

1: (use-package select
2:   :custom
3:   (select-enable-clipboard t))

Compression mode   builtin

1: (use-package jka-cmpr-hook
2:   :custom
3:   (auto-compression-mode t))

recentf   builtin

 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")))))))

eldoc   builtin

1: (use-package eldoc
2:   :hook ((prog-mode . eldoc-mode)
3:          (emacs-lisp-mode . eldoc-mode)
4:          (lisp-interaction-mode . eldoc-mode)))

bookmark   builtin

1: (use-package bookmark
2:   :custom
3:   (bookmark-save-flag 1)
4:   (bookmark-default-file (expand-file-name ".bookmark" user-emacs-directory)))

executable   builtin

1: (use-package executable
2:   :hook
3:   (after-save . executable-make-buffer-file-executable-if-script-p))

files   builtin

 1: (use-package files
 2:   :config
 3:   (defun full-auto-save ()
 4:     (interactive)
 5:     (save-excursion
 6:       (dolist (buf (buffer-list))
 7:         (set-buffer buf)
 8:         (if (and (buffer-file-name) (buffer-modified-p))
 9:             (basic-save-buffer)))))
10:   (add-hook 'auto-save-hook 'full-auto-save)
11:   (nconc
12:    auto-mode-alist
13:    '(("/LICENSE\\'" . text-mode)
14:      ("\\.log\\'" . text-mode)
15:      ("rc\\'" . conf-mode)
16:      ("\\.\\(?:hex\\|nes\\)\\'" . hexl-mode)))
17:   :custom
18:   (confirm-kill-emacs #'yes-or-no-p)
19:   (confirm-kill-processes nil)
20:   (revert-without-query (list "."))
21:   (find-file-visit-truename t)
22:   (version-control t)
23:   (backup-by-copying t)
24:   (delete-old-versions t)
25:   (kept-new-versions 6)
26:   (kept-old-versions 2)
27:   (auto-save-include-big-deletions t)
28:   (auto-save-list-file-prefix (expand-file-name ".autosave/" user-emacs-directory))
29:   (backup-directory-alist `(("." . ,(expand-file-name ".backup" user-emacs-directory))))
30:   (auto-mode-case-fold nil)
31:   (require-final-newline t))

tramp   builtin

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)))

ffap   builtin

1: (use-package ffap
2:   :custom
3:   (ffap-machine-p-known 'reject))

epg-config   builtin

1: (use-package epg-config
2:   :custom
3:   (epg-pinentry-mode 'loopback))

make-mode   builtin

1: (use-package make-mode
2:   :config
3:   (add-hook 'makefile-mode-hook 'indent-tabs-mode))

ispell   builtin

 1: (use-package ispell
 2:   :defer
 3:   :custom
 4:   (ispell-program-name "hunspell")
 5:   (ispell-dictionary "english")
 6:   (ispell-really-hunspell t)
 7:   :config
 8:   (with-eval-after-load 'ispell
 9:     (when (executable-find ispell-program-name)
10:       (add-hook 'text-mode-hook #'flyspell-mode)
11:       (add-hook 'prog-mode-hook #'flyspell-prog-mode)))
12:   (add-to-list 'ispell-skip-region-alist
13:                '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:"))
14:   (add-to-list 'ispell-skip-region-alist
15:                '("#\\+BEGIN_SRC" . "#\\+END_SRC"))
16:   (add-to-list 'ispell-skip-region-alist
17:                '("#\\+begin_src" . "#\\+end_src"))
18:   (add-to-list 'ispell-skip-region-alist
19:                '("#\\+begin_example" . "#\\+end_example"))
20:   (add-to-list 'ispell-skip-region-alist
21:                '("#\\+BEGIN_EXAMPLE" . "#\\+END_EXAMPLE"))
22:   (let ((hunspell-en_us-path (expand-file-name "/usr/share/hunspell/en_US-large.aff" (getenv "HOME")))
23:         (hunspell-en_GB-path (expand-file-name "/usr/share/hunspell/en_GB-large.aff" (getenv "HOME")))
24:         (hunspell-id_ID-path (expand-file-name "/usr/share/hunspell/id_ID.aff" (getenv "HOME"))))
25:     (when (file-exists-p hunspell-en_us-path)
26:       (add-to-list 'ispell-hunspell-dict-paths-alist
27:                    `("american" ,hunspell-en_us-path)))
28:     (when (file-exists-p hunspell-en_GB-path)
29:       (add-to-list 'ispell-hunspell-dict-paths-alist
30:                    `("english" ,hunspell-en_GB-path)))
31:     (when (file-exists-p hunspell-id_ID-path)
32:       (add-to-list 'ispell-hunspell-dict-paths-alist
33:                    `("id_ID" ,hunspell-id_ID-path)))))

whitespace   builtin disabled

1: (use-package whitespace
2:   :hook (((prog-mode text-mode conf-mode) . whitespace-mode)
3:          (before-save . whitespace-cleanup))
4:   :custom
5:   (whitespace-style '(face empty trailing tab-mark
6:                            indentation::space))
7:   (whitespace-action '(warn-if-read-only))
8:   :config
9:   (global-whitespace-mode))

subword   builtin

1: (use-package subword
2:   :init
3:   (global-subword-mode 1))

ediff   builtin

1: (use-package ediff
2:   :config
3:   (setq ediff-diff-options "-w"
4:         ediff-split-window-function 'split-window-horizontally
5:         ediff-window-setup-function 'ediff-setup-windows-plain))

delsel   builtin

1: (use-package delsel
2:   :init
3:   (delete-selection-mode))

text-mode   builtin

1: (use-package text-mode
2:   :ensure nil
3:   :config
4:   (setq-default sentence-end-double-space nil))

flyspell   builtin disabled

1: (use-package flyspell
2:   :custom
3:   (flyspell-issue-welcome-flag nil)
4:   (flyspell-issue-message-flag nil)
5:   :hook (((org-mode message-mode TeX-mode rst-mode mu4e-composer-mode git-commit-mode text-mode)
6:           . flyspell-mode)
7:          (prog-mode . flyspell-prog-mode)))

flymake   builtin disabled

1: (use-package flymake
2:   :hook (prog-mode . flymake-mode))

imenu   builtin

1: (use-package imenu
2:   :custom
3:   (imenu-auto-rescan t))

simple   builtin

 1: (use-package simple
 2:   :hook ((makefile-mode . indent-tabs-mode)
 3:          (text-mode . visual-line-mode))
 4:   :init
 5:   (transient-mark-mode t)
 6:   :custom
 7:   (save-interprogram-paste-before-kill t)
 8:   (shift-select-mode nil)
 9:   (kill-do-not-save-duplicates t)
10:   (shift-select-mode nil)
11:   (set-mark-command-repeat-pop t)
12:   (indent-tabs-mode nil)
13:   (column-number-mode t)
14:   (idle-update-delay 1.0)
15:   :config
16:   (with-eval-after-load 'evil
17:     (evil-set-initial-state #'message-mode 'insert)))

elec-pair   builtin disabled

1: (use-package elec-pair
2:   :init
3:   (electric-pair-mode -1))

xref

 1: (use-package xref
 2:   :ensure nil
 3:   :config
 4:   (with-eval-after-load 'general
 5:     (general-nvmap
 6:      :keymaps 'prog-mode-map
 7:      "M-." 'xref-find-definitions
 8:      "M-?" 'xref-find-references)
 9:     (general-iemap
10:      :keymaps 'prog-mode-map
11:      "M-." 'xref-find-definitions
12:      "M-?" 'xref-find-references)))

server   builtin

(use-package server
  :config
  (unless (server-running-p)
    (server-start))
  (require 'org-protocol))

Completion

vertico

  • Basic configuration
     1: (use-package vertico
     2:   :init
     3:   (vertico-mode)
     4:   ;; Different scroll margin
     5:   ;; (setq vertico-scroll-margin 0)
     6:   ;; Show more candidates
     7:   ;; (setq vertico-count 20)
     8:   ;; Grow and shrink the Vertico minibuffer
     9:   ;; (setq vertico-resize t)
    10:   ;; Optionally enable cycling for `vertico-next' and `vertico-previous'.
    11:   (setq vertico-cycle t)
    12:   )
    13: 
    14: ;; A few more useful configurations...
    15: (use-package emacs
    16:   :init
    17:   ;; Add prompt indicator to `completing-read-multiple'.
    18:   ;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.
    19:   (defun crm-indicator (args)
    20:     (cons (format "[CRM%s] %s"
    21:                   (replace-regexp-in-string
    22:                    "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
    23:                    crm-separator)
    24:                   (car args))
    25:           (cdr args)))
    26:   (advice-add #'completing-read-multiple :filter-args #'crm-indicator)
    27:   ;; Do not allow the cursor in the minibuffer prompt
    28:   (setq minibuffer-prompt-properties
    29:         '(read-only t cursor-intangible t face minibuffer-prompt))
    30:   (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
    31:   ;; Support opening new minibuffers from inside existing minibuffers.
    32:   (setq enable-recursive-minibuffers t)
    33:   ;; Emacs 28 and newer: Hide commands in M-x which do not work in the current
    34:   ;; mode.  Vertico commands are hidden in normal buffers. This setting is
    35:   ;; useful beyond Vertico.
    36:   (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-indexed   disabled
        1: (use-package vertico-indexed
        2:   :after vertico
        3:   :ensure nil
        4:   :config
        5:   (vertico-indexed-mode))
        
      • 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)))
        

marginalia   disabled

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))

nerd-icons-completion   disabled

1: (use-package nerd-icons-completion
2:   :ensure
3:   :hook (marginalia-mode . nerd-icons-completion-marginalia-setup)
4:   :config
5:   (nerd-icons-completion-mode))

orderless

  • Basic Configuration
    1: (use-package orderless
    2:   :init
    3:   ;; Configure a custom style dispatcher (see the Consult wiki)
    4:   ;; (setq orderless-style-dispatchers '(+orderless-consult-dispatch orderless-affix-dispatch)
    5:   ;;       orderless-component-separator #'orderless-escapable-split-on-space)
    6:   (setq completion-styles '(orderless basic)
    7:         completion-category-defaults nil
    8:         completion-category-overrides '((file (styles partial-completion)))))
    

consult   disabled

  1: (use-package consult
  2:   :ensure
  3:   ;; Replace bindings. Lazily loaded due by `use-package'.
  4:   :bind (;; C-c bindings in `mode-specific-map'
  5:          ("C-c M-x" . consult-mode-command)
  6:          ("C-c h" . consult-history)
  7:          ("C-c k" . consult-kmacro)
  8:          ("C-c m" . consult-man)
  9:          ("C-c i" . consult-info)
 10:          ([remap Info-search] . consult-info)
 11:          ;; C-x bindings in `ctl-x-map'
 12:          ("C-x M-:" . consult-complex-command)     ;; orig. repeat-complex-command
 13:          ("C-x b" . consult-buffer)                ;; orig. switch-to-buffer
 14:          ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
 15:          ("C-x 5 b" . consult-buffer-other-frame)  ;; orig. switch-to-buffer-other-frame
 16:          ("C-x t b" . consult-buffer-other-tab)    ;; orig. switch-to-buffer-other-tab
 17:          ("C-x r b" . consult-bookmark)            ;; orig. bookmark-jump
 18:          ("C-x p b" . consult-project-buffer)      ;; orig. project-switch-to-buffer
 19:          ;; Custom M-# bindings for fast register access
 20:          ("M-#" . consult-register-load)
 21:          ("M-'" . consult-register-store)          ;; orig. abbrev-prefix-mark (unrelated)
 22:          ("C-M-#" . consult-register)
 23:          ;; Other custom bindings
 24:          ("M-y" . consult-yank-pop)                ;; orig. yank-pop
 25:          ;; M-g bindings in `goto-map'
 26:          ("M-g e" . consult-compile-error)
 27:          ("M-g f" . consult-flymake)               ;; Alternative: consult-flycheck
 28:          ("M-g g" . consult-goto-line)             ;; orig. goto-line
 29:          ("M-g M-g" . consult-goto-line)           ;; orig. goto-line
 30:          ("M-g o" . consult-outline)               ;; Alternative: consult-org-heading
 31:          ("M-g m" . consult-mark)
 32:          ("M-g k" . consult-global-mark)
 33:          ("M-g i" . consult-imenu)
 34:          ("M-g I" . consult-imenu-multi)
 35:          ;; M-s bindings in `search-map'
 36:          ("M-s d" . consult-find)                  ;; Alternative: consult-fd
 37:          ("M-s c" . consult-locate)
 38:          ("M-s g" . consult-grep)
 39:          ("M-s G" . consult-git-grep)
 40:          ("M-s r" . consult-ripgrep)
 41:          ("M-s l" . consult-line)
 42:          ("M-s L" . consult-line-multi)
 43:          ("M-s k" . consult-keep-lines)
 44:          ("M-s u" . consult-focus-lines)
 45:          ;; Isearch integration
 46:          ("M-s e" . consult-isearch-history)
 47:          :map isearch-mode-map
 48:          ("M-e" . consult-isearch-history)         ;; orig. isearch-edit-string
 49:          ("M-s e" . consult-isearch-history)       ;; orig. isearch-edit-string
 50:          ("M-s l" . consult-line)                  ;; needed by consult-line to detect isearch
 51:          ("M-s L" . consult-line-multi)            ;; needed by consult-line to detect isearch
 52:          ;; Minibuffer history
 53:          :map minibuffer-local-map
 54:          ("M-s" . consult-history)                 ;; orig. next-matching-history-element
 55:          ("M-r" . consult-history))                ;; orig. previous-matching-history-element
 56:   ;; Enable automatic preview at point in the *Completions* buffer. This is
 57:   ;; relevant when you use the default completion UI.
 58:   :hook (completion-list-mode . consult-preview-at-point-mode)
 59:   ;; The :init configuration is always executed (Not lazy)
 60:   :init
 61:   ;; Optionally configure the register formatting. This improves the register
 62:   ;; preview for `consult-register', `consult-register-load',
 63:   ;; `consult-register-store' and the Emacs built-ins.
 64:   (setq register-preview-delay 0.5
 65:         register-preview-function #'consult-register-format)
 66:   ;; Optionally tweak the register preview window.
 67:   ;; This adds thin lines, sorting and hides the mode line of the window.
 68:   (advice-add #'register-preview :override #'consult-register-window)
 69:   ;; Use Consult to select xref locations with preview
 70:   (setq xref-show-xrefs-function #'consult-xref
 71:         xref-show-definitions-function #'consult-xref)
 72:   ;; Configure other variables and modes in the :config section,
 73:   ;; after lazily loading the package.
 74:   :config
 75:   ;; Optionally configure preview. The default value
 76:   ;; is 'any, such that any key triggers the preview.
 77:   ;; (setq consult-preview-key 'any)
 78:   ;; (setq consult-preview-key "M-.")
 79:   ;; (setq consult-preview-key '("S-<down>" "S-<up>"))
 80:   ;; For some commands and buffer sources it is useful to configure the
 81:   ;; :preview-key on a per-command basis using the `consult-customize' macro.
 82:   (consult-customize
 83:    consult-theme :preview-key '(:debounce 0.2 any)
 84:    consult-ripgrep consult-git-grep consult-grep
 85:    consult-bookmark consult-recent-file consult-xref
 86:    consult--source-bookmark consult--source-file-register
 87:    consult--source-recent-file consult--source-project-recent-file
 88:    ;; :preview-key "M-."
 89:    :preview-key '(:debounce 0.4 any))
 90:   ;; Optionally configure the narrowing key.
 91:   ;; Both < and C-+ work reasonably well.
 92:   (setq consult-narrow-key "<") ;; "C-+"
 93:   ;; Optionally make narrowing help available in the minibuffer.
 94:   ;; You may want to use `embark-prefix-help-command' or which-key instead.
 95:   ;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help)
 96: 
 97:   ;; By default `consult-project-function' uses `project-root' from project.el.
 98:   ;; Optionally configure a different project root function.
 99:   ;;;; 1. project.el (the default)
100:   ;; (setq consult-project-function #'consult--default-project--function)
101:   ;;;; 2. vc.el (vc-root-dir)
102:   ;; (setq consult-project-function (lambda (_) (vc-root-dir)))
103:   ;;;; 3. locate-dominating-file
104:   ;; (setq consult-project-function (lambda (_) (locate-dominating-file "." ".git")))
105:   ;;;; 4. projectile.el (projectile-project-root)
106:   ;; (autoload 'projectile-project-root "projectile")
107:   ;; (setq consult-project-function (lambda (_) (projectile-project-root)))
108:   ;;;; 5. No project support
109:   ;; (setq consult-project-function nil)
110:   )

corfu   disabled

 1: (use-package corfu
 2:   :ensure t
 3:   ;; Optional customizations
 4:   :hook ((eshell-mode . (lambda ()
 5:                           (setq-local corfu-auto nil)
 6:                           (corfu-mode))))
 7:   :custom
 8:   (corfu-cycle t)                ;; Enable cycling for `corfu-next/previous'
 9:   (corfu-auto t)                 ;; Enable auto completion
10:   ;; (corfu-separator ?\s)          ;; Orderless field separator
11:   ;; (corfu-quit-at-boundary nil)   ;; Never quit at completion boundary
12:   (corfu-quit-no-match 'separator)      ;; Never quit, even if there is no match
13:   ;; (corfu-quit-no-match nil)      ;; Never quit, even if there is no match
14:   ;; (corfu-preview-current nil)    ;; Disable current candidate preview
15:   (corfu-preselect 'prompt)      ;; Preselect the prompt
16:   ;; (corfu-on-exact-match nil)     ;; Configure handling of exact matches
17:   ;; (corfu-scroll-margin 5)        ;; Use scroll margin
18: 
19:   ;; Enable Corfu only for certain modes.
20:   ;; :hook ((prog-mode . corfu-mode)
21:   ;;        (shell-mode . corfu-mode)
22:   ;;        (eshell-mode . corfu-mode))
23: 
24:   ;; Recommended: Enable Corfu globally.  This is recommended since Dabbrev can
25:   ;; be used globally (M-/).  See also the customization variable
26:   ;; `global-corfu-modes' to exclude certain modes.
27:   :init
28:   (global-corfu-mode)
29:   :bind
30:   (:map corfu-map
31:         ("TAB" . corfu-next)
32:         ([tab] . corfu-next)
33:         ("S-TAB" . corfu-previous)
34:         ([backtab] . corfu-previous)))

nerd-icons-corfu   disabled

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))))

embark   disabled

 1: (use-package embark
 2:   :ensure
 3:   :bind (("C-." . embark-act)
 4:          ("M-." . embark-dwim)
 5:          ("C-h B" . embark-bindings))
 6:   :init
 7:   (setq prefix-help-command #'embark-prefix-help-command)
 8:   (add-hook 'eldoc-documentation-functions #'embark-eldoc-first-target)
 9:   (setq eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly)
10:   :config
11:   (add-to-list 'display-buffer-alist
12:                '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
13:                  nil
14:                  (window-parameters (mode-line-format . none))))
15:   :general
16:   (general-define-key
17:    :keymaps 'override
18:    "C-." 'embark-act
19:    "M-." 'embark-dwim
20:    "C-h B" 'embark-bindings)
21:   (general-iemap
22:     :keymaps 'override
23:     "C-." 'embark-act
24:     "M-." 'embark-dwim
25:     "C-h B" 'embark-bindings)
26:   (+config/leader-key
27:     "." 'embark-act
28:     "M-." 'embark-dwim))

embark-consult   disabled

1: (use-package embark-consult
2:   :ensure t ; only need to install it, embark loads it after consult if found
3:   :hook
4:   (embark-collect-mode . consult-preview-at-point-mode))

cape   disabled

 1: ;; Add extensions
 2: (use-package cape
 3:   :ensure
 4:   ;; Bind dedicated completion commands
 5:   ;; Alternative prefix keys: C-c p, M-p, M-+, ...
 6:   :bind (("C-c p p" . completion-at-point) ;; capf
 7:          ("C-c p t" . complete-tag)        ;; etags
 8:          ("C-c p d" . cape-dabbrev)        ;; or dabbrev-completion
 9:          ("C-c p h" . cape-history)
10:          ("C-c p f" . cape-file)
11:          ("C-c p k" . cape-keyword)
12:          ("C-c p s" . cape-elisp-symbol)
13:          ("C-c p e" . cape-elisp-block)
14:          ("C-c p a" . cape-abbrev)
15:          ("C-c p l" . cape-line)
16:          ("C-c p w" . cape-dict)
17:          ("C-c p :" . cape-emoji)
18:          ("C-c p \\" . cape-tex)
19:          ("C-c p _" . cape-tex)
20:          ("C-c p ^" . cape-tex)
21:          ("C-c p &" . cape-sgml)
22:          ("C-c p r" . cape-rfc1345))
23:   :init
24:   ;; Add to the global default value of `completion-at-point-functions' which is
25:   ;; used by `completion-at-point'.  The order of the functions matters, the
26:   ;; first function returning a result wins.  Note that the list of buffer-local
27:   ;; completion functions takes precedence over the global list.
28:   ;; (add-to-list 'completion-at-point-functions #'cape-dabbrev)
29:   (add-to-list 'completion-at-point-functions #'cape-file)
30:   (add-to-list 'completion-at-point-functions #'cape-elisp-block)
31:   ;;(add-to-list 'completion-at-point-functions #'cape-history)
32:   ;;(add-to-list 'completion-at-point-functions #'cape-keyword)
33:   ;;(add-to-list 'completion-at-point-functions #'cape-tex)
34:   ;;(add-to-list 'completion-at-point-functions #'cape-sgml)
35:   ;;(add-to-list 'completion-at-point-functions #'cape-rfc1345)
36:   ;;(add-to-list 'completion-at-point-functions #'cape-abbrev)
37:   ;;(add-to-list 'completion-at-point-functions #'cape-dict)
38:   (add-to-list 'completion-at-point-functions #'cape-elisp-symbol)
39:   ;;(add-to-list 'completion-at-point-functions #'cape-line)
40:   )

tempel   disabled

 1: (use-package tempel
 2:   :ensure
 3:   :custom
 4:   (tempel-trigger-prefix "<")
 5:   :bind (("M-+" . tempel-complete)
 6:          ("M-*" . tempel-insert))
 7:   :init
 8:   (defun tempel-setup-capf ()
 9:     ;; Add the Tempel Capf to `completion-at-point-functions'.
10:     ;; `tempel-expand' only triggers on exact matches. Alternatively use
11:     ;; `tempel-complete' if you want to see all matches, but then you
12:     ;; should also configure `tempel-trigger-prefix', such that Tempel
13:     ;; does not trigger too often when you don't expect it. NOTE: We add
14:     ;; `tempel-expand' *before* the main programming mode Capf, such
15:     ;; that it will be tried first.
16:     (setq-local completion-at-point-functions
17:                 (cons #'tempel-complete
18:                       completion-at-point-functions)))
19: 
20:   (add-hook 'conf-mode-hook 'tempel-setup-capf)
21:   (add-hook 'prog-mode-hook 'tempel-setup-capf)
22:   (add-hook 'text-mode-hook 'tempel-setup-capf)
23:   (add-hook 'prog-mode-hook #'tempel-abbrev-mode))
24: 
25: (when (file-directory-p (expand-file-name "site-lisp/tempel-collection" user-emacs-directory))
26:   (add-to-list 'load-path (expand-file-name "site-lisp/tempel-collection" user-emacs-directory)))
27: 
28: (use-package tempel-collection)

Shell

eshell   builtin

emacs-eshell.png

Figure 5: eshell in action

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   disabled

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   disabled

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   builtin

 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   disabled

 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   disabled

 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))))

fish-mode   disabled

1: (use-package fish-mode
2:   :ensure
3:   :if (executable-find "fish")
4:   :defer t)

fish-completion   disabled

1: (use-package fish-completion
2:   :ensure
3:   :after fish-mode
4:   :config
5:   (setq fish-completion-fallback-on-bash-p t))

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

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:   :hook (eval-expression-minibuffer-setup . turn-on-smartparens-strict-mode)
 6:   :config
 7:   (require 'smartparens-config)
 8:   (show-smartparens-global-mode 1)
 9:   (smartparens-global-mode 1)
10:   ;; Fix usage of ' in Lisp modes
11:   ;; THANKS: https://github.com/Fuco1/smartparens/issues/286#issuecomment-32324743
12:   ;; (eval) is used as a hack to quiet Flycheck errors about (sp-with-modes)
13:   (eval
14:    '(sp-with-modes sp-lisp-modes
15:       ;; disable ', it's the quote character!
16:       (sp-local-pair "'" nil :actions nil)
17:       ;; also only use the pseudo-quote inside strings where it serve as
18:       ;; hyperlink.
19:       (sp-local-pair "`" "'" :when '(sp-in-string-p sp-in-comment-p))
20:       (sp-local-pair "`" nil
21:                      :skip-match (lambda (ms mb me)
22:                                    (cond
23:                                     ((equal ms "'")
24:                                      (or (sp--org-skip-markup ms mb me)
25:                                          (not (sp-point-in-string-or-comment))))
26:                                     (t (not (sp-point-in-string-or-comment))))))))
27:   (sp-with-modes '(html-mode sgml-mode nxml-mode web-mode)
28:     (sp-local-pair "<" ">"))
29:   ;; (with-eval-after-load 'general
30:   ;;   (general-define-key
31:   ;;    :keymaps 'smartparens-mode-map
32:   ;;    "C-M-f" 'sp-forward-sexp
33:   ;;    "C-M-b" 'sp-backward-sexp
34:   ;;    "C-M-d" 'sp-down-sexp
35:   ;;    "C-M-a" 'sp-backward-down-sexp
36:   ;;    "C-S-d" 'sp-beginning-of-sexp
37:   ;;    "C-S-a" 'sp-end-of-sexp
38:   ;;    "C-M-e" 'sp-up-sexp
39:   ;;    "C-M-u" 'sp-backward-up-sexp
40:   ;;    "C-M-t" 'sp-transpose-sexp
41:   ;;    "C-M-k" 'sp-kill-sexp
42:   ;;    "C-M-w" 'sp-copy-sexp
43:   ;;    "M-<delete>" 'sp-unwrap-sexp
44:   ;;    "M-<backspace>" 'sp-backward-unwrap-sexp
45:   ;;    "C-<right>" 'sp-forward-slurp-sexp
46:   ;;    "C-<left>" 'sp-forward-barf-sexp
47:   ;;    "C-M-<left>" 'sp-backward-slurp-sexp
48:   ;;    "C-M-<right>" 'sp-backward-barf-sexp
49:   ;;    "M-D" 'sp-split-sexp
50:   ;;    "C-M-<delete>" 'sp-splice-sexp-killing-forward
51:   ;;    "C-M-<backspace>" 'sp-splice-sexp-killing-backward
52:   ;;    "C-S-<backspace>" 'sp-splice-sexp-killing-around
53:   ;;    "C-]" 'sp-select-next-thing-exchange
54:   ;;    "C-<left_bracket>" 'sp-select-previous-thing
55:   ;;    "C-M-]" 'sp-select-next-thing
56:   ;;    "M-F" 'sp-forward-symbol
57:   ;;    "M-B" 'sp-backward-symbol
58:   ;;    "C-\"" 'sp-change-inner
59:   ;;    "M-i" 'sp-change-enclosing))
60:   )

The keybinding I got from the example configuration messes up my evil-mode. I have them commented for now.

ws-butler   disabled

1: (use-package ws-butler
2:   :ensure
3:   :hook (prog-mode . ws-butler-mode)
4:   :config
5:   (setq ws-butler-convert-leading-tabs-or-spaces t))

activities-mode   disabled

 1: (use-package activities
 2:   :ensure
 3:   :init
 4:   (activities-mode)
 5:   (activities-tabs-mode)
 6:   ;; Prevent `edebug' default bindings from interfering.
 7:   (setq edebug-inhibit-emacs-lisp-mode-bindings t)
 8:   :bind
 9:   (("C-x C-a C-n" . activities-new)
10:    ("C-x C-a C-d" . activities-define)
11:    ("C-x C-a C-a" . activities-resume)
12:    ("C-x C-a C-s" . activities-suspend)
13:    ("C-x C-a C-k" . activities-kill)
14:    ("C-x C-a RET" . activities-switch)
15:    ("C-x C-a b" . activities-switch-buffer)
16:    ("C-x C-a g" . activities-revert)
17:    ("C-x C-a l" . activities-list))
18:   :general
19:   (+config/leader-activities
20:    "C-n" 'activities-new
21:    "C-d" 'activities-define
22:    "C-a" 'activities-resume
23:    "C-s" 'activities-suspend
24:    "C-k" 'activities-kill
25:    "RET" 'activities-switch
26:    "b" 'activities-switch-buffer
27:    "g" 'activities-revert
28:    "l" 'activities-list))

Project

magit

emacs-magit.png

Figure 6: Emacs magit

 1: (use-package magit
 2:   :ensure
 3:   :demand t
 4:   :config
 5:   (evil-set-initial-state #'git-commit-mode 'insert)
 6:   ;; (with-eval-after-load 'general
 7:   ;;   (+config/leader-go
 8:   ;;    "g" 'magit-status))
 9:   :custom
10:   (magit-revision-show-gravatars '("^Author:     " . "^Commit:     "))
11:   (magit-diff-refine-hunk 'all)
12:   (magit-log-arguments '("-n100" "--graph" "--decorate"))
13:   :general
14:   (+config/leader-go
15:     "g" 'magit-status))

projectile

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")))

ripgrep

1: (use-package ripgrep
2:   :ensure
3:   :init
4:   (with-eval-after-load 'evil-collection
5:     (evil-collection-ripgrep-setup)))

diff-hl

emacs-diff-hl-indicator.png

Figure 7: highlighted uncommited changes

 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))
19:   :general
20:   (general-nvmap
21:     :keymaps 'diff-hl-mode-map
22:     "[[" '(diff-hl-previous-hunk :wk "previous hunk" :repeat t :jump t)
23:     "]]" '(diff-hl-next-hunk :wk "next hunk" :repeat t :jump t)))

perspective

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

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

 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

emacs-git-messenger.png

Figure 8: git messenger popup message

 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

1: (use-package git-timemachine
2:   :ensure
3:   :after magit
4:   :general
5:   (+config/leader-go
6:     "Gt" 'git-timemachine-toggle))

magit-todos   disabled

1: (use-package magit-todos
2:   :ensure
3:   :after magit
4:   :hook (magit-mode . magit-todos-mode)
5:   :custom
6:   (magit-todos-group-by
7:    '(magit-todos-item-first-path-component magit-todos-item-keyword magit-todos-item-filename)))

forge   disabled

1: (use-package forge
2:   :after magit
3:   :defer t
4:   :bind ((:map forge-issue-section-map
5:                ("C-c C-v" . forge-browse-topic))
6:          (:map forge-pullreq-section-map
7:                ("C-c C-v" . forge-browse-topic)))
8:   :custom
9:   (forge-add-default-bindings nil))

org-project-capture

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   disabled

emacs-lsp.png

Figure 9: Emacs lsp in action

 1: (use-package lsp-mode
 2:   :ensure
 3:   :diminish (lsp-lens-mode lsp-mode)
 4:   :commands lsp lsp-deferred
 5:   :init
 6:   (setq lsp-keymap-prefix "C-c C-l")
 7:   (defun my/orderless-dispatch-flex-first (_pattern index _total)
 8:     (and (eq index 0) 'orderless-flex))
 9:   (defun my/lsp-mode-setup-completion ()
10:     (setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults))
11:           '(orderless)))
12:   (add-hook 'orderless-style-dispatchers #'my/orderless-dispatch-flex-first nil 'local)
13:   (when (featurep 'cape)
14:     (setq-local completion-at-point-functions (list (cape-capf-buster #'lsp-completion-at-point))))
15:   :hook
16:   (lsp-mode . lsp-enable-which-key-integration)
17:   (lsp-completion-mode . my/lsp-mode-setup-completion)
18:   ((c-mode c++-mode xml-mode
19:            yaml-mode toml-mode
20:            lua-mode jinja2-mode
21:            json-mode html-mode
22:            web-mode html-mode-local-vars-hook
23:            web-mode-local-vars-hook nxml-mode-local-vars-hook
24:            scss-mode-local-vars css-mode-local-vars
25:            less-css-mode-local-vars css-mode
26:            typescript-mode javascript-mode
27:            js2-mode typescript-tsx-mode) . lsp-deferred)
28:   :config
29:   (setq lsp-toml-command
30:         (if (file-exists-p (expand-file-name ".cargo/bin/taplo" "~"))
31:             (expand-file-name ".cargo/bin/taplo" "~")
32:           "taplo")
33:         lsp-rust-rls-server-command "rls"
34:         lsp-eldoc-render-all t
35:         lsp-enable-snippet nil
36:         lsp-enable-indentation nil
37:         lsp-prefer-flymake nil
38:         lsp-keep-workspace-alive nil
39:         lsp-modeline-code-actions-segments '(count icon name))
40:   :custom
41:   (lsp-completion-provider :none)
42:   :config
43:   (when (featurep 'exwm)
44:     (advice-add #'corfu--make-frame :around
45:                 (defun +corfu--make-frame-a (oldfun &rest args)
46:                   (cl-letf (((symbol-function #'frame-parent)
47:                              (lambda (frame)
48:                                (or (frame-parameter frame 'parent-frame)
49:                                    exwm-workspace--current))))
50:                     (apply oldfun args))
51:                   (when exwm--connection
52:                     (set-frame-parameter corfu--frame 'parent-frame nil))))
53: 
54:     (advice-add #'corfu--popup-redirect-focus :override
55:                 (defun +corfu--popup-redirect-focus-a ()
56:                   (redirect-frame-focus corfu--frame
57:                                         (or (frame-parent corfu--frame)
58:                                             exwm-workspace--current)))))
59:   :general
60:   (+config/leader-key
61:     :keymaps 'lsp-mode-map
62:     "l" (general-simulate-key "C-c C-l"
63:           :name general-SPC-l-simulates-C-c-C-l
64:           :docstring "Simulates C-c C-l"
65:           :which-key "LSP"))
66: 
67:   (general-nvmap
68:     :keymaps 'lsp-mode-map
69:     "K" '(lsp-describe-thing-at-point :wk "describe thing at point")))

lsp-ui   disabled

 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   disabled

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)))

Org-mode

My org-mode configuration is based around my workflow.

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"))))

org-mode main package   builtin

  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:   (with-eval-after-load 'general
 20:     (general-def
 21:       "C-c c" 'org-capture
 22:       "C-c a" 'org-agenda
 23:       "C-c l" 'org-store-link))
 24:   (when(file-directory-p (expand-file-name "braindump/org" org-directory))
 25:     (customize-set-variable '+config/org-roam-directory
 26:                             (expand-file-name "braindump/org" org-directory)))
 27:   (when (file-directory-p (expand-file-name "alexforsale.github.io" org-directory))
 28:     (customize-set-variable '+config/blog-directory
 29:                             (expand-file-name "alexforsale.github.io" org-directory)))
 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:   (modify-syntax-entry ?/ "$" org-mode-syntax-table)
 35:   (modify-syntax-entry ?* "$" org-mode-syntax-table)
 36:   (add-to-list 'org-modules 'org-tempo t)
 37:   (add-to-list 'org-structure-template-alist '("sh" . "src sh"))
 38:   (add-to-list 'org-structure-template-alist '("co" . "src conf"))
 39:   (add-to-list 'org-structure-template-alist '("lisp" . "src lisp"))
 40:   (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
 41:   (add-to-list 'org-structure-template-alist '("sc" . "src scheme"))
 42:   (add-to-list 'org-structure-template-alist '("ts" . "src typescript"))
 43:   (add-to-list 'org-structure-template-alist '("py" . "src python"))
 44:   (add-to-list 'org-structure-template-alist '("go" . "src go"))
 45:   (add-to-list 'org-structure-template-alist '("yaml" . "src yaml"))
 46:   (add-to-list 'org-structure-template-alist '("js" . "src js"))
 47:   (add-to-list 'org-structure-template-alist '("json" . "src json"))
 48:   (add-to-list 'org-structure-template-alist '("n" . "note"))
 49:   (org-babel-do-load-languages
 50:    'org-babel-load-languages
 51:    '((emacs-lisp . t)
 52:      (awk . t)
 53:      (C . t)
 54:      (css . t)
 55:      (calc . t)
 56:      (ditaa . t) ; needs the `ditaa' package
 57:      (diagrams . t) ; `ob-diagrams'
 58:      (dot . t ) ; `graphviz'
 59:      (screen . t)
 60:      (haskell . t)
 61:      (java . t)
 62:      (js . t)
 63:      (latex . t)
 64:      (lisp . t)
 65:      (lua . t)
 66:      (org . t)
 67:      (perl . t)
 68:      (plantuml . t)
 69:      (python .t)
 70:      (ruby . t)
 71:      (shell . t)
 72:      (sed . t)
 73:      (scheme . t)
 74:      (sql . t)
 75:      (sqlite . t)))
 76:   (setq-default org-use-sub-superscripts '{})
 77:   (add-to-list 'org-babel-tangle-lang-exts '("js" . "js"))
 78:   (defun +config/org-prettify-symbols ()
 79:     (push '("[ ]" . "☐") prettify-symbols-alist)
 80:     (push '("[X]" . "☑") prettify-symbols-alist)
 81:     (prettify-symbols-mode))
 82:   :custom
 83:   (org-replace-disputed-keys t)
 84:   (org-indirect-buffer-display 'current-window)
 85:   (org-enforce-todo-dependencies t)
 86:   (org-fontify-whole-heading-line t)
 87:   (org-return-follows-link t)
 88:   (org-mouse-1-follows-link t)
 89:   (org-image-actual-width nil)
 90:   (org-adapt-indentation nil)
 91:   (org-startup-indented t)
 92:   (org-link-descriptive nil)
 93:   (org-log-done 'time)
 94:   (org-log-refile 'time)
 95:   (org-log-redeadline 'time)
 96:   (org-log-reschedule 'time)
 97:   (org-log-into-drawer t)
 98:   (org-clone-delete-id t)
 99:   (org-default-notes-file (expand-file-name "notes.org" org-directory))
100:   (org-insert-heading-respect-content nil)
101:   (org-pretty-entities t)
102:   (org-use-property-inheritance t)
103:   (org-priority-highest ?A)
104:   (org-priority-lowest ?D)
105:   (org-priority-default ?B)
106:   (org-todo-keywords
107:    '((sequence
108:       "TODO(t!)"  ; A task that needs doing & is ready to do
109:       "NEXT(n!)"  ; Tasks that can be delayed
110:       "PROG(p!)"  ; A task that is in progress
111:       "WAIT(w!)"  ; Something external is holding up this task
112:       "HOLD(h!)"  ; This task is paused/on hold because of me
113:       "|"
114:       "DONE(d!)"  ; Task successfully completed
115:       "DELEGATED(l!)" ; Task is delegated
116:       "KILL(k!)") ; Task was cancelled, aborted or is no longer applicable
117:      ))
118:   (org-todo-keyword-faces
119:    '(("PROG" . (:foreground "#5e81ac" :weight bold))
120:      ("WAIT" . (:foreground "#ebcb8b" :weight bold))
121:      ("HOLD" . (:foreground "#d08770" :weight bold))
122:      ("NEXT" . (:foreground "#81a1c1" :weight bold))
123:      ("DELEGATED" . "#8fbcbb")
124:      ("KILL" . "#a3be8c")))
125:   ;; (org-todo-state-tags-triggers
126:   ;;  '(("KILL" ("killed" . t) ("Archives" . t))
127:   ;;    ("WAIT" ("wait" . t))
128:   ;;    ("HOLD" ("wait") ("hold" . t))
129:   ;;    (done ("wait") ("hold"))
130:   ;;    ("PROG" ("active" . t))
131:   ;;    ("TODO" ("wait") ("killed") ("hold"))
132:   ;;    ("NEXT" ("wait") ("killed") ("hold"))
133:   ;;    ("PROG" ("wait") ("killed") ("hold"))
134:   ;;    ("DONE" ("wait") ("killed") ("hold"))))
135:   )

org-src   builtin

1: (use-package org-src
2:   :hook (org-src-mode . (lambda () (outline-minor-mode -1)))
3:   :custom
4:   (org-src-preserve-indentation nil)
5:   (org-edit-src-content-indentation 0))

org-faces   builtin

1: (use-package org-faces
2:   :custom
3:   (org-fontify-quote-and-verse-blocks t))

org-compat   builtin

1: (use-package org-compat
2:   :custom
3:   (org-imenu-depth 6))

org-archive   builtin

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   builtin

 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   builtin

 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-num   builtin

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-fold   builtin

1: (use-package org-fold
2:   :after org org-contrib
3:   :custom
4:   (org-catch-invisible-edits 'smart))

org-id   builtin

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-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   builtin

 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-clock   builtin

 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-agenda   builtin

 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"))))))
57:   :general
58:   (general-nvmap
59:     :keymaps 'org-agenda-mode-map
60:     "q" 'org-agenda-quit
61:     "Q" 'org-agenda-quit
62:     "RET" 'org-agenda-switch-to
63:     "TAB" 'org-agenda-switch-to
64:     "t" 'org-agenda-todo
65:     "gr" 'org-agenda-redo-all))

org-timer   builtin

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-contrib

1: (use-package org-contrib
2:   :ensure t
3:   :after org)

org-superstar   disabled

 1: (use-package org-superstar
 2:   :ensure
 3:   :defer t
 4:   :hook (org-mode . org-superstar-mode)
 5:   :custom
 6:   (org-superstar-leading-bullet ?\s)
 7:   (org-superstar-leading-fallback ?\s)
 8:   (org-hide-leading-stars nil)
 9:   (org-indent-mode-turns-on-hiding-stars nil)
10:   (org-superstar-todo-bullet-alist
11:    '(("TODO" . 9744)
12:      ("[ ]"  . 9744)
13:      ("DONE" . 9745)
14:      ("[X]"  . 9745)))
15:   :config
16:   (org-superstar-configure-like-org-bullets))

org-modern

(use-package org-modern
  :ensure t
  :demand t
  :config
  (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))

org-fancy-priority   disabled

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 '("⚡" "⬆" "⬇" "☕")))

toc-org   disabled

 1: (use-package toc-org
 2:   :ensure
 3:   :defer t
 4:   :hook ((org-mode markdown-mode) . toc-org-mode)
 5:   :custom
 6:   (toc-org-hrefify-default "gh")
 7:   :general
 8:   (+config/local-leader
 9:     :keymaps 'markdown-mode-map
10:     "C-o" 'toc-org-markdown-follow-thing-at-point))

ox-pandoc   disabled

 1: (use-package ox-pandoc
 2:   :ensure
 3:   :if (executable-find "pandoc")
 4:   :after ox
 5:   :defer t
 6:   :init
 7:   (add-to-list 'org-export-backends 'pandoc)
 8:   :custom
 9:   (org-pandoc-options
10:    '((standalone . t)
11:      (mathjax . t)
12:      (variable . "revealjs-url=https://revealjs.com"))))

deft   disabled

 1: (use-package deft
 2:   :ensure
 3:   :defer t
 4:   :after org-roam
 5:   :custom
 6:   (deft-directory org-directory)
 7:   (deft-default-extension "org")
 8:   (deft-recursive t)
 9:   (deft-use-filename-as-title t)
10:   (deft-file-naming-rules
11:    '((noslash . "-")
12:      (nospace . "-")
13:      (case-fn . downcase)))
14:   :config
15:   (setq deft-strip-summary-regexp
16:         (concat "\\("
17:                 "[\n\t]" ;; blank
18:                 "\\|^#\\+[[:alpha:]_]+:.*$" ;; org-mode metadata
19:                 "\\|^:PROPERTIES:\n\\(.+\n\\)+:END:\n" ;; org-roam ID
20:                 "\\|\\[\\[\\(.*\\]\\)" ;; any link
21:                 "\\)"))
22:   (setq deft-strip-title-regexp
23:         (concat "\\("
24:                 "?:^%+"
25:                 "\\|^:PROPERTIES:\n\\(.+\n\\)+:END:\n" ;; org-roam ID
26:                 "\\|^\\TITLE: *"
27:                 "\\|^[#* ]+"
28:                 "\\|-\\*-[[:alpha:]]+-\\*-"
29:                 "\\|^Title:[     ]*"
30:                 "\\|#+$"
31:                 "\\)"))
32:   (setq deft-extensions (list "org"))
33:   (add-hook 'deft-mode-hook #'evil-normalize-keymaps)
34:   (evil-set-initial-state #'deft-mode 'insert)
35:   :general
36:   (general-nvmap
37:     :keymaps 'deft-mode-map
38:     "q" 'evil-quit
39:     "C-j" 'forward-button
40:     "C-k" 'backward-button))

org-pdftools   disabled

1: (use-package org-pdftools
2:   :ensure
3:   :defer t
4:   :hook (org-mode . org-pdftools-setup-link)
5:   :commands org-pdftools-export)

org-noter   disabled

1: (use-package org-noter
2:   :ensure
3:   :defer t
4:   :after org-pdftools
5:   :custom
6:   (org-noter-auto-save-last-location t)
7:   (org-noter-separate-notes-from-heading t)
8:   :config
9:   (require 'org-noter-pdftools))

org-noter-pdftools   disabled

 1: (use-package org-noter-pdftools
 2:   :ensure
 3:   :defer t
 4:   :after org-noter
 5:   :config
 6:   ;; Add a function to ensure precise note is inserted
 7:   (defun org-noter-pdftools-insert-precise-note (&optional toggle-no-questions)
 8:     (interactive "P")
 9:     (org-noter--with-valid-session
10:      (let ((org-noter-insert-note-no-questions (if toggle-no-questions
11:                                                    (not org-noter-insert-note-no-questions)
12:                                                  org-noter-insert-note-no-questions))
13:            (org-pdftools-use-isearch-link t)
14:            (org-pdftools-use-freepointer-annot t))
15:        (org-noter-insert-note (org-noter--get-precise-info)))))
16:   ;; fix https://github.com/weirdNox/org-noter/pull/93/commits/f8349ae7575e599f375de1be6be2d0d5de4e6cbf
17:   (defun org-noter-set-start-location (&optional arg)
18:     "When opening a session with this document, go to the current location.
19:     With a prefix ARG, remove start location."
20:     (interactive "P")
21:     (org-noter--with-valid-session
22:      (let ((inhibit-read-only t)
23:            (ast (org-noter--parse-root))
24:            (location (org-noter--doc-approx-location (when (called-interactively-p 'any) 'interactive))))
25:        (with-current-buffer (org-noter--session-notes-buffer session)
26:          (org-with-wide-buffer
27:           (goto-char (org-element-property :begin ast))
28:           (if arg
29:               (org-entry-delete nil org-noter-property-note-location)
30:             (org-entry-put nil org-noter-property-note-location
31:                            (org-noter--pretty-print-location location))))))))
32:   (with-eval-after-load 'pdf-annot
33:     (add-hook 'pdf-annot-activate-handler-functions #'org-noter-pdftools-jump-to-note)))

ox-gfm   disabled

1: (use-package ox-gfm
2:   :ensure
3:   :defer t
4:   :after org)

org-download   disabled

 1: (use-package org-download
 2:   :ensure
 3:   :defer t
 4:   :after org
 5:   :hook (dired-mode . org-download-enable)
 6:   :commands
 7:   org-download-dnd
 8:   org-download-yank
 9:   org-download-screenshot
10:   org-download-clipboard
11:   org-download-dnd-base64
12:   :custom
13:   (org-download-method 'directory)
14:   (org-download-timestamp "_%Y%m%d_%H%M%S")
15:   (org-download-screenshot-method (cond ((executable-find "maim")  "maim -s %s")
16:                                         ((executable-find "scrot") "scrot -s %s")
17:                                         ((executable-find "gnome-screenshot") "gnome-screenshot -a -f %s")))
18:   (org-download-heading-lvl nil)
19:   (org-download-abbreviate-filename-function
20:    (lambda (path)
21:      (if (file-in-directory-p path org-download-image-dir)
22:          (file-relative-name path org-download-image-dir)
23:        path)))
24:   :config
25:   (unless org-download-image-dir
26:     (setq org-download-image-dir org-attach-id-dir)))

org-cliplink   disabled

 1: (use-package org-cliplink
 2:   :ensure
 3:   :after org
 4:   :defer t
 5:   :bind ("C-x p i" . org-cliplink)
 6:   :config
 7:   (require 'org-capture)
 8:   (add-to-list 'org-capture-templates
 9:                `("c" "Cliplink capture task" entry
10:                  (file+olp ,(expand-file-name "links.org" org-directory) "Cliplink")
11:                  "* %? %(org-cliplink-capture)\n\n SCHEDULED: %t\n"
12:                  :empty-lines 1) t))

hugo function: start server

1: (defun +config/start-hugo-server (args)
2:   "Start hugo server in `+config/blog-dir'."
3:   (interactive (list (transient-args '+config/transient-hugo-server)))
4:   (if (not (executable-find "hugo"))
5:       (message "hugo executable not found")
6:     (let ((default-directory +config/blog-directory)
7:           (command "hugo server"))
8:       (async-shell-command (mapconcat #'identity `(,command ,@args) " ") "*hugo*" "*hugo-error*"))))

hugo function: create new blog post

1: (defun +config/create-new-blog-post ()
2:   "Create new blog post path."
3:   (interactive)
4:   (let ((name (read-string "Filename: ")))
5:     (concat +config/blog-directory "/content-org/" (format "%s" name) "/" (format "%s.org" name))))

Custom capture-template for hugo blog

 1: (merge-list-to-list 'org-capture-templates
 2:                     `(("b" "(b)log post" plain
 3:                        (file +config/create-new-blog-post)
 4:                        "\
 5: #+options: ':nil -:nil ^:{} num:nil toc:nil
 6: #+author: %n
 7: #+creator: Emacs %(eval emacs-version) (Org mode %(eval org-version) + ox-hugo)
 8: #+hugo_section: posts
 9: #+hugo_base_dir: ../../
10: #+date: %t
11: #+title: %^{title}
12: #+description: %^{description}
13: #+hugo_draft: true
14: #+hugo_tags: %^{tags}
15: #+hugo_categories: %^{categories}
16: #+hugo_auto_set_lastmod: t
17: #+startup: inlineimages
18: 
19: * %?
20: " :unnarrowed t :jump-to-captured t)))

transient

 1: (use-package transient
 2:   :defer t
 3:   :config
 4:   (transient-define-prefix +config/transient-hugo-server ()
 5:     "Run hugo server with `transient'."
 6:     :man-page "hugo-server"
 7:     ["Options"
 8:      ("q" "quit" transient-quit-all)
 9:      ("-D" "Build drafts" "--buildDrafts")
10:      ("-E" "Build expired" "--buildExpired")
11:      ("-F" "Build future" "--buildFuture")
12:      ("-d" "Debug" "--debug")
13:      ("-B" "Disable build errors on browser" "--disableBrowserError")
14:      ("-c" "Clean destination dir" "--cleanDestinationDir")
15:      ("-e" "Enable Git info" "--enableGitInfo")
16:      ("-F" "enable full re-renders on changes" "--disableFastRender")
17:      ("-f" "Force sync static files" "--forceSyncStatic")
18:      ("-g" "enable to run some cleanup tasks" "--gc")
19:      ("-m" "Minify any supported output format" "--minify")
20:      ("-C" "No chmod" "--noChmod")
21:      ("-T" "Don't sync modification time of files" "--noTimes")
22:      ("-I" "Print missing translation" "--printI18nWarnings")
23:      ("-M" "Print memory usage" "--printMemoryUsage")
24:      ("-P" "Print warning on duplicate target path" "--printPathWarnings")
25:      ("-q" "Quiet" "--quiet")
26:      ("-v" "Verbose" "--verbose")
27:      ("-w" "Watch filesystem for changes" "--watch")]
28:     ["Action"
29:      ("s" "hugo server" +config/start-hugo-server)]))

ox-hugo

 1: (use-package ox-hugo
 2:   :defer t
 3:   :ensure
 4:   :hook (org-hugo-auto-export-mode . +config/ox-hugo-transient-keybinding)
 5:   :general
 6:   (defun +config/ox-hugo-transient-keybinding ()
 7:     (+config/local-leader
 8:       :keymaps 'org-mode-map
 9:       "h" '(:ignore t :wk "hugo")
10:       "hs" '+config/transient-hugo-server)))

org-roam

  1: (use-package org-roam
  2:   :ensure
  3:   :defer t
  4:   :commands (org-roam-node-find)
  5:   :custom
  6:   (org-roam-completion-everywhere t)
  7:   :config
  8:   (if (not +config/org-roam-directory)
  9:       (customize-set-variable 'org-roam-directory (expand-file-name "roam" org-directory))
 10:     (customize-set-variable 'org-roam-directory +config/org-roam-directory))
 11:   (org-roam-db-autosync-mode)
 12:   (add-to-list 'display-buffer-alist
 13:                '("\\*org-roam\\*"
 14:                  (display-buffer-in-direction)
 15:                  (direction . right)
 16:                  (window-width . 0.33)
 17:                  (window-height . fit-window-to-buffer)))
 18:   (unless +config/org-roam-directory
 19:     (setq org-roam-db-location
 20:           (expand-file-name "org-roam.db"
 21:                             (or (getenv "XDG_DATA_HOME")
 22:                                 (expand-file-name ".local/share"
 23:                                                   (getenv "HOME"))))))
 24:   (when +config/org-roam-directory
 25:     (setq org-roam-capture-templates
 26:           `(("o" "others" plain "%?"
 27:              :target
 28:              (file+head ,(expand-file-name "%<%Y%m%d%H%M%S>-${slug}.org" org-roam-directory) "
 29: #+title: ${title}
 30: #+author: %n
 31: #+description: %^{description}
 32: #+date: %T
 33: #+hugo_base_dir: ..
 34: #+hugo_section: posts
 35: #+hugo_categories: others
 36: #+hugo_tags: %^{tag}
 37: ")
 38:              :unnarrowed t)
 39:             ("t" "tech" plain "%?"
 40:              :target
 41:              (file+head ,(expand-file-name "%<%Y%m%d%H%M%S>-${slug}.org" org-roam-directory) "
 42: #+title: ${title}
 43: #+author: %n
 44: #+description: %^{description}
 45: #+date: %T
 46: #+hugo_base_dir: ..
 47: #+hugo_section: posts
 48: #+hugo_categories: tech
 49: #+hugo_tags: %^{tag}
 50: ")
 51:              :unnarrowed t)
 52:             ("p" "programming" plain "%?"
 53:              :target
 54:              (file+head ,(expand-file-name "%<%Y%m%d%H%M%S>-${slug}.org" org-roam-directory) "
 55: #+title: ${title}
 56: #+author: %n
 57: #+description: %^{description}
 58: #+date: %T
 59: #+hugo_base_dir: ..
 60: #+hugo_section: posts
 61: #+hugo_categories: programming
 62: #+hugo_tags: %^{tag}
 63: ")
 64:              :unnarrowed t)
 65:             )
 66:           ))
 67:   (setq org-roam-completion-everywhere t)
 68:   (require 'org-roam-protocol)
 69:   ;; TODO: implement `hugo' layouts for reference.
 70:   (setq org-roam-capture-ref-templates
 71:         `(("r" "ref" plain "%?" :target
 72:            (file+head ,(expand-file-name "%<%Y%m%d%H%M%S>-${slug}.org" org-roam-directory) "
 73: #+title: ${title}
 74: #+author: %n
 75: #+description: %^{description}
 76: #+date: %T
 77: #+hugo_base_dir: ..
 78: #+hugo_section: posts
 79: #+hugo_categories: reference
 80: #+hugo_tags: %^{tag}
 81: ") :unnarrowed t)))
 82:   (require 'org-roam-dailies)
 83:   (setq org-roam-dailies-directory "daily/"
 84:         org-roam-dailies-capture-templates
 85:         '(("d" "default" entry "* %?" :target
 86:            (file+head "%<%Y-%m-%d>.org" "
 87: #+title: %<%Y-%m-%d>
 88: #+author: %n
 89: #+description: %^{description}
 90: #+date: %T
 91: #+hugo_base_dir: ../..
 92: #+hugo_section: posts
 93: #+hugo_categories: daily
 94: #+hugo_tags: %^{tag}
 95: "))))
 96:   (require 'org-roam-export)
 97:   (org-roam-setup)
 98:   :general
 99:   (+config/leader-notes
100:     "r" '(:ignore t :wk "roam")
101:     "rb" 'org-roam-buffer-toggle
102:     "rc" 'org-roam-capture
103:     "rd" '(:ignore t :wk "dailies")
104:     "rdc" '(:ignore t :wk "capture day")
105:     "rdcd" 'org-roam-dailies-capture-date
106:     "rdct" 'org-roam-dailies-capture-today
107:     "rdg" '(:ignore t :wk "goto")
108:     "rdgt" 'org-roam-dailies-goto-today
109:     "rdgd" 'org-roam-dailies-goto-date
110:     "rdgp" 'org-roam-dailies-goto-previous-note
111:     "rdgy" 'org-roam-dailies-goto-yesterday
112:     "rdcy" 'org-roam-dailies-capture-yesterday
113:     "ri" 'org-roam-node-insert
114:     "rf" 'org-roam-node-find
115:     "rg" 'org-roam-graph
116:     "rr" '(:ignore t :wk "ref")
117:     "rra" 'org-roam-ref-add
118:     "rrf" 'org-roam-ref-find
119:     "rrr" 'org-roam-ref-remove))

org-roam-ui

 1: (use-package org-roam-ui
 2:   :ensure
 3:   :defer t
 4:   :after org-roam
 5:   :config
 6:   (setq org-roam-ui-sync-theme t
 7:         org-roam-ui-follow t
 8:         org-roam-ui-update-on-save t
 9:         org-roam-ui-open-on-start nil)
10:   :general
11:   (+config/leader-notes
12:     "ru" '(:ignore t :wk "org-roam-ui")
13:     "ruf" 'org-roam-ui-follow-mode
14:     "ruo" 'org-roam-ui-open
15:     "rus" 'org-roam-ui-sync-theme)
16:   (+config/leader-notes
17:     :keymaps 'org-roam-mode-map
18:     "ruz" 'org-roam-ui-node-zoom))

org-journal   disabled

 1: (use-package org-journal
 2:   :ensure
 3:   :defer t
 4:   :custom
 5:   (org-icalendar-store-UID t)
 6:   (org-icalendar-include-todo 'all)
 7:   (org-journal-enable-agenda-integration t)
 8:   (org-icalendar-combined-agenda-file (expand-file-name "org-journal.ics" org-directory))
 9:   (org-journal-date-prefix "#+title: ")
10:   (org-journal-file-format "%Y-%m-%d.org")
11:   (org-journal-dir (expand-file-name "journal" org-directory))
12:   (org-journal-date-format "%A, %d %B %Y"))

org-ref   disabled

 1: (use-package org-ref
 2:   :ensure
 3:   :defer t
 4:   :config
 5:   (let ((ref-dir (expand-file-name "bibliography" org-directory)))
 6:     (setq bibtex-completion-bibliography `(,(expand-file-name "references.bib" ref-dir)
 7:                                            ,(expand-file-name "dei.bib" ref-dir)
 8:                                            ,(expand-file-name "master.bib" ref-dir)
 9:                                            ,(expand-file-name "archive.bib" ref-dir))
10:           bibtex-completion-library-path '(,(expand-file-name "bibtex-pdfs/" ref-dir))
11:           bibtex-completion-notes-path (expand-file-name "notes/" ref-dir)
12:           bibtex-completion-notes-template-multiple-files "* ${author-or-editor}, ${title}, ${journal}, (${year}) :${=type=}: \n\nSee [[cite:&${=key=}]]\n"
13:           bibtex-completion-additional-search-fields '(keywords)
14:           bibtex-completion-display-formats
15:           '((article       . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${journal:40}")
16:             (inbook        . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} Chapter ${chapter:32}")
17:             (incollection  . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${booktitle:40}")
18:             (inproceedings . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${booktitle:40}")
19:             (t             . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*}"))))
20:   (setq bibtex-completion-pdf-open-function
21:         (lambda (fpath)
22:           (call-process "open" nil 0 nil fpath))))

consult-bibtex   disabled

1: (when (file-directory-p (expand-file-name "site-lisp/consult-bibtex" user-emacs-directory))
2:   (add-to-list 'load-path (expand-file-name "site-lisp/consult-bibtex" user-emacs-directory)))
3: 
4: (use-package consult-bibtex
5:   :defer t
6:   :config
7:   (with-eval-after-load 'embark
8:     (add-to-list 'embark-keymap-alist '(bibtex-completion . consult-bibtex-embark-map))))

consult-org-roam   disabled

 1: (use-package consult-org-roam
 2:   :ensure
 3:   :defer t
 4:   :after org-roam
 5:   :init
 6:   (require 'consult-org-roam)
 7:   ;; Activate the minor mode
 8:   (consult-org-roam-mode 1)
 9:   :config
10:   (with-eval-after-load 'general
11:     (+config/leader-notes
12:       "rs" 'consult-org-roam-search))
13:   :custom
14:   ;; Use `ripgrep' for searching with `consult-org-roam-search'
15:   (consult-org-roam-grep-func #'consult-ripgrep)
16:   ;; Configure a custom narrow key for `consult-buffer'
17:   (consult-org-roam-buffer-narrow-key ?r)
18:   ;; Display org-roam buffers right after non-org-roam buffers
19:   ;; in consult-buffer (and not down at the bottom)
20:   (consult-org-roam-buffer-after-buffers t)
21:   :config
22:   ;; Eventually suppress previewing for certain functions
23:   (consult-customize
24:    consult-org-roam-forward-links
25:    :preview-key "M-.")
26:   :bind
27:   ;; Define some convenient keybindings as an addition
28:   ("C-c n e" . consult-org-roam-file-find)
29:   ("C-c n b" . consult-org-roam-backlinks)
30:   ("C-c n B" . consult-org-roam-backlinks-recursive)
31:   ("C-c n l" . consult-org-roam-forward-links)
32:   ("C-c n r" . consult-org-roam-search))

ox-latex   builtin

1: (use-package ox-latex
2:   :config
3:   (setq org-latex-pdf-process (list "latexmk -shell-escape -bibtex -f -pdf %f")))

org-plantum   builtin

1: (use-package ob-plantuml
2:   :after org
3:   :demand
4:   :ensure nil
5:   :config
6:   (when (file-exists-p "/usr/share/java/plantuml/plantuml.jar")
7:     (setq org-plantuml-jar-path "/usr/share/java/plantuml/plantuml.jar")))

ob-ditaa   disabled

1: (use-package ob-ditaa
2:   :config
3:   (when (file-exists-p "/usr/share/java/ditaa/ditaa-0.11.jar")
4:     (setq org-ditaa-jar-path "/usr/share/java/ditaa/ditaa-0.11.jar")))

ob-diagrams   disabled

Generate various diagrams inside org mode with org-babel and the help from various tools.

1: (use-package ob-diagrams
2:   :ensure
3:   :demand t)

khalel   disabled

Interacting through Emacs with locally-stored calendars via the console application khal and syncing with remote CalDAV calendars using vdirsyncer.

1: (use-package khalel
2:   :ensure
3:   :if (executable-find "khal")
4:   :after org
5:   :config
6:   (setq khalel-khal-command (executable-find "khal")
7:         khalel-vdirsyncer-command (executable-find "vdirsyncer")
8:         khalel-import-org-file (expand-file-name "calendar.org" org-directory))
9:   (khalel-add-capture-template))

Tools

nov   disabled

Useful for reading epubs.

1: (use-package nov 
2:   :ensure
3:   :defer t)

djvu   disabled

1: (use-package djvu 
2:   :ensure
3:   :defer t)

pdf-tools   disabled

 1: (use-package pdf-tools
 2:   :ensure
 3:   :defer t
 4:   :mode ("\\.[pP][dD][fF]\\'" . pdf-view-mode)
 5:   :hook ((pdf-tools-enabled . (lambda ()
 6:                                 (display-line-numbers-mode -1))))
 7:   :custom
 8:   (pdf-view-use-scaling t)
 9:   (pdf-view-use-imagemagick nil)
10:   (pdf-annot-activate-created-annotations t)
11:   (pdf-view-resize-factor 1.1)
12:   :config
13:   (pdf-tools-install)
14:   (setq-default pdf-view-display-size 'fit-page)
15:   (add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer)
16:   (add-hook 'pdf-view-mode-hook (lambda () (cua-mode 0)))
17:   (add-hook 'pdf-view-mode-hook #'pdf-history-minor-mode)
18:   (define-key pdf-view-mode-map (kbd "h") 'pdf-annot-add-highlight-markup-annotation)
19:   (define-key pdf-view-mode-map (kbd "t") 'pdf-annot-add-text-annotation)
20:   (define-key pdf-view-mode-map (kbd "D") 'pdf-annot-delete))

khalel   disabled

 1: (use-package khalel
 2:   :ensure
 3:   :defer t
 4:   :if (executable-find "khal")
 5:   :config
 6:   (setq khalel-khal-command (executable-find "khal")
 7:         khalel-vdirsyncer-command (executable-find "vdirsyncer")
 8:         khalel-import-org-file (expand-file-name "calendar.org" org-directory)
 9:         khalel-import-org-file-confirm-overwrite nil)
10:   (khalel-add-capture-template))

direnv   disabled

1: (use-package direnv
2:   :ensure
3:   :defer t
4:   :config
5:   (direnv-mode))

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))

ement   disabled

1: (use-package ement
2:   :ensure
3:   :defer t
4:   :config
5:   (setf use-default-font-for-symbols nil)
6:   (set-fontset-font t 'unicode "Noto Emoji" nil 'append))

pinentry

1: (use-package pinentry
2:   :ensure
3:   :defer t
4:   :config
5:   (pinentry-start))

rg

1: (use-package rg
2:   :if (executable-find "rg")
3:   :ensure
4:   :defer t)

wgrep   disabled

1: (use-package wgrep
2:   :ensure
3:   :defer t
4:   :commands wgrep-change-to-wgrep-mode
5:   :config (setq wgrep-auto-save-buffer t))

elfeed   disabled

emacs-elfeed-rss.png

Figure 10: elfeed RSS

 1: (use-package elfeed
 2:   :ensure
 3:   :defer t
 4:   :commands elfeed
 5:   :config
 6:   (setq elfeed-search-filter "@2-week-ago "
 7:         elfeed-show-entry-switch #'pop-to-buffer
 8:         shr-max-image-proportion 0.8)
 9:   :general
10:   (general-def
11:     :keymaps
12:     'elfeed-search-mode-map
13:     :states '(normal visual)
14:     "q" '(elfeed-kill-buffer :wk "kill buffer")
15:     "r" '(elfeed-search-update--force :wk "update")))

elfeed-org   disabled

1: (use-package elfeed-org
2:   :ensure
3:   :defer t
4:   :after org elfeed
5:   :preface
6:   (setq rmh-elfeed-org-files (list (expand-file-name "elfeed.org" org-directory)))
7:   :init
8:   (elfeed-org))

emms

This is supposed to be a builtin package, but somehow I can not load it.

 1: (use-package emms
 2:   :init 
 3:   (require 'emms-setup)
 4:   (require 'emms-mpris)
 5:   :config
 6:   (emms-all)
 7:   (emms-default-players)
 8:   (emms-mpris-enable)
 9:   (setq-default
10:    emms-source-playlist-formats 'm3u
11:    emms-playlist-mode-center-when-go t
12:    emms-playlist-default-major-mode 'emms-playlist-mode
13:    emms-volume-change-function 'emms-volume-pulse-change)
14:   :general
15:   (general-nvmap
16:     :keymaps 'emms-browser-mode-map
17:     "?" 'describe-mode
18:     "TAB" 'emms-browser-toggle-subitems
19:     "RET" 'emms-browser-add-tracks
20:     "C-j" 'emms-browser-add-tracks-and-play
21:     "C" 'emms-browser-clear-playlist
22:     "E" 'emms-browser-expand-all
23:     "p" 'emms-playlist-mode-go
24:     "r" 'emms-browser-goto-random
25:     "1" 'emms-browser-collapse-all
26:     "2" 'emms-browser-expand-to-level-2
27:     "3" 'emms-browser-expand-to-level-3
28:     "4" 'emms-browser-expand-to-level-4
29:     "q" 'bury-buffer)
30:   (general-nvmap
31:     :keymaps 'emms-playlist-mode-map
32:     "?" 'describe-mode
33:     "C-f" 'scroll-up
34:     "C-j" 'emms-playlist-mode-insert-newline
35:     "C-k" 'emms-playlist-mode-kill-track
36:     "C-n" 'next-line
37:     "C-o" 'emms-playlist-mode-shift-track-down
38:     "C-p" 'previous-line
39:     "C-u" 'scroll-up
40:     "TAB" 'emms-playlist-mode-shift-track-up
41:     "RET" 'emms-playlist-mode-play-smart
42:     "a" 'emms-playlist-mode-add-contents
43:     "b" 'emms-playlist-set-playlist-buffer
44:     "c" 'emms-playlist-mode-center-current
45:     "d" 'emms-playlist-mode-goto-dired-at-point
46:     "f" 'emms-show 
47:     "j" 'next-line
48:     "k" 'previous-line
49:     "n" 'emms-next
50:     "p" 'emms-previous
51:     "r" 'emms-random
52:     "s" 'emms-stop
53:     "q" 'bury-buffer)
54:   (+config/leader-open
55:     "e" '((lambda () (interactive) (require 'emms-browser) (emms-browser)) :wk "emms-browser")))

editorconfig   disabled

1: (use-package editorconfig
2:   :ensure
3:   :defer t
4:   :config
5:   (editorconfig-mode 1)
6:   (with-eval-after-load 'ws-butler
7:     (setq editorconfig-trim-whitespaces-mode
8:           'ws-butler-mode)))

pdfgrep   disabled

1: (use-package pdfgrep
2:   :ensure
3:   :defer t
4:   :after pdf-tools
5:   :config (pdfgrep-mode))

selected   disabled

1: (use-package selected
2:   :ensure
3:   :defer t
4:   :commands selected-minor-mode
5:   :init
6:   (selected-global-mode))

yasnippet   disabled

 1: (use-package yasnippet
 2:   :ensure
 3:   :defer t
 4:   :diminish yas-minor-mode
 5:   :commands (yas-minor-mode-on
 6:              yas-expand
 7:              yas-expand-snippet
 8:              yas-lookup-snippet
 9:              yas-insert-snippet
10:              yas-new-snippet
11:              yas-visit-snippet-file
12:              yas-activate-extra-mode
13:              yas-deactivate-extra-mode
14:              yas-maybe-expand-abbrev-key-filter)
15:   :init
16:   (defvar yas-verbosity 2)
17:   :hook (prog-mode . yas-minor-mode)
18:   :config
19:   (when (file-directory-p (expand-file-name "snippets" user-emacs-directory))
20:     (add-to-list 'yas-snippet-dirs (expand-file-name "snippets" user-emacs-directory))))
21: 
22: (use-package yasnippet-snippets
23:   :ensure
24:   :after yasnippet)
25: 
26: (use-package auto-yasnippet
27:   :ensure
28:   :after yasnippet)

lorem-ipsum   disabled

1: (use-package lorem-ipsum
2:   :ensure
3:   :defer t
4:   :general
5:   (+config/leader-insert
6:     "l" '(:ignore t :wk "insert lorem ipsum")
7:     "ll" 'lorem-ipsum-insert-list
8:     "lp" 'lorem-ipsum-insert-paragraphs
9:     "ls" 'lorem-ipsum-insert-sentences))

vimrc-mode   disabled

Blasphemy, I know. But I still needs vim for editing mostly in remote machine, and sometimes the connection is unreliable which makes my Emacs hangs. For this situation, vim + screen or tmux is more sensible.

1: :defer t
2: :config
3: (add-to-list 'auto-mode-alist '("\\.vim\\(rc\\)?\\'" . vimrc-mode)))

dired

dired   builtin

 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   builtin

1: (use-package image-dired
2:   :config
3:   (setq image-dired-thumb-size 150))

dired-x   builtin

 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

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   builtin

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))

Treemacs

I sometimes need treemacs when working on a large directory of files.

treemacs main package   disabled

  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   disabled

1: (use-package treemacs-projectile
2:   :ensure
3:   :after treemacs)

treemacs-icons-dired   disabled

1: (use-package treemacs-icons-dired
2:   :ensure
3:   :after treemacs
4:   :hook (dired-mode . treemacs-icons-dired-enable-once))

treemacs-magit   disabled

1: (use-package treemacs-magit
2:   :ensure
3:   :after treemacs magit)

treemacs-evil   disabled

1: (use-package treemacs-evil
2:   :ensure
3:   :after treemacs evil)

lsp-treemacs   disabled

emacs-lsp-treemacs-symbol.png

Figure 11: symbols in 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   disabled

1: (use-package treemacs-perspective
2:   :ensure
3:   :after treemacs perspective
4:   :config
5:   (treemacs-set-scope-type 'Perspectives))

treemacs-tab-bar   disabled

1: (use-package treemacs-tab-bar
2:   :ensure
3:   :after treemacs)

treemacs-nerd-icons   disabled

1: (use-package treemacs-nerd-icons
2:   :ensure
3:   :after treemacs
4:   :config
5:   (treemacs-load-theme "nerd-icons"))

Mail

notmuch main package

 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

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

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

1: (use-package ol-notmuch
2:   :ensure)

notmuch-maildir

1: (use-package notmuch-maildir
2:   :ensure
3:   :config
4:   (notmuch-maildir-inject-section))

message   builtin

1: (use-package message
2:   :custom
3:   (message-directory (expand-file-name ".mail" (getenv "HOME")))
4:   (message-sendmail-envelope-from 'header))

sendmail   builtin

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

These are the programming languages that I interacts the most, I'm not a programmer, but I've been using GNU/Linux for a while now.

Flycheck

  • flycheck package   disabled
     1: ;;;###autoload
     2: (defun +syntax-init-popups-h ()
     3:   "Activate `flycheck-posframe-mode' if available and in GUI Emacs.
     4: Activate `flycheck-popup-tip-mode' otherwise.
     5: Do nothing if `lsp-ui-mode' is active and `lsp-ui-sideline-enable' is non-nil."
     6:   (unless (and (bound-and-true-p lsp-ui-mode)
     7:                lsp-ui-sideline-enable)
     8:     (if (and (fboundp 'flycheck-posframe-mode)
     9:              (display-graphic-p))
    10:         (flycheck-posframe-mode +1)
    11:       (flycheck-popup-tip-mode +1))))
    12: 
    13: (use-package flycheck
    14:   :ensure
    15:   :defer t
    16:   :commands flycheck-list-errors flycheck-buffer
    17:   :hook (prog-mode . global-flycheck-mode)
    18:   :config
    19:   (delq 'new-line flycheck-check-syntax-automatically)
    20:   (setq flycheck-emacs-lisp-load-path 'inherit
    21:         flycheck-idle-change-delay 1.0
    22:         flycheck-buffer-switch-check-intermediate-buffers t
    23:         flycheck-display-errors-delay 0.25)
    24:   (evil-add-command-properties #'flycheck-next-error :repeat t :jump t)
    25:   (evil-add-command-properties #'flycheck-previous-error :repeat t :jump t)
    26:   :general
    27:   (general-define-key
    28:    :keymaps '(normal visual)
    29:    :prefix "z"
    30:    "C-p" '(flycheck-previous-error
    31:            :properties
    32:            (:repeat t :jump t))
    33:    "C-n" '(flycheck-next-error
    34:            :properties
    35:            (:repeat t :jump t))))
    
  • consult-flycheck   disabled
    1: (use-package consult-flycheck
    2:   :ensure
    3:   :after consult flycheck
    4:   :config
    5:   (with-eval-after-load 'general
    6:     (+config/leader-register
    7:       "F" 'consult-flycheck)))
    
  • flycheck-posframe   disabled
    1: (use-package flycheck-posframe
    2:   :if (display-graphic-p)
    3:   :ensure)
    
  • flycheck-popup-tip   disabled
    1: (use-package flycheck-popup-tip
    2:   :ensure
    3:   :commands flycheck-popup-tip-show-popup flycheck-popup-tip-delete-popup
    4:   :hook (flycheck-mode . +syntax-init-popups-h)
    5:   :hook ((evil-insert-state-entry
    6:           evil-replace-state-entry) . flycheck-popup-tip-delete-popup)
    7:   :config
    8:   (setq flycheck-popup-tip-error-prefix "X "))
    
  • flycheck-color-mode-line   disabled
    1: (use-package flycheck-color-mode-line
    2:   :ensure
    3:   :hook (flycheck-mode . flycheck-color-mode-line-mode))
    

Lisp

  • elisp-mode   builtin
     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   builtin
       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)))))
      
    • elisp-demos
      1: (use-package elisp-demos
      2:   :ensure
      3:   :init
      4:   (advice-add #'describe-function-1 :after #'elisp-demos-advice-describe-function-1)
      5:   (advice-add #'helpful-update :after #'elisp-demos-advice-helpful-update))
      
    • eros
      1: (use-package eros
      2:   :ensure
      3:   :config
      4:   (eros-mode 1))
      
    • buttercup
      1: (use-package buttercup
      2:   :ensure
      3:   :defer t
      4:   :config
      5:   (with-eval-after-load 'evil
      6:     (add-hook 'buttercup-minor-mode-hook #'evil-normalize-keymaps)))
      
  • macrostep
    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)
    
    • sly
      1: (use-package sly
      2:   :ensure
      3:   :commands sly-autoloads
      4:   :hook ((lisp-mode-local-vars . rainbow-delimiters-mode)
      5:          (lisp-mode . sly-editing-mode))
      6:   :config
      7:   (require 'sly-autoloads))
      
    • sly-stepper   disabled
      1: (use-package sly-stepper
      2:   :disabled
      3:   :ensure nil
      4:   :after sly
      5:   :config
      6:   (require 'sly-stepper-autoloads)
      7:   (add-to-list 'sly-contribs 'sly-stepper 'append))
      
    • sly-quicklisp   disabled
      1: (use-package sly-quicklisp
      2:   :disabled
      3:   :ensure t
      4:   :after sly
      5:   :config
      6:   (require 'sly-quicklisp-autoloads)
      7:   (add-to-list 'sly-contribs 'sly-quicklisp 'append))
      
    • sly-macrostep   disabled
      1: (use-package sly-macrostep
      2:   :ensure t
      3:   :disabled
      4:   :after sly
      5:   :config
      6:   (require 'sly-macrostep-autoloads))
      
    • sly-asdf   disabled
      1: (use-package sly-asdf
      2:   :ensure
      3:   :disabled
      4:   :after sly
      5:   :config
      6:   (add-to-list 'sly-contribs 'sly-asdf 'append))
      
    • 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))
      
  • clojure
    • cider
      1: ;;;; clojure
      2: (use-package cider
      3:   :ensure
      4:   :defer t)
      
    • clj-refactor
      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
       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
       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
      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 disabled
     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

  • nxml-mode   builtin disabled
    1: (use-package nxml-mode
    2:   :mode "\\.p\\(?:list\\|om\\)\\'" ; plist, pom
    3:   :mode "\\.xs\\(?:d\\|lt\\)\\'"   ; xslt, xsd
    4:   :mode "\\.rss\\'"
    5:   :config
    6:   (setq nxml-slash-auto-complete-flag t
    7:         nxml-auto-insert-xml-declaration-flag t))
    

YAML

  • yaml-mode   disabled
     1: (use-package yaml-mode
     2:   :ensure
     3:   :defer t
     4:   :config
     5:   (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode))
     6:   (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode))
     7:   (setq tab-width 2)
     8:   ;; (when (treesit-available-p)
     9:   ;;   (add-to-list 'major-mode-remap-alist '(yaml-mode . yaml-ts-mode)))
    10:   :hook
    11:   ((yaml-mode . (lambda ()
    12:                   (define-key yaml-mode-map "\C-m" 'newline-and-indent)))
    13:    (yaml-mode . (lambda ()
    14:                   (run-hooks 'prog-mode-hook)))))
    

TOML

  • toml-mode   disabled
     1: (use-package toml-mode
     2:   :ensure
     3:   :defer t
     4:   :mode
     5:   ("\\.toml\\'" . toml-mode)
     6:   :config
     7:   ;; (when (treesit-available-p)
     8:   ;;    (add-to-list 'major-mode-remap-alist '(toml-mode . toml-ts-mode)))
     9:   (with-eval-after-load 'lsp-mode
    10:     (setq lsp-toml-command (executable-find "taplo")))
    11:   (add-to-list 'lsp-language-id-configuration '("\\.toml$" . "toml")))
    

Lua

  • lua-mode   disabled
    1: (use-package lua-mode
    2:   :ensure
    3:   :defer t
    4:   :config
    5:   (with-eval-after-load 'lsp-mode
    6:     (setq lsp-lua-hint-enable t
    7:           lsp-lua-hint-set-type t)))
    

Jinja2

  • jinja2-mode   disabled
     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)))
    

json

  • json-mode   builtin disabled
    1: (use-package json-mode
    2:   :ensure nil
    3:   :defer t)
    

Web mode

  • web-mode   disabled
     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:     "K" '(lsp-describe-thing-at-point :wk "describe thing at point"))
    92:   (general-nvmap
    93:     :keymaps 'web-mode-map
    94:     "gn" 'web-mode-navigate)
    95:   (general-vmap
    96:     :keymaps 'web-mode-map
    97:     "gs" 'web-mode-surround))
    
  • emmet-mode   disabled
     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   disabled
    1: (use-package skewer-mode
    2:   :ensure
    3:   :defer t
    4:   :hook ((web-mode . skewer-html-mode)
    5:          (js2-mode . skewer-mode)))
    
  • lsp-tailwindcss   disabled
    1: (use-package lsp-tailwindcss
    2:   :ensure
    3:   :defer t
    4:   :init
    5:   (setq lsp-tailwindcss-add-on-mode t))
    
  • sass-mode   disabled
    1: (use-package sass-mode
    2:   :ensure
    3:   :defer t
    4:   :hook (scss-mode . rainbow-mode))
    
  • css-eldoc   disabled
    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   disabled
    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   builtin disabled
    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   disabled
      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   disabled
     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" "$")))
    
  • xref-js2   disabled
    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))))
    
  • js2-refactor   disabled
     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   disabled
     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))
    
  • typescript-mode   disabled
     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   disabled
     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   disabled
    1: (use-package npm-mode
    2:   :ensure
    3:   :defer t)
    
  • nodejs-repl   disabled
    1: (use-package nodejs-repl
    2:   :ensure
    3:   :defer t)
    

Latex

  • auctex   builtin disabled
     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   builtin disabled
    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   builtin disabled
    1: (use-package reftex
    2:   :ensure nil
    3:   :commands turn-on-reftex
    4:   :init
    5:   (setq reftex-plug-into-AUCTeX t))
    
  • bibtex   builtin disabled
    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   disabled
     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

  • markdown-mode   disabled
      1: ;; autoloads (from doom)
      2:   ;;; Compilation handlers
      3: 
      4:   ;;;###autoload
      5: (cond
      6:  ((and (boundp 'transient-mark-mode) (boundp 'mark-active))
      7:   (defun markdown-use-region-p ()
      8:     "Compatibility wrapper to provide `use-region-p'."
      9:     (and transient-mark-mode mark-active))))
     10: 
     11:   ;;;###autoload
     12: (defun +markdown-compile (beg end output-buffer)
     13:   "Compile markdown into html.
     14: 
     15:   Runs `+markdown-compile-functions' until the first function to return non-nil,
     16:   otherwise throws an error."
     17:   (or (run-hook-with-args-until-success '+markdown-compile-functions
     18:                                         beg end output-buffer)
     19:       (user-error "No markdown program could be found. Install marked, pandoc, markdown or multimarkdown.")))
     20: 
     21:   ;;;###autoload
     22: (defun +markdown-compile-marked (beg end output-buffer)
     23:   "Compiles markdown with the marked program, if available.
     24:   Returns its exit code."
     25:   (when (executable-find "marked")
     26:     (apply #'call-process-region
     27:            beg end "marked" nil output-buffer nil
     28:            (when (eq major-mode 'gfm-mode)
     29:              (list "--gfm" "--tables" "--breaks")))))
     30: 
     31:   ;;;###autoload
     32: (defun +markdown-compile-pandoc (beg end output-buffer)
     33:   "Compiles markdown with the pandoc program, if available.
     34:   Returns its exit code."
     35:   (when (executable-find "pandoc")
     36:     (call-process-region beg end "pandoc" nil output-buffer nil
     37:                          "-f" "markdown"
     38:                          "-t" "html"
     39:                          "--mathjax"
     40:                          "--highlight-style=pygments")))
     41: 
     42:   ;;;###autoload
     43: (defun +markdown-compile-multimarkdown (beg end output-buffer)
     44:   "Compiles markdown with the multimarkdown program, if available. Returns its
     45:   exit code."
     46:   (when (executable-find "multimarkdown")
     47:     (call-process-region beg end "multimarkdown" nil output-buffer)))
     48: 
     49:   ;;;###autoload
     50: (defun +markdown-compile-markdown (beg end output-buffer)
     51:   "Compiles markdown using the Markdown.pl script (or markdown executable), if
     52:   available. Returns its exit code."
     53:   (when-let (exe (or (executable-find "Markdown.pl")
     54:                      (executable-find "markdown")))
     55:     (call-process-region beg end exe nil output-buffer nil)))
     56: 
     57: (defvar +markdown-compile-functions
     58:   '(+markdown-compile-marked
     59:     +markdown-compile-pandoc
     60:     +markdown-compile-markdown
     61:     +markdown-compile-multimarkdown)
     62:   "A list of commands to try when attempting to build a markdown file with
     63:   `markdown-open' or `markdown-preview', stopping at the first one to return non-nil.
     64: 
     65:   Each function takes three argument. The beginning position of the region to
     66:   capture, the end position, and the output buffer.")
     67: 
     68:   ;;;###autoload
     69: (defun +markdown/insert-del ()
     70:   "Surround region in github strike-through delimiters."
     71:   (interactive)
     72:   (let ((regexp "\\(^\\|[^\\]\\)\\(\\(~\\{2\\}\\)\\([^ \n       \\]\\|[^ \n     ]\\(?:.\\|\n[^\n]\\)*?[^\\ ]\\)\\(\\3\\)\\)")
     73:         (delim "~~"))
     74:     (if (markdown-use-region-p)
     75:         ;; Active region
     76:         (cl-destructuring-bind (beg . end)
     77:             (markdown-unwrap-things-in-region
     78:              (region-beginning) (region-end)
     79:              regexp 2 4)
     80:           (markdown-wrap-or-insert delim delim nil beg end))
     81:       ;; Bold markup removal, bold word at point, or empty markup insertion
     82:       (if (thing-at-point-looking-at regexp)
     83:           (markdown-unwrap-thing-at-point nil 2 4)
     84:         (markdown-wrap-or-insert delim delim 'word nil nil)))))
     85: 
     86: (use-package markdown-mode
     87:   :ensure
     88:   :mode ("README\\.md\\'" . gfm-mode)
     89:   :mode ("\\.\\(?:md\\|markdown\\|mkd\\|mdown\\|mkdn\\|mdwn\\)\\'" . markdown-mode)
     90:   :hook (markdown-mode . lsp-deferred)
     91:   :defer t
     92:   :init
     93:   (require 'lsp-marksman)
     94:   (cond
     95:    ((executable-find "xdg-open")
     96:     (setq markdown-open-command "xdg-open")))
     97:   (cond ((executable-find "markdown")
     98:          (setq markdown-command "markdown"))
     99:         ((executable-find "multimarkdown")
    100:          (setq markdown-command "multimarkdown"))
    101:         ((executable-find "marked")
    102:          (setq markdown-command "marked")))
    103:   (setq markdown-enable-math t
    104:         markdown-enable-wiki-links t
    105:         markdown-italic-underscore t
    106:         markdown-asymmetric-header t
    107:         markdown-gfm-additional-languages '("sh")
    108:         markdown-make-gfm-checkboxes-buttons t
    109:         markdown-fontify-whole-heading-line t
    110:         markdown-nested-imenu-heading-index (not (ignore-errors (native-comp-available-p)))
    111:         markdown-command #'+markdown-compile
    112:         markdown-content-type "application/xhtml+xml"
    113:         markdown-css-paths
    114:         '("https://cdn.jsdelivr.net/npm/github-markdown-css/github-markdown.min.css"
    115:           "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/github.min.css")
    116:         markdown-xhtml-header-content
    117:         (concat "<meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'>"
    118:                 "<style> body { box-sizing: border-box; max-width: 740px; width: 100%; margin: 40px auto; padding: 0 10px; } </style>"
    119:                 "<script id='MathJax-script' async src='https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'></script>"
    120:                 "<script src='https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js'></script>"
    121:                 "<script>document.addEventListener('DOMContentLoaded', () => { document.body.classList.add('markdown-body'); document.querySelectorAll('pre[lang] > code').forEach((code) => { code.classList.add(code.parentElement.lang); }); document.querySelectorAll('pre > code').forEach((code) => { hljs.highlightBlock(code); }); });</script>"))
    122:   (with-eval-after-load 'org-src
    123:     (add-to-list 'org-src-lang-modes '("md" . markdown)))
    124:   :config
    125:   (with-eval-after-load 'smartparens
    126:     (sp-local-pair 'markdown-mode "-" "-" :actions '(wrap))
    127:     (sp-local-pair '(markdown-mode gfm-mode) "`" "`"
    128:                    :unless '(:add sp-point-before-word-p sp-point-before-same-p)))
    129:   (with-eval-after-load 'rustic-mode
    130:     (add-to-list 'markdown-code-lang-modes '("rust" . rustic-mode)))
    131:   :general
    132:   (+config/local-leader
    133:     :keymaps 'markdown-mode-map
    134:     "i" '(:ignore t :wk "insert")
    135:     "d" '(markdown-do :wk "do checklist")
    136:     "ib" '(markdown-insert-bold :wk "insert bold")
    137:     "ic" '(markdown-insert-code :wk "insert code")
    138:     "iC" '(markdown-insert-gfm-code-block :wk "insert gfm code block")
    139:     "iF" '(markdown-insert-foldable-block :wk "insert foldable block")
    140:     "if" '(markdown-insert-footnote :wk "insert footnote")
    141:     "ig" '(markdown-insert-gfm-checkbox :wk "insert gfm checkbox")
    142:     "ih" '(markdown-insert-header :wk "insert header")
    143:     "iI" '(markdown-insert-image :wk "insert image")
    144:     "ii" '(markdown-insert-italic :wk "insert italic")
    145:     "ij" '(markdown-insert-list-item :wk "insert list items")
    146:     "ik" '(markdown-insert-kbd :wk "insert kbd")
    147:     "il" '(markdown-insert-link :wk "insert link")
    148:     "ip" '(markdown-insert-pre :wk "insert pre")
    149:     "ir" '(markdown-insert-hr :wk "insert horizontal ruler")
    150:     "is" '(markdown-insert-strike-through :wk "insert strike-through")
    151:     "it" '(markdown-insert-table :wk "insert table")
    152:     "iu" '(markdown-insert-url :wk "insert url")
    153:     "iw" '(markdown-insert-wiki-link :wk "insert wikilink")
    154:     "iq" '(markdown-insert-blockquote :wk "insert block quote")
    155:     "m" '(:ignore t :wk "move")
    156:     "m M-j" '(markdown-move-subtree-down :wk "move subtree down")
    157:     "m M-k" '(markdown-move-subtree-up :wk "move subtree up")
    158:     "m C-k" '(markdown-move-list-item-down :wk "move list item down")
    159:     "m C-k" '(markdown-move-list-item-up :wk "move list item up")
    160:     "mj" '(markdown-move-down :wk "move down things at point")
    161:     "mk" '(markdown-move-up :wk "move up things at point")
    162:     "t" '(:ignore t :wk "toggle")
    163:     "ti" '(markdown-toggle-inline-images :wk "toggle inline images")
    164:     "tf" '(markdown-toggle-fontify-code-blocks-natively :wk "toggle fontify code")
    165:     "tG" '(markdown-toggle-gfm-checkbox-button :wk "toggle gfm checkbox button")
    166:     "tg" '(markdown-toggle-gfm-checkbox :wk "toggle gfm checkbox")
    167:     "tM" '(markdown-toggle-markup-hiding :wk "toggle markup hiding")
    168:     "tm" '(markdown-toggle-math :wk "toggle math")
    169:     "tu" '(markdown-toggle-url-hiding :wk "toggle url hiding")
    170:     "tw" '(markdown-toggle-wiki-links :wk "toggle wiki links"))
    171: 
    172:   (+config/local-leader
    173:     :keymaps 'markdown-mode-map
    174:     :states 'visual
    175:     "r" '(:ignore t :wk "region actions")
    176:     "rq" '(markdown-blockquote-region :wk "block quote region")
    177:     "rp" '(markdown-pre-region :wk "pre region"))
    178: 
    179:   (general-nvmap
    180:     :keymaps 'markdown-mode-map
    181:     "gb" '(markdown-outline-previous-same-level :wk "previous same level")
    182:     "gf" '(markdown-outline-next-same-level :wk "next same level")
    183:     "gn" '(markdown-outline-next :wk "outline next")
    184:     "gp" '(markdown-outline-previous :wk "outline previous")
    185:     "z-" '(markdown-promote :wk "pronote")
    186:     "z=" '(markdown-demote :wk "demote")
    187:     "z<" '(markdown-outdent-region :wk "outdent region")
    188:     "z>" '(markdown-indent-region :wk "indent region")
    189:     "zj" '(markdown-move-down :wk "move up")
    190:     "zk" '(markdown-move-up :wk "move up")
    191:     "zt" '(:ignore t :wk "table")
    192:     "ztj" '(markdown-table-insert-row :wk "insert row")
    193:     "ztl" '(markdown-table-insert-column :wk "insert-column"))
    194: 
    195:   (general-def
    196:     :keymaps 'markdown-mode-map
    197:     "M-h" '(markdown-promote-subtree :wk "promote subtree")
    198:     "M-S-h" '(markdown-promote :wk "promote")
    199:     "M-l" '(markdown-demote-subtree :wk "demote subtree")
    200:     "M-S-l" '(markdown-demote :wk "demote")))
    
  • edit-indirect   disabled
    1: (use-package edit-indirect
    2:   :ensure
    3:   :after markdown-mode)
    

Python

  • python   builtin disabled
     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 `(("/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:   (general-nvmap
    51:     :keymaps 'python-mode-map
    52:     "K" 'lsp-describe-thing-at-point)
    53: 
    54:   (+config/local-leader
    55:     :keymaps 'python-mode-map
    56:     "d" '(:ignore t :wk "doc")))
    

    System Packages:

    • mypy
    • python-black
    • autopep8
    • flake8
    • python-pycodestyle
    • python-pydocstyle
    • python-pylint
    • python-pyflakes
    • yapf

    Note: you don't have to install them all, only what you'll going to use.

  • pydoc   disabled
    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   disabled
    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   disabled
    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   builtin disabled
    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   disabled
     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   disabled
    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   disabled
     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")))
    
  • flycheck-pycheckers   disabled
    1: (use-package flycheck-pycheckers
    2:   :ensure
    3:   :config
    4:   (with-eval-after-load 'flycheck
    5:     (add-hook 'flycheck-mode-hook #'flycheck-pycheckers-setup)))
    
  • ein   disabled
    1: (use-package ein
    2:   :ensure t)
    

Rust

  • rust-mode   disabled
     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   disabled
     1: (use-package rustic
     2:   :ensure
     3:                                         ;defer t
     4:   :mode ("\\.rs$" . rustic-mode)
     5:   :init
     6:   (with-eval-after-load 'rustic-flycheck
     7:     (remove-hook 'rustic-mode-hook #'flycheck-mode)
     8:     (remove-hook 'rustic-mode-hook #'flymake-mode-off)
     9:     (remove-hook 'flycheck-mode-hook #'rustic-flycheck-setup))
    10:   (with-eval-after-load 'org-src
    11:     (defalias 'org-babel-execute:rust #'org-babel-execute:rustic))
    12:   :config
    13:   (add-hook 'rustic-mode-hook #'rainbow-delimiters-mode)
    14:   (setq rustic-indent-method-chain t
    15:         rustic-lsp-client 'lsp-mode)
    16:   (add-hook 'rustic-mode-local-vars-hook #'rustic-setup-lsp 'append)
    17:   (add-hook 'rustic-mode-local-vars-hook #'flycheck-mode)
    18:   ;; (add-hook 'rustic-mode-local-vars-hook #'tree-sitter! 'append)
    19:   (with-eval-after-load 'lsp
    20:     (setq lsp-rust-analyzer-display-parameter-hints t))
    21:   (with-eval-after-load 'general
    22:     (general-nvmap
    23:       :keymaps '(rustic-mode-map lsp-mode-map)
    24:       "K" 'lsp-describe-thing-at-point)))
    
  • flycheck-rust   disabled
    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 package   disabled
     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   disabled
    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

  • cperl-mode   disabled
    1: (use-package cperl-mode
    2:   :ensure
    3:   :defer t
    4:   :mode ("\\.\\([pP][Llm]\\|al\\)\\'" . cperl-mode))
    

Haskell

  • haskell-mode   disabled
     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))
    11: 
    12: (use-package lsp-haskell
    13:   :ensure t
    14:   :defer t
    15:   :after lsp)
    

EXWM

Script

  • Allow connection to the X server
    xhost +
    
  • run xinit
    xinit
    
  • set wmname

    Needs the package wmname

    wmname LG3D
    
  • start emacs with dbus
    exec dbus-launch --exit-with-session emacs --eval "(exwm-enable)"
    

Desktop File

This should be placed in /usr/share/xsessions with the name exwm.desktop

[Desktop Entry]
Name=EXWM
Comment=Emacs Window Manager
Exec=exwm-start
Type=Application

the package

  • desktop-environment
     1: (use-package desktop-environment
     2:   :ensure
     3:   :commands (desktop-environment-music-next )
     4:   :after exwm
     5:   :init
     6:   (customize-set-variable 'desktop-environment-brightness-small-increment "1%+")
     7:   (customize-set-variable 'desktop-environment-brightness-small-decrement "1%-")
     8:   (customize-set-variable 'desktop-environment-brightness-normal-increment "1%+")
     9:   (customize-set-variable 'desktop-environment-brightness-normal-decrement "1%-")
    10:   (customize-set-variable 'desktop-environment-volume-normal-decrement "1%-")
    11:   (customize-set-variable 'desktop-environment-volume-normal-increment "1%+")
    12:   (customize-set-variable 'desktop-environment-screenshot-command "flameshot gui")
    13:   (customize-set-variable 'desktop-environment-screenshot-directory (expand-file-name "Screenshots/" (getenv "XDG_PICTURES_DIR")))
    14:   (unless (file-directory-p desktop-environment-screenshot-directory)
    15:     (make-directory desktop-environment-screenshot-directory :parents))
    16:   (if (featurep 'emms)
    17:       (progn
    18:         (customize-set-variable 'desktop-environment-music-next-command nil)
    19:         (customize-set-variable 'desktop-environment-music-previous-command nil)
    20:         (customize-set-variable 'desktop-environment-music-stop-command nil)
    21:         (customize-set-variable 'desktop-environment-music-toggle-command nil)
    22:         ;; (define-key desktop-environment-mode-map (kbd "<XF86AudioNext>") #'emms-next)
    23:         ;; (define-key desktop-environment-mode-map (kbd "<XF86AudioPrev>") #'emms-previous)
    24:         ;; (define-key desktop-environment-mode-map (kbd "<XF86AudioPlay>") #'emms-pause)
    25:         (global-set-key (kbd "M-s-<f12>") #'emms-next)
    26:         (global-set-key (kbd "M-s-<f11>") #'emms-pause)
    27:         (global-set-key (kbd "M-s-<f10>") #'emms-previous)
    28:         (global-set-key (kbd "M-s-<f9>") 'desktop-environment-volume-increment)
    29:         (global-set-key (kbd "M-s-<f8>") 'desktop-environment-volume-decrement)
    30:         (global-set-key (kbd "M-s-<f7>") 'desktop-environment-toggle-mute))
    31:     (progn
    32:       (global-set-key (kbd "M-s-<f12>") 'desktop-environment-music-next)
    33:       (global-set-key (kbd "M-s-<f11>") 'desktop-environment-toggle-music)
    34:       (global-set-key (kbd "M-s-<f10>") 'desktop-environment-music-previous)
    35:       (global-set-key (kbd "M-s-<f9>") 'desktop-environment-volume-increment)
    36:       (global-set-key (kbd "M-s-<f8>") 'desktop-environment-volume-decrement)
    37:       (global-set-key (kbd "M-s-<f7>") 'desktop-environment-toggle-mute)))
    38:   (desktop-environment-mode))
    
  • perspective-exwm
     1: (use-package perspective-exwm
     2:   :ensure
     3:   :after perspective exwm
     4:   :config
     5:   (setq perspective-exwm-override-initial-name
     6:         '((0 . "Term")
     7:           (1 . "Dev")
     8:           (2 . "Web")
     9:           (3 . "Mail")
    10:           (4 . "Files")
    11:           (5 . "Multimedia")
    12:           (6 . "Remotes")
    13:           (7 . "Games")
    14:           (8 . "Work")
    15:           (9 . "Others"))))
    
  • exwm-modeline
    1: (use-package exwm-modeline
    2:   :ensure
    3:   :after exwm)
    
  • exwm
      1: (use-package exwm
      2:   :ensure
      3:   :demand t ; prevent automatic deferred loading.
      4:   :preface ; runs before everything except :disabled.
      5:   (menu-bar-mode -1)
      6:   (tool-bar-mode -1)
      7:   (scroll-bar-mode -1)
      8:   (fringe-mode 1)
      9: 
     10:   (require 'time)
     11:   (setq display-time-default-load-average nil)
     12:   (customize-set-variable 'display-time-24hr-format t)
     13:   (customize-set-variable 'display-time-day-and-date t)
     14:   (display-time-mode 1)
     15: 
     16:   (if (and (fboundp 'server-running-p)
     17:            (not (server-running-p)))
     18:       (server-start))
     19: 
     20:   :init ; runs before `exwm' is loaded.
     21:   (require 'exwm-modeline)
     22:   (require 'battery)
     23:   (with-eval-after-load 'battery
     24:     (when
     25:         (or
     26:          (eq battery-status-function
     27:              'battery-upower)
     28:          (eq battery-status-function
     29:              'battery-bsd-apm)
     30:          (eq battery-status-function
     31:              'battery-linux-sysfs)
     32:          (eq battery-status-function
     33:              'battery-linux-proc-apm)
     34:          (eq battery-status-function
     35:              'battery-linux-proc-acpi))
     36:       (display-battery-mode)))
     37: 
     38:   (unless (equal persp-mode t)
     39:     (persp-mode))
     40: 
     41:   (setenv "GPG_AGENT_INFO" nil)  ;; use emacs pinentry
     42: 
     43:   (when (featurep 'corfu)
     44:     (advice-add #'corfu--make-frame :around
     45:                 (defun +corfu--make-frame-a (oldfun &rest args)
     46:                   (cl-letf (((symbol-function #'frame-parent)
     47:                              (lambda (frame)
     48:                                (or (frame-parameter frame 'parent-frame)
     49:                                    exwm-workspace--current))))
     50:                     (apply oldfun args))
     51:                   (when exwm--connection
     52:                     (set-frame-parameter corfu--frame 'parent-frame nil))))
     53: 
     54:     (advice-add #'corfu--popup-redirect-focus :override
     55:                 (defun +corfu--popup-redirect-focus-a ()
     56:                   (redirect-frame-focus corfu--frame
     57:                                         (or (frame-parent corfu--frame)
     58:                                             exwm-workspace--current)))))
     59: 
     60:   (defun +config-exwm--init-hook ()
     61:     "Things that should run after initialization."
     62:     (+config-exwm--run-in-background "dbus-update-activation-environment --systemd --all")
     63:     (+config-exwm--run-in-background "xrdb -merge ~/.Xresources")
     64:     (+config-exwm--run-in-background "xsetroot -cursor_name left_ptr")
     65:     (+config-exwm--run-in-background "xset r rate 300 30")
     66:     (+config-exwm--run-in-background "nm-applet --indicator")
     67:     (+config-exwm--run-in-background "/usr/lib/polkit-kde-authentication-agent-1")
     68:     (+config-exwm--run-in-background "picom")
     69:     (+config-exwm--run-in-background "udiskie -t")
     70:     (+config-exwm--run-in-background "dunst -conf ~/.config/dunst/dunstrc")
     71:     (+config-exwm--run-in-background "wal --theme solarized")
     72:     (+config-exwm--run-in-background "blueman-applet")
     73:     (+config-exwm--run-in-background "volumeicon")
     74:     (+config-exwm--run-in-background "xsettingsd")
     75:     (+config-exwm--run-in-background "unclutter")
     76:     (+config-exwm--run-in-background "greenclip daemon>/dev/null")
     77:     (+config-exwm--run-in-background "kdeconnect-indicator")
     78:     (+config-exwm--run-in-background "/usr/lib/geoclue-2.0/demos/agent"))
     79: 
     80:   :config ; runs after `exwm' is loaded
     81:   (defun +config-exwm--fix-exwm-floating-windows ()
     82:     "Fix behaviour when switching to floating."
     83:     (setq-local exwm-workspace-warp-cursor nil)
     84:     (setq-local mouse-autoselect-window nil)
     85:     (setq-local focus-follows-mouse nil))
     86: 
     87:   (defun +config-exwm--fix-exwm-title ()
     88:     "Rename buffer name with exwm-title."
     89:     (when (or (not exwm-instance-name)
     90:               (string-prefix-p "sun-awt-X11-" exwm-instance-name)
     91:               (string= "gimp" exwm-instance-name))
     92:       (exwm-workspace-rename-buffer exwm-title)))
     93: 
     94:   (defun +config-exwm--rename-buffer-to-class-name ()
     95:     "Rename workspace buffer to `exwm-class-name'."
     96:     (exwm-workspace-rename-buffer exwm-class-name))
     97: 
     98:   (defmacro +config-exwm--raise-or-run (prog)
     99:     "Run program or raise if already ran."
    100:     (let ((Prog (capitalize prog)))
    101:       `(defun ,(intern (format "run-or-rise-%s" prog)) ()
    102:          ,(format "Run or rise %s" Prog)
    103:          (interactive)
    104:          (if (string= (buffer-name) ,Prog)
    105:              (bury-buffer)
    106:            (if (get-buffer ,Prog)
    107:                (exwm-workspace-switch-to-buffer ,Prog)
    108:              (start-process ,prog nil ,prog))))))
    109: 
    110:   (defun +config-exwm--run-in-background (command)
    111:     "Run COMMAND in background if exists."
    112:     (let ((command-parts (split-string command "[ ]+")))
    113:       (when (executable-find (car command-parts))
    114:         (apply #'call-process `(,(car command-parts) nil 0 nil ,@(cdr command-parts))))))
    115: 
    116:   (defun +config-exwm--exwm-logout ()
    117:     "Logout cleanly from EXWM."
    118:     (interactive)
    119:     (recentf-save-list)
    120:     (save-some-buffers)
    121:     (save-buffers-kill-terminal))
    122: 
    123:   (defun +config-exwm--rofi-launcher ()
    124:     "Run rofi."
    125:     (interactive)
    126:     (+config-exwm--run-in-background "rofi -show drun -theme exwm"))
    127: 
    128:   (defun +config-exwm--greenclip-launcher ()
    129:     "Run greenclip."
    130:     (interactive)
    131:     (+config-exwm--run-in-background "rofi-greenclip exwm"))
    132: 
    133:   (defun +config-exwm--setup-header-line-format ()
    134:     "Hide header line if required."
    135:     (set-window-parameter (next-window) 'header-line-format
    136:                           (unless (window-at-side-p (next-window) 'top)
    137:                             'none))) (defvar +config-exwm--exwm-workspace-switch-history-hack (cons exwm-workspace-current-index '()))
    138: 
    139:   (defun +config-exwm--set-current-workspace-index ()
    140:     "Set index of workspace in +CONFIG-EXWM--EXWM-WORKSPACE-SWITCH-HISTORY-HACK.
    141: Unless EXWM-WORKSPACE-CURRENT-INDEX is equal to +config-exwm--exwm-workspace-switch-history-hack."
    142:     (unless (= exwm-workspace-current-index (car +config-exwm--exwm-workspace-switch-history-hack))
    143:       (setq +config-exwm--exwm-workspace-switch-history-hack
    144:             (cons exwm-workspace-current-index
    145:                   (car +config-exwm--exwm-workspace-switch-history-hack)))))
    146: 
    147:   (defun +config-exwm--workspace-switch-to-last ()
    148:     "Switch to last visited workspace."
    149:     (interactive)
    150:     "Switch to the workspace that was used before current workspace"
    151:     (exwm-workspace-switch (cdr +config-exwm--exwm-workspace-switch-history-hack)))
    152: 
    153:   (defvar +config-exwm--simulation-key-window-classes
    154:     '(google-chrome firefox qutebrowser))
    155: 
    156:   (defun +config-exwm--local-simulation-key ()
    157:     "Simulation keys for certain classes."
    158:     (when (and exwm-class-name
    159:                (member exwm-class-name +config-exwm--simulation-key-window-classes))
    160:       (exwm-input-set-local-simulation-keys
    161:        '(([?\C-b] . [left])
    162:          ([?\M-b] . [C-left])
    163:          ([?\C-f] . [right])
    164:          ([?\M-f] . [C-right])
    165:          ([?\C-p] . [up])
    166:          ([?\C-n] . [down])
    167:          ([?\C-a] . [home])
    168:          ([?\C-e] . [end])
    169:          ([?\M-v] . [prior])
    170:          ([?\C-v] . [next])
    171:          ([?\C-d] . [delete])
    172:          ;;([?\C-k] . [S-end delete])
    173:          ([?\C-w] . [?\C-x])
    174:          ([?\M-w] . [?\C-c])
    175:          ([?\C-y] . [?\C-v])
    176:          ([?\C-c ?\C-c] . [?\C-c])
    177:          ([?\C-w ?\C-w] . [?\C-w])
    178:          ([?\C-v ?\C-v] . [?\C-v])
    179:          ([?\C-s] . [?\C-f])))))
    180: 
    181:   (setq exwm-workspace-show-all-buffers nil ; keep buffers per workspace
    182:         exwm-workspace-warp-cursor t ; after workspace switch
    183:         mouse-autoselect-window t ; like any other tiling window manager
    184:         focus-follows-mouse nil
    185:         exwm-workspace-number 10)
    186: 
    187:   (setq exwm-manage-configurations
    188:         ;; workspace 0 reserved for terminal emulators
    189:         '(((string= exwm-class-name "Xterm")
    190:            char-mode t workspace 0)
    191:           ((string= exwm-class-name "Termite")
    192:            char-mode t workspace 0)
    193:           ((string= exwm-class-name "URxvt")
    194:            char-mode t workspace 0)
    195:           ((string= exwm-class-name "Gnome-terminal")
    196:            char-mode t workspace 0)        ;; windows 1 is exclusively for `Emacs'
    197:           ;; windows 2 is for web browsers
    198:           ((string= exwm-class-name "firefox")
    199:            char-mode t workspace 2)
    200:           ((string= exwm-class-name "Nyxt")
    201:            char-mode t workspace 2)
    202:           ((string= exwm-class-name "qutebrowser")
    203:            char-mode t workspace 2)
    204:           ;; workspace 3 for mail apps
    205:           ((string= exwm-class-name "thunderbird")
    206:            char-mode t workspace 3)
    207:           ((string= exwm-class-name "Mail")
    208:            char-mode t workspace 3)
    209:           ;; workspace 4 is for files
    210:           ((string= exwm-class-name "Thunar")
    211:            char-mode t workspace 4)
    212:           ;; workspace 5 for multimedia
    213:           ((string= exwm-class-name "Spotify")
    214:            char-mode t workspace 5)
    215:           ((string= exwm-class-name "Cheese")
    216:            char-mode t workspace 5)
    217:           ((string= exwm-class-name "Picard")
    218:            char-mode t workspace 5)
    219:           ((string= exwm-class-name "hakuneko-desktop")
    220:            char-mode t workspace 5)
    221:           ((string= exwm-class-name "mpv")
    222:            char-mode t workspace 5)
    223:           ((string= exwm-class-name "vlc")
    224:            char-mode t workspace 5)
    225:           ((string= exwm-class-name "Gimp")
    226:            char-mode t workspace 5)
    227:           ;; workspace 6 for Network apps
    228:           ((string= exwm-class-name "Org.remmina.Remmina")
    229:            char-mode t workspace 6)
    230:           ((string= exwm-class-name "Virt-manager")
    231:            char-mode t workspace 6)
    232:           ((string= exwm-class-name "Vncviewer")
    233:            char-mode t workspace 6)
    234:           ;; workspace 7 for Games
    235:           ;; workspace 8 for work
    236:           ((string= exwm-class-name "TelegramDesktop")
    237:            char-mode t workspace 8)
    238:           ((string= exwm-class-name "libreoffice-startcenter")
    239:            char-mode t workspace 8)
    240:           ((string= exwm-class-name "libreoffice-calc")
    241:            char-mode t workspace 8)
    242:           ((string= exwm-class-name "libreoffice-draw")
    243:            char-mode t workspace 8)
    244:           ((string= exwm-class-name "libreoffice-math")
    245:            char-mode t workspace 8)
    246:           ((string= exwm-class-name "libreoffice-writer")
    247:            char-mode t workspace 8)
    248:           ))
    249: 
    250:   (exwm-input-set-key (kbd "C-x C-c") '+config-exwm--exwm-logout)
    251: 
    252:   (setq exwm-input-global-keys
    253:         `(
    254:           ;; Bind "s-r" to exit char-mode and fullscreen mode.
    255:           ([?\s-r] . exwm-reset)
    256:           ;; Bind "s-w" to switch workspace interactively.
    257:           ([?\s-w] . exwm-workspace-switch)
    258:           ([?\s-q] . delete-window)
    259:           ([?\s-j] . perspective-exwm-cycle-exwm-buffers-forward)
    260:           ([?\s-J] . perspective-exwm-cycle-all-buffers-forward)
    261:           ([?\s-k] . perspective-exwm-cycle-exwm-buffers-backward)
    262:           ([?\s-K] . perspective-exwm-cycle-all-buffers-backward)
    263:           ([?\s-m] . exwm-layout-toggle-mode-line)
    264:           ;; Bind "s-0" to "s-9" to switch to a workspace by its index.
    265:           ,@(mapcar (lambda (i)
    266:                       `(,(kbd (format "s-%d" i)) .
    267:                         (lambda ()
    268:                           (interactive)
    269:                           (exwm-workspace-switch-create ,i))))
    270:                     (number-sequence 0 9))
    271:           ([s-tab] . +config-exwm--workspace-switch-to-last)
    272:           ([?\s-d] . +config-exwm--rofi-launcher)
    273:           ([?\s-c] . +config-exwm--greenclip-launcher)
    274:           ;; Bind "s-&" to launch applications ('M-&' also works if the output
    275:           ;; buffer does not bother you).
    276:           ([?\s-D] . (lambda (command)
    277:                        (interactive (list (read-shell-command "$ ")))
    278:                        (start-process-shell-command command nil command)))
    279:           ([s-f11] . exwm-layout-toggle-fullscreen)
    280:           ;; Bind "s-<f2>" to "slock", a simple X display locker.
    281:           ([s-f1] . (lambda ()
    282:                       (interactive)
    283:                       (start-process "" nil "/usr/bin/slock")))))
    284:   (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key)
    285:   (define-key exwm-mode-map (kbd "C-x C-x")
    286:               (lambda () (interactive) (exwm-input--fake-key ?\C-x)))
    287:   (define-key exwm-mode-map (kbd "C-c C-c")
    288:               (lambda () (interactive) (exwm-input--fake-key ?\C-c)))
    289: 
    290:   (with-eval-after-load 'all-the-icons
    291:     (add-to-list 'all-the-icons-mode-icon-alist
    292:                  '(exwm-mode all-the-icons-faicon "desktop"
    293:                              :height 1.0 :face all-the-icons-purple)))
    294:   (require 'exwm-randr)
    295:   (cond ((string= "somalia-minimal" system-name)
    296:          (progn
    297:            (setq exwm-randr-workspace-monitor-plist
    298:                  '(0 "eDP1" 1 "eDP1" 2 "eDP1" 3 "eDP1" 4 "HDMI-1"
    299:                      5 "HDMI-1" 6 "HDMI-1" 7 "HDMI-1" 8 "HDMI-1" 9 "HDMI-1")))))
    300:   (add-hook 'exwm-randr-screen-change-hook
    301:             (lambda ()
    302:               (+config-exwm--run-in-background "~/.fehbg")))
    303:   ;; (exwm-randr-refresh)
    304:   (exwm-randr-enable)
    305:   (require 'perspective-exwm)
    306:   (perspective-exwm-mode)
    307: 
    308:   (exwm-enable)
    309:   ;; Initialize EXWM
    310:   :hook
    311:   (exwm-init . +config-exwm--init-hook)
    312:   (exwm-init . exwm-modeline-mode)
    313:   ;; Normal hook run when an X window has been made floating
    314:   (exwm-floating-setup . +config-exwm--fix-exwm-floating-windows)
    315:   (exwm-floating-setup . exwm-layout-hide-mode-line)
    316:   ;; Normal hook run when window title is updated.
    317:   (exwm-update-title . +config-exwm--fix-exwm-title)
    318:   ;; Normal hook run when window class is updated.
    319:   (exwm-update-class . +config-exwm--rename-buffer-to-class-name)
    320:   ;; normal hook run after switching workspace.
    321:   (exwm-workspace-switch . +config-exwm--set-current-workspace-index)
    322:   (window-configuration-change . +config-exwm--setup-header-line-format)
    323:   (exwm-manage-finish . +config-exwm--local-simulation-key))
    
  • exwm-systemtray
    (use-package exwm-systemtray
      :after exwm
      :config
      (setq exwm-systemtray-height 12) ; default 16
      (exwm-systemtray-enable))
    

Footnotes:

Date: 2024-03-10 Sun 09:00

Author: Kristian Alexander P

Created: 2024-04-09 Tue 13:05