Add zk.Dir struct

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

@ -18,7 +18,7 @@ type rootConfig struct {
RandomID *randomIDConfig `hcl:"random_id,block"`
Editor string `hcl:"editor,optional"`
Dirs []dirConfig `hcl:"dir,block"`
Ext map[string]string `hcl:"ext,optional"`
Extra map[string]string `hcl:"extra,optional"`
}
type dirConfig struct {
@ -26,7 +26,7 @@ type dirConfig struct {
Filename string `hcl:"filename,optional"`
Template string `hcl:"template,optional"`
RandomID *randomIDConfig `hcl:"random_id,block"`
Ext map[string]string `hcl:"ext,optional"`
Extra map[string]string `hcl:"extra,optional"`
}
type randomIDConfig struct {
@ -46,7 +46,7 @@ func ParseConfig(content []byte) (*Config, error) {
}
// Filename returns the filename template for the notes in the given directory.
func (c *Config) Filename(dir string) string {
func (c *Config) Filename(dir Dir) string {
dirConfig := c.dirConfig(dir)
switch {
@ -60,7 +60,7 @@ func (c *Config) Filename(dir string) string {
}
// Template returns the file template to use for the notes in the given directory.
func (c *Config) Template(dir string) opt.String {
func (c *Config) Template(dir Dir) opt.String {
dirConfig := c.dirConfig(dir)
switch {
@ -74,7 +74,7 @@ func (c *Config) Template(dir string) opt.String {
}
// RandIDOpts returns the options to use to generate a random ID for the given directory.
func (c *Config) RandIDOpts(dir string) rand.IDOpts {
func (c *Config) RandIDOpts(dir Dir) rand.IDOpts {
toCharset := func(charset string) []rune {
switch charset {
case "alphanum":
@ -133,27 +133,27 @@ func (c *Config) RandIDOpts(dir string) rand.IDOpts {
return opts
}
// Ext returns the extra variables for the given directory.
func (c *Config) Ext(dir string) map[string]string {
ext := make(map[string]string)
// Extra returns the extra variables for the given directory.
func (c *Config) Extra(dir Dir) map[string]string {
extra := make(map[string]string)
for k, v := range c.rootConfig.Ext {
ext[k] = v
for k, v := range c.rootConfig.Extra {
extra[k] = v
}
if dirConfig := c.dirConfig(dir); dirConfig != nil {
for k, v := range dirConfig.Ext {
ext[k] = v
for k, v := range dirConfig.Extra {
extra[k] = v
}
}
return ext
return extra
}
// dirConfig returns the dirConfig instance for the given directory.
func (c *Config) dirConfig(dir string) *dirConfig {
func (c *Config) dirConfig(dir Dir) *dirConfig {
for _, dirConfig := range c.rootConfig.Dirs {
if dirConfig.Dir == dir {
if dirConfig.Dir == dir.Name {
return &dirConfig
}
}

@ -27,7 +27,7 @@ func TestParseComplete(t *testing.T) {
length = 4
case = "lower"
}
ext = {
extra = {
hello = "world"
salut = "le monde"
}
@ -39,7 +39,7 @@ func TestParseComplete(t *testing.T) {
length = 8
case = "mixed"
}
ext = {
extra = {
log-ext = "value"
}
}
@ -65,10 +65,10 @@ func TestParseComplete(t *testing.T) {
Length: 8,
Case: "mixed",
},
Ext: map[string]string{"log-ext": "value"},
Extra: map[string]string{"log-ext": "value"},
},
},
Ext: map[string]string{
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
},
@ -84,9 +84,9 @@ func TestParseInvalidConfig(t *testing.T) {
func TestDefaultFilename(t *testing.T) {
config := &Config{}
assert.Equal(t, config.Filename(""), "{{random-id}}")
assert.Equal(t, config.Filename("."), "{{random-id}}")
assert.Equal(t, config.Filename("unknown"), "{{random-id}}")
assert.Equal(t, config.Filename(dir("")), "{{random-id}}")
assert.Equal(t, config.Filename(dir(".")), "{{random-id}}")
assert.Equal(t, config.Filename(dir("unknown")), "{{random-id}}")
}
func TestCustomFilename(t *testing.T) {
@ -99,17 +99,17 @@ func TestCustomFilename(t *testing.T) {
},
},
}}
assert.Equal(t, config.Filename(""), "root-filename")
assert.Equal(t, config.Filename("."), "root-filename")
assert.Equal(t, config.Filename("unknown"), "root-filename")
assert.Equal(t, config.Filename("log"), "log-filename")
assert.Equal(t, config.Filename(dir("")), "root-filename")
assert.Equal(t, config.Filename(dir(".")), "root-filename")
assert.Equal(t, config.Filename(dir("unknown")), "root-filename")
assert.Equal(t, config.Filename(dir("log")), "log-filename")
}
func TestDefaultTemplate(t *testing.T) {
config := &Config{}
assert.Equal(t, config.Template(""), opt.NullString)
assert.Equal(t, config.Template("."), opt.NullString)
assert.Equal(t, config.Template("unknown"), opt.NullString)
assert.Equal(t, config.Template(dir("")), opt.NullString)
assert.Equal(t, config.Template(dir(".")), opt.NullString)
assert.Equal(t, config.Template(dir("unknown")), opt.NullString)
}
func TestCustomTemplate(t *testing.T) {
@ -122,52 +122,52 @@ func TestCustomTemplate(t *testing.T) {
},
},
}}
assert.Equal(t, config.Template(""), opt.NewString("root.tpl"))
assert.Equal(t, config.Template("."), opt.NewString("root.tpl"))
assert.Equal(t, config.Template("unknown"), opt.NewString("root.tpl"))
assert.Equal(t, config.Template("log"), opt.NewString("log.tpl"))
assert.Equal(t, config.Template(dir("")), opt.NewString("root.tpl"))
assert.Equal(t, config.Template(dir(".")), opt.NewString("root.tpl"))
assert.Equal(t, config.Template(dir("unknown")), opt.NewString("root.tpl"))
assert.Equal(t, config.Template(dir("log")), opt.NewString("log.tpl"))
}
func TestNoExtra(t *testing.T) {
config := &Config{}
assert.Equal(t, config.Ext(""), map[string]string{})
assert.Equal(t, config.Extra(dir("")), map[string]string{})
}
func TestMergeExtra(t *testing.T) {
config := &Config{rootConfig{
Ext: map[string]string{
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
},
Dirs: []dirConfig{
dirConfig{
Dir: "log",
Ext: map[string]string{
Extra: map[string]string{
"hello": "override",
"additional": "value",
},
},
},
}}
assert.Equal(t, config.Ext(""), map[string]string{
assert.Equal(t, config.Extra(dir("")), map[string]string{
"hello": "world",
"salut": "le monde",
})
assert.Equal(t, config.Ext("."), map[string]string{
assert.Equal(t, config.Extra(dir(".")), map[string]string{
"hello": "world",
"salut": "le monde",
})
assert.Equal(t, config.Ext("unknown"), map[string]string{
assert.Equal(t, config.Extra(dir("unknown")), map[string]string{
"hello": "world",
"salut": "le monde",
})
assert.Equal(t, config.Ext("log"), map[string]string{
assert.Equal(t, config.Extra(dir("log")), map[string]string{
"hello": "override",
"salut": "le monde",
"additional": "value",
})
// Makes sure we didn't modify the extra in place by getting the `log` ones.
assert.Equal(t, config.Ext(""), map[string]string{
assert.Equal(t, config.Extra(dir("")), map[string]string{
"hello": "world",
"salut": "le monde",
})
@ -181,9 +181,9 @@ func TestDefaultRandIDOpts(t *testing.T) {
Case: rand.LowerCase,
}
assert.Equal(t, config.RandIDOpts(""), defaultOpts)
assert.Equal(t, config.RandIDOpts("."), defaultOpts)
assert.Equal(t, config.RandIDOpts("unknown"), defaultOpts)
assert.Equal(t, config.RandIDOpts(dir("")), defaultOpts)
assert.Equal(t, config.RandIDOpts(dir(".")), defaultOpts)
assert.Equal(t, config.RandIDOpts(dir("unknown")), defaultOpts)
}
func TestOverrideRandIDOpts(t *testing.T) {
@ -207,11 +207,11 @@ func TestOverrideRandIDOpts(t *testing.T) {
Length: 42,
Case: rand.LowerCase,
}
assert.Equal(t, config.RandIDOpts(""), expectedRootOpts)
assert.Equal(t, config.RandIDOpts("."), expectedRootOpts)
assert.Equal(t, config.RandIDOpts("unknown"), expectedRootOpts)
assert.Equal(t, config.RandIDOpts(dir("")), expectedRootOpts)
assert.Equal(t, config.RandIDOpts(dir(".")), expectedRootOpts)
assert.Equal(t, config.RandIDOpts(dir("unknown")), expectedRootOpts)
assert.Equal(t, config.RandIDOpts("log"), rand.IDOpts{
assert.Equal(t, config.RandIDOpts(dir("log")), rand.IDOpts{
Charset: rand.AlphanumCharset,
Length: 28,
Case: rand.LowerCase,
@ -226,7 +226,7 @@ func TestParseRandIDCharset(t *testing.T) {
},
}}
if !cmp.Equal(config.RandIDOpts("").Charset, expected) {
if !cmp.Equal(config.RandIDOpts(dir("")).Charset, expected) {
t.Errorf("Didn't parse random ID charset `%v` as expected", charset)
}
}
@ -247,7 +247,7 @@ func TestParseRandIDCase(t *testing.T) {
},
}}
if !cmp.Equal(config.RandIDOpts("").Case, expected) {
if !cmp.Equal(config.RandIDOpts(dir("")).Case, expected) {
t.Errorf("Didn't parse random ID case `%v` as expected", letterCase)
}
}
@ -257,3 +257,7 @@ func TestParseRandIDCase(t *testing.T) {
test("mixed", rand.MixedCase)
test("unknown", rand.LowerCase)
}
func dir(name string) Dir {
return Dir{Name: name, Path: name}
}

@ -15,10 +15,22 @@ dir "log" {
}
`
// Zk (Zettelkasten) represents an opened slip box.
type Zk struct {
// Slip box root path.
Path string
// User configuration parsed from .zk/config.hsl.
Config Config
}
// Dir represents a directory inside a slip box.
type Dir struct {
// Name of the directory, which is the path relative to the slip box's root.
Name string
// Absolute path to the directory.
Path string
}
// Open locates a slip box at the given path and parses its configuration.
func Open(path string) (*Zk, error) {
wrap := errors.Wrapper("open failed")
@ -42,7 +54,10 @@ func Open(path string) (*Zk, error) {
return nil, wrap(err)
}
return &Zk{*config}, nil
return &Zk{
Path: path,
Config: *config,
}, nil
}
// Create initializes a new slip box at the given path.
@ -110,3 +125,23 @@ func dirExists(path string) bool {
return false
}
}
// DirAt creates a Dir representation of the slip box directory at the given path.
func (zk *Zk) DirAt(path string) (*Dir, error) {
wrap := errors.Wrapperf("%v: not a valid slip box directory", path)
path, err := filepath.Abs(path)
if err != nil {
return nil, wrap(err)
}
name, err := filepath.Rel(zk.Path, path)
if err != nil {
return nil, wrap(err)
}
return &Dir{
Name: name,
Path: path,
}, nil
}

@ -0,0 +1,33 @@
package zk
import (
"os"
"path/filepath"
"testing"
"github.com/mickael-menu/zk/util/assert"
)
func TestDirAt(t *testing.T) {
// The tests are relative to the working directory, for convenience.
wd, err := os.Getwd()
assert.Nil(t, err)
zk := &Zk{
Path: wd,
Config: Config{},
}
for path, name := range map[string]string{
"log": "log",
"log/sub": "log/sub",
"log/sub/..": "log",
"log/sub/../sub": "log/sub",
filepath.Join(wd, "log"): "log",
filepath.Join(wd, "log/sub"): "log/sub",
} {
actual, err := zk.DirAt(path)
assert.Nil(t, err)
assert.Equal(t, actual, &Dir{Name: name, Path: filepath.Join(wd, name)})
}
}

@ -5,14 +5,14 @@ type String struct {
value *string
}
// NullString repreents an empty optional String.
var NullString = String{nil}
// NewString creates a new optional String with the given value.
func NewString(value string) String {
return String{&value}
}
// NullString repreents an empty optional String.
var NullString = String{nil}
// IsNull returns whether the optional String has no value.
func (s String) IsNull() bool {
return s.value == nil

Loading…
Cancel
Save