github.com/rakutentech/cli@v6.12.5-0.20151006231303-24468b65536e+incompatible/cf/terminal/ui.go (about)

     1  package terminal
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"strings"
     8  	"time"
     9  
    10  	. "github.com/cloudfoundry/cli/cf/i18n"
    11  
    12  	"github.com/cloudfoundry/cli/cf"
    13  	"github.com/cloudfoundry/cli/cf/configuration/core_config"
    14  	"github.com/cloudfoundry/cli/cf/trace"
    15  )
    16  
    17  type ColoringFunction func(value string, row int, col int) string
    18  
    19  func NotLoggedInText() string {
    20  	return fmt.Sprintf(T("Not logged in. Use '{{.CFLoginCommand}}' to log in.", map[string]interface{}{"CFLoginCommand": CommandColor(cf.Name() + " " + "login")}))
    21  }
    22  
    23  type UI interface {
    24  	PrintPaginator(rows []string, err error)
    25  	Say(message string, args ...interface{})
    26  	PrintCapturingNoOutput(message string, args ...interface{})
    27  	Warn(message string, args ...interface{})
    28  	Ask(prompt string, args ...interface{}) (answer string)
    29  	AskForPassword(prompt string, args ...interface{}) (answer string)
    30  	Confirm(message string, args ...interface{}) bool
    31  	ConfirmDelete(modelType, modelName string) bool
    32  	ConfirmDeleteWithAssociations(modelType, modelName string) bool
    33  	Ok()
    34  	Failed(message string, args ...interface{})
    35  	PanicQuietly()
    36  	ShowConfiguration(core_config.Reader)
    37  	LoadingIndication()
    38  	Wait(duration time.Duration)
    39  	Table(headers []string) Table
    40  	NotifyUpdateIfNeeded(core_config.Reader)
    41  }
    42  
    43  type terminalUI struct {
    44  	stdin   io.Reader
    45  	printer Printer
    46  }
    47  
    48  func NewUI(r io.Reader, printer Printer) UI {
    49  	return &terminalUI{
    50  		stdin:   r,
    51  		printer: printer,
    52  	}
    53  }
    54  
    55  func (c *terminalUI) PrintPaginator(rows []string, err error) {
    56  	if err != nil {
    57  		c.Failed(err.Error())
    58  		return
    59  	}
    60  
    61  	for _, row := range rows {
    62  		c.Say(row)
    63  	}
    64  }
    65  
    66  func (c *terminalUI) PrintCapturingNoOutput(message string, args ...interface{}) {
    67  	if len(args) == 0 {
    68  		fmt.Printf("%s", message)
    69  	} else {
    70  		fmt.Printf(message, args...)
    71  	}
    72  }
    73  
    74  func (c *terminalUI) Say(message string, args ...interface{}) {
    75  	if len(args) == 0 {
    76  		c.printer.Printf("%s\n", message)
    77  	} else {
    78  		c.printer.Printf(message+"\n", args...)
    79  	}
    80  }
    81  
    82  func (c *terminalUI) Warn(message string, args ...interface{}) {
    83  	message = fmt.Sprintf(message, args...)
    84  	c.Say(WarningColor(message))
    85  	return
    86  }
    87  
    88  func (c *terminalUI) ConfirmDeleteWithAssociations(modelType, modelName string) bool {
    89  	return c.confirmDelete(T("Really delete the {{.ModelType}} {{.ModelName}} and everything associated with it?",
    90  		map[string]interface{}{
    91  			"ModelType": modelType,
    92  			"ModelName": EntityNameColor(modelName),
    93  		}))
    94  }
    95  
    96  func (c *terminalUI) ConfirmDelete(modelType, modelName string) bool {
    97  	return c.confirmDelete(T("Really delete the {{.ModelType}} {{.ModelName}}?",
    98  		map[string]interface{}{
    99  			"ModelType": modelType,
   100  			"ModelName": EntityNameColor(modelName),
   101  		}))
   102  }
   103  
   104  func (c *terminalUI) confirmDelete(message string) bool {
   105  	result := c.Confirm(message)
   106  
   107  	if !result {
   108  		c.Warn(T("Delete cancelled"))
   109  	}
   110  
   111  	return result
   112  }
   113  
   114  func (c *terminalUI) Confirm(message string, args ...interface{}) bool {
   115  	response := c.Ask(message, args...)
   116  	switch strings.ToLower(response) {
   117  	case "y", "yes", T("yes"):
   118  		return true
   119  	}
   120  	return false
   121  }
   122  
   123  func (c *terminalUI) Ask(prompt string, args ...interface{}) (answer string) {
   124  	fmt.Println("")
   125  	fmt.Printf(prompt+PromptColor(">")+" ", args...)
   126  
   127  	rd := bufio.NewReader(c.stdin)
   128  	line, err := rd.ReadString('\n')
   129  	if err == nil {
   130  		return strings.TrimSpace(line)
   131  	}
   132  	return ""
   133  }
   134  
   135  func (c *terminalUI) Ok() {
   136  	c.Say(SuccessColor(T("OK")))
   137  }
   138  
   139  const QuietPanic = "This shouldn't print anything"
   140  
   141  func (c *terminalUI) Failed(message string, args ...interface{}) {
   142  	message = fmt.Sprintf(message, args...)
   143  
   144  	if T == nil {
   145  		c.Say(FailureColor("FAILED"))
   146  		c.Say(message)
   147  
   148  		trace.Logger.Print("FAILED")
   149  		trace.Logger.Print(message)
   150  		c.PanicQuietly()
   151  	} else {
   152  		c.Say(FailureColor(T("FAILED")))
   153  		c.Say(message)
   154  
   155  		trace.Logger.Print(T("FAILED"))
   156  		trace.Logger.Print(message)
   157  		c.PanicQuietly()
   158  	}
   159  }
   160  
   161  func (c *terminalUI) PanicQuietly() {
   162  	panic(QuietPanic)
   163  }
   164  
   165  func (ui *terminalUI) ShowConfiguration(config core_config.Reader) {
   166  	table := NewTable(ui, []string{"", ""})
   167  
   168  	if config.HasAPIEndpoint() {
   169  		table.Add(
   170  			T("API endpoint:"),
   171  			T("{{.ApiEndpoint}} (API version: {{.ApiVersionString}})",
   172  				map[string]interface{}{
   173  					"ApiEndpoint":      EntityNameColor(config.ApiEndpoint()),
   174  					"ApiVersionString": EntityNameColor(config.ApiVersion()),
   175  				}),
   176  		)
   177  	}
   178  
   179  	if !config.IsLoggedIn() {
   180  		table.Print()
   181  		ui.Say(NotLoggedInText())
   182  		return
   183  	} else {
   184  		table.Add(
   185  			T("User:"),
   186  			EntityNameColor(config.UserEmail()),
   187  		)
   188  	}
   189  
   190  	if !config.HasOrganization() && !config.HasSpace() {
   191  		table.Print()
   192  		command := fmt.Sprintf("%s target -o ORG -s SPACE", cf.Name())
   193  		ui.Say(T("No org or space targeted, use '{{.CFTargetCommand}}'",
   194  			map[string]interface{}{
   195  				"CFTargetCommand": CommandColor(command),
   196  			}))
   197  		return
   198  	}
   199  
   200  	if config.HasOrganization() {
   201  		table.Add(
   202  			T("Org:"),
   203  			EntityNameColor(config.OrganizationFields().Name),
   204  		)
   205  	} else {
   206  		command := fmt.Sprintf("%s target -o Org", cf.Name())
   207  		table.Add(
   208  			T("Org:"),
   209  			T("No org targeted, use '{{.CFTargetCommand}}'",
   210  				map[string]interface{}{
   211  					"CFTargetCommand": CommandColor(command),
   212  				}),
   213  		)
   214  	}
   215  
   216  	if config.HasSpace() {
   217  		table.Add(
   218  			T("Space:"),
   219  			EntityNameColor(config.SpaceFields().Name),
   220  		)
   221  	} else {
   222  		command := fmt.Sprintf("%s target -s SPACE", cf.Name())
   223  		table.Add(
   224  			T("Space:"),
   225  			T("No space targeted, use '{{.CFTargetCommand}}'", map[string]interface{}{"CFTargetCommand": CommandColor(command)}),
   226  		)
   227  	}
   228  
   229  	table.Print()
   230  }
   231  
   232  func (c *terminalUI) LoadingIndication() {
   233  	c.printer.Print(".")
   234  }
   235  
   236  func (c *terminalUI) Wait(duration time.Duration) {
   237  	time.Sleep(duration)
   238  }
   239  
   240  func (ui *terminalUI) Table(headers []string) Table {
   241  	return NewTable(ui, headers)
   242  }
   243  
   244  func (ui *terminalUI) NotifyUpdateIfNeeded(config core_config.Reader) {
   245  	if !config.IsMinCliVersion(cf.Version) {
   246  		ui.Say("")
   247  		ui.Say(T("Cloud Foundry API version {{.ApiVer}} requires CLI version {{.CliMin}}.  You are currently on version {{.CliVer}}. To upgrade your CLI, please visit: https://github.com/cloudfoundry/cli#downloads",
   248  			map[string]interface{}{
   249  				"ApiVer": config.ApiVersion(),
   250  				"CliMin": config.MinCliVersion(),
   251  				"CliVer": cf.Version,
   252  			}))
   253  	}
   254  }