mirror of
https://github.com/lancatlin/mdsh.git
synced 2026-11-05 19:30:12 +08:00
feat: add inline and block runner. Improve execution error handling
This commit is contained in:
1 parent
8f764548b9
commit
a2c99c710e
6 files changed
+218
-63
No files matched your search
@@ -0,0 +1,72 @@
|
|||||||
|
; -*- ledger -*-
|
||||||
|
; This example file retrived from ledger-cli.org example journal file
|
||||||
|
; https://ledger-cli.org/doc/ledger3.html#Example-Journal-File
|
||||||
|
|
||||||
|
= /^Income/
|
||||||
|
(Liabilities:Tithe) 0.12
|
||||||
|
|
||||||
|
~ Monthly
|
||||||
|
Assets:Checking $500.00
|
||||||
|
Income:Salary
|
||||||
|
|
||||||
|
~ Monthly
|
||||||
|
Expenses:Food $100
|
||||||
|
Assets
|
||||||
|
|
||||||
|
2010/12/01 * Checking balance
|
||||||
|
Assets:Checking $1,000.00
|
||||||
|
Equity:Opening Balances
|
||||||
|
|
||||||
|
2010/12/20 * Organic Co-op
|
||||||
|
Expenses:Food:Groceries $ 37.50 ; [=2011/01/01]
|
||||||
|
Expenses:Food:Groceries $ 37.50 ; [=2011/02/01]
|
||||||
|
Expenses:Food:Groceries $ 37.50 ; [=2011/03/01]
|
||||||
|
Expenses:Food:Groceries $ 37.50 ; [=2011/04/01]
|
||||||
|
Expenses:Food:Groceries $ 37.50 ; [=2011/05/01]
|
||||||
|
Expenses:Food:Groceries $ 37.50 ; [=2011/06/01]
|
||||||
|
Assets:Checking $ -225.00
|
||||||
|
|
||||||
|
2010/12/28=2011/01/01 Acme Mortgage
|
||||||
|
Liabilities:Mortgage:Principal $ 200.00
|
||||||
|
Expenses:Interest:Mortgage $ 500.00
|
||||||
|
Expenses:Escrow $ 300.00
|
||||||
|
Assets:Checking $ -1000.00
|
||||||
|
|
||||||
|
2011/01/02 Grocery Store
|
||||||
|
Expenses:Food:Groceries $ 65.00
|
||||||
|
Assets:Checking
|
||||||
|
|
||||||
|
2011/01/05 Employer
|
||||||
|
Assets:Checking $ 2000.00
|
||||||
|
Income:Salary
|
||||||
|
|
||||||
|
2011/01/14 Bank
|
||||||
|
; Regular monthly savings transfer
|
||||||
|
Assets:Savings $ 300.00
|
||||||
|
Assets:Checking
|
||||||
|
|
||||||
|
2011/01/19 Grocery Store
|
||||||
|
Expenses:Food:Groceries $ 44.00 ; hastag: not block
|
||||||
|
Assets:Checking
|
||||||
|
|
||||||
|
2011/01/25 Bank
|
||||||
|
; Transfer to cover car purchase
|
||||||
|
Assets:Checking $ 5,500.00
|
||||||
|
Assets:Savings
|
||||||
|
; :nobudget:
|
||||||
|
|
||||||
|
apply tag hastag: true
|
||||||
|
apply tag nestedtag: true
|
||||||
|
2011/01/25 Tom's Used Cars
|
||||||
|
Expenses:Auto $ 5,500.00
|
||||||
|
; :nobudget:
|
||||||
|
Assets:Checking
|
||||||
|
|
||||||
|
2011/01/27 Book Store
|
||||||
|
Expenses:Books $20.00
|
||||||
|
Liabilities:MasterCard
|
||||||
|
end tag
|
||||||
|
2011/12/01 Sale
|
||||||
|
Assets:Checking:Business $ 30.00
|
||||||
|
Income:Sales
|
||||||
|
end tag
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
# Finance Report from 2011-01 to 2011-02
|
||||||
|
|
||||||
|
## Previous status:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
Balance Sheet 2010-12-31
|
||||||
|
|
||||||
|
|| 2010-12-31
|
||||||
|
================================++============
|
||||||
|
Assets ||
|
||||||
|
--------------------------------++------------
|
||||||
|
Assets:Checking || $-225.00
|
||||||
|
--------------------------------++------------
|
||||||
|
|| $-225.00
|
||||||
|
================================++============
|
||||||
|
Liabilities ||
|
||||||
|
--------------------------------++------------
|
||||||
|
Liabilities:Mortgage:Principal || $-200.00
|
||||||
|
--------------------------------++------------
|
||||||
|
|| $-200.00
|
||||||
|
================================++============
|
||||||
|
Net: || $-25.00
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Expenses:
|
||||||
|
|
||||||
|
### Expense Summary by Category
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
Budget performance in 2011-01:
|
||||||
|
|
||||||
|
|| Jan
|
||||||
|
===============++==============================
|
||||||
|
Expenses || $5,629.00
|
||||||
|
Expenses:Food || $109.00 [ 109% of $100.00]
|
||||||
|
---------------++------------------------------
|
||||||
|
|| $5,629.00 [5629% of $100.00]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
$5,500.00 Expenses:Auto
|
||||||
|
$109.00 Expenses:Food
|
||||||
|
$20.00 Expenses:Books
|
||||||
|
--------------------
|
||||||
|
$5,629.00
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Net Income:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
Income Statement 2011-01
|
||||||
|
|
||||||
|
|| Jan
|
||||||
|
=========================++============
|
||||||
|
Revenues ||
|
||||||
|
-------------------------++------------
|
||||||
|
Income:Salary || $2,000.00
|
||||||
|
-------------------------++------------
|
||||||
|
|| $2,000.00
|
||||||
|
=========================++============
|
||||||
|
Expenses ||
|
||||||
|
-------------------------++------------
|
||||||
|
Expenses:Auto || $5,500.00
|
||||||
|
Expenses:Books || $20.00
|
||||||
|
Expenses:Food:Groceries || $109.00
|
||||||
|
-------------------------++------------
|
||||||
|
|| $5,629.00
|
||||||
|
=========================++============
|
||||||
|
Net: || $-3,629.00
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Ending balance:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
Balance Sheet 2011-01-31
|
||||||
|
|
||||||
|
|| 2011-01-31
|
||||||
|
================================++============
|
||||||
|
Assets ||
|
||||||
|
--------------------------------++------------
|
||||||
|
Assets:Checking || $1,366.00
|
||||||
|
Assets:Savings || $-5,200.00
|
||||||
|
--------------------------------++------------
|
||||||
|
|| $-3,834.00
|
||||||
|
================================++============
|
||||||
|
Liabilities ||
|
||||||
|
--------------------------------++------------
|
||||||
|
Liabilities:MasterCard || $20.00
|
||||||
|
Liabilities:Mortgage:Principal || $-200.00
|
||||||
|
--------------------------------++------------
|
||||||
|
|| $-180.00
|
||||||
|
================================++============
|
||||||
|
Net: || $-3,654.00
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
-45
@@ -1,45 +0,0 @@
|
|||||||
---
|
|
||||||
output: "reports_{{.b}}.md"
|
|
||||||
params:
|
|
||||||
b:
|
|
||||||
required: true
|
|
||||||
usage: |
|
|
||||||
Required.
|
|
||||||
The begin time of report.
|
|
||||||
Examples:
|
|
||||||
2025
|
|
||||||
2025-07
|
|
||||||
2025-07-15
|
|
||||||
Jul
|
|
||||||
e:
|
|
||||||
required: true
|
|
||||||
usage: |
|
|
||||||
Required.
|
|
||||||
The end time of report.
|
|
||||||
Same format as -b
|
|
||||||
f:
|
|
||||||
default: ~/.hledger.journal
|
|
||||||
usage: The ledger file to parse
|
|
||||||
---
|
|
||||||
|
|
||||||
# Finance Report from {{.b}} to {{.e}}
|
|
||||||
|
|
||||||
## Previous status:
|
|
||||||
|
|
||||||
{{ sh "hledger -f $f balancesheet -e $b" }}
|
|
||||||
|
|
||||||
## Expenses:
|
|
||||||
|
|
||||||
### Expense Summary by Category
|
|
||||||
|
|
||||||
{{ sh "hledger -f $f bal expenses -b $b -e $e --depth 3 --sort amount" }}
|
|
||||||
|
|
||||||
{{ sh "hledger -f $f bal expenses -b $b -e $e --depth 2 --sort amount" }}
|
|
||||||
|
|
||||||
## Net Income:
|
|
||||||
|
|
||||||
{{sh "hledger -f $f income -b $b -e $e --monthly"}}
|
|
||||||
|
|
||||||
## Ending balance:
|
|
||||||
|
|
||||||
{{sh "hledger -f $f balancesheet -e $e"}}
|
|
||||||
@@ -23,7 +23,7 @@ func parseDocument(doc string) (frontmatter string, body string, err error) {
|
|||||||
err = fmt.Errorf("Invalid document: frontmatter required.\n%s", doc)
|
err = fmt.Errorf("Invalid document: frontmatter required.\n%s", doc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
parts := strings.Split(doc, sep)
|
parts := strings.SplitN(doc, sep, 3)
|
||||||
if len(parts) < 3 {
|
if len(parts) < 3 {
|
||||||
err = fmt.Errorf("Invalid document: frontmatter required.\n%s", doc)
|
err = fmt.Errorf("Invalid document: frontmatter required.\n%s", doc)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -2,28 +2,13 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"os/exec"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
func sh(ctx TemplateContext) func(string) string {
|
|
||||||
return func(command string) string {
|
|
||||||
cmd := exec.Command("sh", "-c", command)
|
|
||||||
for k, v := range ctx {
|
|
||||||
cmd.Env = append(cmd.Env, k+"="+v)
|
|
||||||
}
|
|
||||||
out, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Sprintf("> Failed to execute the command: %s\n> %s\n", cmd.Args, err.Error())
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("\n```\n%s\n```\n", string(out))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func render(tmpl string, ctx TemplateContext) []byte {
|
func render(tmpl string, ctx TemplateContext) []byte {
|
||||||
funcMap := template.FuncMap{
|
funcMap := template.FuncMap{
|
||||||
"sh": sh(ctx),
|
"sh": ctx.inline,
|
||||||
|
"shell": ctx.codeBlock,
|
||||||
}
|
}
|
||||||
t, err := template.New("foo").Funcs(funcMap).Parse(tmpl)
|
t, err := template.New("foo").Funcs(funcMap).Parse(tmpl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,3 +43,34 @@ type ParamSpec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TemplateContext map[string]string
|
type TemplateContext map[string]string
|
||||||
|
|
||||||
|
func (ctx TemplateContext) run(command string) (string, error) {
|
||||||
|
cmd := exec.Command("sh", "-c", command)
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
cmd.Stderr = &stdout
|
||||||
|
for k, v := range ctx {
|
||||||
|
cmd.Env = append(cmd.Env, k+"="+v)
|
||||||
|
}
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.New(stdout.String())
|
||||||
|
}
|
||||||
|
return stdout.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx TemplateContext) codeBlock(command string) string {
|
||||||
|
out, err := ctx.run(command)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("> Failed to execute the command:\n> `%s`\n> %s\n", command, err.Error())
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("\n```\n%s\n```\n", out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx TemplateContext) inline(command string) string {
|
||||||
|
out, err := ctx.run(command)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("`Failed to execute the command: '%s'. %s`", command, err.Error())
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("`%s`", strings.Trim(out, "\n "))
|
||||||
|
}
|
||||||
Reference in new issue
Block a user