1package gui 2 3import ( 4 "context" 5 6 "github.com/mum4k/termdash/container" 7 "github.com/mum4k/termdash/keyboard" 8 "github.com/mum4k/termdash/terminal/terminalapi" 9 10 "github.com/nakabonne/ali/attacker" 11) 12 13func navigateCharts(chartFuncs []func()) func(bool) { 14 position := 0 15 numFuncs := len(chartFuncs) 16 return func(backwards bool) { 17 position++ 18 if backwards { 19 position -= 2 20 if position < 0 { 21 position = numFuncs - 1 22 } 23 } 24 chartFuncs[position%numFuncs]() 25 } 26} 27 28func keybinds(ctx context.Context, cancel context.CancelFunc, c *container.Container, dr *drawer, a attacker.Attacker) func(*terminalapi.Keyboard) { 29 funcs := []func(){ 30 func() { c.Update(chartID, dr.gridOpts.latency...) }, 31 func() { c.Update(chartID, dr.gridOpts.percentiles...) }, 32 } 33 navigateFunc := navigateCharts(funcs) 34 return func(k *terminalapi.Keyboard) { 35 switch k.Key { 36 case keyboard.KeyCtrlC, 'q': // Quit 37 cancel() 38 case keyboard.KeyEnter: // Attack 39 attack(ctx, dr, a) 40 case 'H', 'h': // backwards 41 navigateFunc(true) 42 case 'L', 'l': // forwards 43 navigateFunc(false) 44 } 45 } 46} 47 48func attack(ctx context.Context, d *drawer, a attacker.Attacker) { 49 if d.chartDrawing.Load() { 50 return 51 } 52 child, cancel := context.WithCancel(ctx) 53 54 // To initialize, run redrawChart on a per-attack basis. 55 go d.redrawCharts(child) 56 go d.redrawGauge(child, a.Duration()) 57 go func() { 58 a.Attack(child, d.metricsCh) // this blocks until attack finishes 59 cancel() 60 }() 61} 62