func (shell *Shell) SetDebug(d bool) {
	shell.debug = d
	shell.logf = NewLog(logNS, d)
}
SetDebug enable/disable debug in the shell
package sh
import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/signal"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"github.com/madlambda/nash/ast"
	"github.com/madlambda/nash/errors"
	"github.com/madlambda/nash/internal/sh/builtin"
	"github.com/madlambda/nash/parser"
	"github.com/madlambda/nash/sh"
	"github.com/madlambda/nash/token"
)
const (
	logNS     = "nashell.Shell"
	defPrompt = "\033[31mλ>\033[0m "
)
type (
	Env map[string]sh.Obj
	Var Env
	Fns map[string]sh.FnDef
	StatusCode uint8
	Shell struct {
		name        string
		debug       bool
		interactive bool
		abortOnErr  bool
		logf        LogFn
		nashdPath   string
		isFn        bool
		filename    string  
		sigs        chan os.Signal
		interrupted bool
		looping     bool
		stdin  io.Reader
		stdout io.Writer
		stderr io.Writer
		env   Env
		vars  Var
		binds Fns
		root   *ast.Tree
		parent *Shell
		repr string  
		nashpath string
		nashroot string
		*sync.Mutex
	}
	errIgnore struct {
		*errors.NashError
	}
	errInterrupted struct {
		*errors.NashError
	}
	errStopWalking struct {
		*errors.NashError
	}
)
const (
	ESuccess    StatusCode = 0
	ENotFound              = 127
	ENotStarted            = 255
)
func newErrIgnore(format string, arg ...interface{}) error {
	e := &errIgnore{
		NashError: errors.NewError(format, arg...),
	}
	return e
}
func (e *errIgnore) Ignore() bool { return true }
func newErrInterrupted(format string, arg ...interface{}) error {
	return &errInterrupted{
		NashError: errors.NewError(format, arg...),
	}
}
func (e *errInterrupted) Interrupted() bool { return true }
func newErrStopWalking() *errStopWalking {
	return &errStopWalking{
		NashError: errors.NewError("return"),
	}
}
func (e *errStopWalking) StopWalking() bool { return true }
func NewAbortShell(nashpath string, nashroot string) (*Shell, error) {
	return newShell(nashpath, nashroot, true)
}
func NewShell(nashpath string, nashroot string) (*Shell, error) {
	return newShell(nashpath, nashroot, false)
}
func newShell(nashpath string, nashroot string, abort bool) (*Shell, error) {
	shell := &Shell{
		name:        "parent scope",
		interactive: false,
		abortOnErr:  abort,
		isFn:        false,
		logf:        NewLog(logNS, false),
		nashdPath:   nashdAutoDiscover(),
		stdout:      os.Stdout,
		stderr:      os.Stderr,
		stdin:       os.Stdin,
		env:         make(Env),
		vars:        make(Var),
		binds:       make(Fns),
		Mutex:       &sync.Mutex{},
		sigs:        make(chan os.Signal, 1),
		filename:    "<interactive>",
		nashpath:    nashpath,
		nashroot:    nashroot,
	}
	err := shell.setup()
	if err != nil {
		return nil, err
	}
	shell.setupSignals()
	err = validateDirs(nashpath, nashroot)
	if err != nil {
		if shell.abortOnErr {
			return nil, err
		}
		printerr := func(msg string) {
			shell.Stderr().Write([]byte(msg + "\n"))
		}
		printerr(err.Error())
		printerr("please check your NASHPATH and NASHROOT so they point to valid locations")
	}
	return shell, nil
}
func NewSubShell(name string, parent *Shell) *Shell {
	return &Shell{
		name:      name,
		isFn:      true,
		parent:    parent,
		logf:      NewLog(logNS, false),
		nashdPath: nashdAutoDiscover(),
		stdout:    parent.Stdout(),
		stderr:    parent.Stderr(),
		stdin:     parent.Stdin(),
		env:       make(Env),
		vars:      make(Var),
		binds:     make(Fns),
		Mutex:     parent.Mutex,
		filename:  parent.filename,
	}
}
func (shell *Shell) NashPath() string {
	return shell.nashpath
}
func (shell *Shell) initEnv(processEnv []string) error {
	largs := make([]sh.Obj, len(os.Args))
	for i := 0; i < len(os.Args); i++ {
		largs[i] = sh.NewStrObj(os.Args[i])
	}
	argv := sh.NewListObj(largs)
	shell.Setenv("argv", argv)
	shell.Newvar("argv", argv)
	for _, penv := range processEnv {
		var value sh.Obj
		p := strings.Split(penv, "=")
		if len(p) >= 2 {
			if p[0] == "argv" {
				continue
			}
			value = sh.NewStrObj(strings.Join(p[1:], "="))
			shell.Setenv(p[0], value)
			shell.Newvar(p[0], value)
		}
	}
	pidVal := sh.NewStrObj(strconv.Itoa(os.Getpid()))
	shell.Setenv("PID", pidVal)
	shell.Newvar("PID", pidVal)
	if _, ok := shell.Getenv("SHELL"); !ok {
		shellVal := sh.NewStrObj(nashdAutoDiscover())
		shell.Setenv("SHELL", shellVal)
		shell.Newvar("SHELL", shellVal)
	}
	cwd, err := os.Getwd()
	if err != nil {
		return err
	}
	cwdObj := sh.NewStrObj(cwd)
	shell.Setenv("PWD", cwdObj)
	shell.Newvar("PWD", cwdObj)
	return nil
}
func (shell *Shell) Reset() {
	shell.vars = make(Var)
	shell.env = make(Env)
	shell.binds = make(Fns)
}