mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-04 10:57:50 +08:00
Move functionality of edit/search.go to util.
This commit is contained in:
parent
d76bb34592
commit
d2d119af7f
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/elves/elvish/eval"
|
||||
"github.com/elves/elvish/parse"
|
||||
"github.com/elves/elvish/util"
|
||||
)
|
||||
|
||||
// A completer takes the current node
|
||||
|
@ -86,7 +87,7 @@ func complFormHead(cn *parse.Compound, head string, ed *Editor) []*candidate {
|
|||
}
|
||||
|
||||
func complFormHeadInner(head string, ed *Editor) []*candidate {
|
||||
if eval.DontSearch(head) {
|
||||
if util.DontSearch(head) {
|
||||
return complArgInner(head, ed, true)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package edit
|
|||
import (
|
||||
"github.com/elves/elvish/eval"
|
||||
"github.com/elves/elvish/parse"
|
||||
"github.com/elves/elvish/util"
|
||||
)
|
||||
|
||||
// stylist takes a Node and Editor, and returns a style string. The Node is
|
||||
|
@ -29,9 +30,9 @@ func colorFormHead(n parse.Node, ed *Editor) string {
|
|||
func goodFormHead(head string, ed *Editor) bool {
|
||||
if isBuiltinSpecial[head] {
|
||||
return true
|
||||
} else if eval.DontSearch(head) {
|
||||
} else if util.DontSearch(head) {
|
||||
// XXX don't stat twice
|
||||
return eval.IsExecutable(head) || isDir(head)
|
||||
return util.IsExecutable(head) || isDir(head)
|
||||
} else {
|
||||
return ed.evaler.Global()[eval.FnPrefix+head] != nil ||
|
||||
ed.isExternal[head]
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/elves/elvish/util"
|
||||
)
|
||||
|
||||
// FdNil is a special impossible fd value used for "close fd" in
|
||||
|
@ -28,7 +30,7 @@ func (e ExternalCmd) Repr(int) string {
|
|||
|
||||
// Call calls an external command.
|
||||
func (e ExternalCmd) Call(ec *EvalCtx, argVals []Value) {
|
||||
if DontSearch(e.Name) {
|
||||
if util.DontSearch(e.Name) {
|
||||
stat, err := os.Stat(e.Name)
|
||||
if err == nil && stat.IsDir() {
|
||||
// implicit cd
|
||||
|
|
|
@ -2,60 +2,23 @@ package eval
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/elves/elvish/parse"
|
||||
"github.com/elves/elvish/util"
|
||||
)
|
||||
|
||||
// Search tries to resolve an external command and return the full (possibly
|
||||
// relative) path.
|
||||
func (ev *Evaler) Search(exe string) (string, error) {
|
||||
if DontSearch(exe) {
|
||||
if IsExecutable(exe) {
|
||||
return exe, nil
|
||||
}
|
||||
return "", fmt.Errorf("external command %s not executable", parse.Quote(exe))
|
||||
path, err := util.Search(ev.searchPaths(), exe)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("search %s: %s", parse.Quote(exe), err.Error())
|
||||
}
|
||||
for _, p := range ev.searchPaths() {
|
||||
full := p + "/" + exe
|
||||
if IsExecutable(full) {
|
||||
return full, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("external command %s not found", parse.Quote(exe))
|
||||
return path, nil
|
||||
}
|
||||
|
||||
// AllExecutables writes the names of all executable files in the search path
|
||||
// to a channel.
|
||||
func (ev *Evaler) AllExecutables(names chan<- string) {
|
||||
for _, dir := range ev.searchPaths() {
|
||||
// XXX Ignore error
|
||||
infos, _ := ioutil.ReadDir(dir)
|
||||
for _, info := range infos {
|
||||
if !info.IsDir() && (info.Mode()&0111 != 0) {
|
||||
names <- info.Name()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DontSearch determines whether the path to an external command should be
|
||||
// taken literally and not searched.
|
||||
func DontSearch(exe string) bool {
|
||||
return exe == ".." ||
|
||||
strings.HasPrefix(exe, "/") ||
|
||||
strings.HasPrefix(exe, "./") ||
|
||||
strings.HasPrefix(exe, "../")
|
||||
}
|
||||
|
||||
// IsExecutable determines whether path refers to an executable file.
|
||||
func IsExecutable(path string) bool {
|
||||
fi, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
fm := fi.Mode()
|
||||
return !fm.IsDir() && (fm&0111 != 0)
|
||||
util.AllExecutables(ev.searchPaths(), names)
|
||||
}
|
||||
|
|
64
util/search.go
Normal file
64
util/search.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotExecutable = errors.New("not executable")
|
||||
ErrNotFound = errors.New("not found")
|
||||
)
|
||||
|
||||
// Search tries to resolve an external command and return the full (possibly
|
||||
// relative) path.
|
||||
func Search(paths []string, exe string) (string, error) {
|
||||
if DontSearch(exe) {
|
||||
if IsExecutable(exe) {
|
||||
return exe, nil
|
||||
}
|
||||
return "", ErrNotExecutable
|
||||
}
|
||||
for _, p := range paths {
|
||||
full := p + "/" + exe
|
||||
if IsExecutable(full) {
|
||||
return full, nil
|
||||
}
|
||||
}
|
||||
return "", ErrNotFound
|
||||
}
|
||||
|
||||
// AllExecutables writes the names of all executable files in the search path
|
||||
// to a channel.
|
||||
func AllExecutables(paths []string, names chan<- string) {
|
||||
for _, dir := range paths {
|
||||
// XXX Ignore error
|
||||
infos, _ := ioutil.ReadDir(dir)
|
||||
for _, info := range infos {
|
||||
if !info.IsDir() && (info.Mode()&0111 != 0) {
|
||||
names <- info.Name()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DontSearch determines whether the path to an external command should be
|
||||
// taken literally and not searched.
|
||||
func DontSearch(exe string) bool {
|
||||
return exe == ".." ||
|
||||
strings.HasPrefix(exe, "/") ||
|
||||
strings.HasPrefix(exe, "./") ||
|
||||
strings.HasPrefix(exe, "../")
|
||||
}
|
||||
|
||||
// IsExecutable determines whether path refers to an executable file.
|
||||
func IsExecutable(path string) bool {
|
||||
fi, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
fm := fi.Mode()
|
||||
return !fm.IsDir() && (fm&0111 != 0)
|
||||
}
|
Loading…
Reference in New Issue
Block a user