diff --git a/feed.xml b/feed.xml index b949ba8..eb5d1b3 100644 --- a/feed.xml +++ b/feed.xml @@ -17,8 +17,8 @@ https://judah.freedomland.xyz// en - Fri, 22 Dec 2023 00:00:00 -0500 - Sun, 24 Dec 2023 02:30:24 -0500 + Wed, 27 Dec 2023 00:00:00 -0500 + Wed, 27 Dec 2023 22:58:08 -0500 weblorg 0.1.0 (https://emacs.love/weblorg) Judah Sotomayor @@ -29,10 +29,185 @@ - Reflections on a year of Zettelkasten: Tooling - https://judah.freedomland.xyz//posts/reflections-on-a-year-of-zettelkasten-tooling.html + In Pursuit of an Efficient Org-Agenda + https://judah.freedomland.xyz//posts/efficient-org-agenda.html author@mail.com (Blog Author) - https://judah.freedomland.xyz//posts/reflections-on-a-year-of-zettelkasten-tooling.html + https://judah.freedomland.xyz//posts/efficient-org-agenda.html + + Wed, 27 Dec 2023 00:00:00 -0500 + + +

Table of Contents

+ + +

+After beginning my Emacs and Org-Mode adventures I quickly realized the insufficiency of the standard agenda. +It is wonderful at producing a list, but I am quickly approaching over 1000 notes. +The agenda tooling is incapable of searching this many files efficiently, and it took over thirty seconds to generate an agenda. +

+ +

+This was intolerable. I had two options: +

+
    +
  1. Place all my TODO items into a single file.
  2. +
  3. Narrow the number of files the agenda mechanism needs to search
  4. +
+ +

+I find the first option undesireable for reasons I mentioned in my post about zettelkasten tools. +I like to have my todo items mixed with the context where they were born. +A student of the Getting Things Done methodology might ask, "Doesn't this violate the central todo-list principle?" +Yes, it does. +Org-agenda allows me to have my cake and eat it too. +I can create a centralized todo-list out of all my todo items, and then immediately jump into the context of my next task. +

+ +

+It took several iterations of configuration to reach a seamless workflow. +If you'd like to jump straight to the final setup, here's the link. +

+ +
+

1. First Iteration

+
+

+The first piece of tooling I used came from this post and this Gist. +Essentially it creates a function vulpea-project-files that can easily query for a tag, and then sets the org-agenda files to all the files containing this tag. +

+ +

+Coupled with a helper-function that adds the tag hastodos to any file containing a TODO entry, it functioned well. +

+
+
(defun vulpea-project-files ()
+  "Return a list of note files containing 'hastodos' tag." ;
+  (seq-uniq
+   (seq-map
+    #'car
+    (org-roam-db-query
+     [:select [nodes:file]
+      :from tags
+      :left-join nodes
+      :on (= tags:node-id nodes:id)
+      :where (like tag (quote "%\"hastodos\"%"))]))))
+(setq org-agenda-files (vulpea-project-files))
+
+
+ +

+This solution is great because it is pure elisp. +Anywhere you're running Emacs it should function just fine. +It also works well with one of my needs: transparent file encryption. +Emacs has extensions for both gpg and age encryption that allow files to be transparently encrypted and decrypted. +This solution can make use of that where a standard grep could not. +

+
+
+ +
+

2. Second Iteration

+
+

+Eventually, I grew tired of seeing the entire solution in my config file. +All told, it is about 170 lines. +This is a lot for a small utility! +

+ +

+I decided to try using ripgrep to fix this: +

+
+
(defun set-org-agenda-files-ripgrep ()
+    (setq org-agenda-files (split-string (shell-command-to-string "rg -torg -l TODO /home/user/org"))))
+
+
+

+This worked nicely. +It takes just a few lines, runs just as fast–probably faster–than pure elisp, and is much easier to read and understand. +

+ +

+The only difficulty is encryption. +ripgrep does not operate on open emacs buffers, instead it operates on what is saved to disk. +Naturally, this means that it only sees the encrypted files. +

+
+
+ +
+

3. Final

+
+

+The solution to file encryption is ripgrep preprocessing. +I owe this solution to this reddit post. +

+ +

+Ripgrep can run a command (or shell script!) to files before processing. +While the original poster was using gpg to encrypt files, just a few modifications allowed me to use age. +

