Files
steveandgitadmin 02a5e0df28 init: new dotfile configuration
Remove all org files using a new script to more config over, The old org
file configuaration were great but required org. This new version only
requires the scripts that is included in the repo.

The configuration are all done but have not ported the theming system
yet.

Signed-off-by: Steve Beaulac <steve@sagacity.ca>
Change-Id: I14cd7fe058a71c8ba9d6d35397dc8d7e6a6a6964
2026-03-02 13:26:21 -05:00

4602 lines
153 KiB
EmacsLisp
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;;;; post-init.el --- Init -*- no-byte-compile: t; lexical-binding: t; -*-
(add-to-list 'exec-path "~/.local/bin")
(add-to-list 'exec-path "~/bin")
(setq tls-checktrust t)
(setq gnutls-verify-error t)
(setq tab-always-indent 'complete)
(setq completion-cycle-threshold 3) ; Always show candidates in menu-bar-lines
(keymap-global-set "<remap> <list-buffers>" #'ibuffer-list-buffers)
;;(setq-default search-whitespace-regexp ".*")
(delete-selection-mode t) ; make typing override text selection
(setq bookmark-save-flag t
case-fold-search t
clean-buffer-list-delay-general t
dabrev-case-fold-search t
file-name-shadow-mode 1
help-window-select t
ns-use-native-fullscreen nil
save-abbrevs 'silent
save-interprogram-paste-before-kill t
select-active-regions t
set-mark-command-repeat-pop t
tooltip-delay 1.5
tooltip-use-echo-area t
view-read-only t)
;; (electric-indent-mode -1)
;;(setq next-error-message-highlight t)
;;(setq recenter-positions '(top middle bottom))
;;(setq visual-line-fringe-indicators '(left-curly-arrow right-curly-arrow))
(setq tab-bar-show nil)
(auto-compression-mode t)
(global-subword-mode t)
(global-so-long-mode t)
(global-hl-line-mode -1)
(setq display-line-numbers-type 'relative)
(setq display-line-numbers-grow-only t)
(global-display-line-numbers-mode 1)
(when (fboundp 'winner-mode)
(winner-mode 1))
;; show line numbers on the left side of a window
(pending-delete-mode t)
;;(toggle-save-place-globally 1)
(transient-mark-mode t)
(setq password-cache t
password-cache-expiry 3600)
(setq mode-require-final-newline 'visit-save)
(defvar sys-tools "/opt")
(if (eq system-type 'windows-nt)
(setq sys-tools "c:\\utils"))
(setq auth-sources
'((:source "~/.emacs.d/.authinfo.gpg")))
(require 'semantic/db-file)
(setq custom-file null-device)
;; TODO (advice-add 'jsonrpc--log-event :override #'ignore)
(add-hook 'before-save-hook 'whitespace-cleanup)
(use-package diminish
:ensure t
:config
(diminish 'lisp-interaction-mode " iElisp")
(diminish 'emacs-lisp-mode " Εlisp")
(diminish 'word-wrap-mode "Щ")
(diminish 'eldoc-mode))
(use-package general :ensure t)
(use-package which-key
:ensure t
:demand t
:diminish
:custom
(which-key-sort-order 'which-key-prefix-then-key-order)
(which-key-add-column-padding 2)
(which-key-popup-type 'side-window)
(which-key-max-display-columns nil)
(which-key-separator " ")
:config
(which-key-mode)
(which-key-setup-minibuffer))
(use-package xdg
:ensure nil
:config
(let ((backup-dir (expand-file-name "emacs/backup/" (xdg-data-home)))
(autosave-dir (expand-file-name "emacs/autosave/" (xdg-cache-home))))
(mkdir backup-dir t)
(mkdir autosave-dir t)
(setq backup-directory-alist
`(("." . ,backup-dir)))
(setq tramp-backup-directory-alist backup-directory-alist)
(setq auto-save-file-name-transforms
`((".*" ,autosave-dir t))))
(setq tramp-auto-save-directory
(expand-file-name "tramp-autosave/" (xdg-cache-home)))
;;(setq custom-file (expand-file-name "emacs/custom.el" (xdg-data-home)))
(setq auto-save-list-file-prefix (expand-file-name "emacs/auto-save-list/.saves-" (xdg-cache-home)))
(setq url-history-file (expand-file-name "emacs/url/history" (xdg-data-home)))
(setq save-place-file (expand-file-name "saveplace" (xdg-data-home))))
;;(setq-default line-spacing 0.12)
;(set-face-attribute 'default nil :family "0xProto" :height 130)
;(set-face-attribute 'fixed-pitch nil :family "0xProto" :height 130)
;(set-face-attribute 'fixed-pitch-serif nil :family "0xProto" :height 130)
;(set-face-attribute 'variable-pitch nil :family "0xProto" :height 130)
(set-face-attribute 'default nil :family "MonaspiceNe Nerd Font Mono" :height 130)
(set-face-attribute 'variable-pitch nil :family "MonaspiceRn Nerd Font Propo" :height 130)
(set-face-attribute 'fixed-pitch nil :family "MonaspiceAr Nerd Font Propo" :height 130)
(set-face-attribute 'fixed-pitch-serif nil :family "MonaspiceXe Nerd Font" :height 130)
;;(set-face-attribute 'variable-pitch nil :family "Monaspace Radon" :height 130)
;;(set-face-attribute 'fixed-pitch nil :family "Monaspace Argon" :height 130)
;;(set-face-attribute 'fixed-pitch-serif nil :family "Monaspace Xenon" :height 130)
(use-package mixed-pitch
:after org
:hook
(org-mode . mixed-pitch-mode))
(use-package all-the-icons
:ensure t
:defer t
:config
(defun unpackaged/disable-all-the-icons ()
"Disable all-the-icons."
(all-the-icons-dired-mode 0))
(defun unpackaged/restore-all-the-icons ()
"Restore all-the-icons."
(all-the-icons-dired-mode 1))
(advice-add 'wdired-change-to-wdired-mode
:before #'unpackaged/disable-all-the-icons)
(advice-add 'wdired-finish-edit
:after #'unpackaged/restore-all-the-icons)
(advice-add 'wdired-abort-changes
:after #'unpackaged/restore-all-the-icons))
(use-package all-the-icons-completion
:after (marginalia all-the-icons)
:hook (marginalia-mode . all-the-icons-completion-marginalia-setup)
:init
(all-the-icons-completion-mode))
(use-package all-the-icons-nerd-fonts
:after all-the-icons
:config
(all-the-icons-nerd-fonts-prefer))
(use-package telephone-line
:demand t
:ensure t
:config
(setq telephone-line-primary-left-separator 'telephone-line-gradient
telephone-line-secondary-left-separator 'telephone-line-nil
telephone-line-primary-right-separator 'telephone-line-gradient
telephone-line-secondary-right-separator 'telephone-line-nil)
(setq telephone-line-height 28
telephone-line-evil-use-short-tag t)
(setq telephone-line-lhs
'((evil . (telephone-line-evil-tag-segment))
(accent . (telephone-line-major-mode-segment
telephone-line-process-segment))
(nil . (telephone-line-project-segment))
(nil . (telephone-line-buffer-segment))))
(setq telephone-line-rhs
'((nil . (telephone-line-flymake-segment
telephone-line-misc-info-segment))
(evil . (telephone-line-vc-segment ))))
(telephone-line-mode t))
(use-package modus-themes
:ensure t
:defer t
:config
(setq modus-themes-italic-constructs t
modus-themes-bold-constructs t
modus-themes-mixed-fonts t
modus-themes-subtle-line-numbers nil
modus-themes-deuteranopia t
modus-themes-tabs-accented nil
modus-themes-variable-pitch-ui t
modus-themes-inhibit-reload t)
(setq modus-themes-fringes 'intense)
(setq modus-themes-lang-checkers '(straight-underline text-also))
;(setq modus-themes-mode-line '(borderless (padding . 4) (height . 1.1)))
(setq modus-themes-markup '(background italic intense))
(setq modus-themes-syntax '(yellow-comments green-strings alt-syntax))
(setq modus-themes-hl-line '(accented))
(setq modus-themes-paren-match '(bold intense))
(setq modus-themes-links '(neutral-underline background))
(setq modus-themes-prompts '(intense bold background))
(setq modus-themes-completions '((matches . (extrabold))
(selection . (semibold accented))
(popup . (accented intense))))
(setq modus-themes-mail-citations nil)
(setq modus-themes-region '(accented bg-only no-extend))
(setq modus-themes-diffs 'desaturated)
(setq modus-themes-org-blocks 'gray-background)
(setq modus-themes-org-agenda
'((header-block . (variable-pitch 1.3))
(header-date . (grayscale workaholic bold-today 1.1))
(event . (accented varied))
(scheduled . uniform)
(habit . traffic-light)))
(setq modus-themes-headings
'((0 . (variable-pitch rainbow 1.9))
(1 . (variable-pitch rainbow 1.8))
(2 . (variable-pitch rainbow 1.7))
(3 . (variable-pitch rainbow bold 1.6))
(t . (variable-pitch semilight 1.1))))
(setq modus-themes-scale-headings nil)
;;(modus-themes-load-themes)
;;(modus-themes-load-vivendi)
;;(modus-themes-load-operandi)
)
(use-package ef-themes
:ensure t
:defer t
:general
(private/set-leader-keys
"Tn" '(ef-themes-select-dark :wk "night")
"Td" '(ef-themes-select-light :wk "day"))
:config
(setq ef-themes-region '('intense no-extend neutral))
(setq ef-themes-headings ; read the manual's entry or the doc string
'((0 . (variable-pitch light 1.9))
(1 . (variable-pitch light 1.8))
(2 . (variable-pitch light 1.7))
(3 . (variable-pitch semilight 1.6))
(4 . (variable-pitch semilight 1.5))
(5 . (variable-pitch regular 1.4))
(6 . (variable-pitch regular 1.3))
(7 . (variable-pitch 1.2)) ; absence of weight means `bold'
(agenda-date . (semilight 1.5))
(agenda-structure . (variable-pitch light 1.9))
(t . (variable-pitch 1.1))))
(setq ef-themes-mixed-font t
ef-themes-variable-pitch-ui t)
(defun my-ef-themes-custom-faces ()
(modify-all-frames-parameters
`((right-divider-width . 1)
;(internal-border-width . 1)
(scroll-bar-width . 0)))
(ef-themes-with-colors
(custom-set-faces
`(aw-leading-char-face ((,c :height 3.5)))
`(header-line ((,c :box (:line-width 6 :color ,bg-main :style nil))))
`(header-line-highlight ((,c :box (:color ,bg-main))))
;;`(mode-line ((,c :box (:line-width 0 :color ,bg-main :style nil))))
;;`(mode-line-active ((,c :box (:line-width 0 :color ,bg-main :style nil))))
;;`(mode-line-highlight ((,c :box (:line-width 0 :color ,bg-main))))
;;`(mode-line-inactive ((,c :box (:line-width 0 :color ,bg-main :style nil))))
`(fringe ((t :background ,bg-main)))
`(window-divider ((,c :background ,bg-main :foreground ,bg-main)))
`(window-divider-first-pixel ((,c :background ,bg-main :foreground ,bg-main)))
`(window-divider-last-pixel ((,c :background ,bg-main :foreground ,bg-main)))
`(ocaml-help-face ((,c :foreground ,comment)))
`(ocaml-link-face ((,c :foreground ,link :background ,bg-main)))
`(peek-overlay-content-face ((,c :background ,bg-main))))))
;;(set-face-foreground 'window-divider-first-pixel (face-attribute 'default :foreground))
;;(set-face-foreground 'window-divider-last-pixel (face-attribute 'default :foreground))
(add-hook 'ef-themes-post-load-hook #'my-ef-themes-custom-faces)
;(add-to-list 'ef-themes-collection 'ef-monokai-pro)
;(add-to-list 'ef-themes-dark-themes 'ef-monokai-pro)
)
(with-eval-after-load 'ef-themes
(put 'ef-monokai-pro 'theme-properties (list :background-mode 'dark :kind 'color-scheme :family 'ef))
(add-to-list 'ef-themes-collection 'ef-monokai-pro)
(add-to-list 'ef-themes-dark-themes 'ef-monokai-pro)
)
(with-eval-after-load 'ef-themes
(put 'ef-catppuccin-mocha 'theme-properties (list :background-mode 'dark :kind 'color-scheme :family 'ef))
(add-to-list 'ef-themes-collection 'ef-catppuccin-mocha)
(add-to-list 'ef-themes-dark-themes 'ef-catppuccin-mocha)
)
(with-eval-after-load 'ef-themes
(put 'ef-catppuccin-macchiatto 'theme-properties (list :background-mode 'dark :kind 'color-scheme :family 'ef))
(add-to-list 'ef-themes-collection 'ef-catppuccin-macchiatto)
(add-to-list 'ef-themes-dark-themes 'ef-catppuccin-macchiatto)
(add-to-list 'ef-themes-light-themes 'ef-catppuccin-macchiatto))
(with-eval-after-load 'ef-themes
(put 'ef-catppuccin-frappe 'theme-properties (list :background-mode 'dark :kind 'color-scheme :family 'ef))
(add-to-list 'ef-themes-collection 'ef-catppuccin-frappe)
(add-to-list 'ef-themes-dark-themes 'ef-catppuccin-frappe)
)
(with-eval-after-load 'ef-themes
(put 'ef-catppuccin-latte 'theme-properties (list :background-mode 'light :kind 'color-scheme :family 'ef))
(add-to-list 'ef-themes-collection 'ef-catppuccin-latte)
(add-to-list 'ef-themes-light-themes 'ef-catppuccin-latte)
)
(ef-themes-select 'ef-dream)
;;(ef-themes-select 'ef-catppuccin-macchiatto)
;;(ef-themes-select 'ef-catppuccin-mocha)
;;(ef-themes-select 'ef-catppuccin-frappe)
;;(ef-themes-select 'ef-catppuccin-latte)
(use-package general
:ensure t
:commands (private/set-leader-keys)
:demand t
:config
(general-evil-setup t)
(general-def
[f5] #'compile
[f6] #'recompile)
(general-create-definer
private/set-leader-keys
:states '(normal insert visual emacs)
:prefix "SPC"
:global-prefix "C-SPC")
(general-def "C-h W" 'which-key-show-top-level)
(general-def "M-o" #'other-window
"M-O" #'tab-bar-switch-to-recent-tab)
(private/set-leader-keys
"f" '(:ignore t :which-key "find")
"s" '(:ignore t :which-key "search")
"x" '(:ignore t :which-key "application")
"b" '(:ignore t :which-key "buffers")
"bw" '(:ignore t :which-key "windows")
"c" '(:ignore t :which-key "code")
"e" '(:ignore t :which-key "edit")
"ee" '(:ignore t :which-key "encoding")
"h" '(:ignore t :which-key "help")
"g" '(:ignore t :which-key "go to")
"m" '(:ignore t :which-key "bookmark")
"r" '(:ignore t :which-key "register"))
(private/set-leader-keys
"<return>" #'tab-switch
"-" #'dired-jump)
(private/set-leader-keys
"hf" 'describe-function
"hf" 'describe-function
"hb" 'describe-bindings
"hv" 'describe-variable
"ha" 'apropos
"hk" 'describe-key
"hm" 'describe-mode
"hd" 'apropos-documentation)
(private/set-leader-keys
"!" #'shell-command
"xq" #'restart-emacs
"xp" #'list-processes
"xP" #'proced
"xk" #'package-list-packages
"B" 'ibuffer
"bR" 'read-only-mode
"bwu" 'winner-undo
"bwr" 'winner-redo
"bx" 'kill-buffer
"bX" 'kill-buffer-and-window
"e SPC" 'whitespace-cleanup
"eg" 'mark-whole-buffer
"r SPC" 'point-to-register
"rj" 'jump-to-register
"rw" 'window-configuration-to-register
"Tf" 'toggle-frame-fullscreen
"Tm" 'toggle-frame-maximized
"Tt" 'text-scale-adjust))
;; evil-want-keybinding must be declared before Evil and Evil Collection
(setq evil-want-keybinding nil)
(use-package evil
:ensure t
:demand t
:init
(setq evil-want-integration t)
(setq evil-want-keybinding nil)
:diminish evil-escape-mode
:custom
(evil-want-C-u-scroll t)
;;(evil-want-C-d-scroll t)
;(evil-want-C-i-jump t)
(evil-want-C-h-delete t)
(evil-want-Y-yank-to-eol t)
(evil-respect-visual-line-mode t)
(evil-want-fine-undo t)
(evil-kill-on-visual-paste nil)
(evil-auto-balance-windows t)
(evil-auto-indent t)
;; Move back the cursor one position when exiting insert mode
(evil-move-cursor-back nil)
(evil-move-beyond-eol nil)
:general
(general-def "C-M-u" #'universal-argument)
;(general-def "<escape>" 'keyboard-escape-quit)
(general-imap "C-g" #'evil-normal-state)
;; exit out of a transient with escape
(general-def :keymaps 'transient-map "<escape>" #'transient-quit-one)
;;(general-def :keymaps 'evil-ex-search-keymap "<escape>" 'keyboard-escape-quit)
;;(general-def :keymaps 'evil-ex-search-keymap "C-g" 'keyboard-escape-quit)
;;(general-imap "C-h" 'evil-delete-backward-char-and-join)
;;(general-mmap "j" 'evil-next-visual-line)
;;(general-mmap "k" 'evil-previous-visual-line)
(general-mmap "zn" #'narrow-to-defun)
(general-vmap "zn" #'narrow-to-region)
(general-mmap "zw" #'widen)
(general-nmap "-" #'dired-jump)
(:keymaps 'evil-ex-map
"wq" 'unpackaged/save-and-kill-buffer
"tp" 'tab-previous
"tn" 'tab-next)
(:keymaps 'evil-window-map
"f" #'tab-bar-new-tab)
;; Use visual line motions even outside of visual-line-mode buffers
(general-mmap
"j" 'evil-next-visual-line
"k" 'evil-previous-visual-line)
(private/set-leader-keys
"<escape>" #'evil-ex-nohighlight
"u" 'universal-argument
"w" '(evil-window-map :which-key "window")
"S" '(evil-write-all :which-key "save all")
"`" 'evil-switch-to-windows-last-buffer)
(general-vmap
:prefix "SPC"
"y" (general-simulate-key "\"+y" :state 'visual)
"P" (general-simulate-key "\"_dP" :state 'visual)
"d" (general-simulate-key "\"_d" :state 'visual))
(general-nmap
:prefix "SPC"
"y" (general-simulate-key "\"+y" :state 'normal)
"Y" (general-simulate-key "\"+Y" :state 'normal)
"d" (general-simulate-key "\"_d" :state 'normal))
:config
(evil-set-undo-system 'undo-redo)
(evil-set-initial-state 'eat-mode 'insert)
;; this mirrors the minibuffer in nvim better escape should exit the minibuffer
(add-hook 'minibuffer-mode-hook
(lambda ()
(evil-local-set-key 'insert (kbd "<escape>") 'keyboard-escape-quit)
(evil-local-set-key 'normal (kbd "<escape>") 'keyboard-escape-quit)))
(defun sjb/evil-scroll-line-to-center (&rest _)
(evil-scroll-line-to-center nil))
(advice-add 'evil-search-next :after #'sjb/evil-scroll-line-to-center)
(advice-add 'evil-search-previous :after #'sjb/evil-scroll-line-to-center)
(advice-add 'evil-scroll-down :after #'sjb/evil-scroll-line-to-center)
(advice-add 'evil-scroll-up :after #'sjb/evil-scroll-line-to-center)
(defalias #'forward-evil-word #'forward-evil-symbol)
;; make evil-search-word look for symbol rather than word boundaries
(setq evil-symbol-word-search t)
(evil-define-operator my-evil-comment-or-uncomment (beg end)
"Toggle comment for the region between BEG and END."
(interactive "<r>")
(comment-or-uncomment-region beg end))
(evil-define-key 'normal 'global (kbd "gc") 'my-evil-comment-or-uncomment)
(defun unpackaged/save-and-kill-buffer ()
(interactive)
(save-buffer)
(kill-this-buffer))
(setq org-fold-core-style 'overlays)
(evil-mode +1)
;; Make evil serch more like vim
(evil-select-search-module 'evil-search-module 'evil-search)
(setq search-invisible 'open))
(use-package evil-collection
:ensure t
:after evil
:hook ((eshell-first-time-mode . evil-collection-eshell-setup)
(after-init . evil-collection-init))
:custom
(evil-collection-outline-bind-tab-p t)
(evil-collection-setup-minibuffer t)
(forge-add-default-bindings nil)
(evil-collection-magit-use-z-for-folds nil)
:general
;;(general-def :keymaps 'evil-window-map "d" 'evil-window-delete)
;;(general-def :keymaps 'evil-window-map "=" 'balance-windows-area)
(private/set-leader-keys
"'" '(evil-collection-consult-mark :wk "list mark"))
:config
(with-eval-after-load 'dired
(evil-collection-define-key 'normal 'dired-mode-map
"h" 'dired-single-up-directory
"l" 'dired-single-buffer)
(evil-collection-define-key 'normal 'dired-mode-map
"i" 'wdired-change-to-wdired-mode
"gF" 'multi-dired-find-file
"C-o" 'dired-find-file-below))
(with-eval-after-load 'mu4e
(evil-collection-define-key 'motion 'mu4e-view-mode-map
"go" 'mu4e-view-go-to-url
"gO" 'mu4e-view-go-to-url-gui))
(with-eval-after-load 'epa
(evil-collection-define-key 'normal 'epa-key-list-mode-map
"m" 'epa-mark-key
"u" 'epa-unmark-key)))
(use-package evil-matchit
:ensure t
:defer 1
:hook (after-init . global-evil-matchit-mode)
:after evil)
(use-package evil-surround
:ensure t
:defer t
:commands global-evil-surround-mode
:hook (after-init . global-evil-surround-mode)
:after evil)
(use-package evil-multiedit
:ensure t
:after evil
:defer t
:custom
(evil-multiedit-use-symbols 1)
:general
(general-evil-define-key 'normal 'global
(kbd "M-d") #'evil-multiedit-match-symbol-and-next
(kbd "M-D") #'evil-multiedit-match-symbol-and-prev)
(general-evil-define-key 'visual 'global
"R" #'evil-multiedit-match-all
(kbd "M-d") #'evil-multiedit-match-and-next
(kbd "M-D") #'evil-multiedit-match-and-prev)
(general-evil-define-key '(visual normal) 'global
(kbd "C-M-d") #'evil-multiedit-restore)
(general-evil-define-key 'multiedit 'global
(kbd "M-d") #'evil-multiedit-match-and-next
(kbd "M-S-d") #'evil-multiedit-match-and-prev
(kbd "RET") #'evil-multiedit-toggle-or-restrict-region)
(general-evil-define-key '(multiedit multiedit-insert) 'global
(kbd "C-n") #'evil-multiedit-next
(kbd "C-p") #'evil-multiedit-prev))
(use-package evil-textobj-tree-sitter
:vc (evil-textobj-tree-sitter :url "https://github.com/meain/evil-textobj-tree-sitter.git" :branch "auto-update-queries")
:ensure t
:defer t
:general
(:keymaps 'evil-outer-text-objects-map
"a" (evil-textobj-tree-sitter-get-textobj "parameter.outer")
"b" (evil-textobj-tree-sitter-get-textobj "block.outer")
"c" (evil-textobj-tree-sitter-get-textobj "class.outer")
"f" (evil-textobj-tree-sitter-get-textobj "function.outer")
"l" (evil-textobj-tree-sitter-get-textobj ("conditional.outer" "loop.outer"))
"#" (evil-textobj-tree-sitter-get-textobj "comment.outer")
"=" (evil-textobj-tree-sitter-get-textobj "assignment.outer")
"m" (evil-textobj-tree-sitter-get-textobj "import"
'((python-ts-mode . [(import_statement) @import])
(rust-ts-mode . [(use_declaration) @import]))))
(:keymaps 'evil-inner-text-objects-map
"a" (evil-textobj-tree-sitter-get-textobj "parameter.inner")
"b" (evil-textobj-tree-sitter-get-textobj "block.inner")
"c" (evil-textobj-tree-sitter-get-textobj "class.inner")
"f" (evil-textobj-tree-sitter-get-textobj "function.inner")
"l" (evil-textobj-tree-sitter-get-textobj ("conditional.inner" "loop.inner"))
"#" (evil-textobj-tree-sitter-get-textobj "comment.inner"))
(general-nmap
"]m" '((lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "function.outer")) :wk "function")
"[m" '((lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "function.outer" t)) :wk "function")
"]M" '((lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "function.outer" nil t)) :wk "function")
"[M" '((lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "function.outer" t t)) :wk "function")
"]a" '((lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "parameter.outer")) :wk "param")
"[a" '((lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "parameter.outer" t)) :wk "param")
"]A" '((lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "parameter.outer" nil t)) :wk "param")
"[A" '((lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "parameter.outer" t t)) :wk "param"))
)
(use-package evil-visualstar
:after evil
:ensure t
:defer t
:commands global-evil-visualstar-mode
:hook (after-init . global-evil-visualstar-mode))
(use-package exato
:defer t
:ensure t)
(use-package vdiff
:ensure t
:defer t
:commands (vdiff-buffers
vdiff-buffers3
vdiff-quit
vdiff-files
vdiff-files3)
:custom
(vdiff-auto-refine t)
(vdiff-only-highlight-refinements t))
(use-package fido-vertical-mode
:ensure nil
:defer t
:hook (after-init . fido-vertical-mode))
(use-package cape
;; Bind dedicated completion commands
:ensure t
:defer t
:commands (cape-dabbrev cape-file cape-keyword cape-sgml cape-elisp-block)
:general
("C-c p" '(:keymap cape-prefix-map :wk "cape"))
(private/set-leader-keys
"k" '(:ignore t :which-key "cape")
"kp" 'completion-at-point
"kt" 'complete-tag
"kd" 'cape-dabbrev
"kf" 'cape-file
"kk" 'cape-keyword
"ks" 'cape-symbol
"ka" 'cape-abbrev
"kl" 'cape-line
"kw" 'cape-dict
"k\\" 'cape-tex
"k>" 'cape-sml
"kr" 'cape-rfc1345)
:init
;; Add `completion-at-point-functions', used by `completion-at-point'.
(add-to-list 'completion-at-point-functions #'cape-file)
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
(add-to-list 'completion-at-point-functions #'cape-keyword)
(add-to-list 'completion-at-point-functions #'cape-sgml)
(add-to-list 'completion-at-point-functions #'cape-elisp-block)
;;(add-to-list 'completion-at-point-functions #'cape-rfc1345)
;;(add-to-list 'completion-at-point-functions #'cape-abbrev)
;;(add-to-list 'completion-at-point-functions #'cape-ispell)
;;(add-to-list 'completion-at-point-functions #'cape-dict)
;;(add-to-list 'completion-at-point-functions #'cape-symbol)
;;(add-to-list 'completion-at-point-functions #'cape-line)
;; Silence then pcomplete capf, no errors or messages!
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)
;; Ensure that pcomplete does not write to the buffer
;; and behaves as a pure `completion-at-point-function'.
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)
)
(defun my/ignore-elisp-keywords (cand)
(or (not (keywordp cand))
(eq (char-after (car completion-in-region--data)) ?:)))
(defun my/setup-elisp ()
(setq-local completion-at-point-functions
(list (cape-capf-super
(cape-capf-predicate
#'elisp-completion-at-point
#'my/ignore-elisp-keywords)
#'cape-dabbrev
#'cape-file))
cape-dabbrev-min-length 5))
(add-hook 'emacs-lisp-mode-hook #'my/setup-elisp)
(use-package consult
:ensure t
:demand t
:commands (sjb-embark-preview)
:hook (completion-list-mode . consult-preview-at-point-mode)
:general
;;(general-nmap "/" 'consult-isearch)
("C-S-s" 'consult-line-multi
"C-c h" 'consult-history
"C-c m" 'consult-mode-command
"C-c b" 'consult-bookmark
"C-c k" 'consult-kmacrO
"C-x M-:" 'consult-complex-command
"C-x b" 'consult-buffer
"C-x 4 b" 'consult-buffer-other-window
"C-x 5 b" 'consult-buffer-other-frame
"M-#" 'consult-register-load
"M-'" 'consult-register-store
"C-M-#" 'consult-register)
;; Other custom bindings
("M-y" 'consult-yank-pop) ;; orig. yank-pop
(general-nmap "g:" #'consult-goto-line)
(general-def :keymaps 'minibuffer-local-map "C-;" #'sjb-embark-preview)
(general-def :keymaps 'isearch-mode-map
"M-e" 'consult-isearch-history ;; orig. isearch-edit-string
"M-s e" 'consult-isearch-history ;; orig. isearch-edit-string
"M-s l" 'consult-line) ;; required by consult-line to detect isearch
(private/set-leader-keys
"I" '(consult-imenu-multi :wk "find workspace symbols")
"i" '(consult-imenu :wk "find symbols")
"sb" '(consult-bookmark :wk "find bookmark")
"se" '(consult-compile-error :wk "find compiler error")
"sl" '(consult-line :wk "search line")
"sh" '(consult-org-heading :wk "search heading")
"sm" '(consult-mark :wk "mark")
"sr" '(consult-ripgrep :wk "grep")
"sG" '(consult-git-grep :wk "git grep")
"sK" '(consult-keep-lines :wk "keep lines")
"sL" '(consult-focus-lines :wk "focus lines")
"sM" '(consult-global-mark :wk "global mark")
"sO" '(consult-outline :wk "search outline"))
(private/set-leader-keys
"SPC" '(consult-buffer :wk "buffers")
"fc" '(consult-flymake :wk "flymake")
"ff" '(consult-find :wk "find file")
"fl" '(consult-locate :wk "find locate")
"fh" '(consult-man :wk "find man"))
:custom
(consult-line-numbers-widen t)
(register-preview-function #'consult-register-format)
(xref-show-xrefs-function #'consult-xref)
(xref-show-definitions-function #'consult-xref)
(xref-search-program #'ripgrep)
;;(consult-preview-key nil)
:init
(with-eval-after-load 'project
(setq consult-project-root-function
(lambda ()
(when-let (project (project-current))
(car (project-roots project))))))
:config
(defun sjb-embark-preview ()
"Previews candidate in vertico buffer, unless it's a consult command"
(interactive)
(unless (bound-and-true-p consult--preview-function)
(save-selected-window
(let ((embark-quit-after-action nil))
(embark-dwim))))))
(use-package consult
:defer t
:commands (consult-typhoon)
:general
(private/set-leader-keys
"j" '(consult-typhoon :wk "typhoon"))
:config
(require 'consult)
(require 'project)
(autoload 'org-buffer-list "org")
(defvar consult--source-org
`(:name "Org File"
:narrow ?o
:category file
:history file-name-history
:face consult-file
:state ,#'consult--file-state
:items ,(lambda () (mapcar #'buffer-name (org-buffer-list)))
:action ,(lambda (cand) (find-file cand))))
(defvar consult-project-sjb--source-file
`(:name "Project File"
:narrow (?p . "Project File")
:category file
:history file-name-history
:face consult-file
:state ,#'consult--file-state
:action ,(lambda (cand) (find-file cand))
:enabled ,#'project-current
:items
,(lambda () (let* ((project (project--find-in-directory (project-root (project-current))))
(files (project-files project))) files))))
(defcustom consult-typhoon-sources
'(consult-project-sjb--source-file
consult--source-buffer
consult--source-bookmark
consult--source-recent-file
consult--source-org)
"Sources used by `consult-typhoon'."
:type '(repeat symbol))
(defvar consult--typhoon-history nil)
(defun consult-typhoon (&optional sources)
"Enhanced `switch-to-*` command"
(interactive)
(let ((selected (consult--multi (or sources consult-typhoon-sources)
:require-match
(confirm-nonexistent-file-or-buffer)
:prompt "Switch to: "
:history 'consult--typhoon-history
:sort nil)))
(unless (plist-get (cdr selected) :match)
(consult--buffer-action (car selected))))))
(use-package consult-project-extra
:ensure t
:after consult
:general
(general-def
[remap project-find-file] #'consult-project-extra-find)
(general-def :keymaps 'project-prefix-map
"o" #'consult-project-extra-find-other-window))
(use-package consult-dir
:ensure t
:defer t
:general
(general-def [remap dired] #'consult-dir)
(:keymaps 'minibuffer-local-completion-map
"C-x C-d" 'consult-dir
"C-x C-j" 'consult-dir-jump-file))
(use-package consult-eglot
:ensure t
:defer t
:after (consult eglot)
:general
(:keymaps 'eglot-mode-map
[remap xref-find-apropos] #'consult-eglot-symbols)
(private/set-leader-keys
:keymaps 'eglot-mode-map
"/" '(consult-eglot-symbols :wk "symbols")))
(use-package consult-eglot-embark
:ensure t
:after (consult-eglot)
:config
(consult-eglot-embark-mode))
(use-package corfu
:general
(general-def :keymaps 'corfu-map
[remap evil-complete-next] 'corfu-next
[remap evil-complete-previous] 'corfu-previous
"RET" nil
"<tab>" nil
"TAB" nil
"C-<return>" #'corfu-insert
"M-d" #'corfu-popupinfo-toggle
"M-n" #'corfu-popupinfo-scroll-up
"M-p" #'corfu-popupinfo-scroll-down
"C-g" #'corfu-quit
"M-l" #'corfu-show-location)
(general-def :keymaps '(corfu-map general-override-mode-map)
:states 'insert
"C-y" #'corfu-complete
"\M-q" #'corfu-quick-complete
"\C-q" #'corfu-quick-insert
"\M-m" #'corfu-move-to-minibuffer
"M-SPC" #'corfu-insert-separator)
:custom
;; Works with `indent-for-tab-command'. Make sure tab doesn't indent when you
;; want to perform completion
(corfu-auto t)
(corfu-auto-prefix 3)
(corfu-auto-delay 0.5)
(corfu-echo-documentation 0.25) ; Already use corfu-doc
(corfu-min-width 80)
(corfu-max-width corfu-min-width) ; Always have the same width
(corfu-count 14)
(corfu-scroll-margin 4)
(corfu-cycle t)
(corfu-separator ?\s) ; Necessary for use with orderless
(corfu-quit-no-match 'separator)
(corfu-quit-at-boundary 'separator)
(corfu-preview-current 'insert) ; Preview current candidate?
;;(corfu-preselect-first t) ; Preselect first candidate?
(read-extended-command-predicate #'command-completion-default-include-p)
;; Disable Ispell completion function. As an alternative try `cape-dict'.
(text-mode-ispell-word-completion nil)
(tab-always-indent 'complete)
:init
(require 'corfu-quick)
(require 'corfu-history)
(require 'corfu-popupinfo)
(global-corfu-mode 1)
(corfu-history-mode 1)
(corfu-popupinfo-mode 1)
;;(eldoc-add-command #'corfu-insert)
(defun corfu-enable-in-minibuffer ()
"Enable Corfu in the minibuffer if `completion-at-point' is bound."
(when (where-is-internal #'completion-at-point (list (current-local-map)))
;; (setq-local corfu-auto nil) Enable/disable auto completion
(corfu-mode 1)))
(add-hook 'minibuffer-setup-hook #'corfu-enable-in-minibuffer)
(defun corfu-move-to-minibuffer ()
(interactive)
(let ((completion-extra-properties corfu--extra)
completion-cycle-threshold completion-cycling)
(apply #'consult-completion-in-region completion-in-region--data)))
)
(use-package embark
:ensure t
:general
(general-def
"C-h B" #'embark-bindings
"C-S-a" #'embark-act)
(general-def :keymaps 'minibuffer-local-map
"C-." #'embark-act
"C-," #'embark-become)
(:keymaps 'completion-list-mode-map
"C-S-a" #'embark-minimal-act)
([remap describe-bindings] #'embark-bindings)
(:keymaps 'embark-collect-mode-map
"." #'embark-act
"C-a" #'embark-act
"M-t" #'toggle-truncate-lines)
:custom
(prefix-help-command #'embark-prefix-help-command)
:config
;;(setq embark-prompter 'embark-completing-read-prompter)
(defun embark-hide-which-key-indicator (fn &rest args)
"Hide the which-key indicator immediately when using the completing-read prompter."
(which-key--hide-popup-ignore-command)
(let ((embark-indicators
(remq #'embark-which-key-indicator embark-indicators)))
(apply fn args)))
(defun embark-which-key-indicator ()
"An embark indicator that displays keymaps using which-key.
The which-key help message will show the type and value of the
current target followed by an ellipsis if there are further
targets."
(lambda (&optional keymap targets prefix)
(if (null keymap)
(which-key--hide-popup-ignore-command)
(which-key--show-keymap
(if (eq (plist-get (car targets) :type) 'embark-become)
"Become"
(format "Act on %s '%s'%s"
(plist-get (car targets) :type)
(embark--truncate-target (plist-get (car targets) :target))
(if (cdr targets) "…" "")))
(if prefix
(pcase (lookup-key keymap prefix 'accept-default)
((and (pred keymapp) km) km)
(_ (key-binding prefix 'accept-default)))
keymap)
nil nil t (lambda (binding)
(not (string-suffix-p "-argument" (cdr binding))))))))
;; Embark actions for this buffer/file
(defun embark-target-this-buffer-file ()
(cons 'this-buffer-file (buffer-name)))
(add-to-list 'embark-target-finders #'embark-target-this-buffer-file 'append)
(unless (member 'embark-target-this-buffer-file embark-target-finders)
(setq embark-target-finders
(append (butlast embark-target-finders 2)
'(embark-target-this-buffer-file)
(last embark-target-finders 2))))
(setq embark-indicators
'(embark-which-key-indicator
embark-highlight-indicator
embark-isearch-highlight-indicator))
(setq embark-collect-initial-view-alist
'((consult-yank . zebra)
(consult-register . zebra)
(consult-grep . list)
(consult-location . list)
(kill-ring . zebra)
(file . list)
(buffer . list)
(symbol . list)
(t . list)))
(defun sudo-find-file (file)
"Open FILE as root."
(interactive "FOpen file as root: ")
(when (file-writable-p file)
(user-error "File is user writeable, aborting sudo"))
(find-file (if (file-remote-p file)
(concat "/" (file-remote-p file 'method) ":"
(file-remote-p file 'user) "@" (file-remote-p file 'host)
"|sudo:root@"
(file-remote-p file 'host) ":" (file-remote-p file 'localname))
(concat "/sudo:root@localhost:" file))))
(defun sudo-this-file ()
"Open the current file as root."
(interactive)
(sudo-find-file (file-truename buffer-file-name)))
(defun my/split-window-right (&optional size)
"Split the selected window into two windows, one above the other.
The selected window is below. The newly split-off window is
below and displays the same buffer. Return the new window."
(interactive "P")
(split-window-right size)
(other-window 1))
(defun my/split-window-below (&optional size)
"Split the selected window into two side-by-side windows.
The selected window is on the left. The newly split-off window
is on the right and displays the same buffer. Return the new
window."
(interactive "P")
(split-window-below size)
(other-window 1))
(eval-when-compile
(defmacro my/embark-ace-action (fn)
`(defun ,(intern (concat "my/embark-ace-" (symbol-name fn))) ()
(interactive)
(with-demoted-errors "%s"
(require 'ace-window)
(let ((aw-dispatch-always t))
(aw-switch-to-window (aw-select nil))
(call-interactively (symbol-function ',fn)))))))
(eval-when-compile
(defmacro my/embark-split-below-action (fn)
`(defun ,(intern (concat "my/embark-below-" (symbol-name fn))) ()
(interactive)
(split-window-below)
(other-window 1)
(call-interactively (symbol-function ',fn)))))
(eval-when-compile
(defmacro my/embark-split-right-action (fn)
`(defun ,(intern (concat "my/embark-right" (symbol-name fn))) ()
(interactive)
(split-window-right)
(other-window 1)
(call-interactively (symbol-function ',fn)))))
(general-def :keymaps 'embark-file-map
"a" (my/embark-ace-action find-file)
"2" (my/embark-split-below-action find-file)
"3" (my/embark-split-right-action find-file))
(general-def :keymaps 'embark-buffer-map
"a" (my/embark-ace-action switch-to-buffer)
"2" (my/embark-split-below-action switch-to-buffer)
"3" (my/embark-split-right-action switch-to-buffer))
(general-def :keymaps 'embark-bookmark-map
"a" (my/embark-ace-action bookmark-jump)
"2" (my/embark-split-below-action bookmark-jump)
"3" (my/embark-split-right-action bookmark-jump))
;; Hide the mode line of the Embark live/completions buffers
(add-to-list 'display-buffer-alist
'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
nil
(window-parameters (mode-line-format . none)))))
(use-package embark-consult
:ensure t
:demand t
:hook (embark-collect-mode . consult-preview-at-point-mode))
(use-package avy-embark-collect
:ensure t
:after embark
:general
(:keymaps 'embark-collect-mode-map
"C-'" 'avy-embark-collect-choose
"C-," 'avy-embark-collect-act))
(use-package marginalia
:ensure t
:hook (after-init . marginalia-mode)
:custom
(margnalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
(marginalia-max-relative-age 0)
(marginalia-align 'right)
:general (:keymaps 'minibuffer-local-map "M-A" 'marginalia-cycle))
(use-package orderless
:ensure t
:after corfu
:custom
(completion-styles '(orderless basic))
(completion-category-defaults nil)
(completions-detailed t)
(completion-category-overrides '((file (styles partial-completion))))
(orderless-component-separator 'orderless-escapable-split-on-space)
:config
(with-eval-after-load 'selectrum
(setq selectrum-highlight-candidates-function #'orderless-highlight-matches))
(setq orderless-matching-styles
'(orderless-prefixes
orderless-initialism
orderless-regexp))
(defun first-initialism (pattern index _total)
(if (= index 0) 'orderless-initialism))
(defun flex-if-twiddle (pattern _index _total)
(when (string-suffix-p "~" pattern)
`(orderless-flex . ,(substring pattern 0 -1))))
(defun without-if-bang (pattern _index _total)
(cond
((equal "!" pattern)
'(orderless-literal . ""))
((string-prefix-p "!" pattern)
`(orderless-without-literal . ,(substring pattern 1)))))
(defun orderless-literal-dispatcher (pattern _index _total)
(when (string-suffix-p "=" pattern)
`(orderless-literal . ,(substring pattern 0 -1))))
(defun orderless-initialism-dispatcher (pattern _index _total)
(when (string-suffix-p "," pattern)
`(orderless-strict-leading-initialism . ,(substring pattern 0 -1))))
(setq orderless-style-dispatchers '(flex-if-twiddle
without-if-bang
orderless-literal-dispatcher
orderless-initialism-dispatcher)))
(use-package s :defer t :ensure t)
(use-package tabnine
:vc (tabnine :url "https://github.com/SjB/tabnine.git" :branch "change-completion-keybinding")
:hook ((prog-mode . tabnine-mode)
(kill-emacs . tabnine-kill-process))
:after cape
:preface
(add-to-list 'completion-at-point-functions #'tabnine-completion-at-point)
:custom
(tabnine-wait 2.0)
(tabnine-idle-delay 1.0)
:config
(set-face-attribute 'tabnine-overlay-face nil :family "MonaspiceKr Nerd Font Propo")
:general
(private/set-leader-keys :keymaps 'tabnine-completion-map
"z" #'tabnine-accept-completion))
(use-package gptel
:defer t
:ensure t)
(use-package chatgpt-shell
:ensure t
:general
(general-define-key
:states 'visual
:prefix "SPC"
:global-prefix "C-SPC"
"es" #'chatgpt-shell-proofread-region
"ev" #'chatgpt-shell-write-git-commit)
:config
(setq chatgpt-shell-model-versions '("gpt-3.5-turbo"))
(setq chatgpt-shell-prompt-query-response-style 'inline)
(setq chatgpt-shell-openai-key (auth-source-pick-first-password :host "api.openai.com")))
(use-package treesit
:demand t
:commands (treesit-install-language-grammar nf/treesit-install-all-languages)
:ensure nil
:init
;;(add-to-list 'treesit-extra-load-path (expand-file-name "tree-sitter" user-emacs-directory))
:config
(defun nf/treesit-install-all-languages ()
"Install all languages specified by `treesit-language-source-alist'."
(interactive)
(let ((languages (mapcar 'car treesit-language-source-alist)))
(dolist (lang languages)
(treesit-install-language-grammar lang)
(message "`%s' parser was installed." lang)
(sit-for 0.75)))))
(use-package treesit-auto
:defer 1
:config
(setq my-elisp-ts-auto-recipe
(make-treesit-auto-recipe
:lang 'emacs-lisp
:ts-mode 'elisp-ts-mode
:remap '(elisp-mode emacs-lisp-mode)
:url "https://github.com/Wilfred/tree-sitter-elisp.git"
:revision "master"
:source-dir "src"))
(add-to-list 'treesit-auto-recipe-list my-elisp-ts-auto-recipe)
(setq my-php-ts-auto-recipe
(make-treesit-auto-recipe
:lang 'php
:ts-mode 'php-ts-mode
:remap '(php-mode)
:url "https://github.com/tree-sitter/tree-sitter-php"
:revision "master"
:source-dir "src"))
(add-to-list 'treesit-auto-recipe-list my-php-ts-auto-recipe)
(setq my-svelte-ts-auto-recipe
(make-treesit-auto-recipe
:lang 'svelte
:ts-mode 'svlte-ts-mode
:remap '(svelte-mode)
:url "https://github.com/Himujjal/tree-sitter-sveltet"
:revision "master"
:source-dir "src"))
(add-to-list 'treesit-auto-recipe-list my-svelte-ts-auto-recipe)
(setq my-sql-ts-auto-recipe
(make-treesit-auto-recipe
:lang 'sql
:ts-mode 'sql-ts-mode
:remap '(sql-mode)
:url "https://github.com/Himujjal/tree-sitter-sveltet"
:revision "master"
:source-dir "src"))
(add-to-list 'treesit-auto-recipe-list my-sql-ts-auto-recipe)
(setq my-zig-ts-auto-recipe
(make-treesit-auto-recipe
:lang 'zig
:ts-mode 'zig-ts-mode
:remap '(zig-mode)
:url "https://github.com/GrayJack/tree-sitter-zig"
:revision "master"
:source-dir "src"))
(add-to-list 'treesit-auto-recipe-list my-zig-ts-auto-recipe)
(setq my-vue-ts-auto-recipe
(make-treesit-auto-recipe
:lang 'vue
:ts-mode 'vue-ts-mode
:remap '(vue-mode)
:url "https://github.com/ikatyang/tree-sitter-vue.git"
:revision "master"
:source-dir "src"))
(add-to-list 'treesit-auto-recipe-list my-vue-ts-auto-recipe)
(setq my-ocaml-ts-auto-recipe
(make-treesit-auto-recipe
:lang 'ocaml
:ts-mode 'ocaml-ts-mode
:remap '(caml-mode tuareg-mode)
:url "https://github.com/tree-sitter/tree-sitter-ocaml.git"
:revision "master"
:source-dir "src"))
(add-to-list 'treesit-auto-recipe-list my-ocaml-ts-auto-recipe)
(setq treesit-auto-install 'prompt)
(global-treesit-auto-mode))
;; `M-x combobulate' (or `C-c o o') to start using Combobulate
(use-package combobulate
:defer t
:ensure t
:vc (:fetcher github :repo "mickeynp/combobulate")
;; Optional, but recommended.
;;
;; You can manually enable Combobulate with `M-x
;; combobulate-mode'.
;;:hook (prog-mode . combobulate-mode)
;; Amend this to the directory where you keep Combobulate's source
;; code.
)
(defun setup-shell()
(setq-local show-trailing-whitespace nil)
(ansi-color-for-comint-mode-on))
(add-hook 'shell-mode-hook 'setup-shell)
(add-hook 'term-mode-hook 'setup-shell)
;;(setq epg-pinentry-mode 'loopback) ; This will fail if gpg>=2.1 is not available.
;;(pinentry-start)
(with-eval-after-load 'tramp
(setenv "SHELL" "/bin/bash")
(setq tramp-shell-prompt-pattern "\\(?:^\\| \\)[^]#$%>\n]*#?[]#$%>] *\\(\\[[0-9;]*[a-zA-Z] *\\)*"))
;;(eval-after-load 'shell '(setenv "TERM" "xterm-256color"))
(add-to-list 'comint-output-filter-functions 'ansi-color-process-output)
(use-package shell
:ensure nil
:hook (shell-mode . my-shell-mode-hook-func)
:defer t
:config
(defun my-shell-mode-hook-func ()
(set-process-sentinel (get-buffer-process (current-buffer))
'my-shell-mode-kill-buffer-on-exit))
(defun my-shell-mode-kill-buffer-on-exit (process state)
(message "%s" state)
(if (or
(string-match "exited abnormally with code.*" state)
(string-match "finished" state))
(kill-buffer (current-buffer)))))
(use-package term
:commands term
:init
(setenv "SHELL" "/bin/bash")
(setenv "PAGER" "cat")
(setenv "EDITOR" "emacsclient")
(setq explicit-shell-file-name "/bin/bash")
(when (eq system-type 'windows-nt)
(setq explicit-shell-file-name "powershell.exe")
(setq explicit-powershell.exe-args '()))
(add-hook 'term-mode-hook (lambda ()
(goto-address-mode)
(define-key term-raw-map (kbd "M-o") 'other-window)
(setq yas-dont-activate t)))
:config
(setq term-prompt-regexp "^[^#$%>\n]*[#$%>] *"))
(use-package xterm-color
:ensure t
:after eshell)
(use-package eat
:ensure t
:defer t
:hook (eshell-load-hook . (eat-eshell-mode eat-eshell-visual-command-mode)))
(use-package eshell
:commands (eshell configure-eshell)
:hook (eshell-directory-change . sjb/sync-dir-in-buffer-name)
:custom
(eshell-scroll-to-bottom-on-input t)
(eshell-highlight-prompt nil)
(eshell-history-size 1024)
(eshell-hist-ignoredups t)
;;(eshell-input-filter 'sjb/eshell-input-filter)
(eshell-cd-on-directory t)
(eshell-list-files-after-cd nil)
;;(eshell-error-if-no-glob t)
;;(eshell-review-quick-commands nil)
(eshell-prefer-lisp-functions t)
(eshell-prefer-lisp-variables t)
(eshell-ls-use-colors t)
;;(ffap-shell-prompt-regexp nil)
(eshell-destroy-buffer-when-process-dies t)
;;(eshell-prompt-regexp "^$ ")
(eshell-buffer-maximum-lines 10000)
:general
(private/set-leader-keys
"xe" 'eshell)
(:keymaps 'eshell-mode-map "C-c >" 'sjb/eshell-redirect-input)
(:keymaps 'eshell-hist-mode-map "M-r" 'consult-history)
:init
(add-hook 'eshell-mode-hook (lambda ()
(setq-local completion-styles '(basic))
(setq-local corfu-count 2)
(setq-local completion-at-point-function '(pcomplete-completions-at-point cape-file cape-history))
(setq-local show-trailing-whitespace nil)
(setq-local outline-regexp eshell-prompt-regexp)
(evil-normalize-keymaps)
))
;; We want to use xterm-256color when running interactive commands
;; in eshell but not during other times when we might be launching
;; a shell command to gather its output.
(add-hook 'eshell-pre-command-hook
#'(lambda () (setenv "TERM" "xterm-256color")))
(add-hook 'eshell-post-command-hook
#'(lambda () (setenv "TERM" "dumb")))
:config
(require 'em-tramp)
;;(require 'em-smart)
;;(setq eshell-where-to-jump 'begin
;; eshell-review-quick-commands nil
;; eshell-scroll-to-bottom-on-input nil
;; eshell-smart-space-goes-to-end t)
;; If the above does not work, try uncommenting this.
;; (add-to-list 'eshell-modules-list 'eshell-smart)
(setq eshell-directory-name (expand-file-name "emacs/eshell" (xdg-data-home)))
(setq eshell-visual-commands '("tail" "top" "htop"))
(add-to-list 'eshell-modules-list 'eshell-tramp)
;;(add-to-list 'eshell-modules-list 'eshell-smart)
;;(add-to-list 'eshell-output-filter-functions 'eshell-truncate-buffer)
(defun sjb/sync-dir-in-buffer-name ()
"Update eshell buffer to show directory path.
Stolen from aweshell."
(if (project-current)
(let* ((root (project-root (project-current)))
(root-name (project-name (project-current))))
(rename-buffer (format "*eshell %s* %s" root-name (s-chop-prefix root default-directory)) t))
(rename-buffer (format "*eshell %s*" default-directory) t)))
(defun eshell/gst (&rest args)
(magit-status (pop args) nil)
(eshell/echo)) ;; The echo command suppresses output
(defun eshell/clear ()
"Clear the eshell buffer."
(let ((inhibit-read-only t))
(erase-buffer)
(eshell-send-input)))
(if (eq system-type 'darwin)
;; The 'ls' executable requires the Gnu version on the Mac
(let ((ls (if (file-exists-p "/usr/local/bin/gls")
"/usr/local/bin/gls"
"/bin/ls")))
(eshell/alias "ll" (concat ls " -AlohG --color=always"))))
)
(use-package eshell-syntax-highlighting
:ensure t
:defer t
:commands unpackaged/eshell-syntax-highlighting-init
:hook (eshell-first-time-mode . unpackaged/eshell-syntax-highlighting-init)
:config
(defun unpackaged/eshell-syntax-highlighting-init ()
(eshell-syntax-highlighting-global-mode +1)))
(use-package eshell-z
:ensure t
:after eshell)
(use-package eshell-bookmark
:hook (eshell-mode . eshell-bookmark-setup)
:after eshell)
(use-package eshell-toggle
:ensure t
:defer t
:custom
(eshell-toggle-find-project-root-package nil)
:general
(general-def "C-x C-z" 'smart-eshell-toggle)
:config
(defun smart-eshell-toggle ()
"Detect if we are in a project and dwim"
(interactive)
(if (project-current)
(setq eshell-toggle-find-project-root-package 'project)
(setq eshell-toggle-find-project-root-package nil))
(eshell-toggle))
)
(use-package eshell-git-prompt
:after eshell)
(use-package ace-link
:ensure t
:defer t
:general ((elfeed-show-mode-map org-mode-map) "M-o" 'ace-link-org)
:config
(ace-link-setup-default))
(use-package ace-window
:ensure t
:hook (after-init . ace-window-posframe-mode)
:commands (ace-window-prefix)
:general
("C-x 4 o" 'ace-window-prefix)
([remap other-window] 'ace-window)
(private/set-leader-keys "a" 'ace-window)
:init
(setq aw-char-position 'left)
;;(setq aw-frame-size nil)
;;(setq aw-frame-offset '(13 . 23))
(with-eval-after-load 'evil
(general-define-key :keymaps 'evil-window-map
"a" 'ace-window
"c" 'ace-swap-window
"x" 'ace-delete-window
"m" 'ace-maximize-window))
:config
(defun ace-window-prefix ()
"Use `ace-window' to display the buffer of the next command.
The next buffer is the buffer displayed by the next command invoked
immediately after this command (ignoring reading from the minibuffer).
Creates a new window before displaying the buffer.
When `switch-to-buffer-obey-display-actions' is non-nil,
`switch-to-buffer' commands are also supported."
(interactive)
(display-buffer-override-next-command
(lambda (buffer _)
(let (window type)
(setq
window (aw-select (propertize " ACE" 'face 'mode-line-highlight))
type 'reuse)
(cons window type)))
nil "[ace-window]")
(message "Use `ace-window' to display next command buffer..."))
(setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
(setq aw-dispatch-always nil))
(use-package alert
:ensure t
:commands (alert)
:init
(when (or (eq system-type 'gnu/linux) (eq system-type 'linux))
(setq alert-default-style 'notifications))
(when (eq system-type 'darwin)
(setq alert-default-style 'osx-notifier)))
(use-package async
:ensure t
:defer t
:init
(async-bytecomp-package-mode 1)
:commands (async-start))
(use-package avy
:ensure t
:defer t
:hook (after-init . avy-setup-default)
:general
(:keymaps 'isearch-mode-map "M-j" 'avy-isearch)
;(general-nmap "gr" '(avy-resume :wk "avy resume"))
(private/set-leader-keys
"ec" 'avy-copy-region
"ek" 'avy-kill-region
"em" 'avy-move-region)
:config
(setq avy-background t
avy-highlight-first t
avy-style 'at-full)
(setq avy-orders-alist
'((avy-goto-char-2 . avy-order-closest)
(avy-goto-word-1 . avy-order-closest)
(avy-goto-symbol-1 . avy-order-closest)
(avy-goto-word-or-subword-1 . avy-order-closest)))
(with-eval-after-load 'embark
(defun avy-action-embark (pt)
(unwind-protect
(save-excursion
(goto-char pt)
(embark-act))
(select-window
(cdr (ring-ref avy-ring 0))))
t)
(setf (alist-get ?\. avy-dispatch-alist) 'avy-action-embark))
(defun avy-action-kill-whole-line (pt)
(save-excursion
(goto-char pt)
(kill-whole-line))
(select-window
(cdr
(ring-ref avy-ring 0)))
t)
(setf (alist-get ?k avy-dispatch-alist) 'avy-action-kill-stay)
(setf (alist-get ?K avy-dispatch-alist) 'avy-action-kill-whole-line)
;; Copy text
(defun avy-action-copy-whole-line (pt)
(save-excursion
(goto-char pt)
(cl-destructuring-bind (start . end)
(bounds-of-thing-at-point 'line)
(copy-region-as-kill start end)))
(select-window
(cdr
(ring-ref avy-ring 0)))
t)
(setf (alist-get ?w avy-dispatch-alist) 'avy-action-copy)
(setf (alist-get ?W avy-dispatch-alist) 'avy-action-copy-whole-line)
;; Yank text
(defun avy-action-yank-whole-line (pt)
(avy-action-copy-whole-line pt)
(save-excursion (yank))
t)
(setf (alist-get ?y avy-dispatch-alist) 'avy-action-yank)
(setf (alist-get ?Y avy-dispatch-alist) 'avy-action-yank-whole-line)
;; Transpose/Move text
(defun avy-action-teleport-whole-line (pt)
(avy-action-kill-whole-line pt)
(save-excursion (yank)) t)
(setf (alist-get ?t avy-dispatch-alist) 'avy-action-teleport)
(setf (alist-get ?T avy-dispatch-alist) 'avy-action-teleport-whole-line)
;; Mark text
(defun avy-action-mark-to-char (pt)
(activate-mark)
(goto-char pt))
(setf (alist-get ?m avy-dispatch-alist) 'avy-action-mark-to-char)
;; Flyspell words
(defun avy-action-flyspell (pt)
(save-excursion
(goto-char pt)
(when (require 'flyspell nil t)
(flyspell-auto-correct-word)))
(select-window
(cdr (ring-ref avy-ring 0)))
t)
;; Bind to semicolon (flyspell uses C-;)
(setf (alist-get ?s avy-dispatch-alist) 'avy-action-flyspell)
(with-eval-after-load 'dictionary
(defun dictionary-search-dwim (&optional arg)
"Search for definition of word at point. If region is active,
search for contents of region instead. If called with a prefix
argument, query for word to search."
(interactive "P")
(if arg
(dictionary-search nil)
(if (use-region-p)
(dictionary-search (buffer-substring-no-properties
(region-beginning)
(region-end)))
(if (thing-at-point 'word)
(dictionary-lookup-definition)
(dictionary-search-dwim '(4))))))
(defun avy-action-define (pt)
(save-excursion
(goto-char pt)
(dictionary-search-dwim))
(select-window
(cdr (ring-ref avy-ring 0)))
t)
(setf (alist-get ?\= avy-dispatch-alist) 'dictionary-search-dwim))
;; Get Elisp Help
;; Replace with your package manager or help library of choice
(with-eval-after-load 'helpful
(defun avy-action-helpful (pt)
(save-excursion
(goto-char pt)
(helpful-at-point))
(select-window
(cdr (ring-ref avy-ring 0)))
t)
(setf (alist-get ?H avy-dispatch-alist) 'avy-action-helpful))
;; Isearch in other windows
(defun isearch-forward-other-window (prefix)
"Function to isearch-forward in other-window."
(interactive "P")
(unless (one-window-p)
(save-excursion
(let ((next (if prefix -1 1)))
(other-window next)
(isearch-forward)
(other-window (- next))))))
(defun isearch-backward-other-window (prefix)
"Function to isearch-backward in other-window."
(interactive "P")
(unless (one-window-p)
(save-excursion
(let ((next (if prefix 1 -1)))
(other-window next)
(isearch-backward)
(other-window (- next))))))
(define-key global-map (kbd "C-M-s") 'isearch-forward-other-window)
(define-key global-map (kbd "C-M-r") 'isearch-backward-other-window)
(with-eval-after-load 'lsp-mode
(defun avy-action-lsp-describe (pt)
(save-excursion
(goto-char pt)
(lsp-describe-thing-at-point))
(select-window
(cdr (ring-ref avy-ring 0)))
t)
(setf (alist-get ?L avy-dispatch-alist) 'avy-action-lsp-describe)))
(use-package evil-avy
:ensure t
:general
(general-def [remap evil-find-char] 'evil-avy-goto-char)
(general-def [remap evil-find-char-to] 'evil-avy-goto-word-or-subword-1)
;;(general-nmap "g:" '(evil-avy-goto-line :wk "go to line"))
(general-nmap "gs" '(evil-avy-goto-symbol-1 :wk "go to symbol"))
(private/set-leader-keys
"gw" '(evil-avy-goto-word-0 :wk "jump to word")
"gl" '(evil-avy-goto-line :wk "jump to line")))
;; (with-eval-after-load 'eww-mode
;; (general-def 'motion eww-mode-map
;; "S" 'evil-avy-goto-char-timer
;; "s" 'evil-avy-goto-char-in-line))
(use-package beginend
:ensure t
:hook (prog-mode . beginend-prog-mode))
(use-package bookmark
:defer t
:custom
(bookmark-sort-flag nil)
:preface
(setq bookmark-default-file (expand-file-name "emacs/bookmarks.el" (xdg-data-home)))
(defun jump-to-numbered-bookmark (num)
"Jump to the bookmark with the given numeric prefix."
(let ((bookmark (nth num bookmark-alist)))
(when bookmark
(bookmark-jump bookmark))))
:general
(private/set-leader-keys
"mm" 'bookmark-set
"mS" 'bookmark-save
"ml" 'bookmark-bmenu-list
"@" '(point-to-register :wk "mark")
";" '(jump-to-register :wk "jump")
"," '((lambda () (interactive) (bookmark-set (sjb/get-bookmark-name))) :wk "bookmark"))
;; (private/set-leader-keys
;; "0" '(bookmark-bmenu-list :wk "view harpoon list")
;; "1" '((lambda () (interactive) (jump-to-numbered-bookmark 0)) :wk "harpoon 1")
;; "2" '((lambda () (interactive) (jump-to-numbered-bookmark 1)) :wk "harpoon 2")
;; "3" '((lambda () (interactive) (jump-to-numbered-bookmark 2)) :wk "harpoon 3")
;; "4" '((lambda () (interactive) (jump-to-numbered-bookmark 3)) :wk "harpoon 4")
;; "5" '((lambda () (interactive) (jump-to-numbered-bookmark 4)) :wk "harpoon 5")
;; "6" '((lambda () (interactive) (jump-to-numbered-bookmark 5)) :wk "harpoon 6")
;; "7" '((lambda () (interactive) (jump-to-numbered-bookmark 6)) :wk "harpoon 7")
;; "8" '((lambda () (interactive) (jump-to-numbered-bookmark 7)) :wk "harpoon 8")
;; "9" '((lambda () (interactive) (jump-to-numbered-bookmark 8)) :wk "harpoon 9"))
:init
(add-hook 'bookmark-bmenu-mode-hook #'hl-line-mode)
(defun sjb/get-bookmark-name ()
(let* ((name
(if (treesit-language-at (point))
(treesit-add-log-current-defun)
" "))
(mark (concat (format-mode-line "harpoon| %b:%l [%p] ") name)))
(message "%s" mark)
mark)))
(use-package bookmark-in-project
:ensure t
:defer t
:general
(private/set-leader-keys
"mn" 'bookmark-in-project-jump-next
"mp" 'bookmark-in-project-jump-previous
"mg" 'bookmark-in-project-jump
"z" 'bookmark-in-project-toggle))
(use-package breadcrumb-mode
:after eglot
:vc (:fetcher github :repo "joaotavora/breadcrumb")
:hook (eglot-managed-mode . breadcrumb-local-mode))
(use-package buffer-name-relative
:after project
:config
(buffer-name-relative-mode))
(use-package bufler
:ensure t
:defer 1
:general
(general-def [remap list-buffers] 'bufler)
(general-nmap :keymaps 'bufler-list-mode-map
"gr" '(bufler :wk "Refresh")
"m" '(bufler-mode :wk "Toggle mode")
"q" '(quit-window :wk "Quit")
"SPC" '(bufler-list-buffer-peek :wk "Peek at")
"RET" '(bufler-list-buffer-switch :wk "Switch to")
"x" '(bufler-list-buffer-kill :wk "Kill")
"C-x C-s" '(bufler-list-buffer-save :wk "Save")
"N" '(bufler-list-buffer-name-workspace :wk "Named workspace")
"f" '(bufler-list-group-frame :wk "Focus on")
"F" '(bufler-list-group-make-frame :wk "Make frame")))
(use-package burly
:ensure t
:defer 1
:general
(private/set-leader-keys
"mw" '(burly-bookmark-windows :wk "burly window")
"mr" '(burly-open-bookmark :wk "burly open")))
(use-package cheat-sh
:ensure t
:general
(private/set-leader-keys "hc" 'cheat-sh))
(use-package dired
:ensure nil
:defer t
:hook (dired-mode . unpackaged/dired-startup-init)
:commands (dired dired-find-file-below multi-dired-find-file wdired-change-to-wdired-mode unpackaged/dired-startup-init)
:general ("C-x j" 'dired-jump
"C-x C-j" 'dired-jump-other-window)
:custom
(dired-dwim-target t)
(dired-listing-switches "-agho --group-directories-first")
:config
(defun unpackaged/dired-startup-init ()
(dired-hide-details-mode t)
(auto-revert-mode))
(defun dired-clean-files ()
"Perform a bunch of operations on the whitespace content of a file.
Including indent-buffer, which should not be called automatically on save."
(interactive)
(dired-map-over-marks (funcall 'dired-clean-file) nil t)
(dired-unmark-all-marks))
(defun dired-clean-file ()
(let ((file (dired-get-filename)))
(unpackaged/process-on-file-buffer file 'unpackaged/cleanup-buffer)))
(defun unpackaged/process-on-file-buffer (file func)
"Process func on file"
(message "%s" file)
(find-file file)
(funcall func)
(save-buffer)
(kill-buffer))
(defun dired-find-file-below ()
"Displays file at point in a new window below current"
(interactive)
(display-buffer-below-selected (find-file-noselect (dired-get-file-for-visit)) nil))
(defun multi-dired-find-file (&optional arg)
"Open each of the marked files, or the file under the point, or when prefix arg, the next N files "
(interactive "P")
(let* ((fn-list (dired-get-marked-files nil arg)))
(mapc 'find-file fn-list))))
(use-package envrc
:ensure t
:hook (after-init . envrc-global-mode))
(use-package mise
:ensure t
:hook (after-init . global-mise-mode)
:custom
(mise-update-on-eshell-directory-change t)
:config
(setenv "PATH" (concat (expand-file-name "mise/shims" (xdg-data-home)) ":" (getenv "PATH")))
(add-to-list 'exec-path '((expand-file-name "mise/shims" (xdg-data-home)))))
(use-package drag-stuff
:ensure t
:general
(general-vmap
"J" #'drag-stuff-down
"K" #'drag-stuff-up))
(use-package all-the-icons-dired
:ensure t
:hook (dired-mode . all-the-icons-dired-mode))
(use-package nerd-icons-corfu
:ensure t
:defer 1
:after corfu
:config
(add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
(use-package nerd-icons-completion
:after marginalia
:defer 1
:config
(add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup)
(nerd-icons-completion-mode))
(use-package discover-my-major
:ensure t
:commands (discover-my-mode discover-my-major)
:general ("C-h C-m" 'discover-my-major
"C-h M-m" 'discover-my-mode))
(use-package docker
:ensure t
:defer t
:init
(with-eval-after-load 'evil
(evil-set-initial-state 'docker-images-mode 'emacs)
(evil-set-initial-state 'docker-containers-mode 'emacs)
(evil-set-initial-state 'docker-volumes-mode 'emacs)
(evil-set-initial-state 'docker-machines-mode 'emacs)
(evil-set-initial-state 'docker-netowkrs-mode 'emacs)))
(use-package dogears
;; These bindings are optional, of course:
:defer 1
:hook (after-init . dogears-mode)
:general
(private/set-leader-keys
"." 'dogears-remember
"fd" 'dogears-go
"gd" 'dogears-list
"gD" 'dogears-sidebar)
(general-nmap :keymaps 'dogears-list-mode-map
"d" #'dogears-list-delete
"<return>" #'dogears-list-go)
:custom
;;(dogears-idle 5)
(dogears-functions nil))
(use-package elfeed
:ensure t
:commands elfeed
:general
(general-nmap 'elfeed-search-mode-map
"c" 'elfeed-db-compact
"gu" 'elfeed-unjam)
(private/set-leader-keys "xf" 'elfeed)
:config
(elfeed-org))
(use-package elfeed-org
:ensure t
:after elfeed
:config
(setq rmh-elfeed-org-files (list "~/.dotfiles/elfeed.org")))
(use-package ement
:vc (:fetcher github :repo "alphapapa/ement.el")
:general
(private/set-leader-keys
"xc" 'ement-connect))
(use-package emojify
:hook
(ement-room-mode . emojify-mode)
(markdown-mode . emojify-mode))
(use-package elisp-slime-nav
:ensure t
:commands (elisp-slime-nav-mode elisp-slime-nav-describe-elisp-thing-at-point)
:init
(dolist (hook '(emacs-lisp-mode-hook ielm-mode-hook))
(add-hook hook 'elisp-slime-nav-mode))
(with-eval-after-load 'evil
(evil-define-key 'normal emacs-lisp-mode-map (kbd "K")
'elisp-slime-nav-describe-elisp-thing-at-point))
:config
(with-eval-after-load 'which-key
(which-key-add-key-based-replacements "C-c C-d" "elisp slime")))
(use-package engine-mode
:ensure t
:defer t
:general
(private/set-leader-keys "sw" '(:keymap engine-mode-prefixed-map :wk "web search"))
:config
(setq engine/browser-function 'browse-url-default-browser)
(defengine duckduckgo "http://www.duckduckgo.com/?q=%s" :keybinding "d")
(defengine startpage "https://www.startpage.com/do/dsearch?query=%s" :keybinding "s")
(defengine gowalker "https://gowalker.org/search?q=%s" :keybinding "w")
(defengine github "https://github.com/search?ref=simplesearch&q=%s" :keybinding "g")
(defengine godoc "https://godoc.org/?q=%s")
(defengine golang "https://golang.org/?q=%s" :keybinding "z")
(defengine rustlang "https://doc.rust-lang.org/std/?search=%s" :keybinding "R")
(defengine docsrs "https://docs.rs/releases/search?query=%s&i-am-feeling-lucky=1" :keybinding "r")
(defengine msdn "https://docs.microsoft.com/en-us/dotnet/api/?view=netframework-4.7.1&term=%s" :keybinding "m"))
(use-package erc
:ensure t
:defer t
:commands (erc-znc/dogmatix erc)
:general
(private/set-leader-keys "xi" 'erc-znc/dogmatix)
:config
(require 'erc-ring)
(erc-ring-mode t)
(setq erc-prompt-for-password t)
;;(make-variable-buffer-local 'erc-fill-column)
;; (add-hook 'window-configuration-change-hook
;; '(lambda ()
;; (save-excursion
;; (walk-windows
;; (lambda (w)
;; (let ((buffer (window-buffer w)))
;; (set-buffer buffer)
;; (when (eq major-mode 'erc-mode)
;; (setq erc-fill-column (- (window-width w) 2)))))))))
(defun erc-znc-connect (user host port)
(let ((pass (auth-source-pass-get 'secret (format "znc/%s@%s" user host))))
(erc :server host :port port :nick user :password (format "%s:%s" user pass))))
(defun erc-znc/dogmatix ()
"Connect to freenode via ZNC server at dogmatix"
(interactive)
(erc-znc-connect "sjb" "dogmatix.nca.uwo.ca" 1234))
(setq erc-fill-function 'erc-fill-static
erc-fill-static-center 15)
;; (erc-autojoin-mode 1)
;; (setq erc-autojoin-channels-alist
;; '((".*\\.freenode.net" "#emacs" "#snappy" "#lxcontainers" "#go-nuts" "#Node.js" "#docker" "#linaro" "#linaro-tcwg")))
(erc-track-mode 1)
(setq erc-track-exclude-type '("JOIN" "NICK" "PART" "QUIT" "MODE"
"324" "329" "332" "333" "353" "477"))
(setq erc-prompt (lambda () (concat "[" (buffer-name) "]")))
;;(setq erc-prompt ">")
(setq erc-hide-list '("JOIN" "PART" "QUIT" "NICK")
erc-lurker-hide-list '("JOIN" "PART" "QUIT"))
(setq erc-default-server "irc.libera.chat")
(setq erc-prompt-for-nickserv-password t)
(setq erc-auto-query 'bury
erc-join-buffer 'bury
erc-interpret-mirc-color t
erc-rename-buffers t
erc-track-enable-keybindings nil
erc-track-visibility nil ; Only use the selected frame for visibility
erc-fill-column 80
erc-fill-function 'erc-fill-static
erc-fill-static-center 20
erc-autojoin-channels-alist '(("libera.chat" "#emacs" "#guix"))
erc-quit-reason (lambda (s) (or s "Fading out..."))
erc-modules
'(autoaway autojoin button completion fill irccontrols keep-place
list match menu move-to-prompt netsplit networks noncommands
readonly ring stamp track)))
(use-package empv
:ensure t
:defer t
:config
(add-to-list 'empv-mpv-args "--ytdl-format=best"))
(use-package ess
:ensure t
:defer t
:mode "\\.R\\'"
:config
(setq ess-eval-visibly nil
ess-ask-for-ess-directory nil))
(use-package eww
:ensure t
:defer t
:general
(private/set-leader-keys
"gu" 'browse-last-url-in-browser)
:commands browse-last-url-in-browser
:hook (eww-mode . toggle-word-wrap)
:custom
(browse-url-browser-function '(("." . browse-url-default-browser)))
:config
;;(setq browse-url-secondary-browser-function 'eww-browse-url)
(setq browse-url-secondary-browser-function 'browse-url-xdg-open)
;;(setq browse-url-default-browser 'browser-url-firefox)
(defun browse-last-url-in-browser ()
(interactive)
(save-excursion
(ffap-next t t))))
(use-package exec-path-from-shell
:if (memq window-system '(mac ns x))
:ensure t
:defer 1
:custom
(exec-path-from-shell-variables '("SSH_AUTH_SOCK" "PATH" "MANPATH" "GOPATH" "PYTHONPATH"))
:config
(exec-path-from-shell-initialize))
(use-package expand-region
:ensure t
:defer t
:commands (er/expand-region)
:general
(general-vmap "v" 'er/expand-region)
:config
(with-eval-after-load 'evil
(setq expand-region-contract-fast-key "z")))
(use-package expreg
:ensure t
:defer t
:general
(general-vmap "." 'expreg-expand)
(general-vmap "C-." 'expreg-contract))
(use-package gitignore-templates
:defer t
:ensure t)
(use-package goto-chg
:ensure t
:defer 1)
(use-package harpoon
:ensure t
:config
(setq harpoon-cache-file (expand-file-name "emacs/harpoon/" (xdg-data-home)))
:general
(private/set-leader-keys
"ta" #'harpoon-add-file
"tf" #'harpoon-toggle-file
"tc" #'harpoon-clear
"0" #'harpoon-toggle-quick-menu
"1" #'harpoon-go-to-1
"2" #'harpoon-go-to-2
"3" #'harpoon-go-to-3
"4" #'harpoon-go-to-4
"5" #'harpoon-go-to-5
"6" #'harpoon-go-to-6
"7" #'harpoon-go-to-7
"8" #'harpoon-go-to-8
"9" #'harpoon-go-to-9))
(use-package helpful
:ensure t
:general
(general-def [remap describe-command] #'helpful-command
[remap describe-function] #'helpful-callable
[remap describe-key] #'helpful-key
[remap describe-symbol] #'helpful-symbol
[remap describe-variable] #'helpful-variable)
("C-h f" 'helpful-callable
"C-h v" 'helpful-variable
"C-h K" 'describe-keymap)
(:keymaps 'helpful-mode-map [remap revert-buffer] #'helpful-update)
(private/set-leader-keys "h." 'helpful-at-point)
:init
(setq-default read-symbol-positions-list nil)
(with-eval-after-load 'evil
(add-to-list 'evil-motion-state-modes 'helpful-mode)))
(use-package hippie-exp
:ensure nil
:general
(general-def [remap dabbrev-expand] 'hippie-expand)
:custom
(hippie-expand-try-functions-list
'(try-complete-file-name-partially
try-complete-file-name
try-expand-dabbrev
try-expand-dabbrev-all-buffers
try-expand-dabbrev-from-kill)))
(use-package iedit
:ensure t
:general
("C-;" 'iedit-mode) ; also note: C-' toggles focus of matches
(:keymaps 'iedit-mode-keymap
"C-g" 'iedit-mode) ; so I can exit iedit with C-g
:config
(advice-add #'iedit--get-scope ; switch default to function scope
:filter-args
(defun my/iedit-defun-by-default (arg)
(cond ((eq (car arg) nil) '(0))
((eq (car arg) 0) '(nil))
(t arg)))))
(use-package jinx
:ensure t
:defer t
:general
("M-$" 'jinx-correct
"C-M-$" 'jinx-languages)
:config
(with-eval-after-load 'vertico
(add-to-list 'vertico-multiform-categories
'(jinx grid (vertico-grid-annotate . 20)))
(vertico-multiform-mode 1)))
(use-package kind-icon
:after corfu
;; Add hook to reset cache so the icon colors match my theme
;; NOTE 2022-02-05: This is a hook which resets the cache whenever I switch
;; the theme using my custom defined command for switching themes. If I don't
;; do this, then the backgound color will remain the same, meaning it will not
;; match the background color corresponding to the current theme. Important
;; since I have a light theme and dark theme I switch between. This has no
;; function unless you use something similar
:hook (after-load-theme . (lambda () (interactive) (kind-icon-reset-cache)))
:custom
(kind-icon-use-icons t)
(kind-icon-default-face 'corfu-default) ; Have background color be the same as `corfu' face background
(kind-icon-blend-background nil) ; Use midpoint color between foreground and background colors ("blended")?
(kind-icon-blend-frac 0.08)
:config
(add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter) ; Enable `kind-icon'
(add-to-list 'kind-icon-mapping '(tabnine "ai" :icon "cloud" :face shadow) t))
(use-package link-hint
:ensure t
:defer t
:general
(private/set-leader-keys
"elo" 'link-hint-open-link
"elc" 'link-hist-open-copy))
(use-package lxc
:defer t
:ensure t)
(use-package lxc-tramp
:defer 1
:ensure t)
(use-package lxd-tramp
:defer 1
:ensure t)
(use-package incus-tramp
:ensure nil
:after tramp
:config
(incus-tramp-add-method)
(tramp-set-completion-function incus-tramp-method
'((incus-tramp-completion-function-alist)))
)
(setq mail-user-agent 'mu4e-user-agent)
(use-package mu4e
:if (eq system-type 'gnu/linux)
:ensure nil
:defer t
:hook (mu4e-compose-mode . turn-on-auto-fill)
:general
(private/set-leader-keys "xm" 'mu4e)
:custom
(mu4e-maildir "~/.maildir")
(mu4e-maildir-shortcuts nil)
(mu4e-view-prefer-html t)
(shr-color-visible-luminance-min 70)
(shr-color-visible-distance-min 80)
(mu4e-sent-messages-behavior 'sent)
(mu4e-html-renderer 'w3m)
(mu4e-change-filenames-when-moving t)
(mu4e-view-show-addresses t)
(mu4e-attachment-dir "~/Downloads")
(mu4e-get-mail-command "mbsync -a")
(mu4e-update-interval (* 5 60))
(mu4e-decryption-policy t)
(mu4e-compose-signature-auto-include 't)
(mu4e-compose-format-flowed t)
(mml-secure-smime-sign-with-sender t)
:config
(require 'mu4e-contrib)
(require 'org-mu4e)
;;(setq epg-debug t)
;;(setq mu4e-html2text-command "w3m -dump -T text/html")
;;(setq mu4e-html2text-command 'mu4e-shr2text)
(setq smtpmail-stream-type 'starttls
smtpmail-smtp-service 587)
(setq smtpmail-queue-mail nil)
(setq send-mail-function 'smtpmail-send-it
message-send-mail-function 'smtpmail-send-it)
(add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode)
;; don't keep message buffers around
(setq message-kill-buffer-on-exit t))
(use-package nov
:ensure t
:mode ("\\.epub\\'" . nov-mode)
:custom
(nov-save-place-file (expand-file-name "emacs/nov-places" (xdg-cache-home)))
:config
(with-eval-after-load 'evil
(evil-set-initial-state 'nov-mode 'emacs))
:preface
(defun my-nov-setup ()
(visual-line-mode 1)
(face-remap-add-relative 'variable-pitch :family "Times New Roman" :height 1.5)
(if (fboundp 'olivetti-mode) (olivetti-mode 1)))
:hook (nov-mode . my-nov-setup))
(use-package obsidian
:ensure t
:defer t
:custom
;; This directory will be used for `obsidian-capture' if set.
(obsidian-inbox-directory "Inbox")
(obsidian-templates-directory "Templates")
(obsidian-daily-notes-directory "Dailies")
:general
(private/set-leader-keys
"no" #'obsidian-roam-capture
"s#" '(obsidian-search :wk "obsidian search")
"f#" '(obsidian-tag-find :wk "obsidian find"))
(private/set-leader-keys :keymaps 'obsidian-mode-map
"go" #'obsidian-jump)
(:keymaps 'obsidian-mode-map
;; Replace C-c C-o with Obsidian.el's implementation. It's ok to use another key binding.
"C-c C-o" #'obsidian-follow-link-at-point
;; Jump to backlinks
"C-c C-b" #'obsidian-backlink-jump
;; If you prefer you can use `obsidian-insert-link'
"C-c C-l" #'obsidian-insert-wikilink)
:config
(defun obsidian-roam-capture ()
"Create new obsidian note.
In the `obsidian-inbox-directory' if set otherwise in `obsidian-directory' root."
(interactive)
(let* ((title (read-from-minibuffer "Title: "))
(date (format-time-string "%Y%m%d%H%M%S"))
(filename (s-concat obsidian-directory "/" obsidian-inbox-directory "/" date "-" title ".md"))
(clean-filename (s-replace "//" "/" filename)))
(find-file (expand-file-name clean-filename) t)
(save-buffer)
(add-to-list 'obsidian-files-cache clean-filename)))
(obsidian-specify-path "~/Documents/nca-notes")
(global-obsidian-mode t))
(use-package paren
:ensure nil
:hook (prog-mode . show-paren-mode))
(use-package pass
:ensure t
:defer t)
(use-package auth-source-pass
;; passwdstring
;; host: host.domain.com
;; user: user@domain.com
;; port: 993
:ensure t
:hook (after-init . auth-source-pass-enable)
:config
(defun auth-pass-restart ()
"Restart the auth-password-store package"
(interactive)
(auth-pass-enable)))
(use-package ob-d2
:after org
:vc (:fetcher github :repo "dmacvicar/ob-d2")
:config
(org-babel-do-load-languages 'org-babel-load-languages '((d2 . t))))
(use-package plantuml-mode
:ensure t
:after org
:custom
(org-plantuml-jar-path "/usr/share/java/plantuml/plantuml.jar")
:init
(add-to-list 'org-src-lang-modes '("plantuml" . plantuml))
(org-babel-do-load-languages 'org-babel-load-languages '((plantuml . t))))
(use-package pdf-tools
:mode ("\\.[pP][dD][fF]\\'" . pdf-view-mode)
:magic ("%PDF" . pdf-view-mode)
:custom
;; PDF Files
(doc-view-continuous t)
(pdf-view-display-size 'fit-page)
(pdf-annot-activate-created-annotations t)
:preface
(defun my-pdf-set-midnight-colors ()
(setq pdf-view-midnight-colors
`(,(face-foreground 'default) . ,(face-background 'default))))
;; Workaround for pdf-tools not reopening to last-viewed page
;; https://github.com/politza/pdf-tools/issues/18
(defun my-pdf-set-last-viewed-bookmark ()
(interactive)
(when (eq major-mode 'pdf-view-mode)
(bookmark-set (my-pdf-generate-bookmark-name))))
(defun my-pdf-jump-last-viewed-bookmark ()
(when (my-pdf-has-last-viewed-bookmark)
(bookmark-jump (my-pdf-generate-bookmark-name))))
(defun my-pdf-has-last-viewed-bookmark ()
(assoc
(my-pdf-generate-bookmark-name) bookmark-alist))
(defun my-pdf-generate-bookmark-name ()
(concat "LAST-VIEWED: " (buffer-name)))
(defun my-pdf-set-all-last-viewed-bookmarks ()
(dolist (buf (buffer-list))
(with-current-buffer buf
(my-pdf-set-last-viewed-bookmark))))
:hook ((after-load-theme . my-pdf-set-midnight-colors)
(kill-buffer . my-pdf-set-last-viewed-bookmark)
(pdf-view-mode . my-pdf-jump-last-viewed-bookmark)
(kill-emacs . (lambda ()
(unless noninteractive ; as `save-place-mode' does
(my-pdf-set-all-last-viewed-bookmarks)))))
:config
(require 'pdf-occur)
(define-pdf-cache-function pagelabels)
;; (pdf-tools-install t nil t t)
;; swiper doesn't work with pdf-tools so use normal isearch
(define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward))
(use-package popper
:ensure t
:general
(general-nmap "gp" 'popper-toggle)
(general-def "M-`" 'popper-cycle)
(private/set-leader-keys
"bc" 'popper-cycle
"bp" 'popper-toggle-type
"bk" '(popper-kill-latest-popup :wk "kill popper")
"Tp" '(popper-toggle-latest :wk "popper"))
:defer 1
:config
(setq popper-reference-buffers
'("\\*Messages\\*"
"^\\*Warnings\\*"
"[Oo]utput\\*$"
"^\\*Compile-Log\\*"
"^\\*Backtrace\\*"
"^\\*evil-registers``*"
"^\\*Apropos"
"^Calc:"
"^\\*Shell Command Output\\*"
"\\*[Wo]*Man.*\\*"
cheat-sh-mode
dogears-list-mode
bm-show-mode
help-mode
man-mode
helpful-mode
ibuffer-mode
occur-mode
eldoc-mode
deadgrep-mode
rg-mode
inferior-scheme-mode
term-mode
shell-mode
eshell-mode
magit-stash-mode
magit-status-mode
"magit: .*"
"\\*eshell\\*"
process-menu-mode
compilation-mode))
(setq popper-group-function #'popper-group-by-project)
(setq popper-display-control nil)
(popper-echo-mode 1)
(popper-mode +1))
(use-package project
:ensure t
:demand t
:general
(private/set-leader-keys
"gp" '(project-switch-project :wk "project")
"p" '(:keymap project-prefix-map :wk "project"))
(general-def :keymaps 'project-prefix-map
"a" 'sjb/project-add-git-repo
"." #'flymake-show-project-diagnostics
"L" 'project-remember-projects-under
"X" 'project-forget-project
"Z" 'project-forget-zombie-projects)
:config
(defun sjb/set-tab-bar-name-to-project (&rest _)
(when (project-current)
(tab-bar-rename-tab (project-root (project-current)))))
(advice-add 'project-switch-project :after #'sjb/set-tab-bar-name-to-project)
(with-eval-after-load 'magit
(defun sjb/set-frame-name-to-project (&rest _)
(set-frame-name
(concat "Project|" (project-root (project-current)))))
(advice-add 'project-switch-project :after #'sjb/set-frame-name-to-project)
(require 'magit)
(defun sjb/project-add-git-repo ()
(interactive)
(let ((project-root (magit-toplevel)))
(if (and project-root (not (member `(,project-root) project--list)))
(add-to-list 'project--list `(,project-root))
(message "Project already in the list."))
(project-current nil project-root)
(sjb/set-frame-name-to-project))))
;; Make sure project is initialized
(project--ensure-read-project-list))
(use-package project-x
:vc (:fetcher github :repo "karthink/project-x")
:after project
:custom
(project-x-save-interval nil) ;Save project state every 5 min
:init
(with-eval-after-load 'project
(add-to-list 'project-switch-commands '(?j "Restore windows" project-x-windows) t)
(project-x-mode 1)))
(use-package proced
:ensure nil
:defer t
:custom
(proced-enable-color-flag t)
(proced-tree-flag t))
(use-package rainbow-delimiters
:ensure t
:hook (prog-mode . rainbow-delimiters-mode))
(use-package rainbow-mode
:ensure t
:hook
(org-mode . rainbow-mode)
(css-mode . rainbow-mode)
(scss-mode . rainbow-mode)
(sass-mode . rainbow-mode)
(vue-mode . rainbow-mode))
(use-package ranger
:ensure t
:defer t
:commands (ranger deer)
:general
(private/set-leader-keys
"xr" 'ranger
"xD" 'deer)
:config
(setq ranger-hide-cursor nil))
(use-package recentf
:ensure nil
:defer 1
:hook (after-init . recentf-mode)
:config
(defun my/recent-file-truename (file)
(if (or (file-remote-p file nil t)
(not (file-remote-p file)))
(file-truename file)
file))
(setq recentf-filename-handlers
'(substring-no-properties ;; strip out lingering text properties
my/recent-file-truename ;; resolve symlinks of local files
abbreviate-file-name) ;; replace $HOME with ~
recentf-save-file (expand-file-name "recentf" user-emacs-directory)
recentf-auto-cleanup 'never
recentf-max-menu-items 0)
;; Exclude these from recentf
(dolist
(ex '("\\.gpg$"
"^/scp:"
"^/ssh:"
"^/su:"
"^/tmp/"
"^/sudo:"))
(add-to-list 'recentf-exclude ex))
(add-hook 'dired-mode-hook
(lambda ()
(recentf-add-file default-directory)))
(add-hook 'kill-emacs-hook #'recentf-cleanup)
(setq recentf-save-file (expand-file-name "emacs/recentf" (xdg-cache-home))))
(use-package request
:ensure t
:defer t
:custom
(request-storage-directory (expand-file-name "emacs/request" (xdg-data-home))))
(use-package restclient
:defer t
:ensure t)
(use-package ob-restclient
:ensure t
:defer t
:after org
:init
(with-eval-after-load 'org
(require 'ob-restclient)))
(use-package rg
:ensure t
:defer t
:general
(private/set-leader-keys
"s'" 'rg
"s." 'rg-dwim))
(use-package saveplace
:hook ((after-init . savehist-mode)
(after-init . save-place-mode))
:custom
(save-place t))
(use-package sidecar-locals
:defer 1
:hook (after-init . sidecar-locals-mode)
:config
(setq sidecar-locals-paths-allow
(list "/home/sjb/Projects/")))
(use-package shackle
:ensure
:diminish
:hook (after-init . shackle-mode)
:config
(defun my-split-window-sensibly (&optional window)
"replacement `split-window-sensibly' function which prefers vertical splits"
(interactive)
(let ((window (or window (selected-window))))
(or (and (window-splittable-p window t)
(with-selected-window window
(split-window-right)))
(and (window-splittable-p window)
(with-selected-window window
(split-window-below))))))
(setq split-window-preferred-function #'split-window-sensibly)
(setq shackle-rules '(
("\\*Cargo.*" :regexp t :other t :select nil)
("*Messages*" :select t :same nil :other t :popup t :inhibit-window-quit nil)
("*Warnings*" :select nil :other t :popup t :inhibit-window-quit nil)
("*go-guru-output*" :select t :same t)
("*Proced*" :select t :popup t :align below)
("*eldoc*" :select t :popup t :align right :size 0.4)
("*Buffer List*" :select t :align below :popup t :size 0.4)
("*evil-register* " :select nil :popup t :size 0.33)
(ibuffer-mode :same nil :select t :popup t :size 0.33)
(git-commit-mode :size 0.3 :popup t :select t)
(magit-status-mode :select t :other t :align left :size 0.33)
(magit-log-mode :align left :size 0.33 :select t)
(magit-revision-mode :same t)
(magit-process-mode :frame nil :popup t)
(magit-mode-diff :popup t :same nil :other t)
("*Calendar*" :select t :size 0.3 :align below)
("\\*[Wo]*Man.*\\*" :regexp t :select t :inhibit-window-quit nil :popup t :align left)
("*info*" :select t :inhibit-window-quit t :same t)
("\\*Async Shell.*\\*" :regexp t :ignore t )
(" *transient*" :frame nil :popup t :select nil :align below) ; Magit helper popups
;; ** Proced **
(" *Marked Processes*" :frame nil :popup t :select t)
;; ** Byte-compiler
("*Compile-Log*" :frame nil :popup t :select t)
;; ** Local variables warning **
("*Local Variables*" :same t :frame nil :popup t :select t)
;; ** Misc **
("*Org PDF LaTeX Output*" :select nil)
("*Org Preview LaTeX Output*" :select nil)
(" *undo-tree*" :frame nil)
("*Register Preview*" :frame nil :noselect t)
(flycheck-error-list-mode :select t :align below :size 0.33)
(dired-mode :select t :other t :same t)
((helpful-mode help-mode) :popup t :align right :inihibit-window-quit nil)
("^\\*Dictionary\\*" :popup t :size 0.12)
(apropos-mode :select nil :popup nil :align below :size 0.2)
(special-mode :select t :popup t :size 0.33 :inhibit-window-quit nil)
(rg-mode :select t :popup t :size 0.33)
(grep-mode :select t :popup t :size 0.33)
(occur-mode :select t :popup t :size 0.33)
(completion-list-mode :select nil :popup t :align below :size 0.12)
(process-menu-mode :popup t :align below)
(compilation-mode :select nil :align below :size 0.2 :inhibit-window-quit nil)))
(setq shackle-select-reused-windows nil) ; default nil
(setq shackle-default-alignment 'right) ; default below
(setq shackle-default-size 0.4) ; default 0.5
(setq shackle-default-rule nil))
(use-package super-save
:ensure t
:hook (after-init . super-save-mode))
(use-package texfrag
:ensure t
:hook (markdown-mode . texfrag-mode))
(use-package time
:ensure nil
:hook (after-init . display-time)
:custom
(display-time-day-and-date t)
(display-time-24hr-format t)
;; TODO (display-time-default-load-average t)
(display-time-use-mail-icon t)
(display-time-interval 10))
(use-package vterm
:ensure t
:defer t
:commands vterm
:config
;; Speed up vterm
(setq vterm-timer-delay 0.01))
(use-package vundo
:defer t
:ensure t
:custom
(vundo-glyph-alist vundo-unicode-symbols))
(use-package uniquify
:ensure nil
:defer t
:custom
;; TODO (uniquify-buffer-name-style 'reverse)
(uniquify-separator " • ")
(uniquify-after-kill-buffer-p t)
(uniquify-ignore-buffers-re "^\\*"))
(use-package wgrep
:ensure t
:commands wgrep-change-to-wgrep-mode
:general (:keymaps 'grep-mode-map "C-c C-q" 'wgrep-change-to-wgrep-mode))
(use-package yasnippet
:ensure t
:defer 1
:hook (after-init . yas-global-mode)
:diminish (yas-minor-mode . "γ")
:general
(general-def :keymaps 'yas-minor-mode-map
"<backtab>" #'yas-expand)
(general-def :keymaps 'yas-keymap
"C-e" 'yas/goto-end-of-active-field
"C-a" 'yas/goto-start-of-active-field
"C-n" 'yas-next-field-or-maybe-expand
"C-p" 'yas-prev-field))
(use-package yasnippet-snippets
:ensure t
:after yasnippet)
(use-package yankpad
:ensure t
:commands (yankpad-expand)
:config
(setq yankpad-file "~/.dotfiles/yankpad.org")
(yankpad-reload))
(use-package zoxide
:hook (find-file . zoxide-add)
:general
(general-nmap "gZ" 'zoxide-find-file))
(use-package zoom-window
:ensure t
:commands zoom-window-zoom
:general (:keymaps 'evil-window-map "z" 'zoom-window-zoom))
(setq electric-pair-preserve-balance nil)
(defun comment-auto-fill ()
(setq-local comment-auto-fill-only-comments t)
(auto-fill-mode 1))
(defun default-prog-env-setup ()
(display-line-numbers-mode 1)
;; TODO (setq-local indent-tabs-mode nil)
(subword-mode t)
(comment-auto-fill))
;;(setq font-lock-maximum-decoration '((c-mode . 2) (c++-mode . 2) (t . t)))
(add-hook 'prog-mode-hook #'default-prog-env-setup)
(add-to-list 'auto-mode-alist '("\\.ino\\'" . c-mode))
(setq gdb-many-windows t
gdb-show-main t)
(require 'ansi-color)
(add-hook 'compilation-filter-hook 'ansi-color-compilation-filter)
(add-hook 'comint-mode-hook 'ansi-color-for-comint-mode-on)
(general-define-key :keymaps '(prog-mode-map c-mode-base-map) (kbd "C-c k") 'kill-compilation)
;;(setq compilation-environment '("TERM=tmux-256color"))
(setq compilation-max-output-line-length nil)
(add-hook 'compilation-mode-hook
(lambda ()
;; TODO (setq-local compilation-scroll-output t)
(setq-local scroll-conservatively most-positive-fixnum)
(setq-local scroll-margin 0)))
(use-package eglot-booster
:after eglot
:hook (eglot-managed-mode . eglot-booster-mode)
:vc (:fetcher github :repo "sjb/eglot-booster"))
(use-package eglot
:hook (eglot-managed-mode . sjb/setup-eglot)
:after cape
:general
(general-evil-define-key 'normal eglot-mode-map
"g=" 'eglot-format-buffer)
(general-evil-define-key 'visual eglot-mode-map
"g=" 'eglot-format)
(general-evil-define-key 'normal eglot-mode-map
[remap previous-error] 'flymake-goto-previous-error
[remap next-error] 'flymake-goto-next-error)
(private/set-leader-keys
:keymaps 'eglot-mode-map
"ca" '(eglot-code-actions :wk "code actions")
"cA" '(eglot-code-action-inline :wk "code action")
"ci" '(eglot-code-action-organize-imports :wk "organize imports")
"ce" '(eglot-code-action-extract :wk "extract")
"cw" '(eglot-code-action-rewrite :wk "rewrite")
"cq" '(eglot-code-action-quickfix :wk "quickfix")
"cr" '(eglot-rename :wk "rename")
"cT" '(:ignore t :wk "toggle")
"cTi" '(eglot-inlay-hints-mode :wk "inlay hints"))
:custom
(eglot-events-buffer-size 0)
(eglot-sync-connect nil)
(eglot-report-progress nil)
(eglot-connect-timeout nil)
(eglot-autoshutdown t)
(eglot-send-changes-idle-timeout 1)
(completion-category-defaults nil)
(eldoc-echo-area-prefer-doc-buffer t)
;; display eldoc only in buffer not in minibuffer
;;(eldoc-display-functions '(eldoc-display-in-buffer))
(eldoc-documentation-strategy #'eldoc-documentation-compose)
:init
(defun sjb/setup-eglot ()
;; Optionally configure the cape-capf-buster.
;;(add-hook 'flymake-diagnostic-functions #'eglot-flymake-backend nil t)
;; Show flymake diagnostics first.
;; (setq eldoc-documentation-functions
;; (cons #'flymake-eldoc-function
;; (remove #'flymake-eldoc-function eldoc-documentation-functions)))
;; Show all eldoc feedback.
;;(setq eldoc-documentation-strategy #'eldoc-documentation-compose)
;;(eldoc-mode 1)
;;(flymake-mode 1)
;;(setq-local font-lock-maximum-decoration nil)
(setq-local completion-at-point-functions
(list (cape-capf-super
#'tabnine-completion-at-point
#'eglot-completion-at-point))))
:config
(fset #'jsonrpc--log-event #'ignore)
;; (setq jsonrpc-event-hook nil)
;; disable eldoc
;;(add-to-list 'eglot-stay-out-of 'eldoc)
;;(add-to-list 'eglot-stay-out-of 'flymake)
;;(setq eglot-ignored-server-capabilities '(:documentHighlightProvider))
;; TODO (set-face-attribute 'eglot-inlay-hint-face nil :family "MonaspiceRn Nerd Font" :weight 'thin)
(add-to-list 'eglot-server-programs
'((c++-ts-mode c-ts-mode) . ("clangd"
"-j=8"
"--compile-commands-dir=build"
"--background-index"
"--cross-file-rename"
"--completion-style=detailed"
"--inlay-hints"
"--pch-storage=memory"
"--clang-tidy")))
)
(use-package dape
:defer t
:vc (:fetcher github :repo "svaante/dape"))
(use-package compile-multi
:vc (:fetcher github :repo "mohkale/compile-multi")
:ensure t
:defer t
:general
(general-def [remap compile] #'compile-multi)
:config
(with-eval-after-load 'project
(defun sjb/project-current-root ()
(when-let (project (project-current))
(car (project-roots project))))
(setq compile-multi-default-directory #'sjb/project-current-root))
(setq compile-multi-config '(((file-exists-p "CMakeLists.txt")
("cmake:create" . "cmake -B build .")
("cmake:all" . "cmake --build build --target all")
("cmake:test" . "cmake --build build --target test"))
((file-exists-p "Makefile")
("make:build" . "make build")
("make:push" . "make push")
("make:all" . "make all"))
((file-exists-p "Cargo.toml")
("cargo:build" . "cargo build")
("cargo:run" . "cargo run")
("cargo:clean" . "cargo clean")
("cargo:test" . "cargo test")
("cargo:check" . "cargo check"))
((file-exists-p "build.zig")
("zig:build" . "zig build")
("zig:run" . "zig run"))
((file-expand-wildcards "*.sln")
("dotnet:build" . "dotnet build")
("dotnet:clean" . "dotnet clean")
("dotnet:nuget" . "dotnet nuget locals -c all")
("dotnet:pack" . "dotnet pack")))))
(use-package consult-compile-multi
:ensure t
:after consult
:after compile-multi
:defer 1
:config
(consult-compile-multi-mode))
(use-package compile-multi-all-the-icons
:ensure t
:after all-the-icons-completion
:after compile-multi
:demand t)
(use-package compile-multi-embark
:ensure t
:after embark
:after compile-multi
:demand t
:config (compile-multi-embark-mode +1))
(use-package dumb-jump
:hook (prog-mode . dumb-jump-mode)
;;(xref-backend-functions . dumb-jump-xref-activate)
:general
(general-nmap "g." #'dumb-jump-go)
(private/set-leader-keys
"gq" #'dumb-jump-quick-look)
:custom
(dumb-jump-disable-obsolete-warning t)
;;(xref-show-definitions-function #'xref-show-definitions-completing-read)
:ensure t)
(use-package editorconfig
:ensure t
:hook (prog-mode . editorconfig-mode)
:custom
(editorconfig-get-properties-function 'editorconfig-core-get-properties-hash))
(use-package hideshow
:ensure t
:hook ((prog-mode emacs-lisp-mode sh-mode) . hs-minor-mode)
:config
(defvar hs-overlay-map (make-sparse-keymap) "Keymap for hs minor mode overlay.")
(defun hs-abstract-overlay (ov)
(let* ((start (overlay-start ov))
(end (overlay-end ov))
(str (format " <%d lines> " (count-lines start end))) text)
(setq text (propertize str 'face 'hs-block-flag-face 'help-echo (buffer-substring (1+ start) end)))
(overlay-put ov 'display text)
(overlay-put ov 'pointer 'hand)
(overlay-put ov 'keymap hs-overlay-map)))
(setq hs-set-up-overlay 'hs-abstract-overlay)
(setq hs-isearch-open t))
(use-package ansible
:ensure t
:defer t)
(use-package conf-mode
:mode
(;; systemd
("\\.service\\'" . conf-unix-mode)
("\\.timer\\'" . conf-unix-mode)
("\\.target\\'" . conf-unix-mode)
("\\.mount\\'" . conf-unix-mode)
("\\.automount\\'" . conf-unix-mode)
("\\.slice\\'" . conf-unix-mode)
("\\.socket\\'" . conf-unix-mode)
("\\.path\\'" . conf-unix-mode)
;; general
("conf\\(ig\\)?$" . conf-mode)
("rc\\(_local\\)?$" . conf-mode)))
(use-package c-ts-mode
:ensure t
:defer t
:custom
(gdb-many-windows t)
(gdb-show-main t))
(use-package clang-format
:ensure t
:general (c-mode-base-map "C-c C-f" 'clang-format-region)
(private/set-leader-keys :keymaps 'c-mode-base-map
"bf" 'clang-format-buffer)
(general-evil-define-key 'normal c-mode-base-map
"g=" 'clang-format-buffer)
(general-evil-define-key 'visual c-mode-base-map
"g=" 'clang-format-region)
:init
(setq clang-format-executable "clang-format"))
(use-package cmake-ts-mode
:ensure t
:mode ("\\(?:CMakeLists\\.txt\\|\\.cmake\\)\\'" . cmake-ts-mode)
:general (cmake-mode-map "C-h C-g" 'cmake-help))
(use-package cmake-ide
:ensure t
:hook (c-mode-common-hook . unpackaged/cmake-ide-setup)
:commands (unpackaged/cmake-ide-setup)
:general (c-mode-base-map
"C-c D" 'invoke-gdb
"C-c c" 'cmake-ide-compile)
:config
(defun unpackaged/cmake-ide-setup ()
(let ((root (ignore-errors (project-current))))
(when root
(when (file-exists-p (expand-file-name "CMakeLists.txt" root))
(setq-local cmake-ide-build-dir (expand-file-name "build" root))
(message "cmake : %s" root)
(cmake-ide-setup)))))
(defun invoke-gdb ()
(interactive)
(cd (cmake-ide--get-build-dir))
(gud-gdb (concat "gdb -i=mi --fullname " (cmake-ide--get-build-dir)))))
(use-package disaster
:ensure t
:general (c-mode-base-map "C-c a" 'disaster))
(add-to-list 'auto-mode-alist '("\\.definition\\'" . nxml-mode))
(add-to-list 'auto-mode-alist '("\\.csproj\\'" . nxml-mode))
(use-package csharp-mode
:ensure
:init
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(csharp-ts-mode . ("csharp-ls"))))
:mode
("\\.cs\\'" . csharp-ts-mode)
("\\.cake\\'" . csharp-ts-mode))
(use-package dotnet
:ensure t
:defer t
:init
(setq dotnet-mode-keymap-prefix (kbd "C-c n")))
(use-package csv-mode
:ensure t
:defer t)
(use-package dart-mode
:ensure t
:custom
(dart-sdk-path (concat (getenv "HOME") "/.flutter/bin/cache/dark-sdk/"))
:defer t)
(use-package hover
:ensure t
:general
(:keymaps 'dart-mode-map
"C-M-z" #'hover-run-or-hot-reload
"C-M-x" #'hover-run-or-hot-restart
"C-M-p" #'hover-take-screenshot)
:init
(setq flutter-sdk-path (concat (getenv "HOME") "/.flutter")
hover-command-path (concat (getenv "HOME") "/go/bin/hover")
hover-hot-reload-on-save t
hover-screenshot-path (concat (getenv "HOME") "/Pictures")
hover-screenshot-prefix "flutter-hover-"
hover-observatory-uri "http://localhost:50300"
hover-clear-buffer-on-hot-restart t))
(use-package ein
:defer t
:custom
(ein:jupyter-server-use-subcommand "notebook")
(ein:output-area-inlined-images t)
:config
(require 'ein)
(require 'ein-notebook))
(use-package go-ts-mode
:ensure t
:mode ("\\.go\\'" . go-ts-mode)
:general (go-mode-map
"C-c C-r" 'go-run-main
"C-c C-d" 'godoc-at-point
"C-h C-g" 'godoc)
:custom
(go-play-browse-function 'browse-url)
:init
(defvar go-tools-gopath (expand-file-name "go" (getenv "HOME")))
(defvar go-tools-bin (expand-file-name "bin" go-tools-gopath))
:config
(setq exec-path (append exec-path (list go-tools-bin)))
(setq gofmt-command (cond
((executable-find "goimports")
"goimports")
(t "gofmt"))))
(use-package js
:mode ("\\.js\\'" . js-ts-mode)
:init
(setq js-chain-indent t)
(setq js-indent-level 2)
(setq js-indent-first-init 'dynamic))
(use-package json-mode
:ensure t
:defer t
:mode "\\.json\\'"
:config
(with-eval-after-load 'flycheck
(setq-default flycheck-disabled-checkers
(append flycheck-disabled-checkers '(json-jsonlist)))))
(use-package json-ts-mode
:ensure t
:mode ("\\.json\\'" . json-ts-mode))
(use-package julia-ts-mode
:ensure t
:mode ("\\.jl\\'" . julia-ts-mode))
(use-package julia-repl
:ensure t
:hook (julia-ts-mode julia-repl-mode))
(use-package kotlin-ts-mode
:ensure t
:mode ("\\.kt\\'" . kotlin-ts-mode))
(use-package lua-mode
:ensure t
:mode "\\.lua\\'")
(use-package matlab-mode
:ensure t
:mode "\\.m\\'"
:defer t
:custom
(matlab-shell-command "~/.local/bin/matlab")
(matlab-shell-command-switches (list "-nodisplay -nosplash"))
:config
(matlab-cedet-setup))
(use-package markdown-mode
:ensure t
:commands (markdown-mode gfm-mode)
:custom
(markdown-enable-math t)
(markdown-enable-html t)
(markdown-fontify-code-block-natively t)
(markdown-fontify-whole-heading-line t)
(markdown-hide-markup t)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.text\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode)))
(use-package nix-mode
:ensure t
:mode ("\\.nix\\'" . nix-mode)
:config
(use-package nix-ts-mode :ensure t))
(use-package php-mode
:ensure t
:mode "\\.php\\'")
(use-package pyvenv
:ensure t
:defer t
:custom
(pyvenv-menu t)
:hook ((python-ts-mode . pyvenv-mode)
(pyvenv-post-activate . pyvenv-restart-python))
:config
;; Setting work on to easily switch between environments
(setq pyvenv-workon "emacs")
(setenv "WORKON_HOME" (expand-file-name "~/.cache/envs/"))
(pyvenv-tracking-mode 1))
(use-package qml-mode
:ensure t
:mode "\\.qml\\'")
(use-package r-ts-mode
:mode ("\\.R\\'" . r-ts-mode)
:vc (:fetcher github :repo "sje30/r-ts-mode")
:ensure t)
;; rust-ide
(use-package rust-mode
:mode ("\\.rs\\'" . rust-mode)
:ensure t
:defer t
:custom
(rust-mode-treesitter-derive t)
:init
(setq rust-mode-treesitter-derive t)
:config
(require 'rust-compile)
(require 'rust-cargo)
(require 'rust-playpen)
(require 'rust-rustfmt)
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'((rust-ts-mode rust-mode) . ("rust-analyzer" :initializationOptions
( :procMacro (:enable t)
:cargo ( :buildScripts (:enable t)
:features "all")))))))
(use-package cargo
:ensure t
:hook ((rust-mode rust-ts-mode) . cargo-minor-mode)
:config
(setq exec-path (append exec-path '("~/.cargo/bin"))))
(use-package toml-mode
:ensure t
:mode "\\.toml\\'")
(use-package swift-mode
:ensure t
:mode "\\.swift\\'")
(use-package typescript-ts-mode
:ensure t
:mode ("\\.ts\\'" . typescript-ts-mode)
:config
(setq typescript-indent-level 4))
(use-package svelte-mode
:defer t
:ensure t
:custom
(svelte-basic-offset 4))
(define-derived-mode vue-mode web-mode "Vue" "Major mode for editing Vue code.")
(add-to-list 'auto-mode-alist '("\\.vue\\'" . vue-mode))
(with-eval-after-load 'web-mode
(add-to-list 'web-mode-comment-formats '("javascript" . "//")))
(setq imenu-generic-expression '(("html" "^<template>$" 0)
("js" "^<script>$" 0)
("js" "^\\s-*\\(data\\).*()\\s-?{" 1)
("js" "^\\s-*\\(mounted\\).*()\\s-?{" 1)
("js" "^\\s-*\\(beforeMount\\).*()\\s-?{" 1)
("js" "^\\s-*\\(beforeDestroy\\).*()\\s-?{" 1)
("js" "^\\s-*\\(created\\).*()\\s-?{" 1)
("js" "^\\s-*\\(computed\\):\\s-?{" 1)
("js" "^\\s-*\\(watch\\):\\s-?{" 1)
("js" "^\\s-*\\(methods\\):\\s-?{" 1)
("js" "^\\s-*\\(props\\):\\s-?{" 1)
("css" "^<css>$" 0))
imenu-create-index-function #'imenu-default-create-index-function)
(defun vue-setup-hook ()
(setq-local web-mode-script-padding 0)
(yas-activate-extra-mode 'js-mode)
(smartparens-mode)
;;(add-node-modules-path)
(with-eval-after-load 'evil-matchit
(turn-on-evil-matchit-mode)))
;; post-init
(with-eval-after-load 'flycheck
(flycheck-add-mode 'javascript-eslint 'vue-mode))
(add-hook 'vue-mode-hook #'vue-setup-hook)
(use-package handlebars-mode
:mode ("\\.hbs\\'"))
(use-package sass-mode
:ensure t
:defer t
:mode "\\.sass\\'")
(use-package scss-mode
:ensure t
:defer t
:mode "\\.scss\\'")
(use-package web-mode
:ensure t
:mode ("\\.html\\'" "\\.tpl\\'" "\\.gohtml\\'" "\\.gotmpl\\'" "\\.tsx\\'")
:general (web-mode-map
"C-c C-t v" 'web-mode-element-vanish
"C-c C-t k" 'web-mode-element-kill)
:config
(setq
web-mode-enable-auto-closing t
web-mode-enable-auto-expanding t
web-mode-enable-auto-pairing t
web-mode-enable-block-face t
web-mode-enable-comment-keywords t
web-mode-enable-css-colorization t
web-mode-enable-current-column-highlight t
web-mode-enable-current-element-highlight t
web-mode-markup-indent-offset 2
web-mode-css-indent-offset 2))
(use-package emmet-mode
:ensure t
:hook (sgml-mode web-mode css-mode handlebars-mode)
:general
(private/set-leader-keys
:keymaps 'emmet-mode-keymap
"epl" 'emmet-expand-line
"epy" 'emmet-expand-yas)
:config
(setq emmet-indentation 2)
(setq emmet-move-cursor-between-quotes t))
(use-package yaml-ts-mode
:defer t
:mode ("\\.yaml\\'" "\\.yml\\'"))
(use-package yaml-pro
:ensure t
:hook (yaml-ts-mode . yaml-pro-ts-mode))
(use-package zig-ts-mode
:ensure t
:mode (("\\.zig\\'" . zig-ts-mode)
("\\.zon\\'" . zig-ts-mode))
:vc (zig-ts-mode :url "https://codeberg.org/meow_king/zig-ts-mode.git" :branch "main")
:init
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(zig-ts-mode . ("zls"))))
(add-to-list 'treesit-language-source-alist
'(zig "https://github.com/maxxnino/tree-sitter-zig")))
(use-package lsp-mode
:ensure t
:after cape
:hook ((lsp-mode . lsp-enable-which-key-integration)
(lsp-after-open-hook . my/setup-lsp-capf)
(lsp-completion-mode . my/lsp-mode-setup-completion))
:custom
;; speed up lsp-mode
(lsp-diagnostics-provider :auto)
(lsp-completion-show-detail t)
(lsp-completion-show-kind t)
(lsp-log-io nil)
(lsp-restart 'interactive)
;;(lsp-signature-function 'lsp-signature-posframe)
;;(lsp-signature-render-documentation t)
;;(lsp-signature-auto-activate nil)
;;(lsp-semantic-tokens-enable t)
(lsp-enable-links t)
(lsp-enable-folding t)
(lsp-enable-snippet t)
(lsp-enable-symbol-highlighting t)
(lsp-enable-indentation t)
(lsp-enable-imenu t)
;;(lsp-enable-file-watchers nil)
(lsp-headerline-breadcrumb-enable t)
(lsp-headerline-breadcrumb-segments '(project file symbols))
;;(lsp-keep-workspace-alive nil)
;;(lsp-completion-enable t)
(lsp-eldoc-render-all nil)
(lsp-eldoc-enable-hover nil)
;;(lsp-modeline-diagnostics-mode nil)
;;(lsp-modeline-diagnostics-enable nil)
;;(lsp-modeline-code-actions-enable t)
(lsp-prefer-flymake nil)
(lsp-auto-guess-root t)
(lsp-idle-delay 1.0)
(lsp-inhibit-message t)
(lsp-message-project-root-warning t)
(lsp-session-file (expand-file-name "emacs/lsp-session-v1" (xdg-cache-home)))
;;(lsp-completion-enable-additional-text-edit t)
(lsp-highlight-symbol-at-point nil)
(lsp-keymap-prefix "C-c l")
(lsp-lens-enable nil)
(lsp-document-sync-method nil)
(lsp-disabled-clients (list 'omnisharp))
;; Other
;; (lsp-completion-provider :capf)
(lsp-completion-provider :none) ; Use corfu instead for lsp completions
:general
(:keymaps 'lsp-mode-map
[remap iedit-mode] 'lsp-iedit-highlights)
(general-evil-define-key 'normal lsp-mode-map
"g=" 'lsp-format-buffer)
(general-evil-define-key 'visual lsp-mode-map
"g=" 'lsp-format-region)
:init
(defun my/orderless-dispatch-flex-first (_pattern index _total)
(and (eq index 0) 'orderless-flex))
;; Optionally configure the first word as flex filtered.
(add-hook 'orderless-style-dispatchers #'my/orderless-dispatch-flex-first nil 'local)
;; Setup lsp to use corfu for lsp completion
(defun my/lsp-mode-setup-completion ()
"Use orderless completion style with lsp-capf instead of the
default lsp-passthrough."
(setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults))
'(orderless)))
(defun my/setup-lsp-capf ()
;; Optionally configure the cape-capf-buster.
(setq-local completion-at-point-functions
(list (cape-super-capf
#'tabnine-completion-at-point
#'lsp-completion-at-point
#'cape-file))))
(defun lsp-booster--advice-json-parse (old-fn &rest args)
"Try to parse bytecode instead of json."
(or
(when (equal (following-char) ?#)
(let ((bytecode (read (current-buffer))))
(when (byte-code-function-p bytecode)
(funcall bytecode))))
(apply old-fn args)))
(advice-add (if (progn (require 'json)
(fboundp 'json-parse-buffer))
'json-parse-buffer
'json-read)
:around
#'lsp-booster--advice-json-parse)
(defun lsp-booster--advice-final-command (old-fn cmd &optional test?)
"Prepend emacs-lsp-booster command to lsp CMD."
(let ((orig-result (funcall old-fn cmd test?)))
(if (and (not test?) ;; for check lsp-server-present?
(not (file-remote-p default-directory)) ;; see lsp-resolve-final-command, it would add extra shell wrapper
lsp-use-plists
(not (functionp 'json-rpc-connection)) ;; native json-rpc
(executable-find "emacs-lsp-booster"))
(progn
(message "Using emacs-lsp-booster for %s!" orig-result)
(cons "emacs-lsp-booster" orig-result))
orig-result)))
(advice-add 'lsp-resolve-final-command :around #'lsp-booster--advice-final-command)
:config
;; rust
(setq lsp-rust-server 'rust-analyzer)
;; enable / disable the hints as you prefer:
(setq lsp-rust-analyzer-server-display-inlay-hints nil)
(setq lsp-rust-analyzer-cargo-watch-command "clippy")
(setq lsp-rust-analyzer-display-lifetime-elision-hints-enable "skip_trivial")
(setq lsp-rust-analyzer-display-lifetime-elision-hints-use-parameter-names nil)
(setq lsp-rust-analyzer-display-chaining-hints nil)
(setq lsp-rust-analyzer-display-closure-return-type-hints nil)
(setq lsp-rust-analyzer-display-parameter-hints nil)
(setq lsp-rust-analyzer-display-reborrow-hints nil)
;; vuejs
(setq lsp-vetur-use-workspace-dependencies t)
;; typescript
(setq lsp-typescript-suggest-auto-imports nil)
(setq lsp-typescript-preferences-quote-style "single")
;; clangd
;;(setq lsp-clients-clangd-args '("--header-insertion-decorators" "--clang-tidy"))
;;(setq lsp-clangd-binary-path "~/.emacs.d/.cache/lsp/clangd/clangd_15.0.6/bin/clangd")
(setq lsp-clients-clangd-args '("--header-insertion-decorators=0" "--clang-tidy"))
(defun set-lsp-custom-setting()
(lsp-register-custom-settings
'(("pyls.plugins.pyls_mypy.enabled" t t)
("pyls.plugins.pyls_mypy.live_mode" nil t)
("pyls.plugins.pyls_black.enabled" t t)
("pyls.plugins.pyls_isort.enabled" t t)
;; Disable these as they're duplicated by flake8
("pyls.plugins.pycodestyle.enabled" nil t)
("pyls.plugins.mccabe.enabled" nil t)
("pyls.plugins.pyflakes.enabled" nil t))))
(add-hook 'lsp-after-initialize-hook #'set-lsp-custom-setting))
(use-package lsp-ui
:ensure t
:defer t
:after lsp-mode
:hook (lsp-mode . lsp-ui-mode)
:commands lsp-ui-mode
:custom
(lsp-ui-doc-frame t)
(lsp-ui-doc-enable nil)
(lsp-ui-doc-header t)
(lsp-ui-doc-max-width 60)
(lsp-ui-doc-delay 1.0)
(lsp-ui-doc-show-with-mouse nil)
(lsp-ui-doc-show-with-cursor nil)
(lsp-ui-doc-include-signature t)
(lsp-ui-doc-border (face-foreground 'default))
(lsp-ui-doc-alignment 'frame)
(lsp-ui-doc-position 'top)
(lsp-ui-sideline-enable t)
(lsp-ui-sideline-delay 1.0)
(lsp-ui-sideline-update-mode 'line)
(lsp-ui-sideline-show-hover t)
(lsp-ui-sideline-show-symbol t)
(lsp-ui-sideline-show-diagnostics t)
(lsp-ui-sideline-show-code-actions nil)
(lsp-ui-peek-fontify 'always)
(lsp-ui-peek-list-width 60)
(lsp-ui-peek-always-show t)
:general
(private/set-leader-keys
:keymaps 'lsp-mode-map
"Tls" 'lsp-ui-sideline-toggle-symbols-info
"TlS" 'lsp-ui-sideline-mode
"Tld" 'lsp-ui-doc-mode
"cF" 'lsp-ui-doc-focus-frame
"cU" 'lsp-ui-doc-unfocus-frame
"cK" 'lsp-ui-doc-glance
"cd" 'lsp-ui-peek-find-definitions
"cI" 'lsp-ui-peek-find-implementation
"cw" 'lsp-ui-peek-find-workspace-symbol
"cr" 'lsp-ui-peek-find-references
"ci" 'lsp-ui-imenu
;;"cf" 'lsp-ui-flycheck-list
"cg" 'lsp-ui-doc-glance
"ch" 'lsp-ui-doc-hide
"cs" 'lsp-ui-doc-show))
(use-package lsp-treemacs :ensure t :defer t)
(use-package dap-mode
:ensure t
:defer t
:after lsp-mode
:general
(:keymaps 'lsp-mode-map
"<f12>" 'dap-debug
"<f9>" 'dap-next
"<f8>" 'dap-continue
"<f7>" 'dap-breakpoint-toggle)
:hook ((dap-mode . dap-ui-mode)
(python-mode . (lambda () (require 'dap-python)))
(ruby-mode . (lambda () (require 'dap-ruby)))
(go-mode . (lambda () (require 'dap-go)))
(java-mode . (lambda () (require 'dap-java)))
((c-mode c++-mode objc-mode swift) . (lambda () (require 'dap-lldb)))
(php-mode . (lambda () (require 'dap-php)))
(elixir-mode . (lambda () (require 'dap-elixir))))
:config
(require 'dap-chrome)
(require 'dap-cpptools)
(dap-auto-configure-mode))
(setq-default user-documents-directory (expand-file-name "Documents" "~/"))
(setq-default user-notes-directory (expand-file-name "notes" user-documents-directory))
;;(setq-default org-system-inbox-file (format "Inbox-%s.org" (system-name)))
(setq-default org-system-inbox-file "Inbox.org")
(use-package org
:ensure t
:hook ((org-mode . turn-on-auto-fill)
(org-babel-after-execute . org-redisplay-inline-images))
:commands (unpackaged/org-git-status)
:init
;;(setq-default major-mode 'org-mode)
(setq org-directory user-notes-directory)
(setq org-capture-templates
'(("m" "Follow Up" entry (file+olp org-system-inbox-file "Follow Up")
"* TODO Follow up with %:fromname on %:subject
:PROPERTIES:
:CATEGORY: MAIL FOLLOWUP
:CUSTOMER: %:to
:FOR: %:fromname
:ADDED: %U
:END:
SCHEDULED: %(format-time-string \"%<<%Y-%m-%d %a .+1d/3d>>\")
%a
%i"
:immediate-finish t)
("h" "Habit" entry (file+headline org-system-inbox-file "Tasks")
"* TODO %?
SCHEDULED: %(format-time-string \"%<<%Y-%m-%d %a .+1d/3d>>\")
:PROPERTIES:
:STYLE: habit
:REPEAT_TO_STATE: NEXT
:ADDED: %U
:END:
%?\n")
("r" "WithRef" entry (file+headline org-system-inbox-file "Tasks")
"* TODO %^{Description}
%u
:PROPERTIES:
:CUSTOMER: %^{CUSTOMER}
:PROJECT: %^{PROJECT}
:FOR: %^{FOR}
:ADDED: %U
:END:
:Ref: %a
%?\n" :empty-line-before 1 :clock-in t :clock-resume t)
("t" "Todo" entry (file+headline org-system-inbox-file "Tasks")
"* TODO %^{Description}
:PROPERTIES:
:CUSTOMER: %^{CUSTOMER}
:PROJECT: %^{PROJECT}
:FOR: %^{FOR}
:ADDED: %U
:END:
%?\n" :empty-line-before 1 :clock-in t :clock-resume t)
("T" "Tickler" entry (file+headline org-system-inbox-file "Tickler")
"* %i%?
:PROPERTIES:
:ADDED: %U
:END:" :empty-line-before 1 :clock-in t :clock-resume t)
("S" "Story" entry (file+headline org-system-inbox-file "Tasks")
"* TODO %^{Description}
:PROPERTIES:
:CUSTOMER: %^{CUSTOMER}
:PROJECT: %^{PROJECT}
:ASSIGNED: %^{ASSIGNED}
:ADDED: %U
:END:
%?\n" :empty-line-before 1 :clock-in t :clock-resume t)
("c" "Item to current clocked task" item
(clock)
"%i%?" :empty-lines 1)
("k" "Kill-ring to Current clocked task" plain
(clock)
"%c" :immediate-finish t :empty-lines 1)
("R" "Reading" entry (file+headline org-system-inbox-file "Read Later")
"* %^{Title}
:PROPERTIES:
:AUTHOR: %^{AUTHOR}
:ADDED: %u
:URL: %^{URL}
:END:
%?\n" :empty-line-before 1)
("p" "org-protocol-capture" entry (file+headline org-system-inbox-file "Refile")
"* %:description
:PROPERTIES:
:REF: %:link
:ADDED: %u
:END:
%:initial" :immediate-finish t)))
:general
(:keymaps 'org-mode-map "C-c C-k" 'org-kill-note-or-show-branches)
(private/set-leader-keys
"n" '(:ignore t :wk "org-capture")
"st" 'org-tags-sparse-tree
"sT" 'org-show-todo-tree
"so" 'org-sparse-tree
"o" '(:ignore t :which-key "org-mode")
"o&" 'org-mark-ring-goto
"oc" '(:ignore t :wk "org-clock")
"oco" 'org-clock-out
"oci" 'org-clock-in
"ocx" 'org-clock-in-last
"ocg" 'org-clock-goto
"ocq" 'org-clock-cancel
"ocz" 'org-resolve-clocks
"oa" 'org-agenda
"oA" 'org-agenda-list
"og" 'unpackaged/org-git-status :which-key "magit org"
"ok" 'org-kill-note-or-show-branches
"oL" 'org-insert-link-global
"oj" 'org-capture-goto-last-stored
"om" 'org-tags-view
"oO" 'org-open-at-point-global
"oo" 'org-open-at-point
"op" 'org-set-property
"or" 'org-reveal
"o*" 'org-ctrl-c-start
"os" 'org-save-all-org-buffers
"oS" 'org-sort
"oV" 'org-show-todo-tree
"o." 'outline-cycle
"ot" 'org-time-stamp-inactive
"oy" 'org-copy-visible
"o C-c" 'org-store-link
"o C-p" 'org-insert-last-stored-link)
(private/set-leader-keys
"o$" 'org-archive-subtree ; `C-c $'
"o<" 'org-do-promote ; `C-c C-<'
"o>" 'org-do-demote ; `C-c C->'
"oC" 'org-cycle
"or" 'org-clock-report ; `C-c C-x C-r'
"Tol" 'org-toggle-link-display)
:config
(set-face-attribute 'org-date nil :family "MonaspiceKr Nerd Font")
(set-face-attribute 'org-drawer nil :family "MonaspiceKr Nerd Font")
(require 'org-id)
(setq org-id-track-globally t)
(setq org-id-link-to-org-use-id t)
(setq org-id-locations-file (expand-file-name "emacs/org-id-locations" (xdg-data-home)))
(require 'org-tempo)
(add-to-list 'org-structure-template-alist '("sh" . "src shell"))
(add-to-list 'org-structure-template-alist '("el" . "src elisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(require 'org-faces)
(defun unpackaged/org-git-status ()
(interactive)
(magit-status-setup-buffer org-directory))
(with-eval-after-load 'ido
(setq org-completion-use-ido nil))
(setq org-startup-folded t
org-startup-with-inline-images t
org-image-actual-width '(300)
org-startup-indented t
;;org-use-speed-commands nil
;;org-completion-use-iswitchb nil
org-enforce-todo-dependencies 1
org-use-effective-time t
org-fontify-whole-heading-line t
org-fontify-done-headline t
org-fontify-quote-and-verse-blocks t
org-hide-leading-stars t
org-hide-emphasis-markers t
org-odd-levels-only t
org-list-description-max-indent 5
org-pretty-entities t
;; to disable indentation set this to nil
org-adapt-indentation nil
org-catch-invisible-edits 'smart
org-special-ctrl-a/e t)
(setq org-duration-format (quote (:hours "%d" :require-hours t :minutes ":%02d" :require-minutes t))
org-reverse-note-order t
org-columns-default-format "%70ITEM(Task) %TODO %3PRIORITY %10Effort(Effort){:} %10CLOCKSUM")
(setq org-fontify-whole-heading-line t)
(setq org-fast-tag-selection-single-key 'expert
org-fast-tag-selection-include-todo t)
;;(setq org-clock-persist-file (expand-file-name "emacs/org-clock-save.el" (xdg-cache-home)))
(setq org-clock-persist 'history
org-clock-out-when-done t
org-clock-history-length 23
org-clock-in-resume t
org-clock-into-drawer t
org-clock-auto-clock-resolution 'when-no-clock-is-running
org-clock-report-include-clocking-task t
;; org-clock-in-switch-to-state "NEXT"
;; Remove clocked tasks with 0:00 duration
;; org-clock-out-remove-zero-time-clocks t
org-clock-modeline-total 'current)
(setq org-outline-path-complete-in-steps nil
org-html-checkbox-type 'html)
(setq org-agenda-span 14
org-agenda-block-separator ""
org-agenda-sticky t
org-agenda-columns-add-appointments-to-effort-sum t
org-agenda-insert-diary-extract-time t
org-agenda-include-diary t
org-agenda-include-deadline t
org-agenda-text-search-extra-files '(agenda-archive)
org-agenda-compact-blocks t
org-agenda-restore-windows-after-quit t
org-agenda-window-setup 'current-window
org-agenda-skip-deadline-if-done t
org-agenda-skip-scheduled-if-done t
org-agenda-clockreport-parameter-plist '((:link t :maxlevel 5 :fileskip0 t :compact t :narrow 80)))
(setq org-deadline-warning-days 10)
(defun +org/opened-buffer-files ()
"Return the list of files currently opened in emacs"
(delq nil
(mapcar (lambda (x)
(if (and (buffer-file-name x)
(string-match "\\.org$"
(buffer-file-name x)))
(buffer-file-name x)))
(buffer-list))))
(setq org-refile-targets '((org-agenda-files :maxlevel . 3)
(+org/opened-buffer-files :maxlevel . 9)))
(setq org-refile-use-outline-path 'file
org-refile-allow-creating-parent-nodes 'confirm)
(setq org-src-fontify-natively t
org-src-window-setup 'current-window
org-edit-src-content-indentation 0
org-src-tab-acts-natively t)
(setq org-log-done (quote note)
org-log-redeadline (quote time)
org-log-reschedule (quote time)
org-log-into-drawer "LOGBOOK")
;;(add-to-list 'org-modules 'org-habit)
;;(setq org-habit-show-habits-only-for-today t)
(setq org-confirm-babel-evaluate nil)
;; Treat clipboard input as UTF-8 string first; compound text next, etc.
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
;; not supported in common font, but supported in Symbola (my fall-back font) ⬎, ⤷, ⤵
(setq org-ellipsis "»");; ⤵ ⚡ ≫ ➢ ➣ ➤ ≪ ≫ « »
(font-lock-add-keywords 'org-mode
'(("^ +\\([-*]\\) "
(0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))
(defface org-checkbox-done-text '((t (:foreground "#71696A")))
"Face for the text part of a checked org-mode checkbox.")
(setq org-use-fast-todo-selection t)
(setq org-global-properties
'(("Effort_ALL" . "0:15 0:25 0:55 1:25 1:55 2:25 2:55 3:25 3:55 0:00")
("STYLE_ALL" . "habit")))
(setq org-todo-keywords
'((sequence "TODO(t)" "STARTED(s)" "WAITING(w@/!)" "DELEGATE(g@/!)" "|" "DONE(d)" "CANCELLED(x@/!)")
(sequence "READING(z)" "|" "READ(r)")
(sequency "Backlog" "Planning" "Blocked" "Review" "|" "DONE")
(sequence "REPORT" "BUG(!/!)" "VERIFY(!/!)" "|" "FIXED(f@/!)" "CLOSED(c@/!)")))
(setq org-todo-state-tags-triggers
'(("CANCELLED" ("CANCELLED" .t))
("WAITING" ("WAITING" . t))
("TODO" ("WAITING") ("CANCELLED"))
("STARTED" ("WAITING") ("CANCELLED"))
("DONE" ("WAITING") ("CANCELLED"))))
(setq org-todo-keyword-faces
'(
;; ("STARTED" . (:foreground "teal"))
("WAITING" . (:inherit org-warning))
("DELEGATE" . (:inherit org-warning :strike-through t))
("VERIFY" . (:inherit org-warning :weight bold))
("Backlog" . (:inherit org-todo :weight bold))
("Planning" . (:inherit org-todo :weight bold))
("Blocked" . (:inherit org-warning :weight bold :strike-through t))
("Review" . (:inherit org-todo :weight bold))))
(setq org-tag-alist
'((:startgroup)
("@home" . ?h)
("@nca" . ?W)
("@sagacity" . ?S)
(:endgroup)
("someday" . ?s)
("MEETING" . ?m)
("NOTE" . ?N)
("LEARNING" . ?L)
("CODING" . ?C)
("PERSONAL" . ?P)
("READING" . ?R)
("SUPPORT" . ?S)))
(setq org-agenda-custom-commands '(("w" "Work tasks" tags-todo "-READING"
((org-agenda-sorting-strategy
'(todo-state-down effort-up category-keep))))
("i" "Inbox tasks" tags-todo "Inbox")
("p" "Project tasks" tags-todo "Project")
("h" "Habits" tags-todo "STYLE=\"habit\""
((org-agenda-overriding-header "Habits")
(org-agenda-sorting-strategy
'(todo-state-down effort-up category-keep))))
("c" "Close tasks" todo "DONE|CLOSED|FIXED|CANCELLED")
("A" "Assigned" todo "DELEGATE")
("d" "Upcoming deadlines" agenda ""
((org-agenda-time-grid nil)
(org-deadline-warning-days 10)
(org-agenda-entry-types '(:deadline))))))
(require 'org-crypt)
(org-crypt-use-before-save-magic)
(defun activate-capture-frame ()
"run org-capture in capture frame"
(select-frame-by-name "capture")
(switch-to-buffer (get-buffer-create "*scratch*"))
(org-capture))
;; (defun unpackaged/org-open-at-point (&optional arg)
;; (interactive "P")
;; (if (not arg)
;; (org-open-at-point)
;; (let ((browse-url-browser-function #'browse-url-emacs))
;; (org-open-at-point))))
;; (define-key org-mode-map [remap org-return] (lambda() (interactive)
;; (if (org-in-src-block-p)
;; (org-return)
;; (org-return-indent))))
;; Resume clocking task when emacs is restarted
(org-clock-persistence-insinuate)
(require 'org-capture)
(require 'org-protocol))
(with-eval-after-load 'org
(setq org-startup-with-latex-preview nil)
(setq org-highlight-latex-and-related '(native script entities))
(setq org-format-latex-options (plist-put org-format-latex-options :scale 2.0))
(setq org-preview-latex-image-directory "/tmp/ltximg"))
(use-package org-msg
:ensure t
:defer 1
:after (org mu4e)
:custom
(org-msg-options "html-postamble:nil H:5 num:nil ^:{} toc:nil author:nil email:nil \\n:t")
(org-msg-startup "hidestars indent inlineimages")
(org-msg-greeting-fmt "\nHi *%s*,\n\n")
(org-msg-greeting-name-limit 3)
(org-msg-default-alternatives '(text html))
(org-msg-convert-citation t)
(org-msg-signature "
,#+begin_signature
--
,*Steve Beaulac* (sjb)
,#+end_signature")
:config
(org-msg-mode))
(use-package org-reverse-datetree
:ensure t
:after org
:defer t)
(use-package org-pomodoro
:ensure t
:after org
:defer t
:general
(private/set-leader-keys "op" 'org-pomodoro)
:config
(setq org-pomodoro-play-sounds nil
org-pomodoro-format "Φ %s"
org-pomodoro-keep-killed-pomodoro-time t)
(setq alert-user-configuration (quote ((((:category . "org-pomodoro")) libnotify nil)))))
(use-package org-download
:ensure t
:defer t
:after org
:general
(private/set-leader-keys
"oy" 'org-download-screenshot)
:custom
(org-download-screenshot-method "grim -g \"$(slurp)\" - > %s")
;;(setq org-download-screenshot-method "flameshot gui --raw > %s")
(org-download-image-dir (expand-file-name "images" org-directory)))
(use-package org-bookmark-heading
:ensure t
:defer t
:init
(with-eval-after-load 'org
(require 'org-bookmark-heading)))
(use-package org-web-tools
:defer t
:after org)
(use-package ox-hugo
:ensure t
:defer t
:after org)
(use-package ox-pandoc
:ensure t
:defer t
:after org)
(use-package org-roam
:ensure t
:commands (org-roam-dailies-map
org-roam-node-insert-immediate
my/org-roam-find-project
my/org-roam-capture-inbox
my/org-roam-capture-project)
:custom
(org-roam-v2-ack t)
(org-roam-directory user-notes-directory)
(org-roam-dailies-directory (expand-file-name "journals" user-notes-directory))
(org-roam-db-location (expand-file-name "emacs/org-roam.db" (xdg-data-home)))
(org-roam-completion-everywhere t)
(org-roam-capture-templates
'(("d" "default" plain
(file "~/.emacs.d/org-roam-templates/default.org")
:if-new (file "%<%Y%m%d%H%M%S>-${slug}.org")
:unnarrowed t)
("b" "book notes" plain
"\n* Source\n\nAuthor: %^{Author}\nTitle: ${title}\nYear: %^{Year}\n\n* Summary\n\n%?"
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
:unnarrowed t)
("p" "project" plain
"* Goals\n\n%?\n\n* Tasks\n\n** TODO Add initial tasks\n\n* Dates\n\n"
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+category: ${title}\n#+filetags: Project")
:unnarrowed t)))
(org-roam-dailies-capture-templates
'(("d" "default" entry
"* %?"
:if-new (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d %a>\n\n[[roam:%<%Y-%B>]]\n\n"))
("t" "Task" entry
"* TODO %?\n %U\n %a\n %i\n"
:if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d %a>\n\n[[roam:%<%Y-%B>]]\n\n" ("Tasks"))
:empty-lines 1)
("n" "notes" entry
"* %?\n"
:if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d %a>\n\n[[roam:%<%Y-%B>]]\n\n" ("Notes")))
("p" "planning" entry
"* %?\n"
:if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d %a>\n\n[[roam:%<%Y-%B>]]\n\n" ("Daily Planning")))
("j" "journal" entry
"* %<%I:%M %p> - Journal :journal:\n\n%?\n\n"
:if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d %a>\n\n[[roam:%<%Y-%B>]]\n\n" ("Journal")))
("m" "meeting" entry
"* %<%I:%M %p> - %^{Meeting Title} :meetings:\n\n%?\n\n"
:if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d %a>\n\n[[roam:%<%Y-%B>]]\n\n" ("Journal")))))
:general
(private/set-leader-keys
"Tor" 'org-roam-buffer-toggle
"fn" '(org-roam-node-find :wk "find-node")
"go" '(my/org-roam-find-project :wk "org project")
"nd" 'org-roam-dailies-capture-today
"np" 'my/org-roam-capture-project
"ni" 'my/org-roam-capture-inbox
"onf" 'org-roam-node-find
"oni" 'org-roam-node-insert
"on." 'org-roam-dailies-goto-date
"onx" '(my/org-roam-copy-todo-to-today :wk "archive")
"onc" 'org-roam-dailies-capture-today
"onC" 'org-roam-dailies-capture-tomorrow
"ont" 'org-roam-dailies-find-today
"ony" 'org-roam-dailies-find-yesterday
"onr" 'org-roam-dailies-find-tomorrow
"ond" 'org-roam-dailies-find-directory
"onR" 'my/org-roam-refresh-agenda-list
"onb" 'my/org-roam-capture-inbox
"onp" 'my/org-roam-capture-project
"ong" 'org-roam-graph)
(:keymaps 'org-mode-map
"C-c n i" 'org-roam-node-insert
"C-c n I" 'org-roam-insert-immediate
"C-M-i" 'completion-at-point)
:config
(require 'org-roam-dailies)
(require 'org-roam-protocol)
(defun vulpea-buffer-prop-get (name)
"Get a buffer property called NAME as a string."
(org-with-point-at 1
(when (re-search-forward (concat "^#\\+" name ": \\(.*\\)")
(point-max) t)
(buffer-substring-no-properties
(match-beginning 1)
(match-end 1)))))
(defun vulpea-agenda-category (&optional len)
"Get category of item at point for agenda.
Category is defined by one of the following items:
- CATEGORY property
- TITLE keyword
- TITLE property
- filename without directory and extension
When LEN is a number, resulting string is padded right with
spaces and then truncated with ... on the right if result is
longer than LEN.
Usage example:
(setq org-agenda-prefix-format
'((agenda . \" %(vulpea-agenda-category) %?-12t %12s\")))
Refer to `org-agenda-prefix-format' for more information."
(let* ((file-name (when buffer-file-name
(file-name-sans-extension
(file-name-nondirectory buffer-file-name))))
(title (vulpea-buffer-prop-get "title"))
(category (org-get-category))
(result
(or (if (and
title
(string-equal category file-name))
title
category)
"")))
(if (numberp len)
(s-truncate len (s-pad-right len " " result))
result)))
(setq org-agenda-prefix-format
'((agenda . " %i %(vulpea-agenda-category 18)%?-12t% s")
(todo . " %i %(vulpea-agenda-category 18) ")
(tags . " %i %(vulpea-agenda-category 18) ")
(search . " %i %(vulpea-agenda-category 18) ")))
(cl-defmethod org-roam-node-hierarchy ((node org-roam-node))
(let ((level (org-roam-node-level node)))
(concat
(when (> level 0) (concat (org-roam-node-file-title node) " > "))
(when (> level 1) (concat (string-join (org-roam-node-olp node) " > ") " > "))
(org-roam-node-title node))))
(setq org-roam-node-display-template "${hierarchy:200} ${tags:20}")
(defun org-roam-node-insert-immediate (arg &rest args)
(interactive "P")
(let ((args (cons arg args))
(org-roam-capture-templates (list (append (car org-roam-capture--templates)
'(:immediate-finish t)))))
(apply #'org-roam-node-insert args)))
(defun my/org-roam-filter-by-tag (tag-name)
(lambda (node)
(member tag-name (org-roam-node-tags node))))
(defun my/org-roam-list-notes-by-tag (tag-name)
(delete-dups (mapcar #'org-roam-node-file
(seq-filter
(my/org-roam-filter-by-tag tag-name)
(org-roam-node-list)))))
(defun my/org-roam-refresh-agenda-list()
(interactive)
(setq org-agenda-files (my/org-roam-list-notes-by-tag "Project")))
(my/org-roam-refresh-agenda-list)
(defun my/org-roam-project-finalize-hook ()
"Adds the captured project file to `org-agenda-files' if the
capture was not aborted."
;; Remove the hook since it was added temporarily
(remove-hook 'org-capture-after-finalize-hook #'my/org-roam-project-finalize-hook)
;; Add project file to the agenda list if the capture was confirmed
(unless org-note-abort
(with-current-buffer (org-capture-get :buffer)
(add-to-list 'org-agenda-files (buffer-file-name)))))
(defun my/org-roam-find-project ()
(interactive)
;; Add the project file to the agenda after capture is finished
(add-hook 'org-capture-after-finalize-hook #'my/org-roam-project-finalize-hook)
;; Select a project file to open, creating it if necessary
(org-roam-node-find nil nil
(my/org-roam-filter-by-tag "Project")))
(defun my/org-roam-capture-inbox ()
(interactive)
(org-roam-capture- :node (org-roam-node-create)
:templates `(("n" "Inbox note" entry "* %?\n"
:if-new (file+head+olp ,(format "%s" org-system-inbox-file)
"#+title: ${title}\n#+category: ${title}\n#+filetags: Inbox"
("Notes")))
("m" "Inbox meeting" entry "* TODO %?"
:if-new (file+head+olp ,(format "%s" org-system-inbox-file)
"#+title: ${title}\n#+category: ${title}\n#+filetags: Inbox"
("Meetings")))
("t" "Inbox task" entry
"* TODO %?\n %U\n"
:if-new (file+head+olp ,(format "%s" org-system-inbox-file)
"#+title: ${title}\n#+category: ${title}\n#+filetags: Inbox"
("Tasks"))))))
(defun my/org-roam-capture-project ()
(interactive)
;; Add the project file to the agenda after capture is finished
(add-hook 'org-capture-after-finalize-hook #'my/org-roam-project-finalize-hook)
;; Capture the new task, creating the project file if necessary
(org-roam-capture- :node (org-roam-node-read
nil
(my/org-roam-filter-by-tag "Project"))
:templates '(("n" "Project note" entry "* %?\n"
:if-new (file+head+olp "%<%Y%m%d%H%M%S>-${slug}.org"
"#+title: ${title}\n#+category: ${title}\n#+filetags: Project"
("Notes")))
("m" "Project meeting" entry "* TODO %?"
:if-new (file+head+olp "%<%Y%m%d%H%M%S>-${slug}.org"
"#+title: ${title}\n#+category: ${title}\n#+filetags: Project"
("Meetings")))
("p" "Project task" entry "* TODO %?"
:if-new (file+head+olp "%<%Y%m%d%H%M%S>-${slug}.org"
"#+title: ${title}\n#+category: ${title}\n#+filetags: Project"
("Tasks"))))))
(defun my/org-roam-copy-todo-to-today ()
(interactive)
(let ((org-refile-keep nil) ;; Set this to nil to delete the original!
(org-roam-dailies-capture-templates
'(("t" "tasks" entry "%?"
:if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n" ("Tasks")))))
(org-after-refile-insert-hook #'save-buffer)
today-file
pos)
(save-window-excursion
(org-roam-dailies--capture (current-time) t)
(setq today-file (buffer-file-name))
(setq pos (point)))
;; Only refile if the target file is different than the current file
(unless (equal (file-truename today-file)
(file-truename (buffer-file-name)))
(org-refile nil nil (list "Tasks" today-file nil pos)))))
;; (add-to-list 'org-after-todo-state-change-hook
;; (lambda ()
;; (message org-state)
;; (when (member org-state '("DONE" "CANCELLED" "FIXED" "CLOSED"))
;; (my/org-roam-copy-todo-to-today))))
;;(with-eval-after-load 'helm (setq org-roam-completion-system 'helm))
;;(with-eval-after-load 'ivy (setq org-roam-completion-system 'ivy))
(org-roam-db-autosync-mode))
(use-package org-modern
:ensure t
:after org
:hook ((org-mode . org-modern-mode)
(org-aganda-finalize . org-modern-agenda))
:config
(setq
;; Edit settings
org-auto-align-tags nil
org-tags-column 0
org-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 t
org-pretty-entities nil
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 ─────────────────────────────────────────────────"))
(use-package kanban
:ensure t
:defer t
:after org)
(use-package forge
:ensure t
:after magit
:custom
(forge-database-file (expand-file-name "emacs/forge-database.sqlite" (xdg-data-home)))
:config
(setq forge-add-default-bindings t)
(add-to-list
'forge-alist '("gitlab.sourcingcafe.com"
"gitlab.sourcingcafe.com/api/v4"
"gitlab.sourcingcafe.com"
forge-gitlab-repository))
(add-to-list
'forge-alist '("gitea.sourcingcafe.com"
"gitea.sourcingcafe.com/api/v1"
"gitea.sourcingcafe.com"
forge-gitea-repository))
)
(use-package gitea-forge
:ensure t
:vc (gitea-forge :url "https://github.com/mobid/gitea-forge.git" :branch "master")
:init
(with-eval-after-load 'forge
(require 'gitea-forge))
:after forge)
(use-package gist
:ensure t
:defer t
:general
(general-evil-define-key 'normal gist-list-menu-mode-map
(kbd "<return>") 'gist-fetch-current
(kbd "S-<return>") 'gist-fetch-current-noselect
"gr" 'gist-list-reload
"e" 'gist-edit-current-description
"q" 'gist-kill-current
"i" 'gist-add-buffer
"x" 'gist-remove-file
"gp" 'gist-print-current-url
"go" 'gist-browse-current-url
"m" 'gist-star
"u" 'gist-unstar
"gf" 'gist-fork
"g?" 'gist-list-push-visibility-limit
"A" 'gist-list-push-tag-limit
"a" 'gist-list-pop-limit)
(private/set-leader-keys "xg" 'gist-list)
:config
(evil-set-initial-state 'gist-list-mode 'normal))
(use-package gitconfig
:ensure t
:defer t)
(use-package git-link
:general
(private/set-leader-keys
"cll" 'git-link
"clx" 'git-link-commit
"clh" 'git-link-homepage))
(use-package gitignore-snippets
:ensure t
:after yasnipet)
(use-package git-gutter
:ensure t
:hook (after-init . global-git-gutter-mode)
:custom
(git-gutter:update-interval 2)
:general
(general-nmap "]g" #'git-gutter:next-hunk
"[g" #'git-gutter:previous-hunk)
(private/set-leader-keys
"cp" #'git-gutter:popup-hunk
"cs" #'git-gutter:stage-hunk
"cS" #'git-gutter:revert-hunk))
(use-package gitlab
:ensure t
:defer t)
(use-package magit
:ensure t
:defer t
:general
(:keymaps 'magit-status-mode-map
"q" 'mu-magit-kill-buffers)
(private/set-leader-keys "gv" #'magit-status)
(private/set-leader-keys "v" #'magit-dispatch)
:custom
(magit-clone-default-directory "~/Projects/")
(magit-no-message (list "Turning on magit-auto-revert-mode..."))
:init
(with-eval-after-load 'project
(add-to-list 'project-switch-commands '(?m "magit status" magit-project-status) t))
:config
(git-commit-turn-on-auto-fill)
(defun ross/magit-clone-read-args-a (orig-fun &rest args)
"Sets `vertico-preselect' to `prompt' when cloning repos, so we
clone to the default prompted directory, and not some random
existing directory under `magit-clone-default-directory'."
(let ((vertico-preselect 'prompt))
(apply orig-fun args)))
(advice-add 'magit-clone-read-args :around #'ross/magit-clone-read-args-a)
(setq magit-repository-directories '(("~/Projects" . 3)))
(setq magit-revision-show-gravatars '("^Author: " . "^Commit: ")))
(use-package magit-todos
:defer t
:after magit)
(defun unpackaged/minibuffer-backward-kill (arg)
"When minibuffer is completing a file name delete up to parent
folder, otherwise delete a word"
(interactive "p")
(if minibuffer-completing-file-name
;; Borrowed from https://github.com/raxod502/selectrum/issues/498#issuecomment-803283608
(if (string-match-p "/." (minibuffer-contents))
(zap-up-to-char (- arg) ?/)
(delete-minibuffer-contents))
(backward-kill-word arg)))
(defun unpackaged/dos2unix ()
"Converts the current buffer to Unix file format."
(interactive)
(set-buffer-file-coding-system 'undecided-unix nil))
(private/set-leader-keys "eeu" '(unpackaged/dos2unix :which-key "dos2unix"))
(defun unpackaged/unix2dos ()
"Converts the current buffer to DOS file format."
(interactive)
(set-buffer-file-coding-system 'undecided-dos nil))
(private/set-leader-keys "eed" '(unpackaged/unix2dos :which-key "unix2dos"))
(defun unpackaged/reload-from-disk ()
"Prompt before reverting the file."
(interactive)
(revert-buffer nil t))
(private/set-leader-keys "br" '(unpackaged/reload-from-disk :which-key "reload buffer"))
(defun xah-new-empty-buffer ()
"Open a new empty buffer.
URL `http://ergoemacs.org/emacs/emacs_new_empty_buffer.html'
Version 2016-08-11"
(interactive)
(let ((-buf (generate-new-buffer "untitled")))
(switch-to-buffer -buf)
(funcall initial-major-mode)
(setq buffer-offer-save t)))
(private/set-leader-keys "bn" 'xah-new-empty-buffer)
(defun unpackaged/push-to-kindle (url)
(browse-url (concat "http://fivefilters.org/kindle-it/send.php?url=" url)))
(provide 'post-init)