From 6eeec96f7060a6b47c71deac6c8e12bde031c948 Mon Sep 17 00:00:00 2001 From: anjakefala Date: Fri, 29 Dec 2023 23:57:12 -0800 Subject: [PATCH 01/32] [dev] bump to v3.1dev --- CHANGELOG.md | 2 ++ setup.py | 2 +- visidata/__init__.py | 2 +- visidata/main.py | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 716a16556..359c87e18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # VisiData version history +# v3.x + # v3.0 (2023-12-29) - [reorg] move independent modules into visidata/{features|experimental|themes} diff --git a/setup.py b/setup.py index 3c16e5b56..ce21b061b 100755 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ # tox can't actually run python3 setup.py: https://github.com/tox-dev/tox/issues/96 # from visidata import __version__ -__version__ = "3.0" +__version__ = "3.1dev" setup( name="visidata", diff --git a/visidata/__init__.py b/visidata/__init__.py index 88ce93315..a98e12cc5 100644 --- a/visidata/__init__.py +++ b/visidata/__init__.py @@ -1,6 +1,6 @@ 'VisiData: a curses interface for exploring and arranging tabular data' -__version__ = '3.0' +__version__ = '3.1dev' __version_info__ = 'VisiData v' + __version__ __author__ = 'Saul Pwanson ' __status__ = 'Production/Stable' diff --git a/visidata/main.py b/visidata/main.py index 45ce87cf3..caa06de49 100755 --- a/visidata/main.py +++ b/visidata/main.py @@ -2,7 +2,7 @@ # Usage: $0 [] [ ...] # $0 [] --play [--batch] [-w ] [-o ] [field=value ...] -__version__ = '3.0' +__version__ = '3.1dev' __version_info__ = 'saul.pw/VisiData v' + __version__ from copy import copy From 5985ff924019132c5492f0fd218d40fbd7df4a3b Mon Sep 17 00:00:00 2001 From: anjakefala Date: Sat, 30 Dec 2023 14:41:47 -0800 Subject: [PATCH 02/32] [dev] update release checklist --- dev/checklists/release.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dev/checklists/release.md b/dev/checklists/release.md index 20ef89c8e..1dd706a29 100644 --- a/dev/checklists/release.md +++ b/dev/checklists/release.md @@ -40,16 +40,15 @@ 7. Merge `develop` to stable -14. motd - a. Upload new motd for new version. - b. Test that VisiData downloads motd. - 8. Merge `stable` back into other branches - a. if the branch works with minimal conflicts, keep the branch +9. On develop, create the dev version in setup.py, visidata/__init__.py and visidata/main.py - b. otherwise, clean out the branch + +14. motd + a. Upload new motd for new version and dev version + b. Test that VisiData downloads motd. 9. Push code to stable From cb13dc2c1c4e3c620fae23c141578e339f26368b Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Thu, 28 Dec 2023 22:05:22 -0800 Subject: [PATCH 03/32] [help] fix columns sheet sidebar --- visidata/column.py | 2 +- visidata/metasheets.py | 42 ++++++++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/visidata/column.py b/visidata/column.py index 2d4c31074..ecf0dae7f 100644 --- a/visidata/column.py +++ b/visidata/column.py @@ -186,7 +186,7 @@ def width(self, w): @property def formatted_help(self): - return MissingAttrFormatter().format(self.guide, sheet=self.sheet, col=self, vd=vd) + return MissingAttrFormatter().format(self.help, sheet=self.sheet, col=self, vd=vd) @property def help_formatters(self): diff --git a/visidata/metasheets.py b/visidata/metasheets.py index 47bc393b0..3f64c4fb9 100644 --- a/visidata/metasheets.py +++ b/visidata/metasheets.py @@ -18,14 +18,20 @@ class ColumnsSheet(Sheet): precious = False guide = '''# Columns Sheet This is a list of {sheet.nSourceCols} columns on {sheet.displaySource}. -Edit values on this sheet to change the column's appearance on the source sheet. -Edit the _{sheet.cursorCol.name}_ column to {sheet.cursorCol.formatted_help}. +Edit values on this sheet to change the appearance of the source sheet. +For example, edit the _{sheet.cursorCol.name}_ column to **{sheet.cursorCol.formatted_help}**. -Some column commands can also be done in bulk here, with the `g` prefix: +Some new commands on this sheet operate on all selected columns on the source sheet: -- `ge` to bulk set the _{sheet.cursorCol.name}_ for all selected "columns" -- `g-` to hide selected "columns" -- `g#` (or any standard type) to set the type of all selected "columns" +- {help.commands.hide_selected} +- {help.commands.key_selected} +- {help.commands.key_off_selected} +- {help.commands.type_int_selected} +- or `g` with any standard type to set type of selected source columns to that type + +## As usual + +- {help.commands.setcol_input} {sheet.help_columns} ''' @@ -129,21 +135,21 @@ def join_cols(sheet): Sheet.addCommand('C', 'columns-sheet', 'vd.push(ColumnsSheet(name+"_columns", source=[sheet]))', 'open Columns Sheet: edit column properties for current sheet') # used ColumnsSheet, affecting the 'row' (source column) -ColumnsSheet.addCommand('g!', 'key-selected', 'for c in onlySelectedRows: c.sheet.setKeys([c])', 'toggle selected rows as key columns on source sheet') -ColumnsSheet.addCommand('gz!', 'key-off-selected', 'for c in onlySelectedRows: c.sheet.unsetKeys([c])', 'unset selected rows as key columns on source sheet') +ColumnsSheet.addCommand('g!', 'key-selected', 'for c in onlySelectedRows: c.sheet.setKeys([c])', 'toggle selected source columns as key columns') +ColumnsSheet.addCommand('gz!', 'key-off-selected', 'for c in onlySelectedRows: c.sheet.unsetKeys([c])', 'unset selected source columns as key columns') -ColumnsSheet.addCommand('g-', 'hide-selected', 'onlySelectedRows.hide()', 'hide selected columns on source sheet') +ColumnsSheet.addCommand('g-', 'hide-selected', 'onlySelectedRows.hide()', 'hide selected source columns') ColumnsSheet.addCommand(None, 'resize-source-rows-max', 'for c in selectedRows or [cursorRow]: c.setWidth(c.getMaxWidth(c.sheet.visibleRows))', 'adjust widths of selected source columns') -ColumnsSheet.addCommand('g%', 'type-float-selected', 'onlySelectedRows.type=float', 'set type of selected columns to float') -ColumnsSheet.addCommand('g#', 'type-int-selected', 'onlySelectedRows.type=int', 'set type of selected columns to int') -ColumnsSheet.addCommand('gz#', 'type-len-selected', 'onlySelectedRows.type=vlen', 'set type of selected columns to len') -ColumnsSheet.addCommand('g@', 'type-date-selected', 'onlySelectedRows.type=date', 'set type of selected columns to date') -ColumnsSheet.addCommand('g$', 'type-currency-selected', 'onlySelectedRows.type=currency', 'set type of selected columns to currency') -ColumnsSheet.addCommand('g~', 'type-string-selected', 'onlySelectedRows.type=str', 'set type of selected columns to str') -ColumnsSheet.addCommand('gz~', 'type-any-selected', 'onlySelectedRows.type=anytype', 'set type of selected columns to anytype') -ColumnsSheet.addCommand('gz%', 'type-floatsi-selected', 'onlySelectedRows.type=floatsi', 'set type of selected columns to floatsi') -ColumnsSheet.addCommand('', 'type-floatlocale-selected', 'onlySelectedRows.type=floatlocale', 'set type of selected columns to float using system locale') +ColumnsSheet.addCommand('g%', 'type-float-selected', 'onlySelectedRows.type=float', 'set type of selected source columns to float') +ColumnsSheet.addCommand('g#', 'type-int-selected', 'onlySelectedRows.type=int', 'set type of selected source columns to int') +ColumnsSheet.addCommand('gz#', 'type-len-selected', 'onlySelectedRows.type=vlen', 'set type of selected source columns to len') +ColumnsSheet.addCommand('g@', 'type-date-selected', 'onlySelectedRows.type=date', 'set type of selected source columns to date') +ColumnsSheet.addCommand('g$', 'type-currency-selected', 'onlySelectedRows.type=currency', 'set type of selected source columns to currency') +ColumnsSheet.addCommand('g~', 'type-string-selected', 'onlySelectedRows.type=str', 'set type of selected source columns to str') +ColumnsSheet.addCommand('gz~', 'type-any-selected', 'onlySelectedRows.type=anytype', 'set type of selected source columns to anytype') +ColumnsSheet.addCommand('gz%', 'type-floatsi-selected', 'onlySelectedRows.type=floatsi', 'set type of selected source columns to floatsi') +ColumnsSheet.addCommand('', 'type-floatlocale-selected', 'onlySelectedRows.type=floatlocale', 'set type of selected source columns to float using system locale') MetaSheet.options.header = 0 From 5cb0a947a483be037ba70e3e949560b0933a15b2 Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Sat, 30 Dec 2023 15:45:06 -0800 Subject: [PATCH 04/32] [dev] migrate port-macros to vdx --- bin/vd2to3.vdx | 9 +++++++++ dev/port-macros.vdj | 5 ----- 2 files changed, 9 insertions(+), 5 deletions(-) create mode 100755 bin/vd2to3.vdx delete mode 100644 dev/port-macros.vdj diff --git a/bin/vd2to3.vdx b/bin/vd2to3.vdx new file mode 100755 index 000000000..eb5d87db4 --- /dev/null +++ b/bin/vd2to3.vdx @@ -0,0 +1,9 @@ +#!/usr/bin/env -S vd -p +# VisiData v3.0dev +open-file ~/.visidata/macros.tsv +col command +rename-col binding +col filename +rename-col source +save-sheet ~/.visidata/macros.jsonl +quit-all diff --git a/dev/port-macros.vdj b/dev/port-macros.vdj deleted file mode 100644 index bee7cd72c..000000000 --- a/dev/port-macros.vdj +++ /dev/null @@ -1,5 +0,0 @@ -#!vd -p -{"sheet": null, "col": null, "row": null, "longname": "open-file", "input": "~/.visidata/macros.tsv", "keystrokes": "o", "comment": null} -{"sheet": "macros", "col": "command", "row": "", "longname": "rename-col", "input": "binding", "keystrokes": "^", "comment": "rename current column"} -{"sheet": "macros", "col": "filename", "row": "", "longname": "rename-col", "input": "source", "keystrokes": "^", "comment": "rename current column"} -{"sheet": "macros", "col": "", "row": "", "longname": "save-sheet", "input": "~/.visidata/macros.jsonl", "keystrokes": "Ctrl+S", "comment": "save current sheet to filename in format determined by extension (default .tsv)"} From fb0f22a8b99578dea60ca811a34034a3356a4730 Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Sun, 31 Dec 2023 00:25:01 -0800 Subject: [PATCH 05/32] [dev] cleanup ROADMAP for 3.x --- dev/ROADMAP | 96 ++++++++++++++++++++++++----------------------------- 1 file changed, 43 insertions(+), 53 deletions(-) diff --git a/dev/ROADMAP b/dev/ROADMAP index 3c53e9bc2..2305b483b 100644 --- a/dev/ROADMAP +++ b/dev/ROADMAP @@ -1,60 +1,50 @@ -# Roadmap for 2.x - -1. holdovers from 2.0 - - [canvas] API docs +# Roadmap for v3.x + +1. help: guides and internal docs + - write docs/monorepo (manifesto/explanation about monorepo strategy) + - cleanup files in dev + - review files in docs + - review and commit dev/checklist/feature.md + - link to guidelines in CONTRIBUTING.md + - review/edit docs/api/module.md + - review/edit/commit dev/philosophy.md + - review/edit /docs/customize + - manpage overhaul + - from md instead of troff + - mention "histogram" near Shift+F + - vd.org/formats + - rename 'VisiData loader' column + - from 'aliases' column + +2. hierarchical display + - hierarchical column #692 + - collapsible rows + - org-mode + - json arrays + +3. options - [options] option enums - [options] user-defined option aliases - - [splitpane] File preview in directory view - + [defermods] 'modified since last save' indicator on status bar - - [scroll cell] zh/zl Left hand side of a cell with content hidden doesn't show ellipsis #751 - -2. Persistence - + input history #736 #468 - - key indexes for better joining and lookups - -3. Interface discoverability for commands #247 #742 - - clickable menu canvas - - more clickable affordances all around - - clickable motd - - possibly add popup modals - -4. more expressive expressions - + Memory sheet; can give things names and use in expressions. #392 - - access column values from execstr #655 - + shortcut name for current column #659 - -5. better asynchronicity - - async thread pool - - streaming architecture #366 #656 - -6. Loaders/Savers - - frictionless saver #237 - - RSS reader #157 - - toml loader #735 - - HexSheet for unknown/binary files #548 - - .ods loader (LibreOffice/OpenOffice spreadsheet) #473 - - - jsonl load and save round-trip (minimal diff) #429 + - [options] organized options sheet -## other features +4. tests + - rework sample_data + - basic vdsql tests in CI -a) generate non-terminal graphs (ggplot) -b) automatic reload into time series -c) intra-cell coloring (for search results, markup) - -# major plugin projects - -1. fully operational SQL viewer/editor +5. internals + - async thread pool + - Path.options + - invert input/inputMultiple + - handle all single-line inputs, and all get/setLastArgs - - #282: Select starting table in postgres from command-line - - #579: [Postgres] Allow inserting / deleting rows - - #522: [postgres] parms in options - - #586: SQL query data - - #727: [postgres] Transaction error when viewing table - - #729: Integrate generic SQL loader +6. default theme + - tooling to make it easier to browse color combos -2. web scraper +7. website + - add vd.org/contributors + - add vd.org/pricing - - #480: HTTP API pagination loader - - #465: Ability to load from the contents of a cell. - + #505: [html] Provide way to access non-table elements +8. new clients +- vd tui client: connect to vd server as separate terminal process +- vd web client + - lightweight JS widget to display/interact with command server From caddb05fc8330d8cef7cca52cc318f992305da3f Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Wed, 3 Jan 2024 16:17:43 -0800 Subject: [PATCH 06/32] [dev] remove unused import --- visidata/errors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visidata/errors.py b/visidata/errors.py index cdb910ad3..09f69475a 100644 --- a/visidata/errors.py +++ b/visidata/errors.py @@ -1,6 +1,6 @@ import traceback -from visidata import vd, VisiData, options +from visidata import vd, VisiData vd.option('debug', False, 'exit on error and display stacktrace', max_help=0) From eeea969287047dcc1f8929f7382f62d348d7f5ff Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Tue, 2 Jan 2024 15:26:25 -0800 Subject: [PATCH 07/32] [color] add color_longname to use instead of color_keystrokes #2219 --- visidata/features/cmdpalette.py | 11 ++++++++--- visidata/loaders/api_reddit.py | 10 +++++----- visidata/statusbar.py | 5 +++-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/visidata/features/cmdpalette.py b/visidata/features/cmdpalette.py index 527a05de4..ca5faae9e 100644 --- a/visidata/features/cmdpalette.py +++ b/visidata/features/cmdpalette.py @@ -86,7 +86,7 @@ def _draw_palette(value): palrows.append((None, None)) for i, (m, item) in enumerate(palrows): - trigger_key = ' ' + trigger_key = '' if tabitem >= 0 and item: trigger_key = f'{i+1}'[-1] bindings[trigger_key] = partial(add_to_input if multiple else accept_input, value=item[value_key]) @@ -137,11 +137,16 @@ def inputLongname(sheet): def _fmt_cmdpal_summary(match, row, trigger_key): keystrokes = this_sheets_help.revbinds.get(row.longname, [None])[0] or ' ' formatted_longname = match.formatted.get('longname', row.longname) if match else row.longname - formatted_name = f'[:onclick {row.longname}]{formatted_longname}[/]' + formatted_name = f'[:longname][:onclick {row.longname}]{formatted_longname}[/][/]' if vd.options.debug and match: keystrokes = f'[{match.score}]' r = f' [:keystrokes]{keystrokes.rjust(len(prompt)-5)}[/] ' - r += f'[:keystrokes]{trigger_key}[/] {formatted_name}' + if trigger_key: + r += f'[:keystrokes]{trigger_key}[/]' + else: + r += ' ' + + r += f' {formatted_name}' if row.description: formatted_desc = match.formatted.get('description', row.description) if match else row.description r += f' - {formatted_desc}' diff --git a/visidata/loaders/api_reddit.py b/visidata/loaders/api_reddit.py index 3a5df2bb7..5e60d1ce4 100644 --- a/visidata/loaders/api_reddit.py +++ b/visidata/loaders/api_reddit.py @@ -1,12 +1,12 @@ '''# RedditSheet -- [:keys]Ctrl+O[/] to open a browser tab to [:code]{sheet.cursorRow.display_name_prefixed}[/] -- [:keys]g Ctrl+O[/] to open browser windows for {sheet.nSelectedRows} selected subreddits +- [:keystrokes]Ctrl+O[/] to open a browser tab to [:code]{sheet.cursorRow.display_name_prefixed}[/] +- [:keystrokes]g Ctrl+O[/] to open browser windows for {sheet.nSelectedRows} selected subreddits -- [:keys]Enter[/] to open sheet with top ~1000 submissions for [:code]{sheet.cursorRow.display_name_prefixed}[/] -- [:keys]g Enter[/] to open sheet with top ~1000 submissions for {sheet.nSelectedRows} selected subreddits +- [:keystrokes]Enter[/] to open sheet with top ~1000 submissions for [:code]{sheet.cursorRow.display_name_prefixed}[/] +- [:keystrokes]g Enter[/] to open sheet with top ~1000 submissions for {sheet.nSelectedRows} selected subreddits -- [:keys]ga[/] to append more subreddits matching input by name or description +- [:keystrokes]ga[/] to append more subreddits matching input by name or description ''' import visidata diff --git a/visidata/statusbar.py b/visidata/statusbar.py index 3c8295bc3..4e0a82e92 100644 --- a/visidata/statusbar.py +++ b/visidata/statusbar.py @@ -11,12 +11,13 @@ from visidata import vd, VisiData, BaseSheet, Sheet, ColumnItem, Column, RowColorizer, options, colors, wrmap, clipdraw, ExpectedException, update_attr, dispwidth, ColorAttr -vd.option('disp_rstatus_fmt', '{sheet.threadStatus} {sheet.keystrokeStatus} {sheet.longname} {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus}', 'right-side status format string') +vd.option('disp_rstatus_fmt', '{sheet.threadStatus} {sheet.keystrokeStatus} [:longname]{sheet.longname}[/] {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus}', 'right-side status format string') vd.option('disp_status_fmt', '[:onclick sheets-stack]{sheet.shortcut}› {sheet.name}[/]| ', 'status line prefix') vd.theme_option('disp_lstatus_max', 0, 'maximum length of left status line') vd.theme_option('disp_status_sep', '│', 'separator between statuses') -vd.theme_option('color_keystrokes', 'bold white on 237', 'color of input keystrokes on status line') +vd.theme_option('color_keystrokes', 'bold white on 237', 'color of input keystrokes') +vd.theme_option('color_longname', '6', 'color of command longnames') vd.theme_option('color_keys', 'bold', 'color of keystrokes in help') vd.theme_option('color_status', 'bold on 238', 'status line color') vd.theme_option('color_error', '202 1', 'error message color') From 9dfe44881203cff0cedea5041dd2e318693c322b Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Tue, 2 Jan 2024 15:26:57 -0800 Subject: [PATCH 08/32] [keys] add *BtnUp pretty keys for BUTTON#_RELEASED #2219 --- visidata/keys.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/visidata/keys.py b/visidata/keys.py index 11935acdb..ab76ffb58 100644 --- a/visidata/keys.py +++ b/visidata/keys.py @@ -48,6 +48,9 @@ 'KEY_SNEXT': 'Shift+PgDn', 'KEY_BACKSPACE': 'Bksp', + 'BUTTON1_RELEASED': 'LeftBtnUp', + 'BUTTON2_RELEASED': 'MiddleBtnUp', + 'BUTTON3_RELEASED': 'RightBtnUp', 'BUTTON1_PRESSED': 'LeftClick', 'BUTTON2_PRESSED': 'MiddleClick', 'BUTTON3_PRESSED': 'RightClick', From 3e83ee54065c5827bd1f5f3d83126929e36059fd Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Wed, 3 Jan 2024 15:10:03 -0800 Subject: [PATCH 09/32] [column-] add displayer to column state --- visidata/column.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visidata/column.py b/visidata/column.py index ecf0dae7f..7bf448cf6 100644 --- a/visidata/column.py +++ b/visidata/column.py @@ -111,7 +111,7 @@ def __deepcopy__(self, memo): return self.__copy__() # no separate deepcopy def __getstate__(self): - return {k:getattr(self, k) for k in 'name typestr width height expr keycol formatter fmtstr voffset hoffset aggstr'.split() if hasattr(self, k)} + return {k:getattr(self, k) for k in 'name typestr width height expr keycol formatter displayer fmtstr voffset hoffset aggstr'.split() if hasattr(self, k)} def __setstate__(self, d): for attr, v in d.items(): From 8fe3131c8070ac53b31f1c55625ef2836fe5610d Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Wed, 3 Jan 2024 15:33:07 -0800 Subject: [PATCH 10/32] Revert "[extensible] do not copy over existing attribute #2190" #2225 This reverts commit 5f11da3045d4da33b9d3b040d0275abcc9832db2. --- tests/issue2225.vdx | 3 +++ visidata/extensible.py | 9 +-------- 2 files changed, 4 insertions(+), 8 deletions(-) create mode 100644 tests/issue2225.vdx diff --git a/tests/issue2225.vdx b/tests/issue2225.vdx new file mode 100644 index 000000000..7ff212a40 --- /dev/null +++ b/tests/issue2225.vdx @@ -0,0 +1,3 @@ +select-row +dup-selected +assert-expr sheet.nSelectedRows == 0 diff --git a/visidata/extensible.py b/visidata/extensible.py index 6b076d61c..8a5a20a22 100644 --- a/visidata/extensible.py +++ b/visidata/extensible.py @@ -30,14 +30,7 @@ def newcopy(self, *args, **kwargs): ret = oldcopy(self, *args, **kwargs) else: ret = super(cls, self).__copy__(*args, **kwargs) - - if not hasattr(ret, membername): - if copy and hasattr(self, membername): - v = getattr(self, membername) - else: - v = initfunc() - setattr(ret, membername, v) - + setattr(ret, membername, getattr(self, membername) if copy and hasattr(self, membername) else initfunc()) return ret cls.__copy__ = wraps(oldcopy)(newcopy) if oldcopy else newcopy From 4d20151cb2e15b8c1513521462ac30a64d8ca026 Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Wed, 3 Jan 2024 16:17:29 -0800 Subject: [PATCH 11/32] [expr] add sheet.inputPythonExpr; add assert-expr and assert-expr-row; add sheet to locals for non-row eval --- visidata/basesheet.py | 2 +- visidata/pyobj.py | 9 +++++---- visidata/sheets.py | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/visidata/basesheet.py b/visidata/basesheet.py index 24f29fbe6..4e8126dd0 100644 --- a/visidata/basesheet.py +++ b/visidata/basesheet.py @@ -283,7 +283,7 @@ def checkCursor(self): def evalExpr(self, expr, **kwargs): 'Evaluate Python expression *expr* in the context of *kwargs* (may vary by sheet type).' - return eval(expr, vd.getGlobals(), None) + return eval(expr, vd.getGlobals(), dict(sheet=self)) def formatString(self, fmt, **kwargs): 'Return formatted string with *sheet* and *vd* accessible to expressions. Missing expressions return empty strings instead of error.' diff --git a/visidata/pyobj.py b/visidata/pyobj.py index ae1763ed5..e53eaf08d 100644 --- a/visidata/pyobj.py +++ b/visidata/pyobj.py @@ -229,19 +229,20 @@ def openCellPyobj(sheet, col, rowidx): @BaseSheet.api -def pyobj_expr(sheet): +def inputPythonExpr(sheet): def launch_repl(v, i): import code with SuspendCurses(): code.InteractiveConsole(locals=locals()).interact() return v, i - expr = vd.input("eval: ", "expr", completer=visidata.CompleteExpr(), bindings={'^X': launch_repl}) - vd.push(PyobjSheet(expr, source=sheet.evalExpr(expr))) + return vd.input("eval: ", "expr", completer=visidata.CompleteExpr(), bindings={'^X': launch_repl}) -BaseSheet.addCommand('^X', 'pyobj-expr', 'pyobj_expr()', 'evaluate Python expression and open result as Python object') +BaseSheet.addCommand('^X', 'pyobj-expr', 'expr=inputPythonExpr(); vd.push(PyobjSheet(expr, source=sheet.evalExpr(expr)))', 'evaluate Python expression and open result as Python object') BaseSheet.addCommand('', 'exec-python', 'expr = input("exec: ", "expr", completer=CompleteExpr()); exec(expr, getGlobals(), LazyChainMap(sheet, *vd.contexts, locals=vd.getGlobals()))', 'execute Python statement with expression scope') BaseSheet.addCommand('g^X', 'import-python', 'modname=input("import: ", type="import_python"); exec("import "+modname, getGlobals())', 'import Python module in the global scope') BaseSheet.addCommand('z^X', 'pyobj-expr-row', 'expr = input("eval over current row: ", "expr", completer=CompleteExpr()); vd.push(PyobjSheet(expr, source=evalExpr(expr, row=cursorRow)))', 'evaluate Python expression, in context of current row, and open result as Python object') +BaseSheet.addCommand('', 'assert-expr', 'expr=inputPythonExpr(); assert sheet.evalExpr(expr), f"{expr} not true"', 'eval Python expression and assert result is truthy') +BaseSheet.addCommand('', 'assert-expr-row', 'expr=inputPythonExpr(); assert sheet.evalExpr(expr, row=cursorRow), f"{expr} not true"', 'eval Python expression in context of current row, and assert result is truthy') Sheet.addCommand('^Y', 'pyobj-row', 'status(type(cursorRow).__name__); vd.push(openRowPyobj(cursorRowIndex))', 'open current row as Python object') Sheet.addCommand('z^Y', 'pyobj-cell', 'status(type(cursorValue).__name__); vd.push(openCellPyobj(cursorCol, cursorRowIndex))', 'open current cell as Python object') diff --git a/visidata/sheets.py b/visidata/sheets.py index ce6bbde88..f65456939 100644 --- a/visidata/sheets.py +++ b/visidata/sheets.py @@ -363,7 +363,7 @@ def evalExpr(self, expr, row=None, col=None): # contexts are cached by sheet/rowid for duration of drawcycle contexts = vd._evalcontexts.setdefault((self, self.rowid(row), col), LazyComputeRow(self, row, col=col)) else: - contexts = None + contexts = dict(sheet=self) return eval(expr, vd.getGlobals(), contexts) From 5d0d3b7d01c9d42af851d133d18eec59f796876f Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Wed, 3 Jan 2024 17:35:22 -0800 Subject: [PATCH 12/32] [sort-] maintain ordering on sheet copies #2190 move Sheet._ordering initializer to Sheet.__init__ instead of using Extensible --- tests/issue2190.vdj | 1 + visidata/sheets.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/issue2190.vdj b/tests/issue2190.vdj index 17c82b93c..375e3feac 100644 --- a/tests/issue2190.vdj +++ b/tests/issue2190.vdj @@ -6,3 +6,4 @@ {"sheet": "sample", "col": "", "row": "", "longname": "select-rows", "input": "", "keystrokes": "gs", "comment": "select all rows"} {"sheet": "sample", "col": "", "row": "", "longname": "dup-selected", "input": "", "keystrokes": "\"", "comment": "open a duplicate sheet with only the selected rows"} {"sheet": "sample_selectedref", "col": "", "row": "", "longname": "unselect-rows", "input": "", "keystrokes": "gu", "comment": "unselect all rows"} +{"longname": "assert-expr", "input": "sheet._ordering[0][0] is sheet.column(\"Region\")"} diff --git a/visidata/sheets.py b/visidata/sheets.py index f65456939..f31406ec0 100644 --- a/visidata/sheets.py +++ b/visidata/sheets.py @@ -165,6 +165,8 @@ def __init__(self, *names, rows=UNLOADED, **kwargs): self._colorizers = self.classColorizers self.recalc() # set .sheet on columns and start caches + self._ordering = [] # list of (col:Column, reverse:bool) + self.__dict__.update(kwargs) # also done earlier in BaseSheet.__init__ @property @@ -1105,8 +1107,6 @@ def _async_deepcopy(newlist, oldlist): BaseSheet.init('pane', lambda: 1) -Sheet.init('_ordering', list, copy=False) # (col:Column, reverse:bool) - BaseSheet.addCommand('^R', 'reload-sheet', 'preloadHook(); reload()', 'Reload current sheet') Sheet.addCommand('^G', 'show-cursor', 'status(statusLine)', 'show cursor position and bounds of current sheet on status line') From 9125841aa2668a19808d7c8cd5ee9582c76c6885 Mon Sep 17 00:00:00 2001 From: anjakefala Date: Wed, 3 Jan 2024 20:05:36 -0800 Subject: [PATCH 13/32] [dev] update checklist --- dev/checklists/release.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/dev/checklists/release.md b/dev/checklists/release.md index 1dd706a29..3b71f4efa 100644 --- a/dev/checklists/release.md +++ b/dev/checklists/release.md @@ -40,20 +40,21 @@ 7. Merge `develop` to stable +14. motd + a. Upload new motd for new version. + b. Test that VisiData downloads motd. -8. Merge `stable` back into other branches -9. On develop, create the dev version in setup.py, visidata/__init__.py and visidata/main.py +8. Merge `stable` back into other branches + a. if the branch works with minimal conflicts, keep the branch -14. motd - a. Upload new motd for new version and dev version - b. Test that VisiData downloads motd. + b. otherwise, clean out the branch 9. Push code to stable -10. Push `develop` to pypi +10. Push `stable` to pypi a. set up a ~/.pypirc @@ -76,8 +77,10 @@ Push to pypi ``` + rm -rf dist/ python3 setup.py sdist bdist_wheel - chmod -R a+rX . + chmod -R a+rX dist + ls dist/ twine upload dist/* ``` From bc80ef28f72448f4265d6adb3781324e31d77755 Mon Sep 17 00:00:00 2001 From: anjakefala Date: Wed, 3 Jan 2024 20:30:23 -0800 Subject: [PATCH 14/32] [tests] support the running of tests without goldens --- dev/test.sh | 4 ++++ tests/{issue2225.vdx => issue2225-nosave.vdx} | 0 2 files changed, 4 insertions(+) rename tests/{issue2225.vdx => issue2225-nosave.vdx} (100%) diff --git a/dev/test.sh b/dev/test.sh index f29fb77b9..e7c7c80ff 100755 --- a/dev/test.sh +++ b/dev/test.sh @@ -41,6 +41,10 @@ for i in $TESTS ; do PYTHONPATH=. bin/vd --overwrite=False --play "$i" --batch --output "$goldfn" --config tests/.visidatarc --visidata-dir tests/.visidata echo "save: $goldfn" done + else + echo $TEST + PYTHONPATH=. bin/vd --play "$i" --batch --config tests/.visidatarc --visidata-dir tests/.visidata + echo "done" fi done diff --git a/tests/issue2225.vdx b/tests/issue2225-nosave.vdx similarity index 100% rename from tests/issue2225.vdx rename to tests/issue2225-nosave.vdx From 1c829d2ab30d86b07d16c420936c8fff8f1cbf93 Mon Sep 17 00:00:00 2001 From: anjakefala Date: Wed, 3 Jan 2024 20:47:25 -0800 Subject: [PATCH 15/32] [tests] fix #2190 so that it tests that sort widget is preservered *after* dup --- tests/issue2190.vdj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/issue2190.vdj b/tests/issue2190.vdj index 375e3feac..1ecd0d5e0 100644 --- a/tests/issue2190.vdj +++ b/tests/issue2190.vdj @@ -1,9 +1,7 @@ #!vd -p {"sheet": null, "col": null, "row": null, "longname": "open-file", "input": "sample_data/sample.tsv", "keystrokes": "o", "comment": null} {"sheet": "sample", "col": "Region", "row": "", "longname": "sort-asc", "input": "", "keystrokes": "[", "comment": "sort ascending by current column; replace any existing sort criteria"} +{"sheet": "sample", "col": "", "row": "", "longname": "dup-rows", "input": "", "keystrokes": "g\"", "comment": "open a duplicate sheet with only the selected rows"} {"sheet": "sample", "col": "Rep", "row": "", "longname": "sort-asc-add", "input": "", "keystrokes": "z[", "comment": "sort ascending by current column; add to existing sort criteria"} {"sheet": "sample", "col": "Item", "row": "", "longname": "sort-desc-add", "input": "", "keystrokes": "z]", "comment": "sort descending by current column; add to existing sort criteria"} -{"sheet": "sample", "col": "", "row": "", "longname": "select-rows", "input": "", "keystrokes": "gs", "comment": "select all rows"} -{"sheet": "sample", "col": "", "row": "", "longname": "dup-selected", "input": "", "keystrokes": "\"", "comment": "open a duplicate sheet with only the selected rows"} -{"sheet": "sample_selectedref", "col": "", "row": "", "longname": "unselect-rows", "input": "", "keystrokes": "gu", "comment": "unselect all rows"} {"longname": "assert-expr", "input": "sheet._ordering[0][0] is sheet.column(\"Region\")"} From b34b2e164245c432051e9d16c79bb2b07601f4ce Mon Sep 17 00:00:00 2001 From: anjakefala Date: Wed, 3 Jan 2024 21:52:25 -0800 Subject: [PATCH 16/32] [tests-] update unit tests to use packaged sample.tsv + benchmark.csv #2218 --- MANIFEST.in | 1 + setup.py | 2 +- visidata/features/slide.py | 12 +++++++----- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 2bb774d92..db8fbf332 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -6,6 +6,7 @@ include visidata/man/visidata.1 include visidata/ddw/input.ddw include visidata/ddw/regex.ddw include visidata/tests/sample.tsv +include visidata/tests/benchmark.csv include visidata/desktop/visidata.desktop include visidata/experimental/noahs_tapestry/*.json include visidata/experimental/noahs_tapestry/*.md diff --git a/setup.py b/setup.py index 45910bf75..c7df78125 100755 --- a/setup.py +++ b/setup.py @@ -51,7 +51,7 @@ package_data={ "visidata.man": ["vd.1", "vd.txt"], "visidata.ddw": ["input.ddw", "regex.ddw"], - "visidata.tests": ["sample.tsv"], + "visidata.tests": ["sample.tsv", "benchmark.csv"], "visidata.desktop": ["visidata.desktop"], "visidata.experimenta.noahs_tapestry": [ "clues.json", diff --git a/visidata/features/slide.py b/visidata/features/slide.py index d13fbd4b0..caffaea4b 100644 --- a/visidata/features/slide.py +++ b/visidata/features/slide.py @@ -100,6 +100,8 @@ def moveVisibleCol(sheet, fromVisColIdx, toVisColIdx): ## tests +sample_path = vd.pkg_resources_files(visidata) / 'tests/sample.tsv' +benchmark_path = vd.pkg_resources_files(visidata) / 'tests/benchmark.csv' def make_tester(setup_vdx): def t(vdx, golden): @@ -114,8 +116,8 @@ def t(vdx, golden): return t def test_slide_keycol_1(vd): - t = make_tester(''' - open-file sample_data/sample.tsv + t = make_tester(f''' + open-file {sample_path} +::OrderDate key-col +::Region key-col +::Rep key-col @@ -139,12 +141,12 @@ def test_slide_keycol_1(vd): def test_slide_leftmost(vd): - t = make_tester('''open-file sample_data/benchmark.csv''') + t = make_tester(f'''open-file {benchmark_path}''') t('+::Paid slide-leftmost', 'Paid Date Customer SKU Item Quantity Unit') - t = make_tester(''' - open-file sample_data/benchmark.csv + t = make_tester(f''' + open-file {benchmark_path} +::Date key-col ''') From f5e0e8e1bdcd515ce185d72fb6aff3c80f7f105c Mon Sep 17 00:00:00 2001 From: anjakefala Date: Wed, 3 Jan 2024 22:00:50 -0800 Subject: [PATCH 17/32] [tests-] add assert-expr and assert-expr-row to test_commands --- visidata/tests/test_commands.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/visidata/tests/test_commands.py b/visidata/tests/test_commands.py index 27ac9d714..82048c56f 100644 --- a/visidata/tests/test_commands.py +++ b/visidata/tests/test_commands.py @@ -60,6 +60,8 @@ def isTestableCommand(longname, cmdlist): 'go-row-number': '5', # go to row 5 'addcol-bulk': '1', 'addcol-expr': 'Units', # just copy the column + 'assert-expr': 'sheet.column(\"Units\")', + 'assert-expr-row': 'Units', 'addcol-incr-step': '2', 'setcol-incr-step': '2', 'setcol-iter': 'range(1, 100)', From c6f0d5a38b22e1ace4ed473bae345d2989b30d84 Mon Sep 17 00:00:00 2001 From: anjakefala Date: Wed, 3 Jan 2024 22:18:24 -0800 Subject: [PATCH 18/32] [tests-] add missing benchmark.csv --- visidata/tests/benchmark.csv | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 visidata/tests/benchmark.csv diff --git a/visidata/tests/benchmark.csv b/visidata/tests/benchmark.csv new file mode 100644 index 000000000..bb22dfa25 --- /dev/null +++ b/visidata/tests/benchmark.csv @@ -0,0 +1,52 @@ +Date,Customer,SKU,Item,Quantity,Unit,Paid +7/3/2018 1:47p,Robert Armstrong,FOOD213,BFF Oh My Gravy! Beef & Salmon 2.8oz,4,$12.95,$51.8 +7/3/2018 3:32p,Kyle Kennedy,FOOD121,"Food, Adult Cat - 3.5 oz",1,$4.22,$4.22 +7/5/2018 4:15p,"Douglas ""Dougie"" Powers",FOOD121,"Food, Adult Cat 3.5 oz",1,$4.22,$4.22 +7/6/2018 12:15p,桜 高橋 (Sakura Takahashi),FOOD122,"Food, Senior Wet Cat - 3 oz",12,$1.29,157¥ +7/10/2018 10:28a,David Attenborough,NSCT201,"Food, Salamander",30,$.05,$1.5 +7/10/2018 5:23p,Susan Ashworth,CAT060,"Cat, Korat (Felis catus)",1,$720.42,$720.42 +7/10/2018 5:23p,Susan Ashworth,FOOD130,"Food, Kitten 3kg",1,$14.94,$14.94 +7/13/2018 10:26a,Wil Wheaton,NSCT523,"Monster, Rust (Monstrus gygaxus)",1,$39.95,$39.95 +7/13/2018 3:49p,Robert Armstrong,FOOD216,BFF Oh My Gravy! Chicken & Shrimp 2.8oz,4,$12.95,$51.8 +7/17/2018 9:01a,Robert Armstrong,FOOD217,BFF Oh My Gravy! Duck & Tuna 2.8oz,4,$12.95,$51.8 +7/17/2018 11:30a,Helen Halestorm,LAGO342,Rabbit (Oryctolagus cuniculus),2,$32.94,$65.88 +7/18/2018 12:16p,桜 高橋 (Sakura Takahashi),FOOD122,"Food, Senior Wet Cat - 3 oz",6,$1.29,157¥ +7/19/2018 10:28a,Rubeus Hagrid,FOOD170,"Food, Dog - 5kg",5,$44.95,$224.75 +7/20/2018 2:13p,Jon Arbuckle,FOOD167,"Food, Premium Wet Cat - 3.5 oz",50,$3.95,$197.5 +7/23/2018 1:41p,Robert Armstrong,FOOD215,BFF Oh My Gravy! Lamb & Tuna 2.8oz,4,$12.95,$51.8 +7/23/2018 4:23p,"Douglas ""Dougie"" Powers",TOY235,Laser Pointer,1,$16.12,$16.12 +7/24/2018 12:16p,桜 高橋 (Sakura Takahashi),FOOD122,"Food, Senior Wet Cat - 3 oz",3,$1.29,157¥ +7/26/2018 4:39p,"Douglas ""Dougie"" Powers",FOOD420,"Food, Shark - 10 kg",1,$15.70,$15.7 +7/27/2018 12:16p,桜 高橋 (Sakura Takahashi),FOOD122,"Food, Senior Wet Cat - 3 oz",3,$1.29,157¥ +7/30/2018 12:17p,桜 高橋 (Sakura Takahashi),RETURN,"Food, Senior Wet Cat - 3 oz",1,$1.29,157¥ +7/31/2018 5:42p,Rubeus Hagrid,CAT060,"Food, Dragon - 50kg",5,$720.42,$3602.1 +8/1/2018 2:44p,David Attenborough,FOOD360,"Food, Rhinocerous - 50kg",4,$5.72,$22.88 +8/2/2018 5:12p,Susan Ashworth,CAT110,"Cat, Maine Coon (Felix catus)",1,"$1,309.68",$1309.68 +8/2/2018 5:12p,Susan Ashworth,FOOD130,"Food, Kitten 3kg",3,$14.94,$44.82 +8/6/2018 10:21a,Robert Armstrong,FOOD212,BFF Oh My Gravy! Beef & Chicken 2.8oz,4,$12.95,$51.8 +8/7/2018 4:12p,Juan Johnson,REPT082,"Kingsnake, California (Lampropeltis getula)",1,$89.95,$89.95 +8/7/2018 4:12p,Juan Johnson,RDNT443,"Mouse, Pinky (Mus musculus)",1,$1.49,$1.49 +8/10/2018 4:31p,Robert Armstrong,FOOD211,BFF Oh My Gravy! Chicken & Turkey 2.8oz,4,$12.95,$51.8 +8/13/2018 2:07p,Monica Johnson,RDNT443,"Mouse, Pinky (Mus musculus)",1,$1.49,$1.49 +8/13/2018 2:08p,María Fernández,FOOD146,Forti Diet Prohealth Mouse/Rat 3lbs,2,$2.00,$4.0 +8/15/2018 11:57a,Mr. Praline,RETURN,"Parrot, Norwegian Blue (Mopsitta tanta)",1,$2300.00,-$2300.0 +8/15/2018 3:48p,Kyle Kennedy,FOOD121,"Food, Adult Cat - 3.5 oz",2,$4.22,$8.44 +8/16/2018 11:50a,Helen Halestorm,RETURN,Rabbit (Oryctolagus cuniculus),6,$0,$0.0 +8/16/2018 4:00p,Kyle Kennedy,DOG010,"Dog, Golden Retriever (Canis lupus familiaris)",1,"$2,495.99",$2495.99 +8/16/2018 5:15p,Michael Smith,BIRD160,"Parakeet, Blue (Melopsittacus undulatus)",1,29.95,$31.85 +8/17/2018 9:26a,Rubeus Hagrid,NSCT201,"Food, Spider",5,$.05,$0.25 +8/20/2018 9:36a,Kyle Kennedy,RETURN,"Dog, Golden Retriever (Canis lupus familiaris)",1,"$1,247.99",-$1247.99 +8/20/2018 1:47p,מרוסיה ניסנהולץ אבולעפיה,GOAT224,"Goat, American Pygmy (Capra hircus)",1,₪499,$160.51 +8/20/2018 3:31p,Monica Johnson,NSCT201,"Crickets, Adult Live (Gryllus assimilis)",30,$.05,$1.5 +8/20/2018 5:12p,David Attenborough,NSCT084,"Food, Pangolin",30,$.17,$5.10 +8/21/2018 12:13p,Robert Armstrong,FOOD214,BFF Oh My Gravy! Duck & Salmon 2.8oz,4,$12.95,$51.8 +8/22/2018 9:38a,David Attenborough,BIRD160,"Food, Quoll",1,29.95,$29.95 +8/22/2018 2:13p,Jon Arbuckle,FOOD170,"Food, Adult Dog - 5kg",1,$44.95,$44.95 +8/22/2018 5:49p,מרוסיה ניסנהולץ,SFTY052,"Fire Extinguisher, kitchen-rated",1,$61.70,$61.70 +8/24/2018 11:42a,Robert Armstrong,FOOD218,BFF Oh My Gravy! Chicken & Salmon 2.8oz,4,$12.95,$51.8 +8/27/2018 3:05p,Monica Johnson,NSCT443,"Mealworms, Large (Tenebrio molitor) 100ct",1,$1.99,$1.99 +8/28/2018 5:32p,Susan Ashworth,CAT020,"Cat, Scottish Fold (Felis catus)",1,"$1,964.53",$1964.53 +8/28/2018 5:32p,Susan Ashworth,FOOD130,"Food, Kitten 3kg",2,$14.94,$29.88 +8/29/2018 10:07a,Robert Armstrong,FOOD219,BFF Oh My Gravy! Chicken & Pumpkin 2.8oz,4,$12.95,$51.8 +8/31/2018 12:00a,Robert Armstrong,FOOD219,BFF Oh My Gravy! Chicken & Pumpkin 2.8oz,144,$12.95,$1864.8 +8/31/2018 5:57p,Juan Johnson,REPT217,"Lizard, Spinytail (Uromastyx ornatus)",1,$99.95,$99.95 From 490ad1bf798e6bb6ca200b8132ed98942753e063 Mon Sep 17 00:00:00 2001 From: AJ Kerrigan Date: Tue, 2 Jan 2024 13:08:39 -0500 Subject: [PATCH 19/32] [tests] parameterize feature tests Split feature tests into individual test cases for a single parameterized function. Co-authored-by: Elliott Sales de Andrade --- visidata/tests/test_features.py | 39 +++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/visidata/tests/test_features.py b/visidata/tests/test_features.py index 9c9112ab8..bc86cebec 100644 --- a/visidata/tests/test_features.py +++ b/visidata/tests/test_features.py @@ -1,17 +1,28 @@ import pytest import visidata -@pytest.mark.usefixtures('curses_setup') -class TestFeatures: - def test_features(self, mock_screen): - tests = [ - (mod, getattr(mod, k)) - for mod in visidata.vd.importedModules - for k in dir(mod) - if k.startswith('test_') - ] - for mod, testfunc in tests: - print(mod, testfunc.__name__) - visidata.vd.resetVisiData() - visidata.vd.scr = mock_screen - testfunc(visidata.vd) +def pytest_generate_tests(metafunc): + """Split feature tests into separate test cases + + Look up test methods in imported modules. Turn each one into a single test_feature() + case, with "module::method" as the test id. + """ + tests = [ + (mod, getattr(mod, k)) + for mod in visidata.vd.importedModules + for k in dir(mod) + if k.startswith("test_") + ] + argvalues = [[testfunc] for _, testfunc in tests] + testids = [ + f"{mod.__name__}::{testfunc.__name__}" + for mod, testfunc in tests + ] + metafunc.parametrize(argnames=["testfunc"], argvalues=argvalues, ids=testids) + + +@pytest.mark.usefixtures("curses_setup") +def test_feature(mock_screen, testfunc): + visidata.vd.resetVisiData() + visidata.vd.scr = mock_screen + testfunc(visidata.vd) From 48fc129972bec92c76f1a04815616a6cb08c86a7 Mon Sep 17 00:00:00 2001 From: anjakefala Date: Fri, 5 Jan 2024 21:45:22 -0800 Subject: [PATCH 20/32] [guide] add InputGuide to ToC --- visidata/guide.py | 1 + 1 file changed, 1 insertion(+) diff --git a/visidata/guide.py b/visidata/guide.py index 27238b1bb..ce3bb80cb 100644 --- a/visidata/guide.py +++ b/visidata/guide.py @@ -18,6 +18,7 @@ # real barebones basics MovementGuide ("Movement and Search") +InputGuide ("Input keystrokes") SortGuide ("Sorting") TypesSheet ("The basic type system") CommandLog ("Undo and Replay") From d25924f6e671a9c63262512530acf5f54a51c65a Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Thu, 4 Jan 2024 15:41:09 -0800 Subject: [PATCH 21/32] [html-] ignore parsing exceptions on invalid urls #2227 --- tests/golden/issue2227.tsv | 3 +++ tests/issue2227.html | 5 +++++ tests/issue2227.vdx | 3 +++ visidata/loaders/html.py | 8 ++++++-- 4 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 tests/golden/issue2227.tsv create mode 100644 tests/issue2227.html create mode 100644 tests/issue2227.vdx diff --git a/tests/golden/issue2227.tsv b/tests/golden/issue2227.tsv new file mode 100644 index 000000000..2ff109be7 --- /dev/null +++ b/tests/golden/issue2227.tsv @@ -0,0 +1,3 @@ +url url_link0 +1 https://google.com] +2 https://example.com diff --git a/tests/issue2227.html b/tests/issue2227.html new file mode 100644 index 000000000..bb1526e2e --- /dev/null +++ b/tests/issue2227.html @@ -0,0 +1,5 @@ + + + + +
url
1
2
diff --git a/tests/issue2227.vdx b/tests/issue2227.vdx new file mode 100644 index 000000000..23f2a7bd0 --- /dev/null +++ b/tests/issue2227.vdx @@ -0,0 +1,3 @@ +# VisiData v3.0 +open-file tests/issue2227.html +open-row diff --git a/visidata/loaders/html.py b/visidata/loaders/html.py index cf3672de0..16dc528fe 100644 --- a/visidata/loaders/html.py +++ b/visidata/loaders/html.py @@ -77,7 +77,7 @@ def iterload(self): lxml = vd.importExternal('lxml') from lxml.html import iterlinks root = self.source.getroot() - root.make_links_absolute(self.source.docinfo.URL) + root.make_links_absolute(self.source.docinfo.URL, handle_failures='ignore') yield from iterlinks(root) def openRow(self, row): @@ -131,7 +131,11 @@ def iterload(self): if isinstance(cell, lxml.etree.CommentBase): continue cellval = ' '.join(x.strip() for x in cell.itertext()) # text only without markup - links = [urllib.parse.urljoin(self.source.base_url, x.get('href')) for x in cell.iter('a')] + links = [ + vd.callNoExceptions(urllib.parse.urljoin, self.source.base_url, x.get('href')) or x.get('href') + for x in cell.iter('a') + ] + maxlinks[colnum] = max(maxlinks.get(colnum, 0), len(links)) if is_header(cell): From 72482b5c0613443e85f26cddc88914be53ec5e66 Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Fri, 5 Jan 2024 22:24:57 -0800 Subject: [PATCH 22/32] [cmdpalette-] enter for first row if partially given already #2219 --- visidata/features/cmdpalette.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/visidata/features/cmdpalette.py b/visidata/features/cmdpalette.py index ca5faae9e..a800cef29 100644 --- a/visidata/features/cmdpalette.py +++ b/visidata/features/cmdpalette.py @@ -19,6 +19,17 @@ def add_to_input(v, i, value=''): def accept_input(v, i, value=None): raise AcceptInput(v if value is None else value) +def accept_input_if_subset(v, i, value=''): + # if no input, accept value under cmd palette cursor + if not v: + raise AcceptInput(value) + + # if the last item is a partial match, replace it with the full value + parts = v.split() + if value and value.startswith(parts[-1]): + v = ' '.join(parts[:-1] + [value]) + + raise AcceptInput(v) @VisiData.lazy_property def usedInputs(vd): @@ -95,13 +106,17 @@ def _draw_palette(value): if tabitem < 0 and palrows: _ , topitem = palrows[0] - bindings['^J'] = partial(accept_input, value=None) if multiple: bindings[' '] = partial(add_to_input, value=topitem[value_key]) + bindings['^J'] = partial(accept_input_if_subset, value=topitem[value_key]) + else: + bindings['^J'] = partial(accept_input, value=topitem[value_key]) elif item and i == tabitem: - bindings['^J'] = partial(accept_input, value=None) if multiple: + bindings['^J'] = partial(accept_input_if_subset, value=item[value_key]) bindings[' '] = partial(add_to_input, value=item[value_key]) + else: + bindings['^J'] = partial(accept_input, value=item[value_key]) attr = colors.color_menu_spec match_summary = formatter(m, item, trigger_key) if item else ' ' From 7f715e3f0635eb0948eeafd0c64355c2ac3c5753 Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Fri, 5 Jan 2024 22:54:34 -0800 Subject: [PATCH 23/32] [guide] add show-command-info #2228 --- visidata/guide.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/visidata/guide.py b/visidata/guide.py index ce3bb80cb..645a787e4 100644 --- a/visidata/guide.py +++ b/visidata/guide.py @@ -117,6 +117,9 @@ def __init__(self, cls): self.helpsheet.ensureLoaded() def __getattr__(self, k): + return self.__getitem__(k) + + def __getitem__(self, k): longname = k.replace('_', '-') binding = self.helpsheet.revbinds.get(longname, [None])[0] # cmddict has a SheetClass associated with each command @@ -174,6 +177,22 @@ def getGuide(vd, name): # -> GuideSheet() BaseSheet.addCommand('', 'open-guide-index', 'vd.push(GuideIndex("VisiData_Guide"))', 'open VisiData guides table of contents') +@VisiData.api +def inputKeys(vd, prompt): + return vd.input(prompt, help=f''' + # Input Keystrokes + - Press `Ctrl+N` and then press another keystroke to spell out that keystroke. + - Press `Ctrl+C` to cancel the input. + - Press `Enter` to accept the input. + ''') + +@BaseSheet.api +def getCommandInfo(sheet, keys): + cmd = sheet.getCommand(keys) + return CommandHelpGetter(type(sheet))[cmd.longname] + +vd.addCommand('', 'show-command-info', 'status(getCommandInfo(inputKeys("get command for keystrokes: ")))', 'show longname and helpstring for keybinding') + vd.addMenuItems(''' Help > VisiData Feature Guides > open-guide-index ''') From e6b74b2a36f1701e30516012719ac69cfbbd7298 Mon Sep 17 00:00:00 2001 From: anjakefala Date: Sat, 6 Jan 2024 18:49:14 -0800 Subject: [PATCH 24/32] [tests-] add input for show-command-info --- visidata/tests/test_commands.py | 1 + 1 file changed, 1 insertion(+) diff --git a/visidata/tests/test_commands.py b/visidata/tests/test_commands.py index 82048c56f..f4c8050c1 100644 --- a/visidata/tests/test_commands.py +++ b/visidata/tests/test_commands.py @@ -61,6 +61,7 @@ def isTestableCommand(longname, cmdlist): 'addcol-bulk': '1', 'addcol-expr': 'Units', # just copy the column 'assert-expr': 'sheet.column(\"Units\")', + 'show-command-info': 'select-row', 'assert-expr-row': 'Units', 'addcol-incr-step': '2', 'setcol-incr-step': '2', From bf901720be006ff6fe3cff26d4122c7ec8ff273f Mon Sep 17 00:00:00 2001 From: saulpw Date: Sat, 6 Jan 2024 20:55:39 -0800 Subject: [PATCH 25/32] [expr-] traceback expects locals to be iterable #2179 --- visidata/basesheet.py | 3 +++ visidata/sheets.py | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/visidata/basesheet.py b/visidata/basesheet.py index 4e8126dd0..2d8f58a05 100644 --- a/visidata/basesheet.py +++ b/visidata/basesheet.py @@ -18,6 +18,9 @@ def __init__(self, *objs, locals=None): if k not in self.objs: self.objs[k] = obj + def __iter__(self): + return iter(self.objs) + def __contains__(self, k): return k in self.objs diff --git a/visidata/sheets.py b/visidata/sheets.py index f31406ec0..8e5dc4932 100644 --- a/visidata/sheets.py +++ b/visidata/sheets.py @@ -65,8 +65,15 @@ def _lcm(self): lcmobj._lcm = LazyChainMap(self.sheet, self.col, *vd.contexts) return lcmobj._lcm + def __iter__(self): + yield from self.sheet._ordered_colnames + yield from self._lcm.keys() + yield 'row' + yield 'sheet' + yield 'col' + def keys(self): - return self.sheet._ordered_colnames + self._lcm.keys() + ['row', 'sheet', 'col'] + return list(self.__iter__()) def __str__(self): return str(self.as_dict()) From 624ebb78d77d3877ae73ee79d6d6f452faa079a3 Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Sat, 6 Jan 2024 21:38:49 -0800 Subject: [PATCH 26/32] [threads-] cannot cancel already finished thread #2235 --- visidata/threads.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/visidata/threads.py b/visidata/threads.py index 096f79336..febdb9dc2 100644 --- a/visidata/threads.py +++ b/visidata/threads.py @@ -86,7 +86,8 @@ def Progress(vd, iterable=None, gerund="", total=None, sheet=None): def cancelThread(vd, *threads, exception=EscapeException): 'Raise *exception* in one or more *threads*.' for t in threads: - ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(t.ident), ctypes.py_object(exception)) + if t.ident is not None: + ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(t.ident), ctypes.py_object(exception)) # each row is an augmented threading.Thread object From f93b7e092c488c1c5f0a8c9c0da148f3772ee834 Mon Sep 17 00:00:00 2001 From: midichef <67946319+midichef@users.noreply.github.com> Date: Sat, 6 Jan 2024 22:08:44 -0800 Subject: [PATCH 27/32] [sheets-] limit end separators to rightmost visible col of sheet (#2237) --- visidata/sheets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visidata/sheets.py b/visidata/sheets.py index 8e5dc4932..b8dfc55f6 100644 --- a/visidata/sheets.py +++ b/visidata/sheets.py @@ -873,7 +873,7 @@ def drawRow(self, scr, row, rowidx, ybase, rowcattr: ColorAttr, maxheight, for i, chunks in enumerate(lines): y = ybase+i - if vcolidx == self.rightVisibleColIndex: # right edge of sheet + if vcolidx == self.nVisibleCols-1: # right edge of sheet if len(lines) == 1: sepchars = endsep else: From 86aeb0d7963351b980f8a68b653d3cbbdb7bcef5 Mon Sep 17 00:00:00 2001 From: anjakefala Date: Sat, 6 Jan 2024 22:39:33 -0800 Subject: [PATCH 28/32] [cmdpalette-] add sidebar for longname + aggregator palette #2219 --- visidata/aggregators.py | 15 ++++++++++++++- visidata/features/cmdpalette.py | 14 ++++++++++++++ visidata/man/vd.inc | 2 +- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/visidata/aggregators.py b/visidata/aggregators.py index 15b0dca1f..ef12805ff 100644 --- a/visidata/aggregators.py +++ b/visidata/aggregators.py @@ -7,7 +7,20 @@ from visidata import Progress, Sheet, Column, ColumnsSheet, VisiData from visidata import vd, anytype, vlen, asyncthread, wrapply, AttrDict -vd.help_aggregators = '# Aggregators Help\nHELPTODO' +vd.help_aggregators = '''# Choose Aggregators +Start typing an aggregator name or description. +Multiple aggregators can be added by separating spaces. + +- `Enter` to select top aggregator. +- `Tab` to highlight top aggregator. + +## When Aggregator Highlighted + +- `Tab`/`Shift+Tab` to cycle highlighted aggregator. +- `Enter` to select aggregators. +- `Space` to add highlighted aggregator. +- `0-9` to add numbered aggregator. +''' vd.option('null_value', None, 'a value to be counted as null', replay=True) diff --git a/visidata/features/cmdpalette.py b/visidata/features/cmdpalette.py index a800cef29..2c8025ce3 100644 --- a/visidata/features/cmdpalette.py +++ b/visidata/features/cmdpalette.py @@ -6,6 +6,19 @@ vd.theme_option('color_cmdpalette', 'black on 72', 'base color of command palette') vd.theme_option('disp_cmdpal_max', 10, 'max number of suggestions for command palette') +vd.help_longname = '''# Choose Command +Start typing a command longname or keyword in its helpstring. + +- `Enter` to execute top command. +- `Tab` to highlight top command. + +## When Command Highlighted + +- `Tab`/`Shift+Tab` to cycle highlighted command. +- `Enter` to execute highlighted command. +- `0-9` to execute numbered command. +''' + def add_to_input(v, i, value=''): items = list(v.split()) if not v or v.endswith(' '): @@ -170,6 +183,7 @@ def _fmt_cmdpal_summary(match, row, trigger_key): return sheet.inputPalette(prompt, this_sheets_help.cmdlist, value_key='longname', formatter=_fmt_cmdpal_summary, + help=vd.help_longname, type='longname') diff --git a/visidata/man/vd.inc b/visidata/man/vd.inc index 13dbacf08..9d84b8651 100644 --- a/visidata/man/vd.inc +++ b/visidata/man/vd.inc @@ -101,7 +101,7 @@ toggle sidebar .No redo the most recent undo ( requires enabled Sy options.undo Ns ) .Pp .It Ic "Space" Ar longname -.No open command palette; execute command by its Ar longname +.No open command palette; execute top command by its Ar longname .El .Ss " Command Palette" .Bl -tag -width XXXXXXXXXXXXXXX -compact -offset XXX From 6855213a19614dc254b59ac435c99e9c9f5a239c Mon Sep 17 00:00:00 2001 From: anjakefala Date: Sun, 7 Jan 2024 17:34:20 -0800 Subject: [PATCH 29/32] [sidebar-] fix fmtstr for case where source is BaseSheet Closes #2239 --- visidata/basesheet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/visidata/basesheet.py b/visidata/basesheet.py index 2d8f58a05..999823aee 100644 --- a/visidata/basesheet.py +++ b/visidata/basesheet.py @@ -178,7 +178,7 @@ def __contains__(self, vs): @property def displaySource(self): if isinstance(self.source, BaseSheet): - return f'the *{self.source[0]}* sheet' + return f'the *{self.source}* sheet' if isinstance(self.source, (list, tuple)): if len(self.source) == 1: From 6c2d5a6dd7c80f46f1009b3f8dac15e5097c77bc Mon Sep 17 00:00:00 2001 From: anjakefala Date: Sun, 7 Jan 2024 18:23:33 -0800 Subject: [PATCH 30/32] [dev] update CHANGELOG --- CHANGELOG.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f95b42f9..dc75c60d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,27 @@ # VisiData version history -# v3.x +# v3.0.1 (2024-01-XX) + +- [color] add `color_longname` to use instead of `color_keystrokes` #2219 +- [column] add displayer to column state +- [cmdpalette] Enter executes first row, if partially typed out #2219 +- [cmdpalette] add sidebar for longname and aggregator palette #2219 +- [guide] add `show-command-info` to display command info for a keystroke #2228 +- [keys] add `*BtnUp` pretty keys for `BUTTON#_RELEASED` #2219 +- [tests] add `assert-expr` and `assert-expr-row` to evaluate Python expressions, and assert result is truthy +- [tests] parametrize feature tests (PR by @ajkerrigan #2230) + +## bugfixes + +- [dup-selected] dup-selected should unselect all rows in resulting sheet #2225 +- [expr] fix KeyError crash with invalid inputs in `expr` for Python 3.12 #2179 +- [help] fix columns sheet sidebar +- [loaders html] ignore parsing exceptions on invalid urls #2227 +- [sheets] limit end separators to rightmost visible column of sheet (PR by @midichef #2237) +- [sidebar] fix fmtstr for case where source is BaseSheet #2239 +- [sort] maintain ordering on sheet copies #2190 +- [test] update unit tests to use packaged sample.tsv and benchmark.csv #2218 +- [threads] fix HelpSheet thread causing an Exception #2235 # v3.0 (2023-12-30) From 5772c0f5e817fba2a7a1f9f5949cb959067cebca Mon Sep 17 00:00:00 2001 From: Saul Pwanson Date: Sun, 7 Jan 2024 21:27:59 -0800 Subject: [PATCH 31/32] [dev] update CHANGELOG --- CHANGELOG.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc75c60d8..7a6eb49cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,17 @@ # VisiData version history -# v3.0.1 (2024-01-XX) +# v3.0.1 (2024-01-07) + +### Fixes and minor improvements - [color] add `color_longname` to use instead of `color_keystrokes` #2219 -- [column] add displayer to column state +- [columns] add `displayer` attribute to saved column state - [cmdpalette] Enter executes first row, if partially typed out #2219 - [cmdpalette] add sidebar for longname and aggregator palette #2219 - [guide] add `show-command-info` to display command info for a keystroke #2228 - [keys] add `*BtnUp` pretty keys for `BUTTON#_RELEASED` #2219 -- [tests] add `assert-expr` and `assert-expr-row` to evaluate Python expressions, and assert result is truthy -- [tests] parametrize feature tests (PR by @ajkerrigan #2230) - -## bugfixes -- [dup-selected] dup-selected should unselect all rows in resulting sheet #2225 +- [dup-selected] dup-selected should unselect all rows in copied sheet #2225 - [expr] fix KeyError crash with invalid inputs in `expr` for Python 3.12 #2179 - [help] fix columns sheet sidebar - [loaders html] ignore parsing exceptions on invalid urls #2227 @@ -21,7 +19,10 @@ - [sidebar] fix fmtstr for case where source is BaseSheet #2239 - [sort] maintain ordering on sheet copies #2190 - [test] update unit tests to use packaged sample.tsv and benchmark.csv #2218 -- [threads] fix HelpSheet thread causing an Exception #2235 +- [threads] do not try to cancel already finished thread #2235 + +- [tests] add `assert-expr` and `assert-expr-row` to evaluate Python expressions, and assert result is truthy +- [tests] parametrize feature tests (PR by @ajkerrigan #2230) # v3.0 (2023-12-30) From 12ee88762be31c23f2d86153fdb4ca62eb6c955d Mon Sep 17 00:00:00 2001 From: anjakefala Date: Sun, 7 Jan 2024 18:57:58 -0800 Subject: [PATCH 32/32] [dev] bump to v3.0.1 --- CHANGELOG.md | 2 +- README.md | 2 +- dev/checklists/manual-tests.md | 11 +++++++++++ dev/checklists/release.md | 1 - docs/man.md | 14 +++++++------- setup.py | 2 +- visidata/__init__.py | 2 +- visidata/main.py | 2 +- visidata/man/vd.1 | 14 +++++++------- visidata/man/vd.inc | 4 ++-- visidata/man/vd.txt | 16 ++++++++-------- visidata/man/visidata.1 | 14 +++++++------- 12 files changed, 47 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a6eb49cb..61cf53f23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ - [help] fix columns sheet sidebar - [loaders html] ignore parsing exceptions on invalid urls #2227 - [sheets] limit end separators to rightmost visible column of sheet (PR by @midichef #2237) -- [sidebar] fix fmtstr for case where source is BaseSheet #2239 +- [sidebar] fix fmtstr on DirSheet sidebar for case where source is BaseSheet #2239 - [sort] maintain ordering on sheet copies #2190 - [test] update unit tests to use packaged sample.tsv and benchmark.csv #2218 - [threads] do not try to cancel already finished thread #2235 diff --git a/README.md b/README.md index 1dd117c0a..42cdcc6b0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# VisiData v3.0 +# VisiData v3.0.1 [![Tests](https://github.com/saulpw/visidata/workflows/visidata-ci-build/badge.svg)](https://github.com/saulpw/visidata/actions/workflows/main.yml) [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/saulpw/visidata) diff --git a/dev/checklists/manual-tests.md b/dev/checklists/manual-tests.md index 3834598c5..07e418807 100644 --- a/dev/checklists/manual-tests.md +++ b/dev/checklists/manual-tests.md @@ -94,3 +94,14 @@ 22. Test `open-row` on an html link: https://hls.gsfc.nasa.gov/data/ 23. That DirSheet requires a commit-sheet before changes on filesystem 24. Test adding multiple aggregators via palette (+) +25. cmdpalette + - longname + - Enter executes top recommended + - Tab + Enter cycles through + executes + - 0-9 executes numbered + - aggregators + - Enter executes top + - Tab cycles through + - Space adds aggreqators + - Enter submits aggregators. without adding (except if no aggregators) + - 0-9 adds a number diff --git a/dev/checklists/release.md b/dev/checklists/release.md index 3b71f4efa..8fe6a7efd 100644 --- a/dev/checklists/release.md +++ b/dev/checklists/release.md @@ -13,7 +13,6 @@ 3. Verify that VisiData is up-to-date: * help menu - * plugins.jsonl 3. Ensure `develop` automated tests run correctly with dev/test.sh diff --git a/docs/man.md b/docs/man.md index ed11581ab..c0ec71e00 100644 --- a/docs/man.md +++ b/docs/man.md @@ -51,7 +51,7 @@ vd(1) U undo the most recent modification (requires enabled options.undo) R redo the most recent undo (requires enabled options.undo) - Space longname open command palette; execute command by its longname + Space longname open command palette; Enter to execute top command by its longname Command Palette Tab Move to command palette, and cycle through commands @@ -516,7 +516,7 @@ vd(1) --matrix-device-id=str VisiData device ID associated with matrix login --reddit-client-id=str client_id for reddit api --reddit-client-secret=str client_secret for reddit api - --reddit-user-agent=str 3.0 user_agent for reddit api + --reddit-user-agent=str 3.0.1 user_agent for reddit api --zulip-batch-size=int -100 number of messages to fetch per call (<0 to fetch before anchor) --zulip-anchor=int 1000000000 message id to start fetching from --zulip-delay-s=float 1e-05 seconds to wait between calls (0 to stop after first) @@ -632,13 +632,15 @@ vd(1) color_code bold white on 237 color of code sample color_heading bold 200 color of header color_guide_unwritten 243 on black color of unwritten guides in GuideGuide - disp_rstatus_fmt {sheet.threadStatus} {sheet.keystrokeStatus} {sheet.longname} {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus} + disp_rstatus_fmt {sheet.threadStatus} {sheet.keystrokeStatus} [:longname]{sheet.longname}[/] {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus} right-side status format string disp_status_fmt [:onclick sheets-stack]{sheet.shortcut}› {sheet.name}[/]| status line prefix disp_lstatus_max 0 maximum length of left status line disp_status_sep │ separator between statuses - color_keystrokes bold white on 237 color of input keystrokes on status line + color_keystrokes bold white on 237 color of input keystrokes + color_longname bold 52 on 114 green + color of command longnames color_keys bold color of keystrokes in help color_status bold on 238 status line color color_error 202 1 error message color @@ -692,8 +694,6 @@ vd(1) disp_cmdpal_max 10 max number of suggestions for command palette color_shellcmd 21 on 114 green color_colname underline - color_longname bold 52 on 114 green - disp_scroll_context 0 minimum number of lines to keep visible above/below cursor when scrolling disp_sparkline ▁▂▃▄▅▆▇ characters to display sparkline @@ -788,5 +788,5 @@ vd(1) AUTHOR VisiData was made by Saul Pwanson <vd@saul.pw>. -Linux/MacOS December 29, 2023 Linux/MacOS +Linux/MacOS January 7, 2024 Linux/MacOS diff --git a/setup.py b/setup.py index c7df78125..08b5dc46d 100755 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ # tox can't actually run python3 setup.py: https://github.com/tox-dev/tox/issues/96 # from visidata import __version__ -__version__ = "3.1dev" +__version__ = "3.0.1" setup( name="visidata", diff --git a/visidata/__init__.py b/visidata/__init__.py index a98e12cc5..b18ee004a 100644 --- a/visidata/__init__.py +++ b/visidata/__init__.py @@ -1,6 +1,6 @@ 'VisiData: a curses interface for exploring and arranging tabular data' -__version__ = '3.1dev' +__version__ = '3.0.1' __version_info__ = 'VisiData v' + __version__ __author__ = 'Saul Pwanson ' __status__ = 'Production/Stable' diff --git a/visidata/main.py b/visidata/main.py index caa06de49..765b7cd7a 100755 --- a/visidata/main.py +++ b/visidata/main.py @@ -2,7 +2,7 @@ # Usage: $0 [] [ ...] # $0 [] --play [--batch] [-w ] [-o ] [field=value ...] -__version__ = '3.1dev' +__version__ = '3.0.1' __version_info__ = 'saul.pw/VisiData v' + __version__ from copy import copy diff --git a/visidata/man/vd.1 b/visidata/man/vd.1 index 5f1bccee6..8f163a6a9 100644 --- a/visidata/man/vd.1 +++ b/visidata/man/vd.1 @@ -1,4 +1,4 @@ -.Dd December 29, 2023 +.Dd January 7, 2024 .Dt vd \&1 "Quick Reference Guide" .Os Linux/MacOS . @@ -101,7 +101,7 @@ toggle sidebar .No redo the most recent undo ( requires enabled Sy options.undo Ns ) .Pp .It Ic "Space" Ar longname -.No open command palette; execute command by its Ar longname +.No open command palette; Sy Enter No to execute top command by its Ar longname .El .Ss " Command Palette" .Bl -tag -width XXXXXXXXXXXXXXX -compact -offset XXX @@ -1056,7 +1056,7 @@ device ID associated with matrix login client_id for reddit api .It Sy --reddit-client-secret Ns = Ns Ar "str " No "" client_secret for reddit api -.It Sy --reddit-user-agent Ns = Ns Ar "str " No "3.0" +.It Sy --reddit-user-agent Ns = Ns Ar "str " No "3.0.1" user_agent for reddit api .It Sy --zulip-batch-size Ns = Ns Ar "int " No "-100" number of messages to fetch per call (<0 to fetch before anchor) @@ -1280,7 +1280,7 @@ color of code sample color of header .It Sy "color_guide_unwritten" No "243 on black" color of unwritten guides in GuideGuide -.It Sy "disp_rstatus_fmt " No "{sheet.threadStatus} {sheet.keystrokeStatus} {sheet.longname} {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus}" +.It Sy "disp_rstatus_fmt " No "{sheet.threadStatus} {sheet.keystrokeStatus} [:longname]{sheet.longname}[/] {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus}" right-side status format string .It Sy "disp_status_fmt " No "[:onclick sheets-stack]{sheet.shortcut}\[u203A] {sheet.name}[/]| " status line prefix @@ -1289,7 +1289,9 @@ maximum length of left status line .It Sy "disp_status_sep " No "\[u2502]" separator between statuses .It Sy "color_keystrokes " No "bold white on 237" -color of input keystrokes on status line +color of input keystrokes +.It Sy "color_longname " No "bold 52 on 114 green" +color of command longnames .It Sy "color_keys " No "bold" color of keystrokes in help .It Sy "color_status " No "bold on 238" @@ -1394,8 +1396,6 @@ max number of suggestions for command palette .It Sy "color_colname " No "underline" -.It Sy "color_longname " No "bold 52 on 114 green" - .It Sy "disp_scroll_context" No "0" minimum number of lines to keep visible above/below cursor when scrolling .It Sy "disp_sparkline " No "\[u2581]\[u2582]\[u2583]\[u2584]\[u2585]\[u2586]\[u2587]" diff --git a/visidata/man/vd.inc b/visidata/man/vd.inc index 9d84b8651..4d0b116c3 100644 --- a/visidata/man/vd.inc +++ b/visidata/man/vd.inc @@ -1,4 +1,4 @@ -.Dd December 29, 2023 +.Dd January 7, 2024 .Dt vd \&1 "Quick Reference Guide" .Os Linux/MacOS . @@ -101,7 +101,7 @@ toggle sidebar .No redo the most recent undo ( requires enabled Sy options.undo Ns ) .Pp .It Ic "Space" Ar longname -.No open command palette; execute top command by its Ar longname +.No open command palette; Sy Enter No to execute top command by its Ar longname .El .Ss " Command Palette" .Bl -tag -width XXXXXXXXXXXXXXX -compact -offset XXX diff --git a/visidata/man/vd.txt b/visidata/man/vd.txt index 69273f883..705fdde9c 100644 --- a/visidata/man/vd.txt +++ b/visidata/man/vd.txt @@ -53,7 +53,8 @@ DESCRIPTION R redo the most recent undo (requires enabled options.undo) - Space longname open command palette; execute command by its longname + Space longname open command palette; Enter to execute top command by + its longname Command Palette Tab Move to command palette, and cycle through commands @@ -743,7 +744,7 @@ COMMANDLINE OPTIONS --reddit-client-id=str client_id for reddit api --reddit-client-secret=str client_secret for reddit api - --reddit-user-agent=str 3.0 user_agent for reddit api + --reddit-user-agent=str 3.0.1 user_agent for reddit api --zulip-batch-size=int -100 number of messages to fetch per call (<0 to fetch before anchor) @@ -962,7 +963,7 @@ COMMANDLINE OPTIONS color_guide_unwritten 243 on black color of unwritten guides in GuideGuide disp_rstatus_fmt {sheet.threadStatus} {sheet.keystrokeStatus} - {sheet.longname} + [:longname]{sheet.longname}[/] {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus} right-side status format string @@ -972,8 +973,9 @@ COMMANDLINE OPTIONS disp_lstatus_max 0 maximum length of left status line disp_status_sep │ separator between statuses - color_keystrokes bold white on 237 color of input keystrokes on sta‐ - tus line + color_keystrokes bold white on 237 color of input keystrokes + color_longname bold 52 on 114 green + color of command longnames color_keys bold color of keystrokes in help color_status bold on 238 status line color color_error 202 1 error message color @@ -1045,8 +1047,6 @@ COMMANDLINE OPTIONS command palette color_shellcmd 21 on 114 green color_colname underline - color_longname bold 52 on 114 green - disp_scroll_context 0 minimum number of lines to keep visible above/below cursor when scrolling @@ -1157,4 +1157,4 @@ SUPPORTED SOURCES AUTHOR VisiData was made by Saul Pwanson . -Linux/MacOS December 29, 2023 Linux/MacOS +Linux/MacOS January 7, 2024 Linux/MacOS diff --git a/visidata/man/visidata.1 b/visidata/man/visidata.1 index 5f1bccee6..8f163a6a9 100644 --- a/visidata/man/visidata.1 +++ b/visidata/man/visidata.1 @@ -1,4 +1,4 @@ -.Dd December 29, 2023 +.Dd January 7, 2024 .Dt vd \&1 "Quick Reference Guide" .Os Linux/MacOS . @@ -101,7 +101,7 @@ toggle sidebar .No redo the most recent undo ( requires enabled Sy options.undo Ns ) .Pp .It Ic "Space" Ar longname -.No open command palette; execute command by its Ar longname +.No open command palette; Sy Enter No to execute top command by its Ar longname .El .Ss " Command Palette" .Bl -tag -width XXXXXXXXXXXXXXX -compact -offset XXX @@ -1056,7 +1056,7 @@ device ID associated with matrix login client_id for reddit api .It Sy --reddit-client-secret Ns = Ns Ar "str " No "" client_secret for reddit api -.It Sy --reddit-user-agent Ns = Ns Ar "str " No "3.0" +.It Sy --reddit-user-agent Ns = Ns Ar "str " No "3.0.1" user_agent for reddit api .It Sy --zulip-batch-size Ns = Ns Ar "int " No "-100" number of messages to fetch per call (<0 to fetch before anchor) @@ -1280,7 +1280,7 @@ color of code sample color of header .It Sy "color_guide_unwritten" No "243 on black" color of unwritten guides in GuideGuide -.It Sy "disp_rstatus_fmt " No "{sheet.threadStatus} {sheet.keystrokeStatus} {sheet.longname} {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus}" +.It Sy "disp_rstatus_fmt " No "{sheet.threadStatus} {sheet.keystrokeStatus} [:longname]{sheet.longname}[/] {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus}" right-side status format string .It Sy "disp_status_fmt " No "[:onclick sheets-stack]{sheet.shortcut}\[u203A] {sheet.name}[/]| " status line prefix @@ -1289,7 +1289,9 @@ maximum length of left status line .It Sy "disp_status_sep " No "\[u2502]" separator between statuses .It Sy "color_keystrokes " No "bold white on 237" -color of input keystrokes on status line +color of input keystrokes +.It Sy "color_longname " No "bold 52 on 114 green" +color of command longnames .It Sy "color_keys " No "bold" color of keystrokes in help .It Sy "color_status " No "bold on 238" @@ -1394,8 +1396,6 @@ max number of suggestions for command palette .It Sy "color_colname " No "underline" -.It Sy "color_longname " No "bold 52 on 114 green" - .It Sy "disp_scroll_context" No "0" minimum number of lines to keep visible above/below cursor when scrolling .It Sy "disp_sparkline " No "\[u2581]\[u2582]\[u2583]\[u2584]\[u2585]\[u2586]\[u2587]"