Skip to content

Commit 434b363

Browse files
committed
shell: cmd-clink
experimental initial version
1 parent 8c147a6 commit 434b363

File tree

10 files changed

+134
-1
lines changed

10 files changed

+134
-1
lines changed

command.go

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func addCompletionCommand(targetCmd *cobra.Command) {
5757
ActionStyledValues(
5858
"bash", "#d35673",
5959
"bash-ble", "#c2039a",
60+
"cmd-clink", "#2B3436",
6061
"elvish", "#ffd6c9",
6162
"export", style.Default,
6263
"fish", "#7ea8fc",

complete.go

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/carapace-sh/carapace/internal/config"
77
"github.com/carapace-sh/carapace/internal/shell/bash"
8+
"github.com/carapace-sh/carapace/internal/shell/cmd_clink"
89
"github.com/carapace-sh/carapace/internal/shell/nushell"
910
"github.com/carapace-sh/carapace/pkg/ps"
1011
"github.com/spf13/cobra"
@@ -37,6 +38,14 @@ func complete(cmd *cobra.Command, args []string) (string, error) {
3738
}
3839
return ActionMessage(err.Error()).Invoke(context).value(args[0], args[len(args)-1]), nil
3940
}
41+
case "cmd-clink":
42+
var err error
43+
args, err = cmd_clink.Patch(args)
44+
LOG.Printf("patching args to %#v", args)
45+
if err != nil {
46+
context := NewContext(args...)
47+
return ActionMessage(err.Error()).Invoke(context).value(args[0], args[len(args)-1]), nil
48+
}
4049
}
4150

4251
action, context := traverse(cmd, args[2:])

example/cmd/_test/cmd-clink.lua

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
local function example_completion(word, word_index, line_state, match_builder)
2+
local compline = string.sub(line_state:getline(), 1, line_state:getcursor())
3+
4+
local output = io.popen("env CARAPACE_COMPLINE=" .. string.format("%q", compline) .. " example _carapace cmd-clink \"\""):read("*a")
5+
for line in string.gmatch(output, '[^\r\n]+') do
6+
local matches = {}
7+
for m in string.gmatch(line, '[^\t]+') do
8+
table.insert(matches, m)
9+
end
10+
match_builder:addmatch({
11+
match = matches[1],
12+
display = matches[2],
13+
description = matches[3],
14+
type = "word",
15+
appendchar = matches[4],
16+
suppressappend = false
17+
})
18+
end
19+
return true
20+
end
21+
22+
clink.argmatcher("example"):addarg({nowordbreakchars="'‵+;,", example_completion}):loop(1)
23+

example/cmd/root_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ func TestBashBle(t *testing.T) {
2828
testScript(t, "bash-ble", "./_test/bash-ble.sh")
2929
}
3030

31+
func TestCmdClink(t *testing.T) {
32+
testScript(t, "cmd-clink", "./_test/cmd-clink.lua")
33+
}
34+
3135
func TestElvish(t *testing.T) {
3236
testScript(t, "elvish", "./_test/elvish.elv")
3337
}

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/carapace-sh/carapace
22

3-
go 1.15
3+
go 1.16
44

