10 Commits

Author SHA1 Message Date
Bel LaPointe
b2a51e65b0 time for edit.go 2023-11-06 13:15:01 -07:00
Bel LaPointe
f75dcb3f7a test touched a local file oop 2023-11-06 13:14:20 -07:00
Bel LaPointe
d4466598b4 drop test file 2023-11-06 13:13:42 -07:00
Bel LaPointe
3ba3b78afc use default for effectively default 2023-11-06 13:12:09 -07:00
Bel LaPointe
f2e3e6f505 rm extra mem 2023-11-06 13:11:40 -07:00
Bel LaPointe
1ce120a647 shuffle code 2023-11-06 13:11:22 -07:00
Bel LaPointe
bfdeebb7a2 use pttodo.Todos.Like...() 2023-11-06 13:06:11 -07:00
Bel LaPointe
39345e5e2a use pttodo.NewRootFromFiles in cli 2023-11-06 12:58:46 -07:00
Bel LaPointe
bfcec9d1c5 add pttodo.NewRootFromFiles 2023-11-06 12:58:06 -07:00
Bel LaPointe
3e1f58c7b9 test pttodo.NewRootFromFile accepts both []Todo and Root 2023-11-06 12:54:46 -07:00
7 changed files with 168 additions and 92 deletions

View File

