opentui 0.1.0__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 (328) hide show
  1. opentui-0.1.0/.github/workflows/create-release.yml +91 -0
  2. opentui-0.1.0/.github/workflows/quality.yml +72 -0
  3. opentui-0.1.0/.github/workflows/release.yml +206 -0
  4. opentui-0.1.0/.gitignore +58 -0
  5. opentui-0.1.0/LICENSE +21 -0
  6. opentui-0.1.0/PKG-INFO +350 -0
  7. opentui-0.1.0/README.md +289 -0
  8. opentui-0.1.0/benchmarks/__init__.py +1 -0
  9. opentui-0.1.0/benchmarks/bench_layout_pipeline.py +98 -0
  10. opentui-0.1.0/benchmarks/bench_reactivity.py +1728 -0
  11. opentui-0.1.0/benchmarks/bench_render_matrix.py +662 -0
  12. opentui-0.1.0/benchmarks/bench_text_render.py +56 -0
  13. opentui-0.1.0/benchmarks/bench_yoga_layout_shapes.py +185 -0
  14. opentui-0.1.0/benchmarks/harness.py +307 -0
  15. opentui-0.1.0/benchmarks/run_all.py +158 -0
  16. opentui-0.1.0/examples/counter.py +44 -0
  17. opentui-0.1.0/examples/dashboard.py +642 -0
  18. opentui-0.1.0/pyproject.toml +178 -0
  19. opentui-0.1.0/scripts/download_opentui.py +198 -0
  20. opentui-0.1.0/src/opentui/__init__.py +374 -0
  21. opentui-0.1.0/src/opentui/_signal_types.py +427 -0
  22. opentui-0.1.0/src/opentui/_signals_runtime.py +85 -0
  23. opentui-0.1.0/src/opentui/animation/__init__.py +20 -0
  24. opentui-0.1.0/src/opentui/animation/_runtime.py +230 -0
  25. opentui-0.1.0/src/opentui/animation/easing.py +141 -0
  26. opentui-0.1.0/src/opentui/animation/timeline.py +391 -0
  27. opentui-0.1.0/src/opentui/app.py +66 -0
  28. opentui-0.1.0/src/opentui/attachments.py +76 -0
  29. opentui-0.1.0/src/opentui/components/__init__.py +99 -0
  30. opentui-0.1.0/src/opentui/components/_control_flow_branching.py +381 -0
  31. opentui-0.1.0/src/opentui/components/_control_flow_for.py +271 -0
  32. opentui-0.1.0/src/opentui/components/_control_flow_region.py +275 -0
  33. opentui-0.1.0/src/opentui/components/_raster_cache.py +122 -0
  34. opentui-0.1.0/src/opentui/components/_reactive_binding.py +267 -0
  35. opentui-0.1.0/src/opentui/components/_renderable_base.py +735 -0
  36. opentui-0.1.0/src/opentui/components/_renderable_constants.py +104 -0
  37. opentui-0.1.0/src/opentui/components/_renderable_init.py +437 -0
  38. opentui-0.1.0/src/opentui/components/_renderable_layout.py +166 -0
  39. opentui-0.1.0/src/opentui/components/_scrollbox_state.py +358 -0
  40. opentui-0.1.0/src/opentui/components/_simple_variants.py +460 -0
  41. opentui-0.1.0/src/opentui/components/_syntax_highlight.py +370 -0
  42. opentui-0.1.0/src/opentui/components/_textnode.py +388 -0
  43. opentui-0.1.0/src/opentui/components/base.py +560 -0
  44. opentui-0.1.0/src/opentui/components/box.py +455 -0
  45. opentui-0.1.0/src/opentui/components/code_renderable.py +505 -0
  46. opentui-0.1.0/src/opentui/components/control_flow.py +422 -0
  47. opentui-0.1.0/src/opentui/components/diff/__init__.py +5 -0
  48. opentui-0.1.0/src/opentui/components/diff/diff_config.py +141 -0
  49. opentui-0.1.0/src/opentui/components/diff/diff_parser.py +142 -0
  50. opentui-0.1.0/src/opentui/components/diff/diff_renderable.py +857 -0
  51. opentui-0.1.0/src/opentui/components/diff/diff_views.py +242 -0
  52. opentui-0.1.0/src/opentui/components/framebuffer.py +160 -0
  53. opentui-0.1.0/src/opentui/components/image.py +387 -0
  54. opentui-0.1.0/src/opentui/components/input.py +106 -0
  55. opentui-0.1.0/src/opentui/components/input_renderable.py +553 -0
  56. opentui-0.1.0/src/opentui/components/line_number_gutter.py +394 -0
  57. opentui-0.1.0/src/opentui/components/line_number_renderable.py +425 -0
  58. opentui-0.1.0/src/opentui/components/line_types.py +26 -0
  59. opentui-0.1.0/src/opentui/components/markdown/__init__.py +16 -0
  60. opentui-0.1.0/src/opentui/components/markdown/markdown_blocks.py +539 -0
  61. opentui-0.1.0/src/opentui/components/markdown/markdown_parser.py +286 -0
  62. opentui-0.1.0/src/opentui/components/markdown/markdown_renderable.py +397 -0
  63. opentui-0.1.0/src/opentui/components/markdown/markdown_renderable_blocks.py +218 -0
  64. opentui-0.1.0/src/opentui/components/markdown/markdown_renderable_planning.py +158 -0
  65. opentui-0.1.0/src/opentui/components/scrollbar.py +343 -0
  66. opentui-0.1.0/src/opentui/components/scrollbox.py +464 -0
  67. opentui-0.1.0/src/opentui/components/select.py +125 -0
  68. opentui-0.1.0/src/opentui/components/select_renderable.py +435 -0
  69. opentui-0.1.0/src/opentui/components/slider_renderable.py +367 -0
  70. opentui-0.1.0/src/opentui/components/structural.py +406 -0
  71. opentui-0.1.0/src/opentui/components/tab_select_renderable.py +264 -0
  72. opentui-0.1.0/src/opentui/components/template.py +302 -0
  73. opentui-0.1.0/src/opentui/components/text.py +670 -0
  74. opentui-0.1.0/src/opentui/components/text_renderable.py +816 -0
  75. opentui-0.1.0/src/opentui/components/text_table/__init__.py +5 -0
  76. opentui-0.1.0/src/opentui/components/text_table/text_table_borders.py +247 -0
  77. opentui-0.1.0/src/opentui/components/text_table/text_table_config.py +94 -0
  78. opentui-0.1.0/src/opentui/components/text_table/text_table_fitting.py +186 -0
  79. opentui-0.1.0/src/opentui/components/text_table/text_table_renderable.py +859 -0
  80. opentui-0.1.0/src/opentui/components/text_table/text_table_selection.py +304 -0
  81. opentui-0.1.0/src/opentui/components/textarea/__init__.py +6 -0
  82. opentui-0.1.0/src/opentui/components/textarea/_text_edit_mixin.py +103 -0
  83. opentui-0.1.0/src/opentui/components/textarea/_textarea_init.py +118 -0
  84. opentui-0.1.0/src/opentui/components/textarea/_textarea_mouse.py +279 -0
  85. opentui-0.1.0/src/opentui/components/textarea/_textarea_navigation.py +375 -0
  86. opentui-0.1.0/src/opentui/components/textarea/_textarea_selection.py +177 -0
  87. opentui-0.1.0/src/opentui/components/textarea/textarea.py +206 -0
  88. opentui-0.1.0/src/opentui/components/textarea/textarea_keymap.py +146 -0
  89. opentui-0.1.0/src/opentui/components/textarea/textarea_renderable.py +817 -0
  90. opentui-0.1.0/src/opentui/components/textarea/textarea_text_utils.py +123 -0
  91. opentui-0.1.0/src/opentui/context.py +96 -0
  92. opentui-0.1.0/src/opentui/diagnostics.py +267 -0
  93. opentui-0.1.0/src/opentui/editor/__init__.py +35 -0
  94. opentui-0.1.0/src/opentui/editor/edit_buffer.py +152 -0
  95. opentui-0.1.0/src/opentui/editor/edit_buffer_native.py +384 -0
  96. opentui-0.1.0/src/opentui/editor/editor_view_native.py +302 -0
  97. opentui-0.1.0/src/opentui/editor/extmarks.py +479 -0
  98. opentui-0.1.0/src/opentui/editor/extmarks_wrappers.py +381 -0
  99. opentui-0.1.0/src/opentui/editor/syntax_style.py +270 -0
  100. opentui-0.1.0/src/opentui/editor/text_buffer_native.py +348 -0
  101. opentui-0.1.0/src/opentui/editor/text_view_native.py +167 -0
  102. opentui-0.1.0/src/opentui/enums.py +96 -0
  103. opentui-0.1.0/src/opentui/events.py +298 -0
  104. opentui-0.1.0/src/opentui/expr.py +338 -0
  105. opentui-0.1.0/src/opentui/ffi.py +144 -0
  106. opentui-0.1.0/src/opentui/hooks.py +349 -0
  107. opentui-0.1.0/src/opentui/image/__init__.py +34 -0
  108. opentui-0.1.0/src/opentui/image/encoding.py +639 -0
  109. opentui-0.1.0/src/opentui/image/filters.py +446 -0
  110. opentui-0.1.0/src/opentui/image/loader.py +121 -0
  111. opentui-0.1.0/src/opentui/image/types.py +113 -0
  112. opentui-0.1.0/src/opentui/input/__init__.py +37 -0
  113. opentui-0.1.0/src/opentui/input/_capability_parsing.py +69 -0
  114. opentui-0.1.0/src/opentui/input/_escape_parser.py +702 -0
  115. opentui-0.1.0/src/opentui/input/_mouse_protocol.py +73 -0
  116. opentui-0.1.0/src/opentui/input/event_loop.py +202 -0
  117. opentui-0.1.0/src/opentui/input/handler.py +265 -0
  118. opentui-0.1.0/src/opentui/input/key_handler.py +312 -0
  119. opentui-0.1.0/src/opentui/input/key_maps.py +314 -0
  120. opentui-0.1.0/src/opentui/input/keymapping.py +165 -0
  121. opentui-0.1.0/src/opentui/input/stdin_buffer.py +277 -0
  122. opentui-0.1.0/src/opentui/layout.py +434 -0
  123. opentui-0.1.0/src/opentui/native.py +271 -0
  124. opentui-0.1.0/src/opentui/palette/__init__.py +14 -0
  125. opentui-0.1.0/src/opentui/palette/common.py +81 -0
  126. opentui-0.1.0/src/opentui/palette/detector.py +322 -0
  127. opentui-0.1.0/src/opentui/py.typed +0 -0
  128. opentui-0.1.0/src/opentui/reconciler.py +478 -0
  129. opentui-0.1.0/src/opentui/renderer/__init__.py +34 -0
  130. opentui-0.1.0/src/opentui/renderer/_config.py +291 -0
  131. opentui-0.1.0/src/opentui/renderer/_cursor.py +102 -0
  132. opentui-0.1.0/src/opentui/renderer/_debug.py +77 -0
  133. opentui-0.1.0/src/opentui/renderer/_eventing.py +94 -0
  134. opentui-0.1.0/src/opentui/renderer/_frame_pipeline.py +166 -0
  135. opentui-0.1.0/src/opentui/renderer/_mouse_hit_testing.py +226 -0
  136. opentui-0.1.0/src/opentui/renderer/_mouse_selection.py +519 -0
  137. opentui-0.1.0/src/opentui/renderer/_native_render.py +216 -0
  138. opentui-0.1.0/src/opentui/renderer/_session.py +177 -0
  139. opentui-0.1.0/src/opentui/renderer/buffer.py +413 -0
  140. opentui-0.1.0/src/opentui/renderer/console.py +131 -0
  141. opentui-0.1.0/src/opentui/renderer/core.py +813 -0
  142. opentui-0.1.0/src/opentui/renderer/layout.py +152 -0
  143. opentui-0.1.0/src/opentui/renderer/mouse.py +367 -0
  144. opentui-0.1.0/src/opentui/renderer/native.py +227 -0
  145. opentui-0.1.0/src/opentui/renderer/repaint.py +141 -0
  146. opentui-0.1.0/src/opentui/renderer/repaint_plan.py +195 -0
  147. opentui-0.1.0/src/opentui/resource.py +173 -0
  148. opentui-0.1.0/src/opentui/selection.py +244 -0
  149. opentui-0.1.0/src/opentui/signals.py +166 -0
  150. opentui-0.1.0/src/opentui/structs.py +300 -0
  151. opentui-0.1.0/src/opentui/testing/__init__.py +9 -0
  152. opentui-0.1.0/src/opentui/testing/capture.py +365 -0
  153. opentui-0.1.0/src/opentui/testing/input.py +624 -0
  154. opentui-0.1.0/src/opentui/testing/setup.py +277 -0
  155. opentui-0.1.0/src/opentui/testing/sgr.py +413 -0
  156. opentui-0.1.0/src/opentui/text_utils.py +189 -0
  157. opentui-0.1.0/src/opentui/tree_sitter_client.py +280 -0
  158. opentui-0.1.0/src/opentui/tree_sitter_queries/javascript/highlights.scm +205 -0
  159. opentui-0.1.0/src/opentui/tree_sitter_queries/markdown/highlights.scm +150 -0
  160. opentui-0.1.0/src/opentui/tree_sitter_queries/markdown_inline/highlights.scm +128 -0
  161. opentui-0.1.0/src/opentui/tree_sitter_queries/typescript/highlights.scm +604 -0
  162. opentui-0.1.0/src/opentui/tree_sitter_queries/zig/highlights.scm +284 -0
  163. opentui-0.1.0/src/opentui/viewport.py +146 -0
  164. opentui-0.1.0/src/opentui_bindings/CMakeLists.txt +89 -0
  165. opentui-0.1.0/src/opentui_bindings/bindings.cpp +52 -0
  166. opentui-0.1.0/src/opentui_bindings/border_draw.h +93 -0
  167. opentui-0.1.0/src/opentui_bindings/buffer.cpp +351 -0
  168. opentui-0.1.0/src/opentui_bindings/common_render.cpp +538 -0
  169. opentui-0.1.0/src/opentui_bindings/edit_buffer.cpp +205 -0
  170. opentui-0.1.0/src/opentui_bindings/editor_view.cpp +301 -0
  171. opentui-0.1.0/src/opentui_bindings/graphics.cpp +70 -0
  172. opentui-0.1.0/src/opentui_bindings/hit_grid.cpp +31 -0
  173. opentui-0.1.0/src/opentui_bindings/native_signals.cpp +295 -0
  174. opentui-0.1.0/src/opentui_bindings/native_signals.h +64 -0
  175. opentui-0.1.0/src/opentui_bindings/reconciler_patch.cpp +208 -0
  176. opentui-0.1.0/src/opentui_bindings/renderer.cpp +207 -0
  177. opentui-0.1.0/src/opentui_bindings/slot_utils.h +31 -0
  178. opentui-0.1.0/src/opentui_bindings/text_buffer.cpp +390 -0
  179. opentui-0.1.0/src/opentui_bindings/types.cpp +134 -0
  180. opentui-0.1.0/src/opentui_bindings/yoga_configure.cpp +822 -0
  181. opentui-0.1.0/src/opentui_bindings/yoga_configure.h +129 -0
  182. opentui-0.1.0/tests/__init__.py +0 -0
  183. opentui-0.1.0/tests/conftest.py +73 -0
  184. opentui-0.1.0/tests/integration/__init__.py +0 -0
  185. opentui-0.1.0/tests/integration/test_absolute_positioning.py +898 -0
  186. opentui-0.1.0/tests/integration/test_buffer_diff.py +100 -0
  187. opentui-0.1.0/tests/integration/test_destroy_during_render.py +290 -0
  188. opentui-0.1.0/tests/integration/test_framebuffer.py +39 -0
  189. opentui-0.1.0/tests/integration/test_hover_cursor.py +126 -0
  190. opentui-0.1.0/tests/integration/test_opacity.py +95 -0
  191. opentui-0.1.0/tests/integration/test_renderable.py +1072 -0
  192. opentui-0.1.0/tests/integration/test_renderable_snapshot.py +312 -0
  193. opentui-0.1.0/tests/integration/test_renderer_control.py +558 -0
  194. opentui-0.1.0/tests/integration/test_renderer_destroy_during_render.py +179 -0
  195. opentui-0.1.0/tests/integration/test_renderer_focus.py +452 -0
  196. opentui-0.1.0/tests/integration/test_renderer_focus_restore.py +306 -0
  197. opentui-0.1.0/tests/integration/test_renderer_idle.py +439 -0
  198. opentui-0.1.0/tests/integration/test_renderer_input.py +2008 -0
  199. opentui-0.1.0/tests/integration/test_renderer_kitty_flags.py +156 -0
  200. opentui-0.1.0/tests/integration/test_renderer_mouse.py +1277 -0
  201. opentui-0.1.0/tests/integration/test_renderer_palette.py +827 -0
  202. opentui-0.1.0/tests/integration/test_renderer_selection.py +51 -0
  203. opentui-0.1.0/tests/integration/test_renderer_use_mouse.py +46 -0
  204. opentui-0.1.0/tests/integration/test_scrollbox.py +2127 -0
  205. opentui-0.1.0/tests/integration/test_scrollbox_culling_bug.py +116 -0
  206. opentui-0.1.0/tests/integration/test_scrollbox_hitgrid.py +1117 -0
  207. opentui-0.1.0/tests/integration/test_selection_overlay.py +230 -0
  208. opentui-0.1.0/tests/integration/test_terminal_lifecycle.py +36 -0
  209. opentui-0.1.0/tests/integration/test_text_component.py +339 -0
  210. opentui-0.1.0/tests/integration/test_wrap_resize_perf.py +162 -0
  211. opentui-0.1.0/tests/integration/test_yoga_setters.py +1098 -0
  212. opentui-0.1.0/tests/lib/__init__.py +0 -0
  213. opentui-0.1.0/tests/lib/test_border.py +77 -0
  214. opentui-0.1.0/tests/lib/test_clipboard.py +136 -0
  215. opentui-0.1.0/tests/lib/test_detect_links.py +84 -0
  216. opentui-0.1.0/tests/lib/test_extmarks.py +2564 -0
  217. opentui-0.1.0/tests/lib/test_extmarks_multiwidth.py +226 -0
  218. opentui-0.1.0/tests/lib/test_key_handler.py +484 -0
  219. opentui-0.1.0/tests/lib/test_key_handler_integration.py +248 -0
  220. opentui-0.1.0/tests/lib/test_key_handler_stop_propagation.py +251 -0
  221. opentui-0.1.0/tests/lib/test_keymapping.py +249 -0
  222. opentui-0.1.0/tests/lib/test_objects_in_viewport.py +605 -0
  223. opentui-0.1.0/tests/lib/test_palette.py +1291 -0
  224. opentui-0.1.0/tests/lib/test_parse_keypress.py +1832 -0
  225. opentui-0.1.0/tests/lib/test_parse_keypress_kitty.py +927 -0
  226. opentui-0.1.0/tests/lib/test_parse_mouse.py +814 -0
  227. opentui-0.1.0/tests/lib/test_renderable_validations.py +78 -0
  228. opentui-0.1.0/tests/lib/test_rgba.py +804 -0
  229. opentui-0.1.0/tests/lib/test_selection.py +595 -0
  230. opentui-0.1.0/tests/lib/test_stdin_buffer.py +819 -0
  231. opentui-0.1.0/tests/lib/test_tree_sitter_client.py +327 -0
  232. opentui-0.1.0/tests/lib/test_tree_sitter_queries.py +103 -0
  233. opentui-0.1.0/tests/lib/test_tree_sitter_styled_text.py +544 -0
  234. opentui-0.1.0/tests/lib/test_yoga_options.py +267 -0
  235. opentui-0.1.0/tests/renderables/__init__.py +0 -0
  236. opentui-0.1.0/tests/renderables/test_base_dirty_paths.py +62 -0
  237. opentui-0.1.0/tests/renderables/test_box.py +131 -0
  238. opentui-0.1.0/tests/renderables/test_code.py +2595 -0
  239. opentui-0.1.0/tests/renderables/test_diff.py +1787 -0
  240. opentui-0.1.0/tests/renderables/test_diff_regression.py +142 -0
  241. opentui-0.1.0/tests/renderables/test_input.py +705 -0
  242. opentui-0.1.0/tests/renderables/test_line_number.py +1356 -0
  243. opentui-0.1.0/tests/renderables/test_line_number_scrollbox.py +654 -0
  244. opentui-0.1.0/tests/renderables/test_line_number_scrollbox_simple.py +164 -0
  245. opentui-0.1.0/tests/renderables/test_line_number_wrapping.py +100 -0
  246. opentui-0.1.0/tests/renderables/test_markdown.py +1552 -0
  247. opentui-0.1.0/tests/renderables/test_markdown_parser.py +232 -0
  248. opentui-0.1.0/tests/renderables/test_multi_renderable_selection.py +112 -0
  249. opentui-0.1.0/tests/renderables/test_select.py +753 -0
  250. opentui-0.1.0/tests/renderables/test_slider.py +581 -0
  251. opentui-0.1.0/tests/renderables/test_tab_select.py +178 -0
  252. opentui-0.1.0/tests/renderables/test_text.py +1875 -0
  253. opentui-0.1.0/tests/renderables/test_text_dirty_paths.py +45 -0
  254. opentui-0.1.0/tests/renderables/test_text_selection_buffer.py +133 -0
  255. opentui-0.1.0/tests/renderables/test_text_table.py +1468 -0
  256. opentui-0.1.0/tests/renderables/test_textarea_buffer.py +568 -0
  257. opentui-0.1.0/tests/renderables/test_textarea_destroyed_events.py +465 -0
  258. opentui-0.1.0/tests/renderables/test_textarea_editing.py +1115 -0
  259. opentui-0.1.0/tests/renderables/test_textarea_error_handling.py +24 -0
  260. opentui-0.1.0/tests/renderables/test_textarea_events.py +628 -0
  261. opentui-0.1.0/tests/renderables/test_textarea_highlights.py +619 -0
  262. opentui-0.1.0/tests/renderables/test_textarea_keybinding.py +1993 -0
  263. opentui-0.1.0/tests/renderables/test_textarea_paste.py +234 -0
  264. opentui-0.1.0/tests/renderables/test_textarea_rendering.py +1807 -0
  265. opentui-0.1.0/tests/renderables/test_textarea_scroll.py +927 -0
  266. opentui-0.1.0/tests/renderables/test_textarea_selection.py +1885 -0
  267. opentui-0.1.0/tests/renderables/test_textarea_stress.py +518 -0
  268. opentui-0.1.0/tests/renderables/test_textarea_undo_redo.py +270 -0
  269. opentui-0.1.0/tests/renderables/test_textarea_visual_lines.py +247 -0
  270. opentui-0.1.0/tests/renderables/test_textnode.py +1032 -0
  271. opentui-0.1.0/tests/solid/__init__.py +0 -0
  272. opentui-0.1.0/tests/solid/test_box.py +105 -0
  273. opentui-0.1.0/tests/solid/test_context.py +255 -0
  274. opentui-0.1.0/tests/solid/test_control_flow.py +2226 -0
  275. opentui-0.1.0/tests/solid/test_cursor_behavior.py +643 -0
  276. opentui-0.1.0/tests/solid/test_diff.py +342 -0
  277. opentui-0.1.0/tests/solid/test_dynamic_collections.py +590 -0
  278. opentui-0.1.0/tests/solid/test_error_boundary.py +636 -0
  279. opentui-0.1.0/tests/solid/test_events.py +922 -0
  280. opentui-0.1.0/tests/solid/test_layout.py +429 -0
  281. opentui-0.1.0/tests/solid/test_lazy_and_switch_direct.py +334 -0
  282. opentui-0.1.0/tests/solid/test_line_number.py +137 -0
  283. opentui-0.1.0/tests/solid/test_line_number_scrollbox.py +614 -0
  284. opentui-0.1.0/tests/solid/test_link.py +551 -0
  285. opentui-0.1.0/tests/solid/test_portal.py +662 -0
  286. opentui-0.1.0/tests/solid/test_scrollbox_cleanchildren.py +848 -0
  287. opentui-0.1.0/tests/solid/test_scrollbox_content.py +437 -0
  288. opentui-0.1.0/tests/solid/test_sticky_scroll.py +233 -0
  289. opentui-0.1.0/tests/solid/test_text_elements.py +182 -0
  290. opentui-0.1.0/tests/solid/test_textarea.py +1183 -0
  291. opentui-0.1.0/tests/test_attachment_normalization.py +75 -0
  292. opentui-0.1.0/tests/test_buffer.py +462 -0
  293. opentui-0.1.0/tests/test_console.py +735 -0
  294. opentui-0.1.0/tests/test_diagnostics.py +400 -0
  295. opentui-0.1.0/tests/test_edit_buffer.py +1479 -0
  296. opentui-0.1.0/tests/test_editor_view.py +1265 -0
  297. opentui-0.1.0/tests/test_expr.py +445 -0
  298. opentui-0.1.0/tests/test_ffi.py +355 -0
  299. opentui-0.1.0/tests/test_ffi_behavior.py +246 -0
  300. opentui-0.1.0/tests/test_filters.py +241 -0
  301. opentui-0.1.0/tests/test_graphics.py +406 -0
  302. opentui-0.1.0/tests/test_hooks_registration.py +138 -0
  303. opentui-0.1.0/tests/test_image_api.py +58 -0
  304. opentui-0.1.0/tests/test_image_cache.py +63 -0
  305. opentui-0.1.0/tests/test_image_component.py +889 -0
  306. opentui-0.1.0/tests/test_image_loader.py +137 -0
  307. opentui-0.1.0/tests/test_new_features.py +234 -0
  308. opentui-0.1.0/tests/test_paste_events.py +47 -0
  309. opentui-0.1.0/tests/test_reactive_props.py +1423 -0
  310. opentui-0.1.0/tests/test_reconciler.py +335 -0
  311. opentui-0.1.0/tests/test_render_strategy.py +128 -0
  312. opentui-0.1.0/tests/test_scrollbar.py +250 -0
  313. opentui-0.1.0/tests/test_select_component.py +209 -0
  314. opentui-0.1.0/tests/test_signals.py +1275 -0
  315. opentui-0.1.0/tests/test_syntax_style.py +635 -0
  316. opentui-0.1.0/tests/test_text_buffer.py +379 -0
  317. opentui-0.1.0/tests/test_text_buffer_view.py +613 -0
  318. opentui-0.1.0/tests/test_text_selection.py +220 -0
  319. opentui-0.1.0/tests/test_text_utils.py +80 -0
  320. opentui-0.1.0/tests/test_timeline.py +2852 -0
  321. opentui-0.1.0/tests/test_viewport.py +200 -0
  322. opentui-0.1.0/tests/testing/__init__.py +0 -0
  323. opentui-0.1.0/tests/testing/test_capture_spans.py +192 -0
  324. opentui-0.1.0/tests/testing/test_integration.py +225 -0
  325. opentui-0.1.0/tests/testing/test_mock_keys.py +1105 -0
  326. opentui-0.1.0/tests/testing/test_mock_mouse.py +177 -0
  327. opentui-0.1.0/tests/testing/test_test_recorder.py +428 -0
  328. opentui-0.1.0/uv.lock +458 -0
