summaryrefslogtreecommitdiff
path: root/doom
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
commitbe7e6871ed9d71d217ef144b5c5b6c5be5f9f5bd (patch)
tree0bb0c2a257df4da73a8fc8bcf081d0640522895a /doom
parent6b4299e1a2063181da25f1a0d8df2301e1863176 (diff)
emacs: replace the modular config that takes up a bunch of files with 1 clean config.org file.
Diffstat (limited to 'doom')
-rw-r--r--doom/.config/doom/+colemak.el84
-rw-r--r--doom/.config/doom/+dashboard.el30
-rw-r--r--doom/.config/doom/+eglot.el18
-rw-r--r--doom/.config/doom/+email.el37
-rw-r--r--doom/.config/doom/+emms.el33
-rw-r--r--doom/.config/doom/+eww.el66
-rw-r--r--doom/.config/doom/+flycheck.el21
-rw-r--r--doom/.config/doom/+format.el10
-rw-r--r--doom/.config/doom/+git.el8
-rw-r--r--doom/.config/doom/+indent.el4
-rw-r--r--doom/.config/doom/+jabber.el17
-rw-r--r--doom/.config/doom/+lang.el17
-rw-r--r--doom/.config/doom/+maps.el10
-rw-r--r--doom/.config/doom/+mosey.el10
-rw-r--r--doom/.config/doom/+org.el104
-rw-r--r--doom/.config/doom/+term.el3
-rw-r--r--doom/.config/doom/+ui.el41
-rw-r--r--doom/.config/doom/config.el523
-rw-r--r--doom/.config/doom/config.org972
-rw-r--r--doom/.config/doom/init.el4
-rw-r--r--doom/.config/doom/splash.el (renamed from doom/.config/doom/+splash.el)3
21 files changed, 1482 insertions, 533 deletions
diff --git a/doom/.config/doom/+colemak.el b/doom/.config/doom/+colemak.el
deleted file mode 100644
index 132fa8b..0000000
--- a/doom/.config/doom/+colemak.el
+++ /dev/null
@@ -1,84 +0,0 @@
-;;; $DOOMDIR/+colemak.el -*- lexical-binding: t; -*-
-
-(remove-hook 'doom-first-input-hook #'evil-snipe-mode)
-(evil-set-initial-state 'gnus-browse-mode 'emacs)
-(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)
diff --git a/doom/.config/doom/+dashboard.el b/doom/.config/doom/+dashboard.el
deleted file mode 100644
index a751684..0000000
--- a/doom/.config/doom/+dashboard.el
+++ /dev/null
@@ -1,30 +0,0 @@
-;;; $DOOMDIR/+dashboard.el -*- lexical-binding: t; -*-
-
-(defvar dashboard-messages
- '("Vi-Vi-Vi editor of the beast"
- "Welcome to Emacs"
- "M-x M-x"
- "nnngh *humps* get pregnant!!!"
- "tetris, a therapist, web browser, music player... oh and a text editor if youre into that."
- "wranglin' emacs"
- "wranglin' gnu"
- "teco? i hardly know 'er"
- "teco? thats a bad joke"
- "you can do that in emacs"
- "pig destroyer"
- "billions will abudabi"
- "billions will die"
- "evil is cringe - dustmite"
- "free as in freedom"
- "i extract carbon packets out of sun foam"))
-(defun my/dashboard-random-message ()
- (nth (random (length dashboard-messages))
- dashboard-messages))
-(use-package! minimal-dashboard
- :init
- (setq initial-buffer-choice #'minimal-dashboard)
- :custom
- (minimal-dashboard-buffer-name "*dash*")
- (minimal-dashboard-text #'my/dashboard-random-message)
- (minimal-dashboard-modeline-shown 1))
-(setq doom-fallback-buffer-name "*dash*")
diff --git a/doom/.config/doom/+eglot.el b/doom/.config/doom/+eglot.el
deleted file mode 100644
index 2f26d72..0000000
--- a/doom/.config/doom/+eglot.el
+++ /dev/null
@@ -1,18 +0,0 @@
-;;; $DOOMDIR/+eglot.el -*- lexical-binding: t; -*-
-;; TODO: make eglot work with HTML
-(use-package! eglot
- :hook
- (prog-mode . eglot-ensure)
- (markdown-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
- '((markdown-mode)
- . ("zk" "lsp")))
- (add-to-list 'eglot-server-programs
- '((typescript-ts-mode javascript-mode)
- . ("oxlint" "--lsp"))))
-(setq eglot-sync-connect nil
- eglot-connect-timeout 60)
diff --git a/doom/.config/doom/+email.el b/doom/.config/doom/+email.el
deleted file mode 100644
index df06bea..0000000
--- a/doom/.config/doom/+email.el
+++ /dev/null
@@ -1,37 +0,0 @@
-;;; $DOOMDIR/+email.el -*- lexical-binding: t; -*-
-(setq auth-sources '("~/.authinfo.gpg")
- auth-source-cache-expiry nil)
-(setq gnus-permanently-visible-groups ".")
-(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
- smtpmail-stream-type 'ssl
- message-send-mail-function #'smtpmail-send-it)
-
-(setq user-mail-address "hi@roughlynamed.net"
- user-full-name "Magdalena Szweda")
-
-(setq gnus-message-archive-method '(nnimap "migadu")
- gnus-message-archive-group "Sent")
-
-(setq gnus-large-newsgroup nil
- gnus-fetch-old-headers t
- nnmail-expiry-target "Trash")
-
-(setq mml-secure-openpgp-signers
- '("3258B28C124AB0891D6C9E929B72909EEF00CBD0")
- mml-secure-openpgp-sign-with-sender t)
-
-(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"))
-(setq message-signature-file "~/.signature")
-(map! :map message-mode-map
- :localleader
- "s" #'message-send-and-exit
- "S" #'message-send)
diff --git a/doom/.config/doom/+emms.el b/doom/.config/doom/+emms.el
deleted file mode 100644
index 3b03e9e..0000000
--- a/doom/.config/doom/+emms.el
+++ /dev/null
@@ -1,33 +0,0 @@
-;;; $DOOMDIR/+emms.el -*- lexical-binding: t; -*-
-(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-lyrics-toggle-display-on-modeline)
- (emms-playing-time-mode 1)
- (map! :map emms-browser-mode-map
- :n "RET" #'emms-browser-add-tracks-and-play))
diff --git a/doom/.config/doom/+eww.el b/doom/.config/doom/+eww.el
deleted file mode 100644
index 7f8c97c..0000000
--- a/doom/.config/doom/+eww.el
+++ /dev/null
@@ -1,66 +0,0 @@
-;;; $DOOMDIR/+eww.el -*- lexical-binding: 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)))
-
-(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)))
-
-;; Keep your fallback setting
-(setq browse-url-secondary-browser-function 'browse-url-generic
- browse-url-generic-program "chromium")
-
-(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))
-
-(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)
-
-(defun my/eww-download-image-at-point ()
- "Download image at point to `eww-download-directory'."
- (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)))))
-
-;; Keybinds
-(with-eval-after-load 'eww
- (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)
diff --git a/doom/.config/doom/+flycheck.el b/doom/.config/doom/+flycheck.el
deleted file mode 100644
index 0b184b3..0000000
--- a/doom/.config/doom/+flycheck.el
+++ /dev/null
@@ -1,21 +0,0 @@
-;;; $DOOMDIR/+flycheck.el -*- lexical-binding: t; -*-
-;; TODO: fix linter not working (not popping up and stuff)
-(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)))
diff --git a/doom/.config/doom/+format.el b/doom/.config/doom/+format.el
deleted file mode 100644
index c5bbc79..0000000
--- a/doom/.config/doom/+format.el
+++ /dev/null
@@ -1,10 +0,0 @@
-;;; $DOOMDIR/+format.el -*- lexical-binding: t; -*-
-(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)))
-
diff --git a/doom/.config/doom/+git.el b/doom/.config/doom/+git.el
deleted file mode 100644
index 09790f0..0000000
--- a/doom/.config/doom/+git.el
+++ /dev/null
@@ -1,8 +0,0 @@
-;;; $DOOMDIR/+git.el -*- lexical-binding: t; -*-
-(map!
- :leader
- :prefix "g m"
- :desc "Status" "s" #'majutsu
- :desc "Describe" "c" #'majutsu-describe
- :desc "New" "n" #'majutsu-new
- :desc "Push" "p" #'majutsu-git-push)
diff --git a/doom/.config/doom/+indent.el b/doom/.config/doom/+indent.el
deleted file mode 100644
index 4f55797..0000000
--- a/doom/.config/doom/+indent.el
+++ /dev/null
@@ -1,4 +0,0 @@
-;;; $DOOMDIR/+indent.el -*- lexical-binding: t; -*-
-(use-package! aggressive-indent
- :config
- (global-aggressive-indent-mode 1))
diff --git a/doom/.config/doom/+jabber.el b/doom/.config/doom/+jabber.el
deleted file mode 100644
index 23b420f..0000000
--- a/doom/.config/doom/+jabber.el
+++ /dev/null
@@ -1,17 +0,0 @@
-;;; $DOOMDIR/+jabber.el -*- lexical-binding: t; -*-
-(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)
diff --git a/doom/.config/doom/+lang.el b/doom/.config/doom/+lang.el
deleted file mode 100644
index 6ae23c5..0000000
--- a/doom/.config/doom/+lang.el
+++ /dev/null
@@ -1,17 +0,0 @@
-;;; $DOOMDIR/+lang.el -*- lexical-binding: t; -*-
-(load! "+eglot")
-(load! "+flycheck")
-(load! "+format")
-
-;; functions
-(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)))
diff --git a/doom/.config/doom/+maps.el b/doom/.config/doom/+maps.el
deleted file mode 100644
index 2be1d51..0000000
--- a/doom/.config/doom/+maps.el
+++ /dev/null
@@ -1,10 +0,0 @@
-;;; $DOOMDIR/+maps.el -*- lexical-binding: t; -*-
-(map!
- :leader
- :prefix "o"
- :desc "Woman" "w" #'helm-man-woman)
-(map!
- :leader
- :prefix "d"
- :desc "Dired" "d" #'dired
- :desc "Dired here" "h" #'dired-jump)
diff --git a/doom/.config/doom/+mosey.el b/doom/.config/doom/+mosey.el
deleted file mode 100644
index 06b7c33..0000000
--- a/doom/.config/doom/+mosey.el
+++ /dev/null
@@ -1,10 +0,0 @@
-;;; $DOOMDIR/+mosey.el -*- lexical-binding: t; -*-
-
-(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))
diff --git a/doom/.config/doom/+org.el b/doom/.config/doom/+org.el
deleted file mode 100644
index fbd57db..0000000
--- a/doom/.config/doom/+org.el
+++ /dev/null
@@ -1,104 +0,0 @@
-;;; $DOOMDIR/+org.el -*- lexical-binding: t; -*-
-(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")
- :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
- :desc "Insert node" "i" #'org-roam-node-insert
- :desc "Backlinks" "b" #'org-roam-buffer-toggle
- :desc "Capture" "c" #'org-roam-capture
- :desc "Graph" "g" #'org-roam-graph
- :desc "Random node" "r" #'org-roam-node-random
- :desc "Toggle buffer" "t" #'org-roam-buffer-toggle
- :desc "Open link" "o" #'org-open-at-point
- :desc "Jump back" "O" #'org-mark-ring-goto))
-(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
- org-roam-ui-follow t
- org-roam-ui-update-on-save t))
-(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))
diff --git a/doom/.config/doom/+term.el b/doom/.config/doom/+term.el
deleted file mode 100644
index 1d8f2b9..0000000
--- a/doom/.config/doom/+term.el
+++ /dev/null
@@ -1,3 +0,0 @@
-;;; $DOOMDIR/+term.el -*- lexical-binding: t; -*-
-(setq-default vterm-shell "/usr/bin/fish")
-(setq-default explicit-shell-file-name "/usr/bin/fish")
diff --git a/doom/.config/doom/+ui.el b/doom/.config/doom/+ui.el
deleted file mode 100644
index eed34e9..0000000
--- a/doom/.config/doom/+ui.el
+++ /dev/null
@@ -1,41 +0,0 @@
-;;; $DOOMDIR/+ui.el -*- lexical-binding: t; -*-
-(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-font (font-spec :family "Berkeley Mono" :size 12.0))
-(setq doom-theme 'modus-vivendi)
-;; (setq doom-theme 'tango)
-(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)
- :config
- (breadcrumb-mode 1))
diff --git a/doom/.config/doom/config.el b/doom/.config/doom/config.el
index 7eb4158..efb5f57 100644
--- a/doom/.config/doom/config.el
+++ b/doom/.config/doom/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)
diff --git a/doom/.config/doom/config.org b/doom/.config/doom/config.org
new file mode 100644
index 0000000..9a87eaa
--- /dev/null
+++ b/doom/.config/doom/config.org
@@ -0,0 +1,972 @@
+#+TITLE: Doom Emacs configuration
+#+PROPERTY: header-args:emacs-lisp :tangle config.el
+Hello! This is my literate configuration for Doom Emacs.
+Why literate? because org is cool!
+Made with org-babel (the little begin_src blocks)
+
+* Splash screen
+This is my custom splash screen for Emacs.
+#+begin_src emacs-lisp
+(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)))
+#+end_src
+The splash screen doesnt do much, it prints the emacs version and a warranty notice and whatnot. i like it tho!
+
+* UI
+~How Emacs looks!~
+** Theme
+Load the directory with additional, local themes
+This currently mostly loads the emacs port of the Evergarden theme (made by me!)
+at [[https://codeberg.org/roughlynamed/emacs-evergarden][roughlynamed/emacs-evergarden]], also the fortune-gold theme.
+The reason i use modus-vivendi instead of my evergarden port is because i dont like evergarden (dont tell the devs though!), seeing it not have an emacs port just made me sad.
+I also use tango from time-to-time, thats the comment.
+#+begin_src emacs-lisp
+(add-to-list 'custom-theme-load-path
+ "~/.config/doom/extra-themes/")
+(setq doom-theme 'modus-vivendi)
+;; (setq doom-theme 'tango)
+#+end_src
+** Font
+I use the completely not pirated ~Berkeley Mono~ font. I really like it.
+Sometimes i will use the Commit mono font (sometimes!)
+#+begin_src emacs-lisp
+(setq doom-font (font-spec :family "Berkeley Mono" :size 12.0))
+#+end_src
+
+Line numbers! And not relative!
+I dont like rln, i just dont
+#+begin_src emacs-lisp
+(setq display-line-numbers-type t)
+#+end_src
+** Modeline
+The emacs mood line, It's nice and simple which i adore.
+I might have to try out the default modeline from Emacs sometime though.
+#+begin_src emacs-lisp
+(use-package! mood-line
+ :config
+ (mood-line-mode)
+ :custom
+ (mood-line-glyph-alist mood-line-glyphs-fira-code))
+#+end_src
+
+** Custom window management
+I didnt like how in emacs, split windows under ~SPC w s~ just stack, so i made this function to make it dynamic in a fibonnaci-like layout.
+#+begin_src emacs-lisp
+(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))))
+#+end_src
+
+Map the function to override ~SPC w s~
+#+begin_src emacs-lisp
+(map! :leader "w s" #'my/split-window-dynamically)
+#+end_src
+
+** UX ~ UI
+Scroll margin - when the cursor reaches 3 lines above/below the window bottom/top, the window goes down (this happens in helix automatically, but the margin is 5)
+#+begin_src emacs-lisp
+(setq scroll-margin 3)
+#+end_src
+
+** Breadcrumb
+Breadcrumb is a package that shows you where you are in a file at the very top of the window. Editing this section of this file, the breadcrumb shows:
+~stow/d/.config/doom/config.org : UI~,
+this is because we are in the UI section of the file.
+#+begin_src emacs-lisp
+(use-package! breadcrumb
+ :defer t
+ :hook
+ (prog-mode . breadcrumb-mode) ;; make sure its in programming modes
+ :config
+ (breadcrumb-mode 1))
+#+end_src
+
+* Languages & LSP
+~M-x vscode~
+** Haskell
+A custom function that runs the current Haskell file with runghc (interpreter instead of a compiler).
+#+begin_src emacs-lisp
+(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)))))
+#+end_src
+
+** TODO make this a ~SPC~-based binding
+Hook the function up up to f5
+#+begin_src emacs-lisp
+(add-hook 'haskell-mode-hook
+ (lambda ()
+ (local-set-key (kbd "<f5>") #'my/hs-eval)))
+#+end_src
+
+** Eglot
+Eglot is, well, LSP for Emacs!
+Here i hook eglot-ensure into prog-mode.
+eglot-ensure makes sure that eglot is enabled and working when opening a prog-mode buffer now.
+#+begin_src emacs-lisp
+(use-package! eglot
+ :hook
+ (prog-mode . eglot-ensure))
+#+end_src
+
+I copied this block from somewhere and have no idea what it does.
+#+begin_src emacs-lisp
+(after! eglot
+ (cl-defmethod eglot-register-capability
+ (server (method (eql workspace/didChangeWatchedFiles)) id &key watchers)
+ nil)
+#+end_src
+
+
+Here we add a custom LSP for typescript and javascript mode.
+Oxlint is a rewrite of ESLint in Rust, Not sure why oxlsp isnt its own tool, but oh well.
+#+begin_src emacs-lisp
+ (add-to-list 'eglot-server-programs
+ '((typescript-ts-mode javascript-mode)
+ . ("oxlint" "--lsp"))))
+#+end_src
+
+~eglot-sync-connect~ makes it so that eglot has to catch up and connect before a buffer can be worked on, thats why i set it to nil.
+~eglot-connect-timeout~ just stops trying to connect to eglot after a minute.
+#+begin_src emacs-lisp
+(setq eglot-sync-connect nil
+ eglot-connect-timeout 60)
+#+end_src
+
+** Flycheck
+Flycheck is a linter engine for Emacs.
+
+Here i define a new checker for flycheck, htmlhint (which is the linter i most enjoy using).
+Then i hook it into ~web-mode~
+#+begin_src emacs-lisp
+(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))
+#+end_src
+
+I then add the new checker to the flycheck checkers (say that 3 times fast)
+#+begin_src emacs-lisp
+(add-to-list 'flycheck-checkers 'htmlhint)
+#+end_src
+
+Here we add additional checkers to flycheck.
+We add ESLint and oxlint, and then another block for html-tidy and the new htmlhint.
+The reason this cant be all in one ~flycheck-add-next-checker~ block is because ~flyckech-add-next-checker~ only takes 2 variables.
+#+begin_src emacs-lisp
+ (flycheck-add-next-checker
+ 'javascript-eslint
+ 'javascript-oxlint)
+ (flycheck-add-next-checker
+ 'html-tidy
+ 'htmlhint)
+#+end_src
+
+We then make flycheck check the file after saving.
+#+begin_src emacs-lisp
+ (setq flycheck-check-syntax-automatically
+ '(save mode-enabled)))
+#+end_src
+
+** Apheleia
+
+Apheleia is an easy way to format your files in Emacs.
+First we hook apheleia into prog-mode.
+#+begin_src emacs-lisp
+(use-package! apheleia
+ :hook (prog-mode . apheleia-mode)
+#+end_src
+
+We can then add a new apheleia formatter, in this case oxfmt.
+(why is oxfmt its own tool but oxlsp isnt? why cant it just be ~oxlint --lsp~ and ~oxlint --format~, this is dumb)
+#+begin_src emacs-lisp
+ :config
+ (setf (alist-get 'oxfmt apheleia-formatters)
+ '("oxfmt" "--config=.oxfmtrc.json" "--stdin-filepath" filepath))
+#+end_src
+
+Here we hook the new oxfmt formatter into:
++ html-mode
++ mhtml-mode
++ web-mode
++ css-mode
+#+begin_src emacs-lisp
+ (dolist (mode '(html-mode mhtml-mode web-mode css-mode))
+ (setf (alist-get mode apheleia-mode-alist) 'oxfmt)))
+#+end_src
+
+* Email
+~Emacs - prover of Zawinki's law~
+** Auth
+To send mail, we need to log into everything.
+Instead of typing out passwords every time, we use the ~~.authinfo.gpg~ file (can also be without the gpg encryption).
+To read the file:
+#+begin_src emacs-lisp
+(setq auth-sources '("~/.authinfo.gpg"))
+#+end_src
+Emacs automatically decrypts the file with ~epa~ and ~epg~.
+To make this not expire, we set
+#+begin_src emacs-lisp
+(setq auth-source-cache-expiry nil)
+#+end_src
+
+** Gnus
+Gnus is Emacs's built in Email reader, sender, news viewer and RSS reader.
+But right now we're setting up the Email part.
+
+This makes it so that all subscribed groups are visible, no matter if theres no new messages.
+
+#+begin_src emacs-lisp
+(setq gnus-permanently-visible-groups ".")
+#+end_src
+
+When browsing gnus, make the mode in evil standard emacs.
+#+begin_src emacs-lisp
+(evil-set-initial-state 'gnus-browse-mode 'emacs)
+#+end_src
+Now we configure our user of gnus.
+#+begin_src emacs-lisp
+(setq user-mail-address "hi@roughlynamed.net" ; my email
+ user-full-name "Magdalena Szweda") ; my name
+#+end_src
+While we're at it, lets point Emacs at my LibrePGP key.
+#+begin_src emacs-lisp
+(setq mml-secure-openpgp-signers
+ '("3258B28C124AB0891D6C9E929B72909EEF00CBD0")
+ mml-secure-openpgp-sign-with-sender t)
+#+end_src
+We can also set up the signature via the ~.signature~ file instead of encoding it raw into the config.
+#+begin_src emacs-lisp
+(setq message-signature-file "~/.signature") ; note no trailing slash
+#+end_src
+
+Now we can set up the actual mail part.
+I use migadu for my email hosting, provided to me by ~@bas.sh~
+Here we set up IMAP for receiving mail.
+#+begin_src emacs-lisp
+(setq gnus-select-method
+ '(nnimap "migadu"
+ (nnimap-address "imap.migadu.com")
+ (nnimap-server-port 993)
+ (nnimap-stream ssl)))
+#+end_src
+Once that's done, we can configure the sending (smtp) part.
+#+begin_src emacs-lisp
+(setq smtpmail-smtp-server "smtp.migadu.com"
+ smtpmail-smtp-service 465 ; port 465
+ smtpmail-stream-type 'ssl
+ message-send-mail-function #'smtpmail-send-it
+)
+#+end_src
+
+After that, a little bit more config for UX
+#+begin_src emacs-lisp
+(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")
+#+end_src
+
+I like to sign my message with pgp as a way to confirm that its really me sending the email.
+We can do this with the following:
+#+begin_src emacs-lisp
+(add-hook 'message-send-hook #'mml-secure-message-sign-pgpmime)
+#+end_src
+We use pgpmime to put the signature in the MIME header instead of inline PGP blocks.
+
+I'm not a fan of html in my emails as i find it rendering bad and being hard to navigate, so i set it to discourage html and prefer plain text emails.
+#+begin_src emacs-lisp
+(with-eval-after-load "mm-decode"
+(add-to-list 'mm-discouraged-alternatives "text/html")
+(add-to-list 'mm-discouraged-alternatives "text/richtext"))
+#+end_src
+
+* Jabber
+~Jabber? I hardly know her!~
+
+Excuse the bad pun, jabber.el is a way to use XMPP in Emacs.
+#+begin_src emacs-lisp
+(use-package! jabber
+ :config
+#+end_src
+We point jabber at my XMPP account:
+#+begin_src emacs-lisp
+(setq jabber-account-list
+ '(("roughlynamed@yax.im")))
+#+end_src
+And let jabber use the modeline
+#+begin_src emacs-lisp
+(jabber-modeline-mode 1)
+#+end_src
+Now, we can hook jabber to kill itself when emacs dies.
+#+begin_src emacs-lisp
+:hook
+(kill-emacs . jabber-disconnect))
+#+end_src
+As to not rely on ~M-x~ commands, define a binding as so
+#+begin_src emacs-lisp
+(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)
+#+end_src
+
+
+* EMMS
+~Music to my ears~
+EMMS, the Emacs MultiMedia System (but mostly its just used for music).
+
+Declare the package block and set up the commands.
+** TODO put the following prose in an org-roam file
+~:commands~ in elisp is used to eagerly load functions even when a package is lazy loaded.
+The following makes the commands ~emms~ and ~emms-browser~ available even before emms itself is loaded.
+#+begin_src emacs-lisp
+(use-package! emms
+ :commands (emms emms-browser)
+#+end_src
+
+Configure the mappings for EMMS
+** TODO put the following prose in an org-roam file
+~:init~ in elisp runs the following code =before= a package is loaded.
+In this case, it makes the emms mappings available right when emacs starts up.
+#+begin_src emacs-lisp
+ :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))
+#+end_src
+
+Here we tell EMMS to use the preset configuration loader, this makes it so that i dont have to wire up a bunch of emms submodules myself.
+#+begin_src emacs-lisp
+ :config
+ (require 'emms-setup)
+#+end_src
+
+We then use ~emms-all~ to load every emms submodule. Possible variations include:
+| Name | What it does |
+|----------------+----------------------------------------------------------------|
+| ~emms-all~ | Loads every EMMS submodule. (browser, cover art, lyrics, etc.) |
+|----------------+----------------------------------------------------------------|
+| ~emms-standard~ | Smaller and more curated subset of features |
+|----------------+----------------------------------------------------------------|
+| ~emms-minimal~ | Very barebones EMMS |
+
+#+begin_src emacs-lisp
+ (emms-all)
+#+end_src
+
+Here we tell EMMS to use MPD instead of MPRIS.
+#+begin_src emacs-lisp
+ (require 'emms-player-mpd)
+ (setq emms-player-list '(emms-player-mpd)
+ emms-info-functions '(emms-info-mpd)
+#+end_src
+
+
+Here we point EMMS/MPD at the default server and port for MPD
+#+begin_src emacs-lisp
+emms-player-mpd-server-name "localhost"
+emms-player-mpd-server-port "6600"
+#+end_src
+
+Tell EMMS where MPD's music dir lives, and where its own music dir lives.
+#+begin_src emacs-lisp
+emms-player-mpd-music-directory "~/Music"
+emms-source-file-default-directory (expand-file-name "~/Music/")
+#+end_src
+
+Make playlists loop instead of stopping at the last track.
+#+begin_src emacs-lisp
+emms-repeat-playlist t
+#+end_src
+
+Make EMMS use Doom Emacs' cache instead of its own.
+#+begin_src emacs-lisp
+emms-cache-file (concat doom-cache-dir "emms-cache"))
+#+end_src
+
+Clear the playlist both on EMMS and MPD
+#+begin_src emacs-lisp
+(add-hook 'emms-playlist-cleared-hook #'emms-player-mpd-clear)
+#+end_src
+
+Connect to MPD as soon as this config loads.
+#+begin_src emacs-lisp
+(emms-player-mpd-connect)
+#+end_src
+
+Turn on the little [ARTIST - ALBUM - TITLE] indicator in the modeline.
+#+begin_src emacs-lisp
+(emms-mode-line-mode 1)
+#+end_src
+
+Show lyrics in the buffer whenever its free
+#+begin_src emacs-lisp
+(emms-lyrics-toggle-display-on-minibuffer)
+#+end_src
+
+LISTENED/LENGTH indicator in the modeline
+#+begin_src emacs-lisp
+(emms-playing-time-mode 1)
+#+end_src
+
+This makes it so that presing RET on a song in normal mode adds the tracks to the playlist and plays it.
+This currently doesnt work.
+#+begin_src emacs-lisp
+(map! :map emms-browser-mode-map
+ :n "RET" #'emms-browser-add-tracks-and-play))
+#+end_src
+
+
+
+* Git
+~LEAVE Emacs? You gotta be kidding.~
+** Majutsu
+I use the JuJutsu version control system.
+I am an old user of ~magit~. Why not use magit for JJ?
+
+Define mappings for the already-installed ~majutsu~
+Open the main majutsu buffer.
+#+begin_src emacs-lisp
+(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
+#+end_src
+
+* Org
+~Protesting for Org README support.~
+Org is Emacs's version of markdown, and is what this file is written in.
+
+Tell org what directory to use
+#+begin_src emacs-lisp
+(setq org-directory "~/org/")
+#+end_src
+
+Now it's time to get to the guts; the main org config.
+But first, some good 'ol self-documenting code:
+#+begin_src emacs-lisp
+(after! org
+ (setq
+ org-startup-indented t
+ org-pretty-entities t
+ org-hide-emphasis-markers t
+ org-capture-templates-contexts nil
+#+end_src
+** Org Babel
+Org babel is Org's version of code blocks.
+Every code block defined above and below is made via org-babel and the following config.
+#+begin_src emacs-lisp
+ org-confirm-babel-evaluate nil)
+ (org-babel-do-load-languages
+ 'org-babel-load-languages
+ '((emacs-lisp . t)
+ (python . t)
+ (C . t)
+ (lisp . t))))
+#+end_src
+
+** Org UX
+This makes org capturing much better.
+When capturing a new org note, all windows are deleted, and the capture window is made a dedicated window.
+#+begin_src emacs-lisp
+(add-hook 'org-capture-mode-hook #'delete-other-windows)
+(add-hook 'org-capture-mode-hook
+ (lambda () (set-window-dedicated-p (selected-window) nil)))
+#+end_src
+
+** TODO Org roam
+As much as i'd love to put it under its own higher header, that would be nonsensical.
+Org roam is org's way of a Zettelkasten style knowledge place. Something like obsidian, logseq or ~zk~. Another plus is everything lives in a ~SQLite~ database.
+
+Point org-roam at the org directory (declared seperately).
+#+begin_src emacs-lisp
+(after! org-roam
+ (setq org-roam-directory (file-truename "~/org/"))
+#+end_src
+
+Make roam sync it's database automatically.
+#+begin_src emacs-lisp
+ (org-roam-db-autosync-mode)
+#+end_src
+
+This is a custom function, i made it to mimic how the ~zk~ cli works when making a new note, which is usually a random 4 character string. for example ~zqy2.md~ could be a note.
+#+begin_src emacs-lisp
+ (defun my/org-roam-short-id ()
+ (let ((chars "abcdefghijklmnopqrstuvwxyz0123456789"))
+ (apply #'string
+ (cl-loop repeat 4
+ collect (aref chars (random (length chars)))))))
+
+
+#+end_src
+
+The template for new org notes.
+#+begin_src emacs-lisp
+(setq org-roam-capture-templates
+ '(("d" "default" plain
+ "* %?"
+ :if-new
+#+end_src
+
+Here we use the function defined above to name the captured org file
+#+begin_src emacs-lisp
+ (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)))
+
+
+#+end_src
+
+Define sections in roam.
+#+begin_src emacs-lisp
+ (setq org-roam-mode-sections
+ '(org-roam-backlinks-section
+ org-roam-reflinks-section
+ org-roam-unlinked-references-section))
+#+end_src
+
+*** Link checking
+Here we have custom functions, mimicking the ~zk~ cli.
+This functions check if an org file has an inserted link to itself.
+#+begin_src emacs-lisp
+(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"))))))
+
+
+#+end_src
+
+Check links that dont point to an actual file
+#+begin_src emacs-lisp
+(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)))))
+#+end_src
+*** Hooks
+Run the defined above functions before every org file save
+#+begin_src emacs-lisp
+(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)
+#+end_src
+*** Maps
+Define mappings
+#+begin_src emacs-lisp
+ (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
+
+#+end_src
+** ox-html
+~ox-html~ is a way to convert org files into html.
+#+begin_src emacs-lisp
+(with-eval-after-load 'ox-html
+ (setq org-html-xml-declaration nil
+ org-html-doctype "html5"
+ org-html-html5-fancy t
+#+end_src
+
+Dont use ox's default html style
+#+begin_src emacs-lisp
+ org-html-head-include-default-style nil
+#+end_src
+
+Dont postamble in generated html
+#+begin_src emacs-lisp
+ org-html-postamble nil))
+#+end_src
+
+** org-roam-ui
+~org-roam-ui~ makes a Obsidian-like graph available in the browser.
+It makes a pretty graph of all your notes and puts it at http://localhost:35901.
+
+Required websocket
+#+begin_src emacs-lisp
+(use-package! websocket :after org-roam)
+#+end_src
+
+org-roam config
+#+begin_src emacs-lisp
+(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
+))
+#+end_src
+** org-appear
+Org appear makes it so that inline code blocks (=~~=), words marked verbatim (====) and (hyper)link syntax hide when viewing the file and appear when hovered on for easy editing.
+for example =[[id:xqyz][emacs]]= will become =emacs= when viewing the file, but turn into the original when the cursor is over the text.
+#+begin_src emacs-lisp
+(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))
+#+end_src
+
+* Eww
+~Eww... What browser is that girl using?~
+
+~eww~ (Emacs Web WOWser) is, well, a web browser in Emacs.
+It only renders HTML and tries its best to render CSS, so javascript is out of the question (hooray!)
+
+emms is fine on its own, but i have a config to make the experience better.
+Here we define what to search with, for me this is Ecosia.
+#+begin_src emacs-lisp
+(setq eww-search-prefix "https://ecosia.org/search?q=")
+#+end_src
+
+Where eww downloads files to.
+#+begin_src emacs-lisp
+(setq eww-download-directory (expand-file-name "~/Downloads/"))
+#+end_src
+** Functions
+Open a link in mpv
+#+begin_src emacs-lisp
+(defun my-browse-url-mpv (url &rest _args)
+ "Open URL in mpv."
+ (start-process "mpv" nil "mpv" url))
+#+end_src
+
+Open a url in pdf-tools
+#+begin_src emacs-lisp
+(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)))
+#+end_src
+
+Download an image and put it into ~eww-download-directory~
+#+begin_src emacs-lisp
+(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)))))
+#+end_src
+
+** Config :: Misc
+Use the functions defined above when opening specific links
+#+begin_src emacs-lisp
+(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)))
+
+#+end_src
+
+Open a url in a secondary program, in my case ~Vivaldi~
+#+begin_src emacs-lisp
+(setq browse-url-secondary-browser-function 'browse-url-generic
+ browse-url-generic-program "vivaldi")
+#+end_src
+
+** UI/UX settings
+#+begin_src emacs-lisp
+(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)
+#+end_src
+
+** Keybindings
+#+begin_src emacs-lisp
+(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)
+#+end_src
+
+
+* TODO Elpher
+~Elpher Leaves Protocols Hanging, Eternally Relevant~
+
+
+* Packages
+~The ones that dont belong~
+
+These packages are (mostly) defined in ~packages.el~ and configured here.
+** TODO mosey
+Mosey lets you ~Mosey down~ (get it?) to different points in a code block.
+#+begin_src emacs-lisp
+(use-package! mosey
+ :commands (mosey-forward mosey-backward
+ mosey-forward-bounce mosey-backward-bounce
+ mosey-forward-cycle mosey-backward-cycle))
+#+end_src
+
+*** Keybinds
+Keybinds for mosey, under K because m was taken by localleader bindings
+#+begin_src emacs-lisp
+(map! :leader
+ (:prefix ("k" . "mosey")
+ :desc "Mosey backward" "a" #'mosey-backward-bounce
+ :desc "Mosey forward" "e" #'mosey-forward-bounce))
+#+end_src
+
+** aggressive-indent
+~aggressive-indent~ is a package that makes sure every line is indented properly.
+It follows its own indentation, and forces (very aggressively) for lines to stay on there, live, while editing.
+#+begin_src emacs-lisp
+(use-package! aggressive-indent
+ :config
+ (global-aggressive-indent-mode 1)) ; use aggressive-indent everywhere
+#+end_src
+
+** Woman
+~woman~ is a way to view man pages straight in Emacs, without shelling out to the actual ~man~ binary, it stands for ~without man~
+Because i use Helm, im using the pre-configured Helm version
+#+begin_src emacs-lisp
+(map!
+ :leader
+ :prefix "o"
+ :desc "Woman" "w" #'helm-man-woman)
+#+end_src
+
+** Dired
+~Dired~ (Directory editor) is a way to, well, edit directories (and files!) in Emacs.
+This is similar to ~oil.nvim~
+These are only bindings as dired is pre-installed on Emacs.
+#+begin_src emacs-lisp
+(map!
+ :leader
+ :prefix "d"
+ :desc "Dired" "d" #'dired
+ :desc "Dired here" "h" #'dired-jump)
+#+end_src
+~dired~ prompts for the directory to open first, while ~dired-jump~ opens dired in the current directory, pretty neat.
+
+* Evil
+~Mapping at its finest~
+EVIl mode emulates VIM bindings in Emacs.
+
+Remove ~evil-snipe~ as it conflicts with other bindings
+#+begin_src emacs-lisp
+(remove-hook 'doom-first-input-hook #'evil-snipe-mode)
+#+end_src
+
+
+** Colemak
+The biggest block for last.
+This is a custom mapping i made for EVIl mode that takes the bindings from [[https://github.com/kalbasit/vim-colemak][kalbasit/vim-colemak]] and puts them into Emacs.
+I plan on packaging this to [[https://melpa.org][MELPA]] soon.
+
+Make ~o~ go right in org mode (previously ~inserted on newline~)
+#+begin_src emacs-lisp
+(after! evil-org
+ (evil-define-key 'normal evil-org-mode-map
+ "o" #'evil-forward-char))
+#+end_src
+
+*** Main bindings
+#+begin_src emacs-lisp
+(evil-define-key '(normal visual operator) 'global
+ "n" 'evil-backward-char
+ "e" 'evil-next-line
+ "i" 'evil-previous-line
+ "o" 'evil-forward-char)
+ #+end_src
+*** Motion
+#+begin_src emacs-lisp
+(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))
+
+
+#+end_src
+*** Inserting
+#+begin_src emacs-lisp
+(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)
+#+end_src
+*** Changing
+#+begin_src emacs-lisp
+(evil-define-key '(normal visual) 'global
+ "w" 'evil-change
+ "W" 'evil-change-line)
+
+
+#+end_src
+*** Editing
+#+begin_src emacs-lisp
+(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)
+#+end_src
+*** TODO Undo
+Doesnt work in org files
+#+begin_src emacs-lisp
+(evil-define-key 'normal 'global
+ "z" 'evil-undo
+ "Z" 'evil-redo)
+
+
+#+end_src
+*** Visual
+#+begin_src emacs-lisp
+(evil-define-key 'normal 'global
+ "a" 'evil-visual-char
+ "A" 'evil-visual-line
+ "ga" 'evil-visual-restore)
+
+
+#+end_src
+*** Find/Search
+#+begin_src emacs-lisp
+(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)
+
+
+#+end_src
+*** Inner change
+#+begin_src emacs-lisp
+(with-eval-after-load 'evil
+ (evil-define-key '(operator visual) 'global "r" evil-inner-text-objects-map))
+
+#+end_src
+*** Scroll
+#+begin_src emacs-lisp
+(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)
+
+
+#+end_src
+*** Lookup
+#+begin_src emacs-lisp
+(evil-define-key 'normal 'global
+ "gK" 'evil-lookup)
+
+
+#+end_src
+*** Window management
+#+begin_src emacs-lisp
+(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)
+
+#+end_src
diff --git a/doom/.config/doom/init.el b/doom/.config/doom/init.el
index 5862c74..394574f 100644
--- a/doom/.config/doom/init.el
+++ b/doom/.config/doom/init.el
@@ -144,7 +144,7 @@
;;nix ; I hereby declare "nix geht mehr!"
;;ocaml ; an objective camel
;;odin ; C, minus its footguns
- (org +roam) ; organize your plain life in plain text
+ (org +roam +pretty) ; organize your plain life in plain text
php ; perl's insecure younger brother
;;plantuml ; diagrams for confusing people more
;;graphviz ; diagrams for confusing yourself even more
@@ -182,7 +182,7 @@
;;(rss +org) ; emacs as an RSS reader
:config
- ;;literate
+ literate
(default +bindings +smartparens))
;; If you're a dark-mode user who suffers from the "flash of white Emacs" when
diff --git a/doom/.config/doom/+splash.el b/doom/.config/doom/splash.el
index e76098e..e61adbd 100644
--- a/doom/.config/doom/+splash.el
+++ b/doom/.config/doom/splash.el
@@ -1,6 +1,5 @@
-;;; $DOOMDIR/+splash.el -*- lexical-binding: t; -*-
+;;; $DOOMDIR/splash.el -*- lexical-binding: t; -*-
-;;; Code:
(defun splash--center (str width)
"Return STR centered in WIDTH columns."