Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 30 additions & 12 deletions cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import (
"github.com/mateconpizza/gm/internal/bookmark/port"
"github.com/mateconpizza/gm/internal/cli"
"github.com/mateconpizza/gm/internal/editor"
"github.com/mateconpizza/gm/internal/sys"
"github.com/mateconpizza/gm/internal/ui"
"github.com/mateconpizza/gm/internal/ui/frame"
"github.com/mateconpizza/gm/internal/ui/printer"
"github.com/mateconpizza/gm/pkg/ansi"
)

func NewCmd(app *application.App) *cobra.Command {
Expand All @@ -31,12 +33,10 @@ func NewCmd(app *application.App) *cobra.Command {
Example: app.Example(` $ {cmd} config create
$ {cmd} config create --force
$ {cmd} config edit
$ {cmd} config view
$ {cmd} config --print
$ {cmd} config --json`),
RunE: func(cmd *cobra.Command, args []string) error {
if app.Flags.JSON {
return cfgToJSON(cmd.Context(), app)
}
if app.Flags.Print {
return showPathFile(os.Stdout, app.Path.ConfigFile())
}
Expand All @@ -45,10 +45,9 @@ func NewCmd(app *application.App) *cobra.Command {
},
}
c.Flags().BoolVar(&app.Flags.Print, "print", false, "print config file location")
c.Flags().BoolVarP(&app.Flags.JSON, "json", "j", false, "JSON output")
cmdutil.HideFlag(c, "color", "db", "menu", "head", "tail", "fields", "sort", "tag")

c.AddCommand(newCreateCmd(app), newEditCmd(app))
c.AddCommand(newCreateCmd(app), newEditCmd(app), newViewCmd(app))

return c
}
Expand All @@ -61,7 +60,7 @@ func newCreateCmd(app *application.App) *cobra.Command {
if err := app.Validate(); err != nil {
return err
}
return createConfig(cmd.Context(), ui.DefaultConsole, app)
return createConfig(ui.DefaultConsole, app)
},
}
cmdutil.HideFlag(c, "db")
Expand All @@ -83,6 +82,29 @@ func newEditCmd(app *application.App) *cobra.Command {
}
}

func newViewCmd(app *application.App) *cobra.Command {
c := &cobra.Command{
Use: "view",
Short: "view current configuration",
Aliases: []string{"v"},
RunE: func(cmd *cobra.Command, args []string) error {
if app.Flags.JSON {
return cfgToJSON(cmd.Context(), app)
}

f := frame.New(
frame.WithBordersSmallBlock2(),
frame.WithWriter(os.Stdout),
)
return printer.AppConfig(app, f, ansi.NewPalette())
},
}

c.Flags().BoolVarP(&app.Flags.JSON, "json", "j", false, "JSON output")

return c
}

