diff --git a/CHANGELOG.md b/CHANGELOG.md index c5d0e3c..a39018f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,16 +7,20 @@ All notable changes to this project will be documented in this file. ### Added * LSP: Support for external URLs with `documentLink`. -* New `{{get-date}}` template helper to obtain a date object from natural language. +* New `{{date}}` template helper to obtain a date object from natural language (contributed by [@zalegrala](https://github.com/mickael-menu/zk/pull/262)). ``` Get a relative date using natural language: - {{get-date "next week"}} + {{date "next week"}} Format a date returned by `get-date`: - {{date (get-date "monday") "timestamp"}} + {{format-date (date "monday") "timestamp"}} ``` * `zk list` now support multiple `--match`/`-m` flags, which allows to search for several tokens appearing in any order in the notes (contributed by [@rktjmp](https://github.com/mickael-menu/zk/pull/268)). +### Changed + +* **Breaking change:** The `{{date}}` template helper was renamed to `{{format-date}}`. You might need to update your configuration and templates. + ### Fixed * [#243](https://github.com/mickael-menu/zk/issues/243) LSP: Fixed finding backlink references for notes in a folder. diff --git a/docs/assets/media/alias.svg b/docs/assets/media/alias.svg index 4422111..76b7c71 100644 --- a/docs/assets/media/alias.svg +++ b/docs/assets/media/alias.svg @@ -98,5 +98,5 @@ - $ $ zk list --format "{{word-count}}\t{{title}}" --sort word-count --limit 10 $ zk list --format "{{word-count}}\t{{title}}" --sort word-count --limit 10 7 Interesting subject10 March 05, 202154 A future-proof notebook69 Setting your default editor88 Automating frequent tasks93 Setting your default pager101 Call zk from other programs106 zk – a plain text note-taking assistant117 Notebook122 StylingFound 10 notes$ vim .zk/config.toml 1 [note] 1 filename = "{{slug title}}" 2 template = "default.md" 3 4 [group.journal.note] 5 filename = "{{date now}}" 6 template = "journal.md" 7 8 [tool] 9 editor = "nvim" 10 fzf-preview = "bat -p --theme Nord --color always {-1}" 11 12 [alias] ~ docs/.zk/config.toml 12 [note] 11 filename = "{{slug title}}" 10 template = "default.md" 9 8 [group.journal.note] 7 filename = "{{date now}}" 5 4 [tool] 3 editor = "nvim" 2 fzf-preview = "bat -p --theme Nord --color always {-1}" 1 13 [alias] 13 [note] 12 filename = "{{slug title}}" 11 template = "default.md" 10 9 [group.journal.note] 8 filename = "{{date now}}" 7 template = "journal.md" 6 5 [tool] 4 editor = "nvim" 3 fzf-preview = "bat -p --theme Nord --color always {-1}" 2 1 [alias] 14 -- INSERT -- 14 wc = "zk list --quiet --format '{{word-count}}\t{{title}}' --sort word- count --limit 10 $@" count --limit 10 $@" count --limit 10 $@" : :q "docs/.zk/config.toml" $ zk wc $ zk wc $ zk wc --exclude journal --limit 5 $ zk wc --exclude journal --limit 5 $ - \ No newline at end of file + $ $ zk list --format "{{word-count}}\t{{title}}" --sort word-count --limit 10 $ zk list --format "{{word-count}}\t{{title}}" --sort word-count --limit 10 7 Interesting subject10 March 05, 202154 A future-proof notebook69 Setting your default editor88 Automating frequent tasks93 Setting your default pager101 Call zk from other programs106 zk – a plain text note-taking assistant117 Notebook122 StylingFound 10 notes$ vim .zk/config.toml 1 [note] 1 filename = "{{slug title}}" 2 template = "default.md" 3 4 [group.journal.note] 5 filename = "{{format-date now}}" 6 template = "journal.md" 7 8 [tool] 9 editor = "nvim" 10 fzf-preview = "bat -p --theme Nord --color always {-1}" 11 12 [alias] ~ docs/.zk/config.toml 12 [note] 11 filename = "{{slug title}}" 10 template = "default.md" 9 8 [group.journal.note] 7 filename = "{{format-date now}}" 5 4 [tool] 3 editor = "nvim" 2 fzf-preview = "bat -p --theme Nord --color always {-1}" 1 13 [alias] 13 [note] 12 filename = "{{slug title}}" 11 template = "default.md" 10 9 [group.journal.note] 8 filename = "{{format-date now}}" 7 template = "journal.md" 6 5 [tool] 4 editor = "nvim" 3 fzf-preview = "bat -p --theme Nord --color always {-1}" 2 1 [alias] 14 -- INSERT -- 14 wc = "zk list --quiet --format '{{word-count}}\t{{title}}' --sort word- count --limit 10 $@" count --limit 10 $@" count --limit 10 $@" : :q "docs/.zk/config.toml" $ zk wc $ zk wc $ zk wc --exclude journal --limit 5 $ zk wc --exclude journal --limit 5 $ + diff --git a/docs/assets/media/screencast.svg b/docs/assets/media/screencast.svg index f80fee4..c8dae04 100644 --- a/docs/assets/media/screencast.svg +++ b/docs/assets/media/screencast.svg @@ -145,5 +145,5 @@ - $ $ echo "I'm writing about it" | zk new --interactive --title "Interesting subject" 1 # Interesting subject 1 2 I'm writing about it 3 ~ docs/interesting-subject.md cwd: /Users/mickael/dvpts/mickael/zk 1 # Interesting subject cwd: /Users/mickael/dvpts/mickael/zk Z $ zk list --match "write subject" $ zk list --match "write subject" Interesting subject interesting-subject.md (just now) ‣ I'm writing about itGetting started with zk getting-started.md (2 weeks ago) ‣ …Pick a subject, [create a new note](note-creation.md) and write on! ```sh $ zk new --title "An interesting concept…Found 2 notes$ zk list --match "write OR subject" --limit 5 Extra user variables config-extra.md (2 weeks ago) ‣ …note-creation.md), for example: * expanding custom metadata (author, subject, etc.) * modifying a [template](template.md)'s output dynamically depending…Creating a new note note-creation.md (2 weeks ago) ‣ …sure whether a note already exists for a particular subject, the "search or create" mode might be more appropriate than…Maintaining a daily journal daily-journal.md (2 weeks ago): Found 5 notes$ zk new journal 1 # March 04, 2021 2 What did I do today? 3 * docs/journal/2021-03-04.md Z $ zk edit --interactive --exclude journal > ╭──────────────────────────────────────╮ 26/26 (0) │ │ Ctrl-E: create a note with the quer.. │ │> A future-proof notebook `zk` is de.. │ │ Automating frequent tasks `zk` was.. │ │ Call zk from other programs Callin.. │ │ Command aliases A command alias is.. │ │ Configuration file Each [notebook].. │ │ Creating a new note You can add a .. │ │ Extra user variables `zk` is opene.. │ │ Getting started with zk A short in.. │ │ Integration with fzf [`fzf`](https.. │ │ Interesting subject I'm writing ab.. │ │ Maintaining a daily journal Let's .. │ │ Neuron [Neuron](https://neuron.zet.. │ │ Note ID Each note is uniquely iden.. │ │ Note configuration The `[note]` se.. │ │ Note group A *group* is a named [c.. │ │ Notebook A *notebook* is a directo.. │ │ Notebook housekeeping Tending to y.. │ │ Searching and filtering notes A fe.. │ │ Send notes for processing by other .. │ │ Setting your default editor `zk` i.. │ │ Setting your default pager When `z.. │ │ Styling `zk` supports a `{{style}}.. ╰──────────────────────────────────────╯ 26/26 (0) # A future-proof notebook Ctrl-E: create a note with the quer.. > A future-proof notebook `zk` is de.. `zk` is designed to be future-proof Automating frequent tasks `zk` was.. and rely on simple plain text format Call zk from other programs Callin.. s such as Markdown. Command aliases A command alias is.. Configuration file Each [notebook].. The shape of your [notebook](noteboo Creating a new note You can add a .. k.md) is entirely up to you, making Extra user variables `zk` is opene.. Getting started with zk A short in.. Integration with fzf [`fzf`](https.. Interesting subject I'm writing ab.. Maintaining a daily journal Let's .. Neuron [Neuron](https://neuron.zet.. Note ID Each note is uniquely iden.. Note configuration The `[note]` se.. Note group A *group* is a named [c.. Notebook A *notebook* is a directo.. Notebook housekeeping Tending to y.. Searching and filtering notes A fe.. Send notes for processing by other .. Setting your default editor `zk` i.. Setting your default pager When `z.. > f ╭──────────────────────────────────────╮ 25/26 (0) # A future-proof notebook Call zk from other programs Callin.. and rely on simple plain text format Automating frequent tasks `zk` was.. s such as Markdown. Searching and filtering notes A fe.. k.md) is entirely up to you, making Template context when formatting a .. Template context when creating note.. zk – a plain text note-taking assis.. Styling `zk` supports a `{{style}}.. Template syntax `zk` uses the [Han.. Creating a new note You can add a .. ╰──────────────────────────────────────╯> fz ╭──────────────────────────────────────╮ 6/26 (0) # A future-proof notebook > Integration with fzf [`fzf`](https.. `zk` is designed to be future-proof Configuration file Each [notebook].. and rely on simple plain text format Notebook housekeeping Tending to y.. s such as Markdown. Creating a new note You can add a .. Command aliases A command alias is.. The shape of your [notebook](noteboo ╰──────────────────────────────────────╯ 6/26 (0) # Integration with `fzf` 1/25> Integration with fzf [`fzf`](https.. [`fzf`](https://github.com/junegunn/ Configuration file Each [notebook].. fzf) is an awesome and versatile fuz Notebook housekeeping Tending to y.. zy finder powering `zk`'s [interacti Creating a new note You can add a .. ve filtering mode](note-filtering.md Searching and filtering notes A fe.. Besides the standard [`fzf` configur ation options](https://github.com/ju negunn/fzf) documented on its websit e, `zk` offers additional options yo u can set in the `[tool]` [configura tion section](config.md). If you wish to customize more of `fz f` behavior, [please post a feature request](https://github.com/mickael- menu/zk/issues). ## Preview command You can customize the command used t o preview a note with `fzf-preview` 1 # Integration with fzf 2 `fzf` is an awesome and versatile fuzzy finder powering zk's interactive filtering mode . 4 Besides the standard `fzf` configuration options documented on its website, zk offers additional options you can set in the [tool] configuration section. 5 6 If you wish to customize more of fzf behavior, please post a feature request. 7 8 ## Preview command 9 10 You can customize the command used to preview a note with fzf-preview. The special placeholder {-1} will be expanded to the note file path. 11 12 By default, zk uses cat for preview, which is a bit boring. A much better option would be to use `bat` which supports syntax highlighting. 13 14 ```toml docs/tool-fzf.md $ zk edit --interactive --created-after "one week ago" 4/4 (0) │ │ March 04, 2021 What did I do today.. │ │ │ │ 4/4 (0) # A future-proof notebook Interesting subject I'm writing ab.. and rely on simple plain text format March 04, 2021 What did I do today.. s such as Markdown. The shape of your [notebook](noteboo k.md) is entirely up to you, making > N ╭──────────────────────────────────────╮ 1/4 (0) # A future-proof notebook > Notebook housekeeping Tending to y.. `zk` is designed to be future-proof and rely on simple plain text format s such as Markdown. 1/4 (0) # Notebook housekeeping 1/26> Notebook housekeeping Tending to y.. Tending to your notes does not only mean writing. You need to keep your ## Find related notes To surf your notebook with ease, mak e sure to link all related notes tog ether. You can list notes which coul d be good candidates for a new link with the `--related` [filtering opti on](note-filtering.md). ```sh $ zk list --related note.md ``` This returns notes which are not con nected to the given note, but with a t least one linked note in common. ## Find flimsy notes > Ne ╭──────────────────────────────────────╮ 0/4 (0) > New ╭──────────────────────────────────────╮> New n ╭──────────────────────────────────────╮> New no ╭──────────────────────────────────────╮> New not ╭──────────────────────────────────────╮> New note ╭──────────────────────────────────────╮ 1 # New note 2 docs/new-note.md > New note% $ zk list --link-to note-id.md $ zk list --link-to note-id.md Neuron neuron.md (2 weeks ago) ‣ 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) Note configuration config-note.md (2 weeks ago) ‣ Characters set used to [generate random IDs](note-id.md). ‣ Just a [random ID](note-id.md), simple and elegant. Searching and filtering notes note-filtering.md (2 weeks ago) ‣ 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. Found 3 notes $ zk list --link-to note-id.md --format oneline $ zk list --link-to note-id.md --format oneline Note configuration config-note.md (2 weeks ago)Searching and filtering notes note-filtering.md (2 weeks ago)Found 3 notes$ zk list --link-to note-id.md --format oneline --recursive $ zk list --link-to note-id.md --format oneline --recursive --max-distance 2 $ zk list --link-to note-id.md --format oneline --recursive --max-distance 2 Command aliases config-alias.md (2 weeks ago)Configuration file config.md (3 weeks ago)Integration with fzf tool-fzf.md (2 weeks ago)Neuron neuron.md (2 weeks ago)Note group config-group.md (2 weeks ago)Notebook notebook.md (2 weeks ago)Notebook housekeeping notebook-housekeeping.md (5 days ago)Send notes for processing by other programs external-processing.md (2 weeks ago)Template syntax template.md (2 weeks ago)zk – a plain text note-taking assistant README.md (3 weeks ago)Found 13 notes$ zk list --format "{{word-count}}\t{{title}}" --sort word-count --limit 10 $ zk list --format "{{word-count}}\t{{title}}" --sort word-count --limit 10 3 New note7 Interesting subject10 March 04, 202154 A future-proof notebook69 Setting your default editor88 Automating frequent tasks93 Setting your default pager101 Call zk from other programs106 zk – a plain text note-taking assistant117 NotebookFound 10 notes$ vim .zk/config.toml 1 [note] 1 filename = "{{slug title}}" 2 template = "default.md" 4 [group.journal.note] 5 filename = "{{date now}}" 6 template = "journal.md" 8 [tool] 9 editor = "nvim" 10 fzf-preview = "bat -p --theme Nord --color always {-1}" 12 [alias] docs/.zk/config.toml 12 [note] 11 filename = "{{slug title}}" 10 template = "default.md" 8 [group.journal.note] 7 filename = "{{date now}}" 4 [tool] 3 editor = "nvim" 2 fzf-preview = "bat -p --theme Nord --color always {-1}" 13 [alias] 13 [note] 12 filename = "{{slug title}}" 11 template = "default.md" 10 9 [group.journal.note] 8 filename = "{{date now}}" 7 template = "journal.md" 6 5 [tool] 4 editor = "nvim" 3 fzf-preview = "bat -p --theme Nord --color always {-1}" 1 [alias] 14 -- INSERT -- 14 wc = "zk list --quiet --format '{{word-count}}\t{{title}}' --sort word- count --limit 10 $@" count --limit 10 $@" count --limit 10 $@" "docs/.zk/config.toml" $ zk wc $ zk wc $ zk wc --exclude journal --limit 5 $ zk wc --exclude journal --limit 5 $ + $ $ echo "I'm writing about it" | zk new --interactive --title "Interesting subject" 1 # Interesting subject 1 2 I'm writing about it 3 ~ docs/interesting-subject.md cwd: /Users/mickael/dvpts/mickael/zk 1 # Interesting subject cwd: /Users/mickael/dvpts/mickael/zk Z $ zk list --match "write subject" $ zk list --match "write subject" Interesting subject interesting-subject.md (just now) ‣ I'm writing about itGetting started with zk getting-started.md (2 weeks ago) ‣ …Pick a subject, [create a new note](note-creation.md) and write on! ```sh $ zk new --title "An interesting concept…Found 2 notes$ zk list --match "write OR subject" --limit 5 Extra user variables config-extra.md (2 weeks ago) ‣ …note-creation.md), for example: * expanding custom metadata (author, subject, etc.) * modifying a [template](template.md)'s output dynamically depending…Creating a new note note-creation.md (2 weeks ago) ‣ …sure whether a note already exists for a particular subject, the "search or create" mode might be more appropriate than…Maintaining a daily journal daily-journal.md (2 weeks ago): Found 5 notes$ zk new journal 1 # March 04, 2021 2 What did I do today? 3 * docs/journal/2021-03-04.md Z $ zk edit --interactive --exclude journal > ╭──────────────────────────────────────╮ 26/26 (0) │ │ Ctrl-E: create a note with the quer.. │ │> A future-proof notebook `zk` is de.. │ │ Automating frequent tasks `zk` was.. │ │ Call zk from other programs Callin.. │ │ Command aliases A command alias is.. │ │ Configuration file Each [notebook].. │ │ Creating a new note You can add a .. │ │ Extra user variables `zk` is opene.. │ │ Getting started with zk A short in.. │ │ Integration with fzf [`fzf`](https.. │ │ Interesting subject I'm writing ab.. │ │ Maintaining a daily journal Let's .. │ │ Neuron [Neuron](https://neuron.zet.. │ │ Note ID Each note is uniquely iden.. │ │ Note configuration The `[note]` se.. │ │ Note group A *group* is a named [c.. │ │ Notebook A *notebook* is a directo.. │ │ Notebook housekeeping Tending to y.. │ │ Searching and filtering notes A fe.. │ │ Send notes for processing by other .. │ │ Setting your default editor `zk` i.. │ │ Setting your default pager When `z.. │ │ Styling `zk` supports a `{{style}}.. ╰──────────────────────────────────────╯ 26/26 (0) # A future-proof notebook Ctrl-E: create a note with the quer.. > A future-proof notebook `zk` is de.. `zk` is designed to be future-proof Automating frequent tasks `zk` was.. and rely on simple plain text format Call zk from other programs Callin.. s such as Markdown. Command aliases A command alias is.. Configuration file Each [notebook].. The shape of your [notebook](noteboo Creating a new note You can add a .. k.md) is entirely up to you, making Extra user variables `zk` is opene.. Getting started with zk A short in.. Integration with fzf [`fzf`](https.. Interesting subject I'm writing ab.. Maintaining a daily journal Let's .. Neuron [Neuron](https://neuron.zet.. Note ID Each note is uniquely iden.. Note configuration The `[note]` se.. Note group A *group* is a named [c.. Notebook A *notebook* is a directo.. Notebook housekeeping Tending to y.. Searching and filtering notes A fe.. Send notes for processing by other .. Setting your default editor `zk` i.. Setting your default pager When `z.. > f ╭──────────────────────────────────────╮ 25/26 (0) # A future-proof notebook Call zk from other programs Callin.. and rely on simple plain text format Automating frequent tasks `zk` was.. s such as Markdown. Searching and filtering notes A fe.. k.md) is entirely up to you, making Template context when formatting a .. Template context when creating note.. zk – a plain text note-taking assis.. Styling `zk` supports a `{{style}}.. Template syntax `zk` uses the [Han.. Creating a new note You can add a .. ╰──────────────────────────────────────╯> fz ╭──────────────────────────────────────╮ 6/26 (0) # A future-proof notebook > Integration with fzf [`fzf`](https.. `zk` is designed to be future-proof Configuration file Each [notebook].. and rely on simple plain text format Notebook housekeeping Tending to y.. s such as Markdown. Creating a new note You can add a .. Command aliases A command alias is.. The shape of your [notebook](noteboo ╰──────────────────────────────────────╯ 6/26 (0) # Integration with `fzf` 1/25> Integration with fzf [`fzf`](https.. [`fzf`](https://github.com/junegunn/ Configuration file Each [notebook].. fzf) is an awesome and versatile fuz Notebook housekeeping Tending to y.. zy finder powering `zk`'s [interacti Creating a new note You can add a .. ve filtering mode](note-filtering.md Searching and filtering notes A fe.. Besides the standard [`fzf` configur ation options](https://github.com/ju negunn/fzf) documented on its websit e, `zk` offers additional options yo u can set in the `[tool]` [configura tion section](config.md). If you wish to customize more of `fz f` behavior, [please post a feature request](https://github.com/mickael- menu/zk/issues). ## Preview command You can customize the command used t o preview a note with `fzf-preview` 1 # Integration with fzf 2 `fzf` is an awesome and versatile fuzzy finder powering zk's interactive filtering mode . 4 Besides the standard `fzf` configuration options documented on its website, zk offers additional options you can set in the [tool] configuration section. 5 6 If you wish to customize more of fzf behavior, please post a feature request. 7 8 ## Preview command 9 10 You can customize the command used to preview a note with fzf-preview. The special placeholder {-1} will be expanded to the note file path. 11 12 By default, zk uses cat for preview, which is a bit boring. A much better option would be to use `bat` which supports syntax highlighting. 13 14 ```toml docs/tool-fzf.md $ zk edit --interactive --created-after "one week ago" 4/4 (0) │ │ March 04, 2021 What did I do today.. │ │ │ │ 4/4 (0) # A future-proof notebook Interesting subject I'm writing ab.. and rely on simple plain text format March 04, 2021 What did I do today.. s such as Markdown. The shape of your [notebook](noteboo k.md) is entirely up to you, making > N ╭──────────────────────────────────────╮ 1/4 (0) # A future-proof notebook > Notebook housekeeping Tending to y.. `zk` is designed to be future-proof and rely on simple plain text format s such as Markdown. 1/4 (0) # Notebook housekeeping 1/26> Notebook housekeeping Tending to y.. Tending to your notes does not only mean writing. You need to keep your ## Find related notes To surf your notebook with ease, mak e sure to link all related notes tog ether. You can list notes which coul d be good candidates for a new link with the `--related` [filtering opti on](note-filtering.md). ```sh $ zk list --related note.md ``` This returns notes which are not con nected to the given note, but with a t least one linked note in common. ## Find flimsy notes > Ne ╭──────────────────────────────────────╮ 0/4 (0) > New ╭──────────────────────────────────────╮> New n ╭──────────────────────────────────────╮> New no ╭──────────────────────────────────────╮> New not ╭──────────────────────────────────────╮> New note ╭──────────────────────────────────────╮ 1 # New note 2 docs/new-note.md > New note% $ zk list --link-to note-id.md $ zk list --link-to note-id.md Neuron neuron.md (2 weeks ago) ‣ 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) Note configuration config-note.md (2 weeks ago) ‣ Characters set used to [generate random IDs](note-id.md). ‣ Just a [random ID](note-id.md), simple and elegant. Searching and filtering notes note-filtering.md (2 weeks ago) ‣ 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. Found 3 notes $ zk list --link-to note-id.md --format oneline $ zk list --link-to note-id.md --format oneline Note configuration config-note.md (2 weeks ago)Searching and filtering notes note-filtering.md (2 weeks ago)Found 3 notes$ zk list --link-to note-id.md --format oneline --recursive $ zk list --link-to note-id.md --format oneline --recursive --max-distance 2 $ zk list --link-to note-id.md --format oneline --recursive --max-distance 2 Command aliases config-alias.md (2 weeks ago)Configuration file config.md (3 weeks ago)Integration with fzf tool-fzf.md (2 weeks ago)Neuron neuron.md (2 weeks ago)Note group config-group.md (2 weeks ago)Notebook notebook.md (2 weeks ago)Notebook housekeeping notebook-housekeeping.md (5 days ago)Send notes for processing by other programs external-processing.md (2 weeks ago)Template syntax template.md (2 weeks ago)zk – a plain text note-taking assistant README.md (3 weeks ago)Found 13 notes$ zk list --format "{{word-count}}\t{{title}}" --sort word-count --limit 10 $ zk list --format "{{word-count}}\t{{title}}" --sort word-count --limit 10 3 New note7 Interesting subject10 March 04, 202154 A future-proof notebook69 Setting your default editor88 Automating frequent tasks93 Setting your default pager101 Call zk from other programs106 zk – a plain text note-taking assistant117 NotebookFound 10 notes$ vim .zk/config.toml 1 [note] 1 filename = "{{slug title}}" 2 template = "default.md" 4 [group.journal.note] 5 filename = "{{format-date now}}" 6 template = "journal.md" 8 [tool] 9 editor = "nvim" 10 fzf-preview = "bat -p --theme Nord --color always {-1}" 12 [alias] docs/.zk/config.toml 12 [note] 11 filename = "{{slug title}}" 10 template = "default.md" 8 [group.journal.note] 7 filename = "{{format-date now}}" 4 [tool] 3 editor = "nvim" 2 fzf-preview = "bat -p --theme Nord --color always {-1}" 13 [alias] 13 [note] 12 filename = "{{slug title}}" 11 template = "default.md" 10 9 [group.journal.note] 8 filename = "{{format-date now}}" 7 template = "journal.md" 6 5 [tool] 4 editor = "nvim" 3 fzf-preview = "bat -p --theme Nord --color always {-1}" 1 [alias] 14 -- INSERT -- 14 wc = "zk list --quiet --format '{{word-count}}\t{{title}}' --sort word- count --limit 10 $@" count --limit 10 $@" count --limit 10 $@" "docs/.zk/config.toml" $ zk wc $ zk wc $ zk wc --exclude journal --limit 5 $ zk wc --exclude journal --limit 5 $ diff --git a/docs/config-group.md b/docs/config-group.md index 7858a67..23d5630 100644 --- a/docs/config-group.md +++ b/docs/config-group.md @@ -34,7 +34,7 @@ You can override the global [note configuration](config-note.md) and [extra user ```toml [group.journal.note] -filename = "{{date now}}" +filename = "{{format-date now}}" template = "journal.md" [group.journal.extra] diff --git a/docs/config-note.md b/docs/config-note.md index 2477f9f..3f740a6 100644 --- a/docs/config-note.md +++ b/docs/config-note.md @@ -48,10 +48,10 @@ Here are some common filename patterns you may want to use: * 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` +* `{{format-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` +* `{{format-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` +* `{{format-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 index fd5c03a..a8cff1c 100644 --- a/docs/config.md +++ b/docs/config.md @@ -67,7 +67,7 @@ author = "Mickaël" paths = ["journal/weekly", "journal/daily"] [dir.journal.note] -filename = "{{date now}}" +filename = "{{format-date now}}" # MARKDOWN SETTINGS @@ -114,4 +114,4 @@ lucky = "zk list --quiet --format full --sort random --limit 1" wiki-title = "hint" # Warn for dead links between notes. dead-link = "error" -``` \ No newline at end of file +``` diff --git a/docs/daily-journal.md b/docs/daily-journal.md index 517e5ef..34d8f30 100644 --- a/docs/daily-journal.md +++ b/docs/daily-journal.md @@ -2,7 +2,7 @@ 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. +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 `{{format-date}}` helper. ```toml [group.daily] @@ -10,8 +10,8 @@ First, create a `group` entry in the [configuration file](config.md) to set the 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'}}" +# %Y-%m-%d is actually the default format, so you could use {{format-date now}} instead. +filename = "{{format-date now '%Y-%m-%d'}}" extension = "md" template = "daily.md" ``` @@ -19,7 +19,7 @@ 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"}} +# {{format-date now "long"}} What did I do today? ``` diff --git a/docs/template-creation.md b/docs/template-creation.md index 7bf74c5..ce6c829 100644 --- a/docs/template-creation.md +++ b/docs/template-creation.md @@ -9,7 +9,7 @@ The following variables are available in the templates used when [creating new n | `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) | +| `now` | date | Current date and time, useful when paired with [`{{format-date now}}`](template.md) | | `env` | map | Dictionary of case-sensitive environment variables, e.g. `{{env.PATH}}`. | These additional variables are available only to the note content template, once the filename is generated. diff --git a/docs/template.md b/docs/template.md index 732e788..3a21028 100644 --- a/docs/template.md +++ b/docs/template.md @@ -38,13 +38,25 @@ The `{{concat s1 s2}}` helper concatenates two strings together. For example `{{ * `{{substring 'A full quote' 2 4}}` outputs `full` * `{{substring 'A full quote' -5 5}` outputs `quote` -### Date helper +### Date helpers -The `{{date}}` helper formats the given date for display. +#### Date from natural string helper + +You can get a date object from a natural human date (e.g. `tomorrow`, `2 weeks ago`, `2022-03-24`) using the `{{date}}` helper. It is most useful when paired with the `{{format-date}}` helper. + +``` +{{date "tomorrow"}} + +{{format-date (date "last week") "timestamp"}} +``` + +#### Date formatting helper + +The `{{format-date}}` helper formats the given date for display. Template contexts usually provide a `now` variable which can be used to print the current date. -The default format output by `{{date }}` looks like `2009-11-17`, but you can choose a different format by providing a second argument, e.g. `{{date now "medium"}}`. +The default format output by `{{format-date }}` looks like `2009-11-17`, but you can choose a different format by providing a second argument, e.g. `{{format-date now "medium"}}`. | Format | Output | Notes | |------------------|----------------------------|--------------------------------------------------| @@ -58,7 +70,7 @@ The default format output by `{{date }}` looks like `2009-11-17`, but | `timestamp-unix` | 1258490098 | Number of seconds since January 1, 1970 | | `elapsed` | 12 years ago | Time elapsed since then in human-friendly format | -If none of the provided formats suit you, you can use a custom format using `strftime`-style placeholders, e.g. `{{date now "%m-%d-%Y"}}`. See `man strftime` for a list of placeholders. +If none of the provided formats suit you, you can use a custom format using `strftime`-style placeholders, e.g. `{{format-date now "%m-%d-%Y"}}`. See `man strftime` for a list of placeholders. ### Slug helper diff --git a/internal/adapter/handlebars/handlebars.go b/internal/adapter/handlebars/handlebars.go index 22e361f..7822864 100644 --- a/internal/adapter/handlebars/handlebars.go +++ b/internal/adapter/handlebars/handlebars.go @@ -16,7 +16,7 @@ import ( func Init(supportsUTF8 bool, logger util.Logger) { helpers.RegisterConcat() helpers.RegisterDate(logger) - helpers.RegisterGetDate(logger) + helpers.RegisterFormatDate(logger) helpers.RegisterJoin() helpers.RegisterJSON(logger) helpers.RegisterList(supportsUTF8) diff --git a/internal/adapter/handlebars/handlebars_test.go b/internal/adapter/handlebars/handlebars_test.go index a30bdf8..a7846a8 100644 --- a/internal/adapter/handlebars/handlebars_test.go +++ b/internal/adapter/handlebars/handlebars_test.go @@ -226,25 +226,25 @@ func TestSlugHelper(t *testing.T) { ) } -func TestDateHelper(t *testing.T) { +func TestFormatDateHelper(t *testing.T) { context := map[string]interface{}{"now": time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)} - testString(t, "{{date now}}", context, "2009-11-17") - testString(t, "{{date now 'short'}}", context, "11/17/2009") - testString(t, "{{date now 'medium'}}", context, "Nov 17, 2009") - testString(t, "{{date now 'long'}}", context, "November 17, 2009") - testString(t, "{{date now 'full'}}", context, "Tuesday, November 17, 2009") - testString(t, "{{date now 'year'}}", context, "2009") - testString(t, "{{date now 'time'}}", context, "20:34") - testString(t, "{{date now 'timestamp'}}", context, "200911172034") - testString(t, "{{date now 'timestamp-unix'}}", context, "1258490098") - testString(t, "{{date now 'cust: %Y-%m'}}", context, "cust: 2009-11") - testString(t, "{{date now 'elapsed'}}", context, "14 years ago") + testString(t, "{{format-date now}}", context, "2009-11-17") + testString(t, "{{format-date now 'short'}}", context, "11/17/2009") + testString(t, "{{format-date now 'medium'}}", context, "Nov 17, 2009") + testString(t, "{{format-date now 'long'}}", context, "November 17, 2009") + testString(t, "{{format-date now 'full'}}", context, "Tuesday, November 17, 2009") + testString(t, "{{format-date now 'year'}}", context, "2009") + testString(t, "{{format-date now 'time'}}", context, "20:34") + testString(t, "{{format-date now 'timestamp'}}", context, "200911172034") + testString(t, "{{format-date now 'timestamp-unix'}}", context, "1258490098") + testString(t, "{{format-date now 'cust: %Y-%m'}}", context, "cust: 2009-11") + testString(t, "{{format-date now 'elapsed'}}", context, "14 years ago") } -func TestGetDateHelper(t *testing.T) { +func TestDateHelper(t *testing.T) { context := map[string]interface{}{"now": time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)} localOffsetAndTZ := time.Now().Format("-0700 MST") - testString(t, "{{get-date \"2009-11-17T20:34:58\"}}", context, "2009-11-17 20:34:58 "+localOffsetAndTZ) + testString(t, "{{date \"2009-11-17T20:34:58\"}}", context, "2009-11-17 20:34:58 "+localOffsetAndTZ) } func TestShellHelper(t *testing.T) { diff --git a/internal/adapter/handlebars/helpers/date.go b/internal/adapter/handlebars/helpers/date.go index 136de89..cc64be4 100644 --- a/internal/adapter/handlebars/helpers/date.go +++ b/internal/adapter/handlebars/helpers/date.go @@ -1,24 +1,51 @@ package helpers import ( + "os" "time" "github.com/aymerick/raymond" "github.com/lestrrat-go/strftime" "github.com/mickael-menu/zk/internal/util" + dateutil "github.com/mickael-menu/zk/internal/util/date" + "github.com/pkg/errors" "github.com/rvflash/elapsed" ) -// RegisterDate registers the {{date}} template helpers which format a given date. +// RegisterDate registers the {{date}} template helper to use the `naturaldate` package to generate time.Time based on language strings. +// This can be used in combination with the `format-date` helper to generate dates in the user's language. +// {{format-date (date "last week") "timestamp"}} +func RegisterDate(logger util.Logger) { + raymond.RegisterHelper("date", func(arg1 interface{}, arg2 interface{}) time.Time { + var t time.Time + switch date := arg1.(type) { + case string: + t, err := dateutil.TimeFromNatural(date) + if err != nil { + logger.Err(errors.Wrap(err, "the {{date}} template helper failed to parse the date")) + } + return t + case time.Time: + logger.Println("the {{date}} template helper was renamed to {{format-date}}, please update your configuration") + os.Exit(1) + return t + default: + logger.Println("the {{date}} template helper expects a natural human date as a string for its only argument") + return t + } + }) +} + +// RegisterFormatDate registers the {{format-date}} template helpers which format a given date. // // It supports various styles: short, medium, long, full, year, time, // timestamp, timestamp-unix or a custom strftime format. // -// {{date now}} -> 2009-11-17 -// {{date now "medium"}} -> Nov 17, 2009 -// {{date now "%Y-%m"}} -> 2009-11 -func RegisterDate(logger util.Logger) { - raymond.RegisterHelper("date", func(date time.Time, arg interface{}) string { +// {{format-date now}} -> 2009-11-17 +// {{format-date now "medium"}} -> Nov 17, 2009 +// {{format-date now "%Y-%m"}} -> 2009-11 +func RegisterFormatDate(logger util.Logger) { + raymond.RegisterHelper("format-date", func(date time.Time, arg interface{}) string { format := "%Y-%m-%d" if arg, ok := arg.(string); ok { @@ -31,7 +58,7 @@ func RegisterDate(logger util.Logger) { } else { res, err := strftime.Format(format, date, strftime.WithUnixSeconds('s')) if err != nil { - logger.Printf("the {{date}} template helper failed to format the date: %v", err) + logger.Printf("the {{format-date}} template helper failed to format the date: %v", err) return "" } return res diff --git a/internal/adapter/handlebars/helpers/getdate.go b/internal/adapter/handlebars/helpers/getdate.go deleted file mode 100644 index 023f44b..0000000 --- a/internal/adapter/handlebars/helpers/getdate.go +++ /dev/null @@ -1,23 +0,0 @@ -package helpers - -import ( - "time" - - "github.com/aymerick/raymond" - "github.com/mickael-menu/zk/internal/util" - dateutil "github.com/mickael-menu/zk/internal/util/date" - "github.com/pkg/errors" -) - -// RegisterGetDate registers the {{getdate}} template helper to use the `naturaldate` package to generate time.Time based on language strings. -// This can be used in combination with the `date` helper to generate dates in the user's language. -// {{date (get-date "last week") "timestamp"}} -func RegisterGetDate(logger util.Logger) { - raymond.RegisterHelper("get-date", func(natural string) time.Time { - date, err := dateutil.TimeFromNatural(natural) - if err != nil { - logger.Err(errors.Wrap(err, "the {{get-date}} template helper failed to parse the date")) - } - return date - }) -} diff --git a/internal/cli/cmd/list.go b/internal/cli/cmd/list.go index 444e704..7b8d43f 100644 --- a/internal/cli/cmd/list.go +++ b/internal/cli/cmd/list.go @@ -155,26 +155,26 @@ var defaultNoteFormats = map[string]string{ "path": `{{path}}`, "link": `{{link}}`, - "oneline": `{{style "title" title}} {{style "path" path}} ({{date created "elapsed"}})`, + "oneline": `{{style "title" title}} {{style "path" path}} ({{format-date created "elapsed"}})`, - "short": `{{style "title" title}} {{style "path" path}} ({{date created "elapsed"}}) + "short": `{{style "title" title}} {{style "path" path}} ({{format-date created "elapsed"}}) {{list snippets}}`, "medium": `{{style "title" title}} {{style "path" path}} -Created: {{date created "short"}} +Created: {{format-date created "short"}} {{list snippets}}`, "long": `{{style "title" title}} {{style "path" path}} -Created: {{date created "short"}} -Modified: {{date modified "short"}} +Created: {{format-date created "short"}} +Modified: {{format-date modified "short"}} {{list snippets}}`, "full": `{{style "title" title}} {{style "path" path}} -Created: {{date created "short"}} -Modified: {{date modified "short"}} +Created: {{format-date created "short"}} +Modified: {{format-date modified "short"}} Tags: {{join tags ", "}} {{prepend " " body}} diff --git a/internal/cli/cmd/list_test.go b/internal/cli/cmd/list_test.go index caad91d..3daef79 100644 --- a/internal/cli/cmd/list_test.go +++ b/internal/cli/cmd/list_test.go @@ -8,7 +8,7 @@ import ( func TestListFormatDefault(t *testing.T) { cmd := List{} - assert.Equal(t, cmd.noteTemplate(), `{{style "title" title}} {{style "path" path}} ({{date created "elapsed"}}) + assert.Equal(t, cmd.noteTemplate(), `{{style "title" title}} {{style "path" path}} ({{format-date created "elapsed"}}) {{list snippets}}`) } @@ -25,26 +25,26 @@ func TestListFormatPredefined(t *testing.T) { test("path", `{{path}}`) test("link", `{{link}}`) - test("oneline", `{{style "title" title}} {{style "path" path}} ({{date created "elapsed"}})`) + test("oneline", `{{style "title" title}} {{style "path" path}} ({{format-date created "elapsed"}})`) - test("short", `{{style "title" title}} {{style "path" path}} ({{date created "elapsed"}}) + test("short", `{{style "title" title}} {{style "path" path}} ({{format-date created "elapsed"}}) {{list snippets}}`) test("medium", `{{style "title" title}} {{style "path" path}} -Created: {{date created "short"}} +Created: {{format-date created "short"}} {{list snippets}}`) test("long", `{{style "title" title}} {{style "path" path}} -Created: {{date created "short"}} -Modified: {{date modified "short"}} +Created: {{format-date created "short"}} +Modified: {{format-date modified "short"}} {{list snippets}}`) test("full", `{{style "title" title}} {{style "path" path}} -Created: {{date created "short"}} -Modified: {{date modified "short"}} +Created: {{format-date created "short"}} +Modified: {{format-date modified "short"}} Tags: {{join tags ", "}} {{prepend " " body}} diff --git a/internal/core/notebook_store.go b/internal/core/notebook_store.go index 5cd4186..e258057 100644 --- a/internal/core/notebook_store.go +++ b/internal/core/notebook_store.go @@ -152,7 +152,7 @@ func (ns *NotebookStore) locateNotebook(path string) (string, error) { var locate func(string) (string, error) locate = func(currentPath string) (string, error) { - // For Windows, the root dir may end with volume name, e.g. E:\\ + // For Windows, the root dir may end with volume name, e.g. E:\\ if currentPath == "/" || currentPath == filepath.VolumeName(currentPath)+"\\" || currentPath == "." { return "", ErrNotebookNotFound(path) } @@ -251,7 +251,7 @@ template = "default.md" #[group.""] #paths = ["", ""] #[group."".note] -#filename = "\{{date now}}" +#filename = "\{{format-date now}}" #[group."".extra] #key = "value" diff --git a/tests/cmd-init-defaults.tesh b/tests/cmd-init-defaults.tesh index b20af5a..8a2c853 100644 --- a/tests/cmd-init-defaults.tesh +++ b/tests/cmd-init-defaults.tesh @@ -77,7 +77,7 @@ $ cat .zk/config.toml >#[group.""] >#paths = ["", ""] >#[group."".note] ->#filename = "\{{date now}}" +>#filename = "\{{format-date now}}" >#[group."".extra] >#key = "value" > diff --git a/tests/config-note-filename.tesh b/tests/config-note-filename.tesh index c336ec7..9fed3d3 100644 --- a/tests/config-note-filename.tesh +++ b/tests/config-note-filename.tesh @@ -5,7 +5,7 @@ $ zk new --dry-run 2>{{working-dir}}/{{match "[a-z0-9]{4}"}}.md # Set a custom filename. -$ echo "[note]\n filename = '\{{slug title}} - \{{date now \"%m-%d\"}}'" > .zk/config.toml +$ echo "[note]\n filename = '\{{slug title}} - \{{format-date now \"%m-%d\"}}'" > .zk/config.toml $ zk new --title "A new note" --date "January 5th" --dry-run 2>{{working-dir}}/a-new-note - 01-05.md @@ -16,7 +16,7 @@ $ zk new --title "A new note" --date "January 5th" --dry-run # Test the filename Handlebars variables. $ mkdir "a dir" -$ echo "[note]\n filename = '\{{title}},\{{content}},\{{date now \"%m-%d\"}},\{{json extra}}'" > .zk/config.toml +$ echo "[note]\n filename = '\{{title}},\{{content}},\{{format-date now \"%m-%d\"}},\{{json extra}}'" > .zk/config.toml $ echo "Piped content" | zk new --interactive --title "A new note" --date "January 5th" --extra key=value --dry-run 2>{{working-dir}}/A new note,Piped content 2>,01-05,{"key":"value"}.md diff --git a/tests/config-note-language.tesh b/tests/config-note-language.tesh index fa6ab59..821999b 100644 --- a/tests/config-note-language.tesh +++ b/tests/config-note-language.tesh @@ -1,6 +1,6 @@ $ cd blank -$ echo "[note]\n filename = '\{{slug title}} - \{{date now \"%B\"}}'" > .zk/config.toml +$ echo "[note]\n filename = '\{{slug title}} - \{{format-date now \"%B\"}}'" > .zk/config.toml # The default language is `en`. # Note the & converted to `and` in the slug. diff --git a/tests/fixtures/group/.zk/config.toml b/tests/fixtures/group/.zk/config.toml index 65f9274..b5f99ac 100644 --- a/tests/fixtures/group/.zk/config.toml +++ b/tests/fixtures/group/.zk/config.toml @@ -6,7 +6,7 @@ template = "default.md" content = "Default content" [group.journal.note] -filename = "{{date now '%d-%m'}}" +filename = "{{format-date now '%d-%m'}}" template = "journal.md" [group.journal.extra] diff --git a/tests/fixtures/new/.zk/config.toml b/tests/fixtures/new/.zk/config.toml index 037a369..8f3c4a0 100644 --- a/tests/fixtures/new/.zk/config.toml +++ b/tests/fixtures/new/.zk/config.toml @@ -4,7 +4,7 @@ filename = "{{slug title}}" [group.date.note] template = "empty.md" -filename = "{{date now '%d-%m'}}" +filename = "{{format-date now '%d-%m'}}" [group.date-raw.note] template = "empty.md" diff --git a/tests/fixtures/new/.zk/templates/handlebars.md b/tests/fixtures/new/.zk/templates/handlebars.md index b4f21c3..c0f1131 100644 --- a/tests/fixtures/new/.zk/templates/handlebars.md +++ b/tests/fixtures/new/.zk/templates/handlebars.md @@ -3,7 +3,7 @@ title: {{title}} content: {{content}} dir: {{dir}} extra: {{json extra}} -now: {{date now "%d-%m"}} +now: {{format-date now "%d-%m"}} env: {{env.ZK_NOTEBOOK_DIR}} filename: {{filename}} filename-stem: {{filename-stem}} diff --git a/tests/markdown-yaml-frontmatter.tesh b/tests/markdown-yaml-frontmatter.tesh index 37a2d52..924df2a 100644 --- a/tests/markdown-yaml-frontmatter.tesh +++ b/tests/markdown-yaml-frontmatter.tesh @@ -28,7 +28,7 @@ $ zk list -q --format "\{{path}}: \{{json tags}}" >case.md: ["writing","essay","practice"] # Creation date extracted from the frontmatter. -$ zk list -q --format "\{{path}}: \{{date created 'full'}}" +$ zk list -q --format "\{{path}}: \{{format-date created 'full'}}" >keywords.md: {{match '.*'}} >empty.md: {{match '.*'}} >full.md: Monday, May 16, 2011