Finding my blog posts with consult-omni
| emacsSometimes I just want to quickly get to a blog post by title. I use consult-omni for quick web searches that I can jump to or insert as a link. Sure, I can limit this search to my blog by specifying site:sachachua.com or using the code I wrote to search my blog, notes, and sketches with consult-ripgrep and consult-omni, but the search sometimes gets confused by other text on the page. When I publish my blog with Eleventy, I also create a JSON file with all my blog post URLs and titles. Here's how I can use that data as a consult-omni source.
(defun my-consult-omni-blog-data ()
(let ((base (replace-regexp-in-string "/$" "" my-blog-base-url))
(json-object-type 'alist)
(json-array-type 'list))
(mapcar
(lambda (o)
(list :url (concat base (alist-get 'permalink o))
:title (alist-get 'title o)
:date (alist-get 'date o)))
(sort (json-read-file "~/sync/static-blog/_site/blog/all/index.json")
(lambda (a b)
(string< (or (alist-get 'date b) "")
(or (alist-get 'date a) "")))))))
(unless (get 'my-consult-omni-blog-data :memoize-original-function)
(memoize #'my-consult-omni-blog-data "5 minutes"))
(defun my-consult-omni-blog-titles-builder (input &rest args &key callback &allow-other-keys)
(let* ((quoted (when input (regexp-quote input)))
(list
(if quoted
(seq-filter
(lambda (o)
;; TODO: Someday figure out orderless?
(string-match quoted (concat (plist-get o :title) " - " (plist-get o :title))))
(my-consult-omni-blog-data))
(my-consult-omni-blog-data)))
(candidates
(mapcar
(lambda (o)
(propertize
(concat (plist-get o :title))
:source "Blog"
:date (plist-get o :date)
:title (plist-get o :title)
:url (plist-get o :url)))
(if quoted (seq-take list 3) list))))
(when callback (funcall callback candidates))
candidates))
(defun my-consult-omni-blog-annotation (s)
(format " (%s)"
(propertize (substring (or (get-text-property 0 :date s) "") 0 4)
'face 'completions-annotations)))
(with-eval-after-load 'consult-omni
(consult-omni-define-source
"My blog"
:narrow-char ?b
:type 'sync
:request #'my-consult-omni-blog-titles-builder
:on-return 'my-consult-org-bookmark-visit
:group #'consult-omni--group-function
:annotate #'my-consult-omni-blog-annotation
:min-input 3
:sort nil
:require-match t))
Here's what it looks like by itself when I call consult-omni-my-blog
:

Then I can add it as one of the sources used by consult-omni
:
(setq consult-omni-multi-sources
'(consult-omni--source-google
consult-omni--source-my-org-bookmarks
consult-omni--source-my-blog))
Here's what it looks like when I call consult-omni
to search my bookmarks, blog posts, and Google results at the same time.

Then I can press RET
to open the blog post in my browser or C-. i l
to insert the link using Embark (my-consult-omni-embark-insert-link
).
Related:
- consult-omni–source-my-org-bookmarks
- Completing blog posts (Org link type with completion)
Next steps: I want to find out how to get :sort nil
to be respected so that more recent blog posts are listed first. Also, it might be fun to define a similar source for the sections of my Emacs configuration, like the way I can use my dotemacs: Org Mode link type with completion.