Fix up some miscellaneous shit around the project regarding lua conversions
This commit is contained in:
9
.vscode/launch.json
vendored
9
.vscode/launch.json
vendored
@@ -9,8 +9,13 @@
|
|||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "auto",
|
"mode": "auto",
|
||||||
"program": "${fileDirname}",
|
"program": "${workspaceFolder}",
|
||||||
"args": []
|
"args": [
|
||||||
|
"-mode=json",
|
||||||
|
"$..name",
|
||||||
|
"v='pero'",
|
||||||
|
"test.json"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
28
main.go
28
main.go
@@ -32,7 +32,6 @@ var logger *log.Logger
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
fileModeFlag = flag.String("mode", "regex", "Processing mode: regex, xml, json")
|
fileModeFlag = flag.String("mode", "regex", "Processing mode: regex, xml, json")
|
||||||
verboseFlag = flag.Bool("verbose", false, "Enable verbose output")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -48,12 +47,6 @@ func main() {
|
|||||||
fmt.Fprintf(os.Stderr, "\nOptions:\n")
|
fmt.Fprintf(os.Stderr, "\nOptions:\n")
|
||||||
fmt.Fprintf(os.Stderr, " -mode string\n")
|
fmt.Fprintf(os.Stderr, " -mode string\n")
|
||||||
fmt.Fprintf(os.Stderr, " Processing mode: regex, xml, json (default \"regex\")\n")
|
fmt.Fprintf(os.Stderr, " Processing mode: regex, xml, json (default \"regex\")\n")
|
||||||
fmt.Fprintf(os.Stderr, " -xpath string\n")
|
|
||||||
fmt.Fprintf(os.Stderr, " XPath expression (for XML mode)\n")
|
|
||||||
fmt.Fprintf(os.Stderr, " -jsonpath string\n")
|
|
||||||
fmt.Fprintf(os.Stderr, " JSONPath expression (for JSON mode)\n")
|
|
||||||
fmt.Fprintf(os.Stderr, " -verbose\n")
|
|
||||||
fmt.Fprintf(os.Stderr, " Enable verbose output\n")
|
|
||||||
fmt.Fprintf(os.Stderr, "\nExamples:\n")
|
fmt.Fprintf(os.Stderr, "\nExamples:\n")
|
||||||
fmt.Fprintf(os.Stderr, " Regex mode (default):\n")
|
fmt.Fprintf(os.Stderr, " Regex mode (default):\n")
|
||||||
fmt.Fprintf(os.Stderr, " %s \"<value>(\\d+)</value>\" \"*1.5\" data.xml\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, " %s \"<value>(\\d+)</value>\" \"*1.5\" data.xml\n", os.Args[0])
|
||||||
@@ -83,15 +76,9 @@ func main() {
|
|||||||
var pattern, luaExpr string
|
var pattern, luaExpr string
|
||||||
var filePatterns []string
|
var filePatterns []string
|
||||||
|
|
||||||
if *fileModeFlag == "regex" {
|
pattern = args[0]
|
||||||
pattern = args[0]
|
luaExpr = args[1]
|
||||||
luaExpr = args[1]
|
filePatterns = args[2:]
|
||||||
filePatterns = args[2:]
|
|
||||||
} else {
|
|
||||||
// For XML/JSON modes, pattern comes from flags
|
|
||||||
luaExpr = args[0]
|
|
||||||
filePatterns = args[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare the Lua expression
|
// Prepare the Lua expression
|
||||||
originalLuaExpr := luaExpr
|
originalLuaExpr := luaExpr
|
||||||
@@ -124,11 +111,10 @@ func main() {
|
|||||||
// pattern = *xpathFlag
|
// pattern = *xpathFlag
|
||||||
// logger.Printf("Starting XML modifier with XPath %q, expression %q on %d files",
|
// logger.Printf("Starting XML modifier with XPath %q, expression %q on %d files",
|
||||||
// pattern, luaExpr, len(files))
|
// pattern, luaExpr, len(files))
|
||||||
// case "json":
|
case "json":
|
||||||
// proc = &processor.JSONProcessor{}
|
proc = &processor.JSONProcessor{}
|
||||||
// pattern = *jsonpathFlag
|
logger.Printf("Starting JSON modifier with JSONPath %q, expression %q on %d files",
|
||||||
// logger.Printf("Starting JSON modifier with JSONPath %q, expression %q on %d files",
|
pattern, luaExpr, len(files))
|
||||||
// pattern, luaExpr, len(files))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
@@ -3,6 +3,7 @@ package processor
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"modify/processor/jsonpath"
|
"modify/processor/jsonpath"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -67,33 +68,43 @@ func (p *JSONProcessor) ProcessContent(content string, pattern string, luaExpr s
|
|||||||
return content, 0, 0, nil
|
return content, 0, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize Lua
|
for _, node := range nodes {
|
||||||
L, err := NewLuaState()
|
log.Printf("Processing node at path: %s with value: %v", node.Path, node.Value)
|
||||||
if err != nil {
|
|
||||||
return content, len(nodes), 0, fmt.Errorf("error creating Lua state: %v", err)
|
|
||||||
}
|
|
||||||
defer L.Close()
|
|
||||||
|
|
||||||
err = p.ToLua(L, nodes)
|
// Initialize Lua
|
||||||
if err != nil {
|
L, err := NewLuaState()
|
||||||
return content, len(nodes), 0, fmt.Errorf("error converting to Lua: %v", err)
|
if err != nil {
|
||||||
}
|
return content, len(nodes), 0, fmt.Errorf("error creating Lua state: %v", err)
|
||||||
|
}
|
||||||
|
defer L.Close()
|
||||||
|
log.Println("Lua state initialized successfully.")
|
||||||
|
|
||||||
// Execute Lua script
|
err = p.ToLua(L, node.Value)
|
||||||
if err := L.DoString(luaExpr); err != nil {
|
if err != nil {
|
||||||
return content, len(nodes), 0, fmt.Errorf("error executing Lua %s: %v", luaExpr, err)
|
return content, len(nodes), 0, fmt.Errorf("error converting to Lua: %v", err)
|
||||||
}
|
}
|
||||||
|
log.Printf("Converted node value to Lua: %v", node.Value)
|
||||||
|
|
||||||
// Get modified value
|
// Execute Lua script
|
||||||
result, err := p.FromLua(L)
|
log.Printf("Executing Lua script: %s", luaExpr)
|
||||||
if err != nil {
|
if err := L.DoString(luaExpr); err != nil {
|
||||||
return content, len(nodes), 0, fmt.Errorf("error getting result from Lua: %v", err)
|
return content, len(nodes), 0, fmt.Errorf("error executing Lua %s: %v", luaExpr, err)
|
||||||
}
|
}
|
||||||
|
log.Println("Lua script executed successfully.")
|
||||||
|
|
||||||
// Apply the modification to the JSON data
|
// Get modified value
|
||||||
err = p.updateJSONValue(jsonData, pattern, result)
|
result, err := p.FromLua(L)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return content, len(nodes), 0, fmt.Errorf("error updating JSON: %v", err)
|
return content, len(nodes), 0, fmt.Errorf("error getting result from Lua: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("Retrieved modified value from Lua: %v", result)
|
||||||
|
|
||||||
|
// Apply the modification to the JSON data
|
||||||
|
err = p.updateJSONValue(jsonData, node.Path, result)
|
||||||
|
if err != nil {
|
||||||
|
return content, len(nodes), 0, fmt.Errorf("error updating JSON: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("Updated JSON at path: %s with new value: %v", node.Path, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the modified JSON back to a string with same formatting
|
// Convert the modified JSON back to a string with same formatting
|
||||||
@@ -154,12 +165,16 @@ func detectJsonIndentation(content string) (string, error) {
|
|||||||
|
|
||||||
// updateJSONValue updates a value in the JSON structure based on its JSONPath
|
// updateJSONValue updates a value in the JSON structure based on its JSONPath
|
||||||
func (p *JSONProcessor) updateJSONValue(jsonData interface{}, path string, newValue interface{}) error {
|
func (p *JSONProcessor) updateJSONValue(jsonData interface{}, path string, newValue interface{}) error {
|
||||||
|
err := jsonpath.Set(jsonData, path, newValue)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to update JSON value at path '%s': %w", path, err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToLua converts JSON values to Lua variables
|
// ToLua converts JSON values to Lua variables
|
||||||
func (p *JSONProcessor) ToLua(L *lua.LState, data interface{}) error {
|
func (p *JSONProcessor) ToLua(L *lua.LState, data interface{}) error {
|
||||||
table, err := ToLuaTable(L, data)
|
table, err := ToLua(L, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -170,5 +185,5 @@ func (p *JSONProcessor) ToLua(L *lua.LState, data interface{}) error {
|
|||||||
// FromLua retrieves values from Lua
|
// FromLua retrieves values from Lua
|
||||||
func (p *JSONProcessor) FromLua(L *lua.LState) (interface{}, error) {
|
func (p *JSONProcessor) FromLua(L *lua.LState) (interface{}, error) {
|
||||||
luaValue := L.GetGlobal("v")
|
luaValue := L.GetGlobal("v")
|
||||||
return FromLuaTable(L, luaValue.(*lua.LTable))
|
return FromLua(L, luaValue)
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@ package processor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
lua "github.com/yuin/gopher-lua"
|
lua "github.com/yuin/gopher-lua"
|
||||||
@@ -52,65 +52,75 @@ func NewLuaState() (*lua.LState, error) {
|
|||||||
return L, nil
|
return L, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToLuaTable converts a struct or map to a Lua table recursively
|
// ToLua converts a struct or map to a Lua table recursively
|
||||||
func ToLuaTable(L *lua.LState, data interface{}) (*lua.LTable, error) {
|
func ToLua(L *lua.LState, data interface{}) (lua.LValue, error) {
|
||||||
luaTable := L.NewTable()
|
|
||||||
|
|
||||||
switch v := data.(type) {
|
switch v := data.(type) {
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
|
luaTable := L.NewTable()
|
||||||
for key, value := range v {
|
for key, value := range v {
|
||||||
luaValue, err := ToLuaTable(L, value)
|
luaValue, err := ToLua(L, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
luaTable.RawSetString(key, luaValue)
|
luaTable.RawSetString(key, luaValue)
|
||||||
}
|
}
|
||||||
case struct{}:
|
return luaTable, nil
|
||||||
val := reflect.ValueOf(v)
|
case []interface{}:
|
||||||
for i := 0; i < val.NumField(); i++ {
|
luaTable := L.NewTable()
|
||||||
field := val.Type().Field(i)
|
for i, value := range v {
|
||||||
luaValue, err := ToLuaTable(L, val.Field(i).Interface())
|
luaValue, err := ToLua(L, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
luaTable.RawSetString(field.Name, luaValue)
|
luaTable.RawSetInt(i+1, luaValue) // Lua arrays are 1-indexed
|
||||||
}
|
}
|
||||||
|
return luaTable, nil
|
||||||
case string:
|
case string:
|
||||||
luaTable.RawSetString("v", lua.LString(v))
|
return lua.LString(v), nil
|
||||||
case bool:
|
case bool:
|
||||||
luaTable.RawSetString("v", lua.LBool(v))
|
return lua.LBool(v), nil
|
||||||
case float64:
|
case float64:
|
||||||
luaTable.RawSetString("v", lua.LNumber(v))
|
return lua.LNumber(v), nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported data type: %T", data)
|
return nil, fmt.Errorf("unsupported data type: %T", data)
|
||||||
}
|
}
|
||||||
return luaTable, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromLuaTable converts a Lua table to a struct or map recursively
|
// FromLua converts a Lua table to a struct or map recursively
|
||||||
func FromLuaTable(L *lua.LState, luaTable *lua.LTable) (map[string]interface{}, error) {
|
func FromLua(L *lua.LState, luaValue lua.LValue) (interface{}, error) {
|
||||||
result := make(map[string]interface{})
|
switch v := luaValue.(type) {
|
||||||
|
case *lua.LTable:
|
||||||
luaTable.ForEach(func(key lua.LValue, value lua.LValue) {
|
result := make(map[string]interface{})
|
||||||
switch v := value.(type) {
|
v.ForEach(func(key lua.LValue, value lua.LValue) {
|
||||||
case *lua.LTable:
|
result[key.String()], _ = FromLua(L, value)
|
||||||
nestedMap, err := FromLuaTable(L, v)
|
})
|
||||||
|
// This may be a bit wasteful...
|
||||||
|
// Hopefully it won't run often enough to matter
|
||||||
|
isArray := true
|
||||||
|
for key := range result {
|
||||||
|
_, err := strconv.Atoi(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
isArray = false
|
||||||
|
break
|
||||||
}
|
}
|
||||||
result[key.String()] = nestedMap
|
|
||||||
case lua.LString:
|
|
||||||
result[key.String()] = string(v)
|
|
||||||
case lua.LBool:
|
|
||||||
result[key.String()] = bool(v)
|
|
||||||
case lua.LNumber:
|
|
||||||
result[key.String()] = float64(v)
|
|
||||||
default:
|
|
||||||
result[key.String()] = nil
|
|
||||||
}
|
}
|
||||||
})
|
if isArray {
|
||||||
|
list := make([]interface{}, 0, len(result))
|
||||||
return result, nil
|
for _, value := range result {
|
||||||
|
list = append(list, value)
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
case lua.LString:
|
||||||
|
return string(v), nil
|
||||||
|
case lua.LBool:
|
||||||
|
return bool(v), nil
|
||||||
|
case lua.LNumber:
|
||||||
|
return float64(v), nil
|
||||||
|
default:
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitLuaHelpers initializes common Lua helper functions
|
// InitLuaHelpers initializes common Lua helper functions
|
||||||
|
Reference in New Issue
Block a user