visidata 2.11.dev0__py3-none-any.whl → 3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. visidata/__init__.py +72 -91
  2. visidata/_input.py +263 -44
  3. visidata/_open.py +84 -29
  4. visidata/_types.py +22 -4
  5. visidata/_urlcache.py +17 -4
  6. visidata/aggregators.py +65 -25
  7. visidata/apps/__init__.py +0 -0
  8. visidata/apps/vdsql/__about__.py +8 -0
  9. visidata/apps/vdsql/__init__.py +5 -0
  10. visidata/apps/vdsql/__main__.py +27 -0
  11. visidata/apps/vdsql/_ibis.py +748 -0
  12. visidata/apps/vdsql/bigquery.py +61 -0
  13. visidata/apps/vdsql/clickhouse.py +53 -0
  14. visidata/apps/vdsql/setup.py +40 -0
  15. visidata/apps/vdsql/snowflake.py +67 -0
  16. visidata/apps/vgit/__init__.py +13 -0
  17. visidata/apps/vgit/__main__.py +3 -0
  18. visidata/apps/vgit/abort.py +23 -0
  19. visidata/apps/vgit/blame.py +76 -0
  20. visidata/apps/vgit/branch.py +153 -0
  21. visidata/apps/vgit/config.py +95 -0
  22. visidata/apps/vgit/diff.py +169 -0
  23. visidata/apps/vgit/gitsheet.py +161 -0
  24. visidata/apps/vgit/grep.py +37 -0
  25. visidata/apps/vgit/log.py +81 -0
  26. visidata/apps/vgit/main.py +55 -0
  27. visidata/apps/vgit/remote.py +57 -0
  28. visidata/apps/vgit/repos.py +71 -0
  29. visidata/apps/vgit/setup.py +37 -0
  30. visidata/apps/vgit/stash.py +69 -0
  31. visidata/apps/vgit/status.py +204 -0
  32. visidata/apps/vgit/statusbar.py +34 -0
  33. visidata/basesheet.py +59 -50
  34. visidata/canvas.py +251 -99
  35. visidata/choose.py +15 -11
  36. visidata/clean_names.py +29 -0
  37. visidata/clipboard.py +84 -18
  38. visidata/cliptext.py +220 -46
  39. visidata/cmdlog.py +89 -114
  40. visidata/color.py +142 -56
  41. visidata/column.py +134 -131
  42. visidata/ddw/input.ddw +74 -79
  43. visidata/ddw/regex.ddw +57 -0
  44. visidata/ddwplay.py +33 -14
  45. visidata/deprecated.py +77 -3
  46. visidata/desktop/visidata.desktop +7 -0
  47. visidata/editor.py +12 -6
  48. visidata/errors.py +5 -1
  49. visidata/experimental/__init__.py +0 -0
  50. visidata/experimental/diff_sheet.py +29 -0
  51. visidata/experimental/digit_autoedit.py +6 -0
  52. visidata/experimental/gdrive.py +89 -0
  53. visidata/experimental/google.py +37 -0
  54. visidata/experimental/gsheets.py +79 -0
  55. visidata/experimental/live_search.py +37 -0
  56. visidata/experimental/liveupdate.py +45 -0
  57. visidata/experimental/mark.py +133 -0
  58. visidata/experimental/noahs_tapestry/__init__.py +1 -0
  59. visidata/experimental/noahs_tapestry/tapestry.py +147 -0
  60. visidata/experimental/rownum.py +73 -0
  61. visidata/experimental/slide_cells.py +26 -0
  62. visidata/expr.py +8 -4
  63. visidata/extensible.py +32 -6
  64. visidata/features/__init__.py +0 -0
  65. visidata/features/addcol_audiometadata.py +42 -0
  66. visidata/features/addcol_histogram.py +34 -0
  67. visidata/features/canvas_save_svg.py +69 -0
  68. visidata/features/change_precision.py +46 -0
  69. visidata/features/cmdpalette.py +163 -0
  70. visidata/features/colorbrewer.py +363 -0
  71. visidata/{colorsheet.py → features/colorsheet.py} +17 -16
  72. visidata/features/command_server.py +105 -0
  73. visidata/features/currency_to_usd.py +70 -0
  74. visidata/{customdate.py → features/customdate.py} +2 -0
  75. visidata/features/dedupe.py +132 -0
  76. visidata/{describe.py → features/describe.py} +17 -15
  77. visidata/features/errors_guide.py +26 -0
  78. visidata/features/expand_cols.py +202 -0
  79. visidata/{fill.py → features/fill.py} +4 -2
  80. visidata/{freeze.py → features/freeze.py} +11 -6
  81. visidata/features/graph_seaborn.py +79 -0
  82. visidata/features/helloworld.py +10 -0
  83. visidata/features/hint_types.py +17 -0
  84. visidata/{incr.py → features/incr.py} +5 -0
  85. visidata/{join.py → features/join.py} +107 -53
  86. visidata/features/known_cols.py +21 -0
  87. visidata/features/layout.py +62 -0
  88. visidata/{melt.py → features/melt.py} +33 -21
  89. visidata/features/normcol.py +118 -0
  90. visidata/features/open_config.py +7 -0
  91. visidata/features/open_syspaste.py +18 -0
  92. visidata/features/ping.py +157 -0
  93. visidata/features/procmgr.py +208 -0
  94. visidata/features/random_sample.py +6 -0
  95. visidata/{regex.py → features/regex.py} +47 -31
  96. visidata/features/reload_every.py +55 -0
  97. visidata/features/rename_col_cascade.py +30 -0
  98. visidata/features/scroll_context.py +60 -0
  99. visidata/features/select_equal_selected.py +11 -0
  100. visidata/features/setcol_fake.py +65 -0
  101. visidata/{slide.py → features/slide.py} +75 -21
  102. visidata/features/sparkline.py +48 -0
  103. visidata/features/status_source.py +20 -0
  104. visidata/{sysedit.py → features/sysedit.py} +2 -1
  105. visidata/features/sysopen_mailcap.py +46 -0
  106. visidata/features/term_extras.py +13 -0
  107. visidata/{transpose.py → features/transpose.py} +5 -4
  108. visidata/features/type_ipaddr.py +73 -0
  109. visidata/features/type_url.py +11 -0
  110. visidata/{unfurl.py → features/unfurl.py} +9 -9
  111. visidata/{window.py → features/window.py} +2 -2
  112. visidata/form.py +50 -21
  113. visidata/freqtbl.py +81 -33
  114. visidata/fuzzymatch.py +414 -0
  115. visidata/graph.py +105 -33
  116. visidata/guide.py +180 -0
  117. visidata/help.py +75 -44
  118. visidata/hint.py +39 -0
  119. visidata/indexsheet.py +109 -0
  120. visidata/input_history.py +55 -0
  121. visidata/interface.py +58 -0
  122. visidata/keys.py +17 -16
  123. visidata/loaders/__init__.py +9 -0
  124. visidata/loaders/_pandas.py +61 -21
  125. visidata/loaders/api_airtable.py +70 -0
  126. visidata/loaders/api_bitio.py +102 -0
  127. visidata/loaders/api_matrix.py +148 -0
  128. visidata/loaders/api_reddit.py +306 -0
  129. visidata/loaders/api_zulip.py +249 -0
  130. visidata/loaders/archive.py +41 -7
  131. visidata/loaders/arrow.py +7 -7
  132. visidata/loaders/conll.py +49 -0
  133. visidata/loaders/csv.py +25 -7
  134. visidata/loaders/eml.py +3 -4
  135. visidata/loaders/f5log.py +1204 -0
  136. visidata/loaders/fec.py +325 -0
  137. visidata/loaders/fixed_width.py +3 -5
  138. visidata/loaders/frictionless.py +3 -3
  139. visidata/loaders/geojson.py +8 -5
  140. visidata/loaders/google.py +48 -0
  141. visidata/loaders/graphviz.py +4 -4
  142. visidata/loaders/hdf5.py +4 -4
  143. visidata/loaders/html.py +48 -10
  144. visidata/loaders/http.py +84 -30
  145. visidata/loaders/imap.py +20 -10
  146. visidata/loaders/jrnl.py +52 -0
  147. visidata/loaders/json.py +83 -29
  148. visidata/loaders/jsonla.py +74 -0
  149. visidata/loaders/lsv.py +15 -11
  150. visidata/loaders/mailbox.py +40 -0
  151. visidata/loaders/markdown.py +1 -3
  152. visidata/loaders/mbtiles.py +4 -5
  153. visidata/loaders/mysql.py +11 -13
  154. visidata/loaders/npy.py +7 -7
  155. visidata/loaders/odf.py +4 -1
  156. visidata/loaders/orgmode.py +428 -0
  157. visidata/loaders/pandas_freqtbl.py +14 -20
  158. visidata/loaders/parquet.py +62 -6
  159. visidata/loaders/pcap.py +3 -3
  160. visidata/loaders/pdf.py +4 -3
  161. visidata/loaders/png.py +19 -13
  162. visidata/loaders/postgres.py +9 -8
  163. visidata/loaders/rec.py +7 -3
  164. visidata/loaders/s3.py +342 -0
  165. visidata/loaders/sas.py +5 -5
  166. visidata/loaders/scrape.py +186 -0
  167. visidata/loaders/shp.py +6 -5
  168. visidata/loaders/spss.py +5 -6
  169. visidata/loaders/sqlite.py +68 -28
  170. visidata/loaders/texttables.py +1 -1
  171. visidata/loaders/toml.py +60 -0
  172. visidata/loaders/tsv.py +61 -19
  173. visidata/loaders/ttf.py +19 -7
  174. visidata/loaders/unzip_http.py +6 -5
  175. visidata/loaders/usv.py +1 -1
  176. visidata/loaders/vcf.py +16 -16
  177. visidata/loaders/vds.py +10 -7
  178. visidata/loaders/vdx.py +30 -5
  179. visidata/loaders/xlsb.py +8 -1
  180. visidata/loaders/xlsx.py +145 -25
  181. visidata/loaders/xml.py +6 -3
  182. visidata/loaders/xword.py +4 -4
  183. visidata/loaders/yaml.py +15 -5
  184. visidata/macos.py +1 -1
  185. visidata/macros.py +130 -41
  186. visidata/main.py +119 -94
  187. visidata/mainloop.py +101 -154
  188. visidata/man/parse_options.py +2 -2
  189. visidata/man/vd.1 +302 -147
  190. visidata/man/vd.txt +291 -151
  191. visidata/memory.py +3 -3
  192. visidata/menu.py +104 -423
  193. visidata/metasheets.py +59 -141
  194. visidata/modify.py +79 -23
  195. visidata/motd.py +3 -3
  196. visidata/mouse.py +137 -0
  197. visidata/movement.py +43 -35
  198. visidata/optionssheet.py +99 -0
  199. visidata/path.py +131 -43
  200. visidata/pivot.py +74 -47
  201. visidata/plugins.py +65 -192
  202. visidata/pyobj.py +50 -201
  203. visidata/rename_col.py +20 -0
  204. visidata/save.py +42 -20
  205. visidata/search.py +54 -10
  206. visidata/selection.py +84 -5
  207. visidata/settings.py +162 -24
  208. visidata/sheets.py +229 -257
  209. visidata/shell.py +51 -21
  210. visidata/sidebar.py +162 -0
  211. visidata/sort.py +11 -4
  212. visidata/statusbar.py +113 -104
  213. visidata/stored_list.py +43 -0
  214. visidata/stored_prop.py +38 -0
  215. visidata/tests/conftest.py +3 -3
  216. visidata/tests/test_cliptext.py +39 -0
  217. visidata/tests/test_commands.py +62 -7
  218. visidata/tests/test_edittext.py +2 -2
  219. visidata/tests/test_features.py +17 -0
  220. visidata/tests/test_menu.py +14 -0
  221. visidata/tests/test_path.py +13 -4
  222. visidata/text_source.py +53 -0
  223. visidata/textsheet.py +10 -3
  224. visidata/theme.py +44 -0
  225. visidata/themes/__init__.py +0 -0
  226. visidata/themes/ascii8.py +84 -0
  227. visidata/themes/asciimono.py +84 -0
  228. visidata/themes/light.py +17 -0
  229. visidata/threads.py +87 -39
  230. visidata/tuiwin.py +22 -0
  231. visidata/type_currency.py +22 -3
  232. visidata/type_date.py +31 -9
  233. visidata/type_floatsi.py +5 -1
  234. visidata/undo.py +18 -6
  235. visidata/utils.py +106 -23
  236. visidata/vdobj.py +28 -17
  237. visidata/windows.py +10 -0
  238. visidata/wrappers.py +9 -3
  239. visidata-3.0.data/data/share/applications/visidata.desktop +7 -0
  240. {visidata-2.11.dev0.data → visidata-3.0.data}/data/share/man/man1/vd.1 +302 -147
  241. {visidata-2.11.dev0.data → visidata-3.0.data}/data/share/man/man1/visidata.1 +302 -147
  242. visidata-3.0.data/scripts/vd2to3.vdx +9 -0
  243. {visidata-2.11.dev0.dist-info → visidata-3.0.dist-info}/METADATA +13 -11
  244. visidata-3.0.dist-info/RECORD +257 -0
  245. {visidata-2.11.dev0.dist-info → visidata-3.0.dist-info}/WHEEL +1 -1
  246. {visidata-2.11.dev0.dist-info → visidata-3.0.dist-info}/entry_points.txt +0 -1
  247. visidata/layout.py +0 -44
  248. visidata/misc.py +0 -5
  249. visidata-2.11.dev0.dist-info/RECORD +0 -142
  250. /visidata/{repeat.py → features/repeat.py} +0 -0
  251. {visidata-2.11.dev0.data → visidata-3.0.data}/scripts/vd +0 -0
  252. {visidata-2.11.dev0.dist-info → visidata-3.0.dist-info}/LICENSE.gpl3 +0 -0
  253. {visidata-2.11.dev0.dist-info → visidata-3.0.dist-info}/top_level.txt +0 -0
