Skip to content

Commit

Permalink
Merge pull request #2 from gliderlabs/master
Browse files Browse the repository at this point in the history
v0.3.0
  • Loading branch information
progrium committed Jul 27, 2015
2 parents 258cc69 + 1800485 commit 20c9222
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 55 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
NAME=sigil
ARCH=$(shell uname -m)
ORG=gliderlabs
VERSION=0.2.0
VERSION=0.3.0

build:
mkdir -p build/Linux && GOOS=linux go build -ldflags "-X main.Version $(VERSION)" -o build/Linux/$(NAME) ./cmd
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Sigil

[![CircleCI](https://img.shields.io/circleci/project/gliderlabs/sigil/release.svg)](https://circleci.com/gh/gliderlabs/sigil)
[![IRC Channel](https://img.shields.io/badge/irc-%23gliderlabs-blue.svg)](https://kiwiirc.com/client/irc.freenode.net/#gliderlabs)


Standalone string interpolator and template processor

```
Expand Down Expand Up @@ -91,3 +95,4 @@ documentation there.
## License

BSD
<img src="https://ga-beacon.appspot.com/UA-58928488-2/sigil/readme?pixel" />
201 changes: 169 additions & 32 deletions builtin/builtin.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package builtin

import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"reflect"
"strconv"
Expand All @@ -21,6 +23,7 @@ func init() {
"seq": Seq,
"default": Default,
"join": Join,
"split": Split,
"capitalize": Capitalize,
"lower": Lower,
"upper": Upper,
Expand All @@ -31,6 +34,13 @@ func init() {
"yaml": Yaml,
"pointer": Pointer,
"include": Include,
"indent": Indent,
"var": Var,
"match": Match,
"render": Render,
"exists": Exists,
"dir": Dir,
"stdin": Stdin,
})
}

Expand Down Expand Up @@ -58,14 +68,28 @@ func Seq(i interface{}) ([]string, error) {
}

func Default(value, in interface{}) interface{} {
if in == nil {
return value
}
if reflect.Zero(reflect.TypeOf(in)).Interface() == in {
return value
}
return in
}

func Join(delim string, in []string) string {
return strings.Join(in, delim)
func Join(delim string, in []interface{}) string {
var elements []string
for _, el := range in {
str, ok := el.(string)
if ok {
elements = append(elements, str)
}
}
return strings.Join(elements, delim)
}

func Split(delim string, in string) []string {
return strings.Split(in, delim)
}

func Capitalize(in string) string {
Expand All @@ -88,61 +112,174 @@ func Trim(in string) string {
return strings.Trim(in, " \n")
}

func file(filename string) []byte {
if _, err := os.Stat(filename); os.IsNotExist(err) {
filename = filepath.Join(sigil.TemplateDir, filename)
if _, err := os.Stat(filename); os.IsNotExist(err) {
return []byte{}
}
func read(file interface{}) ([]byte, error) {
stdin, ok := file.(stdinStr)
if ok {
return []byte(stdin), nil
}
data, err := ioutil.ReadFile(filename)
path, ok := file.(string)
if !ok {
return []byte{}, fmt.Errorf("file must be path string or stdin")
}
filepath, err := sigil.LookPath(path)
if err != nil {
return []byte{}, err
}
data, err := ioutil.ReadFile(filepath)
if err != nil {
return []byte{}
return []byte{}, err
}
return data
return data, nil
}

func File(filename string) string {
return string(file(filename))
func File(filename string) (string, error) {
str, err := read(filename)
return string(str), err
}

func Json(filename string) map[string]interface{} {
var obj map[string]interface{}
err := json.Unmarshal(file(filename), &obj)
func Json(file interface{}) (interface{}, error) {
var obj interface{}
f, err := read(file)
if err != nil {
return nil
return nil, err
}
return obj
err = json.Unmarshal(f, &obj)
if err != nil {
return nil, err
}
return obj, nil
}

func Yaml(filename string) map[string]interface{} {
var obj map[string]interface{}
err := yaml.Unmarshal(file(filename), &obj)
func Yaml(file interface{}) (interface{}, error) {
var obj interface{}
f, err := read(file)
if err != nil {
return nil, err
}
err = yaml.Unmarshal(f, &obj)
if err != nil {
return nil
return nil, err
}
return obj
return obj, nil
}

func Pointer(path string, in map[string]interface{}) interface{} {
return jsonpointer.Get(in, path)
func Pointer(path string, in interface{}) (interface{}, error) {
m := make(map[string]interface{})
switch val := in.(type) {
case map[string]interface{}:
for k, v := range val {
m[k] = v
}
case map[interface{}]interface{}:
for k, v := range val {
m[k.(string)] = v
}
default:
return nil, fmt.Errorf("pointer needs a map type")
}
return jsonpointer.Get(m, path), nil
}

func Include(filename string, args ...string) (string, error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
return "", err
func Render(args ...interface{}) (string, error) {
if len(args) == 0 {
fmt.Errorf("render cannot be used without arguments")
}
input := args[len(args)-1].(string)
var vars []interface{}
if len(args) > 1 {
vars = args[0 : len(args)-1]
}
render, err := render([]byte(input), vars, "<render>")
return render.String(), err
}

func render(data []byte, args []interface{}, name string) (bytes.Buffer, error) {
vars := make(map[string]string)
for _, arg := range args {
parts := strings.SplitN(arg, "=", 2)
mv, ok := arg.(map[string]string)
if ok {
for k, v := range mv {
vars[k] = v
}
continue
}
sv, ok := arg.(string)
if !ok {
continue
}
parts := strings.SplitN(sv, "=", 2)
if len(parts) == 2 {
vars[parts[0]] = parts[1]
}
}
str, err := sigil.Execute(string(data), vars)
return sigil.Execute(data, vars, name)
}

func Include(filename string, args ...interface{}) (string, error) {
path, err := sigil.LookPath(filename)
if err != nil {
return "", err
}
data, err := ioutil.ReadFile(path)
if err != nil {
return "", err
}
sigil.PushPath(filepath.Dir(path))
defer sigil.PopPath()
render, err := render(data, args, filepath.Base(path))
return render.String(), err
}

func Indent(indent, in string) string {
var indented []string
lines := strings.Split(in, "\n")
indented = append(indented, lines[0])
if len(lines) > 1 {
for _, line := range lines[1:] {
if line != "" {
indented = append(indented, indent+line)
} else {
indented = append(indented, line)
}
}
}
return strings.Join(indented, "\n")
}

func Var(name string) string {
return os.Getenv(name)
}

func Match(pattern string, str string) (bool, error) {
return path.Match(pattern, str)
}

func Exists(filename string) bool {
_, err := sigil.LookPath(filename)
if err != nil {
return false
}
return true
}

func Dir(path string) ([]string, error) {
var files []string
dir, err := ioutil.ReadDir(path)
if err != nil {
return nil, err
}
for _, fi := range dir {
files = append(files, fi.Name())
}
return files, nil
}

type stdinStr string

func Stdin() (stdinStr, error) {
data, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return "", err
}
return str, nil
return stdinStr(data), nil
}
31 changes: 19 additions & 12 deletions cmd/sigil.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,28 @@ var Version string

var (
filename = flag.String("f", "", "use template file instead of STDIN")
posix = flag.Bool("p", true, "preprocess with POSIX variable expansion")
inline = flag.String("i", "", "use inline template string instead of STDIN")
posix = flag.Bool("p", false, "preprocess with POSIX variable expansion")
version = flag.Bool("v", false, "prints version")
)

func template() (string, error) {
func template() ([]byte, string, error) {
if *filename != "" {
data, err := ioutil.ReadFile(*filename)
if err != nil {
return "", err
return []byte{}, "", err
}
sigil.TemplateDir = filepath.Dir(*filename)
return string(data), nil
sigil.PushPath(filepath.Dir(*filename))
return data, filepath.Base(*filename), nil
}
if *inline != "" {
return []byte(*inline), "<inline>", nil
}
data, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return "", err
return []byte{}, "", err
}
return string(data), nil
return data, "<stdin>", nil
}

func main() {
Expand All @@ -45,6 +49,9 @@ func main() {
if *posix {
sigil.PosixPreprocess = true
}
if os.Getenv("SIGIL_PATH") != "" {
sigil.TemplatePath = strings.Split(os.Getenv("SIGIL_PATH"), ":")
}
vars := make(map[string]string)
for _, arg := range os.Args {
if strings.HasPrefix(arg, "-") {
Expand All @@ -55,15 +62,15 @@ func main() {
vars[parts[0]] = parts[1]
}
}
tmpl, err := template()
tmpl, name, err := template()
if err != nil {
fmt.Println(err)
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
render, err := sigil.Execute(tmpl, vars)
render, err := sigil.Execute(tmpl, vars, name)
if err != nil {
fmt.Println(err)
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Print(render)
os.Stdout.Write(render.Bytes())
}
Loading

0 comments on commit 20c9222

Please sign in to comment.