99 lines
1.9 KiB
Go
99 lines
1.9 KiB
Go
package repl
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/c-bata/go-prompt"
|
|
"github.com/spf13/cobra"
|
|
"gitlink.org.cn/cloudream/common/pkgs/async"
|
|
"gitlink.org.cn/cloudream/jcs-pub/coordinator/internal/accesstoken"
|
|
"gitlink.org.cn/cloudream/jcs-pub/coordinator/internal/db"
|
|
"gitlink.org.cn/cloudream/jcs-pub/coordinator/internal/ticktock"
|
|
"golang.org/x/term"
|
|
)
|
|
|
|
var (
|
|
cmdCtxKey = &CommandContext{}
|
|
)
|
|
|
|
type ReplEventChan = async.UnboundChannel[ReplEvent]
|
|
|
|
type ReplEvent interface {
|
|
IsReplEvent() bool
|
|
}
|
|
|
|
type ExitEvent struct {
|
|
ReplEvent
|
|
}
|
|
|
|
type Repl struct {
|
|
prompt *prompt.Prompt
|
|
evtCh *ReplEventChan
|
|
db *db.DB
|
|
tktk *ticktock.TickTock
|
|
accessToken *accesstoken.Cache
|
|
}
|
|
|
|
func New(db *db.DB, ticktock *ticktock.TickTock, accessToken *accesstoken.Cache) *Repl {
|
|
r := &Repl{
|
|
evtCh: async.NewUnboundChannel[ReplEvent](),
|
|
db: db,
|
|
tktk: ticktock,
|
|
accessToken: accessToken,
|
|
}
|
|
return r
|
|
}
|
|
|
|
func (r *Repl) Start() *ReplEventChan {
|
|
go func() {
|
|
if term.IsTerminal(int(os.Stdin.Fd())) {
|
|
r.prompt = prompt.New(
|
|
r.executor,
|
|
r.completer,
|
|
prompt.OptionPrefix(">>> "),
|
|
prompt.OptionTitle("JCS Coordinator REPL"),
|
|
prompt.OptionSetExitCheckerOnInput(r.exitChecker),
|
|
)
|
|
r.prompt.Run()
|
|
r.evtCh.Send(ExitEvent{})
|
|
}
|
|
}()
|
|
return r.evtCh
|
|
}
|
|
|
|
func (r *Repl) completer(d prompt.Document) []prompt.Suggest {
|
|
return nil
|
|
}
|
|
|
|
func (r *Repl) executor(input string) {
|
|
fields := strings.Fields(input)
|
|
if len(fields) == 0 {
|
|
return
|
|
}
|
|
|
|
RootCmd.SetArgs(fields)
|
|
RootCmd.ExecuteContext(context.WithValue(context.Background(), cmdCtxKey, &CommandContext{
|
|
repl: r,
|
|
}))
|
|
}
|
|
|
|
func (r *Repl) exitChecker(input string, breakline bool) bool {
|
|
if breakline && input == "exit" {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
var RootCmd = &cobra.Command{}
|
|
|
|
type CommandContext struct {
|
|
repl *Repl
|
|
}
|
|
|
|
func GetCmdCtx(cmd *cobra.Command) *CommandContext {
|
|
return cmd.Context().Value(cmdCtxKey).(*CommandContext)
|
|
}
|