|
9 | 9 | "sort" |
10 | 10 | "strings" |
11 | 11 |
|
12 | | - "github.com/donislawdev/TestingFilesGenerator/internal/core" |
13 | 12 | "github.com/donislawdev/TestingFilesGenerator/internal/engine" |
14 | 13 | "github.com/donislawdev/TestingFilesGenerator/internal/format" |
15 | 14 | "github.com/donislawdev/TestingFilesGenerator/internal/manifest" |
@@ -338,251 +337,3 @@ func targetsFromPreset(fs *flag.FlagSet, g *generateOpts, given map[string]bool, |
338 | 337 | opt.Preset = record(expanded) |
339 | 338 | return targetsFromParsedRecipe(rec, hash, g, given, opt), ExitOK |
340 | 339 | } |
341 | | - |
342 | | -func presetCmd(ctx context.Context, args []string, out, errOut io.Writer) int { |
343 | | - if len(args) > 0 { |
344 | | - switch args[0] { |
345 | | - case "list": |
346 | | - return presetList(args[1:], out, errOut) |
347 | | - case "show": |
348 | | - return presetShow(ctx, args[1:], out, errOut) |
349 | | - case "eject": |
350 | | - return presetEject(args[1:], out, errOut) |
351 | | - } |
352 | | - } |
353 | | - |
354 | | - // Asking about the command itself, before any operation is named. |
355 | | - if helpRequested(args) { |
356 | | - presetUsage(out) |
357 | | - return ExitOK |
358 | | - } |
359 | | - if len(args) == 0 { |
360 | | - fmt.Fprintln(errOut, "tfg: preset takes one operation: list, show or eject. Example: tfg preset list") |
361 | | - } else { |
362 | | - fmt.Fprintf(errOut, "tfg: preset has no operation called %q. It takes list, show or eject.\n", args[0]) |
363 | | - } |
364 | | - presetUsage(errOut) |
365 | | - return ExitUsage |
366 | | -} |
367 | | - |
368 | | -func presetUsage(w io.Writer) { |
369 | | - fmt.Fprint(w, `tfg preset - build a set of files from a named test question. |
370 | | -
|
371 | | -Usage: |
372 | | - tfg preset list what this build offers |
373 | | - tfg preset show <id> what it takes and what it would produce |
374 | | - tfg preset eject <id> > my.yaml the recipe it stands for, to edit |
375 | | -
|
376 | | -A preset is a recipe with a name. Ejecting one gives back an ordinary recipe |
377 | | -file, so nothing here is a closed box. |
378 | | -
|
379 | | -Run "tfg generate --preset <id>" to produce the files. |
380 | | -`) |
381 | | -} |
382 | | - |
383 | | -// presetFlagSet builds the flag set of an operation taking one preset id. |
384 | | -// |
385 | | -// The id has to be read before parsing, because the parameters of the preset |
386 | | -// are flags and there is no way to register them until it is known which they |
387 | | -// are. |
388 | | -// asJSON is filled in for the operations that have a machine readable form and |
389 | | -// nil for the one that does not - a recipe is already machine readable, and a |
390 | | -// second encoding of it would be a second thing to keep in step. |
391 | | -func presetFlagSet(name string, args []string, out, errOut io.Writer, usage func(io.Writer), asJSON *bool) ( |
392 | | - *preset.Expansion, int) { |
393 | | - |
394 | | - fs := flag.NewFlagSet("preset "+name, flag.ContinueOnError) |
395 | | - fs.SetOutput(errOut) |
396 | | - fs.Usage = func() { usage(errOut) } |
397 | | - if helpRequested(args) { |
398 | | - usage(out) |
399 | | - return nil, ExitOK |
400 | | - } |
401 | | - // Registered before the parameters, so a preset declaring one called json |
402 | | - // is caught by the collision check rather than by the flag package panicking. |
403 | | - if asJSON != nil { |
404 | | - fs.BoolVar(asJSON, "json", false, "write the answer as JSON to standard output") |
405 | | - } |
406 | | - |
407 | | - id, rest := splitLeadingPath(args) |
408 | | - if id == "" { |
409 | | - fmt.Fprintf(errOut, "tfg: preset %s takes the id of one preset. Run \"tfg preset list\" to see them.\n", name) |
410 | | - return nil, ExitUsage |
411 | | - } |
412 | | - p, err := preset.Get(id) |
413 | | - if err != nil { |
414 | | - fmt.Fprintf(errOut, "tfg: %s\n", describeError(err)) |
415 | | - return nil, classify(err) |
416 | | - } |
417 | | - if clash := clashingParameter(fs, p); clash != "" { |
418 | | - fmt.Fprintf(errOut, "tfg: the preset %s declares a parameter called %q and that is already a flag of this command. This is a fault in the build rather than in what you typed, and there is nothing you can do about it from here.\n", p.ID, clash) |
419 | | - return nil, ExitRuntime |
420 | | - } |
421 | | - registerPresetFlags(fs, p) |
422 | | - |
423 | | - if err := fs.Parse(rest); err != nil { |
424 | | - return nil, ExitUsage |
425 | | - } |
426 | | - if fs.NArg() > 0 { |
427 | | - fmt.Fprintf(errOut, "tfg: preset %s takes one preset id and %q came after it. Give the parameters as flags, for example --limit 10mb.\n", name, fs.Arg(0)) |
428 | | - return nil, ExitUsage |
429 | | - } |
430 | | - |
431 | | - expanded, err := preset.Expand(id, givenPresetArgs(fs, p)) |
432 | | - if err != nil { |
433 | | - fmt.Fprintf(errOut, "tfg: %s\n", describeError(err)) |
434 | | - return nil, classify(err) |
435 | | - } |
436 | | - return expanded, ExitOK |
437 | | -} |
438 | | - |
439 | | -func presetList(args []string, out, errOut io.Writer) int { |
440 | | - fs := flag.NewFlagSet("preset list", flag.ContinueOnError) |
441 | | - fs.SetOutput(errOut) |
442 | | - asJSON := fs.Bool("json", false, "write the list as JSON to standard output") |
443 | | - usage := func(w io.Writer) { |
444 | | - fmt.Fprint(w, `tfg preset list - the test questions this build can answer. |
445 | | -
|
446 | | -Usage: |
447 | | - tfg preset list |
448 | | - tfg preset list --json |
449 | | -
|
450 | | -Flags: |
451 | | -`) |
452 | | - fs.SetOutput(w) |
453 | | - fs.PrintDefaults() |
454 | | - fs.SetOutput(errOut) |
455 | | - } |
456 | | - fs.Usage = func() { usage(errOut) } |
457 | | - if helpRequested(args) { |
458 | | - usage(out) |
459 | | - return ExitOK |
460 | | - } |
461 | | - if err := fs.Parse(args); err != nil { |
462 | | - return ExitUsage |
463 | | - } |
464 | | - |
465 | | - all := preset.All() |
466 | | - if *asJSON { |
467 | | - list := make([]presetEntry, 0, len(all)) |
468 | | - for _, p := range all { |
469 | | - list = append(list, presetEntryFor(p)) |
470 | | - } |
471 | | - return renderJSON(list, out, errOut) |
472 | | - } |
473 | | - |
474 | | - // An empty build says so rather than printing a heading over nothing. |
475 | | - if len(all) == 0 { |
476 | | - fmt.Fprint(out, "This build registers no presets.\n") |
477 | | - return ExitOK |
478 | | - } |
479 | | - fmt.Fprintf(out, "%-18s %s\n", "PRESET", "QUESTION IT ANSWERS") |
480 | | - for _, p := range all { |
481 | | - fmt.Fprintf(out, "%-18s %s\n", p.ID, p.Question) |
482 | | - } |
483 | | - fmt.Fprint(out, "\nRun \"tfg preset show <id>\" for what one takes and what it would produce.\n") |
484 | | - return ExitOK |
485 | | -} |
486 | | - |
487 | | -func presetShow(ctx context.Context, args []string, out, errOut io.Writer) int { |
488 | | - usage := func(w io.Writer) { |
489 | | - fmt.Fprint(w, `tfg preset show - what a preset takes and what it would produce. |
490 | | -
|
491 | | -The budget is counted from the plan, at the parameters you gave, so it is the |
492 | | -number of files and bytes this run would really write. |
493 | | -
|
494 | | -Usage: |
495 | | - tfg preset show size-boundaries |
496 | | - tfg preset show size-boundaries --limit 20mb --format png |
497 | | - tfg preset show size-boundaries --json |
498 | | -`) |
499 | | - } |
500 | | - var asJSON bool |
501 | | - expanded, code := presetFlagSet("show", args, out, errOut, usage, &asJSON) |
502 | | - if expanded == nil { |
503 | | - return code |
504 | | - } |
505 | | - |
506 | | - b, err := budgetOf(ctx, expanded) |
507 | | - if err != nil { |
508 | | - fmt.Fprintf(errOut, "tfg: %s\n", describeError(err)) |
509 | | - return classify(err) |
510 | | - } |
511 | | - |
512 | | - if asJSON { |
513 | | - entry := presetEntryFor(expanded.Preset) |
514 | | - entry.Budget = &b |
515 | | - entry.Defaulted = expanded.Defaulted |
516 | | - entry.Notes = expanded.Notes() |
517 | | - return renderJSON(entry, out, errOut) |
518 | | - } |
519 | | - describePreset(expanded, b, out) |
520 | | - return ExitOK |
521 | | -} |
522 | | - |
523 | | -func describePreset(e *preset.Expansion, b budget, out io.Writer) { |
524 | | - p := e.Preset |
525 | | - fmt.Fprintf(out, "%s - %s\n%s\n", p.ID, p.Title, p.Question) |
526 | | - |
527 | | - if len(p.Parameters) > 0 { |
528 | | - fmt.Fprint(out, "\nparameters:\n") |
529 | | - for _, param := range p.Parameters { |
530 | | - fmt.Fprintf(out, " --%-12s %s\n", param.Name, param.Allowed()) |
531 | | - if param.Detail != "" { |
532 | | - fmt.Fprintf(out, " %-14s %s\n", "", param.Detail) |
533 | | - } |
534 | | - } |
535 | | - } |
536 | | - for _, name := range p.Reads { |
537 | | - fmt.Fprintf(out, " --%-12s the global flag, this preset gives it a default\n", name) |
538 | | - } |
539 | | - |
540 | | - fmt.Fprintf(out, "\nbudget at these values:\n %s, %s, %s total, format %s\n", |
541 | | - core.Count(b.Targets, "target", "targets"), core.Count(b.Files, "file", "files"), |
542 | | - core.ExactBytes(b.Bytes), strings.Join(b.Formats, ", ")) |
543 | | - for _, note := range e.Notes() { |
544 | | - fmt.Fprintf(out, "\nnote: %s\n", note) |
545 | | - } |
546 | | - |
547 | | - if len(p.Catches) > 0 { |
548 | | - fmt.Fprint(out, "\nwhat it typically catches:\n") |
549 | | - for _, c := range p.Catches { |
550 | | - fmt.Fprintf(out, " - %s\n", c) |
551 | | - } |
552 | | - } |
553 | | - fmt.Fprintf(out, "\nRun \"tfg preset eject %s\" for the recipe, or \"tfg generate --preset %s\" to produce the files.\n", |
554 | | - p.ID, p.ID) |
555 | | -} |
556 | | - |
557 | | -func presetEject(args []string, out, errOut io.Writer) int { |
558 | | - usage := func(w io.Writer) { |
559 | | - fmt.Fprint(w, `tfg preset eject - the recipe a preset stands for. |
560 | | -
|
561 | | -Prints an ordinary recipe file. Edit it, commit it, run it with tfg generate - |
562 | | -from here on it is yours and nothing about it is special. |
563 | | -
|
564 | | -The recipe goes to standard output and everything else to standard error, so |
565 | | -"tfg preset eject size-boundaries > my.yaml" gives a clean file. |
566 | | -
|
567 | | -Usage: |
568 | | - tfg preset eject size-boundaries > my.yaml |
569 | | - tfg preset eject size-boundaries --limit 20mb --format png > my.yaml |
570 | | -`) |
571 | | - } |
572 | | - expanded, code := presetFlagSet("eject", args, out, errOut, usage, nil) |
573 | | - if expanded == nil { |
574 | | - return code |
575 | | - } |
576 | | - |
577 | | - // The note goes to the error channel. The recipe is the data here, and a |
578 | | - // sentence about a number we chose has no business inside a file somebody |
579 | | - // is about to commit. |
580 | | - for _, note := range expanded.Notes() { |
581 | | - fmt.Fprintf(errOut, "note: %s\n", note) |
582 | | - } |
583 | | - if _, err := out.Write(expanded.Source); err != nil { |
584 | | - fmt.Fprintf(errOut, "tfg: cannot write the recipe: %s\n", describeError(err)) |
585 | | - return ExitIO |
586 | | - } |
587 | | - return ExitOK |
588 | | -} |
0 commit comments