visidata 3.0__tar.gz → 3.0.1__tar.gz

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.
Files changed (276) hide show
  1. {visidata-3.0 → visidata-3.0.1}/MANIFEST.in +1 -0
  2. {visidata-3.0/visidata.egg-info → visidata-3.0.1}/PKG-INFO +3 -3
  3. {visidata-3.0 → visidata-3.0.1}/README.md +1 -1
  4. {visidata-3.0 → visidata-3.0.1}/setup.py +2 -2
  5. {visidata-3.0 → visidata-3.0.1}/visidata/__init__.py +1 -1
  6. {visidata-3.0 → visidata-3.0.1}/visidata/aggregators.py +14 -1
  7. {visidata-3.0 → visidata-3.0.1}/visidata/basesheet.py +5 -2
  8. {visidata-3.0 → visidata-3.0.1}/visidata/column.py +1 -1
  9. {visidata-3.0 → visidata-3.0.1}/visidata/errors.py +1 -1
  10. {visidata-3.0 → visidata-3.0.1}/visidata/extensible.py +1 -8
  11. {visidata-3.0 → visidata-3.0.1}/visidata/features/cmdpalette.py +39 -5
  12. {visidata-3.0 → visidata-3.0.1}/visidata/features/slide.py +7 -5
  13. {visidata-3.0 → visidata-3.0.1}/visidata/guide.py +20 -0
  14. {visidata-3.0 → visidata-3.0.1}/visidata/keys.py +3 -0
  15. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/api_reddit.py +5 -5
  16. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/html.py +6 -2
  17. {visidata-3.0 → visidata-3.0.1}/visidata/main.py +1 -1
  18. {visidata-3.0 → visidata-3.0.1}/visidata/man/vd.1 +7 -7
  19. {visidata-3.0 → visidata-3.0.1}/visidata/man/vd.txt +8 -8
  20. {visidata-3.0 → visidata-3.0.1}/visidata/man/visidata.1 +7 -7
  21. {visidata-3.0 → visidata-3.0.1}/visidata/pyobj.py +5 -4
  22. {visidata-3.0 → visidata-3.0.1}/visidata/sheets.py +12 -5
  23. {visidata-3.0 → visidata-3.0.1}/visidata/statusbar.py +3 -2
  24. visidata-3.0.1/visidata/tests/benchmark.csv +52 -0
  25. {visidata-3.0 → visidata-3.0.1}/visidata/tests/test_commands.py +3 -0
  26. visidata-3.0.1/visidata/tests/test_features.py +28 -0
  27. {visidata-3.0 → visidata-3.0.1}/visidata/threads.py +2 -1
  28. {visidata-3.0 → visidata-3.0.1/visidata.egg-info}/PKG-INFO +3 -3
  29. {visidata-3.0 → visidata-3.0.1}/visidata.egg-info/SOURCES.txt +1 -0
  30. visidata-3.0/visidata/tests/test_features.py +0 -17
  31. {visidata-3.0 → visidata-3.0.1}/LICENSE.gpl3 +0 -0
  32. {visidata-3.0 → visidata-3.0.1}/bin/vd +0 -0
  33. {visidata-3.0 → visidata-3.0.1}/bin/vd2to3.vdx +0 -0
  34. {visidata-3.0 → visidata-3.0.1}/setup.cfg +0 -0
  35. {visidata-3.0 → visidata-3.0.1}/visidata/__main__.py +0 -0
  36. {visidata-3.0 → visidata-3.0.1}/visidata/_input.py +0 -0
  37. {visidata-3.0 → visidata-3.0.1}/visidata/_open.py +0 -0
  38. {visidata-3.0 → visidata-3.0.1}/visidata/_types.py +0 -0
  39. {visidata-3.0 → visidata-3.0.1}/visidata/_urlcache.py +0 -0
  40. {visidata-3.0 → visidata-3.0.1}/visidata/apps/__init__.py +0 -0
  41. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vdsql/__about__.py +0 -0
  42. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vdsql/__init__.py +0 -0
  43. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vdsql/__main__.py +0 -0
  44. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vdsql/_ibis.py +0 -0
  45. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vdsql/bigquery.py +0 -0
  46. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vdsql/clickhouse.py +0 -0
  47. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vdsql/setup.py +0 -0
  48. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vdsql/snowflake.py +0 -0
  49. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/__init__.py +0 -0
  50. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/__main__.py +0 -0
  51. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/abort.py +0 -0
  52. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/blame.py +0 -0
  53. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/branch.py +0 -0
  54. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/config.py +0 -0
  55. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/diff.py +0 -0
  56. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/gitsheet.py +0 -0
  57. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/grep.py +0 -0
  58. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/log.py +0 -0
  59. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/main.py +0 -0
  60. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/remote.py +0 -0
  61. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/repos.py +0 -0
  62. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/setup.py +0 -0
  63. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/stash.py +0 -0
  64. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/status.py +0 -0
  65. {visidata-3.0 → visidata-3.0.1}/visidata/apps/vgit/statusbar.py +0 -0
  66. {visidata-3.0 → visidata-3.0.1}/visidata/bezier.py +0 -0
  67. {visidata-3.0 → visidata-3.0.1}/visidata/canvas.py +0 -0
  68. {visidata-3.0 → visidata-3.0.1}/visidata/canvas_text.py +0 -0
  69. {visidata-3.0 → visidata-3.0.1}/visidata/choose.py +0 -0
  70. {visidata-3.0 → visidata-3.0.1}/visidata/clean_names.py +0 -0
  71. {visidata-3.0 → visidata-3.0.1}/visidata/clipboard.py +0 -0
  72. {visidata-3.0 → visidata-3.0.1}/visidata/cliptext.py +0 -0
  73. {visidata-3.0 → visidata-3.0.1}/visidata/cmdlog.py +0 -0
  74. {visidata-3.0 → visidata-3.0.1}/visidata/color.py +0 -0
  75. {visidata-3.0 → visidata-3.0.1}/visidata/ddw/input.ddw +0 -0
  76. {visidata-3.0 → visidata-3.0.1}/visidata/ddw/regex.ddw +0 -0
  77. {visidata-3.0 → visidata-3.0.1}/visidata/ddwplay.py +0 -0
  78. {visidata-3.0 → visidata-3.0.1}/visidata/deprecated.py +0 -0
  79. {visidata-3.0 → visidata-3.0.1}/visidata/desktop/visidata.desktop +0 -0
  80. {visidata-3.0 → visidata-3.0.1}/visidata/editor.py +0 -0
  81. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/__init__.py +0 -0
  82. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/diff_sheet.py +0 -0
  83. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/digit_autoedit.py +0 -0
  84. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/gdrive.py +0 -0
  85. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/google.py +0 -0
  86. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/gsheets.py +0 -0
  87. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/live_search.py +0 -0
  88. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/liveupdate.py +0 -0
  89. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/mark.py +0 -0
  90. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/__init__.py +0 -0
  91. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/clues.json +0 -0
  92. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/flame.ddw +0 -0
  93. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/menorah.ddw +0 -0
  94. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/noahs.sqlite +0 -0
  95. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/puzzle0.md +0 -0
  96. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/puzzle1.md +0 -0
  97. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/puzzle2.md +0 -0
  98. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/puzzle3.md +0 -0
  99. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/puzzle4.md +0 -0
  100. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/puzzle5.md +0 -0
  101. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/puzzle6.md +0 -0
  102. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/puzzle7.md +0 -0
  103. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/puzzle8.md +0 -0
  104. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/solutions.json +0 -0
  105. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/tapestry.ddw +0 -0
  106. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/noahs_tapestry/tapestry.py +0 -0
  107. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/rownum.py +0 -0
  108. {visidata-3.0 → visidata-3.0.1}/visidata/experimental/slide_cells.py +0 -0
  109. {visidata-3.0 → visidata-3.0.1}/visidata/expr.py +0 -0
  110. {visidata-3.0 → visidata-3.0.1}/visidata/features/__init__.py +0 -0
  111. {visidata-3.0 → visidata-3.0.1}/visidata/features/addcol_audiometadata.py +0 -0
  112. {visidata-3.0 → visidata-3.0.1}/visidata/features/addcol_histogram.py +0 -0
  113. {visidata-3.0 → visidata-3.0.1}/visidata/features/canvas_save_svg.py +0 -0
  114. {visidata-3.0 → visidata-3.0.1}/visidata/features/change_precision.py +0 -0
  115. {visidata-3.0 → visidata-3.0.1}/visidata/features/colorbrewer.py +0 -0
  116. {visidata-3.0 → visidata-3.0.1}/visidata/features/colorsheet.py +0 -0
  117. {visidata-3.0 → visidata-3.0.1}/visidata/features/command_server.py +0 -0
  118. {visidata-3.0 → visidata-3.0.1}/visidata/features/currency_to_usd.py +0 -0
  119. {visidata-3.0 → visidata-3.0.1}/visidata/features/customdate.py +0 -0
  120. {visidata-3.0 → visidata-3.0.1}/visidata/features/dedupe.py +0 -0
  121. {visidata-3.0 → visidata-3.0.1}/visidata/features/describe.py +0 -0
  122. {visidata-3.0 → visidata-3.0.1}/visidata/features/errors_guide.py +0 -0
  123. {visidata-3.0 → visidata-3.0.1}/visidata/features/expand_cols.py +0 -0
  124. {visidata-3.0 → visidata-3.0.1}/visidata/features/fill.py +0 -0
  125. {visidata-3.0 → visidata-3.0.1}/visidata/features/freeze.py +0 -0
  126. {visidata-3.0 → visidata-3.0.1}/visidata/features/graph_seaborn.py +0 -0
  127. {visidata-3.0 → visidata-3.0.1}/visidata/features/helloworld.py +0 -0
  128. {visidata-3.0 → visidata-3.0.1}/visidata/features/hint_types.py +0 -0
  129. {visidata-3.0 → visidata-3.0.1}/visidata/features/incr.py +0 -0
  130. {visidata-3.0 → visidata-3.0.1}/visidata/features/join.py +0 -0
  131. {visidata-3.0 → visidata-3.0.1}/visidata/features/known_cols.py +0 -0
  132. {visidata-3.0 → visidata-3.0.1}/visidata/features/layout.py +0 -0
  133. {visidata-3.0 → visidata-3.0.1}/visidata/features/melt.py +0 -0
  134. {visidata-3.0 → visidata-3.0.1}/visidata/features/normcol.py +0 -0
  135. {visidata-3.0 → visidata-3.0.1}/visidata/features/open_config.py +0 -0
  136. {visidata-3.0 → visidata-3.0.1}/visidata/features/open_syspaste.py +0 -0
  137. {visidata-3.0 → visidata-3.0.1}/visidata/features/ping.py +0 -0
  138. {visidata-3.0 → visidata-3.0.1}/visidata/features/procmgr.py +0 -0
  139. {visidata-3.0 → visidata-3.0.1}/visidata/features/random_sample.py +0 -0
  140. {visidata-3.0 → visidata-3.0.1}/visidata/features/regex.py +0 -0
  141. {visidata-3.0 → visidata-3.0.1}/visidata/features/reload_every.py +0 -0
  142. {visidata-3.0 → visidata-3.0.1}/visidata/features/rename_col_cascade.py +0 -0
  143. {visidata-3.0 → visidata-3.0.1}/visidata/features/repeat.py +0 -0
  144. {visidata-3.0 → visidata-3.0.1}/visidata/features/scroll_context.py +0 -0
  145. {visidata-3.0 → visidata-3.0.1}/visidata/features/select_equal_selected.py +0 -0
  146. {visidata-3.0 → visidata-3.0.1}/visidata/features/setcol_fake.py +0 -0
  147. {visidata-3.0 → visidata-3.0.1}/visidata/features/sparkline.py +0 -0
  148. {visidata-3.0 → visidata-3.0.1}/visidata/features/status_source.py +0 -0
  149. {visidata-3.0 → visidata-3.0.1}/visidata/features/sysedit.py +0 -0
  150. {visidata-3.0 → visidata-3.0.1}/visidata/features/sysopen_mailcap.py +0 -0
  151. {visidata-3.0 → visidata-3.0.1}/visidata/features/term_extras.py +0 -0
  152. {visidata-3.0 → visidata-3.0.1}/visidata/features/transpose.py +0 -0
  153. {visidata-3.0 → visidata-3.0.1}/visidata/features/type_ipaddr.py +0 -0
  154. {visidata-3.0 → visidata-3.0.1}/visidata/features/type_url.py +0 -0
  155. {visidata-3.0 → visidata-3.0.1}/visidata/features/unfurl.py +0 -0
  156. {visidata-3.0 → visidata-3.0.1}/visidata/features/window.py +0 -0
  157. {visidata-3.0 → visidata-3.0.1}/visidata/form.py +0 -0
  158. {visidata-3.0 → visidata-3.0.1}/visidata/freqtbl.py +0 -0
  159. {visidata-3.0 → visidata-3.0.1}/visidata/fuzzymatch.py +0 -0
  160. {visidata-3.0 → visidata-3.0.1}/visidata/graph.py +0 -0
  161. {visidata-3.0 → visidata-3.0.1}/visidata/help.py +0 -0
  162. {visidata-3.0 → visidata-3.0.1}/visidata/hint.py +0 -0
  163. {visidata-3.0 → visidata-3.0.1}/visidata/indexsheet.py +0 -0
  164. {visidata-3.0 → visidata-3.0.1}/visidata/input_history.py +0 -0
  165. {visidata-3.0 → visidata-3.0.1}/visidata/interface.py +0 -0
  166. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/__init__.py +0 -0
  167. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/_pandas.py +0 -0
  168. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/api_airtable.py +0 -0
  169. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/api_matrix.py +0 -0
  170. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/api_zulip.py +0 -0
  171. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/archive.py +0 -0
  172. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/arrow.py +0 -0
  173. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/conll.py +0 -0
  174. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/csv.py +0 -0
  175. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/eml.py +0 -0
  176. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/f5log.py +0 -0
  177. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/fec.py +0 -0
  178. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/fixed_width.py +0 -0
  179. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/frictionless.py +0 -0
  180. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/geojson.py +0 -0
  181. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/google.py +0 -0
  182. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/graphviz.py +0 -0
  183. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/hdf5.py +0 -0
  184. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/http.py +0 -0
  185. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/imap.py +0 -0
  186. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/jrnl.py +0 -0
  187. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/json.py +0 -0
  188. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/jsonla.py +0 -0
  189. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/lsv.py +0 -0
  190. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/mailbox.py +0 -0
  191. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/markdown.py +0 -0
  192. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/mbtiles.py +0 -0
  193. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/mysql.py +0 -0
  194. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/npy.py +0 -0
  195. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/odf.py +0 -0
  196. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/orgmode.py +0 -0
  197. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/pandas_freqtbl.py +0 -0
  198. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/parquet.py +0 -0
  199. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/pcap.py +0 -0
  200. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/pdf.py +0 -0
  201. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/png.py +0 -0
  202. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/postgres.py +0 -0
  203. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/rec.py +0 -0
  204. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/s3.py +0 -0
  205. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/sas.py +0 -0
  206. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/scrape.py +0 -0
  207. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/shp.py +0 -0
  208. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/spss.py +0 -0
  209. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/sqlite.py +0 -0
  210. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/texttables.py +0 -0
  211. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/toml.py +0 -0
  212. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/tsv.py +0 -0
  213. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/ttf.py +0 -0
  214. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/unzip_http.py +0 -0
  215. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/usv.py +0 -0
  216. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/vcf.py +0 -0
  217. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/vds.py +0 -0
  218. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/vdx.py +0 -0
  219. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/xlsb.py +0 -0
  220. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/xlsx.py +0 -0
  221. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/xml.py +0 -0
  222. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/xword.py +0 -0
  223. {visidata-3.0 → visidata-3.0.1}/visidata/loaders/yaml.py +0 -0
  224. {visidata-3.0 → visidata-3.0.1}/visidata/macos.py +0 -0
  225. {visidata-3.0 → visidata-3.0.1}/visidata/macros.py +0 -0
  226. {visidata-3.0 → visidata-3.0.1}/visidata/mainloop.py +0 -0
  227. {visidata-3.0 → visidata-3.0.1}/visidata/man/parse_options.py +0 -0
  228. {visidata-3.0 → visidata-3.0.1}/visidata/memory.py +0 -0
  229. {visidata-3.0 → visidata-3.0.1}/visidata/menu.py +0 -0
  230. {visidata-3.0 → visidata-3.0.1}/visidata/metasheets.py +0 -0
  231. {visidata-3.0 → visidata-3.0.1}/visidata/modify.py +0 -0
  232. {visidata-3.0 → visidata-3.0.1}/visidata/motd.py +0 -0
  233. {visidata-3.0 → visidata-3.0.1}/visidata/mouse.py +0 -0
  234. {visidata-3.0 → visidata-3.0.1}/visidata/movement.py +0 -0
  235. {visidata-3.0 → visidata-3.0.1}/visidata/optionssheet.py +0 -0
  236. {visidata-3.0 → visidata-3.0.1}/visidata/path.py +0 -0
  237. {visidata-3.0 → visidata-3.0.1}/visidata/pivot.py +0 -0
  238. {visidata-3.0 → visidata-3.0.1}/visidata/plugins.py +0 -0
  239. {visidata-3.0 → visidata-3.0.1}/visidata/rename_col.py +0 -0
  240. {visidata-3.0 → visidata-3.0.1}/visidata/save.py +0 -0
  241. {visidata-3.0 → visidata-3.0.1}/visidata/search.py +0 -0
  242. {visidata-3.0 → visidata-3.0.1}/visidata/selection.py +0 -0
  243. {visidata-3.0 → visidata-3.0.1}/visidata/settings.py +0 -0
  244. {visidata-3.0 → visidata-3.0.1}/visidata/shell.py +0 -0
  245. {visidata-3.0 → visidata-3.0.1}/visidata/sidebar.py +0 -0
  246. {visidata-3.0 → visidata-3.0.1}/visidata/sort.py +0 -0
  247. {visidata-3.0 → visidata-3.0.1}/visidata/stored_list.py +0 -0
  248. {visidata-3.0 → visidata-3.0.1}/visidata/tests/__init__.py +0 -0
  249. {visidata-3.0 → visidata-3.0.1}/visidata/tests/conftest.py +0 -0
  250. {visidata-3.0 → visidata-3.0.1}/visidata/tests/sample.tsv +0 -0
  251. {visidata-3.0 → visidata-3.0.1}/visidata/tests/test_cliptext.py +0 -0
  252. {visidata-3.0 → visidata-3.0.1}/visidata/tests/test_date.py +0 -0
  253. {visidata-3.0 → visidata-3.0.1}/visidata/tests/test_edittext.py +0 -0
  254. {visidata-3.0 → visidata-3.0.1}/visidata/tests/test_menu.py +0 -0
  255. {visidata-3.0 → visidata-3.0.1}/visidata/tests/test_path.py +0 -0
  256. {visidata-3.0 → visidata-3.0.1}/visidata/text_source.py +0 -0
  257. {visidata-3.0 → visidata-3.0.1}/visidata/textsheet.py +0 -0
  258. {visidata-3.0 → visidata-3.0.1}/visidata/theme.py +0 -0
  259. {visidata-3.0 → visidata-3.0.1}/visidata/themes/__init__.py +0 -0
  260. {visidata-3.0 → visidata-3.0.1}/visidata/themes/ascii8.py +0 -0
  261. {visidata-3.0 → visidata-3.0.1}/visidata/themes/asciimono.py +0 -0
  262. {visidata-3.0 → visidata-3.0.1}/visidata/themes/light.py +0 -0
  263. {visidata-3.0 → visidata-3.0.1}/visidata/tuiwin.py +0 -0
  264. {visidata-3.0 → visidata-3.0.1}/visidata/type_currency.py +0 -0
  265. {visidata-3.0 → visidata-3.0.1}/visidata/type_date.py +0 -0
  266. {visidata-3.0 → visidata-3.0.1}/visidata/type_floatsi.py +0 -0
  267. {visidata-3.0 → visidata-3.0.1}/visidata/undo.py +0 -0
  268. {visidata-3.0 → visidata-3.0.1}/visidata/utils.py +0 -0
  269. {visidata-3.0 → visidata-3.0.1}/visidata/vdobj.py +0 -0
  270. {visidata-3.0 → visidata-3.0.1}/visidata/vendor/appdirs.py +0 -0
  271. {visidata-3.0 → visidata-3.0.1}/visidata/windows.py +0 -0
  272. {visidata-3.0 → visidata-3.0.1}/visidata/wrappers.py +0 -0
  273. {visidata-3.0 → visidata-3.0.1}/visidata.egg-info/dependency_links.txt +0 -0
  274. {visidata-3.0 → visidata-3.0.1}/visidata.egg-info/entry_points.txt +0 -0
  275. {visidata-3.0 → visidata-3.0.1}/visidata.egg-info/requires.txt +0 -0
  276. {visidata-3.0 → visidata-3.0.1}/visidata.egg-info/top_level.txt +0 -0
