github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/init.go (about)

     1  package lang
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"sync/atomic"
     7  	"time"
     8  
     9  	"github.com/lmorg/murex/app"
    10  	"github.com/lmorg/murex/builtins/pipes/null"
    11  	"github.com/lmorg/murex/builtins/pipes/term"
    12  	"github.com/lmorg/murex/config"
    13  	"github.com/lmorg/murex/lang/ref"
    14  	"github.com/lmorg/murex/lang/runmode"
    15  	"github.com/lmorg/murex/lang/state"
    16  	"github.com/lmorg/murex/lang/types"
    17  	"github.com/lmorg/murex/utils/consts"
    18  	"github.com/lmorg/murex/utils/json"
    19  )
    20  
    21  var (
    22  	// FlagTry is true if murex was started with `--try`
    23  	FlagTry bool
    24  
    25  	// FlagTryPipe is true if murex was started with `--trypipe`
    26  	FlagTryPipe bool
    27  
    28  	// FlagTryErr is true if murex was started with `--tryerr`
    29  	FlagTryErr bool
    30  
    31  	// FlagTryPipeErr is true if murex was started with `--trypipeerr`
    32  	FlagTryPipeErr bool
    33  
    34  	hasMurexAlreadyBeenInitialised int32 = -1
    35  )
    36  
    37  // InitEnv initialises murex. Exported function to enable unit tests.
    38  func InitEnv() {
    39  	i := atomic.AddInt32(&hasMurexAlreadyBeenInitialised, 1)
    40  	if i > 0 {
    41  		return
    42  	}
    43  
    44  	ShellProcess.CreationTime = time.Now()
    45  	ShellProcess.State.Set(state.Executing)
    46  	ShellProcess.Name.Set(os.Args[0])
    47  	ShellProcess.Parameters.DefineParsed(os.Args[1:])
    48  	ShellProcess.Scope = ShellProcess
    49  	ShellProcess.Parent = ShellProcess
    50  	ShellProcess.Previous = ShellProcess
    51  	ShellProcess.Next = ShellProcess
    52  	ShellProcess.Config = config.InitConf
    53  	ShellProcess.Tests = NewTests(ShellProcess)
    54  	ShellProcess.Variables = NewVariables(ShellProcess)
    55  	ShellProcess.Stdout = new(term.Out)
    56  	ShellProcess.Stderr = term.NewErr(true) // TODO: check this is overridden by `config set ...`
    57  	ShellProcess.FileRef = ref.NewModule(app.ShellModule)
    58  	ShellProcess.Context = context.Background()
    59  	ShellProcess.Done = func() { /* we don't want to accidentally terminate the shell process */ }
    60  	ShellProcess.Kill = func() { /* we don't want to accidentally terminate the shell process */ }
    61  	ShellProcess.Forks = NewForkManagement()
    62  
    63  	switch {
    64  	case FlagTry:
    65  		ShellProcess.RunMode = runmode.ModuleTry
    66  	case FlagTryPipe:
    67  		ShellProcess.RunMode = runmode.ModuleTryPipe
    68  	case FlagTryErr:
    69  		ShellProcess.RunMode = runmode.ModuleTryErr
    70  	case FlagTryPipeErr:
    71  		ShellProcess.RunMode = runmode.ModuleTryPipeErr
    72  	}
    73  
    74  	// Sets $SHELL to be murex
    75  	shellEnv, err := os.Executable()
    76  	if err != nil {
    77  		shellEnv = ShellProcess.Name.String()
    78  	}
    79  	os.Setenv("SHELL", shellEnv)
    80  
    81  	if os.Getenv(consts.EnvMethod) == consts.EnvTrue {
    82  		ShellProcess.Stdin = term.NewIn(os.Getenv(consts.EnvDataType))
    83  		ShellProcess.IsMethod = true
    84  	}
    85  
    86  	if os.Getenv(consts.EnvBackground) == consts.EnvTrue {
    87  		ShellProcess.Background.Set(true)
    88  	}
    89  
    90  	// Pre-populate $PWDHIST with current working directory
    91  	s, _ := os.Getwd()
    92  	pwd := []string{s}
    93  	if b, err := json.Marshal(&pwd, false); err == nil {
    94  		GlobalVariables.Set(ShellProcess, "PWDHIST", string(b), types.Json)
    95  	}
    96  
    97  	if err = MethodStdin.Degroup(); err != nil {
    98  		panic(err.Error())
    99  	}
   100  	if err = MethodStdout.Degroup(); err != nil {
   101  		panic(err.Error())
   102  	}
   103  }
   104  
   105  // NewTestProcess creates a dummy process for testing in Go (ie `go test`)
   106  func NewTestProcess() (p *Process) {
   107  	p = new(Process)
   108  	p.Stdin = new(null.Null)
   109  	p.Stdout = new(null.Null)
   110  	p.Stderr = new(null.Null)
   111  	p.Config = config.InitConf.Copy()
   112  	p.Variables = NewVariables(p)
   113  	p.FileRef = &ref.File{Source: &ref.Source{Module: "builtin/testing"}}
   114  	p.Context, p.Done = context.WithTimeout(context.Background(), 60*time.Second)
   115  	p.Parent = ShellProcess
   116  	p.Scope = ShellProcess
   117  	p.Next = ShellProcess
   118  	p.Previous = ShellProcess
   119  	p.Forks = NewForkManagement()
   120  
   121  	GlobalFIDs.Register(p)
   122  
   123  	return
   124  }