diff --git a/cmd/edit.go b/cmd/edit.go new file mode 100644 index 0000000..7b9f33e --- /dev/null +++ b/cmd/edit.go @@ -0,0 +1,67 @@ +package cmd + +import ( + "fmt" + "path/filepath" + + "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" +) + +// Edit opens notes matching a set of criteria with the user editor. +type Edit struct { + Filtering `embed` + Sorting `embed` + Force bool `help:"Don't confirm before editing many notes at the same time" short:"f"` +} + +func (cmd *Edit) Run(container *Container) error { + zk, err := zk.Open(".") + if err != nil { + return err + } + + opts, err := NewFinderOpts(zk, cmd.Filtering, cmd.Sorting) + if err != nil { + return errors.Wrapf(err, "incorrect criteria") + } + + db, err := container.Database(zk.DBPath()) + if err != nil { + return err + } + + var notes []note.Match + err = db.WithTransaction(func(tx sqlite.Transaction) error { + notes, err = container.NoteFinder(tx).Find(*opts) + return err + }) + if err != nil { + return err + } + + count := len(notes) + + if count > 0 { + if !cmd.Force && count > 2 { + if !container.TTY.Confirm( + fmt.Sprintf("Are you sure you want to open %v notes in the editor?", count), + "Open all the notes", + "Don't open any note", + ) { + return nil + } + } + paths := make([]string, 0) + for _, note := range notes { + absPath := filepath.Join(zk.Path, note.Path) + paths = append(paths, absPath) + } + + note.Edit(zk, paths...) + } + + return err +} diff --git a/core/note/edit.go b/core/note/edit.go index 69fe22c..5455f13 100644 --- a/core/note/edit.go +++ b/core/note/edit.go @@ -3,17 +3,17 @@ package note import ( "fmt" "os" + "os/exec" "github.com/kballard/go-shellquote" "github.com/mickael-menu/zk/core/zk" "github.com/mickael-menu/zk/util/errors" - "github.com/mickael-menu/zk/util/exec" "github.com/mickael-menu/zk/util/opt" osutil "github.com/mickael-menu/zk/util/os" ) -// Edit starts the editor with the note at given path. -func Edit(zk *zk.Zk, path string) error { +// Edit starts the editor with the notes at given paths. +func Edit(zk *zk.Zk, paths ...string) error { editor := editor(zk) if editor.IsNull() { return fmt.Errorf("no editor set in config") @@ -28,9 +28,9 @@ func Edit(zk *zk.Zk, path string) error { if len(args) == 0 { return wrap(fmt.Errorf("editor command is not valid: %v", editor)) } - args = append(args, path) + args = append(args, paths...) - cmd := exec.CommandFromString(editor.String() + " '" + path + "'") + cmd := exec.Command(args[0], args[1:]...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout diff --git a/main.go b/main.go index ca5b3c9..48032e7 100644 --- a/main.go +++ b/main.go @@ -12,6 +12,7 @@ var cli struct { Index cmd.Index `cmd help:"Index the notes in the given directory to be searchable"` Init cmd.Init `cmd help:"Create a slip box in the given directory"` List cmd.List `cmd help:"List notes matching given criteria"` + Edit cmd.Edit `cmd help:"Edit notes matching given criteria"` New cmd.New `cmd help:"Create a new note in the given slip box directory"` NoInput NoInput `help:"Never prompt or ask for confirmation"` Version kong.VersionFlag `help:"Print zk version"`