visidata/ddw/input.ddw CHANGED
@@ -1,79 +1,67 @@
1
- {"x": 1, "y": 7, "text": "Ctrl+A or Ctrl+E", "color": "black on black", "tags": [], "group": "", "frame": "advanced"}
2
- {"x": 0, "y": 6, "text": "Ctrl+B or Ctrl+F", "color": "black on black", "tags": [], "group": "", "frame": "advanced"}
3
- {"x": 0, "y": 6, "text": "\u2190", "color": "bold white on 237", "tags": [], "group": ""}
4
- {"x": 11, "y": 6, "text": "go to prev char", "color": "", "tags": [], "group": ""}
5
- {"x": 0, "y": 4, "text": "Ctrl", "color": "bold white on 237", "tags": [], "group": ""}
6
- {"x": 9, "y": 4, "text": "cancel input (abort command)", "color": "", "tags": [], "group": ""}
7
- {"x": 45, "y": 7, "text": "delete one char at cursor", "color": "", "tags": [], "group": ""}
8
- {"x": 45, "y": 8, "text": "delete one char before cursor", "color": "", "tags": [], "group": ""}
9
- {"x": 0, "y": 16, "text": "Shift", "color": "bold white on 237", "tags": [], "group": ""}
10
- {"x": 0, "y": 3, "text": "Enter", "color": "bold white on 237", "tags": [], "group": ""}
11
- {"x": 9, "y": 3, "text": "accept input (continue command)", "color": "", "tags": [], "group": ""}
12
- {"x": 39, "y": 9, "text": "K", "color": "bold white on 237", "tags": [], "group": ""}
13
- {"x": 45, "y": 9, "text": "delete all chars after cursor", "color": "", "tags": [], "group": ""}
14
- {"x": 39, "y": 15, "text": "O", "color": "bold white on 237", "tags": [], "group": ""}
15
- {"x": 45, "y": 15, "text": "open input in external editor", "color": "", "tags": [], "group": ""}
16
- {"x": 39, "y": 16, "text": "R", "color": "bold white on 237", "tags": [], "group": ""}
17
- {"x": 45, "y": 16, "text": "reload default value", "color": "", "tags": [], "group": ""}
18
- {"x": 39, "y": 12, "text": "T", "color": "bold white on 237", "tags": [], "group": ""}
19
- {"x": 45, "y": 12, "text": "swap last two chars", "color": "", "tags": [], "group": ""}
20
- {"x": 39, "y": 10, "text": "U", "color": "bold white on 237", "tags": [], "group": ""}
21
- {"x": 45, "y": 10, "text": "delete all chars before cursor", "color": "", "tags": [], "group": ""}
22
- {"x": 39, "y": 13, "text": "V", "color": "bold white on 237", "tags": [], "group": ""}
23
- {"x": 45, "y": 13, "text": "insert literal char", "color": "", "tags": [], "group": ""}
24
- {"x": 39, "y": 11, "text": "W", "color": "bold white on 237", "tags": [], "group": ""}
25
- {"x": 45, "y": 11, "text": "delete one word before cursor", "color": "", "tags": [], "group": ""}
26
- {"x": 39, "y": 14, "text": "Y", "color": "bold white on 237", "tags": [], "group": ""}
27
- {"x": 45, "y": 14, "text": "insert clipboard text at cursor", "color": "", "tags": [], "group": ""}
28
- {"x": 5, "y": 10, "text": "\u2190", "color": "bold white on 237", "tags": [], "group": ""}
29
- {"x": 11, "y": 10, "text": "go to prev word", "color": "", "tags": [], "group": ""}
30
- {"x": 0, "y": 0, "text": "Start typing to erase the default value.", "color": "", "tags": [], "group": ""}
31
- {"x": 0, "y": 1, "text": "To edit the default value, press a movement key first.", "color": "", "tags": [], "group": ""}
32
- {"x": 0, "y": 13, "text": "\u2191", "color": "bold white on 237", "tags": [], "group": ""}
33
- {"x": 0, "y": 14, "text": "\u2193", "color": "bold white on 237", "tags": [], "group": ""}
34
- {"x": 0, "y": 8, "text": "Home", "color": "bold white on 237", "tags": [], "group": ""}
35
- {"x": 11, "y": 8, "text": "go to start of input", "color": "", "tags": [], "group": ""}
36
- {"x": 0, "y": 9, "text": "End", "color": "bold white on 237", "tags": [], "group": ""}
37
- {"x": 0, "y": 7, "text": "\u2192", "color": "bold white on 237", "tags": [], "group": ""}
38
- {"x": 34, "y": 7, "text": "Delete", "color": "bold white on 237", "tags": [], "group": ""}
39
- {"x": 34, "y": 8, "text": "Backspace", "color": "bold white on 237", "tags": [], "group": ""}
40
- {"x": 0, "y": 9, "text": "Ctrl+D", "color": "", "tags": [], "group": "", "frame": "advanced"}
41
- {"x": 0, "y": 10, "text": "Ctrl+H", "color": "", "tags": [], "group": "", "frame": "advanced"}
42
- {"x": 34, "y": 6, "text": "Insert", "color": "bold white on 237", "tags": [], "group": ""}
43
- {"x": 45, "y": 6, "text": "toggle insert mode", "color": "", "tags": [], "group": ""}
44
- {"x": 0, "y": 15, "text": "Tab", "color": "bold white on 237", "tags": [], "group": ""}
45
- {"x": 0, "y": 10, "text": "Ctrl", "color": "bold white on 237", "tags": [], "group": ""}
46
- {"x": 34, "y": 9, "text": "Ctrl", "color": "bold white on 237", "tags": [], "group": ""}
47
- {"x": 34, "y": 10, "text": "Ctrl", "color": "bold white on 237", "tags": [], "group": ""}
48
- {"x": 34, "y": 12, "text": "Ctrl", "color": "bold white on 237", "tags": [], "group": ""}
49
- {"x": 34, "y": 11, "text": "Ctrl", "color": "bold white on 237", "tags": [], "group": ""}
50
- {"x": 34, "y": 13, "text": "Ctrl", "color": "bold white on 237", "tags": [], "group": ""}
51
- {"x": 34, "y": 14, "text": "Ctrl", "color": "bold white on 237", "tags": [], "group": ""}
52
- {"x": 34, "y": 15, "text": "Ctrl", "color": "bold white on 237", "tags": [], "group": ""}
53
- {"x": 34, "y": 16, "text": "Ctrl", "color": "bold white on 237", "tags": [], "group": ""}
54
- {"x": 4, "y": 10, "text": "+", "color": "", "tags": [], "group": ""}
55
- {"x": 38, "y": 9, "text": "+", "color": "", "tags": [], "group": ""}
56
- {"x": 38, "y": 10, "text": "+", "color": "", "tags": [], "group": ""}
57
- {"x": 38, "y": 11, "text": "+", "color": "", "tags": [], "group": ""}
58
- {"x": 38, "y": 12, "text": "+", "color": "", "tags": [], "group": ""}
59
- {"x": 38, "y": 13, "text": "+", "color": "", "tags": [], "group": ""}
60
- {"x": 38, "y": 14, "text": "+", "color": "", "tags": [], "group": ""}
61
- {"x": 38, "y": 15, "text": "+", "color": "", "tags": [], "group": ""}
62
- {"x": 38, "y": 16, "text": "+", "color": "", "tags": [], "group": ""}
63
- {"x": 0, "y": 11, "text": "Ctrl", "color": "bold white on 237", "tags": [], "group": ""}
64
- {"x": 4, "y": 11, "text": "+", "color": "", "tags": [], "group": ""}
65
- {"x": 5, "y": 11, "text": "\u2192", "color": "bold white on 237", "tags": [], "group": ""}
66
- {"x": 11, "y": 11, "text": "go to next word", "color": "", "tags": [], "group": ""}
67
- {"x": 11, "y": 9, "text": "go to end of input", "color": "", "tags": [], "group": ""}
68
- {"x": 11, "y": 7, "text": "go to next char", "color": "", "tags": [], "group": ""}
69
- {"x": 11, "y": 13, "text": "next input history", "color": "", "tags": [], "group": ""}
70
- {"x": 11, "y": 14, "text": "prev input history", "color": "", "tags": [], "group": ""}
71
- {"x": 11, "y": 15, "text": "next autocomplete", "color": "", "tags": [], "group": ""}
72
- {"x": 11, "y": 16, "text": "prev autocomplete", "color": "", "tags": [], "group": ""}
73
- {"x": 4, "y": 4, "text": "+", "color": "", "tags": [], "group": ""}
74
- {"x": 5, "y": 4, "text": "C", "color": "bold white on 237", "tags": [], "group": ""}
75
- {"x": 5, "y": 16, "text": "+", "color": "", "tags": [], "group": ""}
76
- {"x": 6, "y": 16, "text": "Tab", "color": "bold white on 237", "tags": [], "group": ""}
1
+ {"id": null, "type": null, "x": 6, "y": 7, "text": "\u2190", "color": "keystrokes", "tags": [], "group": "", "frame": null, "rows": null, "duration_ms": null, "ref": null, "onclick": null}
2
+ {"x": 11, "y": 7, "text": "go to prev/next char", "color": "", "tags": [], "group": ""}
3
+ {"x": 3, "y": 4, "text": "Ctrl", "color": "keystrokes", "tags": [], "group": ""}
4
+ {"x": 11, "y": 4, "text": "cancel input (abort)", "color": "", "tags": [], "group": ""}
5
+ {"x": 45, "y": 4, "text": "delete one char at cursor", "color": "", "tags": [], "group": ""}
6
+ {"x": 45, "y": 5, "text": "delete one char before cursor", "color": "", "tags": [], "group": ""}
7
+ {"x": 0, "y": 13, "text": "Shift", "color": "keystrokes", "tags": [], "group": ""}
8
+ {"x": 4, "y": 3, "text": "Enter", "color": "keystrokes", "tags": [], "group": ""}
9
+ {"x": 11, "y": 3, "text": "accept input", "color": "", "tags": [], "group": ""}
10
+ {"x": 42, "y": 6, "text": "K", "color": "keystrokes", "tags": [], "group": ""}
11
+ {"x": 45, "y": 6, "text": "delete all before/after cursor", "color": "", "tags": [], "group": ""}
12
+ {"x": 42, "y": 12, "text": "O", "color": "keystrokes", "tags": [], "group": ""}
13
+ {"x": 45, "y": 12, "text": "open input in external editor", "color": "", "tags": [], "group": ""}
14
+ {"x": 42, "y": 13, "text": "R", "color": "keystrokes", "tags": [], "group": ""}
15
+ {"x": 45, "y": 13, "text": "restore starting value", "color": "", "tags": [], "group": ""}
16
+ {"x": 42, "y": 8, "text": "T", "color": "keystrokes", "tags": [], "group": ""}
17
+ {"x": 45, "y": 8, "text": "swap last two chars", "color": "", "tags": [], "group": ""}
18
+ {"x": 40, "y": 6, "text": "U", "color": "keystrokes", "tags": [], "group": ""}
19
+ {"x": 42, "y": 9, "text": "V", "color": "keystrokes", "tags": [], "group": ""}
20
+ {"x": 45, "y": 9, "text": "insert literal char", "color": "", "tags": [], "group": ""}
21
+ {"x": 42, "y": 7, "text": "W", "color": "keystrokes", "tags": [], "group": ""}
22
+ {"x": 45, "y": 7, "text": "delete one word before cursor", "color": "", "tags": [], "group": ""}
23
+ {"x": 42, "y": 11, "text": "Y", "color": "keystrokes", "tags": [], "group": ""}
24
+ {"x": 45, "y": 11, "text": "insert clipboard text at cursor", "color": "", "tags": [], "group": ""}
25
+ {"x": 6, "y": 8, "text": "\u2190", "color": "keystrokes", "tags": [], "group": ""}
26
+ {"x": 11, "y": 8, "text": "go to prev/next word", "color": "", "tags": [], "group": ""}
27
+ {"x": 0, "y": 0, "text": "Begin typing to overwrite the starting value.", "color": "", "tags": [], "group": ""}
28
+ {"x": 0, "y": 1, "text": "(To edit the starting value, press a movement key first.)", "color": "", "tags": [], "group": ""}
29
+ {"x": 6, "y": 11, "text": "\u2191", "color": "keystrokes", "tags": [], "group": ""}
30
+ {"x": 1, "y": 9, "text": "Home", "color": "keystrokes", "tags": [], "group": ""}
31
+ {"x": 11, "y": 9, "text": "go to start/end", "color": "", "tags": [], "group": ""}
32
+ {"x": 6, "y": 9, "text": "End", "color": "keystrokes", "tags": [], "group": ""}
33
+ {"x": 8, "y": 7, "text": "\u2192", "color": "keystrokes", "tags": [], "group": ""}
34
+ {"x": 37, "y": 4, "text": "Delete", "color": "keystrokes", "tags": [], "group": ""}
35
+ {"x": 34, "y": 5, "text": "Backspace", "color": "keystrokes", "tags": [], "group": ""}
36
+ {"x": 37, "y": 3, "text": "Insert", "color": "keystrokes", "tags": [], "group": ""}
37
+ {"x": 45, "y": 3, "text": "toggle insert mode", "color": "", "tags": [], "group": ""}
38
+ {"x": 6, "y": 12, "text": "Tab", "color": "keystrokes", "tags": [], "group": ""}
39
+ {"x": 1, "y": 8, "text": "Ctrl", "color": "keystrokes", "tags": [], "group": ""}
40
+ {"x": 35, "y": 6, "text": "Ctrl", "color": "keystrokes", "tags": [], "group": ""}
41
+ {"x": 37, "y": 8, "text": "Ctrl", "color": "keystrokes", "tags": [], "group": ""}
42
+ {"x": 37, "y": 7, "text": "Ctrl", "color": "keystrokes", "tags": [], "group": ""}
43
+ {"x": 37, "y": 9, "text": "Ctrl", "color": "keystrokes", "tags": [], "group": ""}
44
+ {"x": 37, "y": 11, "text": "Ctrl", "color": "keystrokes", "tags": [], "group": ""}
45
+ {"x": 37, "y": 12, "text": "Ctrl", "color": "keystrokes", "tags": [], "group": ""}
46
+ {"x": 37, "y": 13, "text": "Ctrl", "color": "keystrokes", "tags": [], "group": ""}
47
+ {"x": 5, "y": 8, "text": "+", "color": "keystrokes", "tags": [], "group": ""}
48
+ {"x": 39, "y": 6, "text": "+", "color": "keystrokes", "tags": [], "group": ""}
49
+ {"x": 41, "y": 7, "text": "+", "color": "keystrokes", "tags": [], "group": ""}
50
+ {"x": 41, "y": 8, "text": "+", "color": "keystrokes", "tags": [], "group": ""}
51
+ {"x": 41, "y": 9, "text": "+", "color": "keystrokes", "tags": [], "group": ""}
52
+ {"x": 41, "y": 11, "text": "+", "color": "keystrokes", "tags": [], "group": ""}
53
+ {"x": 41, "y": 12, "text": "+", "color": "keystrokes", "tags": [], "group": ""}
54
+ {"x": 41, "y": 13, "text": "+", "color": "keystrokes", "tags": [], "group": ""}
55
+ {"x": 11, "y": 11, "text": "prev/next in history", "color": "", "tags": [], "group": ""}
56
+ {"x": 11, "y": 12, "text": "next autocomplete", "color": "", "tags": [], "group": ""}
57
+ {"x": 11, "y": 13, "text": "prev autocomplete", "color": "", "tags": [], "group": ""}
58
+ {"x": 7, "y": 4, "text": "+", "color": "keystrokes", "tags": [], "group": ""}
59
+ {"x": 8, "y": 4, "text": "C", "color": "keystrokes", "tags": [], "group": ""}
60
+ {"x": 5, "y": 13, "text": "+", "color": "keystrokes", "tags": [], "group": ""}
61
+ {"x": 6, "y": 13, "text": "Tab", "color": "keystrokes", "tags": [], "group": ""}
62
+ {"x": 32, "y": 3, "text": "\u2502", "color": "", "tags": [], "group": ""}
63
+ {"x": 32, "y": 4, "text": "\u2502", "color": "", "tags": [], "group": ""}
64
+ {"x": 32, "y": 5, "text": "\u2502", "color": "", "tags": [], "group": ""}
77
65
  {"x": 32, "y": 6, "text": "\u2502", "color": "", "tags": [], "group": ""}
