dirs.go

 1package cmd
 2
 3import (
 4	"os"
 5	"path/filepath"
 6	"strings"
 7
 8	"charm.land/lipgloss/v2"
 9	"github.com/charmbracelet/crush/internal/config"
10	"github.com/charmbracelet/x/exp/charmtone"
11	"github.com/charmbracelet/x/term"
12	"github.com/spf13/cobra"
13)
14
15var dirsCmd = &cobra.Command{
16	Use:   "dirs",
17	Short: "Show config and data directories",
18	Long: `Show where Crush stores its configuration and data,
19including any project-level config files discovered
20from the current directory up to the project root.`,
21	Example: `
22# Show all directories
23crush dirs
24  `,
25	Run: func(cmd *cobra.Command, args []string) {
26		entries := collectDirs(cmd)
27		if term.IsTerminal(os.Stdout.Fd()) {
28			printDirs(cmd, entries)
29			return
30		}
31		for _, e := range entries {
32			cmd.Println(e)
33		}
34	},
35}
36
37func collectDirs(cmd *cobra.Command) []string {
38	var dirs []string
39
40	dirs = append(dirs, filepath.Dir(config.GlobalConfig()))
41	dirs = append(dirs, filepath.Dir(config.GlobalConfigData()))
42
43	cwd, err := ResolveCwd(cmd)
44	if err != nil {
45		return dirs
46	}
47
48	for _, p := range config.ProjectConfigs(cwd) {
49		d := filepath.Dir(p)
50		// Skip global paths, already shown.
51		if d == filepath.Dir(config.GlobalConfig()) || d == filepath.Dir(config.GlobalConfigData()) {
52			continue
53		}
54		dirs = append(dirs, d)
55	}
56
57	return dirs
58}
59
60func printDirs(cmd *cobra.Command, dirs []string) {
61	labelStyle := lipgloss.NewStyle().Bold(true).Foreground(charmtone.Charple)
62
63	labels := make([]string, len(dirs))
64	longest := 0
65	for i := range dirs {
66		l := dirLabel(i)
67		labels[i] = l + ":"
68		if len(labels[i]) > longest {
69			longest = len(labels[i])
70		}
71	}
72
73	for i, d := range dirs {
74		lipgloss.Println(labelStyle.Render(labels[i]) +
75			strings.Repeat(" ", longest-len(labels[i])) +
76			" " + d)
77	}
78
79	lipgloss.Println(lipgloss.NewStyle().Foreground(charmtone.Squid).Render("Configs merge from top to bottom"))
80}
81
82func dirLabel(i int) string {
83	switch i {
84	case 0:
85		return "Config"
86	case 1:
87		return "Data"
88	default:
89		return "Project"
90	}
91}