codeplain 0.2.6__tar.gz → 0.2.7__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 (193) hide show
  1. {codeplain-0.2.6 → codeplain-0.2.7}/PKG-INFO +1 -1
  2. {codeplain-0.2.6 → codeplain-0.2.7}/config/system_config.yaml +1 -1
  3. codeplain-0.2.7/docs/plain2code_cli.md +63 -0
  4. {codeplain-0.2.6 → codeplain-0.2.7}/git_utils.py +20 -0
  5. {codeplain-0.2.6 → codeplain-0.2.7}/install/walkthrough.sh +47 -50
  6. {codeplain-0.2.6 → codeplain-0.2.7}/module_renderer.py +3 -1
  7. {codeplain-0.2.6 → codeplain-0.2.7}/plain2code.py +43 -5
  8. {codeplain-0.2.6 → codeplain-0.2.7}/plain2code_arguments.py +24 -20
  9. {codeplain-0.2.6 → codeplain-0.2.7}/plain2code_events.py +3 -1
  10. {codeplain-0.2.6 → codeplain-0.2.7}/plain2code_utils.py +5 -5
  11. {codeplain-0.2.6 → codeplain-0.2.7}/pyproject.toml +1 -1
  12. {codeplain-0.2.6 → codeplain-0.2.7}/tui/plain2code_tui.py +7 -7
  13. {codeplain-0.2.6 → codeplain-0.2.7}/tui/state_handlers.py +9 -4
  14. {codeplain-0.2.6 → codeplain-0.2.7}/tui/widget_helpers.py +14 -3
  15. codeplain-0.2.6/docs/plain2code_cli.md +0 -66
  16. {codeplain-0.2.6 → codeplain-0.2.7}/.flake8 +0 -0
  17. {codeplain-0.2.6 → codeplain-0.2.7}/.github/workflows/lint-and-test.yml +0 -0
  18. {codeplain-0.2.6 → codeplain-0.2.7}/.github/workflows/nofity-slack-on-main-merge.yml +0 -0
  19. {codeplain-0.2.6 → codeplain-0.2.7}/.github/workflows/publish-install-script.yml +0 -0
  20. {codeplain-0.2.6 → codeplain-0.2.7}/.github/workflows/publish-to-pypi.yml +0 -0
  21. {codeplain-0.2.6 → codeplain-0.2.7}/.gitignore +0 -0
  22. {codeplain-0.2.6 → codeplain-0.2.7}/.vscode/launch.json +0 -0
  23. {codeplain-0.2.6 → codeplain-0.2.7}/.vscode/settings.json +0 -0
  24. {codeplain-0.2.6 → codeplain-0.2.7}/LICENSE +0 -0
  25. {codeplain-0.2.6 → codeplain-0.2.7}/README.md +0 -0
  26. {codeplain-0.2.6 → codeplain-0.2.7}/codeplain_REST_api.py +0 -0
  27. {codeplain-0.2.6 → codeplain-0.2.7}/concept_utils.py +0 -0
  28. {codeplain-0.2.6 → codeplain-0.2.7}/config/__init__.py +0 -0
  29. {codeplain-0.2.6 → codeplain-0.2.7}/diff_utils.py +0 -0
  30. {codeplain-0.2.6 → codeplain-0.2.7}/docs/generate_cli.py +0 -0
  31. {codeplain-0.2.6 → codeplain-0.2.7}/docs/plain_language_specification.md +0 -0
  32. {codeplain-0.2.6 → codeplain-0.2.7}/docs/starting_a_plain_project_from_scratch.md +0 -0
  33. {codeplain-0.2.6 → codeplain-0.2.7}/event_bus.py +0 -0
  34. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_golang/config.yaml +0 -0
  35. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_golang/harness_tests/hello_world_test.go +0 -0
  36. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_golang/hello_world_golang.plain +0 -0
  37. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_golang/run.sh +0 -0
  38. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_python/config.yaml +0 -0
  39. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +0 -0
  40. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_python/hello_world_python.plain +0 -0
  41. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_python/run.sh +0 -0
  42. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_react/config.yaml +0 -0
  43. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +0 -0
  44. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +0 -0
  45. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +0 -0
  46. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +0 -0
  47. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +0 -0
  48. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_react/hello_world_react.plain +0 -0
  49. {codeplain-0.2.6 → codeplain-0.2.7}/examples/example_hello_world_react/run.sh +0 -0
  50. {codeplain-0.2.6 → codeplain-0.2.7}/examples/run.sh +0 -0
  51. {codeplain-0.2.6 → codeplain-0.2.7}/file_utils.py +0 -0
  52. {codeplain-0.2.6 → codeplain-0.2.7}/hash_key.py +0 -0
  53. {codeplain-0.2.6 → codeplain-0.2.7}/install/examples.sh +0 -0
  54. {codeplain-0.2.6 → codeplain-0.2.7}/install/install.sh +0 -0
  55. {codeplain-0.2.6 → codeplain-0.2.7}/memory_management.py +0 -0
  56. {codeplain-0.2.6 → codeplain-0.2.7}/plain2code_console.py +0 -0
  57. {codeplain-0.2.6 → codeplain-0.2.7}/plain2code_exceptions.py +0 -0
  58. {codeplain-0.2.6 → codeplain-0.2.7}/plain2code_logger.py +0 -0
  59. {codeplain-0.2.6 → codeplain-0.2.7}/plain2code_nodes.py +0 -0
  60. {codeplain-0.2.6 → codeplain-0.2.7}/plain2code_read_config.py +0 -0
  61. {codeplain-0.2.6 → codeplain-0.2.7}/plain2code_state.py +0 -0
  62. {codeplain-0.2.6 → codeplain-0.2.7}/plain_file.py +0 -0
  63. {codeplain-0.2.6 → codeplain-0.2.7}/plain_modules.py +0 -0
  64. {codeplain-0.2.6 → codeplain-0.2.7}/plain_spec.py +0 -0
  65. {codeplain-0.2.6 → codeplain-0.2.7}/pytest.ini +0 -0
  66. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/__init__.py +0 -0
  67. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/analyze_specification_ambiguity.py +0 -0
  68. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/base_action.py +0 -0
  69. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
  70. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/commit_implementation_code_changes.py +0 -0
  71. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/create_dist.py +0 -0
  72. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/exit_with_error.py +0 -0
  73. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/finish_functional_requirement.py +0 -0
  74. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/fix_conformance_test.py +0 -0
  75. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/fix_unit_tests.py +0 -0
  76. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/prepare_repositories.py +0 -0
  77. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/prepare_testing_environment.py +0 -0
  78. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/refactor_code.py +0 -0
  79. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/render_conformance_tests.py +0 -0
  80. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/render_functional_requirement.py +0 -0
  81. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/run_conformance_tests.py +0 -0
  82. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/run_unit_tests.py +0 -0
  83. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/actions/summarize_conformance_tests.py +0 -0
  84. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/code_renderer.py +0 -0
  85. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/conformance_test_helpers.py +0 -0
  86. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/conformance_tests.py +0 -0
  87. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/implementation_code_helpers.py +0 -0
  88. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/render_context.py +0 -0
  89. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/render_types.py +0 -0
  90. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/render_utils.py +0 -0
  91. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/state_machine_config.py +0 -0
  92. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/states.py +0 -0
  93. {codeplain-0.2.6 → codeplain-0.2.7}/render_machine/triggers.py +0 -0
  94. {codeplain-0.2.6 → codeplain-0.2.7}/requirements.txt +0 -0
  95. {codeplain-0.2.6 → codeplain-0.2.7}/resources/codeplain_overview.png +0 -0
  96. {codeplain-0.2.6 → codeplain-0.2.7}/resources/plain_example.png +0 -0
  97. {codeplain-0.2.6 → codeplain-0.2.7}/standard_template_library/__init__.py +0 -0
  98. {codeplain-0.2.6 → codeplain-0.2.7}/standard_template_library/golang-console-app-template.plain +0 -0
  99. {codeplain-0.2.6 → codeplain-0.2.7}/standard_template_library/python-console-app-template.plain +0 -0
  100. {codeplain-0.2.6 → codeplain-0.2.7}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
  101. {codeplain-0.2.6 → codeplain-0.2.7}/standard_template_library/typescript-react-app-template.plain +0 -0
  102. {codeplain-0.2.6 → codeplain-0.2.7}/system_config.py +0 -0
  103. {codeplain-0.2.6 → codeplain-0.2.7}/test_scripts/run_conformance_tests_cypress.sh +0 -0
  104. {codeplain-0.2.6 → codeplain-0.2.7}/test_scripts/run_conformance_tests_golang.sh +0 -0
  105. {codeplain-0.2.6 → codeplain-0.2.7}/test_scripts/run_conformance_tests_python.sh +0 -0
  106. {codeplain-0.2.6 → codeplain-0.2.7}/test_scripts/run_unittests_golang.sh +0 -0
  107. {codeplain-0.2.6 → codeplain-0.2.7}/test_scripts/run_unittests_python.sh +0 -0
  108. {codeplain-0.2.6 → codeplain-0.2.7}/test_scripts/run_unittests_react.sh +0 -0
  109. {codeplain-0.2.6 → codeplain-0.2.7}/tests/__init__.py +0 -0
  110. {codeplain-0.2.6 → codeplain-0.2.7}/tests/conftest.py +0 -0
  111. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/imports/circular_imports_1.plain +0 -0
  112. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/imports/circular_imports_2.plain +0 -0
  113. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/imports/circular_imports_main.plain +0 -0
  114. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/imports/diamond_import_1.plain +0 -0
  115. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/imports/diamond_import_2.plain +0 -0
  116. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/imports/diamond_import_common.plain +0 -0
  117. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/imports/diamond_imports_main.plain +0 -0
  118. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/imports/non_existent_import.plain +0 -0
  119. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfile/duplicate_specification_heading.plain +0 -0
  120. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfile/invalid_specification_order.plain +0 -0
  121. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfile/missing_non_functional_requirements.plain +0 -0
  122. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfile/plain_source_with_absolute_link.plain +0 -0
  123. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfile/plain_source_with_url_link.plain +0 -0
  124. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfile/task_manager_with_reference_links.plain +0 -0
  125. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfile/without_non_functional_requirement.plain +0 -0
  126. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +0 -0
  127. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +0 -0
  128. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +0 -0
  129. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +0 -0
  130. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/concept_validation_definition.plain +0 -0
  131. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/concept_validation_noconcepts.plain +0 -0
  132. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/concept_validation_nonconcept.plain +0 -0
  133. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/concept_validation_nondefined.plain +0 -0
  134. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/concept_validation_redefinition.plain +0 -0
  135. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/concept_validation_several_concepts.plain +0 -0
  136. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/concept_validation_valid.plain +0 -0
  137. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/exported_concepts.plain +0 -0
  138. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/exported_concepts_base.plain +0 -0
  139. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/exported_concepts_example.plain +0 -0
  140. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/exported_concepts_missing.plain +0 -0
  141. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/exported_concepts_missing_example.plain +0 -0
  142. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/exported_concepts_nested.plain +0 -0
  143. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/exported_concepts_nested_example.plain +0 -0
  144. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/exported_concepts_transitive_example.plain +0 -0
  145. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +0 -0
  146. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +0 -0
  147. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/plain_file_parser_with_comments.plain +0 -0
  148. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/plain_file_with_comments_indented.plain +0 -0
  149. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/regular_plain_source.plain +0 -0
  150. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/required_concepts.plain +0 -0
  151. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/required_concepts_defs.plain +0 -0
  152. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/required_concepts_example.plain +0 -0
  153. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/required_concepts_l1.plain +0 -0
  154. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/required_concepts_l2.plain +0 -0
  155. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/required_concepts_missing.plain +0 -0
  156. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/required_concepts_module.plain +0 -0
  157. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/required_concepts_partial.plain +0 -0
  158. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +0 -0
  159. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/topological_sort.plain +0 -0
  160. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/plainfileparser/topological_sort_not_referenced.plain +0 -0
  161. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/circular_requires_main.plain +0 -0
  162. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/circular_requires_sub.plain +0 -0
  163. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/diamond_requires_1.plain +0 -0
  164. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/diamond_requires_2.plain +0 -0
  165. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/diamond_requires_common.plain +0 -0
  166. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/diamond_requires_main.plain +0 -0
  167. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/independent_requires_1.plain +0 -0
  168. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/independent_requires_2.plain +0 -0
  169. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/independent_requires_main.plain +0 -0
  170. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/non_existent_require.plain +0 -0
  171. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/normal_requires_1.plain +0 -0
  172. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/normal_requires_2.plain +0 -0
  173. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/normal_requires_common.plain +0 -0
  174. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/requires/normal_requires_main.plain +0 -0
  175. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/simple.plain +0 -0
  176. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/templates/block_level_include.plain +0 -0
  177. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/templates/code_variables.plain +0 -0
  178. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/templates/header.plain +0 -0
  179. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/templates/implement.plain +0 -0
  180. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/templates/implement_2.plain +0 -0
  181. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/templates/template_include.plain +0 -0
  182. {codeplain-0.2.6 → codeplain-0.2.7}/tests/data/templates/test_hardest_problem.plain +0 -0
  183. {codeplain-0.2.6 → codeplain-0.2.7}/tests/test_git_utils.py +0 -0
  184. {codeplain-0.2.6 → codeplain-0.2.7}/tests/test_imports.py +0 -0
  185. {codeplain-0.2.6 → codeplain-0.2.7}/tests/test_plainfile.py +0 -0
  186. {codeplain-0.2.6 → codeplain-0.2.7}/tests/test_plainfileparser.py +0 -0
  187. {codeplain-0.2.6 → codeplain-0.2.7}/tests/test_plainspec.py +0 -0
  188. {codeplain-0.2.6 → codeplain-0.2.7}/tests/test_requires.py +0 -0
  189. {codeplain-0.2.6 → codeplain-0.2.7}/tui/__init__.py +0 -0
  190. {codeplain-0.2.6 → codeplain-0.2.7}/tui/components.py +0 -0
  191. {codeplain-0.2.6 → codeplain-0.2.7}/tui/models.py +0 -0
  192. {codeplain-0.2.6 → codeplain-0.2.7}/tui/spinner.py +0 -0
  193. {codeplain-0.2.6 → codeplain-0.2.7}/tui/styles.css +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeplain
3
- Version: 0.2.6
3
+ Version: 0.2.7
4
4
  Summary: Transform plain language specifications into working code
5
5
  License-File: LICENSE
6
6
  Classifier: Environment :: Console
@@ -1,4 +1,4 @@
1
- client_version: "0.2.6"
1
+ client_version: "0.2.7"
2
2
 
3
3
  error_messages:
4
4
  template_not_found:
@@ -0,0 +1,63 @@
1
+ # Plain2Code CLI Reference
2
+
3
+ ```text
4
+ usage: generate_cli.py [-h] [--verbose] [--base-folder BASE_FOLDER] [--build-folder BUILD_FOLDER] [--log-to-file | --no-log-to-file] [--log-file-name LOG_FILE_NAME] [--config-name CONFIG_NAME] [--render-range RENDER_RANGE | --render-from RENDER_FROM] [--force-render]
5
+ [--unittests-script UNITTESTS_SCRIPT] [--conformance-tests-folder CONFORMANCE_TESTS_FOLDER] [--conformance-tests-script CONFORMANCE_TESTS_SCRIPT] [--prepare-environment-script PREPARE_ENVIRONMENT_SCRIPT] [--api [API]] [--api-key API_KEY]
6
+ [--full-plain] [--dry-run] [--replay-with REPLAY_WITH] [--template-dir TEMPLATE_DIR] [--copy-build] [--build-dest BUILD_DEST] [--copy-conformance-tests] [--conformance-tests-dest CONFORMANCE_TESTS_DEST] [--render-machine-graph]
7
+ [--logging-config-path]
8
+ filename
9
+
10
+ Render plain code to target code.
11
+
12
+ positional arguments:
13
+ filename Path to the plain file to render. The directory containing this file has highest precedence for template loading, so you can place custom templates here to override the defaults. See --template-dir for more details about template loading.
14
+
15
+ options:
16
+ -h, --help show this help message and exit
17
+ --verbose, -v Enable verbose output
18
+ --base-folder BASE_FOLDER
19
+ Base folder for the build files
20
+ --build-folder BUILD_FOLDER
21
+ Folder for build files
22
+ --log-to-file, --no-log-to-file
23
+ Enable logging to a file. Defaults to True. Use --no-log-to-file to disable.
24
+ --log-file-name LOG_FILE_NAME
25
+ Name of the log file. Defaults to 'codeplain.log'.Always resolved relative to the plain file directory.If file on this path already exists, it will be overwritten by the current logs.
26
+ --render-range RENDER_RANGE
27
+ Specify a range of functional requirements to render (e.g. '1.1,2.3'). Use comma to separate start and end IDs. If only one ID is provided, only that requirement is rendered. Range is inclusive of both start and end IDs.
28
+ --render-from RENDER_FROM
29
+ Continue generation starting from this specific functional requirement (e.g. '2.1'). The requirement with this ID will be included in the output. The ID must match one of the functional requirements in your plain file.
30
+ --force-render Force re-render of all the required modules.
31
+ --unittests-script UNITTESTS_SCRIPT
32
+ Shell script to run unit tests on generated code. Receives the build folder path as its first argument (default: 'plain_modules').
33
+ --conformance-tests-folder CONFORMANCE_TESTS_FOLDER
34
+ Folder for conformance test files
35
+ --conformance-tests-script CONFORMANCE_TESTS_SCRIPT
36
+ Path to conformance tests shell script. The script should accept two arguments: 1) First argument: path to a folder (e.g. 'plain_modules/module_name') containing generated source code, 2) Second argument: path to a subfolder of the conformance
37
+ tests folder (e.g. 'conformance_tests/subfoldername') containing test files.
38
+ --prepare-environment-script PREPARE_ENVIRONMENT_SCRIPT
39
+ Path to a shell script that prepares the testing environment. The script should accept the build folder path as its first argument (default: 'plain_modules').
40
+ --api [API] Alternative base URL for the API. Default: `https://api.codeplain.ai`
41
+ --api-key API_KEY API key used to access the API. If not provided, the CODEPLAIN_API_KEY environment variable is used.
42
+ --full-plain Display the complete plain specification before code generation. This shows your plain file with any included template content expanded. Useful for understanding what content is being processed.
43
+ --dry-run Preview of what Codeplain would do without actually making any changes.
44
+ --replay-with REPLAY_WITH
45
+ --template-dir TEMPLATE_DIR
46
+ Path to a custom template directory. Templates are searched in the following order: 1) directory containing the plain file, 2) this custom template directory (if provided), 3) built-in standard_template_library directory
47
+ --copy-build If set, copy the build folder to `--build-dest` after every successful rendering.
48
+ --build-dest BUILD_DEST
49
+ Target folder to copy build output to (used only if --copy-build is set).
50
+ --copy-conformance-tests
51
+ If set, copy the conformance tests folder to `--conformance-tests-dest` after every successful rendering. Requires --conformance-tests-script.
52
+ --conformance-tests-dest CONFORMANCE_TESTS_DEST
53
+ Target folder to copy conformance tests output to (used only if --copy-conformance-tests is set).
54
+ --render-machine-graph
55
+ If set, render the state machine graph.
56
+ --logging-config-path
57
+ Path to the logging configuration file.
58
+
59
+ configuration:
60
+ --config-name CONFIG_NAME
61
+ Path to the config file, defaults to config.yaml
62
+
63
+ ```
@@ -1,4 +1,5 @@
1
1
  import os
2
+ from configparser import NoOptionError, NoSectionError
2
3
  from typing import Optional, Union
3
4
 
4
5
  from git import Repo
@@ -42,6 +43,24 @@ def _get_full_commit_message(message, module_name, frid, render_id) -> str:
42
43
  return full_message
43
44
 
44
45
 
46
+ def _ensure_git_config(repo: Repo) -> None:
47
+ config = repo.config_reader()
48
+
49
+ try:
50
+ config.get_value("user", "name")
51
+ except (NoSectionError, NoOptionError):
52
+ # user.name not configured, set a default at repo level
53
+ with repo.config_writer(config_level="repository") as writer:
54
+ writer.set_value("user", "name", "Codeplain")
55
+
56
+ try:
57
+ config.get_value("user", "email")
58
+ except (NoSectionError, NoOptionError):
59
+ # user.email not configured, set a default at repo level
60
+ with repo.config_writer(config_level="repository") as writer:
61
+ writer.set_value("user", "email", "codeplain@localhost")
62
+
63
+
45
64
  def init_git_repo(
46
65
  path_to_repo: Union[str, os.PathLike], module_name: Optional[str] = None, render_id: Optional[str] = None
47
66
  ) -> Repo:
@@ -56,6 +75,7 @@ def init_git_repo(
56
75
  os.makedirs(path_to_repo)
57
76
 
58
77
  repo = Repo.init(path_to_repo)
78
+ _ensure_git_config(repo)
59
79
  repo.git.commit(
60
80
  "--allow-empty", "-m", _get_full_commit_message(INITIAL_COMMIT_MESSAGE, module_name, None, render_id)
61
81
  )
@@ -13,13 +13,13 @@ NC="${NC:-\033[0m}"
13
13
  # Onboarding Step 1: Introduction to Plain
14
14
  clear
15
15
  echo ""
16
- echo -e "${GRAY}────────────────────────────────────────────${NC}"
17
- echo -e " ${YELLOW}${BOLD}quick intro to ***plain specification language${NC} - Step 1 of 5"
18
- echo -e "${GRAY}────────────────────────────────────────────${NC}"
16
+ echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}"
17
+ echo -e " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 1 of 5"
18
+ echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}"
19
19
  echo ""
20
- echo -e " ***plain is a language of spec-driven development that allows developers to express intent on any level of detail."
20
+ echo -e " ***plain is a language of spec-driven development that allows developers to express intent at any level of detail."
21
21
  echo ""
22
- echo -e " write specs in ${YELLOW}plain English${NC}, in markdown with additional syntax"
22
+ echo -e " write specs in natural language extended with additional syntax based on markdown."
23
23
  echo ""
24
24
  echo -e " render production-ready code with *codeplain."
25
25
  echo ""
@@ -28,8 +28,8 @@ echo ""
28
28
  echo -e "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}"
29
29
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
30
30
  echo -e "${GRAY} │${NC} ${YELLOW}***definitions***${NC} - key concepts in your app ${GRAY}│${NC}"
31
- echo -e "${GRAY} │${NC} ${YELLOW}***implementation reqs***${NC} - implementation details ${GRAY}│${NC}"
32
- echo -e "${GRAY} │${NC} ${YELLOW}***test reqs***${NC} - testing requirements ${GRAY}│${NC}"
31
+ echo -e "${GRAY} │${NC} ${YELLOW}***implementation reqs***${NC} - implementation details ${GRAY}│${NC}"
32
+ echo -e "${GRAY} │${NC} ${YELLOW}***test reqs***${NC} - testing requirements ${GRAY}│${NC}"
33
33
  echo -e "${GRAY} │${NC} ${YELLOW}***functional specs***${NC} - what the app should do ${GRAY}│${NC}"
34
34
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
35
35
  echo -e "${GRAY} └────────────────────────────────────────────────────────┘${NC}"
@@ -41,33 +41,32 @@ read -r -p " press [Enter] to continue..." < /dev/tty
41
41
  # Onboarding Step 2: Functional Specification
42
42
  clear
43
43
  echo ""
44
- echo -e "${GRAY}────────────────────────────────────────────${NC}"
45
- echo -e " ${YELLOW}${BOLD}Plain Language 101${NC} - Step 2 of 5"
46
- echo -e "${GRAY}────────────────────────────────────────────${NC}"
44
+ echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}"
45
+ echo -e " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 2 of 5"
46
+ echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}"
47
47
  echo ""
48
48
  echo -e " ${WHITE}${BOLD}FUNCTIONAL SPECS${NC} - what should the app do?"
49
49
  echo ""
50
50
  echo -e " This is where you describe ${GREEN}what your app should do${NC},"
51
- echo -e " written in plain English. No code, just requirements."
51
+ echo -e " written in natural language. No code, just requirements."
52
52
  echo ""
53
53
  echo -e "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}"
54
54
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
55
- echo -e "${GRAY} │${NC} ${GRAY}***definitions***${NC} ${GRAY}│${NC}"
55
+ echo -e "${GRAY} │${NC} ${GRAY}***definitions***${NC} ${GRAY}│${NC}"
56
56
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
57
- echo -e "${GRAY} │${NC} ${GRAY}- :App: is a console application.${NC} ${GRAY}│${NC}"
57
+ echo -e "${GRAY} │${NC} ${GRAY}- :App: is a console application.${NC} ${GRAY}│${NC}"
58
58
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
59
- echo -e "${GRAY} │${NC} ${GRAY}***implementation reqs***${NC} ${GRAY}│${NC}"
59
+ echo -e "${GRAY} │${NC} ${GRAY}***implementation reqs***${NC} ${GRAY}│${NC}"
60
60
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
61
- echo -e "${GRAY} │${NC} ${GRAY}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}"
62
- echo -e "${GRAY} │${NC} ${GRAY}- :UnitTests: should use Unittest framework.${NC} ${GRAY}│${NC}"
61
+ echo -e "${GRAY} │${NC} ${GRAY}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}"
63
62
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
64
- echo -e "${GRAY} │${NC} ${GRAY}***test reqs***${NC} ${GRAY}│${NC}"
63
+ echo -e "${GRAY} │${NC} ${GRAY}***test reqs***${NC} ${GRAY}│${NC}"
65
64
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
66
- echo -e "${GRAY} │${NC} ${GRAY}- :ConformanceTests: should use Unittest.${NC} ${GRAY}│${NC}"
65
+ echo -e "${GRAY} │${NC} ${GRAY}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}"
67
66
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
68
- echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***functional specs***${NC} ${GRAY}│${NC}"
67
+ echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***functional specs***${NC} ${GRAY}│${NC}"
69
68
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
70
- echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :App: should display \"hello, world\".${NC} ${GRAY}│${NC}"
69
+ echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :App: should display \"hello, world\".${NC} ${GRAY}│${NC}"
71
70
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
72
71
  echo -e "${GRAY} └────────────────────────────────────────────────────────┘${NC}"
73
72
  echo ""
@@ -79,37 +78,36 @@ read -r -p " press [Enter] to continue..." < /dev/tty
79
78
  # Onboarding Step 3: Definitions
80
79
  clear
81
80
  echo ""
82
- echo -e "${GRAY}────────────────────────────────────────────${NC}"
83
- echo -e " ${YELLOW}${BOLD}Plain Language 101${NC} - Step 3 of 5"
84
- echo -e "${GRAY}────────────────────────────────────────────${NC}"
81
+ echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}"
82
+ echo -e " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 3 of 5"
83
+ echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}"
85
84
  echo ""
86
- echo -e " ${WHITE}${BOLD}DEFINITIONS${NC} - identify key concepts"
85
+ echo -e " ${WHITE}${BOLD}DEFINITIONS${NC} - definitions and descriptions of key concepts"
87
86
  echo ""
88
- echo -e " Define ${GREEN}reusable concepts${NC} with the ${YELLOW}:ConceptName:${NC} syntax."
87
+ echo -e " Define ${GREEN}reusable concepts${NC} using the ${YELLOW}:Concept:${NC} notation."
89
88
  echo -e " These become building blocks you can reference anywhere."
90
89
  echo ""
91
90
  echo -e "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}"
92
91
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
93
- echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***definitions***${NC} ${GRAY}│${NC}"
92
+ echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***definitions***${NC} ${GRAY}│${NC}"
94
93
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
95
- echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :App: is a console application.${NC} ${GRAY}│${NC}"
94
+ echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :App: is a console application.${NC} ${GRAY}│${NC}"
96
95
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
97
- echo -e "${GRAY} │${NC} ${GRAY}***implementation reqs***${NC} ${GRAY}│${NC}"
96
+ echo -e "${GRAY} │${NC} ${GRAY}***implementation reqs***${NC} ${GRAY}│${NC}"
98
97
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
99
- echo -e "${GRAY} │${NC} ${GRAY}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}"
100
- echo -e "${GRAY} │${NC} ${GRAY}- :UnitTests: should use Unittest framework.${NC} ${GRAY}│${NC}"
98
+ echo -e "${GRAY} │${NC} ${GRAY}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}"
101
99
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
102
- echo -e "${GRAY} │${NC} ${GRAY}***test reqs***${NC} ${GRAY}│${NC}"
100
+ echo -e "${GRAY} │${NC} ${GRAY}***test reqs***${NC} ${GRAY}│${NC}"
103
101
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
104
- echo -e "${GRAY} │${NC} ${GRAY}- :ConformanceTests: should use Unittest.${NC} ${GRAY}│${NC}"
102
+ echo -e "${GRAY} │${NC} ${GRAY}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}"
105
103
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
106
- echo -e "${GRAY} │${NC} ${GRAY}***functional specs***${NC} ${GRAY}│${NC}"
104
+ echo -e "${GRAY} │${NC} ${GRAY}***functional specs***${NC} ${GRAY}│${NC}"
107
105
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
108
- echo -e "${GRAY} │${NC} ${GRAY}- :App: should display \"hello, world\".${NC} ${GRAY}│${NC}"
106
+ echo -e "${GRAY} │${NC} ${GRAY}- :App: should display \"hello, world\".${NC} ${GRAY}│${NC}"
109
107
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
110
108
  echo -e "${GRAY} └────────────────────────────────────────────────────────┘${NC}"
111
109
  echo ""
112
- echo -e " ${GREEN}▲${NC} The ${YELLOW}:App:${NC} concept is defined once and used throughout."
110
+ echo -e " ${GREEN}▲${NC} The ${YELLOW}:App:${NC} concept is defined once and used throughout the specs."
113
111
  echo -e " Concepts help keep your specs consistent and clear."
114
112
  echo ""
115
113
  read -r -p " press [Enter] to continue..." < /dev/tty
@@ -117,9 +115,9 @@ read -r -p " press [Enter] to continue..." < /dev/tty
117
115
  # Onboarding Step 4: Implementation & Test Reqs
118
116
  clear
119
117
  echo ""
120
- echo -e "${GRAY}────────────────────────────────────────────${NC}"
121
- echo -e " ${YELLOW}${BOLD}Plain Language 101${NC} - Step 4 of 5"
122
- echo -e "${GRAY}────────────────────────────────────────────${NC}"
118
+ echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}"
119
+ echo -e " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 4 of 5"
120
+ echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}"
123
121
  echo ""
124
122
  echo -e " ${WHITE}${BOLD}IMPLEMENTATION & TEST REQS${NC} - how to implement and test"
125
123
  echo ""
@@ -128,22 +126,21 @@ echo -e " This guides how the code should be generated and verified."
128
126
  echo ""
129
127
  echo -e "${GRAY} ┌────────────────────────────────────────────────────────┐${NC}"
130
128
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
131
- echo -e "${GRAY} │${NC} ${GRAY}***definitions***${NC} ${GRAY}│${NC}"
129
+ echo -e "${GRAY} │${NC} ${GRAY}***definitions***${NC} ${GRAY}│${NC}"
132
130
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
133
- echo -e "${GRAY} │${NC} ${GRAY}- :App: is a console application.${NC} ${GRAY}│${NC}"
131
+ echo -e "${GRAY} │${NC} ${GRAY}- :App: is a console application.${NC} ${GRAY}│${NC}"
134
132
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
135
- echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***implementation reqs***${NC} ${GRAY}│${NC}"
133
+ echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***implementation reqs***${NC} ${GRAY}│${NC}"
136
134
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
137
- echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}"
138
- echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :UnitTests: should use Unittest framework.${NC} ${GRAY}│${NC}"
135
+ echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :Implementation: should be in Python.${NC} ${GRAY}│${NC}"
139
136
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
140
- echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***test reqs***${NC} ${GRAY}│${NC}"
137
+ echo -e "${GRAY} │${NC} ${YELLOW}${BOLD}***test reqs***${NC} ${GRAY}│${NC}"
141
138
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
142
- echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :ConformanceTests: should use Unittest.${NC} ${GRAY}│${NC}"
139
+ echo -e "${GRAY} │${NC} ${GREEN}${BOLD}- :ConformanceTests: should use pytest.${NC} ${GRAY}│${NC}"
143
140
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
144
- echo -e "${GRAY} │${NC} ${GRAY}***functional specs***${NC} ${GRAY}│${NC}"
141
+ echo -e "${GRAY} │${NC} ${GRAY}***functional specs***${NC} ${GRAY}│${NC}"
145
142
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
146
- echo -e "${GRAY} │${NC} ${GRAY}- :App: should display \"hello, world\".${NC} ${GRAY}│${NC}"
143
+ echo -e "${GRAY} │${NC} ${GRAY}- :App: should display \"hello, world\".${NC} ${GRAY}│${NC}"
147
144
  echo -e "${GRAY} │${NC} ${GRAY}│${NC}"
148
145
  echo -e "${GRAY} └────────────────────────────────────────────────────────┘${NC}"
149
146
  echo ""
@@ -155,9 +152,9 @@ read -r -p " press [Enter] to continue..." < /dev/tty
155
152
  # Onboarding Step 5: Rendering Code
156
153
  clear
157
154
  echo ""
158
- echo -e "${GRAY}────────────────────────────────────────────${NC}"
159
- echo -e " ${YELLOW}${BOLD}Plain Language 101${NC} - Step 5 of 5"
160
- echo -e "${GRAY}────────────────────────────────────────────${NC}"
155
+ echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}"
156
+ echo -e " ${YELLOW}${BOLD}***plain specification language intro${NC} - Step 5 of 5"
157
+ echo -e "${GRAY}─────────────────────────────────────────────────────────${NC}"
161
158
  echo ""
162
159
  echo -e " ${WHITE}${BOLD}RENDERING CODE${NC} - generate your app"
163
160
  echo ""
@@ -260,4 +260,6 @@ class ModuleRenderer:
260
260
  self.loaded_modules = list[PlainModule]()
261
261
  _, _, rendering_failed = self._render_module(self.filename, self.render_range, True)
262
262
  if not rendering_failed:
263
- self.event_bus.publish(RenderCompleted())
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))
@@ -3,6 +3,7 @@ import logging
3
3
  import logging.config
4
4
  import os
5
5
  import sys
6
+ from pathlib import Path
6
7
  from typing import Optional
7
8
 
8
9
  import yaml
@@ -42,6 +43,7 @@ from plain2code_logger import (
42
43
  get_log_file_path,
43
44
  )
44
45
  from plain2code_state import RunState
46
+ from plain2code_utils import print_dry_run_output
45
47
  from system_config import system_config
46
48
  from tui.plain2code_tui import Plain2CodeTUI
47
49
 
@@ -72,6 +74,23 @@ def get_render_range_from(start, plain_source):
72
74
  return _get_frids_range(plain_source, start)
73
75
 
74
76
 
77
+ def compute_render_range(args, plain_source_tree):
78
+ """Compute render range from --render-range or --render-from arguments.
79
+
80
+ Args:
81
+ args: Parsed command line arguments
82
+ plain_source_tree: Parsed plain source tree
83
+
84
+ Returns:
85
+ List of FRIDs to render, or None to render all
86
+ """
87
+ if args.render_range:
88
+ return get_render_range(args.render_range, plain_source_tree)
89
+ elif args.render_from:
90
+ return get_render_range_from(args.render_from, plain_source_tree)
91
+ return None
92
+
93
+
75
94
  def _get_frids_range(plain_source, start, end=None):
76
95
  frids = list(plain_spec.get_frids(plain_source))
77
96
 
@@ -196,11 +215,7 @@ def render(args, run_state: RunState, event_bus: EventBus): # noqa: C901
196
215
  if args.render_range or args.render_from:
197
216
  # Parse the plain file to get the plain_source for FRID extraction
198
217
  _, plain_source, _ = plain_file.plain_file_parser(args.filename, template_dirs)
199
-
200
- if args.render_range:
201
- render_range = get_render_range(args.render_range, plain_source)
202
- elif args.render_from:
203
- render_range = get_render_range_from(args.render_from, plain_source)
218
+ render_range = compute_render_range(args, plain_source)
204
219
 
205
220
  codeplainAPI = codeplain_api.CodeplainAPI(args.api_key, console)
206
221
  codeplainAPI.verbose = args.verbose
@@ -242,6 +257,29 @@ def render(args, run_state: RunState, event_bus: EventBus): # noqa: C901
242
257
  def main(): # noqa: C901
243
258
  args = parse_arguments()
244
259
 
260
+ # Handle early-exit flags before heavy initialization
261
+ if args.dry_run or args.full_plain:
262
+ template_dirs = file_utils.get_template_directories(args.filename, args.template_dir, DEFAULT_TEMPLATE_DIRS)
263
+
264
+ try:
265
+ if args.full_plain:
266
+ module_name = Path(args.filename).stem
267
+ plain_source = plain_file.read_module_plain_source(module_name, template_dirs)
268
+ [full_plain_source, _] = file_utils.get_loaded_templates(template_dirs, plain_source)
269
+ console.info("Full plain text:\n")
270
+ console.info(full_plain_source)
271
+ return
272
+
273
+ if args.dry_run:
274
+ console.info("Printing dry run output...\n")
275
+ _, plain_source_tree, _ = plain_file.plain_file_parser(args.filename, template_dirs)
276
+ render_range = compute_render_range(args, plain_source_tree)
277
+ print_dry_run_output(plain_source_tree, render_range)
278
+ return
279
+ except Exception as e:
280
+ console.error(f"Error: {str(e)}")
281
+ return
282
+
245
283
  event_bus = EventBus()
246
284
 
247
285
  if not args.api:
@@ -134,7 +134,7 @@ def create_parser():
134
134
  "--log-to-file",
135
135
  action=argparse.BooleanOptionalAction,
136
136
  default=True,
137
- help="Enable logging to a file. Defaults to True. Use --no-log-to-file to disable.",
137
+ help="Enable logging to a file. Defaults to True. Set to False to disable.",
138
138
  )
139
139
  parser.add_argument(
140
140
  "--log-file-name",
@@ -142,7 +142,7 @@ def create_parser():
142
142
  default=DEFAULT_LOG_FILE_NAME,
143
143
  help=f"Name of the log file. Defaults to '{DEFAULT_LOG_FILE_NAME}'."
144
144
  "Always resolved relative to the plain file directory."
145
- "If file on this path already exists, it will be overwritten by the current logs.",
145
+ "If file on this path already exists, the already existing log file will be overwritten by the current logs.",
146
146
  )
147
147
 
148
148
  # Add config file arguments
@@ -158,14 +158,14 @@ def create_parser():
158
158
  render_range_group.add_argument(
159
159
  "--render-range",
160
160
  type=frid_range_string,
161
- help="Specify a range of functional requirements to render (e.g. '1.1,2.3'). "
161
+ help="Specify a range of functional requirements to render (e.g. `1` , `2`, `3`). "
162
162
  "Use comma to separate start and end IDs. If only one ID is provided, only that requirement is rendered. "
163
163
  "Range is inclusive of both start and end IDs.",
164
164
  )
165
165
  render_range_group.add_argument(
166
166
  "--render-from",
167
167
  type=frid_string,
168
- help="Continue generation starting from this specific functional requirement (e.g. '2.1'). "
168
+ help="Continue generation starting from this specific functional requirement (e.g. `2`). "
169
169
  "The requirement with this ID will be included in the output. The ID must match one of the functional requirements in your plain file.",
170
170
  )
171
171
 
@@ -190,15 +190,15 @@ def create_parser():
190
190
  parser.add_argument(
191
191
  "--conformance-tests-script",
192
192
  type=str,
193
- help="Path to conformance tests shell script. The script should accept two arguments: "
194
- "1) First argument: path to a folder (e.g. 'plain_modules/module_name') containing generated source code, "
195
- "2) Second argument: path to a subfolder of the conformance tests folder (e.g. 'conformance_tests/subfoldername') containing test files.",
193
+ help="Path to conformance tests shell script. Every conformance test script should accept two arguments: "
194
+ "1) Path to a folder (e.g. `plain_modules/module_name`) containing generated source code, "
195
+ "2) Path to a subfolder of the conformance tests folder (e.g. `conformance_tests/subfoldername`) containing test files.",
196
196
  )
197
197
 
198
198
  parser.add_argument(
199
199
  "--prepare-environment-script",
200
200
  type=str,
201
- help="Path to a shell script that prepares the testing environment. The script should accept the build folder path as its first argument (default: 'plain_modules').",
201
+ help="Path to a shell script that prepares the testing environment. The script should accept the source code folder path as its first argument.",
202
202
  )
203
203
 
204
204
  parser.add_argument(
@@ -212,17 +212,18 @@ def create_parser():
212
212
  "--api-key",
213
213
  type=str,
214
214
  default=CODEPLAIN_API_KEY,
215
- help="API key used to access the API. If not provided, the CODEPLAIN_API_KEY environment variable is used.",
215
+ help="API key used to access the API. If not provided, the `CODEPLAIN_API_KEY` environment variable is used.",
216
216
  )
217
217
  parser.add_argument(
218
218
  "--full-plain",
219
219
  action="store_true",
220
- help="Display the complete plain specification before code generation. "
221
- "This shows your plain file with "
222
- "any included template content expanded. Useful for understanding what content is being processed.",
220
+ help="Full preview ***plain specification before code generation."
221
+ "Use when you want to preview context of all ***plain primitives that are going to be included in order to render the given module.",
223
222
  )
224
223
  parser.add_argument(
225
- "--dry-run", action="store_true", help="Preview of what Codeplain would do without actually making any changes."
224
+ "--dry-run",
225
+ action="store_true",
226
+ help="Dry run preview of the code generation (without actually making any changes).",
226
227
  )
227
228
  parser.add_argument(
228
229
  "--replay-with",
@@ -236,33 +237,33 @@ def create_parser():
236
237
  type=str,
237
238
  default=None,
238
239
  help="Path to a custom template directory. Templates are searched in the following order: "
239
- "1) directory containing the plain file, "
240
- "2) this custom template directory (if provided), "
241
- "3) built-in standard_template_library directory",
240
+ "1) Directory containing the plain file, "
241
+ "2) Custom template directory (if provided through this argument), "
242
+ "3) Built-in standard_template_library directory",
242
243
  )
243
244
  parser.add_argument(
244
245
  "--copy-build",
245
246
  action="store_true",
246
247
  default=False,
247
- help="If set, copy the build folder to `--build-dest` after every successful rendering.",
248
+ help="If set, copy the rendered contents of code in `--base-folder` folder to `--build-dest` folder after successful rendering.",
248
249
  )
249
250
  parser.add_argument(
250
251
  "--build-dest",
251
252
  type=non_empty_string,
252
253
  default=DEFAULT_BUILD_DEST,
253
- help="Target folder to copy build output to (used only if --copy-build is set).",
254
+ help="Target folder to copy rendered contents of code to (used only if --copy-build is set).",
254
255
  )
255
256
  parser.add_argument(
256
257
  "--copy-conformance-tests",
257
258
  action="store_true",
258
259
  default=False,
259
- help="If set, copy the conformance tests folder to `--conformance-tests-dest` after every successful rendering. Requires --conformance-tests-script.",
260
+ help="If set, copy the conformance tests of code in `--conformance-tests-folder` folder to `--conformance-tests-dest` folder successful rendering. Requires --conformance-tests-script.",
260
261
  )
261
262
  parser.add_argument(
262
263
  "--conformance-tests-dest",
263
264
  type=non_empty_string,
264
265
  default=DEFAULT_CONFORMANCE_TESTS_DEST,
265
- help="Target folder to copy conformance tests output to (used only if --copy-conformance-tests is set).",
266
+ help="Target folder to copy conformance tests of code to (used only if --copy-conformance-tests is set).",
266
267
  )
267
268
 
268
269
  parser.add_argument(
@@ -301,6 +302,9 @@ def parse_arguments():
301
302
  if not args.log_to_file and args.log_file_name != DEFAULT_LOG_FILE_NAME:
302
303
  parser.error("--log-file-name cannot be used when --log-to-file is False.")
303
304
 
305
+ if args.full_plain and args.dry_run:
306
+ parser.error("--full-plain and --dry-run are mutually exclusive")
307
+
304
308
  script_arg_names = [UNIT_TESTS_SCRIPT_NAME, CONFORMANCE_TESTS_SCRIPT_NAME]
305
309
  for script_name in script_arg_names:
306
310
  args = process_test_script_path(script_name, args)
@@ -24,10 +24,12 @@ class RenderContextSnapshot:
24
24
  module_name: str
25
25
 
26
26
 
27
+ @dataclass
27
28
  class RenderCompleted(BaseEvent):
28
29
  """Event emitted when rendering completes successfully."""
29
30
 
30
- pass
31
+ module_name: str
32
+ build_folder: str
31
33
 
32
34
 
33
35
  @dataclass
@@ -22,14 +22,14 @@ def print_dry_run_output(plain_source_tree: dict, render_range: Optional[list[st
22
22
  specifications, _ = plain_spec.get_specifications_for_frid(plain_source_tree, frid)
23
23
  functional_requirement_text = specifications[plain_spec.FUNCTIONAL_REQUIREMENTS][-1]
24
24
  console.info(
25
- "-------------------------------------"
26
- f"Rendering functional requirement {frid}"
27
- f"{functional_requirement_text}"
28
- "-------------------------------------"
25
+ "-------------------------------------\n"
26
+ f"Rendering functional requirement {frid}\n"
27
+ f"{functional_requirement_text}\n"
28
+ "-------------------------------------\n"
29
29
  )
30
30
  if plain_spec.ACCEPTANCE_TESTS in specifications:
31
31
  for i, acceptance_test in enumerate(specifications[plain_spec.ACCEPTANCE_TESTS], 1):
32
- console.info(f"Generating acceptance test #{i}:\n\n{acceptance_test}")
32
+ console.info(f"Generating acceptance test #{i}:\n\n{acceptance_test}\n")
33
33
  else:
34
34
  console.info(
35
35
  "-------------------------------------\n"
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "codeplain"
7
- version = "0.2.6"
7
+ version = "0.2.7"
8
8
  description = "Transform plain language specifications into working code"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -169,14 +169,10 @@ class Plain2CodeTUI(App):
169
169
  with Vertical(id=TUIComponents.DASHBOARD_VIEW.value):
170
170
  with VerticalScroll():
171
171
  yield Static(
172
- f"[#FFFFFF]*codeplain[/#FFFFFF] [#888888](v{self.state_machine_version})[/#888888]\n",
172
+ f"[#FFFFFF]*codeplain[/#FFFFFF] [#888888](v{self.state_machine_version})[/#888888]",
173
173
  id="codeplain-header",
174
174
  classes="codeplain-header",
175
175
  )
176
- yield Static(
177
- "[#FFFFFF]Rendering in progress...[/#FFFFFF]",
178
- id=TUIComponents.RENDER_STATUS_WIDGET.value,
179
- )
180
176
  yield FRIDProgress(
181
177
  id=TUIComponents.FRID_PROGRESS.value,
182
178
  unittests_script=self.unittests_script,
@@ -190,6 +186,10 @@ class Plain2CodeTUI(App):
190
186
  show_conformance_test=self.conformance_tests_script is not None,
191
187
  show_testing_env=self.prepare_environment_script is not None,
192
188
  )
189
+ yield Static(
190
+ "[#FFFFFF]Rendering in progress...[/#FFFFFF]",
191
+ id=TUIComponents.RENDER_STATUS_WIDGET.value,
192
+ )
193
193
  with Vertical(id=TUIComponents.LOG_VIEW.value):
194
194
  yield LogLevelFilter(id=TUIComponents.LOG_FILTER.value)
195
195
  yield Static("", classes="filter-spacer")
@@ -272,9 +272,9 @@ class Plain2CodeTUI(App):
272
272
 
273
273
  self._state_completion_handler.handle(segments, snapshot, previous_state_segments)
274
274
 
275
- def on_render_completed(self, _event: RenderCompleted):
275
+ def on_render_completed(self, event: RenderCompleted):
276
276
  """Handle successful render completion."""
277
- self._render_success_handler.handle()
277
+ self._render_success_handler.handle(event.module_name, event.build_folder)
278
278
 
279
279
  def on_render_failed(self, event: RenderFailed):
280
280
  """Handle render failure."""