Skip to content

Commit df308e6

Browse files
authored
Merge pull request #1335 from rsteube/spec-integrate-root
spec: integrate on root level
2 parents 5ce0ecd + 4f22458 commit df308e6

File tree

4 files changed

+106
-157
lines changed

4 files changed

+106
-157
lines changed

cmd/carapace/cmd/completers/completers.go

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,62 @@ package completers
33
import (
44
"fmt"
55
"os"
6+
"regexp"
7+
"sort"
8+
"strings"
69

710
"gopkg.in/yaml.v3"
811
)
912

1013
func Names() []string {
11-
return names
14+
unique := make(map[string]string)
15+
for _, name := range names {
16+
unique[name] = name
17+
}
18+
//if specNames, err := Specs(); err == nil {
19+
if specNames, _ := Specs(); true { // TODO use and handle err
20+
for _, name := range specNames {
21+
unique[name] = name
22+
}
23+
}
24+
25+
combined := make([]string, 0, len(unique))
26+
for name := range unique {
27+
combined = append(combined, name)
28+
}
29+
sort.Strings(combined)
30+
return combined
31+
}
32+
33+
func SpecPath(name string) (string, error) {
34+
configDir, err := os.UserConfigDir()
35+
if err != nil {
36+
return "", err
37+
}
38+
39+
path := fmt.Sprintf("%v/carapace/specs/%v.yaml", configDir, name)
40+
if _, err := os.Stat(path); err != nil {
41+
return "", err
42+
}
43+
return path, nil
44+
}
45+
46+
func Specs() (specs []string, dir string) {
47+
r := regexp.MustCompile(`^[0-9a-zA-Z_\-.]+\.yaml$`) // sanity check
48+
specs = make([]string, 0)
49+
if configDir, err := os.UserConfigDir(); err == nil {
50+
dir = configDir + "/carapace/specs"
51+
if entries, err := os.ReadDir(dir); err == nil {
52+
for _, entry := range entries {
53+
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".yaml") && r.MatchString(entry.Name()) {
54+
specs = append(specs, strings.TrimSuffix(entry.Name(), ".yaml"))
55+
}
56+
}
57+
} else if os.IsNotExist(err) {
58+
os.MkdirAll(dir, os.ModePerm)
59+
}
60+
}
61+
return
1262
}
1363

1464
func Description(name string) string {

cmd/carapace/cmd/lazyInit.go

Lines changed: 4 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,16 @@ package cmd
44

55
import (
66
"fmt"
7-
"os"
8-
"regexp"
97
"strings"
108
)
119

12-
func getSpecs() (specs []string, dir string) {
13-
r := regexp.MustCompile(`^[0-9a-zA-Z_\-.]+\.yaml$`) // sanity check
14-
specs = make([]string, 0)
15-
if configDir, err := os.UserConfigDir(); err == nil {
16-
dir = configDir + "/carapace/specs"
17-
if entries, err := os.ReadDir(dir); err == nil {
18-
for _, entry := range entries {
19-
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".yaml") && r.MatchString(entry.Name()) {
20-
specs = append(specs, strings.TrimSuffix(entry.Name(), ".yaml"))
21-
}
22-
}
23-
} else if os.IsNotExist(err) {
24-
os.MkdirAll(dir, os.ModePerm)
25-
}
26-
}
27-
return
28-
}
29-
3010
func bash_lazy(completers []string) string {
3111
snippet := `_carapace_lazy() {
3212
source <(carapace $1 bash)
3313
$"_$1_completion"
3414
}
3515
complete -F _carapace_lazy %v
3616
`
37-
38-
if specs, dir := getSpecs(); len(specs) > 0 {
39-
snippet += fmt.Sprintf(`
40-
_carapace_lazy_spec() {
41-
source <(carapace --spec "%v/$1.yaml" bash)
42-
$"_$1_completion"
43-
}
44-
complete -F _carapace_lazy_spec %v
45-
`, dir, strings.Join(specs, " "))
46-
}
47-
4817
return fmt.Sprintf(snippet, strings.Join(completers, " "))
4918
}
5019

