From 3eae45479b724dfe4da300b2b6c2cd7c715a4b15 Mon Sep 17 00:00:00 2001 From: Justin Lin Date: Fri, 25 Jul 2025 02:30:09 +1000 Subject: [PATCH] feat: input and output file --- main.go | 28 +++++++++++++++++++++++++--- monthly.md | 14 +++++++------- params.go | 6 ++++-- parse.go | 2 +- render.go | 12 ++++++++---- types.go | 20 +++++++++++++++++++- 6 files changed, 64 insertions(+), 18 deletions(-) diff --git a/main.go b/main.go index c72ee05..a501fd9 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "log" + "os" ) var tmpl = ` @@ -19,19 +20,40 @@ Start from {{ .from }} {{ sh "hledger bal assets -b $from" }} ` +func loadTemplate() string { + if len(os.Args) < 2 { + log.Fatal("Please input a markdown template file") + } + filename := os.Args[1] + dat, err := os.ReadFile(filename) + if err != nil { + log.Fatal("Failed to open the file", err) + } + return string(dat) +} + func main() { + tmpl := loadTemplate() frontmatter, body, err := parseDocument(tmpl) if err != nil { - panic(err) + log.Fatal(err) } templateMeta, err := parseFrontmatter(frontmatter) if err != nil { - panic(err) + log.Fatal(err) } fmt.Println(templateMeta) ctx, err := parseParams(templateMeta) if err != nil { log.Fatal(err) } - render(body, ctx) + data := render(body, ctx) + output, err := templateMeta.OutputFile(ctx) + if err != nil { + panic(err) + } + err = os.WriteFile(output, data, 0644) + if err != nil { + panic(err) + } } diff --git a/monthly.md b/monthly.md index 1b926b4..db3cdd4 100644 --- a/monthly.md +++ b/monthly.md @@ -1,5 +1,5 @@ --- -name: "reports/${from}.md" +output: "reports_{{.from}}.md" params: from: required: true @@ -9,24 +9,24 @@ params: default: ~/.hledger.journal --- -# Finance Report from {from} to {to} +# Finance Report from {{.from}} to {{.to}} ## Previous status: -{{hledger -f $file balancesheet -e $from }} +{{ sh "hledger -f $file balancesheet -e $from" }} ## Expenses: ### Expense Summary by Category -{{hledger -f $file bal expenses -b $from -e $to --depth 3 --sort amount}} +{{ sh "hledger -f $file bal expenses -b $from -e $to --depth 3 --sort amount" }} -{{hledger -f $file bal expenses -b $from -e $to --depth 2 --sort amount}} +{{ sh "hledger -f $file bal expenses -b $from -e $to --depth 2 --sort amount" }} ## Net Income: -{{hledger -f $file income -b $from -e $to --monthly}} +{{sh "hledger -f $file income -b $from -e $to --monthly"}} ## Ending balance: -{{hledger -f $file balancesheet -e $to}} +{{sh "hledger -f $file balancesheet -e $to"}} diff --git a/params.go b/params.go index 65e4a36..b3bbcee 100644 --- a/params.go +++ b/params.go @@ -3,14 +3,16 @@ package main import ( "flag" "fmt" + "os" ) func parseParams(meta TemplateMeta) (ctx TemplateContext, err error) { result := make(map[string]*string) + fs := flag.NewFlagSet("params", flag.ExitOnError) for key, spec := range meta.Params { - result[key] = flag.String(key, spec.Default, key) + result[key] = fs.String(key, spec.Default, key) } - flag.Parse() + fs.Parse(os.Args[2:]) ctx = make(TemplateContext) for key, spec := range meta.Params { if spec.Required && *result[key] == "" { diff --git a/parse.go b/parse.go index eeedd36..12fbd70 100644 --- a/parse.go +++ b/parse.go @@ -29,6 +29,6 @@ func parseDocument(doc string) (frontmatter string, body string, err error) { return } frontmatter = parts[1] - body = parts[2] + body = strings.TrimLeft(parts[2], "\n ") return } diff --git a/render.go b/render.go index 644d124..18ed0e3 100644 --- a/render.go +++ b/render.go @@ -1,8 +1,8 @@ package main import ( + "bytes" "fmt" - "os" "os/exec" "text/template" ) @@ -13,7 +13,6 @@ func sh(ctx TemplateContext) func(string) string { for k, v := range ctx { cmd.Env = append(cmd.Env, k+"="+v) } - fmt.Println(cmd.Environ()) out, err := cmd.Output() if err != nil { return fmt.Sprintf("> Failed to execute the command: %s\n> %s\n", cmd.Args, err.Error()) @@ -22,7 +21,7 @@ func sh(ctx TemplateContext) func(string) string { } } -func render(tmpl string, ctx TemplateContext) { +func render(tmpl string, ctx TemplateContext) []byte { funcMap := template.FuncMap{ "sh": sh(ctx), } @@ -30,5 +29,10 @@ func render(tmpl string, ctx TemplateContext) { if err != nil { panic(err) } - t.Execute(os.Stdout, ctx) + var buf bytes.Buffer + err = t.Execute(&buf, ctx) + if err != nil { + panic(err) + } + return buf.Bytes() } diff --git a/types.go b/types.go index 9a2ebeb..0eadc74 100644 --- a/types.go +++ b/types.go @@ -1,6 +1,11 @@ package main -import "encoding/json" +import ( + "bytes" + "encoding/json" + "fmt" + "text/template" +) type TemplateMeta struct { Output string `yaml:"output"` @@ -15,6 +20,19 @@ func (meta TemplateMeta) String() string { return string(data) } +func (meta TemplateMeta) OutputFile(ctx TemplateContext) (output string, err error) { + tmpl, err := template.New("output").Parse(meta.Output) + if err != nil { + return "", fmt.Errorf("Failed to parse output name: %w", err) + } + var buf bytes.Buffer + err = tmpl.Execute(&buf, ctx) + if err != nil { + return "", fmt.Errorf("Failed to execute output name: %w", err) + } + return buf.String(), nil +} + type ParamSpec struct { Required bool `yaml:"required"` Default string `yaml:"default"`