From a21602a450217333a27419d8168865b21fae6e7e Mon Sep 17 00:00:00 2001 From: Gabriel Arakaki Giovanini Date: Sun, 3 Sep 2023 16:01:20 +0200 Subject: feat: Add option for inputing template Now a template file is required to run the cli command. That gives the user an option to provide its own template file. An default will be provided later. --- example.txt | 8 +++ main.go | 18 ++++--- parser.go | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ parser/parser.go | 94 ------------------------------------ template.go | 44 +++++++++++++++++ 5 files changed, 207 insertions(+), 102 deletions(-) create mode 100644 example.txt create mode 100644 parser.go delete mode 100644 parser/parser.go create mode 100644 template.go diff --git a/example.txt b/example.txt new file mode 100644 index 0000000..8c5c0eb --- /dev/null +++ b/example.txt @@ -0,0 +1,8 @@ +# Apks Alpine 3.18 + +{{ range $e := . }} +## {{ $e.Name }} + +{{ range $name, $value := ($e.Properties) }}- **{{$name}}**: {{ $value }} +{{ end }} +{{ end }} diff --git a/main.go b/main.go index fe3c34f..314ecc8 100644 --- a/main.go +++ b/main.go @@ -5,19 +5,18 @@ import ( "bufio" "compress/gzip" "errors" - "fmt" "io" "net/http" "os" - "git.sr.ht/~gabrielgio/apkdoc/parser" flag "github.com/spf13/pflag" ) func main() { url := flag.StringP("url", "u", "", "Url to the APKINDEX.tar.gz") output := flag.StringP("output", "o", "index.md", "Output path") - repositoryFormat := flag.StringP("repository-format", "f", "https://git.sr.ht/~gabrielgio/apkbuilds/tree/%s/item/apks/%s", "Template to build repository link") + templateType := flag.StringP("template-type", "p", "text", "Template system to be used, options: html, text") + templateFile := flag.StringP("template-file", "t", "text", "Template file to be used") flag.Parse() tarStream, err := fechIndex(*url) @@ -47,13 +46,13 @@ func main() { s := bufio.NewScanner(tr) - entries := make([]*parser.Entry, 0) + entries := make([]*Entry, 0) lines := make([]string, 0) for s.Scan() { l := s.Text() if l == "" { - entry := parser.Parse(lines) + entry := Parse(lines) entries = append(entries, entry) lines = make([]string, 0) } else { @@ -66,13 +65,16 @@ func main() { panic("Error openning output file: " + err.Error()) } - for _, e := range entries { - fmt.Fprintln(outputFile, e.FomartLink(*repositoryFormat)) + tmpl, err := GetTemplate(*templateType, *templateFile) + if err != nil { + panic("Error loading template file: " + err.Error()) } + + tmpl.Execute(outputFile, entries) } func getOutputFile(output string) (*os.File, error) { - if output == "" { + if output != "" { outputFile, err := os.Create(output) if err != nil { return nil, err diff --git a/parser.go b/parser.go new file mode 100644 index 0000000..344efca --- /dev/null +++ b/parser.go @@ -0,0 +1,145 @@ +package main + +import ( + "fmt" + "strconv" + "strings" + "time" +) + +type ( + // https://wiki.alpinelinux.org/wiki/Apk_spec + Entry struct { + Checksum string // C + Version string // V + Name string // P + Architecture *string // A + PackageSize int // S + InstalledSize int // I + Description string // T + Url string // U + License string // L + Origin *string // o + Maintainer *string // m + BuildTime *time.Time // t + Commit *string // c + ProviderPriority *int // k + Dependencies []string // D + Provides []string // p + InstallIf []string // i + } +) + +func (e *Entry) FomartLink(format string) string { + c := strings.Replace(*e.Commit, "-dirty", "", -1) + return fmt.Sprintf(format, c, *e.Origin) +} + +func (e *Entry) Properties() map[string]string { + p := make(map[string]string) + + p["checksum"] = e.Checksum + p["version"] = e.Version + p["name"] = e.Name + p["package size"] = strconv.Itoa(e.PackageSize) + p["installed size"] = strconv.Itoa(e.InstalledSize) + p["description"] = e.Description + p["url"] = e.Url + p["license"] = e.License + + if e.Architecture != nil { + p["architecture"] = *e.Architecture + } + + if e.Origin != nil { + p["origin"] = *e.Origin + } + + if e.Maintainer != nil { + p["maintainer"] = *e.Maintainer + } + + if e.BuildTime != nil { + p["build time"] = e.BuildTime.String() + } + + if e.Commit != nil { + p["commit"] = *e.Commit + } + + if e.ProviderPriority != nil { + p["provider priority"] = strconv.Itoa(*e.ProviderPriority) + } + + if len(e.Dependencies) > 0 { + p["dependencies"] = strings.Join(e.Dependencies, " ") + } + + if len(e.Provides) > 0 { + p["provides"] = strings.Join(e.Provides, " ") + } + + if len(e.InstallIf) > 0 { + p["install if"] = strings.Join(e.InstallIf, " ") + } + + return p +} + +func ptr[T any](v T) *T { + return &v +} + +func split(line string) (string, string) { + parts := strings.SplitN(line, ":", 2) + return parts[0], parts[1] +} + +func toInt(v string) int { + i, _ := strconv.Atoi(v) + return i +} + +func Parse(lines []string) *Entry { + entry := &Entry{} + for _, line := range lines { + r, c := split(line) + switch r { + case "C": + entry.Checksum = c + case "V": + entry.Version = c + case "P": + entry.Name = c + case "A": + entry.Architecture = &c + case "S": + entry.PackageSize = toInt(c) + case "I": + entry.InstalledSize = toInt(c) + case "T": + entry.Description = c + case "U": + entry.Url = c + case "L": + entry.License = c + case "o": + entry.Origin = &c + case "m": + entry.Maintainer = &c + case "t": + entry.BuildTime = ptr(time.Unix(int64(toInt(c)), 0)) + case "c": + entry.Commit = &c + case "k": + entry.ProviderPriority = ptr(toInt(c)) + case "D": + entry.Dependencies = strings.Split(c, " ") + case "p": + entry.Dependencies = strings.Split(c, " ") + case "i": + entry.Dependencies = strings.Split(c, " ") + } + } + return entry +} diff --git a/parser/parser.go b/parser/parser.go deleted file mode 100644 index 62b0d85..0000000 --- a/parser/parser.go +++ /dev/null @@ -1,94 +0,0 @@ -package parser - -import ( - "fmt" - "strconv" - "strings" - "time" -) - -type ( - // https://wiki.alpinelinux.org/wiki/Apk_spec - Entry struct { - Checksum string // C - Version string // V - Name string // P - Architecture *string // A - PackageSize int // S - InstalledSize int // I - Description string // T - Url string // U - License string // L - Origin *string // o - Maintainer *string // m - BuildTime *time.Time // t - Commit *string // c - ProviderPriority *int // k - Dependencies []string // D - Provides []string // p - InstallIf []string // i - } -) - -func (e *Entry) FomartLink(format string) string { - c := strings.Replace(*e.Commit, "-dirty", "", -1) - return fmt.Sprintf(format, c, *e.Origin) -} - -func ptr[T any](v T) *T { - return &v -} - -func split(line string) (string, string) { - parts := strings.SplitN(line, ":", 2) - return parts[0], parts[1] -} - -func toInt(v string) int { - i, _ := strconv.Atoi(v) - return i -} - -func Parse(lines []string) *Entry { - entry := &Entry{} - for _, line := range lines { - r, c := split(line) - switch r { - case "C": - entry.Checksum = c - case "V": - entry.Version = c - case "P": - entry.Name = c - case "A": - entry.Architecture = &c - case "S": - entry.PackageSize = toInt(c) - case "I": - entry.InstalledSize = toInt(c) - case "T": - entry.Description = c - case "U": - entry.Url = c - case "L": - entry.License = c - case "o": - entry.Origin = &c - case "m": - entry.Maintainer = &c - case "t": - entry.BuildTime = ptr(time.Unix(int64(toInt(c)), 0)) - case "c": - entry.Commit = &c - case "k": - entry.ProviderPriority = ptr(toInt(c)) - case "D": - entry.Dependencies = strings.Split(c, " ") - case "p": - entry.Dependencies = strings.Split(c, " ") - case "i": - entry.Dependencies = strings.Split(c, " ") - } - } - return entry -} diff --git a/template.go b/template.go new file mode 100644 index 0000000..503af64 --- /dev/null +++ b/template.go @@ -0,0 +1,44 @@ +package main + +import ( + html "html/template" + "io" + "os" + text "text/template" +) + +type Templater interface { + Execute(wr io.Writer, data any) error +} + +var ( + templateFunc = map[string]any{ + "DerefI": func(i *int) int { return *i }, + "DerefS": func(i *string) string { return *i }, + } +) + +func GetTemplate(templateType, filePath string) (Templater, error) { + file, err := os.Open(filePath) + if err != nil { + return nil, err + } + + tmpl, err := io.ReadAll(file) + if err != nil { + return nil, err + } + + switch templateType { + case "text": + return text.New("text"). + Funcs(templateFunc). + Parse(string(tmpl)) + case "html": + return html.New("html"). + Funcs(templateFunc). + Parse(string(tmpl)) + default: + panic("Invalid template-type") + } +} -- cgit v1.2.3