78
66
  {"x": 32, "y": 7, "text": "\u2502", "color": "", "tags": [], "group": ""}
79
67
  {"x": 32, "y": 8, "text": "\u2502", "color": "", "tags": [], "group": ""}
@@ -82,6 +70,13 @@
82
70
  {"x": 32, "y": 11, "text": "\u2502", "color": "", "tags": [], "group": ""}
83
71
  {"x": 32, "y": 12, "text": "\u2502", "color": "", "tags": [], "group": ""}
84
72
  {"x": 32, "y": 13, "text": "\u2502", "color": "", "tags": [], "group": ""}
85
- {"x": 32, "y": 14, "text": "\u2502", "color": "", "tags": [], "group": ""}
86
- {"x": 32, "y": 15, "text": "\u2502", "color": "", "tags": [], "group": ""}
87
- {"x": 32, "y": 16, "text": "\u2502", "color": "", "tags": [], "group": ""}
73
+ {"x": 7, "y": 7, "text": "/", "color": "", "tags": [], "group": ""}
74
+ {"x": 5, "y": 9, "text": "/", "color": "", "tags": [], "group": ""}
75
+ {"x": 8, "y": 8, "text": "\u2192", "color": "keystrokes", "tags": [], "group": ""}
76
+ {"x": 8, "y": 11, "text": "\u2193", "color": "keystrokes", "tags": [], "group": ""}
77
+ {"x": 41, "y": 6, "text": "/", "color": "", "tags": [], "group": ""}
78
+ {"x": 7, "y": 11, "text": "/", "color": "", "tags": [], "group": ""}
79
+ {"x": 7, "y": 8, "text": "/", "color": "", "tags": [], "group": ""}
80
+ {"x": 75, "y": 0, "text": "?", "color": "bold 117 cyan", "tags": [], "group": "", "onclick": "https://visidata.org/input"}
81
+ {"x": 3, "y": 5, "text": "Ctrl+G", "color": "keystrokes", "tags": [], "group": ""}
82
+ {"x": 11, "y": 5, "text": "cycle help sidebar", "color": "", "tags": [], "group": ""}
visidata/ddw/regex.ddw ADDED
@@ -0,0 +1,57 @@
1
+ {"id": null, "type": null, "x": 5, "y": 1, "text": ".", "color": "keystrokes", "tags": [], "group": "", "frame": null, "rows": null, "duration_ms": null, "ref": null, "href": null}
2
+ {"x": 5, "y": 2, "text": "^", "color": "keystrokes", "tags": [], "group": ""}
3
+ {"x": 5, "y": 3, "text": "$", "color": "keystrokes", "tags": [], "group": ""}
4
+ {"x": 38, "y": 1, "text": "*", "color": "keystrokes", "tags": [], "group": ""}
5
+ {"x": 38, "y": 2, "text": "+", "color": "keystrokes", "tags": [], "group": ""}
6
+ {"x": 38, "y": 3, "text": "?", "color": "keystrokes", "tags": [], "group": ""}
7
+ {"x": 34, "y": 5, "text": "{m,n}", "color": "keystrokes", "tags": [], "group": ""}
8
+ {"x": 8, "y": 1, "text": "any char except newline", "color": "", "tags": [], "group": ""}
9
+ {"x": 8, "y": 2, "text": "start of string", "color": "", "tags": [], "group": ""}
10
+ {"x": 8, "y": 3, "text": "end of string", "color": "", "tags": [], "group": ""}
11
+ {"x": 42, "y": 1, "text": "0 or more", "color": "", "tags": [], "group": ""}
12
+ {"x": 42, "y": 2, "text": "1 or more", "color": "", "tags": [], "group": ""}
13
+ {"x": 42, "y": 3, "text": "0 or 1", "color": "", "tags": [], "group": ""}
14
+ {"x": 42, "y": 5, "text": "between m and n", "color": "", "tags": [], "group": ""}
15
+ {"x": 1, "y": 11, "text": "[abc]", "color": "keystrokes", "tags": [], "group": ""}
16
+ {"x": 0, "y": 12, "text": "[^abc]", "color": "keystrokes", "tags": [], "group": ""}
17
+ {"x": 4, "y": 4, "text": "\\d", "color": "keystrokes", "tags": [], "group": ""}
18
+ {"x": 4, "y": 6, "text": "\\s", "color": "keystrokes", "tags": [], "group": ""}
19
+ {"x": 4, "y": 8, "text": "\\w", "color": "keystrokes", "tags": [], "group": ""}
20
+ {"x": 8, "y": 4, "text": "digit char", "color": "", "tags": [], "group": ""}
21
+ {"x": 8, "y": 6, "text": "whitespace char", "color": "", "tags": [], "group": ""}
22
+ {"x": 4, "y": 10, "text": "\\b", "color": "keystrokes", "tags": [], "group": ""}
23
+ {"x": 8, "y": 10, "text": "word boundary", "color": "", "tags": [], "group": ""}
24
+ {"x": 8, "y": 8, "text": "word char", "color": "", "tags": [], "group": ""}
25
+ {"x": 18, "y": 8, "text": "[a-zA-Z0-9_]", "color": "keystrokes", "tags": [], "group": ""}
26
+ {"x": 36, "y": 7, "text": "(\u2026)", "color": "keystrokes", "tags": [], "group": ""}
27
+ {"x": 34, "y": 8, "text": "(?:\u2026)", "color": "keystrokes", "tags": [], "group": ""}
28
+ {"x": 8, "y": 11, "text": "any of", "color": "", "tags": [], "group": ""}
29
+ {"x": 15, "y": 11, "text": "a", "color": "keystrokes", "tags": [], "group": ""}
30
+ {"x": 17, "y": 11, "text": "or", "color": "", "tags": [], "group": ""}
31
+ {"x": 20, "y": 11, "text": "b", "color": "keystrokes", "tags": [], "group": ""}
32
+ {"x": 22, "y": 11, "text": "or", "color": "", "tags": [], "group": ""}
33
+ {"x": 25, "y": 11, "text": "c", "color": "keystrokes", "tags": [], "group": ""}
34
+ {"x": 19, "y": 4, "text": "[0-9]", "color": "keystrokes", "tags": [], "group": ""}
35
+ {"x": 42, "y": 7, "text": "capturing group", "color": "", "tags": [], "group": ""}
36
+ {"x": 42, "y": 8, "text": "non-capturing group", "color": "", "tags": [], "group": ""}
37
+ {"x": 9, "y": 12, "text": "", "color": "", "tags": [], "group": ""}
38
+ {"x": 8, "y": 12, "text": "not", "color": "", "tags": [], "group": ""}
39
+ {"x": 12, "y": 12, "text": "a", "color": "keystrokes", "tags": [], "group": ""}
40
+ {"x": 14, "y": 12, "text": "or", "color": "", "tags": [], "group": ""}
41
+ {"x": 17, "y": 12, "text": "b", "color": "keystrokes", "tags": [], "group": ""}
42
+ {"x": 19, "y": 12, "text": "or", "color": "", "tags": [], "group": ""}
43
+ {"x": 22, "y": 12, "text": "c", "color": "keystrokes", "tags": [], "group": ""}
44
+ {"x": 38, "y": 10, "text": "|", "color": "keystrokes", "tags": [], "group": ""}
45
+ {"x": 42, "y": 10, "text": "logical OR", "color": "", "tags": [], "group": ""}
46
+ {"x": 4, "y": 5, "text": "\\D", "color": "keystrokes", "tags": [], "group": ""}
47
+ {"x": 4, "y": 7, "text": "\\S", "color": "keystrokes", "tags": [], "group": ""}
48
+ {"x": 4, "y": 9, "text": "\\W", "color": "keystrokes", "tags": [], "group": ""}
49
+ {"x": 8, "y": 5, "text": "non-digit char", "color": "", "tags": [], "group": ""}
50
+ {"x": 8, "y": 7, "text": "non-whitespace char", "color": "", "tags": [], "group": ""}
51
+ {"x": 8, "y": 9, "text": "non-word char", "color": "", "tags": [], "group": ""}
52
+ {"x": 36, "y": 4, "text": "{m}", "color": "keystrokes", "tags": [], "group": ""}
53
+ {"x": 42, "y": 4, "text": "exactly m", "color": "", "tags": [], "group": ""}
54
+ {"x": 4, "y": 0, "text": "Character classes", "color": "bold underline", "tags": [], "group": ""}
55
+ {"x": 35, "y": 0, "text": "Repetition", "color": "bold underline", "tags": [], "group": ""}
56
+ {"x": 2, "y": 14, "text": "For full documentation on Python regular expressions, see", "color": "", "tags": [], "group": ""}
57
+ {"x": 6, "y": 15, "text": "https://docs.python.org/3/library/re.html", "color": "underline", "tags": [], "group": "", "href": "https://docs.python.org/3/library/re.html"}
visidata/ddwplay.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from collections import defaultdict
2
2
  import json
3
3
  import time
4
- from visidata import colors, vd
4
+ from visidata import colors, vd, clipdraw, ColorAttr
5
5
 
6
6
  __all__ = ['Animation', 'AnimationMgr']
7
7
 
@@ -31,24 +31,38 @@ class Animation:
31
31
  self.width = 0
32
32
  self.load_from(fp)
33
33
 
34
- def iterdeep(self, rows, x=0, y=0, parents=None):
35
- 'Walk rows deeply and generate (row, x, y, [ancestors]) for each row.'
34
+ def iterdeep(self, rows, x=0, y=0, parents=None, **kwargs):
35
+ 'Walk rows deeply and generate (row, x, y, [ancestors]) for each row, filtering on kwargs.'
36
36
  for r in rows:
37
37
  newparents = (parents or []) + [r]
38
38
  if r.type == 'frame': continue
39
39
  if r.ref:
40
40
  assert r.type == 'ref'
41
41
  g = self.groups[r.ref]
42
- yield from self.iterdeep(map(AttrDict, g.rows or []), x+r.x, y+r.y, newparents)
42
+ if self.matches(r, kwargs):
43
+ yield from self.iterdeep(map(AttrDict, g.rows or []), x+r.x, y+r.y, newparents)
43
44
  else:
44
- yield r, x+r.x, y+r.y, newparents
45
- yield from self.iterdeep(map(AttrDict, r.rows or []), x+r.x, x+r.y, newparents)
45
+ if self.matches(r, kwargs):
46
+ yield r, x+r.x, y+r.y, newparents
47
+ yield from self.iterdeep(map(AttrDict, r.rows or []), x+r.x, x+r.y, newparents)
48
+
49
+ def matches(self, row, values):
50
+ for k, v in values.items():
51
+ actualv = getattr(row, k, None)
52
+ if isinstance(actualv, (list, tuple)) and isinstance(v, (list, tuple)):
53
+ if not any(x in actualv for x in v):
54
+ return False
55
+ elif v != actualv:
56
+ return False
57
+ return True
46
58
 
