Commit
+52 -15 +/-4 browse
1 | diff --git a/go.mod b/go.mod |
2 | index 244d6a4..a88dd56 100644 |
3 | --- a/go.mod |
4 | +++ b/go.mod |
5 | @@ -7,6 +7,7 @@ require ( |
6 | github.com/hanwen/go-fuse v1.0.0 |
7 | github.com/mattn/go-sqlite3 v1.14.13 |
8 | github.com/urfave/cli/v2 v2.8.1 |
9 | + golang.org/x/term v0.15.0 |
10 | ) |
11 | |
12 | require ( |
13 | @@ -14,7 +15,7 @@ require ( |
14 | github.com/kr/pretty v0.1.0 // indirect |
15 | github.com/russross/blackfriday/v2 v2.1.0 // indirect |
16 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect |
17 | - golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect |
18 | + golang.org/x/sys v0.15.0 // indirect |
19 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect |
20 | gopkg.in/yaml.v2 v2.4.0 // indirect |
21 | ) |
22 | diff --git a/go.sum b/go.sum |
23 | index 14a0f68..9f05c40 100644 |
24 | --- a/go.sum |
25 | +++ b/go.sum |
26 | @@ -18,8 +18,10 @@ github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5 |
27 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= |
28 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= |
29 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
30 | - golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU= |
31 | - golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
32 | + golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= |
33 | + golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= |
34 | + golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= |
35 | + golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= |
36 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
37 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= |
38 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
39 | diff --git a/pkg/cmd/app.go b/pkg/cmd/app.go |
40 | index 905134a..e037ad5 100644 |
41 | --- a/pkg/cmd/app.go |
42 | +++ b/pkg/cmd/app.go |
43 | @@ -120,6 +120,18 @@ data structure. It uses SQLite to store note content and metadata. |
44 | Usage: "display notes as a tree", |
45 | Value: true, |
46 | }, |
47 | + &cli.BoolFlag{ |
48 | + Name: "timestamp", |
49 | + Aliases: []string{"m"}, |
50 | + Usage: "print the modification timestamp along side the note", |
51 | + Value: true, |
52 | + }, |
53 | + &cli.StringFlag{ |
54 | + Name: "format", |
55 | + Aliases: []string{"d"}, |
56 | + Usage: "timestamp format when enabled", |
57 | + Value: time.UnixDate, |
58 | + }, |
59 | }, |
60 | Action: func(ctx *cli.Context) error { |
61 | var notes []*hierarchy.Note |
62 | @@ -143,14 +155,19 @@ data structure. It uses SQLite to store note content and metadata. |
63 | } |
64 | if ctx.Bool("tree") { |
65 | tree := hierarchy.Tree{ |
66 | - RootName: rootName, |
67 | - Notes: notes, |
68 | + RootName: rootName, |
69 | + Notes: notes, |
70 | + ShowModification: ctx.Bool("timestamp"), |
71 | + ModificationFormat: ctx.String("format"), |
72 | }.String() |
73 | _, err := fmt.Fprintln(os.Stdout, tree) |
74 | - return err |
75 | - } |
76 | - for _, note := range notes { |
77 | - fmt.Println(note.Name, note.CreatedAt) |
78 | + if err != nil { |
79 | + return err |
80 | + } |
81 | + } else { |
82 | + for _, note := range notes { |
83 | + fmt.Println(note.Name, note.CreatedAt) |
84 | + } |
85 | } |
86 | return nil |
87 | }, |
88 | diff --git a/pkg/hierarchy/tree.go b/pkg/hierarchy/tree.go |
89 | index 68978f8..0874a16 100644 |
90 | --- a/pkg/hierarchy/tree.go |
91 | +++ b/pkg/hierarchy/tree.go |
92 | @@ -4,6 +4,9 @@ import ( |
93 | "bytes" |
94 | "fmt" |
95 | "io" |
96 | + "strings" |
97 | + |
98 | + "golang.org/x/term" |
99 | ) |
100 | |
101 | const ( |
102 | @@ -11,14 +14,18 @@ const ( |
103 | middleItem = "├──" |
104 | continueItem = "│ " |
105 | lastItem = "└──" |
106 | + padOffset = len(emptySpace) |
107 | + padCharacter = " " |
108 | ) |
109 | |
110 | type Tree struct { |
111 | - RootName string |
112 | - Notes []*Note |
113 | + RootName string |
114 | + Notes []*Note |
115 | + ShowModification bool |
116 | + ModificationFormat string |
117 | } |
118 | |
119 | - func (t Tree) fill(w io.Writer, depth []bool) { |
120 | + func (t Tree) fill(w io.Writer, depth []bool) int { |
121 | for i := 0; i < len(depth); i++ { |
122 | if depth[i] { |
123 | fmt.Fprint(w, continueItem) |
124 | @@ -26,21 +33,31 @@ func (t Tree) fill(w io.Writer, depth []bool) { |
125 | fmt.Fprint(w, emptySpace) |
126 | } |
127 | } |
128 | + return len(depth) * len(emptySpace) |
129 | } |
130 | |
131 | func (t Tree) write(notes []*Note, depth []bool, buf *bytes.Buffer) { |
132 | n := len(notes) |
133 | for i, note := range notes { |
134 | - t.fill(buf, depth) |
135 | + padding := t.fill(buf, depth) |
136 | np := ReadPath(note.Name) |
137 | last := i == n-1 |
138 | if last { |
139 | buf.WriteString(lastItem) |
140 | - buf.WriteString(np.Name() + "\n") |
141 | } else { |
142 | buf.WriteString(middleItem) |
143 | - buf.WriteString(np.Name() + "\n") |
144 | } |
145 | + width, _, err := term.GetSize(0) |
146 | + if err != nil { |
147 | + panic(err) |
148 | + } |
149 | + rightColumn := "" |
150 | + if t.ShowModification { |
151 | + timestamp := note.ModifiedAt.Format(t.ModificationFormat) |
152 | + padding = width - len(np.Name()) - padding - len(timestamp) - padOffset |
153 | + rightColumn = strings.Repeat(padCharacter, padding) + timestamp |
154 | + } |
155 | + buf.WriteString(np.Name() + rightColumn + "\n") |
156 | if len(note.Descendants) > 0 { |
157 | t.write(note.Descendants, |
158 | append(depth, len(note.Descendants) > 0 && !last), buf) |