Refactor README and remove widget screenshots
							
								
								
									
										65
									
								
								README.md
									
									
									
									
									
								
							
							
						
						@ -1,6 +1,6 @@
 | 
			
		||||
# termui
 | 
			
		||||
 | 
			
		||||
<img src="./_assets/dashboard1.gif" alt="demo cast under osx 10.10; Terminal.app; Menlo Regular 12pt.)" width="100%">
 | 
			
		||||
[<img src="./_assets/demo.gif" alt="demo cast under osx 10.10; Terminal.app; Menlo Regular 12pt.)" width="100%">](./_examples/demo.go)
 | 
			
		||||
 | 
			
		||||
termui is a cross-platform and fully-customizable terminal dashboard and widget library built on top of [termbox-go](https://github.com/nsf/termbox-go). It is inspired by [blessed-contrib](https://github.com/yaronn/blessed-contrib) and written purely in Go.
 | 
			
		||||
 | 
			
		||||
@ -15,58 +15,23 @@ go get -u github.com/gizak/termui@master
 | 
			
		||||
**Note**: termui is currently undergoing API changes so make sure to check the changelog when upgrading.
 | 
			
		||||
If you upgrade and notice something is missing or don't like a change, revert the upgrade and open an issue.
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
## Widgets
 | 
			
		||||
 | 
			
		||||
### Hello World
 | 
			
		||||
- [BarChart](./_examples/barchart.go)
 | 
			
		||||
- [Canvas](./_examples/canvas.go)
 | 
			
		||||
- [Gauge](./_examples/gauge.go)
 | 
			
		||||
- [LineChart](./_examples/linechart.go)
 | 
			
		||||
- [List](./_examples/list.go)
 | 
			
		||||
- [Paragraph](./_examples/paragraph.go)
 | 
			
		||||
- [PieChart](./_examples/piechart.go)
 | 
			
		||||
- [Sparkline](./_examples/sparkline.go)
 | 
			
		||||
- [StackedBarChart](./_examples/stacked_barchart.go)
 | 
			
		||||
- [Table](./_examples/table.go)
 | 
			
		||||
- [Tabs](./_examples/tabs.go)
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
package main
 | 
			
		||||
Run an example with `go run _examples/{example}.go` or run all of them consecutively with `make run-examples`.
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	ui "github.com/gizak/termui"
 | 
			
		||||
	"github.com/gizak/termui/widgets"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	if err := ui.Init(); err != nil {
 | 
			
		||||
		log.Fatalf("failed to initialize termui: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer ui.Close()
 | 
			
		||||
 | 
			
		||||
	p := widgets.NewParagraph()
 | 
			
		||||
	p.Text = "Hello World!"
 | 
			
		||||
	p.SetRect(0, 0, 25, 5)
 | 
			
		||||
 | 
			
		||||
	ui.Render(p)
 | 
			
		||||
 | 
			
		||||
	for e := range ui.PollEvents() {
 | 
			
		||||
		if e.Type == ui.KeyboardEvent {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Widgets
 | 
			
		||||
 | 
			
		||||
Click image to see the corresponding demo codes.
 | 
			
		||||
 | 
			
		||||
[<img src="./_assets/barchart.png" alt="barchart" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_examples/barchart.go)
 | 
			
		||||
[<img src="./_assets/gauge.png" alt="gauge" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_examples/gauge.go)
 | 
			
		||||
[<img src="./_assets/linechart.png" alt="linechart" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_examples/linechart.go)
 | 
			
		||||
[<img src="./_assets/list.png" alt="list" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_examples/list.go)
 | 
			
		||||
[<img src="./_assets/paragraph.png" alt="paragraph" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_examples/paragraph.go)
 | 
			
		||||
[<img src="./_assets/sparkline.png" alt="sparkline" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_examples/sparkline.go)
 | 
			
		||||
[<img src="./_assets/stacked_barchart.png" alt="stacked_barchart" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_examples/stacked_barchart.go)
 | 
			
		||||
[<img src="./_assets/table.png" alt="table" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_examples/table.go)
 | 
			
		||||
 | 
			
		||||
### Examples
 | 
			
		||||
 | 
			
		||||
Examples can be found in [\_examples](./_examples). Run an example with `go run _examples/{example}.go` or run all of them consecutively with `make run-examples`.
 | 
			
		||||
 | 
			
		||||
### Documentation
 | 
			
		||||
## Documentation
 | 
			
		||||
 | 
			
		||||
- [wiki](https://github.com/gizak/termui/wiki)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 17 KiB  | 
| 
		 Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 152 KiB  | 
| 
		 Before Width: | Height: | Size: 52 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								_assets/grid.gif
									
									
									
									
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 782 KiB  | 
| 
		 Before Width: | Height: | Size: 31 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								_assets/list.png
									
									
									
									
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 28 KiB  | 
| 
		 Before Width: | Height: | Size: 45 KiB  | 
| 
		 Before Width: | Height: | Size: 48 KiB  | 
| 
		 Before Width: | Height: | Size: 71 KiB  | 
| 
		 Before Width: | Height: | Size: 46 KiB  | 
@ -1,370 +0,0 @@
 | 
			
		||||
// Copyright 2017 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT license that can
 | 
			
		||||
// be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build ignore
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"image"
 | 
			
		||||
	"io"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	ui "github.com/gizak/termui"
 | 
			
		||||
	"github.com/gizak/termui/widgets"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const statFilePath = "/proc/stat"
 | 
			
		||||
const meminfoFilePath = "/proc/meminfo"
 | 
			
		||||
 | 
			
		||||
type CpuStat struct {
 | 
			
		||||
	user   float32
 | 
			
		||||
	nice   float32
 | 
			
		||||
	system float32
 | 
			
		||||
	idle   float32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CpusStats struct {
 | 
			
		||||
	stat map[string]CpuStat
 | 
			
		||||
	proc map[string]CpuStat
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewCpusStats(s map[string]CpuStat) *CpusStats {
 | 
			
		||||
	return &CpusStats{stat: s, proc: make(map[string]CpuStat)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cs *CpusStats) String() (ret string) {
 | 
			
		||||
	for key, _ := range cs.proc {
 | 
			
		||||
		ret += fmt.Sprintf("%s: %.2f %.2f %.2f %.2f\n", key, cs.proc[key].user, cs.proc[key].nice, cs.proc[key].system, cs.proc[key].idle)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func subCpuStat(m CpuStat, s CpuStat) CpuStat {
 | 
			
		||||
	return CpuStat{user: m.user - s.user,
 | 
			
		||||
		nice:   m.nice - s.nice,
 | 
			
		||||
		system: m.system - s.system,
 | 
			
		||||
		idle:   m.idle - s.idle}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func procCpuStat(c CpuStat) CpuStat {
 | 
			
		||||
	sum := c.user + c.nice + c.system + c.idle
 | 
			
		||||
	return CpuStat{user: c.user / sum * 100,
 | 
			
		||||
		nice:   c.nice / sum * 100,
 | 
			
		||||
		system: c.system / sum * 100,
 | 
			
		||||
		idle:   c.idle / sum * 100}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cs *CpusStats) tick(ns map[string]CpuStat) {
 | 
			
		||||
	for key, _ := range cs.stat {
 | 
			
		||||
		proc := subCpuStat(ns[key], cs.stat[key])
 | 
			
		||||
		cs.proc[key] = procCpuStat(proc)
 | 
			
		||||
		cs.stat[key] = ns[key]
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type errIntParser struct {
 | 
			
		||||
	err error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (eip *errIntParser) parse(s string) (ret int64) {
 | 
			
		||||
	if eip.err != nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	ret, eip.err = strconv.ParseInt(s, 10, 0)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type LineProcessor interface {
 | 
			
		||||
	process(string) error
 | 
			
		||||
	finalize() interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CpuLineProcessor struct {
 | 
			
		||||
	m map[string]CpuStat
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clp *CpuLineProcessor) process(line string) (err error) {
 | 
			
		||||
	r := regexp.MustCompile("^cpu([0-9]*)")
 | 
			
		||||
 | 
			
		||||
	if r.MatchString(line) {
 | 
			
		||||
		tab := strings.Fields(line)
 | 
			
		||||
		if len(tab) < 5 {
 | 
			
		||||
			err = errors.New("cpu info line has not enough fields")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		parser := errIntParser{}
 | 
			
		||||
		cs := CpuStat{user: float32(parser.parse(tab[1])),
 | 
			
		||||
			nice:   float32(parser.parse(tab[2])),
 | 
			
		||||
			system: float32(parser.parse(tab[3])),
 | 
			
		||||
			idle:   float32(parser.parse(tab[4]))}
 | 
			
		||||
		clp.m[tab[0]] = cs
 | 
			
		||||
		err = parser.err
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clp *CpuLineProcessor) finalize() interface{} {
 | 
			
		||||
	return clp.m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type MemStat struct {
 | 
			
		||||
	total int64
 | 
			
		||||
	free  int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ms MemStat) String() (ret string) {
 | 
			
		||||
	ret = fmt.Sprintf("TotalMem: %d, FreeMem: %d\n", ms.total, ms.free)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ms *MemStat) process(line string) (err error) {
 | 
			
		||||
	rtotal := regexp.MustCompile("^MemTotal:")
 | 
			
		||||
	rfree := regexp.MustCompile("^MemFree:")
 | 
			
		||||
	var aux int64
 | 
			
		||||
	if rtotal.MatchString(line) || rfree.MatchString(line) {
 | 
			
		||||
		tab := strings.Fields(line)
 | 
			
		||||
		if len(tab) < 3 {
 | 
			
		||||
			err = errors.New("mem info line has not enough fields")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		aux, err = strconv.ParseInt(tab[1], 10, 0)
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if rtotal.MatchString(line) {
 | 
			
		||||
		ms.total = aux
 | 
			
		||||
	}
 | 
			
		||||
	if rfree.MatchString(line) {
 | 
			
		||||
		ms.free = aux
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ms *MemStat) finalize() interface{} {
 | 
			
		||||
	return *ms
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func processFileLines(filePath string, lp LineProcessor) (ret interface{}, err error) {
 | 
			
		||||
	var statFile *os.File
 | 
			
		||||
	statFile, err = os.Open(filePath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Printf("open: %v\n", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer statFile.Close()
 | 
			
		||||
 | 
			
		||||
	statFileReader := bufio.NewReader(statFile)
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		var line string
 | 
			
		||||
		line, err = statFileReader.ReadString('\n')
 | 
			
		||||
		if err == io.EOF {
 | 
			
		||||
			err = nil
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fmt.Printf("open: %v\n", err)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		line = strings.TrimSpace(line)
 | 
			
		||||
 | 
			
		||||
		err = lp.process(line)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = lp.finalize()
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getCpusStatsMap() (m map[string]CpuStat, err error) {
 | 
			
		||||
	var aux interface{}
 | 
			
		||||
	aux, err = processFileLines(statFilePath, &CpuLineProcessor{m: make(map[string]CpuStat)})
 | 
			
		||||
	return aux.(map[string]CpuStat), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getMemStats() (ms MemStat, err error) {
 | 
			
		||||
	var aux interface{}
 | 
			
		||||
	aux, err = processFileLines(meminfoFilePath, &MemStat{})
 | 
			
		||||
	return aux.(MemStat), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CpuTabElems struct {
 | 
			
		||||
	GMap   map[string]*widgets.Gauge
 | 
			
		||||
	LChart *widgets.LineChart
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewCpuTabElems(width int) *CpuTabElems {
 | 
			
		||||
	lc := widgets.NewLineChart()
 | 
			
		||||
	lc.SetRect(0, 0, width, 12)
 | 
			
		||||
	lc.LineType = widgets.DotLine
 | 
			
		||||
	lc.Title = "CPU"
 | 
			
		||||
	return &CpuTabElems{
 | 
			
		||||
		GMap:   make(map[string]*widgets.Gauge),
 | 
			
		||||
		LChart: lc,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cte *CpuTabElems) AddGauge(key string, Y int, width int) *widgets.Gauge {
 | 
			
		||||
	cte.GMap[key] = widgets.NewGauge()
 | 
			
		||||
	cte.GMap[key].SetRect(0, Y, width, Y+3)
 | 
			
		||||
	cte.GMap[key].Title = key
 | 
			
		||||
	cte.GMap[key].Percent = 0 //int(val.user + val.nice + val.system)
 | 
			
		||||
	return cte.GMap[key]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cte *CpuTabElems) Update(cs CpusStats) {
 | 
			
		||||
	for key, val := range cs.proc {
 | 
			
		||||
		p := int(val.user + val.nice + val.system)
 | 
			
		||||
		cte.GMap[key].Percent = p
 | 
			
		||||
		if key == "cpu" {
 | 
			
		||||
			cte.LChart.Data = append(cte.LChart.Data, []float64{})
 | 
			
		||||
			cte.LChart.Data[0] = append(cte.LChart.Data[0], 0)
 | 
			
		||||
			copy(cte.LChart.Data[0][1:], cte.LChart.Data[0][0:])
 | 
			
		||||
			cte.LChart.Data[0][0] = float64(p)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type MemTabElems struct {
 | 
			
		||||
	Gauge  *widgets.Gauge
 | 
			
		||||
	SLines *widgets.SparklineGroup
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewMemTabElems(width int) *MemTabElems {
 | 
			
		||||
	g := widgets.NewGauge()
 | 
			
		||||
	g.SetRect(0, 5, width, 10)
 | 
			
		||||
 | 
			
		||||
	sline := widgets.NewSparkline()
 | 
			
		||||
	sline.Title = "MEM"
 | 
			
		||||
 | 
			
		||||
	sls := widgets.NewSparklineGroup(sline)
 | 
			
		||||
	sls.SetRect(0, 10, width, 25)
 | 
			
		||||
	return &MemTabElems{Gauge: g, SLines: sls}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (mte *MemTabElems) Update(ms MemStat) {
 | 
			
		||||
	used := (ms.total - ms.free) * 100 / ms.total
 | 
			
		||||
	mte.Gauge.Percent = int(used)
 | 
			
		||||
	mte.SLines.Sparklines[0].Data = append(mte.SLines.Sparklines[0].Data, 0)
 | 
			
		||||
	copy(mte.SLines.Sparklines[0].Data[1:], mte.SLines.Sparklines[0].Data[0:])
 | 
			
		||||
	mte.SLines.Sparklines[0].Data[0] = float64(used)
 | 
			
		||||
	if len(mte.SLines.Sparklines[0].Data) > mte.SLines.Dx()-2 {
 | 
			
		||||
		mte.SLines.Sparklines[0].Data = mte.SLines.Sparklines[0].Data[0 : mte.SLines.Dx()-2]
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	if runtime.GOOS != "linux" {
 | 
			
		||||
		log.Fatalf("Currently only works on Linux")
 | 
			
		||||
	}
 | 
			
		||||
	if err := ui.Init(); err != nil {
 | 
			
		||||
		log.Fatalf("failed to initialize termui: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer ui.Close()
 | 
			
		||||
 | 
			
		||||
	termWidth := 70
 | 
			
		||||
 | 
			
		||||
	header := widgets.NewParagraph()
 | 
			
		||||
	header.Text = "Press q to quit, Press h or l to switch tabs"
 | 
			
		||||
	header.SetRect(0, 0, 50, 1)
 | 
			
		||||
	header.Border = false
 | 
			
		||||
	header.TextStyle.Bg = ui.ColorBlue
 | 
			
		||||
 | 
			
		||||
	cs, errcs := getCpusStatsMap()
 | 
			
		||||
	cpusStats := NewCpusStats(cs)
 | 
			
		||||
 | 
			
		||||
	if errcs != nil {
 | 
			
		||||
		panic("error")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cpuTabElems := NewCpuTabElems(termWidth)
 | 
			
		||||
 | 
			
		||||
	Y := 5
 | 
			
		||||
	cpuKeys := make([]string, 0, len(cs))
 | 
			
		||||
	for key := range cs {
 | 
			
		||||
		cpuKeys = append(cpuKeys, key)
 | 
			
		||||
	}
 | 
			
		||||
	sort.Strings(cpuKeys)
 | 
			
		||||
	for _, key := range cpuKeys {
 | 
			
		||||
		cpuTabElems.AddGauge(key, Y, termWidth)
 | 
			
		||||
		Y += 3
 | 
			
		||||
	}
 | 
			
		||||
	cpuTabElems.LChart.Rectangle = cpuTabElems.LChart.GetRect().Add(image.Pt(0, Y))
 | 
			
		||||
 | 
			
		||||
	memTabElems := NewMemTabElems(termWidth)
 | 
			
		||||
	ms, errm := getMemStats()
 | 
			
		||||
	if errm != nil {
 | 
			
		||||
		panic(errm)
 | 
			
		||||
	}
 | 
			
		||||
	memTabElems.Update(ms)
 | 
			
		||||
 | 
			
		||||
	tabpane := widgets.NewTabPane("CPU", "MEM")
 | 
			
		||||
	tabpane.SetRect(0, 1, 30, 30)
 | 
			
		||||
	tabpane.Border = false
 | 
			
		||||
	renderTab := func() {
 | 
			
		||||
		switch tabpane.ActiveTabIndex {
 | 
			
		||||
		case 0:
 | 
			
		||||
			ui.Render(cpuTabElems.LChart)
 | 
			
		||||
			for _, gauge := range cpuTabElems.GMap {
 | 
			
		||||
				ui.Render(gauge)
 | 
			
		||||
			}
 | 
			
		||||
		case 1:
 | 
			
		||||
			ui.Render(memTabElems.Gauge, memTabElems.SLines)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ui.Render(header, tabpane)
 | 
			
		||||
	renderTab()
 | 
			
		||||
 | 
			
		||||
	tickerCount := 1
 | 
			
		||||
	uiEvents := ui.PollEvents()
 | 
			
		||||
	ticker := time.NewTicker(time.Second).C
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case e := <-uiEvents:
 | 
			
		||||
			switch e.ID {
 | 
			
		||||
			case "q", "<C-c>":
 | 
			
		||||
				return
 | 
			
		||||
			case "h":
 | 
			
		||||
				tabpane.FocusLeft()
 | 
			
		||||
				ui.Render(header, tabpane)
 | 
			
		||||
				renderTab()
 | 
			
		||||
			case "l":
 | 
			
		||||
				tabpane.FocusRight()
 | 
			
		||||
				ui.Render(header, tabpane)
 | 
			
		||||
				renderTab()
 | 
			
		||||
			}
 | 
			
		||||
		case <-ticker:
 | 
			
		||||
			cs, errcs := getCpusStatsMap()
 | 
			
		||||
			if errcs != nil {
 | 
			
		||||
				panic(errcs)
 | 
			
		||||
			}
 | 
			
		||||
			cpusStats.tick(cs)
 | 
			
		||||
			cpuTabElems.Update(*cpusStats)
 | 
			
		||||
 | 
			
		||||
			ms, errm := getMemStats()
 | 
			
		||||
			if errm != nil {
 | 
			
		||||
				panic(errm)
 | 
			
		||||
			}
 | 
			
		||||
			memTabElems.Update(ms)
 | 
			
		||||
			ui.Render(header, tabpane)
 | 
			
		||||
			renderTab()
 | 
			
		||||
			tickerCount++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -1,48 +0,0 @@
 | 
			
		||||
// +build ignore
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	ui "github.com/gizak/termui"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	if err := ui.Init(); err != nil {
 | 
			
		||||
		log.Fatalf("failed to initialize termui: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer ui.Close()
 | 
			
		||||
 | 
			
		||||
	grid := ui.NewGrid()
 | 
			
		||||
	termWidth, termHeight := ui.TerminalDimensions()
 | 
			
		||||
	grid.SetRect(0, 0, termWidth, termHeight)
 | 
			
		||||
 | 
			
		||||
	grid2 := ui.NewGrid()
 | 
			
		||||
 | 
			
		||||
	grid2.Set(
 | 
			
		||||
		ui.NewCol(.5, ui.NewBlock()),
 | 
			
		||||
		ui.NewCol(.5, ui.NewRow(.5, ui.NewBlock())),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	grid.Set(
 | 
			
		||||
		ui.NewRow(.5, ui.NewBlock()),
 | 
			
		||||
		ui.NewRow(.5, grid2),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	ui.Render(grid)
 | 
			
		||||
 | 
			
		||||
	uiEvents := ui.PollEvents()
 | 
			
		||||
	for {
 | 
			
		||||
		e := <-uiEvents
 | 
			
		||||
		switch e.ID {
 | 
			
		||||
		case "q", "<C-c>":
 | 
			
		||||
			return
 | 
			
		||||
		case "<Resize>":
 | 
			
		||||
			payload := e.Payload.(ui.Resize)
 | 
			
		||||
			grid.SetRect(0, 0, payload.Width, payload.Height)
 | 
			
		||||
			ui.Clear()
 | 
			
		||||
			ui.Render(grid)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||