:title: Denote Filenames with Sphinx :date: 2025-02-17 :tags: blogging, denote, emacs, sphinx :identifier: 20250217T182726 Integrating ``denote`` Filenames with Sphinx ============================================ .. highlight:: none .. container:: post-teaser If you have spent any time following the Emacs community, you will have likely come across Protesilaos Stavrou (aka Prot) and his `denote `__ project. ``denote`` defines a clever file naming scheme and provides a number of utilities for working with these files from within Emacs. I found the simplicity of the approach instantly appealing and before long I found myself wanting to use the ``denote`` naming scheme to organise the content on this website. In this post I outline how I went about integrating ``denote`` with my (perhaps unconventional) static site generator of choice - `Sphinx `__ ``denote`` basics ----------------- For an in-depth introduction to ``denote`` be sure to check out `this video `__ from Prot himself however, at the core of ``denote`` is the file-naming sheme:: --__<tags>.ext where - ``<timestamp>`` captures the date and time the file was created and doubles as the file's unique identifier - ``<title>`` a lowercase ``-`` separated string which captures your traditional file name - ``<tags>`` (called keywords by denote) which is a ``_`` separated string As an example the filename for this blog post is ``20250217T182726--denote-filenames-with-sphinx__blog_blogging_denote_emacs_sphinx.rst`` The main benefit in naming your files in this way is that you can perform some fairly sophisticated queries across your files with simple text based searches. reStructuredText and ``denote.el`` ---------------------------------- While I don't use Emacs all the time, I think it's safe to say it's my default editor when working on personal projects. So it would be nice to be able to make use of the utilities provided by the `denote.el <https://github.com/protesilaos/denote>`__ package when working on this site. One of the main features provided by the package is to insert `front matter <https://protesilaos.com/emacs/denote#h:13218826-56a5-482a-9b91-5b6de4f14261>`__ into your notes corresponding to the information encoded in the filename **and** to keep the two in sync when either one changes. ``denote.el`` has built in support for several markup formats however, the :external+sphinx:std:ref:`reStructuredText <rst-primer>` syntax used by Sphinx is not one of them. Of course, being an Emacs package this isn't something that a few lines of lisp cannot solve! .. admonition:: What about Markdown? Yes, both ``denote.el`` and Sphinx support :external+sphinx:std:ref:`markdown` however, I simply prefer reStructuredText 😅 .. code-block:: elisp :filename: emacs/init.el (use-package denote :ensure t :hook ((dired-mode . denote-dired-mode)) :config ;; Add reStructuredText support to denote (add-to-list 'denote-file-types `(rst :extension ".rst" :date-function denote-date-iso-8601 :front-matter ":title: %s\n:date: %s\n:tags: %s\n:identifier: %s\n\n" :title-key-regexp "^:title:" :title-value-function identity :title-value-reverse-function denote-trim-whitespace :keywords-key-regexp "^:tags:" :keywords-value-function ,(lambda (ks) (string-join ks ", ")) :keywords-value-reverse-function denote-extract-keywords-from-front-matter :link ":denote:link:`%2$s <%1$s>`" :link-in-context-regexp ,(concat ":denote:link:`.*?<\\(?1:" denote-id-regexp "\\)>`")))) Which instructs denote to make use of reStructuredText's :external+sphinx:std:ref:`field list <rst-field-lists>` syntax when inserting front matter. .. literalinclude:: ./20250217T182726--denote-filenames-with-sphinx__blog_blogging_denote_emacs_sphinx.rst :language: rst :end-at: :identifier: It also instructs ``denote`` to use a role called ``denote:link`` when inserting a link to another note, but we'll come back to that a bit later on.