From d51beea88d300cb5066bb92a8148cad52fa1091d Mon Sep 17 00:00:00 2001 From: Sakamoto Date: Sun, 16 Aug 2026 15:34:00 -0500 Subject: update --- dot_config/emacs/lisp/avy-config.el | 176 ++++++++++++++++++ dot_config/emacs/lisp/completion-config.el | 104 +++++++++++ dot_config/emacs/lisp/doom-quit.el | 62 +++++++ dot_config/emacs/lisp/editing-config.el | 41 +++++ dot_config/emacs/lisp/elfeed-config.el | 32 ++++ dot_config/emacs/lisp/emacs-config.el | 280 +++++++++++++++++++++++++++++ dot_config/emacs/lisp/email-config.el | 3 + dot_config/emacs/lisp/embark-config.el | 11 ++ dot_config/emacs/lisp/evil-config.el | 132 ++++++++++++++ dot_config/emacs/lisp/git-config.el | 24 +++ dot_config/emacs/lisp/gptel-config.el | 24 +++ dot_config/emacs/lisp/irc-config.el | 35 ++++ dot_config/emacs/lisp/lsp-mode-config.el | 169 +++++++++++++++++ dot_config/emacs/lisp/meow-config.el | 233 ++++++++++++++++++++++++ dot_config/emacs/lisp/org-demo-macro.el | 66 +++++++ dot_config/emacs/lisp/org-mode-config.el | 165 +++++++++++++++++ dot_config/emacs/lisp/pretty-config.el | 31 ++++ dot_config/emacs/lisp/reading-config.el | 26 +++ dot_config/emacs/lisp/shell-config.el | 26 +++ 19 files changed, 1640 insertions(+) create mode 100644 dot_config/emacs/lisp/avy-config.el create mode 100644 dot_config/emacs/lisp/completion-config.el create mode 100644 dot_config/emacs/lisp/doom-quit.el create mode 100644 dot_config/emacs/lisp/editing-config.el create mode 100644 dot_config/emacs/lisp/elfeed-config.el create mode 100644 dot_config/emacs/lisp/emacs-config.el create mode 100644 dot_config/emacs/lisp/email-config.el create mode 100644 dot_config/emacs/lisp/embark-config.el create mode 100644 dot_config/emacs/lisp/evil-config.el create mode 100644 dot_config/emacs/lisp/git-config.el create mode 100644 dot_config/emacs/lisp/gptel-config.el create mode 100644 dot_config/emacs/lisp/irc-config.el create mode 100644 dot_config/emacs/lisp/lsp-mode-config.el create mode 100644 dot_config/emacs/lisp/meow-config.el create mode 100644 dot_config/emacs/lisp/org-demo-macro.el create mode 100644 dot_config/emacs/lisp/org-mode-config.el create mode 100644 dot_config/emacs/lisp/pretty-config.el create mode 100644 dot_config/emacs/lisp/reading-config.el create mode 100644 dot_config/emacs/lisp/shell-config.el (limited to 'dot_config/emacs/lisp') diff --git a/dot_config/emacs/lisp/avy-config.el b/dot_config/emacs/lisp/avy-config.el new file mode 100644 index 0000000..50c14ce --- /dev/null +++ b/dot_config/emacs/lisp/avy-config.el @@ -0,0 +1,176 @@ +;;; tweaked from karthink's .emacs.d + +(use-package avy + :ensure t + :commands (avy-goto-word-1 avy-goto-char-2 avy-goto-char-timer) + :config + (setq avy-timeout-seconds 0.4) + (setq avy-keys '(?a ?r ?s ?t ?g ?m ?n ?e ?i ?o ?' + ?q ?w ?f ?p ?b ?j ?l ?u ?y ?\; ?- + ?z ?x ?c ?d ?v ?k ?h ?, ?. ?/)) + + (setq avy-single-candidate-jump nil) + (setq avy-dispatch-alist '((?m . avy-action-mark) + (?$ . avy-action-ispell) + (?z . avy-action-zap-to-char) + (? . avy-action-embark) + (?= . avy-action-define) + (23 . avy-action-zap-to-char) + (?c . avy-action-mark-to-char) + (?h . avy-action-helpful) + (?x . avy-action-exchange) + + (11 . avy-action-kill-line) + (25 . avy-action-yank-line) + + (?w . avy-action-easy-kill) + (?k . avy-action-kill-stay) + (?y . avy-action-yank) + (?t . avy-action-teleport) + + (?W . avy-action-copy-whole-line) + (?K . avy-action-kill-whole-line) + (?Y . avy-action-yank-whole-line) + (?T . avy-action-teleport-whole-line))) + + ;; Improved to include transposition by hylophile + (defun avy-action-easy-kill (pt) + (unless (require 'easy-kill nil t) + (user-error "Easy Kill not found, please install.")) + (cl-letf* ((bounds (cond + ((use-region-p) + (prog1 (cons (region-beginning) (region-end)) + (deactivate-mark))) + ((bounds-of-thing-at-point 'sexp)) + (t (cons (point) (point))))) + (transpose-map + (define-keymap + "M-t" (lambda () (interactive "*") + (pcase-let ((`(,beg . ,end) (easy-kill--bounds))) + (transpose-regions (car bounds) (cdr bounds) beg end + 'leave-markers))))) + ((symbol-function 'easy-kill-activate-keymap) + (lambda () + (let ((map (easy-kill-map))) + (set-transient-map + (make-composed-keymap transpose-map map) + (lambda () + ;; Prevent any error from activating the keymap forever. + (condition-case err + (or (and (not (easy-kill-exit-p this-command)) + (or (eq this-command + (lookup-key map (this-single-command-keys))) + (let ((cmd (key-binding + (this-single-command-keys) nil t))) + (command-remapping cmd nil (list map))))) + (ignore + (easy-kill-destroy-candidate) + (unless (or (easy-kill-get mark) (easy-kill-exit-p this-command)) + (easy-kill-save-candidate)))) + (error (message "%s:%s" this-command (error-message-string err)) + nil))) + (lambda () + (let ((dat (ring-ref avy-ring 0))) + (select-frame-set-input-focus + (window-frame (cdr dat))) + (select-window (cdr dat)) + (goto-char (car dat))))))))) + (goto-char pt) + (easy-kill))) + + (defun avy-action-exchange (pt) + "Exchange sexp at PT with the one at point." + (set-mark pt) + (transpose-sexps 0)) + + (defun avy-action-helpful (pt) + (save-excursion + (goto-char pt) + (call-interactively #'display-local-help)) + (select-window + (cdr (ring-ref avy-ring 0))) + t) + + (defun avy-action-define (pt) + (cl-letf (((symbol-function 'keyboard-quit) + #'abort-recursive-edit)) + (save-excursion + (goto-char pt) + (dictionary-search-dwim)) + (select-window + (cdr (ring-ref avy-ring 0)))) + t) + + (defun avy-action-embark (pt) + (unwind-protect + (save-excursion + (goto-char pt) + (embark-act)) + (select-window + (cdr (ring-ref avy-ring 0)))) + t) + + (defun avy-action-kill-line (pt) + (unwind-protect + (save-excursion + (goto-char pt) + (kill-line)) + (avy-resume)) + (select-window + (cdr (ring-ref avy-ring 0))) + t) + + (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) + + (defun avy-action-kill-whole-line (pt) + (unwind-protect + (save-excursion + (goto-char pt) + (kill-whole-line) + (avy-resume))) + (select-window + (cdr + (ring-ref avy-ring 0))) + t) + + (defun avy-action-yank-whole-line (pt) + (avy-action-copy-whole-line pt) + (save-excursion (yank)) + t) + + (defun avy-action-teleport-whole-line (pt) + (avy-action-kill-whole-line pt) + (save-excursion (yank)) t) + + (defun avy-action-mark-to-char (pt) + (activate-mark) + (goto-char pt)) + + :bind (("C-M-'" . avy-resume) + ("C-'" . avy-goto-char-this-window) + ("M-j" . avy-goto-char-timer) + ("M-s y" . avy-copy-line) + ("M-s M-y" . avy-copy-region) + ("M-s M-k" . avy-kill-whole-line) + ("M-s j" . avy-goto-char-2) + ("M-s M-p" . avy-goto-line-above) + ("M-s M-n" . avy-goto-line-below) + ("M-s M-l" . avy-goto-end-of-line) + ("M-s C-w" . avy-kill-region) + ("M-s M-w" . avy-kill-ring-save-region) + ("M-s t" . avy-move-line) + ("M-s M-t" . avy-move-region) + :map isearch-mode-map + ("C-'" . avy-isearch) + ("M-j" . avy-isearch))) + +(provide 'avy-config) diff --git a/dot_config/emacs/lisp/completion-config.el b/dot_config/emacs/lisp/completion-config.el new file mode 100644 index 0000000..75c184a --- /dev/null +++ b/dot_config/emacs/lisp/completion-config.el @@ -0,0 +1,104 @@ +;; Modern interactive completion framework for the minibuffer +(use-package vertico + :hook + (after-init . vertico-mode) ;; Enable vertico after Emacs has initialized. + :custom + (vertico-cycle nil) ;; Do not cycle through candidates when reaching the end of the list. + :config + ;; Customize the display of the current candidate in the completion list. + ;; This will prefix the current candidate with “» ” to make it stand out. + ;; Reference: https://github.com/minad/vertico/wiki#prefix-current-candidate-with-arrow + (advice-add #'vertico--format-candidate :around + (lambda (orig cand prefix suffix index _start) + (setq cand (funcall orig cand prefix suffix index _start)) + (concat + (if (= vertico--index index) + (propertize "» " 'face '(:foreground "#80adf0" :weight bold)) + " ") + cand)))) + +(use-package which-key + :ensure nil + :config + (which-key-mode 1)) + +(use-package orderless + :defer t ;; Load Orderless on demand. + :after vertico ;; Ensure Vertico is loaded before Orderless. + :init + (setq completion-styles '(orderless basic) ;; Set the completion styles. + completion-category-defaults nil ;; Clear default category settings. + completion-category-overrides '((file (styles partial-completion))))) ;; Customize file completion styles. + +;; Marginalia enhances the completion experience in Emacs by adding +;; additional context to the completion candidates. This includes +;; helpful annotations such as documentation and other relevant +;; information, making it easier to choose the right option. +(use-package marginalia + :hook + (after-init . marginalia-mode)) + +;;; CONSULT +;; Consult provides powerful completion and narrowing commands for Emacs. +;; It integrates well with other completion frameworks like Vertico, enabling +;; features like previews and enhanced register management. It's useful for +;; navigating buffers, files, and xrefs with ease. +(use-package consult + :ensure t + :defer t + :init + ;; Enhance register preview with thin lines and no mode line. + (advice-add #'register-preview :override #'consult-register-window) + + ;; Use Consult for xref locations with a preview feature. + (setq xref-show-xrefs-function #'consult-xref + xref-show-definitions-function #'consult-xref) + + :bind (;; C-x bindings in `ctl-x-map' + ("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command + ("C-x b" . consult-buffer) ;; orig. switch-to-buffer + ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window + ("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame + ("C-x t b" . consult-buffer-other-tab) ;; orig. switch-to-buffer-other-tab + ("C-x r b" . consult-bookmark) ;; orig. bookmark-jump + ("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer + ;; Custom M-# bindings for fast register access + ("M-#" . consult-register-load) + ("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated) + ("C-M-#" . consult-register) + ;; Other custom bindings + ("M-y" . consult-yank-pop) ;; orig. yank-pop + ;; M-g bindings in `goto-map' + ("M-g e" . consult-compile-error) + ("M-g r" . consult-grep-match) + ("M-g f" . consult-flymake) ;; Alternative: consult-flycheck + ("M-g g" . consult-goto-line) ;; orig. goto-line + ("M-g M-g" . consult-goto-line) ;; orig. goto-line + ("M-g o" . consult-outline) ;; Alternative: consult-org-heading + ("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 in `search-map' + ("M-s d" . consult-find) ;; Alternative: consult-fd + ("M-s c" . 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) ;; orig. isearch-edit-string + ("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string + ("M-s l" . consult-line) ;; needed by consult-line to detect isearch + ("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch + ;; Minibuffer history + :map minibuffer-local-map + ("M-s" . consult-history) ;; orig. next-matching-history-element + ("M-r" . consult-history))) ;; orig. previous-matching-history-element + +(provide 'completion-config) diff --git a/dot_config/emacs/lisp/doom-quit.el b/dot_config/emacs/lisp/doom-quit.el new file mode 100644 index 0000000..009aff0 --- /dev/null +++ b/dot_config/emacs/lisp/doom-quit.el @@ -0,0 +1,62 @@ +(defvar +doom-quit-messages + `(;; from Doom 1 + "Please don't leave, there's more demons to toast!" + "Let's beat it -- This is turning into a bloodbath!" + ,(format "I wouldn't leave if I were you. %s is much worse." + (if (featurep :system 'windows) "DOS" "UNIX")) + "Don't leave yet -- There's a demon around that corner!" + "Ya know, next time you come in here I'm gonna toast ya." + "Go ahead and leave. See if I care." + "Are you sure you want to quit this great editor?" + ;; from Doom 2 + ,(format "Don't go now, there's a dimensional shambler waiting at the %s prompt!" + (if (featurep :system 'windows) "DOS" "UNIX")) + "Get outta here and go back to your boring operating system." + "Look, bud. You leave now and you forfeit your body count!" + "Just leave. When you come back, I'll be waiting with a bat." + "You're lucky I don't smack you for thinking about leaving." + ;; from Portal + "Thank you for participating in this Aperture Science computer-aided enrichment activity." + "You can't fire me, I quit!" + "I don't know what you think you are doing, but I don't like it. I want you to stop." + "This isn't brave. It's murder. What did I ever do to you?" + "I'm the man who's going to burn your house down! With the lemons!" + "Okay, look. We've both said a lot of things you're going to regret..." + ;; Custom + "(setq nothing t everything 'permitted)" + "Emacs will remember that." + "Emacs, Emacs never changes." + "Hey! Hey, M-x listen!" + "It's not like I'll miss you or anything, b-baka!" + "Wake up, Mr. Stallman. Wake up and smell the ashes." + "You are *not* prepared!" + "Please don't go. The drones need you. They look up to you." + "Don't forget, you're here forever.") + "A list of quit messages, picked randomly by `+doom-quit'. Taken from +http://doom.wikia.com/wiki/Quit_messages and elsewhere.") + +(defun +doom-quit-fn (&rest _) + (doom-quit-p + (format "%s %s" + (propertize (nth (random (length +doom-quit-messages)) + +doom-quit-messages) + 'face '(italic default)) + "Really quit Emacs?"))) + + +(defun doom-quit-p (&optional prompt) + (if use-dialog-box + (x-popup-dialog + t `("Really quit Emacs?" + ("Yes" . t) + ("Cancel" . nil))) + (let ((confirmed (y-or-n-p (format "%s" (or prompt "Really quit Emacs?"))))) + (if confirmed + t + (progn + (message "Aborted") + nil))))) + +(setq confirm-kill-emacs #'+doom-quit-fn) + +(provide 'doom-quit) diff --git a/dot_config/emacs/lisp/editing-config.el b/dot_config/emacs/lisp/editing-config.el new file mode 100644 index 0000000..3df8a99 --- /dev/null +++ b/dot_config/emacs/lisp/editing-config.el @@ -0,0 +1,41 @@ +(use-package expreg + :bind + ("C-=" . expreg-expand) + :config + (defvar expreg-repeat-map + (let ((map (make-sparse-keymap))) + (define-key map "=" #'expreg-expand) + (define-key map "-" #'expreg-contract) + map)) + (put 'expreg-expand 'repeat-map 'expreg-repeat-map) + (put 'expreg-contract 'repeat-map 'expreg-repeat-map)) + +(use-package surround + :ensure t + :bind-keymap ("M-'" . surround-keymap)) + +(use-package easy-kill + :config + (global-set-key [remap kill-ring-save] 'easy-kill) + (global-set-key [remap mark-sexp] 'easy-mark)) + +(use-package devil + :config + (global-devil-mode 1)) + +(use-package ace-window + :config + (global-set-key (kbd "s-w") 'ace-window) + (global-set-key [remap other-window] 'ace-window)) + +(use-package vundo + :bind (("C-x u" . vundo))) + +(use-package multiple-cursors + :ensure t + :bind (("C-c g" . mc/mark-all-dwim) + ("C->" . mc/mark-next-like-this) + ("C-<" . mc/mark-previous-like-this) + ("M-" . mc/add-cursor-on-click))) + +(provide 'editing-config) diff --git a/dot_config/emacs/lisp/elfeed-config.el b/dot_config/emacs/lisp/elfeed-config.el new file mode 100644 index 0000000..9d93327 --- /dev/null +++ b/dot_config/emacs/lisp/elfeed-config.el @@ -0,0 +1,32 @@ +(use-package elfeed + :defer t + :custom + (elfeed-use-curl t) + (elfeed-db-directory "~/.config/emacs/elfeed") + + :config + ;; Mark all YouTube entries + (defun browse-url-mpv (url &optional _new-window) + (start-process "mpv" nil "mpv" url)) + + (setq browse-url-browser-function + '(("https://\\(www\\.\\)?youtu\\(\\.be\\|be\\.com\\)" . browse-url-mpv) + ("." . browse-url-default-browser))) + (add-hook 'elfeed-new-entry-hook + (elfeed-make-tagger :feed-url "youtube\\.com" + :add '(video youtube))) + :bind + ("C-c e" . elfeed)) + +(use-package elfeed-protocol + :ensure t + :after elfeed + :config + (setq elfeed-feeds nil) + (setq elfeed-use-curl t) + (setq elfeed-feeds '(("fever+https://sakamoto@rss.sakamoto.network" + :api-url "https://rss.sakamoto.network/fever/" + :password (password-store-get "rss")))) + (elfeed-protocol-enable)) + +(provide 'elfeed-config) diff --git a/dot_config/emacs/lisp/emacs-config.el b/dot_config/emacs/lisp/emacs-config.el new file mode 100644 index 0000000..bfc15ee --- /dev/null +++ b/dot_config/emacs/lisp/emacs-config.el @@ -0,0 +1,280 @@ +(use-package emacs + :ensure nil + :custom + (user-mail-address "me@sakamoto.network") + (user-full-name "Sakamoto") + (mml-secure-openpgp-sign-with-sender t) + (message-sendmail-envelope-from 'header) + (auto-save-default nil) ;; Disable automatic saving of buffers. + (column-number-mode t) ;; Display the column number in the mode line. + (create-lockfiles nil) ;; Prevent the creation of lock files when editing. + (delete-by-moving-to-trash t) ;; Move deleted files to the trash instead of permanently deleting them. + (delete-selection-mode 1) ;; Enable replacing selected text with typed text. + (display-line-numbers-type 'relative) ;; Use relative line numbering in programming modes. + (global-auto-revert-non-file-buffers t) ;; Automatically refresh non-file buffers. + (history-length 100) ;; Set the length of the command history. + (indent-tabs-mode nil) ;; Disable the use of tabs for indentation (use spaces instead). + (inhibit-startup-message t) ;; Disable the startup message when Emacs launches. + (initial-scratch-message "") ;; Clear the initial message in the *scratch* buffer. + (ispell-program-name "hunspell") + (ispell-dictionary "en_US") + (shr-use-colors nil) + (blink-cursor-mode nil) + (make-backup-files nil) ;; Disable creation of backup files. + (pixel-scroll-precision-mode t) ;; Enable precise pixel scrolling. + (pixel-scroll-precision-use-momentum nil) ;; Disable momentum scrolling for pixel precision. + (fill-column 80) ;; Set column fill + (ring-bell-function 'ignore) ;; Disable the audible bell. + (split-width-threshold 300) ;; Prevent automatic window splitting if the window width exceeds 300 pixels. + (switch-to-buffer-obey-display-actions t) ;; Make buffer switching respect display actions. + (tab-always-indent 'complete) ;; Make the TAB key complete text instead of just indenting. + (tab-width 4) ;; Set the tab width to 4 spaces. + (treesit-font-lock-level 4) ;; Use advanced font locking for Treesit mode. + (truncate-lines t) ;; Enable line truncation to avoid wrapping long lines. + (global-visual-line-mode 1) ;; Soft wrap text + (global-visual-wrap-prefix-mode t) + (use-dialog-box nil) ;; Disable dialog boxes in favor of minibuffer prompts. + (use-short-answers t) ;; Use short answers in prompts for quicker responses (y instead of yes) + (warning-minimum-level :emergency) ;; Set the minimum level of warnings to display. + (help-window-select t) + (repeat-mode 1) + (scroll-conservatively 101) + (epg-pinentry-mode 'loopback) + (view-read-only t) ;; Enter view mode on read-only files + (imenu-auto-rescan t) ;; Automatically update imenu entries based on current buffer/file + (minibuffer-visible-completions t) ;; Use arrow keys to select completion candidates + + :hook ;; Add hooks to enable specific features in certain modes. + (prog-mode . display-line-numbers-mode) ;; Enable line numbers in programming modes. + (text-mode . display-line-numbers-mode) + + :config + ;; By default emacs gives you access to a lot of *special* buffers, while navigating with [b and ]b, + ;; this might be confusing for newcomers. This settings make sure ]b and [b will always load a + ;; file buffer. To see all buffers use SPC, b l, or b i. + (defun skip-these-buffers (_window buffer _bury-or-kill) + "Function for `switch-to-prev-buffer-skip'." + (string-match "\\*[^*]+\\*" (buffer-name buffer))) + (setq switch-to-prev-buffer-skip 'skip-these-buffers) + + (set-face-attribute 'default nil :family "Departure Mono" :height 120) + + ;; Save manual customizations to a separate file instead of cluttering `init.el'. + ;; You can M-x customize, M-x customize-group, or M-x customize-themes, etc. + ;; The saves you do manually using the Emacs interface would overwrite this file. + ;; The following makes sure those customizations are in a separate file. + (setq custom-file (locate-user-emacs-file "custom-vars.el")) ;; Specify the custom file path. + (load custom-file 'noerror 'nomessage) ;; Load the custom file quietly, ignoring errors. + + ;; Makes Emacs vertical divisor the symbol │ instead of |. + (set-display-table-slot standard-display-table 'vertical-border (make-glyph-code ?│)) + + :init ;; Initialization settings that apply before the package is loaded. + (tool-bar-mode -1) ;; Disable the tool bar for a cleaner interface. + (menu-bar-mode -1) ;; Disable the menu bar for a more streamlined look. + + (when scroll-bar-mode + (scroll-bar-mode -1)) ;; Disable the scroll bar if it is active. + + (global-auto-revert-mode 1) ;; Enable global auto-revert mode to keep buffers up to date with their corresponding files. + (recentf-mode 1) ;; Enable tracking of recently opened files. + + (setq history-delete-duplicates t) + (savehist-mode 1) ;; Enable saving of command history. + + (save-place-mode 1) ;; Enable saving the place in files for easier return. + (winner-mode 1) ;; Enable winner mode to easily undo window configuration changes. + (xterm-mouse-mode 1) ;; Enable mouse support in terminal mode. + (file-name-shadow-mode 1) ;; Enable shadowing of filenames for clarity. + + (auth-source-pass-enable) ;; Use password-store instead of authinfo + + (midnight-mode 1) ;; Cleanup every 3 days + + ;; Set the default coding system for files to UTF-8. + (modify-coding-system-alist 'file "" 'utf-8)) + +(use-package windmove + :ensure nil + :init + (windmove-default-keybindings 'meta)) + +(use-package window + :ensure nil ;; This is built-in, no need to fetch it. + :custom + (display-buffer-alist + '( + ;; ("\\*.*e?shell\\*" + ;; (display-buffer-in-side-window) + ;; (window-height . 0.25) + ;; (side . bottom) + ;; (slot . -1)) + + ("\\*\\(Backtrace\\|Warnings\\|Compile-Log\\|[Hh]elp\\|Messages\\|Bookmark List\\|Ibuffer\\|Occur\\|eldoc.*\\)\\*" + (display-buffer-in-side-window) + (window-height . 0.25) + (side . bottom) + (slot . 0)) + + ;; Example configuration for the LSP help buffer, + ;; keeps it always on bottom using 25% of the available space: + ("\\*\\(lsp-help\\)\\*" + (display-buffer-in-side-window) + (window-height . 0.25) + (side . bottom) + (slot . 0)) + + ;; Configuration for displaying various diagnostic buffers on + ;; bottom 25%: + ("\\*\\(Flymake diagnostics\\|xref\\|ivy\\|Swiper\\|Completions\\)" + (display-buffer-in-side-window) + (window-height . 0.25) + (side . bottom) + (slot . 1)) + ))) + +(use-package ibuffer + :ensure nil + :bind ([remap list-buffers] . ibuffer)) + +(use-package dired + :ensure nil ;; This is built-in, no need to fetch it. + :bind + (:map dired-mode-map ("." . dired-omit-mode)) + :hook + (dired-mode . dired-omit-mode) + :init + (with-eval-after-load 'dired (require 'dired-x)) + :custom + (dired-omit-files "^\\.[a-zA-Z0-9]+") + (dired-listing-switches "-lah --group-directories-first") ;; Display files in a human-readable format and group directories first. + (dired-guess-shell-alist-user + '(("\\.\\(mp[34]\\|m4a\\|ogg\\|flac\\|webm\\|mkv\\)" "mpv --really-quiet" "xdg-open" "open") ;; Open audio and video files with `mpv'. + (".*" "open" "xdg-open"))) + (dired-dwim-target t) ;; Enable "do what I mean" for target directories. + (dired-kill-when-opening-new-dired-buffer t) ;; Close the previous buffer when opening a new `dired' instance. + (dired-auto-revert-buffer t) + (dired-mouse-drag-files t) + :config + (when (eq system-type 'darwin) + (let ((gls (executable-find "gls"))) ;; Use GNU ls on macOS if available. + (when gls + (setq insert-directory-program gls))))) + +(use-package isearch + :ensure nil ;; This is built-in, no need to fetch it. + :config + (setq isearch-lazy-count t) ;; Enable lazy counting to show current match information. + (setq lazy-count-prefix-format "(%s/%s) ") ;; Format for displaying current match count. + (setq lazy-count-suffix-format nil) ;; Disable suffix formatting for match count. + (setq search-whitespace-regexp ".*?") ;; Allow searching across whitespace. + :bind (("C-s" . isearch-forward) ;; Bind C-s to forward isearch. + ("C-r" . isearch-backward))) ;; Bind C-r to backward isearch. + +(use-package dictionary + :ensure nil + :bind (("C-c L" . dictionary-lookup-definition)) + :config + (setq dictionary-server "dict.org")) + +(use-package whitespace + :init + (dolist (hook '(text-mode-hook)) + (add-hook hook #'whitespace-mode)) + (add-hook 'before-save-hook #'whitespace-cleanup) + :config + (setq whitespace-line-column 80) ;; limit line length + (setq whitespace-style '(face tabs empty trailing))) + +(use-package eldoc + :ensure nil ;; This is built-in, no need to fetch it. + :config + (setq eldoc-idle-delay 0) ;; Automatically fetch doc help + (setq eldoc-echo-area-use-multiline-p nil) ;; We use the "K" floating help instead + ;; set to t if you want docs on the echo area + (setq eldoc-echo-area-display-truncation-message nil) + :init + (global-eldoc-mode)) + +(use-package completion-preview + :ensure nil + :hook (after-init . global-completion-preview-mode) + :bind + ( :map completion-preview-active-mode-map + ("M-n" . completion-preview-next-candidate) + ("M-p" . completion-preview-prev-candidate) + ("M-" . completion-preview-insert) + ("" . completion-preview-complete)) + :custom + (completion-preview-minimum-symbol-length 2) ; Show the preview already after two symbol characters + (completion-preview-exact-match-only nil) ; If t, only show suggestion if there is only one candidate + (completion-preview-idle-delay 0.3) ; If non-nil, wait this many idle seconds before displaying preview + + :config + (with-eval-after-load 'org + ;; Add Org mode's custom 'self-insert-command' to completion-previews + (push 'org-self-insert-command completion-preview-commands) + ) + ;; Disable completion preview in Org tables (Emacs 31+) + (defun my/detect-org-table () + "Return true if point in Org table." + (and (derived-mode-p 'org-mode) (org-at-table-p))) + (add-hook 'completion-preview-inhibit-functions + #'my/detect-org-table)) + +(use-package tramp + :ensure nil + :commands (sudo-find-file sudo-this-file) + :bind ("C-c f s" . sudo-find-file) + :config + (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 sudoedit () + "Open the current file as root." + (interactive) + (sudo-find-file (file-truename buffer-file-name))) + (setq remote-file-name-inhibit-locks t + remote-file-name-inhibit-auto-save-visited t + tramp-copy-size-limit (* 1024 1024)) + (connection-local-set-profile-variables + 'remote-direct-async-process '((tramp-direct-async-process . t))) + (connection-local-set-profiles + '(:application tramp :protocol "scp") 'remote-direct-async-process) + (with-eval-after-load 'compile + (remove-hook 'compilation-mode-hook + #'tramp-compile-disable-ssh-controlmaster-options))) + +(use-package project + :ensure nil + :config + (setq project-vc-extra-root-markers '(".project"))) + +(use-package proced + :ensure nil + :custom + (proced-auto-update-flag 'visible) + (proced-enable-color-flag t)) + +(use-package flyspell + :disabled ;; TODO: Remove on Emacs 31 + :ensure nil + :config + (flyspell-delay-use-timer t) + :hook + (text-mode . flyspell-mode) + (prog-mode . flyspell-prog-mode)) + +(use-package hippie-exp + :ensure nil + :bind ([remap dabbrev-expand] . hippie-expand)) + +(provide 'emacs-config) diff --git a/dot_config/emacs/lisp/email-config.el b/dot_config/emacs/lisp/email-config.el new file mode 100644 index 0000000..23ad16f --- /dev/null +++ b/dot_config/emacs/lisp/email-config.el @@ -0,0 +1,3 @@ +(use-package notmuch) + +(provide 'email-config) diff --git a/dot_config/emacs/lisp/embark-config.el b/dot_config/emacs/lisp/embark-config.el new file mode 100644 index 0000000..5d39e9d --- /dev/null +++ b/dot_config/emacs/lisp/embark-config.el @@ -0,0 +1,11 @@ +(use-package embark + :ensure t + :bind + (("C-." . embark-act) ;; Pick a target and choose an action + ("M-." . embark-dwim))) ;; "Do What I Mean" default action + +(use-package embark-consult + :ensure t + :after (embark consult)) + +(provide 'embark-config) diff --git a/dot_config/emacs/lisp/evil-config.el b/dot_config/emacs/lisp/evil-config.el new file mode 100644 index 0000000..0be0cc6 --- /dev/null +++ b/dot_config/emacs/lisp/evil-config.el @@ -0,0 +1,132 @@ +;; EVIL +;; The `evil' package provides Vim emulation within Emacs, allowing +;; users to edit text in a modal way, similar to how Vim +;; operates. This setup configures `evil-mode' to enhance the editing +;; experience. +(use-package evil + :straight t + :ensure t + :defer t + :hook + (after-init . evil-mode) + :init + (setq evil-want-integration t) ;; Integrate `evil' with other Emacs features (optional as it's true by default). + (setq evil-want-keybinding nil) ;; Disable default keybinding to set custom ones. + (setq evil-want-C-u-scroll t) ;; Makes C-u scroll + (setq evil-want-C-u-delete t) ;; Makes C-u delete on insert mode + :config + (setq evil-want-fine-undo t) ;; Evil uses finer grain undoing steps + + ;; Keybindings for searching and finding files. + (evil-define-key 'normal 'global (kbd "C-c s f") 'consult-find) + (evil-define-key 'normal 'global (kbd "C-c s g") 'consult-grep) + (evil-define-key 'normal 'global (kbd "C-c s G") 'consult-git-grep) + (evil-define-key 'normal 'global (kbd "C-c s r") 'consult-ripgrep) + (evil-define-key 'normal 'global (kbd "C-c s h") 'consult-info) + (evil-define-key 'normal 'global (kbd "C-c /") 'consult-line) + + ;; Flymake navigation + (evil-define-key 'normal 'global (kbd "C-c x x") 'consult-flymake);; Gives you something like `trouble.nvim' + (evil-define-key 'normal 'global (kbd "] d") 'flymake-goto-next-error) ;; Go to next Flymake error + (evil-define-key 'normal 'global (kbd "[ d") 'flymake-goto-prev-error) ;; Go to previous Flymake error + + ;; Diff-HL navigation for version control + (evil-define-key 'normal 'global (kbd "] c") 'diff-hl-next-hunk) ;; Next diff hunk + (evil-define-key 'normal 'global (kbd "[ c") 'diff-hl-previous-hunk) ;; Previous diff hunk + + ;; Magit keybindings for Git integration + (evil-define-key 'normal 'global (kbd "C-c g g") 'magit-status) ;; Open Magit status + (evil-define-key 'normal 'global (kbd "C-c g l") 'magit-log-current) ;; Show current log + (evil-define-key 'normal 'global (kbd "C-c g d") 'magit-diff-buffer-file) ;; Show diff for the current file + (evil-define-key 'normal 'global (kbd "C-c g D") 'diff-hl-show-hunk) ;; Show diff for a hunk + (evil-define-key 'normal 'global (kbd "C-c g b") 'vc-annotate) ;; Annotate buffer with version control info + + ;; Buffer management keybindings + (evil-define-key 'normal 'global (kbd "] b") 'switch-to-next-buffer) ;; Switch to next buffer + (evil-define-key 'normal 'global (kbd "[ b") 'switch-to-prev-buffer) ;; Switch to previous buffer + (evil-define-key 'normal 'global (kbd "C-c b i") 'consult-buffer) ;; Open consult buffer list + (evil-define-key 'normal 'global (kbd "C-c b b") 'ibuffer) ;; Open Ibuffer + (evil-define-key 'normal 'global (kbd "C-c SPC") 'consult-buffer) ;; Consult buffer + + ;; Yank from kill ring + (evil-define-key 'normal 'global (kbd "P") 'consult-yank-from-kill-ring) + (evil-define-key 'normal 'global (kbd "C-c P") 'consult-yank-from-kill-ring) + + ;; Tab navigation + (evil-define-key 'normal 'global (kbd "] t") 'tab-next) ;; Go to next tab + (evil-define-key 'normal 'global (kbd "[ t") 'tab-previous) ;; Go to previous tab + + ;; LSP commands keybindings + (evil-define-key 'normal lsp-mode-map + ;; (kbd "gd") 'lsp-find-definition ;; evil-collection already provides gd + (kbd "gr") 'lsp-find-references ;; Finds LSP references + (kbd "C-c c a") 'lsp-execute-code-action ;; Execute code actions + (kbd "C-c r n") 'lsp-rename ;; Rename symbol + (kbd "gI") 'lsp-find-implementation ;; Find implementation + (kbd "C-c l f") 'lsp-format-buffer) ;; Format buffer via lsp + + (evil-define-key 'normal 'global (kbd "K") + #'eldoc-box-help-at-point) + + ;; Enable evil mode + (evil-mode 1)) + + +;; EVIL COLLECTION +;; The `evil-collection' package enhances the integration of +;; `evil-mode' with various built-in and third-party packages. It +;; provides a better modal experience by remapping keybindings and +;; commands to fit the `evil' style. +(use-package evil-collection + :straight t + :defer t + :ensure t + :custom + (evil-collection-want-find-usages-bindings t) + ;; Hook to initialize `evil-collection' when `evil-mode' is activated. + ;; :hook + ;; (evil-mode . evil-collection-init)) + ) + +;; EVIL SURROUND +;; The `evil-surround' package provides text object surround +;; functionality for `evil-mode'. This allows for easily adding, +;; changing, or deleting surrounding characters such as parentheses, +;; quotes, and more. +;; +;; With this you can change 'hello there' with ci'" to have +;; "hello there" and cs"

to get

hello there

. +;; More examples here: +;; - https://github.com/emacs-evil/evil-surround?tab=readme-ov-file#examples +(use-package evil-surround + :straight t + :ensure t + :after evil-collection + :config + (global-evil-surround-mode 1)) + +;; EVIL MATCHIT +;; The `evil-matchit' package extends `evil-mode' by enabling +;; text object matching for structures such as parentheses, HTML +;; tags, and other paired delimiters. This makes it easier to +;; navigate and manipulate code blocks. +;; Just use % for jumping between matching structures to check it out. +(use-package evil-matchit + :ensure t + :after evil-collection + :config + (global-evil-matchit-mode 1)) + +(use-package evil-keypad + :straight t + :ensure t + :after evil + :config + (evil-keypad-global-mode 1)) + +(use-package evil-goggles + :ensure t + :config + (evil-goggles-mode)) + +(provide 'evil-config) diff --git a/dot_config/emacs/lisp/git-config.el b/dot_config/emacs/lisp/git-config.el new file mode 100644 index 0000000..6ea08a9 --- /dev/null +++ b/dot_config/emacs/lisp/git-config.el @@ -0,0 +1,24 @@ +(use-package magit + :ensure t + :hook ((git-commit-mode . flyspell-mode) + (git-commit-mode . magit-git-commit-insert-branch)) + :bind ( :map project-prefix-map + ("g" . magit-project-status))) + +(use-package diff-hl + :defer t + :ensure t + :hook + (find-file . (lambda () + (global-diff-hl-mode) ;; Enable Diff-HL mode for all files. + (diff-hl-flydiff-mode) ;; Automatically refresh diffs. + (diff-hl-margin-mode))) ;; Show diff indicators in the margin. + :custom + (diff-hl-side 'left) ;; Set the side for diff indicators. + (diff-hl-margin-symbols-alist '((insert . "┃") ;; Customize symbols for each change type. + (delete . "-") + (change . "┃") + (unknown . "┆") + (ignored . "i")))) + +(provide 'git-config) diff --git a/dot_config/emacs/lisp/gptel-config.el b/dot_config/emacs/lisp/gptel-config.el new file mode 100644 index 0000000..003b757 --- /dev/null +++ b/dot_config/emacs/lisp/gptel-config.el @@ -0,0 +1,24 @@ +(use-package gptel + :defer t + :bind (("C-c C-" . gptel-menu) + ("C-c " . gptel-send) + ("C-c M-j" . gptel) + ("C-c C-g" . gptel-abort)) + :config + (setq gptel--nanogpt (gptel-make-openai "NanoGPT" + :stream t + :host "nano-gpt.com" + :endpoint "/api/v1/chat/completions" + :key gptel-api-key + :models '())) + (setq gptel-model-updater-backends + '(gptel--nanogpt)) + + (gptel-model-updater-update-all) + (sleep-for 2)) ;; TODO: terrible fix + +(use-package gptel-model-updater + :defer t + :vc (:url "https://github.com/chuxubank/gptel-model-updater")) + +(provide 'gptel-config) diff --git a/dot_config/emacs/lisp/irc-config.el b/dot_config/emacs/lisp/irc-config.el new file mode 100644 index 0000000..0a1e406 --- /dev/null +++ b/dot_config/emacs/lisp/irc-config.el @@ -0,0 +1,35 @@ +(use-package clatter + :defer t + :commands clatter-connect + :bind (:map clatter-mode-map + ("C-c ." . clatter-track-switch) + ("C-c C-." . clatter-track-switch) + ("C-c :" . clatter-track-list) + ("C-c n" . clatter-nicklist-toggle) + ("C-c C-n" . clatter-nicklist-toggle)) + :config + ;; Install cleanup hooks and enable the bundled extras. Required: + ;; loading clatter alone has no side effects. + (clatter-setup) + ;; Ensure GnuTLS is loaded before connecting. + (require 'gnutls) + :custom + (clatter-track-in-buffer-mode-line t) + (clatter-message-order 'oldest-first) + ;; (clatter-timestamp-format "%H:%M:%S") + (clatter-networks + `(("Sakamoto" + :server "irc.sakamoto.network" + :nick "sayit" + :username "anon/irc.libera.chat" + :sasl plain + :bouncer t + ) + ("localhost" + :server "localhost" + :tls nil + :port 6667) + )) + (clatter-use-auth-source t)) + +(provide 'irc-config) diff --git a/dot_config/emacs/lisp/lsp-mode-config.el b/dot_config/emacs/lisp/lsp-mode-config.el new file mode 100644 index 0000000..cc26d9c --- /dev/null +++ b/dot_config/emacs/lisp/lsp-mode-config.el @@ -0,0 +1,169 @@ +;; (use-package lsp-mode +;; :init +;; ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l") +;; (setq lsp-keymap-prefix "C-c l") +;; :hook +;; ((lsp-mode . lsp-enable-which-key-integration) +;; (prog-mode . lsp-deferred)) +;; :commands lsp +;; :custom +;; (lsp-keymap-prefix "C-c l") ;; Set the prefix for LSP commands. +;; (lsp-inlay-hint-enable t) ;; Usage of inlay hints. +;; (lsp-session-file (locate-user-emacs-file ".lsp-session")) ;; Specify session file location. +;; (lsp-log-io nil) ;; Disable IO logging for speed. +;; (lsp-idle-delay 0.5) ;; Set the delay for LSP to 0 (debouncing). +;; (lsp-keep-workspace-alive nil) ;; Disable keeping the workspace alive. +;; ;; Core settings +;; (lsp-enable-xref t) ;; Enable cross-references. +;; (lsp-auto-configure t) ;; Automatically configure LSP. +;; (lsp-enable-links nil) ;; Disable links. +;; (lsp-eldoc-enable-hover t) ;; Enable ElDoc hover. +;; (lsp-enable-file-watchers nil) ;; Disable file watchers. +;; (lsp-enable-folding nil) ;; Disable folding. +;; (lsp-enable-imenu t) ;; Enable Imenu support. +;; (lsp-enable-indentation nil) ;; Disable indentation. +;; (lsp-enable-on-type-formatting nil) ;; Disable on-type formatting. +;; (lsp-enable-suggest-server-download t) ;; Enable server download suggestion. +;; (lsp-enable-symbol-highlighting t) ;; Enable symbol highlighting. +;; (lsp-enable-text-document-color t) ;; Enable text document color. +;; (lsp-warn-no-matched-clients nil) ;; Disable warning when there are no supported clients. +;; ;; Modeline settings +;; (lsp-modeline-code-actions-enable nil) ;; Keep modeline clean. +;; (lsp-modeline-diagnostics-enable nil) ;; Use `flymake' instead. +;; (lsp-modeline-workspace-status-enable t) ;; Display "LSP" in the modeline when enabled. +;; (lsp-signature-doc-lines 1) ;; Limit echo area to one line. +;; (lsp-eldoc-render-all t) ;; Render all ElDoc messages. +;; ;; Completion settings +;; (lsp-completion-enable t) ;; Enable completion. +;; (lsp-completion-enable-additional-text-edit t) ;; Enable additional text edits for completions. +;; (lsp-enable-snippet t) ;; Disable snippets +;; (lsp-completion-show-kind t) ;; Show kind in completions. +;; ;; Lens settings +;; (lsp-lens-enable t) ;; Enable lens support. +;; ;; Headerline settings +;; (lsp-headerline-breadcrumb-enable-symbol-numbers t) ;; Enable symbol numbers in the headerline. +;; (lsp-headerline-arrow "▶") ;; Set arrow for headerline. +;; (lsp-headerline-breadcrumb-enable-diagnostics nil) ;; Disable diagnostics in headerline. +;; (lsp-headerline-breadcrumb-icons-enable nil) ;; Disable icons in breadcrumb. +;; ;; Semantic settings +;; (lsp-semantic-tokens-enable nil) +;; :config +;; (define-key lsp-mode-map (kbd "C-c l") lsp-command-map) +;; ) + +(use-package eldoc-box) + +(use-package eglot + :hook + ;; Automatically start Eglot for specific programming modes + ((prog-mode . eglot-ensure)) + :bind + ("C-c l a" . eglot-code-actions) + ("C-c l r" . eglot-rename) + ("C-c l h" . eldoc-box-help-at-point) + ("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 i" . eglot-find-implementation) + :custom + (eglot-autoshutdown t) + :config + ;; Configure rust-analyzer to use Clippy instead of Cargo Check + (setq-default eglot-workspace-configuration + '(:rust-analyzer + (:check + (:command "clippy"))))) + +(use-package corfu + :ensure t + :defer t + :custom + (corfu-auto nil) ;; Only completes when hitting TAB + (corfu-auto-delay 0) ;; Delay before popup (enable if corfu-auto is t) + (corfu-auto-prefix 1) ;; Trigger completion after typing 1 character + (corfu-quit-no-match t) ;; Quit popup if no match + (corfu-scroll-margin 5) ;; Margin when scrolling completions + (corfu-max-width 50) ;; Maximum width of completion popup + (corfu-min-width 50) ;; Minimum width of completion popup + (corfu-popupinfo-delay 0.5) ;; Delay before showing documentation popup + :init + (global-corfu-mode) + (corfu-popupinfo-mode t)) + + +(use-package yasnippet + :ensure t) + ;; :hook ((text-mode + ;; prog-mode + ;; conf-mode +;; snippet-mode) . yas-minor-mode)) + +(use-package yasnippet-capf + :after cape + :config + (add-to-list 'completion-at-point-functions #'yasnippet-capf) + (defun mi/eglot-capf-with-yasnippet () + (setq-local completion-at-point-functions + (list + (cape-capf-super + #'eglot-completion-at-point + #'yasnippet-capf)))) +(with-eval-after-load 'eglot + (add-hook 'eglot-managed-mode-hook #'mi/eglot-capf-with-yasnippet))) + +(use-package yasnippet-snippets) + +;; (use-package flycheck +;; :ensure t +;; :custom +;; (flycheck-display-errors-delay 0)) + +;; (use-package flycheck-inline +;; :hook +;; (flycheck-mode . flycheck-inline-mode)) + +(use-package rustic + :ensure t + :defer t + :init (setq rust-mode-treesitter-derive t) + :config + (setq rustic-lsp-client 'eglot) + (setq rustic-format-on-save t) + (setq rustic-rustfmt-args "--edition 2024") ;; should be a temporary fix + :custom + (rustic-cargo-use-last-stored-arguments t) + (rustic-babel-display-error-popup nil) + (rustic-lsp-setup-p nil) + (lsp-rust-analyzer-cargo-watch-command "clippy")) + +(use-package cape + :demand t + :init + ;; Add `completion-at-point-functions', used by `completion-at-point'. + (setq-default completion-at-point-functions + (append (default-value 'completion-at-point-functions) + (list #'cape-dabbrev #'cape-file #'cape-abbrev #'cape-emoji #'cape-history #'cape-tex)))) + +(use-package fennel-mode + :config + (with-eval-after-load 'org + (require 'ob-fennel))) + +;; DAP Mode +;; (use-package exec-path-from-shell +;; :ensure +;; :init (exec-path-from-shell-initialize)) + +;; (use-package dap-mode +;; :defer t +;; :ensure +;; :config +;; (dap-ui-mode) +;; (dap-ui-controls-mode 1) + +;; (require 'dap-lldb) +;; (require 'dap-gdb-lldb) +;; (dap-gdb-lldb-setup)) + +(provide 'lsp-mode-config) diff --git a/dot_config/emacs/lisp/meow-config.el b/dot_config/emacs/lisp/meow-config.el new file mode 100644 index 0000000..579e31c --- /dev/null +++ b/dot_config/emacs/lisp/meow-config.el @@ -0,0 +1,233 @@ +(use-package meow + :straight t + :init + (defun meow-setup () + (setq meow-use-clipboard select-enable-clipboard) + (setq meow-cheatsheet-layout meow-cheatsheet-layout-colemak-dh) + (meow-motion-define-key + ;; Use e to move up, n to move down. + ;; Since special modes usually use n to move down, we only overwrite e here. + '("e" . meow-prev) + '("" . ignore)) + (meow-leader-define-key + '("?" . meow-cheatsheet) + '("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) + '("f f" . find-file) + '("/" . consult-ripgrep) + '("f r" . consult-recent-file) + '("i" . consult-imenu) + '("f y" . my/yank-buffer-path) + + ;; Projects + '("SPC" . project-find-file) + '("p R" . project-query-replace-regexp) + ;; Window bindings + '("w v" . split-window-right) + '("w s" . split-window-below) + '("w d" . delete-window) + '("w v" . split-window-right) + '("w s" . split-window-below) + '("w d" . delete-window) + + ;; Buffer + '("," . consult-buffer) + '("b k" . (lambda () (interactive) (kill-buffer (current-buffer)))) + '("b l" . (lambda () (interactive) (switch-to-buffer nil))) + '("b b" . switch-to-buffer) + '("b n" . next-buffer) + '("b i" . ibuffer) + + ;; Bookmarks + '("b m" . bookmark-set) + '("b P" . bookmark-save) + '("b D" . bookmark-delete) + '("RET" . bookmark-jump) + '("o b" . browse-url-of-file) + + ;; Magit + '("g" . (lambda () (interactive) (require 'magit) (magit-status))) + + '("e e" . elfeed) + '("e u" . elfeed-update) + '("e a" . elfeed-add-feed)) + + ;; (meow-motion-define-key + ;; ;; Navigation + ;; '("W" . meow-next-word) + ;; '("^" . back-to-indentation) + ;; '("L" . (lambda () (interactive) (meow-line 1) (meow-reverse))) + ;; '("l" . meow-line) + ;; '("M" . meow-mark-symbol) + ;; '("v" . meow-search) + ;; '("V" . meow-visit) + ;; '("%" . expreg-expand) + ;; '("$" . expreg-contract) + + ;; '(";" . meow-reverse) + ;; '("[" . meow-beginning-of-thing) + ;; '("]" . meow-end-of-thing) + ;; '(":" . execute-extended-command) + ;; ;; Yank + ;; '("y" . meow-clipboard-save) + ;; '("g" . meow-cancel-selection) + ;; ;; Jump + ;; '("f" . flash-jump) + ;; '("/" . consult-line) + ;; '("" . ignore)) + + (meow-normal-define-key + '("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) + '("-" . negative-argument) + '(";" . meow-reverse) + '(":" . execute-extended-command) + '("," . meow-inner-of-thing) + '("." . meow-bounds-of-thing) + '("[" . meow-beginning-of-thing) + '("]" . meow-end-of-thing) + '("/" . meow-visit) + '("%" . expreg-expand) + '("$" . expreg-contract) + '("^" . back-to-indentation) + '("a" . meow-append) + '("A" . (lambda () (interactive) (end-of-line) (meow-insert))) + '("b" . meow-back-word) + '("B" . meow-back-symbol) + '("c" . meow-change) + '("C" . (lambda () (interactive) (meow-kill) (meow-insert))) + '("d" . meow-kill) + '("E" . meow-prev-expand) + '("f" . meow-find) + '("g" . meow-cancel-selection) + '("G" . meow-grab) + '("" . meow-left) + '("" . meow-right) + '("" . meow-prev) + '("" . meow-next) + '("H" . meow-left-expand) + '("i" . meow-insert) + '("I" . (lambda () (interactive) (beginning-of-line) (meow-insert))) + '("j" . meow-join) + '("K" . eldoc-box-help-at-point) + '("l" . meow-line) + '("L" . (lambda () (interactive) (meow-line 1) (meow-reverse))) + '("m" . meow-mark-word) + '("M" . meow-mark-symbol) + '("N" . meow-next-expand) + '("o" . meow-open-below) + '("O" . meow-open-above) + '("p" . meow-yank) + '("Q" . meow-quit) + '("r" . meow-replace) + '("R" . meow-swap-grab) + '("s" . meow-change-char) + '("S" . meow-pop-selection) + '("t" . meow-till) + '("u" . meow-undo) + '("U" . meow-undo-in-selection) + '("v" . meow-search) + '("V" . meow-visit) + '("w" . meow-next-word) + '("W" . meow-next-symbol) + '("x" . meow-delete) + '("X" . meow-backward-delete) + '("y" . meow-save) + '(">" . my/indent-right) + '("<" . my/indent-left) + + '("'" . repeat) + '("=" . indent-region) + '("" . ignore) + '("RET" . flash-jump)) + + + (setq meow-mode-state-list + '((dired-mode . motion) + (elfeed-search-mode . motion) + (org-mode . normal) + (elfeed-show-mode . motion) + (erc-mode . insert) + (vterm-mode . insert) + (ghostel-mode . insert) + (pdf-view-mode . motion) + (calibredb-search-mode . motion) + (dirvish-mode . motion) + (messages-buffer-mode . motion) + (help-mode . motion) + (info-mode . motion) + (occur-mode . motion) + (pass-mode . motion) + (grep-mode . motion) + (compilation-mode . motion) + (messages-buffer-mode . motion) + (special-mode . motion) + (notmuch-hello-mode . motion) + (notmuch-search-mode . motion) + (notmuch-tree-mode . motion) + (notmuch-show-mode . motion)))) + :config + (meow-thing-register 'angle '(regexp "<" ">") '(regexp "<" ">")) + (add-to-list 'meow-char-thing-table '(?a . angle)) + + (meow-setup) + (meow-global-mode 1)) + +(defun my/indent-right () + "Indent region or line right." + (interactive) + (if (use-region-p) + (indent-rigidly (region-beginning) (region-end) tab-width) + (indent-rigidly (line-beginning-position) (line-end-position) tab-width))) + +(defun my/indent-left () + "Indent region or line left." + (interactive) + (if (use-region-p) + (indent-rigidly (region-beginning) (region-end) (- tab-width)) + (indent-rigidly (line-beginning-position) (line-end-position) (- tab-width)))) + +(use-package repeat-fu + :straight t + :commands (repeat-fu-mode repeat-fu-execute) + + :config + (setq repeat-fu-preset 'meow) + + :hook + ((meow-mode) + . + (lambda () + (when (and (not (minibufferp)) (not (derived-mode-p 'special-mode))) + (repeat-fu-mode) + (define-key meow-normal-state-keymap (kbd "C-'") 'repeat-fu-execute) + (define-key meow-insert-state-keymap (kbd "C-'") 'repeat-fu-execute))))) + +(use-package expreg + :straight t) + +(use-package surround + :straight t + :ensure t + :bind-keymap ("M-'" . surround-keymap)) + +(use-package eldoc-box + :straight t) + +(provide 'meow-config) diff --git a/dot_config/emacs/lisp/org-demo-macro.el b/dot_config/emacs/lisp/org-demo-macro.el new file mode 100644 index 0000000..36f4100 --- /dev/null +++ b/dot_config/emacs/lisp/org-demo-macro.el @@ -0,0 +1,66 @@ +;;; Execute things in Org presentations +;; https://www.howardism.org/Technical/Emacs/demonstrations-part-two.html +(defun demo-match (triggers state) + "Return t if all elements of TRIGGERS are in STATE. +Where TRIGGERS and STATE are lists of key/value tuple +pairs, e.g. `((:a 1) (:b 2))'." + ;; If difference returns anything, we've failed: + (not (seq-difference triggers state))) + +(defvar demo-prev-state + (make-hash-table :test 'equal) + "Matched states in keys, and store number +of matches as values.") + +(defun demo-state-match (triggers state) + "Return non-nil if STATE contains all TRIGGERS. +The state also includes the number of times the triggers +matched during previous calls. We do this by keeping track +of the number of successful calls, and incrementing +the iteration... if this function returns non-nil." + ;; If the first element is either parameter is NOT a list, + ;; we group it into a list of tuples: + (when (not (listp (car triggers))) + (setq triggers (seq-partition triggers 2))) + (when (not (listp (car state))) + (setq state (seq-partition state 2))) + + (let* ((iteration (gethash state demo-prev-state 0)) + (itful-state (cons `(:i ,iteration) state))) + (when (demo-match triggers itful-state) + (puthash state (1+ iteration) demo-prev-state)))) + +(defmacro demo-step (&rest forms) + "Execute a function based matching list of states at point. +Where FORMS is an even number of _matcher_ and _function_ to call. + +Probably best to explain this in an example: + +(demo-step + (:buffer \"demonstrations.py\") (message \"In a buffer\") + (:mode 'dired-mode) (message \"In a dired\") + (:head \"Raven Civilizations\" (message \"In an org file\"))) + +Calling this function displays a message based on position of the +point in a particular buffer or place in a heading in an Org file. + +You can use the `:i' to specify different forms to call when +the trigger matches the first time, versus the second time, etc. + +(demo-step + (:buffer \"demonstrations.org\" :i 0) (message \"First time\") + (:buffer \"demonstrations.org\" :i 1) (message \"Second time\"))" + (interactive) + `(let ((state (list :buffer (buffer-name) + :mode major-mode + :head (when (eq major-mode 'org-mode) + (org-get-heading))))) + (cond + ,@(seq-map (lambda (tf-pair) + (seq-let (trigger func) tf-pair + (list + `(demo-state-match ',trigger state) + func))) + (seq-partition forms 2))))) + +(provide 'org-demo-macro) diff --git a/dot_config/emacs/lisp/org-mode-config.el b/dot_config/emacs/lisp/org-mode-config.el new file mode 100644 index 0000000..8bc324c --- /dev/null +++ b/dot_config/emacs/lisp/org-mode-config.el @@ -0,0 +1,165 @@ +;;; Org +(use-package org + :ensure nil ; do not try to install it as it is built-in + :commands (org-capture org-agenda) + :custom + (org-M-RET-may-split-line '((default . nil))) + (org-insert-heading-respect-content t) + (org-log-done 'time) + (org-log-into-drawer t) + (org-capture-bookmark nil) + + (org-directory "~/org/") + (org-default-notes-file (concat org-directory "agenda.org")) + (org-agenda-files (list org-directory)) + + ;; Learn about the ! and more by reading the relevant section of the + ;; Org manual. Evaluate: (info "(org) Tracking TODO state changes") + (org-todo-keywords '((sequence "TODO(t)" + "STARTED(s!)" + "NEXT(n)" + "SOMEDAY(.)" + "WAITING(w@)""|" "DONE(x!)" "CANCELLED(c@)"))) + (org-startup-indented t) + (org-pretty-entities t) + (org-startup-with-inline-images t) + (org-image-actual-width 300) + :config + (define-key org-mode-map (kbd "C-c C-r") verb-command-map) + + (setq org-anki-file (concat org-directory "anki.org")) + (setq org-capture-templates + `(("f" "Fleeting note" item + (file+headline org-default-notes-file "Notes") + "- %?") + ("o" "Quote" item + (file+headline ,(concat org-directory "quotes.org") "Quotes") + "- %?") + ("p" "Permanent note" plain + (file denote-last-path) + #'denote-org-capture + :no-save t + :immediate-finish nil + :kill-buffer t + :jump-to-captured nil) + ("t" "New task" entry + (file+headline org-default-notes-file "Tasks") + "* TODO %i%?") + ("j" "Journal" entry + (file denote-journal-path-to-new-or-existing-entry) + "* %U %?\n%i\n%a" + :kill-buffer t + :empty-lines 1) + ("a" "Anki basic" + entry + (file+headline org-anki-file "Dispatch Shelf") + "* Card%^g\n:PROPERTIES:\n:ANKI_NOTE_TYPE: Basic\n:ANKI_DECK: Mega\n:END:\n** Front\n%?\n** Back\n%c\n") + ("A" "Anki cloze" + entry + (file+headline org-anki-file "Dispatch Shelf") + "* Card%^g\n:PROPERTIES:\n:ANKI_NOTE_TYPE: Cloze\n:ANKI_DECK: Mega\n:END:\n** Text\n%c\n** Extra\n"))) + +(add-to-list 'org-export-backends 'md) +:bind +(("C-c C" . org-capture) + ("C-c A" . org-agenda))) + +(use-package org-modern + :ensure t + :defer t + :hook (org-mode . org-modern-mode) + :custom + (org-modern-star "replace")) + +(use-package denote + :after org + :init + (denote-rename-buffer-mode 1) + :custom + (denote-directory (concat org-directory "/notes/")) + :hook + (dired-mode . denote-dired-mode) + :config + ;; https://github.com/protesilaos/denote/issues/681 + (add-to-list 'denote-file-types + '(org-gpg + :extension ".org.gpg" + :front-matter denote-org-front-matter + :title-key-regexp "^#\\+title\\s-*:" + :title-value-function denote-format-string-for-org-front-matter + :title-value-reverse-function denote-trim-whitespace + :keywords-key-regexp "^#\\+filetags\\s-*:" + :keywords-value-function denote-format-keywords-for-org-front-matter + :keywords-value-reverse-function denote-extract-keywords-from-front-matter + :signature-key-regexp "^#\\+signature\\s-*:" + :signature-value-function denote-format-string-for-org-front-matter + :signature-value-reverse-function denote-trim-whitespace + :identifier-key-regexp "^#\\+identifier\\s-*:" + :