Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions cmd/task/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var (
version = "master"
)

const usage = `Usage: task [-ilfwvsd] [--init] [--list] [--force] [--watch] [--verbose] [--silent] [--dir] [--dry] [--summary] [task...]
const usage = `Usage: task [-ilfwvsd] [--init] [--list] [--force] [--watch] [--verbose] [--silent] [--dir] [--dry] [--summary] [--interactive] [task...]

Runs the specified task(s). Falls back to the "default" task if no task name
was specified, or lists all tasks if an unknown task name was specified.
Expand Down Expand Up @@ -58,6 +58,7 @@ func main() {
silent bool
dry bool
summary bool
interactive bool
dir string
output string
color bool
Expand All @@ -73,6 +74,7 @@ func main() {
pflag.BoolVarP(&silent, "silent", "s", false, "disables echoing")
pflag.BoolVar(&dry, "dry", false, "compiles and prints tasks in the order that they would be run, without executing them")
pflag.BoolVar(&summary, "summary", false, "show summary about a task")
pflag.BoolVar(&interactive, "interactive", true, "interactive prompt inputs")
pflag.StringVarP(&dir, "dir", "d", "", "sets directory of execution")
pflag.StringVarP(&output, "output", "o", "", "sets output style: [interleaved|group|prefixed]")
pflag.BoolVarP(&color, "color", "c", true, "colored output")
Expand All @@ -95,14 +97,16 @@ func main() {
}

e := task.Executor{
Force: force,
Watch: watch,
Verbose: verbose,
Silent: silent,
Dir: dir,
Dry: dry,
Summary: summary,
Color: color,
Force: force,
Watch: watch,
Verbose: verbose,
Silent: silent,
Dir: dir,
Dry: dry,
Entrypoint: entrypoint,
Summary: summary,
Color: color,
Interactive: interactive,

Stdin: os.Stdin,
Stdout: os.Stdout,
Expand Down
1 change: 1 addition & 0 deletions completion/zsh/_task
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ _arguments \
'(-l --list)'{-l,--list} \
'(-s --silent)'{-s,--silent} \
'(--status)'--status \
'(--interactive)'--interactive \
'(-v --verbose)'{-v,--verbose} \
'(--version)'--version \
'(-w --watch)'{-w,--watch} \
Expand Down
67 changes: 67 additions & 0 deletions internal/taskfile/input.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package taskfile

import (
"fmt"
"regexp"
"strings"
)

// Inputs represents a group of Input
type Inputs map[string]*Input

// Input represents an interactive input variable
type Input struct {
Desc string
Required bool
Default string
Validator string
}

// FullTitle returns the input full title suffixed
func (i *Input) FullTitle(name string) (t string) {
t = i.Desc
if t == "" {
t = name
}

st := i.subtitle()
if st == "" {
return fmt.Sprintf("%s:", t)
}

return fmt.Sprintf("%s (%s):", t, st)
}

// subtitle returns the input subtitle infos
func (i *Input) subtitle() (subtitle string) {
infos := []string{}

// Required input
if i.Required {
infos = append(infos, "required: yes")
}
// Default value
if i.Default != "" {
infos = append(infos, fmt.Sprintf("default: \"%s\"", i.Default))
}
// Validator value
if i.Validator != "" {
infos = append(infos, fmt.Sprintf("validator: \"%s\"", i.Validator))
}

if len(infos) > 0 {
subtitle = fmt.Sprintf("%s", strings.Join(infos, ","))
}

return
}

// Validate returns if the input is validate
func (i *Input) Validate(val string) bool {
if i.Validator == "" {
return true
}

m, _ := regexp.MatchString(i.Validator, val)
return m
}
31 changes: 16 additions & 15 deletions internal/taskfile/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,21 @@ type Tasks map[string]*Task

// Task represents a task
type Task struct {
Task string
Cmds []*Cmd
Deps []*Dep
Desc string
Summary string
Sources []string
Generates []string
Status []string
Task string
Inputs Inputs
Cmds []*Cmd
Deps []*Dep
Desc string
Summary string
Sources []string
Generates []string
Status []string
Preconditions []*Precondition
Dir string
Vars Vars
Env Vars
Silent bool
Method string
Prefix string
IgnoreError bool `yaml:"ignore_error"`
Dir string
Vars Vars
Env Vars
Silent bool
Method string
Prefix string
IgnoreError bool `yaml:"ignore_error"`
}
49 changes: 41 additions & 8 deletions task.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,17 @@ const (
// Executor executes a Taskfile
type Executor struct {
Taskfile *taskfile.Taskfile
Dir string
Force bool
Watch bool
Verbose bool
Silent bool
Dry bool
Summary bool
Color bool

Dir string
Entrypoint string
Force bool
Watch bool
Verbose bool
Silent bool
Dry bool
Summary bool
Color bool
Interactive bool

Stdin io.Reader
Stdout io.Writer
Expand Down Expand Up @@ -204,6 +207,8 @@ func (e *Executor) Setup() error {

// RunTask runs a task by its name
func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
e.runInputs(ctx, &call)

t, err := e.CompiledTask(call)
if err != nil {
return err
Expand Down Expand Up @@ -273,6 +278,34 @@ func (e *Executor) mkdir(t *taskfile.Task) error {
return nil
}

func (e *Executor) runInputs(ctx context.Context, call *taskfile.Call) {
if origTask, ok := e.Taskfile.Tasks[call.Task]; ok {
if call.Vars == nil {
call.Vars = taskfile.Vars{}
}
for name, input := range origTask.Inputs {
var in string
if e.Interactive {
fmt.Println(input.FullTitle(name))
fmt.Fscanln(e.Stdin, &in)
}
if in == "" {
if input.Required {
e.Logger.Errf("Input required")
continue
}
in = input.Default
}
if !input.Validate(in) {
e.Logger.Errf("Input invalid")
continue
}

call.Vars[name] = taskfile.Var{Static: in}
}
}
}

func (e *Executor) runDeps(ctx context.Context, t *taskfile.Task) error {
g, ctx := errgroup.WithContext(ctx)

Expand Down
1 change: 1 addition & 0 deletions variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {

new := taskfile.Task{
Task: origTask.Task,
Inputs: origTask.Inputs,
Desc: r.Replace(origTask.Desc),
Sources: r.ReplaceSlice(origTask.Sources),
Generates: r.ReplaceSlice(origTask.Generates),
Expand Down