all repos

clerk @ a65ac05

missing tooling for ledger/hledger

clerk/internal/cli/cmd_lint.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
change cli frameworks, 1 month ago
1
package cli
2
3
import (
4
	"context"
5
	"fmt"
6
	"os"
7
	"strings"
8
9
	"github.com/urfave/cli/v3"
10
11
	"olexsmir.xyz/clerk/internal/linter"
12
	"olexsmir.xyz/clerk/journal"
13
	"olexsmir.xyz/clerk/journal/semantic"
14
)
15
16
func (c *Cli) lintAction(ctx context.Context, cmd *cli.Command) error {
17
	format := cmd.String("format")
18
	pathStyle := cmd.String("path-style")
19
20
	lint := linter.NewLinter(linter.Rules)
21
	reporter := linter.NewReporter(os.Stdout, parsePathStyle(pathStyle))
22
23
	journals := cmd.StringArgs("journals")
24
	if len(journals) == 0 {
25
		return c.lintStdin(lint, reporter, format)
26
	}
27
28
	journalFiles, err := resolvePaths(journals)
29
	if err != nil {
30
		return err
31
	}
32
	if len(journalFiles) == 0 {
33
		return nil
34
	}
35
36
	loader := journal.NewLoader()
37
38
	var errs []error
39
	for _, f := range journalFiles {
40
		if _, err := loadFile(loader, f); err != nil {
41
			fmt.Fprintf(os.Stderr, "error: %v\n", err)
42
			errs = append(errs, err)
43
		}
44
	}
45
46
	sema := semantic.Build(loader.Ordered())
47
	reporter.Collect(lint.Run(sema))
48
49
	if err := reporter.Flush(format); err != nil {
50
		return fmt.Errorf("flushing report: %w", err)
51
	}
52
53
	if reporter.HasIssues() || len(errs) > 0 {
54
		return fmt.Errorf("lint found issues")
55
	}
56
	return nil
57
}
58
59
func (c *Cli) lintStdin(lint *linter.Linter, reporter *linter.Reporter, format string) error {
60
	loader := journal.NewLoader()
61
	if _, err := loadStdin(loader); err != nil {
62
		return err
63
	}
64
65
	sema := semantic.Build(loader.Ordered())
66
	reporter.Collect(lint.Run(sema))
67
68
	if err := reporter.Flush(format); err != nil {
69
		return fmt.Errorf("flushing report: %w", err)
70
	}
71
	if reporter.HasIssues() {
72
		return fmt.Errorf("lint found issues")
73
	}
74
	return nil
75
}
76
77
func parsePathStyle(s string) linter.PathStyle {
78
	switch strings.ToLower(s) {
79
	case "basename":
80
		return linter.PathBasename
81
	case "absolute":
82
		return linter.PathAbsolute
83
	default:
84
		return linter.PathRelative
85
	}
86
}