diff --git a/.gitignore b/.gitignore index b4afdb2..656a0a4 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,3 @@ # Dependency directories (remove the comment below to include it) # vendor/ -.zk diff --git a/README.md b/README.md index 7a92d22..9fb862b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,19 @@ -# zk -A plain-text note-taking assistant +# `zk` – a plain text note-taking assistant + +Looking for a quick usage example? [Let's get started](http://mickael-menu.github.io/zk/getting-started). + +`zk` is a command-line tool helping you to maintain a plain text [Zettelkasten](https://zettelkasten.de/introduction/) or [personal wiki](https://en.wikipedia.org/wiki/Personal_wiki). + +It is primarily focused on: + +* [keeping your notebook future-proof](http://mickael-menu.github.io/zk/future-proof), by relying on plain text +* [creating notes from templates](http://mickael-menu.github.io/zk/note-creation) +* performing [advanced search queries](http://mickael-menu.github.io/zk/note-filtering) +* being a hub for everything related to your notes, thanks to [command aliases](http://mickael-menu.github.io/zk/config-alias) and [automation](http://mickael-menu.github.io/zk/automation). +* [notebook housekeeping](http://mickael-menu.github.io/zk/notebook-housekeeping) + +What `zk` is not: + +* a note editor +* a tool to serve your notes on the web – for this, you may be interested in [Neuron](http://mickael-menu.github.io/zk/neuron) or [Gollum](https://github.com/gollum/gollum). + diff --git a/docs/.zk/config.toml b/docs/.zk/config.toml new file mode 100644 index 0000000..60484a6 --- /dev/null +++ b/docs/.zk/config.toml @@ -0,0 +1,10 @@ +[note] +template = "default.md" + +[tool] +editor = "vim" + +[alias] +neuron = 'neuron gen $@' +wc = "zk list --format '{{word-count}}\t{{title}}' --sort word-count -x log $@" + diff --git a/docs/.zk/notebook.db b/docs/.zk/notebook.db new file mode 100644 index 0000000..3dac8dc --- /dev/null +++ b/docs/.zk/notebook.db @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:41e8b104003fba2e5076276d9b4929912391bbd163edd97d6598f654039c82e8 +size 331776 diff --git a/docs/.zk/templates/default.md b/docs/.zk/templates/default.md new file mode 100644 index 0000000..b2f2c4a --- /dev/null +++ b/docs/.zk/templates/default.md @@ -0,0 +1,2 @@ +# {{title}} + diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..9775a82 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,18 @@ +# `zk` – a plain text note-taking assistant + +Looking for a quick usage example? [Let's get started](getting-started.md). + +`zk` is a command-line tool helping you to maintain a plain text [Zettelkasten](https://zettelkasten.de/introduction/) or [personal wiki](https://en.wikipedia.org/wiki/Personal_wiki). + +It is primarily focused on: + +* [keeping your notebook future-proof](future-proof.md), by relying on plain text +* [creating notes from templates](note-creation.md) +* performing [advanced search queries](note-filtering.md) +* being a hub for everything related to your notes, thanks to [command aliases](config-alias.md) and [automation](automation.md). +* [notebook housekeeping](notebook-housekeeping.md) + +What `zk` is not: + +* a note editor +* a tool to serve your notes on the web – for this, you may be interested in [Neuron](neuron.md) or [Gollum](https://github.com/gollum/gollum). diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000..48637e8 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,2 @@ +permalink: /:title +theme: jekyll-theme-modernist \ No newline at end of file diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html new file mode 100644 index 0000000..94cd706 --- /dev/null +++ b/docs/_layouts/default.html @@ -0,0 +1,57 @@ + + + + + + +{% seo %} + + + + + + + + +
+
+

{{ site.title | default: site.github.repository_name }}

+ {% if site.description or site.github.project_tagline %} +

{{ site.description | default: site.github.project_tagline }}

+ {% endif %} +

View the Project on GitHub {{ github_name }}

