Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,11 @@ Now everytime you create a title with "exercise" or any of the other words in
that list _somewhere_ in the title, it will populate the note with the content
of `XDG_DATA_HOME/jn/gym-measurements.md`.


#### Template variables

##### Predefined variables

You can use predefined template variables in your templates.

For example, a template consiting of
Expand Down Expand Up @@ -336,6 +339,30 @@ Note that template variables are very fresh, so there aren't many...

If you have any suggestions on useful ones, raise an issue.

##### Shell variables

Another more powerful (and dangerous/fun) type of template variable is the
shell variable.

This allows you to shell out and fill the template with results of the shell
command.

Shell template variables start with `{%` and end with `%}`.

For example we can do:

```
The year is {% date +%Y %}.

Hello {% echo 'Joe' %} And hello {% echo 'Jim' %}.
Here is a list of my files {% ls %}.
I hope you like them {% echo 'Joe' %}.

Written on {{ today }}.
```

The onus is on you to write the command correctly. It not working is undefined behaviour.


#### Editing a template

Expand Down
13 changes: 7 additions & 6 deletions src/templates/templates.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import std/[os, parsecfg, paths, re, strutils]
import ../config
import ./variables/[today, note as noteV]
import ./variables/[today, note as noteV, shell]


type Template* = object
Expand Down Expand Up @@ -35,12 +35,13 @@ proc getTemplates*(config: Config): seq[Template] {.raises: [KeyError].} =

return templates

proc renderVariables*(templateContent: string, note: Path): string {.raises: [RegexError] .} =
var templateContent = templateContent.replace(re"{{\s*today\s*}}", today.process(note))
templateContent = templateContent.replace(re"{{\s*note\s*}}", noteV.process(note))
return templateContent
proc renderVariables*(templateContent: string, note: Path): string {.raises: [RegexError, OSError, IOError] .} =
var content = templateContent.replace(re"{{\s*today\s*}}", today.process(note))
content = content.replace(re"{{\s*note\s*}}", noteV.process(note))
content = shell.process(content, note)
return content

proc process*(myTemplate: Template, note: Path, config: Config) {.raises: [KeyError, IOError, RegexError].} =
proc process*(myTemplate: Template, note: Path, config: Config) {.raises: [KeyError, OSError, IOError, RegexError].} =
let templatePath = getTemplateLocation(config) / myTemplate.location
let templateContent: string = getContent(templatePath)

Expand Down
16 changes: 16 additions & 0 deletions src/templates/variables/shell.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import std/[osproc, paths, re, strutils]

let pattern = re"{%\s*(.+?)\s*%}"

proc process*(templateContent: string, note: Path): string {.raises: [RegexError, OSError, IOError] .} =
result = templateContent

var matches = result.findAll(pattern)

while matches.len > 0:
let match = matches[0]
let command = match.replace(re"{%\s*|\s*%}", "").strip()
let output = execProcess(command).strip()
result = result.replace(match, output)
matches = result.findAll(pattern)

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, {% echo 'Joe' %} and hello, {% echo 'Jebediah' %}.
1 change: 1 addition & 0 deletions tests/data/templates/test-template-with-shell-variable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, {% echo 'Joe' %}.
Binary file modified tests/test_templates
Binary file not shown.
24 changes: 24 additions & 0 deletions tests/test_templates.nim
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,27 @@ suite "Template tests":
)

check(expected in actual)

test "It renders shell variables":
let expected = "Hello, Joe.\n"

let actual = renderVariables(
getContent(
Path("./tests/data/templates/test-template-with-shell-variable.md")
),
Path("Does not matter")
)

check(expected == actual)

test "It renders multiple shell variables":
let expected = "Hello, Joe and hello, Jebediah.\n"

let actual = renderVariables(
getContent(
Path("./tests/data/templates/test-template-with-multiple-shell-variables.md")
),
Path("Does not matter")
)

check(expected == actual)