func (factory *AppExaminerCommandFactory) visualizeCells(context *cli.Context) { rate := context.Duration("rate") graphicalFlag := context.Bool("graphical") if graphicalFlag { err := factory.graphicalVisualizer.PrintDistributionChart(rate) if err != nil { factory.ui.SayLine("Error Visualization: " + err.Error()) factory.exitHandler.Exit(exit_codes.CommandFailed) } return } factory.ui.SayLine(colors.Bold("Distribution")) linesWritten := factory.printDistribution() if rate == 0 { return } closeChan := make(chan struct{}) factory.ui.Say(cursor.Hide()) factory.exitHandler.OnExit(func() { closeChan <- struct{}{} factory.ui.Say(cursor.Show()) }) for { select { case <-closeChan: return case <-factory.clock.NewTimer(rate).C(): factory.ui.Say(cursor.Up(linesWritten)) linesWritten = factory.printDistribution() } } }
package cursor_test import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/cloudfoundry-incubator/ltc/terminal/cursor" ) var _ = Describe("cursor", func() { Describe("Up", func() { It("moves the cursor up N lines", func() { Expect(cursor.Up(5)).To(Equal("\033[5A")) }) }) Describe("ClearToEndOfLine", func() { It("clears the line after the cursor", func() { Expect(cursor.ClearToEndOfLine()).To(Equal("\033[0K")) }) }) Describe("ClearToEndOfDisplay", func() { It("clears everything below the cursor", func() { Expect(cursor.ClearToEndOfDisplay()).To(Equal("\033[0J")) }) }) Describe("Show", func() { It("shows the cursor", func() { Expect(cursor.Show()).To(Equal("\033[?25h"))
func (factory *AppExaminerCommandFactory) appStatus(context *cli.Context) { detailedFlag := context.Bool("detailed") rateFlag := context.Duration("rate") if len(context.Args()) < 1 { factory.ui.SayIncorrectUsage("App Name required") factory.exitHandler.Exit(exit_codes.InvalidSyntax) return } appName := context.Args()[0] writer := new(bytes.Buffer) appInfo, err := factory.appExaminer.AppStatus(appName) if err != nil { factory.ui.SayLine(err.Error()) factory.exitHandler.Exit(exit_codes.CommandFailed) return } factory.printAppInfo(writer, appInfo) if rateFlag != 0 { if detailedFlag { factory.ui.SayLine("WARNING: flags '--detailed' and '--rate' are incompatible.") } factory.printInstanceSummary(writer, appInfo.ActualInstances) } else if detailedFlag { factory.printInstanceInfo(writer, appInfo.ActualInstances) } else { factory.printInstanceSummary(writer, appInfo.ActualInstances) } factory.ui.Write(writer.Bytes()) if rateFlag == 0 { return } linesWritten := factory.lineCount(writer.Bytes()) closeChan := make(chan struct{}) defer factory.ui.Say(cursor.Show()) factory.ui.Say(cursor.Hide()) factory.exitHandler.OnExit(func() { closeChan <- struct{}{} factory.ui.Say(cursor.Show()) }) for { select { case <-closeChan: return case <-factory.clock.NewTimer(rateFlag).C(): appInfo, err = factory.appExaminer.AppStatus(appName) if err != nil { factory.ui.SayLine("Error getting status: " + err.Error()) return } factory.ui.Say(cursor.Up(linesWritten)) writer = new(bytes.Buffer) factory.printAppInfo(writer, appInfo) factory.printInstanceSummary(writer, appInfo.ActualInstances) factory.ui.Write(writer.Bytes()) linesWritten = factory.lineCount(writer.Bytes()) } } }
closeChan = test_helpers.AsyncExecuteCommandWithArgs(visualizeCommand, []string{"--rate", "2s"}) Eventually(outputBuffer).Should(test_helpers.SayLine("cell-0: " + colors.Red("empty") + cursor.ClearToEndOfLine())) Eventually(outputBuffer).Should(test_helpers.SayLine("cell-1" + colors.Red("[MISSING]") + ": " + cursor.ClearToEndOfLine())) setNumberOfRunningInstances(2) fakeClock.IncrementBySeconds(1) Consistently(outputBuffer).ShouldNot(test_helpers.Say("cell: \n")) // TODO: how would this happen fakeClock.IncrementBySeconds(1) Eventually(outputBuffer).Should(test_helpers.Say(cursor.Hide())) Eventually(outputBuffer).Should(test_helpers.Say(cursor.Up(2))) Eventually(outputBuffer).Should(test_helpers.SayLine("cell-0: " + colors.Green("••") + cursor.ClearToEndOfLine())) Eventually(outputBuffer).Should(test_helpers.SayLine("cell-1" + colors.Red("[MISSING]") + ": " + colors.Green("••") + cursor.ClearToEndOfLine())) Eventually(outputBuffer).Should(test_helpers.Say(cursor.ClearToEndOfDisplay())) Consistently(closeChan).ShouldNot(BeClosed()) }) It("dynamically displays any errors", func() { fakeAppExaminer.ListCellsReturns(nil, errors.New("Spilled the Paint")) closeChan = test_helpers.AsyncExecuteCommandWithArgs(visualizeCommand, []string{"--rate", "1s"}) Eventually(outputBuffer).Should(test_helpers.SayLine("Error visualizing: Spilled the Paint" + cursor.ClearToEndOfLine())) fakeClock.IncrementBySeconds(1)