Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
|
160b3321ef | |
|
73d7db2078 | |
|
b4759d5f08 | |
|
1fbc94aa49 | |
|
26bee58adc | |
|
ba90879ff0 | |
|
a573f722af |
16
command.go
16
command.go
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
type Command struct {
|
||||
Name string
|
||||
version string
|
||||
ShortDescription string
|
||||
LongDescription string
|
||||
Aliases []string
|
||||
|
@ -20,8 +21,8 @@ type Command struct {
|
|||
isRoot bool
|
||||
}
|
||||
|
||||
func NewRoot(name string, options ...Option) *Command {
|
||||
cmd := &Command{Name: name, isRoot: true}
|
||||
func NewRoot(name string, version string, options ...Option) *Command {
|
||||
cmd := &Command{Name: name, version: version, isRoot: true}
|
||||
cmd.ApplyOptions(options...)
|
||||
return cmd
|
||||
}
|
||||
|
@ -91,6 +92,12 @@ func (c *Command) Execute(args []string) {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
versionOpt, ok := opt.Globals().GetBool("version")
|
||||
if ok && versionOpt.Value() {
|
||||
c.ShowVersion()
|
||||
return
|
||||
}
|
||||
|
||||
helpOpt, ok := opt.Globals().GetBool("help")
|
||||
if ok && helpOpt.Value() {
|
||||
c.ShowHelp()
|
||||
|
@ -104,3 +111,8 @@ func (c *Command) Execute(args []string) {
|
|||
|
||||
c.ShowHelp()
|
||||
}
|
||||
|
||||
func (c *Command) ShowVersion() {
|
||||
rootName := c.Root().Name
|
||||
fmt.Printf("%s %s\n", rootName, c.version)
|
||||
}
|
||||
|
|
|
@ -9,11 +9,82 @@ import (
|
|||
|
||||
func WritePowerShellCompletions(out io.Writer, rootCmd *Command) error {
|
||||
return powerShellTpl.Execute(out, map[string]any{
|
||||
"rootCmd": rootCmd,
|
||||
"globalOpts": opt.Globals(),
|
||||
"RootCmd": rootCmd,
|
||||
"GlobalOpts": opt.Globals(),
|
||||
})
|
||||
}
|
||||
|
||||
var powerShellTpl = template.Must(template.New("PowerShell").Parse(`
|
||||
|
||||
var powerShellTpl = template.Must(template.New("PowerShell").Funcs(tplFuncs).Parse(`
|
||||
{{- $rootCmd := .RootCmd -}}
|
||||
{{- $progName := $rootCmd.Name -}}
|
||||
{{- $varName := $rootCmd.Name | camel -}}
|
||||
|
||||
{{- define "cmd" -}}
|
||||
{{- $progName := .ProgName -}}
|
||||
{{- if .Cmd.IsRoot }}
|
||||
{{- /**/}} '{{ $progName }}' {
|
||||
{{- else }}
|
||||
{{- /**/}} '{{ $progName }};{{ join (split .Cmd.CommandPath " ") ";" }}' {
|
||||
{{- end -}}
|
||||
{{- range .Cmd.Opts -}}
|
||||
{{ if ne .Name "" }}
|
||||
[CompletionResult]::new('--{{ .Name }}', '{{ .Name }}', [CompletionResultType]::ParameterName, '{{ .Description }}')
|
||||
{{- end -}}
|
||||
{{- if ne .ShortName "" }}
|
||||
[CompletionResult]::new('-{{ .ShortName }}', '{{ .ShortName }}', [CompletionResultType]::ParameterName, '{{ .Description }}')
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
{{- range .Cmd.Subcommands }}
|
||||
[CompletionResult]::new('{{ .Name }}', '{{ .Name }}', [CompletionResultType]::ParameterValue, '{{ .ShortDescription }}')
|
||||
{{- end }}
|
||||
break;
|
||||
}
|
||||
{{- range .Cmd.Subcommands }}
|
||||
{{ template "cmd" (map "Cmd" . "ProgName" $progName) }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
using namespace System.Management.Automation
|
||||
using namespace System.Management.Automation.Language
|
||||
|
||||
[scriptblock]$__{{ $varName }}CompleterBlock = {
|
||||
param(
|
||||
$wordToComplete,
|
||||
$commandAst,
|
||||
$cursorPosition
|
||||
)
|
||||
|
||||
$commandElements
|
||||
$command = @(
|
||||
'{{ $progName }}'
|
||||
for ($i = 1; $i -lt $commandElements.Count; $i++) {
|
||||
$element = $commandElements[$i]
|
||||
if ($element -isnot [StringConstantExpressionAst] -or
|
||||
$element.StringConstantType -ne [StringConstantType]::BareWord -or
|
||||
$element.Value.StartsWith('-') -or
|
||||
$element.Value -eq $wordToComplete) {
|
||||
break
|
||||
}
|
||||
$element.Value
|
||||
}
|
||||
) -join ';'
|
||||
|
||||
$completions = @(
|
||||
switch ($command) {
|
||||
{{ template "cmd" (map "Cmd" $rootCmd "ProgName" $progName) }}
|
||||
}
|
||||
{{- range .GlobalOpts -}}
|
||||
{{- if ne .Name "" }}
|
||||
[CompletionResult]::new('--{{ .Name }}', '{{ .Name }}', [CompletionResultType]::ParameterName, '{{ .Description }}')
|
||||
{{- end -}}
|
||||
{{- if ne .ShortName "" }}
|
||||
[CompletionResult]::new('-{{ .ShortName }}', '{{ .ShortName }}', [CompletionResultType]::ParameterName, '{{ .Description }}')
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
)
|
||||
|
||||
$completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
|
||||
Sort-Object -Property ListItemText
|
||||
}
|
||||
|
||||
Register-ArgumentCompleter -CommandName {{ $progName }} -ScriptBlock $__{{ $varName }}CompleterBlock
|
||||
`))
|
||||
|
|
|
@ -38,8 +38,12 @@ var zshTpl = template.Must(template.New("zsh").Funcs(tplFuncs).Parse(`
|
|||
_arguments
|
||||
{{- end -}}
|
||||
{{- range .Cmd.Opts -}}
|
||||
{{ " " }}\
|
||||
{{- if ne .Name ""}} \
|
||||
'--{{ .Name }}[{{ .Description }}]'
|
||||
{{- end }}
|
||||
{{- if ne .ShortName ""}} \
|
||||
'-{{ .ShortName }}[{{ .Description }}]'
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if gt (len .Cmd.Subcommands) 0 -}}
|
||||
{{ " " }}\
|
||||
|
@ -63,6 +67,18 @@ var zshTpl = template.Must(template.New("zsh").Funcs(tplFuncs).Parse(`
|
|||
|
||||
function _{{ $varName }} {
|
||||
{{ template "cmd" (map "Cmd" .RootCmd) -}}
|
||||
|
||||
{{- if gt (len .GlobalOpts) 0 }}
|
||||
_arguments
|
||||
{{- range .GlobalOpts -}}
|
||||
{{- if ne .Name ""}} \
|
||||
'--{{ .Name }}[{{ .Description }}]'
|
||||
{{- end }}
|
||||
{{- if ne .ShortName ""}} \
|
||||
'-{{ .ShortName }}[{{ .Description }}]'
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
compdef _{{ $varName }} {{ $progName }}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -1,3 +1,5 @@
|
|||
module go.fifitido.net/cmd
|
||||
|
||||
go 1.21.3
|
||||
|
||||
require github.com/iancoleman/strcase v0.3.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -0,0 +1,2 @@
|
|||
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
|
||||
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
5
help.go
5
help.go
|
@ -2,6 +2,7 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"go.fifitido.net/cmd/opt"
|
||||
)
|
||||
|
@ -43,8 +44,10 @@ func (c *Command) ShowHelp() {
|
|||
fmt.Println("Available subcommands:")
|
||||
}
|
||||
|
||||
paddedWidth := c.Subcommands.MaxWidth()
|
||||
for _, s := range c.Subcommands {
|
||||
fmt.Println(" " + s.Name + " " + s.ShortDescription)
|
||||
spaceSize := 2 + paddedWidth - len(s.Name)
|
||||
fmt.Println(" " + s.Name + strings.Repeat(" ", spaceSize) + s.ShortDescription)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
set.go
2
set.go
|
@ -25,7 +25,7 @@ func (s Set) Get(name string) (*Command, bool) {
|
|||
return nil, false
|
||||
}
|
||||
|
||||
func (s Set) MaxNameWidth() int {
|
||||
func (s Set) MaxWidth() int {
|
||||
max := 0
|
||||
for _, f := range s {
|
||||
if w := len(f.Name); w > max {
|
||||
|
|
19
tpl_funcs.go
19
tpl_funcs.go
|
@ -4,11 +4,14 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/iancoleman/strcase"
|
||||
)
|
||||
|
||||
var tplFuncs = template.FuncMap{
|
||||
"map": tplMap,
|
||||
"cat": tplCat,
|
||||
"split": tplSplit,
|
||||
"join": tplJoin,
|
||||
"under": tplUnder,
|
||||
"varPrefix": tplVarPrefix,
|
||||
|
@ -19,6 +22,8 @@ var tplFuncs = template.FuncMap{
|
|||
"sub": tplSub,
|
||||
"dec": tplDec,
|
||||
"mult": tplMult,
|
||||
"pascal": tplPascal,
|
||||
"camel": tplCamel,
|
||||
}
|
||||
|
||||
func tplMap(vals ...any) (map[string]any, error) {
|
||||
|
@ -37,12 +42,16 @@ func tplCat(strs ...string) string {
|
|||
return strings.Join(strs, "")
|
||||
}
|
||||
|
||||
func tplSplit(s string, sep string) []string {
|
||||
return strings.Split(s, sep)
|
||||
}
|
||||
|
||||
func tplJoin(strs []string, sep string) string {
|
||||
return strings.Join(strs, sep)
|
||||
}
|
||||
|
||||
func tplUnder(s string) string {
|
||||
return strings.ToLower(strings.ReplaceAll(strings.ReplaceAll(s, " ", "_"), "-", "_"))
|
||||
return strcase.ToSnake(s)
|
||||
}
|
||||
|
||||
func tplVarPrefix(s string) string {
|
||||
|
@ -80,3 +89,11 @@ func tplDec(i int) int {
|
|||
func tplMult(a, b int) int {
|
||||
return a * b
|
||||
}
|
||||
|
||||
func tplPascal(s string) string {
|
||||
return strcase.ToCamel(s)
|
||||
}
|
||||
|
||||
func tplCamel(s string) string {
|
||||
return strcase.ToLowerCamel(s)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue