jedib0t / go-pretty

Table-writer and more in golang!
MIT License
3.06k stars 120 forks source link

Reset Rows not working as expected #339

Closed elC0mpa closed 2 weeks ago

elC0mpa commented 2 weeks ago

Describe the bug I am calling the ResetRows method andd after that Appending Rows and previous rows are not deleted. I don´t know if I am doing something wrong or maybe it is a bug

To Reproduce

package table

import (
    "fmt"
    "os"

    "github.com/elC0mpa/gonet/model/network"
    "github.com/jedib0t/go-pretty/v6/table"
)

type drawer struct {
    table      table.Writer
    rowsDrawed int
}

func NewTableDrawer() TableDrawer {
    t := table.NewWriter()
    t.SetOutputMirror(os.Stdout)
    t.AppendHeader(table.Row{"Application", "Bytes Rcvd", "Bytes Sent"})

    return &drawer{
        table:      t,
        rowsDrawed: 0,
    }
}

func (tableDrawer *drawer) Draw(appUsage map[string]network.NetworkInfo) {
    if tableDrawer.rowsDrawed > 0 {
        tableDrawer.table.ResetRows()
    }

    for appName, netInfo := range appUsage {
        tableDrawer.table.AppendRow(table.Row{appName, netInfo.ReceivedBytes, netInfo.SentBytes})
    }

    fmt.Println(tableDrawer.table.Render())

    tableDrawer.rowsDrawed = len(appUsage)
}

Just execute the Draw method multiple times and you will get multiple tables

Expected behavior I just want to refresh my table, not to get multiple tables.

Software (please complete the following information):

jedib0t commented 2 weeks ago

I just want to refresh my table, not to get multiple tables.

Do you mean you want the old table to be wiped out and the new contents displayed in the same location?

ResetRows just clears up the list of rows appended to the table object. It does not do anything to the screen/already-rendered-output. Think of it as a short-hand to reuse the same table object instead of creating a new one every time you need to render a new table with same style/header/footer.

elC0mpa commented 2 weeks ago

I understand Now let me ask you, I need to refresh the Table and that it renders in the same place, is there any workaround for it that you could recommend me?

jedib0t commented 2 weeks ago

You can do something like this:

package main

import (
    "fmt"
    "github.com/jedib0t/go-pretty/v6/table"
    "github.com/jedib0t/go-pretty/v6/text"
    "math/rand"
    "strings"
    "time"
)

func main() {
    numLinesPrinted := 0
    for idx := 0; idx < 10; idx++ {
        // erase all lines printed before
        for numLinesPrinted > 0 {
            fmt.Print(text.CursorUp.Sprint())
            fmt.Print(text.EraseLine.Sprint())
            numLinesPrinted--
        }

        // generate table and print
        out := generateTable(fmt.Sprintf("index=%d", idx), idx+1)
        fmt.Println(out)

        // count the number of lines printed
        numLinesPrinted = strings.Count(out, "\n") + 1 // + 1 due to Println which adds a new-line of its own

        // artificial delay to show the table being changed
        time.Sleep(time.Second)
    }
}

func generateTable(title string, numRows int) string {
    tw := table.NewWriter()
    tw.AppendHeader(table.Row{"ID", "Name", "Age"})
    for idx := 0; idx < numRows; idx++ {
        tw.AppendRow(table.Row{
            idx + 1,
            fmt.Sprintf("Name of #%d", idx),
            rand.Intn(100) + 1,
        })
    }
    tw.SetTitle(title)
    return tw.Render()
}

However, the bigger the number of lines you are erasing, the slower your terminal will perform. And the above doesn't behave well if your table spans more than one terminal page. If you are dealing with a small table it should be fine.