+ +
+
#!/usr/bin/env zsh
+case "$1" in
+*.age)
+    # The -s flag ensures that the file is non-empty.
+    if [ -s "$1" ]; then
+        exec /usr/bin/age --decrypt -i ~/.age/personal $1
+    else
+        exec cat
+    fi
+    ;;
+*)
+    ;;
+esac
+
+
+

+This script operates on all .age files, decrypting them to stdout. +When using a preprocessor, ripgrep will simply search the output of the command. +

+ +

+I often have a mix of files in my notes directory, so I use filetypes to restrict ripgrep. +This means I have to add a new filetype to allow .age files through the filter. +

+
+
rg --type-add 'aorg:*.org.age' \
+    -torg -taorg \
+    --pre ~/age-preprocessor.zsh --pre-glob '*.age' -l TODO /home/user/org
+
+
+ +

+Finally, we have our completed function: +

+
+
(defun set-org-agenda-files-ripgrep ()
+    (setq org-agenda-files (split-string (shell-command-to-string "rg --type-add \'aorg:*.org.age\' -torg -taorg --pre ~/age-preprocessor.zsh --pre-glob \'*.age\' -l TODO /home/user/org "))))
+
+
+ +

+Hope this helps! +

+
+
+]]>
+
+ + + Reflections on a year of Zettelkasten: Tooling + https://judah.freedomland.xyz//posts/reflections-zettelkasten-tooling.html + author@mail.com (Blog Author) + https://judah.freedomland.xyz//posts/reflections-zettelkasten-tooling.html Fri, 22 Dec 2023 00:00:00 -0500 @@ -42,7 +217,7 @@ It has grown to over 723 notes in less than two full years.

-nil +image

@@ -61,8 +236,14 @@ Before I get to that, I'll cover the pieces of the system, what's changed, and w

Text editing

-
+
+

+Text editing is at the heart of the zettelkasten. +A proper text editor will support links, backlinks, note search, and tagging. +It acts as the gateway into your notes, the control panel for your interaction and editing. +

+

Vimwiki

@@ -191,17 +372,16 @@ The default org-mode todo manager is fine, but with the addition of org-roam is the final piece of the puzzle, integrating the best of ID-based linking and backlink features into emacs.

-
-
-

TODO Write ten zettels

+
+

TODO Write ten zettels

-
-

TODO Rewrite d12frosted's absurd code into a simple ripgrep script

+
+

TODO Rewrite d12frosted's absurd code into a simple ripgrep script

-
-

DONE Finish up this post

-
+
+

DONE Finish up this post

+

Org-mode provides far too many features to cover here, but suffice it to say I am very happy with this setup. I have complete freedom to do anything I need to do, all in plain-text, all with an easily-hackable and infinitely customizeable interface. @@ -224,7 +404,7 @@ At the least, don't waste as much time as I did trying to find the perfect setup

- +
@@ -298,7 +478,7 @@ If any project purports to be from me, and is not signed by this key, the

Key:

-
+
 
 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII0YkBVeeBhoCm/+6mCteO7Ikv528ZDmg/tYtWc6O1qP
 
@@ -309,7 +489,7 @@ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII0YkBVeeBhoCm/+6mCteO7Ikv528ZDmg/tYtWc6O1qP
 

Fingerprint:

-
+
 
 SHA256:9Dq4ppxhfAjbX+7HLXEt+ROMiIojI6kqQgUyFUJb9lI
 
@@ -364,8 +544,8 @@ You can check that the latest commits are signed with my key.
       author@mail.com (Blog Author)
       https://judah.freedomland.xyz//posts/qubesos-signing-key.html
       
-      
-
+ +

Double check your keys!

@@ -393,7 +573,7 @@ Qubes release keys and developer keys are all signed with the QMSK. Please see the Qubes website for more information.

-
+
 
 427F 11FD 0FAA 4B08 0123
 F0IC DDFA 1A3E 3687 9494
