;;; $DOOMDIR/config.el -*- lexical-binding: t; -*- (load! "splash") (defun +splash-initial-buffer () (splash-screen) (get-buffer "*splash*")) (setq doom-fallback-buffer-name "*splash*" ; make the splash screen be un-killable initial-buffer-choice #'+splash-initial-buffer) ; appear on emacs startup (defadvice! +splash-regenerate-if-missing-a (&rest _) :before #'doom-fallback-buffer (unless (get-buffer "*splash*") (splash-screen))) (add-to-list 'custom-theme-load-path "~/.config/doom/extra-themes/") ;; (setq doom-theme 'modus-vivendi) ;; (setq doom-theme 'doric-oak) (setq doom-theme 'doric-obsidian) ;; (setq doom-theme 'tango) (setq custom-safe-themes t) (setq doom-font (font-spec :family "Berkeley Mono" :size 13.0)) (setq display-line-numbers-type t) ;; (use-package! mood-line ;; :config ;; (mood-line-mode) ;; :custom ;; (mood-line-glyph-alist mood-line-glyphs-fira-code)) (use-package! minions :config (minions-mode 1)) (defun my/split-window-dynamically () "Split the selected window, choosing orientation by its shape." (interactive) (select-window (if (> (window-total-width) (* 2 (window-total-height))) (split-window-right) (split-window-below)))) (map! :leader "w s" #'my/split-window-dynamically) (setq scroll-margin 3) (use-package! breadcrumb :defer t :hook (prog-mode . breadcrumb-mode) ;; make sure its in programming modes :config (breadcrumb-mode 1)) (setq +zen-mixed-pitch-modes '()) (use-package! vertico-carousel :config (vertico-carousel-mode 1)) (defun my/hs-eval () (interactive) (let* ((src (buffer-file-name)) (out (file-name-sans-extension src))) (when (zerop (call-process-shell-command (format "runghc %s" src) nil "*runghc-output*")) (let ((buf (make-comint "hs-run" out))) (display-buffer buf))))) (add-hook 'haskell-mode-hook (lambda () (local-set-key (kbd "") #'my/hs-eval))) (add-to-list 'major-mode-remap-alist '(html-mode . mhtml-ts-mode)) (add-to-list 'major-mode-remap-alist '(mhtml-mode . mhtml-ts-mode)) (add-to-list 'auto-mode-alist '("\\.html?\\'" . mhtml-ts-mode)) (add-to-list 'major-mode-remap-alist '(html-mode . mhtml-ts-mode)) (add-to-list 'major-mode-remap-alist '(mhtml-mode . mhtml-ts-mode)) (advice-add 'web-mode :around (lambda (orig &rest args) (if (or (null buffer-file-name) (string-match-p "\\.html?\\'" buffer-file-name)) (mhtml-ts-mode) (apply orig args)))) (use-package! eglot :hook (prog-mode . eglot-ensure)) (after! eglot (cl-defmethod eglot-register-capability ((_server eglot-lsp-server) (method (eql workspace/didChangeWatchedFiles)) _id &key _watchers) nil) (add-to-list 'eglot-server-programs '((typescript-ts-mode javascript-mode) . ("oxlint" "--lsp")))) (setq eglot-sync-connect nil eglot-connect-timeout 60) (after! flycheck (flycheck-define-checker htmlhint "htmlhint for flycheck" :command ("htmlhint" "--format" "unix" source) :error-patterns ((error line-start (file-name) ":" line ":" column ": " (message) line-end)) :modes (mhtml-ts-mode)) (add-to-list 'flycheck-checkers 'htmlhint) (flycheck-add-next-checker 'javascript-eslint 'javascript-oxlint) (flycheck-add-next-checker 'html-tidy 'htmlhint) (setq flycheck-check-syntax-automatically '(save mode-enabled))) (use-package! apheleia :hook (prog-mode . apheleia-mode) :config (setf (alist-get 'oxfmt apheleia-formatters) '("oxfmt" "--config=.oxfmtrc.json" "--stdin-filepath" filepath)) (dolist (mode '(mhtml-ts-mode html-mode mhtml-mode web-mode css-mode)) (setf (alist-get mode apheleia-mode-alist) 'oxfmt))) (add-hook 'mhtml-ts-mode-hook #'apheleia-mode) (setq auth-sources '("~/.authinfo.gpg")) (setq auth-source-cache-expiry nil) (setq gnus-permanently-visible-groups ".") (setq user-mail-address "hi@roughlynamed.net" ; my email user-full-name "Magdalena Szweda") ; my name (setq mml-secure-openpgp-signers '("B9CF59FE57835F89ECB33FD417CA809770F85511") mml-secure-openpgp-sign-with-sender t) (setq message-signature-file "~/.signature") ; note no trailing slash (evil-set-initial-state 'gnus-browse-mode 'emacs) (setq gnus-select-method '(nnimap "migadu" (nnimap-address "imap.migadu.com") (nnimap-server-port 993) (nnimap-stream ssl))) (setq smtpmail-smtp-server "smtp.migadu.com" smtpmail-smtp-service 465 ; port 465 smtpmail-stream-type 'ssl message-send-mail-function #'smtpmail-send-it ) (setq gnus-message-archive-method '(nnimap "migadu") ; use migadu for archiving email gnus-message-archive-group "Sent") ; where to put sent mail (setq gnus-large-newsgroup nil gnus-fetch-old-headers t nnmail-expiry-target "Trash") (setq gnus-thread-sort-functions '((not gnus-thread-sort-by-date))) (setq gnus-subthread-sort-functions '((not gnus-thread-sort-by-date))) (setq gnus-thread-sort-most-recent-first t) (setq gnus-always-read-dribble-file nil) (add-hook 'message-send-hook #'mml-secure-message-sign-pgpmime) (with-eval-after-load "mm-decode" (add-to-list 'mm-discouraged-alternatives "text/html") (add-to-list 'mm-discouraged-alternatives "text/richtext")) (map! :leader :prefix "o" :desc "Mail" "m" #'gnus) (use-package! jabber :config (setq jabber-account-list '( ;; ("roughlynamed@yax.im") ("wildebeest@yax.im"))) (jabber-modeline-mode 1) :hook (kill-emacs . jabber-disconnect)) (map! :leader :prefix "j" :desc "Connect" "c" #'jabber-connect-all :desc "Disconnect" "q" #'jabber-disconnect :desc "Dash" "f" #'jabber-roster :desc "Reply" "r" #'jabber-chat-reply :desc "New chat" "n" #'jabber-chat-with :desc "Set status" "s" #'jabber-send-presence) (add-to-list 'load-path "/home/hi/.config/doom/") (use-package! emms :commands (emms emms-browser emms-player-mpd-update-all emms-cache-set-from-mpd-all emms emms-pause emms-next emms-previous emms-stop emms-random emms-add-directory-tree emms-play-playlist) :init (map! :leader (:prefix ("e" . "emms") :desc "Browser" "b" #'emms-browser :desc "Emms" "e" #'emms :desc "Play/pause" "SPC" #'emms-pause :desc "Next" "n" #'emms-next :desc "Previous" "p" #'emms-previous :desc "Stop" "s" #'emms-stop :desc "Add" "a" #'emms-add-playlist :desc "Clear" "c" #'emms-playlist-clear)) :config (require 'emms-setup) (emms-all) (require 'emms-player-xmms2) (setq emms-player-list '(emms-player-xmms2) emms-lyrics-scroll-p nil emms-lyrics-display-on-minibuffer t emms-lyrics-display-on-modeline nil emms-player-mpd-music-directory "~/Music" emms-source-file-default-directory (expand-file-name "~/Music/playlists/") emms-repeat-playlist t emms-cache-file (concat doom-cache-dir "emms-cache")) (emms-mode-line-mode 1) (emms-playing-time-mode 1) (map! :map emms-browser-mode-map :n "RET" #'emms-browser-add-tracks-and-play)) (map! :leader :prefix "v" :desc "vc-edit-next-command" "!" #'vc-edit-next-command :desc "diff-hl-show-hunk" "*" #'diff-hl-show-hunk :desc "vc-update" "+" #'vc-update :desc "diff-hl-goto-hunk" "=" #'diff-hl-diff-goto-hunk :desc "vc-revert" "@" #'vc-revert :desc "vc-update-change-log" "a" #'vc-update-change-log ;; ADD b BINDINGS (branch) :desc "vc-dir" "d" #'vc-dir :desc "vc-root-diff" "D" #'vc-root-diff ;; ADD E BINDINGS :desc "annotate" "g" #'vc-annotate :desc "ignore" "G" #'vc-ignore :desc "region history" "h" #'vc-region-history :desc "register" "i" #'vc-register :desc "root log incoming" "I" #'vc-root-log-incoming :desc "print log" "l" #'vc-print-log :desc "print root log" "L" #'vc-print-root-log :desc "merge" "m" #'vc-merge ;; ADD M BINDINGS :desc "diff revert hunk" "n" #'diff-hl-revert-hunk :desc "root log outgoing" "O" #'vc-root-log-outgoing :desc "push" "p" #'vc-push ; originally P :desc "retrieve tag" "r" #'vc-retrieve-tag :desc "rename file" "R" #'vc-rename-file :desc "create tag" "s" #'vc-create-tag :desc "stage dwim (diff hl)" "S" #'diff-hl-stage-dwim ;; ADD T BINDINGS :desc "vc revert" "u" #'vc-revert ; carried over from the original bindings (repeated by @) :desc "vc next action" "v" #'vc-next-action ; run the next logical action ;; ADD w BINDINGS :desc "revision other window" "~" #'vc-revision-other-window) (use-package! vc-jj) (after! vc-jj (defvar my/vc-jj-advance-to nil) (defun my/vc-jj-bookmark-advance (&optional names) "Advance the closest bookmarks (or just NAMES) forward." (interactive (when current-prefix-arg (list (completing-read-multiple "Advance bookmarks: " (vc-jj--process-lines nil "bookmark" "list" "-T" "if(!self.remote(), self.name() ++ '\n')"))))) (with-temp-buffer (let ((status (apply #'vc-jj--call nil t "bookmark" "advance" (append (when my/vc-jj-advance-to (list "--to" my/vc-jj-advance-to)) names)))) (message "vc-jj: %s" (string-trim (buffer-string))) status))) (defun my/vc-jj--advance-before-push (&rest _) (my/vc-jj-bookmark-advance)) (advice-add 'vc-jj-push :before #'my/vc-jj--advance-before-push) (setq my/vc-jj-advance-to "@-") (defun my/vc-jj-checkin (files comment &optional _rev) "Describe @ and start a fresh change." (let ((default-directory (vc-jj-root (car files)))) (vc-jj-modify-change-comment nil "@" comment) (vc-jj--command-dispatched nil 0 nil "new" "--quiet"))) (advice-add 'vc-jj-checkin :override #'my/vc-jj-checkin)) (after! vc-jj (add-to-list 'display-buffer-alist '("\\`\\*vc-jj : " (display-buffer-no-window) (allow-no-window . t))) (defun my/vc-jj--report-push (&rest _) (when-let* ((root (vc-jj-root default-directory)) (buf (get-buffer (format "*vc-jj : %s*" (expand-file-name root)))) (proc (get-buffer-process buf))) (add-function :around (process-sentinel proc) (lambda (orig p event) (unwind-protect (funcall orig p event) (when (memq (process-status p) '(exit signal)) (if (zerop (process-exit-status p)) (message "vc-jj: push done") (message "vc-jj: push FAILED, output below") (let ((display-buffer-alist nil)) (pop-to-buffer buf))))))))) (defvar vc--inhibit-async-window) (defun my/vc-jj--push-no-window (orig &rest args) (let ((vc--inhibit-async-window t)) (apply orig args))) (advice-add 'vc-jj-push :around #'my/vc-jj--push-no-window) (advice-add 'vc-jj-push :after #'my/vc-jj--report-push) (define-advice ansi-color-filter-region (:around (fn &rest args) my/vc-jj-writable) (let ((inhibit-read-only (or inhibit-read-only (string-prefix-p "*vc-jj" (buffer-name))))) (apply fn args)))) (setq org-directory "~/org/") (setq org-agenda-files "~/org/todo.org") (after! org (setq org-startup-folded t ; fold headers on startup org-pretty-entities t org-hide-emphasis-markers t org-auto-align-tags nil org-tags-column 0 org-catch-invisible-edits 'show-and-error org-agenda-tags-column 0 org-capture-templates-contexts nil org-insert-heading-respect-content t org-special-ctrl-a/e t org-return-follows-link t org-confirm-babel-evaluate nil) (org-babel-do-load-languages 'org-babel-load-languages '((emacs-lisp . t) (python . t) (C . t) (lisp . t)))) (use-package! poly-org :hook (org-mode . poly-org-mode)) (add-hook 'org-src-mode-hook #'eglot-ensure) (setq org-element-use-cache nil) (add-hook 'org-capture-mode-hook #'delete-other-windows) (add-hook 'org-capture-mode-hook (lambda () (set-window-dedicated-p (selected-window) nil))) (after! org-roam (setq org-roam-directory (file-truename "~/org/")) (org-roam-db-autosync-mode) (defun my/org-roam-short-id () (let ((chars "abcdefghijklmnopqrstuvwxyz0123456789")) (apply #'string (cl-loop repeat 4 collect (aref chars (random (length chars))))))) (setq org-roam-capture-templates '(("d" "default" plain "* %?" :if-new (file+head (lambda () (concat (my/org-roam-short-id) ".org")) "#+TITLE: %^{title|Untitled}\n#+FILETAGS: :%^{tags}:\n\n") ; title&tags :unnarrowed t))) (cl-defmethod org-roam-node-file-stem ((node org-roam-node)) (file-name-base (org-roam-node-file node))) (setq org-roam-node-display-template (concat "${title:*} " (propertize "${file-stem}" 'face 'org-tag))) (setq org-roam-mode-sections '(org-roam-backlinks-section org-roam-reflinks-section org-roam-unlinked-references-section)) (defun my/org-roam-check-self-link () (when-let* ((node (org-roam-node-at-point)) (id (org-roam-node-id node))) (save-excursion (goto-char (point-min)) (while (re-search-forward org-link-any-re nil t) (when (string-match-p (regexp-quote id) (match-string 0)) (message "Warning: self-link detected")))))) (defun my/org-roam-check-dead-links () (dolist (link (org-roam-db-query [:select [dest] :from links :where (= source $s1)] (org-roam-id-at-point))) (unless (org-roam-db-query [:select id :from nodes :where (= id $s1)] (car link)) (message "Error: dead link to %s" (car link))))) (add-hook 'before-save-hook (lambda () (when (org-roam-file-p) (my/org-roam-check-self-link) (my/org-roam-check-dead-links))) nil t) (map! :leader :prefix ("n r" . "roam") :desc "Find node" "f" #'org-roam-node-find ; 'zk edit -i' equivalent :desc "Insert node" "i" #'org-roam-node-insert ; link a note :desc "Backlinks" "b" #'org-roam-buffer-toggle :desc "Capture" "c" #'org-roam-capture ; make a new note :desc "Graph" "g" #'org-roam-graph ; graph of every note :desc "Random node" "r" #'org-roam-node-random ; random node :desc "Open link" "o" #'org-open-at-point ; open linked note under cursor :desc "Jump back" "O" #'org-mark-ring-goto)) ; jump back to previous note after SPC n r o (with-eval-after-load 'ox-html (setq org-html-xml-declaration nil org-html-doctype "html5" org-html-html5-fancy t org-html-head-include-default-style nil org-html-postamble nil)) (use-package! websocket :after org-roam) (use-package! org-roam-ui :after org-roam :config (setq org-roam-ui-sync-theme t ; use emacs theme org-roam-ui-follow t org-roam-ui-update-on-save t ; update when a org roam file is saved )) (use-package! org-appear :hook (org-mode . org-appear-mode) :config (setq org-appear-autoemphasis t org-appear-autolinks t org-appear-autosubmarkers t org-appear-autoentities t)) (use-package! org-modern-indent :defer t :hook (org-mode . org-modern-indent-mode)) (setq eww-search-prefix "https://ecosia.org/search?q=") (setq eww-download-directory (expand-file-name "~/Downloads/")) (defun my-browse-url-mpv (url &rest _args) "Open URL in mpv." (start-process "mpv" nil "mpv" url)) (defun my-browse-url-pdf (url &rest _args) "Fetch remote PDF and open in pdf-tools within Emacs." (let ((tmp (make-temp-file "emacs-pdf-" nil ".pdf"))) (url-copy-file url tmp t) (find-file-other-window tmp) (pdf-view-mode))) (defun my/eww-download-image-at-point () (interactive) (let ((url (or (get-text-property (point) 'image-url) (get-text-property (point) 'shr-url)))) (if (not url) (message "No image at point") (let* ((filename (file-name-nondirectory (url-filename (url-generic-parse-url url)))) (dest (expand-file-name filename eww-download-directory))) (url-copy-file url dest t) (message "Saved: %s" dest))))) (setq browse-url-handlers '(("\\(youtube\\.com\\|youtu\\.be\\|vimeo\\.com\\|twitch\\.tv\\)" . my-browse-url-mpv) ("\\.mp4$" . my-browse-url-mpv) ("\\.pdf$" . my-browse-url-pdf) ("^gemini://" . elpher-browse-url-elpher) ("^gopher://" . elpher-browse-url-elpher) ("." . eww-browse-url))) (setq browse-url-secondary-browser-function 'browse-url-generic browse-url-generic-program "vivaldi") (setq shr-width 100) (setq shr-max-width 120) (setq shr-indentation 4) (setq shr-use-fonts nil) (setq shr-max-image-size '(800 . 600)) (setq shr-image-animate t) (add-hook 'eww-after-render-hook #'eww-readable) (with-eval-after-load 'eww (define-key eww-mode-map (kbd "=") #'text-scale-increase) (define-key eww-mode-map (kbd "-") #'text-scale-decrease) (define-key eww-mode-map (kbd "0") #'text-scale-adjust) (define-key eww-mode-map (kbd "b") #'eww-back-url) (define-key eww-mode-map (kbd "a") #'eww-add-bookmark) (define-key eww-mode-map (kbd "U") #'shr-copy-url) (define-key eww-mode-map (kbd "D") #'my/eww-download-image-at-point) (evil-define-key 'normal eww-mode-map "b" #'eww-back-url "a" #'eww-add-bookmark "U" #'shr-copy-url "D" #'my/eww-download-image-at-point)) (provide 'browser) (use-package! elpher) (map! :leader :prefix "o g" :desc "Elpher" "e" #'elpher :desc "Browse Elpher" "b" #'elpher-browse-url-elpher) (map! :leader :prefix "o" :desc "Woman" "w" #'woman) (map! :leader :prefix ("d" . "dired") :desc "Dired" "d" #'dired :desc "Dired here" "h" #'dired-jump) (use-package! eat :defer t) (map! :leader :prefix "o" :desc "Open Eat" "e" #'eat-other-window) ; dont steal the current window (use-package! nov :mode ("\\.epub\\'" . nov-mode) :config (setq nov-text-width 80 nov-variable-pitch t) (add-hook 'nov-mode-hook (lambda () (face-remap-add-relative 'variable-pitch :family "Libron" :height 1.3))) ; different font for reading (add-hook 'nov-mode-hook #'writeroom-mode) ; center text & stuff (map! :map nov-mode-map :n "i" #'nov-scroll-up ; scroll roughly a page up :n "e" #'nov-scroll-down ; scroll roughly a page down :n "]" #'nov-next-document :n "[" #'nov-previous-document :n "t" #'nov-goto-toc)) (use-package! company :ensure t :defer nil) (use-package! hledger-mode :mode ("\\.journal\\'" "\\.hledger\\'") :custom (hledger-jfile (expand-file-name "~/.hledger.journal")) :after (company cape) :config (add-hook 'hledger-mode-hook (lambda () (add-hook 'completion-at-point-functions (cape-company-to-capf #'hledger-company) nil t)))) (with-eval-after-load 'tramp (add-to-list 'tramp-methods '("doas" (tramp-login-program "doas") (tramp-login-args (("-u" "%u") ("-s"))) (tramp-remote-shell "/bin/sh") (tramp-remote-shell-args ("-c")) (tramp-connection-timeout 10)))) (defconst my/exwm-session-p (and (getenv "EXWM") t)) (defun my/spawn (cmd) "Return a command that runs shell CMD." (lambda () (interactive) (start-process-shell-command cmd nil cmd))) (defun my/run-once (cmd) "Run CMD only if no process named like its executable is already running." (let ((name (file-name-nondirectory (car (split-string cmd))))) (start-process-shell-command cmd nil (format "pgrep -x %s >/dev/null || %s" (shell-quote-argument name) cmd)))) (defun my/close-window () (interactive) (kill-buffer) (when (cdr (window-list)) (edwina-delete-window))) (defconst my/spawn-binds '(("s-" . "alacritty") ("s-w" . "vivaldi") ("s-e" . "xfe") ("s-s" . "discord") ("s-x" . "loginctl lock-session") ("" . "screenshot") ("S-" . "screenrecord") ("s-S" . "screenshot select") ("s-R" . "screenrecord select") ("" . "wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%+") ("" . "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-") ("" . "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle") ("" . "playerctl play-pause") ("" . "playerctl next") ("" . "playerctl previous"))) (defconst my/wm-binds '(("s-r" . exwm-reset) ("s-p" . app-launcher-run-app) ("s-j" . edwina-select-next-window) ("s-k" . edwina-select-previous-window) ("s-J" . edwina-swap-next-window) ("s-K" . edwina-swap-previous-window) ("s-h" . edwina-dec-mfact) ("s-l" . edwina-inc-mfact) ("s-H" . edwina-inc-nmaster) ("s-L" . edwina-dec-nmaster) ("s-m" . edwina-zoom) ; promote to master, dwm-style ("s-q" . my/close-window) ("s-f" . exwm-floating-toggle-floating) ("C-s-q" . save-buffers-kill-emacs))) (defconst my/ws-binds (cl-loop for i from 0 below 9 for sym in '("!" "@" "#" "$" "%" "^" "&" "*" "(") collect (cons (format "s-%d" (1+ i)) (let ((ws i)) (lambda () (interactive) (exwm-workspace-switch-create ws)))) collect (cons (format "s-%s" sym) (let ((ws i)) (lambda () (interactive) (exwm-workspace-move-window ws)))))) (defun my/exwm-key (spec) (cons (kbd (car spec)) (if (stringp (cdr spec)) (my/spawn (cdr spec)) (cdr spec)))) (use-package! exwm :when my/exwm-session-p :config (setenv "EXWM" nil) (setq exwm-workspace-number 9 exwm-manage-configurations '(((member exwm-class-name '("Alacritty")) char-mode t) ((equal exwm-class-name "discord") workspace 8) ((member exwm-class-name '("Pavucontrol" "Blueman-manager" "ssh-askpass" "Gcr-prompter")) floating t) ((equal exwm-title "pinentry") floating t)) exwm-input-global-keys (mapcar #'my/exwm-key (append my/spawn-binds my/wm-binds my/ws-binds)) exwm-input-simulation-keys '(([?\C-b] . [left]) ([?\C-f] . [right]) ([?\C-p] . [up]) ([?\C-n] . [down]) ([?\C-a] . [home]) ([?\C-e] . [end]) ([?\C-d] . [delete]) ([?\C-k] . [S-end delete]) ([?\C-w] . [?\C-x]) ([?\M-w] . [?\C-c]) ([?\C-y] . [?\C-v]))) (cl-pushnew ?\C-c exwm-input-prefix-keys) (add-hook 'exwm-update-class-hook (lambda () (exwm-workspace-rename-buffer exwm-class-name))) (add-hook 'exwm-update-title-hook (lambda () (exwm-workspace-rename-buffer (format "%s | %s" exwm-class-name (truncate-string-to-width (or exwm-title "") 40 nil nil "…"))))) (add-hook 'exwm-mode-hook #'doom-mark-buffer-as-real-h) (advice-add #'suspend-frame :override #'ignore) (add-hook 'exwm-init-hook (lambda () (start-process-shell-command "dbus-env" nil "dbus-update-activation-environment DISPLAY XAUTHORITY") (dolist (c '("feh --bg-scale ~/Pictures/floating_gnu.png" "xset m 0")) (start-process-shell-command c nil c)) (my/run-once "~/.cargo/bin/mprisence"))) (if (fboundp 'exwm-systemtray-mode) (exwm-systemtray-mode 1) (exwm-systetray-enable)) (if (fboundp 'exwm-wm-mode) (exwm-wm-mode 1) (exwm-enable))) ; 0.34+ vs 0.33 (use-package! exwm-edit :when my/exwm-session-p :after exwm :config (setq exwm-edit-split "below")) (use-package! exwm-mff :when my/exwm-session-p :hook (exwm-init . exwm-mff-mode)) (use-package! edwina :when my/exwm-session-p :after exwm :config (setq display-buffer-base-action '(display-buffer-below-selected) edwina-mfact 0.50 edwina-narrow-threshold 0) (edwina-mode 1)) (remove-hook 'doom-first-input-hook #'evil-snipe-mode) (use-package lispyville :init (general-add-hook '(emacs-lisp-mode-hook lisp-mode-hook) #'lispyville-mode) ;; lispy lisps :config (lispyville-set-key-theme '(operators c-w additional))) (after! evil-org (evil-define-key 'normal evil-org-mode-map "o" #'evil-forward-char)) (evil-define-key '(normal visual operator) 'global "n" 'evil-backward-char "e" 'evil-next-line "i" 'evil-previous-line "o" 'evil-forward-char) (evil-define-key '(normal visual operator) 'global "l" 'evil-backward-word-begin "L" 'evil-backward-WORD-begin "u" 'evil-forward-word-end "U" 'evil-forward-WORD-end "y" 'evil-forward-word-begin "Y" 'evil-forward-WORD-begin) (with-eval-after-load 'evil-ex (define-key evil-ex-completion-map (kbd "C-l") 'left-word) (define-key evil-ex-completion-map (kbd "C-y") 'right-word)) (evil-define-key 'normal 'global "s" 'evil-insert "S" 'evil-insert-line "t" 'evil-append "T" 'evil-append-line "h" 'evil-open-below "H" 'evil-open-above) (evil-define-key '(normal visual) 'global "w" 'evil-change "W" 'evil-change-line) (evil-define-key 'normal 'global "x" 'evil-delete-char "c" 'evil-yank "v" 'evil-paste-after "X" 'evil-delete-line "C" 'evil-yank-line "V" 'evil-paste-before) (evil-define-key 'visual 'global "x" 'evil-delete "c" 'evil-yank "v" 'evil-paste-after) (evil-define-key 'normal 'global "z" 'evil-undo "Z" 'evil-redo) (evil-define-key 'normal 'global "a" 'evil-visual-char "A" 'evil-visual-line "ga" 'evil-visual-restore) (evil-define-key '(normal visual operator) 'global "p" 'evil-find-char-to "P" 'evil-find-char-to-backward "b" 'evil-repeat-find-char "B" 'evil-repeat-find-char-reverse "k" 'evil-search-next "K" 'evil-search-previous) (with-eval-after-load 'evil (evil-define-key '(operator visual) 'global "r" evil-inner-text-objects-map)) (define-prefix-command 'my-colemak-fold-map) (evil-define-key '(normal visual) 'global "j" 'my-colemak-fold-map) (define-key my-colemak-fold-map "j" 'evil-scroll-line-to-center) (define-key my-colemak-fold-map "n" 'evil-scroll-line-to-top) (define-key my-colemak-fold-map "e" 'evil-scroll-line-to-bottom) (evil-define-key 'normal 'global "gK" 'evil-lookup) (map! :n "SPC w n" #'evil-window-left :n "SPC w e" #'evil-window-down :n "SPC w i" #'evil-window-up :n "SPC w o" #'evil-window-right) (defun my/meow-insert-bol () ; evil I (interactive) (meow-cancel-selection) (back-to-indentation) (meow-insert)) (defun my/meow-append-eol () ; evil A (interactive) (meow-cancel-selection) (end-of-line) (meow-insert)) (defun my/meow-change-eol () ; evil C (interactive) (meow-cancel-selection) (kill-line) (meow-insert)) (defun my/meow-yank-line () ; evil Y (whole line) (interactive) (kill-ring-save (line-beginning-position) (line-beginning-position 2))) (define-key key-translation-map (kbd "q") (kbd "C-")) (defun my/meow-till-back () (interactive) (let ((current-prefix-arg -1)) (call-interactively #'meow-till))) (defun my/meow-find-back () (interactive) (let ((current-prefix-arg -1)) (call-interactively #'meow-find))) (defun my/meow-search-back () (interactive) (let ((current-prefix-arg -1)) (call-interactively #'meow-search))) (defvar my/meow-scroll-map (make-sparse-keymap)) (define-key my/meow-scroll-map "j" (lambda () (interactive) (recenter))) (define-key my/meow-scroll-map "n" (lambda () (interactive) (recenter 0))) (define-key my/meow-scroll-map "e" (lambda () (interactive) (recenter -1))) (defun my/meow-neio-setup () (meow-motion-overwrite-define-key '("e" . meow-next) '("i" . meow-prev)) (meow-normal-define-key '("n" . meow-left) '("N" . meow-left-expand) '("e" . meow-next) '("E" . meow-next-expand) '("i" . meow-prev) '("I" . meow-prev-expand) '("o" . meow-right) '("O" . meow-right-expand) '("l" . meow-back-word) '("L" . meow-back-symbol) '("y" . meow-next-word) '("Y" . meow-next-symbol) '("u" . meow-next-word) '("U" . meow-next-symbol) '("s" . meow-insert) '("S" . my/meow-insert-bol) '("t" . meow-append) '("T" . my/meow-append-eol) '("h" . meow-open-below) '("H" . meow-open-above) '("w" . meow-change) '("W" . my/meow-change-eol) '("x" . meow-delete) '("X" . kill-line) '("c" . meow-save) '("C" . my/meow-yank-line) '("v" . meow-yank) '("V" . meow-yank-pop) '("z" . meow-undo) '("Z" . undo-redo) '("a" . meow-block) '("A" . meow-line) '("p" . meow-till) '("P" . my/meow-till-back) '("F" . my/meow-find-back) '("k" . meow-search) '("K" . my/meow-search-back) '("J" . meow-join)) (define-key meow-normal-state-keymap "j" my/meow-scroll-map)) (after! meow (my/meow-neio-setup)) (advice-add '+meow--setup-colemak :after #'my/meow-neio-setup) (map! :leader (:prefix ("w" . "window") "n" #'windmove-left "e" #'windmove-down "i" #'windmove-up "o" #'windmove-right))