Files
lambda/internal/config/parse_from_args.go
M.V. Hutz 0eff85f8fa feat: add output flag (#13)
## Description

The lambda CLI previously only wrote output to stdout using shell redirection.
This PR adds support for writing results to files using the `-o` flag.
This is implemented using a new `Destination` interface that mirrors the existing `Source` pattern.

Changes:
- Added `Destination` interface with `StdoutDestination` and `FileDestination` implementations.
- Added `-o` flag to CLI argument parser for output file specification.
- Updated `Config` to use `Destination` instead of direct output handling.
- Refactored main to use `Destination.Write()` for result output.
- Updated Makefile targets (`run`, `profile`, `explain`) to use `-o` flag instead of shell redirection.

### Decisions

The `-o` flag defaults to stdout when not specified or when set to `-`.
This maintains backward compatibility while providing explicit file output capability.

## Benefits

- Cleaner command-line interface without shell redirection.
- Symmetric design with `Source` interface for input.
- More portable across different shells and environments.
- Explicit output handling improves code clarity.

## Checklist

- [x] Code follows conventional commit format.
- [x] Branch follows naming convention (`<type>/<description>`).
- [ ] Tests pass (if applicable).
- [ ] Documentation updated (if applicable).

Reviewed-on: #13
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>
2026-01-11 22:14:48 +00:00

57 lines
1.7 KiB
Go

package config
import (
"flag"
"fmt"
)
// Extract the program configuration from the command-line arguments.
func FromArgs() (*Config, error) {
// Relevant flags.
verbose := flag.Bool("v", false, "Verbosity. If set, the program will print logs.")
explanation := flag.Bool("x", false, "Explanation. Whether or not to show all reduction steps.")
statistics := flag.Bool("s", false, "Statistics. If set, the process will print various statistics about the run.")
profile := flag.String("p", "", "CPU profiling. If an output file is defined, the program will profile its execution and dump its results into it.")
file := flag.String("f", "", "File. If set, read source from the specified file.")
output := flag.String("o", "", "Output. If set, write result to the specified file. Use '-' for stdout (default).")
flag.Parse()
// Parse source type.
var source Source
if *file != "" {
// File flag takes precedence.
if flag.NArg() > 0 {
return nil, fmt.Errorf("cannot specify both -f flag and positional argument")
}
source = FileSource{Path: *file}
} else if flag.NArg() == 0 {
return nil, fmt.Errorf("no input given")
} else if flag.NArg() > 1 {
return nil, fmt.Errorf("more than 1 command-line argument")
} else {
// Positional argument.
if flag.Arg(0) == "-" {
source = StdinSource{}
} else {
source = StringSource{Data: flag.Arg(0)}
}
}
// Parse destination type.
var destination Destination
if *output == "" || *output == "-" {
destination = StdoutDestination{}
} else {
destination = FileDestination{Path: *output}
}
return &Config{
Source: source,
Destination: destination,
Verbose: *verbose,
Explanation: *explanation,
Profile: *profile,
Statistics: *statistics,
}, nil
}