Skip to content
This repository has been archived by the owner on May 23, 2022. It is now read-only.

Print commands by group #23

Merged
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
73 changes: 67 additions & 6 deletions console/service/index.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
package service

import (
"github.com/confetti-framework/contract/inter"
"fmt"
"sort"
"strings"

"github.com/confetti-framework/contract/inter"
"github.com/jedib0t/go-pretty/v6/table"
)

var globalOptions = map[string]string{
"-h --help": "Show the command's available arguments.",
"--env-file": "Run the command with a defined environment file.",
}

func RenderIndex(c inter.Cli, commands []inter.Command) inter.ExitCode {
// Add title and instruction for global usage
name := c.App().Make("config.App.Name").(string)
Expand All @@ -16,17 +25,69 @@ func RenderIndex(c inter.Cli, commands []inter.Command) inter.ExitCode {
})

t := c.Table()

t.AppendRow([]interface{}{"\u001B[32mGlobal options:\u001B[0m"})
t.AppendRow([]interface{}{"-h --help", "Show the command's available arguments."})
t.AppendRow([]interface{}{"--env-file", "Run the command with a defined environment file."})
printGlobalOptions(t)

t.AppendRow([]interface{}{"\n\u001B[32mAvailable commands:\u001B[0m"})
printCommandsByGroup(t, commands)

t.Render()

return inter.Success
}

func printGlobalOptions(t table.Writer) {
for flag, description := range globalOptions {
t.AppendRow([]interface{}{" " + flag, description})
}
}

func printCommandsByGroup(t table.Writer, commands []inter.Command) {
// Commands without a group
for _, command := range commands {
t.AppendRow([]interface{}{command.Name(), command.Description()})
if !strings.ContainsRune(command.Name(), ':') {
t.AppendRow([]interface{}{fmt.Sprintf(" \u001B[33m%s\u001B[0m", command.Name()), command.Description()})
}
}

t.Render()
// Commands with a group (e.g. app:serve)
for _, groupName := range getGroupNames(commands) {
t.AppendRow([]interface{}{fmt.Sprintf(" \u001B[32m%s\u001B[0m", groupName)})

return inter.Success
for _, command := range commands {
if strings.HasPrefix(command.Name(), groupName+":") {
t.AppendRow([]interface{}{fmt.Sprintf(" \u001B[33m%s\u001B[0m", command.Name()), command.Description()})
}
}
}
}

func getGroupNames(commands []inter.Command) (names []string) {
groups := map[string]bool{}

// Find all group names (unique!)
for _, command := range commands {
parts := strings.Split(command.Name(), ":")

if len(parts) <= 1 {
continue
}

groupName := parts[0]

groups[groupName] = true
}

// Reduce to keys
for groupName := range groups {
names = append(names, groupName)
}

// Ensure groups are sorted, just like commands
sort.SliceStable(names, func(i, j int) bool {
return names[i] < names[j]
})

return
}
19 changes: 13 additions & 6 deletions test/console/cast_options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ package console
import (
"bytes"
"fmt"
"strconv"
"testing"
"time"

"github.com/confetti-framework/contract/inter"
"github.com/confetti-framework/foundation"
"github.com/confetti-framework/foundation/console"
"github.com/confetti-framework/foundation/console/facade"
"github.com/spf13/cast"
"github.com/stretchr/testify/require"
"strconv"
"testing"
"time"
)

type structWithOptionBool struct {
Expand Down Expand Up @@ -67,7 +68,7 @@ func Test_cast_option_bool_true(t *testing.T) {
Commands: []inter.Command{structWithOptionBool{}},
}.Handle()

require.Contains(t, output.String(), `true`)
require.Contains(t, output.String(), `true`)
}

type structWithOptionString struct {
Expand Down Expand Up @@ -249,10 +250,16 @@ func Test_cast_flag_with_dash(t *testing.T) {
}

type structWithDescription struct {
DryRun bool `short:"dr" flag:"dry-run" description:"The flag description"`
DryRun bool `short:"dr" flag:"dry-run" description:"The flag description"`
CommandName string
}

func (s structWithDescription) Name() string { return "test" }
func (s structWithDescription) Name() string {
if s.CommandName == "" {
return "test"
}
return s.CommandName
}
func (s structWithDescription) Description() string { return "test" }
func (s structWithDescription) Handle(_ inter.Cli) inter.ExitCode {
return inter.Success
Expand Down
28 changes: 26 additions & 2 deletions test/console/options_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package console

import (
"testing"

"github.com/confetti-framework/contract/inter"
"github.com/confetti-framework/foundation/console"
"github.com/confetti-framework/foundation/console/service"
"github.com/confetti-framework/support"
"github.com/stretchr/testify/require"
"testing"
)

type mockCommandWithoutOptions struct{}
Expand All @@ -22,7 +23,30 @@ func Test_show_index_if_no_command(t *testing.T) {
}.Handle()

require.Equal(t, inter.Success, code)
require.Contains(t, TrimDoubleSpaces(output.String()), "\n Confetti\x1b[39m\n\n")
result := TrimDoubleSpaces(output.String())
require.Contains(t, result, "\n Confetti\x1b[39m\n\n")

require.Contains(t, result, "\n \x1b[32mGlobal options:\x1b[0m")
require.Contains(t, result, "-h --help Show the command's available arguments.")
require.Contains(t, result, "--env-file Run the command with a defined environment file.")
}

func Test_show_index_with_groups(t *testing.T) {
output, app := setUp()
app.Bind("config.App.OsArgs", []interface{}{"/exe/main"})

code := console.Kernel{
App: app,
Writer: &output,
Commands: []inter.Command{structWithDescription{CommandName: "make:test"}},
}.Handle()

require.Equal(t, inter.Success, code)
result := TrimDoubleSpaces(output.String())

require.Contains(t, result, "\x1b[32mAvailable commands:\x1b[0m")
require.Contains(t, result, "\x1b[33mbaker\x1b[0m Interact with your application.")
require.Contains(t, result, "\n \x1b[32mmake\x1b[0m\n \x1b[33mmake:test\x1b[0m test\n")
}

func Test_get_option_from_command_without_options(t *testing.T) {
Expand Down