Skip to content

Commit

Permalink
added TasksParsed and TasksPostCleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
hedzr committed Nov 25, 2024
1 parent a38e2be commit 8f82f67
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 13 deletions.
4 changes: 3 additions & 1 deletion cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,17 @@ type Config struct {
TasksAfterXref []Task `json:"-"` // while command linked and xref'd, it's time to insert user-defined commands dynamically.
TasksAfterLoader []Task `json:"-"` // while external loaders loaded.
TasksBeforeParse []Task `json:"-"` // globally pre-parse tasks
TasksParsed []Task `json:"-"` // globally post-parse tasks
TasksBeforeRun []Task `json:"-"` // globally pre-run tasks, it's also used as TasksAfterParsed
TasksAfterRun []Task `json:"-"` // globally post-run tasks
TasksPostCleanup []Task `json:"-"` // globally post-run tasks, specially for cleanup actions
Loaders []Loader `json:"-"` // external loaders. use cli.WithLoader() prefer
HelpScreenWriter HelpWriter `json:"help_screen_writer,omitempty"` // redirect stdout for help screen printing
DebugScreenWriter HelpWriter `json:"debug_screen_writer,omitempty"` // redirect stdout for debugging outputs
Args []string `json:"args,omitempty"` // for testing
Env map[string]string `json:"env,omitempty"` // inject env var & values
AutoEnv bool `json:"auto_env,omitempty"` // enable envvars auto-binding?
AutoEnvPrefix string `json:"auto_env_prefix,omitempty"` // envvars auto-binding prefix
AutoEnvPrefix string `json:"auto_env_prefix,omitempty"` // envvars auto-binding prefix, bind them to corresponding flags
}

// Opt for cmdr system
Expand Down
2 changes: 1 addition & 1 deletion cli/worker/pre.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (w *workerS) preEnvSet(ctx context.Context) {
}