@@ -24,7 +24,7 @@ func TestConfigTargets(t *testing.T) {
},
"one file": {
setup: func(t *testing.T, d string) {
touch(t, "x")
touch(t, path.Join(d, "x"))
},
given: "x",
want: []string{"x"},

View File

@@ -1,13 +1,8 @@
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"gogs.inhome.blapointe.com/bel/pttodo/pttodo"
"gopkg.in/yaml.v2"
@@ -18,103 +13,32 @@ func dump(config config) error {
}
func _dump(writer io.Writer, filepaths []string, tags []string, search, rootDisplay string) error {
var root pttodo.Root
for _, p := range filepaths {
results, err := filepath.Glob(p + ".*")
if err != nil {
return err
}
for _, result := range results {
if result == p {
continue
}
filepaths = append(filepaths, result)
}
root, err := pttodo.NewRootFromFiles(filepaths...)
if err != nil {
return err
}
for _, filepath := range filepaths {
reader, err := filePathReader(filepath)
if err != nil {
return err
}
b, err := ioutil.ReadAll(reader)
if err != nil {
return err
}
var root2, root2post pttodo.Root
if err := yaml.Unmarshal(b, &root2); err != nil {
return err
}
if err := yaml.Unmarshal(b, &root2post); err != nil {
return err
}
root2.MoveScheduledToTodo()
if !root2.Equals(root2post) {
log.Printf("refreshing %s", filepath)
b3, err := yaml.Marshal(root2)
if err != nil {
return err
}
if err := os.WriteFile(filepath, b3, os.ModePerm); err != nil {
return err
}
} else {
//log.Printf("not refreshing %s", filepath)
}
root.MergeIn(root2)
for _, x := range []*[]pttodo.Todo{
&root.Todo,
&root.Scheduled,
&root.Done,
} {
y := pttodo.Todos(*x)
y = y.LikeTags(tags)
y = y.LikeSearch(search)
*x = y
}
root.MoveScheduledToTodo()
var v interface{} = root
switch rootDisplay {
case DUMP_ALL:
case DUMP_TODO:
v = root.Todo
case DUMP_SCHEDULED:
v = root.Scheduled
case DUMP_DONE:
v = root.Done
}
if todos, ok := v.([]pttodo.Todo); ok {
if len(tags) > 0 {
result := make([]pttodo.Todo, 0, len(todos))
for _, todo := range todos {
skip := false
for _, tag := range tags {
positiveTag := strings.TrimLeft(tag, "-")
hasTag := strings.Contains(todo.Tags, positiveTag)
wantToHaveTag := !strings.HasPrefix(tag, "-")
skip = skip || !(hasTag == wantToHaveTag)
}
if !skip {
result = append(result, todo)
}
}
todos = result
}
if len(search) > 0 {
result := make([]pttodo.Todo, 0, len(todos))
for _, todo := range todos {
if strings.Contains(strings.ToLower(fmt.Sprint(todo)), strings.ToLower(search)) {
result = append(result, todo)
}
}
todos = result
}
v = todos
default:
}
b2, err := yaml.Marshal(v)
if err != nil {
return err
}
fmt.Fprintf(writer, "%s\n", b2)
return nil
return yaml.NewEncoder(writer).Encode(v)
}

0
cmd/x
View File

View File

@@ -1,6 +1,7 @@
package pttodo
import (
"bytes"
"os"
yaml "gopkg.in/yaml.v2"
@@ -12,7 +13,24 @@ type Root struct {
Done []Todo
}
func NewRootFromFiles(p ...string) (Root, error) {
var result Root
for _, p := range p {
subroot, err := NewRootFromFile(p)
if err != nil {
return Root{}, err
}
result.MergeIn(subroot)
}
result.AutoMove()
return result, nil
}
func NewRootFromFile(p string) (Root, error) {
if b, err := os.ReadFile(p); err == nil && len(bytes.TrimSpace(b)) == 0 {
return Root{}, nil
}
f, err := os.Open(p)
if os.IsNotExist(err) {
return Root{}, nil
@@ -24,7 +42,11 @@ func NewRootFromFile(p string) (Root, error) {
var result Root
if err := yaml.NewDecoder(f).Decode(&result); err != nil {
return Root{}, err
todos, err2 := NewTodosFromFile(p)
if err2 != nil {
return Root{}, err
}
result.Todo = todos
}
result.AutoMove()

View File

@@ -4,6 +4,8 @@ import (
"bytes"
"encoding/json"
"fmt"
"os"
"path"
"strconv"
"strings"
"testing"
@@ -180,3 +182,78 @@ done:
t.Fatalf("want\n\t%q, got\n\t%q", want, string(got))
}
}
func TestRootFromFile(t *testing.T) {
cases := map[string]struct {
given string
want Root
}{
"empty": {},
"happy": {
given: `{"todo":["a", "b"],"scheduled":["c"], "done":[{"todo": "d"}]}`,
want: Root{
Todo: []Todo{
Todo{Todo: "a"},
Todo{Todo: "b"},
},
Scheduled: []Todo{
Todo{Todo: "c"},
},
Done: []Todo{
Todo{Todo: "d"},
},
},
},
"todos": {
given: `["a", {"todo": "b"}]`,
want: Root{
Todo: []Todo{
{Todo: "a"},
{Todo: "b"},
},
},
},
}
for name, d := range cases {
c := d
t.Run(name, func(t *testing.T) {
d := t.TempDir()
p := path.Join(d, "input.yaml")
if err := os.WriteFile(p, []byte(c.given), os.ModePerm); err != nil {
t.Fatal(err)
}
got, err := NewRootFromFile(p)
if err != nil {
t.Fatal(err)
}
if fmt.Sprintf("%+v", got) != fmt.Sprintf("%+v", c.want) {
t.Errorf("want\n\t%+v, got\n\t%+v", c.want, got)
}
})
}
}
func TestRootFromFiles(t *testing.T) {
d := t.TempDir()
ps := []string{
path.Join(d, "a"),
path.Join(d, "b"),
}
os.WriteFile(ps[0], []byte(`["a"]`), os.ModePerm)
os.WriteFile(ps[1], []byte(`["b"]`), os.ModePerm)
got, err := NewRootFromFiles(ps...)
if err != nil {
t.Fatal(err)
}
want := Root{
Todo: []Todo{
{Todo: "a"},
{Todo: "b"},
},
}
if fmt.Sprintf("%+v", got) != fmt.Sprintf("%+v", want) {
t.Errorf("want\n\t%+v, got \n\t%+v", want, got)
}
}

36
pttodo/todos.go Normal file
View File

@@ -0,0 +1,36 @@
package pttodo
import "strings"
type Todos []Todo
func (todos Todos) LikeSearch(search string) Todos {
return todos.Like(func(todo Todo) bool {
return strings.Contains(
strings.ToLower(todo.Todo),
strings.ToLower(search),
)
})
}
func (todos Todos) LikeTags(tags []string) Todos {
return todos.Like(func(todo Todo) bool {
matches := true
for _, tag := range tags {
str := strings.TrimLeft(tag, "-")
want := !strings.HasPrefix(tag, "-")
matches = matches && strings.Contains(todo.Tags, str) == want
}
return matches
})
}
func (todos Todos) Like(like func(Todo) bool) Todos {
result := make(Todos, 0)
for i := range todos {
if like(todos[i]) {
result = append(result, todos[i])
}
}
return result
}

17
pttodo/todos_test.go Normal file
View File

@@ -0,0 +1,17 @@
package pttodo
import "testing"
func TestTodosLikeTags(t *testing.T) {
todos := Todos{
{Todo: "a", Tags: "x"},
{Todo: "b", Tags: "x,y"},
}
result := todos.LikeTags([]string{"x", "-y"})
if len(result) != 1 {
t.Error(result)
} else if result[0].Todo != "a" {
t.Error(result[0].Todo)
}
}