forked from maaslalani/nap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlist.go
142 lines (122 loc) · 3.84 KB
/
list.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package main
import (
"fmt"
"io"
"strings"
"time"
"github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea"
"github.com/dustin/go-humanize"
)
// FilterValue is the snippet filter value that can be used when searching.
func (s Snippet) FilterValue() string {
return s.Folder + "/" + s.Name + "\n" + "+" + strings.Join(s.Tags, "+") + "\n" + s.Language
}
// snippetDelegate represents the snippet list item.
type snippetDelegate struct {
styles SnippetsBaseStyle
state state
}
// Height is the number of lines the snippet list item takes up.
func (d snippetDelegate) Height() int {
return 2
}
// Spacing is the number of lines to insert between list items.
func (d snippetDelegate) Spacing() int {
return 1
}
// Update is called when the list is updated.
// We use this to update the snippet code view.
func (d snippetDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd {
return func() tea.Msg {
if m.SelectedItem() == nil {
return nil
}
return updateContentMsg(m.SelectedItem().(Snippet))
}
}
// Render renders the list item for the snippet which includes the title,
// folder, and date.
func (d snippetDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) {
if item == nil {
return
}
s, ok := item.(Snippet)
if !ok {
return
}
titleStyle := d.styles.SelectedTitle
subtitleStyle := d.styles.SelectedSubtitle
if d.state == copyingState {
titleStyle = d.styles.CopiedTitle
subtitleStyle = d.styles.CopiedSubtitle
} else if d.state == deletingState {
titleStyle = d.styles.DeletedTitle
subtitleStyle = d.styles.DeletedSubtitle
}
if index == m.Index() {
fmt.Fprintln(w, " "+titleStyle.Render(s.Name))
fmt.Fprint(w, " "+subtitleStyle.Render(s.Folder+" • "+humanizeTime(s.Date)))
return
}
fmt.Fprintln(w, " "+d.styles.UnselectedTitle.Render(s.Name))
fmt.Fprint(w, " "+d.styles.UnselectedSubtitle.Render(s.Folder+" • "+humanizeTime(s.Date)))
}
// Folder represents a group of snippets in a directory.
type Folder string
// FilterValue is the searchable value for the folder.
func (f Folder) FilterValue() string {
return string(f)
}
// folderDelegate represents a folder list item.
type folderDelegate struct{ styles FoldersBaseStyle }
// Height is the number of lines the folder list item takes up.
func (d folderDelegate) Height() int {
return 1
}
// Spacing is the number of lines to insert between folder items.
func (d folderDelegate) Spacing() int {
return 0
}
// Update is what is called when the folder selection is updated.
// TODO: Update the filter search for the snippets with the folder name.
func (d folderDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd {
return nil
}
// Render renders a folder list item.
func (d folderDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) {
f, ok := item.(Folder)
if !ok {
return
}
fmt.Fprint(w, " ")
if index == m.Index() {
fmt.Fprint(w, d.styles.Selected.Render("→ "+string(f)))
return
}
fmt.Fprint(w, d.styles.Unselected.Render(" "+string(f)))
}
const (
Day = 24 * time.Hour
Week = 7 * Day
Month = 30 * Day
Year = 12 * Month
)
var magnitudes = []humanize.RelTimeMagnitude{
{D: 5 * time.Second, Format: "just now", DivBy: time.Second},
{D: time.Minute, Format: "moments ago", DivBy: time.Second},
{D: time.Hour, Format: "%dm %s", DivBy: time.Minute},
{D: 2 * time.Hour, Format: "1h %s", DivBy: 1},
{D: Day, Format: "%dh %s", DivBy: time.Hour},
{D: 2 * Day, Format: "1d %s", DivBy: 1},
{D: Week, Format: "%dd %s", DivBy: Day},
{D: 2 * Week, Format: "1w %s", DivBy: 1},
{D: Month, Format: "%dw %s", DivBy: Week},
{D: 2 * Month, Format: "1mo %s", DivBy: 1},
{D: Year, Format: "%dmo %s", DivBy: Month},
{D: 18 * Month, Format: "1y %s", DivBy: 1},
{D: 2 * Year, Format: "2y %s", DivBy: 1},
}
func humanizeTime(t time.Time) string {
return humanize.CustomRelTime(t, time.Now(), "ago", "from now", magnitudes)
}