diff --git a/env/env.go b/env/env.go index 7ed38497..73c5311d 100755 --- a/env/env.go +++ b/env/env.go @@ -82,7 +82,7 @@ func (e RyeCtx) Preview(idxs Idxs, filter string) string { } bu.WriteString("Context" + ks + ":") if e.Doc > "" { - bu.WriteString("\n\"" + e.Doc + "\"") + bu.WriteString("\n\r\"" + e.Doc + "\"") } arr := make([]string, 0) i := 0 @@ -109,7 +109,7 @@ func (e RyeCtx) Preview(idxs Idxs, filter string) string { for aa := range arr { line := arr[aa] pars := strings.Split(line, "|||") - bu.WriteString("\n " + pars[1] + pars[0]) + bu.WriteString("\n\r " + pars[1] + pars[0]) } return bu.String() } diff --git a/evaldo/builtins.go b/evaldo/builtins.go index 2283e8db..63db2243 100644 --- a/evaldo/builtins.go +++ b/evaldo/builtins.go @@ -2422,6 +2422,15 @@ var builtins = map[string]*env.Builtin{ }, }, + "lsp": { + Argsn: 0, + Doc: "Lists words in current context", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + fmt.Println(ps.Ctx.Parent.Preview(*ps.Idx, "")) + return env.Void{} + }, + }, + "ls\\": { Argsn: 1, Doc: "Lists words in current context with string filter", @@ -2430,6 +2439,22 @@ var builtins = map[string]*env.Builtin{ case env.String: fmt.Println(ps.Ctx.Preview(*ps.Idx, s1.Value)) return env.Void{} + case env.RyeCtx: + fmt.Println(s1.Preview(*ps.Idx, "")) + return env.Void{} + default: + return MakeArgError(ps, 1, []env.Type{env.StringType}, "ls\\") + } + }, + }, + "lsp\\": { + Argsn: 1, + Doc: "Lists words in current context with string filter", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch s1 := arg0.(type) { + case env.String: + fmt.Println(ps.Ctx.Parent.Preview(*ps.Idx, s1.Value)) + return env.Void{} default: return MakeArgError(ps, 1, []env.Type{env.StringType}, "ls\\") } @@ -2450,13 +2475,30 @@ var builtins = map[string]*env.Builtin{ }, }, - "mkcc": { + "ccp": { Argsn: 0, + Doc: "Change to context", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + cc := ps.Ctx + ps.Ctx = ps.Ctx.Parent + return *cc + }, + }, + + "mkcc": { + Argsn: 1, Doc: "Make context with current as parent and change to it.", Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - ctx := ps.Ctx - ps.Ctx = env.NewEnv(ctx) // make new context with current par - return ctx + switch word := arg0.(type) { + case env.Word: + newctx := env.NewEnv(ps.Ctx) + ps.Ctx.Set(word.Index, *newctx) + ctx := ps.Ctx + ps.Ctx = newctx // make new context with current par + return *ctx + default: + return MakeArgError(ps, 1, []env.Type{env.WordType}, "mkcc") + } }, }, @@ -3114,12 +3156,14 @@ var builtins = map[string]*env.Builtin{ case env.Block: ser := ps.Ser ps.Ser = code.Series + purged := make([]env.Object, 0) for i := 0; i < block.Series.Len(); i++ { ps = EvalBlockInj(ps, block.Series.Get(i), true) if ps.ErrorFlag { return ps.Res } if util.IsTruthy(ps.Res) { + purged = append(purged, block.Series.S[i]) block.Series.S = append(block.Series.S[:i], block.Series.S[i+1:]...) i-- } @@ -3127,7 +3171,7 @@ var builtins = map[string]*env.Builtin{ } ps.Ser = ser ctx.Set(wrd.Index, block) - return block + return env.NewBlock(*env.NewTSeries(purged)) default: return MakeArgError(ps, 1, []env.Type{env.BlockType}, "purge!") } diff --git a/main.go b/main.go index d488eb7c..dfefaece 100644 --- a/main.go +++ b/main.go @@ -50,7 +50,7 @@ func main() { evaldo.ShowResults = true if len(os.Args) == 1 { - main_rye_repl(os.Stdin, os.Stdout, false, false) + main_rye_repl(os.Stdin, os.Stdout, true, false) } else if len(os.Args) == 2 { if os.Args[1] == "shell" { main_rysh() @@ -58,34 +58,47 @@ func main() { main_rye_repl(os.Stdin, os.Stdout, true, true) } else if os.Args[1] == "--hr" { evaldo.ShowResults = false - main_rye_repl(os.Stdin, os.Stdout, false, false) - } else if os.Args[1] == "--subc" { main_rye_repl(os.Stdin, os.Stdout, true, false) - } else if os.Args[1] == "web" { - // main_httpd() - } else if os.Args[1] == "ryeco" { - main_ryeco() } else { - main_rye_file(os.Args[1], false, false) + ryeFile := dotsToMainRye(os.Args[1]) + main_rye_file(ryeFile, false, true) } } else if len(os.Args) >= 3 { if os.Args[1] == "ryk" { main_ryk() } else if os.Args[1] == "--hr" { + ryeFile := dotsToMainRye(os.Args[2]) evaldo.ShowResults = false - main_rye_file(os.Args[2], false, false) - } else if os.Args[1] == "--subc" { - main_rye_file(os.Args[2], false, true) + main_rye_file(ryeFile, false, true) } else if os.Args[1] == "cgi" { main_cgi_file(os.Args[2], false) } else if os.Args[1] == "sig" { - main_rye_file(os.Args[2], true, false) + main_rye_file(os.Args[2], true, true) } else { - main_rye_file(os.Args[1], false, false) + ryeFile := dotsToMainRye(os.Args[1]) + main_rye_file(ryeFile, false, true) } } } +func dotsToMainRye(ryeFile string) string { + re := regexp.MustCompile(`^\.$|/\.$`) + if re.MatchString(ryeFile) { + main_path := ryeFile[:len(ryeFile)-1] + "main.rye" + if _, err := os.Stat(main_path); err == nil { + _, err := os.ReadFile(main_path) + if err != nil { + log.Fatal(err) + } + return main_path + } else { + fmt.Println("There was no main.rye") + } + } + return ryeFile + +} + // // main for awk like functionality with rye language // @@ -322,7 +335,7 @@ func main_rye_repl(_ io.Reader, _ io.Writer, subc bool, here bool) { // userHomeDir, _ := os.UserHomeDir() // profile_path := filepath.Join(userHomeDir, ".rye-profile") - fmt.Println("Welcome to Rye shell. Use ls and ls\\ \"pr\" to list the current context.") + fmt.Println("Welcome to Rye shell. ls to list current or lsp or lsp\\ \"prin\" to list parent context.") //if _, err := os.Stat(profile_path); err == nil { //content, err := os.ReadFile(profile_path) diff --git a/main_wasm.go b/main_wasm.go index 45fd5ee8..8a79aeca 100755 --- a/main_wasm.go +++ b/main_wasm.go @@ -35,6 +35,8 @@ var ES *env.ProgramState var CODE []any +var PREV_LINES string + var prevResult env.Object var ml *util.MLState @@ -61,8 +63,9 @@ func sendMessageToJS(message string) { jsCallback.Invoke(message) } -func sendLineToJS(line string) { - jsCallback2.Invoke(line) +func sendLineToJS(line string) string { + ret := jsCallback2.Invoke(line) + return ret.String() } func main() { @@ -109,18 +112,18 @@ func main() { func InitRyeShell(this js.Value, args []js.Value) any { // subc := false - // fmt.Println("INITIALISATION") + // fmt.Println("INITIALIZATION") ps := env.NewProgramStateNEW() evaldo.RegisterBuiltins(ps) contrib.RegisterBuiltins(ps, &evaldo.BuiltinNames) + ctx := ps.Ctx + ps.Ctx = env.NewEnv(ctx) ES = ps /* bloc k := loader.LoadString(" ", false) switch val := block.(type) { case env.Block: if subc { - ctx := es.Ctx - es.Ctx = env.NewEnv(ctx) } evaldo.EvalBlock(es) @@ -143,9 +146,19 @@ func RyeEvalShellLine(this js.Value, args []js.Value) any { subc := false code := args[0].String() + multiline := len(code) > 1 && code[len(code)-1:] == " " + comment := regexp.MustCompile(`\s*;`) codes := comment.Split(code, 2) //--- just very temporary solution for some comments in repl. Later should probably be part of loader ... maybe? code1 := strings.Trim(codes[0], "\t") + if multiline { + PREV_LINES += code1 + return "next line" + } + + code1 = PREV_LINES + "\n" + code1 + + PREV_LINES = "" if ES == nil { return "Error: Rye is not initialized" diff --git a/util/microliner.go b/util/microliner.go index feb8e437..714fc867 100644 --- a/util/microliner.go +++ b/util/microliner.go @@ -122,7 +122,7 @@ type MLState struct { needRefresh bool next <-chan KeyEvent sendBack func(msg string) - enterLine func(line string) + enterLine func(line string) string history []string historyMutex sync.RWMutex columns int @@ -133,7 +133,7 @@ type MLState struct { // NewLiner initializes a new *State, and sets the terminal into raw mode. To // restore the terminal to its previous state, call State.Close(). -func NewMicroLiner(ch chan KeyEvent, sb func(msg string), el func(line string)) *MLState { +func NewMicroLiner(ch chan KeyEvent, sb func(msg string), el func(line string) string) *MLState { var s MLState s.next = ch s.sendBack = sb @@ -369,12 +369,19 @@ func (s *MLState) MicroPrompt(prompt string, text string, pos int) (string, erro historyStale := true // historyAction := false // used to mark history related actions // killAction := 0 // used to mark kill related actions - + multiline := false startOfHere: - s.sendBack(prompt) + var p []rune var line = []rune(text) - p := []rune(prompt) + if !multiline { + s.sendBack(prompt) + p = []rune(prompt) + } else { + s.sendBack(" ") + p = []rune(" ") + multiline = false + } // defer s.stopPrompt() @@ -540,9 +547,13 @@ startOfHere: case 13: // Enter historyStale = true s.sendBack("\n\r") - s.enterLine(string(line)) + xx := s.enterLine(string(line)) pos = 0 - s.sendBack("\n\r") + if xx == "next line" { + multiline = true + } else { + s.sendBack("\n\r") + } line = make([]rune, 0) trace(line) goto startOfHere diff --git a/wasm/ryeshell/index.html b/wasm/ryeshell/index.html index d6c10e52..63a71b2e 100644 --- a/wasm/ryeshell/index.html +++ b/wasm/ryeshell/index.html @@ -196,7 +196,9 @@ function evaluateShellLine(code, term) { var ret = RyeEvalShellLine(code); - + console.log("EVAL SHELL LINE:"); + console.log(ret); + return ret; // term.write(ret); } @@ -215,7 +217,7 @@ } function receiveLineFromGo(line) { - evaluateShellLine(line, term); + return evaluateShellLine(line, term); } function onWasmStdout(out) { @@ -256,6 +258,7 @@