Add the {{sh}} template helper

pull/6/head
Mickaël Menu 3 years ago
parent 1490bb5ecb
commit 768939f3fe
No known key found for this signature in database
GPG Key ID: 53D73664CD359895

@ -14,6 +14,7 @@ import (
func Init(lang string, logger util.Logger, date date.Provider) {
helpers.RegisterSlug(logger, lang)
helpers.RegisterDate(logger, date)
helpers.RegisterShell(logger)
}
// HandlebarsRenderer holds parsed handlebars template and renders them.

@ -2,20 +2,18 @@ package handlebars
import (
"fmt"
"log"
"os"
"testing"
"time"
"github.com/mickael-menu/zk/util"
"github.com/mickael-menu/zk/util/assert"
"github.com/mickael-menu/zk/util/date"
"github.com/mickael-menu/zk/util/fixtures"
)
func init() {
logger := log.New(os.Stderr, "zk: warning: ", 0)
date := date.NewFrozen(time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC))
Init("en", logger, &date)
Init("en", &util.NullLogger, &date)
}
func TestRenderString(t *testing.T) {
@ -82,3 +80,15 @@ func TestDateHelper(t *testing.T) {
test("timestamp-unix", "1258490098")
test("cust: %Y-%m", "cust: 2009-11")
}
func TestShellHelper(t *testing.T) {
sut := NewRenderer()
// block is passed as piped input
res, err := sut.Render(`{{#sh "tr '[a-z]' '[A-Z]'"}}Hello, world!{{/sh}}`, nil)
assert.Nil(t, err)
assert.Equal(t, res, "HELLO, WORLD!")
// inline
res, err = sut.Render(`{{sh "echo 'Hello, world!'"}}`, nil)
assert.Nil(t, err)
assert.Equal(t, res, "Hello, world!\n")
}

@ -7,6 +7,14 @@ import (
"github.com/mickael-menu/zk/util/date"
)
// RegisterDate registers the {{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}} -> 2009-11-17
// {{date "medium"}} -> Nov 17, 2009
// {{date "%Y-%m"}} -> 2009-11
func RegisterDate(logger util.Logger, date date.Provider) {
raymond.RegisterHelper("date", func(arg string) string {
format := findFormat(arg)

@ -0,0 +1,40 @@
package helpers
import (
"os/exec"
"strings"
"github.com/aymerick/raymond"
"github.com/kballard/go-shellquote"
"github.com/mickael-menu/zk/util"
)
// RegisterShell registers the {{sh}} template helper, which runs shell commands.
//
// {{#sh "tr '[a-z]' '[A-Z]'"}}Hello, world!{{/sh}} -> HELLO, WORLD!
// {{sh "echo 'Hello, world!'"}} -> Hello, world!
func RegisterShell(logger util.Logger) {
raymond.RegisterHelper("sh", func(arg string, options *raymond.Options) string {
args, err := shellquote.Split(arg)
if err != nil {
logger.Printf("{{sh}} failed to parse command: %v: %v", arg, err)
return ""
}
if len(args) == 0 {
logger.Printf("{{sh}} expects a valid shell command, received: %v", arg)
return ""
}
cmd := exec.Command(args[0], args[1:]...)
// Feed any block content as piped input
cmd.Stdin = strings.NewReader(options.Fn())
output, err := cmd.Output()
if err != nil {
logger.Printf("{{sh}} command failed: %v", err)
return ""
}
return string(output)
})
}

@ -6,6 +6,10 @@ import (
"github.com/mickael-menu/zk/util"
)
// RegisterSlug registers a {{slug}} template helper to slugify text.
//
// {{slug "This will be slugified!"}} -> this-will-be-slugified
// {{#slug}}This will be slugified!{{/slug}} -> this-will-be-slugified
func RegisterSlug(logger util.Logger, lang string) {
raymond.RegisterHelper("slug", func(opt interface{}) string {
switch arg := opt.(type) {

@ -8,6 +8,7 @@ require (
github.com/google/go-cmp v0.3.1
github.com/gosimple/slug v1.9.0
github.com/hashicorp/hcl/v2 v2.8.1
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/lestrrat-go/strftime v1.0.3
gopkg.in/yaml.v2 v2.4.0 // indirect
)

@ -21,6 +21,8 @@ github.com/gosimple/slug v1.9.0 h1:r5vDcYrFz9BmfIAMC829un9hq7hKM4cHUrsv36LbEqs=
github.com/gosimple/slug v1.9.0/go.mod h1:AMZ+sOVe65uByN3kgEyf9WEBKBCSS+dJjMX9x4vDJbg=
github.com/hashicorp/hcl/v2 v2.8.1 h1:FJ60CIYaMyJOKzPndhMyjiz353Fd+2jr6PodF5Xzb08=
github.com/hashicorp/hcl/v2 v2.8.1/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=

@ -1,8 +1,13 @@
package main
import (
"log"
"os"
"github.com/alecthomas/kong"
"github.com/mickael-menu/zk/adapter/handlebars"
"github.com/mickael-menu/zk/cmd"
"github.com/mickael-menu/zk/util/date"
)
var cli struct {
@ -11,6 +16,13 @@ var cli struct {
}
func main() {
logger := log.New(os.Stderr, "zk: warning: ", 0)
// zk is short-lived, so we freeze the current date to use the same date
// for any rendering during the execution.
date := date.NewFrozenNow()
// FIXME take the language from the config
handlebars.Init("en", logger, &date)
ctx := kong.Parse(&cli,
kong.Name("zk"),
)

@ -6,3 +6,12 @@ type Logger interface {
Printf(format string, v ...interface{})
Println(v ...interface{})
}
// NullLogger is a logger ignoring any input.
var NullLogger = nullLogger{}
type nullLogger struct{}
func (n *nullLogger) Printf(format string, v ...interface{}) {}
func (n *nullLogger) Println(v ...interface{}) {}

Loading…
Cancel
Save