Add a verbose mode to `zk index` (#103)

pull/104/head
Mickaël Menu 3 years ago committed by GitHub
parent 59b8269344
commit aea5308f66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file.
note-detail = "{{filename-stem}}" note-detail = "{{filename-stem}}"
``` ```
* New `--dry-run` flag for `zk new` which prints out the path and content of the generated note instead of saving it to the file system. * New `--dry-run` flag for `zk new` which prints out the path and content of the generated note instead of saving it to the file system.
* New `--verbose` flag for `zk index` which prints detailed information about the indexing process.
### Fixed ### Fixed

@ -171,7 +171,7 @@ func NewServer(opts ServerOpts) *Server {
return nil return nil
} }
_, err = notebook.Index(false) _, err = notebook.Index(core.NoteIndexOpts{})
server.logger.Err(err) server.logger.Err(err)
return nil return nil
} }
@ -485,14 +485,17 @@ func (s *Server) executeCommandIndex(args []interface{}) (interface{}, error) {
return nil, fmt.Errorf("zk.index expects a notebook path as first argument, got: %v", args[0]) return nil, fmt.Errorf("zk.index expects a notebook path as first argument, got: %v", args[0])
} }
force := false opts := core.NoteIndexOpts{}
if len(args) == 2 { if len(args) == 2 {
options, ok := args[1].(map[string]interface{}) options, ok := args[1].(map[string]interface{})
if !ok { if !ok {
return nil, fmt.Errorf("zk.index expects a dictionary of options as second argument, got: %v", args[1]) return nil, fmt.Errorf("zk.index expects a dictionary of options as second argument, got: %v", args[1])
} }
if forceOption, ok := options["force"]; ok { if forceOption, ok := options["force"]; ok {
force = toBool(forceOption) opts.Force = toBool(forceOption)
}
if verboseOption, ok := options["verbose"]; ok {
opts.Verbose = toBool(verboseOption)
} }
} }
@ -501,7 +504,7 @@ func (s *Server) executeCommandIndex(args []interface{}) (interface{}, error) {
return nil, err return nil, err
} }
return notebook.Index(force) return notebook.Index(opts)
} }
const cmdNew = "zk.new" const cmdNew = "zk.new"

@ -4,12 +4,14 @@ import (
"fmt" "fmt"
"github.com/mickael-menu/zk/internal/cli" "github.com/mickael-menu/zk/internal/cli"
"github.com/mickael-menu/zk/internal/core"
) )
// Index indexes the content of all the notes in the notebook. // Index indexes the content of all the notes in the notebook.
type Index struct { type Index struct {
Force bool `short:"f" help:"Force indexing all the notes."` Force bool `short:"f" help:"Force indexing all the notes."`
Quiet bool `short:"q" help:"Do not print statistics nor progress."` Verbose bool `short:"v" help:"Print detailed information about the indexing process."`
Quiet bool `short:"q" help:"Do not print statistics nor progress."`
} }
func (cmd *Index) Help() string { func (cmd *Index) Help() string {
@ -22,7 +24,10 @@ func (cmd *Index) Run(container *cli.Container) error {
return err return err
} }
stats, err := notebook.Index(cmd.Force) stats, err := notebook.Index(core.NoteIndexOpts{
Force: cmd.Force,
Verbose: cmd.Verbose,
})
if err != nil { if err != nil {
return err return err
} }

@ -32,8 +32,7 @@ func (cmd *Init) Run(container *cli.Container) error {
return err return err
} }
force := false _, err = notebook.Index(core.NoteIndexOpts{})
_, err = notebook.Index(force)
if err != nil { if err != nil {
return err return err
} }