diff --git a/index.html b/index.html
index 18514e9..3d0fdfc 100644
--- a/index.html
+++ b/index.html
@@ -43,7 +43,16 @@
   
  • - + + + Dec 27, 2023 — + + In Pursuit of an Efficient Org-Agenda + +
  • + +
  • + Dec 22, 2023 — diff --git a/posts/efficient-org-agenda.html b/posts/efficient-org-agenda.html new file mode 100644 index 0000000..9330032 --- /dev/null +++ b/posts/efficient-org-agenda.html @@ -0,0 +1,238 @@ + + + + + + + Open Thoughts + + + + + + + + + + + + + + + + + + + + +
    +

    + + Open Thoughts + +

    + jump to main content + +
    + + + +
    + +
    +

    + In Pursuit of an Efficient Org-Agenda +

    + +
    +
    +

    Table of Contents

    + +
    +

    +After beginning my Emacs and Org-Mode adventures I quickly realized the insufficiency of the standard agenda. +It is wonderful at producing a list, but I am quickly approaching over 1000 notes. +The agenda tooling is incapable of searching this many files efficiently, and it took over thirty seconds to generate an agenda. +

    + +

    +This was intolerable. I had two options: +

    +
      +
    1. Place all my TODO items into a single file.
    2. +
    3. Narrow the number of files the agenda mechanism needs to search
    4. +
    + +

    +I find the first option undesireable for reasons I mentioned in my post about zettelkasten tools. +I like to have my todo items mixed with the context where they were born. +A student of the Getting Things Done methodology might ask, "Doesn't this violate the central todo-list principle?" +Yes, it does. +Org-agenda allows me to have my cake and eat it too. +I can create a centralized todo-list out of all my todo items, and then immediately jump into the context of my next task. +

    + +

    +It took several iterations of configuration to reach a seamless workflow. +If you'd like to jump straight to the final setup, here's the link. +

    + +
    +

    1. First Iteration

    +
    +

    +The first piece of tooling I used came from this post and this Gist. +Essentially it creates a function vulpea-project-files that can easily query for a tag, and then sets the org-agenda files to all the files containing this tag. +

    + +

    +Coupled with a helper-function that adds the tag hastodos to any file containing a TODO entry, it functioned well. +

    +
    +
    (defun vulpea-project-files ()
    +  "Return a list of note files containing 'hastodos' tag." ;
    +  (seq-uniq
    +   (seq-map
    +    #'car
    +    (org-roam-db-query
    +     [:select [nodes:file]
    +      :from tags
    +      :left-join nodes
    +      :on (= tags:node-id nodes:id)
    +      :where (like tag (quote "%\"hastodos\"%"))]))))
    +(setq org-agenda-files (vulpea-project-files))
    +
    +
    + +

    +This solution is great because it is pure elisp. +Anywhere you're running Emacs it should function just fine. +It also works well with one of my needs: transparent file encryption. +Emacs has extensions for both gpg and age encryption that allow files to be transparently encrypted and decrypted. +This solution can make use of that where a standard grep could not. +

    +
    +
    + +
    +

    2. Second Iteration

    +
    +

    +Eventually, I grew tired of seeing the entire solution in my config file. +All told, it is about 170 lines. +This is a lot for a small utility! +

    + +

    +I decided to try using ripgrep to fix this: +

    +
    +
    (defun set-org-agenda-files-ripgrep ()
    +    (setq org-agenda-files (split-string (shell-command-to-string "rg -torg -l TODO /home/user/org"))))
    +
    +
    +

    +This worked nicely. +It takes just a few lines, runs just as fast–probably faster–than pure elisp, and is much easier to read and understand. +

    + +

    +The only difficulty is encryption. +ripgrep does not operate on open emacs buffers, instead it operates on what is saved to disk. +Naturally, this means that it only sees the encrypted files. +

    +
    +
    + +
    +

    3. Final

    +
    +

    +The solution to file encryption is ripgrep preprocessing. +I owe this solution to this reddit post. +

    + +

    +Ripgrep can run a command (or shell script!) to files before processing. +While the original poster was using gpg to encrypt files, just a few modifications allowed me to use age. +

    + +
    +
    #!/usr/bin/env zsh
    +case "$1" in
    +*.age)
    +    # The -s flag ensures that the file is non-empty.
    +    if [ -s "$1" ]; then
    +        exec /usr/bin/age --decrypt -i ~/.age/personal $1
    +    else
    +        exec cat
    +    fi
    +    ;;
    +*)
    +    ;;
    +esac
    +
    +
    +

    +This script operates on all .age files, decrypting them to stdout. +When using a preprocessor, ripgrep will simply search the output of the command. +

    + +

    +I often have a mix of files in my notes directory, so I use filetypes to restrict ripgrep. +This means I have to add a new filetype to allow .age files through the filter. +

    +
    +
    rg --type-add 'aorg:*.org.age' \
    +    -torg -taorg \
    +    --pre ~/age-preprocessor.zsh --pre-glob '*.age' -l TODO /home/user/org
    +
    +
    + +

    +Finally, we have our completed function: +

    +
    +
    (defun set-org-agenda-files-ripgrep ()
    +    (setq org-agenda-files (split-string (shell-command-to-string "rg --type-add \'aorg:*.org.age\' -torg -taorg --pre ~/age-preprocessor.zsh --pre-glob \'*.age\' -l TODO /home/user/org "))))
    +
    +
    + +

    +Hope this helps! +

    +
    +
    + +
    +
    + +
    + + + + + + + + diff --git a/posts/my-ssh-key.html b/posts/my-ssh-key.html index 161c98c..ffe2f0b 100644 --- a/posts/my-ssh-key.html +++ b/posts/my-ssh-key.html @@ -63,7 +63,7 @@ If any project purports to be from me, and is not signed by this key, the

    Key:

    -
    +
     
     ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII0YkBVeeBhoCm/+6mCteO7Ikv528ZDmg/tYtWc6O1qP
     
    @@ -74,7 +74,7 @@ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII0YkBVeeBhoCm/+6mCteO7Ikv528ZDmg/tYtWc6O1qP
     

    Fingerprint:

    -
    +
     
     SHA256:9Dq4ppxhfAjbX+7HLXEt+ROMiIojI6kqQgUyFUJb9lI
     
    diff --git a/posts/qubesos-signing-key.html b/posts/qubesos-signing-key.html
    index e646c7e..8da1e77 100644
    --- a/posts/qubesos-signing-key.html
    +++ b/posts/qubesos-signing-key.html
    @@ -52,8 +52,8 @@
           
         
         
    -
    -
    +
    +

    Double check your keys!

    @@ -81,7 +81,7 @@ Qubes release keys and developer keys are all signed with the QMSK. Please see the Qubes website for more information.

    -
    +
     
     427F 11FD 0FAA 4B08 0123
     F0IC DDFA 1A3E 3687 9494
    diff --git a/posts/reflections-on-a-year-of-zettelkasten-tooling.html b/posts/reflections-zettelkasten-tooling.html
    similarity index 93%
    rename from posts/reflections-on-a-year-of-zettelkasten-tooling.html
    rename to posts/reflections-zettelkasten-tooling.html
    index 9073a9f..e04ff2a 100644
    --- a/posts/reflections-on-a-year-of-zettelkasten-tooling.html
    +++ b/posts/reflections-zettelkasten-tooling.html
    @@ -13,7 +13,7 @@
         
         
       
    -  
    +  
       
       
       
    @@ -60,7 +60,7 @@ It has grown to over 723 notes in less than two full years.
     

    -nil +image

    @@ -79,8 +79,14 @@ Before I get to that, I'll cover the pieces of the system, what's changed, and w

    Text editing

    -
    +
    +

    +Text editing is at the heart of the zettelkasten. +A proper text editor will support links, backlinks, note search, and tagging. +It acts as the gateway into your notes, the control panel for your interaction and editing. +

    +

    Vimwiki

    @@ -209,17 +215,16 @@ The default org-mode todo manager is fine, but with the addition of org-roam is the final piece of the puzzle, integrating the best of ID-based linking and backlink features into emacs.

    -
    -
    -

    TODO Write ten zettels

    +
    +

    TODO Write ten zettels

    -
    -

    TODO Rewrite d12frosted's absurd code into a simple ripgrep script

    +
    +

    TODO Rewrite d12frosted's absurd code into a simple ripgrep script

    -
    -

    DONE Finish up this post

    -
    +
    +

    DONE Finish up this post

    +

    Org-mode provides far too many features to cover here, but suffice it to say I am very happy with this setup. I have complete freedom to do anything I need to do, all in plain-text, all with an easily-hackable and infinitely customizeable interface. @@ -242,7 +247,7 @@ At the least, don't waste as much time as I did trying to find the perfect setup

    - +
    diff --git a/static/style.css b/static/style.css index c0eeeeb..f348ad7 100644 --- a/static/style.css +++ b/static/style.css @@ -6,7 +6,7 @@ --cl-background: #212121; --cl-gray: #828282; --cl-note: #F2FFDD; - --cl-link: #0074D9; + --cl-link: #4074D9; --cl-meta: #F7A32E;