From 5028bf60c6eff015b3667753305c3db4f572d3cf Mon Sep 17 00:00:00 2001 From: Lonny Wong Date: Sat, 25 Nov 2023 22:39:13 +0800 Subject: [PATCH] support group labels --- go.mod | 4 +-- go.sum | 8 +++--- tssh/config.go | 69 +++++++++++++++++++++++++++++++++++++++++--------- tssh/prompt.go | 21 ++++++++++----- 4 files changed, 77 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index c2b8f7f..ad0ca33 100644 --- a/go.mod +++ b/go.mod @@ -14,8 +14,8 @@ require ( github.com/stretchr/testify v1.8.4 github.com/trzsz/go-arg v1.5.2 github.com/trzsz/iterm2 v0.1.1 - github.com/trzsz/promptui v0.10.3 - github.com/trzsz/ssh_config v1.3.3 + github.com/trzsz/promptui v0.10.4 + github.com/trzsz/ssh_config v1.3.4 github.com/trzsz/trzsz-go v1.1.7-0.20231111144918-b45bed013817 golang.org/x/crypto v0.15.0 golang.org/x/sys v0.14.0 diff --git a/go.sum b/go.sum index a871590..9934a80 100644 --- a/go.sum +++ b/go.sum @@ -57,10 +57,10 @@ github.com/trzsz/go-arg v1.5.2 h1:zGxCuTKvtC3jBf7HbvNk0HooUjv8uKAy2mY+bHVhRas= github.com/trzsz/go-arg v1.5.2/go.mod h1:IC6Z/FiVH7uYvcbp1/gJhDYCFPS/GkL0APYakVvgY4I= github.com/trzsz/iterm2 v0.1.1 h1:UZ+Su5xOuBNDXpRStfuMCsTWhajNnKEHChJ4tfd62Mc= github.com/trzsz/iterm2 v0.1.1/go.mod h1:PMI+3JcT7J9D0T6e3mOWv8ICYdrrNZwuge3Tm7zDLws= -github.com/trzsz/promptui v0.10.3 h1:uhcLQsLZqMxEtGiYoeM2lR/Hd4pSxoYsd2eFctH8MCs= -github.com/trzsz/promptui v0.10.3/go.mod h1:GMZtu6ZTzU73CBFkzGtmB4wnTROIAbv4GFA74fV8V8g= -github.com/trzsz/ssh_config v1.3.3 h1:FodC5NBpnBSI2CJqU62d0Ya3yTUHWDpbWKugKX0LXZs= -github.com/trzsz/ssh_config v1.3.3/go.mod h1:Dl1okTjVVfsrtTA8nqkJ1OnjiCrZY6DUEI2DGT2/YoQ= +github.com/trzsz/promptui v0.10.4 h1:EuoA4zGJ5sco3rmyssvkP42xb8ZxiYza1OeDIlhWOk8= +github.com/trzsz/promptui v0.10.4/go.mod h1:GMZtu6ZTzU73CBFkzGtmB4wnTROIAbv4GFA74fV8V8g= +github.com/trzsz/ssh_config v1.3.4 h1:7of+6rUmdWdqfgXnH9csgJe1kNkriS9xOiFGx4KCkEw= +github.com/trzsz/ssh_config v1.3.4/go.mod h1:Dl1okTjVVfsrtTA8nqkJ1OnjiCrZY6DUEI2DGT2/YoQ= github.com/trzsz/trzsz-go v1.1.7-0.20231111144918-b45bed013817 h1:AGD0x1Oo3xIV3Gv7Pv1mGRcVCf7jV69oaEGgDgPs7wM= github.com/trzsz/trzsz-go v1.1.7-0.20231111144918-b45bed013817/go.mod h1:sOLnYeA77qyF2Aqj+leycDWxFpylV46BA7g6F3gWcfQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= diff --git a/tssh/config.go b/tssh/config.go index 7e52d8f..39be1a5 100644 --- a/tssh/config.go +++ b/tssh/config.go @@ -61,6 +61,7 @@ type sshHost struct { ProxyCommand string ProxyJump string RemoteCommand string + GroupLabels string Selected bool } @@ -211,7 +212,7 @@ func (c *tsshConfig) doLoadConfig() { ssh_config.SetDefault("IdentityFile", "") if c.configPath == "" { - debug("no configuration files will be read") + debug("no ssh configuration file path") return } c.config = loadConfig(c.configPath, false) @@ -226,6 +227,20 @@ func (c *tsshConfig) doLoadConfig() { }) } +func (c *tsshConfig) doLoadExConfig() { + c.loadExConfig.Do(func() { + if c.exConfigPath == "" { + debug("no extended configuration file path") + return + } + if !isFileExist(c.exConfigPath) { + debug("extended config [%s] does not exist", c.exConfigPath) + return + } + c.exConfig = loadConfig(c.exConfigPath, false) + }) +} + func getConfig(alias, key string) string { userConfig.doLoadConfig() @@ -269,17 +284,7 @@ func getAllConfig(alias, key string) []string { } func getExConfig(alias, key string) string { - userConfig.loadExConfig.Do(func() { - if userConfig.exConfigPath == "" { - debug("no extended configuration will be read") - return - } - if !isFileExist(userConfig.exConfigPath) { - debug("extended config [%s] does not exist", userConfig.exConfigPath) - return - } - userConfig.exConfig = loadConfig(userConfig.exConfigPath, false) - }) + userConfig.doLoadExConfig() if userConfig.exConfig != nil { value, _ := userConfig.exConfig.Get(alias, key) @@ -289,10 +294,31 @@ func getExConfig(alias, key string) string { } } + if value := getConfig(alias, key); value != "" { + debug("get extended config [%s] for [%s] success", key, alias) + return value + } + debug("no extended config [%s] for [%s]", key, alias) return "" } +func getAllExConfig(alias, key string) []string { + userConfig.doLoadExConfig() + + var values []string + if userConfig.exConfig != nil { + if vals, _ := userConfig.exConfig.GetAll(alias, key); len(vals) > 0 { + values = append(values, vals...) + } + } + if vals := getAllConfig(alias, key); len(vals) > 0 { + values = append(values, vals...) + } + + return values +} + func getAllHosts() []*sshHost { userConfig.loadHosts.Do(func() { userConfig.doLoadConfig() @@ -346,12 +372,31 @@ func appendPromptHosts(hosts []*sshHost, cfgHosts ...*ssh_config.Host) []*sshHos ProxyCommand: getConfig(alias, "ProxyCommand"), ProxyJump: getConfig(alias, "ProxyJump"), RemoteCommand: getConfig(alias, "RemoteCommand"), + GroupLabels: getGroupLabels(alias), }) } } return hosts } +func getGroupLabels(alias string) string { + var groupLabels []string + addGroupLabel := func(groupLabel string) { + for _, label := range groupLabels { + if label == groupLabel { + return + } + } + groupLabels = append(groupLabels, groupLabel) + } + for _, groupLabel := range getAllExConfig(alias, "GroupLabels") { + for _, label := range strings.Fields(groupLabel) { + addGroupLabel(label) + } + } + return strings.Join(groupLabels, " ") +} + func getOptionConfig(args *sshArgs, option string) string { if value := args.Option.get(option); value != "" { return value diff --git a/tssh/prompt.go b/tssh/prompt.go index d5c6ded..e65f211 100644 --- a/tssh/prompt.go +++ b/tssh/prompt.go @@ -538,10 +538,13 @@ func (p *sshPrompt) wrapStdin() { } func matchHost(h *sshHost, keywords []string) bool { - alias := strings.ReplaceAll(strings.ToLower(h.Alias), " ", "") - host := strings.ReplaceAll(strings.ToLower(h.Host), " ", "") - for _, keywork := range keywords { - if !strings.Contains(alias, keywork) && !strings.Contains(host, keywork) { + host := strings.ToLower(h.Host) + alias := strings.ToLower(h.Alias) + labels := strings.ToLower(h.GroupLabels) + for _, keyword := range keywords { + if !strings.Contains(host, keyword) && + !strings.Contains(alias, keyword) && + !strings.Contains(labels, keyword) { return false } } @@ -557,9 +560,10 @@ func chooseAlias(keywords string) (string, bool, error) { templates := &promptui.SelectTemplates{ Help: `{{ "Use ← ↓ ↑ → h j k l to navigate, / toggles search, ? toggles help" | faint }}`, - Active: fmt.Sprintf(`%s {{ if .Selected }}{{ "✔ " | green }}{{ end }}{{ .Alias | cyan }} ({{ .Host | red }})`, - promptCursorIcon), - Inactive: ` {{ if .Selected }}{{ "✔ " | green }}{{ end }}{{ .Alias | cyan }} ({{ .Host | red }})`, + Active: fmt.Sprintf(`%s {{ if .Selected }}{{ "✔ " | green }}{{ end }}{{ .Alias | cyan }} ({{ .Host | red }})`+ + ` {{ .GroupLabels }}`, promptCursorIcon), + Inactive: ` {{ if .Selected }}{{ "✔ " | green }}{{ end }}{{ .Alias | cyan }} ({{ .Host | red }})` + + ` {{ .GroupLabels }}`, Details: ` --------- SSH Alias ---------- {{ "Alias:" | faint }} {{ .Alias }} @@ -570,6 +574,9 @@ func chooseAlias(keywords string) (string, bool, error) { {{- if .User }} {{ "User:" | faint }} {{ .User }} {{- end }} +{{- if .GroupLabels }} +{{ "GroupLabels:" | faint }} {{ .GroupLabels }} +{{- end }} {{- if .IdentityFile }} {{ "IdentityFile:" | faint }} {{ .IdentityFile }} {{- end }}