diff options
author | Sean E. Russell <ser@ser1.net> | 2020-02-20 08:19:15 -0600 |
---|---|---|
committer | Sean E. Russell <ser@ser1.net> | 2020-02-20 08:19:15 -0600 |
commit | 7b09a00230e059129e010039a159ef9ce7aecc11 (patch) | |
tree | 7583287cfc2fdc277d7d361ec484e17c3016a0af | |
parent | 66ad0f878540dee82ae2c2b5c561754b6480a157 (diff) |
Issue #56. Slight improvement in layout algorithm. Still doesn't handle > 2 columns well, but it's more correct and lays the foundation for a correct solution. It's clear, however, that a full table model parser will require a substantial rewrite and, possibly, a change in the layout syntax. That would add substantial complexity, so maybe for some future effort. I'll fix the basic column layout (rowspans at the edges), and then shelve it.
-rw-r--r-- | cmd/gotop/main.go | 1 | ||||
-rw-r--r-- | layout/layout.go | 39 | ||||
-rw-r--r-- | layout/layout_test.go | 27 | ||||
-rw-r--r-- | layouts/kitchensink | 9 | ||||
-rw-r--r-- | layouts/many_columns_test | 4 |
5 files changed, 59 insertions, 21 deletions
diff --git a/cmd/gotop/main.go b/cmd/gotop/main.go index a85f147..9d1f0a5 100644 --- a/cmd/gotop/main.go +++ b/cmd/gotop/main.go @@ -423,7 +423,6 @@ func getLayout(conf gotop.Config) io.Reader { case "battery": return strings.NewReader(batteryUI) default: - log.Printf("layout = %s", conf.Layout) fp := filepath.Join(conf.ConfigDir, conf.Layout) fin, err := os.Open(fp) if err != nil { diff --git a/layout/layout.go b/layout/layout.go index 359b47e..0ab6b54 100644 --- a/layout/layout.go +++ b/layout/layout.go @@ -31,17 +31,17 @@ var widgetNames []string = []string{"cpu", "disk", "mem", "temp", "net", "procs" func Layout(wl layout, c gotop.Config) (*MyGrid, error) { rowDefs := wl.Rows - uiRows := make([]ui.GridItem, 0) + uiRows := make([][]interface{}, 0) numRows := countNumRows(wl.Rows) - var uiRow ui.GridItem + var uiRow []interface{} for len(rowDefs) > 0 { uiRow, rowDefs = processRow(c, numRows, rowDefs) uiRows = append(uiRows, uiRow) } rgs := make([]interface{}, 0) + rh := 1.0 / float64(len(uiRows)) for _, ur := range uiRows { - ur.HeightRatio = ur.HeightRatio / float64(numRows) - rgs = append(rgs, ur) + rgs = append(rgs, ui.NewRow(rh, ur...)) } grid := &MyGrid{ui.NewGrid(), nil, nil} grid.Set(rgs...) @@ -58,11 +58,10 @@ func Layout(wl layout, c gotop.Config) (*MyGrid, error) { // if there's a row span widget in the row; in this case, it'll consume as many // rows as the largest row span object in the row, and produce an uber-row // containing all that stuff. It returns a slice without the consumed elements. -func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) (ui.GridItem, [][]widgetRule) { - // FIXME: 3\:A 2\:B\nC should stop consuming rows when all columns are full +func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) ([]interface{}, [][]widgetRule) { // Recursive function #3. See the comment in deepFindProc. if len(rowDefs) < 1 { - return ui.GridItem{}, [][]widgetRule{} + return nil, [][]widgetRule{} } // The height of the tallest widget in this row; the number of rows that // will be consumed, and the overall height of the row that will be @@ -87,6 +86,7 @@ func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) (ui.GridIte columns = append(columns, make([]interface{}, 0)) } colHeights := make([]int, numCols) +outer: for i, row := range processing { // A definition may fill up the columns before all rows are consumed, // e.g. wid1/2 wid2/2. This block checks for that and, if it occurs, @@ -102,16 +102,25 @@ func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) (ui.GridIte rowDefs = append(processing[i:], rowDefs...) break } - // Not all rows have been consumed, so go ahead and place the row's widgets in columns - for _, wid := range row { - for j, ch := range colHeights { - if ch+wid.Height <= maxHeight { - widget := makeWidget(c, wid) - columns[j] = append(columns[j], ui.NewRow(float64(wid.Height)/float64(maxHeight), widget)) - colHeights[j] += wid.Height + // Not all rows have been consumed, so go ahead and place the row's + // widgets in columns + for w, widg := range row { + placed := false + for k := w; k < len(colHeights); k++ { // there are enough columns + ch := colHeights[k] + if ch+widg.Height <= maxHeight { + widget := makeWidget(c, widg) + columns[k] = append(columns[k], ui.NewRow(float64(widg.Height)/float64(maxHeight), widget)) + colHeights[k] += widg.Height + placed = true break } } + // If all columns are full, break out, return the row, and continue processing + if !placed { + rowDefs = processing[i:] + break outer + } } } var uiColumns []interface{} @@ -121,7 +130,7 @@ func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) (ui.GridIte } } - return ui.NewRow(1.0/float64(numRows), uiColumns...), rowDefs + return uiColumns, rowDefs } type Metric interface { diff --git a/layout/layout_test.go b/layout/layout_test.go index d1f016d..568bbee 100644 --- a/layout/layout_test.go +++ b/layout/layout_test.go @@ -101,6 +101,33 @@ func TestParsing(t *testing.T) { assert.Equal(t, 1, l.Rows[1][0].Height) assert.Equal(t, 1.0, l.Rows[1][0].Weight) }}, + {"cpu/2 mem/1 6:procs\n3:temp/1 2:disk/2\npower\nnet procs", func(l layout) { + assert.Equal(t, 4, len(l.Rows)) + // First row + assert.Equal(t, 3, len(l.Rows[0])) + assert.Equal(t, 1, l.Rows[0][0].Height) + assert.Equal(t, 0.5, l.Rows[0][0].Weight) + assert.Equal(t, 1, l.Rows[0][1].Height) + assert.Equal(t, 0.25, l.Rows[0][1].Weight) + assert.Equal(t, 6, l.Rows[0][2].Height) + assert.Equal(t, 0.25, l.Rows[0][2].Weight) + // Second row + assert.Equal(t, 2, len(l.Rows[1])) + assert.Equal(t, 3, l.Rows[1][0].Height) + assert.Equal(t, 1/3.0, l.Rows[1][0].Weight) + assert.Equal(t, 2, l.Rows[1][1].Height) + assert.Equal(t, 2/3.0, l.Rows[1][1].Weight) + // Third row + assert.Equal(t, 1, len(l.Rows[2])) + assert.Equal(t, 1, l.Rows[2][0].Height) + assert.Equal(t, 1.0, l.Rows[2][0].Weight) + // Fourth row + assert.Equal(t, 2, len(l.Rows[3])) + assert.Equal(t, 1, l.Rows[3][0].Height) + assert.Equal(t, 0.5, l.Rows[3][0].Weight) + assert.Equal(t, 1, l.Rows[3][1].Height) + assert.Equal(t, 0.5, l.Rows[3][1].Weight) + }}, } for _, tc := range tests { diff --git a/layouts/kitchensink b/layouts/kitchensink index 762ff91..5e25894 100644 --- a/layouts/kitchensink +++ b/layouts/kitchensink @@ -1,5 +1,4 @@ -cpu/2 mem/1 -3:temp/1 2:disk/2 - power - power -net procs +cpu/2 mem/1 +3:temp/1 2:disk/2 + power +net procs diff --git a/layouts/many_columns_test b/layouts/many_columns_test new file mode 100644 index 0000000..f2d57e3 --- /dev/null +++ b/layouts/many_columns_test @@ -0,0 +1,4 @@ +cpu/2 mem/1 6:procs/2 +3:temp/1 2:disk/2 +power +net procs |