Parcourir la source

Updated panel move. Added Goroutine display.

Steve Thielemann il y a 1 an
Parent
commit
52d578b8f4
2 fichiers modifiés avec 211 ajouts et 13 suppressions
  1. 121 0
      testdoor/runtime-info.go
  2. 90 13
      testdoor/testdoor.go

+ 121 - 0
testdoor/runtime-info.go

@@ -0,0 +1,121 @@
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"log"
+	"runtime"
+	"strings"
+)
+
+// reused by GoRuntinesStatus()
+var buffer []byte
+
+// Get Go Routines and map the Status.  See GStatus.
+func GoRoutinesStatus() string {
+	var result string
+	// Map status to letter.
+	var GStatus = map[string]string{
+		"idle":         "I",
+		"runnable":     "r",
+		"running":      "R",
+		"syscall":      "s",
+		"waiting":      "W",
+		"dead":         "D",
+		"copystack":    "C",
+		"preempted":    "P",
+		"sleep":        "S",
+		"select":       "s", // missing
+		"chan receive": "<", // missing
+	}
+	if buffer == nil {
+		buffer = make([]byte, 1024) // 2048)
+	}
+	read := runtime.Stack(buffer, true)
+
+	if read == cap(buffer) {
+		log.Printf("Increasing buffer from (%d bytes)\n", cap(buffer))
+		buffer = make([]byte, cap(buffer)+1024)
+		return GoRoutinesStatus()
+	}
+
+	// fmt.Println(string(buffer[0:read]))
+
+	var reader = bytes.NewReader(buffer[0:read])
+	var scanner = bufio.NewScanner(reader)
+	for scanner.Scan() {
+		var text = scanner.Text()
+		if strings.HasPrefix(text, "goroutine ") {
+			// fmt.Println(text)
+			// goroutine 20 [runnable]:
+			// goroutine 1 [select, 1 minutes]:
+			// goroutine 17 [chan receive]:
+
+			// Get ID and get Status.
+			parts := strings.SplitN(text, " ", 3)
+			/*
+				gid, err := strconv.Atoi(parts[1])
+				if err != nil {
+					continue
+				}
+			*/
+			status := parts[2][1 : len(parts[2])-2]
+			if strings.Contains(status, ",") {
+				status = strings.Split(status, ",")[0]
+			}
+			rstatus, ok := GStatus[status]
+			if ok {
+				result += rstatus
+			} else {
+				log.Printf("Status %s not found.\n[%s]\n", rstatus, text)
+			}
+		}
+	}
+	return result
+}
+
+// Return a nicely formatted string representing memory usage.
+func ReprMem(size uint64) string {
+	var value float64 = float64(size)
+	var units string = ""
+
+	if value > 1024 {
+		// In KB
+		units = "K"
+		value /= 1024
+	}
+	if value > 1024 {
+		// In MB
+		units = "M"
+		value /= 1024
+	}
+	if value > 1024 {
+		// Im GB
+		units = "G"
+		value /= 1024
+	}
+	var test = fmt.Sprintf("%0.2f", value)
+	if len(test) > 4 {
+		test = fmt.Sprintf("%0.1f", value)
+	}
+	if len(test) > 4 {
+		test = fmt.Sprintf("%0.0f", value)
+	}
+	return test + units
+}
+
+// Return array of memory usage information
+func Memory() map[string]string {
+	var memstats runtime.MemStats
+	var result map[string]string = make(map[string]string, 7)
+	runtime.ReadMemStats(&memstats)
+	result["Heap"] = ReprMem(memstats.HeapAlloc)
+	result["HeapInUse"] = ReprMem(memstats.HeapInuse)
+	result["HeapSys"] = ReprMem(memstats.HeapSys)
+	result["Sys"] = ReprMem(memstats.Sys)
+	result["StackInUse"] = ReprMem(memstats.StackInuse)
+	result["StackSys"] = ReprMem(memstats.StackSys)
+	result["GCSys"] = ReprMem(memstats.GCSys)
+	return result
+}

+ 90 - 13
testdoor/testdoor.go

