diff --git a/cmd/config.go b/cmd/config.go index 4385a50..4588b04 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -22,6 +22,7 @@ type config struct { addTags string dryRun bool archive string + dedupe bool } func getConfig() config { @@ -39,6 +40,7 @@ func getConfig() config { flag.StringVar(&tagss, "tags", "", "csv of all tags to find, -x to invert") flag.StringVar(&config.search, "search", "", "fts case insensitive") flag.BoolVar(&config.edit, "e", false, "edit file") + flag.BoolVar(&config.dedupe, "dedupe", false, "dedupe file") flag.BoolVar(&config.dryRun, "dry-run", false, "dry run") flag.StringVar(&config.add, "add", "", "todo to add") flag.StringVar(&config.addSchedule, "add-schedule", "", "todo to add schedule") diff --git a/cmd/go.mod b/cmd/go.mod index b82262e..e2edeff 100644 --- a/cmd/go.mod +++ b/cmd/go.mod @@ -1,6 +1,6 @@ module pttodo-cli -go 1.17 +go 1.21 require ( gitea.inhome.blapointe.com/gogs/pttodo v0.0.0-20231109151914-5d74b458d542 diff --git a/cmd/main.go b/cmd/main.go index 3008245..cd85b4e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -7,6 +7,8 @@ import ( "log" "os" + "slices" + "gitea.inhome.blapointe.com/gogs/pttodo/pttodo" "gopkg.in/yaml.v2" @@ -32,6 +34,8 @@ func _main() error { return merge(&config) } else if config.archive != "" { return archive(&config) + } else if config.dedupe { + return dedupe(&config) } else { if err := add(&config); err != nil { return err @@ -43,6 +47,54 @@ func _main() error { } } +func dedupe(config *config) error { + baseReader, err := filePathReader(config.target) + if err != nil { + return err + } + baseB, err := ioutil.ReadAll(baseReader) + if err != nil { + return err + } + + var base pttodo.Root + if err := yaml.Unmarshal(baseB, &base); err != nil { + return err + } + + do := func(todos []pttodo.Todo) []pttodo.Todo { + i := len(todos) - 1 + for i >= 0 { + j := slices.IndexFunc(todos, func(todo pttodo.Todo) bool { + return todo.Equals(todos[i]) + }) + if j >= 0 && j != i { + todos[j] = todos[i] + base.Done = append(base.Done, todos[j]) + todos = todos[:i] + } + i -= 1 + } + return todos + } + + base.Todo = do(base.Todo) + base.Scheduled = do(base.Scheduled) + + if tmppath, err := marshalRootToTempFile(base); err != nil { + return err + } else if config.dryRun { + log.Println("===before===") + _dump(os.Stdout, []string{config.target}, config.tags, config.search, config.root) + log.Println("===after===") + _dump(os.Stdout, []string{tmppath}, config.tags, config.search, config.root) + } else if err := rename(tmppath, config.target); err != nil { + return err + } + + return nil +} + func archive(config *config) error { if config.archive == "" { return nil diff --git a/cmd/testdata/1.yaml b/cmd/testdata/1.yaml index ca66683..f0391e4 100755 --- a/cmd/testdata/1.yaml +++ b/cmd/testdata/1.yaml @@ -1,4 +1,18 @@ todo: - "1" -scheduled: [] -done: [] +- "2" +- "1" +- "2" +- "2" +scheduled: +- todo: "10" +- todo: "20" +- todo: "10" +- todo: "20" +- todo: "20" +done: +- todo: "100" +- todo: "200" +- todo: "100" +- todo: "200" +- todo: "200" diff --git a/go.mod b/go.mod index 88ebfa0..dca6add 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module gitea.inhome.blapointe.com/gogs/pttodo -go 1.17 +go 1.21 require ( github.com/robfig/cron/v3 v3.0.1