refactor to decouple commands form entrypoint for reusability and centralizing commands.

Increase reusability and composition
This commit is contained in:
Robin Olsen
2026-02-22 19:46:55 +01:00
parent 118e67dbf4
commit 33c8c05ae3
28 changed files with 305 additions and 282 deletions

View File

@@ -3,12 +3,24 @@ package main
import (
"context"
issuesCmd "github.com/LazyBachelor/LazyPM/internal/commands/issues"
surveyCmd "github.com/LazyBachelor/LazyPM/internal/commands/survey"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/cli"
)
func main() {
if err := cli.NewCli().Run(context.Background(), service.BaseConfig); err != nil {
if err := cli.NewCli(issuesCmd.RootCmd).Run(context.Background(), service.BaseConfig); err != nil {
return
}
}
func init() {
issuesCmd.RootCmd.AddCommand(issuesCmd.GetCmd)
issuesCmd.RootCmd.AddCommand(issuesCmd.ListCmd)
issuesCmd.RootCmd.AddCommand(issuesCmd.CloseCmd)
issuesCmd.RootCmd.AddCommand(issuesCmd.CreateCmd)
issuesCmd.RootCmd.AddCommand(issuesCmd.DeleteCmd)
issuesCmd.RootCmd.AddCommand(issuesCmd.UpdateCmd)
issuesCmd.RootCmd.AddCommand(surveyCmd.StatusCmd)
}

View File

@@ -1,98 +0,0 @@
package main
import (
"fmt"
"github.com/LazyBachelor/LazyPM/pkg/task"
"github.com/spf13/cobra"
)
var interfaceType string
var stage int
var rootCmd = &cobra.Command{
Use: "survey",
Long: `Project Management Interface Survey
Thank you for participating in our survey!
We are gathering data on how users interact with different task management interfaces to better understand their preferences and compare their usability.
This survey will present you with a series of tasks to complete using various interfaces, including command-line, web-based, and terminal user interfaces.
Please answer the questions honestly and to the best of your ability.
Your responses will be kept confidential and used solely for research purposes.`}
var startCmd = &cobra.Command{
Use: "start",
Short: "Start the user survey",
RunE: runStartCmd,
}
var submitCmd = &cobra.Command{
Use: "submit",
Short: "Submit your survey responses",
RunE: func(cmd *cobra.Command, args []string) error {
cmd.Println("Submitting responses and metrics...")
return nil
},
}
func runStartCmd(cmd *cobra.Command, args []string) error {
interfaces := initInterfaces()
svc, cleanup, err := initializeServices(cmd.Context())
if err != nil {
return returnIfUserQuit(err, "failed to initialize services")
}
defer cleanup()
surveyTasks := initTasks(svc)
if cmd.Flags().Changed("interface") {
if _, ok := interfaces[interfaceType]; !ok {
return fmt.Errorf("invalid interface, valid are (tui, repl, web)")
}
interfaces = map[string]task.Interface{
interfaceType: interfaces[interfaceType],
}
}
if cmd.Flags().Changed("stage") {
if stage < 1 || stage > len(surveyTasks) {
return fmt.Errorf("invalid stage")
}
if err := runTask(cmd.Context(), surveyTasks[stage-1], interfaces[interfaceType]); err != nil {
return err
}
return nil
}
if err := newIntroModel().Run(); err != nil {
return returnIfUserQuit(err, "failed to run intro")
}
if err := taskLoop(cmd.Context(), surveyTasks, interfaces); err != nil {
return returnIfUserQuit(err, "task loop failed")
}
return nil
}
var listCmd = &cobra.Command{
Use: "list",
Short: "List available tasks",
RunE: func(cmd *cobra.Command, args []string) error {
for i, name := range task.List() {
cmd.Printf("%d. %s\n", i+1, name)
}
return nil
},
}
func init() {
rootCmd.CompletionOptions.DisableDefaultCmd = true
startCmd.Flags().StringVarP(&interfaceType, "interface", "i", "tui", "Specify interface.")
startCmd.Flags().IntVarP(&stage, "stage", "s", 1, "Run stage directly")
rootCmd.AddCommand(startCmd)
rootCmd.AddCommand(submitCmd)
rootCmd.AddCommand(listCmd)
}

View File

@@ -3,14 +3,33 @@ package main
import (
"context"
"github.com/LazyBachelor/LazyPM/cmd/survey/tasks"
"github.com/LazyBachelor/LazyPM/internal/commands/survey"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/task"
"github.com/charmbracelet/fang"
)
func main() {
ctx := context.Background()
if err := fang.Execute(ctx, rootCmd,
if err := fang.Execute(ctx, surveyCmd.RootCmd,
fang.WithColorSchemeFunc(fang.AnsiColorScheme)); err != nil {
return
}
}
func init() {
surveyCmd.StartCmd.RunE = runStartCmd
surveyCmd.RootCmd.AddCommand(surveyCmd.StartCmd)
surveyCmd.RootCmd.AddCommand(surveyCmd.SubmitCmd)
surveyCmd.RootCmd.AddCommand(surveyCmd.StatusCmd)
surveyCmd.RootCmd.AddCommand(surveyCmd.ListCmd)
task.Register("create_issue", func(app *service.App) task.Tasker {
return tasks.NewCreateIssueTask(app)
})
task.Register("coding_task", func(app *service.App) task.Tasker {
return tasks.NewCodingTask(app)
})
}

View File

@@ -7,28 +7,67 @@ import (
"math/rand"
"github.com/LazyBachelor/LazyPM/cmd/survey/tasks"
surveyCmd "github.com/LazyBachelor/LazyPM/internal/commands/survey"
"github.com/LazyBachelor/LazyPM/pkg/task"
"github.com/spf13/cobra"
)
func runTask(ctx context.Context, t task.Tasker, i task.Interface) error {
return task.RunTask(ctx, t, i, tasks.InterfaceToType(i))
func runStartCmd(cmd *cobra.Command, args []string) error {
interfaces := initInterfaces()
svc, cleanup, err := initializeServices(cmd.Context())
if err != nil {
return returnIfUserQuit(err, "failed to initialize services")
}
defer cleanup()
surveyTasks := initTasks(svc)
if cmd.Flags().Changed("interface") {
if _, ok := interfaces[surveyCmd.InterfaceType]; !ok {
return fmt.Errorf("invalid interface, valid are (tui, repl, web)")
}
interfaces = map[string]task.Interface{
surveyCmd.InterfaceType: interfaces[surveyCmd.InterfaceType],
}
}
if cmd.Flags().Changed("stage") {
if surveyCmd.Task < 1 || surveyCmd.Task > len(surveyTasks) {
return fmt.Errorf("invalid stage")
}
if err := task.RunTask(cmd.Context(), surveyTasks[surveyCmd.Task-1],
interfaces[surveyCmd.InterfaceType], tasks.InterfaceToType(interfaces[surveyCmd.InterfaceType])); err != nil {
return err
}
return nil
}
if err := newIntroModel().Run(); err != nil {
return returnIfUserQuit(err, "failed to run intro")
}
if err := taskLoop(cmd.Context(), surveyTasks, interfaces); err != nil {
return returnIfUserQuit(err, "task loop failed")
}
return nil
}
func taskLoop(ctx context.Context, surveyTasks []task.Tasker, interfaces map[string]task.Interface) error {
var ifaceNames []string
var iNames []string
for name := range interfaces {
ifaceNames = append(ifaceNames, name)
iNames = append(iNames, name)
}
rand.Shuffle(len(ifaceNames), func(i, j int) {
ifaceNames[i], ifaceNames[j] = ifaceNames[j], ifaceNames[i]
rand.Shuffle(len(iNames), func(i, j int) {
iNames[i], iNames[j] = iNames[j], iNames[i]
})
for i, t := range surveyTasks {
idx := i % len(ifaceNames)
selected := interfaces[ifaceNames[idx]]
idx := i % len(iNames)
selected := interfaces[iNames[idx]]
if err := runTask(ctx, t, selected); err != nil {
if err := task.RunTask(ctx, t, selected, tasks.InterfaceToType(selected)); err != nil {
return err
}
}

View File

@@ -2,7 +2,7 @@ package tasks
import (
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/cli/repl"
"github.com/LazyBachelor/LazyPM/pkg/repl"
"github.com/LazyBachelor/LazyPM/pkg/task"
taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui"
"github.com/LazyBachelor/LazyPM/pkg/tui"