From db920336425eb994cba7cb7f1ec663f0efbd8e60 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Tue, 25 Mar 2025 18:28:28 +0100 Subject: [PATCH] Rework rounding and building lua script To allow user script to specify what was modified where --- processor/json.go | 54 +++++++++++++++--------------------------- processor/processor.go | 23 ++++++++++++++++-- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/processor/json.go b/processor/json.go index 60d267e..b72cc1e 100644 --- a/processor/json.go +++ b/processor/json.go @@ -7,7 +7,6 @@ import ( "modify/processor/jsonpath" "os" "path/filepath" - "strings" lua "github.com/yuin/gopher-lua" ) @@ -68,6 +67,7 @@ func (p *JSONProcessor) ProcessContent(content string, pattern string, luaExpr s return content, 0, 0, nil } + modCount := 0 for _, node := range nodes { log.Printf("Processing node at path: %s with value: %v", node.Path, node.Value) @@ -85,10 +85,14 @@ func (p *JSONProcessor) ProcessContent(content string, pattern string, luaExpr s } log.Printf("Converted node value to Lua: %v", node.Value) + originalScript := luaExpr + fullScript := BuildLuaScript(luaExpr) + log.Printf("Original script: %q, Full script: %q", originalScript, fullScript) + // Execute Lua script - log.Printf("Executing Lua script: %s", luaExpr) - if err := L.DoString(luaExpr); err != nil { - return content, len(nodes), 0, fmt.Errorf("error executing Lua %s: %v", luaExpr, err) + log.Printf("Executing Lua script: %q", fullScript) + if err := L.DoString(fullScript); err != nil { + return content, len(nodes), 0, fmt.Errorf("error executing Lua %q: %v", fullScript, err) } log.Println("Lua script executed successfully.") @@ -99,53 +103,33 @@ func (p *JSONProcessor) ProcessContent(content string, pattern string, luaExpr s } log.Printf("Retrieved modified value from Lua: %v", result) + modified := false + modified = L.GetGlobal("modified").String() == "true" + if !modified { + log.Printf("No changes made to node at path: %s", node.Path) + continue + } + // 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) + modCount++ } // Convert the modified JSON back to a string with same formatting var jsonBytes []byte - if indent, err := detectJsonIndentation(content); err == nil && indent != "" { - // Use detected indentation for output formatting - jsonBytes, err = json.MarshalIndent(jsonData, "", indent) - } else { - // Fall back to standard 2-space indent - jsonBytes, err = json.MarshalIndent(jsonData, "", " ") + jsonBytes, err = json.MarshalIndent(jsonData, "", " ") + if err != nil { + return content, len(nodes), 0, fmt.Errorf("error marshalling JSON: %v", err) } // We changed all the nodes trust me bro return string(jsonBytes), len(nodes), len(nodes), nil } -// detectJsonIndentation tries to determine the indentation used in the original JSON -func detectJsonIndentation(content string) (string, error) { - lines := strings.Split(content, "\n") - if len(lines) < 2 { - return "", fmt.Errorf("not enough lines to detect indentation") - } - - // Look for the first indented line - for i := 1; i < len(lines); i++ { - line := lines[i] - trimmed := strings.TrimSpace(line) - if trimmed == "" { - continue - } - - // Calculate leading whitespace - indent := line[:len(line)-len(trimmed)] - if len(indent) > 0 { - return indent, nil - } - } - - return "", fmt.Errorf("no indentation detected") -} - // / Selects from the root node // // Selects nodes in the document from the current node that match the selection no matter where they are // . Selects the current node diff --git a/processor/processor.go b/processor/processor.go index e268a63..9afd8ab 100644 --- a/processor/processor.go +++ b/processor/processor.go @@ -129,7 +129,10 @@ func InitLuaHelpers(L *lua.LState) error { -- Custom Lua helpers for math operations function min(a, b) return math.min(a, b) end function max(a, b) return math.max(a, b) end -function round(x) return math.floor(x + 0.5) end +function round(x, n) + if n == nil then n = 0 end + return math.floor(x * 10^n + 0.5) / 10^n +end function floor(x) return math.floor(x) end function ceil(x) return math.ceil(x) end function upper(s) return string.upper(s) end @@ -149,6 +152,8 @@ end function is_number(str) return tonumber(str) ~= nil end + +modified = false ` if err := L.DoString(helperScript); err != nil { return fmt.Errorf("error loading helper functions: %v", err) @@ -187,7 +192,21 @@ func BuildLuaScript(luaExpr string) string { luaExpr = "v1 = " + luaExpr } - return luaExpr + // This allows the user to specify whether or not they modified a value + // If they do nothing we assume they did modify (no return at all) + // If they return before our return then they themselves specify what they did + // If nothing is returned lua assumes nil + // So we can say our value was modified if the return value is either nil or true + // If the return value is false then the user wants to keep the original + fullScript := fmt.Sprintf(` + function run() + %s + end + local res = run() + modified = res == nil or res + `, luaExpr) + + return fullScript } // Max returns the maximum of two integers