@@ -55,17 +24,6 @@ func bash_ble_lazy(completers []string) string {
5524
}
5625
complete -F _carapace_lazy %v
5726
`
58-
59-
if specs, dir := getSpecs(); len(specs) > 0 {
60-
snippet += fmt.Sprintf(`
61-
_carapace_lazy_spec() {
62-
source <(carapace --spec %v/$1.yaml bash-ble)
63-
$"_$1_completion_ble"
64-
}
65-
complete -F _carapace_lazy_spec %v
66-
`, dir, strings.Join(specs, " "))
67-
}
68-
6927
return fmt.Sprintf(snippet, strings.Join(completers, " "))
7028
}
7129

@@ -78,20 +36,6 @@ func elvish_lazy(completers []string) string {
7836
}
7937
}
8038
`
81-
if specs, dir := getSpecs(); len(specs) > 0 {
82-
snippet += fmt.Sprintf(`
83-
put %v | each {|c|
84-
set edit:completion:arg-completer[$c] = {|@arg|
85-
set edit:completion:arg-completer[$c] = {|@arg| }
86-
eval (carapace --spec "%v/"$c".yaml" elvish | slurp)
87-
$edit:completion:arg-completer[$c] $@arg
88-
}
89-
90-
}
91-
`, strings.Join(specs, " "), dir)
92-
93-
}
94-
9539
return fmt.Sprintf(snippet, strings.Join(completers, " "))
9640
}
9741

@@ -107,42 +51,17 @@ end
10751
for index, completer := range completers {
10852
complete[index] = fmt.Sprintf(`complete -c '%v' -f -a '(_carapace_lazy %v)'`, completer, completer)
10953
}
110-
111-
if specs, dir := getSpecs(); len(specs) > 0 {
112-
snippet += fmt.Sprintf(`
113-
function _carapace_lazy_spec
114-
complete -c $argv[1] -e
115-
carapace --spec "%v/$argv[1].yaml" fish | source
116-
complete --do-complete=(commandline -cp)
117-
end
118-
119-
`, dir)
120-
for _, spec := range specs {
121-
snippet += fmt.Sprintf(`complete -c '%v' -f -a '(_carapace_lazy_spec %v)'
122-
`, spec, spec)
123-
}
124-
}
125-
12654
return fmt.Sprintf(snippet, strings.Join(complete, "\n"))
12755
}
12856

12957
func nushell_lazy(completers []string) string {
130-
specs, dir := getSpecs()
131-
132-
specSnippets := make([]string, 0)
133-
for _, spec := range specs {
134-
specSnippets = append(specSnippets, fmt.Sprintf(` %v: { carapace --spec '%v/%v.yaml' nushell $spans | from json }
135-
`, spec, dir, spec))
136-
}
137-
return fmt.Sprintf(`let external_completer = {|spans|
138-
{
139-
$spans.0: {carapace $spans.0 nushell $spans | from json } # default
140-
%v } | get $spans.0 | each {|it| do $it}
58+
return `let carapace_completer = {|spans|
59+
carapace $spans.0 nushell $spans | from json
14160
}
14261
14362
let-env config = {
144-
external_completer: $external_completer
145-
}`, strings.Join(specSnippets, ""))
63+
external_completer: $carapace_completer
64+
}`
14665
}
14766

14867
func oil_lazy(completers []string) string {
@@ -152,17 +71,6 @@ func oil_lazy(completers []string) string {
15271
}
15372
complete -F _carapace_lazy %v
15473
`
155-
156-
if specs, dir := getSpecs(); len(specs) > 0 {
157-
snippet += fmt.Sprintf(`
158-
_carapace_lazy_spec() {
159-
source <(carapace --spec "%v/$1.yaml" oil)
160-
$"_$1_completion"
161-
}
162-
complete -F _carapace_lazy_spec %v
163-
`, dir, strings.Join(specs, " "))
164-
}
165-
16674
return fmt.Sprintf(snippet, strings.Join(completers, " "))
16775
}
16876

@@ -179,22 +87,6 @@ func powershell_lazy(completers []string) string {
17987
for index, completer := range completers {
18088
complete[index] = fmt.Sprintf(`Register-ArgumentCompleter -Native -CommandName '%v' -ScriptBlock $_carapace_lazy`, completer)
18189
}
182-
183-
if specs, dir := getSpecs(); len(specs) > 0 {
184-
snippet += fmt.Sprintf(`$_carapace_lazy_spec = {
185-
param($wordToComplete, $commandAst, $cursorPosition)
186-
$completer = $commandAst.CommandElements[0].Value
187-
carapace --spec "%v/$completer.yaml" powershell | Out-String | Invoke-Expression
188-
& (Get-Item "Function:_${completer}_completer") $wordToComplete $commandAst $cursorPosition
189-
}
190-
`, dir)
191-
for _, spec := range specs {
192-
snippet += fmt.Sprintf(`Register-ArgumentCompleter -Native -CommandName '%v' -ScriptBlock $_carapace_lazy_spec
193-
`, spec)
194-
}
195-
196-
}
197-
19890
return fmt.Sprintf(snippet, strings.Join(complete, "\n"))
19991
}
20092

@@ -204,12 +96,6 @@ func tcsh_lazy(completers []string) string {
20496
for index, c := range completers {
20597
snippet[index] = fmt.Sprintf("complete \"%v\" 'p@*@`echo \"$COMMAND_LINE'\"''\"'\" | xargs carapace %v tcsh `@@' ;", c, c)
20698
}
207-
208-
if specs, dir := getSpecs(); len(specs) > 0 {
209-
for _, spec := range specs {
210-
snippet = append(snippet, fmt.Sprintf("complete \"%v\" 'p@*@`echo \"$COMMAND_LINE'\"''\"'\" | xargs carapace --spec \"%v/%v.yaml\" tcsh `@@' ;", spec, dir, spec))
211-
}
212-
}
21399
return strings.Join(snippet, "\n")
214100
}
215101