@@ -0,0 +1,91 @@
1
+ name: Create Release Tag
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ release_type:
7
+ description: 'Release type'
8
+ required: true
9
+ type: choice
10
+ options:
11
+ - patch
12
+ - minor
13
+ - major
14
+ default: patch
15
+
16
+ jobs:
17
+ create-tag:
18
+ runs-on: ubuntu-latest
19
+ permissions:
20
+ contents: write
21
+
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ with:
25
+ fetch-depth: 0
26
+ token: ${{ secrets.RELEASE_TOKEN }}
27
+
28
+ - name: Configure Git
29
+ run: |
30
+ git config user.name "${{ github.actor }}"
31
+ git config user.email "${{ github.actor }}@users.noreply.github.com"
32
+
33
+ - name: Get current version and calculate next version
34
+ id: version
35
+ run: |
36
+ CURRENT_VERSION=$(grep "^version = " pyproject.toml | cut -d'"' -f2)
37
+ echo "Current version: $CURRENT_VERSION"
38
+
39
+ if [ -z "$CURRENT_VERSION" ]; then
40
+ echo "Error: Could not extract version"
41
+ exit 1
42
+ fi
43
+
44
+ IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION"
45
+
46
+ RELEASE_TYPE="${{ inputs.release_type }}"
47
+ case $RELEASE_TYPE in
48
+ major)
49
+ NEW_MAJOR=$((MAJOR + 1)); NEW_MINOR=0; NEW_PATCH=0
50
+ ;;
51
+ minor)
52
+ NEW_MAJOR=$MAJOR; NEW_MINOR=$((MINOR + 1)); NEW_PATCH=0
53
+ ;;
54
+ patch)
55
+ NEW_MAJOR=$MAJOR; NEW_MINOR=$MINOR; NEW_PATCH=$((PATCH + 1))
56
+ ;;
57
+ esac
58
+
59
+ NEW_VERSION="$NEW_MAJOR.$NEW_MINOR.$NEW_PATCH"
60
+
61
+ echo "Current: $CURRENT_VERSION -> New: $NEW_VERSION ($RELEASE_TYPE)"
62
+ echo "current=$CURRENT_VERSION" >> $GITHUB_OUTPUT
63
+ echo "new=$NEW_VERSION" >> $GITHUB_OUTPUT
64
+
65
+ - name: Check if version already exists
66
+ run: |
67
+ VERSION="v${{ steps.version.outputs.new }}"
68
+ if git rev-parse "$VERSION" >/dev/null 2>&1; then
69
+ echo "Tag $VERSION already exists!"
70
+ exit 1
71
+ fi
72
+ echo "Tag $VERSION does not exist"
73
+
74
+ - name: Update version in pyproject.toml
75
+ run: |
76
+ VERSION="${{ steps.version.outputs.new }}"
77
+ sed -i "s/^version = .*/version = \"$VERSION\"/" pyproject.toml
78
+ grep "^version = " pyproject.toml
79
+
80
+ - name: Commit and push
81
+ run: |
82
+ git add pyproject.toml
83
+ git commit -m "chore: bump version to ${{ steps.version.outputs.new }}"
84
+ git push origin main
85
+
86
+ - name: Create and push tag
87
+ run: |
88
+ VERSION="v${{ steps.version.outputs.new }}"
89
+ git tag -a "$VERSION" -m "Release $VERSION"
90
+ git push origin "$VERSION"
91
+ echo "Created tag $VERSION - this will trigger release workflow"
@@ -0,0 +1,72 @@
1
+ name: Code Quality
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ quality:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.12", "3.13"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v4
21
+
22
+ - name: Set up Python ${{ matrix.python-version }}
23
+ run: uv python install ${{ matrix.python-version }}
24
+
25
+ - name: Download OpenTUI native library
26
+ run: python scripts/download_opentui.py
27
+
28
+ - name: Install dependencies
29
+ run: uv sync --all-extras
30
+
31
+ - name: Lint with ruff
32
+ run: |
33
+ uv run ruff check
34
+ uv run ruff format --check
35
+
36
+ - name: Type check with ty
37
+ run: uv run ty check
38
+
39
+ - name: Run tests
40
+ run: uv run pytest tests/ -v --tb=short
41
+
42
+ quality-check:
43
+ runs-on: ubuntu-latest
44
+ needs: quality
45
+ steps:
46
+ - name: All quality checks passed
47
+ run: echo "All quality checks passed!"
48
+
49
+ release-build-smoke:
50
+ name: Release build (sdist + Linux wheel)
51
+ runs-on: ubuntu-latest
52
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+ - name: Install uv
56
+ uses: astral-sh/setup-uv@v4
57
+ - name: Build sdist
58
+ run: pip install -q build validate-pyproject && validate-pyproject pyproject.toml && python -m build --sdist
59
+ - name: Build one Linux wheel (cibuildwheel smoke)
60
+ uses: pypa/cibuildwheel@v2.22.0
61
+ env:
62
+ CIBW_BUILD: "cp312-*"
63
+ CIBW_SKIP: "*-win* *-macos* *-manylinux_i686 *-musllinux_*"
64
+ CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
65
+ CIBW_BEFORE_ALL_LINUX: "dnf install -y git && python {project}/scripts/download_opentui.py && cp {project}/src/opentui/opentui-libs/libopentui.so /usr/local/lib/ && ldconfig"
66
+ CIBW_ENVIRONMENT_LINUX: "LD_LIBRARY_PATH={project}/src/opentui/opentui-libs"
67
+ CIBW_BUILD_FRONTEND: "build[uv]"
68
+ CIBW_BUILD_VERBOSITY: "3"
69
+ CIBW_ENVIRONMENT_PASS_LINUX: "GIT_TERMINAL_PROMPT"
70
+ GIT_TERMINAL_PROMPT: "0"
71
+ - name: List artifacts
72
+ run: ls -la wheelhouse/ dist/
@@ -0,0 +1,206 @@
1
+ name: Release to PyPI and GitHub
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ version:
10
+ description: "Version to release (e.g., 0.1.0)"
11
+ required: true
12
+ type: string
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ jobs:
18
+ build_wheels:
19
+ name: Build wheels (${{ matrix.os }})
20
+ runs-on: ${{ matrix.runs-on }}
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ include:
25
+ - os: linux-x86_64
26
+ runs-on: ubuntu-22.04
27
+ cibw_archs: x86_64
28
+ - os: linux-aarch64
29
+ runs-on: ubuntu-22.04
30
+ cibw_archs: aarch64
31
+ - os: macos-arm64
32
+ runs-on: macos-14
33
+ cibw_archs: arm64
34
+ - os: macos-x86_64
35
+ runs-on: macos-14
36
+ cibw_archs: x86_64
37
+
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+ with:
41
+ fetch-depth: 0
42
+
43
+ - name: Set up QEMU (Linux aarch64)
44
+ if: matrix.cibw_archs == 'aarch64'
45
+ uses: docker/setup-qemu-action@v3
46
+
47
+ - name: Install uv
48
+ uses: astral-sh/setup-uv@v4
49
+
50
+ - name: Build wheels
51
+ uses: pypa/cibuildwheel@v2.22.0
52
+ env:
53
+ CIBW_BUILD: "cp312-* cp313-*"
54
+ CIBW_SKIP: "*-manylinux_i686 *-musllinux_*"
55
+ CIBW_ARCHS_LINUX: ${{ matrix.cibw_archs }}
56
+ CIBW_ARCHS_MACOS: ${{ matrix.cibw_archs }}
57
+ CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
58
+ CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28
59
+ CIBW_BEFORE_ALL_LINUX: "dnf install -y git && python {project}/scripts/download_opentui.py && cp {project}/src/opentui/opentui-libs/libopentui.so /usr/local/lib/ && ldconfig"
60
+ CIBW_BEFORE_ALL_MACOS: "python {project}/scripts/download_opentui.py --force --arch ${{ matrix.cibw_archs }} && sudo mkdir -p /usr/local/lib && sudo cp {project}/src/opentui/opentui-libs/libopentui.dylib /usr/local/lib/"
61
+ CIBW_ENVIRONMENT_LINUX: "LD_LIBRARY_PATH={project}/src/opentui/opentui-libs"
62
+ CIBW_ENVIRONMENT_MACOS: "MACOSX_DEPLOYMENT_TARGET=13.0"
63
+ CIBW_TEST_REQUIRES: "pytest pytest-asyncio"
64
+ CIBW_TEST_COMMAND: "pytest {project}/tests -v --tb=short -x"
65
+ CIBW_TEST_SKIP: "*-macosx_x86_64"
66
+ CIBW_ENVIRONMENT_PASS_LINUX: "GIT_TERMINAL_PROMPT"
67
+ GIT_TERMINAL_PROMPT: "0"
68
+ CIBW_BUILD_FRONTEND: "build[uv]"
69
+ CIBW_BUILD_VERBOSITY: "1"
70
+
71
+ - uses: actions/upload-artifact@v4
72
+ with:
73
+ name: wheels-${{ matrix.os }}
74
+ path: wheelhouse/*.whl
75
+
76
+ build_sdist:
77
+ name: Build sdist
78
+ runs-on: ubuntu-latest
79
+ steps:
80
+ - uses: actions/checkout@v4
81
+ with:
82
+ fetch-depth: 0
83
+
84
+ - name: Install build
85
+ run: pip install -q build
86
+
87
+ - name: Validate pyproject.toml
88
+ run: pip install -q validate-pyproject && validate-pyproject pyproject.toml
89
+
90
+ - name: Build sdist
91
+ run: python -m build --sdist
92
+
93
+ - uses: actions/upload-artifact@v4
94
+ with:
95
+ name: sdist
96
+ path: dist/*.tar.gz
97
+
98
+ publish-to-pypi:
99
+ name: Publish to PyPI
100
+ needs: [build_wheels, build_sdist]
101
+ runs-on: ubuntu-latest
102
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
103
+ environment:
104
+ name: pypi
105
+ url: https://pypi.org/p/opentui
106
+ permissions:
107
+ id-token: write
108
+ contents: write
109
+
110
+ steps:
111
+ - name: Download all artifacts
112
+ uses: actions/download-artifact@v4
113
+ with:
114
+ path: dist
115
+ merge-multiple: true
116
+
117
+ - name: Flatten dist
118
+ run: |
119
+ mkdir -p dist/merged
120
+ find dist -maxdepth 3 -type f \( -name "*.whl" -o -name "*.tar.gz" \) -exec cp {} dist/merged/ \;
121
+ rm -rf dist/wheels-* dist/sdist
122
+ mv dist/merged/* dist/
123
+ rmdir dist/merged
124
+ ls -la dist/
125
+
126
+ - name: Publish to PyPI
127
+ uses: pypa/gh-action-pypi-publish@release/v1
128
+ with:
129
+ print-hash: true
130
+
131
+ publish-to-testpypi:
132
+ name: Publish to TestPyPI
133
+ needs: [build_wheels, build_sdist]
134
+ runs-on: ubuntu-latest
135
+ if: github.event_name == 'workflow_dispatch'
136
+ environment:
137
+ name: test-pypi
138
+ url: https://test.pypi.org/p/opentui
139
+ permissions:
140
+ id-token: write
141
+
142
+ steps:
143
+ - name: Download all artifacts
144
+ uses: actions/download-artifact@v4
145
+ with:
146
+ path: dist
147
+ merge-multiple: true
148
+
149
+ - name: Flatten dist
150
+ run: |
151
+ mkdir -p dist/merged
152
+ find dist -maxdepth 3 -type f \( -name "*.whl" -o -name "*.tar.gz" \) -exec cp {} dist/merged/ \;
153
+ rm -rf dist/wheels-* dist/sdist
154
+ mv dist/merged/* dist/
155
+ rmdir dist/merged
156
+ ls -la dist/
157
+
158
+ - name: Publish to TestPyPI
159
+ uses: pypa/gh-action-pypi-publish@release/v1
160
+ with:
161
+ repository-url: https://test.pypi.org/legacy/
162
+ print-hash: true
163
+
164
+ create-github-release:
165
+ name: Create GitHub Release
166
+ needs: [publish-to-pypi]
167
+ runs-on: ubuntu-latest
168
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
169
+ permissions:
170
+ contents: write
171
+
172
+ steps:
173
+ - uses: actions/checkout@v4
174
+ with:
175
+ fetch-depth: 0
176
+
177
+ - name: Download all artifacts
178
+ uses: actions/download-artifact@v4
179
+ with:
180
+ path: dist
181
+ merge-multiple: true
182
+
183
+ - name: Flatten dist for release upload
184
+ run: |
185
+ mkdir -p release_assets
186
+ find dist -maxdepth 3 -type f \( -name "*.whl" -o -name "*.tar.gz" \) -exec cp {} release_assets/ \;
187
+ ls -la release_assets/
188
+
189
+ - name: Determine release type
190
+ id: release-type
191
+ run: |
192
+ if [[ ${{ github.ref_name }} =~ -alpha|-beta|-rc ]]; then
193
+ echo "prerelease=true" >> $GITHUB_OUTPUT
194
+ else
195
+ echo "prerelease=false" >> $GITHUB_OUTPUT
196
+ fi
197
+
198
+ - name: Create GitHub Release
199
+ run: |
200
+ gh release create ${{ github.ref_name }} \
201
+ --title "opentui ${{ github.ref_name }}" \
202
+ --generate-notes \
203
+ ${{ steps.release-type.outputs.prerelease == 'true' && '--prerelease' || '--latest' }} \
204
+ release_assets/*
205
+ env:
206
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,58 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ *.egg
8
+
9
+ # Virtual environments
10
+ .venv/
11
+
12
+ # IDE
13
+ .idea/
14
+ .vscode/
15
+ *.swp
16
+ *.swo
17
+ .claude/
18
+ # Build artifacts
19
+ src/opentui/opentui-libs/
20
+ src/opentui_bindings/build/
21
+ *.so
22
+ *.dylib
23
+ *.pyd
24
+ _skbuild/
25
+ CMakeCache.txt
26
+ CMakeFiles/
27
+
28
+ # Coverage
29
+ .coverage
30
+ htmlcov/
31
+
32
+ # Cache
33
+ .ruff_cache/
34
+ .mypy_cache/
35
+ .pytest_cache/
36
+
37
+ # OS
38
+ .DS_Store
39
+
40
+ # Reference upstream source (not for distribution)
41
+ reference/
42
+
43
+ # Internal docs and planning (not for distribution)
44
+ docs/
45
+ AGENTS.md
46
+ PLAN.md
47
+ progress.md
48
+ buffer_dump/
49
+
50
+ # Diagnostics
51
+ opentui-debug.log
52
+
53
+ # Benchmark baselines (machine-specific)
54
+ benchmarks/baselines/
55
+
56
+ # Issue tracking
57
+ .beads/
58
+
opentui-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 firefly
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.