Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
73d93367a0 | |||
64f690f6b4 |
24
main.go
24
main.go
@@ -35,22 +35,39 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// TODO: Implement some sort of git integration
|
||||||
|
// Maybe use go-git
|
||||||
|
// Specify a -git flag
|
||||||
|
// If we are operating with git then:
|
||||||
|
// Inmitialize a repo if one doesn't exist (try to open right?)
|
||||||
|
// For each file matched by glob first figure out if it's already tracked
|
||||||
|
// If not tracked then track it and commit (either it alone or maybe multiple together somehow)
|
||||||
|
// Then reset the file (to undo previous modifications)
|
||||||
|
// THEN change the file
|
||||||
|
// In addition add a -undo flag that will ONLY reset the files without changing them
|
||||||
|
// Only for the ones matched by glob
|
||||||
|
// ^ important because binary files would fuck us up
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintf(os.Stderr, "Usage: %s [options] <pattern> <lua_expression> <...files_or_globs>\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, "Usage: %s [options] <pattern> <lua_expression> <...files_or_globs>\n", os.Args[0])
|
||||||
fmt.Fprintf(os.Stderr, "\nOptions:\n")
|
fmt.Fprintf(os.Stderr, "\nOptions:\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " -json\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " Process JSON files\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " -xml\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " Process XML files\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, "\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])
|
||||||
fmt.Fprintf(os.Stderr, " XML mode:\n")
|
fmt.Fprintf(os.Stderr, " XML mode:\n")
|
||||||
fmt.Fprintf(os.Stderr, " %s -mode=xml -xpath=\"//value\" \"*1.5\" data.xml\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, " %s -xml \"//value\" \"*1.5\" data.xml\n", os.Args[0])
|
||||||
fmt.Fprintf(os.Stderr, " JSON mode:\n")
|
fmt.Fprintf(os.Stderr, " JSON mode:\n")
|
||||||
fmt.Fprintf(os.Stderr, " %s -mode=json -jsonpath=\"$.items[*].value\" \"*1.5\" data.json\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, " %s -json \"$.items[*].value\" \"*1.5\" data.json\n", os.Args[0])
|
||||||
fmt.Fprintf(os.Stderr, "\nNote: v1, v2, etc. are used to refer to capture groups as numbers.\n")
|
fmt.Fprintf(os.Stderr, "\nNote: v1, v2, etc. are used to refer to capture groups as numbers.\n")
|
||||||
fmt.Fprintf(os.Stderr, " s1, s2, etc. are used to refer to capture groups as strings.\n")
|
fmt.Fprintf(os.Stderr, " s1, s2, etc. are used to refer to capture groups as strings.\n")
|
||||||
fmt.Fprintf(os.Stderr, " Helper functions: num(str) converts string to number, str(num) converts number to string\n")
|
fmt.Fprintf(os.Stderr, " Helper functions: num(str) converts string to number, str(num) converts number to string\n")
|
||||||
fmt.Fprintf(os.Stderr, " is_number(str) checks if a string is numeric\n")
|
fmt.Fprintf(os.Stderr, " is_number(str) checks if a string is numeric\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " For XML and JSON, the captured values are exposed as 'v', which can be of any type we capture (string, number, table).\n")
|
||||||
fmt.Fprintf(os.Stderr, " If expression starts with an operator like *, /, +, -, =, etc., v1 is automatically prepended\n")
|
fmt.Fprintf(os.Stderr, " If expression starts with an operator like *, /, +, -, =, etc., v1 is automatically prepended\n")
|
||||||
fmt.Fprintf(os.Stderr, " You can use any valid Lua code, including if statements, loops, etc.\n")
|
fmt.Fprintf(os.Stderr, " You can use any valid Lua code, including if statements, loops, etc.\n")
|
||||||
fmt.Fprintf(os.Stderr, " Glob patterns are supported for file selection (*.xml, data/**.xml, etc.)\n")
|
fmt.Fprintf(os.Stderr, " Glob patterns are supported for file selection (*.xml, data/**.xml, etc.)\n")
|
||||||
@@ -117,7 +134,8 @@ func main() {
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
logger.Printf("Processing file: %s", file)
|
logger.Printf("Processing file: %s", file)
|
||||||
|
|
||||||
modCount, matchCount, err := proc.Process(file, pattern, luaExpr)
|
// It's a bit fucked, maybe I could do better to call it from proc... But it'll do for now
|
||||||
|
modCount, matchCount, err := processor.Process(proc, file, pattern, luaExpr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Failed to process file %s: %v\n", file, err)
|
fmt.Fprintf(os.Stderr, "Failed to process file %s: %v\n", file, err)
|
||||||
stats.FailedFiles++
|
stats.FailedFiles++
|
||||||
|
@@ -5,8 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"modify/processor/jsonpath"
|
"modify/processor/jsonpath"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
lua "github.com/yuin/gopher-lua"
|
lua "github.com/yuin/gopher-lua"
|
||||||
)
|
)
|
||||||
@@ -14,39 +12,6 @@ import (
|
|||||||
// JSONProcessor implements the Processor interface for JSON documents
|
// JSONProcessor implements the Processor interface for JSON documents
|
||||||
type JSONProcessor struct{}
|
type JSONProcessor struct{}
|
||||||
|
|
||||||
// Process implements the Processor interface for JSONProcessor
|
|
||||||
func (p *JSONProcessor) Process(filename string, pattern string, luaExpr string) (int, int, error) {
|
|
||||||
// Read file content
|
|
||||||
cwd, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, fmt.Errorf("error getting current working directory: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fullPath := filepath.Join(cwd, filename)
|
|
||||||
content, err := os.ReadFile(fullPath)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, fmt.Errorf("error reading file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fileContent := string(content)
|
|
||||||
|
|
||||||
// Process the content
|
|
||||||
modifiedContent, modCount, matchCount, err := p.ProcessContent(fileContent, pattern, luaExpr)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we made modifications, save the file
|
|
||||||
if modCount > 0 {
|
|
||||||
err = os.WriteFile(fullPath, []byte(modifiedContent), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, fmt.Errorf("error writing file: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return modCount, matchCount, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessContent implements the Processor interface for JSONProcessor
|
// ProcessContent implements the Processor interface for JSONProcessor
|
||||||
func (p *JSONProcessor) ProcessContent(content string, pattern string, luaExpr string) (string, int, int, error) {
|
func (p *JSONProcessor) ProcessContent(content string, pattern string, luaExpr string) (string, int, int, error) {
|
||||||
// Parse JSON document
|
// Parse JSON document
|
||||||
|
@@ -2,6 +2,8 @@ package processor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
lua "github.com/yuin/gopher-lua"
|
lua "github.com/yuin/gopher-lua"
|
||||||
@@ -10,7 +12,8 @@ import (
|
|||||||
// Processor defines the interface for all file processors
|
// Processor defines the interface for all file processors
|
||||||
type Processor interface {
|
type Processor interface {
|
||||||
// Process handles processing a file with the given pattern and Lua expression
|
// Process handles processing a file with the given pattern and Lua expression
|
||||||
Process(filename string, pattern string, luaExpr string) (int, int, error)
|
// Now implemented as a base function in processor.go
|
||||||
|
// Process(filename string, pattern string, luaExpr string) (int, int, error)
|
||||||
|
|
||||||
// ProcessContent handles processing a string content directly with the given pattern and Lua expression
|
// ProcessContent handles processing a string content directly with the given pattern and Lua expression
|
||||||
// Returns the modified content, modification count, match count, and any error
|
// Returns the modified content, modification count, match count, and any error
|
||||||
@@ -51,6 +54,38 @@ func NewLuaState() (*lua.LState, error) {
|
|||||||
return L, nil
|
return L, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Process(p Processor, filename string, pattern string, luaExpr string) (int, int, error) {
|
||||||
|
// Read file content
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("error getting current working directory: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fullPath := filepath.Join(cwd, filename)
|
||||||
|
content, err := os.ReadFile(fullPath)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("error reading file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileContent := string(content)
|
||||||
|
|
||||||
|
// Process the content
|
||||||
|
modifiedContent, modCount, matchCount, err := p.ProcessContent(fileContent, pattern, luaExpr)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we made modifications, save the file
|
||||||
|
if modCount > 0 {
|
||||||
|
err = os.WriteFile(fullPath, []byte(modifiedContent), 0644)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("error writing file: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modCount, matchCount, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ToLua converts a struct or map to a Lua table recursively
|
// ToLua converts a struct or map to a Lua table recursively
|
||||||
func ToLua(L *lua.LState, data interface{}) (lua.LValue, error) {
|
func ToLua(L *lua.LState, data interface{}) (lua.LValue, error) {
|
||||||
switch v := data.(type) {
|
switch v := data.(type) {
|
||||||
|
@@ -2,8 +2,6 @@ package processor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -14,34 +12,6 @@ import (
|
|||||||
// RegexProcessor implements the Processor interface using regex patterns
|
// RegexProcessor implements the Processor interface using regex patterns
|
||||||
type RegexProcessor struct{}
|
type RegexProcessor struct{}
|
||||||
|
|
||||||
// Process implements the Processor interface for RegexProcessor
|
|
||||||
func (p *RegexProcessor) Process(filename string, pattern string, luaExpr string) (int, int, error) {
|
|
||||||
// Read file content
|
|
||||||
fullPath := filepath.Join(".", filename)
|
|
||||||
content, err := os.ReadFile(fullPath)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, fmt.Errorf("error reading file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fileContent := string(content)
|
|
||||||
|
|
||||||
// Process the content
|
|
||||||
modifiedContent, modCount, matchCount, err := p.ProcessContent(fileContent, pattern, luaExpr)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we made modifications, save the file
|
|
||||||
if modCount > 0 {
|
|
||||||
err = os.WriteFile(fullPath, []byte(modifiedContent), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, fmt.Errorf("error writing file: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return modCount, matchCount, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToLua sets capture groups as Lua variables (v1, v2, etc. for numeric values and s1, s2, etc. for strings)
|
// ToLua sets capture groups as Lua variables (v1, v2, etc. for numeric values and s1, s2, etc. for strings)
|
||||||
func (p *RegexProcessor) ToLua(L *lua.LState, data interface{}) error {
|
func (p *RegexProcessor) ToLua(L *lua.LState, data interface{}) error {
|
||||||
captures, ok := data.([]string)
|
captures, ok := data.([]string)
|
||||||
|
@@ -2,8 +2,6 @@ package processor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/antchfx/xmlquery"
|
"github.com/antchfx/xmlquery"
|
||||||
@@ -13,34 +11,6 @@ import (
|
|||||||
// XMLProcessor implements the Processor interface for XML documents
|
// XMLProcessor implements the Processor interface for XML documents
|
||||||
type XMLProcessor struct{}
|
type XMLProcessor struct{}
|
||||||
|
|
||||||
// Process implements the Processor interface for XMLProcessor
|
|
||||||
func (p *XMLProcessor) Process(filename string, pattern string, luaExpr string) (int, int, error) {
|
|
||||||
// Read file content
|
|
||||||
fullPath := filepath.Join(".", filename)
|
|
||||||
content, err := os.ReadFile(fullPath)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, fmt.Errorf("error reading file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fileContent := string(content)
|
|
||||||
|
|
||||||
// Process the content
|
|
||||||
modifiedContent, modCount, matchCount, err := p.ProcessContent(fileContent, pattern, luaExpr)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we made modifications, save the file
|
|
||||||
if modCount > 0 {
|
|
||||||
err = os.WriteFile(fullPath, []byte(modifiedContent), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, fmt.Errorf("error writing file: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return modCount, matchCount, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessContent implements the Processor interface for XMLProcessor
|
// ProcessContent implements the Processor interface for XMLProcessor
|
||||||
func (p *XMLProcessor) ProcessContent(content string, pattern string, luaExpr string) (string, int, int, error) {
|
func (p *XMLProcessor) ProcessContent(content string, pattern string, luaExpr string) (string, int, int, error) {
|
||||||
// Parse XML document
|
// Parse XML document
|
||||||
|
Reference in New Issue
Block a user