Created
April 23, 2020 08:16
-
-
Save geekscrapy/052f8b7b10d5ef1347a35f6329efd4f2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from visidata import * | |
option(name='delta_timedelta', default='days=1', helpstr='delta between date columns. This should be in the timedelta kwarg format such as days=1, or hours=3') | |
option(name='delta_nocase', default=True, helpstr='compare keycol strings ignoring case') | |
option(name='delta_round_timedelta', default=True, helpstr='draw a line where the time delta is rounded down. The delta will be rounded down') | |
option(name='delta_int', default=0, helpstr='delta between integers/floats for cpmparison') | |
option(name='delta_nKeyCols', default=-1, helpstr='number of keyColumns to compare. -1 is all') | |
theme('color_delta', 'underline', 'color of a row which is different to the one below') | |
dt_unit_order = ['year', 'month', 'day', 'hour', 'minute', 'second', 'microsecond'] | |
def deltaColorizer(sheet, col, row, cellval): | |
## Give up if there are no keycolumns - speeds up loaders without default keycols | |
if len(sheet.keyCols) <= 0: return False | |
## Get the next row, unless we are at the end | |
try: next_row = sheet.rows[sheet.rows.index(row)+1] | |
except: return False | |
## Lists of the keycol values we compare later to eval if they match | |
curr_values = [] | |
next_values = [] | |
if options.delta_nKeyCols == -1: | |
considerCols = sheet.keyCols | |
else: | |
considerCols = sheet.keyCols[:options.delta_nKeyCols] | |
## Setup the date replacements now, for speed | |
delta_unit, delta_val = options.delta_timedelta.split('=')[0], int(options.delta_timedelta.split('=')[1]) | |
dt_unit_i = dt_unit_order.index(delta_unit[:-1])+1 | |
built_dt_replace = dict([(unit,0) for unit in dt_unit_order[dt_unit_i:]]) | |
for kc in considerCols: | |
override = False | |
c_value = kc.getTypedValue(row) | |
n_value = kc.getTypedValue(next_row) | |
if type(c_value) in [TypedExceptionWrapper, TypedWrapper]: | |
override = True | |
## Compare ranges of ints/dates | |
elif kc.type in [int, date]: | |
if kc.type == int: | |
margin = int(options.delta_int) | |
elif kc.type == date and options.delta_round_timedelta: | |
## This nulls the datetime units (day/hour/min) that are rounded | |
## to the required delta (options.delta_date_unit) | |
margin = datetime.timedelta(**{delta_unit: delta_val}) | |
c_value = c_value.replace(**built_dt_replace) | |
n_value = n_value.replace(**built_dt_replace) | |
if not(abs(c_value - n_value) >= margin): | |
override = True | |
if not override: | |
curr_values.append( str(kc.getDisplayValue(row)).lower() if options.delta_nocase else str(kc.getDisplayValue(row)) ) | |
next_values.append( str(kc.getDisplayValue(next_row)).lower() if options.delta_nocase else str(kc.getDisplayValue(next_row)) ) | |
else: | |
curr_values.append(override) | |
next_values.append(override) | |
return curr_values != next_values | |
# @functools.lru_cache(100) | |
# def delta_compare(c_value, n_value): | |
# return True, True | |
@Sheet.api | |
def DeltaColorizer(sheet, enable=True): | |
c = RowColorizer(8, 'color_delta', deltaColorizer) | |
if enable: | |
if not c in sheet.allColorizers: | |
sheet.addColorizer(c) | |
vd.addUndo(sheet.removeColorizer, c) | |
else: | |
try: sheet.removeColorizer(c) | |
except ValueError: status('already disabled') | |
Sheet.addCommand(None, 'delta-enable', 'DeltaColorizer(True)', helpstr='Enable delta') | |
Sheet.addCommand(None, 'delta-disable', 'DeltaColorizer(False)', helpstr='Disable delta') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment