Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2.10.1 #1525

Merged
merged 33 commits into from
Sep 15, 2022
Merged

v2.10.1 #1525

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
41127ed
[dev] bump to v2.11dev
anjakefala Aug 29, 2022
f54dfa9
[thread-] is_alive() not reliable; check in threading.enumerate()
saulpw Aug 30, 2022
db4894a
[sidebar] tighter wordwrap
saulpw Aug 30, 2022
85a39dc
[man] add "rename" to description of rename-*
saulpw Aug 30, 2022
98c62d6
[docs] add rename to rename-column helpstrings
anjakefala Aug 30, 2022
0bd576a
[dev] run mkman
anjakefala Aug 30, 2022
fb8c89e
[freq] disable histogram if disp_histolen or disp_histogram not set
saulpw Aug 30, 2022
0274873
[freq] cleanup imports
saulpw Aug 30, 2022
062c4e2
[expand] add ExpandedColumn to globals
saulpw Aug 31, 2022
62ee13e
[menu-] add BUTTON1_CLICKED same as BUTTON1_PRESSED
saulpw Aug 31, 2022
9c0922d
[regex api] add vd.parse_sed_transform
saulpw Sep 1, 2022
1bf3c18
[tests] package sample.tsv into visidata.tests Closes #1499
anjakefala Sep 7, 2022
3ffb5ea
[path-] remove only one suffix #1494
saulpw Aug 31, 2022
eff9833
Add `open-cell` (`zo`) to open file or url from path in current cell …
anjakefala Sep 8, 2022
226d428
[cmdlog-] add more portable shebang in vdj
saulpw Sep 8, 2022
fa89248
[plugin usd] change to use apilayer
hanfried Sep 9, 2022
388035c
[status-] reduce priority of active coloring #804
saulpw Sep 9, 2022
27bf0d8
[date-] fix date.__ge__ #1507
saulpw Sep 10, 2022
f4fef3b
Document `-d` option
abitrolly Sep 11, 2022
bc0b26a
[tests] move jetsam and flotsam to current folder
anjakefala Sep 11, 2022
414f2dc
Adds unguard-sheet command
hanfried Sep 9, 2022
e9e32c1
Add Menu option for unguarding too
hanfried Sep 9, 2022
1334dae
[guard] rename unguard-sheet to guard-sheet-off
saulpw Sep 11, 2022
57d2d73
Update menu.py
saulpw Sep 11, 2022
97cb8c0
[api] add Extensible.before and Extensible.after
saulpw Sep 12, 2022
3029508
[repeat-] fix repeat- since 184d9e955
anjakefala Sep 12, 2022
2591b37
[macros-] fix macros-record since 184d9e955
anjakefala Sep 12, 2022
4263c83
[macros-] ensure macros are set upon startup
anjakefala Sep 12, 2022
15e0a05
[dev] update CHANGELOG
anjakefala Sep 13, 2022
3fb84f0
Merge branch 'stable' into develop
anjakefala Sep 13, 2022
9380b1e
[docs] update manpage
anjakefala Sep 13, 2022
0e43c19
[docs man] fix display of tab character
anjakefala Sep 14, 2022
3fbcad5
[macros-] add new macro to macrosheet
anjakefala Sep 14, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
# VisiData version history

# v2.10.1 (2022-09-12)

## Improvements

