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 fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Config not found; run 'lune init' to configure areas"))
37
38 return err
39 }
40
41 if len(cfg.Areas) == 0 {
42 fmt.Fprintln(cmd.OutOrStdout(), "No areas configured")
43
44 return nil
45 }
46
47 jsonFlag, _ := cmd.Flags().GetBool("json")
48 if jsonFlag {
49 return outputJSON(cmd, cfg.Areas)
50 }
51
52 return outputTable(cmd, cfg.Areas)
53}
54
55func outputJSON(cmd *cobra.Command, areas []config.Area) error {
56 enc := json.NewEncoder(cmd.OutOrStdout())
57 enc.SetIndent("", " ")
58
59 if err := enc.Encode(areas); err != nil {
60 return fmt.Errorf("encoding JSON: %w", err)
61 }
62
63 return nil
64}
65
66func outputTable(cmd *cobra.Command, areas []config.Area) error {
67 rows := make([][]string, 0, len(areas))
68
69 for _, area := range areas {
70 goals := formatGoals(area.Goals)
71 rows = append(rows, []string{area.Key, area.Name, goals})
72 }
73
74 tbl := table.New().
75 Headers("KEY", "NAME", "GOALS").
76 Rows(rows...).
77 StyleFunc(func(row, col int) lipgloss.Style {
78 if row == table.HeaderRow {
79 return ui.Bold
80 }
81
82 return lipgloss.NewStyle()
83 }).
84 Border(lipgloss.HiddenBorder())
85
86 fmt.Fprintln(cmd.OutOrStdout(), tbl.Render())
87
88 return nil
89}
90
91func formatGoals(goals []config.Goal) string {
92 if len(goals) == 0 {
93 return "-"
94 }
95
96 keys := make([]string, len(goals))
97 for i, g := range goals {
98 keys[i] = g.Key
99 }
100
101 if len(keys) <= 3 {
102 return joinKeys(keys)
103 }
104
105 return joinKeys(keys[:3]) + fmt.Sprintf(" (+%d)", len(keys)-3)
106}
107
108func joinKeys(keys []string) string {
109 result := ""
110
111 for i, k := range keys {
112 if i > 0 {
113 result += ", "
114 }
115
116 result += k
117 }
118
119 return result
120}