visidata 2.11.1__py3-none-any.whl → 3.0.1__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 (256) hide show
  1. visidata/__init__.py +72 -91
  2. visidata/_input.py +259 -42
  3. visidata/_open.py +84 -29
  4. visidata/_types.py +21 -3
  5. visidata/_urlcache.py +17 -4
  6. visidata/aggregators.py +78 -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. {vgit → visidata/apps/vgit}/blame.py +5 -2
  18. {vgit → visidata/apps/vgit}/branch.py +31 -16
  19. {vgit → visidata/apps/vgit}/config.py +3 -3
  20. visidata/apps/vgit/diff.py +169 -0
  21. visidata/apps/vgit/gitsheet.py +161 -0
  22. {vgit → visidata/apps/vgit}/grep.py +6 -5
  23. visidata/apps/vgit/log.py +81 -0
  24. {vgit → visidata/apps/vgit}/main.py +18 -5
  25. {vgit → visidata/apps/vgit}/remote.py +8 -4
  26. visidata/apps/vgit/repos.py +71 -0
  27. {vgit → visidata/apps/vgit}/setup.py +6 -4
  28. visidata/apps/vgit/stash.py +69 -0
  29. visidata/apps/vgit/status.py +204 -0
  30. {vgit → visidata/apps/vgit}/statusbar.py +2 -0
  31. visidata/basesheet.py +63 -51
  32. visidata/canvas.py +208 -93
  33. visidata/choose.py +6 -6
  34. visidata/clean_names.py +29 -0
  35. visidata/clipboard.py +73 -17
  36. visidata/cliptext.py +220 -46
  37. visidata/cmdlog.py +88 -114
  38. visidata/color.py +142 -56
  39. visidata/column.py +121 -129
  40. visidata/ddw/input.ddw +74 -79
  41. visidata/ddw/regex.ddw +57 -0
  42. visidata/ddwplay.py +33 -14
  43. visidata/deprecated.py +77 -3
  44. visidata/desktop/visidata.desktop +7 -0
  45. visidata/editor.py +12 -6
  46. visidata/errors.py +6 -2
  47. visidata/experimental/__init__.py +0 -0
  48. visidata/experimental/diff_sheet.py +29 -0
  49. visidata/experimental/digit_autoedit.py +6 -0
  50. visidata/experimental/gdrive.py +89 -0
  51. visidata/experimental/google.py +37 -0
  52. visidata/experimental/gsheets.py +79 -0
  53. visidata/experimental/live_search.py +37 -0
  54. visidata/experimental/liveupdate.py +45 -0
  55. visidata/experimental/mark.py +133 -0
  56. visidata/experimental/noahs_tapestry/__init__.py +1 -0
  57. visidata/experimental/noahs_tapestry/tapestry.py +147 -0
  58. visidata/experimental/rownum.py +73 -0
  59. visidata/experimental/slide_cells.py +26 -0
  60. visidata/expr.py +8 -4
  61. visidata/extensible.py +22 -4
  62. visidata/features/__init__.py +0 -0
  63. visidata/features/addcol_audiometadata.py +42 -0
  64. visidata/features/addcol_histogram.py +34 -0
  65. visidata/features/canvas_save_svg.py +69 -0
  66. visidata/features/change_precision.py +46 -0
  67. visidata/features/cmdpalette.py +197 -0
  68. visidata/features/colorbrewer.py +363 -0
  69. visidata/{colorsheet.py → features/colorsheet.py} +17 -16
  70. visidata/features/command_server.py +105 -0
  71. visidata/features/currency_to_usd.py +70 -0
  72. visidata/{customdate.py → features/customdate.py} +2 -0
  73. visidata/features/dedupe.py +132 -0
  74. visidata/{describe.py → features/describe.py} +17 -15
  75. visidata/features/errors_guide.py +26 -0
  76. visidata/features/expand_cols.py +202 -0
  77. visidata/{fill.py → features/fill.py} +3 -1
  78. visidata/{freeze.py → features/freeze.py} +11 -6
  79. visidata/features/graph_seaborn.py +79 -0
  80. visidata/features/helloworld.py +10 -0
  81. visidata/features/hint_types.py +17 -0
  82. visidata/{incr.py → features/incr.py} +5 -0
  83. visidata/{join.py → features/join.py} +107 -53
  84. visidata/features/known_cols.py +21 -0
  85. visidata/features/layout.py +62 -0
  86. visidata/{melt.py → features/melt.py} +32 -21
  87. visidata/features/normcol.py +118 -0
  88. visidata/features/open_config.py +7 -0
  89. visidata/features/open_syspaste.py +18 -0
  90. visidata/features/ping.py +157 -0
  91. visidata/features/procmgr.py +208 -0
  92. visidata/features/random_sample.py +6 -0
  93. visidata/{regex.py → features/regex.py} +47 -31
  94. visidata/features/reload_every.py +55 -0
  95. visidata/features/rename_col_cascade.py +30 -0
  96. visidata/features/scroll_context.py +60 -0
  97. visidata/features/select_equal_selected.py +11 -0
  98. visidata/features/setcol_fake.py +65 -0
  99. visidata/{slide.py → features/slide.py} +77 -21
  100. visidata/features/sparkline.py +48 -0
  101. visidata/features/status_source.py +20 -0
  102. visidata/{sysedit.py → features/sysedit.py} +2 -1
  103. visidata/features/sysopen_mailcap.py +46 -0
  104. visidata/features/term_extras.py +13 -0
  105. visidata/{transpose.py → features/transpose.py} +5 -4
  106. visidata/features/type_ipaddr.py +73 -0
  107. visidata/features/type_url.py +11 -0
  108. visidata/{unfurl.py → features/unfurl.py} +9 -9
  109. visidata/{window.py → features/window.py} +2 -2
  110. visidata/form.py +50 -21
  111. visidata/freqtbl.py +81 -33
  112. visidata/fuzzymatch.py +414 -0
  113. visidata/graph.py +105 -33
  114. visidata/guide.py +200 -0
  115. visidata/help.py +75 -44
  116. visidata/hint.py +39 -0
  117. visidata/indexsheet.py +109 -0
  118. visidata/input_history.py +55 -0
  119. visidata/interface.py +58 -0
  120. visidata/keys.py +20 -16
  121. visidata/loaders/__init__.py +9 -0
  122. visidata/loaders/_pandas.py +61 -21
  123. visidata/loaders/api_airtable.py +70 -0
  124. visidata/loaders/api_bitio.py +102 -0
  125. visidata/loaders/api_matrix.py +148 -0
  126. visidata/loaders/api_reddit.py +306 -0
  127. visidata/loaders/api_zulip.py +249 -0
  128. visidata/loaders/archive.py +41 -7
  129. visidata/loaders/arrow.py +7 -7
  130. visidata/loaders/conll.py +49 -0
  131. visidata/loaders/csv.py +25 -7
  132. visidata/loaders/eml.py +3 -4
  133. visidata/loaders/f5log.py +1204 -0
  134. visidata/loaders/fec.py +325 -0
  135. visidata/loaders/fixed_width.py +2 -4
  136. visidata/loaders/frictionless.py +3 -3
  137. visidata/loaders/geojson.py +8 -5
  138. visidata/loaders/google.py +48 -0
  139. visidata/loaders/graphviz.py +4 -4
  140. visidata/loaders/hdf5.py +4 -4
  141. visidata/loaders/html.py +54 -12
  142. visidata/loaders/http.py +84 -30
  143. visidata/loaders/imap.py +20 -10
  144. visidata/loaders/jrnl.py +52 -0
  145. visidata/loaders/json.py +83 -29
  146. visidata/loaders/jsonla.py +74 -0
  147. visidata/loaders/lsv.py +15 -11
  148. visidata/loaders/mailbox.py +40 -0
  149. visidata/loaders/markdown.py +1 -3
  150. visidata/loaders/mbtiles.py +4 -5
  151. visidata/loaders/mysql.py +11 -13
  152. visidata/loaders/npy.py +7 -7
  153. visidata/loaders/odf.py +4 -1
  154. visidata/loaders/orgmode.py +428 -0
  155. visidata/loaders/pandas_freqtbl.py +14 -20
  156. visidata/loaders/parquet.py +62 -6
  157. visidata/loaders/pcap.py +3 -3
  158. visidata/loaders/pdf.py +4 -3
  159. visidata/loaders/png.py +19 -13
  160. visidata/loaders/postgres.py +9 -8
  161. visidata/loaders/rec.py +7 -3
  162. visidata/loaders/s3.py +342 -0
  163. visidata/loaders/sas.py +5 -5
  164. visidata/loaders/scrape.py +186 -0
  165. visidata/loaders/shp.py +6 -5
  166. visidata/loaders/spss.py +5 -6
  167. visidata/loaders/sqlite.py +68 -28
  168. visidata/loaders/texttables.py +1 -1
  169. visidata/loaders/toml.py +60 -0
  170. visidata/loaders/tsv.py +61 -19
  171. visidata/loaders/ttf.py +19 -7
  172. visidata/loaders/unzip_http.py +6 -5
  173. visidata/loaders/usv.py +1 -1
  174. visidata/loaders/vcf.py +16 -16
  175. visidata/loaders/vds.py +10 -7
  176. visidata/loaders/vdx.py +30 -5
  177. visidata/loaders/xlsb.py +8 -1
  178. visidata/loaders/xlsx.py +145 -25
  179. visidata/loaders/xml.py +6 -3
  180. visidata/loaders/xword.py +4 -4
  181. visidata/loaders/yaml.py +15 -5
  182. visidata/macros.py +129 -42
  183. visidata/main.py +119 -94
  184. visidata/mainloop.py +101 -155
  185. visidata/man/parse_options.py +2 -2
  186. visidata/man/vd.1 +302 -149
  187. visidata/man/vd.txt +291 -154
  188. visidata/memory.py +3 -3
  189. visidata/menu.py +104 -423
  190. visidata/metasheets.py +59 -141
  191. visidata/modify.py +78 -23
  192. visidata/motd.py +3 -3
  193. visidata/mouse.py +137 -0
  194. visidata/movement.py +43 -35
  195. visidata/optionssheet.py +99 -0
  196. visidata/path.py +113 -32
  197. visidata/pivot.py +73 -47
  198. visidata/plugins.py +65 -192
  199. visidata/pyobj.py +55 -205
  200. visidata/rename_col.py +20 -0
  201. visidata/save.py +37 -20
  202. visidata/search.py +54 -10
  203. visidata/selection.py +84 -5
  204. visidata/settings.py +162 -25
  205. visidata/sheets.py +239 -260
  206. visidata/shell.py +51 -21
  207. visidata/sidebar.py +162 -0
  208. visidata/sort.py +11 -4
  209. visidata/statusbar.py +114 -104
  210. visidata/stored_list.py +43 -0
  211. visidata/stored_prop.py +38 -0
  212. visidata/tests/benchmark.csv +52 -0
  213. visidata/tests/conftest.py +3 -3
  214. visidata/tests/test_cliptext.py +39 -0
  215. visidata/tests/test_commands.py +65 -7
  216. visidata/tests/test_edittext.py +2 -2
  217. visidata/tests/test_features.py +28 -0
  218. visidata/tests/test_menu.py +14 -0
  219. visidata/tests/test_path.py +13 -4
  220. visidata/text_source.py +53 -0
  221. visidata/textsheet.py +10 -3
  222. visidata/theme.py +44 -0
  223. visidata/themes/__init__.py +0 -0
  224. visidata/themes/ascii8.py +84 -0
  225. visidata/themes/asciimono.py +84 -0
  226. visidata/themes/light.py +17 -0
  227. visidata/threads.py +89 -40
  228. visidata/tuiwin.py +22 -0
  229. visidata/type_currency.py +22 -3
  230. visidata/type_date.py +31 -9
  231. visidata/type_floatsi.py +5 -1
  232. visidata/undo.py +17 -5
  233. visidata/utils.py +106 -23
  234. visidata/vdobj.py +28 -17
  235. visidata/windows.py +10 -0
  236. visidata/wrappers.py +9 -3
  237. visidata-3.0.1.data/data/share/applications/visidata.desktop +7 -0
  238. {visidata-2.11.1.data → visidata-3.0.1.data}/data/share/man/man1/vd.1 +302 -149
  239. {visidata-2.11.1.data → visidata-3.0.1.data}/data/share/man/man1/visidata.1 +302 -149
  240. visidata-3.0.1.data/scripts/vd2to3.vdx +9 -0
  241. {visidata-2.11.1.dist-info → visidata-3.0.1.dist-info}/METADATA +12 -8
  242. visidata-3.0.1.dist-info/RECORD +258 -0
  243. {visidata-2.11.1.dist-info → visidata-3.0.1.dist-info}/WHEEL +1 -1
  244. vgit/__init__.py +0 -1
  245. vgit/gitsheet.py +0 -164
  246. visidata/layout.py +0 -44
  247. visidata/misc.py +0 -5
  248. visidata-2.11.1.data/scripts/vgit +0 -9
  249. visidata-2.11.1.dist-info/RECORD +0 -155
  250. {vgit → visidata/apps/vgit}/__main__.py +0 -0
  251. {vgit → visidata/apps/vgit}/abort.py +0 -0
  252. /visidata/{repeat.py → features/repeat.py} +0 -0
  253. {visidata-2.11.1.data → visidata-3.0.1.data}/scripts/vd +0 -0
  254. {visidata-2.11.1.dist-info → visidata-3.0.1.dist-info}/LICENSE.gpl3 +0 -0
  255. {visidata-2.11.1.dist-info → visidata-3.0.1.dist-info}/entry_points.txt +0 -0
  256. {visidata-2.11.1.dist-info → visidata-3.0.1.dist-info}/top_level.txt +0 -0
visidata/utils.py CHANGED
@@ -1,10 +1,11 @@
1
+ from contextlib import contextmanager
1
2
  import operator
2
3
  import string
3
4
  import re
4
5
 
5
6
  'Various helper classes and functions.'
6
7
 
7
- __all__ = ['AlwaysDict', 'AttrDict', 'moveListItem', 'namedlist', 'classproperty', 'cleanName', 'MissingAttrFormatter']
8
+ __all__ = ['AlwaysDict', 'AttrDict', 'DefaultAttrDict', 'moveListItem', 'namedlist', 'classproperty', 'MissingAttrFormatter', 'getitem', 'setitem', 'getitemdef', 'getitemdeep', 'setitemdeep', 'getattrdeep', 'setattrdeep', 'ExplodingMock', 'ScopedSetattr']
8
9
 
9
10
 
10
11
  class AlwaysDict(dict):
@@ -36,6 +37,24 @@ class AttrDict(dict):
36
37
  return self.keys()
37
38
 
38
39
 
40
+ class DefaultAttrDict(dict):
41
+ 'Augment a dict with more convenient .attr syntax. not-present keys store new DefaultAttrDict. like a recursive defaultdict.'
42
+ def __getattr__(self, k):
43
+ if k not in self:
44
+ if k.startswith("__"):
45
+ raise AttributeError from e
46
+ self[k] = DefaultAttrDict()
47
+ return self[k]
48
+
49
+ def __setattr__(self, k, v):
50
+ self[k] = v
51
+
52
+ def __dir__(self):
53
+ return self.keys()
54
+
55
+
56
+
57
+
39
58
  class classproperty(property):
40
59
  def __get__(self, cls, obj):
41
60
  return classmethod(self.fget).__get__(None, obj or cls)()
@@ -50,34 +69,75 @@ def moveListItem(L, fromidx, toidx):
50
69
  return toidx
51
70
 
52
71
 
53
- def cleanName(s):
54
- s = re.sub(r'[^\w\d_]', '_', s) # replace non-alphanum chars with _
55
- s = re.sub(r'_+', '_', s) # replace runs of _ with a single _
56
- s = s.strip('_')
57
- return s
72
+ def setitem(r, i, v): # function needed for use in lambda
73
+ r[i] = v
74
+ return True
75
+
76
+ def getitem(o, k, default=None):
77
+ return default if o is None else o[k]
78
+
79
+ def getitemdef(o, k, default=None):
80
+ try:
81
+ return default if o is None else o[k]
82
+ except Exception:
83
+ return default
84
+
58
85
 
86
+ def getattrdeep(obj, attr, *default, getter=getattr):
87
+ try:
88
+ 'Return dotted attr (like "a.b.c") from obj, or default if any of the components are missing.'
89
+ if not isinstance(attr, str):
90
+ return getter(obj, attr, *default)
91
+
92
+ try: # if attribute exists, return toplevel value, even if dotted
93
+ if attr in obj:
94
+ return getter(obj, attr)
95
+ except RecursionError: #1696
96
+ raise
97
+ except Exception as e:
98
+ pass
99
+
100
+ attrs = attr.split('.')
101
+ for a in attrs[:-1]:
102
+ obj = getter(obj, a)
103
+
104
+ return getter(obj, attrs[-1])
105
+ except Exception as e:
106
+ if not default: raise
107
+ return default[0]
59
108
 
60
- class OnExit:
61
- '"with OnExit(func, ...):" calls func(...) when the context is exited'
62
- def __init__(self, func, *args, **kwargs):
63
- self.func = func
64
- self.args = args
65
- self.kwargs = kwargs
66
109
 
67
- def __enter__(self):
68
- return self
110
+ def setattrdeep(obj, attr, val, getter=getattr, setter=setattr):
111
+ 'Set dotted attr (like "a.b.c") on obj to val.'
112
+ if not isinstance(attr, str):
113
+ return setter(obj, attr, val)
69
114
 
70
- def __exit__(self, exc_type, exc_value, exc_traceback):
115
+ try: # if attribute exists, overwrite toplevel value, even if dotted
116
+ getter(obj, attr)
117
+ return setter(obj, attr, val)
118
+ except Exception as e:
119
+ pass
120
+
121
+ attrs = attr.split('.')
122
+ for a in attrs[:-1]:
71
123
  try:
72
- self.func(*self.args, **self.kwargs)
124
+ obj = getter(obj, a)
73
125
  except Exception as e:
74
- vd.exceptionCaught(e)
126
+ obj = obj[a] = type(obj)() # assume homogeneous nesting
127
+
128
+ setter(obj, attrs[-1], val)
75
129
 
76
130
 
77
- def itemsetter(i):
78
- def g(obj, v):
79
- obj[i] = v
80
- return g
131
+ def getitemdeep(obj, k, *default):
132
+ if not isinstance(k, str):
133
+ try:
134
+ return obj[k]
135
+ except IndexError:
136
+ pass
137
+ return getattrdeep(obj, k, *default, getter=getitem)
138
+
139
+ def setitemdeep(obj, k, val):
140
+ return setattrdeep(obj, k, val, getter=getitemdef, setter=setitem)
81
141
 
82
142
 
83
143
  def namedlist(objname, fieldnames):
@@ -111,11 +171,24 @@ def namedlist(objname, fieldnames):
111
171
 
112
172
  return NamedListTemplate
113
173
 
174
+
175
+ class ExplodingMock:
176
+ 'A mock object that raises an exception for everything except conversion to True/False.'
177
+ def __init__(self, msg):
178
+ self.__msg = msg
179
+
180
+ def __getattr__(self, k):
181
+ raise Exception(self.__msg)
182
+
183
+ def __bool__(self):
184
+ return False
185
+
186
+
114
187
  class MissingAttrFormatter(string.Formatter):
115
188
  "formats {} fields with `''`, that would normally result in a raised KeyError or AttributeError; intended for user customisable format strings."
116
- def get_field(self, field_name, *args, **kwargs):
189
+ def get_field(self, field_name, args, kwargs):
117
190
  try:
118
- return super().get_field(field_name, *args, **kwargs)
191
+ return super().get_field(field_name, args, kwargs)
119
192
  except (KeyError, AttributeError):
120
193
  return (None, field_name)
121
194
 
@@ -126,3 +199,13 @@ class MissingAttrFormatter(string.Formatter):
126
199
  elif not value:
127
200
  return str(value)
128
201
  return super().format_field(value, format_spec)
202
+
203
+
204
+ @contextmanager
205
+ def ScopedSetattr(obj, attrname, val):
206
+ oldval = getattr(obj, attrname)
207
+ try:
208
+ setattr(obj, attrname, val)
209
+ yield
210
+ finally:
211
+ setattr(obj, attrname, oldval)
visidata/vdobj.py CHANGED
@@ -1,5 +1,4 @@
1
1
  from functools import wraps
2
- from unittest import mock
3
2
  import curses
4
3
 
5
4
  import visidata
@@ -25,7 +24,7 @@ def asyncthread(func):
25
24
 
26
25
 
27
26
  class VisiData(visidata.Extensible):
28
- allPrefixes = ['g', 'z', ESC] # embig'g'en, 'z'mallify, ESC=Alt/Meta
27
+ allPrefixes = ['g', 'z', 'Alt+'] # embig'g'en, 'z'mallify, Alt/Esc=User
29
28
 
30
29
  @classmethod
31
30
  def global_api(cls, func):
@@ -42,9 +41,16 @@ class VisiData(visidata.Extensible):
42
41
  self.lastErrors = []
43
42
  self.pendingKeys = []
44
43
  self.keystrokes = ''
45
- self.scrFull = mock.MagicMock(__bool__=mock.Mock(return_value=False)) # disable curses in batch mode
44
+ self.scrFull = None
46
45
  self._cmdlog = None
46
+ self.currentReplay = None
47
47
  self.contexts = [self] # objects whose attributes are in the fallback context for eval/exec.
48
+ self.importingModule = None
49
+ self.importedModules = []
50
+
51
+ @property
52
+ def cursesEnabled(self):
53
+ return bool(self.scrFull)
48
54
 
