Skip to content

Commit

Permalink
ActionPathExecutables: improve performance
Browse files Browse the repository at this point in the history
  • Loading branch information
rsteube committed Sep 24, 2022
1 parent 271b550 commit e6d9898
Show file tree
Hide file tree
Showing 7 changed files with 595 additions and 57 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ cmd/carafmt/carafmt
cmd/caralint/caralint
cmd/carapace/carapace
cmd/carapace/cmd/completers.go
cmd/carapace/cmd/completers/name.go
cmd/carapace/cmd/completers/description.go
cmd/carapace/cmd/completers_release.go
cmd/carapace/cmd/macros.go
cmd/caraparse/caraparse
Expand Down
475 changes: 475 additions & 0 deletions cmd/carapace/cmd/completers/description.go

Large diffs are not rendered by default.

29 changes: 15 additions & 14 deletions cmd/carapace/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"strconv"
"strings"

"github.com/rsteube/carapace-bin/cmd/carapace/cmd/completers"
spec "github.com/rsteube/carapace-spec"
"github.com/rsteube/carapace/pkg/ps"
"github.com/rsteube/carapace/pkg/style"
Expand Down Expand Up @@ -75,7 +76,7 @@ var rootCmd = &cobra.Command{
Specs are loaded from [%v/carapace/specs].
`, suppressErr(os.UserCacheDir), suppressErr(os.UserConfigDir), suppressErr(os.UserConfigDir)),
Args: cobra.MinimumNArgs(1),
ValidArgs: completers,
ValidArgs: completers.Names,
Run: func(cmd *cobra.Command, args []string) {
// since flag parsing is disabled do this manually
switch args[0] {
Expand Down Expand Up @@ -119,25 +120,25 @@ var rootCmd = &cobra.Command{
}
switch shell {
case "bash":
fmt.Println(bash_lazy(completers))
fmt.Println(bash_lazy(completers.Names))
case "bash-ble":
fmt.Println(bash_ble_lazy(completers))
fmt.Println(bash_ble_lazy(completers.Names))
case "elvish":
fmt.Println(elvish_lazy(completers))
fmt.Println(elvish_lazy(completers.Names))
case "fish":
fmt.Println(fish_lazy(completers))
fmt.Println(fish_lazy(completers.Names))
case "nushell":
fmt.Println(nushell_lazy(completers))
fmt.Println(nushell_lazy(completers.Names))
case "oil":
fmt.Println(oil_lazy(completers))
fmt.Println(oil_lazy(completers.Names))
case "powershell":
fmt.Println(powershell_lazy(completers))
fmt.Println(powershell_lazy(completers.Names))
case "tcsh":
fmt.Println(tcsh_lazy(completers))
fmt.Println(tcsh_lazy(completers.Names))
case "xonsh":
fmt.Println(xonsh_lazy(completers))
fmt.Println(xonsh_lazy(completers.Names))
case "zsh":
fmt.Println(zsh_lazy(completers))
fmt.Println(zsh_lazy(completers.Names))
default:
fmt.Fprintln(os.Stderr, "could not determine shell")
}
Expand All @@ -159,14 +160,14 @@ func suppressErr(f func() (string, error)) string { s, _ := f(); return s }

func printCompleters() {
maxlen := 0
for _, name := range completers {
for _, name := range completers.Names {
if len := len(name); len > maxlen {
maxlen = len
}
}

for _, name := range completers {
fmt.Printf("%-"+strconv.Itoa(maxlen)+"v %v\n", name, descriptions[name])
for _, name := range completers.Names {
fmt.Printf("%-"+strconv.Itoa(maxlen)+"v %v\n", name, completers.Descriptions[name])
}
}

Expand Down
10 changes: 2 additions & 8 deletions cmd/generate/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,12 @@ func main() {
import (
%v)
var completers = []string{
%v}
var descriptions = map[string]string{
%v}
func executeCompleter(completer string) {
switch completer {
%v }
}
`,
fmt.Sprintln(strings.Join(imports, "\n")),
fmt.Sprintln(strings.Join(formattedNames, "\n")),
fmt.Sprintln(strings.Join(formattedDescriptions, "\n")),
fmt.Sprintln(strings.Join(cases, "\n")),
)

Expand All @@ -80,6 +72,8 @@ func executeCompleter(completer string) {
}

os.WriteFile(root+"/cmd/carapace/cmd/completers.go", []byte("//go:build !release\n\n"+content), 0644)
os.WriteFile(root+"/cmd/carapace/cmd/completers/name.go", []byte(fmt.Sprintf("package completers\n\nvar Names = []string{\n%v\n}\n", strings.Join(formattedNames, "\n"))), 0644)
os.WriteFile(root+"/cmd/carapace/cmd/completers/description.go", []byte(fmt.Sprintf("package completers\n\nvar Descriptions = map[string]string{\n%v\n}\n", strings.Join(formattedDescriptions, "\n"))), 0644)
os.WriteFile(root+"/cmd/carapace/cmd/completers_release.go", []byte("//go:build release\n\n"+strings.Replace(content, "/completers/", "/completers_release/", -1)), 0644)
os.RemoveAll(root + "/completers_release")
execabs.Command("cp", "-r", root+"/completers", root+"/completers_release").Run()
Expand Down
29 changes: 28 additions & 1 deletion pkg/actions/bridge/carapace.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package bridge

