;;; -*- lexical-binding: t -*-
;; https://github.com/hlissner/doom-emacs/blob/develop/core/core.el
(setq auto-mode-case-fold nil
bidi-inhibit-bpa t
highlight-nonselected-windows nil
fast-but-imprecise-scrolling t
frame-inhibit-implied-resize t
idle-update-delay 1.0
pgtk-wait-for-event-timeout 0.001
redisplay-skip-fontification-on-input t
command-line-ns-option-alist nil
ad-redefinition-action 'accept
debug-on-error init-file-debug
jka-compr-verbose init-file-debug
inhibit-default-init t)
(setq-default bidi-display-reordering 'left-to-right
bidi-paragraph-direction 'left-to-right
cursor-in-non-selected-windows nil)
;; custom
(setq default-directory "~/"
custom-file (expand-file-name "custom.el" user-emacs-directory)
read-process-output-max (* 1024 1024) ;; https://emacs-lsp.github.io/lsp-mode/page/performance/
enable-local-eval t
mouse-wheel-scroll-amount '(2 ((shift) . 2))
mouse-wheel-progressive-speed nil
same-window-buffer-names '("*Help*")
Man-notify-method 'pushy
inhibit-startup-screen t
initial-scratch-message nil
initial-major-mode 'text-mode
ring-bell-function 'ignore
use-dialog-box nil
vc-follow-symlinks t
split-height-threshold 120
split-width-threshold 160
;; Kill active process buffer no prompt
kill-buffer-query-functions (remq 'process-kill-buffer-query-function kill-buffer-query-functions)
display-buffer-alist
'(("*Async Shell Command*" . (display-buffer-no-window))))
(setq-default indent-tabs-mode nil
sentence-end-double-space nil
;; increase (magit-commit) line autowrap width (default=70)
fill-column 80)
(setopt use-short-answers t)
(delete-selection-mode 1)
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)
;;;; as per https://github.com/minad/vertico#configuration
;; Add prompt indicator to `completing-read-multiple'.
;; Alternatively try `consult-completing-read-multiple'.
(defun crm-indicator (args)
(cons (concat "[CRM] " (car args)) (cdr args)))
(advice-add #'completing-read-multiple :filter-args #'crm-indicator)
;; Do not allow the cursor in the minibuffer prompt
(setq minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
;; disabled: breaks kill-buffer diff save behavior
;; (setq enable-recursive-minibuffers t)
(setq use-package-compute-statistics nil
comp-async-report-warnings-errors nil
warning-suppress-log-types '((comp))
)
;; https://github.com/progfolio/elpaca/issues/222#issuecomment-1872596777
;; https://github.com/NixOS/nixpkgs/issues/267548
(setq elpaca-core-date '(20231211))
;; installer
(defvar elpaca-installer-version 0.7)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
:ref nil :depth 1
:files (:defaults "elpaca-test.el" (:exclude "extensions"))
:build (:not elpaca--activate-package)))
(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory))
(build (expand-file-name "elpaca/" elpaca-builds-directory))
(order (cdr elpaca-order))
(default-directory repo))
(add-to-list 'load-path (if (file-exists-p build) build repo))
(unless (file-exists-p repo)
(make-directory repo t)
(when (< emacs-major-version 28) (require 'subr-x))
(condition-case-unless-debug err
(if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
((zerop (apply #'call-process `("git" nil ,buffer t "clone"
,@(when-let ((depth (plist-get order :depth)))
(list (format "--depth=%d" depth) "--no-single-branch"))
,(plist-get order :repo) ,repo))))
((zerop (call-process "git" nil buffer t "checkout"
(or (plist-get order :ref) "--"))))
(emacs (concat invocation-directory invocation-name))
((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
"--eval" "(byte-recompile-directory \".\" 0 'force)")))
((require 'elpaca))
((elpaca-generate-autoloads "elpaca" repo)))
(progn (message "%s" (buffer-string)) (kill-buffer buffer))
(error "%s" (with-current-buffer buffer (buffer-string))))
((error) (warn "%s" err) (delete-directory repo 'recursive))))
(unless (require 'elpaca-autoloads nil t)
(require 'elpaca)
(elpaca-generate-autoloads "elpaca" repo)
(load "./elpaca-autoloads")))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))
;; installer end
;; (setq elpaca-verbosity most-positive-fixnum)
;; load directly before elpaca-use-package to register :blackout use-package handler
(elpaca blackout)
(elpaca elpaca-use-package
;; Enable use-package :ensure support for Elpaca.
(elpaca-use-package-mode)
(setq use-package-always-ensure t))
(elpaca-wait)
(use-package emacs
:ensure nil
:custom
browse-url-browser-function 'browse-url-generic
browse-url-generic-program (executable-find "handlr")
browse-url-generic-args '("open")
;; https://github.com/minad/corfu?tab=readme-ov-file#configuration
;;
(tab-always-indent 'complete)
;; Disable Ispell completion function (using manual jinx spell check instead)
(text-mode-ispell-word-completion nil)
;; Hide commands in M-x which do not apply to the current mode
(read-extended-command-predicate #'command-completion-default-include-p)
;; permanently accept '-*- buffer-auto-save-file-name: nil; -*-' file variable as safe
;; https://emacs.stackexchange.com/questions/73868/automatically-mark-risky-file-local-variable-safe
(safe-local-variable-values `((buffer-auto-save-file-name . nil)))
)
(use-package f)
(use-package dash)
(use-package a)
(use-package ts)
(use-package request)
;; install latest transient before my-menus
(use-package transient)
(use-package my
:after (request transient)
:load-path "my"
:ensure nil
:config
(add-to-list 'save-some-buffers-action-alist
`(?r my-discard-buffer-action
"discard this buffer"))
:custom
(org-make-link-description-function 'my-url-get-title)
:demand t)
(elpaca-wait)
;; Required to get e.g. wl-clipboard, browse-url wayland connection working on system start (without having to restart the daemon)
;; Used in conjunction with 'systemctl --user import-environment WAYLAND_DISPLAY DISPLAY' in the sway config
(use-package exec-path-from-shell
:custom
(exec-path-from-shell-arguments nil)
(exec-path-from-shell-variables '("DISPLAY" "WAYLAND_DISPLAY"))
:init
(my-with-eval-after-frame
(exec-path-from-shell-initialize)))
(use-package general
:config
(general-auto-unbind-keys))
(elpaca-wait)
(general-unbind
;; disable overwrite
"<insert>"
;; disable mouse-wheel zoom
"<C-mouse-4>"
"<C-mouse-5>"
"C-<wheel-down>"
"C-<wheel-up>"
"<pinch>"
;; https://www.reddit.com/r/emacs/comments/3c61zl/abolish_the_secondary_selection_quick_and_easy/
"<M-drag-mouse-1>" ; mouse-set-secondary
"<M-down-mouse-1>" ; mouse-drag-secondary
"<M-mouse-1>" ; mouse-start-secondary
"<M-mouse-2>" ; mouse-yank-secondary
"<M-mouse-3>") ; mouse-secondary-save-then-kill
(general-def
:keymaps 'prog-mode-map
;; not global because conflict with org-mode new heading
"C-<return>" 'crux-smart-open-line
"M-<return>" 'crux-smart-open-line-above
)
(general-def
"C-z" 'yank
"C-M-`" 'quoted-insert
"M-y" 'consult-yank-pop
"C-M-s" 'consult-ripgrep
"C-M-r" 'project-query-replace-regexp
"C-x b" 'magit-blame
"C-x l" 'magit-log-buffer-file
"M-." 'xref-find-definitions
;; clashes with run-elisp-function
;; "M-:" 'xref-find-definitions-other-window
"C-M-." 'xref-find-references
"C-r" 'substitute-target-in-buffer
"C-<backspace>" 'puni-backward-kill-word)
(general-def
:keymaps 'override
:prefix "C-c"
"l" 'org-store-link
"a" 'org-agenda
"b" 'org-iswitchb
"c" 'org-capture)
(general-def
:keymaps 'org-mode-map :package 'org
"<return>" 'org-return
"M-S-<delete>" 'my/org-delete-heading-or-line
"C-M-<end>" 'org-sentence-newline
"C-c e" 'org-edit-special
"C-c TAB" nil)
(general-def :package 'mosey
"C-a" 'mosey-backward-bounce
"C-e" 'mosey-forward-bounce
)
(general-def
:keymaps 'key-translation-map
"M-q" "C-u")
(general-def
:keymaps 'org-src-mode-map :package 'org
"C-c e" 'org-edit-src-exit)
(general-def
:keymaps 'drag-stuff-mode-map :package 'drag-stuff
"M-<up>" 'drag-stuff-up
"M-<down>" 'drag-stuff-down)
(general-def
:keymaps 'isearch-mode-map
"C-r" 'isearch-query-replace)
(general-def
:keymaps 'dired-mode-map :package 'dirvish
"M-<return>" 'dirvish-dispatch
"M-#" 'dired-find-file
)
(general-def
:keymaps 'override
"C-l" 'goto-line
"C-q" 'embark-act
"M-'" 'crux-duplicate-current-line-or-region
"˝" 'previous-buffer
"’" 'next-buffer
"C-^" 'delete-window
"C-1" 'delete-other-windows
"C-2" 'split-window-right
"C-3" 'split-window-below
"C-M-1" 'winner-undo
"C-M-2" 'winner-redo
"M-[" 'windmove-left
"M-\\" 'windmove-right
"M-=" 'windmove-up
"M-]" 'windmove-down
"M-{" 'buf-move-left
"M-|" 'buf-move-right
"M-+" 'buf-move-up
"M-}" 'buf-move-down
"C-d" 'consult-project-extra-find
"M-d" 'consult-buffer
"C-M-d" 'find-file
"C-M-p" 'vundo
"C-p" 'undo-fu-only-undo
"M-p" 'undo-fu-only-redo
"C-<up>" 'golden-ratio-scroll-screen-down
"C-<down>" 'golden-ratio-scroll-screen-up
"C-x ^" nil
"C-x d" nil
"C-<tab>" 'my-indent-rigidly
"C-M-k" 'kill-current-buffer
"M-r" 'revert-buffer
"<f5>" 'profiler-start
"<f6>" 'profiler-stop
"C-M-f" 'my-menus-code
"C-x f" 'my-menus-files
)
(general-def
:keymaps 'eglot-mode-map :package 'eglot
"M-/" 'eglot-code-actions
"C-r" 'eglot-rename)
(general-def
:keymaps 'embark-file-map :package 'embark
"!" nil
"&" nil
"f" nil
"r" nil
"d" nil
"R" nil
"b" nil
"l" nil
"m" 'magit-project-status)
(general-def
:keymaps 'embark-region-map :package 'embark
"t" 'google-translate-smooth-translate
"d" 'lexic-search)
(general-def
:keymaps 'embark-identifier-map :package 'embark
"s" 'jinx-correct)
(general-def
:keymaps 'embark-symbol-map :package 'embark
"s" 'jinx-correct)
(blackout 'eldoc-mode)
(setq xref-prompt-for-identifier nil)
(setq-default
mode-line-position (list "%l,%c")
mode-line-format
'("%e" mode-line-front-space
mode-line-mule-info
(:propertize (" " mode-line-position) display (min-width (8.0)))
mode-line-frame-identification mode-line-buffer-identification
mode-line-modes mode-line-misc-info " "
mode-line-end-spaces)
)
(use-package explain-pause-mode
:ensure (:host github :repo "lastquestion/explain-pause-mode")
:commands explain-pause-mode)
(use-package esup
:custom
(esup-depth 0)
:commands esup)
(setq delete-old-versions t
kept-new-versions 6
create-lockfiles nil
kept-old-versions 2
version-control t
backup-by-copying t
emacs-tmp-dir (my-ensure-dir user-emacs-directory "tmp/")
emacs-backup-dir (my-ensure-dir emacs-tmp-dir "backups/")
emacs-autosave-dir (my-ensure-dir emacs-tmp-dir "autosaves/")
backup-directory-alist `(("." . ,emacs-backup-dir))
auto-save-file-name-transforms `((".*" ,emacs-autosave-dir t))
auto-save-list-file-prefix emacs-autosave-dir)
(winner-mode 1)
(use-package buffer-move)
(use-package mosey)
(use-package edit-indirect
:ensure (:type git :host github :repo "Fanael/edit-indirect")
:commands edit-indirect-region)
(use-package activities
:init
(activities-mode)
(activities-tabs-mode)
:bind (("M-1" . activities-new)
("M-2" . activities-resume)
("M-3" . activities-suspend)
("M-4" . activities-discard))
:custom
(tab-bar-show 1)
(tab-bar-new-button-show nil)
(tab-bar-close-button-show nil)
)
;;; from https://github.com/nex3/perspective-el#some-musings-on-emacs-window-layouts
(customize-set-variable 'display-buffer-base-action
'((display-buffer-reuse-window display-buffer-same-window)
(reusable-frames . t)))
(customize-set-variable 'even-window-sizes nil) ; avoid resizing
(use-package auth-source-pass
:ensure nil
:init (auth-source-pass-enable)
:custom
(auth-source-pass-filename (getenv "PASSWORD_STORE_DIR"))
(auth-sources '(password-store)))
(use-package
epa-file
:ensure nil
:custom (epa-file-select-keys nil))
(use-package secrets
:ensure nil)
http://trey-jackson.blogspot.com/2010/04/emacs-tip-36-abort-minibuffer-when.html
(defun stop-using-minibuffer ()
"kill the minibuffer"
(when (and (>= (recursion-depth) 1) (active-minibuffer-window))
(abort-recursive-edit)))
(add-hook 'mouse-leave-buffer-hook 'stop-using-minibuffer)
;; disabled in order to fix isearch reveal of collapsed org trees
;; (use-package reveal
;; :hook (org-mode . reveal-mode)
;; :blackout reveal-mode)
(use-package org
:mode ("\\.org\\'" . org-mode)
:config
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(latex . t)
(python . t)
(gnuplot . t)
(shell . t)
(sql . t)))
:custom
(org-directory "~/dot/notes/org")
(org-capture-templates '(("a" "Brain" plain (function org-brain-goto-end)
"* %i%?" :empty-lines 1)))
(org-return-follows-link nil)
(org-support-shift-select t)
(org-image-actual-width '(500))
(org-list-allow-alphabetical t)
(org-use-property-inheritance t)
(org-use-sub-superscripts nil)
(org-checkbox-hierarchical-statistics t)
(org-export-with-toc nil)
(org-export-with-section-numbers nil)
(org-refile-use-outline-path t)
(org-datetree-add-timestamp 1)
(org-extend-today-until 6)
(org-duration-format (quote h:mm))
(org-outline-path-complete-in-steps nil)
(org-hide-emphasis-markers t)
(org-refile-targets '((nil :level . 2)))
(org-src-fontify-natively t)
(org-src-tab-acts-natively t)
(org-pretty-entities t)
(org-src-preserve-indentation t)
(org-src-window-setup 'current-window)
(org-edit-src-auto-save-idle-delay 60)
(org-insert-heading-respect-content t)
(org-startup-folded t)
(org-priority-lowest 70)
)
(use-package org-contrib
:after org
:config
(require 'org-checklist)
)
(use-package company-org-block
:commands company-org-block
:after (org cape))
(use-package my-org
:after org
:load-path "my/org"
:ensure nil
)
(use-package polymode :defer t)
(use-package org-modern
:after org
:init (global-org-modern-mode))
(use-package org-web-tools
:after org
:bind (:map org-mode-map
(("M-l" . org-web-tools-insert-link-for-url)))
)
https://orgmode.org/manual/Org-Crypt.html
(use-package org-crypt
:after org
:ensure nil
:config
(org-crypt-use-before-save-magic)
(add-to-list 'safe-local-variable-values
'(buffer-auto-save-file-name nil))
:custom
(org-crypt-key "jan.moeller0@gmail.com")
)
;; https://stackoverflow.com/questions/76388376/emacs-org-encrypt-entry-hangs-when-file-is-modified
(fset 'epg-wait-for-status 'ignore)
(use-package age
:config
(age-file-enable)
:custom
(age-default-identity "~/.config/age/identity.age")
(age-default-recipient "~/.config/age/public-key.txt"))
(use-package denote
:after org
:init
(setq my/denote-directory-moi "~/dot/notes/moi"
my/denote-directory-wrk "~/dot/notes/wrk")
:custom
(denote-directory my/denote-directory-moi)
)
(use-package denote-silo-extras
:after denote
:ensure nil
:custom
(denote-silo-extras-directories `(,my/denote-directory-wrk))
)
(use-package consult-notes
:after denote
:bind
("C-<home>" . consult-notes)
("C-S-<home>" . (lambda () (interactive) (let ((denote-directory my/denote-directory-wrk)) (consult-notes))))
("M-<home>" . consult-notes-search-in-all-notes)
("M-S-<home>" . (lambda () (interactive) (let ((denote-directory my/denote-directory-wrk)) (consult-notes-search-in-all-notes))))
:init (consult-notes-denote-mode)
:custom
(consult-notes-denote-display-id nil)
)
(use-package vlf
:commands (vlf-mode vlf)
:init (require 'vlf-setup))
(use-package logview
:commands logview-mode)
(use-package journalctl-mode
:commands journalctl)
(use-package whole-line-or-region
:init (whole-line-or-region-global-mode 1)
:blackout whole-line-or-region-local-mode)
(use-package editorconfig
:config (editorconfig-mode 1)
:blackout editorconfig-mode)
(use-package hungry-delete
:init (global-hungry-delete-mode)
:blackout hungry-delete-mode)
;; https://github.com/lassik/emacs-format-all-the-code/issues/33
(use-package envrc
:init (envrc-global-mode)
:blackout envrc-mode)
;; currently no usage for it
;; but keep an eye on future features
;; (use-package async)
(use-package midnight
:ensure nil
:config
(setq midnight-period (* 60 60 3)) ;; 3h
(advice-add 'clean-buffer-list :around 'suppress-message-advice-around)
(midnight-delay-set 'midnight-delay (ts-format "%I:%M%p" (ts-adjust 'minute 5 (ts-now))))
:custom
;; https://www.emacswiki.org/emacs/CleanBufferList
(clean-buffer-list-delay-special (* 60 60 2)) ;; 2h
(clean-buffer-list-kill-regexps '(".*")))
(use-package treesit-auto
:config
(global-treesit-auto-mode))
(use-package substitute)
(use-package drag-stuff
:init
(drag-stuff-global-mode 1)
:config
(setq drag-stuff-except-modes '(org-mode))
:blackout drag-stuff-mode)
(use-package golden-ratio-scroll-screen
:custom
(golden-ratio-scroll-highlight-flag nil)
(golden-ratio-scroll-screen-ratio 3.0))
(use-package quickrun :commands quickrun)
(use-package expreg
:bind
("C-M-w" . expreg-expand)
("C-M-q" . expreg-contract)
)
(use-package combobulate
:custom
(combobulate-flash-node nil)
:ensure (:host github :repo "mickeynp/combobulate" :build (:not autoloads))
)
;; (use-package dogears
;; :init (dogears-mode)
;; :custom
;; (dogears-hooks '(xref-after-jump-hook isearch-mode-end-hook))
;; :straight (:host github :repo "alphapapa/dogears.el"))
(use-package binky
:init
(binky-mode)
)
;; Unified approach inc: https://github.com/purcell/reformatter.el/pull/24
(use-package apheleia
:init (apheleia-global-mode +1)
:config
;; add additional formatters
(push '(treefmt . ("treefmt" "-v" "--config-file" (expand-file-name "~/.config/treefmt/treefmt.toml") "--tree-root" "." "--stdin" filepath)) apheleia-formatters)
;; overwrite mode formatters
(setf (alist-get 'nix-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'sh-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'bash-ts-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'go-ts-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'terraform-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'rustic-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'web-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'html-ts-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'typescript-ts-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'js-ts-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'css-ts-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'scss-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'slint-mode apheleia-mode-alist) 'treefmt)
(setf (alist-get 'toml-ts-mode apheleia-mode-alist) 'treefmt)
;; add mode formatters
(push '(nxml-mode . treefmt) apheleia-mode-alist)
(push '(jsonnet-mode . treefmt) apheleia-mode-alist)
(push '(d2-mode . treefmt) apheleia-mode-alist)
(push '(emacs-lisp-mode . lisp-indent) apheleia-mode-alist)
;; disable mode formatting
(setf apheleia-mode-alist (assoc-delete-all 'yaml-ts-mode apheleia-mode-alist))
:blackout)
(use-package eglot
:ensure nil
:custom
(eglot-autoshutdown t)
(eglot-confirm-server-initiated-edits nil)
)
(use-package eglot-booster
:ensure (:host github :repo "jdtsmith/eglot-booster")
:after eglot
:config
(eglot-booster-mode)
)
(use-package jinx ;; spell checking
:ensure nil ;; built by nix
:hook (text-mode conf-mode)
:custom (jinx-languages "en_US")
:blackout)
(use-package isearch-mb
:init (isearch-mb-mode)
:config
(setq-default
isearch-lazy-count t
search-ring-max 200
regexp-search-ring-max 200))
;;;; isearch tweaks
;;; auto-wrap isearch: https://stackoverflow.com/a/36707038
;; Prevents issue where you have to press backspace twice when
;; trying to remove the first character that fails a search
(define-key isearch-mode-map [remap isearch-delete-char] 'isearch-del-char)
(defadvice isearch-search (after isearch-no-fail activate)
(unless isearch-success
(ad-disable-advice 'isearch-search 'after 'isearch-no-fail)
(ad-activate 'isearch-search)
(isearch-repeat (if isearch-forward 'forward))
(ad-enable-advice 'isearch-search 'after 'isearch-no-fail)
(ad-activate 'isearch-search)))
;; instant isearch reverse
;; https://emacs.stackexchange.com/a/58825
(define-advice isearch-repeat (:before (direction &optional count) goto-other-end)
"If reversing, start the search from the other end of the current match."
(unless (eq isearch-forward (eq direction 'forward))
(when isearch-other-end
(goto-char isearch-other-end))))
(use-package vertico
:ensure (vertico :files (:defaults "extensions/*"))
:init
(vertico-mode)
)
(use-package vertico-directory
:ensure nil
:after vertico
:hook (rfn-eshadow-update-overlay . vertico-directory-tidy)
:bind (:map vertico-map
(("M-<right>" . vertico-directory-enter)
("M-<left>" . vertico-directory-delete-word)))
)
(use-package savehist
:ensure nil
:init
(savehist-mode))
(use-package orderless
:custom
(orderless-matching-styles '(orderless-prefixes))
)
(use-package fussy
:custom
(completion-styles '(fussy basic))
(completion-category-defaults nil)
(completion-category-overrides nil)
(fussy-filter-fn 'fussy-filter-orderless)
)
;; https ://www.reddit.com/r/emacs/comments/krptmz/emacs_completion_framework_embark_consult/
(use-package consult
:after consult-project-extra
:custom
(consult-preview-key nil)
(consult-narrow-key "^")
(consult-buffer-sources '(consult--source-hidden-buffer
consult--source-modified-buffer
consult--source-buffer
consult--source-recent-file
consult--source-file-register
consult--source-bookmark))
:config
(consult-customize
consult--source-bookmark
:hidden t)
)
(use-package consult-project-extra)
(use-package marginalia
:init
(marginalia-mode)
:config
;; disable all annotations
(mapc
(lambda (x)
(setcdr x (cons 'none (remq 'none (cdr x)))))
marginalia-annotator-registry)
)
(use-package embark-consult
:hook
(embark-collect-mode . consult-preview-at-point-mode))
(use-package embark
:after embark-consult
:config
(push 'embark--ignore-target
(alist-get 'jinx-correct embark-target-injection-hooks))
)
https://github.com/bbatsov/crux
(use-package crux)
(use-package colorful-mode
:ensure (:type git :host github :repo "DevelopmentCool2449/colorful-mode")
:hook (css-ts-mode org-mode help-mode)
:blackout)
(use-package kurecolor :defer t)
(use-package evil-nerd-commenter
:config
(evilnc-default-hotkeys))
(use-package outshine
:commands outshine-mode)
(use-package navi-mode
:commands navi-mode)
(use-package corfu
:init (global-corfu-mode)
:custom
(corfu-auto t)
(corfu-auto-prefix 2)
:blackout corfu-mode
)
(use-package cape
:init
;; TODO: maybe use cape-dict with long delay
;; (add-to-list 'completion-at-point-functions #'cape-ispell)
(add-to-list 'completion-at-point-functions (cape-company-to-capf #'company-org-block))
)
(use-package puni
:defer t
:init
;; The autoloads of Puni are set up so you can enable `puni-mode` or
;; `puni-global-mode` before `puni` is actually loaded. Only after you press
;; any key that calls Puni commands, it's loaded.
(puni-global-mode)
:custom
(puni-confirm-when-delete-unbalanced-active-region nil))
(electric-pair-mode 1)
(use-package vundo)
(use-package undo-fu)
TODO more at oremacs.com
(setq ediff-keep-variants nil)
(setq ediff-window-setup-function 'ediff-setup-windows-plain
ediff-split-window-function 'split-window-horizontally)
(add-hook 'ediff-prepare-buffer-hook 'show-all)
(use-package wgrep :defer t)
(setq project-vc-merge-submodules nil)
(use-package which-key
:init (which-key-mode)
:custom
(which-key-show-early-on-C-h t)
(which-key-idle-delay 3.0)
(which-key-idle-secondary-delay 0.05)
:blackout which-key-mode)
(use-package
helpful
:bind* (("C-h f" . helpful-callable)
("C-h v" . helpful-variable)
("C-h k" . helpful-key)
("C-h C-d" . helpful-at-point)
("C-h F" . helpful-function)
("C-h C" . helpful-command)))
(use-package
dumb-jump
:init (add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
:custom (dumb-jump-prefer-searcher 'rg))
(use-package webpaste
:commands (webpaste-paste-buffer-or-region)
:custom
(webpaste-provider-priority '("paste.rs"))
)
(use-package magit
:commands magit-status
:custom
(magit-auto-revert-mode nil)
(magit-diff-section-arguments (quote ("--no-ext-diff" "-U2")))
(magit-diff-refine-ignore-whitespace nil)
(magit-refs-margin '(t "%Y-%m-%d %H:%M" magit-log-margin-width nil 18))
(magit-log-margin '(t "%Y-%m-%d %H:%M" magit-log-margin-width t 18))
(magit-diff-refine-hunk t)
(magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1)
(git-commit-use-local-message-ring t)
:config
(magit-add-section-hook 'magit-status-sections-hook
'magit-insert-modules-unpulled-from-upstream
'magit-insert-unpulled-from-upstream)
(magit-add-section-hook 'magit-status-sections-hook
'magit-insert-modules-unpushed-to-upstream
'magit-insert-unpulled-from-upstream)
;; significantly improves performance in large repos (e.g. nixpkgs)
;; see https://discourse.nixos.org/t/how-to-handle-nixpkgs-as-a-very-large-git-repo/24614/9
(remove-hook 'magit-status-headers-hook 'magit-insert-tags-header)
(defun my--git-commit-check-commitlint (force)
(or force
(let ((old-buffer (current-buffer)))
(save-window-excursion
(with-temp-buffer
(insert-buffer-substring old-buffer)
(let* ((commitlint-cmd "commitlint -g ~/.config/commitlint-rs/config.yaml")
(exit-code (shell-command-on-region (point-min) (point-max) commitlint-cmd)))
(if (equal exit-code 0)
t
(pop-to-buffer-same-window "*Shell Command Output*" ())
(ansi-color-apply-on-region (point-min) (point-max))
(y-or-n-p "Commitlint error. Commit anyway?")
)
))))))
(cl-pushnew 'my--git-commit-check-commitlint git-commit-finish-query-functions))
;; mostly based on https://github.com/alexluigit/dirvish/blob/main/Configuration.org#Example-config
(use-package dired
:ensure nil
:custom
(dired-recursive-deletes 'top)
(dired-recursive-copies 'always)
(delete-by-moving-to-trash t)
(dired-dwim-target t)
(dired-auto-revert-buffer t)
(dired-clean-confirm-killing-deleted-buffers nil)
;; todo: not respected?
(dired-kill-when-opening-new-dired-buffer t)
(dired-listing-switches "-aDGhvl --group-directories-first --time-style=long-iso"))
(use-package dirvish
:demand t
:custom
(dirvish-mode-line-height 15)
:init
(dirvish-override-dired-mode))
(use-package dired-x
:ensure nil
;; Enable dired-omit-mode by default
;; :hook
;; (dired-mode . dired-omit-mode)
:config
;; Make dired-omit-mode hide all "dotfiles"
;; (setq dired-omit-files
;; (concat dired-omit-files "\\|^\\..*$"))
)
(use-package diredfl
:hook
(dired-mode . diredfl-mode))
(use-package adoc-mode
:mode "\\.adoc\\'")
(use-package c++-mode
:ensure nil
:mode "\\.h\\'")
(use-package rtags
:defer t)
(use-package irony
:init (defun my--on-c++-mode ()
(irony-mode)
(flycheck-mode)
;; (rtags-start-process-unless-running)
)
:hook (c++-mode . my--on-c++-mode))
(use-package flycheck-irony
:hook (flycheck-mode . flycheck-irony-setup))
;; no idea which one is the main elisp file
;; (use-package doc-tools
;; :ensure (:host github :repo "dalanicolai/doc-tools")
;; :mode "\\.pdf\\'")
(use-package csv-mode)
(use-package dockerfile-mode
:mode ("\\Dockerfile\\'" "\\Dockerfile\\'"))
(use-package emacs-lisp
:ensure nil
:hook (emacs-lisp-mode . nameless-mode)
)
(use-package nameless
:commands nameless-mode
:custom (nameless-private-prefix t))
(use-package xtest :defer t)
(use-package elixir-mode
:hook (elixir-mode . flycheck-mode)
:mode "\\.ex\\'")
(use-package flycheck-credo
:after elixir-mode
:config
(flycheck-credo-setup)
:custom
(flycheck-elixir-credo-strict nil))
(use-package go-mode
:mode "\\.go\\'"
;; :config
;; (require 'dap-dlv-go)
:hook (go-ts-mode . eglot-ensure))
(use-package graphql-mode
:mode ("\\.gql\\'" "\\.graphql\\'"))
(use-package java-mode
:ensure nil
;; :hook (java-mode . eglot-ensure)
:mode "\\.java\\'")
(use-package json-mode
:mode "\\.json\\'"
:custom
(json-reformat:indent-width 2)
(js-indent-level 2))
(use-package jsonnet-mode
:mode ("\\.jsonnet\\'" "\\.libsonnet\\'"))
(use-package just-mode
:mode ("justfile\\'"))
(use-package kotlin-mode
:mode "\\.kt\\'")
(use-package tex
:ensure nil ;; built by nix
:mode "\\.tex\\'"
:hook (LaTeX-mode . turn-on-reftex))
(use-package lua-mode
:mode ("\\.lua\\'"))
(use-package markdown-mode
:mode "\\.md\\'")
(use-package grip-mode
:custom
(grip-preview-use-webkit nil))
(use-package nim-mode
:mode "\\.nim\\'"
:hook ((nim-mode . nimsuggest-mode)))
(use-package nix-mode
:mode "\\.nix.*\\'"
:hook (nix-mode . eglot-ensure))
(use-package php-mode
:mode "\\.php\\'")
(use-package
plantuml-mode
:mode "\\.puml\\'"
:custom
(plantuml-executable-path "/usr/bin/plantuml")
(plantuml-default-exec-mode 'executable))
(use-package d2-mode
:mode "\\.d2\\'"
)
(use-package python
:ensure nil
:mode ("\\.py\\'" . python-ts-mode)
:hook (python-ts-mode . (lambda ()
(eglot-ensure)
(combobulate-mode)
))
)
;; emacs-ipython-notebook
(use-package ein
:mode ("\\.ipynb\\'" . ein:ipynb-mode))
;; No conditional-on-mode necessary
(use-package rustic
:ensure (:host github :repo "emacs-rustic/rustic")
:custom
(rustic-lsp-client 'eglot)
(rust-mode-treesitter-derive t)
)
(use-package ron-mode
:mode "\\.ron\\'"
)
(use-package slint-mode
:mode "\\.slint\\'")
(use-package sql-indent
:hook (sql-mode . sqlind-minor-mode)
:blackout sqlind-minor-mode)
(use-package terraform-mode
:mode "\\.tf\\'"
;; too expensive to auto-enable when just viewing files (enable on demand when developing)
;; :hook (terraform-mode . eglot-ensure)
)
(use-package sh-mode
:ensure nil
:hook (sh-mode . eglot-ensure))
(use-package nushell-mode
:mode "\\.nu\\'")
(use-package fish-mode
:mode "\\.fish\\'")
(setq tramp-default-method "ssh")
(use-package css-ts-mode
:ensure nil
:mode ("\\.less\\'" "\\.css\\'" "\\.sass\\'")
:custom
(css-indent-offset 4))
(use-package scss-mode
:ensure nil
:mode ("\\.scss\\'"))
(use-package js2-mode
:mode "\\.js\\'"
:hook (js2-mode . eglot-ensure)
:custom
(js2-basic-offset 2)
(js2-strict-inconsistent-return-warning nil)
(js2-strict-missing-semi-warning nil)
:blackout)
(use-package web-mode
:mode ("\\.jsx\\'" "\\.tsx\\'")
:custom
(web-mode-enable-auto-closing t)
(web-mode-enable-auto-indentation nil))
(use-package html-ts-mode
:ensure nil
:mode ("\\.html?\\'"))
(use-package typescript-ts-mode
:ensure nil
:mode "\\.ts\\'"
:hook (typescript-ts-mode . (lambda ()
(eglot-ensure)
(combobulate-mode)
))
)
;; todo: https://github.com/zkry/yaml-pro
(use-package yaml-ts-mode
:ensure nil
:mode ("\\.yml.*\\'" "\\.yaml.*\\'")
)
(use-package hurl-mode
:ensure (:host github :repo "jaszhe/hurl-mode")
:mode "\\.hurl\\'")
(use-package x509-mode :defer t)
(use-package restclient
:mode ("\\.http\\'" . restclient-mode)
:commands restclient-mode)
(use-package ledger-mode
:mode "\\.ledger\\'")
(use-package google-translate)
(use-package google-translate-smooth-ui
:after google-translate
:ensure nil
:commands google-translate-smooth-translate
:config
;; https://github.com/atykhonov/google-translate/issues/52#issuecomment-727920888
(setq google-translate-translation-directions-alist '(("de" . "en")("en" . "de")))
(defun google-translate--search-tkk () "Search TKK." (list 430675 2721866130))
(google-translate--setup-minibuffer-keymap)
)
(use-package mail-mode
:ensure nil
:mode "\\/tmp\\/neomutt.*\\'")
(use-package khardel
:general
(:keymaps 'mail-mode-map
"C-f" 'khardel-insert-email))
(use-package himalaya)
(use-package notmuch)
(use-package gif-screencast
:commands gif-screencast-start-or-stop
:custom
(gif-screencast-program "grim")
(gif-screencast-args ()))
(use-package insert-shebang
:init
;; revert ;;;###autoload(add-hook 'find-file-hook 'insert-shebang)
(remove-hook 'find-file-hook 'insert-shebang)
:commands insert-shebang
:custom
(insert-shebang-track-ignored-filename nil))
(use-package org-download
:after org)
(use-package string-inflection
:commands (string-inflection-all-cycle))
(use-package recover-buffers)
(use-package ebuku
:commands ebuku)
(use-package units-mode
:commands units-mode)
(use-package lorem-ipsum
:commands (lorem-ipsum-insert-sentences lorem-ipsum-insert-paragraphs))
;; (use-package spookfox
;; :straight
;; (spookfox :type git
;; :host github
;; :repo "bitspook/spookfox"
;; :files ("lisp/*.el" "lisp/apps/*.el"))
;; :config
;; (require 'spookfox-org-tabs)
;; (setq spookfox-enabled-apps '(spookfox-org-tabs))
;; ;; (spookfox-init)
;; )
(use-package org-ai
:after org)
(menu-bar-mode -1)
(tool-bar-mode -1)
(tooltip-mode -1)
(mouse-avoidance-mode)
(setq blink-cursor-blinks 3)
(scroll-bar-mode -1)
(column-number-mode 1)
(set-face-attribute 'default nil :family "Monospace" :height 110)
(setq-default cursor-type 'bar)
(use-package olivetti
:hook
;; alternatively try as global mode: https://github.com/rnkn/olivetti/pull/56
(text-mode . olivetti-mode)
(prog-mode . olivetti-mode)
(dired-mode . olivetti-mode)
(magit-mode . olivetti-mode)
;; (fundamental-mode . olivetti-mode)
:custom
(olivetti-mode-on-hook '())
(olivetti-body-width 125)
:blackout olivetti-mode)
;; https://stackoverflow.com/questions/27845980/how-do-i-remove-newline-symbols-inside-emacs-vertical-border
(setf (cdr (assq 'continuation fringe-indicator-alist))
'(nil right-curly-arrow) ;; right indicator only
)
(use-package modus-themes
:init
(defun my-modus-themes-custom-faces ()
(modus-themes-with-colors
(custom-set-faces
`(show-paren-match ((,c :foreground ,green-intense :background unspecified :weight bold)))
`(olivetti-fringe ((,c :background ,bg-main)))
)))
;; TODO: not working, must be called manually after load-theme
(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces)
:config
(load-theme 'modus-operandi-tinted :no-confim)
(my-modus-themes-custom-faces)
)
(use-package gcmh
:init
;; https://github.com/hlissner/doom-emacs/blob/develop/core/core.el#L295
(setq gcmh-idle-delay 'auto ; default is 15s
gcmh-auto-idle-delay-factor 10
;; 16mb
gcmh-high-cons-threshold (* 16 1024 1024))
(gcmh-mode 1)
:blackout)
https://www.reddit.com/r/emacs/comments/1mbn0s/the_emacs_calculator/
\(Buy: \)\([0-9]+\) -> \1\,(+ \#2 \#)