diff options
| author | Magdalena Szweda <hi@roughlynamed.net> | 2026-09-27 19:07:34 +0200 |
|---|---|---|
| committer | Magdalena Szweda <hi@roughlynamed.net> | 2026-09-29 14:14:30 +0200 |
| commit | 0fe368fc5f196569a3e0abb8800de155affc5ddf (patch) | |
| tree | 7864439ad95aee4d88df8ce7d1f31936ba70a91c /dots.org | |
| parent | 30a274f48e1f0746a2aaff34eed09df80a47ec1f (diff) | |
gen2
Diffstat (limited to 'dots.org')
| -rw-r--r-- | dots.org | 1061 |
1 files changed, 0 insertions, 1061 deletions
diff --git a/dots.org b/dots.org deleted file mode 100644 index 2fcd355..0000000 --- a/dots.org +++ /dev/null @@ -1,1061 +0,0 @@ -#+title: Dots -My literate system configuration -* TODO Foreword -* Emacs -** 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 - -By default, Emacs prompts 2 times when loading a theme, this is annoying so im getting rid of it. -#+begin_src emacs-lisp - (setq custom-safe-themes t) -#+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 - -mood-line is a nice & simple modeline for emacs! -#+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 - -*** Zen -the ~zen~ option in Doom Emacs enables ~writeroom~ mode on toggle. -~writeroom~ centers the buffer, makes it bigger and lets you type away without distractions. -By default, entering ~writeroom~ mode (which i will continue to call ~zen~ mode) changes the typeface in the buffer. -I don't like that, especially when im editing source blocks (e.g here). Let's turn it off. -#+begin_src emacs-lisp - (setq +zen-mixed-pitch-modes '()) -#+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 - -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 - -By default, Gnus puts entries newest last, let's reverse it. -#+begin_src emacs-lisp -(setq gnus-thread-sort-functions - '((not gnus-thread-sort-by-date))) - -(setq gnus-subthread-sort-functions - '((not gnus-thread-sort-by-date))) -(setq gnus-thread-sort-most-recent-first t) -#+end_src - -What Gnus also does by default is ask to read the .newsrc file, this file is basically an auto-save, 90% of the time you want to read it. -Let's just disable the prompt on every Gnus startup. -#+begin_src emacs-lisp - (setq gnus-always-read-dribble-file nil) -#+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). - -Now, emms has this issue where mpd and the emms cache fall out of sync. This is a documented issue so lets make them catch up by default. -#+BEGIN_SRC emacs-lisp - (defun emms-full-resync () - "Update MPD's db, then pull it into EMMS's cache, then rebuild the browser." - (interactive) - (emms-player-mpd-update-all) - (run-with-timer 2 nil - (lambda () - (emms-cache-set-from-mpd-all) - (when (get-buffer "Browsing by: artist") - (with-current-buffer "Browsing by: artist" (revert-buffer))))) - (emms-browser)) -#+END_SRC - -Declare the package block and set up the commands. -~: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 emms-player-mpd-update-all emms-cache-set-from-mpd-all) -#+end_src - -Configure the mappings for EMMS -~: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-full-resync - :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" "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 -#+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-folded t ; fold headers on startup - org-pretty-entities t - org-hide-emphasis-markers t - org-auto-align-tags nil - org-tags-column 0 - org-catch-invisible-edits 'show-and-error - org-agenda-tags-column 0 - org-capture-templates-contexts nil - org-insert-heading-respect-content t - org-special-ctrl-a/e t - org-return-follows-link t -#+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 -*** poly-org -~poly-org~ lets you use LSP and autocompletion in org code blocks without pressing ~C-c '~ -By default, org lets you 'enter' code blocks with ~C-c '~ and have actual autocompletion/LSP features. -But, typing that every block is annoying (especially with a literate config), that's why ~poly-org~ does the same thing* as ~C-c '~, but it happens when -the cursor hovers over a block. -#+begin_src emacs-lisp - (use-package! poly-org - :hook (org-mode . poly-org-mode)) -#+end_src - -After that, we still need to add Eglot integration. -#+begin_src emacs-lisp - (add-hook 'org-src-mode-hook #'eglot-ensure) -#+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 -#+end_src -The org graph requires Graphviz and the ~dot~ executable -#+begin_src emacs-lisp - :desc "Graph" "g" #'org-roam-graph ; graph of every note -#+end_src -#+begin_src emacs-lisp - :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 -*** org-modern-indent -Because doom's org ~+pretty~ flag turns on org modern, and org-modern is incompatible with ~org-startup-indented~, we use the ~org-indent-modern~ package -#+begin_src emacs-lisp -(use-package! org-modern-indent - :defer t -:hook (org-mode . org-modern-indent-mode)) -#+end_src -** Eww -#+begin_quote -Eww... What browser is that girl using? -#+end_quote - -~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!) - -~eww~ 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 - -Let's make ~eww~ go into readable mode on page enter. -#+begin_src emacs-lisp - (add-hook 'eww-after-render-hook #'eww-readable) -#+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 - -** Elpher -#+begin_quote -Elpher? I hardly know her! -#+end_quote - -Elpher is a way to use the Gemini and Gopher protocols in Emacs. -#+begin_src emacs-lisp -(use-package! elpher) -#+end_src -There's not much config needed except 1 (one) binding -#+begin_src emacs-lisp - (map! - :leader - :prefix "o g" - :desc "Elpher" "e" #'elpher - :desc "Browse Elpher" "b" #'elpher-browse-url-elpher) -#+end_src -** Packages -#+BEGIN_QUOTE -The ones that dont belong -#+END_QUOTE -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 -TODO: make this work properly and not just go to the start/end of line -**** 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 - -*** 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~ -Let's map this to a mnemonic binding, in this case ~Open Woman~ - -#+begin_src emacs-lisp - (map! - :leader - :prefix "o" - :desc "Woman" "w" #'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. -*** eat -~eat~ (emulate a terminal) is a terminal emulator, in elisp, for emacs! -It is not available as a doom emacs module, so we declare it manually. -#+begin_src emacs-lisp - (use-package! eat - :defer t) -#+end_src - -Then we add bindings for ~eat~ as to not have to run ~M-x~ everytime. -#+begin_src emacs-lisp - (map! - :leader - :prefix "o" - :desc "Open Eat" "e" #'eat-other-window) ; dont steal the current window -#+end_src - -** 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 - -*** Lispy -~lispy~[fn:1] is a way to run vim motions in a S-exp aware way. -As an example , running ~D~ on -~(message "Get rid of |everything" a b (+ 1 2))~, where ~|~ is the point would ruin the S-exp, but with ~lispy~, this turns into: -~(message "Get rid of ")~ -Pretty neat, huh? -#+begin_src emacs-lisp - (use-package lispyville - :init - (general-add-hook '(emacs-lisp-mode-hook lisp-mode-hook) #'lispyville-mode) ;; lispy lisps - :config - (lispyville-set-key-theme '(operators c-w additional))) -#+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 - -** Footnotes - -[fn:1] -The actual vim motion part is provided by ~lispyville~, which adds evil support into |
