diff --git a/complete.go b/complete.go index bad22f1..d23cee1 100644 --- a/complete.go +++ b/complete.go @@ -33,7 +33,7 @@ func binaryComplete(query, ctx string, fields []string) ([]string, string) { if len(fileCompletions) != 0 { for _, f := range fileCompletions { name := strings.Replace(query + f, "~", curuser.HomeDir, 1) - if info, err := os.Stat(name); err == nil && info.Mode().Perm() & 0100 == 0 { + if err := findExecutable(name, false, true); err != nil { continue } completions = append(completions, f) @@ -51,7 +51,8 @@ func binaryComplete(query, ctx string, fields []string) ([]string, string) { // get basename from matches for _, match := range matches { // check if we have execute permissions for our match - if info, err := os.Stat(match); err == nil && info.Mode().Perm() & 0100 == 0 { + err := findExecutable(match, true, false) + if err != nil { continue } // get basename from match diff --git a/exec.go b/exec.go index cb24b08..efc92ab 100644 --- a/exec.go +++ b/exec.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "path/filepath" + "runtime" "strings" "time" @@ -161,15 +162,20 @@ func execCommand(cmd, old string) error { } func lookpath(file string) error { // custom lookpath function so we know if a command is found *and* is executable - skip := []string{"./", "/", "../", "~/"} + var skip []string + if runtime.GOOS == "windows" { + skip = []string{"./", "../", "~/", "C:"} + } else { + skip = []string{"./", "/", "../", "~/"} + } for _, s := range skip { if strings.HasPrefix(file, s) { - return findExecutable(file) + return findExecutable(file, false, false) } } for _, dir := range filepath.SplitList(os.Getenv("PATH")) { path := filepath.Join(dir, file) - err := findExecutable(path) + err := findExecutable(path, true, false) if err == errNotExec { return err } else if err == nil { diff --git a/execfile_unix.go b/execfile_unix.go index 49a337e..3160b85 100644 --- a/execfile_unix.go +++ b/execfile_unix.go @@ -6,13 +6,19 @@ import ( "os" ) -func findExecutable(path string) error { +func findExecutable(path string, inPath, dirs bool) error { f, err := os.Stat(path) if err != nil { return err } - if m := f.Mode(); !m.IsDir() && m & 0111 != 0 { - return nil + if dirs { + if m := f.Mode(); m & 0111 != 0 { + return nil + } + } else { + if m := f.Mode(); !m.IsDir() && m & 0111 != 0 { + return nil + } } return errNotExec } diff --git a/execfile_windows.go b/execfile_windows.go index a11ea86..502a595 100644 --- a/execfile_windows.go +++ b/execfile_windows.go @@ -7,20 +7,30 @@ import ( "os" ) -func findExecutable(path string) error { +func findExecutable(path string, inPath, dirs bool) error { nameExt := filepath.Ext(path) - if nameExt == "" { - for _, ext := range filepath.SplitList(os.Getenv("PATHEXT")) { - _, err := os.Stat(path + ext) + pathExts := filepath.SplitList(os.Getenv("PATHEXT")) + if inPath { + if nameExt == "" { + for _, ext := range pathExts { + _, err := os.Stat(path + ext) + if err == nil { + return nil + } + } + } else { + _, err := os.Stat(path) if err == nil { - return nil + if contains(pathExts, nameExt) { return nil } + return errNotExec } } - } - - _, err := os.Stat(path) - if err == nil { - return errNotExec + } else { + _, err := os.Stat(path) + if err == nil { + if contains(pathExts, nameExt) { return nil } + return errNotExec + } } return os.ErrNotExist diff --git a/main.go b/main.go index 6bd0532..c506b57 100644 --- a/main.go +++ b/main.go @@ -286,3 +286,12 @@ func removeDupes(slice []string) []string { return newSlice } + +func contains(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +}