1
0
mirror of https://github.com/go-task/task.git synced 2025-06-23 00:38:19 +02:00

feat: better functional options for reader (#2148)

This commit is contained in:
Pete Davison
2025-04-01 14:51:25 +01:00
committed by GitHub
parent 1939f83ffe
commit cd81d94e18
5 changed files with 266 additions and 203 deletions

View File

@ -17,7 +17,8 @@ import (
)
type (
// An ExecutorOption is a functional option for an [Executor].
// An ExecutorOption is any type that can apply a configuration to an
// [Executor].
ExecutorOption interface {
ApplyToExecutor(*Executor)
}
@ -112,14 +113,14 @@ func (e *Executor) Options(opts ...ExecutorOption) {
// WithDir sets the working directory of the [Executor]. By default, the
// directory is set to the user's current working directory.
func WithDir(dir string) ExecutorOption {
return dirOption{dir}
return &dirOption{dir}
}
type dirOption struct {
dir string
}
func (o dirOption) ApplyToExecutor(e *Executor) {
func (o *dirOption) ApplyToExecutor(e *Executor) {
e.Dir = o.dir
}
@ -127,14 +128,14 @@ func (o dirOption) ApplyToExecutor(e *Executor) {
// default, Task will search for one of the default Taskfiles in the given
// directory.
func WithEntrypoint(entrypoint string) ExecutorOption {
return entrypointOption{entrypoint}
return &entrypointOption{entrypoint}
}
type entrypointOption struct {
entrypoint string
}
func (o entrypointOption) ApplyToExecutor(e *Executor) {
func (o *entrypointOption) ApplyToExecutor(e *Executor) {
e.Entrypoint = o.entrypoint
}
@ -142,98 +143,98 @@ func (o entrypointOption) ApplyToExecutor(e *Executor) {
// storing temporary files like checksums and cached remote files. By default,
// the temporary directory is set to the user's temporary directory.
func WithTempDir(tempDir TempDir) ExecutorOption {
return tempDirOption{tempDir}
return &tempDirOption{tempDir}
}
type tempDirOption struct {
tempDir TempDir
}
func (o tempDirOption) ApplyToExecutor(e *Executor) {
func (o *tempDirOption) ApplyToExecutor(e *Executor) {
e.TempDir = o.tempDir
}
// WithForce ensures that the [Executor] always runs a task, even when
// fingerprinting or prompts would normally stop it.
func WithForce(force bool) ExecutorOption {
return forceOption{force}
return &forceOption{force}
}
type forceOption struct {
force bool
}
func (o forceOption) ApplyToExecutor(e *Executor) {
func (o *forceOption) ApplyToExecutor(e *Executor) {
e.Force = o.force
}
// WithForceAll ensures that the [Executor] always runs all tasks (including
// subtasks), even when fingerprinting or prompts would normally stop them.
func WithForceAll(forceAll bool) ExecutorOption {
return forceAllOption{forceAll}
return &forceAllOption{forceAll}
}
type forceAllOption struct {
forceAll bool
}
func (o forceAllOption) ApplyToExecutor(e *Executor) {
func (o *forceAllOption) ApplyToExecutor(e *Executor) {
e.ForceAll = o.forceAll
}
// WithInsecure allows the [Executor] to make insecure connections when reading
// remote taskfiles. By default, insecure connections are rejected.
func WithInsecure(insecure bool) ExecutorOption {
return insecureOption{insecure}
return &insecureOption{insecure}
}
type insecureOption struct {
insecure bool
}
func (o insecureOption) ApplyToExecutor(e *Executor) {
func (o *insecureOption) ApplyToExecutor(e *Executor) {
e.Insecure = o.insecure
}
// WithDownload forces the [Executor] to download a fresh copy of the taskfile
// from the remote source.
func WithDownload(download bool) ExecutorOption {
return downloadOption{download}
return &downloadOption{download}
}
type downloadOption struct {
download bool
}
func (o downloadOption) ApplyToExecutor(e *Executor) {
func (o *downloadOption) ApplyToExecutor(e *Executor) {
e.Download = o.download
}
// WithOffline stops the [Executor] from being able to make network connections.
// It will still be able to read local files and cached copies of remote files.
func WithOffline(offline bool) ExecutorOption {
return offlineOption{offline}
return &offlineOption{offline}
}
type offlineOption struct {
offline bool
}
func (o offlineOption) ApplyToExecutor(e *Executor) {
func (o *offlineOption) ApplyToExecutor(e *Executor) {
e.Offline = o.offline
}
// WithTimeout sets the [Executor]'s timeout for fetching remote taskfiles. By
// default, the timeout is set to 10 seconds.
func WithTimeout(timeout time.Duration) ExecutorOption {
return timeoutOption{timeout}
return &timeoutOption{timeout}
}
type timeoutOption struct {
timeout time.Duration
}
func (o timeoutOption) ApplyToExecutor(e *Executor) {
func (o *timeoutOption) ApplyToExecutor(e *Executor) {
e.Timeout = o.timeout
}
@ -241,166 +242,166 @@ func (o timeoutOption) ApplyToExecutor(e *Executor) {
// for changes to the fingerprint of the tasks that are run. When changes are
// detected, a new task run is triggered.
func WithWatch(watch bool) ExecutorOption {
return watchOption{watch}
return &watchOption{watch}
}
type watchOption struct {
watch bool
}
func (o watchOption) ApplyToExecutor(e *Executor) {
func (o *watchOption) ApplyToExecutor(e *Executor) {
e.Watch = o.watch
}
// WithVerbose tells the [Executor] to output more information about the tasks
// that are run.
func WithVerbose(verbose bool) ExecutorOption {
return verboseOption{verbose}
return &verboseOption{verbose}
}
type verboseOption struct {
verbose bool
}
func (o verboseOption) ApplyToExecutor(e *Executor) {
func (o *verboseOption) ApplyToExecutor(e *Executor) {
e.Verbose = o.verbose
}
// WithSilent tells the [Executor] to suppress all output except for the output
// of the tasks that are run.
func WithSilent(silent bool) ExecutorOption {
return silentOption{silent}
return &silentOption{silent}
}
type silentOption struct {
silent bool
}
func (o silentOption) ApplyToExecutor(e *Executor) {
func (o *silentOption) ApplyToExecutor(e *Executor) {
e.Silent = o.silent
}
// WithAssumeYes tells the [Executor] to assume "yes" for all prompts.
func WithAssumeYes(assumeYes bool) ExecutorOption {
return assumeYesOption{assumeYes}
return &assumeYesOption{assumeYes}
}
type assumeYesOption struct {
assumeYes bool
}
func (o assumeYesOption) ApplyToExecutor(e *Executor) {
func (o *assumeYesOption) ApplyToExecutor(e *Executor) {
e.AssumeYes = o.assumeYes
}
// WithAssumeTerm is used for testing purposes to simulate a terminal.
func WithAssumeTerm(assumeTerm bool) ExecutorOption {
return assumeTermOption{assumeTerm}
return &assumeTermOption{assumeTerm}
}
type assumeTermOption struct {
assumeTerm bool
}
func (o assumeTermOption) ApplyToExecutor(e *Executor) {
func (o *assumeTermOption) ApplyToExecutor(e *Executor) {
e.AssumeTerm = o.assumeTerm
}
// WithDry tells the [Executor] to output the commands that would be run without
// actually running them.
func WithDry(dry bool) ExecutorOption {
return dryOption{dry}
return &dryOption{dry}
}
type dryOption struct {
dry bool
}
func (o dryOption) ApplyToExecutor(e *Executor) {
func (o *dryOption) ApplyToExecutor(e *Executor) {
e.Dry = o.dry
}
// WithSummary tells the [Executor] to output a summary of the given tasks
// instead of running them.
func WithSummary(summary bool) ExecutorOption {
return summaryOption{summary}
return &summaryOption{summary}
}
type summaryOption struct {
summary bool
}
func (o summaryOption) ApplyToExecutor(e *Executor) {
func (o *summaryOption) ApplyToExecutor(e *Executor) {
e.Summary = o.summary
}
// WithParallel tells the [Executor] to run tasks given in the same call in
// parallel.
func WithParallel(parallel bool) ExecutorOption {
return parallelOption{parallel}
return &parallelOption{parallel}
}
type parallelOption struct {
parallel bool
}
func (o parallelOption) ApplyToExecutor(e *Executor) {
func (o *parallelOption) ApplyToExecutor(e *Executor) {
e.Parallel = o.parallel
}
// WithColor tells the [Executor] whether or not to output using colorized
// strings.
func WithColor(color bool) ExecutorOption {
return colorOption{color}
return &colorOption{color}
}
type colorOption struct {
color bool
}
func (o colorOption) ApplyToExecutor(e *Executor) {
func (o *colorOption) ApplyToExecutor(e *Executor) {
e.Color = o.color
}
// WithConcurrency sets the maximum number of tasks that the [Executor] can run
// in parallel.
func WithConcurrency(concurrency int) ExecutorOption {
return concurrencyOption{concurrency}
return &concurrencyOption{concurrency}
}
type concurrencyOption struct {
concurrency int
}
func (o concurrencyOption) ApplyToExecutor(e *Executor) {
func (o *concurrencyOption) ApplyToExecutor(e *Executor) {
e.Concurrency = o.concurrency
}
// WithInterval sets the interval at which the [Executor] will wait for
// duplicated events before running a task.
func WithInterval(interval time.Duration) ExecutorOption {
return intervalOption{interval}
return &intervalOption{interval}
}
type intervalOption struct {
interval time.Duration
}
func (o intervalOption) ApplyToExecutor(e *Executor) {
func (o *intervalOption) ApplyToExecutor(e *Executor) {
e.Interval = o.interval
}
// WithOutputStyle sets the output style of the [Executor]. By default, the
// output style is set to the style defined in the Taskfile.
func WithOutputStyle(outputStyle ast.Output) ExecutorOption {
return outputStyleOption{outputStyle}
return &outputStyleOption{outputStyle}
}
type outputStyleOption struct {
outputStyle ast.Output
}
func (o outputStyleOption) ApplyToExecutor(e *Executor) {
func (o *outputStyleOption) ApplyToExecutor(e *Executor) {
e.OutputStyle = o.outputStyle
}
@ -408,67 +409,67 @@ func (o outputStyleOption) ApplyToExecutor(e *Executor) {
// default, the sorter is set to sort tasks alphabetically, but with tasks with
// no namespace (in the root Taskfile) first.
func WithTaskSorter(sorter sort.Sorter) ExecutorOption {
return taskSorterOption{sorter}
return &taskSorterOption{sorter}
}
type taskSorterOption struct {
sorter sort.Sorter
}
func (o taskSorterOption) ApplyToExecutor(e *Executor) {
func (o *taskSorterOption) ApplyToExecutor(e *Executor) {
e.TaskSorter = o.sorter
}
// WithStdin sets the [Executor]'s standard input [io.Reader].
func WithStdin(stdin io.Reader) ExecutorOption {
return stdinOption{stdin}
return &stdinOption{stdin}
}
type stdinOption struct {
stdin io.Reader
}
func (o stdinOption) ApplyToExecutor(e *Executor) {
func (o *stdinOption) ApplyToExecutor(e *Executor) {
e.Stdin = o.stdin
}
// WithStdout sets the [Executor]'s standard output [io.Writer].
func WithStdout(stdout io.Writer) ExecutorOption {
return stdoutOption{stdout}
return &stdoutOption{stdout}
}
type stdoutOption struct {
stdout io.Writer
}
func (o stdoutOption) ApplyToExecutor(e *Executor) {
func (o *stdoutOption) ApplyToExecutor(e *Executor) {
e.Stdout = o.stdout
}
// WithStderr sets the [Executor]'s standard error [io.Writer].
func WithStderr(stderr io.Writer) ExecutorOption {
return stderrOption{stderr}
return &stderrOption{stderr}
}
type stderrOption struct {
stderr io.Writer
}
func (o stderrOption) ApplyToExecutor(e *Executor) {
func (o *stderrOption) ApplyToExecutor(e *Executor) {
e.Stderr = o.stderr
}
// WithIO sets the [Executor]'s standard input, output, and error to the same
// [io.ReadWriter].
func WithIO(rw io.ReadWriter) ExecutorOption {
return ioOption{rw}
return &ioOption{rw}
}
type ioOption struct {
rw io.ReadWriter
}
func (o ioOption) ApplyToExecutor(e *Executor) {
func (o *ioOption) ApplyToExecutor(e *Executor) {
e.Stdin = o.rw
e.Stdout = o.rw
e.Stderr = o.rw
@ -476,13 +477,13 @@ func (o ioOption) ApplyToExecutor(e *Executor) {
// WithVersionCheck tells the [Executor] whether or not to check the version of
func WithVersionCheck(enableVersionCheck bool) ExecutorOption {
return versionCheckOption{enableVersionCheck}
return &versionCheckOption{enableVersionCheck}
}
type versionCheckOption struct {
enableVersionCheck bool
}
func (o versionCheckOption) ApplyToExecutor(e *Executor) {
func (o *versionCheckOption) ApplyToExecutor(e *Executor) {
e.EnableVersionCheck = o.enableVersionCheck
}