Rework rounding and building lua script

To allow user script to specify what was modified where
This commit is contained in:
2025-03-25 18:28:28 +01:00
parent 1b0b198297
commit db92033642
2 changed files with 40 additions and 37 deletions

View File

@@ -7,7 +7,6 @@ import (
"modify/processor/jsonpath" "modify/processor/jsonpath"
"os" "os"
"path/filepath" "path/filepath"
"strings"
lua "github.com/yuin/gopher-lua" 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 return content, 0, 0, nil
} }
modCount := 0
for _, node := range nodes { for _, node := range nodes {
log.Printf("Processing node at path: %s with value: %v", node.Path, node.Value) 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) 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 // Execute Lua script
log.Printf("Executing Lua script: %s", luaExpr) log.Printf("Executing Lua script: %q", fullScript)
if err := L.DoString(luaExpr); err != nil { if err := L.DoString(fullScript); err != nil {
return content, len(nodes), 0, fmt.Errorf("error executing Lua %s: %v", luaExpr, err) return content, len(nodes), 0, fmt.Errorf("error executing Lua %q: %v", fullScript, err)
} }
log.Println("Lua script executed successfully.") 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) 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 // Apply the modification to the JSON data
err = p.updateJSONValue(jsonData, node.Path, result) err = p.updateJSONValue(jsonData, node.Path, result)
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 updating JSON: %v", err)
} }
log.Printf("Updated JSON at path: %s with new value: %v", node.Path, result) 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 // Convert the modified JSON back to a string with same formatting
var jsonBytes []byte 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 // We changed all the nodes trust me bro
return string(jsonBytes), len(nodes), len(nodes), nil 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 from the root node
// // Selects nodes in the document from the current node that match the selection no matter where they are // // Selects nodes in the document from the current node that match the selection no matter where they are
// . Selects the current node // . Selects the current node

View File

@@ -129,7 +129,10 @@ func InitLuaHelpers(L *lua.LState) error {
-- Custom Lua helpers for math operations -- Custom Lua helpers for math operations
function min(a, b) return math.min(a, b) end function min(a, b) return math.min(a, b) end
function max(a, b) return math.max(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 floor(x) return math.floor(x) end
function ceil(x) return math.ceil(x) end function ceil(x) return math.ceil(x) end
function upper(s) return string.upper(s) end function upper(s) return string.upper(s) end
@@ -149,6 +152,8 @@ end
function is_number(str) function is_number(str)
return tonumber(str) ~= nil return tonumber(str) ~= nil
end end
modified = false
` `
if err := L.DoString(helperScript); err != nil { if err := L.DoString(helperScript); err != nil {
return fmt.Errorf("error loading helper functions: %v", err) return fmt.Errorf("error loading helper functions: %v", err)
@@ -187,7 +192,21 @@ func BuildLuaScript(luaExpr string) string {
luaExpr = "v1 = " + luaExpr 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 // Max returns the maximum of two integers