In one of my previous posts Note Taking for Minimalists we argued about the importance to keep full control over all the tools we take personal notes with. In this approach personal notes are simple text files, that live in the filesystem next to other resources they refer to. As (note) files are identified by their filename, special care needs to be taken to ensure that the files are named consistently e.g. using so called sort tags, that specify their sequence or chronological order when listed. Secondly, the filename must reflect the content description (meta data) of a note. This is where the note taking tool Tp-Note comes into play: it takes care, that the filename of a note exposes the note's meta data. Technically, Tp-Note reads the YAML header of the note file - in particular the title field - and corrects the filename of the note, if does not comply with some synchronization rule. From it's first version on Tp-Note was able to synchronize the note's meta data and filename unidirectionally. With Tp-Note version 1.16 comes a new feature: bidirectional filename synchronization. This new feature allows you to add automatically YAML header to any existing text file. Used in scripts you can convert your random text file collection into ordered note files with meta data.

Example: convert a text file into a Tp-Note file

Here a practical example of the new feature introduced with version 1.16.0:

Consider the content of the following text file Ascii-Hangman--A game for children.md whose creation date is 13 March 2022:

A little game designed for primary kids to revise vocabulary in classroom.

To convert the text file into a Tp-Note file type:

> tpnote --add-header --batch "Ascii-Hangman--A game for children.md"

NB: the --add-header flag is actually not necessary, as it is enabled by default through the configuration file variable [arg_default] add_header = true.

As a result of the above command, Tp-Note converts the filename into: 20220313-Ascii-Hangman--A game for children.md and prepends a YAML header to the file's content:

---
title:      "Ascii-Hangman "
subtitle:   "A game for children"
author:     "getreu"
date:       "2022-03-13"
lang:       "en-GB"
orig_name:  "Ascii-Hangman--A game for children.md"
---

A little game designed for primary kids to revise vocabulary in classroom.

More about templates

The content of a new notes is composed by one of it's internal customisable templates, hence the name Tp-Note, where Tp stands for “template”. Which of the internal templates is applied depends on the context in which Tp-Note is invoked: e.g. the template for clipboard text input is called [tmpl] from_clipboard_content. If the clipboard contains text with a YAML header, the template [tmpl] from_clipboard_yaml_content is used.

In total, there are 5 different [tmpl] *_content templates:

  • [tmpl] new_content
  • [tmpl] from_clipboard_content
  • [tmpl] from_clipboard_yaml_content
  • [tmpl] from_text_file_content
  • [tmpl] annotate_file_content

In general, the templates are designed in a way, that the text input stream -usually originating from the clipboard- ends up in the body of the note file, whereas the environment -such as the user name- ends up in the header of the note file.

Once the content of the new note is set by one of the content templates, another template type comes into play: the so called filename template. Each content template has a corresponding filename template, e.g.:

  • [tmpl] new_filename
  • [tmpl] from_clipboard_filename
  • [tmpl] from_clipboard_yaml_filename
  • [tmpl] from_text_file_filename
  • [tmpl] annotate_file_filename
  • [tmpl] sync_filename (no corresponding content template)

As the name suggests, the role of a filename template is to determine the filename of the new note. This is done by evaluating (deserialising) it's YAML header. The values of the note's YAML header fields are can be accessed in filename templates through various {{ fm_<key> }} dynamically created template variables. For example the value of the YAML header field title: can be accessed with {{ fm_title }}. Once the filename is set, Tp-Note writes out the new note on disk.

Most of the above templates are dedicated to the creation of new note files. However, two of them have a special role: prepend header to text file and synchronize filename:

  • Prepend header to text file (new feature in Tp-Note v1.16.0): When Tp-Note opens a regular text file without a YAML header, a new header is prepended automatically. It's data origins mainly form the filename of the text file. The templates applied in this use case are: [tmpl] from_text_file_content and [tmpl] from_text_file_filename.

  • Synchronize filename: This function mode is invoked when Tp-Note opens an existing note file, after it's YAML header is evaluated. The extracted header information is then applied to the [tmpl] sync_filename template and the resulting filename is compared to the actual filename on disk. If they differ, Tp-Note renames the note file. The [tmpl] sync_filename template operates on it's own without a corresponding content template.

Note, that in the operation mode synchronize filename, the header data overwrites the filename of the note, whereas in the operation mode prepend header the filename data is copied into the new prepended header. Keep in mind, that even in the latter mode the filename might change slightly. This is because after the header creation with the [tmpl] from_text_file_content template, the [tmpl] from_text_file_filename template is applied, which might cause a slight filename modification due to it's sanitization filters (cf. sanit() in the section Template filters).

Customize the filename synchronization scheme

As mentioned above, the filename synchronization scheme is fully customizable. To design such a custom scheme, start to set up your synchronization rules in the [tmpl] sync_filename template. Then adjust all [tmpl] *_filename templates to comply with these rules. In order to verify your design, check that the following holds for any sequential application of one [tmpl] *_filename template followed directly by the [tmpl] sync_filename template: The latter should never change the filename initially set up by any [tmpl] *_filename template.

Secondly, make sure that the expression in [tmpl] sync_filename describing the filename's sort tag e.g. {{ path | file_sort_tag }} is always followed by a variable with the sanit(alpha=true) filter set, e.g.:

{{ path | file_sort_tag }}{{ fm_title | sanit(alpha=true) }}

The first expression guarantees, that it resolves only to characters defined in the [filename] sort_tag_chars set, while the second expression is known to not start with such a character. This way Tp-Note is able to separate sort tags in filenames and avoids cyclic filename change. Or, in other words: the [tmpl] sync_filname template should always give the same result, even after repeated application.

To debug your [tmpl] sync_filename template, create a test note file test.md and invoke Tp-Note with --debug trace and --batch:

> tpnote --batch --debug trace test.md

Read more

A good start is Tp-Note's project page or the introductory video. The source code is available on GitHub - getreu/tp-note and some binaries and packages for Linux, Windows and Mac can be found here. To fully profit of Tp-note, I recommend reading Tp-Note's user manual. If you like Tp-Note, you probably soon want to customize it. How to do so, is explained in Tp-Note's manual page.