import "github.com/rsteube/carapace"
import (
"fmt"
"os"

"github.com/rsteube/carapace"
spec "github.com/rsteube/carapace-spec"
)

// ActionCarapace bridges rsteube/carapace completion
func ActionCarapace(cmd string) carapace.Action {
Expand All @@ -19,6 +25,15 @@ func ActionCarapace(cmd string) carapace.Action {

// ActionCarapaceBin bridges a completer provided by carapace-bin
func ActionCarapaceBin(completer string) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
if a, err := actionSpec(completer); err == nil {
return a
}
return actionCarapaceBin(completer)
})
}

func actionCarapaceBin(completer string) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
args := []string{completer, "export", ""}
args = append(args, c.Args...)
Expand All @@ -31,3 +46,15 @@ func ActionCarapaceBin(completer string) carapace.Action {
})
})
}

func actionSpec(completer string) (carapace.Action, error) {
configDir, err := os.UserConfigDir()
if err != nil {
return carapace.ActionValues(), err
}
path := fmt.Sprintf("%v/carapace/specs/%v.yaml", configDir, completer)
if _, err := os.Stat(path); os.IsNotExist(err) {
return carapace.ActionValues(), err
}
return spec.ActionSpec(path), nil
}
73 changes: 73 additions & 0 deletions pkg/actions/os/executable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package os

import (
"fmt"
"os"
"strings"

"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/cmd/carapace/cmd/completers"
"github.com/rsteube/carapace/pkg/style"
"gopkg.in/yaml.v3"
)

// ActionPathExecutables completes executable files from PATH
//
// nvim
// chmod
func ActionPathExecutables() carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
batch := carapace.Batch()
dirs := strings.Split(os.Getenv("PATH"), string(os.PathListSeparator))
for i := len(dirs) - 1; i >= 0; i-- {
batch = append(batch, actionDirectoryExecutables(dirs[i], c.CallbackValue))
}
return batch.ToA()
})
}

func actionDirectoryExecutables(dir string, prefix string) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
if files, err := os.ReadDir(dir); err == nil {
vals := make([]string, 0)
for _, f := range files {
if strings.HasPrefix(f.Name(), prefix) {
if info, err := f.Info(); err == nil && !f.IsDir() && isExecAny(info.Mode()) {
if description, err := specDescription(f.Name()); err != nil {
vals = append(vals, f.Name(), completers.Descriptions[f.Name()], style.ForPath(dir+"/"+f.Name()))
} else {
vals = append(vals, f.Name(), description, style.ForPath(dir+"/"+f.Name()))
}
}
}
}
return carapace.ActionStyledValuesDescribed(vals...)
}
return carapace.ActionValues()
})
}

func isExecAny(mode os.FileMode) bool {
return mode&0111 != 0
}

func specDescription(name string) (string, error) {
confDir, err := os.UserConfigDir()
if err != nil {
return "", err
}

content, err := os.ReadFile(fmt.Sprintf("%v/carapace/specs/%v.yaml", confDir, name))
if err != nil {
return "", err
}
var s struct {
Description string
}

err = yaml.Unmarshal(content, &s)
if err != nil {
return "", err
}
return s.Description, nil
}
34 changes: 0 additions & 34 deletions pkg/actions/os/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
package os

import (
"os"
"strings"

"github.com/rsteube/carapace"
"github.com/rsteube/carapace/pkg/style"
)

// ActionShells completes available terminal shells
Expand All @@ -22,38 +20,6 @@ func ActionShells() carapace.Action {
})
}

// ActionPathExecutables completes executable files from PATH
//
// nvim
// chmod
func ActionPathExecutables() carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
executables := make(map[string]string)

for _, folder := range strings.Split(os.Getenv("PATH"), string(os.PathListSeparator)) {
if files, err := os.ReadDir(folder); err == nil {
for _, f := range files {
if _, ok := executables[f.Name()]; !ok {
if info, err := f.Info(); err == nil && !f.IsDir() && isExecAny(info.Mode()) {
executables[f.Name()] = style.ForPath(folder + "/" + f.Name())
}
}
}
}
}

vals := make([]string, 0)
for executable, _style := range executables {
vals = append(vals, executable, _style)
}
return carapace.ActionStyledValues(vals...)
})
}

func isExecAny(mode os.FileMode) bool {
return mode&0111 != 0
}

// ActionCgroups completes cgroup names
//
// blkio
Expand Down

0 comments on commit e6d9898

Please sign in to comment.