.../.config/emacs/config.org
2025-10-22 15:44:22 -03:00

835 lines
25 KiB
Org Mode
Raw 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.

#+TITLE: >.<macs
#+AUTHOR: mux
#+STARTUP: shrink
* SANE DEFAULTS
** Generic optimizations
#+begin_src emacs-lisp
(setq gc-cons-threshold most-positive-fixnum)
(add-hook
'emacs-startup-hook
(lambda () (setq gc-cons-threshold (* 50 1024 1024))))
(setq backup-directory-alist '(("." . "~/.config/emacs/backups")))
(setq auto-save-file-name-transforms
'((".*" "~/.config/emacs/auto-save-list/" t)))
(setq
delete-old-versions t
kept-new-versions 6
kept-old-versions 2
version-control t)
(setq undo-limit (* 8 1024 1024))
(save-place-mode 1)
#+end_src
#+RESULTS:
: t
** Declutter user interface
#+begin_src emacs-lisp
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(setq warning-minimum-level :error)
#+end_src
** Tweak appearance
#+begin_src emacs-lisp
(set-face-attribute 'default nil
:family "ShureTechMono Nerd Font"
:height 190)
(global-display-line-numbers-mode 1)
(setq display-line-numbers 'relative)
(setq-default line-spacing 5)
(setq-default
inhibit-startup-message t
initial-scratch-message nil
sentence-end-double-space nil
ring-bell-function 'ignore
make-backup-files t
vc-follow-symlinks t
ad-redefinition-action 'accept
help-window-select t
use-short-answers t)
(dolist (mode
'(term-mode-hook
shell-mode-hook
treemacs-mode-hook
eshell-mode-hook
help-mode-hook
neotree-mode-hook
vterm-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode 0))))
#+end_src
* PACKAGE MANAGEMENT
** Elpaca package manager
#+begin_src emacs-lisp
(defvar elpaca-installer-version 0.11)
(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 :inherit ignore
: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)
(let ((load-source-file-function nil)) (load "./elpaca-autoloads"))))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))
;; Install use-package support
(elpaca elpaca-use-package
(elpaca-use-package-mode))
#+end_src
* EDITING & MODAL INPUT
** Meow modal editing
#+begin_src emacs-lisp
(use-package
meow
:ensure t
:preface
(defun meow-word ()
"Expand word/symbol under cursor."
(interactive)
(if (and (use-region-p)
(equal
(car (region-bounds)) (bounds-of-thing-at-point 'word)))
(meow-mark-symbol 1)
(progn
(when (and (mark)
(equal
(car (region-bounds))
(bounds-of-thing-at-point 'symbol)))
(meow-pop-selection))
(meow-mark-word 1))))
(defun meow-kill-line ()
"Kill till the end of line."
(interactive)
(let ((select-enable-clipboard meow-use-clipboard))
(kill-line)))
(defun meow-change-line ()
"Kill till end of line and switch to INSERT state."
(interactive)
(meow--cancel-selection)
(meow-end-of-thing (car (rassoc 'line meow-char-thing-table)))
(meow-change))
(defun meow-save-clipboard ()
"Copy in clipboard."
(interactive)
(let ((meow-use-clipboard t))
(meow-save)))
(defvar meow--trim-yank nil)
(defun meow-insert-for-yank-advice (orig-fn str)
"Advice for `insert-for-yank' function to correctly insert lines."
(when meow--trim-yank
(set 'str (string-trim-right str "\n")))
(if (and (not (eq (point) (+ 1 (line-end-position 0))))
(string-match-p "^.+\n$" str))
(save-excursion
(beginning-of-line)
(funcall orig-fn str))
(funcall orig-fn str)))
(defun meow-yank-dwim ()
"Smart yank."
(interactive)
(advice-add 'insert-for-yank :around 'meow-insert-for-yank-advice)
(if (use-region-p)
(let ((meow--trim-yank t))
(delete-region (region-beginning) (region-end))
(meow-yank))
(meow-yank))
(advice-remove 'insert-for-yank 'meow-insert-for-yank-advice))
(defun meow-yank-pop-dwim ()
"Smart yank pop."
(interactive)
(advice-add 'insert-for-yank :around 'meow-insert-for-yank-advice)
(if (use-region-p)
(let ((meow--trim-yank t))
(delete-region (region-beginning) (region-end))
(meow-yank-pop))
(meow-yank-pop))
(advice-remove 'insert-for-yank 'meow-insert-for-yank-advice))
(defun meow-smart-reverse ()
"Reverse selection or begin negative argument."
(interactive)
(if (use-region-p)
(meow-reverse)
(negative-argument nil)))
(defun meow-kmacro ()
"Toggle recording of kmacro."
(interactive)
(if defining-kbd-macro
(meow-end-kmacro)
(meow-start-kmacro)))
(defun meow-eldoc ()
"Toggle the display of the eldoc window."
(interactive)
(if (get-buffer-window eldoc--doc-buffer)
(delete-window (get-buffer-window eldoc--doc-buffer))
(eldoc-doc-buffer t)))
(defun meow-ergo-setup ()
(setq meow-cheatsheet-layout meow-cheatsheet-layout-qwerty)
(setq meow-normal-state-keymap (make-sparse-keymap))
(setf (alist-get 'normal meow-keymap-alist)
meow-normal-state-keymap)
(meow-motion-define-key
'("l" . meow-next) '("j" . meow-prev) '("<escape>" . ignore))
(meow-leader-define-key
'("1" . meow-digit-argument)
'("2" . meow-digit-argument)
'("3" . meow-digit-argument)
'("4" . meow-digit-argument)
'("5" . meow-digit-argument)
'("6" . meow-digit-argument)
'("7" . meow-digit-argument)
'("8" . meow-digit-argument)
'("9" . meow-digit-argument)
'("0" . meow-digit-argument)
'("/" . meow-keypad-describe-key)
'("?" . meow-cheatsheet))
(meow-thing-register
'angle '(pair ("<") (">")) '(pair ("<") (">")))
(setq meow-char-thing-table
'((?f . round)
(?d . square)
(?s . curly)
(?a . angle)
(?r . string)
(?v . paragraph)
(?c . line)
(?x . buffer)))
(meow-normal-define-key
;; Expansion
'("0" . meow-expand-0)
'("1" . meow-expand-1)
'("2" . meow-expand-2)
'("3" . meow-expand-3)
'("4" . meow-expand-4)
'("5" . meow-expand-5)
'("6" . meow-expand-6)
'("7" . meow-expand-7)
'("8" . meow-expand-8)
'("9" . meow-expand-9)
'("'" . meow-reverse)
;; Movement
'("i" . meow-prev)
'("k" . meow-next)
'("j" . meow-left)
'("l" . meow-right)
'("y" . meow-search)
'("/" . meow-visit)
;; Expansion
'("I" . meow-prev-expand)
'("K" . meow-next-expand)
'("J" . meow-left-expand)
'("L" . meow-right-expand)
'("u" . meow-back-word)
'("U" . meow-back-symbol)
'("o" . meow-next-word)
'("O" . meow-next-symbol)
'("a" . meow-mark-word)
'("A" . meow-mark-symbol)
'("s" . meow-line)
'("S" . meow-goto-line)
'("w" . meow-block)
'("q" . meow-join)
'("g" . meow-grab)
'("G" . meow-pop-grab)
'("m" . meow-swap-grab)
'("M" . meow-sync-grab)
'("p" . meow-cancel-selection)
'("P" . meow-pop-selection)
'("x" . meow-till)
'("z" . meow-find)
'("," . meow-beginning-of-thing)
'("." . meow-end-of-thing)
'("<" . meow-inner-of-thing)
'(">" . meow-bounds-of-thing)
;; Editing
'("d" . meow-kill)
'("f" . meow-change)
'("t" . meow-delete)
'("c" . meow-save)
'("v" . meow-yank)
'("V" . meow-yank-pop)
'("e" . meow-insert)
'("E" . meow-open-above)
'("r" . meow-append)
'("R" . meow-open-below)
'("h" . undo-only)
'("H" . undo-redo)
'("b" . open-line)
'("B" . split-line)
'("[" . indent-rigidly-left-to-tab-stop)
'("]" . indent-rigidly-right-to-tab-stop)
;; Prefix commands
'("nf" . meow-comment)
'("nt" . meow-start-kmacro-or-insert-counter)
'("nr" . meow-start-kmacro)
'("ne" . meow-end-or-call-kmacro)
'(";f" . save-buffer)
'(";F" . save-some-buffers)
'(";d" . meow-query-replace-regexp)
;; Buffer navigation
'(";[b" . previous-buffer)
'(";]b" . next-buffer)
'(";b" . switch-to-buffer)
'(";nb" . rename-buffer)
'(";B" . revert-buffer)
'("<escape>" . ignore)))
:config (meow-ergo-setup) (meow-global-mode 1))
#+end_src
** Formatter
#+begin_src emacs-lisp
(use-package format-all
:ensure t
:preface
(defun refmt ()
"Auto-format whole buffer."
(interactive)
(cond
((and (bound-and-true-p eglot--managed-mode)
(eglot-managed-p))
(eglot-format-buffer))
((derived-mode-p 'prolog-mode)
(prolog-indent-buffer))
((derived-mode-p 'emacs-lisp-mode)
(indent-region (point-min) (point-max)))
((derived-mode-p 'org-mode)
(org-indent-region (point-min) (point-max)))
(t
(format-all-buffer))))
:config
(global-set-key (kbd "M-f") #'refmt)
(add-hook 'prog-mode-hook #'format-all-ensure-formatter))
#+end_src
#+RESULTS:
: [nil 26871 47188 711924 nil elpaca-process-queues nil nil 283000 nil]
* PROGRAMMING FEATURES
** Syntax highlighting
#+begin_src emacs-lisp
(use-package treesit-auto
:ensure t
:custom
(treesit-auto-install 'prompt)
:config
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode))
#+end_src
#+RESULTS:
: [nil 26870 64740 146030 nil elpaca-process-queues nil nil 133000 nil]
** LSP
#+begin_src emacs-lisp
;; (use-package
;; lsp-mode
;; :ensure t
;; :hook
;; (prog-mode . lsp-deferred)
;; (lsp-mode . lsp-enable-which-key-integration)
;; :commands (lsp lsp-deferred)
;; :init (setq lsp-keymap-prefix "C-c l")
;; :custom
;; (lsp-completion-provider :none)
;; (lsp-headerline-breadcrumb-enable nil))
(use-package eglot
:hook
(prog-mode . eglot-ensure)
:custom
(eglot-events-buffer-size 0)
(eglot-sync-connect t)
(eglot-autoshutdown t)
(eglot-report-progress t)
:bind (:map eglot-mode-map
("C-c l r" . eglot-rename)
("C-c l a" . eglot-code-actions)
("C-c l f" . eglot-format)
("C-c l F" . eglot-format-buffer)
("C-c l d" . xref-find-definitions)
("C-c l R" . xref-find-references)
("C-c l h" . eldoc))
:config
(add-to-list 'eglot-server-programs
'((js-mode typescript-mode tsx-ts-mode typescript-ts-mode js-ts-mode)
. ("deno" "lsp" :initializationOptions
(:enable t
:lint t
:unstable t
:config nil)))))
#+end_src
#+RESULTS:
: [nil 26873 7819 534617 nil elpaca-process-queues nil nil 890000 nil]
qq
: #[128 "\304\300\"\205 \304\301\"\207" [lsp-display-warning-advise #<subr display-warning> :before-while nil apply] 4 advice]
** Indentation preferences
#+begin_src emacs-lisp
(setq-default
indent-tabs-mode t
tab-width 4
standard-indent 4)
(setq tab-always-indent t)
(use-package
dtrt-indent
:ensure t
:hook (prog-mode . dtrt-indent-mode))
(use-package
highlight-indent-guides
:ensure t
:hook
(prog-mode . highlight-indent-guides-mode)
(org-mode . highlight-indent-guides-mode)
:custom
(highlight-indent-guides-auto-enabled nil)
(highlight-indent-guides-method 'bitmap)
:config
(set-face-background 'highlight-indent-guides-odd-face "#252A2E")
(set-face-background 'highlight-indent-guides-even-face "#16191C")
(set-face-foreground 'highlight-indent-guides-character-face "#252A2E"))
#+end_src
#+RESULTS:
: [nil 26871 55888 184183 nil elpaca-process-queues nil nil 358000 nil]
** Emacs Lisp Tools
#+begin_src emacs-lisp
(use-package elisp-autofmt
:ensure t)
#+end_src
#+RESULTS:
: [nil 26871 52804 309295 nil elpaca-process-queues nil nil 101000 nil]
* COMPLETION SYSTEM
** Helpful documentation
(use-package helpful
:ensure t
:bind
([remap describe-function] . helpful-callable)
([remap describe-variable] . helpful-variable)
([remap describe-key] . helpful-key))
#+end_src
** Minibuffer completion (Vertico + Marginalia)
#+begin_src emacs-lisp
(use-package
marginalia
:ensure t
:bind (:map minibuffer-local-map ("M-A" . marginalia-cycle))
:init (marginalia-mode))
(use-package
vertico
:ensure t
:custom (vertico-cycle t)
:init (vertico-mode))
(use-package savehist :init (savehist-mode))
(use-package
orderless
:ensure t
:custom
(completion-styles '(orderless basic))
(completion-category-defaults nil)
(completion-category-overrides
'((file (styles partial-completion)))))
(use-package
consult
:ensure t
:bind
( ;; C-c bindings (mode-specific-map)
("C-c h" . consult-history)
("C-c m" . consult-mode-command)
("C-c k" . consult-kmacro)
;; C-x bindings (ctl-x-map)
("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)
("C-x r b" . consult-bookmark)
;; M-g bindings (goto-map)
("M-g e" . consult-compile-error)
("M-g g" . consult-goto-line)
("M-g M-g" . consult-goto-line)
("M-g o" . consult-outline)
("M-g m" . consult-mark)
("M-g k" . consult-global-mark)
("M-g i" . consult-imenu)
("M-g I" . consult-imenu-multi)
;; M-s bindings (search-map)
("M-s d" . consult-find)
("M-s D" . consult-locate)
("M-s g" . consult-grep)
("M-s G" . consult-git-grep)
("M-s r" . consult-ripgrep)
("M-s l" . consult-line)
("M-s L" . consult-line-multi)
("M-s k" . consult-keep-lines)
("M-s u" . consult-focus-lines)
;; Isearch integration
("M-s e" . consult-isearch-history)
:map
isearch-mode-map
("M-e" . consult-isearch-history)
("M-s e" . consult-isearch-history)
("M-s l" . consult-line)
("M-s L" . consult-line-multi)
;; Minibuffer history
:map
minibuffer-local-map
("M-s" . consult-history)
("M-r" . consult-history))
:hook (completion-list-mode . consult-preview-at-point-mode)
:init
(setq
xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
:custom (consult-preview-key 'any) (consult-narrow-key "<")
:config
(consult-customize
consult-theme
:preview-key
'(:debounce 0.2 any)
consult-ripgrep
consult-git-grep
consult-grep
consult-bookmark
consult-recent-file
consult-xref
consult--source-bookmark
consult--source-file-register
consult--source-recent-file
consult--source-project-recent-file
:preview-key '(:debounce 0.4 any)))
(use-package
consult-projectile
:ensure t
:after (consult projectile)
:bind
("C-c p p" . consult-projectile-switch-project)
("C-c p f" . consult-projectile-find-file)
("C-c p s" . consult-projectile-ripgrep))
(use-package
consult-eglot
:ensure t
:after (consult eglot)
:bind
(:map eglot-mode-map ("C-c l s" . consult-eglot-symbols)))
#+end_src
** Minibuffer settings
#+begin_src emacs-lisp
(use-package
emacs
:custom (context-menu-mode t) (enable-recursive-minibuffers t)
(read-extended-command-predicate
#'command-completion-default-include-p)
(text-mode-ispell-word-completion nil)
(minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt)))
#+end_src
** In-buffer completion (Corfu + Cape)
#+begin_src emacs-lisp
(use-package
corfu
:ensure t
:custom (corfu-auto t) (corfu-cycle t) (corfu-preselect 'prompt)
:init (global-corfu-mode) (corfu-history-mode) (corfu-popupinfo-mode)
:bind
(:map
corfu-map
("TAB" . corfu-next)
([tab] . corfu-next)
("S-TAB" . corfu-previous)
([backtab] . corfu-previous)))
(use-package
cape
:ensure t
:bind ("C-c p" . cape-prefix-map)
:hook
((completion-at-point-functions . cape-dabbrev)
(completion-at-point-functions . cape-file)
(completion-at-point-functions . cape-elisp-block)))
#+end_src
#+RESULTS:
: [nil 26870 55996 618175 nil elpaca-process-queues nil nil 712000 nil]
* VISUAL APPEARANCE
** Theme and colors
#+begin_src emacs-lisp
(use-package base16-theme
:ensure t
:config
(load-theme 'base16-moonlight t)
(let ((bg "#16191C")
(fg "#C5CACE")
(bg-alt "#252A2E")
(fg-alt "#A3AAAF")
(fg-muted "#50555A"))
(custom-theme-set-faces `user
`(default
((t (:background ,bg :foreground ,fg))))
`(fringe ((t (:background ,bg))))
`(hl-line ((t (:background ,bg-alt))))
`(mode-line
((t
(:background
,bg-alt
:foreground ,fg))))
`(mode-line-inactive
((t
(:background
,bg
:foreground ,fg-muted))))
`(line-number
((t
(:foreground
,fg-muted
:background ,bg))))
`(line-number-current-line
((t
(:foreground
,fg-alt
:background ,bg-alt
:weight bold))))
`(font-lock-comment-face
((t (:foreground ,fg-alt))))
;; Whitespace
`(whitespace-space-after-tab
((t (:background ,bg :foreground ,bg-alt))))
`(whitespace-space--tab
((t (:background ,bg :foreground ,bg-alt))))
`(whitespace-indentation
((t (:background ,bg :foreground ,bg-alt))))
`(whitespace-newline
((t (:background ,bg :foreground ,bg-alt))))
`(whitespace-trailing
((t (:background ,bg :foreground ,bg-alt))))
;; Org blocks
`(org-block
((t (:background ,bg :foreground ,fg))))
`(org-block-begin-line
((t
(:background
,bg-alt
:foreground ,fg-alt))))
`(org-block-end-line
((t
(:background
,bg-alt
:foreground ,fg-alt)))))))
#+end_src
#+RESULTS:
: [nil 26871 55003 957999 nil elpaca-process-queues nil nil 979000 nil]
** Modeline
#+begin_src emacs-lisp
(use-package doom-modeline
:ensure t
:init (doom-modeline-mode +1))
#+end_src
** Color preview
#+begin_src emacs-lisp
(use-package colorful-mode
:ensure t
:custom
(colorful-use-prefix t)
(colorful-only-strings 'only-prog)
(css-fontify-colors nil)
:hook
(prog-mode . colorful-mode)
(org-mode . colorful-mode)
:config
(add-to-list 'global-colorful-modes 'helpful-mode))
(use-package rainbow-delimiters
:ensure t
:hook (prog-mode . rainbow-delimiters-mode))
#+end_src
#+RESULTS:
: [nil 26871 58654 83112 nil elpaca-process-queues nil nil 37000 nil]
* INTEGRATIONS & UTILITIES
** Discord presence
#+begin_src emacs-lisp
(use-package elcord
:ensure t
:custom
(elcord-client-id "1430340921655824454")
(elcord-icon-base "https://raw.githubusercontent.com/xwra/elcord/master/icons/")
(elcord-refresh-rate 5)
(elcord-idle-timer 150)
(elcord-show-small-icon nil)
:config
(elcord-mode +1))
#+end_src
** Project management
#+begin_src emacs-lisp
(use-package projectile
:ensure t
:config
(projectile-mode +1)
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map))
(use-package editorconfig
:ensure t
:config
(editorconfig-mode 1))
#+end_src
** Dashboard
#+begin_src emacs-lisp
(use-package page-break-lines
:ensure t
:config
(page-break-lines-mode +1))
(use-package all-the-icons
:ensure t
:if (display-graphic-p))
(use-package dashboard
:ensure t
:custom
(dashboard-banner-logo-title "DMs~ ;)")
(dashboard-startup-banner "~/.config/emacs/dash.gif")
:config
(add-hook 'elpaca-after-init-hook #'dashboard-insert-startupify-lists)
(add-hook 'elpaca-after-init-hook #'dashboard-initialize)
(dashboard-setup-startup-hook)
(setq initial-buffer-choice (lambda () (get-buffer "*dashboard*"))))
#+end_src
** File tree
#+begin_src emacs-lisp
(use-package neotree
:ensure t
:bind ("C-c t" . neotree-toggle))
#+end_src
#+RESULTS:
: [nil 26872 5674 84936 nil elpaca-process-queues nil nil 792000 nil]
** Which-key and navigation
#+begin_src emacs-lisp
(use-package
which-key
:ensure t
:custom
(which-key-idle-delay 0.3)
(which-key-popup-type 'side-window)
(which-key-side-window-location 'bottom)
(which-key-side-window-max-height 0.1)
(which-key-max-description-length 32)
(which-key-add-column-padding 1)
(which-key-sort-order 'which-key-key-order-alpha)
(which-key-separator "")
(which-key-prefix-prefix "+")
(which-key-allow-imprecise-window-fit nil)
:config (which-key-mode +1))
(use-package
eldoc-box
:ensure t
:hook (eglot-managed-mode . eldoc-box-hover-at-point-mode)
:custom
(eldoc-box-max-pixel-width 800)
(eldoc-box-max-pixel-height 600))
(use-package
embark
:ensure t
:bind
(("C-." . embark-act)
("C-;" . embark-dwim)
("C-h C-z" . embark-bindings))
:config (setq prefix-help-command #'embark-prefix-help-command))
#+end_src
#+RESULTS:
: [nil 26873 9253 947918 nil elpaca-process-queues nil nil 729000 nil]