+ +
+
+ + {{ content }} + +
+
+ + + + {% if site.google_analytics %} + + {% endif %} + + diff --git a/docs/assets/css/style.scss b/docs/assets/css/style.scss new file mode 100644 index 0000000..9a115ef --- /dev/null +++ b/docs/assets/css/style.scss @@ -0,0 +1,9 @@ +--- +--- + +@import "{{ site.theme }}"; + +code, pre { + font-size: inherit; +} + diff --git a/docs/automation.md b/docs/automation.md new file mode 100644 index 0000000..ee04a37 --- /dev/null +++ b/docs/automation.md @@ -0,0 +1,10 @@ +# Automating frequent tasks + +`zk` was designed with automation in mind and strive to be [a good Unix citizen](https://en.wikipedia.org/wiki/Unix_philosophy). As such, it offers a number of ways to interface with other programs: + +* [write command aliases](config-alias.md) for repeated complex commands +* [call `zk` from other programs](external-call.md) +* [send notes for processing by other programs](external-processing.md) +* [create a note with initial content](note-creation.md) from a standard input pipe + +If you find out that `zk` does not behave as expected or could communicate better with other programs, [please post an issue](https://github.com/mickael-menu/zk/issues). diff --git a/docs/config-alias.md b/docs/config-alias.md new file mode 100644 index 0000000..03a54dd --- /dev/null +++ b/docs/config-alias.md @@ -0,0 +1,193 @@ +# Command aliases + +A command alias is a custom `zk` command which can run another `zk` command or an external program. + +Declaring your own aliases is a great way to make your experience with `zk` easier and more familiar. With aliases, `zk` becomes a hub capable of launching all the programs you need to manage your [notebook](notebook.md). + +## Configuring aliases + +Command aliases are declared in your [configuration file](config.md), under the `[alias]` section. They are executed with `$SHELL -c`, which allows you to: + +* expand arguments with `$@` or `$*` +* expand environment variables +* run several commands with `&&` +* pipe several commands with `|` + +An alias can call other aliases but cannot call itself. This enables you to override the default options of native commands, for example: + +```toml +[alias] +edit = "zk edit --interactive $@" +``` + +When running an alias, the `ZK_PATH` environment variable is set to the absolute path of the current notebook. You can use it to run commands working no matter the location of the working directory. + +```toml +journal = 'zk new "$ZK_PATH/journal"' +``` + +If you need to surround the path with quotes, make sure you use double quotes, otherwise environment variables will not be expanded. + +### `xargs` formula + +Calling an external program with a list of note paths using `xargs` is such a common use case that we can extract a reusable alias pattern. + +```toml +alias = "zk list --quiet --format path --delimiter0 $@ | xargs -0 " +``` + +Find more details about these options in [Send notes for processing by other programs](external-processing.md). + +## Collection of useful aliases + +Here are a few aliases to get you started writing your own. + +### Shortcuts for native commands + +```toml +ls = "zk list $@" +ed = "zk edit $@" +n = "zk new $@" +``` + +### Edit the last modified note + +Suffixing the `modified` sort criterion with `-` orders the notes by *descendent* modification date. + +```toml +edlast = "zk edit --limit 1 --sort modified- $@" +``` + +### Edit the notes created during the last two weeks + +This command uses `--interactive` to let the user select which notes to actually edit among the recent ones. Note the use of human friendly language for `--created-after`'s argument. + +In this case, additional arguments do not necessarily make sense, so we omit the trailing `$@`. + +```toml +recent = "zk edit --sort created- --created-after 'last two weeks' --interactive" +``` + +### Edit the configuration file + +Here's a concrete example using environment variables, in particular `ZK_PATH`. Note the double quotes around the path. + +```toml +conf = '$EDITOR "$ZK_PATH/.zk/config.toml"' +``` + +### List paths in a command-line friendly fashion + +Use this alias to send a list of space-separated file paths matching the given [filtering criteria](note-filtering.md) to another program. See [send notes for processing by other programs](external-processing.md) for more details. + +```toml +paths = "zk list --quiet --format \"'{{path}}'\" --delimiter ' ' $@" +``` + +### List paths to be used in a parent `zk` command + +Similarly, use this alias to expand filtered note paths inside a parent `zk` command taking a comma-separated paths list. + +```toml +inline = "zk list --quiet --format {{path}} --delimiter , $@" +``` + +Examples of use: + +```sh +# List the notes which have at least one link pointing to them (i.e. not orphans). +$ zk list --exclude "`zk inline --orphan`" + +# List the notes which are linked by at least one note from the journal/ directory. +$ zk list --linked-by "`zk inline journal`" +``` + +### Print a random note + +Increasing serendipity while using your notebook is important to spark new ideas. The `random` sort criterion is the key to this alias. + +```toml +lucky = "zk list --quiet --format full --sort random --limit 1" +``` + +### Create a note from a free title + +If you often create notes with `zk new --title "An interesting concept"`, you will like this alias. Using `"$*"`, you do not need to quote the arguments anymore. + +```toml +nt = 'zk new --title "$*"' +``` + +Usage: `zk nt An interesting concept` + +No more forgotten quotes! + +### Create a note and save its path into the clipboard (macOS) + +Build upon the previous alias, but instead of editing the created note it will copy the created note's path into the macOS clipboard. + +```toml +ntc = 'zk new --print-path --title "$*" | pbcopy' +``` + +### Print and sort the word count of selected notes + +This will list the notes and their word count sorted by increasing word count. It is useful to spot flimsy notes that you could flesh out. + +```toml +wc = "zk list --format '{{word-count}}\t{{title}}' --sort word-count $@" +``` + +Usage: + +```sh +$ zk wc +4 Integration with fzf +5 Searching and filtering notes +63 Setting your default editor +86 Anatomy of a notebook +... +``` + +### Print the backlinks of a note + +This is such a useful command, that an alias might be helpful. + +```toml +bl = "zk list --linking-to $@" +``` + +### Browse the Git history of selected notes + +This example showcases the "`xargs` formula" with a concrete example. + +```toml +log = "zk list --quiet --format path --delimiter0 $@ | xargs -0 git log --patch --" +``` + +### Saving the changes in the Git repository + +This alias does not call `zk` at all! This shows how you can use `zk` as a hub for everything related to your notes. + +```toml +save = 'git add . && git commit -m "$*"' +``` + +Usage: `zk save Expand the note on command aliases` + +### Copy/backup selected notes + +A more complex example backing up the notes matching the given filtering criteria in a target directory. It creates intermediate directories if needed. + +`$1` and `${@:2}` are used to split the arguments between the first one which will be the destination directory, and the remaining arguments which will be used as filtering options. + +```toml +# macOS +cp = 'zk list --quiet --format path --delimiter0 ${@:2} | xargs -t -0 -I % ditto "%" "$1/%"' + +# Linux +cp = 'mkdir -p "$1" && zk list --quiet --format path --delimiter0 ${@:2} | xargs -t -0 -I % cp --parents "%" "$1"' +``` + +Usage: `zk cp output/ --created-after 'last two weeks'` + diff --git a/docs/config-extra.md b/docs/config-extra.md new file mode 100644 index 0000000..6d91e7e --- /dev/null +++ b/docs/config-extra.md @@ -0,0 +1,43 @@ +# Extra user variables + +`zk` is opened for template context extension which can be useful when [creating new notes](note-creation.md), for example: + +* expanding custom metadata (author, subject, etc.) +* modifying a [template](template.md)'s output dynamically depending on the value of an extra variable + +## Static extra variables + +You can declare static extra variables in the [configuration file](config.md)'s `[extra]` section. Each [note group](config-group.md) can have its own `[extra]` section, which may override values from the root section. + +```toml +[extra] +visibility = "public" +author = "Mickaël" + +[group.journal.extra] +visibility = "private" # overrides +``` + +## Dynamic extra variables + +Maybe more useful, you can provide additional extra variables dynamically to `zk new` from the command-line with `--extra`. Multiple variables must be separated by a semicolon `;`, in which case quoting the argument is required. + +```sh +$ zk new --extra author=Thomas +$ zk new --extra "show-header=1;author=Thomas" +``` + +## Using extra variables in templates + +After declaring extra variables, you can expand them inside the [template used when creating new notes](template-creation.md), using the usual [Handlebars syntax](template.md). + +```markdown +# {{title}} + +Written by {{extra.author}}. + +{{#if extra.show-header}} +Behold, the mighty dynamic header! +{{/if}} +``` + diff --git a/docs/config-group.md b/docs/config-group.md new file mode 100644 index 0000000..7858a67 --- /dev/null +++ b/docs/config-group.md @@ -0,0 +1,50 @@ +# Note group + +A *group* is a named [configuration section](config.md) used to override [note creation rules](config-note.md) for specific directories. This allows you to use your [notebook](notebook.md) very differently depending on the type of note created. For a practical example, take a look at [maintaining a daily journal](daily-journal.md). + +## Declaring a new group + +To add a new group to your configuration file, declare a new `[group.]` section. It takes a single optional property `paths`, which is the list of directories belonging to this group. + +```toml +[group.journal] +paths = [ + "journal/daily", + "journal/weekly" +] +``` + +You can also use [glob patterns](https://en.wikipedia.org/wiki/Glob_\(programming\)) in `paths`. + +```toml +[group.journal] +paths = ["journal/*"] +``` + +If you omit `paths`, the directory named after the group will be inferred. Note the double quotes when using spaces or slashes for subdirectories. + +```toml +# This will automatically apply to the `citations/web` directory +[group."citations/web"] +``` + +## Overriding note configuration and extra variables + +You can override the global [note configuration](config-note.md) and [extra user variables](config-extra.md) for a given group. + +```toml +[group.journal.note] +filename = "{{date now}}" +template = "journal.md" + +[group.journal.extra] +author = "Mickaël" +``` + +## Choose a group dynamically + +If you prefer to keep multiple groups in a single directory, you can specify which group to use when creating a new note explicitly. + +```sh +$ zk new --group journal +``` diff --git a/docs/config-note.md b/docs/config-note.md new file mode 100644 index 0000000..6c36c6d --- /dev/null +++ b/docs/config-note.md @@ -0,0 +1,55 @@ +# Note configuration + +The `[note]` section from the [configuration file](config.md) is used to set the [note creation rules](note-creation.md). The following properties are customizable: + +* `language` (string) + * Two-letters code of the language used when writing notes, e.g. `en`. + * This is used to generate slugs or with date formats. For now, only English is fully supported. +* `default-title` (string) + * The default title used for new notes when no `--title` option is provided. +* `filename` (string) + * [Template](template.md) used to generate the note filename, without its file extension. +* `extension` (string) + * File extension for the generated note. By default, `md` (Markdown) is used. +* `template` (string) + * Path to the [template](template.md) used to generate the note content. + * Either an absolute path, or relative to `.zk/templates/`. +* `id-charset` (string) + * Characters set used to [generate random IDs](note-id.md). + * You can use: + * `letters` for characters from `a` to `z` + * `numbers` for characters from `0` to `9` + * `alphanum` for `letters` + `numbers` + * `hex` for characters from `a` to `f` and `0` to `9` + * a free string for custom characters +* `id-length` (integer) + * Length of the generated random IDs. +* `id-case` (enum) + * Letter case for the generated random IDs. + * Possible values are `lower`, `upper` or `mixed`. + +## Common filename templates + +Here are some common filename patterns you may want to use: + +* `{{id}}` – e.g. `i2hn8.md` + * Just a [random ID](note-id.md), simple and elegant. + * To use [Neuron](neuron.md)'s ID format, set: + ```toml + [note] + id-charset = "hex" + id-length = 8 + id-case = "lower" + ``` +* `{{slug title}}` – e.g. `an-interesting-concept.md` + * A [slugified](template.md) version of the title given with `--title`. + * Readable and practical for web servers, but fragile in case of renaming. +* `{{id}}-{{slug title}}` – e.g. `i2hn8-an-interesting-concept.md` + * The best of both worlds? Readable but if you link only with the prefix ID, you can rename without breaking links. +* `{{date now 'timestamp'}}` – e.g. `200911172034.md` + * Verbose, but sortable by creation date and stable. +* `{{date now 'timestamp'}} {{title}}` – e.g. `200911172034 An interesting concept.md` + * The format of [The Archive](https://zettelkasten.de/the-archive/) and [sirupsen's zk](https://github.com/sirupsen/zk). +* `{{date now '%Y-%m-%d'}}` – e.g. `2009-11-17.md` + * Sortable, human-friendly format for a daily journal. + * i.e. [Maintaining a daily journal](daily-journal.md). diff --git a/docs/config.md b/docs/config.md new file mode 100644 index 0000000..50be448 --- /dev/null +++ b/docs/config.md @@ -0,0 +1,89 @@ +# Configuration file + +Each [notebook](notebook.md) contains a configuration file used to customize your experience with `zk`. This file is located at `.zk/config.toml` and uses the [TOML format](https://github.com/toml-lang/toml). It is composed of several optional sections: + +* `[note]` sets the [note creation rules](config-note.md) +* `[extra]` contains free [user variables](config-extra.md) which can be expanded in templates +* `[group]` defines [note groups](config-group.md) with custom rules +* `[tool]` customizes interaction with external programs such as: + * [your default editor](tool-editor.md) + * [your default pager](tool-pager.md) + * [`fzf`](tool-fzf.md) +* `[alias]` holds your [command aliases](config-alias.md) + +## Complete example + +Here's an example of a complete configuration file: + +```toml +# NOTE SETTINGS +[note] + +# Language used when writing notes. +# This is used to generate slugs or with date formats. +language = "en" + +# The default title used for new note, if no `--title` flag is provided. +default-title = "Untitled" + +# Template used to generate a note's filename, without extension. +filename = "{{id}}-{{slug title}}" + +# The file extension used for the notes. +extension = "md" + +# Template used to generate a note's content. +# If not an absolute path, it is relative to .zk/templates/ +template = "default.md" + +# Configure random ID generation. + +# The charset used for random IDs. +id-charset = "alphanum" + +# Length of the generated IDs. +id-length = 4 + +# Letter case for the random IDs. +id-case = "lower" + + +# EXTRA VARIABLES +[extra] +author = "Mickaël" + + +# GROUP OVERRIDES +[dir.journal] +paths = ["journal/weekly", "journal/daily"] + +[dir.journal.note] +filename = "{{date now}}" + + +# EXTERNAL TOOLS +[tool] + +# Default editor used to open notes. +editor = "nvim" + +# Pager used to scroll through long output. +pager = "less -FIRX" + +# Command used to preview a note during interactive fzf mode. +fzf-preview = "bat -p --color always {-1}" + + +# COMMAND ALIASES +[alias] + +# Edit the last modified note. +edlast = "zk edit --limit 1 --sort modified- $@" + +# Edit the notes selected interactively among the notes created the last two weeks. +recent = "zk edit --sort created- --created-after 'last two weeks' --interactive" + +# Show a random note. +lucky = "zk list --quiet --format full --sort random --limit 1" +``` + diff --git a/docs/daily-journal.md b/docs/daily-journal.md new file mode 100644 index 0000000..cb910af --- /dev/null +++ b/docs/daily-journal.md @@ -0,0 +1,48 @@ +# Maintaining a daily journal + + + +Let's assume you want to write daily notes named like `2021-02-16.md` in a `journal/daily` sub-directory. This common use case is a good fit for creating a [note group](config-group.md) overriding the default [note creation](note-creation.md) settings. + +First, create a `group` entry in the [configuration file](config.md) to set the note settings for this directory. Refer to the [template syntax reference](template.md) to understand how to use the `{{date}}` helper. + +```toml +[group.daily] +# Directories listed here will automatically use this group when creating notes. +paths = ["journal/daily"] + +[group.daily.note] +# %Y-%m-%d is actually the default format, so you could use {{date now}} instead. +filename = "{{date now '%Y-%m-%d'}}" +extension = "md" +template = "daily.md" +``` + +Next, create a template file under `.zk/templates/daily.md` to render the note content. Here we used the date again to generate a title like "February 16, 2021". + +```markdown +# {{date now "long"}} + +What did I do today? +``` + +We are now ready to write today's note! We don't need to set `--title` since the note's title is entirely generated by the template. + +```sh +$ zk new journal/daily +``` + +That is a bit of a mouthful for a command called every day. Would it not be better to just write `zk daily`? We can, by defining a [command alias](config-alias.md) in the [configuration file](config.md). + +```toml +[alias] +daily = 'zk new --no-input "$ZK_PATH/journal/daily"' +``` + +Let's unpack this alias: + +* `zk new` will refuse to overwrite notes. If you already created today's note, it will instead ask you if you wish to edit it. Using `--no-input` skips the prompt and edit the existing note right away. +* `$ZK_PATH` is set to the absolute path of the current [notebook](notebook.md) when running an alias. Using it allows you to run `zk daily` no matter where you are in the notebook folder hierarchy. +* We need to use double quotes around `$ZK_PATH`, otherwise it will not be expanded. + + diff --git a/docs/external-call.md b/docs/external-call.md new file mode 100644 index 0000000..7568c2d --- /dev/null +++ b/docs/external-call.md @@ -0,0 +1,15 @@ +# Call `zk` from other programs + +Calling `zk` from other programs can be useful in a number of situations, such as: + +* creating notes from your text editor using a custom shortcut +* creating a reference note from the text selected in your web browser +* automating periodical maintenance tasks on your [notebook](notebook.md) +* displaying the backlinks of a note in a GUI wrapper around `zk` + +The following options can be useful to make sure `zk` behaves properly in a background context: + + +* `--no-input` disables all user prompts and ignores `--interactive` +* `--quiet` reduces unnecessary output + diff --git a/docs/external-processing.md b/docs/external-processing.md new file mode 100644 index 0000000..8c5c558 --- /dev/null +++ b/docs/external-processing.md @@ -0,0 +1,62 @@ +# Send notes for processing by other programs + + + + +A great way to expand `zk` feature set is to explore a wealth of command-line tools available. You can use `zk`'s powerful [searching and filtering](note-filtering.md) capabilities to select notes before delegating further processing to other programs. + +## Process file paths + +Many programs expect file paths for input. You can interface with such program using the `path` list format and a space delimiter. + +```sh +$ zk list --format path --delimiter " " +``` + +If the file paths can contain spaces, you may want to quote manually the paths, using the `{{path}}` [template variable](template-format.md) instead: + +```sh +$ zk list --format "'{{path}}'" --delimiter " " +``` + +As always, this is such a useful [command alias](config-alias.md) to have: + +```toml +paths = "zk list --format \"'{{path}}'\" --quiet --delimiter ' ' $@" +``` + +Some programs – such as `xargs` – work better when file paths are separated by the ASCII NUL character (`\0`). In this case, you can use the `--delimiter0` (or `-0`) option. + +For example, this command prints the full Git history of the notes: + +```sh +$ zk list --format path --delimiter0 | xargs -0 git log --patch -- +``` + +### Feeding `zk` to itself + +Some `zk` options such as `--exclude` also take file paths for parameters. Let's increase their flexibility by nesting `zk` calls. In this case, the delimiter will be `,`. + +For example, this command lists the notes which are linked by at least one other note – so the notes which are *not* orphans. + +```sh +$ zk list --exclude "`zk list -q -f path -d "," --orphan`" +``` + +And this one finds the notes which are linked by at least one note in `journal/`. + +```sh +$ zk list --linked-by "`zk list -q -f path -d "," journal`" +``` + +## Process the content of a note + +If you want to directly transform the content instead, you may use the `raw-content` template variable, which will print the full content of the note file. + +In this particular case, we usually want to process only one note at a time. You can make sure that `zk list` will print only the first note from the result with `--limit 1` (or `-n1`). + +```sh +$ zk list --format {{raw-content}} --limit 1 +``` + + diff --git a/docs/future-proof.md b/docs/future-proof.md new file mode 100644 index 0000000..4384200 --- /dev/null +++ b/docs/future-proof.md @@ -0,0 +1,5 @@ +# A future-proof notebook + +`zk` is designed to be future-proof and rely on simple plain text formats such as Markdown. + +The shape of your [notebook](notebook.md) is entirely up to you, making `zk` flexible enough to be used in a variety of contexts. However, `zk` shines in a Zettelkasten-style notebook with many small interlinked notes. diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..d861b76 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,49 @@ +# Getting started with `zk` + +A short introduction showing how to use `zk`. + +## Create a new notebook + +Create a [notebook](notebook.md) to host your notes. You are free to organize your notebook as you want, adding subdirectories if needed. + +```sh +$ zk init my-notes +Initialized a notebook in my-notes + +$ cd my-notes +``` + +## Edit the configuration file + +To customize your experience with `zk`, you may want to edit the [user configuration file](config.md). + +```sh +$ vim .zk/config.toml +``` + +## Create your first notes + +Now you are ready to write your very first note. Pick a subject, [create a new note](note-creation.md) and write on! + +```sh +$ zk new --title "An interesting concept" +``` + +## Edit existing notes + +After some time, hopefully you will have enough notes to be lost in it. Use `zk`'s powerful [filtering capabilities](note-filtering.md) to find what you need. + +```sh +$ zk edit --interactive --match "recipe pizza -pineapple" + +# or with short flags +$ zk edit -i -m "recipe pizza -pineapple" +``` + +## List existing notes + +If you do not need to edit a note, use `zk list` instead to print context-sensitive results. + +```sh +$ zk list -m "recipe pizza -pineapple" +``` diff --git a/docs/neuron.dhall b/docs/neuron.dhall new file mode 100644 index 0000000..e69de29 diff --git a/docs/neuron.md b/docs/neuron.md new file mode 100644 index 0000000..62aeb0d --- /dev/null +++ b/docs/neuron.md @@ -0,0 +1,29 @@ +# Neuron + +[Neuron](https://neuron.zettel.page/) is a command-line app for managing a plain-text [Zettelkasten](https://zettelkasten.de/introduction/). + +While there is some overlap with `zk`'s features, both tools are actually useful when paired together: + +* `zk` has powerful [filtering](note-filtering.md) and [note generation](note-creation.md) capabilities +* Neuron shines with its static website generation + +Close integration with Neuron was thought through from the start when designing `zk`. For example, Neuron's [Folgezettel](https://neuron.zettel.page/folgezettel.html) syntax is supported: `[[[link]]]`, `#[[link]]` and `[[link]]#`. + + + +But you can make your [notebook](notebook.md) even more tightly integrated with Neuron by: + +* using the [same settings as Neuron](https://neuron.zettel.page/id.html) to generate the [note IDs](note-id.md) in the [note configuration](config-note.md) + ```toml + [note] + filename = "{{id}}" + id-charset = "hex" + id-length = 8 + id-case = "lower" + ``` +* adding [command aliases](config-alias.md) for your frequently used `neuron` commands + ```toml + [alias] + serve = "neuron gen -wS" + gen = "neuron gen -o public" + ``` diff --git a/docs/note-creation.md b/docs/note-creation.md new file mode 100644 index 0000000..49c5240 --- /dev/null +++ b/docs/note-creation.md @@ -0,0 +1,28 @@ +# Creating a new note + + + +You can add a new note to a [notebook](notebook.md) using `zk new --title "An interesting concept" []`. + +`zk` automatically generates a filename and initial content according to rules set in your [configuration file](config.md). These settings can be customized per [group of notes](config-group.md) in your notebook, as illustrated in [Maintaining a daily journal](daily-journal.md). + +By default, `zk new` will start [your editor](tool-editor.md) after creating the note. You can choose instead to print the absolute path to the note with `--print-path`, which is more useful for [automation](automation.md). + +## Search or create with a single command + +If you are not sure whether a note already exists for a particular subject, the "search or create" mode might be more appropriate than `zk new`. It is inspired by [Notational Velocity](https://notational.net/) and enables searching for an existing note or creating a new one in a single action. + +This option is available when running `zk edit --interactive`, which spawns [`fzf`](tool-fzf.md) to filter selected notes. From `fzf`, press `Ctrl-N` to create a new note using the current search query as title. + +## Create a note with initial content + +Initial content can be fed to the template through a standard input pipe, which will be expandable with the `{{content}}` [template variable](template-creation.md). + +For example, to use the content of the macOS clipboard as the initial content you can run: + +```sh +$ pbpaste | zk new +``` + + + diff --git a/docs/note-filtering.md b/docs/note-filtering.md new file mode 100644 index 0000000..e284ba8 --- /dev/null +++ b/docs/note-filtering.md @@ -0,0 +1,198 @@ +# Searching and filtering notes + +A few commands are built upon `zk`'s powerful note filtering capabilities, such as `edit` and `list`. They accept any option described here. + +## Filter by path + +All filtering commands take for unique positional argument a list of paths. When set, only the notes matching the given paths will be returned. + +You can use it to find all the notes in a directory. + +```sh +$ zk list journal/daily journal/weekly +``` + +Or specific notes. + +```sh +$ zk edit 200911172034-an-interesting-concept.md +``` + +It works fine with only a path prefix as well. This is useful when you have a [note ID](note-id.md) prefix, but not the full file path. + +```sh +$ zk edit 200911172034 +``` + +These rules apply to all the following options, when they expect a `` parameter. + +```sh +$ zk list --linking-to 200911172034 +``` + +You can also use a nested `zk` command to pre-filter paths to feed to an option with a `` argument. [See the `inline` command alias example](config-alias.md) for more explanation. + +```sh +# List the notes which have at least one link pointing to them (i.e. not orphans). +$ zk list --exclude "`zk inline --orphan`" + +# List the notes which are linked by at least one note from the journal/ directory. +$ zk list --linked-by "`zk inline journal`" +``` + + +## Search the title or body + +Use `--match ` (or `-m`) to search through the title and body of notes. + +The search is powered by a [full-text search](https://en.wikipedia.org/wiki/Full-text_search) database enabling near-instant results. Queries are not case-sensitive and terms are tokenized, which means that searching for `create` will also match `created` and `creating`. + +A syntax similar to Google Search is available for advanced search queries. + +### Combining terms + +By default, the search engine will find the notes containing all the terms in the query, in any order. + +``` +"tesla edison" +``` + +If you want to find the notes containing any or both of the terms, put `OR` (all caps) or a pipe `|` between them. + +``` +"tesla OR edison" +"tesla | edison" +``` + +Search for an exact phrase by surrounding it with double quotes. In this case, you will need to single quote the full query if you do not want to escape the double quotes. + +``` +'tesla "alternating current"' +``` + +To construct more complex queries, you can group sub-queries with parentheses. + +``` +"current (tesla OR edison)" +``` + +Finally, you can filter out results by excluding a term with `NOT` (all caps) or a `-` prefix. + +``` +"tesla NOT car" +"tesla -car" +``` + +### Search in specific fields + +If you want to search only in the title or body of notes, prefix a query with `title:` or `body:`. + +``` +"title: tesla" +"body: (tesla OR edison)" +``` + +### Prefix terms + +Match any term beginning with the given prefix with a wildcard `*`. + +``` +"edi*" +``` + +Prefixing a query with `^` will match notes whose title or body start with the following term. + +``` +"title: ^journal" +``` + +## Filter by creation or modification date + +To find notes created or modified on a specific day, use `--created ` and `--modified `. They accept a human-friendly date for argument. + +``` +--created yesterday +--created "last tuesday" +--modified "Feb 3" +``` + +You can filter by range instead, using `--created-before`, `--created-after`, `--modified-before` and `--modified-after`. + +``` +--created-before 10am +--modified-after 2021 +--created-after "last monday" --created-before yesterday +``` + +## Explore links + +You can use the following options to explore the web of links spanning your [notebook](notebook.md). + +`--linked-by ` (or `-l`) finds the notes linked by the given one, while `--linking-to ` (or `-L`) searches the notes having a link to it (also known as *backlinks*). + +``` +--linked-by 200911172034 +--linking-to 200911172034 +``` + +These options stop at the first level by default. But you can explore the whole web by adding the `--recursive` (or `-r`) option to find all the notes leading to (or from) a given note. If you feel overwhelmed, limit the distance between two notes with `--max-distance `. + +``` +--linked-by 200911172034 --recursive --max-distance 3 +``` + +Finally, it can be useful to see which notes have no links pointing to them at all. You can use the `--orphan` option for this. + +## Find related notes + +Part of writing a great notebook is to establish links between related notes. The `--related ` option can help by listing results having a linked note in common, but not yet connected to the note. + +``` +--related 200911172034 +``` + +## Exclude notes from the results + +To prevent certain notes from polluting the results, you can explicitly exclude them with `--exclude ` (or `-x`). This is particularly useful when you have a whole directory of notes to be ignored. + +``` +-x journal +``` + +## Limit the number of results + +If you are only interested into the first few notes, limit the number of results with `--limit ` (or `-n`). + +``` +--limit 20 +``` + +Using `-n1` is particularly common when you are expecting only a single result. + +## Interactive filtering + +A common search flow is to reduce the search scope using `zk`'s filtering options, before selecting manually the notes to process among them. This is especially useful with `zk edit` to avoid opening many unwanted notes with your editor. + +Use `--interactive` (or `-i`) to select filtered notes manually. The interactive selection is handled by [`fzf`](tool-fzf.md) which brings a powerful fuzzy matching search into the mix. + +## Sort the results + +After finding matching notes, it might be useful to sort them before processing. The `--sort ` (or `-s`) option is made for that. + +You can add a `+` (ascending) or `-` (descending) suffix to a sort criterion to customize the order. Each criterion has a sensible intrinsic order by default. + +``` +--sort path +--sort created+ +-st- (eq. --sort title-) +``` + +| Criterion | Shortcut | Order | Description | +|--------------|----------|-------|------------------------------------| +| `created` | `c` | `-` | Creation date | +| `modified` | `m` | `-` | Modification date | +| `path` | `p` | `+` | File path relative to the notebook | +| `title` | `t` | `+` | Note title | +| `random` | `r` | `+` | Order notes randomly | +| `word-count` | `wc` | `+` | Word count in the note | + diff --git a/docs/note-id.md b/docs/note-id.md new file mode 100644 index 0000000..32cb918 --- /dev/null +++ b/docs/note-id.md @@ -0,0 +1,20 @@ +# Note ID + +Each note is uniquely identified by its path relative to the [notebook](notebook.md)'s root. However, in some cases it is more convenient to refer to a "note ID", which is the unique part of its filename. For example, the note ID of the file `200911172034 An interesting concept.md` is `200911172034`. You could have several notes named "An interesting concept", but only one with the ID `200911172034`. + +The purpose of using a unique identifier in your note filenames is to create stable links between your notes, which will not break even if you change the title of the linked note. [See this reference for more information](https://zettelkasten.de/introduction/#the-unique-identifier). + +There are several flavors of note IDs and `zk` supports most of them. You can set it up in the [note configuration](config-note.md). + +## Random ID + +A random ID enables short and memorable unique identifiers. By default, `zk` is configured to generate random IDs of four alphanumeric characters. I found this to be the sweet spot between an easily memorable and usable ID and enough candidates. This default setting can generate 1 679 616 unique IDs. + +## Timestamp + +Another common ID is a timestamp in the `YYYYMMDDHHMM` shape. This is less readable than a short random ID, but has the added advantage of being sortable by creation date. However, I find this not so useful in practice. + +## Sequential IDs + +Sequential (incremented) IDs are currently not supported by `zk`. They get ugly very quickly when deleting outdated notes and have an irregular shape. + diff --git a/docs/notebook-housekeeping.md b/docs/notebook-housekeeping.md new file mode 100644 index 0000000..584e9ec --- /dev/null +++ b/docs/notebook-housekeeping.md @@ -0,0 +1,26 @@ +# Notebook housekeeping + +Tending to your notes does not only mean writing. You need to keep your [notebook](notebook.md) in great shape to make good use of it. For many maintenance tasks, `zk` can help! + +## Find related notes + +To surf your notebook with ease, make sure to link all related notes together. You can list notes which could be good candidates for a new link with the `--related` [filtering option](note-filtering.md). + +```sh +$ zk list --related note.md +``` + +This returns notes which are not connected to the given note, but with at least one linked note in common. + +## Find flimsy notes + +To find flimsy notes needing to be fleshed out, you can list the first few notes with the smallest word count from your notebook with the following command: + +```sh +$ zk list --format '{{word-count}}\t{{title}}' --sort word-count --limit 20 +4 Integration with fzf +5 Searching and filtering notes +63 Setting your default editor +86 Anatomy of a notebook +... +``` diff --git a/docs/notebook.md b/docs/notebook.md new file mode 100644 index 0000000..0644446 --- /dev/null +++ b/docs/notebook.md @@ -0,0 +1,15 @@ +# Notebook + +A *notebook* is a directory containing a collection of notes managed by `zk`. Notebooks cannot be nested, but you are free to organize your notes in subdirectories. + +To create a new notebook, simply run `zk init []`. + +Most `zk` commands are operating "Git-style" on the notebook containing the current working directory (or one of its parents). + +## Anatomy of a notebook + +Similarly to Git, a notebook is identified by the presence of a `.zk` directory at its root. This directory contains the only `zk`-specific files in your notebook: + +* `.zk/config.toml` is the user [configuration file](config.md) +* `.zk/templates/` contains [user templates](template.md) used when [creating new notes](note-creation.md) +* `.zk/notebook.db` is the SQLite database enabling [powerful search features](note-filtering.md). diff --git a/docs/style.md b/docs/style.md new file mode 100644 index 0000000..e8e5915 --- /dev/null +++ b/docs/style.md @@ -0,0 +1,32 @@ +# Styling + + + + + +`zk` supports a `{{style}}` [template helper](template.md) to format its output with colors and font decorations. + +Usage: `{{style "" ""}}` + +Multiple rules can be provided, separated by spaces. + +Examples: +``` +Inline: {{style "red bold" "One is never alone with a rubber duck."}} + +Block: +{{#style "underline"}} +For a moment, nothing happened. Then, after a second +or so, nothing continued to happen. +{{/style}} +``` + +## Styling rules + +* Decorations: `bold`, `italic`, `faint`, `underline`, `strikethrough`, `blink`, `reverse`, `hidden` +* Text color: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white` +* Text color (bright): `bright-black`, `bright-red`, `bright-green`, `bright-yellow`, `bright-blue`, `bright-magenta`, `bright-cyan`, `bright-white` +* Background color: `black-bg`, `red-bg`, `green-bg`, `yellow-bg`, `blue-bg`, `magenta-bg`, `cyan-bg`, `white-bg` +* Background color (bright): `bright-black-bg`, `bright-red-bg`, `bright-green-bg`, `bright-yellow-bg`, `bright-blue-bg`, `bright-magenta-bg`, `bright-cyan-bg`, `bright-white-bg` + + diff --git a/docs/template-creation.md b/docs/template-creation.md new file mode 100644 index 0000000..b21d110 --- /dev/null +++ b/docs/template-creation.md @@ -0,0 +1,23 @@ +# Template context when creating notes + + + +The following variables are available in the templates used when [creating new notes](note-creation.md) – both for the filename and the note content. + +| Variable | Type | Description | +|---------------|--------|---------------------------------------------------------------------------------------| +| `id` | string | Random ID generated for this note | +| `title` | string | Note title given to `--title` | +| `content` | string | Any text piped through the standard input | +| `dir` | string | Parent directory in the notebook | +| `extra.` | string | [Additional variables](config-extra.md) provided through the config file or `--extra` | +| `now` | date | Current date and time, useful when paired with [`{{date now}}`](template.md) | + +These additional variables are available only to the note content template, once the filename is generated. + +| Variable | Type | Description | +|-----------------|--------|----------------------------------------------------------------| +| `filename` | string | Filename generated for this note, including the file extension | +| `filename-stem` | string | Filename without the file extension | + + diff --git a/docs/template-format.md b/docs/template-format.md new file mode 100644 index 0000000..2313d27 --- /dev/null +++ b/docs/template-format.md @@ -0,0 +1,17 @@ +# Template context when formatting a note + +The following variables are available in the templates used when formatting notes, for example with `zk list --format