lune

created pr with 124.1 on 2026-04-22T02:46:44Z · by 613b58b7
changed status to closed on 2026-06-21T16:45:31Z · by 66ddd677
Closing as superceded by 126
cmds
checkout latest patchset:
ssh pr.pico.sh print 124 | git am -3
checkout any patchset in a patch request:
ssh pr.pico.sh print 124.[rev] | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 124
set PR to open (enables RSS notifications):
ssh pr.pico.sh pr open 124
set PR to draft (stops RSS notifications):
ssh pr.pico.sh pr draft 124

Patchset 124.1 on 2026-04-22T02:46:44Z · commit eb39ebc

listing real name of tasks
juan 2026-04-21T03:21:16Z
construction of db for management of decrypted names of tasks
juan 2026-04-21T05:43:09Z
fix UTF8 chracteres
juan 2026-04-21T21:13:24Z
filter by status and coloring types of status
juan 2026-04-21T21:18:53Z
update help
juan 2026-04-21T21:21:36Z
list areas names
juan 2026-04-21T21:44:53Z
adjust table tasks to truncate name and list area
juan 2026-04-21T21:56:40Z
partial implementation of listing tasks by areas
juan 2026-04-21T22:05:20Z
final implementation of listing tasks by areas with UTF-8 chracteres
juan 2026-04-21T22:10:20Z
sort on task list to show first do now
juan 2026-04-21T22:33:29Z
update with 8 char of id and db.go
juan 2026-04-21T23:27:54Z
partial implementation of TUI menu on task update
juan 2026-04-21T23:35:35Z
task name correcion on TUI menu of Update task
juan 2026-04-21T23:38:19Z
TUI menu for update task with others flags
juan 2026-04-21T23:43:02Z
helper for TUI update task
juan 2026-04-21T23:49:56Z
search by first 8 char of note id for editing it
juan 2026-04-22T00:00:17Z
partial implementation on note TUI menu for update
juan 2026-04-22T00:05:46Z
TUI menu notebook just with tags
juan 2026-04-22T00:20:55Z
Note update now let you insert only the first 8 char of notebook id in update
juan 2026-04-22T00:25:53Z
implementation of (lune note notebook-list) for listing all notebooks and its ID
juan 2026-04-22T01:10:51Z
partial implementation of lune note show-content ID
juan 2026-04-22T02:01:11Z
convert \n in new line and \ in space for lune note show-content ID
juan 2026-04-22T02:18:42Z
+56 -10 cmd/task/list.go #
......@@ -59,6 +59,11 @@ func init() {
5959 }
6060
6161 func runList(cmd *cobra.Command, _ []string) error {
62+ cfg, _ := config.Load()
63+ if cfg != nil && cfg.Experimental.LocalDB {
64+ _ = db.WarmCache()
65+ }
66+
6267 apiClient, err := client.New()
6368 if err != nil {
6469 return err
......@@ -71,7 +76,6 @@ func runList(cmd *cobra.Command, _ []string) error {
7176 return err
7277 }
7378
74- cfg, _ := config.Load()
7579 enriched := make([]enrichedTask, 0, len(tasks))
7680 for _, t := range tasks {
7781 name := ""
......@@ -246,6 +250,7 @@ func outputJSONEnriched(cmd *cobra.Command, tasks []enrichedTask) error {
246250 }
247251
248252 func outputTableEnriched(cmd *cobra.Command, tasks []enrichedTask) error {
253+ cfg, _ := config.Load()
249254 rows := make([][]string, 0, len(tasks))
250255
251256 for _, task := range tasks {
......@@ -264,36 +269,77 @@ func outputTableEnriched(cmd *cobra.Command, tasks []enrichedTask) error {
264269 name = task.ID[:8] + "..."
265270 }
266271
267- rows = append(rows, []string{name, status, scheduled})
272+ // Resolve Area name
273+ area := "-"
274+ if task.AreaID != nil {
275+ area = *task.AreaID
276+ if cfg != nil {
277+ if a := cfg.AreaByID(*task.AreaID); a != nil {
278+ area = a.Key
279+ } else if cfg.Experimental.LocalDB {
280+ // Proactive area lookup in local DB
281+ if dbName, _ := db.EnrichTask(*task.AreaID); dbName != "" {
282+ area = dbName
283+ }
284+ }
285+ }
286+ }
287+
288+ // Truncate name and area for clean table layout
289+ if len(name) > 50 {
290+ name = name[:47] + "..."
291+ }
292+ if len(area) > 20 {
293+ area = area[:17] + "..."
294+ }
295+
296+ rows = append(rows, []string{task.ID[:8], name, status, scheduled, area})
268297 }
269298
270299 tbl := table.New().
271- Headers("NAME", "STATUS", "SCHEDULED").
300+ Headers("ID", "NAME", "STATUS", "SCHEDULED", "AREA").
272301 Rows(rows...).
273302 StyleFunc(func(row, col int) lipgloss.Style {
303+ style := lipgloss.NewStyle()
304+
305+ // Set column widths via style
306+ switch col {
307+ case 0: // ID
308+ style = style.Width(10)
309+ case 1: // NAME
310+ style = style.Width(52)
311+ case 2: // STATUS
312+ style = style.Width(12)
313+ case 3: // SCHEDULED
314+ style = style.Width(12)
315+ case 4: // AREA
316+ style = style.Width(22)
317+ }
318+
274319 if row == table.HeaderRow {
275- return ui.TableHeaderStyle()
320+ return style.Inherit(ui.TableHeaderStyle())
276321 }
277322
323+ // Color logic based on status
278324 if row >= 0 && row < len(tasks) {
279325 t := tasks[row]
280326 if t.Status != nil {
281327 switch *t.Status {
282328 case lunatask.StatusLater:
283- return ui.StatusLater
329+ style = style.Inherit(ui.StatusLater)
284330 case lunatask.StatusNext:
285- return ui.StatusNext
331+ style = style.Inherit(ui.StatusNext)
286332 case lunatask.StatusInProgress:
287- return ui.StatusInProgress
333+ style = style.Inherit(ui.StatusInProgress)
288334 case lunatask.StatusWaiting:
289- return ui.StatusWaiting
335+ style = style.Inherit(ui.StatusWaiting)
290336 case lunatask.StatusCompleted:
291- return ui.StatusCompleted
337+ style = style.Inherit(ui.StatusCompleted)
292338 }
293339 }
294340 }
295341
296- return lipgloss.NewStyle()
342+ return style
297343 }).
298344 Border(ui.TableBorder()).
299345 BorderRow(true)
+46 -9 internal/db/reader.go #
......@@ -56,10 +56,20 @@ func SetMasterPassword(password string) error {
5656 return os.WriteFile(path, f, 0600)
5757 }
5858
59-func EnrichTask(taskID string) (string, error) {
59+var (
60+ nameCache = make(map[string]string)
61+ cacheWarmed = false
62+)
63+
64+// WarmCache loads all names (tasks, notes, areas, notebooks) into memory.
65+func WarmCache() error {
66+ if cacheWarmed {
67+ return nil
68+ }
69+
6070 dbPath := GetDefaultPath()
6171 if _, err := os.Stat(dbPath); os.IsNotExist(err) {
62- return "", nil
72+ return nil
6373 }
6474
6575 o := &opt.Options{
......@@ -69,7 +79,7 @@ func EnrichTask(taskID string) (string, error) {
6979
7080 db, err := leveldb.OpenFile(dbPath, o)
7181 if err != nil {
72- return "", err
82+ return err
7383 }
7484 defer db.Close()
7585
......@@ -78,15 +88,42 @@ func EnrichTask(taskID string) (string, error) {
7888
7989 for iter.Next() {
8090 val := iter.Value()
81- if bytes.Contains(val, []byte(taskID)) {
82- re := regexp.MustCompile(`"(title|name)"\s*:\s*"([^"]+)"`)
83- matches := re.FindSubmatch(val)
84- if len(matches) > 2 {
85- return cleanName(string(matches[2])), nil
91+ // Try to find JSON-like blobs
92+ if bytes.Contains(val, []byte("\"id\"")) && bytes.Contains(val, []byte("\"name\"")) {
93+ start := bytes.IndexByte(val, '{')
94+ end := bytes.LastIndexByte(val, '}')
95+ if start != -1 && end != -1 && end > start {
96+ jsonBytes := val[start : end+1]
97+ id := extractField(jsonBytes, "id")
98+ name := extractField(jsonBytes, "name")
99+ if id != "" && name != "" {
100+ nameCache[id] = cleanName(name)
101+ }
102+ }
103+ } else if bytes.Contains(val, []byte("\"id\"")) && bytes.Contains(val, []byte("\"title\"")) {
104+ // Notes use "title"
105+ start := bytes.IndexByte(val, '{')
106+ end := bytes.LastIndexByte(val, '}')
107+ if start != -1 && end != -1 && end > start {
108+ jsonBytes := val[start : end+1]
109+ id := extractField(jsonBytes, "id")
110+ title := extractField(jsonBytes, "title")
111+ if id != "" && title != "" {
112+ nameCache[id] = cleanName(title)
113+ }
86114 }
87115 }
88116 }
89- return "", nil
117+ cacheWarmed = true
118+ return nil
119+}
120+
121+// EnrichTask attempts to find the task or note name in the cache or local database.
122+func EnrichTask(taskID string) (string, error) {
123+ if !cacheWarmed {
124+ _ = WarmCache()
125+ }
126+ return nameCache[taskID], nil
90127 }
91128
92129 // Area represents a Lunatask area found in the local database.
Back to top