codeplain 0.2.7__tar.gz → 0.2.9__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 (192) hide show
  1. {codeplain-0.2.7 → codeplain-0.2.9}/.vscode/launch.json +1 -1
  2. {codeplain-0.2.7 → codeplain-0.2.9}/PKG-INFO +3 -3
  3. {codeplain-0.2.7 → codeplain-0.2.9}/config/system_config.yaml +1 -1
  4. {codeplain-0.2.7 → codeplain-0.2.9}/module_renderer.py +7 -2
  5. {codeplain-0.2.7 → codeplain-0.2.9}/plain2code_arguments.py +2 -1
  6. {codeplain-0.2.7 → codeplain-0.2.9}/plain2code_events.py +1 -2
  7. {codeplain-0.2.7 → codeplain-0.2.9}/pyproject.toml +6 -6
  8. {codeplain-0.2.7 → codeplain-0.2.9}/requirements.txt +2 -2
  9. {codeplain-0.2.7 → codeplain-0.2.9}/tui/components.py +14 -3
  10. {codeplain-0.2.7 → codeplain-0.2.9}/tui/plain2code_tui.py +31 -4
  11. {codeplain-0.2.7 → codeplain-0.2.9}/tui/state_handlers.py +3 -4
  12. {codeplain-0.2.7 → codeplain-0.2.9}/tui/styles.css +162 -156
  13. {codeplain-0.2.7 → codeplain-0.2.9}/tui/widget_helpers.py +3 -6
  14. {codeplain-0.2.7 → codeplain-0.2.9}/.flake8 +0 -0
  15. {codeplain-0.2.7 → codeplain-0.2.9}/.github/workflows/lint-and-test.yml +0 -0
  16. {codeplain-0.2.7 → codeplain-0.2.9}/.github/workflows/nofity-slack-on-main-merge.yml +0 -0
  17. {codeplain-0.2.7 → codeplain-0.2.9}/.github/workflows/publish-install-script.yml +0 -0
  18. {codeplain-0.2.7 → codeplain-0.2.9}/.github/workflows/publish-to-pypi.yml +0 -0
  19. {codeplain-0.2.7 → codeplain-0.2.9}/.gitignore +0 -0
  20. {codeplain-0.2.7 → codeplain-0.2.9}/.vscode/settings.json +0 -0
  21. {codeplain-0.2.7 → codeplain-0.2.9}/LICENSE +0 -0
  22. {codeplain-0.2.7 → codeplain-0.2.9}/README.md +0 -0
  23. {codeplain-0.2.7 → codeplain-0.2.9}/codeplain_REST_api.py +0 -0
  24. {codeplain-0.2.7 → codeplain-0.2.9}/concept_utils.py +0 -0
  25. {codeplain-0.2.7 → codeplain-0.2.9}/config/__init__.py +0 -0
  26. {codeplain-0.2.7 → codeplain-0.2.9}/diff_utils.py +0 -0
  27. {codeplain-0.2.7 → codeplain-0.2.9}/docs/generate_cli.py +0 -0
  28. {codeplain-0.2.7 → codeplain-0.2.9}/docs/plain2code_cli.md +0 -0
  29. {codeplain-0.2.7 → codeplain-0.2.9}/docs/plain_language_specification.md +0 -0
  30. {codeplain-0.2.7 → codeplain-0.2.9}/docs/starting_a_plain_project_from_scratch.md +0 -0
  31. {codeplain-0.2.7 → codeplain-0.2.9}/event_bus.py +0 -0
  32. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_golang/config.yaml +0 -0
  33. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_golang/harness_tests/hello_world_test.go +0 -0
  34. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_golang/hello_world_golang.plain +0 -0
  35. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_golang/run.sh +0 -0
  36. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_python/config.yaml +0 -0
  37. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +0 -0
  38. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_python/hello_world_python.plain +0 -0
  39. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_python/run.sh +0 -0
  40. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_react/config.yaml +0 -0
  41. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +0 -0
  42. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +0 -0
  43. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +0 -0
  44. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +0 -0
  45. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +0 -0
  46. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_react/hello_world_react.plain +0 -0
  47. {codeplain-0.2.7 → codeplain-0.2.9}/examples/example_hello_world_react/run.sh +0 -0
  48. {codeplain-0.2.7 → codeplain-0.2.9}/examples/run.sh +0 -0
  49. {codeplain-0.2.7 → codeplain-0.2.9}/file_utils.py +0 -0
  50. {codeplain-0.2.7 → codeplain-0.2.9}/git_utils.py +0 -0
  51. {codeplain-0.2.7 → codeplain-0.2.9}/hash_key.py +0 -0
  52. {codeplain-0.2.7 → codeplain-0.2.9}/install/examples.sh +0 -0
  53. {codeplain-0.2.7 → codeplain-0.2.9}/install/install.sh +0 -0
  54. {codeplain-0.2.7 → codeplain-0.2.9}/install/walkthrough.sh +0 -0
  55. {codeplain-0.2.7 → codeplain-0.2.9}/memory_management.py +0 -0
  56. {codeplain-0.2.7 → codeplain-0.2.9}/plain2code.py +0 -0
  57. {codeplain-0.2.7 → codeplain-0.2.9}/plain2code_console.py +0 -0
  58. {codeplain-0.2.7 → codeplain-0.2.9}/plain2code_exceptions.py +0 -0
  59. {codeplain-0.2.7 → codeplain-0.2.9}/plain2code_logger.py +0 -0
  60. {codeplain-0.2.7 → codeplain-0.2.9}/plain2code_nodes.py +0 -0
  61. {codeplain-0.2.7 → codeplain-0.2.9}/plain2code_read_config.py +0 -0
  62. {codeplain-0.2.7 → codeplain-0.2.9}/plain2code_state.py +0 -0
  63. {codeplain-0.2.7 → codeplain-0.2.9}/plain2code_utils.py +0 -0
  64. {codeplain-0.2.7 → codeplain-0.2.9}/plain_file.py +0 -0
  65. {codeplain-0.2.7 → codeplain-0.2.9}/plain_modules.py +0 -0
  66. {codeplain-0.2.7 → codeplain-0.2.9}/plain_spec.py +0 -0
  67. {codeplain-0.2.7 → codeplain-0.2.9}/pytest.ini +0 -0
  68. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/__init__.py +0 -0
  69. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/analyze_specification_ambiguity.py +0 -0
  70. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/base_action.py +0 -0
  71. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
  72. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/commit_implementation_code_changes.py +0 -0
  73. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/create_dist.py +0 -0
  74. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/exit_with_error.py +0 -0
  75. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/finish_functional_requirement.py +0 -0
  76. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/fix_conformance_test.py +0 -0
  77. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/fix_unit_tests.py +0 -0
  78. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/prepare_repositories.py +0 -0
  79. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/prepare_testing_environment.py +0 -0
  80. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/refactor_code.py +0 -0
  81. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/render_conformance_tests.py +0 -0
  82. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/render_functional_requirement.py +0 -0
  83. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/run_conformance_tests.py +0 -0
  84. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/run_unit_tests.py +0 -0
  85. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/actions/summarize_conformance_tests.py +0 -0
  86. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/code_renderer.py +0 -0
  87. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/conformance_test_helpers.py +0 -0
  88. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/conformance_tests.py +0 -0
  89. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/implementation_code_helpers.py +0 -0
  90. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/render_context.py +0 -0
  91. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/render_types.py +0 -0
  92. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/render_utils.py +0 -0
  93. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/state_machine_config.py +0 -0
  94. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/states.py +0 -0
  95. {codeplain-0.2.7 → codeplain-0.2.9}/render_machine/triggers.py +0 -0
  96. {codeplain-0.2.7 → codeplain-0.2.9}/resources/codeplain_overview.png +0 -0
  97. {codeplain-0.2.7 → codeplain-0.2.9}/resources/plain_example.png +0 -0
  98. {codeplain-0.2.7 → codeplain-0.2.9}/standard_template_library/__init__.py +0 -0
  99. {codeplain-0.2.7 → codeplain-0.2.9}/standard_template_library/golang-console-app-template.plain +0 -0
  100. {codeplain-0.2.7 → codeplain-0.2.9}/standard_template_library/python-console-app-template.plain +0 -0
  101. {codeplain-0.2.7 → codeplain-0.2.9}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
  102. {codeplain-0.2.7 → codeplain-0.2.9}/standard_template_library/typescript-react-app-template.plain +0 -0
  103. {codeplain-0.2.7 → codeplain-0.2.9}/system_config.py +0 -0
  104. {codeplain-0.2.7 → codeplain-0.2.9}/test_scripts/run_conformance_tests_cypress.sh +0 -0
  105. {codeplain-0.2.7 → codeplain-0.2.9}/test_scripts/run_conformance_tests_golang.sh +0 -0
  106. {codeplain-0.2.7 → codeplain-0.2.9}/test_scripts/run_conformance_tests_python.sh +0 -0
  107. {codeplain-0.2.7 → codeplain-0.2.9}/test_scripts/run_unittests_golang.sh +0 -0
  108. {codeplain-0.2.7 → codeplain-0.2.9}/test_scripts/run_unittests_python.sh +0 -0
  109. {codeplain-0.2.7 → codeplain-0.2.9}/test_scripts/run_unittests_react.sh +0 -0
  110. {codeplain-0.2.7 → codeplain-0.2.9}/tests/__init__.py +0 -0
  111. {codeplain-0.2.7 → codeplain-0.2.9}/tests/conftest.py +0 -0
  112. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/imports/circular_imports_1.plain +0 -0
  113. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/imports/circular_imports_2.plain +0 -0
  114. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/imports/circular_imports_main.plain +0 -0
  115. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/imports/diamond_import_1.plain +0 -0
  116. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/imports/diamond_import_2.plain +0 -0
  117. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/imports/diamond_import_common.plain +0 -0
  118. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/imports/diamond_imports_main.plain +0 -0
  119. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/imports/non_existent_import.plain +0 -0
  120. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfile/duplicate_specification_heading.plain +0 -0
  121. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfile/invalid_specification_order.plain +0 -0
  122. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfile/missing_non_functional_requirements.plain +0 -0
  123. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfile/plain_source_with_absolute_link.plain +0 -0
  124. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfile/plain_source_with_url_link.plain +0 -0
  125. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfile/task_manager_with_reference_links.plain +0 -0
  126. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfile/without_non_functional_requirement.plain +0 -0
  127. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +0 -0
  128. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +0 -0
  129. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +0 -0
  130. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +0 -0
  131. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/concept_validation_definition.plain +0 -0
  132. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/concept_validation_noconcepts.plain +0 -0
  133. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/concept_validation_nonconcept.plain +0 -0
  134. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/concept_validation_nondefined.plain +0 -0
  135. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/concept_validation_redefinition.plain +0 -0
  136. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/concept_validation_several_concepts.plain +0 -0
  137. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/concept_validation_valid.plain +0 -0
  138. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/exported_concepts.plain +0 -0
  139. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/exported_concepts_base.plain +0 -0
  140. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/exported_concepts_example.plain +0 -0
  141. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/exported_concepts_missing.plain +0 -0
  142. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/exported_concepts_missing_example.plain +0 -0
  143. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/exported_concepts_nested.plain +0 -0
  144. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/exported_concepts_nested_example.plain +0 -0
  145. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/exported_concepts_transitive_example.plain +0 -0
  146. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +0 -0
  147. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +0 -0
  148. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/plain_file_parser_with_comments.plain +0 -0
  149. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/plain_file_with_comments_indented.plain +0 -0
  150. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/regular_plain_source.plain +0 -0
  151. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/required_concepts.plain +0 -0
  152. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/required_concepts_defs.plain +0 -0
  153. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/required_concepts_example.plain +0 -0
  154. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/required_concepts_l1.plain +0 -0
  155. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/required_concepts_l2.plain +0 -0
  156. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/required_concepts_missing.plain +0 -0
  157. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/required_concepts_module.plain +0 -0
  158. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/required_concepts_partial.plain +0 -0
  159. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +0 -0
  160. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/topological_sort.plain +0 -0
  161. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/plainfileparser/topological_sort_not_referenced.plain +0 -0
  162. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/circular_requires_main.plain +0 -0
  163. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/circular_requires_sub.plain +0 -0
  164. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/diamond_requires_1.plain +0 -0
  165. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/diamond_requires_2.plain +0 -0
  166. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/diamond_requires_common.plain +0 -0
  167. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/diamond_requires_main.plain +0 -0
  168. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/independent_requires_1.plain +0 -0
  169. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/independent_requires_2.plain +0 -0
  170. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/independent_requires_main.plain +0 -0
  171. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/non_existent_require.plain +0 -0
  172. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/normal_requires_1.plain +0 -0
  173. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/normal_requires_2.plain +0 -0
  174. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/normal_requires_common.plain +0 -0
  175. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/requires/normal_requires_main.plain +0 -0
  176. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/simple.plain +0 -0
  177. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/templates/block_level_include.plain +0 -0
  178. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/templates/code_variables.plain +0 -0
  179. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/templates/header.plain +0 -0
  180. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/templates/implement.plain +0 -0
  181. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/templates/implement_2.plain +0 -0
  182. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/templates/template_include.plain +0 -0
  183. {codeplain-0.2.7 → codeplain-0.2.9}/tests/data/templates/test_hardest_problem.plain +0 -0
  184. {codeplain-0.2.7 → codeplain-0.2.9}/tests/test_git_utils.py +0 -0
  185. {codeplain-0.2.7 → codeplain-0.2.9}/tests/test_imports.py +0 -0
  186. {codeplain-0.2.7 → codeplain-0.2.9}/tests/test_plainfile.py +0 -0
  187. {codeplain-0.2.7 → codeplain-0.2.9}/tests/test_plainfileparser.py +0 -0
  188. {codeplain-0.2.7 → codeplain-0.2.9}/tests/test_plainspec.py +0 -0
  189. {codeplain-0.2.7 → codeplain-0.2.9}/tests/test_requires.py +0 -0
  190. {codeplain-0.2.7 → codeplain-0.2.9}/tui/__init__.py +0 -0
  191. {codeplain-0.2.7 → codeplain-0.2.9}/tui/models.py +0 -0
  192. {codeplain-0.2.7 → codeplain-0.2.9}/tui/spinner.py +0 -0
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.2.0",
2
+ "version": "0.2.9",
3
3
  "configurations": [
4
4
  {
5
5
  "name": "Debug plain2code.py for file hello_world_python.plain",
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeplain
3
- Version: 0.2.7
3
+ Version: 0.2.9
4
4
  Summary: Transform plain language specifications into working code
5
5
  License-File: LICENSE
6
6
  Classifier: Environment :: Console
7
7
  Classifier: Intended Audience :: Developers
8
8
  Classifier: Operating System :: OS Independent
9
9
  Classifier: Topic :: Software Development :: Code Generators
10
- Requires-Python: >=3.11
10
+ Requires-Python: ==3.11
11
11
  Requires-Dist: gitpython==3.1.42
12
12
  Requires-Dist: mistletoe==1.3.0
13
13
  Requires-Dist: networkx==3.6.1
@@ -16,7 +16,7 @@ Requires-Dist: python-liquid2==0.3.0
16
16
  Requires-Dist: pyyaml==6.0.2
17
17
  Requires-Dist: requests==2.32.4
18
18
  Requires-Dist: rich==14.2.0
19
- Requires-Dist: textual==1.0.0
19
+ Requires-Dist: textual>=7.5.0
20
20
  Requires-Dist: tiktoken==0.12.0
21
21
  Requires-Dist: transitions==0.9.3
22
22
  Provides-Extra: dev
@@ -1,4 +1,4 @@
1
- client_version: "0.2.7"
1
+ client_version: "0.17.0"
2
2
 
3
3
  error_messages:
4
4
  template_not_found:
@@ -261,5 +261,10 @@ class ModuleRenderer:
261
261
  _, _, rendering_failed = self._render_module(self.filename, self.render_range, True)
262
262
  if not rendering_failed:
263
263
  # Get the last module that completed rendering
264
- last_module_name = self.loaded_modules[-1].name if self.loaded_modules else ""
265
- self.event_bus.publish(RenderCompleted(module_name=last_module_name, build_folder=self.args.build_folder))
264
+ if self.args.copy_build:
265
+ rendered_code_path = f"{self.args.build_dest}/"
266
+ else:
267
+ last_module_name = self.filename.replace(plain_file.PLAIN_SOURCE_FILE_EXTENSION, "")
268
+ rendered_code_path = f"{os.path.join(self.args.build_folder, last_module_name)}/"
269
+
270
+ self.event_bus.publish(RenderCompleted(rendered_code_path=rendered_code_path))
@@ -15,6 +15,7 @@ DEFAULT_CONFORMANCE_TESTS_DEST = "dist_conformance_tests"
15
15
  UNIT_TESTS_SCRIPT_NAME = "unittests_script"
16
16
  CONFORMANCE_TESTS_SCRIPT_NAME = "conformance_tests_script"
17
17
  DEFAULT_LOG_FILE_NAME = "codeplain.log"
18
+ PREPARE_ENVIRONMENT_SCRIPT_NAME = "prepare_environment_script"
18
19
 
19
20
 
20
21
  def process_test_script_path(script_arg_name, config):
@@ -305,7 +306,7 @@ def parse_arguments():
305
306
  if args.full_plain and args.dry_run:
306
307
  parser.error("--full-plain and --dry-run are mutually exclusive")
307
308
 
308
- script_arg_names = [UNIT_TESTS_SCRIPT_NAME, CONFORMANCE_TESTS_SCRIPT_NAME]
309
+ script_arg_names = [UNIT_TESTS_SCRIPT_NAME, CONFORMANCE_TESTS_SCRIPT_NAME, PREPARE_ENVIRONMENT_SCRIPT_NAME]
309
310
  for script_name in script_arg_names:
310
311
  args = process_test_script_path(script_name, args)
311
312
 
@@ -28,8 +28,7 @@ class RenderContextSnapshot:
28
28
  class RenderCompleted(BaseEvent):
29
29
  """Event emitted when rendering completes successfully."""
30
30
 
31
- module_name: str
32
- build_folder: str
31
+ rendered_code_path: str
33
32
 
34
33
 
35
34
  @dataclass
@@ -4,10 +4,10 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "codeplain"
7
- version = "0.2.7"
7
+ version = "0.2.9"
8
8
  description = "Transform plain language specifications into working code"
9
9
  readme = "README.md"
10
- requires-python = ">=3.11"
10
+ requires-python = "==3.11"
11
11
  classifiers = [
12
12
  "Environment :: Console",
13
13
  "Intended Audience :: Developers",
@@ -22,10 +22,10 @@ dependencies = [
22
22
  "PyYAML==6.0.2",
23
23
  "gitpython==3.1.42",
24
24
  "transitions==0.9.3",
25
- "textual==1.0.0",
25
+ "textual>=7.5.0",
26
26
  "rich==14.2.0",
27
27
  "python-frontmatter==1.1.0",
28
- "networkx==3.6.1"
28
+ "networkx==3.6.1",
29
29
  ]
30
30
 
31
31
  [project.optional-dependencies]
@@ -46,7 +46,7 @@ include = [
46
46
  "config/**/*",
47
47
  "render_machine/**/*",
48
48
  "standard_template_library/**/*",
49
- "tui/**/*"
49
+ "tui/**/*",
50
50
  ]
51
51
 
52
52
  [tool.black]
@@ -111,4 +111,4 @@ exclude = [
111
111
  [tool.pytest.ini_options]
112
112
  pythonpath = ["src"]
113
113
  testpaths = ["tests"]
114
- norecursedirs = ["tests/data"]
114
+ norecursedirs = ["tests/data"]
@@ -7,7 +7,7 @@ tiktoken==0.12.0
7
7
  PyYAML==6.0.2
8
8
  gitpython==3.1.42
9
9
  pytest==8.3.4
10
- textual==1.0.0
10
+ textual>=7.5.0
11
11
  networkx==3.6.1
12
12
  transitions==0.9.3
13
13
 
@@ -16,4 +16,4 @@ transitions==0.9.3
16
16
  flake8==7.0.0
17
17
  black==24.3.0
18
18
  isort==5.13.2
19
- mypy==1.11.2
19
+ mypy==1.11.2
@@ -13,14 +13,23 @@ from .spinner import Spinner
13
13
  class CustomFooter(Horizontal):
14
14
  """A custom footer with keyboard shortcuts and render ID."""
15
15
 
16
+ FOOTER_TEXT = "ctrl+c: copy * ctrl+d: quit * ctrl+l: toggle logs"
17
+ RENDER_FINISHED_TEXT = "enter: exit * ctrl+c: copy * ctrl+l: toggle logs"
18
+
16
19
  def __init__(self, render_id: str = "", **kwargs):
17
20
  super().__init__(**kwargs)
18
21
  self.render_id = render_id
19
22
 
20
23
  def compose(self):
21
- yield Static("ctrl+c: quit * ctrl+l: toggle logs", classes="custom-footer-text")
24
+ self._footer_text_widget = Static(self.FOOTER_TEXT, classes="custom-footer-text")
25
+ yield self._footer_text_widget
22
26
  if self.render_id:
23
- yield Static(f"render id: {self.render_id}", classes="custom-footer-render-id")
27
+ yield Static(f"render id: {self.render_id} ", classes="custom-footer-render-id")
28
+
29
+ def show_render_finished(self) -> None:
30
+ """Update footer text to show render-finished keybindings."""
31
+ if self._footer_text_widget is not None:
32
+ self._footer_text_widget.update(self.RENDER_FINISHED_TEXT)
24
33
 
25
34
 
26
35
  class ScriptOutputType(str, Enum):
@@ -451,7 +460,9 @@ class LogEntry(Vertical):
451
460
  pass
452
461
 
453
462
  def on_click(self) -> None:
454
- """Toggle details visibility on click."""
463
+ """Toggle details visibility on click, unless text is selected."""
464
+ if self.screen.get_selected_text():
465
+ return
455
466
  try:
456
467
  details = self.query_one(f"#log-details-{id(self)}")
457
468
  indicator = self.query_one(".log-expand-indicator", Static)
@@ -4,7 +4,9 @@ import time
4
4
  from typing import Callable, Optional
5
5
 
6
6
  from textual.app import App, ComposeResult
7
+ from textual.binding import Binding
7
8
  from textual.containers import Vertical, VerticalScroll
9
+ from textual.css.query import NoMatches
8
10
  from textual.widgets import ContentSwitcher, Static
9
11
  from textual.worker import Worker, WorkerFailed, WorkerState
10
12
 
@@ -53,7 +55,9 @@ class Plain2CodeTUI(App):
53
55
  """A Textual TUI for plain2code."""
54
56
 
55
57
  BINDINGS = [
56
- ("ctrl+c", "quit", "Quit"),
58
+ Binding("ctrl+c", "copy_selection", "Copy", show=False),
59
+ Binding("ctrl+d", "quit", "Quit", show=False),
60
+ Binding("enter", "enter_exit", "Exit", show=False),
57
61
  ("ctrl+l", "toggle_logs", "Toggle Logs"),
58
62
  ]
59
63
 
@@ -77,6 +81,7 @@ class Plain2CodeTUI(App):
77
81
  self.conformance_tests_script: Optional[str] = conformance_tests_script
78
82
  self.prepare_environment_script: Optional[str] = prepare_environment_script
79
83
  self.state_machine_version = state_machine_version
84
+ self._render_finished = False
80
85
 
81
86
  # Initialize state handlers
82
87
  self._state_handlers: dict[str, StateHandler] = {
@@ -274,7 +279,13 @@ class Plain2CodeTUI(App):
274
279
 
275
280
  def on_render_completed(self, event: RenderCompleted):
276
281
  """Handle successful render completion."""
277
- self._render_success_handler.handle(event.module_name, event.build_folder)
282
+ self._render_success_handler.handle(event.rendered_code_path)
283
+ self._render_finished = True
284
+ try:
285
+ footer = self.screen.query_one(CustomFooter)
286
+ footer.show_render_finished()
287
+ except NoMatches:
288
+ pass
278
289
 
279
290
  def on_render_failed(self, event: RenderFailed):
280
291
  """Handle render failure."""
@@ -298,12 +309,28 @@ class Plain2CodeTUI(App):
298
309
  # daemon=True ensures this thread dies with the process if it exits before the timer fires
299
310
  threading.Thread(target=ensure_exit, daemon=True).start()
300
311
 
312
+ async def action_copy_selection(self) -> None:
313
+ """Handle ctrl+c: copy selected text if any.
314
+
315
+ - If text is selected -> copy it to clipboard
316
+ - If no text is selected -> do nothing
317
+ """
318
+ selected_text = self.screen.get_selected_text()
319
+ if selected_text:
320
+ self.copy_to_clipboard(selected_text)
321
+ self.screen.clear_selection()
322
+ self.notify("Copied to clipboard", timeout=2)
323
+
324
+ def action_enter_exit(self) -> None:
325
+ """Handle enter: exit the TUI only after rendering has finished."""
326
+ if self._render_finished:
327
+ self.action_quit()
328
+
301
329
  def action_quit(self) -> None:
302
- """An action to quit the application immediately when user presses 'q'.
330
+ """Quit the application immediately.
303
331
 
304
332
  Note: Force exit may leave files partially written if interrupted during file I/O operations.
305
333
  This is acceptable since the folders in which we are writing are git versioned and are reset in the next render.
306
334
  """
307
- # Show stopping message to user
308
335
  self.render_worker.cancel()
309
336
  self.exit()
@@ -299,14 +299,13 @@ class RenderSuccessHandler:
299
299
  """
300
300
  self.tui = tui
301
301
 
302
- def handle(self, module_name: str, build_folder: str) -> None:
302
+ def handle(self, rendered_code_path: str) -> None:
303
303
  """Handle successful render completion.
304
304
 
305
305
  Args:
306
- module_name: Name of the last module that completed rendering
307
- build_folder: The build folder path
306
+ rendered_code_path: The path to the rendered code
308
307
  """
309
- display_success_message(self.tui, module_name, build_folder)
308
+ display_success_message(self.tui, rendered_code_path)
310
309
 
311
310
 
312
311
  class RenderErrorHandler: