Skip to content

Commit

Permalink
Merge pull request #355 from hairyhenderson/path-functions
Browse files Browse the repository at this point in the history
New path/filepath function namespaces
  • Loading branch information
hairyhenderson committed Jul 12, 2018
2 parents 7e48439 + ac54b0f commit 37627e8
Show file tree
Hide file tree
Showing 8 changed files with 918 additions and 0 deletions.
402 changes: 402 additions & 0 deletions docs/content/functions/filepath.md

Large diffs are not rendered by default.

267 changes: 267 additions & 0 deletions docs/content/functions/path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
---
title: path functions
menu:
main:
parent: functions
---

The path functions are split into 2 namespaces:
- `path`, which is useful for manipulating slash-based (`/`) paths, such as in URLs
- `filepath`, which should be used for local filesystem paths, especially when Windows paths may be involved

This page documents the `path` namespace - see also the [`filepath`](../filepath) documentation.

These functions are wrappers for Go's [`path`](https://golang.org/pkg/path/) and [`path/filepath`](https://golang.org/pkg/path/filepath/) packages.

## `path.Base`


Returns the last element of path. Trailing slashes are removed before extracting the last element. If the path is empty, Base returns `.`. If the path consists entirely of slashes, Base returns `/`.

A wrapper for Go's [`path.Base`](https://golang.org/pkg/path/#Base) function.


### Usage
```go
path.Base path
```

```go
path | path.Base
```


### Arguments

| name | description |
|------|-------------|
| `path` | _(required)_ The input path |


### Examples

```console
$ gomplate -i '{{ path.Base "/tmp/foo" }}'
foo
```

## `path.Clean`


Clean returns the shortest path name equivalent to path by purely lexical processing.

A wrapper for Go's [`path.Clean`](https://golang.org/pkg/path/#Clean) function.


### Usage
```go
path.Clean path
```

```go
path | path.Clean
```


### Arguments

| name | description |
|------|-------------|
| `path` | _(required)_ The input path |


### Examples

```console
$ gomplate -i '{{ path.Clean "/tmp//foo/../" }}'
/tmp
```

## `path.Dir`


Returns all but the last element of path, typically the path's directory.

A wrapper for Go's [`path.Dir`](https://golang.org/pkg/path/#Dir) function.


### Usage
```go
path.Dir path
```

```go
path | path.Dir
```


### Arguments

| name | description |
|------|-------------|
| `path` | _(required)_ The input path |


### Examples

```console
$ gomplate -i '{{ path.Dir "/tmp/foo" }}'
/tmp
```

## `path.Ext`


Returns the file name extension used by path.

A wrapper for Go's [`path.Ext`](https://golang.org/pkg/path/#Ext) function.


### Usage
```go
path.Ext path
```

```go
path | path.Ext
```


### Arguments

| name | description |
|------|-------------|
| `path` | _(required)_ The input path |


### Examples

```console
$ gomplate -i '{{ path.Ext "/tmp/foo.csv" }}'
.csv
```

## `path.IsAbs`


Reports whether the path is absolute.

A wrapper for Go's [`path.IsAbs`](https://golang.org/pkg/path/#IsAbs) function.


### Usage
```go
path.IsAbs path
```

```go
path | path.IsAbs
```


### Arguments

| name | description |
|------|-------------|
| `path` | _(required)_ The input path |


### Examples

```console
$ gomplate -i 'the path is {{ if (path.IsAbs "/tmp/foo.csv") }}absolute{{else}}relative{{end}}'
the path is absolute
$ gomplate -i 'the path is {{ if (path.IsAbs "../foo.csv") }}absolute{{else}}relative{{end}}'
the path is relative
```

## `path.Join`


Joins any number of path elements into a single path, adding a separating slash if necessary.

A wrapper for Go's [`path.Join`](https://golang.org/pkg/path/#Join) function.


### Usage
```go
path.Join elem...
```


### Arguments

| name | description |
|------|-------------|
| `elem...` | _(required)_ The path elements to join (0 or more) |


### Examples

```console
$ gomplate -i '{{ path.Join "/tmp" "foo" "bar" }}'
/tmp/foo/bar
```

## `path.Match`


Reports whether name matches the shell file name pattern.

A wrapper for Go's [`path.Match`](https://golang.org/pkg/path/#Match) function.


### Usage
```go
path.Match pattern path
```


### Arguments

| name | description |
|------|-------------|
| `pattern` | _(required)_ The pattern to match on |
| `path` | _(required)_ The path to match |


### Examples

```console
$ gomplate -i '{{ path.Match "*.csv" "foo.csv" }}'
true
```

## `path.Split`


Splits path immediately following the final slash, separating it into a directory and file name component.

The function returns an array with two values, the first being the diretory, and the second the file.

A wrapper for Go's [`path.Split`](https://golang.org/pkg/path/#Split) function.


### Usage
```go
path.Split path
```

```go
path | path.Split
```


### Arguments

| name | description |
|------|-------------|
| `path` | _(required)_ The input path |


### Examples

```console
$ gomplate -i '{{ $p := path.Split "/tmp/foo" }}{{ $dir := index $p 0 }}{{ $file := index $p 1 }}dir is {{$dir}}, file is {{$file}}'
dir is /tmp/, file is foo
```
2 changes: 2 additions & 0 deletions funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ func initFuncs(d *data.Data) template.FuncMap {
funcs.AddMathFuncs(f)
funcs.AddCryptoFuncs(f)
funcs.AddFileFuncs(f)
funcs.AddFilePathFuncs(f)
funcs.AddPathFuncs(f)
funcs.AddSockaddrFuncs(f)
return f
}
90 changes: 90 additions & 0 deletions funcs/filepath.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package funcs

import (
"path/filepath"
"sync"

"github.com/hairyhenderson/gomplate/conv"
)

var (
fpf *FilePathFuncs
fpfInit sync.Once
)

// FilePathNS - the Path namespace
func FilePathNS() *FilePathFuncs {
fpfInit.Do(func() { fpf = &FilePathFuncs{} })
return fpf
}

// AddFilePathFuncs -
func AddFilePathFuncs(f map[string]interface{}) {
f["filepath"] = FilePathNS
}

// FilePathFuncs -
type FilePathFuncs struct {
}

// Base -
func (f *FilePathFuncs) Base(in interface{}) string {
return filepath.Base(conv.ToString(in))
}

// Clean -
func (f *FilePathFuncs) Clean(in interface{}) string {
return filepath.Clean(conv.ToString(in))
}

// Dir -
func (f *FilePathFuncs) Dir(in interface{}) string {
return filepath.Dir(conv.ToString(in))
}

// Ext -
func (f *FilePathFuncs) Ext(in interface{}) string {
return filepath.Ext(conv.ToString(in))
}

// FromSlash -
func (f *FilePathFuncs) FromSlash(in interface{}) string {
return filepath.FromSlash(conv.ToString(in))
}

// IsAbs -
func (f *FilePathFuncs) IsAbs(in interface{}) bool {
return filepath.IsAbs(conv.ToString(in))
}

// Join -
func (f *FilePathFuncs) Join(elem ...interface{}) string {
s := conv.ToStrings(elem...)
return filepath.Join(s...)
}

// Match -
func (f *FilePathFuncs) Match(pattern, name interface{}) (matched bool, err error) {
return filepath.Match(conv.ToString(pattern), conv.ToString(name))
}

// Rel -
func (f *FilePathFuncs) Rel(basepath, targpath interface{}) (string, error) {
return filepath.Rel(conv.ToString(basepath), conv.ToString(targpath))
}

// Split -
func (f *FilePathFuncs) Split(in interface{}) []string {
dir, file := filepath.Split(conv.ToString(in))
return []string{dir, file}
}

// ToSlash -
func (f *FilePathFuncs) ToSlash(in interface{}) string {
return filepath.ToSlash(conv.ToString(in))
}

// VolumeName -
func (f *FilePathFuncs) VolumeName(in interface{}) string {
return filepath.VolumeName(conv.ToString(in))
}
30 changes: 30 additions & 0 deletions funcs/filepath_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//+build !windows

package funcs

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestFilePathFuncs(t *testing.T) {
f := FilePathNS()
assert.Equal(t, "bar", f.Base("foo/bar"))
assert.Equal(t, "bar", f.Base("/foo/bar"))

assert.Equal(t, "/foo/baz", f.Clean("/foo/bar/../baz"))
assert.Equal(t, "foo", f.Dir("foo/bar"))
assert.Equal(t, ".txt", f.Ext("/foo/bar/baz.txt"))
assert.False(t, f.IsAbs("foo/bar"))
assert.True(t, f.IsAbs("/foo/bar"))
assert.Equal(t, "foo/bar/qux", f.Join("foo", "bar", "baz", "..", "qux"))
m, _ := f.Match("*.txt", "foo.json")
assert.False(t, m)
m, _ = f.Match("*.txt", "foo.txt")
assert.True(t, m)
r, _ := f.Rel("/foo/bar", "/foo/bar/baz")
assert.Equal(t, "baz", r)
assert.Equal(t, []string{"/foo/bar/", "baz"}, f.Split("/foo/bar/baz"))
assert.Equal(t, "", f.VolumeName("/foo/bar"))
}
Loading

0 comments on commit 37627e8

Please sign in to comment.