summaryrefslogtreecommitdiff
path: root/config/emacs.org
diff options
context:
space:
mode:
authorPreston Pan <ret2pop@nullring.xyz>2026-03-31 02:25:24 -0700
committerPreston Pan <ret2pop@nullring.xyz>2026-03-31 02:25:24 -0700
commitf17203b32bd1ecb0d908bbf03b9239e2efde59d6 (patch)
tree67971ff0cfc50d8e22a2af94d8aee98cdfd4d262 /config/emacs.org
parent42656b6d8e9d433ee9a032605755679157980365 (diff)
parent369c079498ffa28dec74a259e7acd69d09a36106 (diff)
Merge branch 'qtile'
Diffstat (limited to 'config/emacs.org')
-rw-r--r--config/emacs.org1312
1 files changed, 897 insertions, 415 deletions
diff --git a/config/emacs.org b/config/emacs.org
index 29794af..6dc0719 100644
--- a/config/emacs.org
+++ b/config/emacs.org
@@ -79,7 +79,7 @@ syntax elsewhere. Generally, however, these are all unordered and not dependent
;; start with sane defaults
(pixel-scroll-precision-mode 1)
- (display-battery-mode 1)
+ ;; (display-battery-mode 1)
(display-time-mode 1)
(menu-bar-mode -1)
(scroll-bar-mode -1)
@@ -87,14 +87,15 @@ syntax elsewhere. Generally, however, these are all unordered and not dependent
(global-auto-revert-mode 1)
;; load theme, fonts, and transparency. Prettify symbols.
- (set-face-attribute 'default nil :font "Iosevka Nerd Font" :height 130)
- (set-face-attribute 'variable-pitch nil :font "Lora" :height 1.1)
-
- (when (display-graphic-p)
- (set-fontset-font t 'han (font-spec :family "Noto Sans CJK SC"))
- (set-fontset-font t 'kana (font-spec :family "Noto Sans CJK JP"))
- (set-fontset-font t 'symbol (font-spec :family "Noto Color Emoji"))
- (set-fontset-font t 'symbol (font-spec :family "Symbols Nerd Font Mono") nil 'append)))
+ (unless noninteractive (when (display-graphic-p)
+ (set-face-attribute 'default nil :font "Iosevka Nerd Font" :height 130)
+ (set-face-attribute 'variable-pitch nil :font "Lora" :height 1.1)
+ (set-fontset-font t 'han (font-spec :family "Noto Sans CJK SC"))
+ (set-fontset-font t 'kana (font-spec :family "Noto Sans CJK JP"))
+ (set-fontset-font t 'emoji (font-spec :family "Noto Color Emoji") nil 'prepend)
+ (set-fontset-font t 'symbol (font-spec :family "Noto Color Emoji") nil 'append)
+ (set-fontset-font t '(#x1f300 . #x1f5ff) (font-spec :family "Noto Color Emoji") nil 'prepend)
+ (set-fontset-font t '(#xe000 . #xf8ff) (font-spec :family "Symbols Nerd Font Mono") nil 'append))))
;; imperative
(defun evil-config ()
@@ -126,11 +127,54 @@ syntax elsewhere. Generally, however, these are all unordered and not dependent
(defun remove-annoying-pairing () (remove-hook 'post-self-insert-hook #'yaml-electric-bar-and-angle t))
;; taken from blog https://writepermission.com/org-blogging-rss-feed.html
+;; (defun rp/org-rss-publish-to-rss (plist filename pub-dir)
+;; "Publish RSS with PLIST, only when FILENAME is 'rss.org'.
+;; PUB-DIR is when the output will be placed."
+;; (if (equal "rss.org" (file-name-nondirectory filename))
+;; (org-rss-publish-to-rss plist filename pub-dir)))
+
+;; (defun rp/org-rss-publish-to-rss (plist filename pub-dir)
+;; "Publish an Org file to RSS without creating Org IDs."
+;; (let* ((ext (concat "." (or (plist-get plist :rss-extension)
+;; org-rss-extension
+;; "xml")))
+;; (visiting (find-buffer-visiting filename))
+;; (buf (or visiting
+;; (let ((org-inhibit-startup t))
+;; (find-file-noselect filename)))))
+;; (unwind-protect
+;; (with-current-buffer buf
+;; (let ((org-inhibit-startup t))
+;; ;; Keep PUBDATE generation.
+;; (org-rss-add-pubdate-property)
+;; (save-buffer))
+;; (org-publish-org-to 'rss filename ext plist pub-dir))
+;; (unless visiting
+;; (kill-buffer buf)))))
+
(defun rp/org-rss-publish-to-rss (plist filename pub-dir)
- "Publish RSS with PLIST, only when FILENAME is 'rss.org'.
-PUB-DIR is when the output will be placed."
- (if (equal "rss.org" (file-name-nondirectory filename))
- (org-rss-publish-to-rss plist filename pub-dir)))
+ (org-publish-org-to
+ 'rss
+ filename
+ (concat "." (or (plist-get plist :rss-extension)
+ org-rss-extension
+ "xml"))
+ plist
+ pub-dir))
+
+;; (defun rp/org-rss-publish-to-rss (plist filename pub-dir)
+;; "Use stock RSS publishing for normal posts, but bypass UID/PUBDATE
+;; mutation for the generated rss.org sitemap."
+;; (if (string-equal (file-name-nondirectory filename) "rss.org")
+;; (org-publish-org-to
+;; 'rss
+;; filename
+;; (concat "." (or (plist-get plist :rss-extension)
+;; org-rss-extension
+;; "xml"))
+;; plist
+;; pub-dir)
+;; (org-rss-publish-to-rss plist filename pub-dir)))
(defun format-rss-feed-entry (entry style project)
"Format ENTRY for the RSS feed.
@@ -154,6 +198,7 @@ PROJECT is the current project."
(file-name-nondirectory (directory-file-name entry)))
(t entry)))
+
(defun format-rss-feed (title list)
"Generate the rss.org file from the formatted list."
(with-temp-buffer
@@ -182,6 +227,106 @@ PROJECT is the current project."
(defun rp/org-sitemap-publish-function (plist filename pub-dir)
(when (string-equal (file-name-nondirectory filename) "sitemap.xml")
(org-publish-attachment plist filename pub-dir)))
+
+(defvar my-mu4e-search-history nil)
+
+(defun my-mu4e-search-with-ivy ()
+ "Search mu4e using the native prompt wrapped in Ivy."
+ (interactive)
+ ;; We use mu4e's own query reader if possible, otherwise fallback
+ (let ((query (completing-read "mu4e search: "
+ my-mu4e-search-history nil nil nil
+ 'my-mu4e-search-history)))
+ (unless (string-blank-p query)
+ (mu4e-search query))))
+
+(defun my-mu4e-narrow-with-ivy ()
+ "Live-preview matches in the current buffer using Ivy,
+then append the typed input to the mu4e database query."
+ (interactive)
+ (let* ((current-query (or (mu4e-last-query) ""))
+ ;; 1. Collect all lines in the current headers buffer for the preview
+ (lines (save-excursion
+ (goto-char (point-min))
+ (let (res)
+ (while (not (eobp))
+ (push (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position))
+ res)
+ (forward-line 1))
+ (reverse res)))))
+
+ ;; 2. Launch Ivy with the collected lines
+ (ivy-read (format "Narrow '%s' with: " current-query)
+ lines
+ :action (lambda (_)
+ ;; 3. IGNORE the selected line (_).
+ ;; Instead, grab exactly what you typed into the prompt.
+ (let ((input ivy-text))
+ (if (string-blank-p input)
+ (message "No narrowing term provided. Canceled.")
+ ;; 4. Combine the old query with your new input and query Xapian
+ (mu4e-search (format "(%s) AND (%s)" current-query input))))))))
+
+(defvar my-current-weather "Fetching weather..."
+ "Stores the latest fetched weather string.")
+
+;; 2. The asynchronous fetch function
+(defun my-fetch-weather-async ()
+ "Fetch weather asynchronously without blocking Emacs."
+ (interactive)
+ (let ((buf (get-buffer-create " *wttr-output*")))
+ (with-current-buffer buf (erase-buffer))
+ (make-process
+ :name "wttr-fetch"
+ :buffer buf
+ :command '("curl" "-s" "--max-time" "2" "wttr.in/?format=3")
+ ;; The sentinel runs when the process finishes (success or fail)
+ :sentinel (lambda (process event)
+ (when (string-match-p "finished" event)
+ (let ((output (with-current-buffer (process-buffer process)
+ (string-trim (buffer-string)))))
+ ;; Validate output just like your old try macro did
+ (if (or (string-blank-p output)
+ (string-match-p "BLOCK FAILED\\|Unknown location\\|<html>" output))
+ (setq my-current-weather "Weather currently unavailable.")
+ (setq my-current-weather output)))
+
+ ;; If the dashboard is visible, refresh it so the new text appears!
+ (when (get-buffer-window "*dashboard*" 'visible)
+ (with-current-buffer "*dashboard*"
+ (dashboard-refresh-buffer))))))))
+
+;; 3. Your new, simplified (and fast!) dashboard widget
+(defun my-dashboard-insert-weather-clock (list-size)
+ "Insert a styled clock and the pre-fetched weather variable."
+ (let ((clock (format-time-string "%I:%M %p • %A, %B %d")))
+ (insert "\n")
+ (insert (propertize clock 'face '(:height 1.5 :weight bold :foreground "#51afef")))
+ (insert "\n\n")
+ ;; Just insert the variable. No network calls happen here.
+ (insert (propertize my-current-weather 'face '(:foreground "#a9a1e1" :weight semi-bold)))
+ (insert "\n\n")))
+
+(defun my-refresh-dashboard-if-visible ()
+ "Refresh the dashboard buffer, but only if it's currently visible in a window."
+ (when (get-buffer-window "*dashboard*" 'visible)
+ (with-current-buffer "*dashboard*"
+ (dashboard-refresh-buffer))))
+
+(defun my-setup-dashboard-timer ()
+ "Start a timer to refresh the dashboard every 60 seconds."
+ ;; Cancel any existing timer first to avoid creating multiple timers
+ (when (timerp my-dashboard-refresh-timer)
+ (cancel-timer my-dashboard-refresh-timer))
+ ;; Run the refresh function every 60 seconds
+ (setq my-dashboard-refresh-timer (run-with-timer 60 60 #'my-refresh-dashboard-if-visible)))
+
+(defun my-fix-htmlize-invalid-face-bug (orig-fn face attribute &optional frame inherit)
+ (if (facep face)
+ (funcall orig-fn face attribute frame inherit)
+ 'unspecified))
#+end_src
** Random Packages
These are packages that I require in order to write some scripts in emacs-lisp.
@@ -202,54 +347,67 @@ configuration as they are also defined using the use-package macros. Some of the
have documentation strings attached, so it is easy to follow what the individual options do.
Emacs is self documenting, after all!
#+begin_src emacs-lisp :tangle ../nix/init.el
- (use-package emacs
- :custom
- ;; global defaults
- (enable-local-variables :all "don't emit local variable warnings when publishing")
- (indent-tabs-mode nil "no real tabs, only spaces")
- (tab-width 2 "tab show as 2 spaces")
- (standard-indent 2 "base indentation")
- (custom-safe-themes t "I already manage my themes with nix")
- (custom-file null-device "Don't save custom configs")
-
- ;; Startup errors
- (warning-minimum-level :emergency "Supress emacs warnings")
- (confirm-kill-processes nil "Don't ask to quit")
- (debug-ignored-errors (cons 'remote-file-error debug-ignored-errors) "Remove annoying error from debug errors")
- (browse-url-generic-program "qutebrowser" "set browser to librewolf")
- (browse-url-secondary-browser-function 'browse-url-generic "set browser")
- (browse-url-browser-function 'browse-url-generic "set browser")
- (default-frame-alist '((alpha-background . 80)
- (vertical-scroll-bars)
- (internal-border-width . 24)
- (left-fringe . 8)
- (right-fringe . 8)))
+(use-package emacs
+ :custom
+ ;; global defaults
+ (enable-local-variables :all "don't emit local variable warnings when publishing")
+ (indent-tabs-mode nil "no real tabs, only spaces")
+ (tab-width 2 "tab show as 2 spaces")
+ (standard-indent 2 "base indentation")
+ (custom-safe-themes t "I already manage my themes with nix")
+ (custom-file null-device "Don't save custom configs")
+ (jit-lock-chunk-size 16384 "actually load code blocks")
+ (jit-lock-stealth-time 1.25 "fontify in the background after 1.25s of idle time")
+ (jit-lock-stealth-nice 0.1 "don't freeze Emacs while stealth fontifying")
+ ;; ---------------------------------------------------------------------------
+ ;; UTF-8 Everywhere
+ ;; ---------------------------------------------------------------------------
+ (set-language-environment "UTF-8")
+ (set-default-coding-systems 'utf-8)
+ (prefer-coding-system 'utf-8)
+ (set-terminal-coding-system 'utf-8)
+ (set-keyboard-coding-system 'utf-8)
+ (set-selection-coding-system 'utf-8)
+ (locale-coding-system 'utf-8)
+ (use-default-font-for-symbols nil)
- ;; Mouse wheel
- (mouse-wheel-scroll-amount '(1 ((shift) . 1)) "Nicer scrolling")
- (mouse-wheel-progressive-speed nil "Make scrolling non laggy")
- (mouse-wheel-follow-mouse 't "Scroll correct window")
- (scroll-conservatively 101 "Sort of smooth scrolling")
- (scroll-step 1 "Scroll one line at a time")
- (debug-on-error nil "Don't make the annoying popups")
- (display-time-24hr-format t "Use 24 hour format to read the time")
- (display-line-numbers-type 'relative "Relative line numbers for easy vim jumping")
- (use-short-answers t "Use y instead of yes")
- (make-backup-files nil "Don't make backups")
- (display-fill-column-indicator-column 150 "Draw a line at 100 characters")
- (fill-column 150)
- (line-spacing 2 "Default line spacing")
- (c-doc-comment-style '((c-mode . doxygen)
- (c++-mode . doxygen)))
+ ;; Startup errors
+ (warning-minimum-level :emergency "Supress emacs warnings")
+ (confirm-kill-processes nil "Don't ask to quit")
+ (debug-ignored-errors (cons 'remote-file-error debug-ignored-errors) "Remove annoying error from debug errors")
+ (browse-url-generic-program "qutebrowser" "set browser to librewolf")
+ (browse-url-secondary-browser-function 'browse-url-generic "set browser")
+ (browse-url-browser-function 'browse-url-generic "set browser")
+ (default-frame-alist '((alpha-background . 100)
+ (vertical-scroll-bars)
+ (internal-border-width . 24)
+ (left-fringe . 8)
+ (right-fringe . 8)))
+ ;; Mouse wheel
+ (mouse-wheel-scroll-amount '(1 ((shift) . 1)) "Nicer scrolling")
+ (mouse-wheel-progressive-speed nil "Make scrolling non laggy")
+ (mouse-wheel-follow-mouse 't "Scroll correct window")
+ (scroll-conservatively 101 "Sort of smooth scrolling")
+ (scroll-step 1 "Scroll one line at a time")
+ (debug-on-error nil "Don't make the annoying popups")
+ (display-time-24hr-format t "Use 24 hour format to read the time")
+ (display-line-numbers-type 'relative "Relative line numbers for easy vim jumping")
+ (use-short-answers t "Use y instead of yes")
+ (make-backup-files nil "Don't make backups")
+ (display-fill-column-indicator-column 150 "Draw a line at 100 characters")
+ (fill-column 150)
+ (line-spacing 2 "Default line spacing")
+ (c-doc-comment-style '((c-mode . doxygen)
+ (c++-mode . doxygen)))
- :hook ((text-mode . visual-line-mode)
- (prog-mode . display-line-numbers-mode)
- (prog-mode . display-fill-column-indicator-mode)
- (org-mode . auto-fill-mode)
- (org-mode . display-fill-column-indicator-mode)
- (org-mode . display-line-numbers-mode))
- :config (emacs-config))
+ :hook ((text-mode . visual-line-mode)
+ (prog-mode . display-line-numbers-mode)
+ (prog-mode . display-fill-column-indicator-mode)
+ (org-mode . auto-fill-mode)
+ (org-mode . display-fill-column-indicator-mode)
+ (org-mode . display-line-numbers-mode))
+ :config (emacs-config))
#+end_src
As you can see, the config (and sometimes the init section) of most of these use-package blocks
contain most of the imperative commands. In fact, most of the configurations are completely
@@ -261,29 +419,38 @@ a variable an option. Often you will see a config section of a use-package decla
only one or two entries, which is intentional, as I've designed this configuration to put as
little in config as possible. I hardly consider most of this configuration to be imperative, but
of course Emacs was not designed to be fully imperative.
+** Network
+#+begin_src emacs-lisp :tangle ../nix/init.el
+(use-package enwc :custom (enwc-default-backend 'nm "use networkmanager backend"))
+#+end_src
+** System Monitor
+#+begin_src emacs-lisp :tangle ../nix/init.el
+(use-package proced
+ :custom (proced-enable-color-flag t "use colors in proced"))
+#+end_src
** Org Mode
This is my org mode configuration, which also configures latex.
#+begin_src emacs-lisp :tangle ../nix/init.el
- (use-package org
- :demand t
- :after (f s dash nix-mode)
- :hook
- ((org-mode . remove-annoying-pairing))
- :custom
- (org-export-allow-bind-keywords t "don't emit warnings")
- (org-confirm-babel-evaluate nil "I want to evaluate stuff when publishing")
- ;; Fix terrible indentation issues
- (org-edit-src-content-indentation 0)
- (org-src-tab-acts-natively t)
- (org-src-preserve-indentation t)
+(use-package org
+ :demand t
+ :after (f s dash nix-mode)
+ :hook
+ ((org-mode . remove-annoying-pairing))
+ :custom
+ (org-export-allow-bind-keywords t "don't emit warnings")
+ (org-confirm-babel-evaluate nil "I want to evaluate stuff when publishing")
+ ;; Fix terrible indentation issues
+ (org-edit-src-content-indentation 0)
+ (org-src-tab-acts-natively t)
+ (org-src-preserve-indentation t)
- (TeX-PDF-mode t)
- (org-confirm-babel-evaluate nil "Don't ask to evaluate code block")
- (org-export-with-broken-links t "publish website even with broken links")
- (org-src-fontify-natively t "Colors!")
+ (TeX-PDF-mode t)
+ (org-confirm-babel-evaluate nil "Don't ask to evaluate code block")
+ (org-export-with-broken-links t "publish website even with broken links")
+ (org-src-fontify-natively t "Colors!")
- ;; org-latex
- (org-format-latex-header "\\documentclass{article} \
+ ;; org-latex
+ (org-format-latex-header "\\documentclass{article} \
\\usepackage[usenames]{color} \
[DEFAULT-PACKAGES] \
[PACKAGES] \
@@ -303,187 +470,212 @@ This is my org mode configuration, which also configures latex.
\\addtolength{\\topmargin}{-2.54cm} \
\\usepackage{amsmath} \
")
- (org-preview-latex-image-directory (expand-file-name "~/.cache/ltximg/") "don't use weird cache location")
- (org-latex-preview-ltxpng-directory (expand-file-name "~/.cache/ltximg/") "don't use weird cache location")
- (org-latex-to-html-convert-command "printf '%%s' %i | pandoc -f latex -t html --mathml | tr -d '\\n' | sed -e 's/^<p>//' -e 's/<\\/p>$//'" "latex to MathML with special character handling")
- (org-latex-to-mathml-convert-command "printf '%%s' %i | pandoc -f latex -t html --mathml | tr -d '\\n' | sed -e 's/^<p>//' -e 's/<\\/p>$//'" "latex to MathML with special character handling")
+ (org-preview-latex-image-directory (expand-file-name "~/.cache/ltximg/") "don't use weird cache location")
+ (org-latex-preview-ltxpng-directory (expand-file-name "~/.cache/ltximg/") "don't use weird cache location")
+ (org-latex-to-html-convert-command "printf '%%s' %i | pandoc -f latex -t html --mathml | tr -d '\\n' | sed -e 's/^<p>//' -e 's/<\\/p>$//'" "latex to MathML with special character handling")
+ (org-latex-to-mathml-convert-command "printf '%%s' %i | pandoc -f latex -t html --mathml | tr -d '\\n' | sed -e 's/^<p>//' -e 's/<\\/p>$//'" "latex to MathML with special character handling")
- (TeX-engine 'xetex "set xelatex as default engine")
- (preview-default-option-list '("displaymath" "textmath" "graphics") "preview latex")
- ;; (preview-image-type 'png "Use PNGs")
- (org-preview-latex-default-process 'dvipng)
- (org-format-latex-options
- '(:foreground default
- :background default
- :scale 2
- :html-foreground "Black"
- :html-background "Transparent"
- :html-scale 1.5
- :matchers ("begin" "$1" "$" "$$" "\\(" "\\[")) "space latex better")
- (org-return-follows-link t "be able to follow links without mouse")
- (org-startup-indented t "Indent the headings")
- (org-image-actual-width '(300) "Cap width")
- (org-startup-with-latex-preview t "see latex previews on opening file")
- (org-startup-with-inline-images t "See images on opening file")
- (org-hide-emphasis-markers t "prettify org mode")
- (org-use-sub-superscripts "{}" "Only display superscripts and subscripts when enclosed in {}")
- (org-pretty-entities t "prettify org mode")
- (org-agenda-files (list "~/monorepo/agenda.org" "~/org/notes.org" "~/org/agenda.org") "set default org files")
- (org-default-notes-file (concat org-directory "/notes.org") "Notes file")
+ (TeX-engine 'xetex "set xelatex as default engine")
+ (preview-default-option-list '("displaymath" "textmath" "graphics") "preview latex")
+ ;; (preview-image-type 'png "Use PNGs")
+ (org-preview-latex-default-process 'dvipng)
+ (org-format-latex-options
+ '(:foreground default
+ :background default
+ :scale 2
+ :html-foreground "Black"
+ :html-background "Transparent"
+ :html-scale 1.5
+ :matchers ("begin" "$1" "$" "$$" "\\(" "\\[")) "space latex better")
+ (org-return-follows-link t "be able to follow links without mouse")
+ (org-startup-indented t "Indent the headings")
+ (org-image-actual-width '(300) "Cap width")
+ (org-startup-with-latex-preview t "see latex previews on opening file")
+ (org-startup-with-inline-images t "See images on opening file")
+ (org-hide-emphasis-markers t "prettify org mode")
+ (org-use-sub-superscripts "{}" "Only display superscripts and subscripts when enclosed in {}")
+ (org-pretty-entities t "prettify org mode")
+ (org-agenda-files (list "~/monorepo/agenda.org" "~/org/notes.org" "~/org/agenda.org") "set default org files")
+ (org-agenda-block-separator "")
+ (org-fontify-whole-heading-line t)
+ (org-fontify-done-headline t)
+ (org-fontify-quote-and-verse-blocks t)
+ (org-default-notes-file (concat org-directory "/notes.org") "Notes file")
- ;; ricing
- (org-auto-align-tags nil)
- (org-tags-column 0)
- (org-catch-invisible-edits 'show-and-error)
- (org-special-ctrl-a/e t)
- (org-insert-heading-respect-content t)
- (org-hide-emphasis-markers t)
- (org-pretty-entities t)
- (org-agenda-tags-column 0)
- (org-ellipsis "…")
- :config
- (org-babel-do-load-languages 'org-babel-load-languages
- '((shell . t)
- (python . t)
- (nix . t)
- (scheme . t)
- (latex . t))))
+ ;; ricing
+ (org-auto-align-tags nil)
+ (org-tags-column 0)
+ (org-catch-invisible-edits 'show-and-error)
+ (org-special-ctrl-a/e t)
+ (org-insert-heading-respect-content t)
+ (org-hide-emphasis-markers t)
+ (org-pretty-entities t)
+ (org-agenda-tags-column 0)
+ (org-ellipsis "…")
+ :config
+ (org-babel-do-load-languages 'org-babel-load-languages
+ '((shell . t)
+ (python . t)
+ (nix . t)
+ (scheme . t)
+ (latex . t))))
- (use-package org-tempo
- :after org)
+(use-package org-tempo
+ :after org)
- (use-package org-habit
- :after org
- :custom
- (org-habit-preceding-days 7 "See org habit entries")
- (org-habit-following-days 35 "See org habit entries")
- (org-habit-show-habits t "See org habit entries")
- (org-habit-show-habits-only-for-today nil "See org habit entries")
- (org-habit-show-all-today t "Show org habit graph"))
+(use-package org-habit
+ :after org
+ :custom
+ (org-habit-preceding-days 7 "See org habit entries")
+ (org-habit-following-days 35 "See org habit entries")
+ (org-habit-show-habits t "See org habit entries")
+ (org-habit-show-habits-only-for-today nil "See org habit entries")
+ (org-habit-show-all-today t "Show org habit graph"))
- (use-package htmlize
- :demand t
- :after (catppuccin-theme doom-themes yaml-mode))
+(use-package htmlize
+ :demand t
+ :after (doom-themes yaml-mode)
+ :config (advice-add 'face-attribute :around #'my-fix-htmlize-invalid-face-bug))
- (unless noninteractive
- (use-package htmlize
- :after (doom-themes)))
+(use-package ox-latex
+ :after (org)
+ :custom
+ (org-latex-compiler "xelatex" "Use latex as default")
+ (org-latex-pdf-process '("xelatex -interaction=nonstopmode -output-directory=%o %f") "set xelatex as default"))
- (use-package ox-latex
- :after (org)
- :custom
- (org-latex-compiler "xelatex" "Use latex as default")
- (org-latex-pdf-process '("xelatex -interaction=nonstopmode -output-directory=%o %f") "set xelatex as default"))
+(use-package ox-html
+ :demand t
+ :after (org htmlize)
+ :custom
+ (org-html-htmlize-output-type 'css "allow styling from CSS file")
+ (org-html-with-latex 'html "let my html handler handle latex")
+ (org-html-mathjax-options nil "disable mathjax, use MathML")
+ (org-html-mathjax-template "" "disable mathjax, use MathML")
+ (org-html-head-include-default-style nil "use my own css for everything")
+ (org-html-head-include-scripts nil "use my own js for everything")
+ (org-html-postamble (concat "Copyright © 2024 " system-fullname) "set copyright notice on bottom of site")
+ (org-html-divs '((preamble "header" "preamble")
+ (content "main" "content")
+ (postamble "footer" "postamble")) "semantic html exports")
+ (org-html-viewport '((width "device-width")
+ (initial-scale "1.0")
+ (minimum-scale "1.0")) "Prevent zooming out past default size")
+ :config (advice-add 'org-html-latex-environment :around #'org-html-latex-environment-pandoc-fix))
- (use-package ox-html
- :demand t
- :after (org htmlize)
- :custom
- (org-html-htmlize-output-type 'css "allow styling from CSS file")
- (org-html-with-latex 'html "let my html handler handle latex")
- (org-html-mathjax-options nil "disable mathjax, use MathML")
- (org-html-mathjax-template "" "disable mathjax, use MathML")
- (org-html-head-include-default-style nil "use my own css for everything")
- (org-html-head-include-scripts nil "use my own js for everything")
- (org-html-postamble (concat "Copyright © 2024 " system-fullname) "set copyright notice on bottom of site")
- (org-html-divs '((preamble "header" "preamble")
- (content "main" "content")
- (postamble "footer" "postamble")) "semantic html exports")
- (org-html-viewport '((width "device-width")
- (initial-scale "1.0")
- (minimum-scale "1.0")) "Prevent zooming out past default size")
- :config (advice-add 'org-html-latex-environment :around #'org-html-latex-environment-pandoc-fix))
+(use-package ox-rss
+ :after org
+ :demand t)
- (use-package ox-rss
- :after org
- :demand t)
+(use-package ox-publish
+ :demand t
+ :after (org f s dash ox-html ox-rss)
+ :custom
+ (org-publish-project-alist
+ `(("website-org"
+ :base-directory "~/monorepo"
+ :base-extension "org"
+ :exclude "nix/README\\.org\\|blog/rss\\.org\\|result/.*\\|nix/.*"
+ :publishing-directory "~/website_html"
+ :with-author t
+ :with-date t
+ :with-broken-links t
+ :language en
- (use-package ox-publish
- :demand t
- :after (org f s dash ox-html ox-rss)
- :custom
- (org-publish-project-alist
- `(("website-org"
- :base-directory "~/monorepo"
- :base-extension "org"
- :exclude "nix/README\\.org\\|blog/rss\\.org\\|result/.*\\|nix/.*"
- :publishing-directory "~/website_html"
- :with-author t
- :with-date t
- :with-broken-links t
- :language en
+ :recursive t
+ :publishing-function org-html-publish-to-html
+ :headline-levels 4
+ :html-footnotes-section "<div id=\"footnotes\"><hr><div id=\"text-footnotes\"><span class=\"footnotes-label-hidden\">%s</span>%s</div></div>"
+ :html-head ,(concat "<link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS Feed\" href=\"/blog/rss.xml\"><meta name=\"theme-color\" content=\"#ffffff\">\n<link rel=\"preload\" href=\"/fonts/Inconsolata-Medium.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n<meta name=\"theme-color\" content=\"#ffffff\">\n<link rel=\"preload\" href=\"/fonts/Lora-Medium.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n<link rel=\"preload\" href=\"/fonts/CormorantGaramond-Bold.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n<link rel=\"preload\" href=\"/fonts/CormorantGaramond-Medium.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n<link rel=\"manifest\" href=\"/site.webmanifest\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/favicon-16x16.png\">\n<link rel=\"mask-icon\" href=\"/safari-pinned-tab.svg\" color=\"#5bbad5\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/favicon-32x32.png\">\n<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/apple-touch-icon.png\"><meta name=\"msapplication-TileColor\" content=\"#da532c\">\n"
+ "<style>"
+ (->> (create-htmlize-css)
+ (s-replace-regexp "<style[^>]*>" "")
+ (s-replace "</style>" "")
+ (s-replace "<![CDATA[/*><![CDATA[/*>\n" "")
+ (s-replace "/*]]>*/-->" "")
+ (s-trim)
+ (minify-css))
+ (f-read-text "~/monorepo/style.css" 'utf-8)
+ "</style>")
+ :html-preamble t
+ :html-preamble-format (("en" "<p class=\"preamble\"><a href=\"/index.html\">home</a> | <a href=\"./index.html\">section main page</a> | <a href=\"/blog/rss.xml\">rss feed</a></p><hr>"))
- :recursive t
- :publishing-function org-html-publish-to-html
- :headline-levels 4
- :html-footnotes-section "<div id=\"footnotes\"><hr><div id=\"text-footnotes\"><span class=\"footnotes-label-hidden\">%s</span>%s</div></div>"
- :html-head ,(concat "<meta name=\"theme-color\" content=\"#ffffff\">\n<link rel=\"preload\" href=\"/fonts/Inconsolata-Medium.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n<meta name=\"theme-color\" content=\"#ffffff\">\n<link rel=\"preload\" href=\"/fonts/Lora-Medium.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n<link rel=\"preload\" href=\"/fonts/CormorantGaramond-Bold.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n<link rel=\"preload\" href=\"/fonts/CormorantGaramond-Medium.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n<link rel=\"manifest\" href=\"/site.webmanifest\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/favicon-16x16.png\">\n<link rel=\"mask-icon\" href=\"/safari-pinned-tab.svg\" color=\"#5bbad5\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/favicon-32x32.png\">\n<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/apple-touch-icon.png\"><meta name=\"msapplication-TileColor\" content=\"#da532c\">\n"
- "<style>"
- (->> (create-htmlize-css)
- (s-replace-regexp "<style[^>]*>" "")
- (s-replace "</style>" "")
- (s-replace "<![CDATA[/*><![CDATA[/*>\n" "")
- (s-replace "/*]]>*/-->" "")
- (s-trim)
- (minify-css))
- (f-read-text "~/monorepo/style.css" 'utf-8)
- "</style>")
- :html-preamble t
- :html-preamble-format (("en" "<p class=\"preamble\"><a href=\"/index.html\">home</a> | <a href=\"./index.html\">section main page</a> | <a href=\"/blog/rss.xml\">rss feed</a></p><hr>"))
+ ;; sitemap.html stuff
+ :auto-sitemap t
+ :sitemap-filename "sitemap.org"
+ :sitemap-title "Site Index"
+ :sitemap-style list
+ :sitemap-sort-files anti-chronologically)
- ;; sitemap.html stuff
- :auto-sitemap t
- :sitemap-filename "sitemap.org"
- :sitemap-title "Site Index"
- :sitemap-style list
- :sitemap-sort-files anti-chronologically)
+ ;; ("website-blog-rss"
+ ;; :base-directory "~/monorepo/blog"
+ ;; :base-extension "org"
+ ;; :recursive nil
+ ;; :exclude "rss\\.org\\|index\\.org\\|404\\.org"
+ ;; :rss-extension "xml"
- ("website-blog-rss"
- :base-directory "~/monorepo/blog"
- :base-extension "org"
- :recursive nil
- :exclude "rss\\.org\\|index\\.org\\|404\\.org"
- :rss-extension "xml"
+ ;; :publishing-directory "~/website_html/blog"
+ ;; :publishing-function rp/org-rss-publish-to-rss
+ ;; :html-link-home "https://ret2pop.net/blog/"
+ ;; :html-link-use-abs-url t
- :publishing-directory "~/website_html/blog"
- :publishing-function rp/org-rss-publish-to-rss
- :html-link-home "https://ret2pop.net/blog/"
- :html-link-use-abs-url t
+ ;; ;; use custom sitemap functionality to publish rss feed
+ ;; :auto-sitemap t
+ ;; :sitemap-filename "rss.org"
+ ;; :sitemap-title "Blog Feed"
+ ;; :sitemap-style list
+ ;; :sitemap-sort-folders ignore
+ ;; :sitemap-sort-files anti-chronologically
+ ;; :sitemap-format-entry format-rss-feed-entry
+ ;; :sitemap-function format-rss-feed)
- ;; use custom sitemap functionality to publish rss feed
- :auto-sitemap t
- :sitemap-filename "rss.org"
- :sitemap-title "Blog Feed"
- :sitemap-style list
- :sitemap-sort-folders ignore
- :sitemap-sort-files anti-chronologically
- :sitemap-format-entry format-rss-feed-entry
- :sitemap-function format-rss-feed)
+ ("website-blog-rss"
+ :base-directory "~/monorepo/blog"
+ :base-extension "org"
+ :recursive nil
- ("website-sitemap-xml"
- :base-directory "~/monorepo"
- :base-extension "org"
- :recursive t
- :exclude "nix/README\\.org\\|blog/rss\\.org"
- :publishing-directory "~/website_html"
- :publishing-function rp/org-sitemap-publish-function
- :auto-sitemap t
- :sitemap-filename "sitemap.xml"
- :sitemap-format-entry org-sitemap-format-entry-xml
- :sitemap-style list
- :sitemap-function org-sitemap-format-xml)
+ ;; Only publish the generated feed source.
+ :exclude ".*"
+ :include ("rss.org")
- ("website-static"
- :base-directory "~/monorepo"
- :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|ico\\|asc\\|pub\\|webmanifest\\|xml\\|svg\\|txt\\|webp\\|conf"
- :publishing-directory "~/website_html/"
- :recursive t
- :publishing-function org-publish-attachment)
+ :rss-extension "xml"
+ :publishing-directory "~/website_html/blog"
+ :publishing-function rp/org-rss-publish-to-rss
+ :html-link-home "https://ret2pop.net/blog/"
+ :html-link-use-abs-url t
- ("website"
- :auto-sitemap t
- :components ("website-org" "website-static" "website-blog-rss" "website-sitemap-xml")))
- "functions to publish website"))
+ :auto-sitemap t
+ :sitemap-filename "rss.org"
+ :sitemap-title "Blog Feed"
+ :sitemap-style list
+ :sitemap-sort-folders ignore
+ :sitemap-sort-files anti-chronologically
+ :sitemap-format-entry format-rss-feed-entry
+ :sitemap-function format-rss-feed)
+
+ ("website-sitemap-xml"
+ :base-directory "~/monorepo"
+ :base-extension "org"
+ :recursive t
+ :exclude "nix/README\\.org\\|blog/rss\\.org"
+ :publishing-directory "~/website_html"
+ :publishing-function rp/org-sitemap-publish-function
+ :auto-sitemap t
+ :sitemap-filename "sitemap.xml"
+ :sitemap-format-entry org-sitemap-format-entry-xml
+ :sitemap-style list
+ :sitemap-function org-sitemap-format-xml)
+
+ ("website-static"
+ :base-directory "~/monorepo"
+ :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|ico\\|asc\\|pub\\|webmanifest\\|xml\\|svg\\|txt\\|webp\\|conf"
+ :publishing-directory "~/website_html/"
+ :recursive t
+ :publishing-function org-publish-attachment)
+
+ ("website"
+ :auto-sitemap t
+ :components ("website-org" "website-static" "website-blog-rss" "website-sitemap-xml")))
+ "functions to publish website"))
#+end_src
As you can see, I only have one real entry in config here (I don't count requires even though
they have to be on the top)
@@ -497,8 +689,7 @@ I already pull in all-the-icons, but we need the emacs package to load it correc
I use this in org-mode so that I can read/write with variable pitched font. Feels like I'm reading a blog article or something.
#+begin_src emacs-lisp :tangle ../nix/init.el
(use-package mixed-pitch
- :hook ((text-mode . mixed-pitch-mode)
- (org-mode . mixed-pitch-mode))
+ :hook ((org-mode . mixed-pitch-mode))
:custom (mixed-pitch-set-height t)
:config
(dolist (face '(org-latex-and-related
@@ -518,7 +709,19 @@ I want to show indent lines in emacs so that I can line things up.
#+begin_src emacs-lisp :tangle ../nix/init.el
(use-package indent-bars
:after (nix-mode)
- :hook ((python-mode yaml-mode nix-mode) . indent-bars-mode))
+ :hook (
+ (python-ts-mode . indent-bars-mode)
+ (css-ts-mode . indent-bars-mode)
+ (haskell-mode . indent-bars-mode)
+ (js-ts-mode . indent-bars-mode)
+ (c-ts-mode . indent-bars-mode)
+ (c++-ts-mode . indent-bars-mode)
+ (rust-ts-mode . indent-bars-mode)
+ (go-ts-mode . indent-bars-mode)
+ (python-mode . indent-bars-mode)
+ (yaml-ts-mode . indent-bars-mode)
+ (nix-mode . indent-bars-mode)
+ (emacs-lisp-mode . indent-bars-mode)))
#+end_src
* Autopair
Use electric-pair to automatically complete pairs of things. We need to change
@@ -556,15 +759,29 @@ Yasnippets are useful for macros that automatically complete to an arbitrary for
Company-mode! We need this to do autocomplete stuff.
#+begin_src emacs-lisp :tangle ../nix/init.el
(use-package company
- :custom (company-backends '(company-ispell company-capf company-yasnippet company-files) "Set company backends")
+ :custom
+ (company-backends '(company-capf company-files company-yasnippet company-ispell))
+
+ (company-idle-delay 0.1)
+ (company-minimum-prefix-length 1)
+ (company-require-match nil)
+ (company-selection-wrap-around t)
+ (company-tooltip-align-annotations t)
+
:bind (:map company-active-map
("RET" . nil)
("<return>" . nil)
- ("tab" . company-complete-selection)
- ("<tab>" . company-complete-selection))
+ ("TAB" . company-complete-selection)
+ ("<tab>" . company-complete-selection)
+ ("C-j" . company-select-next)
+ ("C-k" . company-select-previous))
+
:hook ((after-init . global-company-mode)))
+
(use-package company-box
- :hook (company-mode . company-box-mode))
+ :hook (company-mode . company-box-mode)
+ :custom
+ (company-box-scrollbar nil))
#+end_src
* Spelling
This loads a dictionary so that I can save certain words to be not misspelled and also have
@@ -586,41 +803,200 @@ this spellcheck during org mode.
* Packages
First, some small configurations and some evil-mode initilaization because I like vim keybindings:
#+begin_src emacs-lisp :tangle ../nix/init.el
-(use-package evil
- :demand t
- :custom (evil-want-keybinding nil "Don't load a whole bunch of default keybindings")
- :bind
- (:map evil-normal-state-map
- ("/" . swiper)
- ("?" . (lambda () (interactive) (swiper "--reverse"))))
- :config (evil-config))
+ (use-package evil
+ :demand t
+ :custom (evil-want-keybinding nil "Don't load a whole bunch of default keybindings")
+ :bind
+ (:map evil-normal-state-map
+ ("/" . swiper)
+ ("?" . (lambda () (interactive) (swiper "--reverse"))))
+ :config (evil-config))
-(use-package evil-collection
- :demand t
- :after (evil)
- :bind (:map evil-motion-state-map
- ("SPC" . nil)
- ("RET" . nil)
- ("TAB" . nil))
- :config (evil-collection-init))
+ (use-package evil-collection
+ :demand t
+ :after (evil)
+ :bind (:map evil-motion-state-map
+ ("SPC" . nil)
+ ("RET" . nil)
+ ("TAB" . nil))
+ :config (evil-collection-init))
+
+ (use-package evil-commentary
+ :after (evil)
+ :config (evil-commentary-mode))
+
+ (use-package evil-org
+ :after (evil org)
+ :hook (org-mode . evil-org-mode))
+
+ (use-package evil-org-agenda
+ :after (evil-org)
+ :config (evil-org-agenda-set-keys))
+
+ (use-package which-key
+ :config (which-key-mode))
+
+ (use-package page-break-lines
+ :config (page-break-lines-mode))
+
+ (use-package evil-mc
+ :after evil
+ :config (global-evil-mc-mode 1))
+
+ (use-package evil-surround
+ :after evil
+ :config
+ (global-evil-surround-mode 1))
+
+ (use-package evil-lion
+ :config
+ (evil-lion-mode))
+
+ (use-package evil-multiedit
+ :after evil
+ :config
+ (evil-multiedit-default-keybinds))
+
+ (use-package evil-textobj-tree-sitter
+ :ensure t
+ ;; Ensure Evil is loaded first so the text-object maps exist
+ :after evil
+
+ ;; 1. The Keybindings
+ :bind ((:map evil-outer-text-objects-map
+ ("f" . my-treesit-outer-function)
+ ("c" . my-treesit-outer-class)
+ ("a" . my-treesit-outer-arg))
+
+ (:map evil-inner-text-objects-map
+ ("f" . my-treesit-inner-function)
+ ("c" . my-treesit-inner-class)
+ ("a" . my-treesit-inner-arg))
+
+ (:map evil-normal-state-map
+ ("] f" . my-treesit-goto-next-function)
+ ("[ f" . my-treesit-goto-prev-function)
+ ("] c" . my-treesit-goto-next-class)
+ ("[ c" . my-treesit-goto-prev-class)))
+
+ ;; 2. The Command Definitions
+ :config
+ ;; Link the custom names we bound above to the actual Tree-sitter closures
+ (defalias 'my-treesit-outer-function (evil-textobj-tree-sitter-get-textobj "function.outer"))
+ (defalias 'my-treesit-inner-function (evil-textobj-tree-sitter-get-textobj "function.inner"))
+
+ (defalias 'my-treesit-outer-class (evil-textobj-tree-sitter-get-textobj "class.outer"))
+ (defalias 'my-treesit-inner-class (evil-textobj-tree-sitter-get-textobj "class.inner"))
+
+ ;; "a" is standard Vim terminology for "argument" (parameter)
+ (defalias 'my-treesit-outer-arg (evil-textobj-tree-sitter-get-textobj "parameter.outer"))
+ (defalias 'my-treesit-inner-arg (evil-textobj-tree-sitter-get-textobj "parameter.inner"))
+
+ ;; Navigation commands are standard interactive functions, so we wrap them cleanly
+ (defun my-treesit-goto-next-function ()
+ (interactive)
+ (evil-textobj-tree-sitter-goto-textobj "function.outer"))
+
+ (defun my-treesit-goto-prev-function ()
+ (interactive)
+ (evil-textobj-tree-sitter-goto-textobj "function.outer" t))
+
+ (defun my-treesit-goto-next-class ()
+ (interactive)
+ (evil-textobj-tree-sitter-goto-textobj "class.outer"))
+
+ (defun my-treesit-goto-prev-class ()
+ (interactive)
+ (evil-textobj-tree-sitter-goto-textobj "class.outer" t)))
+
+
+ (use-package general
+ :after (evil evil-collection)
+ :config
+ (general-create-definer leader-key :prefix "SPC")
+ ;; these are just bindings but the symbols are all lazily handled by general
+ (create-irc-servers
+ (znc "ret2pop.net" "5000")
+ (prestonpan "nullring.xyz" "6697")
+ (libera-chat "irc.libera.chat" "6697")
+ (efnet "irc.prison.net" "6697")
+ (matrix-org "matrix.org" "8448")
+ (gimp-org "irc.gimp.org" "6697"))
+
+ (leader-key 'normal
+ "o c" '(org-capture :wk "Capture")
+ ;; Org Mode
+ "n" '(:ignore t :wk "Org mode plugins")
+ "n j j" '(org-journal-new-entry :wk "Make new journal entry")
+ "n r f" '(org-roam-node-find :wk "Find roam node")
+ "n r i" '(org-roam-node-insert :wk "Insert roam node")
+ "n r a" '(org-roam-alias-add :wk "Add alias to org roam node")
+ "n r g" '(org-roam-graph :wk "Graph roam database")
+ "m I" '(org-id-get-create :wk "Make org id")
+
+ ;; Programming Projects
+ "." '(counsel-find-file :wk "find file")
+ "p a" '(projectile-add-known-project :wk "Add to project list")
+
+ "N f" '(nix-flake :wk "nix flake menu")
+ "f" '(:ignore t :wk "file operations")
+ "f p" '(projectile-switch-project :wk "find project to switch to")
+ "f f" '(counsel-fzf :wk "find file in project")
+ "f s" '(counsel-rg :wk "find string in project")
+
+ "y n s" '(yas-new-snippet :wk "Create new snippet")
+
+ "g" '(:ignore t :wk "Magit")
+ "g /" '(magit-dispatch :wk "git commands")
+ "g P" '(magit-push :wk "git push")
+ "g c" '(magit-commit :wk "git commit")
+ "g p" '(magit-pull :wk "Pull from git")
+ "g s" '(magit-status :wk "Change status of files")
+ "g i" '(magit-init :wk "init new git project")
+ "g r" '(magit-rebase :wk "Rebase branch")
+ "g m" '(magit-merge :wk "Merge branches")
+ "g b" '(magit-branch :wk "Git branch")
+
+ "o p" '(treemacs :wk "Project Drawer")
+ "o P" '(treemacs-projectile :wk "Import Projectile project to treemacs")
+
+ "w r" '(writeroom-mode :wk "focus mode for writing")
-(use-package evil-commentary
- :after (evil)
- :config (evil-commentary-mode))
+ ;; Applications
+ "o" '(:ignore t :wk "Open application")
+ "o t" '(projectile-run-vterm-other-window :wk "Terminal")
+ "o e" '(projectile-run-eshell :wk "Elisp Interpreter")
+ "o m" '(mu4e :wk "Email")
+ "o M" '(matrix-org :wk "Connect to matrix")
+ "o r s" '(elfeed :wk "rss feed")
+ "o a" '(org-agenda :wk "Open agenda")
+ "o w" '(eww :wk "web browser")
+ "o n" '(enwc :wk "NetworkManager Interface")
+ "m m" '(emms :wk "Music player")
+ "s m" '(proced :wk "System Manager")
+ "l p" '(list-processes :wk "List Emacs Processes")
-(use-package evil-org
- :after (evil org)
- :hook (org-mode . evil-org-mode))
+ "m P p" '(org-publish :wk "Publish website components")
+ "s e" '(sudo-edit :wk "Edit file with sudo")
-(use-package evil-org-agenda
- :after (evil-org)
- :config (evil-org-agenda-set-keys))
+ ;; "f f" '(eglot-format :wk "Format code buffer")
+ "i p c" '(prestonpan :wk "Connect to my IRC server")
+ "i l c" '(liberachat :wk "Connect to libera chat server")
+ "i e c" '(efnet :wk "Connect to efnet chat server")
+ "i g c" '(gimp-org :wk "Connect to gimp chat server")
+ "i z c" '(znc :wk "Connect to my ZNC instance")
-(use-package which-key
- :config (which-key-mode))
+ ;; Documentation
+ "h" '(:ignore t :wk "Documentation")
+ "h v" '(counsel-describe-variable :wk "Describe variable")
+ "h f" '(counsel-describe-function :wk "Describe function")
+ "h h" '(help :wk "Help")
+ "h m" '(woman :wk "Manual")
+ "h i" '(info :wk "Info")
-(use-package page-break-lines
- :config (page-break-lines-mode))
+ "s i p" '(insert-urandom-password :wk "insert random password to buffer (for sops)")
+
+ "h r r" '(lambda () (interactive) (load-file (expand-file-name "~/monorepo/nix/init.el")))))
#+end_src
** Journal
I use org-journal to journal about my life, and it's a part of my website:
@@ -677,6 +1053,7 @@ I used to use catppuccin, but the doom themes are so good that I am willing to b
to use doom themes. I mean it looks better anyways if emacs is a distinct theme.
#+begin_src emacs-lisp :tangle ../nix/init.el
(use-package doom-themes
+ :demand t
:custom
(doom-themes-enable-bold t "use bold letters")
(doom-themes-enable-italic t "use italic letters")
@@ -684,9 +1061,6 @@ to use doom themes. I mean it looks better anyways if emacs is a distinct theme.
:config
(unless noninteractive (doom-themes-config)))
-(use-package catppuccin-theme
- :config (when noninteractive (try (load-theme 'catppuccin-theme t))))
-
(use-package solaire-mode
:after doom-themes
:config (solaire-global-mode +1))
@@ -712,17 +1086,110 @@ Org superstar adds those nice looking utf-8 bullets:
:config
(global-org-modern-mode))
#+end_src
+** Notifications
+We use org-alert in order to give us notifications based on our org-agenda.
+#+begin_src emacs-lisp :tangle ../nix/init.el
+(use-package org-alert
+ :after (org ox-publish)
+ :custom
+ (alert-default-style 'libnotify)
+ (org-alert-interval 300)
+ (org-alert-notify-cutoff 10)
+ (org-alert-notify-after-event-cutoff 10)
+ :config (org-alert-enable))
+#+end_src
** LSP
We set up eglot, the LSP manager for emacs, now built in:
#+begin_src emacs-lisp :tangle ../nix/init.el
-(use-package lsp
+(use-package python
+ :after lsp-mode
+ :hook (python-ts-mode . lsp-deferred))
+
+(use-package yaml-mode
+ :after lsp-mode
+ :hook (yaml-ts-mode . lsp-deferred))
+
+(use-package go-ts-mode
+ :after lsp-mode
+ :hook (go-ts-mode . lsp-deferred))
+
+(use-package haskell-mode
+ :after lsp-mode
+ :hook (haskell-mode . lsp-deferred))
+
+(use-package scheme-mode
+ :hook (scheme-mode . lsp-deferred)
+ :after lsp-mode
+ :mode ("\\.sls\\'" "\\.scm\\'"))
+
+(use-package elisp-mode
+ :after lsp-mode
+ :hook (emacs-lisp-mode . lsp-deferred))
+
+(use-package cc-mode
+ :after lsp-mode
+ :hook ((c-mode . lsp-deferred)
+ (c-ts-mode . lsp-deferred)))
+
+(use-package css-mode
+ :after lsp-mode
+ :hook ((css-mode . lsp-deferred)
+ (css-ts-mode . lsp-deferred)))
+
+(use-package js
+ :after lsp-mode
+ :hook ((js-mode . lsp-deferred)
+ (js-ts-mode . lsp-deferred)
+ (tsx-ts-mode . lsp-deferred)))
+
+(use-package json-mode
+ :after lsp-mode
+ :hook ((json-mode . lsp-deferred)
+ (json-ts-mode . lsp-deferred)))
+
+(use-package toml-mode
+ :after lsp-mode
+ :hook ((toml-ts-mode . lsp-deferred)))
+
+(use-package nix-mode
+ :demand t
+ :after lsp-mode
+ :hook (nix-mode . lsp-deferred)
+ :mode "\\.nix\\'")
+
+(use-package sh-script
+ :after lsp-mode
+ :hook (sh-mode . lsp-deferred))
+
+(use-package poetry
+ :config (poetry-tracking-mode 1))
+
+(use-package lsp-mode
+ :demand t
:custom
(lsp-use-plists t)
(lsp-typescript-format-enable t)
(lsp-typescript-indent-size 4)
(lsp-typescript-tab-size 4)
(lsp-typescript-indent-style "spaces")
- :hook ((prog-mode . lsp)))
+
+ (lsp-auto-guess-root t)
+ (lsp-restart 'auto-restart)
+ (lsp-keep-workspace-alive t)
+
+ :general
+ (:states 'normal :keymaps 'lsp-mode-map
+ "gI" #'lsp-find-implementation
+ "gy" #'lsp-find-type-definition
+ "K" #'lsp-describe-thing-at-point))
+
+(use-package lsp-ui
+ :after lsp-mode
+ :general
+ (:states 'normal :keymaps 'lsp-mode-map
+ "gd" #'lsp-ui-peek-find-definitions
+ "gr" #'lsp-ui-peek-find-references)
+ :hook (lsp-mode . lsp-ui-mode))
(use-package editorconfig
:config (editorconfig-mode 1))
@@ -732,6 +1199,11 @@ We set up eglot, the LSP manager for emacs, now built in:
(use-package platformio-mode
:hook (prog-mode . platformio-conditionally-enable))
+
+(use-package dap-mode
+ :custom
+ (dap-auto-configure-features '(sessions locals controls tooltip))
+ :hook (lsp-mode . dap-mode))
#+end_src
*** C/C++
Specific configuration for C (I also use the clangd lsp):
@@ -749,8 +1221,6 @@ Specific configuration for C (I also use the clangd lsp):
For writing solidity:
#+begin_src emacs-lisp :tangle ../nix/init.el
(use-package solidity-mode)
-(use-package company-solidity
- :after company)
(use-package solidity-flycheck
:after flycheck
:custom (solidity-flycheck-solc-checker-active t))
@@ -769,17 +1239,40 @@ We want our emacs initialization to be pretty and display useful things.
(use-package dashboard
:after (projectile)
:custom
- (dashboard-banner-logo-title "Welcome, Commander!" "Set title for dashboard")
- (dashboard-icon-type 'nerd-icons "Use nerd icons")
- (dashboard-vertically-center-content t "Center content")
+ (dashboard-banner-logo-title "Introducing: Ret2pop!" "Set title for dashboard")
+ (dashboard-startup-banner logo-file)
+ (dashboard-icon-type 'all-the-icons "Use nerd icons")
+ (dashboard-center-content t "Center content")
(dashboard-set-init-info t)
+ (dashboard-set-heading-icons t)
+ (dashboard-set-file-icons t)
+ (dashboard-projects-backend 'projectile)
+
(dashboard-week-agenda t "Agenda in dashboard")
(dashboard-items '((recents . 5)
- (bookmarks . 5)
(projects . 5)
- (agenda . 5)
- (registers . 5)) "Look at some items")
- :config (unless noninteractive (dashboard-setup-startup-hook)))
+ (agenda . 5)) "Look at some items")
+ (dashboard-startupify-list '(dashboard-insert-banner
+ dashboard-insert-newline
+ dashboard-insert-banner-title
+ dashboard-insert-newline
+ dashboard-insert-navigator
+ dashboard-insert-newline
+ dashboard-insert-init-info
+ dashboard-insert-items
+ dashboard-insert-newline
+ dashboard-insert-footer))
+ :config
+ (unless noninteractive (dashboard-setup-startup-hook))
+
+ (my-fetch-weather-async)
+ (defvar my-weather-timer nil)
+ (when (timerp my-weather-timer)
+ (cancel-timer my-weather-timer))
+ (setq my-weather-timer (run-with-timer 900 900 #'my-fetch-weather-async))
+
+ (add-to-list 'dashboard-item-generators '(weather-clock . my-dashboard-insert-weather-clock))
+ (add-to-list 'dashboard-items '(weather-clock . 1)))
#+end_src
** Ivy
Ivy is a pretty cool general program for displaying stuff:
@@ -792,8 +1285,12 @@ Ivy is a pretty cool general program for displaying stuff:
:bind
("C-j" . ivy-immediate-done)
("C-c C-r" . ivy-resume)
- :init (ivy-mode)
- :config (ivy-rich-mode))
+ :config
+ (ivy-mode))
+
+(use-package ivy-rich
+ :config
+ (ivy-rich-mode))
(use-package counsel
:after ivy
@@ -832,6 +1329,34 @@ I use magit in order to do all my git management in emacs.
(use-package git-gutter
:config
(global-git-gutter-mode +1))
+
+(defun ret2pop/enable-smerge-maybe ()
+ (save-excursion
+ (goto-char (point-min))
+ (when (re-search-forward "^<<<<<<< " nil t)
+ (smerge-mode 1))))
+
+(use-package smerge-mode
+ :hook ((find-file . ret2pop/enable-smerge-maybe))
+ :general
+ (:states '(normal motion)
+ :keymaps 'smerge-mode-map
+ "]c" #'smerge-next
+ "[c" #'smerge-prev)
+ (:states '(normal visual)
+ :keymaps 'smerge-mode-map
+ :prefix ","
+ "n" #'smerge-next
+ "p" #'smerge-prev
+ "u" #'smerge-keep-upper
+ "l" #'smerge-keep-lower
+ "m" #'smerge-keep-current
+ "o" #'smerge-keep-other
+ "a" #'smerge-keep-all
+ "b" #'smerge-keep-base
+ "r" #'smerge-resolve
+ "R" #'smerge-refine
+ "e" #'smerge-ediff))
#+end_src
** IRC
Configure IRC to use my username.
@@ -842,98 +1367,6 @@ Configure IRC to use my username.
(erc-nick system-username "sets erc username to the one set in nix config")
(erc-user-full-name system-fullname "sets erc fullname to the one set in nix config"))
#+end_src
-** Keybindings
-Global keybindings for everything that I care about globally. It's all here! I use general
-to manage my global keybindings in a declarative way. These are in part inspired by the doom
-emacs keybindings.
-#+begin_src emacs-lisp :tangle ../nix/init.el
-(use-package general
- :after (evil evil-collection)
- :init (general-create-definer leader-key :prefix "SPC")
- :config
- ;; these are just bindings but the symbols are all lazily handled by general
- (create-irc-servers
- (znc "ret2pop.net" "5000")
- (prestonpan "nullring.xyz" "6697")
- (libera-chat "irc.libera.chat" "6697")
- (efnet "irc.prison.net" "6697")
- (matrix-org "matrix.org" "8448")
- (gimp-org "irc.gimp.org" "6697"))
-
- (leader-key 'normal
- "o c" '(org-capture :wk "Capture")
- ;; Org Mode
- "n" '(:ignore t :wk "Org mode plugins")
- "n j j" '(org-journal-new-entry :wk "Make new journal entry")
- "n r f" '(org-roam-node-find :wk "Find roam node")
- "n r i" '(org-roam-node-insert :wk "Insert roam node")
- "n r a" '(org-roam-alias-add :wk "Add alias to org roam node")
- "n r g" '(org-roam-graph :wk "Graph roam database")
- "m I" '(org-id-get-create :wk "Make org id")
-
- ;; Programming Projects
- "." '(counsel-find-file :wk "find file")
- "p a" '(projectile-add-known-project :wk "Add to project list")
-
- "N f" '(nix-flake :wk "nix flake menu")
- "f" '(:ignore t :wk "file operations")
- "f p" '(projectile-switch-project :wk "find project to switch to")
- "f f" '(counsel-fzf :wk "find file in project")
- "f s" '(counsel-rg :wk "find string in project")
-
- "y n s" '(yas-new-snippet :wk "Create new snippet")
-
- "g" '(:ignore t :wk "Magit")
- "g /" '(magit-dispatch :wk "git commands")
- "g P" '(magit-push :wk "git push")
- "g c" '(magit-commit :wk "git commit")
- "g p" '(magit-pull :wk "Pull from git")
- "g s" '(magit-status :wk "Change status of files")
- "g i" '(magit-init :wk "init new git project")
- "g r" '(magit-rebase :wk "Rebase branch")
- "g m" '(magit-merge :wk "Merge branches")
- "g b" '(magit-branch :wk "Git branch")
-
- "o p" '(treemacs :wk "Project Drawer")
- "o P" '(treemacs-projectile :wk "Import Projectile project to treemacs")
-
- "w r" '(writeroom-mode :wk "focus mode for writing")
-
- ;; Applications
- "o" '(:ignore t :wk "Open application")
- "o t" '(vterm :wk "Terminal")
- "o e" '(eshell :wk "Elisp Interpreter")
- "o m" '(mu4e :wk "Email")
- "o M" '(matrix-org :wk "Connect to matrix")
- "o r s" '(elfeed :wk "rss feed")
- "o a" '(org-agenda :wk "Open agenda")
- "o w" '(eww :wk "web browser")
- "m m" '(emms :wk "Music player")
- "s m" '(proced :wk "System Manager")
- "l p" '(list-processes :wk "List Emacs Processes")
-
- "m P p" '(org-publish :wk "Publish website components")
- "s e" '(sudo-edit :wk "Edit file with sudo")
-
- ;; "f f" '(eglot-format :wk "Format code buffer")
- "i p c" '(prestonpan :wk "Connect to my IRC server")
- "i l c" '(liberachat :wk "Connect to libera chat server")
- "i e c" '(efnet :wk "Connect to efnet chat server")
- "i g c" '(gimp-org :wk "Connect to gimp chat server")
- "i z c" '(znc :wk "Connect to my ZNC instance")
-
- ;; Documentation
- "h" '(:ignore t :wk "Documentation")
- "h v" '(counsel-describe-variable :wk "Describe variable")
- "h f" '(counsel-describe-function :wk "Describe function")
- "h h" '(help :wk "Help")
- "h m" '(woman :wk "Manual")
- "h i" '(info :wk "Info")
-
- "s i p" '(insert-urandom-password :wk "insert random password to buffer (for sops)")
-
- "h r r" '(lambda () (interactive) (load-file (expand-file-name "~/monorepo/nix/init.el")))))
-#+end_src
** LLM
I use LLMs in order to help me come up with ideas. I use a local LLM so that I can have a
competitive LLM that doesn't cost money.
@@ -942,30 +1375,20 @@ Minuet does my code completion, showing the potential code completion as a ghost
still. It is kind of like copilot but it works with local LLMs, which is better. Though, it's obviously not always the most accurate.
#+begin_src emacs-lisp :tangle ../nix/init.el
(use-package minuet
- :bind
- (("M-y" . #'minuet-complete-with-minibuffer)
- ("C-c m" . #'minuet-show-suggestion)
- :map minuet-active-mode-map
- ("C-c r" . #'minuet-dismiss-suggestion)
- ("TAB" . #'minuet-accept-suggestion))
- :hook ((prog-mode-hook . minuet-auto-suggestion-mode))
- :custom
- (minuet-request-timeout 40 "Max timeout in seconds")
- (minuet-provider 'openai-fim-compatible "FIM compatible OpenAI-like API (Ollama)")
- (minuet-n-completions 1 "I am using ghost text so I only need one possible completion")
- (minuet-context-window 1024 "how much context do I want?")
- (minuet-openai-fim-compatible-options
- '(
- :end-point "http://localhost:11434/v1/completions"
- :name "Ollama"
- :api-key "TERM"
- :template (
- :prompt minuet--default-fim-prompt-function
- :suffix minuet--default-fim-suffix-function)
- :transform ()
- :get-text-fn minuet--openai-fim-get-text-fn
- :optional (:max-tokens 50)
- :model "qwen2.5-coder:14b")))
+ :config
+ (setq minuet-provider 'openai-fim-compatible)
+ (setq minuet-n-completions 1)
+ (setq minuet-context-window 4096)
+ (plist-put minuet-openai-fim-compatible-options :end-point "http://localhost:11434/v1/completions")
+ ;; an arbitrary non-null environment variable as placeholder.
+ ;; For Windows users, TERM may not be present in environment variables.
+ ;; Consider using APPDATA instead.
+ (plist-put minuet-openai-fim-compatible-options :name "Ollama")
+ (plist-put minuet-openai-fim-compatible-options :api-key "nothing")
+ (plist-put minuet-openai-fim-compatible-options :model "rnj-1:latest")
+
+ (minuet-set-optional-options minuet-openai-fim-compatible-options :max_tokens 100)
+ :hook (prog-mode-hook . minuet-auto-suggestion-mode))
#+end_src
** RSS Feed
I use really simple syndication (RSS) in order to read news. As a result, I use
@@ -1141,10 +1564,10 @@ elfeed to fetch feeds found on my website:
(use-package elfeed
:hook ((elfeed-search-mode . elfeed-update))
+ :general (:states 'normal :keymaps 'elfeed-search-mode-map "r" 'elfeed-update)
:custom
(elfeed-search-filter (format "@1-month-ago +unread !%s" (elfeed-final-filter elfeed-hn-filter-list)) "Only display unread articles from a month ago")
- (elfeed-curl-max-connections 8 "less max connections for less lag")
- :config (run-with-timer 0 (* 60 10) 'elfeed-update))
+ (elfeed-curl-max-connections 8 "less max connections for less lag"))
(use-package elfeed-org
:after (elfeed org)
@@ -1168,6 +1591,8 @@ interface and can control it from emacs):
:config (elfeed-tube-setup))
(use-package elfeed-tube-mpv
+ :after elfeed-tube
+ :demand t
:bind (:map elfeed-show-mode-map
("C-c C-f" . elfeed-tube-mpv-follow-mode)
("C-c C-c" . elfeed-tube-mpv)
@@ -1180,12 +1605,14 @@ I use treemacs as my sidebar for projects, so that I can easily navigate to any
project directory.
#+begin_src emacs-lisp :tangle ../nix/init.el
(use-package treemacs
+ :demand t
:after doom-themes)
(use-package treemacs-evil
:after (treemacs evil))
(use-package treemacs-projectile
+ :demand t
:after (treemacs projectile))
(use-package treemacs-magit
@@ -1214,15 +1641,9 @@ to Chromium if I have to:
** Nix Mode
Load Nix mode so our exported website has syntax highlighting for Nix blocks.
#+begin_src emacs-lisp :tangle ../nix/init.el
- (use-package nix-mode
- :demand t
- :mode "\\.nix\\'")
#+end_src
** Scheme
#+begin_src emacs-lisp :tangle ../nix/init.el
-(use-package scheme-mode
- :mode ("\\.sls\\'" "\\.scm\\'"))
-
(use-package geiser
:after scheme)
@@ -1281,6 +1702,17 @@ Email in emacs can be done with Mu4e.
(use-package mu4e
:after smtpmail
+ :general
+ (:states '(normal motion) :keymaps 'mu4e-main-mode-map
+ "s" #'my-ivy-mu4e-search)
+
+ (:states '(normal motion) :keymaps 'mu4e-headers-mode-map
+ "s" #'my-ivy-mu4e-search
+ "/" #'my-mu4e-narrow-with-ivy)
+
+ (:states '(normal motion) :keymaps 'mu4e-thread-mode-map
+ "s" #'my-ivy-mu4e-search
+ "/" #'my-mu4e-narrow-with-ivy)
:hook
((mu4e-compose-mode . mml-secure-message-sign-pgpmime))
:custom
@@ -1297,6 +1729,7 @@ Email in emacs can be done with Mu4e.
(mu4e-compose-reply-ignore-address (list "no-?reply" system-email) "ignore my own address and noreply")
(mu4e-html2text-command "w3m -T text/html" "Use w3m to convert html to text")
(mu4e-update-interval 300 "Update duration")
+ (mu4e-completing-read-function 'ivy-completing-read)
(mu4e-headers-auto-update t "Auto-updates feed")
(mu4e-view-show-images t "Shows images")
(mu4e-compose-signature-auto-include nil)
@@ -1338,6 +1771,55 @@ I use tabs because sometimes I like using the mouse (it's actually more efficien
:demand t
:config (centaur-tabs-mode t))
#+end_src
+** Sops
+#+begin_src emacs-lisp :tangle ../nix/init.el
+(unless noninteractive
+ (use-package sops
+ :bind (("C-c C-c" . sops-save-file)
+ ("C-c C-k" . sops-cancel)
+ ("C-c C-d" . sops-edit-file))
+ :init (global-sops-mode 1)))
+#+end_src
+** Pulseaudio
+#+begin_src emacs-lisp :tangle ../nix/init.el
+(unless noninteractive
+ (use-package pulseaudio-control
+ :config (pulseaudio-control-default-keybindings)))
+#+end_src
+** TreeSitter
+#+begin_src emacs-lisp :tangle ../nix/init.el
+(use-package treesit-auto
+ :custom
+ (treesit-auto-install 'prompt)
+ :config
+ (treesit-auto-add-to-auto-mode-alist 'all)
+ (global-treesit-auto-mode))
+#+end_src
+** Indentation
+#+begin_src emacs-lisp :tangle ../nix/init.el
+(use-package aggressive-indent
+ :hook ((js-ts-mode . aggressive-indent-mode)
+ (css-ts-mode . aggressive-indent-mode)
+ (json-ts-mode . aggressive-indent-mode)
+ (nix-mode . aggressive-indent-mode)
+ (c-ts-mode . aggressive-indent-mode)))
+#+end_src
+** Pulsar
+#+begin_src emacs-lisp :tangle ../nix/init.el
+(use-package pulsar
+ :custom
+ (pulsar-delay 0.055)
+ (pulsar-iterations 5)
+ (pulsar-face 'pulsar-green)
+ (pulsar-region-face 'pulsar-yellow)
+ (pulsar-highlight-face 'pulsar-magenta)
+ :bind
+ (:map global-map
+ ("C-x l" . pulsar-pulse-line)
+ ("C-x L" . pulsar-highlight-permanently-dwim))
+ :config
+ (pulsar-global-mode 1))
+#+end_src
* Unpinned
** Lean4
For some reason, lean4-mode is not in MELPA currently so I have to do this ugly thing: