Visidata: [colorizer] how to get row index

Created on 1 Jan 2020  路  8Comments  路  Source: saulpw/visidata

From within a colorizer it is not clear how to get context about what we are coloring. Currently you get the row/col/cell. But, it is not clear what the current row or col index is. Or what is the value of the previous/next row/cell.

My Goal: add a command that adds a colorizer to a table that alternates colors on different rows:

  • option 1: alternate rows have alternating colors.

    • Examples from elsewhere:



      • css allows styling odd/even rows differently.


      • continuous feed printer paper that has alternating blue lines



    • Just having the row-index within the colorizer would be enough.

  • option 2: alternate rows based on changes in the key value.

    • if the key value on the previous row is different from the current row use the alternate color

    • It would be useful to be able to compare the current row with the previous row. It would be useful to remember what the previous color value, too.

This issue is follow up to https://github.com/saulpw/visidata/issues/287. On that issue there was feedback from sfranky saying it would have been useful to also color duplicate rows. It seems like row context would be useful for that.

question

Most helpful comment

Thanks for the help, @saulpw I was able to add a colorizer that would add coloring on the row when a timestamp column changed date boundaries. Making it easier to navigate and understand some log data I'm looking at.

I've created a few bugs based on this exercise. Hopefully they are helpful feedback.

All 8 comments

Hi @frosencrantz, unfortunately that isn't supported in core VisiData. However, the rownum plugin maintains a row-number index and provides a Sheet.rowindex(row) function that you can call to get the row number.

If you need the column index, use Sheet.visibleCols.index(col). (Almost always a user extension should use visibleCols instead of columns). It's not ideal for performance reasons (this needs to be called for every cell on the screen), but it is probably okay for most datasets with a handful of columns.

Thanks @saulpw that seems to partially work for option 1.

Trying something like:

Sheet.addCommand('zz', 'printout', 'sheet.addColorizer(RowColorizer(10, None, lambda s,c,r,v: "blue" if s.rowindex(r) % 2 else None))')

Problems:

  • many times rowindex returns None. Gets lot of tracebacks, it is not easy to tell the real source of problem. The tracebacks all start from line sheets.py:208. Is this being called on non-rows?
  • The colorizer appears to apply to all sheets, not just the current sheet. Why? How do I add a colorizer only to the current sheet.

How would you do something like this for option 2, where I want to compare against a value in the previous row? I want to change row color when a timestamp column changes to a new day from the previous row.

This is a known issue with Colorizers. I've tried a few times to improve the API, but the more cases I wanted to handle the more complicated it got. So the way it works, the colorizer function gets called with a None row for the header, and a None column for the separators. This way if you want to color a row completely you can ignore the column, and it will apply as you'd expect (and same with columns). But this means that usually you want to prepend r and to the lambda if you are colorizing actual data rows.

sheet.addColorizer seems like it should only add the colorizer to the current sheet, I agree. This is probably just a bug, though it may prove difficult to fix in the short term. We'll look into this, esp as we finalize the API for 2.0.

Is the assumption that a RowColorizer's value doesn't change for an entire row? And likewise for a ColumnColorizer? And are those values cached for a given row/column? It doesn't look like it to me.

For the option 2 I mentioned above is there a similar method to look at the previous row? Or is it easy and efficient to go from a rowindex to a row?

In actuality, there is no difference between RowColorizer, ColumnColorizer, and CellColorizer. VisiData currently makes no assumptions about how they are used, and calls the full set of colorizers for each interface element.

It is easy and efficient to go from a rowindex to a row with self.rows[rowindex]. To get the value of a cell using that row use col.getTypedValue(row).

How do you set the text color and the background color independently?

The background color cannot be set except with the reverse attribute.

Thanks for the help, @saulpw I was able to add a colorizer that would add coloring on the row when a timestamp column changed date boundaries. Making it easier to navigate and understand some log data I'm looking at.

I've created a few bugs based on this exercise. Hopefully they are helpful feedback.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aborruso picture aborruso  路  3Comments

paulklemm picture paulklemm  路  4Comments

frosencrantz picture frosencrantz  路  4Comments

pigreco picture pigreco  路  3Comments

suntzuisafterU picture suntzuisafterU  路  3Comments