Add language, file extension and default title in user config

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

@ -3,7 +3,6 @@ package cmd
import (
"github.com/mickael-menu/zk/adapter/handlebars"
"github.com/mickael-menu/zk/adapter/sqlite"
"github.com/mickael-menu/zk/core/zk"
"github.com/mickael-menu/zk/util"
"github.com/mickael-menu/zk/util/date"
)
@ -25,10 +24,9 @@ func NewContainer() *Container {
}
}
func (c *Container) TemplateLoader() *handlebars.Loader {
func (c *Container) TemplateLoader(lang string) *handlebars.Loader {
if c.templateLoader == nil {
// FIXME take the language from the config
handlebars.Init("en", c.Logger, c.Date)
handlebars.Init(lang, c.Logger, c.Date)
c.templateLoader = handlebars.NewLoader()
}
return c.templateLoader
@ -36,8 +34,8 @@ func (c *Container) TemplateLoader() *handlebars.Loader {
// Database returns the DB instance for the given slip box, after executing any
// pending migration.
func (c *Container) Database(zk *zk.Zk) (*sqlite.DB, error) {
db, err := sqlite.Open(zk.DBPath())
func (c *Container) Database(path string) (*sqlite.DB, error) {
db, err := sqlite.Open(path)
if err != nil {
return nil, err
}

@ -22,7 +22,7 @@ func (cmd *Index) Run(container *Container) error {
return err
}
db, err := container.Database(zk)
db, err := container.Database(zk.DBPath())
if err != nil {
return err
}

@ -46,7 +46,7 @@ func (cmd *New) Run(container *Container) error {
Title: opt.NewNotEmptyString(cmd.Title),
Content: content,
}
file, err := note.Create(opts, container.TemplateLoader())
file, err := note.Create(opts, container.TemplateLoader(dir.Config.Lang))
if err != nil {
return err
}

@ -10,7 +10,9 @@ import (
)
// Walk emits the metadata of each file stored in the directory.
func Walk(dir zk.Dir, logger util.Logger) <-chan Metadata {
func Walk(dir zk.Dir, extension string, logger util.Logger) <-chan Metadata {
extension = "." + extension
c := make(chan Metadata, 50)
go func() {
defer close(c)
@ -29,8 +31,7 @@ func Walk(dir zk.Dir, logger util.Logger) <-chan Metadata {
}
} else {
// FIXME: Customize extension in config
if isHidden || filepath.Ext(filename) != ".md" {
if isHidden || filepath.Ext(filename) != extension {
return nil
}

@ -15,7 +15,7 @@ var root = fixtures.Path("walk")
func TestWalkRootDir(t *testing.T) {
dir := zk.Dir{Name: "", Path: root}
res := toSlice(Walk(dir, &util.NullLogger))
res := toSlice(Walk(dir, "md", &util.NullLogger))
assert.Equal(t, res, []Metadata{
{
Path: Path{Dir: "", Filename: "a.md", Abs: filepath.Join(root, "a.md")},
@ -46,7 +46,7 @@ func TestWalkRootDir(t *testing.T) {
func TestWalkSubDir(t *testing.T) {
dir := zk.Dir{Name: "dir1", Path: filepath.Join(root, "dir1")}
res := toSlice(Walk(dir, &util.NullLogger))
res := toSlice(Walk(dir, "md", &util.NullLogger))
assert.Equal(t, res, []Metadata{
{
Path: Path{Dir: "dir1", Filename: "a.md", Abs: filepath.Join(root, "dir1/a.md")},
@ -65,7 +65,7 @@ func TestWalkSubDir(t *testing.T) {
func TestWalkSubSubDir(t *testing.T) {
dir := zk.Dir{Name: "dir1/dir1", Path: filepath.Join(root, "dir1/dir1")}
res := toSlice(Walk(dir, &util.NullLogger))
res := toSlice(Walk(dir, "md", &util.NullLogger))
assert.Equal(t, res, []Metadata{
{
Path: Path{Dir: "dir1/dir1", Filename: "a.md", Abs: filepath.Join(root, "dir1/dir1/a.md")},

@ -94,14 +94,13 @@ func create(
deps createDeps,
) (*createdNote, error) {
context := renderContext{
// FIXME Customize default title in config
Title: opts.Title.OrDefault("Untitled"),
Title: opts.Title.OrDefault(opts.Dir.Config.DefaultTitle),
Content: opts.Content.Unwrap(),
Dir: opts.Dir.Name,
Extra: opts.Dir.Config.Extra,
}
path, context, err := genPath(context, opts.Dir.Path, deps)
path, context, err := genPath(context, opts.Dir, deps)
if err != nil {
return nil, err
}
@ -116,7 +115,7 @@ func create(
func genPath(
context renderContext,
basePath string,
dir zk.Dir,
deps createDeps,
) (string, renderContext, error) {
var path string
@ -128,8 +127,8 @@ func genPath(
return "", context, err
}
// FIXME Customize extension in config
path = filepath.Join(basePath, filename+".md")
filename = filename + "." + dir.Config.Extension
path = filepath.Join(dir.Path, filename)
validPath, err := deps.validatePath(path)
if err != nil {
return "", context, err

@ -20,6 +20,7 @@ func TestCreate(t *testing.T) {
Name: "log",
Path: "/test/log",
Config: zk.DirConfig{
Extension: "md",
Extra: map[string]string{
"hello": "world",
},
@ -77,6 +78,9 @@ func TestCreateTriesUntilValidPath(t *testing.T) {
Dir: zk.Dir{
Name: "log",
Path: "/test/log",
Config: zk.DirConfig{
Extension: "md",
},
},
Title: opt.NewString("Note title"),
},
@ -122,6 +126,9 @@ func TestCreateErrorWhenNoValidPaths(t *testing.T) {
Dir: zk.Dir{
Name: "log",
Path: "/test/log",
Config: zk.DirConfig{
Extension: "md",
},
},
},
createDeps{

@ -41,7 +41,7 @@ type Indexer interface {
func Index(dir zk.Dir, indexer Indexer, logger util.Logger) error {
wrap := errors.Wrapper("indexation failed")
source := file.Walk(dir, logger)
source := file.Walk(dir, dir.Config.Extension, logger)
target, err := indexer.Indexed()
if err != nil {
return wrap(err)

@ -18,8 +18,11 @@ type Config struct {
// DirConfig holds the user configuration for a given directory.
type DirConfig struct {
FilenameTemplate string
Extension string
BodyTemplatePath opt.String
IDOptions IDOptions
Lang string
DefaultTitle string
Extra map[string]string
}
@ -64,18 +67,24 @@ func ParseConfig(content []byte, templatesDir string) (*Config, error) {
root := DirConfig{
FilenameTemplate: "{{id}}",
Extension: "md",
BodyTemplatePath: opt.NullString,
IDOptions: IDOptions{
Charset: CharsetAlphanum,
Length: 5,
Case: CaseLower,
},
Extra: make(map[string]string),
Lang: "en",
DefaultTitle: "Untitled",
Extra: make(map[string]string),
}
if hcl.Filename != "" {
root.FilenameTemplate = hcl.Filename
}
if hcl.Extension != "" {
root.Extension = hcl.Extension
}
if hcl.Template != "" {
root.BodyTemplatePath = templatePathFromString(hcl.Template, templatesDir)
}
@ -90,6 +99,12 @@ func ParseConfig(content []byte, templatesDir string) (*Config, error) {
root.IDOptions.Case = caseFromString(hcl.ID.Case)
}
}
if hcl.Lang != "" {
root.Lang = hcl.Lang
}
if hcl.DefaultTitle != "" {
root.DefaultTitle = hcl.DefaultTitle
}
if hcl.Extra != nil {
for k, v := range hcl.Extra {
root.Extra[k] = v
@ -112,8 +127,11 @@ func ParseConfig(content []byte, templatesDir string) (*Config, error) {
func (c DirConfig) merge(hcl hclDirConfig, templatesDir string) DirConfig {
res := DirConfig{
FilenameTemplate: c.FilenameTemplate,
Extension: c.Extension,
BodyTemplatePath: c.BodyTemplatePath,
IDOptions: c.IDOptions,
Lang: c.Lang,
DefaultTitle: c.DefaultTitle,
Extra: make(map[string]string),
}
for k, v := range c.Extra {
@ -123,6 +141,9 @@ func (c DirConfig) merge(hcl hclDirConfig, templatesDir string) DirConfig {
if hcl.Filename != "" {
res.FilenameTemplate = hcl.Filename
}
if hcl.Extension != "" {
res.Extension = hcl.Extension
}
if hcl.Template != "" {
res.BodyTemplatePath = templatePathFromString(hcl.Template, templatesDir)
}
@ -137,6 +158,12 @@ func (c DirConfig) merge(hcl hclDirConfig, templatesDir string) DirConfig {
res.IDOptions.Case = caseFromString(hcl.ID.Case)
}
}
if hcl.Lang != "" {
res.Lang = hcl.Lang
}
if hcl.DefaultTitle != "" {
res.DefaultTitle = hcl.DefaultTitle
}
if hcl.Extra != nil {
for k, v := range hcl.Extra {
res.Extra[k] = v
@ -147,20 +174,26 @@ func (c DirConfig) merge(hcl hclDirConfig, templatesDir string) DirConfig {
// hclConfig holds the HCL representation of Config
type hclConfig struct {
Filename string `hcl:"filename,optional"`
Template string `hcl:"template,optional"`
ID *hclIDConfig `hcl:"id,block"`
Extra map[string]string `hcl:"extra,optional"`
Dirs []hclDirConfig `hcl:"dir,block"`
Editor string `hcl:"editor,optional"`
Filename string `hcl:"filename,optional"`
Extension string `hcl:"extension,optional"`
Template string `hcl:"template,optional"`
ID *hclIDConfig `hcl:"id,block"`
Lang string `hcl:"language,optional"`
DefaultTitle string `hcl:"default-title,optional"`
Extra map[string]string `hcl:"extra,optional"`
Dirs []hclDirConfig `hcl:"dir,block"`
Editor string `hcl:"editor,optional"`
}
type hclDirConfig struct {
Dir string `hcl:"dir,label"`
Filename string `hcl:"filename,optional"`
Template string `hcl:"template,optional"`
ID *hclIDConfig `hcl:"id,block"`
Extra map[string]string `hcl:"extra,optional"`
Dir string `hcl:"dir,label"`
Filename string `hcl:"filename,optional"`
Extension string `hcl:"extension,optional"`
Template string `hcl:"template,optional"`
ID *hclIDConfig `hcl:"id,block"`
Lang string `hcl:"language,optional"`
DefaultTitle string `hcl:"default-title,optional"`
Extra map[string]string `hcl:"extra,optional"`
}
type hclIDConfig struct {

@ -17,13 +17,16 @@ func TestParseDefaultConfig(t *testing.T) {
Editor: opt.NullString,
DirConfig: DirConfig{
FilenameTemplate: "{{id}}",
Extension: "md",
BodyTemplatePath: opt.NullString,
IDOptions: IDOptions{
Length: 5,
Charset: CharsetAlphanum,
Case: CaseLower,
},
Extra: make(map[string]string),
DefaultTitle: "Untitled",
Lang: "en",
Extra: make(map[string]string),
},
Dirs: make(map[string]DirConfig),
})
@ -41,24 +44,30 @@ func TestParseComplete(t *testing.T) {
// Comment
editor = "vim"
filename = "{{id}}.note"
extension = "txt"
template = "default.note"
id {
charset = "alphanum"
length = 4
case = "lower"
}
language = "fr"
default-title = "Sans titre"
extra = {
hello = "world"
salut = "le monde"
}
dir "log" {
filename = "{{date}}.md"
extension = "note"
template = "log.md"
id {
charset = "letters"
length = 8
case = "mixed"
}
language = "de"
default-title = "Ohne Titel"
extra = {
log-ext = "value"
}
@ -72,12 +81,15 @@ func TestParseComplete(t *testing.T) {
assert.Equal(t, conf, &Config{
DirConfig: DirConfig{
FilenameTemplate: "{{id}}.note",
Extension: "txt",
BodyTemplatePath: opt.NewString("default.note"),
IDOptions: IDOptions{
Length: 4,
Charset: CharsetAlphanum,
Case: CaseLower,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
@ -86,12 +98,15 @@ func TestParseComplete(t *testing.T) {
Dirs: map[string]DirConfig{
"log": {
FilenameTemplate: "{{date}}.md",
Extension: "note",
BodyTemplatePath: opt.NewString("log.md"),
IDOptions: IDOptions{
Length: 8,
Charset: CharsetLetters,
Case: CaseMixed,
},
Lang: "de",
DefaultTitle: "Ohne Titel",
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
@ -100,12 +115,15 @@ func TestParseComplete(t *testing.T) {
},
"ref": {
FilenameTemplate: "{{slug title}}.md",
Extension: "txt",
BodyTemplatePath: opt.NewString("default.note"),
IDOptions: IDOptions{
Length: 4,
Charset: CharsetAlphanum,
Case: CaseLower,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
@ -119,12 +137,15 @@ func TestParseComplete(t *testing.T) {
func TestParseMergesDirConfig(t *testing.T) {
conf, err := ParseConfig([]byte(`
filename = "root-filename"
extension = "txt"
template = "root-template"
id {
charset = "letters"
length = 42
case = "upper"
}
language = "fr"
default-title = "Sans titre"
extra = {
hello = "world"
salut = "le monde"
@ -149,12 +170,15 @@ func TestParseMergesDirConfig(t *testing.T) {
assert.Equal(t, conf, &Config{
DirConfig: DirConfig{
FilenameTemplate: "root-filename",
Extension: "txt",
BodyTemplatePath: opt.NewString("root-template"),
IDOptions: IDOptions{
Length: 42,
Charset: CharsetLetters,
Case: CaseUpper,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
@ -163,12 +187,15 @@ func TestParseMergesDirConfig(t *testing.T) {
Dirs: map[string]DirConfig{
"log": {
FilenameTemplate: "log-filename",
Extension: "txt",
BodyTemplatePath: opt.NewString("log-template"),
IDOptions: IDOptions{
Length: 8,
Charset: CharsetNumbers,
Case: CaseMixed,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Extra: map[string]string{
"hello": "override",
"salut": "le monde",
@ -177,12 +204,15 @@ func TestParseMergesDirConfig(t *testing.T) {
},
"inherited": {
FilenameTemplate: "root-filename",
Extension: "txt",
BodyTemplatePath: opt.NewString("root-template"),
IDOptions: IDOptions{
Length: 42,
Charset: CharsetLetters,
Case: CaseUpper,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Extra: map[string]string{
"hello": "world",
"salut": "le monde",
@ -243,12 +273,15 @@ func TestParseResolvesTemplatePaths(t *testing.T) {
func TestDirConfigClone(t *testing.T) {
original := DirConfig{
FilenameTemplate: "{{id}}.note",
Extension: "md",
BodyTemplatePath: opt.NewString("default.note"),
IDOptions: IDOptions{
Length: 4,
Charset: CharsetAlphanum,
Case: CaseLower,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Extra: map[string]string{
"hello": "world",
},
@ -259,21 +292,27 @@ func TestDirConfigClone(t *testing.T) {
assert.Equal(t, clone, original)
clone.FilenameTemplate = "modified"
clone.Extension = "txt"
clone.BodyTemplatePath = opt.NewString("modified")
clone.IDOptions.Length = 41
clone.IDOptions.Charset = CharsetNumbers
clone.IDOptions.Case = CaseUpper
clone.Lang = "de"
clone.DefaultTitle = "Ohne Titel"
clone.Extra["test"] = "modified"
// Check that we didn't modify the original
assert.Equal(t, original, DirConfig{
FilenameTemplate: "{{id}}.note",
Extension: "md",
BodyTemplatePath: opt.NewString("default.note"),
IDOptions: IDOptions{
Length: 4,
Charset: CharsetAlphanum,
Case: CaseLower,
},
Lang: "fr",
DefaultTitle: "Sans titre",
Extra: map[string]string{
"hello": "world",
},

Loading…
Cancel
Save