parseArgumentValues returns a map of argument names and their parsed values
( ctx context.Context, md *moduleDef, fn *modFunction, args []string, )
| 666 | |
| 667 | // parseArgumentValues returns a map of argument names and their parsed values |
| 668 | func (h *shellCallHandler) parseArgumentValues( |
| 669 | ctx context.Context, |
| 670 | md *moduleDef, |
| 671 | fn *modFunction, |
| 672 | args []string, |
| 673 | ) (rargs map[string]any, rerr error) { |
| 674 | values, newArgs, err := h.shellPreprocessArgs(ctx, fn, args) |
| 675 | if err != nil { |
| 676 | return nil, errors.Join(err, fmt.Errorf("usage: %s", h.FunctionFullUseLine(md, fn))) |
| 677 | } |
| 678 | |
| 679 | // Flag processing can be a source of bugs so it's very useful to be |
| 680 | // able to debug this step but excessive on default verbosity. |
| 681 | if debugFlag && verbose > 3 && !slices.Equal(args, newArgs) { |
| 682 | dbgArgs := []any{ |
| 683 | "function", fn.CmdName(), |
| 684 | "before", args, |
| 685 | "after", newArgs, |
| 686 | } |
| 687 | if len(values) > 0 { |
| 688 | dbgArgs = append(dbgArgs, "values", values) |
| 689 | } |
| 690 | slog := slog.SpanLogger(ctx, InstrumentationLibrary) |
| 691 | slog.Debug("preprocess function argument flags", dbgArgs...) |
| 692 | } |
| 693 | |
| 694 | // no further processing needed |
| 695 | if len(newArgs) == 0 { |
| 696 | return values, nil |
| 697 | } |
| 698 | |
| 699 | flags := pflag.NewFlagSet(fn.CmdName(), pflag.ContinueOnError) |
| 700 | flags.SetOutput(io.MultiWriter( |
| 701 | interp.HandlerCtx(ctx).Stderr, |
| 702 | telemetry.SpanStdio(ctx, InstrumentationLibrary).Stderr, |
| 703 | )) |
| 704 | |
| 705 | // Add flags for each argument, including unsupported ones, which we |
| 706 | // assume it's being supported through some other means, so we just |
| 707 | // bypass the flags. This how we pass ID values to flag parsing, without |
| 708 | // having support for it with a custom flag. |
| 709 | // TODO: Create an "ID" or "Raw" type flag and validate appropriately |
| 710 | for _, a := range fn.Args { |
| 711 | err := a.AddFlag(flags) |
| 712 | var e *UnsupportedFlagError |
| 713 | if errors.As(err, &e) { |
| 714 | // This is just enough to trigger passing the value to ParseAll, |
| 715 | // but will only be used for getting the value if it doesn't |
| 716 | // originate from a command expansion (subshell). |
| 717 | // TODO: This will likely fail if value doesn't come from command |
| 718 | // expansion because the value that is passed goes directly to the |
| 719 | // API. We should validate this more, or refactor. |
| 720 | flags.String(a.FlagName(), "", a.Description) |
| 721 | flags.MarkHidden(a.FlagName()) |
| 722 | continue |
| 723 | } |
| 724 | if err != nil { |
| 725 | return nil, fmt.Errorf("error addding flag: %w", err) |
no test coverage detected