Author: Kevin Schoon [me@kevinschoon.com]
Hash: 577d179ebb1eb753cbe1a012cdd9ea484eb9ad5c
Timestamp: Fri, 10 Jun 2022 18:41:21 +0000 (2 years ago)

+92 -7 +/-3 browse
add tree output
1diff --git a/pkg/cmd/app.go b/pkg/cmd/app.go
2index 6345381..62b9463 100644
3--- a/pkg/cmd/app.go
4+++ b/pkg/cmd/app.go
5 @@ -99,22 +99,45 @@ data structure. It uses SQLite to store note content and metadata.
6 Usage: "list only one note per line",
7 Value: false,
8 },
9+ &cli.BoolFlag{
10+ Name: "tree",
11+ Aliases: []string{"t"},
12+ Usage: "display notes as a tree",
13+ Value: true,
14+ },
15 },
16 Action: func(ctx *cli.Context) error {
17+ var notes []*hierarchy.Note
18 path := ctx.Args().First()
19- if path == "" {
20- notes, err := hierarchy.Load(*cfg)
21+ if path != "" {
22+ n, err := hierarchy.Find(*cfg, path)
23 if err != nil {
24 return err
25 }
26- return json.NewEncoder(os.Stdout).Encode(notes)
27+ notes = n.Descendants
28+ } else {
29+ n, err := hierarchy.Load(*cfg)
30+ if err != nil {
31+ return err
32+ }
33+ notes = n
34 }
35-
36- note, err := hierarchy.Find(*cfg, path)
37- if err != nil {
38+ rootName := path
39+ if path == "" {
40+ rootName = "/"
41+ }
42+ if ctx.Bool("tree") {
43+ tree := hierarchy.Tree{
44+ RootName: rootName,
45+ Notes: notes,
46+ }.String()
47+ _, err := fmt.Fprintln(os.Stdout, tree)
48 return err
49 }
50- return json.NewEncoder(os.Stdout).Encode(note)
51+ for _, note := range notes {
52+ fmt.Println(note.Name, note.CreatedAt)
53+ }
54+ return nil
55 },
56 },
57 {
58 diff --git a/pkg/hierarchy/display.go b/pkg/hierarchy/display.go
59new file mode 100644
60index 0000000..34afb51
61--- /dev/null
62+++ b/pkg/hierarchy/display.go
63 @@ -0,0 +1,2 @@
64+ package hierarchy
65+
66 diff --git a/pkg/hierarchy/tree.go b/pkg/hierarchy/tree.go
67new file mode 100644
68index 0000000..0c02123
69--- /dev/null
70+++ b/pkg/hierarchy/tree.go
71 @@ -0,0 +1,60 @@
72+ package hierarchy
73+
74+ import (
75+ "bytes"
76+ "fmt"
77+ "io"
78+ )
79+
80+ const (
81+ emptySpace = " "
82+ middleItem = "├──"
83+ continueItem = "│ "
84+ lastItem = "└──"
85+ )
86+
87+ type Tree struct {
88+ RootName string
89+ Notes []*Note
90+ }
91+
92+ func (t Tree) next(value bool, depth []bool) (result []bool) {
93+ return append(append(result, depth...), value)
94+ }
95+
96+ func (t Tree) fill(w io.Writer, depth []bool) {
97+ for i := 0; i < len(depth); i++ {
98+ if depth[i] {
99+ fmt.Fprint(w, continueItem)
100+ } else {
101+ fmt.Fprint(w, emptySpace)
102+ }
103+ }
104+ }
105+
106+ func (t Tree) write(notes []*Note, depth []bool, buf *bytes.Buffer) {
107+ n := len(notes)
108+ for i, note := range notes {
109+ t.fill(buf, depth)
110+ np := ReadPath(note.Name)
111+ last := i == n-1
112+ if last {
113+ buf.WriteString(lastItem)
114+ buf.WriteString(np.Name() + "\n")
115+ } else {
116+ buf.WriteString(middleItem)
117+ buf.WriteString(np.Name() + "\n")
118+ }
119+ if len(note.Descendants) > 0 {
120+ t.write(note.Descendants, t.next(len(note.Descendants) >
121+ 0 && !last, depth), buf)
122+ }
123+ }
124+ }
125+
126+ func (t Tree) String() string {
127+ buf := bytes.NewBuffer(nil)
128+ buf.WriteString(fmt.Sprintf("[%s]\n", t.RootName))
129+ t.write(t.Notes, nil, buf)
130+ return buf.String()
131+ }