wip: checkpoint before v0.3.3 parity rewrite
Cli as service with ServiceRuntime, incomplete. Need to properly port v0.3.3 service_manager, message_bus, WithService with full name/IPC discovery. Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
f69be963bc
commit
198ab839a8
3 changed files with 43 additions and 34 deletions
53
cli.go
53
cli.go
|
|
@ -1,7 +1,6 @@
|
|||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
// Cli is the CLI surface layer for the Core command tree.
|
||||
// It reads commands from Core's registry and wires them to terminal I/O.
|
||||
//
|
||||
// c := core.New(core.WithOption("name", "myapp")).Value.(*Core)
|
||||
// c.Command("deploy", core.Command{Action: handler})
|
||||
|
|
@ -13,18 +12,23 @@ import (
|
|||
"os"
|
||||
)
|
||||
|
||||
// CliOptions holds configuration for the Cli service.
|
||||
type CliOptions struct{}
|
||||
|
||||
// Cli is the CLI surface for the Core command tree.
|
||||
type Cli struct {
|
||||
core *Core
|
||||
*ServiceRuntime[CliOptions]
|
||||
output io.Writer
|
||||
banner func(*Cli) string
|
||||
}
|
||||
|
||||
// New creates a Cli bound to a Core instance.
|
||||
// Register creates a Cli service factory for core.WithService.
|
||||
//
|
||||
// cli := core.Cli{}.New(c)
|
||||
func (cl Cli) New(c *Core) *Cli {
|
||||
return &Cli{core: c, output: os.Stdout}
|
||||
// core.New(core.WithService(core.CliRegister))
|
||||
func CliRegister(c *Core) Result {
|
||||
cl := &Cli{output: os.Stdout}
|
||||
cl.ServiceRuntime = NewServiceRuntime[CliOptions](c, CliOptions{})
|
||||
return c.RegisterService("cli", cl)
|
||||
}
|
||||
|
||||
// Print writes to the CLI output (defaults to os.Stdout).
|
||||
|
|
@ -51,17 +55,18 @@ func (cl *Cli) Run(args ...string) Result {
|
|||
}
|
||||
|
||||
clean := FilterArgs(args)
|
||||
c := cl.Core()
|
||||
|
||||
if cl.core == nil || cl.core.commands == nil {
|
||||
if c == nil || c.commands == nil {
|
||||
if cl.banner != nil {
|
||||
cl.Print(cl.banner(cl))
|
||||
}
|
||||
return Result{}
|
||||
}
|
||||
|
||||
cl.core.commands.mu.RLock()
|
||||
cmdCount := len(cl.core.commands.commands)
|
||||
cl.core.commands.mu.RUnlock()
|
||||
c.commands.mu.RLock()
|
||||
cmdCount := len(c.commands.commands)
|
||||
c.commands.mu.RUnlock()
|
||||
|
||||
if cmdCount == 0 {
|
||||
if cl.banner != nil {
|
||||
|
|
@ -74,16 +79,16 @@ func (cl *Cli) Run(args ...string) Result {
|
|||
var cmd *Command
|
||||
var remaining []string
|
||||
|
||||
cl.core.commands.mu.RLock()
|
||||
c.commands.mu.RLock()
|
||||
for i := len(clean); i > 0; i-- {
|
||||
path := JoinPath(clean[:i]...)
|
||||
if c, ok := cl.core.commands.commands[path]; ok {
|
||||
cmd = c
|
||||
if found, ok := c.commands.commands[path]; ok {
|
||||
cmd = found
|
||||
remaining = clean[i:]
|
||||
break
|
||||
}
|
||||
}
|
||||
cl.core.commands.mu.RUnlock()
|
||||
c.commands.mu.RUnlock()
|
||||
|
||||
if cmd == nil {
|
||||
if cl.banner != nil {
|
||||
|
|
@ -121,13 +126,14 @@ func (cl *Cli) Run(args ...string) Result {
|
|||
//
|
||||
// c.Cli().PrintHelp()
|
||||
func (cl *Cli) PrintHelp() {
|
||||
if cl.core == nil || cl.core.commands == nil {
|
||||
c := cl.Core()
|
||||
if c == nil || c.commands == nil {
|
||||
return
|
||||
}
|
||||
|
||||
name := ""
|
||||
if cl.core.app != nil {
|
||||
name = cl.core.app.Name
|
||||
if c.app != nil {
|
||||
name = c.app.Name
|
||||
}
|
||||
if name != "" {
|
||||
cl.Print("%s commands:", name)
|
||||
|
|
@ -135,14 +141,14 @@ func (cl *Cli) PrintHelp() {
|
|||
cl.Print("Commands:")
|
||||
}
|
||||
|
||||
cl.core.commands.mu.RLock()
|
||||
defer cl.core.commands.mu.RUnlock()
|
||||
c.commands.mu.RLock()
|
||||
defer c.commands.mu.RUnlock()
|
||||
|
||||
for path, cmd := range cl.core.commands.commands {
|
||||
for path, cmd := range c.commands.commands {
|
||||
if cmd.Hidden || (cmd.Action == nil && cmd.Lifecycle == nil) {
|
||||
continue
|
||||
}
|
||||
tr := cl.core.I18n().Translate(cmd.I18nKey())
|
||||
tr := c.I18n().Translate(cmd.I18nKey())
|
||||
desc, _ := tr.Value.(string)
|
||||
if desc == "" || desc == cmd.I18nKey() {
|
||||
cl.Print(" %s", path)
|
||||
|
|
@ -164,8 +170,9 @@ func (cl *Cli) Banner() string {
|
|||
if cl.banner != nil {
|
||||
return cl.banner(cl)
|
||||
}
|
||||
if cl.core != nil && cl.core.app != nil && cl.core.app.Name != "" {
|
||||
return cl.core.app.Name
|
||||
c := cl.Core()
|
||||
if c != nil && c.app != nil && c.app.Name != "" {
|
||||
return c.app.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,9 @@ func New(opts ...CoreOption) Result {
|
|||
commands: &commandRegistry{commands: make(map[string]*Command)},
|
||||
}
|
||||
c.context, c.cancel = context.WithCancel(context.Background())
|
||||
c.cli = Cli{}.New(c)
|
||||
|
||||
// Core services
|
||||
CliRegister(c)
|
||||
|
||||
for _, opt := range opts {
|
||||
if r := opt(c); !r.OK {
|
||||
|
|
|
|||
20
core.go
20
core.go
|
|
@ -15,15 +15,15 @@ import (
|
|||
|
||||
// Core is the central application object that manages services, assets, and communication.
|
||||
type Core struct {
|
||||
options *Options // c.Options() — Input configuration used to create this Core
|
||||
app *App // c.App() — Application identity + optional GUI runtime
|
||||
data *Data // c.Data() — Embedded/stored content from packages
|
||||
drive *Drive // c.Drive() — Resource handle registry (transports)
|
||||
fs *Fs // c.Fs() — Local filesystem I/O (sandboxable)
|
||||
config *Config // c.Config() — Configuration, settings, feature flags
|
||||
error *ErrorPanic // c.Error() — Panic recovery and crash reporting
|
||||
log *ErrorLog // c.Log() — Structured logging + error wrapping
|
||||
cli *Cli // c.Cli() — CLI surface layer
|
||||
options *Options // c.Options() — Input configuration used to create this Core
|
||||
app *App // c.App() — Application identity + optional GUI runtime
|
||||
data *Data // c.Data() — Embedded/stored content from packages
|
||||
drive *Drive // c.Drive() — Resource handle registry (transports)
|
||||
fs *Fs // c.Fs() — Local filesystem I/O (sandboxable)
|
||||
config *Config // c.Config() — Configuration, settings, feature flags
|
||||
error *ErrorPanic // c.Error() — Panic recovery and crash reporting
|
||||
log *ErrorLog // c.Log() — Structured logging + error wrapping
|
||||
// cli accessed via ServiceFor[*Cli](c, "cli")
|
||||
commands *commandRegistry // c.Command("path") — Command tree
|
||||
services *serviceRegistry // c.Service("name") — Service registry
|
||||
lock *Lock // c.Lock("name") — Named mutexes
|
||||
|
|
@ -49,7 +49,7 @@ func (c *Core) Fs() *Fs { return c.fs }
|
|||
func (c *Core) Config() *Config { return c.config }
|
||||
func (c *Core) Error() *ErrorPanic { return c.error }
|
||||
func (c *Core) Log() *ErrorLog { return c.log }
|
||||
func (c *Core) Cli() *Cli { return c.cli }
|
||||
func (c *Core) Cli() *Cli { return cli.New() }
|
||||
func (c *Core) IPC() *Ipc { return c.ipc }
|
||||
func (c *Core) I18n() *I18n { return c.i18n }
|
||||
func (c *Core) Env(key string) string { return Env(key) }
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue