From 109ff0c6a9678bba481ed97222b4c6dac3946ef6 Mon Sep 17 00:00:00 2001 From: SqrtMinusOne Date: Sat, 9 Aug 2025 12:50:23 +0000 Subject: [PATCH] deploy: 68f8a284769ff1368db1e2064be8e07e25db46f0 --- configs/console/index.html | 4 + configs/desktop/index.html | 65 +- configs/emacs/index.html | 1009 +++++++++++++++++++++--------- configs/mail/index.html | 14 +- index.html | 2 +- index.xml | 2 +- posts/2022-09-16-vosk/index.html | 2 +- posts/index.xml | 2 +- sass/researcher.min.css | 2 +- stats/all.png | Bin 124236 -> 124272 bytes stats/emacs-vim.png | Bin 64079 -> 68931 bytes stats/literate-config.png | Bin 70408 -> 66417 bytes 12 files changed, 773 insertions(+), 329 deletions(-) diff --git a/configs/console/index.html b/configs/console/index.html index 78c173c..9666c29 100644 --- a/configs/console/index.html +++ b/configs/console/index.html @@ -202,6 +202,10 @@
if [ -d "$HOME/.nix-profile" ] && [ -z "$NO_GUIX" ]; then
     export XDG_DATA_DIRS="$XDG_DATA_DIRS:$HOME/.nix-profile/share/applications"
 fi
+

Gradle:

+
if [ -d "$HOME/bin/gradle/gradle-9.0.0" ]; then
+    export PATH="$HOME/bin/gradle/gradle-9.0.0/bin:$PATH"
+fi
 

npm

npm is especially cumbersome, for instance because by default it tries to install packages to /gnu/store/.

In principle, one can set a prefix like this:

diff --git a/configs/desktop/index.html b/configs/desktop/index.html index 4e6c98a..d97f512 100644 --- a/configs/desktop/index.html +++ b/configs/desktop/index.html @@ -278,9 +278,9 @@ x-scheme-handler/http=firefox.desktop x-scheme-handler/https=firefox.desktop x-scheme-handler/tg=userapp-Telegram Desktop-7PVWF1.desktop -image/png=com.interversehq.qView.desktop -image/jpg=com.interversehq.qView.desktop -image/jpeg=com.interversehq.qView.desktop +image/png=feh.desktop +image/jpg=feh.desktop +image/jpeg=feh.desktop application/pdf=org.pwmt.zathura.desktop [Added Associations] @@ -627,19 +627,25 @@

The monitor list

The second piece of the puzzle is getting the monitor list in the right order.

While it is possible to retrieve the monitor list from exwm-randr-workspace-monitor-plist, this won’t scale well beyond two monitors, mainly because changing this variable may screw up the order.

-

So the easiest way is to just define the variable like that:

+
(defun my/exwm-xrandr-monitor-list ()
+  (split-string
+   (string-trim
+    (shell-command-to-string "xrandr --listmonitors | grep '+' | awk {'print $4'}
+"))))
+

So the easiest way is to just define the variable like that:

(setq my/exwm-monitor-list
       (pcase (system-name)
         ("indigo" '(nil "DVI-D-0"))
-        ("violet" '(nil "DP-1"))
+        ("violet" (my/exwm-xrandr-monitor-list))
         (_ '(nil))))
-

If you are changing the RandR configuration on the fly, this variable will also need to be changed, but for now, I don’t have such a necessity.

-

A function to get the current monitor:

+

A function to get the current monitor:

(defun my/exwm-get-current-monitor ()
   "Return the current monitor name or nil."
-  (plist-get exwm-randr-workspace-monitor-plist
-             (cl-position (selected-frame)
-                          exwm-workspace--list)))
+  (or
+   (plist-get exwm-randr-workspace-monitor-plist
+              (cl-position (selected-frame)
+                           exwm-workspace--list))
+   (car my/exwm-monitor-list)))
 

And a function to cycle the monitor list in either direction:

(defun my/exwm-get-other-monitor (dir)
   "Cycle the monitor list in the direction DIR.
@@ -665,16 +671,17 @@
   (my/exwm-last-workspaces-clear)
   (let ((mouse-autoselect-window nil))
     (exwm-workspace-switch
-     (cl-loop with other-monitor = (my/exwm-get-other-monitor (or dir 'right))
-              for i in (append my/exwm-last-workspaces
-                               (cl-loop for i from 0
-                                        for _ in exwm-workspace--list
-                                        collect i))
-              if (if other-monitor
-                     (string-equal (plist-get exwm-randr-workspace-monitor-plist i)
-                                   other-monitor)
-                   (not (plist-get exwm-randr-workspace-monitor-plist i)))
-              return i))))
+     (or
+      (cl-loop with other-monitor = (my/exwm-get-other-monitor (or dir 'right))
+               for i in (append my/exwm-last-workspaces
+                                (cl-loop for i from 0
+                                         for _ in exwm-workspace--list
+                                         collect i))
+               if (if other-monitor
+                      (string-equal (plist-get exwm-randr-workspace-monitor-plist i)
+                                    other-monitor)
+                    (not (plist-get exwm-randr-workspace-monitor-plist i)))
+               return i)))))
 

I bind this function to s-q, as I’m used from i3.

Move the workspace to another monitor

Now, moving the workspace to another monitor.

@@ -717,6 +724,18 @@ (my/exwm-switch-to-other-monitor dir)) (cl-loop while (windmove-find-other-window opposite-dir) do (windmove-do-window-select opposite-dir)))))) +

Update the monitor list

+
(defun my/exwm-refresh-monitors ()
+  (interactive)
+  (setq my/exwm-monitor-list (my/exwm-xrandr-monitor-list))
+  (cl-loop for i from 0 to (1- exwm-workspace-number)
+           for monitor = (plist-get exwm-randr-workspace-monitor-plist
+                                    i)
+           if (not (member monitor my/exwm-monitor-list))
+           do
+           (setf (plist-get exwm-randr-workspace-monitor-plist i)
+                 (car my/exwm-monitor-list)))
+  (exwm-randr-refresh))
 

Completions

Setting up some completion interfaces that fit particularly well to use with EXWM. While rofi also works, I want to use Emacs functionality wherever possible to have one completion interface everywhere.

ivy-posframe

@@ -1213,7 +1232,8 @@ (start-process-shell-command "xrandr" nil "~/bin/scripts/screen-layout") (when (string= (system-name) "violet") (setq my/exwm-another-monitor "DP-1") - (setq exwm-randr-workspace-monitor-plist `(2 ,my/exwm-another-monitor 3 ,my/exwm-another-monitor))) + (setq exwm-randr-workspace-monitor-plist `(2 ,my/exwm-another-monitor 3 ,my/exwm-another-monitor)) + (my/exwm-refresh-monitors)) (setq exwm-workspace-warp-cursor t) (setq mouse-autoselect-window t) @@ -4827,7 +4847,7 @@ desktop-misc - qview + geeqie Image viewer @@ -4960,6 +4980,7 @@
  • Switch to another monitor
  • Move the workspace to another monitor
  • Windmove between monitors
  • +
  • Update the monitor list
  • Completions diff --git a/configs/emacs/index.html b/configs/emacs/index.html index 0c028fd..404fa75 100644 --- a/configs/emacs/index.html +++ b/configs/emacs/index.html @@ -222,6 +222,34 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp link tasks to meetings 23496bfacc31ffedf2092da04e4e602b71373425 + + forge and code-review + bb1365d9a026cefb7051992a68176ea00f041abd + + + phscroll + bb1365d9a026cefb7051992a68176ea00f041abd + + + org-make-toc + bb1365d9a026cefb7051992a68176ea00f041abd + + + edraw-org + bb1365d9a026cefb7051992a68176ea00f041abd + + + sx.el + bb1365d9a026cefb7051992a68176ea00f041abd + + + atomic-chrome + bb1365d9a026cefb7051992a68176ea00f041abd + + + screenshot.el + bb1365d9a026cefb7051992a68176ea00f041abd +

    Initial setup

    @@ -259,26 +287,612 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
    (straight-use-package 'use-package)
     (eval-when-compile (require 'use-package))
    -

    Variables & environment

    -

    This section is about optioning the Emacs config.

    -

    The following is true is Emacs is run on a remote server where I don’t need stuff like my org workflow

    -
    (setq my/remote-server
    -      (or (string= (getenv "IS_REMOTE") "true")
    -          (string= (system-name) "dev-digital")
    -          (string= (system-name) "viridian")))
    -

    And the following is true if Emacs is run from termux on Android.

    -
    (setq my/is-termux (string-match-p (rx (* nonl) "com.termux" (* nonl)) (getenv "HOME")))
    +

    Modular configuration & environments

    +

    I’ve made the config sort of modular because I need different parts in different environments. With such a large config as mine, this is important.

    +

    The problem with one large init.el is it’s evaluated fully in every envronment, which means use-package will try to download, compile, etc. every package, which takes a lot of time on termux.

    +

    So this isn’t about separation of concerns or something like that. Modules aren’t independent; they’re loaded in the same order as they are specified in this file; further modules may depend on previously loaded modules.

    +

    Also, the modules are basically as large or small as they need to be required on each system.

    +

    Obviously, there are a lot of compromises in this approach, but it works for me. For a more careful approach to modules, take a look, e.g., at Protesilaos’ config.

    +

    First, I need to get the current environment:

    +
    (defun my/get-env ()
    +  (or (getenv "EMACS_ENV")
    +      (when (member (system-name) '("dev-digital" "viridian"))
    +        "remote")
    +      (when (string-match-p (rx (* nonl) "com.termux" (* nonl)) (getenv "HOME"))
    +        "termux")
    +      "normal"))
    +
    +(setq my/env (my/get-env))
    +

    Also, I sometimes need to know if a program is running inside Emacs (say, inside a terminal emulator). And sometimes I need to know if I’m running a nested Emacs session. To do that, I set the following environment variable:

    +
    (setq my/nested-emacs (and (getenv "IS_EMACS") t))
    +(setenv "IS_EMACS" "true")
     

    Custom system name logic because on termux it’s always “localhost”.

    (defun my/system-name ()
       (or (getenv "ANDROID_NAME")
           (system-name)))
    -

    Also, I sometimes need to know if a program is running inside Emacs (say, inside a terminal emulator). And sometimes I need to know if I’m running a nested Emacs session. To do that, I set the following environment variable:

    -
    (setq my/nested-emacs (and (getenv "IS_EMACS") t))
    -(setenv "IS_EMACS" "true")
    -

    Finally, I want to have a minimal Emacs config for debugging purposes. This has just straight.el, use-packages, and evil.

    -
    <<minimal>>
    -

    To launch Emacs with this config, run

    -
    emacs -q -l ~/.emacs.d/init-minimal.el
    +

    And a few legacy variables, which is true on termux.

    +
    (setq my/is-termux (equal (my/get-env) "termux"))
    +(setq my/remote-server (equal (my/get-env) "remote"))
    +

    Below is the configuration table that shows which module is activated in which environment.

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Module namenormaltermuxremote
    performance+++
    micromamba+
    misc-initial+++
    keybindings+++
    termux+
    i3+
    general-config+++
    wakatime++
    activitywatch+
    general-ui+++
    doom-modeline+++
    perspective+++
    treemacs++
    lsp+
    flycheck+++
    tree-sitter+++
    dap
    reformatter+
    copilot
    web+
    latex++
    markup+++
    lisp+++
    misc-programming+
    general-org++
    org-literate+
    org-productivity++
    org-export+
    dired+++
    tramp+
    terms+++
    dotfiles+++
    elfeed+
    mail+
    gnus+
    emms+
    misc-internet+++
    erc+
    mastodon+
    wallabag
    ement+
    telega++
    docs++
    ai+
    index++
    pass++
    docker+
    misc-apps++
    guix+
    emacs-pinentry+
    productivity-apps++
    chess+
    discord
    gource+
    +

    I want this table to be updated automatically based on this file.

    +

    So, first, specify how the modules are stored:

    +
    (setq my/modules-dir (file-name-as-directory
    +                      (expand-file-name "modules" user-emacs-directory)))
    +
    +(setq my/modules-prefix "sqrt-")
    +

    Then, scan Emacs.org for headings with the MODULE_NAME property and set the tangle property:

    +
    (defun my/modules--refresh-and-list ()
    +  (let (modules-list
    +        headlines)
    +    (org-element-map (org-element-parse-buffer) 'headline
    +      (lambda (elem) (push elem headlines)))
    +    (mapc
    +     (lambda (elem)
    +       (when-let ((module-name (org-element-property :MODULE_NAME elem)))
    +         (save-excursion
    +           (goto-char (org-element-property :begin elem))
    +           (org-set-property
    +            "header-args:emacs-lisp"
    +            (concat ":tangle " my/modules-dir my/modules-prefix module-name ".el"
    +                    " :comments links"))
    +           (push module-name modules-list))))
    +     headlines)
    +    (seq-uniq modules-list)))
    +

    Then, read and update the settings table:

    +
    (defun my/modules--read-table ()
    +  (save-excursion
    +    (goto-char (point-min))
    +    (re-search-forward (rx bol "#+NAME: modules-settings"))
    +    (forward-line)
    +    (let* ((table (org-element-at-point))
    +           (table-contents
    +            (mapcar
    +             (lambda (elem)
    +               (if (listp elem)
    +                   (mapcar #'substring-no-properties elem)
    +                 elem))
    +             (org-table-to-lisp)))
    +           (envs-list (cdar table-contents)))
    +      (mapcar
    +       (lambda (elem)
    +         (cons (car elem)
    +               (cl-loop for sign in (cdr elem)
    +                        for env in envs-list
    +                        collect (cons env (not (string-empty-p sign))))))
    +       (cddr table-contents)))))
    +
    +(defun my/modules--refresh-table (modules-list)
    +  (save-excursion
    +    (goto-char (point-min))
    +    (search-forward "#+NAME: modules-settings")
    +    (let* ((table (org-element-at-point))
    +           (table-contents
    +            (my/modules--read-table))
    +           (envs-list (mapcar #'car (cdar table-contents))))
    +      (delete-region (org-element-property :contents-begin table)
    +                     (org-element-property :contents-end table))
    +      (insert
    +       "\n"
    +       (string-trim
    +        (with-temp-buffer
    +          (insert "| Module name |"
    +                  (mapconcat #'identity envs-list " | ")
    +                  "\n")
    +          (insert "|--|\n")
    +          (dolist (module modules-list)
    +            (insert "| " module " | "
    +                    (cl-loop
    +                     for env in envs-list
    +                     if (alist-get
    +                         env
    +                         (alist-get module table-contents nil nil #'equal)
    +                         nil nil #'equal)
    +                     concat " + |"
    +                     else
    +                     concat " |")
    +                     "\n"))
    +          (goto-char (point-min))
    +          (org-table-align)
    +          (buffer-substring-no-properties (point-min) (point-max))))))))
    +

    Then, update the loading code that requires the necessary modules based on the environment:

    +
    (defun my/modules--refresh-loading ()
    +  (let* ((modules-table (my/modules--read-table))
    +         (envs-list (mapcar #'car (cdar modules-table))))
    +    (save-excursion
    +      (goto-char (point-min))
    +      (re-search-forward (rx bol "#+NAME: modules-loading"))
    +      (beginning-of-line 3)
    +      (delete-region
    +       (point)
    +       (save-excursion
    +         (re-search-forward (rx bol "#+end_src"))
    +         (end-of-line 0)
    +         (point)))
    +      (insert
    +       (pp-to-string
    +        `(pcase my/env
    +           ,@(mapcar
    +              (lambda (env)
    +                `(,env
    +                  ,@(seq-filter
    +                     #'identity
    +                     (mapcar
    +                      (lambda (elem)
    +                        (when (alist-get env (cdr elem) nil nil #'equal)
    +                          `(require ',(intern (concat my/modules-prefix (car elem))))))
    +                      modules-table))))
    +              envs-list)))))))
    +

    Also delete unnecessary modules:

    +
    (defun my/modules--cleanup-folder (modules-list)
    +  (let ((source-files (seq-filter
    +                       (lambda (f)
    +                         (equal (file-name-extension f) "el"))
    +                       (directory-files my/modules-dir)))
    +        (target-files
    +         (mapcar (lambda (m)
    +                   (concat my/modules-prefix m ".el"))
    +                 modules-list)))
    +    (dolist (extra-file (seq-difference source-files target-files))
    +      (delete-file (concat my/modules-dir extra-file)))))
    +

    And a function that combines all of the above:

    +
    (defun my/modules-settings-refresh ()
    +  (interactive)
    +  (org-fold-show-all)
    +  (let ((modules-list (my/modules--refresh-and-list)))
    +    (my/modules--refresh-table modules-list)
    +    (my/modules--refresh-loading)
    +    (my/modules--cleanup-folder modules-list)
    +    (setq my/modules-list modules-list)))
    +

    Now, add the modules directory to the load-path variable:

    +
    (push my/modules-dir load-path)
    +

    And require the necessary modules with the autogenerated code:

    +

    +
    (pcase my/env
    +  ("normal"
    +   (require 'sqrt-performance)
    +   (require 'sqrt-micromamba)
    +   (require 'sqrt-misc-initial)
    +   (require 'sqrt-keybindings)
    +   (require 'sqrt-i3)
    +   (require 'sqrt-general-config)
    +   (require 'sqrt-wakatime)
    +   (require 'sqrt-activitywatch)
    +   (require 'sqrt-general-ui)
    +   (require 'sqrt-doom-modeline)
    +   (require 'sqrt-perspective)
    +   (require 'sqrt-treemacs)
    +   (require 'sqrt-lsp)
    +   (require 'sqrt-flycheck)
    +   (require 'sqrt-tree-sitter)
    +   (require 'sqrt-reformatter)
    +   (require 'sqrt-web)
    +   (require 'sqrt-latex)
    +   (require 'sqrt-markup)
    +   (require 'sqrt-lisp)
    +   (require 'sqrt-misc-programming)
    +   (require 'sqrt-general-org)
    +   (require 'sqrt-org-literate)
    +   (require 'sqrt-org-productivity)
    +   (require 'sqrt-org-export)
    +   (require 'sqrt-dired)
    +   (require 'sqrt-tramp)
    +   (require 'sqrt-terms)
    +   (require 'sqrt-dotfiles)
    +   (require 'sqrt-elfeed)
    +   (require 'sqrt-mail)
    +   (require 'sqrt-gnus)
    +   (require 'sqrt-emms)
    +   (require 'sqrt-misc-internet)
    +   (require 'sqrt-erc)
    +   (require 'sqrt-mastodon)
    +   (require 'sqrt-ement)
    +   (require 'sqrt-telega)
    +   (require 'sqrt-docs)
    +   (require 'sqrt-ai)
    +   (require 'sqrt-index)
    +   (require 'sqrt-pass)
    +   (require 'sqrt-docker)
    +   (require 'sqrt-misc-apps)
    +   (require 'sqrt-guix)
    +   (require 'sqrt-productivity-apps)
    +   (require 'sqrt-chess)
    +   (require 'sqrt-gource))
    +  ("termux"
    +   (require 'sqrt-performance)
    +   (require 'sqrt-misc-initial)
    +   (require 'sqrt-keybindings)
    +   (require 'sqrt-termux)
    +   (require 'sqrt-general-config)
    +   (require 'sqrt-wakatime)
    +   (require 'sqrt-general-ui)
    +   (require 'sqrt-doom-modeline)
    +   (require 'sqrt-perspective)
    +   (require 'sqrt-treemacs)
    +   (require 'sqrt-flycheck)
    +   (require 'sqrt-tree-sitter)
    +   (require 'sqrt-latex)
    +   (require 'sqrt-markup)
    +   (require 'sqrt-lisp)
    +   (require 'sqrt-general-org)
    +   (require 'sqrt-org-productivity)
    +   (require 'sqrt-dired)
    +   (require 'sqrt-terms)
    +   (require 'sqrt-dotfiles)
    +   (require 'sqrt-misc-internet)
    +   (require 'sqrt-telega)
    +   (require 'sqrt-docs)
    +   (require 'sqrt-index)
    +   (require 'sqrt-pass)
    +   (require 'sqrt-misc-apps)
    +   (require 'sqrt-emacs-pinentry)
    +   (require 'sqrt-productivity-apps))
    +  ("remote"
    +   (require 'sqrt-performance)
    +   (require 'sqrt-misc-initial)
    +   (require 'sqrt-keybindings)
    +   (require 'sqrt-general-config)
    +   (require 'sqrt-general-ui)
    +   (require 'sqrt-doom-modeline)
    +   (require 'sqrt-perspective)
    +   (require 'sqrt-flycheck)
    +   (require 'sqrt-tree-sitter)
    +   (require 'sqrt-markup)
    +   (require 'sqrt-lisp)
    +   (require 'sqrt-dired)
    +   (require 'sqrt-terms)
    +   (require 'sqrt-dotfiles)
    +   (require 'sqrt-misc-internet)))
    +

    Finally, some post-processing of the tangled files:

    +
    (defun my/modules--post-tangle ()
    +  (when (string-match-p (rx bos (literal my/modules-dir)
    +                            (* nonl) ".el")
    +                        (buffer-file-name))
    +    (goto-char (point-min))
    +    (insert ";;; -*- lexical-binding: t -*-\n")
    +    (goto-char (point-max))
    +    (insert "\n(provide '" (file-name-base
    +                            (buffer-file-name)) ")")
    +    (save-buffer)
    +    (message "Processed %s as emacs config module" (buffer-file-name))))
    +
    +(add-hook 'org-babel-post-tangle-hook #'my/modules--post-tangle)
     

    Performance

    Measure startup speed

    A small function to print out the loading time and number of GCs during the loading. Can be useful as a point of data for optimizing Emacs startup time.

    @@ -340,7 +954,8 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp :straight t :if (executable-find "micromamba") :config - (micromamba-activate "general")) + (ignore-errors + (micromamba-activate "general")))

    Config files

    Custom file location

    By default, custom writes stuff to init.el, which is somewhat annoying. The following makes it write to a separate file custom.el

    @@ -369,9 +984,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
    (defun my/quit-window-and-buffer ()
       (interactive)
       (quit-window t))
    -

    Prevent Emacs from closing

    -

    This adds a confirmation to avoid accidental Emacs closing.

    -
    (setq confirm-kill-emacs 'y-or-n-p)
     

    Scratch buffer

    I have a problem with emacs-lisp-mode as initial-major-mode because in my config it loads lispy, which loads org-mode.

    So until I’ve made a better loading screen, this will do.

    @@ -690,7 +1302,7 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp ;; change font size, interactively (global-set-key (kbd "C-+") 'my/zoom-in) (global-set-key (kbd "C-=") 'my/zoom-out) -

    Termux

    +

    Termux settings

    For some reason my ONYX device has the tilde and escape wrong.

    (when (and my/is-termux (not (equal (my/system-name) "snow")))
       (define-key key-translation-map (kbd "`") (kbd "<escape>"))
    @@ -954,6 +1566,11 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
     
     
    (use-package smartparens
       :straight t)
    +

    The function below make smartparens behave the way I like for C-like languages:

    +
    (defun my/set-smartparens-indent (mode)
    +  (sp-local-pair mode "{" nil :post-handlers '(("|| " "SPC") ("||\n[i]" "RET")))
    +  (sp-local-pair mode "[" nil :post-handlers '(("|| " "SPC") ("||\n[i]" "RET")))
    +  (sp-local-pair mode "(" nil :post-handlers '(("|| " "SPC") ("||\n[i]" "RET"))))
     
    Visual fill column mode
    (use-package visual-fill-column
       :straight t
    @@ -1033,11 +1650,24 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
     

    I used to have Treemacs here, but in the end decided that dired with dired-sidebar does a better job. Dired has its separate section in “Applications”.

    Projectile

    Projectile gives a bunch of useful functions for managing projects, like finding files within a project, fuzzy-find, replace, etc.

    + + + + + + + + + + + + + +
    TypeNote
    TODOMaybe set projectile-project-search-path based on the folder index?
    (use-package projectile
       :straight t
       :config
       (projectile-mode +1)
    -  (setq projectile-project-search-path '("~/Code" "~/Documents"))
       (general-define-key
         :keymaps 'projectile-command-map
         "b" #'consult-project-buffer))
    @@ -1127,66 +1757,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
     

    And I suspect the built-in window width function doesn’t work as intended because of global-display-line-numbers-mode.

    (setq difftastic-requested-window-width-function
           (lambda () (- (frame-width) 4)))
    -

    Forge and code-review

    -

    forge provides integration with forges, such as GitHub and GitLab.

    -
    (use-package forge
    -  :after magit
    -  :straight t
    -  :config
    -  (add-to-list 'forge-alist '("gitlab.etu.ru"
    -                              "gitlab.etu.ru/api/v4"
    -                              "gitlab.etu.ru"
    -                              forge-gitlab-repository)))
    -

    forge depends on a package called ghub. I don’t like that it uses auth-source to store the token so I’ll advise it to use password-store.

    -
    (defun my/password-store-get-field (entry field)
    -  (if-let (field (password-store-get-field entry field))
    -      field
    -    (my/password-store-get-field entry field)))
    -
    -(defun my/ghub--token (host username package &optional nocreate forge)
    -  (cond ((and (or (equal host "gitlab.etu.ru/api/v4")
    -                  (equal host "gitlab.etu.ru/api"))
    -              (equal username "pvkorytov"))
    -         (my/password-store-get-field
    -          "Job/Digital/Infrastructure/gitlab.etu.ru"
    -          (format "%s-token" package)))
    -        (t (error "Don't know token: %s %s %s" host username package))))
    -
    -(with-eval-after-load 'ghub
    -  (advice-add #'ghub--token :override #'my/ghub--token))
    -

    code-review is a package that implements code review in Emacs. The main branch is broken, but this PR works.

    -
    (use-package code-review
    -  :straight (:host github :repo "phelrine/code-review" :branch "fix/closql-update")
    -  :after forge
    -  :config
    -  (setq code-review-auth-login-marker 'forge)
    -  (setq code-review-gitlab-base-url "gitlab.etu.ru")
    -  (setq code-review-gitlab-host "gitlab.etu.ru/api")
    -  (setq code-review-gitlab-graphql-host "gitlab.etu.ru/api")
    -  (general-define-key
    -   :states '(normal visual)
    -   :keymaps '(code-review-mode-map)
    -   "RET" #'code-review-comment-add-or-edit
    -   "gr" #'code-review-reload
    -   "r" #'code-review-transient-api
    -   "s" #'code-review-comment-code-suggestion
    -   "d" #'code-review-submit-single-diff-comment-at-point
    -   "TAB" #'magit-section-toggle)
    -  (general-define-key
    -   :states '(normal)
    -   :keymaps '(forge-topic-mode-map)
    -   "M-RET" #'code-review-forge-pr-at-point))
    -

    Fix issue 253:

    -
    (defun my/code-review-comment-quit ()
    -  "Quit the comment window."
    -  (interactive)
    -  (magit-mode-quit-window t)
    -  (with-current-buffer (get-buffer code-review-buffer-name)
    -    (goto-char code-review-comment-cursor-pos)
    -    (code-review-comment-reset-global-vars)))
    -
    -(with-eval-after-load 'code-review
    -  (advice-add #'code-review-comment-quit :override #'my/code-review-comment-quit))
     

    Editorconfig

    Editorconfig support for Emacs.

    References:

    @@ -1557,7 +2127,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
    (use-package wakatime-mode
       :straight (:host github :repo "SqrtMinusOne/wakatime-mode")
    -  :if (not (or my/remote-server))
       :config
       (setq wakatime-ignore-exit-codes '(0 1 102 112))
       (advice-add 'wakatime-init :after
    @@ -1578,7 +2147,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
     
     (use-package activity-watch-mode
       :straight t
    -  :if (not (or my/is-termux my/remote-server))
       :config
       (global-activity-watch-mode))
     

    UI settings

    @@ -1595,6 +2163,8 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp

    Transparency. Not setting it here, as I used to use picom with i3, and EXWM config has its own settings.

    ;; (set-frame-parameter (selected-frame) 'alpha '(90 . 90))
     ;; (add-to-list 'default-frame-alist '(alpha . (90 . 90)))
    +

    This adds a confirmation to avoid accidental Emacs closing.

    +
    (setq confirm-kill-emacs 'y-or-n-p)
     

    Prettify symbols. Also not setting it, ligatures seem to be enough for me.

    ;; (global-prettify-symbols-mode)
     

    Do not show GUI dialogs

    @@ -1676,9 +2246,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
    :config (setq doom-themes-enable-bold t doom-themes-enable-italic t) - ;; (if my/remote-server - ;; (load-theme 'doom-gruvbox t) - ;; (load-theme 'doom-palenight t)) (doom-themes-visual-bell-config) (setq doom-themes-treemacs-theme "doom-colors") (doom-themes-treemacs-config)) @@ -2027,7 +2594,7 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp

    Highlight indent guides. I used highlight-indent-guides before but indent-bars seems to work better, and it doesn’t break with treesit-fold.

    (use-package indent-bars
       :straight (:host github :repo "jdtsmith/indent-bars")
    -  :if (not (or my/remote-server))
    +  :if (display-graphic-p)
       :hook ((prog-mode . indent-bars-mode)
              (LaTeX-mode . indent-bars-mode))
       :config
    @@ -2277,7 +2844,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
     
    Setup
    (use-package lsp-mode
       :straight t
    -  :if (not (or my/is-termux my/remote-server))
       :hook (
              (typescript-mode . lsp)
              (js-mode . lsp)
    @@ -2389,11 +2955,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
       :config
       (global-flycheck-mode)
       (setq flycheck-check-syntax-automatically '(save idle-buffer-switch mode-enabled))
    -  ;; (add-hook 'evil-insert-state-exit-hook
    -  ;;           (lambda ()
    -  ;;             (if flycheck-checker
    -  ;;                 (flycheck-buffer))
    -  ;;             ))
       (advice-add 'flycheck-eslint-config-exists-p :override (lambda() t))
       (add-to-list 'display-buffer-alist
                    `(,(rx bos "*Flycheck errors*" eos)
    @@ -2402,18 +2963,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
                      (side            . bottom)
                      (reusable-frames . visible)
                      (window-height   . 0.33))))
    -

    General additional config

    -

    Have to put this before tree-sitter because I need my/set-smartparens-indent there.

    -

    Make smartparens behave the way I like for C-like languages.

    -
    (defun my/set-smartparens-indent (mode)
    -  (sp-local-pair mode "{" nil :post-handlers '(("|| " "SPC") ("||\n[i]" "RET")))
    -  (sp-local-pair mode "[" nil :post-handlers '(("|| " "SPC") ("||\n[i]" "RET")))
    -  (sp-local-pair mode "(" nil :post-handlers '(("|| " "SPC") ("||\n[i]" "RET"))))
    -

    Override flycheck checker with eslint.

    -
    (defun my/set-flycheck-eslint()
    -  "Override flycheck checker with eslint."
    -  (setq-local lsp-diagnostic-package :none)
    -  (setq-local flycheck-checker 'javascript-eslint))
     

    Tree-sitter

    References:

      @@ -2534,7 +3083,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
      (use-package dap-mode
         :straight t
      -  :if (not (or my/remote-server my/is-termux))
         :commands (dap-debug)
         :init
         (setq lsp-enable-dap-auto-configure nil)
      @@ -2805,7 +3353,21 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
       
      (use-package reformatter
         :straight t)
       

      copilot

      -

      GitHub Copilot is a project of GitHub and OpenAI that provides code completions. It’s somewhat controversial in the Emacs community but I opt in for now.

      +

      GitHub Copilot is a project of GitHub and OpenAI that provides code completions.

      + + + + + + + + + + + + + +
      TypeNote
      TODOFigure out how to bypass U.S. export controls
      (defun my/copilot-tab ()
         (interactive)
         (or (copilot-accept-completion)
      @@ -3677,7 +4239,7 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
         :commands (python-pytest-dispatch)
         :init
         (my-leader-def
      -    :keymaps 'python-mode-map
      +    :keymaps '(python-mode-map python-ts-mode-map)
           :infix "t"
           "t" 'python-pytest-dispatch)
         :config
      @@ -3896,7 +4458,7 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
         :straight t
         :after (lsp)
         :config
      -  (setq lsp-java-jdt-download-url "https://download.eclipse.org/jdtls/milestones/0.57.0/jdt-language-server-0.57.0-202006172108.tar.gz"))
      +  (setq lsp-java-jdt-download-url "https://www.eclipse.org/downloads/download.php?file=/jdtls/milestones/1.23.0/jdt-language-server-1.23.0-202304271346.tar.gz"))
       
       (add-hook 'java-mode-hook #'smartparens-mode)
       ;; (add-hook 'java-mode-hook #'hs-minor-mode)
      @@ -3981,7 +4543,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
       
       (use-package org
         :straight (:type built-in)
      -  :if (not my/remote-server)
         :defer t
         :init
         (unless (file-exists-p org-directory)
      @@ -4041,16 +4602,9 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
                    :repo "https://git.sr.ht/~bzg/org-contrib"
                    :build t)
         :after (org)
      -  :if (not my/remote-server)
         :config
         (require 'ox-extra)
         (ox-extras-activate '(latex-header-blocks ignore-headlines)))
      -

      ol-notmuch

      -

      ol-notmuch is a package that adds Org links to notmuch messages.

      -
      (unless (or my/remote-server my/is-termux)
      -  (use-package ol-notmuch
      -    :straight t
      -    :after (org notmuch)))
       

      org-tempo

      org-tempo is a convinient package that provides snippets for various org blocks.

      (with-eval-after-load 'org
      @@ -4279,8 +4833,7 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
       
       
      (use-package jupyter
         :straight t
      -  :after (org)
      -  :if (not (or my/remote-server my/is-termux)))
      +  :after (org))
       

      Refresh kernelspecs.

      Kernelspecs by default are hashed, so even switching Anaconda environments doesn’t change the kernel (i.e. kernel from the first environment is run after the switch to the second one).

      (defun my/jupyter-refresh-kernelspecs ()
      @@ -4303,7 +4856,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
       

      Hy

      (use-package ob-hy
         :after (org)
      -  :if (not my/remote-server)
         :straight t)
       

      View HTML in browser

      Open HTML in the begin_export block with xdg-open.

      @@ -4338,7 +4890,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
    (use-package restclient
    -  :if (not my/remote-server)
       :straight t
       :mode ("\\.http\\'" . restclient-mode)
       :config
    @@ -4356,7 +4907,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
     
     (use-package ob-restclient
       :after (org restclient)
    -  :if (not my/remote-server)
       :straight t)
     

    Org Babel Setup

    Enable languages

    @@ -4614,7 +5164,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
    (use-package org-present :straight (:host github :repo "rlister/org-present") - :if (not my/remote-server) :commands (org-present) :config (general-define-key @@ -4652,22 +5201,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp (org-latex-preview '(64)) (olivetti-mode -1) (setq-local olivetti-body-width (default-value 'olivetti-body-width)))))) -

    TOC

    -

    Make a TOC inside the org file.

    -

    References:

    - - -
    (use-package org-make-toc
    -  :after (org)
    -  :if (not my/remote-server)
    -  :commands
    -  (org-make-toc
    -   org-make-toc-insert
    -   org-make-toc-set
    -   org-make-toc-at-point)
    -  :straight t)
     

    Screenshots

    A nice package to make screenshots and insert them to the Org document.

    (use-package org-attach-screenshot
    @@ -4694,14 +5227,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
        "C-c t a" #'org-transclusion-add
        "C-c t A" #'org-transclusion-add-all
        "C-c t t" #'org-transclusion-mode))
    -

    Drawing

    -

    This package is unbelievably good. I would have never thought it’s even possible to have this in Emacs.

    -
    (use-package edraw-org
    -  :straight (:host github :repo "misohena/el-easydraw")
    -  :if (and (not my/is-termux) (not my/remote-server))
    -  :after (org)
    -  :config
    -  (edraw-org-setup-default))
     

    Managing tables

    I use Org to manage some small tables which I want to process further. So here is a function that saves each table to a CSV file.

    (defun my/export-org-tables-to-csv ()
    @@ -4717,14 +5242,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
               (buffer-file-name))
              name ".csv")
             "orgtbl-to-csv")))))
    -

    Partial scrolling

    -
    (use-package phscroll
    -  :straight (:host github :repo "misohena/phscroll")
    -  :commands (org-phscroll-mode)
    -  :config
    -  (with-eval-after-load 'org
    -    (require 'org-phscroll)
    -    (org-phscroll-deactivate)))
     

    Productivity & Knowledge management

    My ongoing effort to get a productivity setup manage something in my life in Org.

    Initial inspirations (<2021-06-30 Wed>):

    @@ -5004,7 +5521,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp

    org-ql is a package to query org files.

    (use-package org-ql
       :after (org)
    -  :if (not my/remote-server)
       :straight t
       :config
       (setq org-ql-ask-unsafe-queries nil)
    @@ -5654,7 +6170,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
     

    And it was interesting to find the reinforcement effect of checked dates on the calendar.

    (use-package org-journal
       :straight t
    -  :if (not my/remote-server)
       :init
       (my-leader-def
         :infix "oj"
    @@ -5674,7 +6189,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
     
    (use-package org-journal-tags
       :straight (:host github :repo "SqrtMinusOne/org-journal-tags")
       :after (org-journal)
    -  :if (not my/remote-server)
       :config
       (org-journal-tags-autosync-mode)
       (general-define-key
    @@ -5804,7 +6318,6 @@ Emacs is also particularly great at writing Lisp code, e.g. Clojure, Common Lisp
     

    Also, at some point the package loaded Helm on start, so I exclude these files from the recipe.

    (use-package org-ref
       :straight (:files (:defaults "citeproc" (:exclude "*helm*")))
    -  :if (not my/remote-server)
       :commands (org-ref-insert-link-hydra/body
                  org-ref-bibtex-hydra/body)
       :init
    @@ -5866,15 +6379,12 @@ Didn’t work out as I expected, so I’ve made org-journal-tags
     
    (use-package emacsql-sqlite
       :defer t
    -  :if (not my/remote-server)
       :straight (:type built-in))
     
     (use-package org-roam
       :straight (:host github :repo "org-roam/org-roam"
                        :files (:defaults "extensions/*.el"))
    -  :if (and
    -       (not my/remote-server)
    -       (file-directory-p org-roam-directory))
    +  :if (file-directory-p org-roam-directory)
       :after org
       :init
       (setq org-roam-file-extensions '("org"))
    @@ -6058,7 +6568,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tagsActually, I don’t find this quite as useful as structure nodes, because over time my graph grew somewhat convoluted. But it looks impressive.

    (use-package org-roam-ui
       :straight (:host github :repo "org-roam/org-roam-ui" :branch "main" :files ("*.el" "out"))
    -  :if (not my/remote-server)
       :after org-roam
       ;; :hook (org-roam . org-roam-ui-mode)
       :init
    @@ -6067,7 +6576,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tagsDeft is an Emacs package to quickly find notes. I use it as a full-text search engine for org-roam.

    (use-package deft
       :straight t
    -  :if (not my/remote-server)
       :commands (deft)
       :after (org)
       :init
    @@ -6469,7 +6977,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tagsIt seems the package has been somewhat revived in the recent months. It used things like lexical-let when I first found it.

    (use-package org-contacts
       :straight (:type git :repo "https://repo.or.cz/org-contacts.git")
    -  :if (not my/remote-server)
       :after (org)
       :config
       (setq org-contacts-files (list
    @@ -6538,19 +7045,16 @@ Didn’t work out as I expected, so I’ve made org-journal-tags
     
    (use-package ox-hugo
       :straight t
    -  :if (not my/remote-server)
       :after ox)
     

    Jupyter Notebook

    (use-package ox-ipynb
       :straight (:host github :repo "jkitchin/ox-ipynb")
    -  :if (not my/remote-server)
       :disabled t
       :after ox)
     

    Html export

    (use-package htmlize
       :straight t
       :after ox
    -  :if (not my/remote-server)
       :config
       (setq org-html-htmlize-output-type 'css))
     

    org-ref

    @@ -7178,6 +7682,14 @@ Didn’t work out as I expected, so I’ve made org-journal-tags
    (mastodon-toot-attach-media file (read-from-minibuffer (format "Description for %s: " file)))))) +

    Attach files to gptel.

    +
    (defun my/dired-attach-to-gptel (files)
    +  (interactive
    +   (list (dired-get-marked-files nil nil #'dired-nondirectory-p)))
    +  (unless files
    +    (user-error "No (non-directory) files selected"))
    +  (dolist (file files)
    +    (gptel-context-add-file file)))
     

    And the keybindings:

    (with-eval-after-load 'dired
       (general-define-key
    @@ -7186,7 +7698,8 @@ Didn’t work out as I expected, so I’ve made org-journal-tags   "a" nil
        "at" #'my/dired-attach-to-telega
        "am" #'my/dired-attach-to-notmuch
    -   "ai" #'my/dired-attach-to-ement
    +   "ae" #'my/dired-attach-to-ement
    +   "ai" #'my/dired-attach-to-gptel
        "an" #'my/dired-attach-to-mastodon))
     
    (with-eval-after-load 'telega
       (general-define-key
    @@ -7212,7 +7725,7 @@ Didn’t work out as I expected, so I’ve made org-journal-tags        (append tramp-remote-path
                     '(tramp-own-remote-path))))
     

    Set the default shell to bin/bash for TRAMP or on a remote server.

    -
    (when (or my/remote-server)
    +
    (when my/remote-server
       (setq explicit-shell-file-name "/bin/bash"))
     

    Package optimizations

    Unfortunately, many Emacs packages don’t exactly moderate their rate of filesystem operations, and on TRAMP over network each operation adds additional overhead, so… it can get pretty slow. To debug these issues, set the following variable to 6:

    @@ -7793,7 +8306,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tagsUsing my own fork until the modifications are merged into master.

    (use-package elfeed
       :straight (:repo "SqrtMinusOne/elfeed" :host github)
    -  :if (not (or my/is-termux my/remote-server))
       :commands (elfeed)
       :init
       (my-leader-def "ae" #'elfeed-summary)
    @@ -7905,7 +8417,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tagselfeed-sync is my package to sync elfeed with tt-rss.

    (use-package elfeed-sync
       :straight (:host github :repo "SqrtMinusOne/elfeed-sync")
    -  :if (not my/remote-server)
       :after elfeed
       :config
       (elfeed-sync-mode)
    @@ -8389,11 +8900,10 @@ Didn’t work out as I expected, so I’ve made org-journal-tagsInternet & Multimedia
     

    Notmuch

    My notmuch config now resides in Mail.org.

    -
    (unless (or my/remote-server)
    -  (let ((mail-file (expand-file-name "mail.el" user-emacs-directory)))
    -    (if (file-exists-p mail-file)
    -        (load-file mail-file)
    -      (message "Can't load mail.el"))))
    +
    (let ((mail-file (expand-file-name "mail.el" user-emacs-directory)))
    +  (if (file-exists-p mail-file)
    +      (load-file mail-file)
    +    (message "Can't load mail.el")))
     

    Gnus

    Gnus is an Emacs newsreader.

    I’ll try to use it for NTTP for now. Will see if I can do more with it.

    @@ -8468,7 +8978,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tags
    (use-package emms
       :straight t
    -  :if (not (or my/remote-server my/is-termux))
       :commands (emms-smart-browse
                  emms-browser
                  emms-add-url
    @@ -9119,9 +9628,9 @@ Didn’t work out as I expected, so I’ve made org-journal-tags     :class transient-row
          ("r" "Reply" mastodon-toot-reply)
          ("v" "Vote" mastodon-tl-poll-vote)
    -     ("b" "Boost" my/mastodon-toot--toggle-boost-confirm)
    -     ("f" "Favourite" my/mastodon-toot--toggle-favourite-confirm)
    -     ("k" "Bookmark" my/mastodon-toot--toggle-bookmark-confirm)]
    +     ("b" "Boost" my/mastodon-toot-toggle-boost-confirm)
    +     ("f" "Favourite" my/mastodon-toot-toggle-favourite-confirm)
    +     ("k" "Bookmark" my/mastodon-toot-toggle-bookmark-confirm)]
         ["My Toot Actions"
          :class transient-row
          ("md" "Delete" mastodon-toot-delete-toot)
    @@ -9349,7 +9858,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tags  ;; :straight (:type built-in)
       ;; For now emacs-telega-server is compatible with the latest telega.el
       :straight t
    -  :if (not (or my/remote-server))
       :commands (telega)
       :init
       (my-leader-def "a l" (my/command-in-persp "telega" "telega" 3 (telega)))
    @@ -9479,7 +9987,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tags
     
    (use-package google-translate
       :straight t
    -  :if (not my/remote-server)
       :functions (my-google-translate-at-point google-translate--search-tkk)
       :commands (google-translate-at-point
                  google-translate-at-point-reverse
    @@ -9592,61 +10099,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tags    "O" #'devdocs-browser-remove-offline-data
         "u" #'devdocs-browser-upgrade-all-docs
         "r" #'devdocs-browser-update-docs))
    -

    StackExchange

    -

    sx.el is a StackExchange client for Emacs.

    -
    (use-package sx
    -  :straight t
    -  :commands (sx-search sx-tab-frontpage)
    -  :config
    -  (general-define-key
    -   :states '(normal)
    -   :keymaps '(sx-question-mode-map sx-question-list-mode-map)
    -   "go" #'sx-visit-externally
    -   "q" #'quit-window
    -   "s*" #'sx-tab-starred
    -   "sU" #'sx-tab-unanswered-my-tags
    -   "sa" #'sx-ask
    -   "sf" #'sx-tab-featured
    -   "sh" #'sx-tab-frontpage
    -   "si" #'sx-inbox
    -   "sm" #'sx-tab-meta-or-main
    -   "sn" #'sx-tab-newest
    -   "su" #'sx-tab-unanswered
    -   "sv" #'sx-tab-topvoted
    -   "sw" #'sx-tab-week
    -   "u" #'sx-upvote
    -   "d" #'sx-downvote
    -   "j" nil
    -   "k" nil)
    -  (general-define-key
    -   :states '(normal)
    -   :keymaps '(sx-question-mode-map)
    -   "gr" #'sx-question-mode-refresh
    -   "J" #'sx-question-mode-next-section
    -   "K" #'sx-question-mode-previous-section
    -   "a" #'sx-answer
    -   "e" #'sx-edit
    -   "D" #'sx-delete
    -   "c" #'sx-comment)
    -  (general-define-key
    -   :states '(normal)
    -   :keymaps '(sx-question-list-mode-map)
    -   "RET" 'sx-display
    -   "j" #'sx-question-list-next
    -   "k" #'sx-question-list-previous
    -   "S" #'sx-search
    -   "m" #'sx-question-list-mark-read
    -   "O" #'sx-question-list-order-by
    -   "t" #'sx-tab-switch)
    -  (my-leader-def
    -   "hs" #'sx-search
    -   "hS" #'sx-tab-frontpage)
    -  (my/use-colors
    -   (sx-question-mode-accepted :foreground (my/color-value 'green)
    -                              :weight 'bold)
    -   (sx-question-mode-content :background nil))
    -  (add-hook 'sx-question-mode-hook #'doom-modeline-mode)
    -  (add-hook 'sx-question-list-mode-hook #'doom-modeline-mode))
     

    Not-an-AI

    Workflows, which are sometimes referred to as “AI”, go in here.

    I’m technically writing a PhD on a related topic, so I’m a bit more receptive towards the whole thing than most of the community. But I’m still not calling it AI.

    @@ -9672,10 +10124,10 @@ Didn’t work out as I expected, so I’ve made org-journal-tags
    :stream t :models '("llama3.1:8b" "deepseek-r1:32b" "qwen2.5:32b" "qwen2.5-coder:32b" + "qwen3:30b" "qwen3:32b" "eva-qwen2.5-q4_k_l-32b:latest" - "t-pro-1.0-q4_k_m:latest" - "qwq:32b" - (gemma3:32b + "gpt-oss" + (gemma3:27b :capabilities (media) :mime-types ("image/jpeg" "image/png"))))) (gptel-make-openai "OpenRouter" @@ -9683,7 +10135,9 @@ Didn’t work out as I expected, so I’ve made org-journal-tags :key (lambda () (my/password-store-get-field "My_Online/Accounts/openrouter" "api-key")) :stream t - :models '("anthropic/claude-3.5-haiku")) + :models '("anthropic/claude-sonnet-4" + "qwen/qwen3-coder" + "qwen/qwen3-coder:free")) (setq gptel--known-backends (seq-filter (lambda (cell) @@ -9699,6 +10153,10 @@ Didn’t work out as I expected, so I’ve made org-journal-tags :states '(insert normal) "C-<return>" 'gptel-send "M-o" #'gptel-menu)) +
    Add files to context
    +
    (defun my/gptel-add-current-file ()
    +  (interactive)
    +  (gptel-context-add-file (buffer-file-name)))
     
    ellama

    ellama provides commands that feed things from Emacs buffers into LLMs with various prompts.

    (use-package ellama
    @@ -10388,7 +10846,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tags   (mapcar
         (lambda (elem) (my/index--tree-narrow-recursive elem (my/system-name)))
         (copy-tree tree))))
    -
    my/index--tree-narrow
     

    Commands

    Next, apply the tree to the filesystem.

    I’ve decided to implement this by generating a bash script and executing it with bash +x. This way, I can check the required changes in advance and avert potential data loss if something unexpected happens.

    @@ -10583,7 +11040,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tags
    (format "mega-sync -d \"%s\"" (substring path 0 (1- (length path)))) "Mega remove sync" 4))))) -
    my/index--mega-commands
     
    Git repos

    To sync git, we just need to clone the required git repos. Removing the repos is handled by the folder sync commands.

    (defun my/index--git-commands (tree)
    @@ -10690,7 +11146,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tags                                 (substring symlink 0 -1))
                              "Make symlinks" 7)
                append (my/index-get-symlink-commands (alist-get :children elem))))
    -
    my/index-get-symlink-commands
     
    Run all commands

    And put that all together.

    First, as I want to check what’s going to be executed, let’s make a function to display commands in a separate buffer.

    @@ -10977,36 +11432,18 @@ Didn’t work out as I expected, so I’ve made org-journal-tags
    (if-let ((res (password-store-get entry))) res (my/password-store-get entry))) + +(defun my/password-store-get-field (entry field) + (if-let (field (password-store-get-field entry field)) + field + (my/password-store-get-field entry field)))

    Docker

    A package to manage docker containers from Emacs.

    (use-package docker
       :straight t
    -  :if (not (or my/remote-server my/is-termux))
       :commands (docker)
       :init
       (my-leader-def "ao" 'docker))
    -

    screenshot.el

    -

    Tecosaur’s plugin to make beautiful code screenshots.

    - - - - - - - - - - - -
    Guix dependency
    imagemagick
    -
    (use-package screenshot
    -  :straight (:repo "tecosaur/screenshot"
    -                   :host github
    -                   :build (:not compile))
    -  :if (display-graphic-p)
    -  :commands (screenshot)
    -  :init
    -  (my-leader-def "S" 'screenshot))
     

    proced

    proced is an Emacs built-it process viewer, like top.

    (my-leader-def "ah" 'proced)
    @@ -11019,7 +11456,7 @@ Didn’t work out as I expected, so I’ve made org-journal-tagsAn Emacs package to help managing GNU Guix.

    (use-package guix
       :straight t
    -  :if (not (or my/remote-server my/is-termux))
    +  :if (executable-find "guix")
       :commands (guix)
       :init
       (my-leader-def "ag" 'guix)
    @@ -11027,12 +11464,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tags    "A dummy function.")
       (defvar geiser-repl-company-p nil
         "A dummy variable."))
    -

    Atomic Chrome

    -

    Atomic Chrome is an extension that allows to edit browser text fields in Emacs. Despite its name, it also works for Firefox with GhostText, which is what I use.

    -
    (use-package atomic-chrome
    -  :if (not (or my/remote-server my/is-termux))
    -  :commands (atomic-chrome-start-server)
    -  :straight t)
     

    Pinentry

    Emacs-based pinentry works great on Termux.

    (use-package pinentry
    @@ -11233,8 +11664,8 @@ Didn’t work out as I expected, so I’ve made org-journal-tags            (string= (system-name) "violet")
                 (string= (system-name) "eminence")
                 (string= (system-name) "iris"))
    -           (not my/remote-server)
                (not my/nested-emacs))
    +  :disabled t
       :config
       (setq elcord-buffer-details-format-function #'my/elcord-buffer-details-format-functions)
       (advice-add 'elcord--try-update-presence :filter-args #'my/elcord-update-presence-mask-advice)
    @@ -11246,13 +11677,6 @@ Didn’t work out as I expected, so I’ve made org-journal-tags
    (use-package snow
       :straight (:repo "alphapapa/snow.el" :host github)
       :commands (snow))
    -

    Power mode

    -

    When Emacs doesn’t feel powerful enough.

    -

    Watch out if you are using EXWM.

    -
    (use-package power-mode
    -  :straight (:host github :repo "elizagamedev/power-mode.el")
    -  :disabled
    -  :commands (power-mode))
     

    Redacted

    (use-package redacted
       :commands (redacted-mode)
    @@ -11574,7 +11998,7 @@ I’ve seen a couple of cases where people would swap their username and ema
                 
  • use-package
  • -
  • Variables & environment
  • +
  • Modular configuration & environments
  • Performance
  • -
  • Prevent Emacs from closing
  • Scratch buffer
  • @@ -11610,9 +12033,9 @@ I’ve seen a couple of cases where people would swap their username and ema
  • which-key
  • Evil
  • My keybindings
  • -
  • Termux
  • +
  • Termux settings
  • i3 integration
  • Editing text