From 2e3833dd30fafdc270e8d80a78af9116571dc247 Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Thu, 27 Aug 2026 13:49:00 +0200 Subject: Use subcommand args instead of flags for CLI --- cli/cli.go | 68 ++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 19 deletions(-) (limited to 'cli/cli.go') diff --git a/cli/cli.go b/cli/cli.go index 1fdb866..c71fd9e 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -4,7 +4,6 @@ import ( "context" "database/sql" "errors" - "flag" "fmt" "log/slog" "math" @@ -21,23 +20,26 @@ import ( "github.com/schollz/progressbar/v3" ) -var ( - fetchOSM = flag.Bool("fetch-osm", false, "download the France OSM PBF (resumable) into france-latest.osm.pbf") - extractOSM = flag.String("extract-osm", "", "extract mountain passes from an OSM PBF file into the database") - backfill = flag.Bool("backfill", false, "recompute all stored ride values") - backtest = flag.Bool("backtest", false, "run data benchmarks comparing computed values against stored reference values") - enablePprof = flag.Bool("pprof", false, "expose pprof endpoints at /debug/pprof") -) +func Run(db *sql.DB, configPath string, appConfig config.Config, args []string, enablePprof bool) { + if len(args) == 0 { + runServer(db, configPath, appConfig, enablePprof) + return + } -func Run(db *sql.DB, configPath string, appConfig config.Config) { - switch { - case *fetchOSM: + switch args[0] { + case "fetch-osm": err := mountain_pass.FetchFrancePBF("france-latest.osm.pbf") kcore.Expect(err, "failed to download France OSM PBF") - case *extractOSM != "": + case "extract-osm": + if len(args) < 2 { + fmt.Fprintln(os.Stderr, "extract-osm requires a PBF file path argument") + printUsage() + os.Exit(2) + } + pbfPath := args[1] enabled := progressBarEnabled() var bar *progressbar.ProgressBar - _, err := mountain_pass.ExtractMountainPasses(context.Background(), *extractOSM, db, func(current, total int64) { + _, err := mountain_pass.ExtractMountainPasses(context.Background(), pbfPath, db, func(current, total int64) { if bar == nil && enabled { bar = progressbar.DefaultBytes(total, "Extracting mountain passes") } @@ -49,7 +51,7 @@ func Run(db *sql.DB, configPath string, appConfig config.Config) { bar.Finish() } kcore.Expect(err, "failed to extract mountain passes from OSM") - case *backfill: + case "backfill": enabled := progressBarEnabled() var bar *progressbar.ProgressBar count, err := ride.Backfill(db, func(current, total int) { @@ -65,13 +67,41 @@ func Run(db *sql.DB, configPath string, appConfig config.Config) { } kcore.Expect(err, "failed to backfill ride values") slog.Info("Backfilled ride values", "rides", count) - case *backtest: + case "backtest": kcore.Expect(runBacktest(db), "failed to run backtest") + case "serve": + pprof := enablePprof + for _, arg := range args[1:] { + if arg == "--pprof" || arg == "-pprof" || arg == "pprof" { + pprof = true + } + } + runServer(db, configPath, appConfig, pprof) + case "help", "-h", "--help": + printUsage() default: - runServer(db, configPath, appConfig) + fmt.Fprintf(os.Stderr, "unknown command %q\n", args[0]) + printUsage() + os.Exit(2) } } +func printUsage() { + fmt.Fprintf(os.Stderr, `Usage: biking_home [global flags] [args] + +Global flags: + -config path to YAML configuration file (default "config.yaml") + -pprof expose pprof endpoints at /debug/pprof (also: "serve --pprof") + +Commands: + serve start web server (default when no command given) + fetch-osm download the France OSM PBF into france-latest.osm.pbf + extract-osm extract mountain passes from an OSM PBF file + backfill recompute all stored ride values + backtest run data benchmarks comparing computed values against stored reference values +`) +} + // progressBarEnabled reports whether stderr is attached to a terminal, so the // progress bar only renders for interactive runs and stays out of piped or // redirected output. @@ -80,9 +110,9 @@ func progressBarEnabled() bool { return err == nil && fi.Mode()&os.ModeCharDevice != 0 } -func runServer(db *sql.DB, configPath string, appConfig config.Config) { - server := web.NewServer(db, configPath).WithPprof(*enablePprof) - if *enablePprof { +func runServer(db *sql.DB, configPath string, appConfig config.Config, enablePprof bool) { + server := web.NewServer(db, configPath).WithPprof(enablePprof) + if enablePprof { slog.Info("pprof enabled", "endpoint", appConfig.Server.PublicURL+"/debug/pprof/") } slog.Info("Starting web server", "address", appConfig.Server.PublicURL) -- cgit v1.3