Author: Kevin Schoon [me@kevinschoon.com]
Hash: fdb8a29939b87ca83bd228cee76b649ca2ffccda
Timestamp: Mon, 04 Dec 2023 11:40:20 +0000 (7 months ago)

+52 -15 +/-4 browse
show modification time on righthand side of tree output
1diff --git a/go.mod b/go.mod
2index 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
23index 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
40index 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
89index 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)