Browse Source

Updated panel move. Added Goroutine display.

Steve Thielemann 1 year ago
parent
commit
52d578b8f4
2 changed files with 211 additions and 13 deletions
  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.",
 		"Display TheDraw Fonts. Font information is compiled into the door.",
 		"Input some values, while updating the time.",
 		"Input some values, while updating the time.",
 		"Isn't this is a menu?",
 		"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 multiple panels. Panels can be mouse drag/drop around.",
 		"Show about the door, using NoMoreSecrets effect.",
 		"Show about the door, using NoMoreSecrets effect.",
 		"Examples using the full width of the screen.",
 		"Examples using the full width of the screen.",
@@ -274,9 +274,14 @@ func font_demo(d *door.Door) {
 	var centering string
 	var centering string
 	var now time.Time = time.Now()
 	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)
 	d.Write(door.Clrscr + door.CRNL) //  + door.CRNL + door.CRNL)
 	var fac door.ColorFont = FontAmazonCyan()
 	var fac door.ColorFont = FontAmazonCyan()
 	output, l = fac.Output(now.Format("Jan Mon"))
 	output, l = fac.Output(now.Format("Jan Mon"))
+
+	// Size check:  Is this too big for the screen?
 	/*
 	/*
 		if l > door.Width {
 		if l > door.Width {
 			output, l = fac.Output("Jan")
 			output, l = fac.Output("Jan")
@@ -698,36 +703,54 @@ func panel_demo(d *door.Door) {
 					d.Update(movingPanel.Output())
 					d.Update(movingPanel.Output())
 				} else if m.Button == 4 {
 				} else if m.Button == 4 {
 					if movingPanel != nil {
 					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!
 						// Ok, panel is move!
 						d.Update(movingPanel.Clear())
 						d.Update(movingPanel.Clear())
+
+						// Restore panel border
 						movingPanel.BorderColor = panelColor
 						movingPanel.BorderColor = panelColor
+
+						// move panel
 						movingPanel.X -= (moveX - int(m.X))
 						movingPanel.X -= (moveX - int(m.X))
 						movingPanel.Y -= (moveY - int(m.Y))
 						movingPanel.Y -= (moveY - int(m.Y))
+
 						// sanity checks
 						// 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 {
 						if movingPanel.X+movingPanel.Width >= door.Width {
 							movingPanel.X = door.Width - movingPanel.Width - 1
 							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 {
 						if movingPanel.Y+movingPanel.Length() >= door.Height {
 							movingPanel.Y = door.Height - movingPanel.Length() - 1
 							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)
 						// 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
 						// This "fixes" it.  (Maybe a better way would be to not use last
 						// line on the screen?)
 						// line on the screen?)
 
 
-						if edgeX && edgeY {
+						// Or another way:
+						if PR == door.Width && PB == door.Height {
 							movingPanel.X--
 							movingPanel.X--
 						}
 						}
+						/*
+							if edgeX && edgeY {
+								movingPanel.X--
+								log.Printf("Panel adjust X\n")
+							}
+						*/
 
 
 						d.Update(movingPanel.Output())
 						d.Update(movingPanel.Output())
 					}
 					}
@@ -802,13 +825,67 @@ func main() {
 	var spin2 door.SpinRite = door.SpinRiteInit(13, 5,
 	var spin2 door.SpinRite = door.SpinRiteInit(13, 5,
 		door.ColorText("BRI CYA ON BLUE"))
 		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() {
 	go func() {
 		var output string
 		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 {
 		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() {
 			if !d.Disconnect() {
-				d.Write(output)
+				d.Update(output)
 			} else {
 			} else {
 				ticker.Stop()
 				ticker.Stop()
 				return
 				return