Skip to content

Commit 738a8be

Browse files
committed
feat: implement dynamic shell completion for margin keys and IDs (#22)
1 parent ba1d30b commit 738a8be

7 files changed

Lines changed: 156 additions & 0 deletions

File tree

cmd/delete.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,23 @@ var deleteCmd = &cobra.Command{
2727

2828
fmt.Printf("%s Entry %s deleted.\n", successStyle.Render("✓"), id)
2929
},
30+
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
31+
if len(args) != 0 {
32+
return nil, cobra.ShellCompDirectiveNoFileComp
33+
}
34+
35+
s, err := storage.NewStorage()
36+
if err != nil {
37+
return nil, cobra.ShellCompDirectiveError
38+
}
39+
40+
ids, err := s.GetRecentIDs()
41+
if err != nil {
42+
return nil, cobra.ShellCompDirectiveError
43+
}
44+
45+
return ids, cobra.ShellCompDirectiveNoFileComp
46+
},
3047
}
3148

3249
func init() {

cmd/done.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,23 @@ var doneCmd = &cobra.Command{
4646

4747
fmt.Printf("%s Task %s marked as done.\n", successStyle.Render("✓"), id)
4848
},
49+
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
50+
if len(args) != 0 {
51+
return nil, cobra.ShellCompDirectiveNoFileComp
52+
}
53+
54+
s, err := storage.NewStorage()
55+
if err != nil {
56+
return nil, cobra.ShellCompDirectiveError
57+
}
58+
59+
ids, err := s.GetRecentIDs()
60+
if err != nil {
61+
return nil, cobra.ShellCompDirectiveError
62+
}
63+
64+
return ids, cobra.ShellCompDirectiveNoFileComp
65+
},
4966
}
5067

5168
func init() {

cmd/edit.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,23 @@ var editCmd = &cobra.Command{
3030

3131
fmt.Printf("%s Entry %s updated.\n", successStyle.Render("✓"), id)
3232
},
33+
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
34+
if len(args) != 0 {
35+
return nil, cobra.ShellCompDirectiveNoFileComp
36+
}
37+
38+
s, err := storage.NewStorage()
39+
if err != nil {
40+
return nil, cobra.ShellCompDirectiveError
41+
}
42+
43+
ids, err := s.GetRecentIDs()
44+
if err != nil {
45+
return nil, cobra.ShellCompDirectiveError
46+
}
47+
48+
return ids, cobra.ShellCompDirectiveNoFileComp
49+
},
3350
}
3451

3552
func init() {

cmd/list.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,26 @@ var listCmd = &cobra.Command{
124124
renderEntry(e, maxMargin)
125125
}
126126
},
127+
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
128+
if len(args) != 0 {
129+
return nil, cobra.ShellCompDirectiveNoFileComp
130+
}
131+
132+
s, err := storage.NewStorage()
133+
if err != nil {
134+
return nil, cobra.ShellCompDirectiveError
135+
}
136+
137+
keys, err := s.GetUniqueMarginKeys()
138+
if err != nil {
139+
return nil, cobra.ShellCompDirectiveError
140+
}
141+
142+
// Add static time filters
143+
keys = append(keys, "today", "3d", "7d", "30d")
144+
145+
return keys, cobra.ShellCompDirectiveNoFileComp
146+
},
127147
}
128148

129149
func init() {

cmd/migrate.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,23 @@ var migrateCmd = &cobra.Command{
6767

6868
fmt.Printf("%s Task %s migrated to today (New ID: %s).\n", successStyle.Render("✓"), id, newID)
6969
},
70+
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
71+
if len(args) != 0 {
72+
return nil, cobra.ShellCompDirectiveNoFileComp
73+
}
74+
75+
s, err := storage.NewStorage()
76+
if err != nil {
77+
return nil, cobra.ShellCompDirectiveError
78+
}
79+
80+
ids, err := s.GetRecentIDs()
81+
if err != nil {
82+
return nil, cobra.ShellCompDirectiveError
83+
}
84+
85+
return ids, cobra.ShellCompDirectiveNoFileComp
86+
},
7087
}
7188

7289
func init() {

cmd/pin.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,23 @@ var pinCmd = &cobra.Command{
3232
}
3333
fmt.Printf("Entry %s %s.\n", id, status)
3434
},
35+
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
36+
if len(args) != 0 {
37+
return nil, cobra.ShellCompDirectiveNoFileComp
38+
}
39+
40+
s, err := storage.NewStorage()
41+
if err != nil {
42+
return nil, cobra.ShellCompDirectiveError
43+
}
44+
45+
ids, err := s.GetRecentIDs()
46+
if err != nil {
47+
return nil, cobra.ShellCompDirectiveError
48+
}
49+
50+
return ids, cobra.ShellCompDirectiveNoFileComp
51+
},
3552
}
3653

3754
func init() {

internal/storage/storage.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"os"
99
"path/filepath"
1010
"rapide/internal/model"
11+
"sort"
1112
"time"
1213
)
1314

@@ -303,6 +304,56 @@ func (s *Storage) TrimBefore(cutoff time.Time) (int, error) {
303304
return count, s.saveAll(toKeep)
304305
}
305306

307+
func (s *Storage) GetUniqueMarginKeys() ([]string, error) {
308+
entries, err := s.List()
309+
if err != nil {
310+
return nil, err
311+
}
312+
313+
keysMap := make(map[string]struct{})
314+
for _, e := range entries {
315+
if e.MarginKey != "" {
316+
keysMap[e.MarginKey] = struct{}{}
317+
}
318+
}
319+
320+
keys := make([]string, 0, len(keysMap))
321+
for k := range keysMap {
322+
keys = append(keys, k)
323+
}
324+
return keys, nil
325+
}
326+
327+
func (s *Storage) GetRecentIDs() ([]string, error) {
328+
entries, err := s.List()
329+
if err != nil {
330+
return nil, err
331+
}
332+
333+
// Only return IDs for relevant items (maybe last 50?)
334+
// Sort by timestamp desc
335+
sort.Slice(entries, func(i, j int) bool {
336+
return entries[i].Timestamp.After(entries[j].Timestamp)
337+
})
338+
339+
limit := 50
340+
if len(entries) < limit {
341+
limit = len(entries)
342+
}
343+
344+
ids := make([]string, 0, limit)
345+
for i := 0; i < limit; i++ {
346+
// Include content snippet in completion description if possible
347+
// Cobra supports "id\tDescription" format
348+
snippet := entries[i].Content
349+
if len(snippet) > 30 {
350+
snippet = snippet[:27] + "..."
351+
}
352+
ids = append(ids, fmt.Sprintf("%s\t%s %s", entries[i].ID, entries[i].Bullet, snippet))
353+
}
354+
return ids, nil
355+
}
356+
306357
func generateID(e model.Entry) string {
307358
h := sha1.New()
308359
h.Write([]byte(fmt.Sprintf("%d%s%s", e.Timestamp.UnixNano(), e.Bullet, e.Content)))

0 commit comments

Comments
 (0)