47
59
  def load_from(self, fp):
48
60
  for line in fp.readlines():
49
61
  r = AttrDict(json.loads(line))
50
62
  if r.type == 'frame':
51
- self.frames[r.id].update(r)
63
+ f = self.frames[r.id]
64
+ f.update(r)
65
+ f.rows = []
52
66
  elif r.type == 'group':
53
67
  self.groups[r.id].update(r)
54
68
 
@@ -66,9 +80,12 @@ class Animation:
66
80
  self.width = max(self.width, x+len(r.text))
67
81
  self.height = max(self.height, y)
68
82
 
69
- def draw(self, scr, *, t=0, x=0, y=0, loop=False, **kwargs):
70
- for r, dx, dy, _ in self.iterdeep(self.frames[''].rows):
71
- scr.addstr(y+dy, x+dx, r.text, colors[r.color])
83
+ def draw(self, scr, *, t=0, x=0, y=0, loop=False, attr=ColorAttr(), **kwargs):
84
+ windowHeight, windowWidth = scr.getmaxyx()
85
+ for r, dx, dy, _ in self.iterdeep(self.frames[''].rows, **kwargs):
86
+ text = f'[:onclick {r.href}]{r.text}[/]' if r.href else r.text
87
+ if y+dy < windowHeight:
88
+ clipdraw(scr, y+dy, x+dx, text, attr.update(colors[r.color], 2))
72
89
 