49
55
  def sheetstack(self, pane=0):
50
56
  'Return list of sheets in given *pane*. pane=0 is the active pane. pane=-1 is the inactive pane.'
@@ -74,10 +80,6 @@ class VisiData(visidata.Extensible):
74
80
  def activeStack(self):
75
81
  return self.sheetstack() or self.sheetstack(-1)
76
82
 
77
- @visidata.drawcache_property
78
- def mousereg(self):
79
- return []
80
-
81
83
  def __copy__(self):
82
84
  'Dummy method for Extensible.init()'
83
85
  pass
@@ -100,12 +102,29 @@ class VisiData(visidata.Extensible):
100
102
  'Invalidate internal caches between command inputs.'
101
103
  visidata.Extensible.clear_all_caches()
102
104
 
105
+ def resetVisiData(self):
106
+ self.clearCaches() # we want vd to return a new VisiData object for each command
107
+ vd = visidata.vd # get the new vd
108
+ vd.cmdlog.rows = []
109
+ vd.sheets = []
110
+ vd.allSheets = []
111
+ return vd
112
+
113
+ def get_wch(self, scr):
114
+ try:
115
+ return scr.get_wch()
116
+ except AttributeError: #192 some packages don't have wide chars
117
+ k = scr.getch()
118
+ if k == -1: # mimic get_wch behavior
119
+ raise curses.error('no char ready')
120
+ return k
121
+
103
122
  def drainPendingKeys(self, scr):
104
123
  '''Call scr.get_wch() until no more keypresses are available. Return True if any keypresses are pending.'''
105
124
  scr.timeout(0)
106
125
  try:
107
126
  while True:
108
- k = scr.get_wch()
127
+ k = self.get_wch(scr)
109
128
  if k:
110
129
  self.pendingKeys.append(k)
111
130
  else:
@@ -127,7 +146,7 @@ class VisiData(visidata.Extensible):
127
146
  curses.reset_prog_mode() #1347
128
147
  try:
129
148
  scr.refresh()
130
- k = scr.get_wch()
149
+ k = self.get_wch(scr)
131
150
  vs = vs or self.activeSheet
132
151
  if vs:
133
152
  self.drawRightStatus(vs._scr, vs) # continue to display progress %
@@ -140,14 +159,6 @@ class VisiData(visidata.Extensible):
140
159
  k = ord(k)
141
160
  return curses.keyname(k).decode('utf-8')
142
161
 
143
- def onMouse(self, scr, y, x, h, w, **kwargs):
144
- self.mousereg.append((scr, y, x, h, w, kwargs))
145
-
146
- def getMouse(self, _scr, _x, _y, button):
147
- for scr, y, x, h, w, kwargs in self.mousereg[::-1]:
148
- if scr is _scr and x <= _x < x+w and y <= _y < y+h and button in kwargs:
149
- return kwargs[button]
150
-
151
162
  @property
152
163
  def screenHeight(self):
153
164
  return self.scrFull.getmaxyx()[0] if self.scrFull else 25
visidata/windows.py ADDED
@@ -0,0 +1,10 @@
1
+ '''
2
+ Windows-specific code
3
+ '''
4
+
5
+ import string
6
+ from visidata import vd
7
+
8
+
9
+ for c in string.ascii_uppercase:
10
+ vd.bindkey('ALT_'+c , 'Alt+'+c.lower()) #1630
visidata/wrappers.py CHANGED
@@ -5,9 +5,6 @@ import functools
5
5
 
6
6
  from visidata import options, stacktrace, BaseSheet, vd
7
7
 
8
- __all__ = ['forward', 'wrmap', 'wrapply', 'TypedWrapper', 'TypedExceptionWrapper']
9
-
10
- vd.option('null_value', None, 'a value to be counted as null', replay=True)
11
8
 
12
9
  @BaseSheet.api
13
10
  def isNullFunc(sheet):
@@ -109,3 +106,12 @@ def wrapply(func, *args, **kwargs):
109
106
  except Exception as e:
110
107
  e.stacktrace = stacktrace()
111
108
  return TypedExceptionWrapper(func, *args, exception=e)
109
+
110
+
111
+ vd.addGlobals(
112
+ forward=forward,
113
+ wrmap=wrmap,
114
+ wrapply=wrapply,
115
+ TypedWrapper=TypedWrapper,
116
+ TypedExceptionWrapper=TypedExceptionWrapper
117
+ )
@@ -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;