# Introduction The **jt** software (short for "journalling tool") is a helper for maintaining a journal or personal knowledge base. It has been written for the personal use of its authors, but might be useful for others. The guiding principle for jt is that having longevity for one's data and complete control over it are crucial. Because of these, the approach taken by jt is to build a static web site from source files stored in a version control system. The files will be edited with a text editor chosen by the journal writer, rather than via a custom web, desktop, or mobile application. The built journal is then served with some suitable web server. The role of jt is to make it easier to create new journal entries (new Markdown files), and to make all the common tasks of maintaining a knowledge base have minimal friction. ## Example The following example creates a new journal, which will be the default journal for the user, and a new journal entry. The entry is a draft until it's finished. ~~~sh $ jt --dirname ~/Journal init default "My private journal" $ jt new --tag meta --tag journalling "My first journal entry" ... # text editor is opened so the new entry can be written $ jt finish 0 first-entry ~~~ # Acceptance criteria and their verification This chapter defines detailed acceptance criteria and how they're verified using *scenarios* for the [Subplot][] tool. [Subplot]: https://subplot.liw.fi/ ## Configuration file handling These scenarios verify that jt handles its configuration file correctly. ### Shows defaults if no configuration file is present ~~~scenario given an installed jt when I run jt2 config then stdout matches regex dirname:.*/\.local.share/jt2 then stdout matches regex editor: "/usr/bin/editor" ~~~ ### Gives error if configuration missing file specified ~~~scenario given an installed jt when I try to run jt2 --config does-not-exist config then command fails then stderr contains "does-not-exist" ~~~ ### Accepts empty configuration file ~~~scenario given an installed jt given file empty.yaml when I run jt2 --config empty.yaml config then stdout matches regex dirname:.*/\.local.share/jt2 then stdout matches regex editor: "/usr/bin/editor" ~~~ ~~~{#empty.yaml .file .yaml} {} ~~~ ### Accepts configuration file Note that the configuration file uses a tilde syntax to refer to the user's home directory. ~~~scenario given an installed jt given file config.yaml when I run jt2 --config config.yaml config then stdout matches regex dirname:.*/.*/journal then stdout matches regex editor: "emacs" ~~~ ~~~{#config.yaml .file .yaml} dirname: ~/journal editor: emacs ~~~ ### Command line options override configuration file fields ~~~scenario given an installed jt given file config.yaml when I run jt2 --config config.yaml --dirname xxx --editor yyy config then stdout matches regex dirname: "xxx" then stdout matches regex editor: "yyy" ~~~ ### Rejects configuration file with extra entries ~~~scenario given an installed jt given file toomuch.yaml when I try to run jt2 --config toomuch.yaml config then command fails then stderr contains "unknown_field" ~~~ ~~~{#toomuch.yaml .file .yaml} unknown_field: foo ~~~ ## Create a new local journal repository `jt` works on a local repository, and it can be created an initialised using the tool. ~~~scenario given an installed jt when I run jt2 --dirname jrnl init default "My test journal" then command is successful and directory jrnl exists then there are no uncommitted changes in jrnl when I run jt2 --dirname jrnl is-journal then command is successful when I try to run jt2 --dirname bogus is-journal then command fails ~~~ ## Create a new draft, edit it, then publish it Verify that we can create a new draft entry for the journal. ~~~scenario given an installed jt when I run jt2 --dirname jrnl init default "My test journal" then command is successful and there are no drafts in jrnl and there are no journal entries in jrnl when I run jt2 --editor=none --dirname=jrnl new "Abracadabra" then command is successful and there is one draft in jrnl and draft 0 in jrnl contains "Abracadabra" and draft 0 in jrnl contains "!meta date=" given an executable script append.sh when I run jt2 --editor=./append.sh --dirname=jrnl edit 0 then command is successful and draft 0 in jrnl contains "Open sesame!" when I run jt2 --dirname=jrnl finish 0 abra then command is successful and there is one journal entry in jrnl, at FILE and file name ends with .mdwn and journal entry contains "Abracadabra" and journal entry contains "Open sesame!" and there are no drafts in jrnl and there are no uncommitted changes in jrnl ~~~ ~~~{#append.sh .file .numberLines} #!/bin/sh set -eux echo "Open sesame!" >> "$1" ~~~ ## Create two drafts Verify that we can create two draft entries at the same time. ~~~scenario given an installed jt when I run jt2 --dirname jrnl init default "My test journal" then command is successful then there are no drafts in jrnl then there are no journal entries in jrnl when I run jt2 --editor=none --dirname=jrnl new "Abracadabra" then command is successful then there is one draft in jrnl then draft 0 in jrnl contains "Abracadabra" when I run jt2 --editor=none --dirname=jrnl new "Simsalabim" then command is successful then there are two drafts in jrnl then draft 0 in jrnl contains "Abracadabra" then draft 1 in jrnl contains "Simsalabim" given an executable script append.sh when I run jt2 --editor=./append.sh --dirname=jrnl edit 0 then draft 0 in jrnl contains "Open sesame!" when I run jt2 --editor=./append.sh --dirname=jrnl edit 1 then draft 1 in jrnl contains "Open sesame!" when I run jt2 --dirname=jrnl finish 0 abra then command is successful then there is one journal entry in jrnl, at FILE then journal entry contains "Abracadabra" then journal entry contains "Open sesame!" then there is one draft in jrnl when I run jt2 --dirname=jrnl finish 1 sim then command is successful then there are two journal entries in jrnl, at FILE1 and FILE2 then journal entry contains "Abracadabra" then journal entry contains "Simsalabim" then there are no drafts in jrnl then there are no uncommitted changes in jrnl ~~~ ## Override template for new journal entries Verify that we can have a custom template for new journal entries. ~~~scenario given an installed jt when I run jt2 --dirname jrnl init default "My test journal" then command is successful given file jrnl/.config/templates/new_entry from new_entry_template when I run jt2 --editor=none --dirname=jrnl new "Abracadabra" then command is successful and there is one draft in jrnl and draft 0 in jrnl contains "custom new entry template" ~~~ ~~~{#new_entry_template .file .numberLines} This is a custom new entry template. ~~~ ## Use topic pages Verify that we can create a new topic page and a new entry referring to that topic page. ~~~scenario given an installed jt when I run jt2 --dirname jrnl init default "My test journal" then command is successful when I try to run jt2 --editor=none --dirname=jrnl new --topic foo "Abracadabra" then command fails then stderr contains "foo" when I run jt2 --editor=none --dirname=jrnl new-topic foo "Things about Foo" then command is successful then file jrnl/foo.mdwn contains "Things about Foo" then there are no uncommitted changes in jrnl when I run jt2 --editor=none --dirname=jrnl new --topic foo "Abracadabra" then command is successful and there is one draft in jrnl and draft 0 in jrnl links to "foo" ~~~ # Colophon This document is meant to be processed with the [Subplot][] program to typeset into HTML or PDF or to generate a program that automatically verifies that all acceptance criteria are met. [Subplot]: https://subplot.liw.fi/ --- title: "jt—a journalling tool" author: - Lars Wirzenius - Daniel Silverstone template: python bindings: - subplot/jt.yaml - lib/files.yaml - lib/runcmd.yaml functions: - subplot/jt.py - lib/files.py - lib/runcmd.py ...