73
90
  if not self.total_ms:
74
91
  return None
@@ -77,8 +94,10 @@ class Animation:
77
94
  for f in self.frames.values():
78
95
  ms -= int(f.duration_ms or 0)
79
96
  if ms < 0:
80
- for r, dx, dy, _ in self.iterdeep(f.rows):
81
- scr.addstr(y+dy, x+dx, r.text, colors[r.color])
97
+ for r, dx, dy, _ in self.iterdeep(f.rows, **kwargs):
98
+ text = f'[:onclick {r.href}]{r.text}[/]' if r.href else r.text
99
+ if y+dy < windowHeight:
100
+ clipdraw(scr, y+dy, x+dx, text, colors[r.color])
82
101
 
83
102
  return -ms/1000
84
103
 
@@ -117,9 +136,9 @@ class AnimationMgr:
117
136
  for row in self.active:
118
137
  startt, anim, akwargs = row
119
138
  kwargs.update(akwargs)
120
- nextt = anim.draw(scr, t=t-startt, **kwargs)
139
+ nextt = anim.draw(scr, t=t+startt, **kwargs)
121
140
  if nextt is None:
122
- if not akwargs.get('loop'):
141
+ if not akwargs.get('loop', True):
123
142
  done.append(row)
124
143
  else:
125
144
  times.append(t+nextt)