@@ -231,22 +117,6 @@ def _carapace_lazy(context):
231117
for index, completer := range completers {
232118
complete[index] = fmt.Sprintf(`'%v'`, completer)
233119
}
234-
235-
if specs, dir := getSpecs(); len(specs) > 0 {
236-
quotedSpecs := make([]string, 0)
237-
for _, spec := range specs {
238-
quotedSpecs = append(quotedSpecs, fmt.Sprintf(`'%v'`, spec))
239-
}
240-
snippet += fmt.Sprintf(`
241-
if (context.command and
242-
context.command.arg_index > 0 and
243-
context.command.args[0].value in [%v]):
244-
XSH.completers = XSH.completers.copy()
245-
exec(compile(subprocess.run(['carapace', '--spec', '%v/'+context.command.args[0].value+'.yaml', 'xonsh'], stdout=subprocess.PIPE).stdout.decode('utf-8'), "", "exec"))
246-
return XSH.completers[context.command.args[0].value](context)
247-
`, strings.Join(quotedSpecs, ", "), dir)
248-
249-
}
250120
snippet += `_add_one_completer('carapace_lazy', _carapace_lazy, 'start')`
251121
return fmt.Sprintf(snippet, strings.Join(complete, ", "))
252122
}
@@ -257,15 +127,5 @@ func zsh_lazy(completers []string) string {
257127
}
258128
compdef _carapace_lazy %v
259129
`
260-
261-
if specs, dir := getSpecs(); len(specs) > 0 {
262-
snippet += fmt.Sprintf(`function _carapace_lazy_spec {
263-
source <(carapace --spec "%v/$words[1].yaml" zsh)
264-
}
265-
compdef _carapace_lazy_spec %v
266-
`, dir, strings.Join(specs, " "))
267-
268-
}
269-
270130
return fmt.Sprintf(snippet, strings.Join(completers, " "))
271131
}

cmd/carapace/cmd/root.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package cmd
44

55
import (
66
"bytes"
7+
"encoding/json"
78
"fmt"
89
"io"
910
"os"
@@ -107,6 +108,8 @@ var rootCmd = &cobra.Command{
107108
println(cmd.Version)
108109
case "--list":
109110
printCompleters()
111+
case "--list=json":
112+
printCompletersJson()
110113
case "--style":
111114
if len(args) > 1 {
112115
if err := setStyle(args[1]); err != nil {
@@ -143,7 +146,11 @@ var rootCmd = &cobra.Command{
143146
fmt.Fprintln(os.Stderr, "could not determine shell")
144147
}
145148
default:
146-
invokeCompleter(args[0])
149+
if specPath, err := completers.SpecPath(args[0]); err == nil {
150+
specCompletion(specPath, args[1:]...)
151+
} else {
152+
invokeCompleter(args[0])
153+
}
147154
}
148155

149156
},
@@ -171,6 +178,28 @@ func printCompleters() {
171178
}
172179
}
173180

181+
func printCompletersJson() {
182+
// TODO move to completers package
183+
type _completer struct {
184+
Name string
185+
Description string
186+
Spec string
187+
}
188+
189+
_completers := make([]_completer, 0)
190+
for _, name := range completers.Names() {
191+
specPath, _ := completers.SpecPath(name) // TODO handle error (log?)
192+
_completers = append(_completers, _completer{
193+
Name: name,
194+
Description: completers.Description(name),
195+
Spec: specPath,
196+
})
197+
}
198+
if m, err := json.Marshal(_completers); err == nil { // TODO handle error (log?)
199+
fmt.Println(string(m))
200+
}
201+
}
202+
174203
func printMacros() {
175204
maxlen := 0
176205
names := make([]string, 0)

0 commit comments

Comments
 (0)