diff options
| author | Preston Pan <ret2pop@nullring.xyz> | 2026-03-31 02:25:24 -0700 |
|---|---|---|
| committer | Preston Pan <ret2pop@nullring.xyz> | 2026-03-31 02:25:24 -0700 |
| commit | f17203b32bd1ecb0d908bbf03b9239e2efde59d6 (patch) | |
| tree | 67971ff0cfc50d8e22a2af94d8aee98cdfd4d262 /config | |
| parent | 42656b6d8e9d433ee9a032605755679157980365 (diff) | |
| parent | 369c079498ffa28dec74a259e7acd69d09a36106 (diff) | |
Merge branch 'qtile'
Diffstat (limited to 'config')
| -rw-r--r-- | config/emacs.org | 1312 | ||||
| -rw-r--r-- | config/index.org | 1 | ||||
| -rw-r--r-- | config/nix.org | 1109 | ||||
| -rw-r--r-- | config/qtile.org | 422 | ||||
| -rw-r--r-- | config/qutebrowser.org | 99 |
5 files changed, 1581 insertions, 1362 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: diff --git a/config/index.org b/config/index.org index 138c940..bba3e9a 100644 --- a/config/index.org +++ b/config/index.org @@ -28,6 +28,7 @@ Here is a list of my configurations for various programs: - [[file:elfeed.org][Interesting RSS Feeds]] - [[file:emacs.org][Emacs Configuration]] - [[file:nix.org][NixOS Configuration]] +- [[file:qtile.org][QTile Configuration]] - [[file:qutebrowser.org][Qutebrowser Configuration]] @@html: </div>@@ diff --git a/config/nix.org b/config/nix.org index 5690f7f..dca7f38 100644 --- a/config/nix.org +++ b/config/nix.org @@ -92,6 +92,10 @@ and now for the main flake: url = "github:cachix/git-hooks.nix"; inputs.nixpkgs.follows = "nixpkgs"; }; + catppuccin-qutebrowser = { + url = "github:catppuccin/qutebrowser"; + flake = false; + }; }; outputs = { @@ -130,21 +134,21 @@ and now for the main flake: }; commonModules = hostname: [ - impermanence.nixosModules.impermanence - nix-topology.nixosModules.default - lanzaboote.nixosModules.lanzaboote - disko.nixosModules.disko - home-manager.nixosModules.home-manager - sops-nix.nixosModules.sops - nixos-dns.nixosModules.dns - { - nixpkgs.overlays = [ nur.overlays.default ]; - home-manager.extraSpecialArgs = attrs // { - systemHostName = "${hostname}"; - }; - networking.hostName = "${hostname}"; - } - (./. + "/systems/${hostname}/default.nix") + impermanence.nixosModules.impermanence + nix-topology.nixosModules.default + lanzaboote.nixosModules.lanzaboote + disko.nixosModules.disko + home-manager.nixosModules.home-manager + sops-nix.nixosModules.sops + nixos-dns.nixosModules.dns + { + nixpkgs.overlays = [ nur.overlays.default ]; + home-manager.extraSpecialArgs = attrs // { + systemHostName = "${hostname}"; + }; + networking.hostName = "${hostname}"; + } + (./. + "/systems/${hostname}/default.nix") ]; mkHostModules = hostname: @@ -391,26 +395,27 @@ with mkDiskoFiles. * Sops Configuration In order to use the sops configuration, you must change the age public key to the one that you own: -#+begin_src yaml :tangle ../nix/.sops.yaml - keys: - - &primary age165ul43e8rc0qwzz2f2q9cw02psm2mkudsrwavq2e0pxs280p64yqy2z0dr - - &vps age1acpuyy2qnduyxzwvusd8urr6a78e3f37ylhvh2pngyqytf5r8ans5vkest - creation_rules: - - path_regex: secrets/secrets.yaml$ - key_groups: - - age: - - *primary +#+begin_src yaml :tangle ../nix/.sops.yaml :comments no +keys: + - &primary age165ul43e8rc0qwzz2f2q9cw02psm2mkudsrwavq2e0pxs280p64yqy2z0dr + - &vps age1acpuyy2qnduyxzwvusd8urr6a78e3f37ylhvh2pngyqytf5r8ans5vkest - - path_regex: secrets/vps_secrets.yaml$ - key_groups: - - age: - - *vps +creation_rules: + - path_regex: secrets/secrets.yaml$ + key_groups: + - age: + - *primary - - path_regex: secrets/common_secrets.yaml$ - key_groups: - - age: - - *primary - - *vps + - path_regex: secrets/vps_secrets.yaml$ + key_groups: + - age: + - *vps + + - path_regex: secrets/common_secrets.yaml$ + key_groups: + - age: + - *primary + - *vps #+end_src also note that you will have to write your own secrets.yaml file, with an entry called ~mail~, which is used for the imaps and smtps password. @@ -1564,19 +1569,29 @@ does not support conduit at the moment. Note that this is not fully declarative ** Ollama Use ollama for serving large language models to my other computers. #+begin_src nix :tangle ../nix/modules/ollama.nix - { config, lib, pkgs, ... }: - { - # services.open-webui.enable = lib.mkDefault (!config.monorepo.profiles.server.enable); - services.ollama = { - enable = lib.mkDefault config.monorepo.profiles.desktop.enable; - package = if (config.monorepo.profiles.cuda.enable) then pkgs.ollama-cuda else pkgs.ollama-vulkan; - loadModels = if (config.monorepo.profiles.cuda.enable) then [ - ] else [ - ]; - host = "0.0.0.0"; - openFirewall = true; +{ config, lib, pkgs, ... }: +{ + services.open-webui = { + enable = lib.mkDefault config.services.ollama.enable; + port = 11111; + host = "127.0.0.1"; + environment = { + OLLAMA_API_BASE_URL = "http://127.0.0.1:11434"; + # Disable authentication + WEBUI_AUTH = "False"; }; - } + }; + + services.ollama = { + enable = lib.mkDefault config.monorepo.profiles.desktop.enable; + package = if (config.monorepo.profiles.cuda.enable) then pkgs.ollama-cuda else pkgs.ollama-vulkan; + loadModels = if (config.monorepo.profiles.cuda.enable) then [ + ] else [ + ]; + host = "0.0.0.0"; + openFirewall = true; + }; +} #+end_src ** Bitcoind #+begin_src nix :tangle ../nix/modules/bitcoin.nix @@ -2356,6 +2371,33 @@ We must put Nixpkgs in another configuration because we don't want to include it }; } #+end_src +** QTile +#+begin_src nix :tangle ../nix/modules/qtile.nix +{ lib, config, ... }: +{ + services.xserver.windowManager.qtile = { + enable = lib.mkDefault config.monorepo.profiles.desktop.enable; + + extraPackages = python3Packages: with python3Packages; [ + qtile-extras + ]; + }; +} +#+end_src +** Libinput +#+begin_src nix :tangle ../nix/modules/libinput.nix +{ lib, config, ... }: +{ + services.libinput = { + enable = lib.mkDefault config.monorepo.profiles.desktop.enable; + mouse = { + dev = "/dev/input/by-id/usb-047d_80fd-event-mouse"; + scrollMethod = "button"; + scrollButton = 276; + }; + }; +} +#+end_src ** Main Configuration This is the backbone of the all the NixOS configurations, with all these options being shared because they enhance security. @@ -3116,6 +3158,7 @@ in lang-lean.enable = lib.mkEnableOption "Enables lean language support"; lang-haskell.enable = lib.mkEnableOption "Enables haskell language support"; lang-scheme.enable = lib.mkEnableOption "Enables scheme language support"; + lang-data.enable = lib.mkEnableOption "Enables markup languages support"; crypto.enable = lib.mkEnableOption "Enables various cryptocurrency wallets"; art.enable = lib.mkEnableOption "Enables various art programs"; music.enable = lib.mkEnableOption "Enables mpd"; @@ -3165,13 +3208,20 @@ in (if config.monorepo.profiles.lang-python.enable then (with pkgs; [ poetry python3 - python314Packages.python-lsp-server + semgrep + ty + ruff + python314Packages.debugpy ]) else []) ++ (if config.monorepo.profiles.lang-sol.enable then (with pkgs; [ solc ]) else []) ++ + (if config.monorepo.profiles.lang-data.enable then (with pkgs; [ + yaml-language-server + ]) else []) + ++ (if config.monorepo.profiles.lang-openscad.enable then (with pkgs; [ openscad openscad-lsp @@ -3268,6 +3318,7 @@ in lang-idris.enable = lib.mkDefault config.monorepo.profiles.enable; lang-agda.enable = lib.mkDefault config.monorepo.profiles.enable; lang-scheme.enable = lib.mkDefault config.monorepo.profiles.enable; + lang-data.enable = lib.mkDefault config.monorepo.profiles.enable; crypto.enable = lib.mkDefault config.monorepo.profiles.enable; art.enable = lib.mkDefault config.monorepo.profiles.enable; @@ -3352,7 +3403,7 @@ be straightforward. #+end_src *** QuteBrowser #+begin_src nix :tangle ../nix/modules/home/qutebrowser.nix -{ lib, config, ... }: +{ lib, config, catppuccin-qutebrowser, ... }: { programs.qutebrowser = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; @@ -3362,10 +3413,31 @@ be straightforward. w = "https://en.wikipedia.org/wiki/Special:Search?search={}&go=Go&ns0=1"; aw = "https://wiki.archlinux.org/?search={}"; nw = "https://wiki.nixos.org/index.php?search={}"; + npk = "https://search.nixos.org/packages?channel=unstable&query={}"; }; settings = { content.blocking.method = "both"; + fonts.default_family = "Lora"; + fonts.default_size = "12pt"; + + # Command/completion UI + fonts.statusbar = "12pt Lora"; + fonts.completion.entry = "12pt Lora"; + fonts.completion.category = "bold 12pt Lora"; + fonts.prompts = "12pt Lora"; + + # Tabs + fonts.tabs.selected = "12pt Lora"; + fonts.tabs.unselected = "12pt Lora"; + + # Hints + fonts.hints = "bold 12pt Lora"; }; + extraConfig = (builtins.readFile "${catppuccin-qutebrowser}/setup.py") + +'' +config.load_autoconfig() +setup(c, "mocha", True) +''; }; } #+end_src @@ -3394,7 +3466,7 @@ compilation, and because I can fetch their exact versions. Note that I have a st configuration here that tells emacs to load my real configuration at ~~/monorepo/config/emacs.org~ as an org file which gets automatically tangled to an emacs-lisp file. #+begin_src nix :tangle ../nix/modules/home/emacs.nix -{ lib, config, pkgs, super, ... }: +{ lib, config, pkgs, super, self, ... }: { programs.emacs = { @@ -3402,6 +3474,7 @@ as an org file which gets automatically tangled to an emacs-lisp file. package = pkgs.emacs-pgtk; extraConfig = '' (setq debug-on-error t) + (setq logo-file "${self}/data/logo.png") (setq system-email "${super.monorepo.vars.email}") (setq system-username "${super.monorepo.vars.internetName}") (setq system-fullname "${super.monorepo.vars.fullName}") @@ -3423,105 +3496,119 @@ as an org file which gets automatically tangled to an emacs-lisp file. **** Emacs Packages I want to separate out these packages so that my parent flake which builds my website has a list of my packages. #+begin_src nix :tangle ../nix/modules/home/emacs-packages.nix -epkgs: [ - epkgs.all-the-icons - epkgs.agda2-mode - epkgs.auctex - epkgs.catppuccin-theme - epkgs.company - epkgs.company-box - epkgs.company-solidity - epkgs.counsel - epkgs.centaur-tabs - epkgs.dash - epkgs.dashboard - epkgs.doom-themes - epkgs.doom-modeline - epkgs.indent-bars - epkgs.irony - epkgs.elfeed - epkgs.elfeed-org - epkgs.elfeed-tube - epkgs.elfeed-tube-mpv - epkgs.elpher - epkgs.ement - epkgs.emmet-mode - epkgs.emms - epkgs.engrave-faces - epkgs.enwc - epkgs.evil - epkgs.evil-collection - epkgs.evil-commentary - epkgs.evil-org - epkgs.f - epkgs.flycheck - epkgs.geiser - epkgs.geiser-chez - epkgs.general - epkgs.git-gutter - epkgs.gptel - epkgs.gruvbox-theme - epkgs.haskell-mode - epkgs.htmlize - epkgs.idris-mode - epkgs.irony-eldoc - epkgs.ivy - epkgs.ivy-posframe - epkgs.latex-preview-pane - epkgs.lsp-ivy - epkgs.lsp-mode - epkgs.lsp-haskell - epkgs.lyrics-fetcher - epkgs.mastodon - epkgs.magit - epkgs.magit-delta - epkgs.mu4e - epkgs.mixed-pitch - epkgs.minuet - epkgs.nix-mode - epkgs.ox-rss - epkgs.ob-nix - epkgs.org-contrib - epkgs.org-ql - epkgs.org-super-agenda - epkgs.org-fragtog - epkgs.org-journal - epkgs.org-modern - epkgs.org-roam - epkgs.org-roam-ui - epkgs.page-break-lines - epkgs.password-store - epkgs.pdf-tools - epkgs.pinentry - epkgs.platformio-mode - epkgs.projectile - epkgs.rustic - epkgs.s - epkgs.solaire-mode - epkgs.scad-mode - epkgs.simple-httpd - epkgs.solidity-flycheck - epkgs.solidity-mode - epkgs.sudo-edit - epkgs.treemacs - epkgs.treemacs-evil - epkgs.treemacs-magit - epkgs.treemacs-projectile - epkgs.treemacs-all-the-icons - epkgs.all-the-icons-ivy-rich - epkgs.treesit-auto - epkgs.typescript-mode - epkgs.use-package - epkgs.vterm - epkgs.wgrep - epkgs.web-mode - epkgs.websocket - epkgs.which-key - epkgs.writegood-mode - epkgs.writeroom-mode - epkgs.yaml-mode - epkgs.yasnippet - epkgs.yasnippet-snippets +epkgs: with epkgs; [ + aggressive-indent + all-the-icons + agda2-mode + auctex + catppuccin-theme + company + company-box + company-solidity + counsel + centaur-tabs + dap-mode + dash + dashboard + doom-themes + doom-modeline + indent-bars + irony + elfeed + elfeed-org + elfeed-tube + elfeed-tube-mpv + elpher + ement + emmet-mode + emms + engrave-faces + enwc + evil + evil-collection + evil-commentary + evil-multiedit + evil-mc + evil-surround + evil-org + evil-lion + evil-textobj-tree-sitter + f + flycheck + geiser + geiser-chez + general + git-gutter + gptel + gruvbox-theme + haskell-mode + htmlize + idris-mode + irony-eldoc + ivy + ivy-posframe + latex-preview-pane + lsp-ivy + lsp-mode + lsp-ui + lsp-haskell + lyrics-fetcher + mastodon + magit + magit-delta + mu4e + mixed-pitch + minuet + nix-mode + ox-rss + ob-nix + org-alert + org-contrib + org-ql + org-super-agenda + org-fragtog + org-journal + org-modern + org-roam + org-roam-ui + pulseaudio-control + pulsar + page-break-lines + password-store + pdf-tools + pinentry + platformio-mode + projectile + polymode + poetry + rustic + s + sops + solaire-mode + scad-mode + simple-httpd + solidity-flycheck + solidity-mode + sudo-edit + treemacs + treemacs-evil + treemacs-magit + treemacs-projectile + treemacs-all-the-icons + all-the-icons-ivy-rich + treesit-auto + typescript-mode + use-package + vterm + wgrep + web-mode + websocket + which-key + writegood-mode + writeroom-mode + yaml-mode + yasnippet + yasnippet-snippets ] #+end_src *** Gammastep @@ -3561,7 +3648,7 @@ declaratively, so in case element-desktop stops working because of lack of decla settings = { default_profile = "personal"; profiles.personal = { - user_id = "${super.monorepo.vars.internetName}@matrix.${super.monorepo.vars.orgHost}"; + user_id = "@${super.monorepo.vars.internetName}:matrix.${super.monorepo.vars.orgHost}"; }; image_preview.protocol = { type = "kitty"; @@ -3641,208 +3728,6 @@ Make sure those are set correctly. I've set it to sign by default. }; } #+end_src -*** Hyprland -My compositor/window manager. This automatically starts on startup. Instructions on how -to use this component will come soon. -#+begin_src nix :tangle ../nix/modules/home/hyprland.nix -{ lib, config, wallpapers, pkgs, scripts, ... }: -{ - wayland.windowManager.hyprland = { - enable = lib.mkDefault config.monorepo.profiles.hyprland.enable; - package = pkgs.hyprland; - xwayland.enable = true; - systemd.enable = true; - settings = { - "$mod" = "SUPER"; - bezier = [ - "overshot, 0.05, 0.9, 0.1, 1.05" - ]; - animation = [ - # "workspaces, 1, 10, overshot" - "windows, 1, 2, default" - "workspaces, 1, 2, default, slidefade 20%" - ]; - exec-once = [ - "waybar" - "swww-daemon --format xrgb" - "sh -c 'swww img \"$(find ${wallpapers} -type f \\( -iname \"*.jpg\" -o -iname \"*.png\" \\) | shuf -n1)\"'" - "fcitx5-remote -r" - "fcitx5 -d --replace" - "fcitx5-remote -r" - "emacs" - "qutebrowser" - ]; - env = [ - "LIBVA_DRIVER_NAME,nvidia" - "XDG_SESSION_TYPE,wayland" - "GBM_BACKEND,nvidia-drm" - "__GLX_VENDOR_LIBRARY_NAME,nvidia" - "ELECTRON_OZONE_PLATFORM_HINT,auto" - ]; - - monitor = [ - "DP-4,2560x1440@165.000000,0x0,1" - "Unknown-1,disable" - ]; - - layerrule = [ - { - name = "waybar blur"; - "match:namespace" = "waybar"; - blur = "on"; - } - ]; - - windowrule = [ - { - name = "emacs"; - "match:class" = "emacs"; - workspace = 1; - } - { - name = "librewolf"; - "match:class" = "librewolf"; - workspace = 2; - } - { - name = "qutebrowser"; - "match:class" = "qutebrowser"; - workspace = 2; - } - { - name = "chromium-browser"; - "match:class" = "chromium-browser"; - workspace = 2; - } - { - name = "signal"; - "match:class" = "signal"; - workspace = 3; - } - { - name = "Element"; - "match:class" = "Element"; - workspace = 3; - } - { - name = "pavucontrol"; - "match:class" = "pavucontrol"; - workspace = 4; - } - { - name = "qpwgraph"; - "match:class" = "qpwgraph"; - workspace = 4; - } - { - name = "mpv"; - "match:class" = "mpv"; - workspace = 4; - } - ]; - - bind = [ - "$mod, F, exec, qutebrowser" - "$mod, Return, exec, kitty" - "$mod, E, exec, emacs" - "$mod, B, exec, bitcoin-qt" - "$mod, S, exec, pavucontrol" - "$mod, M, exec, monero-wallet-gui" - "$mod, V, exec, element-desktop" - "$mod, C, exec, signal-desktop" - "$mod, D, exec, wofi --show run" - "$mod, P, exec, bash ${scripts}/powermenu.sh" - "$mod, Q, killactive" - "$mod SHIFT, H, movewindow, l" - "$mod SHIFT, L, movewindow, r" - "$mod SHIFT, K, movewindow, u" - "$mod SHIFT, J, movewindow, d" - - "$mod SHIFT, T, togglefloating" - "$mod SHIFT, F, fullscreen" - - "$mod, H, movefocus, l" - "$mod, L, movefocus, r" - "$mod, K, movefocus, u" - "$mod, J, movefocus, d" - ", XF86AudioPlay, exec, mpc toggle" - ", Print, exec, grim" - - "$mod, right, resizeactive, 30 0" - "$mod, left, resizeactive, -30 0" - "$mod, up, resizeactive, 0 -30" - "$mod, down, resizeactive, 0 30" - ] - ++ ( - builtins.concatLists (builtins.genList - ( - x: - let - ws = - let - c = (x + 1) / 10; - in - builtins.toString (x + 1 - (c * 10)); - in - [ - "$mod, ${ws}, workspace, ${toString (x + 1)}" - "$mod SHIFT, ${ws}, movetoworkspace, ${toString (x + 1)}" - ] - ) - 10) - ); - bindm = [ - "$mod, mouse:272, movewindow" - "$mod, mouse:273, resizewindow" - "$mod ALT, mouse:272, resizewindow" - ]; - binde = [ - ", XF86AudioRaiseVolume, exec, wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+" - ", XF86AudioLowerVolume, exec, wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%-" - ", XF86AudioNext, exec, mpc next" - ", XF86AudioPrev, exec, mpc prev" - ", XF86MonBrightnessUp , exec, xbacklight -inc 10" - ", XF86MonBrightnessDown, exec, xbacklight -dec 10" - ]; - decoration = { - blur = { - enabled = true; - size = 9; - passes = 4; - contrast = 0.8; - brightness = 1.1; - noise = 0.02; - new_optimizations = true; - ignore_opacity = true; - xray = false; - }; - rounding = 5; - }; - input = { - scroll_method = "on_button_down"; - scroll_button = 276; - sensitivity = -0.5; - kb_options = "caps:swapescape"; - repeat_delay = 300; - repeat_rate = 50; - natural_scroll = false; - touchpad = { - natural_scroll = true; - disable_while_typing = true; - tap-to-click = true; - }; - }; - cursor = { - no_hardware_cursors = true; - }; - misc = { - force_default_wallpaper = 0; - disable_hyprland_logo = true; - }; - }; - }; -} -#+end_src *** Kitty I've set my terminal, kitty, to use catppuccin colors. #+begin_src nix :tangle ../nix/modules/home/kitty.nix @@ -3855,7 +3740,7 @@ I've set my terminal, kitty, to use catppuccin colors. font_family = "Iosevka Nerd Font"; font_size = 14; confirm_os_window_close = 0; - background_opacity = "0.7"; + background_opacity = "1"; # Catppuccin theme foreground = "#cdd6f4"; background = "#1e1e2e"; @@ -3900,26 +3785,6 @@ I've set my terminal, kitty, to use catppuccin colors. }; } #+end_src -*** Mako -This is my notification system. My flake automatically fetches the notification sound, so you -are all set from the get-go! -#+begin_src nix :tangle ../nix/modules/home/mako.nix -{ lib, config, sounds, ... }: -{ - services.mako = { - enable = lib.mkDefault config.monorepo.profiles.graphics.enable; - settings = { - on-notify = "exec mpv ${sounds}/polite.ogg --no-config --no-video"; - background-color = "#11111bf8"; - text-color = "#cdd6f4"; - border-color = "#89b4faff"; - border-radius = 1; - font = "Fira Code 10"; - default-timeout = 3000; - }; - }; -} -#+end_src *** Mbsync Note that in order to use my email configuration, your imaps and smtps servers must be encrypted. This module uses the ~vars.nix~ as well as the home ~default.nix~ options. @@ -4051,7 +3916,6 @@ here: profile = "gpu-hq"; force-window = true; ytdl-format = "bestvideo+bestaudio"; - cache-default = 4000000; }; }; } @@ -4086,475 +3950,18 @@ here: }; } #+end_src -*** Waybar -This is the bar I use for my hyprland configuration. You will need to adjust the monitors field -in the ~default.nix~ for it to really appear. -#+begin_src nix :tangle ../nix/modules/home/waybar.nix -{ lib, config, super, ... }: -{ - programs.waybar = { - enable = lib.mkDefault config.monorepo.profiles.hyprland.enable; - style = '' - ,* { - border: none; - border-radius: 0px; - font-family: Iosevka Nerd Font, FontAwesome, Noto Sans CJK; - font-size: 14px; - font-style: normal; - min-height: 0; - } - - window#waybar { - background: rgba(30, 30, 46, 0.5); - border-bottom: 1px solid #45475a; - color: #cdd6f4; - } - - #workspaces { - background: #45475a; - margin: 5px 5px 5px 5px; - padding: 0px 5px 0px 5px; - border-radius: 16px; - border: solid 0px #f4d9e1; - font-weight: normal; - font-style: normal; - } - #workspaces button { - padding: 0px 5px; - border-radius: 16px; - color: #a6adc8; - } - - #workspaces button.active { - color: #f4d9e1; - background-color: transparent; - border-radius: 16px; - } - - #workspaces button:hover { - background-color: #cdd6f4; - color: black; - border-radius: 16px; - } - - #custom-date, #clock, #battery, #pulseaudio, #network, #custom-randwall, #custom-launcher { - background: transparent; - padding: 5px 5px 5px 5px; - margin: 5px 5px 5px 5px; - border-radius: 8px; - border: solid 0px #f4d9e1; - } - - #custom-date { - color: #D3869B; - } - - #custom-power { - color: #24283b; - background-color: #db4b4b; - border-radius: 5px; - margin-right: 10px; - margin-top: 5px; - margin-bottom: 5px; - margin-left: 0px; - padding: 5px 10px; - } - - #tray { - background: #45475a; - margin: 5px 5px 5px 5px; - border-radius: 16px; - padding: 0px 5px; - /*border-right: solid 1px #282738;*/ - } - - #clock { - color: #cdd6f4; - background-color: #45475a; - border-radius: 0px 0px 0px 24px; - padding-left: 13px; - padding-right: 15px; - margin-right: 0px; - margin-left: 10px; - margin-top: 0px; - margin-bottom: 0px; - font-weight: bold; - /*border-left: solid 1px #282738;*/ - } - - #battery { - color: #89b4fa; - } - - #battery.charging { - color: #a6e3a1; - } - - #battery.warning:not(.charging) { - background-color: #f7768e; - color: #f38ba8; - border-radius: 5px 5px 5px 5px; - } - - #backlight { - background-color: #24283b; - color: #db4b4b; - border-radius: 0px 0px 0px 0px; - margin: 5px; - margin-left: 0px; - margin-right: 0px; - padding: 0px 0px; - } - - #network { - color: #f4d9e1; - border-radius: 8px; - margin-right: 5px; - } - - #pulseaudio { - color: #f4d9e1; - border-radius: 8px; - margin-left: 0px; - } - - #pulseaudio.muted { - background: transparent; - color: #928374; - border-radius: 8px; - margin-left: 0px; - } - - #custom-randwall { - color: #f4d9e1; - border-radius: 8px; - margin-right: 0px; - } - - #custom-launcher { - color: #e5809e; - background-color: #45475a; - border-radius: 0px 24px 0px 0px; - margin: 0px 0px 0px 0px; - padding: 0 20px 0 13px; - /*border-right: solid 1px #282738;*/ - font-size: 20px; - } - - #custom-launcher button:hover { - background-color: #FB4934; - color: transparent; - border-radius: 8px; - margin-right: -5px; - margin-left: 10px; - } - - #custom-playerctl { - background: #45475a; - padding-left: 15px; - padding-right: 14px; - border-radius: 16px; - /*border-left: solid 1px #282738;*/ - /*border-right: solid 1px #282738;*/ - margin-top: 5px; - margin-bottom: 5px; - margin-left: 0px; - font-weight: normal; - font-style: normal; - font-size: 16px; - } - - #custom-playerlabel { - background: transparent; - padding-left: 10px; - padding-right: 15px; - border-radius: 16px; - /*border-left: solid 1px #282738;*/ - /*border-right: solid 1px #282738;*/ - margin-top: 5px; - margin-bottom: 5px; - font-weight: normal; - font-style: normal; - } - - #window { - background: #45475a; - padding-left: 15px; - padding-right: 15px; - border-radius: 16px; - /*border-left: solid 1px #282738;*/ - /*border-right: solid 1px #282738;*/ - margin-top: 5px; - margin-bottom: 5px; - font-weight: normal; - font-style: normal; - } - - #custom-wf-recorder { - padding: 0 20px; - color: #e5809e; - background-color: #1E1E2E; - } - - #cpu { - background-color: #45475a; - /*color: #FABD2D;*/ - border-radius: 16px; - margin: 5px; - margin-left: 5px; - margin-right: 5px; - padding: 0px 10px 0px 10px; - font-weight: bold; - } - - #memory { - background-color: #45475a; - /*color: #83A598;*/ - border-radius: 16px; - margin: 5px; - margin-left: 5px; - margin-right: 5px; - padding: 0px 10px 0px 10px; - font-weight: bold; - } - - #disk { - background-color: #45475a; - /*color: #8EC07C;*/ - border-radius: 16px; - margin: 5px; - margin-left: 5px; - margin-right: 5px; - padding: 0px 10px 0px 10px; - font-weight: bold; - } - - #custom-hyprpicker { - background-color: #45475a; - /*color: #8EC07C;*/ - border-radius: 16px; - margin: 5px; - margin-left: 5px; - margin-right: 5px; - padding: 0px 11px 0px 9px; - font-weight: bold; - } - ''; - settings = { - mainBar = { - layer = "top"; - position = "top"; - height = 50; - - output = super.monorepo.vars.monitors; - - modules-left = [ "hyprland/workspaces" ]; - modules-center = [ "hyprland/window" ]; - modules-right = [ "battery" "clock" ]; - - battery = { - format = "{icon} {capacity}%"; - format-icons = ["" "" "" "" "" ]; - }; - - clock = { - format = "⏰ {:%a %d, %b %H:%M}"; - }; - }; - }; - }; -} -#+end_src -*** Wofi -This is a run launcher for wayland. I also use it for my powermenu. -#+begin_src nix :tangle ../nix/modules/home/wofi.nix -{ lib, config, ... }: +*** QTile +#+begin_src nix :tangle ../nix/modules/home/qtile.nix +{ sounds, wallpapers, pkgs, ... }: +let + qtilePaths = pkgs.writeText "qtile-paths.py" '' +WALLPAPER = "${wallpapers}/pastel-city.png" +SOUND = "${sounds}/nice.wav" + ''; +in { - programs.wofi = { - enable = lib.mkDefault config.monorepo.profiles.graphics.enable; - settings = { - location = "bottom-right"; - allow_markup = true; - show = "drun"; - width = 750; - height = 400; - always_parse_args = true; - show_all = false; - term = "kitty"; - hide_scroll = true; - print_command = true; - insensitive = true; - prompt = "Run what, Commander?"; - columns = 2; - }; - - style = '' - @define-color rosewater #f5e0dc; - @define-color rosewater-rgb rgb(245, 224, 220); - @define-color flamingo #f2cdcd; - @define-color flamingo-rgb rgb(242, 205, 205); - @define-color pink #f5c2e7; - @define-color pink-rgb rgb(245, 194, 231); - @define-color mauve #cba6f7; - @define-color mauve-rgb rgb(203, 166, 247); - @define-color red #f38ba8; - @define-color red-rgb rgb(243, 139, 168); - @define-color maroon #eba0ac; - @define-color maroon-rgb rgb(235, 160, 172); - @define-color peach #fab387; - @define-color peach-rgb rgb(250, 179, 135); - @define-color yellow #f9e2af; - @define-color yellow-rgb rgb(249, 226, 175); - @define-color green #a6e3a1; - @define-color green-rgb rgb(166, 227, 161); - @define-color teal #94e2d5; - @define-color teal-rgb rgb(148, 226, 213); - @define-color sky #89dceb; - @define-color sky-rgb rgb(137, 220, 235); - @define-color sapphire #74c7ec; - @define-color sapphire-rgb rgb(116, 199, 236); - @define-color blue #89b4fa; - @define-color blue-rgb rgb(137, 180, 250); - @define-color lavender #b4befe; - @define-color lavender-rgb rgb(180, 190, 254); - @define-color text #cdd6f4; - @define-color text-rgb rgb(205, 214, 244); - @define-color subtext1 #bac2de; - @define-color subtext1-rgb rgb(186, 194, 222); - @define-color subtext0 #a6adc8; - @define-color subtext0-rgb rgb(166, 173, 200); - @define-color overlay2 #9399b2; - @define-color overlay2-rgb rgb(147, 153, 178); - @define-color overlay1 #7f849c; - @define-color overlay1-rgb rgb(127, 132, 156); - @define-color overlay0 #6c7086; - @define-color overlay0-rgb rgb(108, 112, 134); - @define-color surface2 #585b70; - @define-color surface2-rgb rgb(88, 91, 112); - @define-color surface1 #45475a; - @define-color surface1-rgb rgb(69, 71, 90); - @define-color surface0 #313244; - @define-color surface0-rgb rgb(49, 50, 68); - @define-color base #1e1e2e; - @define-color base-rgb rgb(30, 30, 46); - @define-color mantle #181825; - @define-color mantle-rgb rgb(24, 24, 37); - @define-color crust #11111b; - @define-color crust-rgb rgb(17, 17, 27); - - ,* { - font-family: 'Iosevka Nerd Font', monospace; - font-size: 14px; - } - - /* Window */ - window { - margin: 0px; - padding: 10px; - border: 0.16em solid @lavender; - border-radius: 0.1em; - background-color: @base; - animation: slideIn 0.5s ease-in-out both; - } - - /* Slide In */ - @keyframes slideIn { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } - } - - /* Inner Box */ - #inner-box { - margin: 5px; - padding: 10px; - border: none; - background-color: @base; - animation: fadeIn 0.5s ease-in-out both; - } - - /* Fade In */ - @keyframes fadeIn { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } - } - - /* Outer Box */ - #outer-box { - margin: 5px; - padding: 10px; - border: none; - background-color: @base; - } - - /* Scroll */ - #scroll { - margin: 0px; - padding: 10px; - border: none; - background-color: @base; - } - - /* Input */ - #input { - margin: 5px 20px; - padding: 10px; - border: none; - border-radius: 0.1em; - color: @text; - background-color: @base; - animation: fadeIn 0.5s ease-in-out both; - } - - #input image { - border: none; - color: @red; - } - - #input * { - outline: 4px solid @red!important; - } - - /* Text */ - #text { - margin: 5px; - border: none; - color: @text; - animation: fadeIn 0.5s ease-in-out both; - } - - #entry { - background-color: @base; - } - - #entry arrow { - border: none; - color: @lavender; - } - - /* Selected Entry */ - #entry:selected { - border: 0.11em solid @lavender; - } - - #entry:selected #text { - color: @mauve; - } - - #entry:drop(active) { - background-color: @lavender!important; - } - ''; - }; + xdg.configFile."qtile/config.py".source = ../../qtile/config.py; + xdg.configFile."qtile/paths.py".source = qtilePaths; } #+end_src *** yt-dlp @@ -4643,7 +4050,7 @@ standard. }; loginExtra = '' if [[ "$(tty)" = "/dev/tty1" ]]; then - exec start-hyprland + exec qtile start -b wayland fi ''; }; @@ -4703,10 +4110,10 @@ for these configurations. # Apps octaveFull - grim swww vim kotatogram-desktop tg qwen-code element-desktop signal-desktop signal-cli thunderbird jami + grim swww vim element-desktop signal-desktop signal-cli thunderbird jami imv slurp # Sound/media - pavucontrol alsa-utils imagemagick ffmpeg helvum + pavucontrol alsa-utils imagemagick ffmpeg helvum pulseaudio # Net curl rsync gitFull ungoogled-chromium devd @@ -4816,17 +4223,17 @@ for these configurations. ''; }; }; - xdg.mimeApps = { +xdg.mimeApps = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; defaultApplications = { "x-scheme-handler/mailto" = "emacsclient-mail.desktop"; - "text/html" = "qutebrowser.desktop"; - "text/xml" = "qutebrowser.desktop"; - "application/xhtml+xml" = "qutebrowser.desktop"; - "x-scheme-handler/http" = "qutebrowser.desktop"; - "x-scheme-handler/https" = "qutebrowser.desktop"; - "x-scheme-handler/about" = "qutebrowser.desktop"; - "x-scheme-handler/unknown" = "qutebrowser.desktop"; + "text/html" = "org.qutebrowser.qutebrowser.desktop"; + "text/xml" = "org.qutebrowser.qutebrowser.desktop"; + "application/xhtml+xml" = "org.qutebrowser.qutebrowser.desktop"; + "x-scheme-handler/http" = "org.qutebrowser.qutebrowser.desktop"; + "x-scheme-handler/https" = "org.qutebrowser.qutebrowser.desktop"; + "x-scheme-handler/about" = "org.qutebrowser.qutebrowser.desktop"; + "x-scheme-handler/unknown" = "org.qutebrowser.qutebrowser.desktop"; }; }; diff --git a/config/qtile.org b/config/qtile.org new file mode 100644 index 0000000..83d0c8d --- /dev/null +++ b/config/qtile.org @@ -0,0 +1,422 @@ +#+title: QTile Configuration +#+author: Preston Pan +#+description: My personal qtile configuration to be used with NixOS +#+date: [2026-03-25 Wed] +#+language: en + +#+OPTIONS: broken-links:t +#+PROPERTY: header-args :tangle yes :comments link + +* Introduction +This is a QTile configuration meant to be a monolithic configuration of QTile along with widgets i.e. run launcher, bar, and notification panel. +This enables the window manager to be integrated with these things entirely, making for a unified experience in terms of configuration, styling, +and functionality. + +This configuration imports ~WALLPAPER~ and ~SOUND~ from my [[file:./nix.org][NixOS Configuration]], and therefore if you use this standalone you must replace those variables. +* Imports +We start with imports: +#+begin_src python :tangle ../nix/qtile/config.py +from paths import WALLPAPER, SOUND +from libqtile import bar, layout, widget, qtile +from libqtile.config import Key, Group, Screen, Click, Drag, Match +from libqtile.lazy import lazy +from libqtile.backend.wayland import InputConfig +from qtile_extras.layout.decorations import RoundedCorners + +import re +#+end_src +We're using wayland because it's better. +* Data +#+begin_src python :tangle ../nix/qtile/config.py +mod = "mod4" +terminal = "kitty" +wallpaper = WALLPAPER + +colors = { + "rosewater": "#f5e0dc", + "flamingo": "#f2cdcd", + "pink": "#f5c2e7", + "mauve": "#cba6f7", + "red": "#f38ba8", + "maroon": "#eba0ac", + "peach": "#fab387", + "yellow": "#f9e2af", + "green": "#a6e3a1", + "teal": "#94e2d5", + "sky": "#89dceb", + "sapphire": "#74c7ec", + "blue": "#89b4fa", + "lavender": "#b4befe", + "text": "#cdd6f4", + "subtext1": "#bac2de", + "subtext0": "#a6adc8", + "overlay2": "#9399b2", + "overlay1": "#7f849c", + "overlay0": "#6c7086", + "surface2": "#585b70", + "surface1": "#45475a", + "surface0": "#313244", + "base": "#1e1e2e", + "mantle": "#181825", + "crust": "#11111b", +} + +workspace_keys = { + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9", +} +#+end_src +* Config +#+begin_src python :tangle ../nix/qtile/config.py +groups = [ + Group("1", matches=[Match(wm_class=re.compile(r"^emacs$", re.IGNORECASE))]), + Group("2", matches=[Match(wm_class=re.compile(r"(qutebrowser|org\.qutebrowser\.qutebrowser)", re.IGNORECASE))]), + Group( + "3", + matches=[ + Match(wm_class=re.compile(r"^signal.*", re.IGNORECASE)), + Match(wm_class=re.compile(r"^element.*", re.IGNORECASE)), + ], + ), + Group("4", matches=[Match(wm_class=re.compile(r"(pavucontrol|org\.pulseaudio\.pavucontrol)", re.IGNORECASE))]), + Group("5"), + Group("6"), + Group("7"), + Group("8"), + Group("9"), +] + +wl_input_rules = { + "type:keyboard": InputConfig( + kb_options="caps:escape", + kb_repeat_rate=50, + kb_repeat_delay=250, + ), + + "type:pointer": InputConfig( + scroll_method="on_button_down", + scroll_button=276, # Your exact trackball button code + ), +} + +class QuietBattery(widget.Battery): + def poll(self): + try: + status = self._battery.update_status() + except RuntimeError: + return "" + return self.build_string(status) + +def logout(): + qtile.stop() + + +def reboot(): + qtile.spawn("systemctl reboot") + + +def shutdown(): + qtile.spawn("systemctl poweroff") + + +def workspace_bindings(): + bindings = [] + for group_name, key_name in workspace_keys.items(): + bindings.append(Key([mod], key_name, lazy.group[group_name].toscreen())) + bindings.append(Key([mod, "shift"], key_name, lazy.window.togroup(group_name))) + return bindings + + +keys = [ + # apps / session + Key([mod], "Return", lazy.spawn(terminal)), + Key([mod], "d", lazy.spawncmd()), + Key([mod], "q", lazy.window.kill()), + Key([mod], "f", lazy.window.toggle_fullscreen()), + Key([mod], "Tab", lazy.next_layout()), + Key([mod, "control"], "r", lazy.reload_config()), + Key([mod], "t", lazy.window.toggle_floating()), + + # focus + Key([mod], "h", lazy.layout.left()), + Key([mod], "j", lazy.layout.down()), + Key([mod], "k", lazy.layout.up()), + Key([mod], "l", lazy.layout.right()), + + # move windows + Key([mod, "shift"], "h", lazy.layout.shuffle_left()), + Key([mod, "shift"], "j", lazy.layout.shuffle_down()), + Key([mod, "shift"], "k", lazy.layout.shuffle_up()), + Key([mod, "shift"], "l", lazy.layout.shuffle_right()), + + # resize windows + Key([mod, "control"], "h", lazy.layout.grow_left()), + Key([mod, "control"], "j", lazy.layout.grow_down()), + Key([mod, "control"], "k", lazy.layout.grow_up()), + Key([mod, "control"], "l", lazy.layout.grow_right()), + Key([mod], "n", lazy.layout.normalize()), + + # layout helpers + Key([mod], "space", lazy.layout.next()), + Key([mod, "shift"], "space", lazy.layout.toggle_split()), + + # session shortcuts + Key([mod, "shift"], "q", lazy.shutdown()), + Key([mod, "control"], "Delete", lazy.spawn("systemctl reboot")), + Key([mod, "shift"], "Delete", lazy.spawn("systemctl poweroff")), + + # app launchers + Key([mod], "e", lazy.spawn("emacs")), + Key([mod], "w", lazy.spawn("qutebrowser")), + Key([mod], "c", lazy.spawn("signal-desktop")), + Key([mod], "v", lazy.spawn("element-desktop")), + Key([mod], "s", lazy.spawn("pavucontrol")), + + Key([], "XF86AudioPlay", lazy.spawn("mpc toggle")), + Key([], "XF86AudioNext", lazy.spawn("mpc next")), + Key([], "XF86AudioPrev", lazy.spawn("mpc prev")), + Key([], "XF86AudioStop", lazy.spawn("mpc stop")), + + Key([], "XF86AudioRaiseVolume", lazy.spawn("wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%+")), + Key([], "XF86AudioLowerVolume", lazy.spawn("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-")), + Key([], "XF86AudioMute", lazy.spawn("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle")), + Key([], "Print", lazy.spawn("sh -c 'grim ~/screenshot-$(date +%Y%m%d-%H%M%S).png'")), +] + workspace_bindings() + +layouts = [ + layout.Columns( + border_focus=colors["blue"], + border_normal=colors["surface0"], + + border_focus_stack=colors["mauve"], + border_normal_stack=colors["surface1"], + + border_width=3, + margin=8, + insert_position=1, + ), + layout.Max( + border_focus=colors["blue"], + border_normal=colors["surface0"], + border_width=3, + margin=8, + ), +] + +widget_defaults = { + "font": "Iosevka Nerd Font", + "fontsize": 13, + "padding": 6, + "background": colors["mantle"], + "foreground": colors["text"], +} +extension_defaults = widget_defaults.copy() + +mouse = [ + Drag( + [mod], + "Button1", + lazy.window.set_position_floating(), + start=lazy.window.get_position(), + ), + Drag( + [mod], + "Button3", + lazy.window.set_size_floating(), + start=lazy.window.get_size(), + ), + Click( + [mod], + "Button2", + lazy.window.bring_to_front(), + ), +] + + +def segment_icon(text, color, background=None, padding=8, font=None, fontsize=None): + return widget.TextBox( + text=text, + foreground=color, + background=background or colors["surface0"], + padding=padding, + font=font or "Iosevka Nerd Font", + fontsize=fontsize, + ) + + +def segment_sep(padding=6): + return widget.Sep( + linewidth=0, + padding=padding, + background=colors["mantle"], + ) + + +power_widget = widget.WidgetBox( + text_closed="", + text_open="", + close_button_location="right", + background=colors["mantle"], + font="Iosevka Nerd Font", + widgets=[ + widget.TextBox( + text=" ", + foreground=colors["blue"], + background=colors["surface0"], + padding=8, + font="Iosevka Nerd Font", + mouse_callbacks={"Button1": reboot}, + ), + widget.TextBox( + text=" ", + foreground=colors["mauve"], + background=colors["surface0"], + padding=8, + font="Iosevka Nerd Font", + mouse_callbacks={"Button1": logout}, + ), + widget.TextBox( + text=" ", + foreground=colors["red"], + background=colors["surface0"], + padding=8, + font="Iosevka Nerd Font", + mouse_callbacks={"Button1": shutdown}, + ), + ], +) + +screens = [ + Screen( + wallpaper=wallpaper, + wallpaper_mode="fill", + top=bar.Bar( + [ + widget.GroupBox( + font="Iosevka Nerd Font", + fontsize=13, + background=colors["mantle"], + active=colors["text"], + inactive=colors["overlay0"], + highlight_method="line", + highlight_color=[colors["mantle"], colors["mantle"]], + this_current_screen_border=colors["lavender"], + other_current_screen_border=colors["blue"], + this_screen_border=colors["surface2"], + other_screen_border=colors["surface1"], + urgent_border=colors["red"], + urgent_text=colors["red"], + borderwidth=2, + rounded=False, + disable_drag=True, + spacing=8, + padding_x=8, + padding_y=5, + margin_y=2, + margin_x=0, + ), + widget.Spacer(length=10), + widget.Prompt( + name="prompt", + prompt="❯ ", + cursor_color=colors["blue"], + foreground=colors["text"], + background=colors["surface0"], + padding=10, + font="Iosevka Nerd Font", + ), + widget.Spacer(), + + segment_icon("", colors["blue"]), + widget.Wttr( + background=colors["surface0"], + format="%l: %t %C", + update_interval=1800, + font="Iosevka Nerd Font", + foreground=colors["teal"], + ), + segment_sep(), + + segment_icon("", colors["green"]), + widget.Mpd2( + background=colors["surface0"], + foreground=colors["green"], + status_format="{play_status} {artist} - {title}", + idle_format=" idle", + idle_message="idle", + max_chars=40, + padding=10, + hide_crash=True, + font="Iosevka Nerd Font", + ), + segment_sep(), + + segment_icon("", colors["yellow"]), + QuietBattery( + background=colors["surface0"], + foreground=colors["yellow"], + format="{percent:2.0%}", + charge_char="", + discharge_char="", + full_char="", + empty_char="", + update_interval=30, + padding=10, + font="Iosevka Nerd Font", + ), + segment_sep(), + + segment_icon("", colors["peach"]), + widget.Notify( + foreground=colors["peach"], + background=colors["surface0"], + default_timeout=10, + audiofile=SOUND, + padding=10, + font="Iosevka Nerd Font", + ), + segment_sep(), + + segment_icon("", colors["lavender"]), + widget.Clock( + format="%a %d %b", + foreground=colors["lavender"], + background=colors["surface0"], + padding=10, + font="Lora", + ), + segment_icon("", colors["blue"]), + widget.Clock( + format="%H:%M", + foreground=colors["blue"], + background=colors["surface0"], + padding=10, + font="Iosevka Nerd Font", + ), + + widget.Spacer(length=10), + power_widget, + widget.Spacer(length=10), + ], + 30, + margin=[8, 10, 0, 10], + background=colors["mantle"], + opacity=0.97, + ), + ), +] + +follow_mouse_focus = True +bring_front_click = False +cursor_warp = False +auto_fullscreen = True +auto_minimize = True +wmname = "Qtile" +#+end_src diff --git a/config/qutebrowser.org b/config/qutebrowser.org index 2a3e180..da7dccb 100644 --- a/config/qutebrowser.org +++ b/config/qutebrowser.org @@ -5,101 +5,8 @@ #+auto_tangle: t * Configuration -** Imports -We start with imports: +This is my qutebrowser configuration, meant to be used with my [[file:./nix.org][NixOS Configuration]], and is extra configuration on top of what I have there. #+begin_src python :tangle ../nix/qutebrowser.py -from pathlib import Path -from urllib.parse import urlparse -# import catppuccin -#+end_src -We import pathlib to get our home directory. -** Theming -I am experimenting with many themes right now, and one of them is the [[https://github.com/gicrisf/qute-city-lights][city-lights]] theme. -Another one I have used is the [[https://github.com/catppuccin/catppuccin][catppuccin]] theme. -#+begin_src python :tangle config.py -# config.source('themes/qute-city-lights/city-lights-theme.py') -config.source('gruvbox.py') -#+end_src -** Variables -We need the location of the home directory. -#+begin_src python :tangle config.py -home = str(Path.home()) -#+end_src -** Fonts -We are using Fira Code for the font in all the non-webpage ui elements. -#+begin_src python :tangle config.py -c.fonts.hints = '14pt FiraCode Nerd Font' -c.fonts.keyhint = '14pt FiraCode Nerd Font' -c.fonts.prompts = '14pt FiraCode Nerd Font' -c.fonts.downloads = '14pt FiraCode Nerd Font' -c.fonts.statusbar = '14pt FiraCode Nerd Font' -c.fonts.contextmenu = '14pt FiraCode Nerd Font' -c.fonts.messages.info = '14pt FiraCode Nerd Font' -c.fonts.debug_console = '14pt FiraCode Nerd Font' -c.fonts.completion.entry = '14pt FiraCode Nerd Font' -c.fonts.completion.category = '14pt FiraCode Nerd Font' -c.fonts.tabs.selected = '14pt FiraCode Nerd Font' -c.fonts.tabs.unselected = '14pt FiraCode Nerd Font' -#+end_src -** Search Engine -We should set our default search engine to google because duckduckgo is useless, and -we should give other search engine bang options. -#+begin_src python :tangle config.py -c.url.searchengines = { - 'DEFAULT': 'https://google.com/search?hl=en&q={}', - '!a': 'https://www.amazon.com/s?k={}', - '!d': 'https://duckduckgo.com/?ia=web&q={}', - '!dd': 'https://thefreedictionary.com/{}', - '!e': 'https://www.ebay.com/sch/i.html?_nkw={}', - '!fb': 'https://www.facebook.com/s.php?q={}', - '!gh': 'https://github.com/search?o=desc&q={}&s=stars', - '!gist': 'https://gist.github.com/search?q={}', - '!gi': 'https://www.google.com/search?tbm=isch&q={}&tbs=imgo:1', - '!gn': 'https://news.google.com/search?q={}', - '!ig': 'https://www.instagram.com/explore/tags/{}', - '!m': 'https://www.google.com/maps/search/{}', - '!p': 'https://pry.sh/{}', - '!r': 'https://www.reddit.com/search?q={}', - '!sd': 'https://slickdeals.net/newsearch.php?q={}&searcharea=deals&searchin=first', - '!t': 'https://www.thesaurus.com/browse/{}', - '!tw': 'https://twitter.com/search?q={}', - '!w': 'https://en.wikipedia.org/wiki/{}', - '!yelp': 'https://www.yelp.com/search?find_desc={}', - '!yt': 'https://www.youtube.com/results?search_query={}' -} -#+end_src -** Start Page -Set the default start page to my own website. -#+begin_src python :tangle config.py -c.url.start_pages = ["file:///home/preston/website_html/index.html"] -c.url.default_page = "file:///home/preston/website_html/index.html" -#+end_src -** Keybindings -Now we define our keybindings for useful programs while browsing: -#+begin_src python :tangle config.py -config.bind('xm', 'hint links spawn mpv {hint-url}') -config.bind('xy', 'hint links spawn yt-dlp {hint-url} -o "~/videos/youtube/%(title)s.%(ext)s"') -config.bind('xr', 'hint links spawn bash -c "echo \'*** {hint-url}\' >> ~/org/elfeed.org"') -config.bind('xj', 'spawn bash -c "echo {url} >> ~/.config/qutebrowser/js_blacklist.txt"') -#+end_src -** Paywall Bypassing -Sometimes websites like the New York Times try to make money. I won't let that happen. -#+begin_src python :tangle config.py -with open(f"{home}/.config/qutebrowser/js_blacklist.txt") as f: - js_blacklist = f.read().splitlines() - -for item in js_blacklist: - domain = urlparse(item).netloc - config.set('content.javascript.enabled', False, f"*://{domain}/*") - config.set('content.javascript.enabled', False, f"*://www.{domain}/*") -#+end_src -** Misc. -Doing mundane things like setting the downloads directory to not use an upper case letter. -#+begin_src python :tangle config.py -c.downloads.location.directory = "~/Downloads" -#+end_src -** End of Config -#+begin_src python :tangle config.py -config.load_autoconfig() -# catppuccin.setup(c, 'mocha', False) +config.bind(",m", "spawn mpv {url}") +config.bind(",M", "hint links spawn mpv {hint-url}") #+end_src |
