Parcourir la source

Update documentation of cmd/pingo.go and tui.go

arianagiroux il y a 6 jours
Parent
commit
b5164986eb
4 fichiers modifiés avec 68 ajouts et 31 suppressions
  1. 14 6
      Readme.md
  2. 42 21
      cmd/pingo.go
  3. 4 4
      cmd/pingo_test.go
  4. 8 0
      tui.go

+ 14 - 6
Readme.md

@@ -1,20 +1,28 @@
 # Pingo - a simple ping visualizer written in go
 
-To run the project, simply `go run .`
+To run the project, simply `go run cmd/pingo.go`
 
-To install the project, simply `go install .`
+To install the project, simply `go install cmd/pingo.go`
 
 To compile the project, simply `go build cmd/pingo.go`
 
+To use the project as a bubble in bubbletea programs:
+
+```
+import "git.crowcollective.space/pingo"
+bubble := pingo.InitialPeakModel()
+```
+
+> for an example implementation of the bubble, see cmd/pingo.go
+
 ## Roadmap:
 > see ./issues for more. See also [issues-go][issues-go] for a browser TUI.
 
-- `ping.go:// TODO(performance): implement ping message channel buffering`
-- `tui.go:// TODO(chart): dynamically render charts to fit height on not set`
-- `tui.go:// TODO(styling): allow end user to define their own styles when hacking.`
+ - `ping.go:// TODO(performance): implement ping message channel buffering`
+ - `tui.go:// TODO(chart): dynamically render charts to fit height on not set`
+ - `tui.go:// TODO(styling): allow end user to define their own styles when hacking.`
 
  - [ ] "scroll peek" refinements
- - [ ] documentation update
 
 ## Core
  - [x] Implements Bubbletea framework

+ 42 - 21
cmd/pingo.go

@@ -1,8 +1,4 @@
 // A simple TUI application that charts latency times to specified hosts.
