You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ntool/nsys/sysenv.go

185 lines
3.8 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package nsys
import (
"git.noahlan.cn/noahlan/ntool/internal/common"
"git.noahlan.cn/noahlan/ntool/ncli"
"golang.org/x/term"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"
)
// IsMSys msys(MINGW64) env不一定支持颜色
func IsMSys() bool {
// "MSYSTEM=MINGW64"
return len(os.Getenv("MSYSTEM")) > 0
}
// IsConsole check out is in stderr/stdout/stdin
//
// Usage:
//
// sysutil.IsConsole(os.Stdout)
func IsConsole(out io.Writer) bool {
o, ok := out.(*os.File)
if !ok {
return false
}
fd := o.Fd()
// fix: cannot use 'o == os.Stdout' to compare
return fd == uintptr(syscall.Stdout) || fd == uintptr(syscall.Stdin) || fd == uintptr(syscall.Stderr)
}
// IsTerminal isatty check
//
// Usage:
//
// sysutil.IsTerminal(os.Stdout.Fd())
func IsTerminal(fd uintptr) bool {
// return isatty.IsTerminal(fd) // "github.com/mattn/go-isatty"
return term.IsTerminal(int(fd))
}
// StdIsTerminal os.Stdout is terminal
func StdIsTerminal() bool {
return IsTerminal(os.Stdout.Fd())
}
// Hostname is alias of os.Hostname, but ignore error
func Hostname() string {
name, _ := os.Hostname()
return name
}
// CurrentShell get current used shell env file.
//
// eg "/bin/zsh" "/bin/bash".
// if onlyName=true, will return "zsh", "bash"
func CurrentShell(onlyName bool) (path string) {
return ncli.CurrentShell(onlyName)
}
// HasShellEnv has shell env check.
//
// Usage:
//
// HasShellEnv("sh")
// HasShellEnv("bash")
func HasShellEnv(shell string) bool {
// can also use: "echo $0"
out, err := ShellExec("echo OK", shell)
if err != nil {
return false
}
return strings.TrimSpace(out) == "OK"
}
// IsShellSpecialVar reports whether the character identifies a special
// shell variable such as $*.
func IsShellSpecialVar(c uint8) bool {
switch c {
case '*', '#', '$', '@', '!', '?', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return true
}
return false
}
// FindExecutable in the system
//
// Usage:
//
// sysutil.FindExecutable("bash")
func FindExecutable(binName string) (string, error) {
return exec.LookPath(binName)
}
// Executable find in the system, alias of FindExecutable()
//
// Usage:
//
// sysutil.Executable("bash")
func Executable(binName string) (string, error) {
return exec.LookPath(binName)
}
// HasExecutable in the system
//
// Usage:
//
// HasExecutable("bash")
func HasExecutable(binName string) bool {
_, err := exec.LookPath(binName)
return err == nil
}
// GetEnv get ENV value by key name, can with default value
func GetEnv(name string, def ...string) string {
val := os.Getenv(name)
if val == "" && len(def) > 0 {
val = def[0]
}
return val
}
// Environ like os.Environ, but will returns key-value map[string]string data.
func Environ() map[string]string { return common.Environ() }
// EnvMapWith like os.Environ, but will return key-value map[string]string data.
func EnvMapWith(newEnv map[string]string) map[string]string {
envMp := common.Environ()
for name, value := range newEnv {
envMp[name] = value
}
return envMp
}
// EnvPaths get and split $PATH to []string
func EnvPaths() []string {
return filepath.SplitList(os.Getenv("PATH"))
}
// SearchPath search executable files in the system $PATH
//
// Usage:
//
// sysutil.SearchPath("go")
func SearchPath(keywords string, limit int) []string {
path := os.Getenv("PATH")
ptn := "*" + keywords + "*"
list := make([]string, 0)
checked := make(map[string]bool)
for _, dir := range filepath.SplitList(path) {
// Unix shell semantics: path element "" means "."
if dir == "" {
dir = "."
}
// mark dir is checked
if _, ok := checked[dir]; ok {
continue
}
checked[dir] = true
matches, err := filepath.Glob(filepath.Join(dir, ptn))
if err == nil && len(matches) > 0 {
list = append(list, matches...)
size := len(list)
// limit result size
if limit > 0 && size >= limit {
list = list[:limit]
break
}
}
}
return list
}