@ -67,14 +67,22 @@ func (s NoteIndexingStats) String() string {
) )
} }
// NoteIndexOpts holds the options for the indexing process.
type NoteIndexOpts struct {
// When true, existing notes will be reindexed.
Force bool
Verbose bool
}
// indexTask indexes the notes in the given directory with the NoteIndex. // indexTask indexes the notes in the given directory with the NoteIndex.
type indexTask struct { type indexTask struct {
path string path string
config Config config Config
force bool force bool
index NoteIndex verbose bool
parser NoteParser index NoteIndex
logger util.Logger parser NoteParser
logger util.Logger
} }
func (t *indexTask) execute(callback func(change paths.DiffChange)) (NoteIndexingStats, error) { func (t *indexTask) execute(callback func(change paths.DiffChange)) (NoteIndexingStats, error) {
@ -88,15 +96,35 @@ func (t *indexTask) execute(callback func(change paths.DiffChange)) (NoteIndexin
return stats, wrap(err) return stats, wrap(err)
} }
print := func(message string) {
if t.verbose {
fmt.Println(message)
}
}
force := t.force || needsReindexing force := t.force || needsReindexing
type IgnoredFile struct {
Path string
Reason string
}
ignoredFiles := []IgnoredFile{}
shouldIgnorePath := func(path string) (bool, error) { shouldIgnorePath := func(path string) (bool, error) {
notifyIgnored := func(reason string) {
ignoredFiles = append(ignoredFiles, IgnoredFile{
Path: path,
Reason: reason,
})
}
group, err := t.config.GroupConfigForPath(path) group, err := t.config.GroupConfigForPath(path)
if err != nil { if err != nil {
return true, err return true, err
} }
if filepath.Ext(path) != "."+group.Note.Extension { if filepath.Ext(path) != "."+group.Note.Extension {
notifyIgnored("expected extension \"" + group.Note.Extension + "\"")
return true, nil return true, nil
} }
@ -106,6 +134,7 @@ func (t *indexTask) execute(callback func(change paths.DiffChange)) (NoteIndexin
return true, errors.Wrapf(err, "failed to match ignore glob %s to %s", ignoreGlob, path) return true, errors.Wrapf(err, "failed to match ignore glob %s to %s", ignoreGlob, path)
} }
if matches { if matches {
notifyIgnored("matched ignore glob \"" + ignoreGlob + "\"")
return true, nil return true, nil
} }
} }
@ -123,6 +152,7 @@ func (t *indexTask) execute(callback func(change paths.DiffChange)) (NoteIndexin
// FIXME: Use the FS? // FIXME: Use the FS?
count, err := paths.Diff(source, target, force, func(change paths.DiffChange) error { count, err := paths.Diff(source, target, force, func(change paths.DiffChange) error {
callback(change) callback(change)
print("- " + change.Kind.String() + " " + change.Path)
absPath := filepath.Join(t.path, change.Path) absPath := filepath.Join(t.path, change.Path)
switch change.Kind { switch change.Kind {
@ -147,9 +177,14 @@ func (t *indexTask) execute(callback func(change paths.DiffChange)) (NoteIndexin
err := t.index.Remove(change.Path) err := t.index.Remove(change.Path)
t.logger.Err(err) t.logger.Err(err)
} }
return nil return nil
}) })
for _, ignored := range ignoredFiles {
print("- ignored " + ignored.Path + ": " + ignored.Reason)
}
stats.SourceCount = count stats.SourceCount = count
stats.Duration = time.Since(startTime) stats.Duration = time.Since(startTime)
@ -157,5 +192,6 @@ func (t *indexTask) execute(callback func(change paths.DiffChange)) (NoteIndexin
err = t.index.SetNeedsReindexing(false) err = t.index.SetNeedsReindexing(false)
} }
print("")
return stats, wrap(err) return stats, wrap(err)
} }

