commit de5de7a79aecf2a540f02072fb6304735b215dd5 Author: surdeus Date: Mon Feb 26 02:22:09 2024 +0500 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed4f642 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +pp diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..568817a --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +# +go build ./cmd/pp diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..05059a2 --- /dev/null +++ b/errors.go @@ -0,0 +1,15 @@ +package pp + +import ( + //"errors" + "fmt" +) + +type UnexpectedError struct { + What string + Line int +} +func (err UnexpectedError) Error() string { + return fmt.Sprintf("%d: unexpected %s", err.Line, err.What) +} + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..205ce5e --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module vultras.su/util/pp + +go 1.21.7 + +require ( + github.com/d5/tengo/v2 v2.16.1 // indirect + vultras.su/core/cli v0.0.0-20240104195345-5d79542278a0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..f57549c --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/d5/tengo/v2 v2.16.1 h1:/N6dqiGu9toqANInZEOQMM8I06icdZnmb+81DG/lZdw= +github.com/d5/tengo/v2 v2.16.1/go.mod h1:XRGjEs5I9jYIKTxly6HCF8oiiilk5E/RYXOZ5b0DZC8= +vultras.su/core/cli v0.0.0-20240104195345-5d79542278a0 h1:acA77oEg7hDuUchyBvw7scG9gayVLFAC9/CGuqyfLSA= +vultras.su/core/cli v0.0.0-20240104195345-5d79542278a0/go.mod h1:rYu/sFWE3vUkDSSJCZt+K1aVaso0MYcZ+tmxQd4whdQ= diff --git a/main.go b/main.go new file mode 100644 index 0000000..8b17c4e --- /dev/null +++ b/main.go @@ -0,0 +1,109 @@ +package pp + +import ( + "github.com/d5/tengo/v2" + "github.com/d5/tengo/v2/stdlib" + "context" + "strings" + "fmt" +) + +type Preprocessor struct { + // The string will be inserted in the + // beginning of processed files. + head string + + tags [2]string + modules *tengo.ModuleMap +} + +// Evaluate the expression and return the value +// it would print. +func (pp *Preprocessor) Eval(data string) (string, error) { + const retHead = ` + printf := func(format, ...vals) { + __ret__ += __Sprintf(format, vals...) + } + ` + script := tengo.NewScript([]byte(retHead + pp.head + "\n" + data)) + err := script.Add("__Sprintf", &tengo.UserFunction{ + Value: func(args ...tengo.Object) (tengo.Object, error){ + if len(args) < 1 { + return nil, tengo.ErrWrongNumArguments + } + format, ok := tengo.ToString(args[0]) + if !ok { + return nil, tengo.ErrInvalidArgumentType{ + Expected: "string", + } + } + gargs := make([]any, len(args) - 1) + for i := range gargs { + gargs[i] = tengo.ToInterface(args[i+1]) + //fmt.Printf("shit: %q\n", gargs[i]) + } + str := fmt.Sprintf(format, gargs...) + return tengo.FromInterface(str) + }, + }, + ) + if err != nil { + return "", err + } + err = script.Add("__ret__", "") + if err != nil{ + return "", err + } + compiled, err := script.RunContext(context.Background()) + if err != nil { + return "", err + } + + return compiled.Get("__ret__").String(), nil +} + +// Get the new preprocessor with default options. +func NewPp() *Preprocessor { + pp := &Preprocessor{ + tags: [2]string{ + "", + }, + modules: stdlib.GetModuleMap(stdlib.AllModuleNames()...) + } + return pp +} + +func (pp *Preprocessor) Process(data string) (string, error) { + var b strings.Builder + last := 0 + for { + idxStart := strings.Index(data[last:], pp.tags[0]) + idxEnd := strings.Index(data[last:], pp.tags[1]) + //fmt.Printf("cock %d %d %d\n", last, idxStart, idxEnd) + if idxStart < 0 { + if idxEnd >= 0 { + return "", UnexpectedError{ + What: "end tag", + } + } + fmt.Fprint(&b, data[last:]) + break + } else if idxEnd < 0 { + return "", UnexpectedError{ + What: "start tag", + } + } + fmt.Fprint(&b, data[last:idxStart]) + code := data[idxStart+len(pp.tags[0]):idxEnd] + str, err := pp.Eval(code) + if err != nil { + return "", err + } + fmt.Fprint(&b, str) + data = data[idxEnd + len(pp.tags[1])+1:] + } + + return b.String(), nil +} + diff --git a/tests/index.md.pp b/tests/index.md.pp new file mode 100644 index 0000000..8126fd1 --- /dev/null +++ b/tests/index.md.pp @@ -0,0 +1,11 @@ +# The index testing + 1 + 1 = +## The shit after + +checking + diff --git a/tool.go b/tool.go new file mode 100644 index 0000000..1c206e9 --- /dev/null +++ b/tool.go @@ -0,0 +1,28 @@ +package pp + +import ( + "vultras.su/core/cli/mtool" + "fmt" + "os" + "log" + "path/filepath" +) + +var Tool = mtool.T("pp").Func(func(flags *mtool.Flags){ + pp := NewPp() + filePaths := flags.Parse() + for _, filePath := range filePaths { + pth := filepath.FromSlash(filePath) + bts, err := os.ReadFile(pth) + if err != nil { + log.Println("read error:", err) + continue + } + str, err := pp.Process(string(bts)) + if err != nil { + log.Println("pp error:", err) + continue + } + fmt.Print(str) + } +})