diff --git a/completions_powershell.go b/completions_powershell.go index a0f271a..ea55e56 100644 --- a/completions_powershell.go +++ b/completions_powershell.go @@ -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 `)) diff --git a/completions_zsh.go b/completions_zsh.go index 50f0cf7..3f0d286 100644 --- a/completions_zsh.go +++ b/completions_zsh.go @@ -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 }} diff --git a/go.mod b/go.mod index f6fed3c..3aac729 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module go.fifitido.net/cmd go 1.21.3 + +require github.com/iancoleman/strcase v0.3.0 diff --git a/go.sum b/go.sum index e69de29..6261b6a 100644 --- a/go.sum +++ b/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= diff --git a/tpl_funcs.go b/tpl_funcs.go index 834f3a4..ab29b83 100644 --- a/tpl_funcs.go +++ b/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) +}