mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 19:11:25 +01:00
feat: accept ls and rm for list and delete commands
Every list command also answers to ls and every delete command to rm, as in gh. flagAliases lets a command accept old flag names for renamed flags without listing them in help, so singular gh names such as --add-label can become primary while the plural names keep working. Signed-off-by: bircni <bircni@icloud.com>
This commit is contained in:
2 files changed
+65
No files matched your search
@@ -26,6 +26,7 @@ import (
|
||||
"gitea.dev/tea/internal/transport"
|
||||
"gitea.dev/tea/internal/version"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// Dependencies supplies external boundaries for a fresh CLI invocation.
|
||||
@@ -149,9 +150,37 @@ func NewRoot(deps Dependencies) *cobra.Command {
|
||||
root.InitDefaultCompletionCmd()
|
||||
root.SetVersionTemplate("{{.Version}}\n")
|
||||
rejectUnknownSubcommands(root)
|
||||
addVerbAliases(root)
|
||||
return root
|
||||
}
|
||||
|
||||
// verbAliases are the gh-style short names that every command with a common verb accepts (D6).
|
||||
// Commands add other gh verbs, such as new, co, add and get, to their own Aliases.
|
||||
var verbAliases = map[string]string{"list": "ls", "delete": "rm"}
|
||||
|
||||
// addVerbAliases gives every list and delete command its short name.
|
||||
func addVerbAliases(cmd *cobra.Command) {
|
||||
if alias, ok := verbAliases[cmd.Name()]; ok && cmd.HasParent() && !slices.Contains(cmd.Aliases, alias) {
|
||||
cmd.Aliases = append(cmd.Aliases, alias)
|
||||
}
|
||||
for _, child := range cmd.Commands() {
|
||||
addVerbAliases(child)
|
||||
}
|
||||
}
|
||||
|
||||
// flagAliases makes the flags of cmd accept each key of aliases as another name of the flag it maps
|
||||
// to, without showing it in help. Renamed flags keep their old names working this way, such as the
|
||||
// plural --add-labels after the singular gh name --add-label became primary (D8).
|
||||
func flagAliases(cmd *cobra.Command, aliases map[string]string) {
|
||||
normalize := cmd.Flags().GetNormalizeFunc()
|
||||
cmd.Flags().SetNormalizeFunc(func(flags *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
if to, ok := aliases[name]; ok {
|
||||
name = to
|
||||
}
|
||||
return normalize(flags, name)
|
||||
})
|
||||
}
|
||||
|
||||
// checkOutputFlags validates --json and --jq before a command runs. --jq alone selects every field,
|
||||
// except on commands that filter their raw JSON themselves (annotation tea.rawjson).
|
||||
func (a *application) checkOutputFlags(cmd *cobra.Command) error {
|
||||
|
||||
@@ -192,3 +192,39 @@ func TestRawJSONCommandsKeepJQToThemselves(t *testing.T) {
|
||||
root.SetArgs([]string{"raw", "--json"})
|
||||
require.ErrorContains(t, root.Execute(), "raw prints text; --json is not supported")
|
||||
}
|
||||
|
||||
func TestVerbAndFlagAliases(t *testing.T) {
|
||||
deps, _, _ := testDeps(t)
|
||||
root := NewRoot(deps)
|
||||
for _, args := range [][]string{{"issue", "ls"}, {"label", "rm"}, {"pr", "review", "ls"}} {
|
||||
cmd, _, err := root.Find(args)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, map[string]string{"ls": "list", "rm": "delete"}[args[len(args)-1]], cmd.Name(), args)
|
||||
}
|
||||
// Aliases never shadow a sibling command.
|
||||
walkCommands(root, func(cmd *cobra.Command) {
|
||||
names := map[string]string{}
|
||||
for _, child := range cmd.Commands() {
|
||||
for _, name := range append([]string{child.Name()}, child.Aliases...) {
|
||||
require.Empty(t, names[name], "%s %s is both %s and %s", cmd.CommandPath(), name, names[name], child.Name())
|
||||
names[name] = child.Name()
|
||||
}
|
||||
}
|
||||
})
|
||||
var labels []string
|
||||
edit := &cobra.Command{Use: "edit", RunE: func(*cobra.Command, []string) error { return nil }}
|
||||
edit.Flags().StringSliceVar(&labels, "add-label", nil, "Add labels")
|
||||
flagAliases(edit, map[string]string{"add-labels": "add-label"})
|
||||
edit.SetArgs([]string{"--add-labels", "bug", "--add-label", "docs"})
|
||||
require.NoError(t, edit.Execute())
|
||||
require.Equal(t, []string{"bug", "docs"}, labels)
|
||||
require.NotContains(t, edit.UsageString(), "add-labels")
|
||||
}
|
||||
|
||||
// walkCommands calls visit for cmd and each of its descendants.
|
||||
func walkCommands(cmd *cobra.Command, visit func(*cobra.Command)) {
|
||||
visit(cmd)
|
||||
for _, child := range cmd.Commands() {
|
||||
walkCommands(child, visit)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user