Code to complete executables in PATH
This commit is contained in:
parent
10cf7f06c6
commit
8c2e435793
@ -8,6 +8,8 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
@ -54,3 +56,21 @@ func complete_files(prefix string, callback CompleteFilesCallback) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func complete_executables_in_path(prefix string, paths ...string) []string {
|
||||
ans := make([]string, 0, 1024)
|
||||
if len(paths) == 0 {
|
||||
paths = filepath.SplitList(os.Getenv("PATH"))
|
||||
}
|
||||
for _, dir := range paths {
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err == nil {
|
||||
for _, e := range entries {
|
||||
if strings.HasPrefix(e.Name(), prefix) && !e.IsDir() && unix.Access(filepath.Join(dir, e.Name()), unix.X_OK) == nil {
|
||||
ans = append(ans, e.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ans
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -19,11 +20,16 @@ func TestCompleteFiles(t *testing.T) {
|
||||
defer os.Chdir(cwd)
|
||||
}
|
||||
os.Chdir(tdir)
|
||||
os.Create(filepath.Join(tdir, "one.txt"))
|
||||
os.Create(filepath.Join(tdir, "two.txt"))
|
||||
|
||||
create := func(parts ...string) {
|
||||
f, _ := os.Create(filepath.Join(tdir, filepath.Join(parts...)))
|
||||
f.Close()
|
||||
}
|
||||
create("one.txt")
|
||||
create("two.txt")
|
||||
os.Mkdir(filepath.Join(tdir, "odir"), 0700)
|
||||
os.Create(filepath.Join(tdir, "odir", "three.txt"))
|
||||
os.Create(filepath.Join(tdir, "odir", "four.txt"))
|
||||
create("odir", "three.txt")
|
||||
create("odir", "four.txt")
|
||||
|
||||
test_candidates := func(prefix string, expected ...string) {
|
||||
if expected == nil {
|
||||
@ -77,3 +83,36 @@ func TestCompleteFiles(t *testing.T) {
|
||||
test_candidates("x")
|
||||
|
||||
}
|
||||
|
||||
func TestCompleteExecutables(t *testing.T) {
|
||||
tdir := t.TempDir()
|
||||
create := func(base string, name string, mode os.FileMode) {
|
||||
f, _ := os.OpenFile(filepath.Join(tdir, base, name), os.O_CREATE, mode)
|
||||
f.Close()
|
||||
}
|
||||
os.Mkdir(filepath.Join(tdir, "one"), 0700)
|
||||
os.Mkdir(filepath.Join(tdir, "two"), 0700)
|
||||
|
||||
create("", "not-in-path", 0700)
|
||||
create("one", "one-exec", 0700)
|
||||
create("one", "one-not-exec", 0600)
|
||||
create("two", "two-exec", 0700)
|
||||
os.Symlink(filepath.Join(tdir, "two", "two-exec"), filepath.Join(tdir, "one", "s"))
|
||||
os.Symlink(filepath.Join(tdir, "one", "one-not-exec"), filepath.Join(tdir, "one", "n"))
|
||||
|
||||
t.Setenv("PATH", strings.Join([]string{filepath.Join(tdir, "one"), filepath.Join(tdir, "two")}, string(os.PathListSeparator)))
|
||||
test_candidates := func(prefix string, expected ...string) {
|
||||
if expected == nil {
|
||||
expected = make([]string, 0)
|
||||
}
|
||||
actual := complete_executables_in_path(prefix)
|
||||
sort.Strings(expected)
|
||||
sort.Strings(actual)
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Fatalf("Did not get expected completion candidates for prefix: %#v\nExpected: %#v\nActual: %#v", prefix, expected, actual)
|
||||
}
|
||||
}
|
||||
test_candidates("", "one-exec", "two-exec", "s")
|
||||
test_candidates("o", "one-exec")
|
||||
test_candidates("x")
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user