From 17d5fdf03bb372db3a268d20498c1873753e519d Mon Sep 17 00:00:00 2001 From: J S Date: Wed, 27 Dec 2023 22:04:41 -0500 Subject: [PATCH] feat[agenda] Swapped vulpea for ripgrep I exchanged the bulky vulpea source code for ripgrep. It's faster, and much easier to understand. --- config.org | 260 +++++++++++------------------------------------------ 1 file changed, 52 insertions(+), 208 deletions(-) diff --git a/config.org b/config.org index bd3444c..0874d59 100644 --- a/config.org +++ b/config.org @@ -143,6 +143,34 @@ Because I sometimes use Fish or another shell, it's good to make sure bash is ru (age-file-enable)) #+end_src +*** Preprocessor +:PROPERTIES: +:CUSTOM_ID: ripgrep-pre +:END: +This preprocessor script allows me to use Ripgrep with Age to filter agenda files. +You can see the configuration for that in [[#agenda-efficient][this section]]. + + +#+begin_src zsh :tangle "/home/user/age-preprocessor.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 +#+end_src + + + + ** Org-mode security settings These mostly concern limiting evaluation of code-blocks without confirmation. The final two lines concern local variables, which may try to evaluate code. @@ -162,232 +190,48 @@ Emacs has better default values now, so it will ask to evaluate local variables. #+end_src * Org-mode for a great todo list ** Making the Agenda features more efficient +Using ripgrep we can automatically narrow org-agenda files. -#+begin_src emacs-lisp :tangle no -(dolist (file (org-roam-list-files)) -(message "processing %s" file) -(with-current-buffer (or (find-buffer-visiting file) - (find-file-noselect file)) -(vulpea-project-update-tag) -(save-buffer))) +*** Finding Files with Ripgrep +:PROPERTIES: +:CUSTOM_ID: agenda-efficient +:END: +This piece of code will allow us to capture all the agenda files using the preprocessor we wrote [[#ripgrep-pre][here]] +#+name: search-agenda-files +#+begin_src sh :exports code :tangle no +rg --type-add 'aorg:*.org.age' \ + -torg -taorg \ + --pre ~/age-preprocessor.zsh --pre-glob '*.age' -l TODO /home/user/org #+end_src -#+RESULTS: - - - -Only include files with the hastodos tag. -This section is contributed from [[https://gist.github.com/d12frosted/a60e8ccb9aceba031af243dff0d19b2e][d12frosted]] and use his vulpea.el package's functions. -I ripped out the essentials because I don't want all the other stuff in that package. - +Now, of course, this code is not useful as it is--after all, we can't tangle a ~.sh~ script into [[file:config.el]]. +*** Adding results to agenda files +The rubber hits the road here. +I'll call that shell command to set the agenda files correctly. #+begin_src emacs-lisp -(after! org-roam -(defun vulpea-project-p () -"Return non-nil if current buffer has any todo entry. -TODO entries marked as done are ignored, meaning the this -function returns nil if current buffer contains only completed -tasks." -(seq-find ; (3) -(lambda (type) -(eq type 'todo)) -(org-element-map ; (2) -(org-element-parse-buffer 'headline) ; (1) -'headline -(lambda (h) -(org-element-property :todo-type h))))) - -(defun vulpea-project-update-tag () -"Update PROJECT tag in the current buffer." -(when (and (not (active-minibuffer-window)) - (vulpea-buffer-p)) -(save-excursion -(goto-char (point-min)) -(let* ((tags (vulpea-buffer-tags-get)) - (original-tags tags)) - (if (vulpea-project-p) - (setq tags (cons "hastodos" tags)) - (setq tags (remove "hastodos" tags))) - - ;; cleanup duplicates - (setq tags (seq-uniq tags)) - - ;; update tags if changed - (when (or (seq-difference tags original-tags) - (seq-difference original-tags tags)) - (apply #'vulpea-buffer-tags-set tags)))))) - -(defun vulpea-buffer-p () -"Return non-nil if the currently visited buffer is a note." -(and buffer-file-name -(string-prefix-p -(expand-file-name (file-name-as-directory org-roam-directory)) -(file-name-directory buffer-file-name)))) - -(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\"%"))])))) - -(defun vulpea-agenda-files-update (&rest _) -"Update the value of `org-agenda-files'." -(setq org-agenda-files (vulpea-project-files))) - -(add-hook 'find-file-hook #'vulpea-project-update-tag) -(add-hook 'before-save-hook #'vulpea-project-update-tag) - -(advice-add 'org-agenda :before #'vulpea-agenda-files-update) -(advice-add 'org-todo-list :before #'vulpea-agenda-files-update) - -;; functions borrowed from `vulpea' library -;; https://github.com/d12frosted/vulpea/blob/6a735c34f1f64e1f70da77989e9ce8da7864e5ff/vulpea-buffer.el - -(defun vulpea-buffer-tags-get () -"Return filetags value in current buffer." -(vulpea-buffer-prop-get-list "filetags" "[ :]")) - -(defun vulpea-buffer-tags-set (&rest tags) -"Set TAGS in current buffer. -If filetags value is already set, replace it." -(if tags -(vulpea-buffer-prop-set -"filetags" (concat ":" (string-join tags ":") ":")) -(vulpea-buffer-prop-remove "filetags"))) - -(defun vulpea-buffer-tags-add (tag) -"Add a TAG to filetags in current buffer." -(let* ((tags (vulpea-buffer-tags-get)) - (tags (append tags (list tag)))) -(apply #'vulpea-buffer-tags-set tags))) - -(defun vulpea-buffer-tags-remove (tag) -"Remove a TAG from filetags in current buffer." -(let* ((tags (vulpea-buffer-tags-get)) - (tags (delete tag tags))) -(apply #'vulpea-buffer-tags-set tags))) - -(defun vulpea-buffer-prop-set (name value) -"Set a file property called NAME to VALUE in buffer file. -If the property is already set, replace its value." -(setq name (downcase name)) -(org-with-point-at 1 -(let ((case-fold-search t)) -(if (re-search-forward (concat "^#\\+" name ":\\(.*\\)") - (point-max) t) - (replace-match (concat "#+" name ": " value) 'fixedcase) -(while (and (not (eobp)) - (looking-at "^[#:]")) - (if (save-excursion (end-of-line) (eobp)) - (progn - (end-of-line) - (insert "\n")) - (forward-line) - (beginning-of-line))) -(insert "#+" name ": " value "\n"))))) - -(defun vulpea-buffer-prop-set-list (name values &optional separators) -"Set a file property called NAME to VALUES in current buffer. -VALUES are quoted and combined into single string using -`combine-and-quote-strings'. -If SEPARATORS is non-nil, it should be a regular expression -matching text that separates, but is not part of, the substrings. -If nil it defaults to `split-string-default-separators', normally -\"[ \f\t\n\r\v]+\", and OMIT-NULLS is forced to t. -If the property is already set, replace its value." -(vulpea-buffer-prop-set -name (combine-and-quote-strings values separators))) - -(defun vulpea-buffer-prop-get (name) -"Get a buffer property called NAME as a string." -(org-with-point-at 1 -(when (re-search-forward (concat "^#\\+" name ": \\(.*\\)") - (point-max) t) -(buffer-substring-no-properties -(match-beginning 1) -(match-end 1))))) - -(defun vulpea-buffer-prop-get-list (name &optional separators) -"Get a buffer property NAME as a list using SEPARATORS. -If SEPARATORS is non-nil, it should be a regular expression -matching text that separates, but is not part of, the substrings. -If nil it defaults to `split-string-default-separators', normally -\"[ \f\t\n\r\v]+\", and OMIT-NULLS is forced to t." -(let ((value (vulpea-buffer-prop-get name))) -(when (and value (not (string-empty-p value))) -(split-string-and-unquote value separators)))) - -(defun vulpea-buffer-prop-remove (name) -"Remove a buffer property called NAME." -(org-with-point-at 1 -(when (re-search-forward (concat "\\(^#\\+" name ":.*\n?\\)") - (point-max) t) -(replace-match "")))) - -(setq org-agenda-files (vulpea-project-files))) +(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 ")))) #+end_src +And then we want to call this before building the agenda: +#+begin_src emacs-lisp +(add-hook 'org-agenda-mode-hook 'set-org-agenda-files-ripgrep) +#+end_src + + ** Basic settings #+begin_src emacs-lisp (setq org-log-done 'time) -(after! org-mode +(after! org (setq org-log-done 'time) (setq org-archive-location "~/org/archive.org") - (add-to-list 'org-tags-exclude-from-inheritance "hastodos") (setq org-hide-emphasis-markers nil)) (setq org-directory "~/org/") (setq org-roam-directory org-directory) #+end_src ** Appearances -*** Deprecated: TODO Keywords -I like to have a few different todo keywords for different sorts of activities. -Purchasing todos: -#+begin_src emacs-lisp :tangle no - -(setq org-todo-keywords -'((sequence "PROJ(p)" "|" "COMPLETE") -(type "TICKLE") -(type "DELE") -(type "WAIT") -(sequence "TODO(t)" "|" "DONE") -(sequence "DELEGATED" "VERIFY" "|" "DONE") -(sequence "BUY(b)" "|" "BOUGHT") -)) -(setq org-todo-keyword-faces -'(("TODO" . "salmon1") -("START" . "spring green" ) -("DELE" . "gold") -("TICKLE" . "magenta") -("WAIT" . "gold") -("PROJ" . "deep sky blue"))) -#+end_src - -These settings aren't very useful for me, as I like default colors and keywords. -*** Deprecated: Settings for org-modern - -#+begin_src emacs-lisp :tangle no -(setq org-modern-todo-faces -'(("START" :background "spring green" :foreground "black") -("DELE" :background "gold" :foreground "black") -("WAIT" :background "gold" :foreground "black") -("PROJ" :background "deep sky blue" :foreground "black") -("TICKLE" :background "magenta" :foreground "black"))) - -(setq org-modern-priority-faces -'((?A :background "salmon1" :foreground "black") -(?B :background "gold" :foreground "black") -(?C :background "spring green" :foreground "black"))) -#+end_src - -I currently have org-modern stripped out of my config. -I probably won't need this again, but in case I do I want all my preferences to be there. *** Images Preferences We want to show images when loading a file, and also after evaluating code blocks. #+begin_src emacs-lisp