@@ -154,7 +154,7 @@ func MainMenu() door.Menu {
 		"Display TheDraw Fonts. Font information is compiled into the door.",
 		"Input some values, while updating the time.",
 		"Isn't this is a menu?",
-		"Display various progress bar styles: half step, display percentage, and gradient.",
+		"Display progress bar styles: half step, display percentage, and gradient.",
 		"Show multiple panels. Panels can be mouse drag/drop around.",
 		"Show about the door, using NoMoreSecrets effect.",
 		"Examples using the full width of the screen.",
@@ -274,9 +274,14 @@ func font_demo(d *door.Door) {
 	var centering string
 	var now time.Time = time.Now()
 
+	// I have checks here (but not all are complete), that verify the font
+	// output doesn't exceed the size of the screen.
+
 	d.Write(door.Clrscr + door.CRNL) //  + door.CRNL + door.CRNL)
 	var fac door.ColorFont = FontAmazonCyan()
 	output, l = fac.Output(now.Format("Jan Mon"))
+
+	// Size check:  Is this too big for the screen?
 	/*
 		if l > door.Width {
 			output, l = fac.Output("Jan")
@@ -698,36 +703,54 @@ func panel_demo(d *door.Door) {
 					d.Update(movingPanel.Output())
 				} else if m.Button == 4 {
 					if movingPanel != nil {
+						PR, PB := movingPanel.RightBottomPos()
+						log.Printf("Panel (%d,%d) End(%d,%d) W %d, L %d\n", movingPanel.X, movingPanel.Y, PR, PB, movingPanel.Width, movingPanel.Length())
 						// Ok, panel is move!
 						d.Update(movingPanel.Clear())
+
+						// Restore panel border
 						movingPanel.BorderColor = panelColor
+
+						// move panel
 						movingPanel.X -= (moveX - int(m.X))
 						movingPanel.Y -= (moveY - int(m.Y))
+
 						// sanity checks
-						if movingPanel.X < 0 {
-							movingPanel.X = 0
+						if movingPanel.X < 1 {
+							movingPanel.X = 1
 						}
-						var edgeX bool
+
+						// var edgeX bool
 						if movingPanel.X+movingPanel.Width >= door.Width {
 							movingPanel.X = door.Width - movingPanel.Width - 1
-							edgeX = true
+							// edgeX = true
 						}
-						if movingPanel.Y < 0 {
-							movingPanel.Y = 0
+						if movingPanel.Y < 1 {
+							movingPanel.Y = 1
 						}
-						var edgeY bool
+
+						// var edgeY bool
 						if movingPanel.Y+movingPanel.Length() >= door.Height {
 							movingPanel.Y = door.Height - movingPanel.Length() - 1
-							edgeY = true
+							// edgeY = true
 						}
 
+						PR, PB = movingPanel.RightBottomPos()
+						log.Printf("Panel Now (%d,%d) End (%d,%d) %d, %d\n", movingPanel.X, movingPanel.Y, PR, PB, movingPanel.Width, movingPanel.Length()) //, edgeX, edgeY)
 						// If panel is at the end of the screen -- it scrolls (syncterm)
 						// This "fixes" it.  (Maybe a better way would be to not use last
 						// line on the screen?)
 
-						if edgeX && edgeY {
+						// Or another way:
+						if PR == door.Width && PB == door.Height {
 							movingPanel.X--
 						}
+						/*
+							if edgeX && edgeY {
+								movingPanel.X--
+								log.Printf("Panel adjust X\n")
+							}
+						*/
 
 						d.Update(movingPanel.Output())
 					}
@@ -802,13 +825,67 @@ func main() {
 	var spin2 door.SpinRite = door.SpinRiteInit(13, 5,
 		door.ColorText("BRI CYA ON BLUE"))
 
+	// Add in the GoRoutine Status panel
+
+	var goPanel door.Panel = door.Panel{X: 0,
+		Y:           1,
+		Width:       18,
+		Style:       door.DOUBLE,
+		Title:       "] GoRoutines [",
+		BorderColor: door.ColorText("BOLD YEL ON BLU"),
+	}
+	goLineUpdater := func() string {
+		status := GoRoutinesStatus()
+		// log.Println(status)
+		return status
+	}
+
+	var goLine door.Line = door.Line{
+		UpdateF: goLineUpdater,
+		Width:   goPanel.Width,
+	}
+	// goLine.Update() // Force Update
+	goPanel.Lines = append(goPanel.Lines, goLine)
+	goPanel.Lines = append(goPanel.Lines, door.Line{Width: goPanel.Width})
+	var lIndex int = 0
+	var legendCount int = 0
+	const legendUpdate = 20
+
 	go func() {
 		var output string
+		var legend []string = []string{
+			"R=run r=Runnable",
+			"S=Select s=Syscall",
+			"Chan <read >write",
+			"Z=Sleep P=Preempt",
+			"I=Idle D=Dead",
+			"W=Wait C=Copystk",
+		}
+		goPanel.Lines[1].Text = legend[0]
+
 		for range ticker.C {
-			output = door.SavePos + door.Goto(door.Width-16, 1) + spin.Output() +
-				door.Goto(door.Width-15, 3) + spin2.Output() + door.RestorePos
+			// output = door.SavePos + door.Goto(door.Width-16, 1) + spin.Output() +
+			//	door.Goto(door.Width-15, 3) + spin2.Output() + door.RestorePos
+
+			legendCount++
+			if legendCount >= legendUpdate {
+				legendCount = 0
+				lIndex++
+				if lIndex == len(legend) {
+					lIndex = 0
+				}
+				goPanel.Lines[1].Text = legend[lIndex]
+			}
+
+			if goPanel.X == 0 {
+				goPanel.X = door.Width - 40
+			}
+
+			goPanel.Update()
+			output = door.Goto(door.Width-16, 1) + spin.Output() +
+				door.Goto(door.Width-15, 3) + spin2.Output() + goPanel.Output()
 			if !d.Disconnect() {
-				d.Write(output)
+				d.Update(output)
 			} else {
 				ticker.Stop()
 				return