dirs.go

  1package cmd
  2
  3import (
  4	"fmt"
  5	"os"
  6	"path/filepath"
  7	"strings"
  8
  9	"charm.land/lipgloss/v2"
 10	"charm.land/lipgloss/v2/table"
 11	"github.com/charmbracelet/crush/internal/config"
 12	"github.com/charmbracelet/x/term"
 13	"github.com/spf13/cobra"
 14)
 15
 16var dirsCmd = &cobra.Command{
 17	Use:   "dirs",
 18	Short: "Print directories used by Crush",
 19	Long: `Print the directories where Crush stores its configuration and data files.
 20This includes the global configuration directory and data directory.`,
 21	Example: `
 22# Print all global directories
 23crush dirs
 24
 25# Print data directory and all project specific config directories
 26crush dirs -p
 27
 28# Print only global config directory
 29crush dirs config
 30
 31# Print only project specific config directories
 32crush dirs -p config
 33
 34# Print only the data directory
 35crush dirs data
 36  `,
 37	RunE: func(cmd *cobra.Command, args []string) error {
 38		dirs, err := configDirs(cmd)
 39		if err != nil {
 40			return fmt.Errorf("cannot collect config directories: %w", err)
 41		}
 42
 43		if term.IsTerminal(os.Stdout.Fd()) {
 44			// We're in a TTY: make it fancy.
 45			t := table.New().
 46				Border(lipgloss.RoundedBorder()).
 47				StyleFunc(func(row, col int) lipgloss.Style {
 48					return lipgloss.NewStyle().Padding(0, 2)
 49				}).
 50				Row("Config", dirs).
 51				Row("Data", filepath.Dir(config.GlobalConfigData()))
 52			lipgloss.Println(t)
 53			return nil
 54		}
 55		// Not a TTY.
 56		cmd.Println(dirs)
 57		cmd.Println(filepath.Dir(config.GlobalConfigData()))
 58
 59		return nil
 60	},
 61}
 62
 63var configDirCmd = &cobra.Command{
 64	Use:   "config",
 65	Short: "Print the configuration directory used by Crush",
 66	RunE: func(cmd *cobra.Command, args []string) error {
 67		dirs, err := configDirs(cmd)
 68		if err != nil {
 69			return fmt.Errorf("cannot collect config directories: %w", err)
 70		}
 71		cmd.Println(dirs)
 72		return nil
 73	},
 74}
 75
 76var dataDirCmd = &cobra.Command{
 77	Use:   "data",
 78	Short: "Print the datauration directory used by Crush",
 79	Run: func(cmd *cobra.Command, args []string) {
 80		cmd.Println(filepath.Dir(config.GlobalConfigData()))
 81	},
 82}
 83
 84// configDirs returns formatted string with one or more project config paths
 85func configDirs(cmd *cobra.Command) (string, error) {
 86	configDir := filepath.Dir(config.GlobalConfig())
 87	if ok, _ := cmd.Flags().GetBool("project"); !ok {
 88		return configDir, nil
 89	}
 90
 91	cwd, err := ResolveCwd(cmd)
 92	if err != nil {
 93		return "", fmt.Errorf("cannot resolve current working directory: %w", err)
 94	}
 95
 96	var sb strings.Builder
 97	for i, path := range config.ProjectConfigs(cwd) {
 98		if i > 0 {
 99			sb.WriteByte('\n')
100		}
101		sb.WriteString(filepath.Dir(path))
102	}
103	return sb.String(), nil
104}
105
106func init() {
107	dirsCmd.PersistentFlags().BoolP("project", "p", false, "Print project specific configs")
108
109	dirsCmd.AddCommand(configDirCmd, dataDirCmd)
110}