summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--init.el1
-rw-r--r--lib/doc/jao-org-notes.el92
2 files changed, 45 insertions, 48 deletions
diff --git a/init.el b/init.el
index f29fb75..57c7a7b 100644
--- a/init.el
+++ b/init.el
@@ -3216,6 +3216,7 @@
[["Notes"
("n" "create new note" jao-org-notes-create)
("/" "open note" jao-org-notes-open)
+ ("\\" "open note by tags" jao-org-notes-open-tags)
("d" "go to doc" jao-select-pdf :if display-graphic-p)
("d" "search docs" jao-recoll-consult-docs :if-not display-graphic-p)
("D" "open doc" jao-open-doc)]
diff --git a/lib/doc/jao-org-notes.el b/lib/doc/jao-org-notes.el
index b7700ec..05481b7 100644
--- a/lib/doc/jao-org-notes.el
+++ b/lib/doc/jao-org-notes.el
@@ -1,6 +1,6 @@
;;; jao-org-notes.el --- A simple system for org note taking -*- lexical-binding: t; -*-
-;; Copyright (C) 2020, 2021, 2022 jao
+;; Copyright (C) 2020, 2021, 2022, 2024 jao
;; Author: jao <mail@jao.io>
;; Keywords: tools
@@ -26,30 +26,42 @@
;;; Code:
(require 'org)
(require 'consult)
+(require 'jao-shell)
(defvar jao-org-notes-dir (expand-file-name "notes" org-directory))
-(defun jao-org-notes--rg (str)
+(defun jao-org-notes--title-or-tags (str)
+ (let ((ts (split-string str "[:,]+" t)))
+ (format "^#.(title: .*%s|tags:.*(%s:))" str (mapconcat #'identity ts ":|"))))
+
+(defun jao-org-notes--rg-cmd (rgx &rest args)
`("rg" "--null" "--line-buffered" "--color=never" "--max-columns=250"
- "--no-heading" "--line-number" "--smart-case" "." "-e"
- ,(format "^(#.(title|tags): .*)%s" str)))
+ "--no-heading" "--smart-case" ,@args "." "-e" ,rgx))
+
+(defun jao-org-notes--rg-title-or-tags (str)
+ (jao-org-notes--rg-cmd (jao-org-notes--title-or-tags str) "-m" "2"))
(defun jao-org-notes--clean-match (m)
(cons (format "%s %s"
(replace-regexp-in-string "^\\./" "" (car m))
- (replace-regexp-in-string "[0-9]+:#\\+\\(title\\|tags\\):"
+ (replace-regexp-in-string "#\\+\\(title\\|tags\\):"
" (\\1)" (cadr m)))
(expand-file-name (car m) default-directory)))
(defun jao-org-notes--matches (lines)
(mapcar (lambda (l) (jao-org-notes--clean-match (split-string l "\0" t))) lines))
+(defun jao-org-notes--grep-rx (rx)
+ (let ((default-directory jao-org-notes-dir))
+ (jao-org-notes--matches
+ (apply #'jao-shell-cmd-lines (jao-org-notes--rg-cmd rx)))))
+
(defvar jao-org-notes--grep-history nil)
-(defun jao-org--grep (prompt &optional cat no-req)
+(defun jao-org-notes--consult-rg (prompt &optional cat no-req)
(let ((default-directory (expand-file-name (or cat "") jao-org-notes-dir)))
(consult--read
- (consult--async-command #'jao-org-notes--rg
+ (consult--async-command #'jao-org-notes--rg-title-or-tags
(consult--async-transform jao-org-notes--matches))
:prompt prompt
:initial (consult--async-split-initial "")
@@ -66,12 +78,11 @@
(defun jao-org-notes--cat ()
(let* ((cat (completing-read "Top level category: " (jao-org-notes-cats))))
(cond ((file-exists-p (expand-file-name cat jao-org-notes-dir)) cat)
- ((yes-or-no-p "New category, create?") cat)
- (t (jao-roam--cat)))))
+ ((yes-or-no-p "New category, create?") cat))))
(defun jao-org-notes--insert-title ()
(let* ((cat (jao-org-notes--cat))
- (title (file-name-base (jao-org--grep "Title: " cat t)))
+ (title (file-name-base (jao-org-notes--consult-rg "Title: " cat t)))
(title (replace-regexp-in-string "^#" "" title)))
(when (not (string-empty-p title))
(let* ((base (replace-regexp-in-string " +" "-" (downcase title)))
@@ -83,30 +94,13 @@
(insert "#+title: " title "\n")
t)))))
-(defvar jao-org-notes--tags nil)
-(defvar jao-org-notes-tags-cache-file "~/.emacs.d/cache/tags.eld")
-
-(defun jao-org-notes--save-tags ()
- (with-current-buffer (find-file-noselect jao-org-notes-tags-cache-file)
- (delete-region (point-min) (point-max))
- (print jao-org-notes--tags (current-buffer))
- (let ((message-log-max nil)
- (inhibit-message t))
- (save-buffer))))
-
-(defun jao-org-notes--read-tags-cache ()
- (let ((b (find-file-noselect jao-org-notes-tags-cache-file)))
- (with-current-buffer b (goto-char (point-min)))
- (setq jao-org-notes--tags (read b))))
+(persist-defvar jao-org-notes--tags nil "Tags used so far in notes.")
+(defvar jao-org-notes--tag-history nil)
(defun jao-org-notes--read-tags ()
- (unless jao-org-notes--tags (jao-org-notes--read-tags-cache))
- (let* ((tags (completing-read-multiple "Tags: " jao-org-notes--tags))
- (new-tags (seq-difference tags jao-org-notes--tags)))
- (when new-tags
- (setq jao-org--notes-tags
- (sort (append new-tags jao-org-notes--tags) #'string<))
- (jao-org-notes--save-tags))
+ (let* ((tags (completing-read-multiple "Tags: " jao-org-notes--tags nil nil nil
+ 'jao-org-notes--tag-history)))
+ (setq jao-org-notes--tags (seq-union jao-org-notes--tags tags #'string=))
tags))
(defun jao-org-notes--insert-tags ()
@@ -115,21 +109,31 @@
":\n"))
(defun jao-org-notes--insert-date ()
- (insert "#+date: ")
- (org-insert-time-stamp (current-time))
- (insert "\n"))
+ (org-insert-time-stamp (current-time) t t "#+date: " "\n"))
(defun jao-org-notes--template (k)
- `(,k "Note" plain (file jao-org-notes-create)
- "\n- %a\n %i" :jump-to-captured t))
+ `(,k "Note" plain (file jao-org-notes-create) "\n- %a\n %i" :jump-to-captured t))
;;;###autoload
(defun jao-org-notes-open ()
"Search for a note file, matching tags and titles with completion."
(interactive)
- (when-let (f (jao-org--grep "Search notes: "))
+ (when-let (f (jao-org-notes--consult-rg "Search notes: "))
(find-file f)))
+(defun jao-org-notes-open-tags ()
+ "Search for a note file, matching all tags with completion."
+ (interactive)
+ (let* ((tags (jao-org-notes--read-tags))
+ (fn (lambda ()
+ (prog1 (jao-org-notes--grep-rx (format "^#.tags:.*:%s:" (car tags)))
+ (setq tags (cdr tags)))))
+ (res (funcall fn)))
+ (while (and res tags) (setq res (seq-intersection res (funcall fn))))
+ (unless res (user-error "No notes found"))
+ (when-let (f (completing-read "Select file: " (mapcar #'car res)))
+ (find-file (cdr (assoc f res))))))
+
;;;###autoload
(defun jao-org-notes-create ()
"Create a new note file, matching tags and titles with completion."
@@ -154,18 +158,10 @@
(expand-file-name (concat d bn ".org") jao-org-notes-dir)))))
;;;###autoload
-(defun jao-org-notes-grep ()
- "Perform a grep search on all org notes body, via consult-ripgrep."
- (interactive)
- (consult-ripgrep jao-org-notes-dir initial))
-
-(make-obsolete 'jao-org-notes-grep 'consult-recoll "2022-08-22")
-
-;;;###autoload
(defun jao-org-notes-backlinks ()
"Show a list of note files linking to the current one."
(interactive)
- (jao-org--grep (concat "\\[\\[file:\\(.*/\\)?" (buffer-name))))
+ (jao-org-notes--grep-rx (concat "\\[\\[file:\\(.*/\\)?" (buffer-name))))
;;;###autoload
(defun jao-org-notes-insert-tags ()
@@ -177,7 +173,7 @@
(defun jao-org-notes-insert-link ()
"Select a note file (with completion) and insert a link to it."
(interactive)
- (when-let (f (jao-org--grep "Notes file: "))
+ (when-let (f (jao-org-notes--consult-rg "Notes file: "))
(let ((rel-path (file-relative-name f default-directory))
(title (with-current-buffer (find-file-noselect f)
(save-excursion