feat: input and output file

This commit is contained in:
Justin Lin committed 2025-07-25 02:30:09 +10:00
1 parent 12dcbb460c
commit 3eae45479b
6 files changed
+64 -18

No files matched your search

+25 -3
View File
@@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"log" "log"
"os"
) )
var tmpl = ` var tmpl = `
@@ -19,19 +20,40 @@ Start from {{ .from }}
{{ sh "hledger bal assets -b $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() { func main() {
tmpl := loadTemplate()
frontmatter, body, err := parseDocument(tmpl) frontmatter, body, err := parseDocument(tmpl)
if err != nil { if err != nil {
panic(err) log.Fatal(err)
} }
templateMeta, err := parseFrontmatter(frontmatter) templateMeta, err := parseFrontmatter(frontmatter)
if err != nil { if err != nil {
panic(err) log.Fatal(err)
} }
fmt.Println(templateMeta) fmt.Println(templateMeta)
ctx, err := parseParams(templateMeta) ctx, err := parseParams(templateMeta)
if err != nil { if err != nil {
log.Fatal(err) 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)
}
} }
+7 -7
View File
@@ -1,5 +1,5 @@
--- ---
name: "reports/${from}.md" output: "reports_{{.from}}.md"
params: params:
from: from:
required: true required: true
@@ -9,24 +9,24 @@ params:
default: ~/.hledger.journal default: ~/.hledger.journal
--- ---
# Finance Report from {from} to {to} # Finance Report from {{.from}} to {{.to}}
## Previous status: ## Previous status:
{{hledger -f $file balancesheet -e $from }} {{ sh "hledger -f $file balancesheet -e $from" }}
## Expenses: ## Expenses:
### Expense Summary by Category ### 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: ## Net Income:
{{hledger -f $file income -b $from -e $to --monthly}} {{sh "hledger -f $file income -b $from -e $to --monthly"}}
## Ending balance: ## Ending balance:
{{hledger -f $file balancesheet -e $to}} {{sh "hledger -f $file balancesheet -e $to"}}
+4 -2
View File
@@ -3,14 +3,16 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"os"
) )
func parseParams(meta TemplateMeta) (ctx TemplateContext, err error) { func parseParams(meta TemplateMeta) (ctx TemplateContext, err error) {
result := make(map[string]*string) result := make(map[string]*string)
fs := flag.NewFlagSet("params", flag.ExitOnError)
for key, spec := range meta.Params { 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) ctx = make(TemplateContext)
for key, spec := range meta.Params { for key, spec := range meta.Params {
if spec.Required && *result[key] == "" { if spec.Required && *result[key] == "" {
+1 -1
View File
@@ -29,6 +29,6 @@ func parseDocument(doc string) (frontmatter string, body string, err error) {
return return
} }
frontmatter = parts[1] frontmatter = parts[1]
body = parts[2] body = strings.TrimLeft(parts[2], "\n ")
return return
} }
+8 -4
View File
@@ -1,8 +1,8 @@
package main package main
import ( import (
"bytes"
"fmt" "fmt"
"os"
"os/exec" "os/exec"
"text/template" "text/template"
) )
@@ -13,7 +13,6 @@ func sh(ctx TemplateContext) func(string) string {
for k, v := range ctx { for k, v := range ctx {
cmd.Env = append(cmd.Env, k+"="+v) cmd.Env = append(cmd.Env, k+"="+v)
} }
fmt.Println(cmd.Environ())
out, err := cmd.Output() out, err := cmd.Output()
if err != nil { if err != nil {
return fmt.Sprintf("> Failed to execute the command: %s\n> %s\n", cmd.Args, err.Error()) 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{ funcMap := template.FuncMap{
"sh": sh(ctx), "sh": sh(ctx),
} }
@@ -30,5 +29,10 @@ func render(tmpl string, ctx TemplateContext) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
t.Execute(os.Stdout, ctx) var buf bytes.Buffer
err = t.Execute(&buf, ctx)
if err != nil {
panic(err)
}
return buf.Bytes()
} }
+19 -1
View File
@@ -1,6 +1,11 @@
package main package main
import "encoding/json" import (
"bytes"
"encoding/json"
"fmt"
"text/template"
)
type TemplateMeta struct { type TemplateMeta struct {
Output string `yaml:"output"` Output string `yaml:"output"`
@@ -15,6 +20,19 @@ func (meta TemplateMeta) String() string {
return string(data) 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 { type ParamSpec struct {
Required bool `yaml:"required"` Required bool `yaml:"required"`
Default string `yaml:"default"` Default string `yaml:"default"`