Skip to content

Commit b087d3b

Browse files
committed
Add REPL functionality and enhance Lua integration with new file and environment APIs
1 parent b50c9bd commit b087d3b

File tree

10 files changed

+241
-150
lines changed

10 files changed

+241
-150
lines changed

glosfs/memoryfs.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
)
88

99
var MemoryFS = make(map[string]string) // In-memory file system
10+
var GlosEnv = make(map[string]string) // In-memory environment storage
1011
const fsFilename = "memoryfs.dat" // Persistent storage file
1112
const utilsDir = "utils"
1213

luaexec/lua_runner.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package luaexec
22

33
import (
4+
"bufio"
5+
"fmt"
6+
"glos/glosfs"
7+
"os"
8+
"strings"
9+
410
lua "github.com/yuin/gopher-lua"
511
)
612

@@ -10,6 +16,15 @@ func Execute(content string, args []string) error {
1016

1117
SafePreload(L)
1218

19+
L.SetGlobal("read_file", L.NewFunction(luaReadFile))
20+
L.SetGlobal("list_files", L.NewFunction(luaListFiles))
21+
L.SetGlobal("write_file", L.NewFunction(luaWriteFile))
22+
L.SetGlobal("read_multiline_input", L.NewFunction(luaReadMultilineInput))
23+
L.SetGlobal("delete_file", L.NewFunction(luaDeleteFile))
24+
L.SetGlobal("set_env", L.NewFunction(luaSetEnv))
25+
L.SetGlobal("get_env", L.NewFunction(luaGetEnv))
26+
L.SetGlobal("clear_screen", L.NewFunction(luaClearScreen))
27+
1328
luaTable := L.NewTable()
1429
for i, arg := range args {
1530
L.SetTable(luaTable, lua.LNumber(i+1), lua.LString(arg))
@@ -18,3 +33,119 @@ func Execute(content string, args []string) error {
1833

1934
return L.DoString(content)
2035
}
36+
37+
// Example usage in Lua:
38+
// content = read_file("filename")
39+
// print(content)
40+
func luaReadFile(L *lua.LState) int {
41+
filename := L.ToString(1) // Get the first argument from Lua
42+
content, exists := glosfs.MemoryFS[filename]
43+
if !exists {
44+
L.Push(lua.LNil)
45+
L.Push(lua.LString("File not found"))
46+
return 2 // Return nil and error message
47+
}
48+
L.Push(lua.LString(content))
49+
return 1 // Return file content
50+
}
51+
52+
// Example usage in Lua:
53+
// files = list_files()
54+
// for filename, _ in pairs(files) do
55+
//
56+
// print(filename)
57+
//
58+
// end
59+
func luaListFiles(L *lua.LState) int {
60+
luaTable := L.NewTable()
61+
for filename := range glosfs.MemoryFS {
62+
L.SetTable(luaTable, lua.LString(filename), lua.LTrue)
63+
}
64+
L.Push(luaTable)
65+
return 1
66+
}
67+
68+
// Example usage in Lua:
69+
// write_file("filename", "content")
70+
func luaWriteFile(L *lua.LState) int {
71+
filename := L.ToString(1)
72+
content := L.ToString(2)
73+
glosfs.MemoryFS[filename] = content
74+
return 0
75+
}
76+
77+
// Example usage in Lua:
78+
// content = read_multiline_input()
79+
// print(content)
80+
func luaReadMultilineInput(L *lua.LState) int {
81+
scanner := bufio.NewScanner(os.Stdin)
82+
var content strings.Builder
83+
84+
for scanner.Scan() {
85+
line := scanner.Text()
86+
if line == ":exit" {
87+
break
88+
}
89+
content.WriteString(line + "\n")
90+
}
91+
92+
if err := scanner.Err(); err != nil {
93+
fmt.Println("Error reading input:", err)
94+
}
95+
L.Push(lua.LString(content.String()))
96+
return 1
97+
}
98+
99+
// Example usage in Lua, including error handling:
100+
// success, error_message = delete_file("filename")
101+
// if not success then
102+
//
103+
// print(error_message)
104+
//
105+
// end
106+
func luaDeleteFile(L *lua.LState) int {
107+
filename := L.ToString(1)
108+
if _, exists := glosfs.MemoryFS[filename]; !exists {
109+
L.Push(lua.LNil)
110+
L.Push(lua.LString("File not found"))
111+
return 2 // Return nil and error message
112+
}
113+
delete(glosfs.MemoryFS, filename)
114+
115+
// Explicitly return true for success
116+
L.Push(lua.LTrue)
117+
return 1
118+
}
119+
120+
// Example usage in Lua:
121+
// set_env("variable_name", "variable_value")
122+
// variable_value = get_env("variable_name")
123+
// print(variable_value)
124+
func luaSetEnv(L *lua.LState) int {
125+
varName := L.ToString(1)
126+
varValue := L.ToString(2)
127+
glosfs.GlosEnv[varName] = varValue
128+
L.Push(lua.LTrue)
129+
return 1
130+
}
131+
132+
// Example usage in Lua:
133+
// variable_value = get_env("variable_name")
134+
// print(variable_value)
135+
func luaGetEnv(L *lua.LState) int {
136+
varName := L.ToString(1)
137+
value, exists := glosfs.GlosEnv[varName]
138+
if !exists {
139+
L.Push(lua.LNil)
140+
return 1
141+
}
142+
L.Push(lua.LString(value))
143+
return 1
144+
}
145+
146+
// Example usage in Lua:
147+
// clear_screen()
148+
func luaClearScreen(L *lua.LState) int {
149+
fmt.Print("\033[2J\033[H") // ANSI code: Clear screen and move cursor to home
150+
return 0
151+
}

main.go

Lines changed: 2 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -1,154 +1,7 @@
11
package main
22

3-
import (
4-
"bufio"
5-
"fmt"
6-
"glos/glosfs"
7-
"glos/luaexec"
8-
"os"
9-
"strings"
10-
11-
lua "github.com/yuin/gopher-lua"
12-
)
3+
import "glos/repl"
134

145
func main() {
15-
glosfs.LoadMemoryFS() // Load memoryFS on start
16-
fmt.Println("Welcome to GLOS (Go/Lua OS) 1.0")
17-
scanner := bufio.NewScanner(os.Stdin)
18-
19-
for {
20-
fmt.Print("glos> ")
21-
if !scanner.Scan() {
22-
break
23-
}
24-
input := scanner.Text()
25-
args := strings.SplitN(input, " ", 2)
26-
command := args[0]
27-
var param string
28-
if len(args) > 1 {
29-
param = args[1]
30-
}
31-
32-
switch command {
33-
case "exit":
34-
fmt.Println("Exiting GLOS...")
35-
glosfs.SaveMemoryFS() // Save memoryFS before exit
36-
return
37-
case "write":
38-
writeFile(param)
39-
case "ls":
40-
listFiles()
41-
case "run":
42-
runLua(param)
43-
case "help":
44-
fmt.Println("Commands: write <filename>, ls, run <filename> [args...], exit")
45-
default:
46-
if _, exists := glosfs.MemoryFS[command]; exists {
47-
runLua(command + " " + param) // Execute exact match
48-
} else if _, exists := glosfs.MemoryFS[command+".lua"]; exists {
49-
runLua(command + ".lua" + " " + param) // Try with .lua extension
50-
} else {
51-
fmt.Println("Unknown command")
52-
}
53-
54-
}
55-
}
56-
}
57-
58-
func writeFile(filename string) {
59-
if filename == "" {
60-
fmt.Println("Usage: write <filename>")
61-
return
62-
}
63-
64-
fmt.Println("Enter text (Type ':exit' to save and exit):")
65-
66-
content := readMultilineInput()
67-
glosfs.MemoryFS[filename] = content
68-
fmt.Printf("File '%s' saved in memory.\n", filename)
69-
}
70-
71-
func readMultilineInput() string {
72-
scanner := bufio.NewScanner(os.Stdin)
73-
var content strings.Builder
74-
75-
for scanner.Scan() {
76-
line := scanner.Text()
77-
if line == ":exit" {
78-
break
79-
}
80-
content.WriteString(line + "\n")
81-
}
82-
83-
if err := scanner.Err(); err != nil {
84-
fmt.Println("Error reading input:", err)
85-
}
86-
return content.String()
87-
}
88-
89-
func listFiles() {
90-
if len(glosfs.MemoryFS) == 0 {
91-
fmt.Println("No files in memory.")
92-
return
93-
}
94-
fmt.Println("Files in memory:")
95-
for filename := range glosfs.MemoryFS {
96-
fmt.Println("-", filename)
97-
}
98-
}
99-
100-
func runLua(input string) {
101-
if input == "" {
102-
fmt.Println("Usage: run <filename> [args...]")
103-
return
104-
}
105-
106-
args := strings.SplitN(input, " ", 2)
107-
filename := args[0]
108-
var luaArgs []string
109-
110-
if len(args) > 1 {
111-
luaArgs = strings.Fields(args[1])
112-
}
113-
114-
content, exists := glosfs.MemoryFS[filename]
115-
if !exists {
116-
fmt.Printf("File '%s' not found.\n", filename)
117-
return
118-
}
119-
120-
// Create a new Lua state
121-
L := lua.NewState()
122-
defer L.Close()
123-
124-
// Remove dangerous standard libraries
125-
luaexec.SafePreload(L)
126-
127-
// Register custom API functions
128-
L.SetGlobal("read_file", L.NewFunction(luaReadFile))
129-
// L.SetGlobal("shutdown", L.NewFunction(luaShutdown)) // Custom shutdown function
130-
131-
// Provide script arguments
132-
luaTable := L.NewTable()
133-
for i, arg := range luaArgs {
134-
L.SetTable(luaTable, lua.LNumber(i+1), lua.LString(arg))
135-
}
136-
L.SetGlobal("args", luaTable)
137-
138-
// Execute Lua script
139-
if err := L.DoString(content); err != nil {
140-
fmt.Println("Error executing Lua:", err)
141-
}
142-
}
143-
144-
func luaReadFile(L *lua.LState) int {
145-
filename := L.ToString(1) // Get the first argument from Lua
146-
content, exists := glosfs.MemoryFS[filename]
147-
if !exists {
148-
L.Push(lua.LNil)
149-
L.Push(lua.LString("File not found"))
150-
return 2 // Return nil and error message
151-
}
152-
L.Push(lua.LString(content))
153-
return 1 // Return file content
6+
repl.StartREPL()
1547
}

repl/repl.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,73 @@
11
package repl
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"glos/glosfs"
7+
"glos/luaexec"
8+
"os"
9+
"strings"
10+
)
11+
12+
// StartREPL starts the interactive shell for GLOS.
13+
func StartREPL() {
14+
glosfs.LoadMemoryFS() // Load memoryFS on start
15+
fmt.Println("Welcome to GLOS (Go/Lua OS) 1.0")
16+
scanner := bufio.NewScanner(os.Stdin)
17+
18+
for {
19+
fmt.Print("glos> ")
20+
if !scanner.Scan() {
21+
break
22+
}
23+
input := scanner.Text()
24+
args := strings.SplitN(input, " ", 2)
25+
command := args[0]
26+
var param string
27+
if len(args) > 1 {
28+
param = args[1]
29+
}
30+
31+
switch command {
32+
case "exit":
33+
fmt.Println("Exiting GLOS...")
34+
glosfs.SaveMemoryFS() // Save memoryFS before exit
35+
return
36+
case "run":
37+
runLua(param)
38+
default:
39+
if _, exists := glosfs.MemoryFS[command]; exists {
40+
runLua(command + " " + param) // Execute exact match
41+
} else if _, exists := glosfs.MemoryFS[command+".lua"]; exists {
42+
runLua(command + ".lua" + " " + param) // Try with .lua extension
43+
} else {
44+
fmt.Println("Unknown command")
45+
}
46+
}
47+
}
48+
}
49+
50+
func runLua(input string) {
51+
if input == "" {
52+
fmt.Println("Usage: run <filename> [args...]")
53+
return
54+
}
55+
56+
args := strings.SplitN(input, " ", 2)
57+
filename := args[0]
58+
var luaArgs []string
59+
60+
if len(args) > 1 {
61+
luaArgs = strings.Fields(args[1])
62+
}
63+
64+
content, exists := glosfs.MemoryFS[filename]
65+
if !exists {
66+
fmt.Printf("File '%s' not found.\n", filename)
67+
return
68+
}
69+
70+
if err := luaexec.Execute(content, luaArgs); err != nil {
71+
fmt.Println("Error executing Lua:", err)
72+
}
73+
}

utils/cat.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
if not args or #args == 0 then
2-
print("Usage: lua print_file.lua <filename>")
2+
print("Usage: cat <filename>")
33
return
44
end
55

utils/clear.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
clear_screen()

0 commit comments

Comments
 (0)