aboutsummaryrefslogtreecommitdiff
path: root/config.org
diff options
context:
space:
mode:
Diffstat (limited to 'config.org')
-rw-r--r--config.org637
1 files changed, 362 insertions, 275 deletions
diff --git a/config.org b/config.org
index 74578e0..5e2ae0b 100644
--- a/config.org
+++ b/config.org
@@ -1,9 +1,10 @@
#+TITLE: Doom Emacs configuration
#+PROPERTY: header-args:emacs-lisp :tangle config.el
-* TODO Foreword
+* Foreword
Hello! This is my literate configuration for Doom Emacs.
Why literate? because org is cool!
-
+I use Doom Emacs because it's easy, simple & easy to configure.
+This config will be ported into normal Emacs in the future, but im not planning that for now.
* Splash screen
This is my custom splash screen for Emacs.
#+begin_src emacs-lisp
@@ -36,23 +37,28 @@ I also use tango from time-to-time, thats the comment.
(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))
+ (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)
+ (setq display-line-numbers-type t)
#+end_src
** Modeline
-The emacs mood line, It's nice and simple which i adore.
-I might have to try out the default modeline from Emacs sometime though.
+
+mood-line is a nice & simple modeline for emacs!
#+begin_src emacs-lisp
-(use-package! mood-line
+ (use-package! mood-line
:config
(mood-line-mode)
:custom
@@ -62,24 +68,24 @@ I might have to try out the default modeline from Emacs sometime though.
** 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
@@ -87,35 +93,42 @@ Breadcrumb is a package that shows you where you are in a file at the very top o
~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))
+ (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)))))
+ (defun my/hs-eval ()
+ (interactive)
+ (let* ((src (buffer-file-name))
+ (out (file-name-sans-extension src)))
+ (when (zerop (call-process-shell-command
+ (format "runghc %s" src) nil "*runghc-output*"))
+ (let ((buf (make-comint "hs-run" out)))
+ (display-buffer buf)))))
#+end_src
-** TODO make this a ~SPC~-based binding
Hook the function up up to f5
#+begin_src emacs-lisp
-(add-hook 'haskell-mode-hook
- (lambda ()
- (local-set-key (kbd "<f5>") #'my/hs-eval)))
+ (add-hook 'haskell-mode-hook
+ (lambda ()
+ (local-set-key (kbd "<f5>") #'my/hs-eval)))
#+end_src
** Eglot
@@ -123,17 +136,17 @@ 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))
+ (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)
+ (after! eglot
+ (cl-defmethod eglot-register-capability
+ (server (method (eql workspace/didChangeWatchedFiles)) id &key watchers)
+ nil)
#+end_src
@@ -148,8 +161,8 @@ Oxlint is a rewrite of ESLint in Rust, Not sure why oxlsp isnt its own tool, but
~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
@@ -158,33 +171,33 @@ 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))
+ (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)
+ (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
++begin_src emacs-lisp
(flycheck-add-next-checker
'javascript-eslint
'javascript-oxlint)
- (flycheck-add-next-checker
- 'html-tidy
- 'htmlhint)
+(flycheck-add-next-checker
+ 'html-tidy
+ 'htmlhint)
#+end_src
We then make flycheck check the file after saving.
@@ -227,12 +240,12 @@ 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"))
+ (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
@@ -240,105 +253,124 @@ 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 ".")
+ (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
- '("3258B28C124AB0891D6C9E929B72909EEF00CBD0")
- mml-secure-openpgp-sign-with-sender t)
+ (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
+ (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
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)
+ (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
* 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
+ (use-package! jabber
+ :config
#+end_src
We point jabber at my XMPP account:
#+begin_src emacs-lisp
-(setq jabber-account-list
- '(("roughlynamed@yax.im")))
+ (setq jabber-account-list
+ '(("roughlynamed@yax.im")))
#+end_src
And let jabber use the modeline
#+begin_src emacs-lisp
-(jabber-modeline-mode 1)
+ (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))
+ :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
@@ -350,8 +382,8 @@ 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)
+ (use-package! emms
+ :commands (emms emms-browser)
#+end_src
Configure the mappings for EMMS
@@ -374,7 +406,7 @@ In this case, it makes the emms mappings available right when emacs starts up.
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)
+(require 'emms-setup)
#+end_src
We then use ~emms-all~ to load every emms submodule. Possible variations include:
@@ -393,63 +425,63 @@ We then use ~emms-all~ to load every emms submodule. Possible variations include
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)
+(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-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-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
+ 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"))
+ 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)
+ (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)
+ (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)
+ (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)
+ (emms-lyrics-toggle-display-on-minibuffer)
#+end_src
LISTENED/LENGTH indicator in the modeline
+
#+begin_src emacs-lisp
-(emms-playing-time-mode 1)
+ (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))
+ (map! :map emms-browser-mode-map
+ :n "RET" #'emms-browser-add-tracks-and-play))
#+end_src
* Git
@@ -461,13 +493,13 @@ 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
+ (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
@@ -476,40 +508,58 @@ 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-directory "~/org/")
#+end_src
-
Now it's time to get to the guts; the main org config.
But first, some good 'ol self-documenting code:
#+begin_src emacs-lisp
-(after! org
- (setq
- org-startup-indented t
- org-startup-folded t ; fold headers on startup
- org-pretty-entities t
- org-hide-emphasis-markers t
- org-capture-templates-contexts nil
+ (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))))
+ 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)))
+ (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
@@ -518,8 +568,8 @@ Org roam is org's way of a Zettelkasten style knowledge place. Something like ob
Point org-roam at the org directory (declared seperately).
#+begin_src emacs-lisp
-(after! org-roam
- (setq org-roam-directory (file-truename "~/org/"))
+ (after! org-roam
+ (setq org-roam-directory (file-truename "~/org/"))
#+end_src
Make roam sync it's database automatically.
@@ -540,7 +590,7 @@ This is a custom function, i made it to mimic how the ~zk~ cli works when making
The template for new org notes.
#+begin_src emacs-lisp
-(setq org-roam-capture-templates
+ (setq org-roam-capture-templates
'(("d" "default" plain
"* %?"
:if-new
@@ -548,16 +598,16 @@ The template for new org notes.
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)))
+ (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
@@ -574,7 +624,7 @@ Define sections in roam.
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 ()
+ (defun my/org-roam-check-self-link ()
(when-let* ((node (org-roam-node-at-point))
(id (org-roam-node-id node)))
(save-excursion
@@ -588,7 +638,7 @@ This functions check if an org file has an inserted link to itself.
Check links that dont point to an actual file
#+begin_src emacs-lisp
-(defun my/org-roam-check-dead-links ()
+ (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)))
@@ -598,7 +648,7 @@ Check links that dont point to an actual file
*** Hooks
Run the defined above functions before every org file save
#+begin_src emacs-lisp
-(add-hook 'before-save-hook
+ (add-hook 'before-save-hook
(lambda ()
(when (org-roam-file-p)
(my/org-roam-check-self-link)
@@ -618,31 +668,31 @@ Define mappings
#+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
+ :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
+ :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
+ (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
+ org-html-head-include-default-style nil
#+end_src
Dont postamble in generated html
#+begin_src emacs-lisp
- org-html-postamble nil))
+ org-html-postamble nil))
#+end_src
** org-roam-ui
@@ -651,102 +701,110 @@ 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)
+ (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
-(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
+(use-package! org-modern-indent
+ :defer t
+:hook (org-mode . org-modern-indent-mode))
#+end_src
-
* Eww
-~Eww... What browser is that girl using?~
+#+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!)
-emms is fine on its own, but i have a config to make the experience better.
+~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)
@@ -774,13 +832,22 @@ Open a url in a secondary program, in my case ~Vivaldi~
#+end_src
* Elpher
-~Elpher Leaves Protocols Hanging as Eternally Relevant~
+#+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
-That's about... all the config this package needs.
+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
~The ones that dont belong~
@@ -803,48 +870,65 @@ Keybinds for mosey, under K because m was taken by localleader bindings
:desc "Mosey forward" "e" #'mosey-forward-bounce))
#+end_src
-** aggressive-indent
-~aggressive-indent~ is a package that makes sure every line is indented properly.
-It follows its own indentation, and forces (very aggressively) for lines to stay on there, live, while editing.
-#+begin_src emacs-lisp
-(use-package! aggressive-indent
- :config
- (global-aggressive-indent-mode 1)) ; use aggressive-indent everywhere
-#+end_src
-
** Woman
~woman~ is a way to view man pages straight in Emacs, without shelling out to the actual ~man~ binary, it stands for ~without man~
-Because i use Helm, im using the pre-configured Helm version
+Let's map this to a mnemonic binding, in this case ~Open Woman~
+
#+begin_src emacs-lisp
-(map!
- :leader
- :prefix "o"
- :desc "Woman" "w" #'helm-man-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"
- :desc "Dired" "d" #'dired
- :desc "Dired here" "h" #'dired-jump)
+ (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)
+ (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.
@@ -852,28 +936,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)
- #+end_src
+ (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)
@@ -883,31 +967,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
@@ -975,3 +1057,8 @@ Doesnt work in org files
: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