Skip to content

Commit

Permalink
Fix go-prompt caused bash hijack
Browse files Browse the repository at this point in the history
Signed-off-by: Congqi Xia <[email protected]>
  • Loading branch information
congqixia committed Dec 13, 2022
1 parent ee1d59f commit 664a214
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 11 deletions.
31 changes: 25 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,18 @@ var (
)

func main() {
defer handleExit()
app := states.Start()
runPrompt(app)
}

func handleExit() {
rawModeOff := exec.Command("/bin/stty", "-raw", "echo")
rawModeOff.Stdin = os.Stdin
_ = rawModeOff.Run()
rawModeOff.Wait()
}

// run start BirdWatcher with promptui. (disable suggestion and history)
func run(app states.State) {
for {
Expand All @@ -45,13 +53,13 @@ func run(app states.State) {

// promptApp model wraps states to provide function for go-prompt.
type promptApp struct {
exited bool
currentState states.State
}

// promptExecute actual execution logic entry.
func (a *promptApp) promptExecute(in string) {
in = strings.TrimSpace(in)
var err error

// try to get $PAGER env
pager := os.Getenv("PAGER")
Expand Down Expand Up @@ -93,10 +101,10 @@ func (a *promptApp) promptExecute(in string) {
}()
}
}

a.currentState, err = a.currentState.Process(in)
if errors.Is(err, states.ExitErr) {
os.Exit(0)
a.currentState, _ = a.currentState.Process(in)
if a.currentState.IsEnding() {
fmt.Println("Bye!")
a.exited = true
}
}

Expand All @@ -119,6 +127,9 @@ func (a *promptApp) completeInput(d prompt.Document) []prompt.Suggest {

// livePrefix implements dynamic change prefix.
func (a *promptApp) livePrefix() (string, bool) {
if a.exited {
return "", false
}
return fmt.Sprintf("%s > ", a.currentState.Label()), true
}

Expand All @@ -132,6 +143,14 @@ func runPrompt(app states.State) {
prompt.OptionPrefixTextColor(prompt.Yellow),
prompt.OptionPreviewSuggestionTextColor(prompt.Blue),
prompt.OptionSelectedSuggestionBGColor(prompt.LightGray),
prompt.OptionSuggestionBGColor(prompt.DarkGray))
prompt.OptionSuggestionBGColor(prompt.DarkGray),
prompt.OptionSetExitCheckerOnInput(func(in string, breakline bool) bool {
// setup exit command
if strings.ToLower(in) == "exit" && breakline {
return true
}
return false
}),
)
p.Run()
}
4 changes: 4 additions & 0 deletions states/exit.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func getExitCmd(state State) *cobra.Command {
Aliases: []string{"quit"},
RunE: func(*cobra.Command, []string) error {
state.SetNext(&exitState{})
// cannot return ExitErr here to avoid print help message
return nil
},
}
Expand All @@ -36,6 +37,9 @@ type exitState struct {
// also called after each command run to reset flag values.
func (s *exitState) SetupCommands() {}

// IsEnding returns true for exit State
func (s *exitState) IsEnding() bool { return true }

// getDisconnectCmd disconnect from current state.
// will call close method for current state.
func getDisconnectCmd(state State) *cobra.Command {
Expand Down
15 changes: 10 additions & 5 deletions states/states.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package states

import (
"errors"
"fmt"
"strings"

Expand All @@ -16,6 +17,7 @@ type State interface {
SetNext(state State)
Suggestions(input string) map[string]string
SetupCommands()
IsEnding() bool
}

// cmdState is the basic state to process input command.
Expand Down Expand Up @@ -133,15 +135,13 @@ func (s *cmdState) Process(cmd string) (State, error) {
}
s.rootCmd.SetArgs(args)
err = s.rootCmd.Execute()
if errors.Is(err, ExitErr) {
return s.nextState, ExitErr
}
if err != nil {
return s, err
}
if s.nextState != nil {
//defer s.Close()
// TODO fix ugly type cast
if _, ok := s.nextState.(*exitState); ok {
return s.nextState, ExitErr
}
nextState := s.nextState
s.nextState = nil
return nextState, nil
Expand All @@ -160,6 +160,9 @@ func (s *cmdState) SetNext(state State) {
// Close empty method to implement State.
func (s *cmdState) Close() {}

// Check
func (s *cmdState) IsEnding() bool { return false }

// Start returns the first state - offline.
func Start() State {
root := &cobra.Command{
Expand All @@ -177,6 +180,8 @@ func Start() State {
getConnectCommand(state),
// load-backup
getLoadBackupCmd(state),
// pulsarctl
getPulsarctlCmd(state),
// exit
getExitCmd(state))

Expand Down

0 comments on commit 664a214

Please sign in to comment.