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 all tracked project directories",
17	Long: `List all directories where Crush has been used.
18This includes the working directory, data directory path, and last accessed time.`,
19	Example: `
20# List all projects in a table
21crush projects
22
23# Output as JSON
24crush projects --json
25  `,
26	RunE: func(cmd *cobra.Command, args []string) error {
27		jsonOutput, _ := cmd.Flags().GetBool("json")
28
29		projectList, err := projects.List()
30		if err != nil {
31			return err
32		}
33
34		if jsonOutput {
35			output := struct {
36				Projects []projects.Project `json:"projects"`
37			}{Projects: projectList}
38
39			data, err := json.Marshal(output)
40			if err != nil {
41				return err
42			}
43			cmd.Println(string(data))
44			return nil
45		}
46
47		if len(projectList) == 0 {
48			cmd.Println("No projects tracked yet.")
49			return nil
50		}
51
52		if term.IsTerminal(os.Stdout.Fd()) {
53			// We're in a TTY: make it fancy.
54			t := table.New().
55				Border(lipgloss.RoundedBorder()).
56				StyleFunc(func(row, col int) lipgloss.Style {
57					return lipgloss.NewStyle().Padding(0, 2)
58				}).
59				Headers("Path", "Data Dir", "Last Accessed")
60
61			for _, p := range projectList {
62				t.Row(p.Path, p.DataDir, p.LastAccessed.Local().Format("2006-01-02 15:04"))
63			}
64			lipgloss.Println(t)
65			return nil
66		}
67
68		// Not a TTY: plain output
69		for _, p := range projectList {
70			cmd.Printf("%s\t%s\t%s\n", p.Path, p.DataDir, p.LastAccessed.Format("2006-01-02T15:04:05Z07:00"))
71		}
72		return nil
73	},
74}
75
76func init() {
77	projectsCmd.Flags().Bool("json", false, "Output as JSON")
78}