fix: completions of executables and running absolute paths on windows

pull/128/head
TorchedSammy 2022-03-17 20:22:30 -04:00
parent 925ded6cea
commit f73c6d4aa8
Signed by: sammyette
GPG Key ID: 904FC49417B44DCD
5 changed files with 50 additions and 18 deletions

View File

@ -33,7 +33,7 @@ func binaryComplete(query, ctx string, fields []string) ([]string, string) {
if len(fileCompletions) != 0 { if len(fileCompletions) != 0 {
for _, f := range fileCompletions { for _, f := range fileCompletions {
name := strings.Replace(query + f, "~", curuser.HomeDir, 1) 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 continue
} }
completions = append(completions, f) completions = append(completions, f)
@ -51,7 +51,8 @@ func binaryComplete(query, ctx string, fields []string) ([]string, string) {
// get basename from matches // get basename from matches
for _, match := range matches { for _, match := range matches {
// check if we have execute permissions for our match // 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 continue
} }
// get basename from match // get basename from match

12
exec.go
View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
"time" "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 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 { for _, s := range skip {
if strings.HasPrefix(file, s) { if strings.HasPrefix(file, s) {
return findExecutable(file) return findExecutable(file, false, false)
} }
} }
for _, dir := range filepath.SplitList(os.Getenv("PATH")) { for _, dir := range filepath.SplitList(os.Getenv("PATH")) {
path := filepath.Join(dir, file) path := filepath.Join(dir, file)
err := findExecutable(path) err := findExecutable(path, true, false)
if err == errNotExec { if err == errNotExec {
return err return err
} else if err == nil { } else if err == nil {

View File

@ -6,13 +6,19 @@ import (
"os" "os"
) )
func findExecutable(path string) error { func findExecutable(path string, inPath, dirs bool) error {
f, err := os.Stat(path) f, err := os.Stat(path)
if err != nil { if err != nil {
return err return err
} }
if m := f.Mode(); !m.IsDir() && m & 0111 != 0 { if dirs {
return nil if m := f.Mode(); m & 0111 != 0 {
return nil
}
} else {
if m := f.Mode(); !m.IsDir() && m & 0111 != 0 {
return nil
}
} }
return errNotExec return errNotExec
} }

View File

@ -7,20 +7,30 @@ import (
"os" "os"
) )
func findExecutable(path string) error { func findExecutable(path string, inPath, dirs bool) error {
nameExt := filepath.Ext(path) nameExt := filepath.Ext(path)
if nameExt == "" { pathExts := filepath.SplitList(os.Getenv("PATHEXT"))
for _, ext := range filepath.SplitList(os.Getenv("PATHEXT")) { if inPath {
_, err := os.Stat(path + ext) if nameExt == "" {
for _, ext := range pathExts {
_, err := os.Stat(path + ext)
if err == nil {
return nil
}
}
} else {
_, err := os.Stat(path)
if err == nil { if err == nil {
return nil if contains(pathExts, nameExt) { return nil }
return errNotExec
} }
} }
} } else {
_, err := os.Stat(path)
_, err := os.Stat(path) if err == nil {
if err == nil { if contains(pathExts, nameExt) { return nil }
return errNotExec return errNotExec
}
} }
return os.ErrNotExist return os.ErrNotExist

View File

@ -286,3 +286,12 @@ func removeDupes(slice []string) []string {
return newSlice return newSlice
} }
func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}