(load! "splash") (defun +splash-initial-buffer () (splash-screen) (get-buffer "*splash*")) (setq doom-fallback-buffer-name "*splash*" initial-buffer-choice #'+splash-initial-buffer) (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 'tango) (setq doom-font (font-spec :family "Berkeley Mono" :size 12.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)) (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)) (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))) (use-package! eglot :hook (prog-mode . eglot-ensure)) (after! eglot (cl-defmethod eglot-register-capability (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 (web-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 '(html-mode mhtml-mode web-mode css-mode)) (setf (alist-get mode apheleia-mode-alist) 'oxfmt))) (setq auth-sources '("~/.authinfo.gpg")) (setq auth-source-cache-expiry nil) (setq gnus-permanently-visible-groups ".") (evil-set-initial-state 'gnus-browse-mode 'emacs) (setq user-mail-address "hi@roughlynamed.net" ; my email user-full-name "Magdalena Szweda") ; my name (setq mml-secure-openpgp-signers '("3258B28C124AB0891D6C9E929B72909EEF00CBD0") mml-secure-openpgp-sign-with-sender t) (setq message-signature-file "~/.signature") ; note no trailing slash (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") (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")) (use-package! jabber :config (setq jabber-account-list '(("roughlynamed@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) (use-package! emms :commands (emms emms-browser) :init (map! :leader (:prefix ("e" . "emms") :desc "Browser" "b" #'emms-browser :desc "Playlist" "m" #'emms-playlist-mode-go :desc "Play/pause" "SPC" #'emms-pause :desc "Next" "n" #'emms-next :desc "Previous" "p" #'emms-previous :desc "Stop" "s" #'emms-stop :desc "Clear" "c" #'emms-playlist-clear)) :config (require 'emms-setup) (emms-all) (require 'emms-player-mpd) (setq emms-player-list '(emms-player-mpd) emms-info-functions '(emms-info-mpd) emms-player-mpd-server-name "localhost" emms-player-mpd-server-port "6600" emms-player-mpd-music-directory "~/Music" emms-source-file-default-directory (expand-file-name "~/Music/") emms-repeat-playlist t emms-cache-file (concat doom-cache-dir "emms-cache")) (add-hook 'emms-playlist-cleared-hook #'emms-player-mpd-clear) (emms-player-mpd-connect) (emms-mode-line-mode 1) (emms-lyrics-toggle-display-on-minibuffer) (emms-playing-time-mode 1) (map! :map emms-browser-mode-map :n "RET" #'emms-browser-add-tracks-and-play)) (map! :leader :prefix "g m" :desc "Status" "m" #'majutsu ; default majutsu buffer :desc "Describe" "d" #'majutsu-describe ; equivalent of 'jj describe' :desc "New" "n" #'majutsu-new ; new jj rev :desc "Push" "p" #'majutsu-git-push) ; push to git (setq org-directory "~/org/") (after! org (setq org-startup-indented t org-startup-folded t ; fold headers on startup org-pretty-entities t org-hide-emphasis-markers t org-capture-templates-contexts nil org-confirm-babel-evaluate nil) (org-babel-do-load-languages 'org-babel-load-languages '((emacs-lisp . t) (python . t) (C . t) (lisp . t)))) (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)) (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) (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) (use-package! mosey :commands (mosey-forward mosey-backward mosey-forward-bounce mosey-backward-bounce mosey-forward-cycle mosey-backward-cycle)) (map! :leader (:prefix ("k" . "mosey") :desc "Mosey backward" "a" #'mosey-backward-bounce :desc "Mosey forward" "e" #'mosey-forward-bounce)) (use-package! aggressive-indent :config (global-aggressive-indent-mode 1)) ; use aggressive-indent everywhere (map! :leader :prefix "o" :desc "Woman" "w" #'helm-man-woman) (map! :leader :prefix "d" :desc "Dired" "d" #'dired :desc "Dired here" "h" #'dired-jump) (remove-hook 'doom-first-input-hook #'evil-snipe-mode) (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)