func cfgToJSON(ctx context.Context, app *application.App) error {
app.DBName = strings.TrimSuffix(app.DBName, ".db")
j, err := port.ToJSON(app)
Expand All @@ -93,18 +115,14 @@ func cfgToJSON(ctx context.Context, app *application.App) error {
}

// createConfig dumps the app configuration to a YAML file.
func createConfig(ctx context.Context, c *ui.Console, app *application.App) error {
func createConfig(c *ui.Console, app *application.App) error {
cfgFile := app.Path.ConfigFile()
if files.Exists(cfgFile) && !app.Flags.Force {
p := c.Palette()
f := p.BrightYellow.Wrap("--force", p.Italic, p.Bold)
return fmt.Errorf("%w. use %s to overwrite", os.ErrExist, f)
}

if !app.Flags.Force && !c.Confirm(ctx, fmt.Sprintf("create configfile %q", cfgFile), "y") {
return sys.ErrActionAborted
}

if err := app.WriteConfig(app.Flags.Force); err != nil {
return err
}
Expand Down
31 changes: 2 additions & 29 deletions cmd/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
files "github.com/mateconpizza/gofiles"

"github.com/mateconpizza/gm/internal/application"
"github.com/mateconpizza/gm/internal/sys"
"github.com/mateconpizza/gm/internal/sys/terminal"
"github.com/mateconpizza/gm/internal/testutil"
"github.com/mateconpizza/gm/internal/ui"
Expand All @@ -38,7 +37,7 @@ func TestConfig_Create(t *testing.T) {
app.Path.Data = dir
fn := application.ConfigFilename

err := createConfig(t.Context(), c, app)
err := createConfig(c, app)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -49,32 +48,6 @@ func TestConfig_Create(t *testing.T) {
}
})

t.Run("returns ErrActionAborted when user declines", func(t *testing.T) {
t.Parallel()
var buf bytes.Buffer

c := ui.NewConsole(
ui.WithWriter(&buf),
ui.WithTerminal(terminal.New(
terminal.WithReader(strings.NewReader("n\n")), // decline
terminal.WithWriter(io.Discard),
)),
)

app := testutil.SetupApp(t)
app.Flags.Yes = true
dir := t.TempDir()
app.Path.Data = dir

err := createConfig(t.Context(), c, app)
if err == nil {
t.Fatal("expected error but got none")
}
if !errors.Is(err, sys.ErrActionAborted) {
t.Fatalf("got error %v, want %v", err, sys.ErrActionAborted)
}
})

t.Run("returns ErrFileExists when config file already exists", func(t *testing.T) {
t.Parallel()

Expand All @@ -89,7 +62,7 @@ func TestConfig_Create(t *testing.T) {
app.Path.Data = dir

c := ui.NewConsole()
err = createConfig(t.Context(), c, app)
err = createConfig(c, app)
if !errors.Is(err, os.ErrExist) {
t.Fatalf("got error %v, want %v", err, os.ErrExist)
}
Expand Down
77 changes: 77 additions & 0 deletions internal/ui/printer/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,21 @@ import (
"strings"
"text/tabwriter"

menu "github.com/mateconpizza/go-fzf"
files "github.com/mateconpizza/gofiles"

"github.com/mateconpizza/gm/internal/application"
"github.com/mateconpizza/gm/internal/bookmark/port"
"github.com/mateconpizza/gm/internal/deps"
"github.com/mateconpizza/gm/internal/gitops"
"github.com/mateconpizza/gm/internal/locker"
"github.com/mateconpizza/gm/internal/picker/menucfg"
"github.com/mateconpizza/gm/internal/summary"
"github.com/mateconpizza/gm/internal/ui"
"github.com/mateconpizza/gm/internal/ui/formatter"
"github.com/mateconpizza/gm/internal/ui/frame"
"github.com/mateconpizza/gm/internal/ui/txt"
"github.com/mateconpizza/gm/pkg/ansi"
"github.com/mateconpizza/gm/pkg/bookmark"
"github.com/mateconpizza/gm/pkg/db"
)
Expand Down Expand Up @@ -360,3 +364,76 @@ func Display(ctx context.Context, c *ui.Console, f string, bs []*bookmark.Bookma

return Print(ctx, c, bs, fm.Render)
}

func AppConfig(app *application.App, f *frame.Frame, p *ansi.Palette) error {
header := func() string {
return p.BrightBlue.Wrap(txt.GlyphSmallSquare.Prefix(" "), p.Bold)
}

const padding = 20
pad := func(label string, value any) string {
return txt.PaddedLineWithPad(label+":", value, padding)
}

f.CustomFunc(header, app.PrettyVersion()).
Rowln().
Rowln(pad("current db", p.BrightYellow.Wrap(app.DBBaseName(), p.Italic))).
Rowln(pad("format", app.Format))

// config file
if files.Exists(app.Path.ConfigFile()) {
f.Rowln(pad("config:", files.CollapseHomeDir(app.Path.ConfigFile())))
}

// menu.
m := app.Menu
f.MidCln(p.BrightRed.With(p.Bold), p.BrightRed.Wrap("menu", p.Bold)).
Rowln(pad("use defaults", boolFmt(m.Defaults))).
Rowln(pad("format", m.Format)).
Rowln(pad("prompt", m.Prompt)).
Rowln(pad("preview enabled", boolFmt(m.Preview))).
Rowln(pad("header enabled", boolFmt(m.Header.Enabled))).
Rowln(pad("header separator", m.Header.Sep))

// keymaps.
ph := app.Formatter().Menu.Placeholder()
keymaps := app.Menu.LoadKeymaps(
menucfg.NewBindBuilder().
WithCommand(app.Command()).
WithDBName(app.DBBaseName()).
WithPlaceholder(ph.Multi()),
)
f.MidCln(p.BrightMagenta.With(p.Bold), p.BrightMagenta.Wrap("keymaps", p.Bold))
for i := range keymaps {
k := keymaps[i]
f.Rowln(pad(k.Desc, formatKeymap(k)))
}

// git.
if g := app.Git; g.Enabled {
f.MidCln(p.BrightYellow.With(p.Bold), p.BrightYellow.Wrap("git", p.Bold)).
Rowln(pad("enabled", boolFmt(g.Enabled))).
Rowln(pad("logging", boolFmt(g.Log))).
Rowln(pad("remote", p.Italic.Sprint(g.Remote)))
}

f.Flush()

return nil
}

func formatKeymap(k *menu.Keymap) string {
keybind, action, _ := strings.Cut(k.String(), ":")
return txt.PaddedLineWithPad(
ansi.Bold.Sprint(keybind),
ansi.Italic.Sprint(":"+action),
8,
)
}

func boolFmt(b bool) string {
if !b {
return ansi.BrightRed.Sprint("false")
}
return ansi.BrightGreen.Sprint("true")
}