-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
116 lines (100 loc) · 3.2 KB
/
main.go
File metadata and controls
116 lines (100 loc) · 3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package main
import (
"flag"
"fmt"
"io"
"log"
"os"
"github.com/verkaro/editml-go"
)
// AppVersion holds the version of the utility.
const AppVersion = "1.0.0"
// run contains the core processing logic for the application.
// It takes the raw input text, processes it through the EditML library,
// and returns the clean text and any issues encountered.
func run(inputText string) (cleanText string, allIssues []editml.Issue) {
nodes, parseIssues := editml.Parse(inputText)
// Even if parsing has issues, we attempt to transform to see if we get more issues or partial output.
cleanText, transformIssues := editml.TransformCleanView(nodes)
allIssues = append(parseIssues, transformIssues...)
return cleanText, allIssues
}
// main handles command-line parsing, I/O, and coordinating the call to the
// core run function. It is responsible for exit codes and printing issues.
func main() {
// --- 1. Flag Definition & Parsing ---
versionFlag := flag.Bool("version", false, "Print version and exit.")
outputFlag := flag.String("o", "", "Write output to the specified file instead of stdout. (shorthand)")
outputFlagLong := flag.String("output", "", "Write output to the specified file instead of stdout.")
debugFlag := flag.Bool("debug", false, "Emit parse/transform issues (warnings/errors) to stderr.")
strictFlag := flag.Bool("strict", false, "Treat warnings as errors (exit non-zero on any issue).")
flag.Parse()
if *versionFlag {
fmt.Println("editml-clean version", AppVersion)
os.Exit(0)
}
// --- 2. Input Handling ---
var inputReader io.Reader = os.Stdin
var err error
if flag.NArg() > 0 {
inputFilename := flag.Arg(0)
file, err := os.Open(inputFilename)
if err != nil {
log.Fatalf("Fatal: could not open input file %s: %v", inputFilename, err)
}
defer file.Close()
inputReader = file
}
inputBytes, err := io.ReadAll(inputReader)
if err != nil {
log.Fatalf("Fatal: could not read input: %v", err)
}
inputText := string(inputBytes)
// --- 3. Core Processing ---
cleanText, allIssues := run(inputText)
// --- 4. Issue and Error Handling ---
hasError := false
hasWarning := false
if len(allIssues) > 0 {
for _, issue := range allIssues {
if issue.Severity == editml.SeverityError {
hasError = true
} else {
hasWarning = true
}
if *debugFlag {
severityStr := "Warning"
if issue.Severity == editml.SeverityError {
severityStr = "Error"
}
fmt.Fprintf(os.Stderr, "[%s] %s (L%d:C%d)\n", severityStr, issue.Message, issue.Line, issue.Column)
}
}
}
// --- 5. Exit Code and Output Logic ---
if hasError {
os.Exit(1)
}
if hasWarning && *strictFlag {
os.Exit(2)
}
var outputWriter io.Writer = os.Stdout
outputPath := *outputFlag
if *outputFlagLong != "" {
outputPath = *outputFlagLong
}
if outputPath != "" {
file, err := os.Create(outputPath)
if err != nil {
log.Fatalf("Fatal: could not create output file %s: %v", outputPath, err)
}
defer file.Close()
outputWriter = file
}
// FIX: Use fmt.Fprintln to ensure the output always ends with a newline,
// which is standard convention for command-line tools.
_, err = fmt.Fprintln(outputWriter, cleanText)
if err != nil {
log.Fatalf("Fatal: could not write to output: %v", err)
}
}