diff --git a/CHANGELOG.md b/CHANGELOG.md index 79ab46a..fe28e53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file. 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 `--verbose` flag for `zk index` which prints detailed information about the indexing process. ### Fixed diff --git a/internal/adapter/lsp/server.go b/internal/adapter/lsp/server.go index 054631f..6973c8c 100644 --- a/internal/adapter/lsp/server.go +++ b/internal/adapter/lsp/server.go @@ -171,7 +171,7 @@ func NewServer(opts ServerOpts) *Server { return nil } - _, err = notebook.Index(false) + _, err = notebook.Index(core.NoteIndexOpts{}) server.logger.Err(err) 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]) } - force := false + opts := core.NoteIndexOpts{} if len(args) == 2 { options, ok := args[1].(map[string]interface{}) if !ok { return nil, fmt.Errorf("zk.index expects a dictionary of options as second argument, got: %v", args[1]) } 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 notebook.Index(force) + return notebook.Index(opts) } const cmdNew = "zk.new" diff --git a/internal/cli/cmd/index.go b/internal/cli/cmd/index.go index eba08d3..1a323b7 100644 --- a/internal/cli/cmd/index.go +++ b/internal/cli/cmd/index.go @@ -4,12 +4,14 @@ import ( "fmt" "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. type Index struct { - Force bool `short:"f" help:"Force indexing all the notes."` - Quiet bool `short:"q" help:"Do not print statistics nor progress."` + Force bool `short:"f" help:"Force indexing all the notes."` + 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 { @@ -22,7 +24,10 @@ func (cmd *Index) Run(container *cli.Container) error { return err } - stats, err := notebook.Index(cmd.Force) + stats, err := notebook.Index(core.NoteIndexOpts{ + Force: cmd.Force, + Verbose: cmd.Verbose, + }) if err != nil { return err } diff --git a/internal/cli/cmd/init.go b/internal/cli/cmd/init.go index b2d1085..d1d15b6 100644 --- a/internal/cli/cmd/init.go +++ b/internal/cli/cmd/init.go @@ -32,8 +32,7 @@ func (cmd *Init) Run(container *cli.Container) error { return err } - force := false - _, err = notebook.Index(force) + _, err = notebook.Index(core.NoteIndexOpts{}) if err != nil { return err } diff --git a/internal/core/note_index.go b/internal/core/note_index.go index d958617..7bb2144 100644 --- a/internal/core/note_index.go +++ b/internal/core/note_index.go @@ -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. type indexTask struct { - path string - config Config - force bool - index NoteIndex - parser NoteParser - logger util.Logger + path string + config Config + force bool + verbose bool + index NoteIndex + parser NoteParser + logger util.Logger } 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) } + print := func(message string) { + if t.verbose { + fmt.Println(message) + } + } + force := t.force || needsReindexing + type IgnoredFile struct { + Path string + Reason string + } + ignoredFiles := []IgnoredFile{} + shouldIgnorePath := func(path string) (bool, error) { + notifyIgnored := func(reason string) { + ignoredFiles = append(ignoredFiles, IgnoredFile{ + Path: path, + Reason: reason, + }) + } + group, err := t.config.GroupConfigForPath(path) if err != nil { return true, err } if filepath.Ext(path) != "."+group.Note.Extension { + notifyIgnored("expected extension \"" + group.Note.Extension + "\"") 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) } if matches { + notifyIgnored("matched ignore glob \"" + ignoreGlob + "\"") return true, nil } } @@ -123,6 +152,7 @@ func (t *indexTask) execute(callback func(change paths.DiffChange)) (NoteIndexin // FIXME: Use the FS? count, err := paths.Diff(source, target, force, func(change paths.DiffChange) error { callback(change) + print("- " + change.Kind.String() + " " + change.Path) absPath := filepath.Join(t.path, change.Path) switch change.Kind { @@ -147,9 +177,14 @@ func (t *indexTask) execute(callback func(change paths.DiffChange)) (NoteIndexin err := t.index.Remove(change.Path) t.logger.Err(err) } + return nil }) + for _, ignored := range ignoredFiles { + print("- ignored " + ignored.Path + ": " + ignored.Reason) + } + stats.SourceCount = count stats.Duration = time.Since(startTime) @@ -157,5 +192,6 @@ func (t *indexTask) execute(callback func(change paths.DiffChange)) (NoteIndexin err = t.index.SetNeedsReindexing(false) } + print("") return stats, wrap(err) } diff --git a/internal/core/notebook.go b/internal/core/notebook.go index 6da957f..197b575 100644 --- a/internal/core/notebook.go +++ b/internal/core/notebook.go @@ -62,8 +62,7 @@ type NotebookPorts struct { type NotebookFactory func(path string, config Config) (*Notebook, error) // Index indexes the content of the notebook to be searchable. -// If force is true, existing notes will be reindexed. -func (n *Notebook) Index(force bool) (stats NoteIndexingStats, err error) { +func (n *Notebook) Index(opts NoteIndexOpts) (stats NoteIndexingStats, err error) { // FIXME: Move out of Core bar := progressbar.NewOptions(-1, 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 { task := indexTask{ - path: n.Path, - config: n.Config, - force: force, - index: index, - parser: n, - logger: n.logger, + path: n.Path, + config: n.Config, + force: opts.Force, + verbose: opts.Verbose, + index: index, + parser: n, + logger: n.logger, } stats, err = task.execute(func(change paths.DiffChange) { bar.Add(1) diff --git a/internal/util/paths/diff.go b/internal/util/paths/diff.go index 4b1db5a..2f40ad4 100644 --- a/internal/util/paths/diff.go +++ b/internal/util/paths/diff.go @@ -20,10 +20,27 @@ const ( DiffAdded DiffKind = iota + 1 DiffModified DiffRemoved + DiffUnchanged ) // String implements Stringer. 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 { case DiffAdded: return "+" @@ -31,6 +48,8 @@ func (k DiffKind) String() string { return "~" case DiffRemoved: return "-" + case DiffUnchanged: + return "/" default: 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. if forceModified || p.source.Modified != p.target.Modified { change = &DiffChange{p.source.Path, DiffModified} + } else { + change = &DiffChange{p.source.Path, DiffUnchanged} } p.source = nil p.target = nil diff --git a/internal/util/paths/diff_test.go b/internal/util/paths/diff_test.go index 0197eff..32d7d4d 100644 --- a/internal/util/paths/diff_test.go +++ b/internal/util/paths/diff_test.go @@ -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) { @@ -86,6 +90,10 @@ func TestDiff(t *testing.T) { Path: "a/3", Kind: DiffRemoved, }, + { + Path: "b/1", + Kind: DiffUnchanged, + }, }) } @@ -165,6 +173,10 @@ func TestDiffWithMoreInSource(t *testing.T) { } test(t, source, target, false, []DiffChange{ + { + Path: "a/1", + Kind: DiffUnchanged, + }, { Path: "a/2", Kind: DiffAdded, @@ -192,6 +204,10 @@ func TestDiffWithMoreInTarget(t *testing.T) { } test(t, source, target, false, []DiffChange{ + { + Path: "a/1", + Kind: DiffUnchanged, + }, { Path: "a/2", Kind: DiffRemoved, diff --git a/main.go b/main.go index 521fa07..efdba59 100644 --- a/main.go +++ b/main.go @@ -87,7 +87,7 @@ func main() { // command, otherwise it would hide the stats. if ctx.Command() != "index" { if notebook, err := container.CurrentNotebook(); err == nil { - _, err = notebook.Index(false) + _, err = notebook.Index(core.NoteIndexOpts{}) ctx.FatalIfErrorf(err) } }