aboutsummaryrefslogtreecommitdiff
path: root/doom
diff options
context:
space:
mode:
Diffstat (limited to 'doom')
-rw-r--r--doom/.config/doom/config.el150
-rw-r--r--doom/.config/doom/config.org1229
2 files changed, 755 insertions, 624 deletions
diff --git a/doom/.config/doom/config.el b/doom/.config/doom/config.el
index 213b60f..2f08da8 100644
--- a/doom/.config/doom/config.el
+++ b/doom/.config/doom/config.el
@@ -16,7 +16,8 @@
(add-to-list 'custom-theme-load-path
"~/.config/doom/extra-themes/")
;; (setq doom-theme 'modus-vivendi)
-(setq doom-theme 'doric-oak)
+;; (setq doom-theme 'doric-oak)
+(setq doom-theme 'doric-obsidian)
;; (setq doom-theme 'tango)
(setq custom-safe-themes t)
@@ -73,6 +74,20 @@
(lambda ()
(local-set-key (kbd "<f5>") #'my/hs-eval)))
+(add-to-list 'major-mode-remap-alist '(html-mode . mhtml-ts-mode))
+(add-to-list 'major-mode-remap-alist '(mhtml-mode . mhtml-ts-mode))
+
+(add-to-list 'auto-mode-alist '("\\.html?\\'" . mhtml-ts-mode))
+(add-to-list 'major-mode-remap-alist '(html-mode . mhtml-ts-mode))
+(add-to-list 'major-mode-remap-alist '(mhtml-mode . mhtml-ts-mode))
+
+(advice-add 'web-mode :around
+ (lambda (orig &rest args)
+ (if (or (null buffer-file-name)
+ (string-match-p "\\.html?\\'" buffer-file-name))
+ (mhtml-ts-mode)
+ (apply orig args))))
+
(use-package! eglot
:hook
(prog-mode . eglot-ensure))
@@ -82,12 +97,12 @@
:config (eglot-booster-mode))
(after! eglot
- (cl-defmethod eglot-register-capability
- ((_server eglot-lsp-server)
- (method (eql workspace/didChangeWatchedFiles))
- _id
- &key _watchers)
- nil)
+ (cl-defmethod eglot-register-capability
+ ((_server eglot-lsp-server)
+ (method (eql workspace/didChangeWatchedFiles))
+ _id
+ &key _watchers)
+ nil)
(add-to-list 'eglot-server-programs
'((typescript-ts-mode javascript-mode)
@@ -105,13 +120,13 @@
line-start
(file-name) ":" line ":" column ": "
(message) line-end))
- :modes (web-mode))
+ :modes (mhtml-ts-mode))
(add-to-list 'flycheck-checkers 'htmlhint)
(flycheck-add-next-checker
- 'javascript-eslint
- 'javascript-oxlint)
+ 'javascript-eslint
+ 'javascript-oxlint)
(flycheck-add-next-checker
'html-tidy
'htmlhint)
@@ -120,14 +135,17 @@
'(save mode-enabled)))
(use-package! apheleia
- :hook (prog-mode . apheleia-mode)
+ :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)))
+(dolist (mode '(mhtml-ts-mode html-mode mhtml-mode web-mode css-mode))
+ (setf (alist-get mode apheleia-mode-alist) 'oxfmt)))
+
+(add-hook 'mhtml-ts-mode-hook #'apheleia-mode)
(use-package! pinentry
:config
@@ -164,7 +182,7 @@
)
(setq gnus-message-archive-method '(nnimap "migadu") ; use migadu for archiving email
- gnus-message-archive-group "Sent") ; where to put sent mail
+ gnus-message-archive-group "Sent") ; where to put sent mail
(setq gnus-large-newsgroup nil
gnus-fetch-old-headers t
@@ -212,39 +230,16 @@
:desc "New chat" "n" #'jabber-chat-with
:desc "Set status" "s" #'jabber-send-presence)
-(defun emms--wait-for-mpd-update (callback)
- "Poll MPD status until updating_db clears, then call CALLBACK."
- (emms-player-mpd-get-status
- callback
- (lambda (callback info)
- (if (assoc "updating_db" info)
- (run-with-timer 0.5 nil #'emms--wait-for-mpd-update callback)
- (funcall callback)))))
-
-(defun emms-full-resync ()
- "Update MPD's db, then pull it into EMMS's cache, then rebuild the browser."
- (interactive)
- (message "emms: starting mpd db update...")
- (emms-player-mpd-update-all)
- (emms--wait-for-mpd-update
- (lambda ()
- (emms-cache-set-from-mpd-all)
- (dolist (buf (buffer-list))
- (with-current-buffer buf
- (when (derived-mode-p 'emms-browser-mode)
- (revert-buffer))))
- (emms-browser)
- (message "emms: resync done"))))
-
+(add-to-list 'load-path "/home/hi/.config/doom/")
(use-package! emms
- :commands (emms emms-browser emms-player-mpd-update-all emms-cache-set-from-mpd-all emms emms-pause emms-next emms-previous emms-stop
- emms-random emms-add-directory-tree emms-play-playlist)
+:commands (emms emms-browser emms-player-mpd-update-all emms-cache-set-from-mpd-all emms emms-pause emms-next emms-previous emms-stop
+ emms-random emms-add-directory-tree emms-play-playlist)
:init
(map! :leader
(:prefix ("e" . "emms")
- :desc "Browser" "b" #'emms-full-resync
- :desc "Playlist" "m" #'emms-playlist-mode-go
+ :desc "Browser" "b" #'emms-browser
+ :desc "Emms" "e" #'emms
:desc "Play/pause" "SPC" #'emms-pause
:desc "Next" "n" #'emms-next
:desc "Previous" "p" #'emms-previous
@@ -257,12 +252,13 @@
(emms-all)
-(require 'emms-player-mpd)
-(setq emms-player-list '(emms-player-mpd)
- emms-info-functions '(emms-info-mpd)
+(require 'emms-player-xmms2)
+(setq
+ emms-player-list '(emms-player-xmms2)
-emms-player-mpd-server-name "localhost"
-emms-player-mpd-server-port "6600"
+emms-lyrics-scroll-p nil
+emms-lyrics-display-on-minibuffer t
+emms-lyrics-display-on-modeline nil
emms-player-mpd-music-directory "~/Music"
emms-source-file-default-directory (expand-file-name "~/Music/playlists/")
@@ -271,14 +267,8 @@ 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
@@ -346,11 +336,11 @@ emms-cache-file (concat doom-cache-dir "emms-cache"))
(advice-add 'vc-jj-push :before #'my/vc-jj--advance-before-push)
(setq my/vc-jj-advance-to "@-")
-(defun my/vc-jj-checkin (files comment &optional _rev)
- "Describe @ and start a fresh change."
- (let ((default-directory (vc-jj-root (car files))))
- (vc-jj-modify-change-comment nil "@" comment)
- (vc-jj--command-dispatched nil 0 nil "new" "--quiet")))
+ (defun my/vc-jj-checkin (files comment &optional _rev)
+ "Describe @ and start a fresh change."
+ (let ((default-directory (vc-jj-root (car files))))
+ (vc-jj-modify-change-comment nil "@" comment)
+ (vc-jj--command-dispatched nil 0 nil "new" "--quiet")))
(advice-add 'vc-jj-checkin :override #'my/vc-jj-checkin))
(after! vc-jj
@@ -381,7 +371,7 @@ emms-cache-file (concat doom-cache-dir "emms-cache"))
(advice-add 'vc-jj-push :around #'my/vc-jj--push-no-window)
(advice-add 'vc-jj-push :after #'my/vc-jj--report-push)
- (define-advice ansi-color-filter-region (:around (fn &rest args) my/vc-jj-writable)
+ (define-advice ansi-color-filter-region (:around (fn &rest args) my/vc-jj-writable)
(let ((inhibit-read-only (or inhibit-read-only
(string-prefix-p "*vc-jj" (buffer-name)))))
(apply fn args))))
@@ -405,11 +395,11 @@ emms-cache-file (concat doom-cache-dir "emms-cache"))
org-confirm-babel-evaluate nil)
(org-babel-do-load-languages
-'org-babel-load-languages
-'((emacs-lisp . t)
- (python . t)
- (C . t)
- (lisp . t))))
+ 'org-babel-load-languages
+ '((emacs-lisp . t)
+ (python . t)
+ (C . t)
+ (lisp . t))))
(use-package! poly-org
:hook (org-mode . poly-org-mode))
@@ -439,9 +429,9 @@ org-confirm-babel-evaluate nil)
:if-new
(file+head
- (lambda () (concat (my/org-roam-short-id) ".org"))
- "#+TITLE: %^{title|Untitled}\n#+FILETAGS: :%^{tags}:\n\n") ; title&tags
-:unnarrowed t)))
+ (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)))
@@ -520,7 +510,7 @@ org-html-postamble nil))
(use-package! org-modern-indent
:defer t
-:hook (org-mode . org-modern-indent-mode))
+ :hook (org-mode . org-modern-indent-mode))
(setq eww-search-prefix "https://ecosia.org/search?q=")
@@ -657,12 +647,12 @@ org-html-postamble nil))
"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)
+ "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)
@@ -681,12 +671,12 @@ org-html-postamble nil))
"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)
+ "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
diff --git a/doom/.config/doom/config.org b/doom/.config/doom/config.org
index 1b98c5d..f633aac 100644
--- a/doom/.config/doom/config.org
+++ b/doom/.config/doom/config.org
@@ -41,48 +41,49 @@ The reason i use modus-vivendi instead of my evergarden port is because i dont l
For this to work, we need modus & ef themes installed.
Doric themes are also nice.
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (package! modus-themes)
- (package! ef-themes)
- (package! doric-themes)
+(package! modus-themes)
+(package! ef-themes)
+(package! doric-themes)
#+end_src
#+begin_src emacs-lisp
(add-to-list 'custom-theme-load-path
"~/.config/doom/extra-themes/")
;; (setq doom-theme 'modus-vivendi)
-(setq doom-theme 'doric-oak)
+;; (setq doom-theme 'doric-oak)
+(setq doom-theme 'doric-obsidian)
;; (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)
+(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 or Cozette! (sometimes!)
#+begin_src emacs-lisp
- (setq doom-font (font-spec :family "Berkeley Mono" :size 13.0))
+(setq doom-font (font-spec :family "Berkeley Mono" :size 13.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)
+(setq display-line-numbers-type t)
#+end_src
** Modeline
mood-line is a nice & simple modeline for emacs!
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- ;; (package! mood-line)
+;; (package! mood-line)
#+end_src
#+begin_src emacs-lisp
- ;; (use-package! mood-line
- ;; :config
- ;; (mood-line-mode)
- ;; :custom
- ;; (mood-line-glyph-alist mood-line-glyphs-fira-code))
+;; (use-package! mood-line
+;; :config
+;; (mood-line-mode)
+;; :custom
+;; (mood-line-glyph-alist mood-line-glyphs-fira-code))
#+end_src
The above is commented if the below is in action.
I might try out the default Emacs modeline for a bit sometime, or maybe spacemacs' ~spaceline~
@@ -91,38 +92,38 @@ I might try out the default Emacs modeline for a bit sometime, or maybe spacemac
The default Emacs modeline, by default, spills out EVERY minor & major mode into the modeline.
That's kind of yucky, so the ~minions~ package fixes it by hiding most of them & having a menu for which to show.
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (package! minions)
+(package! minions)
#+end_src
Now, let's configure it!
#+begin_src emacs-lisp
- (use-package! minions
- :config
- (minions-mode 1))
+(use-package! minions
+ :config
+ (minions-mode 1))
#+end_src
...Yea that's 'bout it.
** 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))))
+(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)
+(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)
+(setq scroll-margin 3)
#+end_src
** Breadcrumb
@@ -131,16 +132,16 @@ Breadcrumb is a package that shows you where you are in a file at the very top o
this is because we are in the UI section of the file.
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (package! breadcrumb)
+(package! breadcrumb)
#+end_src
#+begin_src emacs-lisp
- (use-package! breadcrumb
- :defer t
- :hook
- (prog-mode . breadcrumb-mode) ;; make sure its in programming modes
- :config
- (breadcrumb-mode 1))
+(use-package! breadcrumb
+ :defer t
+ :hook
+ (prog-mode . breadcrumb-mode) ;; make sure its in programming modes
+ :config
+ (breadcrumb-mode 1))
#+end_src
** Zen
@@ -149,7 +150,7 @@ the ~zen~ option in Doom Emacs enables ~writeroom~ mode on toggle.
By default, entering ~writeroom~ 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 '())
+(setq +zen-mixed-pitch-modes '())
#+end_src
** vertico-carousel
~vertico~ is the equivalent of nvim's ~telescope~ in Emacs.
@@ -158,55 +159,85 @@ I don't like that, especially when im editing source blocks (e.g here). Let's tu
the currently selected candidate on the first line of the candidate list,
then displays the following candidates below it, cycling from the end back
to the beginning.
- -- vertico-carousel README
+-- vertico-carousel README
#+end_quote
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (package! vertico-carousel
- :recipe (:host github :repo "kn66/vertico-carousel"))
+(package! vertico-carousel
+ :recipe (:host github :repo "kn66/vertico-carousel"))
#+end_src
#+begin_src emacs-lisp
- (use-package! vertico-carousel
- :config
- (vertico-carousel-mode 1))
+(use-package! vertico-carousel
+ :config
+ (vertico-carousel-mode 1))
#+end_src
-* Languages & LSP
+* 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)))))
+(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)))
+(add-hook 'haskell-mode-hook
+ (lambda ()
+ (local-set-key (kbd "<f5>") #'my/hs-eval)))
+#+end_src
+
+** HTML
+HTML is a big part of my programming life.
+There are, however, alot of modes for HTML (html-mode, web-mode, mhtml-mode).
+These are all good, but the BEST one by far is ~mhtml-ts-mode~, it outcompetes almost all of the above.
+#+begin_src emacs-lisp
+ (add-to-list 'major-mode-remap-alist '(html-mode . mhtml-ts-mode))
+ (add-to-list 'major-mode-remap-alist '(mhtml-mode . mhtml-ts-mode))
#+end_src
+web-mode rescans the whole altered block on every edit, which gets slow on HTML with big inline ~<script>~ and ~<style>~ blocks.
+~mhtml-ts-mode~ is built in and tree-sitter based. It needs the html, css and javascript grammars, which ~M-x mhtml-ts-mode-install-parsers~ builds.
+
+Claim =.html= for it, and remap the other HTML modes to it.
+
+#+begin_src emacs-lisp
+(add-to-list 'auto-mode-alist '("\\.html?\\'" . mhtml-ts-mode))
+(add-to-list 'major-mode-remap-alist '(html-mode . mhtml-ts-mode))
+(add-to-list 'major-mode-remap-alist '(mhtml-mode . mhtml-ts-mode))
+#+end_src
+
+Things like ~php~ or ~vue~ call ~web-mode~ directly, and ~mhtml-ts-mode~ doesnt understand those languages, so we make sure that
+those languages get ~web-mode~
+#+begin_src emacs-lisp
+(advice-add 'web-mode :around
+ (lambda (orig &rest args)
+ (if (or (null buffer-file-name)
+ (string-match-p "\\.html?\\'" buffer-file-name))
+ (mhtml-ts-mode)
+ (apply orig args))))
+#+end_src
** Eglot
Eglot is, well, LSP for Emacs!
It bundles all your LSP's into one big package so you dont have to install everything manually
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))
+(use-package! eglot
+ :hook
+ (prog-mode . eglot-ensure))
#+end_src
Then we can set up ~eglot-booster~, which adds ~emacs-lsp-booster~ integration into eglot.
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (package! eglot-booster
- :recipe (:host github :repo "jdtsmith/eglot-booster"))
+(package! eglot-booster
+ :recipe (:host github :repo "jdtsmith/eglot-booster"))
#+end_src
emacs-lsp-booster, well, boosts lsp (with rust!)
#+begin_src emacs-lisp
@@ -217,7 +248,7 @@ emacs-lsp-booster, well, boosts lsp (with rust!)
I copied this block from somewhere and have no idea what it does.
#+begin_src emacs-lisp
- (after! eglot
+(after! eglot
(cl-defmethod eglot-register-capability
((_server eglot-lsp-server)
(method (eql workspace/didChangeWatchedFiles))
@@ -226,22 +257,22 @@ I copied this block from somewhere and have no idea what it does.
nil)
-#+end_src
+ #+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)
- . ("emacs-lsp-booster" "--" "oxlint" "--lsp"))))
+ 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)
+ . ("emacs-lsp-booster" "--" "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)
+(setq eglot-sync-connect nil
+ eglot-connect-timeout 60)
#+end_src
** Flycheck
@@ -250,37 +281,37 @@ 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
+(after! flycheck
+ (flycheck-define-checker htmlhint
+ "htmlhint for flycheck"
+ :command ("htmlhint" "--format" "unix" source)
+ :error-patterns
+ ((error
+ line-start
+ (file-name) ":" line ":" column ": "
+ (message) line-end))
+ :modes (mhtml-ts-mode))
+ #+end_src
-I then add the new checker to the flycheck checkers (say that 3 times fast)
-#+begin_src emacs-lisp
+ 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
+ #+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
+ 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
+ (flycheck-add-next-checker
+ 'html-tidy
+ 'htmlhint)
+ #+end_src
-We then make flycheck check the file after saving.
-#+begin_src emacs-lisp
+ We then make flycheck check the file after saving.
+ #+begin_src emacs-lisp
(setq flycheck-check-syntax-automatically
'(save mode-enabled)))
#+end_src
@@ -291,23 +322,27 @@ 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
+ :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
+ 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
+ #+end_src
-Here we hook the new oxfmt formatter into:
-#+begin_src emacs-lisp
-(dolist (mode '(html-mode mhtml-mode web-mode css-mode))
+ Here we hook the new oxfmt formatter into apheleia:
+ #+begin_src emacs-lisp
+ (dolist (mode '(mhtml-ts-mode html-mode mhtml-mode web-mode css-mode))
(setf (alist-get mode apheleia-mode-alist) 'oxfmt)))
+ #+end_src
+ Let's also hook mhtml-ts-mode into apheleia
+#+begin_src emacs-lisp
+ (add-hook 'mhtml-ts-mode-hook #'apheleia-mode)
#+end_src
-
* Email
~Emacs - prover of Zawinki's law~
** Auth
@@ -315,23 +350,23 @@ 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).
First we install & set up pinentry.
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (package! pinentry)
+(package! pinentry)
#+end_src
#+begin_src emacs-lisp
- (use-package! pinentry
- :config
- (pinentry-start))
- (setq epg-pinentry-mode 'loopback)
+(use-package! pinentry
+ :config
+ (pinentry-start))
+(setq epg-pinentry-mode 'loopback)
#+end_src
To read the file:
#+begin_src emacs-lisp
- (setq auth-sources '("~/.authinfo.gpg"))
+(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)
+(setq auth-source-cache-expiry nil)
#+end_src
** Gnus
@@ -340,56 +375,56 @@ 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 ".")
+(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)
+(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
+(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
- '("B9CF59FE57835F89ECB33FD417CA809770F85511")
- mml-secure-openpgp-sign-with-sender t)
+(setq mml-secure-openpgp-signers
+ '("B9CF59FE57835F89ECB33FD417CA809770F85511")
+ 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
+(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)))
+(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
- )
+(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-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
@@ -409,214 +444,320 @@ By default, Gnus puts entries newest last, let's reverse it.
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)
+(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)
+(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"))
+(with-eval-after-load "mm-decode"
+ (add-to-list 'mm-discouraged-alternatives "text/html")
+ (add-to-list 'mm-discouraged-alternatives "text/richtext"))
#+end_src
While we're at it, let's make opening gnus easier.
#+begin_src emacs-lisp
- (map!
- :leader
- :prefix "o"
- :desc "Mail" "m" #'gnus)
+(map!
+ :leader
+ :prefix "o"
+ :desc "Mail" "m" #'gnus)
#+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 :tangle ~/.config/doom/packages.el
- (package! jabber)
+(package! jabber)
#+end_src
#+begin_src emacs-lisp
- (use-package! jabber
- :config
-#+end_src
-We point jabber at my XMPP account:
-#+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")
("wildebeest@yax.im")))
-#+end_src
-And let jabber use the modeline
-#+begin_src emacs-lisp
+ #+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
+ #+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)
+(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
+* TODO EMMS
#+begin_quote
~Music to my ears~
#+end_quote
+** TODO EMMS xmms2
+
+This is a project for adding xmms2 support into the Emacs MultiMedia System.
+I plan on getting this into Savannah, then GNU ELPA, or having it merged with the official EMMS repository.
+
+And now, ladies & gentlemen, i present to you a bunch of self-documenting code im too lazy to split up into different source blocks!!!
+#+begin_src emacs-lisp :tangle ~/.config/doom/emms-player-xmms2.el
+;;; emms-player-xmms2.el --- XMMS2 player for EMMS (stage 1 - unfinished) -*- lexical-binding: t; -*-
+;; Copyright (C) 2026 Magdalena Szweda
+;; Author: Magdalena Szweda
+;; Setup:
+;; (add-to-list 'load-path "/dir/containing/this/file")
+;; (require 'emms-player-xmms2)
+;; (setq emms-player-list '(emms-player-xmms2))
+
+(require 'cl-lib)
+(require 'dbus)
+(require 'emms-player-simple)
+
+(defgroup emms-player-xmms2 nil
+ "EMMS player for XMMS2."
+ :group 'emms-player
+ :prefix "emms-player-xmms2-")
+
+(defcustom emms-player-xmms2-command "xmms2"
+ "The xmms2 CLI executable."
+ :type 'string)
+
+(defcustom emms-player-xmms2-mpris-service "org.mpris.MediaPlayer2.xmms2"
+ "D-Bus name owned by the xmms2 MPRIS bridge."
+ :type 'string)
+
+(defcustom emms-player-xmms2-check-interval 1
+ "Seconds between playback-state checks."
+ :type 'number)
+
+(defcustom emms-player-xmms2
+ (emms-player #'emms-player-xmms2-start
+ #'emms-player-xmms2-stop
+ #'emms-player-xmms2-playable-p)
+ "Parameters for the XMMS2 player."
+ :type '(cons symbol alist))
+
+(emms-player-set emms-player-xmms2 'regex
+ (concat "\\`http[s]?://\\|"
+ (emms-player-simple-regexp
+ "ogg" "flac" "mp3" "wav" "opus" "m4a" "aac" "mod")))
+(emms-player-set emms-player-xmms2 'pause 'emms-player-xmms2-pause)
+(emms-player-set emms-player-xmms2 'resume 'emms-player-xmms2-resume)
+(emms-player-set emms-player-xmms2 'seek 'emms-player-xmms2-seek)
+(emms-player-set emms-player-xmms2 'seek-to 'emms-player-xmms2-seek-to)
+
+;;; Internals
+
+(defvar emms-player-xmms2--timer nil)
+(defvar emms-player-xmms2--seen-playing nil
+ "Non-nil once XMMS2 has reported Playing/Paused for the current track.")
+
+(defun emms-player-xmms2--run (&rest args)
+ "Run the xmms2 CLI with ARGS. "
+ (zerop (apply #'call-process emms-player-xmms2-command nil nil nil args)))
+
+(defun emms-player-xmms2--state ()
+ "Return the MPRIS PlaybackStatus string, or nil if unreachable."
+ (ignore-errors
+ (dbus-get-property :session emms-player-xmms2-mpris-service
+ "/org/mpris/MediaPlayer2"
+ "org.mpris.MediaPlayer2.Player" "PlaybackStatus")))
+
+(defun emms-player-xmms2--cancel-timer ()
+ (when emms-player-xmms2--timer
+ (cancel-timer emms-player-xmms2--timer)
+ (setq emms-player-xmms2--timer nil)))
+
+(defun emms-player-xmms2--poll ()
+ "Tell EMMS when XMMS2 finishes the track on its own."
+ (let ((state (emms-player-xmms2--state)))
+ (cond ((member state '("Playing" "Paused"))
+ (setq emms-player-xmms2--seen-playing t))
+ ((and emms-player-xmms2--seen-playing (equal state "Stopped"))
+ (emms-player-xmms2--cancel-timer)
+ (setq emms-player-xmms2--seen-playing nil)
+ ;; stopped-p is nil here, so EMMS advances to the next track
+ (emms-player-stopped)))))
+
+;;; EMMS API
+
+(defun emms-player-xmms2-playable-p (track)
+ "Return non-nil when we can play TRACK."
+ (and (memq (emms-track-type track) '(file url))
+ (string-match (emms-player-get emms-player-xmms2 'regex)
+ (emms-track-name track))
+ (executable-find emms-player-xmms2-command)
+ t))
+
+(defun emms-player-xmms2-start (track)
+ "Play TRACK: clear XMMS2's playlist, add it, play."
+ (emms-player-xmms2--cancel-timer)
+ (setq emms-player-xmms2--seen-playing nil)
+ (let ((name (emms-track-name track)))
+ (when (eq (emms-track-type track) 'file)
+ (setq name (expand-file-name name)))
+ (if (and (emms-player-xmms2--run "clear")
+ (emms-player-xmms2--run "add" name)
+ (emms-player-xmms2--run "play"))
+ (progn
+ (emms-player-started 'emms-player-xmms2)
+ (setq emms-player-xmms2--timer
+ (run-at-time emms-player-xmms2-check-interval
+ emms-player-xmms2-check-interval
+ #'emms-player-xmms2--poll)))
+ (message "XMMS2: could not start %s" name))))
+
+(defun emms-player-xmms2-stop ()
+ "Stop playback."
+ (interactive)
+ (emms-player-xmms2--cancel-timer)
+ (setq emms-player-xmms2--seen-playing nil)
+ (emms-player-xmms2--run "stop")
+ (let ((emms-player-stopped-p t))
+ (emms-player-stopped)))
+
+(defun emms-player-xmms2-pause ()
+ "Pause playback."
+ (interactive)
+ (emms-player-xmms2--run "pause"))
+
+(defun emms-player-xmms2-resume ()
+ "Resume playback."
+ (interactive)
+ (emms-player-xmms2--run "play"))
+
+(defun emms-player-xmms2-seek (amount)
+ "Seek by AMOUNT seconds."
+ (interactive "nSeconds: ")
+ (emms-player-xmms2--run "seek" (format "%+d" (round amount))))
+
+(defun emms-player-xmms2-seek-to (pos)
+ "Seek to POS seconds from the start of the track."
+ (interactive "nSeconds: ")
+ (emms-player-xmms2--run "seek" (number-to-string (round pos))))
+
+(provide 'emms-player-xmms2)
+
+;;; emms-player-xmms2.el ends here
+#+end_src
+
+#+RESULTS:
+: emms-player-xmms2
+** EMMS - for real now
EMMS, the Emacs MultiMedia System (but mostly its just used for music).
EMMS has a Doom Emacs module, so it doesnt require a ~(package!)~ line
+Here we 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.
-Here, a quick function to help with mpd caching on emms (a documented issue)
#+begin_src emacs-lisp
-(defun emms--wait-for-mpd-update (callback)
- "Poll MPD status until updating_db clears, then call CALLBACK."
- (emms-player-mpd-get-status
- callback
- (lambda (callback info)
- (if (assoc "updating_db" info)
- (run-with-timer 0.5 nil #'emms--wait-for-mpd-update callback)
- (funcall callback)))))
+ (add-to-list 'load-path "/home/hi/.config/doom/")
+(use-package! emms
+:commands (emms emms-browser emms-player-mpd-update-all emms-cache-set-from-mpd-all emms emms-pause emms-next emms-previous emms-stop
+ emms-random emms-add-directory-tree emms-play-playlist)
#+end_src
-And wire it into emms
-#+BEGIN_SRC emacs-lisp
-(defun emms-full-resync ()
- "Update MPD's db, then pull it into EMMS's cache, then rebuild the browser."
- (interactive)
- (message "emms: starting mpd db update...")
- (emms-player-mpd-update-all)
- (emms--wait-for-mpd-update
- (lambda ()
- (emms-cache-set-from-mpd-all)
- (dolist (buf (buffer-list))
- (with-current-buffer buf
- (when (derived-mode-p 'emms-browser-mode)
- (revert-buffer))))
- (emms-browser)
- (message "emms: resync done"))))
-#+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-browser
+ :desc "Emms" "e" #'emms
+ :desc "Play/pause" "SPC" #'emms-pause
+ :desc "Next" "n" #'emms-next
+ :desc "Previous" "p" #'emms-previous
+ :desc "Stop" "s" #'emms-stop
+ :desc "Add" "a" #'emms-add-playlist
+ :desc "Clear" "c" #'emms-playlist-clear))
+#+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.
+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
- (use-package! emms
- :commands (emms emms-browser emms-player-mpd-update-all emms-cache-set-from-mpd-all emms emms-pause emms-next emms-previous emms-stop
- emms-random emms-add-directory-tree emms-play-playlist)
- #+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 "Add" "a" #'emms-add-playlist
- :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/playlists/")
- #+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))
+(emms-all)
+#+end_src
+
+Here we tell EMMS to use XMMS2 instead of MPRIS or Mpd.
+#+begin_src emacs-lisp
+
+(require 'emms-player-xmms2)
+(setq
+ emms-player-list '(emms-player-xmms2)
+ #+end_src
+
+ Stop lyrics from scrolling, and have them appear on the minibuffer
+ #+begin_src emacs-lisp
+ emms-lyrics-scroll-p nil
+ emms-lyrics-display-on-minibuffer t
+ emms-lyrics-display-on-modeline nil
+ #+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/playlists/")
+ #+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
+
+Turn on the little [ARTIST - ALBUM - TITLE] indicator in the modeline.
+#+begin_src emacs-lisp
+(emms-mode-line-mode 1)
+#+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
* vc
@@ -629,50 +770,50 @@ By default, vc bindings are under ~C-x v~, but thats annoying, i'll be binding i
I tried my best to match these to the default bindings under ~C-x v~
#+begin_src emacs-lisp
- (map!
- :leader
- :prefix "v"
- :desc "vc-edit-next-command" "!" #'vc-edit-next-command
- :desc "diff-hl-show-hunk" "*" #'diff-hl-show-hunk
- :desc "vc-update" "+" #'vc-update
- :desc "diff-hl-goto-hunk" "=" #'diff-hl-diff-goto-hunk
- :desc "vc-revert" "@" #'vc-revert
- :desc "vc-update-change-log" "a" #'vc-update-change-log
- ;; ADD b BINDINGS (branch)
- :desc "vc-dir" "d" #'vc-dir
- :desc "vc-root-diff" "D" #'vc-root-diff
- ;; ADD E BINDINGS
- :desc "annotate" "g" #'vc-annotate
- :desc "ignore" "G" #'vc-ignore
- :desc "region history" "h" #'vc-region-history
- :desc "register" "i" #'vc-register
- :desc "root log incoming" "I" #'vc-root-log-incoming
- :desc "print log" "l" #'vc-print-log
- :desc "print root log" "L" #'vc-print-root-log
- :desc "merge" "m" #'vc-merge
- ;; ADD M BINDINGS
- :desc "diff revert hunk" "n" #'diff-hl-revert-hunk
- :desc "root log outgoing" "O" #'vc-root-log-outgoing
- :desc "push" "p" #'vc-push ; originally P
- :desc "retrieve tag" "r" #'vc-retrieve-tag
- :desc "rename file" "R" #'vc-rename-file
- :desc "create tag" "s" #'vc-create-tag
- :desc "stage dwim (diff hl)" "S" #'diff-hl-stage-dwim
- ;; ADD T BINDINGS
- :desc "vc revert" "u" #'vc-revert ; carried over from the original bindings (repeated by @)
- :desc "vc next action" "v" #'vc-next-action ; run the next logical action
- ;; ADD w BINDINGS
- :desc "revision other window" "~" #'vc-revision-other-window)
+(map!
+ :leader
+ :prefix "v"
+ :desc "vc-edit-next-command" "!" #'vc-edit-next-command
+ :desc "diff-hl-show-hunk" "*" #'diff-hl-show-hunk
+ :desc "vc-update" "+" #'vc-update
+ :desc "diff-hl-goto-hunk" "=" #'diff-hl-diff-goto-hunk
+ :desc "vc-revert" "@" #'vc-revert
+ :desc "vc-update-change-log" "a" #'vc-update-change-log
+ ;; ADD b BINDINGS (branch)
+ :desc "vc-dir" "d" #'vc-dir
+ :desc "vc-root-diff" "D" #'vc-root-diff
+ ;; ADD E BINDINGS
+ :desc "annotate" "g" #'vc-annotate
+ :desc "ignore" "G" #'vc-ignore
+ :desc "region history" "h" #'vc-region-history
+ :desc "register" "i" #'vc-register
+ :desc "root log incoming" "I" #'vc-root-log-incoming
+ :desc "print log" "l" #'vc-print-log
+ :desc "print root log" "L" #'vc-print-root-log
+ :desc "merge" "m" #'vc-merge
+ ;; ADD M BINDINGS
+ :desc "diff revert hunk" "n" #'diff-hl-revert-hunk
+ :desc "root log outgoing" "O" #'vc-root-log-outgoing
+ :desc "push" "p" #'vc-push ; originally P
+ :desc "retrieve tag" "r" #'vc-retrieve-tag
+ :desc "rename file" "R" #'vc-rename-file
+ :desc "create tag" "s" #'vc-create-tag
+ :desc "stage dwim (diff hl)" "S" #'diff-hl-stage-dwim
+ ;; ADD T BINDINGS
+ :desc "vc revert" "u" #'vc-revert ; carried over from the original bindings (repeated by @)
+ :desc "vc next action" "v" #'vc-next-action ; run the next logical action
+ ;; ADD w BINDINGS
+ :desc "revision other window" "~" #'vc-revision-other-window)
#+end_src
** vc-jj
~vc-jj~ adds jujutsu integration to Emacs's ~vc~!
-#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (package! vc-jj)
+#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
+(package! vc-jj)
#+END_SRC
Then, we actually enable it.
#+begin_src emacs-lisp
- (use-package! vc-jj)
+(use-package! vc-jj)
#+end_src
vc-jj has a bit of a... weird flow, it runs ~jj commit~ instead of ~jj describe~, and doesnt advance bookmarks the way i usually do in my flow.
@@ -703,11 +844,11 @@ Here we fix it!
(advice-add 'vc-jj-push :before #'my/vc-jj--advance-before-push)
(setq my/vc-jj-advance-to "@-")
-(defun my/vc-jj-checkin (files comment &optional _rev)
- "Describe @ and start a fresh change."
- (let ((default-directory (vc-jj-root (car files))))
- (vc-jj-modify-change-comment nil "@" comment)
- (vc-jj--command-dispatched nil 0 nil "new" "--quiet")))
+ (defun my/vc-jj-checkin (files comment &optional _rev)
+ "Describe @ and start a fresh change."
+ (let ((default-directory (vc-jj-root (car files))))
+ (vc-jj-modify-change-comment nil "@" comment)
+ (vc-jj--command-dispatched nil 0 nil "new" "--quiet")))
(advice-add 'vc-jj-checkin :override #'my/vc-jj-checkin))
#+end_src
Now, this opens an ugly buffer in a split window and just... leaves it there.
@@ -741,7 +882,7 @@ A simple fix indeed.
(advice-add 'vc-jj-push :around #'my/vc-jj--push-no-window)
(advice-add 'vc-jj-push :after #'my/vc-jj--report-push)
- (define-advice ansi-color-filter-region (:around (fn &rest args) my/vc-jj-writable)
+ (define-advice ansi-color-filter-region (:around (fn &rest args) my/vc-jj-writable)
(let ((inhibit-read-only (or inhibit-read-only
(string-prefix-p "*vc-jj" (buffer-name)))))
(apply fn args))))
@@ -752,37 +893,37 @@ 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/")
- (setq org-agenda-files "~/org/todo.org")
+(setq org-directory "~/org/")
+(setq org-agenda-files "~/org/todo.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))))
+(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
@@ -791,29 +932,29 @@ By default, org lets you 'enter' code blocks with ~C-c '~ and have actual autoco
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 :tangle ~/.config/doom/packages.el
- (package! poly-org)
+(package! poly-org)
#+end_src
#+begin_src emacs-lisp
- (use-package! poly-org
- :hook (org-mode . poly-org-mode))
+(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)
+(add-hook 'org-src-mode-hook #'eglot-ensure)
#+end_src
There's a bug that hits org-lint & poly-org & flycheck about org element's cache, so lets just disable it.
#+begin_src emacs-lisp
- (setq org-element-use-cache nil)
+(setq org-element-use-cache nil)
#+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)))
+(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
@@ -822,22 +963,22 @@ Org roam is org's way of a Zettelkasten style knowledge place. Something like ob
Here we unpin org-roam from Doom's version, as it is reccomended for custom configs like this.
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (unpin! org-roam)
+(unpin! org-roam)
#+end_src
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
+(after! org-roam
+ (setq org-roam-directory (file-truename "~/org/"))
+ #+end_src
-Make roam sync it's database automatically.
-#+begin_src emacs-lisp
+ Make roam sync it's database automatically.
+ #+begin_src emacs-lisp
(org-roam-db-autosync-mode)
-#+end_src
+ #+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
+ 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
@@ -845,44 +986,44 @@ This is a custom function, i made it to mimic how the ~zk~ cli works when making
collect (aref chars (random (length chars)))))))
-#+end_src
+ #+end_src
-The template for new org notes.
-#+begin_src emacs-lisp
+ The template for new org notes.
+ #+begin_src emacs-lisp
(setq org-roam-capture-templates
'(("d" "default" plain
"* %?"
:if-new
-#+end_src
+ #+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)))
+ 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)))
+ (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-node-display-template
+ (concat "${title:*} " (propertize "${file-stem}" 'face 'org-tag)))
-#+end_src
+ #+end_src
-Define sections in roam.
-#+begin_src emacs-lisp
+ 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
+ #+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
+ *** 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)))
@@ -893,30 +1034,30 @@ This functions check if an org file has an inserted link to itself.
(message "Warning: self-link detected"))))))
-#+end_src
+ #+end_src
-Check links that dont point to an actual file
-#+begin_src emacs-lisp
+ 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
+ #+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
+ #+end_src
+ *** Maps
+ Define mappings
+ #+begin_src emacs-lisp
(map!
:leader
:prefix ("n r" . "roam")
@@ -924,84 +1065,84 @@ Define mappings
: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
+ 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
+(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 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))
+ 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.
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (package! org-roam-ui)
+(package! org-roam-ui)
#+end_src
Websocket required
#+begin_src emacs-lisp
- (use-package! websocket :after org-roam)
+(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
- ))
+(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 :tangle ~/.config/doom/packages.el
- (package! org-appear)
+(package! org-appear)
#+end_src
#+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))
+(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 :tangle ~/.config/doom/packages.el
- (package! org-modern-indent
- :recipe (:host github :repo "jdtsmith/org-modern-indent"))
+(package! org-modern-indent
+ :recipe (:host github :repo "jdtsmith/org-modern-indent"))
#+end_src
#+begin_src emacs-lisp
(use-package! org-modern-indent
:defer t
-:hook (org-mode . org-modern-indent-mode))
+ :hook (org-mode . org-modern-indent-mode))
#+end_src
* Eww
#+begin_quote
@@ -1014,67 +1155,67 @@ It only renders HTML and tries its best to render CSS, so javascript is out of t
~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=")
+(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/"))
+(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))
+(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)))
+(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)))))
+(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)))
+(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")
+(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-width 100)
(setq shr-max-width 120)
(setq shr-indentation 4)
(setq shr-use-fonts nil)
@@ -1084,7 +1225,7 @@ Open a url in a secondary program, in my case ~Vivaldi~
Let's make ~eww~ go into readable mode on page enter.
#+begin_src emacs-lisp
- (add-hook 'eww-after-render-hook #'eww-readable)
+(add-hook 'eww-after-render-hook #'eww-readable)
#+end_src
** Keybindings
#+begin_src emacs-lisp
@@ -1112,18 +1253,18 @@ Elpher? I hardly know her!
Elpher is a way to use the Gemini and Gopher protocols in Emacs.
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (package! elpher)
+(package! elpher)
#+end_src
#+begin_src emacs-lisp
- (use-package! elpher)
+(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)
+(map!
+ :leader
+ :prefix "o g"
+ :desc "Elpher" "e" #'elpher
+ :desc "Browse Elpher" "b" #'elpher-browse-url-elpher)
#+end_src
* Packages
#+BEGIN_QUOTE
@@ -1136,40 +1277,40 @@ These packages are (mostly) defined in ~packages.el~ and configured here.
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)
+(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" . "dired")
- :desc "Dired" "d" #'dired
- :desc "Dired here" "h" #'dired-jump)
+(map!
+ :leader
+ :prefix ("d" . "dired")
+ :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 :tangle ~/.config/doom/packages.el
- (package! eat)
+(package! eat)
#+end_src
#+begin_src emacs-lisp
- (use-package! eat
- :defer t)
+(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
+(map!
+ :leader
+ :prefix "o"
+ :desc "Open Eat" "e" #'eat-other-window) ; dont steal the current window
#+end_src
** nov.el
@@ -1179,7 +1320,7 @@ This is pushing it.
nov.el is a way to read EPUB's in Emacs! because why buy a kindle if you have GNU?
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (package! nov)
+(package! nov)
#+end_src
#+begin_src emacs-lisp
@@ -1208,7 +1349,7 @@ nov.el is a way to read EPUB's in Emacs! because why buy a kindle if you have GN
** try
~try~ is a package that lets you ~try~ out other packages without fully installing them!
#+begin_src emacs-lisp :tangle ~/.config/doom/packages.el
- (package! try)
+(package! try)
#+end_src
That's about all ~try~ needs.
* Tramp
@@ -1231,7 +1372,7 @@ 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)
+(remove-hook 'doom-first-input-hook #'evil-snipe-mode)
#+end_src
** Lispy
@@ -1241,11 +1382,11 @@ As an example , running ~D~ on
~(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)))
+(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.
@@ -1254,28 +1395,28 @@ 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))
+(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)
+(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)
+(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)
@@ -1285,29 +1426,29 @@ Make ~o~ go right in org mode (previously ~inserted on newline~)
#+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)
+(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)
+(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 '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