mirror of https://github.com/Hilbis/Hilbish
refactor: make initial changes for snail lib (shell interp)
parent
4743222044
commit
0b0821f410
4
api.go
4
api.go
|
@ -508,7 +508,7 @@ func hlexec(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
}
|
}
|
||||||
cmdArgs, _ := splitInput(cmd)
|
cmdArgs, _ := splitInput(cmd)
|
||||||
if runtime.GOOS != "windows" {
|
if runtime.GOOS != "windows" {
|
||||||
cmdPath, err := exec.LookPath(cmdArgs[0])
|
cmdPath, err := util.LookPath(cmdArgs[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
// if we get here, cmdPath will be nothing
|
// if we get here, cmdPath will be nothing
|
||||||
|
@ -706,7 +706,7 @@ func hlwhich(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.PushingNext1(t.Runtime, rt.StringValue(cmd)), nil
|
return c.PushingNext1(t.Runtime, rt.StringValue(cmd)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
path, err := exec.LookPath(cmd)
|
path, err := util.LookPath(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
45
exec.go
45
exec.go
|
@ -411,7 +411,7 @@ func execHandle(bg bool) interp.ExecHandlerFunc {
|
||||||
return interp.NewExitStatus(exitcode)
|
return interp.NewExitStatus(exitcode)
|
||||||
}
|
}
|
||||||
|
|
||||||
path, err := lookpath(args[0])
|
path, err := util.LookPath(args[0])
|
||||||
if err == errNotExec {
|
if err == errNotExec {
|
||||||
return execError{
|
return execError{
|
||||||
typ: "not-executable",
|
typ: "not-executable",
|
||||||
|
@ -524,41 +524,14 @@ func handleExecErr(err error) (exit uint8) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func lookpath(file string) (string, error) { // custom lookpath function so we know if a command is found *and* is executable
|
|
||||||
var skip []string
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
skip = []string{"./", "../", "~/", "C:"}
|
|
||||||
} else {
|
|
||||||
skip = []string{"./", "/", "../", "~/"}
|
|
||||||
}
|
|
||||||
for _, s := range skip {
|
|
||||||
if strings.HasPrefix(file, s) {
|
|
||||||
return file, findExecutable(file, false, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, dir := range filepath.SplitList(os.Getenv("PATH")) {
|
|
||||||
path := filepath.Join(dir, file)
|
|
||||||
err := findExecutable(path, true, false)
|
|
||||||
if err == errNotExec {
|
|
||||||
return "", err
|
|
||||||
} else if err == nil {
|
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", os.ErrNotExist
|
|
||||||
}
|
|
||||||
|
|
||||||
func splitInput(input string) ([]string, string) {
|
func splitInput(input string) ([]string, string) {
|
||||||
// end my suffering
|
// end my suffering
|
||||||
// TODO: refactor this garbage
|
// TODO: refactor this garbage
|
||||||
quoted := false
|
quoted := false
|
||||||
startlastcmd := false
|
|
||||||
lastcmddone := false
|
|
||||||
cmdArgs := []string{}
|
cmdArgs := []string{}
|
||||||
sb := &strings.Builder{}
|
sb := &strings.Builder{}
|
||||||
cmdstr := &strings.Builder{}
|
cmdstr := &strings.Builder{}
|
||||||
lastcmd := "" //readline.GetHistory(readline.HistorySize() - 1)
|
|
||||||
|
|
||||||
for _, r := range input {
|
for _, r := range input {
|
||||||
if r == '"' {
|
if r == '"' {
|
||||||
|
@ -574,22 +547,6 @@ func splitInput(input string) ([]string, string) {
|
||||||
// if not quoted and there's a space then add to cmdargs
|
// if not quoted and there's a space then add to cmdargs
|
||||||
cmdArgs = append(cmdArgs, sb.String())
|
cmdArgs = append(cmdArgs, sb.String())
|
||||||
sb.Reset()
|
sb.Reset()
|
||||||
} else if !quoted && r == '^' && startlastcmd && !lastcmddone {
|
|
||||||
// if ^ is found, isnt in quotes and is
|
|
||||||
// the second occurence of the character and is
|
|
||||||
// the first time "^^" has been used
|
|
||||||
cmdstr.WriteString(lastcmd)
|
|
||||||
sb.WriteString(lastcmd)
|
|
||||||
|
|
||||||
startlastcmd = !startlastcmd
|
|
||||||
lastcmddone = !lastcmddone
|
|
||||||
|
|
||||||
continue
|
|
||||||
} else if !quoted && r == '^' && !lastcmddone {
|
|
||||||
// if ^ is found, isnt in quotes and is the
|
|
||||||
// first time of starting "^^"
|
|
||||||
startlastcmd = !startlastcmd
|
|
||||||
continue
|
|
||||||
} else {
|
} else {
|
||||||
sb.WriteRune(r)
|
sb.WriteRune(r)
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,12 +110,10 @@ func (f *fs) fcd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
}
|
}
|
||||||
path = util.ExpandHome(strings.TrimSpace(path))
|
path = util.ExpandHome(strings.TrimSpace(path))
|
||||||
|
|
||||||
abspath, _ := filepath.Abs(path)
|
|
||||||
err = os.Chdir(path)
|
err = os.Chdir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
interp.Dir(abspath)(f.runner)
|
|
||||||
|
|
||||||
return c.Next(), err
|
return c.Next(), err
|
||||||
}
|
}
|
||||||
|
|
4
job.go
4
job.go
|
@ -56,8 +56,8 @@ func (j *job) start() error {
|
||||||
}
|
}
|
||||||
j.setHandle(&cmd)
|
j.setHandle(&cmd)
|
||||||
}
|
}
|
||||||
// bgProcAttr is defined in execfile_<os>.go, it holds a procattr struct
|
// bgProcAttr is defined in job_<os>.go, it holds a procattr struct
|
||||||
// in a simple explanation, it makes signals from hilbish (sigint)
|
// in a simple explanation, it makes signals from hilbish (like sigint)
|
||||||
// not go to it (child process)
|
// not go to it (child process)
|
||||||
j.handle.SysProcAttr = bgProcAttr
|
j.handle.SysProcAttr = bgProcAttr
|
||||||
// reset output buffers
|
// reset output buffers
|
||||||
|
|
|
@ -10,6 +10,10 @@ import (
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var bgProcAttr *syscall.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Setpgid: true,
|
||||||
|
}
|
||||||
|
|
||||||
func (j *job) foreground() error {
|
func (j *job) foreground() error {
|
||||||
if jobs.foreground {
|
if jobs.foreground {
|
||||||
return errors.New("(another) job already foregrounded")
|
return errors.New("(another) job already foregrounded")
|
||||||
|
|
|
@ -4,8 +4,13 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var bgProcAttr *syscall.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP,
|
||||||
|
}
|
||||||
|
|
||||||
func (j *job) foreground() error {
|
func (j *job) foreground() error {
|
||||||
return errors.New("not supported on windows")
|
return errors.New("not supported on windows")
|
||||||
}
|
}
|
||||||
|
|
2
main.go
2
main.go
|
@ -38,11 +38,9 @@ var (
|
||||||
cmds *commander.Commander
|
cmds *commander.Commander
|
||||||
defaultConfPath string
|
defaultConfPath string
|
||||||
defaultHistPath string
|
defaultHistPath string
|
||||||
runner *interp.Runner
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runner, _ = interp.New()
|
|
||||||
curuser, _ = user.Current()
|
curuser, _ = user.Current()
|
||||||
homedir := curuser.HomeDir
|
homedir := curuser.HomeDir
|
||||||
confDir, _ = os.UserConfigDir()
|
confDir, _ = os.UserConfigDir()
|
||||||
|
|
|
@ -3,8 +3,9 @@ local commander = require 'commander'
|
||||||
local fs = require 'fs'
|
local fs = require 'fs'
|
||||||
local dirs = require 'nature.dirs'
|
local dirs = require 'nature.dirs'
|
||||||
|
|
||||||
dirs.old = hilbish.cwd()
|
|
||||||
commander.register('cd', function (args, sinks)
|
commander.register('cd', function (args, sinks)
|
||||||
|
local oldPath = hilbish.cwd()
|
||||||
|
|
||||||
if #args > 1 then
|
if #args > 1 then
|
||||||
sinks.out:writeln("cd: too many arguments")
|
sinks.out:writeln("cd: too many arguments")
|
||||||
return 1
|
return 1
|
||||||
|
@ -16,13 +17,10 @@ commander.register('cd', function (args, sinks)
|
||||||
sinks.out:writeln(path)
|
sinks.out:writeln(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
dirs.setOld(hilbish.cwd())
|
|
||||||
dirs.push(path)
|
|
||||||
|
|
||||||
local ok, err = pcall(function() fs.cd(path) end)
|
local ok, err = pcall(function() fs.cd(path) end)
|
||||||
if not ok then
|
if not ok then
|
||||||
sinks.out:writeln(err)
|
sinks.out:writeln(err)
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
bait.throw('cd', path)
|
bait.throw('hilbish.cd', fs.abs(path), oldPath)
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
-- @module dirs
|
-- @module dirs
|
||||||
|
local bait = require 'bait'
|
||||||
local fs = require 'fs'
|
local fs = require 'fs'
|
||||||
|
|
||||||
local dirs = {}
|
local dirs = {}
|
||||||
|
@ -73,4 +74,9 @@ function dirs.setOld(d)
|
||||||
dirs.old = d
|
dirs.old = d
|
||||||
end
|
end
|
||||||
|
|
||||||
|
bait.catch('hilbish.cd', function(path, oldPath)
|
||||||
|
dirs.setOld(oldPath)
|
||||||
|
dirs.push(path)
|
||||||
|
end)
|
||||||
|
|
||||||
return dirs
|
return dirs
|
||||||
|
|
25
util/util.go
25
util/util.go
|
@ -141,3 +141,28 @@ func AbbrevHome(path string) string {
|
||||||
|
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LookPath(file string) (string, error) { // custom lookpath function so we know if a command is found *and* is executable
|
||||||
|
var skip []string
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
skip = []string{"./", "../", "~/", "C:"}
|
||||||
|
} else {
|
||||||
|
skip = []string{"./", "/", "../", "~/"}
|
||||||
|
}
|
||||||
|
for _, s := range skip {
|
||||||
|
if strings.HasPrefix(file, s) {
|
||||||
|
return file, findExecutable(file, false, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, dir := range filepath.SplitList(os.Getenv("PATH")) {
|
||||||
|
path := filepath.Join(dir, file)
|
||||||
|
err := findExecutable(path, true, false)
|
||||||
|
if err == errNotExec {
|
||||||
|
return "", err
|
||||||
|
} else if err == nil {
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", os.ErrNotExist
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
//go:build unix
|
//go:build unix
|
||||||
|
|
||||||
package main
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var bgProcAttr *syscall.SysProcAttr = &syscall.SysProcAttr{
|
func FindExecutable(path string, inPath, dirs bool) error {
|
||||||
Setpgid: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
@ -1,18 +1,13 @@
|
||||||
//go:build windows
|
//go:build windows
|
||||||
|
|
||||||
package main
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var bgProcAttr *syscall.SysProcAttr = &syscall.SysProcAttr{
|
func FindExecutable(path string, inPath, dirs bool) error {
|
||||||
CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP,
|
|
||||||
}
|
|
||||||
|
|
||||||
func findExecutable(path string, inPath, dirs bool) error {
|
|
||||||
nameExt := filepath.Ext(path)
|
nameExt := filepath.Ext(path)
|
||||||
pathExts := filepath.SplitList(os.Getenv("PATHEXT"))
|
pathExts := filepath.SplitList(os.Getenv("PATHEXT"))
|
||||||
if inPath {
|
if inPath {
|
Loading…
Reference in New Issue