diff --git a/v3/cmd/wails/main.go b/v3/cmd/wails/main.go index 77eaa120d..915209fac 100644 --- a/v3/cmd/wails/main.go +++ b/v3/cmd/wails/main.go @@ -10,11 +10,16 @@ import ( ) func main() { - app := clir.NewCli("Wails", "The Wails CLI", "v3") + app := clir.NewCli("wails", "The Wails CLI", "v3") + app.NewSubCommandFunction("build", "Build the project", commands.Build) app.NewSubCommandFunction("init", "Initialise a new project", commands.Init) task := app.NewSubCommand("task", "Run and list tasks") - task.NewSubCommandFunction("run", "Run a task", commands.RunTask) - task.NewSubCommandFunction("list", "List tasks", commands.ListTasks) + var taskFlags commands.RunTaskOptions + task.AddFlags(&taskFlags) + task.Action(func() error { + return commands.RunTask(&taskFlags, task.OtherArgs()) + }) + task.LongDescription("\nUsage: wails task [taskname] [flags]\n\nTasks are defined in the `Taskfile.yaml` file. See https://taskfile.dev for more information.") generate := app.NewSubCommand("generate", "Generation tools") generate.NewSubCommandFunction("defaults", "Generate default build assets", commands.Defaults) generate.NewSubCommandFunction("icons", "Generate icons", commands.GenerateIcons) diff --git a/v3/go.mod b/v3/go.mod index 5bcbc2fc7..f935c3cbc 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/go-task/task/v3 v3.20.0 github.com/jackmordaunt/icns/v2 v2.2.1 - github.com/leaanthony/clir v1.5.0 + github.com/leaanthony/clir v1.6.0 github.com/leaanthony/gosod v1.0.3 github.com/leaanthony/winicon v1.0.0 github.com/pterm/pterm v0.12.51 diff --git a/v3/go.sum b/v3/go.sum index 7a5ef1a8f..e08b169ad 100644 --- a/v3/go.sum +++ b/v3/go.sum @@ -47,8 +47,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= -github.com/leaanthony/clir v1.5.0 h1:zaH7fgsZ5OLfr0YwJBwQ+EYxCjXQsHF+CRudIiZb0KQ= -github.com/leaanthony/clir v1.5.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= +github.com/leaanthony/clir v1.6.0 h1:mLV9thGkmqFqJU7ozmqlER8sBtGdZlz6H3gKsfIiB3o= +github.com/leaanthony/clir v1.6.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc= github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA= github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ= diff --git a/v3/internal/commands/build.go b/v3/internal/commands/build.go new file mode 100644 index 000000000..1c3f82ad1 --- /dev/null +++ b/v3/internal/commands/build.go @@ -0,0 +1,12 @@ +package commands + +import ( + "os" + + "github.com/wailsapp/wails/v3/internal/flags" +) + +func Build(_ *flags.Build) error { + os.Args = []string{"wails", "task", "build"} + return RunTask(&RunTaskOptions{}, []string{}) +} diff --git a/v3/internal/commands/task.go b/v3/internal/commands/task.go index ae33e9215..c80d677e6 100644 --- a/v3/internal/commands/task.go +++ b/v3/internal/commands/task.go @@ -3,67 +3,173 @@ package commands import ( "context" "fmt" + "log" + "os" + "path/filepath" + "strings" + "time" "github.com/pterm/pterm" + "github.com/go-task/task/v3/args" + "github.com/go-task/task/v3" "github.com/go-task/task/v3/taskfile" ) type RunTaskOptions struct { - Name string `name:"n" description:"The name of the task to run"` + Name string `pos:"1"` + Help bool `name:"h" description:"shows Task usage"` + Init bool `name:"i" description:"creates a new Taskfile.yml"` + List bool `name:"list" description:"tasks with description of current Taskfile"` + ListAll bool `name:"list-all" description:"lists tasks with or without a description"` + ListJSON bool `name:"json" description:"formats task list as json"` + Status bool `name:"status" description:"exits with non-zero exit code if any of the given tasks is not up-to-date"` + Force bool `name:"f" description:"forces execution even when the task is up-to-date"` + Watch bool `name:"w" description:"enables watch of the given task"` + Verbose bool `name:"v" description:"enables verbose mode"` + Silent bool `name:"s" description:"disables echoing"` + Parallel bool `name:"p" description:"executes tasks provided on command line in parallel"` + Dry bool `name:"dry" description:"compiles and prints tasks in the order that they would be run, without executing them"` + Summary bool `name:"summary" description:"show summary about a task"` + ExitCode bool `name:"x" description:"pass-through the exit code of the task command"` + Dir string `name:"dir" description:"sets directory of execution"` + EntryPoint string `name:"taskfile" description:"choose which Taskfile to run."` + OutputName string `name:"output" description:"sets output style: [interleaved|group|prefixed]"` + OutputGroupBegin string `name:"output-group-begin" description:"message template to print before a task's grouped output"` + OutputGroupEnd string `name:"output-group-end" description:"message template to print after a task's grouped output"` + Color bool `name:"c" description:"colored output. Enabled by default. Set flag to false or use NO_COLOR=1 to disable" default:"true"` + Concurrency int `name:"C" description:"limit number tasks to run concurrently"` + Interval int64 `name:"interval" description:"interval to watch for changes"` } -func RunTask(options *RunTaskOptions) error { - if options.Name == "" { - return fmt.Errorf("name of task required") - } +func RunTask(options *RunTaskOptions, otherArgs []string) error { - e := task.Executor{} - err := e.Setup() - if err != nil { - return err - } - build := taskfile.Call{ - Task: options.Name, - Vars: nil, - } - return e.Run(context.Background(), build) -} - -type ListTaskOptions struct { -} - -func ListTasks(options *ListTaskOptions) error { - e := task.Executor{} - if err := e.Setup(); err != nil { - return err - } - tasks, err := e.GetTaskList() - if err != nil { - return err - } - if len(tasks) == 0 { - return fmt.Errorf("no tasks found. Ensure there is a `Taskfile.tmpl.yml` in your project. You can generate a default takfile by running `wails generate defaults`") - } - tableData := [][]string{ - {"Task", "Summary"}, - } - println() - - for _, thisTask := range tasks { - if thisTask.Internal { - continue + if options.Init { + wd, err := os.Getwd() + if err != nil { + return err } - var thisRow = make([]string, 2) - thisRow[0] = thisTask.Task - thisRow[1] = thisTask.Summary - tableData = append(tableData, thisRow) + return task.InitTaskfile(os.Stdout, wd) } - err = pterm.DefaultTable.WithHasHeader(true).WithHeaderRowSeparator("-").WithData(tableData).Render() + + if options.Dir != "" && options.EntryPoint != "" { + return fmt.Errorf("task: You can't set both --dir and --taskfile") + } + + if options.EntryPoint != "" { + options.Dir = filepath.Dir(options.EntryPoint) + options.EntryPoint = filepath.Base(options.EntryPoint) + } + + if options.OutputName != "group" { + if options.OutputGroupBegin != "" { + return fmt.Errorf("task: You can't set --output-group-begin without --output=group") + } + if options.OutputGroupBegin != "" { + return fmt.Errorf("task: You can't set --output-group-end without --output=group") + } + } + + e := task.Executor{ + Force: options.Force, + Watch: options.Watch, + Verbose: options.Verbose, + Silent: options.Silent, + Dir: options.Dir, + Dry: options.Dry, + Entrypoint: options.EntryPoint, + Summary: options.Summary, + Parallel: options.Parallel, + Color: options.Color, + Concurrency: options.Concurrency, + Interval: time.Duration(options.Interval) * time.Second, + + Stdin: os.Stdin, + Stdout: os.Stdout, + Stderr: os.Stderr, + + OutputStyle: taskfile.Output{ + Name: options.OutputName, + Group: taskfile.OutputGroup{ + Begin: options.OutputGroupBegin, + End: options.OutputGroupEnd, + }, + }, + } + + var listOptions = task.NewListOptions(options.List, options.ListAll, options.ListJSON) + if err := listOptions.Validate(); err != nil { + log.Fatal(err) + } + + if (listOptions.ShouldListTasks()) && options.Silent { + e.ListTaskNames(options.ListAll) + return nil + } + + if err := e.Setup(); err != nil { + log.Fatal(err) + } + v, err := e.Taskfile.ParsedVersion() if err != nil { return err } - println() + + if listOptions.ShouldListTasks() { + if foundTasks, err := e.ListTasks(listOptions); !foundTasks || err != nil { + os.Exit(1) + } + return nil + } + + var ( + calls []taskfile.Call + globals *taskfile.Vars + ) + + var taskAndVars []string + for _, taskAndVar := range os.Args[2:] { + if taskAndVar == "--" { + break + } + taskAndVars = append(taskAndVars, taskAndVar) + } + + if len(taskAndVars) > 0 && len(otherArgs) > 0 { + if taskAndVars[0] == otherArgs[0] { + otherArgs = otherArgs[1:] + } + } + + if v >= 3.0 { + calls, globals = args.ParseV3(taskAndVars...) + } else { + calls, globals = args.ParseV2(taskAndVars...) + } + + globals.Set("CLI_ARGS", taskfile.Var{Static: strings.Join(otherArgs, " ")}) + e.Taskfile.Vars.Merge(globals) + + if !options.Watch { + e.InterceptInterruptSignals() + } + + ctx := context.Background() + + if options.Status { + return e.Status(ctx, calls...) + } + + if err := e.Run(ctx, calls...); err != nil { + pterm.Error.Println(err.Error()) + + if options.ExitCode { + if err, ok := err.(*task.TaskRunError); ok { + os.Exit(err.ExitCode()) + } + } + os.Exit(1) + } return nil } diff --git a/v3/internal/commands/task_test.go b/v3/internal/commands/task_test.go index df365c99c..a88304272 100644 --- a/v3/internal/commands/task_test.go +++ b/v3/internal/commands/task_test.go @@ -4,7 +4,8 @@ import "testing" func TestBuild(t *testing.T) { type args struct { - options *RunTaskOptions + options *RunTaskOptions + otherArgs []string } tests := []struct { name string @@ -30,7 +31,7 @@ func TestBuild(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := RunTask(tt.args.options); (err != nil) != tt.wantErr { + if err := RunTask(tt.args.options, tt.args.otherArgs); (err != nil) != tt.wantErr { t.Errorf("Run() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/v3/internal/flags/build.go b/v3/internal/flags/build.go new file mode 100644 index 000000000..260c6067d --- /dev/null +++ b/v3/internal/flags/build.go @@ -0,0 +1,5 @@ +package flags + +type Build struct { + Common +}