visidata 2.11.1__py3-none-any.whl → 3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- visidata/__init__.py +72 -91
- visidata/_input.py +259 -42
- visidata/_open.py +84 -29
- visidata/_types.py +21 -3
- visidata/_urlcache.py +17 -4
- visidata/aggregators.py +65 -25
- visidata/apps/__init__.py +0 -0
- visidata/apps/vdsql/__about__.py +8 -0
- visidata/apps/vdsql/__init__.py +5 -0
- visidata/apps/vdsql/__main__.py +27 -0
- visidata/apps/vdsql/_ibis.py +748 -0
- visidata/apps/vdsql/bigquery.py +61 -0
- visidata/apps/vdsql/clickhouse.py +53 -0
- visidata/apps/vdsql/setup.py +40 -0
- visidata/apps/vdsql/snowflake.py +67 -0
- visidata/apps/vgit/__init__.py +13 -0
- {vgit → visidata/apps/vgit}/blame.py +5 -2
- {vgit → visidata/apps/vgit}/branch.py +31 -16
- {vgit → visidata/apps/vgit}/config.py +3 -3
- visidata/apps/vgit/diff.py +169 -0
- visidata/apps/vgit/gitsheet.py +161 -0
- {vgit → visidata/apps/vgit}/grep.py +6 -5
- visidata/apps/vgit/log.py +81 -0
- {vgit → visidata/apps/vgit}/main.py +18 -5
- {vgit → visidata/apps/vgit}/remote.py +8 -4
- visidata/apps/vgit/repos.py +71 -0
- {vgit → visidata/apps/vgit}/setup.py +6 -4
- visidata/apps/vgit/stash.py +69 -0
- visidata/apps/vgit/status.py +204 -0
- {vgit → visidata/apps/vgit}/statusbar.py +2 -0
- visidata/basesheet.py +59 -50
- visidata/canvas.py +208 -93
- visidata/choose.py +6 -6
- visidata/clean_names.py +29 -0
- visidata/clipboard.py +73 -17
- visidata/cliptext.py +220 -46
- visidata/cmdlog.py +88 -114
- visidata/color.py +142 -56
- visidata/column.py +121 -129
- visidata/ddw/input.ddw +74 -79
- visidata/ddw/regex.ddw +57 -0
- visidata/ddwplay.py +33 -14
- visidata/deprecated.py +77 -3
- visidata/desktop/visidata.desktop +7 -0
- visidata/editor.py +12 -6
- visidata/errors.py +5 -1
- visidata/experimental/__init__.py +0 -0
- visidata/experimental/diff_sheet.py +29 -0
- visidata/experimental/digit_autoedit.py +6 -0
- visidata/experimental/gdrive.py +89 -0
- visidata/experimental/google.py +37 -0
- visidata/experimental/gsheets.py +79 -0
- visidata/experimental/live_search.py +37 -0
- visidata/experimental/liveupdate.py +45 -0
- visidata/experimental/mark.py +133 -0
- visidata/experimental/noahs_tapestry/__init__.py +1 -0
- visidata/experimental/noahs_tapestry/tapestry.py +147 -0
- visidata/experimental/rownum.py +73 -0
- visidata/experimental/slide_cells.py +26 -0
- visidata/expr.py +8 -4
- visidata/extensible.py +30 -5
- visidata/features/__init__.py +0 -0
- visidata/features/addcol_audiometadata.py +42 -0
- visidata/features/addcol_histogram.py +34 -0
- visidata/features/canvas_save_svg.py +69 -0
- visidata/features/change_precision.py +46 -0
- visidata/features/cmdpalette.py +163 -0
- visidata/features/colorbrewer.py +363 -0
- visidata/{colorsheet.py → features/colorsheet.py} +17 -16
- visidata/features/command_server.py +105 -0
- visidata/features/currency_to_usd.py +70 -0
- visidata/{customdate.py → features/customdate.py} +2 -0
- visidata/features/dedupe.py +132 -0
- visidata/{describe.py → features/describe.py} +17 -15
- visidata/features/errors_guide.py +26 -0
- visidata/features/expand_cols.py +202 -0
- visidata/{fill.py → features/fill.py} +3 -1
- visidata/{freeze.py → features/freeze.py} +11 -6
- visidata/features/graph_seaborn.py +79 -0
- visidata/features/helloworld.py +10 -0
- visidata/features/hint_types.py +17 -0
- visidata/{incr.py → features/incr.py} +5 -0
- visidata/{join.py → features/join.py} +107 -53
- visidata/features/known_cols.py +21 -0
- visidata/features/layout.py +62 -0
- visidata/{melt.py → features/melt.py} +32 -21
- visidata/features/normcol.py +118 -0
- visidata/features/open_config.py +7 -0
- visidata/features/open_syspaste.py +18 -0
- visidata/features/ping.py +157 -0
- visidata/features/procmgr.py +208 -0
- visidata/features/random_sample.py +6 -0
- visidata/{regex.py → features/regex.py} +47 -31
- visidata/features/reload_every.py +55 -0
- visidata/features/rename_col_cascade.py +30 -0
- visidata/features/scroll_context.py +60 -0
- visidata/features/select_equal_selected.py +11 -0
- visidata/features/setcol_fake.py +65 -0
- visidata/{slide.py → features/slide.py} +75 -21
- visidata/features/sparkline.py +48 -0
- visidata/features/status_source.py +20 -0
- visidata/{sysedit.py → features/sysedit.py} +2 -1
- visidata/features/sysopen_mailcap.py +46 -0
- visidata/features/term_extras.py +13 -0
- visidata/{transpose.py → features/transpose.py} +5 -4
- visidata/features/type_ipaddr.py +73 -0
- visidata/features/type_url.py +11 -0
- visidata/{unfurl.py → features/unfurl.py} +9 -9
- visidata/{window.py → features/window.py} +2 -2
- visidata/form.py +50 -21
- visidata/freqtbl.py +81 -33
- visidata/fuzzymatch.py +414 -0
- visidata/graph.py +105 -33
- visidata/guide.py +180 -0
- visidata/help.py +75 -44
- visidata/hint.py +39 -0
- visidata/indexsheet.py +109 -0
- visidata/input_history.py +55 -0
- visidata/interface.py +58 -0
- visidata/keys.py +17 -16
- visidata/loaders/__init__.py +9 -0
- visidata/loaders/_pandas.py +61 -21
- visidata/loaders/api_airtable.py +70 -0
- visidata/loaders/api_bitio.py +102 -0
- visidata/loaders/api_matrix.py +148 -0
- visidata/loaders/api_reddit.py +306 -0
- visidata/loaders/api_zulip.py +249 -0
- visidata/loaders/archive.py +41 -7
- visidata/loaders/arrow.py +7 -7
- visidata/loaders/conll.py +49 -0
- visidata/loaders/csv.py +25 -7
- visidata/loaders/eml.py +3 -4
- visidata/loaders/f5log.py +1204 -0
- visidata/loaders/fec.py +325 -0
- visidata/loaders/fixed_width.py +2 -4
- visidata/loaders/frictionless.py +3 -3
- visidata/loaders/geojson.py +8 -5
- visidata/loaders/google.py +48 -0
- visidata/loaders/graphviz.py +4 -4
- visidata/loaders/hdf5.py +4 -4
- visidata/loaders/html.py +48 -10
- visidata/loaders/http.py +84 -30
- visidata/loaders/imap.py +20 -10
- visidata/loaders/jrnl.py +52 -0
- visidata/loaders/json.py +83 -29
- visidata/loaders/jsonla.py +74 -0
- visidata/loaders/lsv.py +15 -11
- visidata/loaders/mailbox.py +40 -0
- visidata/loaders/markdown.py +1 -3
- visidata/loaders/mbtiles.py +4 -5
- visidata/loaders/mysql.py +11 -13
- visidata/loaders/npy.py +7 -7
- visidata/loaders/odf.py +4 -1
- visidata/loaders/orgmode.py +428 -0
- visidata/loaders/pandas_freqtbl.py +14 -20
- visidata/loaders/parquet.py +62 -6
- visidata/loaders/pcap.py +3 -3
- visidata/loaders/pdf.py +4 -3
- visidata/loaders/png.py +19 -13
- visidata/loaders/postgres.py +9 -8
- visidata/loaders/rec.py +7 -3
- visidata/loaders/s3.py +342 -0
- visidata/loaders/sas.py +5 -5
- visidata/loaders/scrape.py +186 -0
- visidata/loaders/shp.py +6 -5
- visidata/loaders/spss.py +5 -6
- visidata/loaders/sqlite.py +68 -28
- visidata/loaders/texttables.py +1 -1
- visidata/loaders/toml.py +60 -0
- visidata/loaders/tsv.py +61 -19
- visidata/loaders/ttf.py +19 -7
- visidata/loaders/unzip_http.py +6 -5
- visidata/loaders/usv.py +1 -1
- visidata/loaders/vcf.py +16 -16
- visidata/loaders/vds.py +10 -7
- visidata/loaders/vdx.py +30 -5
- visidata/loaders/xlsb.py +8 -1
- visidata/loaders/xlsx.py +145 -25
- visidata/loaders/xml.py +6 -3
- visidata/loaders/xword.py +4 -4
- visidata/loaders/yaml.py +15 -5
- visidata/macros.py +129 -42
- visidata/main.py +119 -94
- visidata/mainloop.py +101 -155
- visidata/man/parse_options.py +2 -2
- visidata/man/vd.1 +301 -148
- visidata/man/vd.txt +290 -153
- visidata/memory.py +3 -3
- visidata/menu.py +104 -423
- visidata/metasheets.py +59 -141
- visidata/modify.py +78 -23
- visidata/motd.py +3 -3
- visidata/mouse.py +137 -0
- visidata/movement.py +43 -35
- visidata/optionssheet.py +99 -0
- visidata/path.py +113 -32
- visidata/pivot.py +73 -47
- visidata/plugins.py +65 -192
- visidata/pyobj.py +50 -201
- visidata/rename_col.py +20 -0
- visidata/save.py +37 -20
- visidata/search.py +54 -10
- visidata/selection.py +84 -5
- visidata/settings.py +162 -25
- visidata/sheets.py +229 -257
- visidata/shell.py +51 -21
- visidata/sidebar.py +162 -0
- visidata/sort.py +11 -4
- visidata/statusbar.py +113 -104
- visidata/stored_list.py +43 -0
- visidata/stored_prop.py +38 -0
- visidata/tests/conftest.py +3 -3
- visidata/tests/test_cliptext.py +39 -0
- visidata/tests/test_commands.py +62 -7
- visidata/tests/test_edittext.py +2 -2
- visidata/tests/test_features.py +17 -0
- visidata/tests/test_menu.py +14 -0
- visidata/tests/test_path.py +13 -4
- visidata/text_source.py +53 -0
- visidata/textsheet.py +10 -3
- visidata/theme.py +44 -0
- visidata/themes/__init__.py +0 -0
- visidata/themes/ascii8.py +84 -0
- visidata/themes/asciimono.py +84 -0
- visidata/themes/light.py +17 -0
- visidata/threads.py +87 -39
- visidata/tuiwin.py +22 -0
- visidata/type_currency.py +22 -3
- visidata/type_date.py +31 -9
- visidata/type_floatsi.py +5 -1
- visidata/undo.py +17 -5
- visidata/utils.py +106 -23
- visidata/vdobj.py +28 -17
- visidata/windows.py +10 -0
- visidata/wrappers.py +9 -3
- visidata-3.0.data/data/share/applications/visidata.desktop +7 -0
- {visidata-2.11.1.data → visidata-3.0.data}/data/share/man/man1/vd.1 +301 -148
- {visidata-2.11.1.data → visidata-3.0.data}/data/share/man/man1/visidata.1 +301 -148
- visidata-3.0.data/scripts/vd2to3.vdx +9 -0
- {visidata-2.11.1.dist-info → visidata-3.0.dist-info}/METADATA +12 -8
- visidata-3.0.dist-info/RECORD +257 -0
- {visidata-2.11.1.dist-info → visidata-3.0.dist-info}/WHEEL +1 -1
- vgit/__init__.py +0 -1
- vgit/gitsheet.py +0 -164
- visidata/layout.py +0 -44
- visidata/misc.py +0 -5
- visidata-2.11.1.data/scripts/vgit +0 -9
- visidata-2.11.1.dist-info/RECORD +0 -155
- {vgit → visidata/apps/vgit}/__main__.py +0 -0
- {vgit → visidata/apps/vgit}/abort.py +0 -0
- /visidata/{repeat.py → features/repeat.py} +0 -0
- {visidata-2.11.1.data → visidata-3.0.data}/scripts/vd +0 -0
- {visidata-2.11.1.dist-info → visidata-3.0.dist-info}/LICENSE.gpl3 +0 -0
- {visidata-2.11.1.dist-info → visidata-3.0.dist-info}/entry_points.txt +0 -0
- {visidata-2.11.1.dist-info → visidata-3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
__author__ = 'Andy Craig, andycraig (https://github.com/andycraig)'
|
2
|
+
|
3
|
+
|
4
|
+
import re
|
5
|
+
|
6
|
+
from visidata import vd, Sheet, Column, floatsi, currency, date
|
7
|
+
|
8
|
+
date_fmtstrs = [
|
9
|
+
'%Y',
|
10
|
+
'%Y-%m',
|
11
|
+
# '%Y-W%U',
|
12
|
+
'%Y-%m-%d',
|
13
|
+
'%Y-%m-%d %H',
|
14
|
+
'%Y-%m-%d %H:%M',
|
15
|
+
'%Y-%m-%d %H:%M:%S',
|
16
|
+
'%Y-%m-%d %H:%M:%S.%f',
|
17
|
+
]
|
18
|
+
|
19
|
+
@Column.api
|
20
|
+
def setcol_precision(col, amount:int):
|
21
|
+
if col.type is date:
|
22
|
+
try:
|
23
|
+
i = date_fmtstrs.index(col.fmtstr)
|
24
|
+
except ValueError:
|
25
|
+
i = 2
|
26
|
+
col.fmtstr = date_fmtstrs[(i+amount)%len(date_fmtstrs)]
|
27
|
+
elif col.type in (float, floatsi, currency):
|
28
|
+
if col.fmtstr == '':
|
29
|
+
col.fmtstr = f'%.{2 + amount}f'
|
30
|
+
else:
|
31
|
+
precision_str = re.match(r'%.([0-9]+)f', col.fmtstr)
|
32
|
+
if not precision_str is None:
|
33
|
+
col.fmtstr = f'%.{max(0, int(precision_str[1]) + amount)}f'
|
34
|
+
else:
|
35
|
+
col.type = float
|
36
|
+
if col.fmtstr == '':
|
37
|
+
col.fmtstr = '%.2f'
|
38
|
+
|
39
|
+
|
40
|
+
vd.addMenuItems('''
|
41
|
+
Column > Set precision > more > setcol-precision-more
|
42
|
+
Column > Set precision > less > setcol-precision-less
|
43
|
+
''')
|
44
|
+
|
45
|
+
Sheet.addCommand('Alt+-', 'setcol-precision-less', 'cursorCol.setcol_precision(-1)', 'show less precision in current column')
|
46
|
+
Sheet.addCommand('Alt++', 'setcol-precision-more', 'cursorCol.setcol_precision(1)', 'show more precision in current column')
|
@@ -0,0 +1,163 @@
|
|
1
|
+
import collections
|
2
|
+
from functools import partial
|
3
|
+
from visidata import DrawablePane, BaseSheet, vd, VisiData, CompleteKey, clipdraw, HelpSheet, colors, AcceptInput, AttrDict, drawcache_property
|
4
|
+
|
5
|
+
|
6
|
+
vd.theme_option('color_cmdpalette', 'black on 72', 'base color of command palette')
|
7
|
+
vd.theme_option('disp_cmdpal_max', 10, 'max number of suggestions for command palette')
|
8
|
+
|
9
|
+
def add_to_input(v, i, value=''):
|
10
|
+
items = list(v.split())
|
11
|
+
if not v or v.endswith(' '):
|
12
|
+
items.append(value)
|
13
|
+
else:
|
14
|
+
items[-1] = value
|
15
|
+
v = ' '.join(items) + ' '
|
16
|
+
return v, len(v)
|
17
|
+
|
18
|
+
|
19
|
+
def accept_input(v, i, value=None):
|
20
|
+
raise AcceptInput(v if value is None else value)
|
21
|
+
|
22
|
+
|
23
|
+
@VisiData.lazy_property
|
24
|
+
def usedInputs(vd):
|
25
|
+
return collections.defaultdict(int)
|
26
|
+
|
27
|
+
@DrawablePane.after
|
28
|
+
def execCommand2(sheet, cmd, *args, **kwargs):
|
29
|
+
vd.usedInputs[cmd.longname] += 1
|
30
|
+
|
31
|
+
@BaseSheet.api
|
32
|
+
def inputPalette(sheet, prompt, items,
|
33
|
+
value_key='key',
|
34
|
+
formatter=lambda m, item, trigger_key: f'{trigger_key} {item}',
|
35
|
+
multiple=False,
|
36
|
+
**kwargs):
|
37
|
+
bindings = dict()
|
38
|
+
|
39
|
+
tabitem = -1
|
40
|
+
|
41
|
+
def tab(n, nitems):
|
42
|
+
nonlocal tabitem
|
43
|
+
tabitem = (tabitem + n) % nitems
|
44
|
+
|
45
|
+
def _draw_palette(value):
|
46
|
+
words = value.lower().split()
|
47
|
+
|
48
|
+
if multiple and words:
|
49
|
+
if value.endswith(' '):
|
50
|
+
finished_words = words
|
51
|
+
unfinished_words = []
|
52
|
+
else:
|
53
|
+
finished_words = words[:-1]
|
54
|
+
unfinished_words = [words[-1]]
|
55
|
+
else:
|
56
|
+
unfinished_words = words
|
57
|
+
finished_words = []
|
58
|
+
|
59
|
+
unuseditems = [item for item in items if item[value_key] not in finished_words]
|
60
|
+
|
61
|
+
matches = vd.fuzzymatch(unuseditems, unfinished_words)
|
62
|
+
|
63
|
+
h = sheet.windowHeight
|
64
|
+
w = min(100, sheet.windowWidth)
|
65
|
+
nitems = min(h-1, sheet.options.disp_cmdpal_max)
|
66
|
+
|
67
|
+
useditems = []
|
68
|
+
palrows = []
|
69
|
+
|
70
|
+
for m in matches[:nitems]:
|
71
|
+
useditems.append(m.match)
|
72
|
+
palrows.append((m, m.match))
|
73
|
+
|
74
|
+
favitems = sorted([item for item in unuseditems if item not in useditems],
|
75
|
+
key=lambda item: -vd.usedInputs.get(item[value_key], 0))
|
76
|
+
|
77
|
+
for item in favitems[:nitems-len(palrows)]:
|
78
|
+
palrows.append((None, item))
|
79
|
+
|
80
|
+
navailitems = min(len(palrows), nitems)
|
81
|
+
|
82
|
+
bindings['^I'] = lambda *args: tab(1, navailitems) or args
|
83
|
+
bindings['KEY_BTAB'] = lambda *args: tab(-1, navailitems) or args
|
84
|
+
|
85
|
+
for i in range(nitems-len(palrows)):
|
86
|
+
palrows.append((None, None))
|
87
|
+
|
88
|
+
for i, (m, item) in enumerate(palrows):
|
89
|
+
trigger_key = ' '
|
90
|
+
if tabitem >= 0 and item:
|
91
|
+
trigger_key = f'{i+1}'[-1]
|
92
|
+
bindings[trigger_key] = partial(add_to_input if multiple else accept_input, value=item[value_key])
|
93
|
+
|
94
|
+
attr = colors.color_cmdpalette
|
95
|
+
|
96
|
+
if tabitem < 0 and palrows:
|
97
|
+
_ , topitem = palrows[0]
|
98
|
+
bindings['^J'] = partial(accept_input, value=None)
|
99
|
+
if multiple:
|
100
|
+
bindings[' '] = partial(add_to_input, value=topitem[value_key])
|
101
|
+
elif item and i == tabitem:
|
102
|
+
bindings['^J'] = partial(accept_input, value=None)
|
103
|
+
if multiple:
|
104
|
+
bindings[' '] = partial(add_to_input, value=item[value_key])
|
105
|
+
attr = colors.color_menu_spec
|
106
|
+
|
107
|
+
match_summary = formatter(m, item, trigger_key) if item else ' '
|
108
|
+
|
109
|
+
clipdraw(sheet._scr, h-nitems-1+i, 0, match_summary, attr, w=w)
|
110
|
+
|
111
|
+
return None
|
112
|
+
|
113
|
+
completer = CompleteKey(sorted(item[value_key] for item in items))
|
114
|
+
return vd.input(prompt,
|
115
|
+
completer=completer,
|
116
|
+
updater=_draw_palette,
|
117
|
+
bindings=bindings,
|
118
|
+
**kwargs)
|
119
|
+
|
120
|
+
|
121
|
+
def cmdlist(sheet):
|
122
|
+
return [
|
123
|
+
AttrDict(longname=row.longname,
|
124
|
+
description=sheet.cmddict[(row.sheet, row.longname)].helpstr)
|
125
|
+
for row in sheet.rows
|
126
|
+
]
|
127
|
+
HelpSheet.cmdlist = drawcache_property(cmdlist)
|
128
|
+
|
129
|
+
|
130
|
+
@BaseSheet.api
|
131
|
+
def inputLongname(sheet):
|
132
|
+
prompt = 'command name: '
|
133
|
+
# get set of commands possible in the sheet
|
134
|
+
this_sheets_help = HelpSheet('', source=sheet)
|
135
|
+
this_sheets_help.ensureLoaded()
|
136
|
+
|
137
|
+
def _fmt_cmdpal_summary(match, row, trigger_key):
|
138
|
+
keystrokes = this_sheets_help.revbinds.get(row.longname, [None])[0] or ' '
|
139
|
+
formatted_longname = match.formatted.get('longname', row.longname) if match else row.longname
|
140
|
+
formatted_name = f'[:onclick {row.longname}]{formatted_longname}[/]'
|
141
|
+
if vd.options.debug and match:
|
142
|
+
keystrokes = f'[{match.score}]'
|
143
|
+
r = f' [:keystrokes]{keystrokes.rjust(len(prompt)-5)}[/] '
|
144
|
+
r += f'[:keystrokes]{trigger_key}[/] {formatted_name}'
|
145
|
+
if row.description:
|
146
|
+
formatted_desc = match.formatted.get('description', row.description) if match else row.description
|
147
|
+
r += f' - {formatted_desc}'
|
148
|
+
return r
|
149
|
+
|
150
|
+
return sheet.inputPalette(prompt, this_sheets_help.cmdlist,
|
151
|
+
value_key='longname',
|
152
|
+
formatter=_fmt_cmdpal_summary,
|
153
|
+
type='longname')
|
154
|
+
|
155
|
+
|
156
|
+
@BaseSheet.api
|
157
|
+
def exec_longname(sheet, longname):
|
158
|
+
if not sheet.getCommand(longname):
|
159
|
+
vd.fail(f'no command {longname}')
|
160
|
+
sheet.execCommand(longname)
|
161
|
+
|
162
|
+
|
163
|
+
vd.addCommand('Space', 'exec-longname', 'exec_longname(inputLongname())', 'execute command by its longname')
|
@@ -0,0 +1,363 @@
|
|
1
|
+
'''Colorbrewer scales for plotting in Visidata.
|
2
|
+
|
3
|
+
Thanks to:
|
4
|
+
- Prof. Cynthia Brewer et al. @ colorbrewer.org
|
5
|
+
- @dsc https://github.com/dsc/colorbrewer-python
|
6
|
+
- @MicahElliott https://gist.github.com/MicahElliott/719710
|
7
|
+
- @er1kb https://github.com/er1kb/visidata-plugins
|
8
|
+
|
9
|
+
This feature adds these commands which can be used while viewing a plot (GraphSheet):
|
10
|
+
- color-cycle: change plot colors to another palette
|
11
|
+
- color-reset:
|
12
|
+
'''
|
13
|
+
from visidata import vd, VisiData, GraphSheet, BaseSheet, Sheet, ItemColumn, CellColorizer, ENTER
|
14
|
+
|
15
|
+
# https://raw.githubusercontent.com/er1kb/colorbrewer-python/master/colorbrewer.py
|
16
|
+
# https://gist.githubusercontent.com/er1kb/02f1fee3453431d5c0ccad5e62326a99/raw/73d047f0a3ffc35f0655488547e7f24fa3f04ea6/colortrans.py
|
17
|
+
|
18
|
+
vd.option('plot_palette', 'Set3', 'colorbrewer palette to use')
|
19
|
+
|
20
|
+
|
21
|
+
colorbrewer_palettes = dict(
|
22
|
+
Accent='114 146 216 228 61 198 130 59',
|
23
|
+
Dark2='36 166 97 162 70 178 136 59',
|
24
|
+
Paired='152 31 150 70 210 160 215 208 182 60 228 130',
|
25
|
+
Pastel1='217 152 194 188 223 230 187 225 231',
|
26
|
+
Pastel2='152 223 188 224 194 229 224 188',
|
27
|
+
Set1='160 67 71 97 208 227 130 211 102',
|
28
|
+
Set2='73 209 110 176 149 220 186 145',
|
29
|
+
Set3='116 229 146 209 110 215 149 224 188 139 194 227',
|
30
|
+
|
31
|
+
YellowGreen = {
|
32
|
+
3: '229 150 71',
|
33
|
+
4: '230 150 114 29',
|
34
|
+
5: '230 150 114 71 23',
|
35
|
+
6: '230 193 150 114 71 23',
|
36
|
+
7: '230 193 150 114 71 29 23',
|
37
|
+
8: '230 229 193 150 114 71 29 23',
|
38
|
+
9: '230 229 193 150 114 71 29 23 22',
|
39
|
+
},
|
40
|
+
YellowGreenBlue = {
|
41
|
+
3: '229 115 31',
|
42
|
+
4: '230 151 74 25',
|
43
|
+
5: '230 151 74 31 24',
|
44
|
+
6: '230 187 115 74 31 24',
|
45
|
+
7: '230 187 115 74 31 25 18',
|
46
|
+
8: '230 229 187 115 74 31 25 18',
|
47
|
+
9: '230 229 187 115 74 31 25 24 17',
|
48
|
+
},
|
49
|
+
GreenBlue = {
|
50
|
+
3: '194 151 74',
|
51
|
+
4: '230 151 116 31',
|
52
|
+
5: '230 151 116 74 25',
|
53
|
+
6: '230 194 151 116 74 25',
|
54
|
+
7: '230 194 151 116 74 31 25',
|
55
|
+
8: '231 194 194 151 116 74 31 25',
|
56
|
+
9: '231 194 194 151 116 74 31 25 24',
|
57
|
+
},
|
58
|
+
BlueGreen = {
|
59
|
+
3: '195 116 35',
|
60
|
+
4: '231 152 73 29',
|
61
|
+
5: '231 152 73 35 22',
|
62
|
+
6: '231 194 116 73 35 22',
|
63
|
+
7: '231 194 116 73 72 29 22',
|
64
|
+
8: '231 195 194 116 73 72 29 22',
|
65
|
+
9: '231 195 194 116 73 72 29 22 22',
|
66
|
+
},
|
67
|
+
PurpleBlueGreen = {
|
68
|
+
3: '225 146 30',
|
69
|
+
4: '231 152 74 30',
|
70
|
+
5: '231 152 74 30 23',
|
71
|
+
6: '231 188 146 74 30 23',
|
72
|
+
7: '231 188 146 74 67 30 23',
|
73
|
+
8: '231 225 188 146 74 67 30 23',
|
74
|
+
9: '231 225 188 146 74 67 30 23 23',
|
75
|
+
},
|
76
|
+
PurpleBlue = {
|
77
|
+
3: '225 146 31',
|
78
|
+
4: '231 152 110 25',
|
79
|
+
5: '231 152 110 31 24',
|
80
|
+
6: '231 188 146 110 31 24',
|
81
|
+
7: '231 188 146 110 67 25 24',
|
82
|
+
8: '231 225 188 146 110 67 25 24',
|
83
|
+
9: '231 225 188 146 110 67 25 24 23',
|
84
|
+
},
|
85
|
+
BluePurple = {
|
86
|
+
3: '195 146 97',
|
87
|
+
4: '231 152 104 97',
|
88
|
+
5: '231 152 104 97 90',
|
89
|
+
6: '231 152 146 104 97 90',
|
90
|
+
7: '231 152 146 104 97 97 53',
|
91
|
+
8: '231 195 152 146 104 97 97 53',
|
92
|
+
9: '231 195 152 146 104 97 97 90 53',
|
93
|
+
},
|
94
|
+
RedPurple = {
|
95
|
+
3: '224 217 162',
|
96
|
+
4: '230 217 205 126',
|
97
|
+
5: '230 217 205 162 90',
|
98
|
+
6: '230 223 217 205 162 90',
|
99
|
+
7: '230 223 217 205 168 126 90',
|
100
|
+
8: '231 224 223 217 205 168 126 90',
|
101
|
+
9: '231 224 223 217 205 168 126 90 53',
|
102
|
+
},
|
103
|
+
PurpleRed = {
|
104
|
+
3: '189 176 162',
|
105
|
+
4: '231 182 169 161',
|
106
|
+
5: '231 182 169 162 89',
|
107
|
+
6: '231 182 176 169 162 89',
|
108
|
+
7: '231 182 176 169 162 161 89',
|
109
|
+
8: '231 189 182 176 169 162 161 89',
|
110
|
+
9: '231 189 182 176 169 162 161 89 52',
|
111
|
+
},
|
112
|
+
OrangeRed = {
|
113
|
+
3: '224 216 167',
|
114
|
+
4: '230 222 209 166',
|
115
|
+
5: '230 222 209 167 124',
|
116
|
+
6: '230 223 216 209 167 124',
|
117
|
+
7: '230 223 216 209 203 166 88',
|
118
|
+
8: '231 224 223 216 209 203 166 88',
|
119
|
+
9: '231 224 223 216 209 203 166 124 88',
|
120
|
+
},
|
121
|
+
YellowOrangeRed = {
|
122
|
+
3: '229 215 202',
|
123
|
+
4: '229 221 209 160',
|
124
|
+
5: '229 221 209 202 124',
|
125
|
+
6: '229 222 215 209 202 124',
|
126
|
+
7: '229 222 215 209 202 160 124',
|
127
|
+
8: '230 229 222 215 209 202 160 124',
|
128
|
+
9: '230 229 222 215 209 202 160 124 88',
|
129
|
+
},
|
130
|
+
YellowOrangeBrown= {
|
131
|
+
3: '229 221 166',
|
132
|
+
4: '230 222 208 166',
|
133
|
+
5: '230 222 208 166 94',
|
134
|
+
6: '230 222 221 208 166 94',
|
135
|
+
7: '230 222 221 208 202 166 88',
|
136
|
+
8: '230 229 222 221 208 202 166 88',
|
137
|
+
9: '230 229 222 221 208 202 166 94 52',
|
138
|
+
},
|
139
|
+
Purples = {
|
140
|
+
3: '231 146 97',
|
141
|
+
4: '231 188 140 61',
|
142
|
+
5: '231 188 140 97 54',
|
143
|
+
6: '231 189 146 140 97 54',
|
144
|
+
7: '231 189 146 140 103 61 54',
|
145
|
+
8: '231 231 189 146 140 103 61 54',
|
146
|
+
9: '231 231 189 146 140 103 61 54 54',
|
147
|
+
},
|
148
|
+
Blues = {
|
149
|
+
3: '195 152 67',
|
150
|
+
4: '231 152 74 25',
|
151
|
+
5: '231 152 74 67 25',
|
152
|
+
6: '231 189 152 74 67 25',
|
153
|
+
7: '231 189 152 74 68 25 24',
|
154
|
+
8: '231 195 189 152 74 68 25 24',
|
155
|
+
9: '231 195 189 152 74 68 25 25 23',
|
156
|
+
},
|
157
|
+
Greens = {
|
158
|
+
3: '194 151 71',
|
159
|
+
4: '230 151 114 29',
|
160
|
+
5: '230 151 114 71 22',
|
161
|
+
6: '230 187 151 114 71 22',
|
162
|
+
7: '230 187 151 114 71 29 23',
|
163
|
+
8: '231 194 187 151 114 71 29 23',
|
164
|
+
9: '231 194 187 151 114 71 29 22 22',
|
165
|
+
},
|
166
|
+
Oranges = {
|
167
|
+
3: '224 215 166',
|
168
|
+
4: '230 216 209 166',
|
169
|
+
5: '230 216 209 166 130',
|
170
|
+
6: '230 223 215 209 166 130',
|
171
|
+
7: '230 223 215 209 202 166 88',
|
172
|
+
8: '231 224 223 215 209 202 166 88',
|
173
|
+
9: '231 224 223 215 209 202 166 130 88',
|
174
|
+
},
|
175
|
+
Reds = {
|
176
|
+
3: '224 209 160',
|
177
|
+
4: '224 216 203 160',
|
178
|
+
5: '224 216 203 160 124',
|
179
|
+
6: '224 217 209 203 160 124',
|
180
|
+
7: '224 217 209 203 202 160 88',
|
181
|
+
8: '231 224 217 209 203 202 160 88',
|
182
|
+
9: '231 224 217 209 203 202 160 124 52',
|
183
|
+
},
|
184
|
+
Greys = {
|
185
|
+
3: '231 145 59',
|
186
|
+
4: '231 188 102 59',
|
187
|
+
5: '231 188 102 59 16',
|
188
|
+
6: '231 188 145 102 59 16',
|
189
|
+
7: '231 188 145 102 102 59 16',
|
190
|
+
8: '231 231 188 145 102 102 59 16',
|
191
|
+
9: '231 231 188 145 102 102 59 16 16',
|
192
|
+
},
|
193
|
+
PurpleOrange = {
|
194
|
+
3: '215 231 104',
|
195
|
+
4: '166 215 146 60',
|
196
|
+
5: '166 215 231 146 60',
|
197
|
+
6: '130 215 223 189 104 54',
|
198
|
+
7: '130 215 223 231 189 104 54',
|
199
|
+
8: '130 172 215 223 189 146 103 54',
|
200
|
+
9: '130 172 215 223 231 189 146 103 54',
|
201
|
+
10: '94 130 172 215 223 189 146 103 54 17',
|
202
|
+
11: '94 130 172 215 223 231 189 146 103 54 17',
|
203
|
+
},
|
204
|
+
BrownGreen = {
|
205
|
+
3: '179 231 73',
|
206
|
+
4: '130 180 115 29',
|
207
|
+
5: '130 180 231 115 29',
|
208
|
+
6: '94 179 224 188 73 23',
|
209
|
+
7: '94 179 224 231 188 73 23',
|
210
|
+
8: '94 136 180 224 188 115 66 23',
|
211
|
+
9: '94 136 180 224 231 188 115 66 23',
|
212
|
+
10: '58 94 136 180 224 188 115 66 23 23',
|
213
|
+
11: '58 94 136 180 224 231 188 115 66 23 23',
|
214
|
+
},
|
215
|
+
PurpleGreen = {
|
216
|
+
3: '140 231 108',
|
217
|
+
4: '96 146 151 29',
|
218
|
+
5: '96 146 231 151 29',
|
219
|
+
6: '90 140 188 194 108 29',
|
220
|
+
7: '90 140 188 231 194 108 29',
|
221
|
+
8: '90 97 146 188 194 151 71 29',
|
222
|
+
9: '90 97 146 188 231 194 151 71 29',
|
223
|
+
10: '53 90 97 146 188 194 151 71 29 22',
|
224
|
+
11: '53 90 97 146 188 231 194 151 71 29 22',
|
225
|
+
},
|
226
|
+
PinkYellowGreen = {
|
227
|
+
3: '182 231 149',
|
228
|
+
4: '162 218 150 70',
|
229
|
+
5: '162 218 231 150 70',
|
230
|
+
6: '162 182 225 194 149 64',
|
231
|
+
7: '162 182 225 231 194 149 64',
|
232
|
+
8: '162 175 218 225 194 150 107 64',
|
233
|
+
9: '162 175 218 225 231 194 150 107 64',
|
234
|
+
10: '89 162 175 218 225 194 150 107 64 22',
|
235
|
+
11: '89 162 175 218 225 231 194 150 107 64 22',
|
236
|
+
},
|
237
|
+
RedBlue = {
|
238
|
+
3: '209 231 74',
|
239
|
+
4: '160 216 116 25',
|
240
|
+
5: '160 216 231 116 25',
|
241
|
+
6: '124 209 224 189 74 25',
|
242
|
+
7: '124 209 224 231 189 74 25',
|
243
|
+
8: '124 167 216 224 189 116 68 25',
|
244
|
+
9: '124 167 216 224 231 189 116 68 25',
|
245
|
+
10: '52 124 167 216 224 189 116 68 25 23',
|
246
|
+
11: '52 124 167 216 224 231 189 116 68 25 23',
|
247
|
+
},
|
248
|
+
RedGrey = {
|
249
|
+
3: '209 231 102',
|
250
|
+
4: '160 216 145 59',
|
251
|
+
5: '160 216 231 145 59',
|
252
|
+
6: '124 209 224 188 102 59',
|
253
|
+
7: '124 209 224 231 188 102 59',
|
254
|
+
8: '124 167 216 224 188 145 102 59',
|
255
|
+
9: '124 167 216 224 231 188 145 102 59',
|
256
|
+
10: '52 124 167 216 224 188 145 102 59 16',
|
257
|
+
11: '52 124 167 216 224 231 188 145 102 59 16',
|
258
|
+
},
|
259
|
+
RedYellowBlue = {
|
260
|
+
3: '209 229 110',
|
261
|
+
4: '160 215 152 31',
|
262
|
+
5: '160 215 229 152 31',
|
263
|
+
6: '166 209 222 195 110 67',
|
264
|
+
7: '166 209 222 229 195 110 67',
|
265
|
+
8: '166 203 215 222 195 152 110 67',
|
266
|
+
9: '166 203 215 222 229 195 152 110 67',
|
267
|
+
10: '124 166 203 215 222 195 152 110 67 60',
|
268
|
+
11: '124 166 203 215 222 229 195 152 110 67 60',
|
269
|
+
},
|
270
|
+
Spectral = {
|
271
|
+
3: '209 229 114',
|
272
|
+
4: '160 215 151 31',
|
273
|
+
5: '160 215 229 151 31',
|
274
|
+
6: '167 209 222 192 114 67',
|
275
|
+
7: '167 209 222 229 192 114 67',
|
276
|
+
8: '167 203 215 222 192 151 73 67',
|
277
|
+
9: '167 203 215 222 229 192 151 73 67',
|
278
|
+
10: '125 167 203 215 222 192 151 73 67 61',
|
279
|
+
11: '125 167 203 215 222 229 192 151 73 67 61',
|
280
|
+
},
|
281
|
+
RedYellowGreen = {
|
282
|
+
3: '209 229 113',
|
283
|
+
4: '160 215 149 29',
|
284
|
+
5: '160 215 229 149 29',
|
285
|
+
6: '166 209 222 192 113 29',
|
286
|
+
7: '166 209 222 229 192 113 29',
|
287
|
+
8: '166 203 215 222 192 149 71 29',
|
288
|
+
9: '166 203 215 222 229 192 149 71 29',
|
289
|
+
10: '124 166 203 215 222 192 149 71 29 23',
|
290
|
+
11: '124 166 203 215 222 229 192 149 71 29 23',
|
291
|
+
},
|
292
|
+
)
|
293
|
+
|
294
|
+
vd.colorbrewer_choices = [dict(key=k, colors=v) for k, v in colorbrewer_palettes.items()]
|
295
|
+
|
296
|
+
|
297
|
+
class PalettesSheet(Sheet):
|
298
|
+
colorizers = [
|
299
|
+
CellColorizer(2, None, lambda s,c,r,v: f'black on {v.value}' if c and r and c.name.startswith('c') else None)
|
300
|
+
]
|
301
|
+
columns = [
|
302
|
+
ItemColumn('name', 0),
|
303
|
+
ItemColumn('n', 1, type=int),
|
304
|
+
] + [
|
305
|
+
ItemColumn(f'c{i}', i+1)
|
306
|
+
for i in range(1, 13)
|
307
|
+
]
|
308
|
+
|
309
|
+
def iterload(self):
|
310
|
+
for palname, pals in colorbrewer_palettes.items():
|
311
|
+
if isinstance(pals, str):
|
312
|
+
yield [palname, len(pals.split())] + pals.split()
|
313
|
+
else:
|
314
|
+
for n, pal in pals.items():
|
315
|
+
yield [palname, n] + pal.split()
|
316
|
+
|
317
|
+
|
318
|
+
@GraphSheet.api
|
319
|
+
def cycle_palette(obj):
|
320
|
+
pals = list(colorbrewer_palettes.keys())
|
321
|
+
i = pals.index(obj.options.plot_palette)
|
322
|
+
i = (i+1)%len(pals)
|
323
|
+
n = len(obj.legends) if getattr(obj, 'legends', None) else 8
|
324
|
+
obj.set_palette(pals[i], n)
|
325
|
+
|
326
|
+
|
327
|
+
@GraphSheet.api
|
328
|
+
def set_palette(obj, palname, n):
|
329
|
+
r = colorbrewer_palettes[palname]
|
330
|
+
if not isinstance(r, str):
|
331
|
+
n = max(n, min(r.keys()))
|
332
|
+
n = min(n, max(r.keys()))
|
333
|
+
r = r[n]
|
334
|
+
|
335
|
+
vd.status(f'Using {palname} {n}-color palette')
|
336
|
+
obj.options.plot_palette = palname
|
337
|
+
obj.options.plot_colors = r
|
338
|
+
|
339
|
+
if isinstance(obj, GraphSheet):
|
340
|
+
obj.reload()
|
341
|
+
|
342
|
+
|
343
|
+
VisiData.set_palette = GraphSheet.set_palette
|
344
|
+
VisiData.cycle_palette = GraphSheet.cycle_palette
|
345
|
+
|
346
|
+
|
347
|
+
BaseSheet.addCommand(None, 'open-palettes', 'vd.push(PalettesSheet("palettes", source=vd))', 'open color palettes sheet for graphs')
|
348
|
+
BaseSheet.addCommand(None, 'cycle-palette', 'vd.cycle_palette()', 'cycle to next color palette for graphs')
|
349
|
+
BaseSheet.addCommand(None, 'unset-palette', 'vd.options.unset("plot_colors")', 'reset to default color palette for graphs')
|
350
|
+
|
351
|
+
GraphSheet.addCommand('C', 'open-palettes-sheet', 'vd.push(PalettesSheet("palettes", source=sheet))', 'open color palettes sheet for this graph')
|
352
|
+
GraphSheet.addCommand('zc', 'cycle-palette-sheet', 'sheet.cycle_palette()', 'cycle to next color palette for this graph')
|
353
|
+
GraphSheet.addCommand(None, 'unset-palette-sheet', 'sheet.options.unset("plot_colors"); reload()', 'reset to default color palette for this graph')
|
354
|
+
|
355
|
+
PalettesSheet.addCommand(ENTER, 'choose-palette', 'source.set_palette(cursorRow[0], cursorRow[1])', 'set current palette for source graph')
|
356
|
+
|
357
|
+
vd.addMenuItems('''
|
358
|
+
Plot > Palette > cycle > cycle-palette-sheet
|
359
|
+
Plot > Palette > unset > unset-palette-sheet
|
360
|
+
Plot > Palette > choose > open-palettes
|
361
|
+
''')
|
362
|
+
|
363
|
+
vd.addGlobals(PalettesSheet=PalettesSheet)
|
@@ -1,42 +1,43 @@
|
|
1
1
|
import curses
|
2
|
-
from visidata import VisiData, colors, Sheet, Column, RowColorizer, wrapply, BaseSheet
|
2
|
+
from visidata import VisiData, colors, Sheet, Column, ItemColumn, RowColorizer, wrapply, BaseSheet
|
3
3
|
|
4
4
|
|
5
5
|
class ColorSheet(Sheet):
|
6
|
-
rowtype = 'colors' # rowdef: [
|
6
|
+
rowtype = 'colors' # rowdef: [fg, bg, color_attr, colornamestr]
|
7
7
|
columns = [
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
ItemColumn('fg', 0, type=int),
|
9
|
+
ItemColumn('bg', 1, type=int),
|
10
|
+
ItemColumn('pairnum', 2),
|
11
|
+
ItemColumn('name', 3),
|
12
|
+
]
|
13
13
|
colorizers = [
|
14
|
-
RowColorizer(7, None, lambda s,c,r,v: r and r[
|
14
|
+
RowColorizer(7, None, lambda s,c,r,v: r and r[3])
|
15
15
|
]
|
16
16
|
|
17
17
|
def iterload(self):
|
18
18
|
self.rows = []
|
19
19
|
for k, v in colors.color_pairs.items():
|
20
|
-
|
20
|
+
fg, bg = k
|
21
|
+
pairnum, colorname = v
|
22
|
+
yield [fg, bg, pairnum, colorname]
|
21
23
|
|
22
24
|
for i in range(0, 256):
|
23
|
-
yield [
|
25
|
+
yield [i, 0, None, f'{i}']
|
24
26
|
|
25
27
|
def draw(self, scr):
|
26
28
|
super().draw(scr)
|
27
29
|
rightcol = max(self._visibleColLayout.values())
|
28
30
|
xstart = rightcol[0] + rightcol[1] + 4
|
29
31
|
for i, r in enumerate(self.rows[(self.topRowIndex//6)*6:(self.bottomRowIndex//6+1)*6]):
|
32
|
+
fg, bg, _, colorstr = r
|
33
|
+
s = f'█▌{fg:3}▐█'
|
30
34
|
y=i//6+1
|
31
|
-
x=(i%6)*
|
32
|
-
c = r[1][1]
|
33
|
-
s = '██'
|
35
|
+
x=(i%6)*(len(s)+2)+xstart
|
34
36
|
if y > self.windowHeight-1:
|
35
37
|
break
|
36
38
|
if r is self.cursorRow:
|
37
|
-
|
38
|
-
|
39
|
-
scr.addstr(y, x, s, colors[c])
|
39
|
+
s = f'█[{fg:3}]█'
|
40
|
+
scr.addstr(y, x, s, colors[colorstr].attr)
|
40
41
|
|
41
42
|
|
42
43
|
BaseSheet.addCommand(None, 'open-colors', 'vd.push(vd.colorsSheet)', 'open Color Sheet with available terminal colors')
|