visidata/deprecated.py CHANGED
@@ -73,7 +73,7 @@ visidata.Sheet.exec_command = deprecated('2.0')(visidata.Sheet.execCommand)
73
73
  @VisiData.api
74
74
  def filetype(vd, ext, constructor):
75
75
  'Add constructor to handle the given file type/extension.'
76
- globals().setdefault('open_'+ext, lambda p,ext=ext: constructor(p.name, source=p, filetype=ext))
76
+ globals().setdefault('open_'+ext, lambda p,ext=ext: constructor(p.base_stem, source=p, filetype=ext))
77
77
 
78
78
  @deprecated('2.0', 'Sheet(namepart1, namepart2, ...)')
79
79
  @VisiData.global_api
@@ -135,11 +135,12 @@ alias('show-aggregate', 'memo-aggregate')
135
135
 
136
136
  # 2.6
137
137
 
138
- clean_name = visidata.cleanName
138
+ def clean_name(s):
139
+ return visidata.vd.cleanName(s)
139
140
 
140
141
  def maybe_clean(s, vs):
141
142
  if (vs or visidata.vd).options.clean_names:
142
- s = visidata.cleanName(s)
143
+ s = visidata.vd.cleanName(s)
143
144
  return s
144
145
 
145
146
  def load_tsv(fn):
@@ -164,3 +165,76 @@ exceptionCaught = deprecated('2.6', 'vd.exceptionCaught')(vd.exceptionCaught)
164
165
  openSource = deprecated('2.6', 'vd.openSource')(vd.openSource)
165
166
  globalCommand = visidata.BaseSheet.addCommand
166
167
  visidata.Sheet.StaticColumn = deprecated('2.11', 'Sheet.freeze_col')(visidata.Sheet.freeze_col)
168
+ visidata.Path.open_text = deprecated('3.0', 'visidata.Path.open')(visidata.Path.open)
169
+
170
+ vd.sysclip_value = deprecated('3.0', 'vd.sysclipValue')(vd.sysclipValue)
171
+
172
+ def itemsetter(i):
173
+ def g(obj, v):
174
+ obj[i] = v
175
+ return g
176
+
177
+
178
+ vd.optalias('force_valid_colnames', 'clean_names')
179
+ vd.optalias('dir_recurse', 'dir_depth', 100000)
180
+ vd.optalias('confirm_overwrite', 'overwrite', 'confirm')
181
+ vd.optalias('show_graph_labels', 'disp_graph_labels')
182
+ vd.optalias('zoom_incr', 'disp_zoom_incr')
183
+
184
+ alias('visibility-sheet', 'toggle-multiline')
185
+ alias('visibility-col', 'toggle-multiline')
186
+
187
+ def clean_to_id(s):
188
+ return visidata.vd.cleanName(s)
189
+
190
+ @deprecated('3.0', 'use try/finally')
191
+ class OnExit:
192
+ '"with OnExit(func, ...):" calls func(...) when the context is exited'
193
+ def __init__(self, func, *args, **kwargs):
194
+ self.func = func
195
+ self.args = args
196
+ self.kwargs = kwargs
197
+
198
+ def __enter__(self):
199
+ return self
200
+
201
+ def __exit__(self, exc_type, exc_value, exc_traceback):
202
+ try:
203
+ self.func(*self.args, **self.kwargs)
204
+ except Exception as e:
205
+ vd.exceptionCaught(e)
206
+
207
+ alias('open-inputs', 'open-input-history')
208
+
209
+ #vd.option('plugins_url', 'https://visidata.org/plugins/plugins.jsonl', 'source of plugins sheet')
210
+
211
+ @visidata.VisiData.api
212
+ def inputRegexSubstOld(vd, prompt):
213
+ 'Input regex transform via oneliner (separated with `/`). Return parsed transformer as dict(before=, after=).'
214
+ rex = vd.inputRegex(prompt, type='regex-subst')
215
+ before, after = vd.parse_sed_transform(rex)
216
+ return dict(before=before, after=after)
217
+
218
+
219
+ visidata.Sheet.addCommand('', 'addcol-subst', 'addColumnAtCursor(Column(cursorCol.name + "_re", getter=regexTransform(cursorCol, **inputRegexSubstOld("transform column by regex: "))))', 'add column derived from current column, replacing regex with subst (may include \1 backrefs)', deprecated=True)
220
+ visidata.Sheet.addCommand('', 'setcol-subst', 'setValuesFromRegex([cursorCol], someSelectedRows, **inputRegexSubstOld("transform column by regex: "))', 'regex/subst - modify selected rows in current column, replacing regex with subst, (may include backreferences \\1 etc)', deprecated=True)
221
+ visidata.Sheet.addCommand('', 'setcol-subst-all', 'setValuesFromRegex(visibleCols, someSelectedRows, **inputRegexSubstOld(f"transform {nVisibleCols} columns by regex: "))', 'modify selected rows in all visible columns, replacing regex with subst (may include \\1 backrefs)', deprecated=True)
222
+
223
+ visidata.Sheet.addCommand('', 'split-col', 'addRegexColumns(makeRegexSplitter, cursorCol, inputRegex("split regex: ", type="regex-split"))', 'Add new columns from regex split', deprecated=True)
224
+ visidata.Sheet.addCommand('', 'capture-col', 'addRegexColumns(makeRegexMatcher, cursorCol, inputRegex("capture regex: ", type="regex-capture"))', 'add new column from capture groups of regex; requires example row', deprecated=True)
225
+
226
+ #vd.option('cmdlog_histfile', '', 'file to autorecord each cmdlog action to', sheettype=None)
227
+ #BaseSheet.bindkey('KEY_BACKSPACE', 'menu-help')
228
+
229
+ @deprecated('3.0', 'vd.callNoExceptions(col.setValue, row, value)')
230
+ @visidata.Column.api
231
+ def setValueSafe(self, row, value):
232
+ 'setValue and ignore exceptions.'
233
+ return vd.callNoExceptions(self.setValue, row, value)
234
+
235
+ @deprecated('3.0', 'vd.callNoExceptions(sheet.checkCursor)')
236
+ @visidata.BaseSheet.api
237
+ def checkCursorNoExceptions(sheet):
238
+ return vd.callNoExceptions(sheet.checkCursor)
239
+
240
+ vd.addGlobals(globals())
@@ -0,0 +1,7 @@
1
+ [Desktop Entry]
2
+ Type=Application
3
+ Terminal=true
4
+ Name=VisiData
5
+ Icon=utilities-terminal
6
+ Exec=bash -i -c 'vd %f'
7
+ Categories=Application;
visidata/editor.py CHANGED
@@ -12,14 +12,16 @@ visidata.vd.tstp_signal = None
12
12
  class SuspendCurses:
13
13
  'Context manager to leave windowed mode on enter and restore it on exit.'
14
14
  def __enter__(self):
15
- curses.endwin()
15
+ if visidata.vd.scrFull:
16
+ curses.endwin()
16
17
  if visidata.vd.tstp_signal:
17
18
  signal.signal(signal.SIGTSTP, visidata.vd.tstp_signal)
18
19
 
19
20
  def __exit__(self, exc_type, exc_val, tb):
20
- curses.reset_prog_mode()
21
- visidata.vd.scrFull.refresh()
22
- curses.doupdate()
21
+ if visidata.vd.scrFull:
22
+ curses.reset_prog_mode()
23
+ visidata.vd.scrFull.refresh()
24
+ curses.doupdate()
23
25
 
24
26
 
25
27
  @visidata.VisiData.api
@@ -34,7 +36,7 @@ def launchEditor(vd, *args):
34
36
  @visidata.VisiData.api
35
37
  def launchBrowser(vd, *args):
36
38
  'Launch $BROWSER with *args* as arguments.'
37
- browser = os.environ.get('BROWSER') or vd.fail('(no $BROWSER) for %s' % args[0])
39
+ browser = os.environ.get('BROWSER') or vd.fail('no $BROWSER for %s' % args[0])
38
40
  args = [browser] + list(args)
39
41
  subprocess.call(args)
40
42
 
@@ -44,6 +46,7 @@ def launchExternalEditor(vd, v, linenum=0):
44
46
  'Launch $EDITOR to edit string *v* starting on line *linenum*.'
45
47
  import tempfile
46
48
  with tempfile.NamedTemporaryFile() as temp:
49
+ temp.close() #2118 must close before re-opening on windows
47
50
  with open(temp.name, 'w') as fp:
48
51
  fp.write(v)
49
52
  return vd.launchExternalEditorPath(visidata.Path(temp.name), linenum)
@@ -65,7 +68,8 @@ def launchExternalEditorPath(vd, path, linenum=0):
65
68
  return ''
66
69
 
67
70
 
68
- def suspend():
71
+ @visidata.VisiData.api
72
+ def suspend(vd):
69
73
  import signal
70
74
  with SuspendCurses():
71
75
  os.kill(os.getpid(), signal.SIGSTOP)
@@ -94,3 +98,5 @@ sys.breakpointhook = _breakpoint
94
98
 
95
99
  visidata.BaseSheet.addCommand('^Z', 'suspend', 'suspend()', 'suspend VisiData process')
96
100
  visidata.BaseSheet.addCommand('', 'breakpoint', 'breakpoint()', 'drop into pdb REPL')
101
+
102
+ visidata.vd.addGlobals(SuspendCurses=SuspendCurses)
visidata/errors.py CHANGED
@@ -2,7 +2,8 @@ import traceback
2
2
 
3
3
  from visidata import vd, VisiData, options
4
4
 
5
- __all__ = ['stacktrace', 'ExpectedException']
5
+ vd.option('debug', False, 'exit on error and display stacktrace', max_help=0)
6
+
6
7
 
7
8
  class ExpectedException(Exception):
8
9
  'Controlled Exception from fail() or confirm(). Status or other interface update is done by raiser.'
@@ -28,4 +29,7 @@ def exceptionCaught(vd, exc=None, status=True, **kwargs):
28
29
  if vd.options.debug:
29
30
  raise
30
31
 
32
+
33
+ vd.addGlobals(stacktrace=stacktrace, ExpectedException=ExpectedException)
34
+
31
35
  # see textsheet.py for ErrorSheet and associated commands
File without changes
@@ -0,0 +1,29 @@
1
+ # command setdiff-sheet adds a diff colorizer for all sheets against current sheet
2
+
3
+ from visidata import Sheet, CellColorizer, vd
4
+
5
+ vd.theme_option('color_diff', 'red', 'color of values different from --diff source')
6
+ vd.theme_option('color_diff_add', 'yellow', 'color of rows/columns added to --diff source')
7
+
8
+
9
+ def makeDiffColorizer(othersheet):
10
+ def colorizeDiffs(sheet, col, row, cellval):
11
+ if row is None or col is None:
12
+ return None
13
+ vcolidx = sheet.visibleCols.index(col)
14
+ rowidx = sheet.rows.index(row)
15
+ if vcolidx < len(othersheet.visibleCols) and rowidx < len(othersheet.rows):
16
+ otherval = othersheet.visibleCols[vcolidx].getDisplayValue(othersheet.rows[rowidx])
17
+ if cellval.display != otherval:
18
+ return 'color_diff'
19
+ else:
20
+ return 'color_diff_add'
21
+ return colorizeDiffs
22
+
23
+
24
+ @Sheet.api
25
+ def setDiffSheet(vs):
26
+ Sheet.colorizers.append(CellColorizer(8, None, makeDiffColorizer(vs)))
27
+
28
+
29
+ Sheet.addCommand(None, 'setdiff-sheet', 'setDiffSheet()', 'set this sheet as diff sheet for all new sheets')
@@ -0,0 +1,6 @@
1
+ 'Enter edit mode automatically when typing numeric digits.'
2
+
3
+ from visidata import Sheet
4
+
5
+ for i in range(0, 10):
6
+ Sheet.addCommand(str(i), 'autoedit-%s' % i, 'cursorCol.setValues([cursorRow], editCell(cursorVisibleColIndex, value="%s", i=1))' % i, 'replace cell value with input starting with %s' % i)