Skip to content

Commit b1bf2b0

Browse files
authored
Merge pull request #3012 from carapace-sh/ssh-config-include
ssh: support `Include` directive
2 parents 8b6d56e + 30714e3 commit b1bf2b0

File tree

7 files changed

+32
-39
lines changed

7 files changed

+32
-39
lines changed

completers/common/scp_completer/cmd/root.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ func init() {
7474
carapace.ActionMultiParts(":", func(c carapace.Context) carapace.Action {
7575
switch len(c.Parts) {
7676
case 0:
77-
return net.ActionHosts().Invoke(c).Merge(carapace.ActionFiles().Invoke(c)).ToA().NoSpace()
77+
return carapace.Batch(
78+
net.ActionHosts(),
79+
ssh.ActionHosts(rootCmd.Flag("F").Value.String()).Style("yellow"),
80+
carapace.ActionFiles(),
81+
).ToA().NoSpace()
7882
default:
7983
return carapace.ActionValues()
8084
}

completers/common/ssh_completer/cmd/root.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,16 @@ func init() {
104104

105105
carapace.Gen(rootCmd).PositionalCompletion(
106106
carapace.ActionCallback(func(c carapace.Context) carapace.Action {
107+
action := carapace.Batch(
108+
net.ActionHosts(),
109+
ssh.ActionHosts(rootCmd.Flag("F").Value.String()).Style("yellow"),
110+
).ToA()
111+
107112
if strings.Contains(c.Value, "@") {
108113
prefix := strings.SplitN(c.Value, "@", 2)[0]
109-
return net.ActionHosts().Invoke(c).Prefix(prefix + "@").ToA()
110-
} else {
111-
return net.ActionHosts()
114+
action = action.Prefix(prefix + "@")
112115
}
116+
return action
113117
}),
114118
)
115119
}

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ require (
1818

1919
require (
2020
github.com/inconshreveable/mousetrap v1.1.0 // indirect
21+
github.com/kevinburke/ssh_config v1.4.0
2122
github.com/stretchr/testify v1.8.1 // indirect
2223
)
2324

2425
replace github.com/spf13/pflag => github.com/carapace-sh/carapace-pflag v1.0.0
26+
27+
replace github.com/kevinburke/ssh_config => github.com/carapace-sh/ssh_config v1.4.1-0.20251016142129-177d27a2d08a

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ github.com/carapace-sh/carapace-shlex v1.1.0 h1:58QSJTUxghpa/rEn6+Z9UM/Hy0ipVHDU
1010
github.com/carapace-sh/carapace-shlex v1.1.0/go.mod h1:lJ4ZsdxytE0wHJ8Ta9S7Qq0XpjgjU0mdfCqiI2FHx7M=
1111
github.com/carapace-sh/carapace-spec v1.3.4 h1:uNGRIP1XX68xl7rvXfpnVsDJh5ct+X1fFTswZ1IFXbQ=
1212
github.com/carapace-sh/carapace-spec v1.3.4/go.mod h1:zyc8AB5LiJ1g2apoejms+CHOVZKSVra4tefyWL5nU9s=
13+
github.com/carapace-sh/ssh_config v1.4.1-0.20251016142129-177d27a2d08a h1:00oRlK/Mk5oYS0lh/X2bmgLeO9fuoE8B/8i1gQuJpaE=
14+
github.com/carapace-sh/ssh_config v1.4.1-0.20251016142129-177d27a2d08a/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
1315
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
1416
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1517
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=

internal/actions/net/ssh/ssh.go

Lines changed: 0 additions & 6 deletions
This file was deleted.

pkg/actions/net/net.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"strings"
88

99
"github.com/carapace-sh/carapace"
10-
"github.com/carapace-sh/carapace-bin/internal/actions/net/ssh"
1110
"github.com/carapace-sh/carapace/pkg/execlog"
1211
"github.com/carapace-sh/carapace/pkg/style"
1312
)
@@ -39,9 +38,8 @@ func ActionHosts() carapace.Action {
3938
batch = append(batch, carapace.ActionMessage(err.Error()))
4039
}
4140
}
42-
batch = append(batch, ssh.ActionHosts().Style(style.Yellow).Suppress(`open .*/.ssh/config: no such file or directory`))
4341
return batch.ToA()
44-
}).Tag("hosts")
42+
}).Tag("known hosts")
4543
}
4644

4745
type IncludedDevices struct {
@@ -179,7 +177,7 @@ func ActionBssids() carapace.Action {
179177

180178
vals := make([]string, 0)
181179
for _, line := range lines[:len(lines)-1] {
182-
mac := strings.Replace(line[:22], `\:`, `:`, -1)
180+
mac := strings.ReplaceAll(line[:22], `\:`, `:`)
183181
splitted := strings.Split(line[23:], ":")
184182
if name := splitted[0]; name != "" {
185183
vals = append(vals, mac, splitted[0], styleForBars(splitted[1]))
@@ -201,7 +199,7 @@ func ActionSsids() carapace.Action {
201199

202200
vals := make([]string, 0)
203201
for _, line := range lines[:len(lines)-1] {
204-
mac := strings.Replace(line[:22], `\:`, `:`, -1)
202+
mac := strings.ReplaceAll(line[:22], `\:`, `:`)
205203
splitted := strings.Split(line[23:], ":")
206204
if name := splitted[0]; name != "" {
207205
vals = append(vals, splitted[0], mac, styleForBars(splitted[1]))

pkg/actions/net/ssh/host.go

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,31 @@
11
package ssh
22

33
import (
4-
"bufio"
5-
"os"
64
"strings"
75

86
"github.com/carapace-sh/carapace"
9-
"github.com/carapace-sh/carapace-bin/internal/actions/net/ssh"
7+
"github.com/kevinburke/ssh_config"
108
)
119

1210
// ActionHosts completes ssh hosts
13-
func ActionHosts() carapace.Action {
11+
func ActionHosts(config string) carapace.Action {
1412
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
15-
path, err := c.Abs("~/.ssh/config")
16-
if err != nil {
17-
return carapace.ActionValues()
13+
settings := ssh_config.DefaultUserSettings
14+
if config != "" {
15+
// TODO this skips the system config
16+
settings.ConfigFinder(func() string {
17+
return config
18+
})
1819
}
1920

20-
file, err := os.Open(path)
21-
if err != nil {
22-
return carapace.ActionMessage(err.Error())
23-
}
24-
defer file.Close()
25-
2621
vals := make([]string, 0)
27-
scanner := bufio.NewScanner(file)
28-
for scanner.Scan() {
29-
if line := scanner.Text(); strings.HasPrefix(line, "Host ") {
30-
for _, field := range strings.Fields(strings.TrimPrefix(line, "Host ")) {
31-
if !strings.ContainsAny(field, `\*{}[]+`) {
32-
vals = append(vals, field)
33-
}
22+
for _, host := range settings.GetHosts() {
23+
for _, pattern := range host.Patterns {
24+
if s := strings.ReplaceAll(pattern.String(), `\`, ""); !strings.ContainsAny(s, `+*?()|[]{}^$!`) {
25+
vals = append(vals, s)
3426
}
3527
}
3628
}
3729
return carapace.ActionValues(vals...)
3830
}).Tag("ssh hosts")
3931
}
40-
41-
func init() {
42-
ssh.ActionHosts = ActionHosts
43-
}

0 commit comments

Comments
 (0)