From 9e562ab17d588aad0d23ed8e85c3cf40db35bd63 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mikl=C3=B3s=20T=C3=B3th?= <tothmiklostibor@gmail.com>
Date: Sun, 9 May 2021 21:18:07 +0200
Subject: [PATCH] flatten beginning

---
 plab/flatten/TexFile.go     |   1 +
 plab/flatten/flatten.go     |  32 +++++++++
 plab/flatten/flattenable.go |   5 ++
 plab/flatten/function.go    | 134 ++++++++++++++++++++++++++++++++++++
 plab/main.go                |   3 +-
 5 files changed, 174 insertions(+), 1 deletion(-)
 create mode 100644 plab/flatten/TexFile.go
 create mode 100644 plab/flatten/flatten.go
 create mode 100644 plab/flatten/flattenable.go
 create mode 100644 plab/flatten/function.go

diff --git a/plab/flatten/TexFile.go b/plab/flatten/TexFile.go
new file mode 100644
index 0000000..dc237a7
--- /dev/null
+++ b/plab/flatten/TexFile.go
@@ -0,0 +1 @@
+package flatten
diff --git a/plab/flatten/flatten.go b/plab/flatten/flatten.go
new file mode 100644
index 0000000..7f4e616
--- /dev/null
+++ b/plab/flatten/flatten.go
@@ -0,0 +1,32 @@
+package flatten
+
+import (
+	"fmt"
+	"git.sch.bme.hu/insert-epic-projlab-team-name-here/tooling/plab/helpers"
+)
+
+var Flatten = helpers.Subcommand{
+	Name: "flatten",
+	Command: func(args []string) {
+		if len(args) < 2 {
+			fmt.Println("usage: <entrypoint.tex> [functions.tex...] <merged.tex>")
+			return
+		}
+
+		entry := args[0]
+		out := args[len(args)-1]
+
+		_, _ = entry, out
+
+		funcFiles := args[1 : len(args)-1]
+
+		for _, f := range funcFiles {
+			e := ParseFile(f)
+			if e != nil {
+				panic(e)
+			}
+		}
+		fmt.Println("flattened")
+	},
+	Help: "flaten a .tex file",
+}
diff --git a/plab/flatten/flattenable.go b/plab/flatten/flattenable.go
new file mode 100644
index 0000000..b84178b
--- /dev/null
+++ b/plab/flatten/flattenable.go
@@ -0,0 +1,5 @@
+package flatten
+
+type flattenable interface {
+	Flatten() string
+}
diff --git a/plab/flatten/function.go b/plab/flatten/function.go
new file mode 100644
index 0000000..2bc8052
--- /dev/null
+++ b/plab/flatten/function.go
@@ -0,0 +1,134 @@
+package flatten
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+type FunctionImplementation struct {
+	Name string
+	Body string
+	ArgNum int
+}
+
+func InlineAllFuncs(str string) (string, error) {
+	for _, f := range funcs {
+		var soFar bytes.Buffer
+		tmpRegexp, e := regexp.Compile(fmt.Sprintf(`\\%s`, f.Name))
+		if e != nil {
+			return "", e
+		}
+		idx := tmpRegexp.FindAllStringIndex(str, -1)
+		prevStop := 0
+		for _, i := range idx {
+			nameStart := i[0]
+			argsStart := i[1]
+
+			name := str[nameStart:argsStart]
+			var fi *FunctionImplementation = nil
+			for fidx, f := range funcs {
+				if f.Name == name {
+					fi = &funcs[fidx]
+				}
+			}
+			if fi == nil {
+				continue
+			}
+
+			soFar.WriteString(str[prevStop:nameStart])
+
+			args := make([]string, 0)
+			for i := 0; i < fi.ArgNum; i++ {
+				depth := 0
+				var arg string
+				for
+			}
+		}
+	}
+	return str
+}
+
+func (f *FunctionImplementation) Inline(args ...string) string {
+	const canary = "🙂🙃🙂"
+	str := "{"
+	str = f.Body
+	str = strings.ReplaceAll(str, `\#`, canary)
+	for i, a := range args {
+		str = strings.ReplaceAll(str, fmt.Sprintf("#%d", i), a)
+	}
+	str = strings.ReplaceAll(str, canary, `\#`)
+	str += "}"
+	return str
+}
+
+var funcs = make([]FunctionImplementation, 0)
+
+var cmdRegex = regexp.MustCompile(`\\newcommand{`)
+
+func ParseFile(filename string) error {
+	b, e := ioutil.ReadFile(filename)
+	if e != nil {
+		return e
+	}
+
+	str := string(b)
+
+	idx := cmdRegex.FindAllStringIndex(str, -1)
+
+	for _, i := range idx {
+		nameStart := i[1]
+		nameStop := strings.Index(str[nameStart:], "}")+nameStart
+		name := str[nameStart:nameStop]
+
+		bodystart := strings.Index(str[nameStop:], "{")+nameStop+1
+		var depth = 0
+		var bodyend = 0
+		for i, r := range str[bodystart:] {
+			s := string([]rune{r})
+			_ = s
+			switch r {
+			case '{':
+				depth++
+			case '}':
+				depth--
+			}
+
+			if depth < 0 {
+				bodyend = bodystart + i
+				break
+			}
+		}
+
+		body := str[bodystart:bodyend]
+
+		toDelet := []string{"}", "{", "[", "]"}
+		argNumStr := str[nameStop:bodystart]
+		for _, d := range toDelet {
+			argNumStr = strings.ReplaceAll(argNumStr, d, "")
+		}
+
+		argNum := 0
+		if strings.TrimSpace(argNumStr) != "" {
+			argNum, e = strconv.Atoi(argNumStr)
+			if e != nil {
+				return e
+			}
+		}
+
+		fi := FunctionImplementation{
+			Name: name,
+			Body: body,
+			ArgNum: argNum,
+		}
+
+		funcs = append(funcs, fi)
+	}
+
+	return nil
+}
+
diff --git a/plab/main.go b/plab/main.go
index 609a012..c7157a1 100644
--- a/plab/main.go
+++ b/plab/main.go
@@ -1,13 +1,14 @@
 package main
 
 import (
+	"git.sch.bme.hu/insert-epic-projlab-team-name-here/tooling/plab/flatten"
 	"git.sch.bme.hu/insert-epic-projlab-team-name-here/tooling/plab/helpers"
 	"git.sch.bme.hu/insert-epic-projlab-team-name-here/tooling/plab/tests"
 	"os"
 )
 
 func main() {
-	mainCmds := helpers.CmdFrom(os.Args[0], "go projlab tool", Timetable, Javadoc, Classdiag, Check, Filelist, tests.TestsToLatex, AllTime)
+	mainCmds := helpers.CmdFrom(os.Args[0], "go projlab tool", Timetable, Javadoc, Classdiag, Check, Filelist, tests.TestsToLatex, flatten.Flatten, AllTime)
 	if len(os.Args) < 2 {
 		os.Args = append(os.Args, "help")
 	}
-- 
GitLab