omdev 0.0.0.dev463__tar.gz → 0.0.0.dev464__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 (369) hide show
  1. {omdev-0.0.0.dev463/omdev.egg-info → omdev-0.0.0.dev464}/PKG-INFO +2 -2
  2. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/rich/__init__.py +1 -0
  3. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/textual/__init__.py +16 -0
  4. omdev-0.0.0.dev464/omdev/tui/textual/autocomplete/LICENSE +21 -0
  5. omdev-0.0.0.dev464/omdev/tui/textual/autocomplete/__init__.py +33 -0
  6. omdev-0.0.0.dev464/omdev/tui/textual/autocomplete/matching.py +226 -0
  7. omdev-0.0.0.dev464/omdev/tui/textual/autocomplete/paths.py +202 -0
  8. omdev-0.0.0.dev464/omdev/tui/textual/autocomplete/widget.py +612 -0
  9. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464/omdev.egg-info}/PKG-INFO +2 -2
  10. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev.egg-info/SOURCES.txt +6 -1
  11. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev.egg-info/requires.txt +1 -1
  12. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/pyproject.toml +2 -2
  13. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/LICENSE +0 -0
  14. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/MANIFEST.in +0 -0
  15. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/README.md +0 -0
  16. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/.omlish-manifests.json +0 -0
  17. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/__about__.py +0 -0
  18. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/__init__.py +0 -0
  19. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/__init__.py +0 -0
  20. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/__main__.py +0 -0
  21. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/cli/__init__.py +0 -0
  22. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/cli/main.py +0 -0
  23. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/__init__.py +0 -0
  24. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/gen.py +0 -0
  25. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/imports.py +0 -0
  26. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/manifests.py +0 -0
  27. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/resources.py +0 -0
  28. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/srcfiles.py +0 -0
  29. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/strip.py +0 -0
  30. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/types.py +0 -0
  31. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/typing.py +0 -0
  32. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/sources.py +0 -0
  33. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/__init__.py +0 -0
  34. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/__init__.py +0 -0
  35. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/cache.py +0 -0
  36. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/contexts.py +0 -0
  37. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/currents.py +0 -0
  38. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/fns.py +0 -0
  39. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/resolvers.py +0 -0
  40. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/storage.py +0 -0
  41. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/types.py +0 -0
  42. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/__init__.py +0 -0
  43. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/actions.py +0 -0
  44. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/cache.py +0 -0
  45. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/consts.py +0 -0
  46. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/defaults.py +0 -0
  47. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/manifests.py +0 -0
  48. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/specs.py +0 -0
  49. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/__init__.py +0 -0
  50. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/darwin/__init__.py +0 -0
  51. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/darwin/aps.py +0 -0
  52. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/darwin/ax.py +0 -0
  53. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/darwin/cf.py +0 -0
  54. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/darwin/cg.py +0 -0
  55. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/linux/__init__.py +0 -0
  56. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/linux/x11.py +0 -0
  57. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/__init__.py +0 -0
  58. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/__main__.py +0 -0
  59. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/cdeps.py +0 -0
  60. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/cdeps.toml +0 -0
  61. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/cli.py +0 -0
  62. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/srclangs.py +0 -0
  63. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/__init__.py +0 -0
  64. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_boilerplate.cc +0 -0
  65. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/LICENSE +0 -0
  66. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/__init__.py +0 -0
  67. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/build_ext.py +0 -0
  68. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
  69. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
  70. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/compilers/options.py +0 -0
  71. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
  72. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/dir_util.py +0 -0
  73. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/errors.py +0 -0
  74. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/extension.py +0 -0
  75. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/file_util.py +0 -0
  76. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/modified.py +0 -0
  77. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/spawn.py +0 -0
  78. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/sysconfig.py +0 -0
  79. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/util.py +0 -0
  80. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/version.py +0 -0
  81. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/build.py +0 -0
  82. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/cmake.py +0 -0
  83. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/importhook.py +0 -0
  84. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/magic.py +0 -0
  85. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/scan.py +0 -0
  86. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/__init__.py +0 -0
  87. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/__main__.py +0 -0
  88. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/cache.py +0 -0
  89. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/ci.py +0 -0
  90. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/cli.py +0 -0
  91. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/compose.py +0 -0
  92. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/consts.py +0 -0
  93. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/__init__.py +0 -0
  94. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/buildcaching.py +0 -0
  95. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/cache.py +0 -0
  96. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/cacheserved/__init__.py +0 -0
  97. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/cacheserved/cache.py +0 -0
  98. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/cacheserved/manifests.py +0 -0
  99. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/cmds.py +0 -0
  100. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/dataserver.py +0 -0
  101. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/imagepulling.py +0 -0
  102. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/inject.py +0 -0
  103. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/packing.py +0 -0
  104. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/repositories.py +0 -0
  105. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/utils.py +0 -0
  106. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/__init__.py +0 -0
  107. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/__init__.py +0 -0
  108. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/clients.py +0 -0
  109. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v1/__init__.py +0 -0
  110. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v1/api.py +0 -0
  111. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v1/client.py +0 -0
  112. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v2/__init__.py +0 -0
  113. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v2/api.py +0 -0
  114. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v2/azure.py +0 -0
  115. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v2/client.py +0 -0
  116. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/bootstrap.py +0 -0
  117. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/cache.py +0 -0
  118. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/cli.py +0 -0
  119. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/env.py +0 -0
  120. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/inject.py +0 -0
  121. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/inject.py +0 -0
  122. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/requirements.py +0 -0
  123. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/shell.py +0 -0
  124. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/utils.py +0 -0
  125. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/__init__.py +0 -0
  126. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/__main__.py +0 -0
  127. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/_pathhack.py +0 -0
  128. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/clicli.py +0 -0
  129. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/install.py +0 -0
  130. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/main.py +0 -0
  131. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/managers.py +0 -0
  132. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/types.py +0 -0
  133. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/clipboard/__init__.py +0 -0
  134. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/clipboard/clipboard.py +0 -0
  135. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/clipboard/darwin_cf.py +0 -0
  136. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/clipboard/linux_x11.py +0 -0
  137. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmake.py +0 -0
  138. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmdlog/__init__.py +0 -0
  139. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmdlog/__main__.py +0 -0
  140. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmdlog/_cmdlog.py +0 -0
  141. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmdlog/cli.py +0 -0
  142. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmdlog/cmdlog.py +0 -0
  143. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataclasses/__init__.py +0 -0
  144. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataclasses/__main__.py +0 -0
  145. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataclasses/cli.py +0 -0
  146. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataclasses/codegen.py +0 -0
  147. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/__init__.py +0 -0
  148. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/handlers.py +0 -0
  149. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/http.py +0 -0
  150. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/routes.py +0 -0
  151. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/server.py +0 -0
  152. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/targets.py +0 -0
  153. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/git/__init__.py +0 -0
  154. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/git/magic.py +0 -0
  155. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/git/revisions.py +0 -0
  156. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/git/shallow.py +0 -0
  157. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/git/status.py +0 -0
  158. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/home/__init__.py +0 -0
  159. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/home/paths.py +0 -0
  160. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/home/secrets.py +0 -0
  161. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/home/shadow.py +0 -0
  162. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/imgur.py +0 -0
  163. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/intellij/__init__.py +0 -0
  164. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/intellij/cli.py +0 -0
  165. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/intellij/ides.py +0 -0
  166. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/intellij/open.py +0 -0
  167. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/__init__.py +0 -0
  168. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/__main__.py +0 -0
  169. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/cli.py +0 -0
  170. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/default.py +0 -0
  171. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/inject.py +0 -0
  172. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/inspect.py +0 -0
  173. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/__init__.py +0 -0
  174. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/base.py +0 -0
  175. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/inject.py +0 -0
  176. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/running.py +0 -0
  177. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/standalone.py +0 -0
  178. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/system.py +0 -0
  179. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/pyenv/__init__.py +0 -0
  180. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/pyenv/inject.py +0 -0
  181. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/pyenv/install.py +0 -0
  182. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/pyenv/provider.py +0 -0
  183. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/pyenv/pyenv.py +0 -0
  184. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/resolvers.py +0 -0
  185. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/types.py +0 -0
  186. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/uv/__init__.py +0 -0
  187. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/uv/inject.py +0 -0
  188. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/uv/provider.py +0 -0
  189. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/uv/uv.py +0 -0
  190. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/venvs.py +0 -0
  191. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/__init__.py +0 -0
  192. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/messages/__init__.py +0 -0
  193. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/messages/base.py +0 -0
  194. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/messages/formats.py +0 -0
  195. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/messages/messages.py +0 -0
  196. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/messages/parsing.py +0 -0
  197. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/numerics/__init__.py +0 -0
  198. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/numerics/formats.py +0 -0
  199. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/numerics/numerics.py +0 -0
  200. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/numerics/types.py +0 -0
  201. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/LICENSE +0 -0
  202. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/__init__.py +0 -0
  203. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/consts.py +0 -0
  204. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/errors.py +0 -0
  205. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/message.py +0 -0
  206. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/nuh.py +0 -0
  207. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/parsing.py +0 -0
  208. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/rendering.py +0 -0
  209. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/tags.py +0 -0
  210. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/utils.py +0 -0
  211. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/__init__.py +0 -0
  212. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/__main__.py +0 -0
  213. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/cli.py +0 -0
  214. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/find.py +0 -0
  215. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/magic.py +0 -0
  216. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/prepare.py +0 -0
  217. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/styles.py +0 -0
  218. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/__init__.py +0 -0
  219. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/__main__.py +0 -0
  220. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/_dumping.py +0 -0
  221. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/building.py +0 -0
  222. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/dumping.py +0 -0
  223. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/main.py +0 -0
  224. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/markdown/__init__.py +0 -0
  225. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/markdown/incparse.py +0 -0
  226. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/markdown/tokens.py +0 -0
  227. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/mypy/__init__.py +0 -0
  228. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/mypy/debug.py +0 -0
  229. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/mypy/report.py +0 -0
  230. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/__init__.py +0 -0
  231. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/building.py +0 -0
  232. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/compression.py +0 -0
  233. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/data.py +0 -0
  234. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/datarefs.py +0 -0
  235. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/dataserver.py +0 -0
  236. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/loading.py +0 -0
  237. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/media.py +0 -0
  238. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/pack/__init__.py +0 -0
  239. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/pack/packing.py +0 -0
  240. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/pack/repositories.py +0 -0
  241. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/pack/unpacking.py +0 -0
  242. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/repositories.py +0 -0
  243. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/tars.py +0 -0
  244. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/__init__.py +0 -0
  245. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/marshal.py +0 -0
  246. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/names.py +0 -0
  247. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/requires.py +0 -0
  248. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/revisions.py +0 -0
  249. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/specifiers.py +0 -0
  250. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/versions.py +0 -0
  251. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/wheelfile.py +0 -0
  252. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pip.py +0 -0
  253. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/__init__.py +0 -0
  254. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/__main__.py +0 -0
  255. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/base.py +0 -0
  256. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/blanklines.py +0 -0
  257. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/caches.py +0 -0
  258. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/git.py +0 -0
  259. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/imports.py +0 -0
  260. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/lite.py +0 -0
  261. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/main.py +0 -0
  262. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/manifests.py +0 -0
  263. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/scripts.py +0 -0
  264. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/unicode.py +0 -0
  265. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/__init__.py +0 -0
  266. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/attrdocs.py +0 -0
  267. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/bracepy.py +0 -0
  268. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/classdot.py +0 -0
  269. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/LICENSE +0 -0
  270. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/__init__.py +0 -0
  271. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/attrdoc.py +0 -0
  272. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/common.py +0 -0
  273. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/epydoc.py +0 -0
  274. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/google.py +0 -0
  275. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/numpydoc.py +0 -0
  276. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/parser.py +0 -0
  277. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/rest.py +0 -0
  278. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/findimports.py +0 -0
  279. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/scripts/__init__.py +0 -0
  280. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/scripts/bumpversion.py +0 -0
  281. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/scripts/execstat.py +0 -0
  282. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/scripts/importtrace.py +0 -0
  283. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/srcheaders.py +0 -0
  284. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/tools/__init__.py +0 -0
  285. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/tools/importscan.py +0 -0
  286. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/tools/mkrelimp.py +0 -0
  287. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/__init__.py +0 -0
  288. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/__main__.py +0 -0
  289. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/cexts.py +0 -0
  290. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/cli.py +0 -0
  291. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/configs.py +0 -0
  292. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/inject.py +0 -0
  293. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/pkg.py +0 -0
  294. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/reqs.py +0 -0
  295. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/resources/__init__.py +0 -0
  296. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/resources/docker-dev.sh +0 -0
  297. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/resources/python.sh +0 -0
  298. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/venvs.py +0 -0
  299. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/__init__.py +0 -0
  300. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/ci.py +0 -0
  301. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/interp.py +0 -0
  302. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/lib/__init__.py +0 -0
  303. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/lib/inject.py +0 -0
  304. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/lib/logs.py +0 -0
  305. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/lib/marshal.py +0 -0
  306. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/pyproject.py +0 -0
  307. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/slowcat.py +0 -0
  308. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/tmpexec.py +0 -0
  309. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tagstrings.py +0 -0
  310. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tokens/__init__.py +0 -0
  311. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tokens/all.py +0 -0
  312. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tokens/tokenizert.py +0 -0
  313. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tokens/utils.py +0 -0
  314. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/__init__.py +0 -0
  315. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/cloc.py +0 -0
  316. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/diff.py +0 -0
  317. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/doc.py +0 -0
  318. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/docker.py +0 -0
  319. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/__init__.py +0 -0
  320. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/__main__.py +0 -0
  321. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/cli.py +0 -0
  322. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/cloning.py +0 -0
  323. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/consts.py +0 -0
  324. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/messages.py +0 -0
  325. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/__init__.py +0 -0
  326. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/__main__.py +0 -0
  327. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/cli.py +0 -0
  328. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/formats.py +0 -0
  329. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/io.py +0 -0
  330. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/parsing.py +0 -0
  331. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/processing.py +0 -0
  332. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/rendering.py +0 -0
  333. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/__init__.py +0 -0
  334. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/__main__.py +0 -0
  335. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/cli.py +0 -0
  336. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/resources/__init__.py +0 -0
  337. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/resources/jsonview.css +0 -0
  338. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/resources/jsonview.js +0 -0
  339. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/linehisto.py +0 -0
  340. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/mkenv.py +0 -0
  341. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/notebook.py +0 -0
  342. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/pawk/__init__.py +0 -0
  343. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/pawk/__main__.py +0 -0
  344. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/pawk/pawk.py +0 -0
  345. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/pip.py +0 -0
  346. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/prof.py +0 -0
  347. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/qr.py +0 -0
  348. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/shadow.py +0 -0
  349. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/shell.py +0 -0
  350. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/sqlrepl.py +0 -0
  351. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/__init__.py +0 -0
  352. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/__init__.py +0 -0
  353. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/__init__.py +0 -0
  354. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/__main__.py +0 -0
  355. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/app.py +0 -0
  356. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/client.py +0 -0
  357. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/commands.py +0 -0
  358. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/main.py +0 -0
  359. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/markdown/__init__.py +0 -0
  360. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/markdown/__main__.py +0 -0
  361. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/markdown/cli.py +0 -0
  362. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/rich/console2.py +0 -0
  363. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/rich/markdown2.py +0 -0
  364. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/textual/app2.py +0 -0
  365. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/textual/drivers2.py +0 -0
  366. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev.egg-info/dependency_links.txt +0 -0
  367. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev.egg-info/entry_points.txt +0 -0
  368. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev.egg-info/top_level.txt +0 -0
  369. {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omdev
3
- Version: 0.0.0.dev463
3
+ Version: 0.0.0.dev464
4
4
  Summary: omdev
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Python: >=3.13
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: omlish==0.0.0.dev463
17
+ Requires-Dist: omlish==0.0.0.dev464
18
18
  Provides-Extra: all
19
19
  Requires-Dist: black~=25.9; extra == "all"
20
20
  Requires-Dist: pycparser~=2.23; extra == "all"
@@ -9,6 +9,7 @@ with _lang.auto_proxy_init(globals()):
9
9
  from rich import console # noqa
10
10
  from rich import live # noqa
11
11
  from rich import markdown # noqa
12
+ from rich import repr # noqa
12
13
  from rich import text # noqa
13
14
  from rich.console import Console # noqa
14
15
  from rich.live import Live # noqa
@@ -8,13 +8,16 @@ with _lang.auto_proxy_init(globals()):
8
8
 
9
9
  from textual import app # noqa
10
10
  from textual import binding # noqa
11
+ from textual import constants # noqa
11
12
  from textual import containers # noqa
12
13
  from textual import content # noqa
13
14
  from textual import driver # noqa
14
15
  from textual import events # noqa
16
+ from textual import geometry # noqa
15
17
  from textual import markup # noqa
16
18
  from textual import message # noqa
17
19
  from textual import messages # noqa
20
+ from textual import on # noqa
18
21
  from textual import pad # noqa
19
22
  from textual import reactive # noqa
20
23
  from textual import screen # noqa
@@ -116,6 +119,16 @@ with _lang.auto_proxy_init(globals()):
116
119
  from textual.events import Show # noqa
117
120
  from textual.events import Timer as TimerEvent # noqa
118
121
  from textual.events import Unmount # noqa
122
+ from textual.geometry import NULL_OFFSET # noqa
123
+ from textual.geometry import NULL_REGION # noqa
124
+ from textual.geometry import NULL_SIZE # noqa
125
+ from textual.geometry import NULL_SPACING # noqa
126
+ from textual.geometry import Offset # noqa
127
+ from textual.geometry import Region # noqa
128
+ from textual.geometry import Size # noqa
129
+ from textual.geometry import Spacing # noqa
130
+ from textual.geometry import SpacingDimensions # noqa
131
+ from textual.geometry import clamp # noqa
119
132
  from textual.markup import MarkupError # noqa
120
133
  from textual.markup import MarkupTokenizer # noqa
121
134
  from textual.markup import StyleTokenizer # noqa
@@ -197,6 +210,9 @@ with _lang.auto_proxy_init(globals()):
197
210
  from textual.widgets import Tooltip # noqa
198
211
  from textual.widgets import Tree # noqa
199
212
  from textual.widgets import Welcome # noqa
213
+ from textual.widgets.option_list import OptionDoesNotExist # noqa
214
+ from textual.widgets.option_list import Option # noqa
215
+ from textual.widgets.option_list import DuplicateID # noqa
200
216
 
201
217
  ##
202
218
 
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Darren Burns
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,33 @@
1
+ # MIT License
2
+ #
3
+ # Copyright (c) 2023 Darren Burns
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ # https://github.com/darrenburns/textual-autocomplete/tree/0344cd3eb3383cbbd80e01b035ed808ce53cef4d
19
+ from .matching import ( # noqa
20
+ FuzzySearch,
21
+ FuzzyMatcher,
22
+ )
23
+
24
+ from .paths import ( # noqa
25
+ PathAutoComplete,
26
+ )
27
+
28
+ from .widget import ( # noqa
29
+ AutoCompleteItem,
30
+ AutoCompleteItemHit,
31
+ AutoCompleteList,
32
+ AutoComplete,
33
+ )
@@ -0,0 +1,226 @@
1
+ import functools
2
+ import operator
3
+ import re
4
+ import typing as ta
5
+
6
+ import rich.repr
7
+ from textual.cache import LRUCache
8
+ from textual.content import Content
9
+ from textual.style import Style
10
+
11
+
12
+ ##
13
+
14
+
15
+ class FuzzySearch:
16
+ """
17
+ Performs a fuzzy search.
18
+
19
+ Unlike a regex solution, this will finds all possible matches.
20
+ """
21
+
22
+ def __init__(
23
+ self,
24
+ case_sensitive: bool = False,
25
+ *,
26
+ cache_size: int = 1024 * 4,
27
+ ) -> None:
28
+ """
29
+ Initialize fuzzy search.
30
+
31
+ Args:
32
+ case_sensitive: Is the match case sensitive?
33
+ cache_size: Number of queries to cache.
34
+ """
35
+
36
+ self.case_sensitive = case_sensitive
37
+ self.cache: LRUCache[tuple[str, str], tuple[float, ta.Sequence[int]]] = LRUCache(cache_size)
38
+
39
+ def match(self, query: str, candidate: str) -> tuple[float, ta.Sequence[int]]:
40
+ """
41
+ Match against a query.
42
+
43
+ Args:
44
+ query: The fuzzy query.
45
+ candidate: A candidate to check,.
46
+
47
+ Returns:
48
+ A pair of (score, tuple of offsets). `(0, ())` for no result.
49
+ """
50
+
51
+ cache_key = (query, candidate)
52
+ if cache_key in self.cache:
53
+ return self.cache[cache_key]
54
+ default: tuple[float, ta.Sequence[int]] = (0.0, [])
55
+ result = max(self._match(query, candidate), key=operator.itemgetter(0), default=default)
56
+ self.cache[cache_key] = result
57
+ return result
58
+
59
+ @classmethod
60
+ @functools.lru_cache(maxsize=1024)
61
+ def get_first_letters(cls, candidate: str) -> frozenset[int]:
62
+ return frozenset({match.start() for match in re.finditer(r'\w+', candidate)})
63
+
64
+ def score(self, candidate: str, positions: ta.Sequence[int]) -> float:
65
+ """
66
+ Score a search.
67
+
68
+ Args:
69
+ search: Search object.
70
+
71
+ Returns:
72
+ Score.
73
+ """
74
+
75
+ first_letters = self.get_first_letters(candidate)
76
+ # This is a heuristic, and can be tweaked for better results.
77
+ # Boost first letter matches.
78
+ offset_count = len(positions)
79
+ score: float = offset_count + len(first_letters.intersection(positions))
80
+
81
+ groups = 1
82
+ last_offset, *offsets = positions
83
+ for offset in offsets:
84
+ if offset != last_offset + 1:
85
+ groups += 1
86
+ last_offset = offset
87
+
88
+ # Boost to favor less groups
89
+ normalized_groups = (offset_count - (groups - 1)) / offset_count
90
+ score *= 1 + (normalized_groups * normalized_groups)
91
+ return score
92
+
93
+ def _match(self, query: str, candidate: str) -> ta.Iterable[tuple[float, ta.Sequence[int]]]:
94
+ letter_positions: list[list[int]] = []
95
+ position = 0
96
+
97
+ if not self.case_sensitive:
98
+ candidate = candidate.lower()
99
+ query = query.lower()
100
+ score = self.score
101
+ if query in candidate:
102
+ # Quick exit when the query exists as a substring
103
+ query_location = candidate.rfind(query)
104
+ offsets = list(range(query_location, query_location + len(query)))
105
+ yield (
106
+ score(candidate, offsets) * (2.0 if candidate == query else 1.5),
107
+ offsets,
108
+ )
109
+ return
110
+
111
+ for offset, letter in enumerate(query):
112
+ last_index = len(candidate) - offset
113
+ positions: list[int] = []
114
+ letter_positions.append(positions)
115
+ index = position
116
+ while (location := candidate.find(letter, index)) != -1:
117
+ positions.append(location)
118
+ index = location + 1
119
+ if index >= last_index:
120
+ break
121
+ if not positions:
122
+ yield (0.0, ())
123
+ return
124
+ position = positions[0] + 1
125
+
126
+ possible_offsets: list[list[int]] = []
127
+ query_length = len(query)
128
+
129
+ def get_offsets(offsets: list[int], positions_index: int) -> None:
130
+ """
131
+ Recursively match offsets.
132
+
133
+ Args:
134
+ offsets: A list of offsets.
135
+ positions_index: Index of query letter.
136
+ """
137
+
138
+ for offset in letter_positions[positions_index]:
139
+ if not offsets or offset > offsets[-1]:
140
+ new_offsets = [*offsets, offset]
141
+ if len(new_offsets) == query_length:
142
+ possible_offsets.append(new_offsets)
143
+ else:
144
+ get_offsets(new_offsets, positions_index + 1)
145
+
146
+ get_offsets([], 0)
147
+
148
+ for offsets in possible_offsets:
149
+ yield score(candidate, offsets), offsets
150
+
151
+
152
+ @rich.repr.auto
153
+ class FuzzyMatcher:
154
+ """A fuzzy matcher."""
155
+
156
+ def __init__(
157
+ self,
158
+ query: str,
159
+ *,
160
+ match_style: Style | None = None,
161
+ case_sensitive: bool = False,
162
+ ) -> None:
163
+ """
164
+ Initialize the fuzzy matching object.
165
+
166
+ Args:
167
+ query: A query as typed in by the user.
168
+ match_style: The style to use to highlight matched portions of a string.
169
+ case_sensitive: Should matching be case sensitive?
170
+ """
171
+
172
+ self._query = query
173
+ self._match_style = Style(reverse=True) if match_style is None else match_style
174
+ self._case_sensitive = case_sensitive
175
+ self.fuzzy_search = FuzzySearch()
176
+
177
+ @property
178
+ def query(self) -> str:
179
+ """The query string to look for."""
180
+
181
+ return self._query
182
+
183
+ @property
184
+ def match_style(self) -> Style:
185
+ """The style that will be used to highlight hits in the matched text."""
186
+
187
+ return self._match_style
188
+
189
+ @property
190
+ def case_sensitive(self) -> bool:
191
+ """Is this matcher case sensitive?"""
192
+
193
+ return self._case_sensitive
194
+
195
+ def match(self, candidate: str) -> float:
196
+ """
197
+ Match the candidate against the query.
198
+
199
+ Args:
200
+ candidate: Candidate string to match against the query.
201
+
202
+ Returns:
203
+ Strength of the match from 0 to 1.
204
+ """
205
+
206
+ return self.fuzzy_search.match(self.query, candidate)[0]
207
+
208
+ def highlight(self, candidate: str) -> Content:
209
+ """
210
+ Highlight the candidate with the fuzzy match.
211
+
212
+ Args:
213
+ candidate: The candidate string to match against the query.
214
+
215
+ Returns:
216
+ A [`Text`][rich.text.Text] object with highlighted matches.
217
+ """
218
+
219
+ content = Content.from_markup(candidate)
220
+ score, offsets = self.fuzzy_search.match(self.query, candidate)
221
+ if not score:
222
+ return content
223
+ for offset in offsets:
224
+ if not candidate[offset].isspace():
225
+ content = content.stylize(self._match_style, offset, offset + 1)
226
+ return content
@@ -0,0 +1,202 @@
1
+ import os
2
+ import pathlib
3
+ import typing as ta
4
+
5
+ from textual.cache import LRUCache
6
+ from textual.content import Content
7
+ from textual.widgets import Input
8
+
9
+ from .widget import AutoComplete
10
+ from .widget import AutoCompleteItem
11
+
12
+
13
+ ##
14
+
15
+
16
+ class PathAutoCompleteItem(AutoCompleteItem):
17
+ def __init__(self, completion: str, path: pathlib.Path) -> None:
18
+ super().__init__(completion)
19
+
20
+ self.path = path
21
+
22
+
23
+ def default_path_input_sort_key(item: PathAutoCompleteItem) -> tuple[bool, bool, str]:
24
+ """
25
+ Sort key function for results within the dropdown.
26
+
27
+ Args:
28
+ item: The PathAutoCompleteItem to get a sort key for.
29
+
30
+ Returns:
31
+ A tuple of (is_dotfile, is_file, lowercase_name) for sorting.
32
+ """
33
+
34
+ name = item.path.name
35
+ is_dotfile = name.startswith('.')
36
+ return (not item.path.is_dir(), not is_dotfile, name.lower())
37
+
38
+
39
+ class PathAutoComplete(AutoComplete):
40
+ def __init__(
41
+ self,
42
+ target: Input | str,
43
+ path: str | pathlib.Path = '.',
44
+ *,
45
+ show_dotfiles: bool = True,
46
+ sort_key: ta.Callable[[PathAutoCompleteItem], ta.Any] = default_path_input_sort_key,
47
+ folder_prefix: Content = Content('📂'),
48
+ file_prefix: Content = Content('📄'),
49
+ prevent_default_enter: bool = True,
50
+ prevent_default_tab: bool = True,
51
+ cache_size: int = 100,
52
+ name: str | None = None,
53
+ id: str | None = None, # noqa
54
+ classes: str | None = None,
55
+ disabled: bool = False,
56
+ ) -> None:
57
+ """
58
+ An autocomplete widget for filesystem paths.
59
+
60
+ Args:
61
+ target: The target input widget to autocomplete.
62
+ path: The base path to autocomplete from.
63
+ show_dotfiles: Whether to show dotfiles (files/dirs starting with ".").
64
+ sort_key: Function to sort the dropdown items.
65
+ folder_prefix: The prefix for folder items (e.g. 📂).
66
+ file_prefix: The prefix for file items (e.g. 📄).
67
+ prevent_default_enter: Whether to prevent the default enter behavior.
68
+ prevent_default_tab: Whether to prevent the default tab behavior.
69
+ cache_size: The number of directories to cache.
70
+ name: The name of the widget.
71
+ id: The DOM node id of the widget.
72
+ classes: The CSS classes of the widget.
73
+ disabled: Whether the widget is disabled.
74
+ """
75
+
76
+ super().__init__(
77
+ target,
78
+ None,
79
+ prevent_default_enter=prevent_default_enter,
80
+ prevent_default_tab=prevent_default_tab,
81
+ name=name,
82
+ id=id,
83
+ classes=classes,
84
+ disabled=disabled,
85
+ )
86
+
87
+ self.path = pathlib.Path(path) if isinstance(path, str) else path
88
+ self.show_dotfiles = show_dotfiles
89
+ self.sort_key = sort_key
90
+ self.folder_prefix = folder_prefix
91
+ self.file_prefix = file_prefix
92
+ self._directory_cache: LRUCache[str, list[os.DirEntry[str]]] = LRUCache(cache_size)
93
+
94
+ def get_candidates(self, target_state: AutoComplete.TargetState) -> list[AutoCompleteItem]:
95
+ """
96
+ Get the candidates for the current path segment.
97
+
98
+ This is called each time the input changes or the cursor position changes/
99
+ """
100
+
101
+ current_input = target_state.text[: target_state.cursor_position]
102
+
103
+ if '/' in current_input:
104
+ last_slash_index = current_input.rindex('/')
105
+ path_segment = current_input[:last_slash_index] or '/'
106
+ directory = self.path / path_segment if path_segment != '/' else self.path
107
+ else:
108
+ directory = self.path
109
+
110
+ # Use the directory path as the cache key
111
+ cache_key = str(directory)
112
+ cached_entries = self._directory_cache.get(cache_key)
113
+
114
+ if cached_entries is not None:
115
+ entries = cached_entries
116
+ else:
117
+ try:
118
+ entries = list(os.scandir(directory))
119
+ self._directory_cache[cache_key] = entries
120
+ except OSError:
121
+ return []
122
+
123
+ results: list[PathAutoCompleteItem] = []
124
+ for entry in entries:
125
+ # Only include the entry name, not the full path
126
+ completion = entry.name
127
+ if not self.show_dotfiles and completion.startswith('.'):
128
+ continue
129
+ if entry.is_dir():
130
+ completion += '/'
131
+ results.append(PathAutoCompleteItem(completion, path=pathlib.Path(entry.path)))
132
+
133
+ results.sort(key=self.sort_key)
134
+ folder_prefix = self.folder_prefix
135
+ file_prefix = self.file_prefix
136
+ return [
137
+ AutoCompleteItem(
138
+ item.main,
139
+ prefix=folder_prefix if item.path.is_dir() else file_prefix,
140
+ )
141
+ for item in results
142
+ ]
143
+
144
+ def get_search_string(self, target_state: AutoComplete.TargetState) -> str:
145
+ """Return only the current path segment for searching in the dropdown."""
146
+
147
+ current_input = target_state.text[: target_state.cursor_position]
148
+
149
+ if '/' in current_input:
150
+ last_slash_index = current_input.rindex('/')
151
+ search_string = current_input[last_slash_index + 1:]
152
+ return search_string
153
+ else:
154
+ return current_input
155
+
156
+ def apply_completion(self, value: str, state: AutoComplete.TargetState) -> None:
157
+ """Apply the completion by replacing only the current path segment."""
158
+
159
+ target = self.target
160
+ current_input = state.text
161
+ cursor_position = state.cursor_position
162
+
163
+ # There's a slash before the cursor, so we only want to replace the text after the last slash with the selected
164
+ # value
165
+ try:
166
+ replace_start_index = current_input.rindex('/', 0, cursor_position)
167
+ except ValueError:
168
+ # No slashes, so we do a full replacement
169
+ new_value = value
170
+ new_cursor_position = len(value)
171
+ else:
172
+ # Keep everything before and including the slash before the cursor.
173
+ path_prefix = current_input[: replace_start_index + 1]
174
+ new_value = path_prefix + value
175
+ new_cursor_position = len(path_prefix) + len(value)
176
+
177
+ with self.prevent(Input.Changed):
178
+ target.value = new_value
179
+ target.cursor_position = new_cursor_position
180
+
181
+ def post_completion(self) -> None:
182
+ if not self.target.value.endswith('/'):
183
+ self.action_hide()
184
+
185
+ def should_show_dropdown(self, search_string: str) -> bool:
186
+ return (
187
+ super().should_show_dropdown(search_string) or
188
+ (
189
+ (search_string == '' and self.target.value != '') and
190
+ self.option_list.option_count > 1
191
+ )
192
+ )
193
+
194
+ def clear_directory_cache(self) -> None:
195
+ """
196
+ Clear the directory cache. If you know that the contents of the directory have changed, you can call this method
197
+ to invalidate the cache.
198
+ """
199
+
200
+ self._directory_cache.clear()
201
+ target_state = self._get_target_state()
202
+ self._rebuild_options(target_state, self.get_search_string(target_state))