@@ -6,6 +6,7 @@ include visidata/man/visidata.1
6
6
  include visidata/ddw/input.ddw
7
7
  include visidata/ddw/regex.ddw
8
8
  include visidata/tests/sample.tsv
9
+ include visidata/tests/benchmark.csv
9
10
  include visidata/desktop/visidata.desktop
10
11
  include visidata/experimental/noahs_tapestry/*.json
11
12
  include visidata/experimental/noahs_tapestry/*.md
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: visidata
3
- Version: 3.0
3
+ Version: 3.0.1
4
4
  Summary: terminal interface for exploring and arranging tabular data
5
5
  Home-page: https://visidata.org
6
- Download-URL: https://github.com/saulpw/visidata/tarball/3.0
6
+ Download-URL: https://github.com/saulpw/visidata/tarball/3.0.1
7
7
  Author: Saul Pwanson
8
8
  Author-email: visidata@saul.pw
9
9
  License: GPLv3
@@ -26,7 +26,7 @@ Requires-Python: >=3.7
26
26
  Description-Content-Type: text/markdown
27
27
  License-File: LICENSE.gpl3
28
28
 
29
- # VisiData v3.0
29
+ # VisiData v3.0.1
30
30
 
31
31
  [![Tests](https://github.com/saulpw/visidata/workflows/visidata-ci-build/badge.svg)](https://github.com/saulpw/visidata/actions/workflows/main.yml)
32
32
  [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/saulpw/visidata)
@@ -1,4 +1,4 @@
1
- # VisiData v3.0
1
+ # VisiData v3.0.1
2
2
 
3
3
  [![Tests](https://github.com/saulpw/visidata/workflows/visidata-ci-build/badge.svg)](https://github.com/saulpw/visidata/actions/workflows/main.yml)
4
4
  [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/saulpw/visidata)
@@ -4,7 +4,7 @@ from setuptools import setup
4
4
 
5
5
  # tox can't actually run python3 setup.py: https://github.com/tox-dev/tox/issues/96
6
6
  # from visidata import __version__
7
- __version__ = "3.0"
7
+ __version__ = "3.0.1"
8
8
 
9
9
  setup(
10
10
  name="visidata",
@@ -51,7 +51,7 @@ setup(
51
51
  package_data={
52
52
  "visidata.man": ["vd.1", "vd.txt"],
53
53
  "visidata.ddw": ["input.ddw", "regex.ddw"],
54
- "visidata.tests": ["sample.tsv"],
54
+ "visidata.tests": ["sample.tsv", "benchmark.csv"],
55
55
  "visidata.desktop": ["visidata.desktop"],
56
56
  "visidata.experimenta.noahs_tapestry": [
57
57
  "clues.json",
@@ -1,6 +1,6 @@
1
1
  'VisiData: a curses interface for exploring and arranging tabular data'
2
2
 
3
- __version__ = '3.0'
3
+ __version__ = '3.0.1'
4
4
  __version_info__ = 'VisiData v' + __version__
5
5
  __author__ = 'Saul Pwanson <vd@saul.pw>'
6
6
  __status__ = 'Production/Stable'
@@ -7,7 +7,20 @@ import statistics
7
7
  from visidata import Progress, Sheet, Column, ColumnsSheet, VisiData
8
8
  from visidata import vd, anytype, vlen, asyncthread, wrapply, AttrDict
9
9
 
10
- vd.help_aggregators = '# Aggregators Help\nHELPTODO'
10
+ vd.help_aggregators = '''# Choose Aggregators
11
+ Start typing an aggregator name or description.
12
+ Multiple aggregators can be added by separating spaces.
13
+
14
+ - `Enter` to select top aggregator.
15
+ - `Tab` to highlight top aggregator.
16
+
17
+ ## When Aggregator Highlighted
18
+
19
+ - `Tab`/`Shift+Tab` to cycle highlighted aggregator.
20
+ - `Enter` to select aggregators.
21
+ - `Space` to add highlighted aggregator.
22
+ - `0-9` to add numbered aggregator.
23
+ '''
11
24
 
12
25
  vd.option('null_value', None, 'a value to be counted as null', replay=True)
13
26
 
@@ -18,6 +18,9 @@ class LazyChainMap:
18
18
  if k not in self.objs:
19
19
  self.objs[k] = obj
20
20
 
21
+ def __iter__(self):
22
+ return iter(self.objs)
23
+
21
24
  def __contains__(self, k):
22
25
  return k in self.objs
23
26
 
@@ -175,7 +178,7 @@ class BaseSheet(DrawablePane):
175
178
  @property
176
179
  def displaySource(self):
177
180
  if isinstance(self.source, BaseSheet):
178
- return f'the *{self.source[0]}* sheet'
181
+ return f'the *{self.source}* sheet'
179
182
 
180
183
  if isinstance(self.source, (list, tuple)):
181
184
  if len(self.source) == 1:
@@ -283,7 +286,7 @@ class BaseSheet(DrawablePane):
283
286
 
284
287
  def evalExpr(self, expr, **kwargs):
285
288
  'Evaluate Python expression *expr* in the context of *kwargs* (may vary by sheet type).'
286
- return eval(expr, vd.getGlobals(), None)
289
+ return eval(expr, vd.getGlobals(), dict(sheet=self))
287
290
 
288
291
  def formatString(self, fmt, **kwargs):
289
292
  'Return formatted string with *sheet* and *vd* accessible to expressions. Missing expressions return empty strings instead of error.'
@@ -111,7 +111,7 @@ class Column(Extensible):
111
111
  return self.__copy__() # no separate deepcopy
112
112
 
113
113
  def __getstate__(self):
114
- return {k:getattr(self, k) for k in 'name typestr width height expr keycol formatter fmtstr voffset hoffset aggstr'.split() if hasattr(self, k)}
114
+ 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)}
115
115
 
116
116
  def __setstate__(self, d):
117
117
  for attr, v in d.items():
@@ -1,6 +1,6 @@
1
1
  import traceback
2
2
 
3
- from visidata import vd, VisiData, options
3
+ from visidata import vd, VisiData
4
4
 
5
5
  vd.option('debug', False, 'exit on error and display stacktrace', max_help=0)
6
6
 
@@ -30,14 +30,7 @@ class Extensible:
30
30
  ret = oldcopy(self, *args, **kwargs)
31
31
  else:
32
32
  ret = super(cls, self).__copy__(*args, **kwargs)
33
-
34
- if not hasattr(ret, membername):
35
- if copy and hasattr(self, membername):
36
- v = getattr(self, membername)
37
- else:
38
- v = initfunc()
39
- setattr(ret, membername, v)
40
-
33
+ setattr(ret, membername, getattr(self, membername) if copy and hasattr(self, membername) else initfunc())
41
34
  return ret
42
35
  cls.__copy__ = wraps(oldcopy)(newcopy) if oldcopy else newcopy
43
36
 
@@ -6,6 +6,19 @@ from visidata import DrawablePane, BaseSheet, vd, VisiData, CompleteKey, clipdra
6
6
  vd.theme_option('color_cmdpalette', 'black on 72', 'base color of command palette')
7
7
  vd.theme_option('disp_cmdpal_max', 10, 'max number of suggestions for command palette')
8
8
 
9
+ vd.help_longname = '''# Choose Command
10
+ Start typing a command longname or keyword in its helpstring.
11
+
12
+ - `Enter` to execute top command.
13
+ - `Tab` to highlight top command.
14
+
15
+ ## When Command Highlighted
16
+
17
+ - `Tab`/`Shift+Tab` to cycle highlighted command.
18
+ - `Enter` to execute highlighted command.
19
+ - `0-9` to execute numbered command.
20
+ '''
21
+
9
22
  def add_to_input(v, i, value=''):
10
23
  items = list(v.split())
11
24
  if not v or v.endswith(' '):
@@ -19,6 +32,17 @@ def add_to_input(v, i, value=''):
19
32
  def accept_input(v, i, value=None):
20
33
  raise AcceptInput(v if value is None else value)
21
34
 
35
+ def accept_input_if_subset(v, i, value=''):
36
+ # if no input, accept value under cmd palette cursor
37
+ if not v:
38
+ raise AcceptInput(value)
39
+
40
+ # if the last item is a partial match, replace it with the full value
41
+ parts = v.split()
42
+ if value and value.startswith(parts[-1]):
43
+ v = ' '.join(parts[:-1] + [value])
44
+
45
+ raise AcceptInput(v)
22
46
 
23
47
  @VisiData.lazy_property
24
48
  def usedInputs(vd):
@@ -86,7 +110,7 @@ def inputPalette(sheet, prompt, items,
86
110
  palrows.append((None, None))
87
111
 
88
112
  for i, (m, item) in enumerate(palrows):
89
- trigger_key = ' '
113
+ trigger_key = ''
90
114
  if tabitem >= 0 and item:
91
115
  trigger_key = f'{i+1}'[-1]
92
116
  bindings[trigger_key] = partial(add_to_input if multiple else accept_input, value=item[value_key])
@@ -95,13 +119,17 @@ def inputPalette(sheet, prompt, items,
95
119
 
96
120
  if tabitem < 0 and palrows:
97
121
  _ , topitem = palrows[0]
98
- bindings['^J'] = partial(accept_input, value=None)
99
122
  if multiple:
100
123
  bindings[' '] = partial(add_to_input, value=topitem[value_key])
124
+ bindings['^J'] = partial(accept_input_if_subset, value=topitem[value_key])
125
+ else:
126
+ bindings['^J'] = partial(accept_input, value=topitem[value_key])
101
127
  elif item and i == tabitem:
102
- bindings['^J'] = partial(accept_input, value=None)
103
128
  if multiple:
129
+ bindings['^J'] = partial(accept_input_if_subset, value=item[value_key])
104
130
  bindings[' '] = partial(add_to_input, value=item[value_key])
131
+ else:
132
+ bindings['^J'] = partial(accept_input, value=item[value_key])
105
133
  attr = colors.color_menu_spec
106
134
 
107
135
  match_summary = formatter(m, item, trigger_key) if item else ' '
@@ -137,11 +165,16 @@ def inputLongname(sheet):
137
165
  def _fmt_cmdpal_summary(match, row, trigger_key):
138
166
  keystrokes = this_sheets_help.revbinds.get(row.longname, [None])[0] or ' '
139
167
  formatted_longname = match.formatted.get('longname', row.longname) if match else row.longname
140
- formatted_name = f'[:onclick {row.longname}]{formatted_longname}[/]'
168
+ formatted_name = f'[:longname][:onclick {row.longname}]{formatted_longname}[/][/]'
141
169
  if vd.options.debug and match:
142
170
  keystrokes = f'[{match.score}]'
143
171
  r = f' [:keystrokes]{keystrokes.rjust(len(prompt)-5)}[/] '
144
- r += f'[:keystrokes]{trigger_key}[/] {formatted_name}'
172
+ if trigger_key:
173
+ r += f'[:keystrokes]{trigger_key}[/]'
174
+ else:
175
+ r += ' '
176
+
177
+ r += f' {formatted_name}'
145
178
  if row.description:
146
179
  formatted_desc = match.formatted.get('description', row.description) if match else row.description
147
180
  r += f' - {formatted_desc}'
@@ -150,6 +183,7 @@ def inputLongname(sheet):
150
183
  return sheet.inputPalette(prompt, this_sheets_help.cmdlist,
151
184
  value_key='longname',
152
185
  formatter=_fmt_cmdpal_summary,
186
+ help=vd.help_longname,
153
187
  type='longname')
154
188
 
155
189
 
@@ -100,6 +100,8 @@ vd.addMenuItems('''
100
100
 
101
101
  ## tests
102
102
 
103
+ sample_path = vd.pkg_resources_files(visidata) / 'tests/sample.tsv'
104
+ benchmark_path = vd.pkg_resources_files(visidata) / 'tests/benchmark.csv'
103
105
 
104
106
  def make_tester(setup_vdx):
105
107
  def t(vdx, golden):
@@ -114,8 +116,8 @@ def make_tester(setup_vdx):
114
116
  return t
115
117
 
116
118
  def test_slide_keycol_1(vd):
117
- t = make_tester('''
118
- open-file sample_data/sample.tsv
119
+ t = make_tester(f'''
120
+ open-file {sample_path}
119
121
  +::OrderDate key-col
120
122
  +::Region key-col
121
123
  +::Rep key-col
@@ -139,12 +141,12 @@ def test_slide_keycol_1(vd):
139
141
 
140
142
 
141
143
  def test_slide_leftmost(vd):
142
- t = make_tester('''open-file sample_data/benchmark.csv''')
144
+ t = make_tester(f'''open-file {benchmark_path}''')
143
145
 
144
146
  t('+::Paid slide-leftmost', 'Paid Date Customer SKU Item Quantity Unit')
145
147
 
146
- t = make_tester('''
147
- open-file sample_data/benchmark.csv
148
+ t = make_tester(f'''
149
+ open-file {benchmark_path}
148
150
  +::Date key-col
149
151
  ''')
150
152
 
@@ -18,6 +18,7 @@ CommandsSheet ("How to find the command you want run")
18
18
 
19
19
  # real barebones basics
20
20
  MovementGuide ("Movement and Search")
21
+ InputGuide ("Input keystrokes")
21
22
  SortGuide ("Sorting")
22
23
  TypesSheet ("The basic type system")
23
24
  CommandLog ("Undo and Replay")
@@ -116,6 +117,9 @@ class CommandHelpGetter:
116
117
  self.helpsheet.ensureLoaded()
117
118
 
118
119
  def __getattr__(self, k):
120
+ return self.__getitem__(k)
121
+
122
+ def __getitem__(self, k):
119
123
  longname = k.replace('_', '-')
120
124
  binding = self.helpsheet.revbinds.get(longname, [None])[0]
121
125
  # cmddict has a SheetClass associated with each command
@@ -173,6 +177,22 @@ def getGuide(vd, name): # -> GuideSheet()
173
177
 
174
178
  BaseSheet.addCommand('', 'open-guide-index', 'vd.push(GuideIndex("VisiData_Guide"))', 'open VisiData guides table of contents')
175
179
 
180
+ @VisiData.api
181
+ def inputKeys(vd, prompt):
182
+ return vd.input(prompt, help=f'''
183
+ # Input Keystrokes
184
+ - Press `Ctrl+N` and then press another keystroke to spell out that keystroke.
185
+ - Press `Ctrl+C` to cancel the input.
186
+ - Press `Enter` to accept the input.
187
+ ''')
188
+
189
+ @BaseSheet.api
190
+ def getCommandInfo(sheet, keys):
191
+ cmd = sheet.getCommand(keys)
192
+ return CommandHelpGetter(type(sheet))[cmd.longname]
193
+
194
+ vd.addCommand('', 'show-command-info', 'status(getCommandInfo(inputKeys("get command for keystrokes: ")))', 'show longname and helpstring for keybinding')
195
+
176
196
  vd.addMenuItems('''
177
197
  Help > VisiData Feature Guides > open-guide-index
178
198
  ''')
@@ -48,6 +48,9 @@ visidata.vd.prettykeys_trdict = {
48
48
  'KEY_SNEXT': 'Shift+PgDn',
49
49
 
50
50
  'KEY_BACKSPACE': 'Bksp',
51
+ 'BUTTON1_RELEASED': 'LeftBtnUp',
52
+ 'BUTTON2_RELEASED': 'MiddleBtnUp',
53
+ 'BUTTON3_RELEASED': 'RightBtnUp',
51
54
  'BUTTON1_PRESSED': 'LeftClick',
52
55
  'BUTTON2_PRESSED': 'MiddleClick',
53
56
  'BUTTON3_PRESSED': 'RightClick',
@@ -1,12 +1,12 @@
1
1
  '''# RedditSheet
2
2
 
3
- - [:keys]Ctrl+O[/] to open a browser tab to [:code]{sheet.cursorRow.display_name_prefixed}[/]
4
- - [:keys]g Ctrl+O[/] to open browser windows for {sheet.nSelectedRows} selected subreddits
3
+ - [:keystrokes]Ctrl+O[/] to open a browser tab to [:code]{sheet.cursorRow.display_name_prefixed}[/]
4
+ - [:keystrokes]g Ctrl+O[/] to open browser windows for {sheet.nSelectedRows} selected subreddits
5
5
 
6
- - [:keys]Enter[/] to open sheet with top ~1000 submissions for [:code]{sheet.cursorRow.display_name_prefixed}[/]
7
- - [:keys]g Enter[/] to open sheet with top ~1000 submissions for {sheet.nSelectedRows} selected subreddits
6
+ - [:keystrokes]Enter[/] to open sheet with top ~1000 submissions for [:code]{sheet.cursorRow.display_name_prefixed}[/]
7
+ - [:keystrokes]g Enter[/] to open sheet with top ~1000 submissions for {sheet.nSelectedRows} selected subreddits
8
8
 
9
- - [:keys]ga[/] to append more subreddits matching input by name or description
9
+ - [:keystrokes]ga[/] to append more subreddits matching input by name or description
10
10
  '''
11
11
 
12
12
  import visidata
@@ -77,7 +77,7 @@ class HtmlLinksSheet(Sheet):
77
77
  lxml = vd.importExternal('lxml')
78
78
  from lxml.html import iterlinks
79
79
  root = self.source.getroot()
80
- root.make_links_absolute(self.source.docinfo.URL)
80
+ root.make_links_absolute(self.source.docinfo.URL, handle_failures='ignore')
81
81
  yield from iterlinks(root)
82
82
 
83
83
  def openRow(self, row):
@@ -131,7 +131,11 @@ class HtmlTableSheet(Sheet):
131
131
  if isinstance(cell, lxml.etree.CommentBase):
132
132
  continue
133
133
  cellval = ' '.join(x.strip() for x in cell.itertext()) # text only without markup
134
- links = [urllib.parse.urljoin(self.source.base_url, x.get('href')) for x in cell.iter('a')]
134
+ links = [
135
+ vd.callNoExceptions(urllib.parse.urljoin, self.source.base_url, x.get('href')) or x.get('href')
136
+ for x in cell.iter('a')
137
+ ]
138
+
135
139
  maxlinks[colnum] = max(maxlinks.get(colnum, 0), len(links))
136
140
 
137
141
  if is_header(cell):
@@ -2,7 +2,7 @@
2
2
  # Usage: $0 [<options>] [<input> ...]
3
3
  # $0 [<options>] --play <cmdlog> [--batch] [-w <waitsecs>] [-o <output>] [field=value ...]
4
4
 
5
- __version__ = '3.0'
5
+ __version__ = '3.0.1'
6
6
  __version_info__ = 'saul.pw/VisiData v' + __version__
7
7
 
8
8
  from copy import copy
@@ -1,4 +1,4 @@
1
- .Dd December 29, 2023
1
+ .Dd January 7, 2024
2
2
  .Dt vd \&1 "Quick Reference Guide"
3
3
  .Os Linux/MacOS
4
4
  .
@@ -101,7 +101,7 @@ toggle sidebar
101
101
  .No redo the most recent undo ( requires enabled Sy options.undo Ns )
102
102
  .Pp
103
103
  .It Ic "Space" Ar longname
104
- .No open command palette; execute command by its Ar longname
104
+ .No open command palette; Sy Enter No to execute top command by its Ar longname
105
105
  .El
106
106
  .Ss " Command Palette"
107
107
  .Bl -tag -width XXXXXXXXXXXXXXX -compact -offset XXX
@@ -1056,7 +1056,7 @@ device ID associated with matrix login
1056
1056
  client_id for reddit api
1057
1057
  .It Sy --reddit-client-secret Ns = Ns Ar "str " No ""
1058
1058
  client_secret for reddit api
1059
- .It Sy --reddit-user-agent Ns = Ns Ar "str " No "3.0"
1059
+ .It Sy --reddit-user-agent Ns = Ns Ar "str " No "3.0.1"
1060
1060
  user_agent for reddit api
1061
1061
  .It Sy --zulip-batch-size Ns = Ns Ar "int " No "-100"
1062
1062
  number of messages to fetch per call (<0 to fetch before anchor)
@@ -1280,7 +1280,7 @@ color of code sample
1280
1280
  color of header
1281
1281
  .It Sy "color_guide_unwritten" No "243 on black"
1282
1282
  color of unwritten guides in GuideGuide
1283
- .It Sy "disp_rstatus_fmt " No "{sheet.threadStatus} {sheet.keystrokeStatus} {sheet.longname} {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus}"
1283
+ .It Sy "disp_rstatus_fmt " No "{sheet.threadStatus} {sheet.keystrokeStatus} [:longname]{sheet.longname}[/] {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus}"
1284
1284
  right-side status format string
1285
1285
  .It Sy "disp_status_fmt " No "[:onclick sheets-stack]{sheet.shortcut}\[u203A] {sheet.name}[/]| "
1286
1286
  status line prefix
@@ -1289,7 +1289,9 @@ maximum length of left status line
1289
1289
  .It Sy "disp_status_sep " No "\[u2502]"
1290
1290
  separator between statuses
1291
1291
  .It Sy "color_keystrokes " No "bold white on 237"
1292
- color of input keystrokes on status line
1292
+ color of input keystrokes
1293
+ .It Sy "color_longname " No "bold 52 on 114 green"
1294
+ color of command longnames
1293
1295
  .It Sy "color_keys " No "bold"
1294
1296
  color of keystrokes in help
1295
1297
  .It Sy "color_status " No "bold on 238"
@@ -1394,8 +1396,6 @@ max number of suggestions for command palette
1394
1396
 
1395
1397
  .It Sy "color_colname " No "underline"
1396
1398
 
1397
- .It Sy "color_longname " No "bold 52 on 114 green"
1398
-
1399
1399
  .It Sy "disp_scroll_context" No "0"
1400
1400
  minimum number of lines to keep visible above/below cursor when scrolling
1401
1401
  .It Sy "disp_sparkline " No "\[u2581]\[u2582]\[u2583]\[u2584]\[u2585]\[u2586]\[u2587]"
@@ -53,7 +53,8 @@ DESCRIPTION
53
53
  R redo the most recent undo (requires enabled
54
54
  options.undo)
55
55
 
56
- Space longname open command palette; execute command by its longname
56
+ Space longname open command palette; Enter to execute top command by
57
+ its longname
57
58
 
58
59
  Command Palette
59
60
  Tab Move to command palette, and cycle through commands
@@ -743,7 +744,7 @@ COMMANDLINE OPTIONS
743
744
  --reddit-client-id=str client_id for reddit api
744
745
  --reddit-client-secret=str client_secret for reddit
745
746
  api
746
- --reddit-user-agent=str 3.0 user_agent for reddit api
747
+ --reddit-user-agent=str 3.0.1 user_agent for reddit api
747
748
  --zulip-batch-size=int -100 number of messages to
748
749
  fetch per call (<0 to
749
750
  fetch before anchor)
@@ -962,7 +963,7 @@ COMMANDLINE OPTIONS
962
963
  color_guide_unwritten 243 on black color of unwritten guides in
963
964
  GuideGuide
964
965
  disp_rstatus_fmt {sheet.threadStatus} {sheet.keystrokeStatus}
965
- {sheet.longname}
966
+ [:longname]{sheet.longname}[/]
966
967
  {sheet.nRows:9d} {sheet.rowtype}
967
968
  {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus}
968
969
  right-side status format string
@@ -972,8 +973,9 @@ COMMANDLINE OPTIONS
972
973
  disp_lstatus_max 0 maximum length of left status
973
974
  line
974
975
  disp_status_sep │ separator between statuses
975
- color_keystrokes bold white on 237 color of input keystrokes on sta‐
976
- tus line
976
+ color_keystrokes bold white on 237 color of input keystrokes
977
+ color_longname bold 52 on 114 green
978
+ color of command longnames
977
979
  color_keys bold color of keystrokes in help
978
980
  color_status bold on 238 status line color
979
981
  color_error 202 1 error message color
@@ -1045,8 +1047,6 @@ COMMANDLINE OPTIONS
1045
1047
  command palette
1046
1048
  color_shellcmd 21 on 114 green
1047
1049
  color_colname underline
1048
- color_longname bold 52 on 114 green
1049
-
1050
1050
  disp_scroll_context 0 minimum number of lines to keep
1051
1051
  visible above/below cursor when
1052
1052
  scrolling
@@ -1157,4 +1157,4 @@ SUPPORTED SOURCES
1157
1157
  AUTHOR
1158
1158
  VisiData was made by Saul Pwanson <vd@saul.pw>.
1159
1159
 
1160
- Linux/MacOS December 29, 2023 Linux/MacOS
1160
+ Linux/MacOS January 7, 2024 Linux/MacOS
@@ -1,4 +1,4 @@
1
- .Dd December 29, 2023
1
+ .Dd January 7, 2024
2
2
  .Dt vd \&1 "Quick Reference Guide"
3
3
  .Os Linux/MacOS
4
4
  .
@@ -101,7 +101,7 @@ toggle sidebar
101
101
  .No redo the most recent undo ( requires enabled Sy options.undo Ns )
102
102
  .Pp
103
103
  .It Ic "Space" Ar longname
104
- .No open command palette; execute command by its Ar longname
104
+ .No open command palette; Sy Enter No to execute top command by its Ar longname
105
105
  .El
106
106
  .Ss " Command Palette"
107
107
  .Bl -tag -width XXXXXXXXXXXXXXX -compact -offset XXX
@@ -1056,7 +1056,7 @@ device ID associated with matrix login
1056
1056
  client_id for reddit api
1057
1057
  .It Sy --reddit-client-secret Ns = Ns Ar "str " No ""
1058
1058
  client_secret for reddit api
1059
- .It Sy --reddit-user-agent Ns = Ns Ar "str " No "3.0"
1059
+ .It Sy --reddit-user-agent Ns = Ns Ar "str " No "3.0.1"
1060
1060
  user_agent for reddit api
1061
1061
  .It Sy --zulip-batch-size Ns = Ns Ar "int " No "-100"
1062
1062
  number of messages to fetch per call (<0 to fetch before anchor)
@@ -1280,7 +1280,7 @@ color of code sample
1280
1280
  color of header
1281
1281
  .It Sy "color_guide_unwritten" No "243 on black"
1282
1282
  color of unwritten guides in GuideGuide
1283
- .It Sy "disp_rstatus_fmt " No "{sheet.threadStatus} {sheet.keystrokeStatus} {sheet.longname} {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus}"
1283
+ .It Sy "disp_rstatus_fmt " No "{sheet.threadStatus} {sheet.keystrokeStatus} [:longname]{sheet.longname}[/] {sheet.nRows:9d} {sheet.rowtype} {sheet.modifiedStatus}{sheet.selectedStatus}{vd.replayStatus}"
1284
1284
  right-side status format string
1285
1285
  .It Sy "disp_status_fmt " No "[:onclick sheets-stack]{sheet.shortcut}\[u203A] {sheet.name}[/]| "
1286
1286
  status line prefix
@@ -1289,7 +1289,9 @@ maximum length of left status line
1289
1289
  .It Sy "disp_status_sep " No "\[u2502]"
1290
1290
  separator between statuses
1291
1291
  .It Sy "color_keystrokes " No "bold white on 237"
1292
- color of input keystrokes on status line
1292
+ color of input keystrokes
1293
+ .It Sy "color_longname " No "bold 52 on 114 green"
1294
+ color of command longnames
1293
1295
  .It Sy "color_keys " No "bold"
1294
1296
  color of keystrokes in help
1295
1297
  .It Sy "color_status " No "bold on 238"
@@ -1394,8 +1396,6 @@ max number of suggestions for command palette
1394
1396
 
1395
1397
  .It Sy "color_colname " No "underline"
1396
1398
 
1397
- .It Sy "color_longname " No "bold 52 on 114 green"
1398
-
1399
1399
  .It Sy "disp_scroll_context" No "0"
1400
1400
  minimum number of lines to keep visible above/below cursor when scrolling
1401
1401
  .It Sy "disp_sparkline " No "\[u2581]\[u2582]\[u2583]\[u2584]\[u2585]\[u2586]\[u2587]"
@@ -229,19 +229,20 @@ def openCellPyobj(sheet, col, rowidx):
229
229
 
230
230
 
231
231
  @BaseSheet.api
232
- def pyobj_expr(sheet):
232
+ def inputPythonExpr(sheet):
233
233
  def launch_repl(v, i):
234
234
  import code
235
235
  with SuspendCurses():
236
236
  code.InteractiveConsole(locals=locals()).interact()
237
237
  return v, i
238
- expr = vd.input("eval: ", "expr", completer=visidata.CompleteExpr(), bindings={'^X': launch_repl})
239
- vd.push(PyobjSheet(expr, source=sheet.evalExpr(expr)))
238
+ return vd.input("eval: ", "expr", completer=visidata.CompleteExpr(), bindings={'^X': launch_repl})
240
239
 
241
- BaseSheet.addCommand('^X', 'pyobj-expr', 'pyobj_expr()', 'evaluate Python expression and open result as Python object')
240
+ BaseSheet.addCommand('^X', 'pyobj-expr', 'expr=inputPythonExpr(); vd.push(PyobjSheet(expr, source=sheet.evalExpr(expr)))', 'evaluate Python expression and open result as Python object')
242
241
  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')
243
242
  BaseSheet.addCommand('g^X', 'import-python', 'modname=input("import: ", type="import_python"); exec("import "+modname, getGlobals())', 'import Python module in the global scope')
244
243
  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')
244
+ BaseSheet.addCommand('', 'assert-expr', 'expr=inputPythonExpr(); assert sheet.evalExpr(expr), f"{expr} not true"', 'eval Python expression and assert result is truthy')
245
+ 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')
245
246
 
246
247
  Sheet.addCommand('^Y', 'pyobj-row', 'status(type(cursorRow).__name__); vd.push(openRowPyobj(cursorRowIndex))', 'open current row as Python object')
247
248
  Sheet.addCommand('z^Y', 'pyobj-cell', 'status(type(cursorValue).__name__); vd.push(openCellPyobj(cursorCol, cursorRowIndex))', 'open current cell as Python object')
@@ -65,8 +65,15 @@ class LazyComputeRow:
65
65
  lcmobj._lcm = LazyChainMap(self.sheet, self.col, *vd.contexts)
66
66
  return lcmobj._lcm
67
67
 
68
+ def __iter__(self):
69
+ yield from self.sheet._ordered_colnames
70
+ yield from self._lcm.keys()
71
+ yield 'row'
72
+ yield 'sheet'
73
+ yield 'col'
74
+
68
75
  def keys(self):
69
- return self.sheet._ordered_colnames + self._lcm.keys() + ['row', 'sheet', 'col']
76
+ return list(self.__iter__())
70
77
 
71
78
  def __str__(self):
72
79
  return str(self.as_dict())
@@ -165,6 +172,8 @@ class TableSheet(BaseSheet):
165
172
  self._colorizers = self.classColorizers
166
173
  self.recalc() # set .sheet on columns and start caches
167
174
 
175
+ self._ordering = [] # list of (col:Column, reverse:bool)
176
+
168
177
  self.__dict__.update(kwargs) # also done earlier in BaseSheet.__init__
169
178
 
170
179
  @property
@@ -363,7 +372,7 @@ class TableSheet(BaseSheet):
363
372
  # contexts are cached by sheet/rowid for duration of drawcycle
364
373
  contexts = vd._evalcontexts.setdefault((self, self.rowid(row), col), LazyComputeRow(self, row, col=col))
365
374
  else:
366
- contexts = None
375
+ contexts = dict(sheet=self)
367
376
 
368
377
  return eval(expr, vd.getGlobals(), contexts)
369
378
 
@@ -864,7 +873,7 @@ class TableSheet(BaseSheet):
864
873
  for i, chunks in enumerate(lines):
865
874
  y = ybase+i
866
875
 
867
- if vcolidx == self.rightVisibleColIndex: # right edge of sheet
876
+ if vcolidx == self.nVisibleCols-1: # right edge of sheet
868
877
  if len(lines) == 1:
869
878
  sepchars = endsep
870
879
  else:
@@ -1105,8 +1114,6 @@ def async_deepcopy(sheet, rowlist):
1105
1114
 
1106
1115
  BaseSheet.init('pane', lambda: 1)
1107
1116
 
1108
- Sheet.init('_ordering', list, copy=False) # (col:Column, reverse:bool)
1109
-
1110
1117
 
1111
1118
  BaseSheet.addCommand('^R', 'reload-sheet', 'preloadHook(); reload()', 'Reload current sheet')
1112
1119
  Sheet.addCommand('^G', 'show-cursor', 'status(statusLine)', 'show cursor position and bounds of current sheet on status line')
@@ -11,12 +11,13 @@ import visidata
11
11
  from visidata import vd, VisiData, BaseSheet, Sheet, ColumnItem, Column, RowColorizer, options, colors, wrmap, clipdraw, ExpectedException, update_attr, dispwidth, ColorAttr
12
12
 
13
13
 
14
- 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')
14
+ 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')
15
15
  vd.option('disp_status_fmt', '[:onclick sheets-stack]{sheet.shortcut}› {sheet.name}[/]| ', 'status line prefix')
16
16
  vd.theme_option('disp_lstatus_max', 0, 'maximum length of left status line')
17
17
  vd.theme_option('disp_status_sep', '│', 'separator between statuses')
18
18
 
19
- vd.theme_option('color_keystrokes', 'bold white on 237', 'color of input keystrokes on status line')
19
+ vd.theme_option('color_keystrokes', 'bold white on 237', 'color of input keystrokes')
20
+ vd.theme_option('color_longname', '6', 'color of command longnames')
20
21
  vd.theme_option('color_keys', 'bold', 'color of keystrokes in help')
21
22
  vd.theme_option('color_status', 'bold on 238', 'status line color')
22
23
  vd.theme_option('color_error', '202 1', 'error message color')