-//
-//	i.e, change the address title to red so long as there is a single -1 in
-//	the display buffer, and a toast notification (???) if a display buffer is
-//	entirely composed of -1
 package main
 
 import (
@@ -17,14 +13,18 @@ import (
 	"charm.land/lipgloss/v2"
 )
 
-type md struct {
+// the bubbletea.Model for the executable
+type Model struct {
 	viewport viewport.Model
 	speed    time.Duration
 	p        pingo.Peak
 }
 
+// timingMsg is used for tracking Peak.Poll timing intervals, emitted by an
+// anonymous function in the update function.
 type timingMsg time.Time
 
+// lipgloss styles for the tui
 var (
 	// footer styles
 	titleStyle = lipgloss.NewStyle().
@@ -39,48 +39,59 @@ var (
 			Faint(true)
 )
 
-func (m md) Init() tea.Cmd {
+// The tea.Cmd command to be called upon model initialization by bubbletea.
+func (m Model) Init() tea.Cmd {
 	return tea.Tick(m.speed*time.Millisecond, func(t time.Time) tea.Msg { return timingMsg(t) })
 }
 
-func (m md) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
-	var cmds []tea.Cmd
+// The core Update loop function.
+func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
+	// data prep
+	var cmds []tea.Cmd // final return
 	var cmd tea.Cmd
 
 	switch msg := msg.(type) {
-	case tea.WindowSizeMsg:
+	case tea.WindowSizeMsg: // handle window resizing
+		// update pingo.Peak bubble
 		m.p.Width = msg.Width
 		m.p.Height = msg.Height - m.getVerticalMargin() - 1
+
+		// if the viewport has not been initialized
 		if m.viewport.Width() == 0 && m.viewport.Height() == 0 {
-			m.viewport = viewport.New(
+			m.viewport = viewport.New( // init viewport
 				viewport.WithHeight(msg.Height-m.getVerticalMargin()),
 				viewport.WithWidth(msg.Width),
 			)
+			m.viewport.YPosition = 1 // tell viewport to render after an empty line
+		} else {
+			m.viewport.SetHeight(msg.Height - m.getVerticalMargin())
+			m.viewport.SetWidth(msg.Width)
 		}
-		m.viewport.SetHeight(msg.Height - m.getVerticalMargin())
-		m.viewport.SetWidth(msg.Width)
-		m.viewport.YPosition = 1
-	case tea.KeyPressMsg:
+
+	case tea.KeyPressMsg: // handle quit
 		k := msg.String()
 		if k == "ctrl+c" {
 			return m, tea.Quit
 		}
-	case timingMsg:
+
+	case timingMsg: // handle timingMsg (timing loop)
 		cmd = tea.Tick(m.speed*time.Millisecond, func(t time.Time) tea.Msg { return timingMsg(t) })
 		cmds = append(cmds, tea.Sequence(m.p.Poll(), cmd))
 	}
 
+	// update viewport bubble
 	m.viewport.SetContent(m.p.View().Content)
 	m.viewport, cmd = m.viewport.Update(msg)
 	cmds = append(cmds, cmd)
 
+	// update Peak bubble
 	m.p, cmd = m.p.Update(msg)
 	cmds = append(cmds, cmd)
 
 	return m, tea.Batch(cmds...)
 }
 
-func (m md) View() tea.View {
+func (m Model) View() tea.View {
 	m.viewport.SetContent(m.p.View().Content)
 	content := fmt.Sprintf("%s%s\n%s", m.header(), m.viewport.View(), m.footer())
 
@@ -90,16 +101,18 @@ func (m md) View() tea.View {
 	return v
 }
 
-func (m md) header() string { return titleStyle.Width(m.viewport.Width()).Render("pingo v0") }
+func (m Model) header() string { return titleStyle.Width(m.viewport.Width()).Render("pingo v0") }
 
-func (m md) footer() string {
+func (m Model) footer() string {
 	return footerStyle.Width(m.viewport.Width()).Render("j/k: down/up\t|\tctrl+c: quit")
 }
 
-func (m md) getVerticalMargin() int { return lipgloss.Height(m.header() + m.footer()) }
+// get lipgloss.Height value of header and footer
+func (m Model) getVerticalMargin() int { return lipgloss.Height(m.header() + m.footer()) }
 
 func main() {
-	speed := flag.Int("s", 80, "the speed with which the UI runs")
+	// get timing interval in milliseconds
+	speed := flag.Int("s", 80, "the interval in milliseconds between pings")
 	chartHeight := flag.Int("h", 0,
 		"the height of the latency chart. set to 0 to render charts full screen.")
 	flag.Parse()
@@ -110,7 +123,15 @@ func main() {
 		return
 	}
 
-	p := tea.NewProgram(md{p: pingo.InitialPeakBubble(hosts, 20, 10, *chartHeight), speed: time.Duration(*speed)})
+	if *speed < 1 {
+		fmt.Println("speed must not be below 1")
+		os.Exit(1)
+	}
+
+	p := tea.NewProgram(Model{
+		p:     pingo.InitialPeakBubble(hosts, 20, 10, *chartHeight),
+		speed: time.Duration(*speed),
+	})
 
 	if _, err := p.Run(); err != nil {
 		fmt.Printf("Alas, there's been an error: %v", err)

+ 4 - 4
cmd/pingo_test.go

@@ -10,8 +10,8 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func spawnMD(hosts []string, width, height, chartHeight int) md {
-	return md{p: pingo.InitialPeakBubble(hosts, width, height, chartHeight)}
+func spawnMD(hosts []string, width, height, chartHeight int) Model {
+	return Model{p: pingo.InitialPeakBubble(hosts, width, height, chartHeight)}
 }
 
 func Test_md_Init(t *testing.T) {
@@ -31,8 +31,8 @@ func Test_md_Update_handle_windowsize(t *testing.T) {
 
 	model, cmd := testMD.Update(testMsg)
 	assert.Nil(t, cmd)
-	assert.Equal(t, 80, model.(md).p.Width)
-	assert.Equal(t, 80-2, model.(md).p.Height)
+	assert.Equal(t, 80, model.(Model).p.Width)
+	assert.Equal(t, 80-2, model.(Model).p.Height)
 }
 
 func Test_md_Update_handle_keymsg(t *testing.T) {

+ 8 - 0
tui.go

@@ -35,6 +35,14 @@
 //   - Model.Poll() tea.Msg: used to asynchronously call all Model.Addresses.Poll()
 //     functions.
 //
+// NOTE: the project does not implement a timing mechanism for polling Addresses.
+// It is expected that the developer implements a timing mechanism.
+//
+// CRITICAL NOTE: it is possible to exceed rate limits from remote targets. It is
+// recommended to ensure that you implement a minimum time between calls to Poll.
+// As timing may be handled in a number of ways, it exceeds the scope of this
+// project to provide one.
+//
 // For an example implementation, see cmd/pingo.go
 package pingo