feat[posts] Added org-agenda post.
I added a post on org-agenda I renamed zettelkasten-tooling post's slug. I made the link color slightly brighter.
This commit is contained in:
parent
0e8c78466d
commit
ef43fe3f0a
222
feed.xml
222
feed.xml
@ -17,8 +17,8 @@
|
||||
<link>https://judah.freedomland.xyz//</link>
|
||||
<description><![CDATA[]]></description>
|
||||
<language>en</language>
|
||||
<pubDate>Fri, 22 Dec 2023 00:00:00 -0500</pubDate>
|
||||
<lastBuildDate>Sun, 24 Dec 2023 02:30:24 -0500</lastBuildDate>
|
||||
<pubDate>Wed, 27 Dec 2023 00:00:00 -0500</pubDate>
|
||||
<lastBuildDate>Wed, 27 Dec 2023 22:58:08 -0500</lastBuildDate>
|
||||
<generator>weblorg 0.1.0 (https://emacs.love/weblorg)</generator>
|
||||
<webMaster>Judah Sotomayor</webMaster>
|
||||
<image>
|
||||
@ -29,10 +29,185 @@
|
||||
|
||||
|
||||
<item>
|
||||
<title>Reflections on a year of Zettelkasten: Tooling</title>
|
||||
<link>https://judah.freedomland.xyz//posts/reflections-on-a-year-of-zettelkasten-tooling.html</link>
|
||||
<title>In Pursuit of an Efficient Org-Agenda</title>
|
||||
<link>https://judah.freedomland.xyz//posts/efficient-org-agenda.html</link>
|
||||
<author>author@mail.com (Blog Author)</author>
|
||||
<guid isPermaLink="false">https://judah.freedomland.xyz//posts/reflections-on-a-year-of-zettelkasten-tooling.html</guid>
|
||||
<guid isPermaLink="false">https://judah.freedomland.xyz//posts/efficient-org-agenda.html</guid>
|
||||
|
||||
<pubDate>Wed, 27 Dec 2023 00:00:00 -0500</pubDate>
|
||||
|
||||
<description><![CDATA[<div id="table-of-contents" role="doc-toc">
|
||||
<h2>Table of Contents</h2>
|
||||
<div id="text-table-of-contents" role="doc-toc">
|
||||
<ul>
|
||||
<li><a href="#first-iteration">1. First Iteration</a></li>
|
||||
<li><a href="#second-iteration">2. Second Iteration</a></li>
|
||||
<li><a href="#finally">3. Final</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This was intolerable. I had two options:
|
||||
</p>
|
||||
<ol class="org-ol">
|
||||
<li>Place all my TODO items into a single file.</li>
|
||||
<li>Narrow the number of files the agenda mechanism needs to search</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
I find the first option undesireable for reasons I mentioned in my <a href="https://judah.freedomland.xyz//posts/reflections-zettelkasten-tooling.html">post</a> about zettelkasten tools.
|
||||
I like to have my todo items mixed with the context where they were born.
|
||||
A student of the <i>Getting Things Done</i> 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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It took several iterations of configuration to reach a seamless workflow.
|
||||
If you'd like to jump straight to the final setup, <a href="#finally">here's the link.</a>
|
||||
</p>
|
||||
|
||||
<div id="outline-container-first-iteration" class="outline-2">
|
||||
<h2 id="first-iteration"><span class="section-number-2">1.</span> First Iteration</h2>
|
||||
<div class="outline-text-2" id="text-1">
|
||||
<p>
|
||||
The first piece of tooling I used came from <a href="https://d12frosted.io/posts/2021-01-16-task-management-with-roam-vol5.html">this post</a> and <a href="https://gist.github.com/d12frosted/a60e8ccb9aceba031af243dff0d19b2e">this Gist</a>.
|
||||
Essentially it creates a function <code>vulpea-project-files</code> that can easily query for a tag, and then sets the org-agenda files to all the files containing this tag.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Coupled with a helper-function that adds the tag <code>hastodos</code> to any file containing a TODO entry, it functioned well.
|
||||
</p>
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-emacs-lisp">(<span class="org-keyword">defun</span> <span class="org-function-name">vulpea-project-files</span> ()
|
||||
<span class="org-doc">"Return a list of note files containing '</span><span class="org-doc"><span class="org-constant">hastodos</span></span><span class="org-doc">' tag."</span> <span class="org-comment-delimiter">;</span>
|
||||
(seq-uniq
|
||||
(seq-map
|
||||
#'car
|
||||
(org-roam-db-query
|
||||
[<span class="org-builtin">:select</span> [nodes:file]
|
||||
<span class="org-builtin">:from</span> tags
|
||||
<span class="org-builtin">:left-join</span> nodes
|
||||
<span class="org-builtin">:on</span> (= tags:node-id nodes:id)
|
||||
<span class="org-builtin">:where</span> (like tag (<span class="org-keyword">quote</span> <span class="org-string">"%\"hastodos\"%"</span>))]))))
|
||||
(<span class="org-keyword">setq</span> org-agenda-files (vulpea-project-files))
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
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 <code>gpg</code> and <code>age</code> encryption that allow files to be transparently encrypted and decrypted.
|
||||
This solution can make use of that where a standard <code>grep</code> could not.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="outline-container-second-iteration" class="outline-2">
|
||||
<h2 id="second-iteration"><span class="section-number-2">2.</span> Second Iteration</h2>
|
||||
<div class="outline-text-2" id="text-2">
|
||||
<p>
|
||||
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!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I decided to try using <code>ripgrep</code> to fix this:
|
||||
</p>
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-emacs-lisp">(<span class="org-keyword">defun</span> <span class="org-function-name">set-org-agenda-files-ripgrep</span> ()
|
||||
(<span class="org-keyword">setq</span> org-agenda-files (split-string (shell-command-to-string <span class="org-string">"rg -torg -l TODO /home/user/org"</span>))))
|
||||
</pre>
|
||||
</div>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The only difficulty is encryption.
|
||||
<code>ripgrep</code> 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.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="outline-container-finally" class="outline-2">
|
||||
<h2 id="finally"><span class="section-number-2">3.</span> Final</h2>
|
||||
<div class="outline-text-2" id="text-finally">
|
||||
<p>
|
||||
The solution to file encryption is ripgrep preprocessing.
|
||||
I owe this solution to <a href="https://www.reddit.com/r/emacs/comments/q4e2az/full_text_search_of_gpg_encrypted_files/">this reddit post</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Ripgrep can run a command (or shell script!) to files before processing.
|
||||
While the original poster was using <code>gpg</code> to encrypt files, just a few modifications allowed me to use <code>age</code>.
|
||||
</p>
|
||||
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-zsh">#!/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
|
||||
</pre>
|
||||
</div>
|
||||
<p>
|
||||
This script operates on all <code>.age</code> files, decrypting them to stdout.
|
||||
When using a preprocessor, ripgrep will simply search the output of the command.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
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 <code>.age</code> files through the filter.
|
||||
</p>
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-sh">rg --type-add <span class="org-string">'aorg:*.org.age'</span> <span class="org-sh-escaped-newline">\</span>
|
||||
-torg -taorg <span class="org-sh-escaped-newline">\</span>
|
||||
--pre ~/age-preprocessor.zsh --pre-glob <span class="org-string">'*.age'</span> -l TODO /home/user/org
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Finally, we have our completed function:
|
||||
</p>
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-emacs-lisp">(<span class="org-keyword">defun</span> <span class="org-function-name">set-org-agenda-files-ripgrep</span> ()
|
||||
(<span class="org-keyword">setq</span> org-agenda-files (split-string (shell-command-to-string <span class="org-string">"rg --type-add </span><span class="org-string"><span class="org-warning">\</span></span><span class="org-string">'aorg:*.org.age</span><span class="org-string"><span class="org-warning">\</span></span><span class="org-string">' -torg -taorg --pre ~/age-preprocessor.zsh --pre-glob </span><span class="org-string"><span class="org-warning">\</span></span><span class="org-string">'*.age</span><span class="org-string"><span class="org-warning">\</span></span><span class="org-string">' -l TODO /home/user/org "</span>))))
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Hope this helps!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
]]></description>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<title>Reflections on a year of Zettelkasten: Tooling</title>
|
||||
<link>https://judah.freedomland.xyz//posts/reflections-zettelkasten-tooling.html</link>
|
||||
<author>author@mail.com (Blog Author)</author>
|
||||
<guid isPermaLink="false">https://judah.freedomland.xyz//posts/reflections-zettelkasten-tooling.html</guid>
|
||||
|
||||
<pubDate>Fri, 22 Dec 2023 00:00:00 -0500</pubDate>
|
||||
|
||||
@ -42,7 +217,7 @@ It has grown to over 723 notes in less than two full years.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="https://judah.freedomland.xyz//static/img/filetypes.svg" alt="nil" />
|
||||
<img src="https://judah.freedomland.xyz//static/img/filetypes.svg" alt="image" />
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -61,8 +236,14 @@ Before I get to that, I'll cover the pieces of the system, what's changed, and w
|
||||
|
||||
<div id="outline-container-text-editing" class="outline-2">
|
||||
<h2 id="text-editing">Text editing</h2>
|
||||
<div class="outline-text-2" id="text-text-editing">
|
||||
<div class="outline-text-2">
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="outline-container-vimwiki" class="outline-3">
|
||||
<h3 id="vimwiki">Vimwiki</h3>
|
||||
<div class="outline-text-3">
|
||||
@ -191,17 +372,16 @@ The default org-mode todo manager is fine, but with the addition of <a href="htt
|
||||
<a href="https://www.orgroam.com/">org-roam</a> is the final piece of the puzzle, integrating the best of ID-based linking and backlink features into emacs.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="outline-container-write-ten-zettels" class="outline-3">
|
||||
<h3 id="write-ten-zettels"><span class="todo TODO">TODO</span> Write ten zettels</h3>
|
||||
<div id="outline-container-write-ten-zettels" class="outline-4">
|
||||
<h4 id="write-ten-zettels"><span class="todo TODO">TODO</span> Write ten zettels</h4>
|
||||
</div>
|
||||
<div id="outline-container-rewrite-d12frosted-s-absurd-code-into-a-simple-ripgrep-script" class="outline-3">
|
||||
<h3 id="rewrite-d12frosted-s-absurd-code-into-a-simple-ripgrep-script"><span class="todo TODO">TODO</span> Rewrite d12frosted's absurd code into a simple ripgrep script</h3>
|
||||
<div id="outline-container-rewrite-d12frosted-s-absurd-code-into-a-simple-ripgrep-script" class="outline-4">
|
||||
<h4 id="rewrite-d12frosted-s-absurd-code-into-a-simple-ripgrep-script"><span class="todo TODO">TODO</span> Rewrite d12frosted's absurd code into a simple ripgrep script</h4>
|
||||
</div>
|
||||
<div id="outline-container-finish-up-this-post" class="outline-3">
|
||||
<h3 id="finish-up-this-post"><span class="done DONE">DONE</span> Finish up this post</h3>
|
||||
<div class="outline-text-3">
|
||||
<div id="outline-container-finish-up-this-post" class="outline-4">
|
||||
<h4 id="finish-up-this-post"><span class="done DONE">DONE</span> Finish up this post</h4>
|
||||
<div class="outline-text-4">
|
||||
<p>
|
||||
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
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="outline-container-misc-software" class="outline-2">
|
||||
@ -298,7 +478,7 @@ If any project purports to be from me, and is <i>not</i> signed by this key, the
|
||||
<div id="outline-container-key" class="outline-2">
|
||||
<h2 id="key">Key:</h2>
|
||||
<div class="outline-text-2">
|
||||
<pre class="example" id="org010940c">
|
||||
<pre class="example" id="org00f7ab6">
|
||||
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII0YkBVeeBhoCm/+6mCteO7Ikv528ZDmg/tYtWc6O1qP
|
||||
|
||||
@ -309,7 +489,7 @@ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII0YkBVeeBhoCm/+6mCteO7Ikv528ZDmg/tYtWc6O1qP
|
||||
<div id="outline-container-fingerprint" class="outline-2">
|
||||
<h2 id="fingerprint">Fingerprint:</h2>
|
||||
<div class="outline-text-2">
|
||||
<pre class="example" id="org6bc0a4e">
|
||||
<pre class="example" id="org8d4e235">
|
||||
|
||||
SHA256:9Dq4ppxhfAjbX+7HLXEt+ROMiIojI6kqQgUyFUJb9lI
|
||||
|
||||
@ -364,8 +544,8 @@ You can check that the latest commits are signed with my key.
|
||||
<author>author@mail.com (Blog Author)</author>
|
||||
<guid isPermaLink="false">https://judah.freedomland.xyz//posts/qubesos-signing-key.html</guid>
|
||||
|
||||
<description><![CDATA[<div class="alert" id="org47978ac">
|
||||
<div class="alert-heading" id="orgad55953">
|
||||
<description><![CDATA[<div class="alert" id="org1069968">
|
||||
<div class="alert-heading" id="org7baa11e">
|
||||
<p>
|
||||
Double check your keys!
|
||||
</p>
|
||||
@ -393,7 +573,7 @@ Qubes release keys and developer keys are all signed with the QMSK.
|
||||
Please see <a href="https://www.qubes-os.org/security/verifying-signatures/#how-to-import-and-authenticate-the-qubes-master-signing-key">the Qubes website</a> for more information.
|
||||
</p>
|
||||
|
||||
<pre class="example" id="org3b4e4bf">
|
||||
<pre class="example" id="org5a5c928">
|
||||
|
||||
427F 11FD 0FAA 4B08 0123
|
||||
F0IC DDFA 1A3E 3687 9494
|
||||
|
11
index.html
11
index.html
@ -43,7 +43,16 @@
|
||||
<ul class="posts">
|
||||
|
||||
<li class="post-title">
|
||||
<a href="https://judah.freedomland.xyz//posts/reflections-on-a-year-of-zettelkasten-tooling.html">
|
||||
<a href="https://judah.freedomland.xyz//posts/efficient-org-agenda.html">
|
||||
|
||||
Dec 27, 2023 —
|
||||
|
||||
In Pursuit of an Efficient Org-Agenda
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="post-title">
|
||||
<a href="https://judah.freedomland.xyz//posts/reflections-zettelkasten-tooling.html">
|
||||
|
||||
Dec 22, 2023 —
|
||||
|
||||
|
238
posts/efficient-org-agenda.html
Normal file
238
posts/efficient-org-agenda.html
Normal file
@ -0,0 +1,238 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>
|
||||
Open Thoughts
|
||||
|
||||
</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="author" content="Judah Sotomayor" />
|
||||
|
||||
|
||||
|
||||
<meta property="og:title" content="In Pursuit of an Efficient Org-Agenda">
|
||||
<meta property="og:url" content="https://judah.freedomland.xyz//posts/efficient-org-agenda.html">
|
||||
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
|
||||
<link rel="stylesheet" href="https://judah.freedomland.xyz//static/style.css" type="text/css" />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Lora&family=Space+Mono&display=swap" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<header>
|
||||
<h1>
|
||||
<a href="https://judah.freedomland.xyz//">
|
||||
Open Thoughts
|
||||
</a>
|
||||
</h1>
|
||||
<a href="#main" class="visually-hidden">jump to main content</a>
|
||||
<nav>
|
||||
<ul class="menu">
|
||||
<li><a href="https://judah.freedomland.xyz//about">about</a></li>
|
||||
<li><a href="https://judah.freedomland.xyz//">blog</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
<main id="main">
|
||||
|
||||
<article class="post">
|
||||
<h1 class="post__title">
|
||||
In Pursuit of an Efficient Org-Agenda
|
||||
</h1>
|
||||
<section class="post__meta">
|
||||
|
||||
Dec 27, 2023
|
||||
|
||||
</section>
|
||||
<section>
|
||||
<div id="table-of-contents" role="doc-toc">
|
||||
<h2>Table of Contents</h2>
|
||||
<div id="text-table-of-contents" role="doc-toc">
|
||||
<ul>
|
||||
<li><a href="#first-iteration">1. First Iteration</a></li>
|
||||
<li><a href="#second-iteration">2. Second Iteration</a></li>
|
||||
<li><a href="#finally">3. Final</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This was intolerable. I had two options:
|
||||
</p>
|
||||
<ol class="org-ol">
|
||||
<li>Place all my TODO items into a single file.</li>
|
||||
<li>Narrow the number of files the agenda mechanism needs to search</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
I find the first option undesireable for reasons I mentioned in my <a href="https://judah.freedomland.xyz//posts/reflections-zettelkasten-tooling.html">post</a> about zettelkasten tools.
|
||||
I like to have my todo items mixed with the context where they were born.
|
||||
A student of the <i>Getting Things Done</i> 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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It took several iterations of configuration to reach a seamless workflow.
|
||||
If you'd like to jump straight to the final setup, <a href="#finally">here's the link.</a>
|
||||
</p>
|
||||
|
||||
<div id="outline-container-first-iteration" class="outline-2">
|
||||
<h2 id="first-iteration"><span class="section-number-2">1.</span> First Iteration</h2>
|
||||
<div class="outline-text-2" id="text-1">
|
||||
<p>
|
||||
The first piece of tooling I used came from <a href="https://d12frosted.io/posts/2021-01-16-task-management-with-roam-vol5.html">this post</a> and <a href="https://gist.github.com/d12frosted/a60e8ccb9aceba031af243dff0d19b2e">this Gist</a>.
|
||||
Essentially it creates a function <code>vulpea-project-files</code> that can easily query for a tag, and then sets the org-agenda files to all the files containing this tag.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Coupled with a helper-function that adds the tag <code>hastodos</code> to any file containing a TODO entry, it functioned well.
|
||||
</p>
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-emacs-lisp">(<span class="org-keyword">defun</span> <span class="org-function-name">vulpea-project-files</span> ()
|
||||
<span class="org-doc">"Return a list of note files containing '</span><span class="org-doc"><span class="org-constant">hastodos</span></span><span class="org-doc">' tag."</span> <span class="org-comment-delimiter">;</span>
|
||||
(seq-uniq
|
||||
(seq-map
|
||||
#'car
|
||||
(org-roam-db-query
|
||||
[<span class="org-builtin">:select</span> [nodes:file]
|
||||
<span class="org-builtin">:from</span> tags
|
||||
<span class="org-builtin">:left-join</span> nodes
|
||||
<span class="org-builtin">:on</span> (= tags:node-id nodes:id)
|
||||
<span class="org-builtin">:where</span> (like tag (<span class="org-keyword">quote</span> <span class="org-string">"%\"hastodos\"%"</span>))]))))
|
||||
(<span class="org-keyword">setq</span> org-agenda-files (vulpea-project-files))
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
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 <code>gpg</code> and <code>age</code> encryption that allow files to be transparently encrypted and decrypted.
|
||||
This solution can make use of that where a standard <code>grep</code> could not.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="outline-container-second-iteration" class="outline-2">
|
||||
<h2 id="second-iteration"><span class="section-number-2">2.</span> Second Iteration</h2>
|
||||
<div class="outline-text-2" id="text-2">
|
||||
<p>
|
||||
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!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I decided to try using <code>ripgrep</code> to fix this:
|
||||
</p>
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-emacs-lisp">(<span class="org-keyword">defun</span> <span class="org-function-name">set-org-agenda-files-ripgrep</span> ()
|
||||
(<span class="org-keyword">setq</span> org-agenda-files (split-string (shell-command-to-string <span class="org-string">"rg -torg -l TODO /home/user/org"</span>))))
|
||||
</pre>
|
||||
</div>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The only difficulty is encryption.
|
||||
<code>ripgrep</code> 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.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="outline-container-finally" class="outline-2">
|
||||
<h2 id="finally"><span class="section-number-2">3.</span> Final</h2>
|
||||
<div class="outline-text-2" id="text-finally">
|
||||
<p>
|
||||
The solution to file encryption is ripgrep preprocessing.
|
||||
I owe this solution to <a href="https://www.reddit.com/r/emacs/comments/q4e2az/full_text_search_of_gpg_encrypted_files/">this reddit post</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Ripgrep can run a command (or shell script!) to files before processing.
|
||||
While the original poster was using <code>gpg</code> to encrypt files, just a few modifications allowed me to use <code>age</code>.
|
||||
</p>
|
||||
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-zsh">#!/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
|
||||
</pre>
|
||||
</div>
|
||||
<p>
|
||||
This script operates on all <code>.age</code> files, decrypting them to stdout.
|
||||
When using a preprocessor, ripgrep will simply search the output of the command.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
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 <code>.age</code> files through the filter.
|
||||
</p>
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-sh">rg --type-add <span class="org-string">'aorg:*.org.age'</span> <span class="org-sh-escaped-newline">\</span>
|
||||
-torg -taorg <span class="org-sh-escaped-newline">\</span>
|
||||
--pre ~/age-preprocessor.zsh --pre-glob <span class="org-string">'*.age'</span> -l TODO /home/user/org
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Finally, we have our completed function:
|
||||
</p>
|
||||
<div class="org-src-container">
|
||||
<pre class="src src-emacs-lisp">(<span class="org-keyword">defun</span> <span class="org-function-name">set-org-agenda-files-ripgrep</span> ()
|
||||
(<span class="org-keyword">setq</span> org-agenda-files (split-string (shell-command-to-string <span class="org-string">"rg --type-add </span><span class="org-string"><span class="org-warning">\</span></span><span class="org-string">'aorg:*.org.age</span><span class="org-string"><span class="org-warning">\</span></span><span class="org-string">' -torg -taorg --pre ~/age-preprocessor.zsh --pre-glob </span><span class="org-string"><span class="org-warning">\</span></span><span class="org-string">'*.age</span><span class="org-string"><span class="org-warning">\</span></span><span class="org-string">' -l TODO /home/user/org "</span>))))
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Hope this helps!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</article>
|
||||
|
||||
</main>
|
||||
|
||||
|
||||
|
||||
<footer>
|
||||
Made with ♥ and
|
||||
<a href="https://emacs.love/weblorg" target="_blank">
|
||||
weblorg
|
||||
</a>
|
||||
</footer>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@ -63,7 +63,7 @@ If any project purports to be from me, and is <i>not</i> signed by this key, the
|
||||
<div id="outline-container-key" class="outline-2">
|
||||
<h2 id="key">Key:</h2>
|
||||
<div class="outline-text-2">
|
||||
<pre class="example" id="org8cf2466">
|
||||
<pre class="example" id="org4a19c68">
|
||||
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII0YkBVeeBhoCm/+6mCteO7Ikv528ZDmg/tYtWc6O1qP
|
||||
|
||||
@ -74,7 +74,7 @@ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII0YkBVeeBhoCm/+6mCteO7Ikv528ZDmg/tYtWc6O1qP
|
||||
<div id="outline-container-fingerprint" class="outline-2">
|
||||
<h2 id="fingerprint">Fingerprint:</h2>
|
||||
<div class="outline-text-2">
|
||||
<pre class="example" id="org86d4133">
|
||||
<pre class="example" id="org1dfa8c6">
|
||||
|
||||
SHA256:9Dq4ppxhfAjbX+7HLXEt+ROMiIojI6kqQgUyFUJb9lI
|
||||
|
||||
|
@ -52,8 +52,8 @@
|
||||
|
||||
</section>
|
||||
<section>
|
||||
<div class="alert" id="org5b376bd">
|
||||
<div class="alert-heading" id="org430cc95">
|
||||
<div class="alert" id="org6558c15">
|
||||
<div class="alert-heading" id="org3dbd5c3">
|
||||
<p>
|
||||
Double check your keys!
|
||||
</p>
|
||||
@ -81,7 +81,7 @@ Qubes release keys and developer keys are all signed with the QMSK.
|
||||
Please see <a href="https://www.qubes-os.org/security/verifying-signatures/#how-to-import-and-authenticate-the-qubes-master-signing-key">the Qubes website</a> for more information.
|
||||
</p>
|
||||
|
||||
<pre class="example" id="org42a8cf9">
|
||||
<pre class="example" id="org0f0642a">
|
||||
|
||||
427F 11FD 0FAA 4B08 0123
|
||||
F0IC DDFA 1A3E 3687 9494
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
<meta property="og:title" content="Reflections on a year of Zettelkasten: Tooling">
|
||||
<meta property="og:url" content="https://judah.freedomland.xyz//posts/reflections-on-a-year-of-zettelkasten-tooling.html">
|
||||
<meta property="og:url" content="https://judah.freedomland.xyz//posts/reflections-zettelkasten-tooling.html">
|
||||
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
@ -60,7 +60,7 @@ It has grown to over 723 notes in less than two full years.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="https://judah.freedomland.xyz//static/img/filetypes.svg" alt="nil" />
|
||||
<img src="https://judah.freedomland.xyz//static/img/filetypes.svg" alt="image" />
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -79,8 +79,14 @@ Before I get to that, I'll cover the pieces of the system, what's changed, and w
|
||||
|
||||
<div id="outline-container-text-editing" class="outline-2">
|
||||
<h2 id="text-editing">Text editing</h2>
|
||||
<div class="outline-text-2" id="text-text-editing">
|
||||
<div class="outline-text-2">
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="outline-container-vimwiki" class="outline-3">
|
||||
<h3 id="vimwiki">Vimwiki</h3>
|
||||
<div class="outline-text-3">
|
||||
@ -209,17 +215,16 @@ The default org-mode todo manager is fine, but with the addition of <a href="htt
|
||||
<a href="https://www.orgroam.com/">org-roam</a> is the final piece of the puzzle, integrating the best of ID-based linking and backlink features into emacs.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="outline-container-write-ten-zettels" class="outline-3">
|
||||
<h3 id="write-ten-zettels"><span class="todo TODO">TODO</span> Write ten zettels</h3>
|
||||
<div id="outline-container-write-ten-zettels" class="outline-4">
|
||||
<h4 id="write-ten-zettels"><span class="todo TODO">TODO</span> Write ten zettels</h4>
|
||||
</div>
|
||||
<div id="outline-container-rewrite-d12frosted-s-absurd-code-into-a-simple-ripgrep-script" class="outline-3">
|
||||
<h3 id="rewrite-d12frosted-s-absurd-code-into-a-simple-ripgrep-script"><span class="todo TODO">TODO</span> Rewrite d12frosted's absurd code into a simple ripgrep script</h3>
|
||||
<div id="outline-container-rewrite-d12frosted-s-absurd-code-into-a-simple-ripgrep-script" class="outline-4">
|
||||
<h4 id="rewrite-d12frosted-s-absurd-code-into-a-simple-ripgrep-script"><span class="todo TODO">TODO</span> Rewrite d12frosted's absurd code into a simple ripgrep script</h4>
|
||||
</div>
|
||||
<div id="outline-container-finish-up-this-post" class="outline-3">
|
||||
<h3 id="finish-up-this-post"><span class="done DONE">DONE</span> Finish up this post</h3>
|
||||
<div class="outline-text-3">
|
||||
<div id="outline-container-finish-up-this-post" class="outline-4">
|
||||
<h4 id="finish-up-this-post"><span class="done DONE">DONE</span> Finish up this post</h4>
|
||||
<div class="outline-text-4">
|
||||
<p>
|
||||
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
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="outline-container-misc-software" class="outline-2">
|
@ -6,7 +6,7 @@
|
||||
--cl-background: #212121;
|
||||
--cl-gray: #828282;
|
||||
--cl-note: #F2FFDD;
|
||||
--cl-link: #0074D9;
|
||||
--cl-link: #4074D9;
|
||||
|
||||
--cl-meta: #F7A32E;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user