- [docs] document `-d` option (thanks @abitrolly for PR #1515)
- [freq] disable histogram if `disp_histlen` or `disp_histogram` set to 0 or empty string
- [guard] add `guard-sheet-off` which unsets `options.quitguard` on current sheet (thanks @hanfried for PR #1517)
- [menu] add `BUTTON1_CLICKED` (same as `BUTTON1_PRESSED`)
- [open] add `zo` to open file or url from path in current cell

## Bugfixes

- fix Guix build problems (reported by @ryanprior #1499)
- add support for sheet names with multiple `.` (periods) in the name (requested by @geekscrapy #1494)
- [cmdlog] add more portable shebang in vdj
- [date] fix custom date greater than or equal to comparison
- [macros] fix `macro-record` (#1513)
- [macros] refresh `macro-sheet` upon macro addition
- [macros] ensure macros are set upon startup
- [plugins] update usd plugin api (thanks @hanfried for PR #1510)
- [repeat] fix `repeat-` (#1513)
- [status] reduce priority of active colouring (reported by @geekscrapy #804)

## API

- add `ExpandedColumn` to globals
- add `Extensible.before` and `Extensible.after`
- `def foo` decorated with `@VisiData.before` will run it before `vd.foo()`
- `def foo` decorated with `@VisiData.after` will run it immediately after



# v2.10 (2022-08-28)

- [plugins] load all entry points in `visidata.plugins` group before config load
Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ include visidata/man/vd.1
include visidata/man/vd.txt
include visidata/man/visidata.1
include visidata/ddw/input.ddw
include visidata/tests/sample.tsv
1,118 changes: 560 additions & 558 deletions docs/man.md

Large diffs are not rendered by default.

24 changes: 21 additions & 3 deletions plugins/usd.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import json

vd.option('fixer_key', '', 'API Key for fixer.io')
vd.option('fixer_currency_cache_days', 1, 'Cache days for currency conversions')

currency_symbols = {
'$': 'USD',
Expand All @@ -19,9 +20,25 @@
'₫': 'VND',
}

def currency_rates_json(date='latest'):
url = 'http://data.fixer.io/api/%s?access_key=%s' % (date, vd.options.fixer_key)
return vd.urlcache(url).read_text()
def currency_rates_json(date='latest', base='USD'):
url = 'https://api.apilayer.com/fixer/%s?base=%s' % (date, base)
return vd.urlcache(
url,
days=vd.options.fixer_currency_cache_days,
headers={
# First need to set some additional headers as otherwise apilayers will block it with a 403
# See also https://stackoverflow.com/questions/13303449/urllib2-httperror-http-error-403-forbidden
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'Accept-Encoding': 'none',
'Accept-Language': 'en-US,en;q=0.8',
'Connection': 'keep-alive',

# Finally set Apikey
'apikey': vd.options.fixer_key
}
).read_text()

@functools.lru_cache()
def currency_rates():
Expand All @@ -37,6 +54,7 @@ def currency_multiplier(src_currency, dest_currency):
usd_mult = eur_usd_mult/eur_src_mult
if dest_currency == 'USD':
return usd_mult

return usd_mult/currency_rates()[dest_currency]

def USD(s):
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from setuptools import setup
# tox can't actually run python3 setup.py: https://github.com/tox-dev/tox/issues/96
#from visidata import __version__
__version__ = '2.10'
__version__ = '2.11dev'

setup(name='visidata',
version=__version__,
Expand All @@ -29,7 +29,7 @@
packages=['visidata', 'visidata.loaders', 'visidata.vendor', 'visidata.tests'],
include_package_data=True,
data_files = [('share/man/man1', ['visidata/man/vd.1', 'visidata/man/visidata.1'])],
package_data={'visidata': ['man/vd.1', 'man/vd.txt', 'ddw/input.ddw']},
package_data={'visidata': ['man/vd.1', 'man/vd.txt', 'ddw/input.ddw', 'tests/sample.tsv']},
license='GPLv3',
classifiers=[
'Development Status :: 5 - Production/Stable',
Expand Down
2 changes: 1 addition & 1 deletion tests/diff-join.vd
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ sheet col row longname input keystrokes comment
open-file tests/data2.tsv o
data1 Key key-col !
data1 sheets-stack S
sheets キdata2 open-row ^J
sheets キdata2 open-row-pyobj ^J
data2 Key key-col !
data2 sheets-stack S
sheets キdata2 select-row s
Expand Down
2 changes: 1 addition & 1 deletion tests/edit-joinkey-2.vd
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ data2+data1 A key-col !
data2+data1 Key キ2 edit-cell 4 e
data2+data1 reload-sheet ^R
data2 sheets-stack S
sheets キdata1 open-row ^J
sheets キdata1 open-row-pyobj ^J
2 changes: 1 addition & 1 deletion tests/edit-joinregular-2.vd
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ data2+data1 sort-keys-asc g[
data2+data1 A key-col !
data2+data1 C キ2 edit-cell a3 e
data2+data1 sheets-stack S
sheets キdata2 open-row ^J
sheets キdata2 open-row-pyobj ^J
2 changes: 1 addition & 1 deletion tests/invalid_unicode_sqlite.vd
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ sheet col row longname input keystrokes comment
global encoding set-option latin-1
invalid_unicode encoding set-option latin-1
open-file tests/invalid_unicode.sqlite o
invalid_unicode キTest open-row Enter open sheet with copies of rows referenced in current row
invalid_unicode キTest open-row-pyobj Enter open sheet with copies of rows referenced in current row
2 changes: 1 addition & 1 deletion tests/join-cols-single-sheet.vd
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ sample_columns キRegion select-row s select current row
sample_columns キRep select-row s select current row
sample_columns join-cols & add column from concatenating selected source columns
sample_columns sheets-stack S open Sheets Stack: join or jump between the active sheets on the current stack
sheets キsample open-row ^J open sheet with copies of rows referenced in current row
sheets キsample open-row-pyobj ^J open sheet with copies of rows referenced in current row
6 changes: 3 additions & 3 deletions tests/join-different-types.vd
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
sheet col row longname input keystrokes comment
open-file tests/joining_error.xlsx o
open-file tests/joining_error_interesting_records.csv o
joining_error キrecords open-row ^J open sheet with copies of rows referenced in current row
joining_error キrecords open-row-pyobj ^J open sheet with copies of rows referenced in current row
joining_error_records sheets-stack S open Sheets Stack: join or jump between the active sheets on the current stack
sheets キjoining_error_interesting_records slide-up K slide current row up
sheets キjoining_error_interesting_records slide-up K slide current row up
sheets キjoining_error_interesting_records select-row s select current row
sheets キjoining_error_records select-row s select current row
sheets キjoining_error_interesting_records open-row ^J open sheet referenced in current row
sheets キjoining_error_interesting_records open-row-pyobj ^J open sheet referenced in current row
joining_error_interesting_records Row key-col ! toggle current column as a key column
joining_error_interesting_records sheets-stack S open Sheets Stack: join or jump between the active sheets on the current stack
sheets キjoining_error_records open-row ^J open sheet referenced in current row
sheets キjoining_error_records open-row-pyobj ^J open sheet referenced in current row
joining_error_records Row key-col ! toggle current column as a key column
joining_error_records sheets-stack S open Sheets Stack: join or jump between the active sheets on the current stack
sheets キjoining_error_interesting_records slide-up K slide current row up
Expand Down
2 changes: 1 addition & 1 deletion tests/join-non-unique-cols.vd
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ sheets join-sheets outer &
benchmark+sample columns-sheet C
benchmark+sample_columns name sort-desc ]
benchmark+sample_columns sheets-stack S
sheets キbenchmark+sample open-row ^J
sheets キbenchmark+sample open-row-pyobj ^J
2 changes: 1 addition & 1 deletion tests/listofdictobj.vd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
sheet col row longname input keystrokes comment
open-file sample_data/y77d-th95.json.gz o
y77d-th95 geolocation expand-col-depth 1 z( expand current column of containers to given depth (0=fully)
geolocation.coordinates 0 open-cell z^J open sheet with copies of rows referenced in current cell
geolocation.coordinates 0 open-cell-pyobj z^J open sheet with copies of rows referenced in current cell
2 changes: 1 addition & 1 deletion tests/load-ods.vd
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
sheet col row longname input keystrokes comment
open-file sample_data/benchmark.ods o
benchmark キbenchmark open-row Enter open sheet with copies of rows referenced in current row
benchmark キbenchmark open-row-pyobj Enter open sheet with copies of rows referenced in current row
2 changes: 1 addition & 1 deletion tests/load-sqlite-view.vd
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
sheet col row longname input keystrokes comment
open-file sample_data/employees.sqlite o
employees キemp_view open-row Enter open sheet with copies of rows referenced in current row
employees キemp_view open-row-pyobj Enter open sheet with copies of rows referenced in current row
6 changes: 3 additions & 3 deletions tests/load-zip.vd
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
sheet col row longname input keystrokes comment keystrokes input longname sheet col row comment undofuncs
open-file sample_data/benchmark.zip o o sample_data/benchmark.zip open-file
benchmark キsample_data/,benchmark.csv open-row Enter open sheet with copies of rows referenced in current row Enter open-row benchmark キsample_data/,benchmark.csv open sheet with copies of rows referenced in current row [29] [3] <built-in function setattr>; [3] benchmark; _names; [1] benchmark; {0}; [3] <built-in function setattr>; [3] benchmark; _names; [1] benchmark; {0}; [3] <function undoAttrFunc.<locals>._undofunc at 0x7fb5c11b3f40>; [0] ; {0}; [3] <built-in function setattr>; [3] benchmark_cmdlog; _names; [1] benchmark_cmdlog; {0}; [3] <built-in function setattr>; [3] benchmark_cmdlog; _names; [1] benchmark_cmdlog; {0}; [3] <function undoAttrFunc.<locals>._undofunc at 0x7fb5c11b3eb0>; [0] ; {0}; [3] <built-in function setattr>; [3] benchmark_cmdlog; _names; [1] benchmark_cmdlog; {0}; [3] <built-in function setattr>; [3] benchmark_cmdlog; _names; [1] benchmark_cmdlog; {0}; [3] <function undoAttrFunc.<locals>._undofunc at 0x7fb5c11b3d90>; [0] ; {0}; [3] <built-in method remove of list object at 0x7fb5c1118740>; [1] <visidata.column.ItemColumn object at 0x7fb5c11e8850>; {0}; [3] <built-in method remove of list object at 0x7fb5c1118740>; [1] <visidata.column.ItemColumn object at 0x7fb5c11af880>; {0}; [3] <built-in method remove of list object at 0x7fb5c1118740>; [1] <visidata.column.ItemColumn object at 0x7fb5c11e8be0>; {0}; [3] <built-in method remove of list object at 0x7fb5c1118740>; [1] <visidata.column.ItemColumn object at 0x7fb5c11eabf0>; {0}; [3] <built-in method remove of list object at 0x7fb5c1118740>; [1] <visidata.column.ItemColumn object at 0x7fb5c0528c40>; {0}; [3] <built-in method remove of list object at 0x7fb5c0516e40>; [1] <visidata.column.ItemColumn object at 0x7fb5c05287c0>; {0}; [3] <built-in method remove of list object at 0x7fb5c0516e40>; [1] <visidata.column.ItemColumn object at 0x7fb5c0528ca0>; {0}; [3] <built-in method remove of list object at 0x7fb5c0516e40>; [1] <visidata.column.ItemColumn object at 0x7fb5c0528cd0>; {0}; [3] <built-in method remove of list object at 0x7fb5c0516e40>; [1] <visidata.column.ItemColumn object at 0x7fb5c0528d00>; {0}; [3] <built-in method remove of list object at 0x7fb5c0516e40>; [1] <visidata.column.ItemColumn object at 0x7fb5c0528d30>; {0}; [3] <built-in method remove of list object at 0x7fb5c0516e40>; [1] <visidata.column.ItemColumn object at 0x7fb5c0528d60>; {0}; [3] <built-in method remove of list object at 0x7fb5c0516e40>; [1] <visidata.column.ItemColumn object at 0x7fb5c0528d90>; {0}; [3] <built-in method remove of list object at 0x7fb5c0516e40>; [1] <visidata.column.ItemColumn object at 0x7fb5c0528dc0>; {0}; [3] <built-in method remove of list object at 0x7fb5c11fdcc0>; [1] <visidata.column.ItemColumn object at 0x7fb5c0529000>; {0}; [3] <built-in method remove of list object at 0x7fb5c11fdcc0>; [1] <visidata.column.ItemColumn object at 0x7fb5c11de0b0>; {0}; [3] <built-in method remove of list object at 0x7fb5c11fdcc0>; [1] <visidata.column.ItemColumn object at 0x7fb5c0529030>; {0}; [3] <built-in method remove of list object at 0x7fb5c11fdcc0>; [1] <visidata.column.ItemColumn object at 0x7fb5c0529090>; {0}; [3] <built-in method remove of list object at 0x7fb5c11fdcc0>; [1] <visidata.column.ItemColumn object at 0x7fb5c05290c0>; {0}; [3] <built-in method remove of list object at 0x7fb5c11fdcc0>; [1] <visidata.column.ItemColumn object at 0x7fb5c0529150>; {0}; [3] <built-in method remove of list object at 0x7fb5c11fdcc0>; [1] <visidata.column.ItemColumn object at 0x7fb5c0529180>; {0}
sheet col row longname input keystrokes comment
open-file sample_data/benchmark.zip o
benchmark キsample_data/,benchmark.csv open-row-pyobj Enter open sheet with copies of rows referenced in current row
2 changes: 1 addition & 1 deletion tests/sqlite_withoutrowid.vd
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
sheet col row longname input keystrokes comment
open-file tests/without_rowid.db o
without_rowid キwithoutrowid open-row Enter open sheet with copies of rows referenced in current row
without_rowid キwithoutrowid open-row-pyobj Enter open sheet with copies of rows referenced in current row
2 changes: 1 addition & 1 deletion tests/xlsx-color-cells.vd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
sheet col row longname input keystrokes comment
global xlsx_meta_columns set-option True
open-file sample_data/color-merged-cells.xlsx o
color-merged-cells キSheet1 open-row Enter open sheet with copies of rows referenced in current row
color-merged-cells キSheet1 open-row-pyobj Enter open sheet with copies of rows referenced in current row
2 changes: 1 addition & 1 deletion tests/xlsx-empty-cell.vd
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
sheet col row longname input keystrokes comment
open-file sample_data/empty-cell.xlsx o
empty-cell キSheet1 open-row Enter open sheet with copies of rows referenced in current row
empty-cell キSheet1 open-row-pyobj Enter open sheet with copies of rows referenced in current row
2 changes: 1 addition & 1 deletion tests/xlsx-merged-cells.vd
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
sheet col row longname input keystrokes comment
open-file sample_data/color-merged-cells.xlsx o
color-merged-cells キSheet1 open-row Enter open sheet with copies of rows referenced in current row
color-merged-cells キSheet1 open-row-pyobj Enter open sheet with copies of rows referenced in current row
2 changes: 1 addition & 1 deletion visidata/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'VisiData: a curses interface for exploring and arranging tabular data'

__version__ = '2.10'
__version__ = '2.11dev'
__version_info__ = 'VisiData v' + __version__
__author__ = 'Saul Pwanson <vd@saul.pw>'
__status__ = 'Production/Stable'
Expand Down
1 change: 1 addition & 0 deletions visidata/_open.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,4 @@ def loadInternalSheet(vd, cls, p, **kwargs):


BaseSheet.addCommand('o', 'open-file', 'vd.push(openSource(inputFilename("open: "), create=True))', 'Open file or URL')
TableSheet.addCommand('zo', 'open-cell', 'vd.push(openSource(cursorDisplay))', 'Open file or URL from path in current cell')
2 changes: 1 addition & 1 deletion visidata/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def __le__(self, b):
return NotImplemented

def __ge__(self, b):
if isinstance(b, datetime.datetime): return datetime.datetime.__le__(self, b)
if isinstance(b, datetime.datetime): return datetime.datetime.__ge__(self, b)
elif isinstance(b, datetime.date): return self.date().__ge__(b)
return NotImplemented

Expand Down
8 changes: 4 additions & 4 deletions visidata/cmdlog.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def open_vdj(vd, p):
@VisiData.api
def save_vdj(vd, p, *vsheets):
with p.open_text(mode='w', encoding=vsheets[0].options.encoding) as fp:
fp.write("#!vd -p\n")
fp.write("#!/usr/bin/env vd -p\n")
for vs in vsheets:
vs.write_jsonl(fp)

Expand Down Expand Up @@ -178,7 +178,7 @@ def beforeExecHook(self, sheet, cmd, args, keystrokes):
self.afterExecSheet(sheet, False, '')

colname, rowname, sheetname = '', '', None
if sheet and not (cmd.longname.startswith('open-') and not cmd.longname in ('open-row', 'open-cell')):
if sheet and not (cmd.longname.startswith('open-') and not cmd.longname in ('open-row-pyobj', 'open-cell-pyobj')):
sheetname = sheet.name

colname, rowname = sheet.commandCursor(cmd.execstr)
Expand Down Expand Up @@ -464,14 +464,14 @@ def modifyCommand(vd):
return vd.cmdlog.rows[-1]


@CommandLog.api
@CommandLogJsonl.api
@asyncthread
def repeat_for_n(cmdlog, r, n=1):
r.sheet = r.row = r.col = ""
for i in range(n):
vd.replayOne(r)

@CommandLog.api
@CommandLogJsonl.api
@asyncthread
def repeat_for_selected(cmdlog, r):
r.sheet = r.row = r.col = ""
Expand Down
5 changes: 3 additions & 2 deletions visidata/deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,9 @@ def isNumeric(col):
alias('next-null', 'go-next-null')
alias('page-right', 'go-right-page')
alias('page-left', 'go-left-page')
alias('dive-cell', 'open-cell')
alias('dive-row', 'open-row')
alias('dive-cell', 'open-cell-pyobj')
alias('dive-row', 'open-row-pyobj')
alias('open-row', 'open-row-pyobj')
alias('add-sheet', 'open-new')
alias('save-sheets-selected', 'save-selected')
alias('join-sheets', 'join-selected')
Expand Down
31 changes: 31 additions & 0 deletions visidata/extensible.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,37 @@ def api(cls, func):
setattr(cls, func.__name__, func)
return func

@classmethod
def before(cls, beforefunc):
funcname = beforefunc.__name__
oldfunc = getattr(cls, funcname, None)
if not oldfunc:
vd.fail('@before on non-existing func {cls.__name__}.{funcname}')

@wraps(oldfunc)
def wrappedfunc(*args, **kwargs):
beforefunc(*args, **kwargs)
return oldfunc(*args, **kwargs)

setattr(cls, funcname, wrappedfunc)
return wrappedfunc

@classmethod
def after(cls, beforefunc):
funcname = beforefunc.__name__
oldfunc = getattr(cls, funcname, None)
if not oldfunc:
vd.fail('@after on non-existing func {cls.__name__}.{funcname}')

@wraps(oldfunc)
def wrappedfunc(*args, **kwargs):
r = oldfunc(*args, **kwargs)
beforefunc(*args, **kwargs)
return r

setattr(cls, funcname, wrappedfunc)
return wrappedfunc

@classmethod
def class_api(cls, func):
name = func.__get__(None, dict).__func__.__name__
Expand Down
23 changes: 15 additions & 8 deletions visidata/freqtbl.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import math
import collections
from copy import copy

from visidata import *
from visidata.pivot import PivotSheet
from visidata import vd, asyncthread, vlen, VisiData, Column, AttrColumn, Sheet, ColumnsSheet, ENTER
from visidata.pivot import PivotSheet, PivotGroupRow


vd.option('disp_histogram', '*', 'histogram element character')
Expand Down Expand Up @@ -47,10 +46,18 @@ def reload(self):

# add default bonus columns
for c in [
ColumnAttr('count', 'sourcerows', type=vlen),
Column('percent', type=float, getter=lambda col,row: len(row.sourcerows)*100/col.sheet.source.nRows),
Column('histogram', type=str, getter=lambda col,row: options.disp_histogram*(options.disp_histolen*len(row.sourcerows)//col.sheet.largest), width=options.disp_histolen+2),
]:
AttrColumn('count', 'sourcerows', type=vlen),
Column('percent', type=float, getter=lambda col,row: len(row.sourcerows)*100/col.sheet.source.nRows),
]:
self.addColumn(c)

if self.options.disp_histolen and self.options.disp_histogram:
def histogram(col, row):
histogram = col.sheet.options.disp_histogram
histolen = col.sheet.options.disp_histolen
return histogram*(histolen*len(row.sourcerows)//col.sheet.largest)

c = Column('histogram', type=str, getter=histogram, width=self.options.disp_histolen+2)
self.addColumn(c)

# two more threads
Expand Down