Initialize Go CLI skeleton
This commit is contained in:
11
cmd/audita/main.go
Normal file
11
cmd/audita/main.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gitea.maximumdirect.net/eric/audita/internal/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
os.Exit(cli.Run(os.Args[1:], os.Stdout, os.Stderr))
|
||||||
|
}
|
||||||
127
internal/cli/run.go
Normal file
127
internal/cli/run.go
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
const processNotImplementedMessage = "process command is not implemented yet"
|
||||||
|
|
||||||
|
// Run executes the Audita CLI with the provided arguments and streams.
|
||||||
|
func Run(args []string, stdout, stderr io.Writer) int {
|
||||||
|
if len(args) == 0 {
|
||||||
|
writeRootUsage(stdout)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if isHelpCommand(args) {
|
||||||
|
writeRootUsage(stdout)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if args[0] == "process" {
|
||||||
|
return runProcess(args[1:], stdout, stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(stderr, "audita: unknown command %q\n\n", args[0])
|
||||||
|
writeRootUsage(stderr)
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func runProcess(args []string, stdout, stderr io.Writer) int {
|
||||||
|
if isHelpCommand(args) || hasHelpFlag(args) {
|
||||||
|
writeProcessUsage(stdout)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fs := flag.NewFlagSet("process", flag.ContinueOnError)
|
||||||
|
fs.SetOutput(stderr)
|
||||||
|
|
||||||
|
glossaryPath := fs.String("glossary", "", "Path to glossary YAML file")
|
||||||
|
outputPath := fs.String("output", "", "Path to corrected transcript JSON output file")
|
||||||
|
reportJSONPath := fs.String("report-json", "", "Path to machine-readable report JSON output file")
|
||||||
|
modules := fs.String("modules", "", "Comma-separated module sequence override")
|
||||||
|
|
||||||
|
_ = glossaryPath
|
||||||
|
_ = outputPath
|
||||||
|
_ = reportJSONPath
|
||||||
|
_ = modules
|
||||||
|
|
||||||
|
if err := fs.Parse(args); err != nil {
|
||||||
|
if errors.Is(err, flag.ErrHelp) {
|
||||||
|
writeProcessUsage(stdout)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
remaining := fs.Args()
|
||||||
|
if len(remaining) != 1 {
|
||||||
|
fmt.Fprintln(stderr, "audita process: expected exactly 1 transcript JSON path argument")
|
||||||
|
fmt.Fprintln(stderr)
|
||||||
|
writeProcessUsage(stderr)
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(stderr, "audita process: %s\n", processNotImplementedMessage)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func isHelpCommand(args []string) bool {
|
||||||
|
if len(args) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(args) == 1 {
|
||||||
|
switch args[0] {
|
||||||
|
case "help", "-h", "--help":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(args) == 2 && args[0] == "help" {
|
||||||
|
switch args[1] {
|
||||||
|
case "process":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasHelpFlag(args []string) bool {
|
||||||
|
for _, arg := range args {
|
||||||
|
if arg == "-h" || arg == "--help" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeRootUsage(w io.Writer) {
|
||||||
|
fmt.Fprintln(w, "Audita is a transcript polishing CLI.")
|
||||||
|
fmt.Fprintln(w)
|
||||||
|
fmt.Fprintln(w, "Usage:")
|
||||||
|
fmt.Fprintln(w, " audita <command> [options]")
|
||||||
|
fmt.Fprintln(w)
|
||||||
|
fmt.Fprintln(w, "Commands:")
|
||||||
|
fmt.Fprintln(w, " process Process a transcript JSON file")
|
||||||
|
fmt.Fprintln(w)
|
||||||
|
fmt.Fprintln(w, "Example:")
|
||||||
|
fmt.Fprintln(w, " audita process transcript.json --glossary glossary.yaml --output corrected.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeProcessUsage(w io.Writer) {
|
||||||
|
fmt.Fprintln(w, "Process a transcript JSON file.")
|
||||||
|
fmt.Fprintln(w)
|
||||||
|
fmt.Fprintln(w, "Usage:")
|
||||||
|
fmt.Fprintln(w, " audita process <transcript.json> [flags]")
|
||||||
|
fmt.Fprintln(w)
|
||||||
|
fmt.Fprintln(w, "Flags:")
|
||||||
|
fmt.Fprintln(w, " --glossary <path> Path to glossary YAML file")
|
||||||
|
fmt.Fprintln(w, " --output <path> Path to corrected transcript JSON output file")
|
||||||
|
fmt.Fprintln(w, " --report-json <path> Path to machine-readable report JSON output file")
|
||||||
|
fmt.Fprintln(w, " --modules <list> Comma-separated module sequence override")
|
||||||
|
fmt.Fprintln(w)
|
||||||
|
fmt.Fprintln(w, "Example:")
|
||||||
|
fmt.Fprintln(w, " audita process transcript.json --glossary glossary.yaml --output corrected.json")
|
||||||
|
}
|
||||||
77
internal/cli/run_test.go
Normal file
77
internal/cli/run_test.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRunRootHelp(t *testing.T) {
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
|
||||||
|
exitCode := Run([]string{"--help"}, &stdout, &stderr)
|
||||||
|
if exitCode != 0 {
|
||||||
|
t.Fatalf("expected exit code 0, got %d", exitCode)
|
||||||
|
}
|
||||||
|
if !strings.Contains(stdout.String(), "audita <command> [options]") {
|
||||||
|
t.Fatalf("expected root usage in stdout, got %q", stdout.String())
|
||||||
|
}
|
||||||
|
if !strings.Contains(stdout.String(), "process") {
|
||||||
|
t.Fatalf("expected process command in root help, got %q", stdout.String())
|
||||||
|
}
|
||||||
|
if stderr.Len() != 0 {
|
||||||
|
t.Fatalf("expected empty stderr, got %q", stderr.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunProcessHelp(t *testing.T) {
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
|
||||||
|
exitCode := Run([]string{"process", "--help"}, &stdout, &stderr)
|
||||||
|
if exitCode != 0 {
|
||||||
|
t.Fatalf("expected exit code 0, got %d", exitCode)
|
||||||
|
}
|
||||||
|
if !strings.Contains(stdout.String(), "audita process <transcript.json> [flags]") {
|
||||||
|
t.Fatalf("expected process usage in stdout, got %q", stdout.String())
|
||||||
|
}
|
||||||
|
if !strings.Contains(stdout.String(), "--glossary") {
|
||||||
|
t.Fatalf("expected glossary flag in process help, got %q", stdout.String())
|
||||||
|
}
|
||||||
|
if stderr.Len() != 0 {
|
||||||
|
t.Fatalf("expected empty stderr, got %q", stderr.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunUnknownCommand(t *testing.T) {
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
|
||||||
|
exitCode := Run([]string{"unknown"}, &stdout, &stderr)
|
||||||
|
if exitCode != 2 {
|
||||||
|
t.Fatalf("expected exit code 2, got %d", exitCode)
|
||||||
|
}
|
||||||
|
if stdout.Len() != 0 {
|
||||||
|
t.Fatalf("expected empty stdout, got %q", stdout.String())
|
||||||
|
}
|
||||||
|
if !strings.Contains(stderr.String(), "unknown command") {
|
||||||
|
t.Fatalf("expected unknown command error in stderr, got %q", stderr.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunProcessNotImplemented(t *testing.T) {
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
|
||||||
|
exitCode := Run([]string{"process", "transcript.json"}, &stdout, &stderr)
|
||||||
|
if exitCode == 0 {
|
||||||
|
t.Fatalf("expected nonzero exit code for not-implemented process")
|
||||||
|
}
|
||||||
|
if stdout.Len() != 0 {
|
||||||
|
t.Fatalf("expected empty stdout, got %q", stdout.String())
|
||||||
|
}
|
||||||
|
if !strings.Contains(stderr.String(), processNotImplementedMessage) {
|
||||||
|
t.Fatalf("expected not-implemented message in stderr, got %q", stderr.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user