@ -62,8 +62,7 @@ type NotebookPorts struct {
type NotebookFactory func(path string, config Config) (*Notebook, error) type NotebookFactory func(path string, config Config) (*Notebook, error)
// Index indexes the content of the notebook to be searchable. // Index indexes the content of the notebook to be searchable.
// If force is true, existing notes will be reindexed. func (n *Notebook) Index(opts NoteIndexOpts) (stats NoteIndexingStats, err error) {
func (n *Notebook) Index(force bool) (stats NoteIndexingStats, err error) {
// FIXME: Move out of Core // FIXME: Move out of Core
bar := progressbar.NewOptions(-1, bar := progressbar.NewOptions(-1,
progressbar.OptionSetWriter(os.Stderr), progressbar.OptionSetWriter(os.Stderr),
@ -73,12 +72,13 @@ func (n *Notebook) Index(force bool) (stats NoteIndexingStats, err error) {
err = n.index.Commit(func(index NoteIndex) error { err = n.index.Commit(func(index NoteIndex) error {
task := indexTask{ task := indexTask{
path: n.Path, path: n.Path,
config: n.Config, config: n.Config,
force: force, force: opts.Force,
index: index, verbose: opts.Verbose,
parser: n, index: index,
logger: n.logger, parser: n,
logger: n.logger,
} }
stats, err = task.execute(func(change paths.DiffChange) { stats, err = task.execute(func(change paths.DiffChange) {
bar.Add(1) bar.Add(1)

@ -20,10 +20,27 @@ const (
DiffAdded DiffKind = iota + 1 DiffAdded DiffKind = iota + 1
DiffModified DiffModified
DiffRemoved DiffRemoved
DiffUnchanged
) )
// String implements Stringer. // String implements Stringer.
func (k DiffKind) String() string { func (k DiffKind) String() string {
switch k {
case DiffAdded:
return "added"
case DiffModified:
return "modified"
case DiffRemoved:
return "removed"
case DiffUnchanged:
return "unchanged"
default:
panic(fmt.Sprintf("%d: unknown DiffKind", int(k)))
}
}
// Symbol returns a single character symbol representing this change.
func (k DiffKind) Symbol() string {
switch k { switch k {
case DiffAdded: case DiffAdded:
return "+" return "+"
@ -31,6 +48,8 @@ func (k DiffKind) String() string {
return "~" return "~"
case DiffRemoved: case DiffRemoved:
return "-" return "-"
case DiffUnchanged:
return "/"
default: default:
panic(fmt.Sprintf("%d: unknown DiffKind", int(k))) panic(fmt.Sprintf("%d: unknown DiffKind", int(k)))
} }
@ -102,6 +121,8 @@ func (p *diffPair) diff(forceModified bool) *DiffChange {
case p.source.Path == p.target.Path: // Same files, compare their modification date. case p.source.Path == p.target.Path: // Same files, compare their modification date.
if forceModified || p.source.Modified != p.target.Modified { if forceModified || p.source.Modified != p.target.Modified {
change = &DiffChange{p.source.Path, DiffModified} change = &DiffChange{p.source.Path, DiffModified}
} else {
change = &DiffChange{p.source.Path, DiffUnchanged}
} }
p.source = nil p.source = nil
p.target = nil p.target = nil

@ -35,7 +35,11 @@ func TestNoDiff(t *testing.T) {
}, },
} }
test(t, files, files, false, []DiffChange{}) test(t, files, files, false, []DiffChange{
{Path: "a/1", Kind: DiffUnchanged},
{Path: "a/2", Kind: DiffUnchanged},
{Path: "b/1", Kind: DiffUnchanged},
})
} }
func TestDiff(t *testing.T) { func TestDiff(t *testing.T) {
@ -86,6 +90,10 @@ func TestDiff(t *testing.T) {
Path: "a/3", Path: "a/3",
Kind: DiffRemoved, Kind: DiffRemoved,
}, },
{
Path: "b/1",
Kind: DiffUnchanged,
},
}) })
} }
@ -165,6 +173,10 @@ func TestDiffWithMoreInSource(t *testing.T) {
} }
test(t, source, target, false, []DiffChange{ test(t, source, target, false, []DiffChange{
{
Path: "a/1",
Kind: DiffUnchanged,
},
{ {
Path: "a/2", Path: "a/2",
Kind: DiffAdded, Kind: DiffAdded,
@ -192,6 +204,10 @@ func TestDiffWithMoreInTarget(t *testing.T) {
} }
test(t, source, target, false, []DiffChange{ test(t, source, target, false, []DiffChange{
{
Path: "a/1",
Kind: DiffUnchanged,
},
{ {
Path: "a/2", Path: "a/2",
Kind: DiffRemoved, Kind: DiffRemoved,

@ -87,7 +87,7 @@ func main() {
// command, otherwise it would hide the stats. // command, otherwise it would hide the stats.
if ctx.Command() != "index" { if ctx.Command() != "index" {
if notebook, err := container.CurrentNotebook(); err == nil { if notebook, err := container.CurrentNotebook(); err == nil {
_, err = notebook.Index(false) _, err = notebook.Index(core.NoteIndexOpts{})
ctx.FatalIfErrorf(err) ctx.FatalIfErrorf(err)
} }
} }

Loading…
Cancel
Save