diff --git a/cmd/container.go b/cmd/container.go
index 6970afc..b12af73 100644
--- a/cmd/container.go
+++ b/cmd/container.go
@@ -2,6 +2,7 @@ package cmd
import (
"io"
+ "sync"
"github.com/mickael-menu/zk/adapter/fzf"
"github.com/mickael-menu/zk/adapter/handlebars"
@@ -20,6 +21,10 @@ type Container struct {
Logger util.Logger
Terminal *term.Terminal
templateLoader *handlebars.Loader
+
+ zkOnce sync.Once
+ zk *zk.Zk
+ zkErr error
}
func NewContainer() *Container {
@@ -34,6 +39,13 @@ func NewContainer() *Container {
}
}
+func (c *Container) OpenZk() (*zk.Zk, error) {
+ c.zkOnce.Do(func() {
+ c.zk, c.zkErr = zk.Open(".")
+ })
+ return c.zk, c.zkErr
+}
+
func (c *Container) TemplateLoader(lang string) *handlebars.Loader {
if c.templateLoader == nil {
handlebars.Init(lang, c.Logger, c.Terminal)
diff --git a/cmd/edit.go b/cmd/edit.go
index 68b26d1..21520b9 100644
--- a/cmd/edit.go
+++ b/cmd/edit.go
@@ -6,7 +6,6 @@ import (
"github.com/mickael-menu/zk/adapter/sqlite"
"github.com/mickael-menu/zk/core/note"
- "github.com/mickael-menu/zk/core/zk"
"github.com/mickael-menu/zk/util/errors"
)
@@ -18,7 +17,7 @@ type Edit struct {
}
func (cmd *Edit) Run(container *Container) error {
- zk, err := zk.Open(".")
+ zk, err := container.OpenZk()
if err != nil {
return err
}
@@ -61,6 +60,8 @@ func (cmd *Edit) Run(container *Container) error {
}
note.Edit(zk, paths...)
+ } else {
+ fmt.Println("Found 0 note")
}
return err
diff --git a/cmd/index.go b/cmd/index.go
index 6eca011..962d12f 100644
--- a/cmd/index.go
+++ b/cmd/index.go
@@ -7,7 +7,6 @@ import (
"github.com/mickael-menu/zk/adapter/sqlite"
"github.com/mickael-menu/zk/core/note"
- "github.com/mickael-menu/zk/core/zk"
"github.com/mickael-menu/zk/util/paths"
"github.com/schollz/progressbar/v3"
)
@@ -20,7 +19,7 @@ type Index struct {
}
func (cmd *Index) Run(container *Container) error {
- zk, err := zk.Open(".")
+ zk, err := container.OpenZk()
if err != nil {
return err
}
diff --git a/cmd/list.go b/cmd/list.go
index 6e6c917..5fab2b2 100644
--- a/cmd/list.go
+++ b/cmd/list.go
@@ -7,7 +7,6 @@ import (
"github.com/mickael-menu/zk/adapter/sqlite"
"github.com/mickael-menu/zk/core/note"
- "github.com/mickael-menu/zk/core/zk"
"github.com/mickael-menu/zk/util/errors"
"github.com/mickael-menu/zk/util/opt"
"github.com/mickael-menu/zk/util/strings"
@@ -22,7 +21,7 @@ type List struct {
}
func (cmd *List) Run(container *Container) error {
- zk, err := zk.Open(".")
+ zk, err := container.OpenZk()
if err != nil {
return err
}
diff --git a/cmd/new.go b/cmd/new.go
index 6913b46..3cc4943 100644
--- a/cmd/new.go
+++ b/cmd/new.go
@@ -12,7 +12,7 @@ import (
// New adds a new note to the slip box.
type New struct {
Directory string `arg optional type:"path" default:"." help:"Directory in which to create the note"`
- PrintPath bool `help:"Prints the path of the created note to stdin instead of editing it"`
+ PrintPath bool `help:"Prints the path of the created note to stdin instead of editing it" short:"p"`
Title string `short:"t" help:"Title of the new note" placeholder:"
"`
Template string `type:"path" help:"Custom template to use to render the note" placeholder:""`
Extra map[string]string `help:"Extra variables passed to the templates"`
@@ -26,7 +26,7 @@ func (cmd *New) ConfigOverrides() zk.ConfigOverrides {
}
func (cmd *New) Run(container *Container) error {
- zk, err := zk.Open(".")
+ zk, err := container.OpenZk()
if err != nil {
return err
}
diff --git a/core/zk/config.go b/core/zk/config.go
index 45b7069..4b4d117 100644
--- a/core/zk/config.go
+++ b/core/zk/config.go
@@ -15,6 +15,7 @@ type Config struct {
Editor opt.String
Pager opt.String
NoPager bool
+ Aliases map[string]string
}
// DirConfig holds the user configuration for a given directory.
@@ -113,19 +114,26 @@ func ParseConfig(content []byte, templatesDir string) (*Config, error) {
}
}
- config := Config{
- DirConfig: root,
- Dirs: make(map[string]DirConfig),
- Editor: opt.NewNotEmptyString(hcl.Editor),
- Pager: opt.NewNotEmptyString(hcl.Pager),
- NoPager: hcl.NoPager,
+ dirs := make(map[string]DirConfig)
+ for _, dirHCL := range hcl.Dirs {
+ dirs[dirHCL.Dir] = root.merge(dirHCL, templatesDir)
}
- for _, dirHCL := range hcl.Dirs {
- config.Dirs[dirHCL.Dir] = root.merge(dirHCL, templatesDir)
+ aliases := make(map[string]string)
+ if hcl.Aliases != nil {
+ for k, v := range hcl.Aliases {
+ aliases[k] = v
+ }
}
- return &config, nil
+ return &Config{
+ DirConfig: root,
+ Dirs: dirs,
+ Editor: opt.NewNotEmptyString(hcl.Editor),
+ Pager: opt.NewNotEmptyString(hcl.Pager),
+ NoPager: hcl.NoPager,
+ Aliases: aliases,
+ }, nil
}
func (c DirConfig) merge(hcl hclDirConfig, templatesDir string) DirConfig {
@@ -189,6 +197,7 @@ type hclConfig struct {
Editor string `hcl:"editor,optional"`
Pager string `hcl:"pager,optional"`
NoPager bool `hcl:"no-pager,optional"`
+ Aliases map[string]string `hcl:"aliases,optional"`
}
type hclDirConfig struct {
diff --git a/core/zk/config_test.go b/core/zk/config_test.go
index dedfa30..9c70a06 100644
--- a/core/zk/config_test.go
+++ b/core/zk/config_test.go
@@ -28,7 +28,8 @@ func TestParseDefaultConfig(t *testing.T) {
Lang: "en",
Extra: make(map[string]string),
},
- Dirs: make(map[string]DirConfig),
+ Dirs: make(map[string]DirConfig),
+ Aliases: make(map[string]string),
})
}
@@ -45,6 +46,11 @@ func TestParseComplete(t *testing.T) {
editor = "vim"
pager = "less"
no-pager = true
+ aliases = {
+ ls = "zk list $@"
+ ed = "zk edit $@"
+ }
+
filename = "{{id}}.note"
extension = "txt"
template = "default.note"
@@ -135,6 +141,10 @@ func TestParseComplete(t *testing.T) {
Editor: opt.NewString("vim"),
Pager: opt.NewString("less"),
NoPager: true,
+ Aliases: map[string]string{
+ "ls": "zk list $@",
+ "ed": "zk edit $@",
+ },
})
}
@@ -223,6 +233,7 @@ func TestParseMergesDirConfig(t *testing.T) {
},
},
},
+ Aliases: make(map[string]string),
})
}
diff --git a/main.go b/main.go
index 108f584..c2a6d61 100644
--- a/main.go
+++ b/main.go
@@ -1,8 +1,13 @@
package main
import (
+ "fmt"
+ "os"
+ "os/exec"
+
"github.com/alecthomas/kong"
"github.com/mickael-menu/zk/cmd"
+ executil "github.com/mickael-menu/zk/util/exec"
)
var Version = "dev"
@@ -18,25 +23,73 @@ var cli struct {
Version kong.VersionFlag `help:"Print zk version"`
}
+// NoInput is a flag preventing any user prompt when enabled.
+type NoInput bool
+
+func (f NoInput) BeforeApply(container *cmd.Container) error {
+ container.Terminal.NoInput = true
+ return nil
+}
+
func main() {
// Create the dependency graph.
container := cmd.NewContainer()
- ctx := kong.Parse(&cli,
- kong.Bind(container),
- kong.Name("zk"),
- kong.Vars{
- "version": Version,
- },
- )
- err := ctx.Run(container)
- ctx.FatalIfErrorf(err)
+ indexZk(container)
+
+ if isAlias, err := runAlias(container, os.Args[1:]); isAlias {
+ fatalIfError(err)
+
+ } else {
+ ctx := kong.Parse(&cli,
+ kong.Bind(container),
+ kong.Name("zk"),
+ kong.Vars{
+ "version": Version,
+ },
+ )
+
+ err := ctx.Run(container)
+ ctx.FatalIfErrorf(err)
+ }
}
-// NoInput is a flag preventing any user prompt when enabled.
-type NoInput bool
+func fatalIfError(err error) {
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "zk: error: %v\n", err)
+ os.Exit(1)
+ }
+}
-func (f NoInput) BeforeApply(container *cmd.Container) error {
- container.Terminal.NoInput = true
- return nil
+// indexZk will index any slip box in the working directory.
+func indexZk(container *cmd.Container) {
+ (&cmd.Index{Quiet: true}).Run(container)
+}
+
+// runAlias will execute a user alias if the command is one of them.
+func runAlias(container *cmd.Container, args []string) (bool, error) {
+ if zk, err := container.OpenZk(); err == nil && len(args) >= 1 {
+ for alias, cmdStr := range zk.Config.Aliases {
+ if alias != args[0] {
+ continue
+ }
+
+ cmd := executil.CommandFromString(cmdStr, args...)
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ err := cmd.Run()
+ if err != nil {
+ if err, ok := err.(*exec.ExitError); ok {
+ os.Exit(err.ExitCode())
+ return true, nil
+ } else {
+ return true, err
+ }
+ }
+ return true, nil
+ }
+ }
+
+ return false, nil
}
diff --git a/util/exec/exec_unix.go b/util/exec/exec_unix.go
index 5522e9d..edf12ad 100644
--- a/util/exec/exec_unix.go
+++ b/util/exec/exec_unix.go
@@ -8,10 +8,11 @@ import (
)
// CommandFromString returns a Cmd running the given command with $SHELL.
-func CommandFromString(command string) *exec.Cmd {
+func CommandFromString(command string, args ...string) *exec.Cmd {
shell := os.Getenv("SHELL")
if len(shell) == 0 {
shell = "sh"
}
- return exec.Command(shell, "-c", command)
+ args = append([]string{"-c", command}, args...)
+ return exec.Command(shell, args...)
}