aboutsummaryrefslogtreecommitdiff
path: root/config.el
diff options
context:
space:
mode:
authorMagdalena Szweda <hi@roughlynamed.net>2026-09-22 16:31:35 +0200
committerMagdalena Szweda <hi@roughlynamed.net>2026-09-22 16:32:37 +0200
commit6bb6bd1da70858f83f848234cfee8a881881f93d (patch)
tree0667ab2747de3d9835302a70766bc9e1a13513f6 /config.el
parent376841ef8ee82afcfcdbfe95d196931c0b5c931e (diff)
emacs: replace the modular config that takes up a bunch of files with 1 clean config.org file.
Diffstat (limited to 'config.el')
-rw-r--r--config.el523
1 files changed, 507 insertions, 16 deletions
diff --git a/config.el b/config.el
index 7eb4158..efb5f57 100644
--- a/config.el
+++ b/config.el
@@ -1,16 +1,507 @@
-;;; $DOOMDIR/config.el -*- lexical-binding: t; -*-
-(load! "+ui")
-;; (load! "+dashboard") ; this is the bigger dashboard
-(load! "+splash") ; this is the more minimal one
-(load! "+maps")
-(load! "+colemak")
-(load! "+lang")
-(load! "+email")
-(load! "+jabber")
-(load! "+emms")
-(load! "+term")
-(load! "+git")
-(load! "+org")
-(load! "+eww")
-(load! "+mosey")
-(load! "+indent")
+(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 "<f5>") #'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" "s" #'majutsu ; default majutsu buffer
+ :desc "Describe" "c" #'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-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! 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)