projects.go

 1package cmd
 2
 3import (
 4	"encoding/json"
 5	"os"
 6
 7	"charm.land/lipgloss/v2"
 8	"charm.land/lipgloss/v2/table"
 9	"github.com/charmbracelet/crush/internal/projects"
10	"github.com/charmbracelet/x/term"
11	"github.com/spf13/cobra"
12)
13
14var projectsCmd = &cobra.Command{
15	Use:   "projects",
16	Short: "List project directories",
17	Long:  "List directories where Crush project data is known to exist",
18	Example: `
19# List all projects in a table
20crush projects
21
22# Output projects data as JSON
23crush projects --json
24  `,
25	RunE: func(cmd *cobra.Command, args []string) error {
26		jsonOutput, _ := cmd.Flags().GetBool("json")
27
28		projectList, err := projects.List()
29		if err != nil {
30			return err
31		}
32
33		if jsonOutput {
34			output := struct {
35				Projects []projects.Project `json:"projects"`
36			}{Projects: projectList}
37
38			data, err := json.Marshal(output)
39			if err != nil {
40				return err
41			}
42			cmd.Println(string(data))
43			return nil
44		}
45
46		if len(projectList) == 0 {
47			cmd.Println("No projects tracked yet.")
48			return nil
49		}
50
51		if term.IsTerminal(os.Stdout.Fd()) {
52			// We're in a TTY: make it fancy.
53			t := table.New().
54				Border(lipgloss.RoundedBorder()).
55				StyleFunc(func(row, col int) lipgloss.Style {
56					return lipgloss.NewStyle().Padding(0, 2)
57				}).
58				Headers("Path", "Data Dir", "Last Accessed")
59
60			for _, p := range projectList {
61				t.Row(p.Path, p.DataDir, p.LastAccessed.Local().Format("2006-01-02 15:04"))
62			}
63			lipgloss.Println(t)
64			return nil
65		}
66
67		// Not a TTY: plain output
68		for _, p := range projectList {
69			cmd.Printf("%s\t%s\t%s\n", p.Path, p.DataDir, p.LastAccessed.Format("2006-01-02T15:04:05Z07:00"))
70		}
71		return nil
72	},
73}
74
75func init() {
76	projectsCmd.Flags().Bool("json", false, "Output as JSON")
77}