1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5package area
6
7import (
8 "encoding/json"
9 "fmt"
10
11 "git.secluded.site/lune/internal/config"
12 "git.secluded.site/lune/internal/ui"
13 "github.com/charmbracelet/lipgloss"
14 "github.com/charmbracelet/lipgloss/table"
15 "github.com/spf13/cobra"
16)
17
18// ListCmd lists configured areas and their goals.
19var ListCmd = &cobra.Command{
20 Use: "list",
21 Short: "List configured areas",
22 Long: `List areas configured in lune.
23
24Areas are copied from the Lunatask desktop app during 'lune init'.
25Each area may have goals associated with it.`,
26 RunE: runList,
27}
28
29func init() {
30 ListCmd.Flags().Bool("json", false, "Output as JSON")
31}
32
33func runList(cmd *cobra.Command, _ []string) error {
34 cfg, err := config.Load()
35 if err != nil {
36 return err
37 }
38
39 if len(cfg.Areas) == 0 {
40 fmt.Fprintln(cmd.OutOrStdout(), "No areas configured")
41
42 return nil
43 }
44
45 jsonFlag, _ := cmd.Flags().GetBool("json")
46 if jsonFlag {
47 return outputJSON(cmd, cfg.Areas)
48 }
49
50 return outputTable(cmd, cfg.Areas)
51}
52
53func outputJSON(cmd *cobra.Command, areas []config.Area) error {
54 enc := json.NewEncoder(cmd.OutOrStdout())
55 enc.SetIndent("", " ")
56
57 if err := enc.Encode(areas); err != nil {
58 return fmt.Errorf("encoding JSON: %w", err)
59 }
60
61 return nil
62}
63
64func outputTable(cmd *cobra.Command, areas []config.Area) error {
65 rows := make([][]string, 0, len(areas))
66
67 for _, area := range areas {
68 goals := formatGoals(area.Goals)
69 rows = append(rows, []string{area.Key, area.Name, goals})
70 }
71
72 tbl := table.New().
73 Headers("KEY", "NAME", "GOALS").
74 Rows(rows...).
75 StyleFunc(func(row, col int) lipgloss.Style {
76 if row == table.HeaderRow {
77 return ui.TableHeaderStyle()
78 }
79
80 return lipgloss.NewStyle()
81 }).
82 Border(ui.TableBorder())
83
84 fmt.Fprintln(cmd.OutOrStdout(), tbl.Render())
85
86 return nil
87}
88
89func formatGoals(goals []config.Goal) string {
90 if len(goals) == 0 {
91 return "-"
92 }
93
94 keys := make([]string, len(goals))
95 for i, g := range goals {
96 keys[i] = g.Key
97 }
98
99 if len(keys) <= 3 {
100 return joinKeys(keys)
101 }
102
103 return joinKeys(keys[:3]) + fmt.Sprintf(" (+%d)", len(keys)-3)
104}
105
106func joinKeys(keys []string) string {
107 result := ""
108
109 for i, k := range keys {
110 if i > 0 {
111 result += ", "
112 }
113
114 result += k
115 }
116
117 return result
118}