func (w *workerS) postEnvLoad(ctx context.Context) {
// logz.InfoContext(ctx, "postEnvLoad()", "FORCE_DEFAULT_ACTION", os.Getenv("FORCE_DEFAULT_ACTION"))
logz.VerboseContext(ctx, "postEnvLoad()", "FORCE_DEFAULT_ACTION", os.Getenv("FORCE_DEFAULT_ACTION"))
if w.Store().Has("app.force-default-action") {
w.ForceDefaultAction = w.Store().MustBool("app.force-default-action", false)
logz.VerboseContext(ctx, "postEnvLoad() - reset forceDefaultAction from store value", "ForceDefaultAction", w.ForceDefaultAction)
Expand Down
2 changes: 2 additions & 0 deletions cli/worker/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,11 @@ func (w *workerS) Run(ctx context.Context, opts ...cli.Opt) (err error) {
defer func() { w.attachError(w.postProcess(ctx, pc)) }()
if w.invokeTasks(ctx, pc, w.errs, w.Config.TasksBeforeParse...) ||
w.attachError(w.parse(ctx, pc)) ||
w.invokeTasks(ctx, pc, w.errs, w.Config.TasksParsed...) ||
w.invokeTasks(ctx, pc, w.errs, w.Config.TasksBeforeRun...) ||
w.attachError(w.exec(ctx, pc)) ||
w.invokeTasks(ctx, pc, w.errs, w.Config.TasksAfterRun...) ||
w.invokeTasks(ctx, pc, w.errs, w.Config.TasksPostCleanup...) ||
dummy() {
// any errors occurred
return
Expand Down
82 changes: 71 additions & 11 deletions cmdr.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,41 @@ func WithStore(conf store.Store) cli.Opt {
}
}

// WithExternalLoaders sets the loaders of external sources, which will be loaded
// at cmdr's preparing time (xref-building time).
//
// The orders could be referred as:
//
// - constructing cmdr commands system (by your prepareApp)
// - entering cmdr.Run
// - cmdr preparing stage
// - build commands and flags xref
// - load and apply envvars if matched
// - load external sources
// - post preparing time
//
// - cmdr parsing stage
// - cmdr invoking stage
// - cmdr cleanup stage
//
// Using our loaders repo is a good idea: https://github.com/hedzr/cmdr-loaders
//
// Typical app:
//
// app = cmdr.New(opts...).
// Info("tiny-app", "0.3.1").
// Author("The Example Authors") // .Description(``).Header(``).Footer(``)
// cmdr.WithStore(store.New()), // use an option store explicitly, or a dummy store by default
//
// cmdr.WithExternalLoaders(
// local.NewConfigFileLoader(), // import "github.com/hedzr/cmdr-loaders/local" to get in advanced external loading features
// local.NewEnvVarLoader(),
// ),
// )
// if err := app.Run(ctx); err != nil {
// logz.ErrorContext(ctx, "Application Error:", "err", err) // stacktrace if in debug mode/build
// os.Exit(app.SuggestRetCode())
// }
func WithExternalLoaders(loaders ...cli.Loader) cli.Opt {
return func(s *cli.Config) {
s.Loaders = append(s.Loaders, loaders...)
Expand All @@ -221,6 +256,17 @@ func WithTasksBeforeParse(tasks ...cli.Task) cli.Opt {
}
}

// WithTasksParsed installs callbacks after parsing stage.
//
// The internal stages are: initial -> preload + xref -> parse -> run/invoke -> post-actions.
//
// Another way is disabling cmdr default executing/run/invoke stage by WithDontExecuteAction(true).
func WithTasksParsed(tasks ...cli.Task) cli.Opt {
return func(s *cli.Config) {
s.TasksParsed = append(s.TasksParsed, tasks...)
}
}

// WithTasksBeforeRun installs callbacks before run/invoke stage.
//
// The internal stages are: initial -> preload + xref -> parse -> run/invoke -> post-actions.
Expand All @@ -230,15 +276,38 @@ func WithTasksBeforeParse(tasks ...cli.Task) cli.Opt {
// - preload & xref
// - <tasksBeforeParse>
// - parse
// - <tasksParsed>
// - <tasksBeforeRun> ( = tasksAfterParse )
// - exec (run/invoke)
// - <tasksAfterRun>
// - <tasksPostCleanup>
// - basics.closers...Close()
func WithTasksBeforeRun(tasks ...cli.Task) cli.Opt {
return func(s *cli.Config) {
s.TasksBeforeRun = append(s.TasksBeforeRun, tasks...)
}
}

// WithTasksAfterRun installs callbacks after run/invoke stage.
//
// The internal stages are: initial -> preload + xref -> parse -> run/invoke -> post-actions.
func WithTasksAfterRun(tasks ...cli.Task) cli.Opt {
return func(s *cli.Config) {
s.TasksAfterRun = append(s.TasksAfterRun, tasks...)
}
}

// WithTasksPostCleanup install callbacks at cmdr ending.
//
// See the stagings order introduce at [WithTasksBeforeRun].
//
// See also WithTasksSetupPeripherals, WithPeripherals.
func WithTasksPostCleanup(tasks ...cli.Task) cli.Opt {
return func(s *cli.Config) {
s.TasksPostCleanup = append(s.TasksPostCleanup, tasks...)
}
}

// WithTasksSetupPeripherals gives a special chance to setup
// your server's peripherals (such as database, redis, message
// queues, or others).
Expand All @@ -256,8 +325,8 @@ func WithTasksBeforeRun(tasks ...cli.Task) cli.Opt {
// import "github.com/hedzr/is/basics"
// type Obj struct{}
// func (o *Obj) Init(context.Context) *Obj { return o } // initialize itself
// func (o *Obj) Close(){...} // destory itself
// app := cmdr.New(cmdr.WithTasksSetupPeripherals(func(ctx context.Context, cmd *CmdS, runner Runner, extras ...any) (err error) {
// func (o *Obj) Close(){...} // destroy itself
// app := cmdr.New(cmdr.WithTasksSetupPeripherals(func(ctx context.Context, cmd cli.Cmd, runner cli.Runner, extras ...any) (err error) {
// obj := new(Obj)
// basics.RegisterPeripheral(obj.Init(ctx)) // initialize obj at first, and register it to basics.Closers for auto-shutting-down
// return
Expand Down Expand Up @@ -286,15 +355,6 @@ func WithPeripherals(peripherals ...basics.Peripheral) cli.Opt {
}
}

// WithTasksAfterRun installs callbacks after run/invoke stage.
//
// The internal stages are: initial -> preload + xref -> parse -> run/invoke -> post-actions.
func WithTasksAfterRun(tasks ...cli.Task) cli.Opt {
return func(s *cli.Config) {
s.TasksAfterRun = append(s.TasksAfterRun, tasks...)
}
}

func WithSortInHelpScreen(b bool) cli.Opt {
return func(s *cli.Config) {
s.SortInHelpScreen = b
Expand Down

0 comments on commit 8f82f67

Please sign in to comment.