From 0cfddddccb88816f8e70754567f11eaf967599cc Mon Sep 17 00:00:00 2001 From: Marek Goc Date: Sun, 29 Mar 2026 15:04:11 +0200 Subject: [PATCH] Add --filter batch mode, rename binary to gormcol --- README.md | 26 +++++++++++++++++++------- cmd/gormcol/main.go | 27 ++++++++++++++++++++------- gormcol | Bin 0 -> 19689286 bytes 3 files changed, 39 insertions(+), 14 deletions(-) create mode 100755 gormcol diff --git a/README.md b/README.md index 8c673dd..ca72d1c 100644 --- a/README.md +++ b/README.md @@ -69,15 +69,19 @@ go install ./cmd/gormcol ### Usage ``` -gormcol-gen [options] +gormcol [options] ``` DSN can be provided via `--dsn` flag or `DSN` env var (from `.env` file). +**Modes:** +- **Interactive (default)**: select tables with fzf +- **Batch (`--filter` or `--all`)**: generate matching tables with confirmation + | Flag | Default | Description | |----------|------------------------|--------------------------------------------------| | `--dsn` | *(from DSN env)* | MySQL/MariaDB DSN, e.g. `user:pass@tcp(localhost:3306)/dbname` | -| `--filter` | `(ps_|b2b_).*` | Regex matching table names to generate | +| `--filter` | *(interactive)* | Regex matching table names to generate (triggers batch mode) | | `--all` | *(interactive)* | Generate all tables matching filter (shows confirmation) | | `--out` | `./app/model/dbmodel` | Output directory for generated files | | `--pkg` | `dbmodel` | Go package name for generated files | @@ -87,7 +91,7 @@ DSN can be provided via `--dsn` flag or `DSN` env var (from `.env` file). Without flags, the tool launches an interactive table selector: ```bash -gormcol-gen --dsn "user:pass@tcp(localhost:3306)/mydb" +gormcol --dsn "user:pass@tcp(localhost:3306)/mydb" ``` Features: @@ -96,12 +100,20 @@ Features: - **Enter** - confirm selection - **Esc** - cancel -### Generate All Tables +### Batch Mode (--filter) -Use `--all` to generate all tables matching the filter: +Use `--filter` to generate all tables matching a regex pattern: ```bash -gormcol-gen --dsn "user:pass@tcp(localhost:3306)/mydb" --all +gormcol --dsn "user:pass@tcp(localhost:3306)/mydb" --filter "ps_product.*" +``` + +### Generate All Tables (--all) + +Use `--all` to generate all tables matching the default filter `(ps_|b2b_).*`: + +```bash +gormcol --dsn "user:pass@tcp(localhost:3306)/mydb" --all ``` A confirmation prompt appears: @@ -115,7 +127,7 @@ WARNING: Generate all 325 tables? [Enter] confirm / [Esc] cancel ### Example ```bash -./gormcol-gen --dsn "user:pass@tcp(localhost:3306)/mydb" --filter "ps_.*" --out ./internal/model --pkg model +./gormcol --dsn "user:pass@tcp(localhost:3306)/mydb" --filter "ps_.*" --out ./internal/model --pkg model ``` This connects to the database, generates a `.go` model file for each matching table, and appends `Cols` variables with typed `gormcol.Field` descriptors to each file. diff --git a/cmd/gormcol/main.go b/cmd/gormcol/main.go index af9109d..fb6850c 100644 --- a/cmd/gormcol/main.go +++ b/cmd/gormcol/main.go @@ -20,14 +20,17 @@ import ( // and generates GORM models with column descriptors. func main() { dsn := flag.String("dsn", "", "database DSN (e.g. user:pass@tcp(host:3306)/dbname)") - filter := flag.String("filter", "(ps_|b2b_).*", "regex to match table names") + filter := flag.String("filter", "", "regex to match table names (triggers batch mode)") all := flag.Bool("all", false, "generate all tables matching filter (shows confirmation)") outDir := flag.String("out", "./app/model/dbmodel", "output directory for generated files") pkgName := flag.String("pkg", "dbmodel", "Go package name for generated files") flag.Usage = func() { - fmt.Fprintf(os.Stderr, "gormcol-gen - generate GORM models with column descriptors\n\n") + fmt.Fprintf(os.Stderr, "gormcol - generate GORM models with column descriptors\n\n") fmt.Fprintf(os.Stderr, "Usage:\n") - fmt.Fprintf(os.Stderr, " gormcol-gen [options]\n\n") + fmt.Fprintf(os.Stderr, " gormcol [options]\n\n") + fmt.Fprintf(os.Stderr, "Modes:\n") + fmt.Fprintf(os.Stderr, " - Interactive (default): select tables with fzf\n") + fmt.Fprintf(os.Stderr, " - Batch (--filter or --all): generate matching tables with confirmation\n\n") fmt.Fprintf(os.Stderr, "DSN can be provided via --dsn flag or DSN env var (from .env)\n\n") fmt.Fprintf(os.Stderr, "Flags:\n") flag.PrintDefaults() @@ -65,15 +68,25 @@ func main() { TableFilter: *filter, } - // Interactive mode (default): select tables using fzf. - // All mode: generate all tables matching filter with confirmation. - if *all { + // Modes: + // 1. --all: generate all tables matching filter with confirmation + // 2. --filter: generate all tables matching provided regex with confirmation + // 3. Default: interactive mode with fzf + if *all || *filter != "" { + if *filter == "" { + // --all without explicit filter, use default + cfg.TableFilter = "(ps_|b2b_).*" + } + yellow := "\033[33m" + reset := "\033[0m" + fmt.Printf("%sBatch mode:%s generating tables matching filter '%s'\n", yellow, reset, cfg.TableFilter) if !confirmGenerateAll(db) { fmt.Println("Aborted.") os.Exit(0) } } else { - // Check if fzf is available for interactive mode. + // Interactive mode + // Check if fzf is available. if _, err := exec.LookPath("fzf"); err != nil { fmt.Fprintln(os.Stderr, "error: fzf is required for interactive mode. Install from https://github.com/junegunn/fzf") os.Exit(1) diff --git a/gormcol b/gormcol new file mode 100755 index 0000000000000000000000000000000000000000..5d07ad5c529fce676b88f938c357903bfa55de75 GIT binary patch literal 19689286 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