github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/cmd/cli/cli.go (about) 1 // Copyright 2022 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package cli 15 16 import ( 17 "fmt" 18 "io" 19 "os" 20 21 "github.com/chzyer/readline" 22 "github.com/mattn/go-shellwords" 23 "github.com/pingcap/tiflow/engine/pkg/cmd/util" 24 ticdcutil "github.com/pingcap/tiflow/pkg/cmd/util" 25 "github.com/spf13/cobra" 26 ) 27 28 // options defines flags for the `cli` command. 29 type options struct { 30 interact bool 31 } 32 33 // newOptions creates new options for the `cli` command. 34 func newOptions() *options { 35 return &options{} 36 } 37 38 // addFlags receives a *cobra.Command reference and binds 39 // flags related to template printing to it. 40 func (o *options) addFlags(c *cobra.Command) { 41 if o == nil { 42 return 43 } 44 c.PersistentFlags().BoolVarP(&o.interact, "interact", "i", false, "Run cdc cli with readline") 45 } 46 47 // NewCmdCli creates the `cli` command. 48 func NewCmdCli() *cobra.Command { 49 o := newOptions() 50 51 cmds := &cobra.Command{ 52 Use: "cli", 53 Short: "Manage jobs and dataflow engine cluster", 54 PersistentPreRunE: func(cmd *cobra.Command, args []string) error { 55 // Initialize signal handler set the current default context. 56 util.InitCmd(cmd) 57 ticdcutil.LogHTTPProxies() 58 return nil 59 }, 60 Args: cobra.NoArgs, 61 RunE: func(cmd *cobra.Command, args []string) error { 62 // Whether to run interactively or not. 63 if o.interact { 64 run() 65 return nil 66 } 67 return cmd.Help() 68 }, 69 } 70 71 // Binding the `cli` command flags. 72 o.addFlags(cmds) 73 74 // Add subcommands. 75 cmds.AddCommand(newCmdJob()) 76 77 return cmds 78 } 79 80 func run() { 81 l, err := readline.NewEx(&readline.Config{ 82 Prompt: "\033[31m»\033[0m ", 83 HistoryFile: "/tmp/readline.tmp", 84 InterruptPrompt: "^C", 85 EOFPrompt: "^D", 86 HistorySearchFold: true, 87 }) 88 if err != nil { 89 panic(err) 90 } 91 defer l.Close() 92 93 for { 94 line, err := l.Readline() 95 if err != nil { 96 if err == readline.ErrInterrupt { 97 break 98 } else if err == io.EOF { 99 break 100 } 101 continue 102 } 103 if line == "exit" { 104 os.Exit(0) 105 } 106 args, err := shellwords.Parse(line) 107 if err != nil { 108 fmt.Printf("parse command err: %v\n", err) 109 continue 110 } 111 112 command := NewCmdCli() 113 command.SetArgs(args) 114 _ = command.ParseFlags(args) 115 command.SetOut(os.Stdout) 116 command.SetErr(os.Stdout) 117 if err = command.Execute(); err != nil { 118 command.Println(err) 119 } 120 } 121 }