55
require (
66
github.com/carapace-sh/carapace-shlex v1.0.1

internal/shell/cmd_clink/action.go

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package cmd_clink
2+
3+
import (
4+
"strings"
5+
6+
"github.com/carapace-sh/carapace/internal/common"
7+
)
8+
9+
var sanitizer = strings.NewReplacer(
10+
"\n", ``,
11+
"\r", ``,
12+
"\t", ``,
13+
)
14+
15+
func ActionRawValues(currentWord string, meta common.Meta, values common.RawValues) string {
16+
vals := make([]string, len(values))
17+
for index, val := range values {
18+
appendChar := " "
19+
if meta.Nospace.Matches(val.Value) {
20+
appendChar = ""
21+
}
22+
vals[index] = strings.Join([]string{
23+
sanitizer.Replace(val.Value),
24+
sanitizer.Replace(val.Display),
25+
sanitizer.Replace(val.TrimmedDescription()),
26+
appendChar,
27+
}, "\t")
28+
}
29+
return strings.Join(vals, "\n")
30+
}

internal/shell/cmd_clink/patch.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package cmd_clink
2+
3+
import (
4+
"os"
5+
6+
shlex "github.com/carapace-sh/carapace-shlex"
7+
)
8+
9+
func Patch(args []string) ([]string, error) {
10+
compline, ok := os.LookupEnv("CARAPACE_COMPLINE")
11+
if !ok {
12+
return args, nil
13+
}
14+
os.Unsetenv("CARAPACE_COMPLINE")
15+
16+
if compline == "" {
17+
return args, nil
18+
}
19+
20+
tokens, err := shlex.Split(compline)
21+
if err != nil {
22+
return nil, err
23+
}
24+
args = append(args[:1], tokens.CurrentPipeline().FilterRedirects().Words().Strings()...)
25+
return args, nil
26+
}

internal/shell/cmd_clink/snippet.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package cmd_clink
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/carapace-sh/carapace/pkg/uid"
7+
"github.com/spf13/cobra"
8+
)
9+
10+
func Snippet(cmd *cobra.Command) string {
11+
result := fmt.Sprintf(`local function %v_completion(word, word_index, line_state, match_builder)
12+
local compline = string.sub(line_state:getline(), 1, line_state:getcursor())
13+
14+
local output = io.popen("env CARAPACE_COMPLINE=" .. string.format("%%q", compline) .. " %v _carapace cmd-clink \"\""):read("*a")
15+
for line in string.gmatch(output, '[^\r\n]+') do
16+
local matches = {}
17+
for m in string.gmatch(line, '[^\t]+') do
18+
table.insert(matches, m)
19+
end
20+
match_builder:addmatch({
21+
match = matches[1],
22+
display = matches[2],
23+
description = matches[3],
24+
type = "word",
25+
appendchar = matches[4],
26+
suppressappend = false
27+
})
28+
end
29+
return true
30+
end
31+
32+
clink.argmatcher("%v"):addarg({nowordbreakchars="'‵+;,", %v_completion}):loop(1)
33+
`, cmd.Name(), uid.Executable(), cmd.Name(), cmd.Name())
34+
return result
35+
}

internal/shell/shell.go

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/carapace-sh/carapace/internal/env"
1111
"github.com/carapace-sh/carapace/internal/shell/bash"
1212
"github.com/carapace-sh/carapace/internal/shell/bash_ble"
13+
"github.com/carapace-sh/carapace/internal/shell/cmd_clink"
1314
"github.com/carapace-sh/carapace/internal/shell/elvish"
1415
"github.com/carapace-sh/carapace/internal/shell/export"
1516
"github.com/carapace-sh/carapace/internal/shell/fish"
@@ -33,6 +34,7 @@ func Snippet(cmd *cobra.Command, shell string) (string, error) {
3334
shellSnippets := map[string]func(cmd *cobra.Command) string{
3435
"bash": bash.Snippet,
3536
"bash-ble": bash_ble.Snippet,
37+
"cmd-clink": cmd_clink.Snippet,
3638
"export": export.Snippet,
3739
"fish": fish.Snippet,
3840
"elvish": elvish.Snippet,
@@ -60,6 +62,7 @@ func Value(shell string, value string, meta common.Meta, values common.RawValues
6062
shellFuncs := map[string]func(currentWord string, meta common.Meta, values common.RawValues) string{
6163
"bash": bash.ActionRawValues,
6264
"bash-ble": bash_ble.ActionRawValues,
65+
"cmd-clink": cmd_clink.ActionRawValues,
6366
"fish": fish.ActionRawValues,
6467
"elvish": elvish.ActionRawValues,
6568
"export": export.ActionRawValues,

pkg/ps/ps.go

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ func DetermineShell() string {
2626
return "bash-ble"
2727
}
2828
return "bash"
29+
case "cmd":
30+
return "cmd-clink"
2931
case "elvish":
3032
return "elvish"
3133
case "fish":

0 commit comments

Comments
 (0)