codeplain 0.3.10.dev5__tar.gz → 0.3.11.dev6__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 (265) hide show
  1. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/PKG-INFO +1 -1
  2. codeplain-0.3.11.dev6/install/bash/examples.sh +175 -0
  3. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/install/bash/install.sh +4 -2
  4. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/install/powershell/examples.ps1 +65 -3
  5. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/install/powershell/install.ps1 +9 -2
  6. codeplain-0.3.10.dev5/install/bash/examples.sh +0 -97
  7. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.claude/settings.json +0 -0
  8. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.flake8 +0 -0
  9. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.github/dependabot.yml +0 -0
  10. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.github/workflows/e2e.yml +0 -0
  11. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.github/workflows/lint-and-test.yml +0 -0
  12. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.github/workflows/lint-powershell.yml +0 -0
  13. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.github/workflows/nofity-slack-on-main-merge.yml +0 -0
  14. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.github/workflows/publish-dev-to-pypi.yml +0 -0
  15. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.github/workflows/publish-install-script.yml +0 -0
  16. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.github/workflows/publish-to-pypi.yml +0 -0
  17. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.gitignore +0 -0
  18. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.vscode/launch.json +0 -0
  19. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/.vscode/settings.json +0 -0
  20. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/CLAUDE.md +0 -0
  21. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/CONTRIBUTING.md +0 -0
  22. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/LICENSE +0 -0
  23. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/README.md +0 -0
  24. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/change_detection.py +0 -0
  25. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/cli_output/__init__.py +0 -0
  26. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/cli_output/dry_run.py +0 -0
  27. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/cli_output/render_summary.py +0 -0
  28. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/cli_output/status.py +0 -0
  29. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/codeplain_REST_api.py +0 -0
  30. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/concept_utils.py +0 -0
  31. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/config/__init__.py +0 -0
  32. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/config/system_config.yaml +0 -0
  33. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/conformance_fix_journal.py +0 -0
  34. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/diff_utils.py +0 -0
  35. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/docs/generate_cli.py +0 -0
  36. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/docs/plain2code_cli.md +0 -0
  37. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/docs/starting_a_plain_project_from_scratch.md +0 -0
  38. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/event_bus.py +0 -0
  39. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_golang/config.yaml +0 -0
  40. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_golang/harness_tests/hello_world_test.go +0 -0
  41. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_golang/hello_world_golang.plain +0 -0
  42. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_golang/run.sh +0 -0
  43. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_python/config.yaml +0 -0
  44. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +0 -0
  45. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_python/hello_world_python.plain +0 -0
  46. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_python/run.sh +0 -0
  47. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_react/config.yaml +0 -0
  48. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +0 -0
  49. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +0 -0
  50. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +0 -0
  51. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +0 -0
  52. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +0 -0
  53. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_react/hello_world_react.plain +0 -0
  54. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/example_hello_world_react/run.sh +0 -0
  55. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/examples/run.sh +0 -0
  56. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/file_utils.py +0 -0
  57. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/git_utils.py +0 -0
  58. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/install/bash/walkthrough.sh +0 -0
  59. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/install/powershell/walkthrough.ps1 +0 -0
  60. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/memory_management.py +0 -0
  61. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/metadata_utils.py +0 -0
  62. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/module_renderer.py +0 -0
  63. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/partial_rendering.py +0 -0
  64. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/path_resolution.py +0 -0
  65. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code.py +0 -0
  66. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code_arguments.py +0 -0
  67. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code_cli.md +0 -0
  68. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code_console.py +0 -0
  69. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code_events.py +0 -0
  70. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code_exceptions.py +0 -0
  71. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code_logger.py +0 -0
  72. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code_nodes.py +0 -0
  73. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code_read_config.py +0 -0
  74. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code_state.py +0 -0
  75. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code_telemetry.py +0 -0
  76. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain2code_utils.py +0 -0
  77. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain_file.py +0 -0
  78. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain_modules.py +0 -0
  79. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/plain_spec.py +0 -0
  80. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/pyproject.toml +0 -0
  81. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/pytest.ini +0 -0
  82. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/__init__.py +0 -0
  83. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/analyze_specification_ambiguity.py +0 -0
  84. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/base_action.py +0 -0
  85. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
  86. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/commit_implementation_code_changes.py +0 -0
  87. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/create_dist.py +0 -0
  88. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/distill_conformance_test_memory.py +0 -0
  89. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/exit_with_error.py +0 -0
  90. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/finish_functional_requirement.py +0 -0
  91. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/fix_conformance_test.py +0 -0
  92. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/fix_unit_tests.py +0 -0
  93. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/prepare_repositories.py +0 -0
  94. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/prepare_testing_environment.py +0 -0
  95. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/refactor_code.py +0 -0
  96. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/render_conformance_tests.py +0 -0
  97. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/render_functional_requirement.py +0 -0
  98. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/run_conformance_tests.py +0 -0
  99. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/run_unit_tests.py +0 -0
  100. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/actions/summarize_conformance_tests.py +0 -0
  101. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/code_renderer.py +0 -0
  102. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/conformance_tests.py +0 -0
  103. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/implementation_code_helpers.py +0 -0
  104. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/render_context.py +0 -0
  105. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/render_types.py +0 -0
  106. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/render_utils.py +0 -0
  107. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/state_machine_config.py +0 -0
  108. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/states.py +0 -0
  109. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/render_machine/triggers.py +0 -0
  110. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/requirements.txt +0 -0
  111. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/resources/codeplain_overview.png +0 -0
  112. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/resources/plain_example.png +0 -0
  113. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/standard_template_library/golang-console-app-template.plain +0 -0
  114. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/standard_template_library/python-console-app-template.plain +0 -0
  115. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
  116. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/standard_template_library/typescript-react-app-template.plain +0 -0
  117. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/system_config.py +0 -0
  118. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_conformance_tests_cypress.ps1 +0 -0
  119. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_conformance_tests_cypress.sh +0 -0
  120. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_conformance_tests_golang.ps1 +0 -0
  121. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_conformance_tests_golang.sh +0 -0
  122. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_conformance_tests_python.ps1 +0 -0
  123. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_conformance_tests_python.sh +0 -0
  124. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_unittests_flutter.ps1 +0 -0
  125. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_unittests_flutter.sh +0 -0
  126. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_unittests_golang.ps1 +0 -0
  127. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_unittests_golang.sh +0 -0
  128. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_unittests_python.ps1 +0 -0
  129. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_unittests_python.sh +0 -0
  130. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_unittests_react.ps1 +0 -0
  131. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/test_scripts/run_unittests_react.sh +0 -0
  132. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/__init__.py +0 -0
  133. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/conftest.py +0 -0
  134. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/acceptance_tests_warning/main_requiring_acceptance_tests.plain +0 -0
  135. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/acceptance_tests_warning/required_with_acceptance_tests.plain +0 -0
  136. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/imports/circular_imports_1.plain +0 -0
  137. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/imports/circular_imports_2.plain +0 -0
  138. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/imports/circular_imports_main.plain +0 -0
  139. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/imports/diamond_import_1.plain +0 -0
  140. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/imports/diamond_import_2.plain +0 -0
  141. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/imports/diamond_import_common.plain +0 -0
  142. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/imports/diamond_imports_main.plain +0 -0
  143. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/imports/import_with_functionalities.plain +0 -0
  144. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/imports/imports_module_with_functionalities.plain +0 -0
  145. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/imports/non_existent_import.plain +0 -0
  146. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/partial_rendering/pr_code_var.plain +0 -0
  147. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/partial_rendering/pr_implement.plain +0 -0
  148. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/partial_rendering/pr_leaf.plain +0 -0
  149. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/partial_rendering/pr_middle.plain +0 -0
  150. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/partial_rendering/pr_root.plain +0 -0
  151. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/partial_rendering/pr_solo.plain +0 -0
  152. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfile/add_new_task_modal_specification.yaml +0 -0
  153. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfile/duplicate_specification_heading.plain +0 -0
  154. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfile/empty_functional_specs_section.plain +0 -0
  155. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfile/invalid_specification_order.plain +0 -0
  156. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfile/missing_non_functional_requirements.plain +0 -0
  157. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfile/no_functional_specs_section.plain +0 -0
  158. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfile/plain_source_with_absolute_link.plain +0 -0
  159. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfile/plain_source_with_url_link.plain +0 -0
  160. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfile/task_list_ui_specification.yaml +0 -0
  161. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfile/task_manager_with_reference_links.plain +0 -0
  162. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfile/without_non_functional_requirement.plain +0 -0
  163. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +0 -0
  164. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +0 -0
  165. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +0 -0
  166. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +0 -0
  167. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/concept_validation_definition.plain +0 -0
  168. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/concept_validation_noconcepts.plain +0 -0
  169. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/concept_validation_nonconcept.plain +0 -0
  170. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/concept_validation_nondefined.plain +0 -0
  171. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/concept_validation_redefinition.plain +0 -0
  172. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/concept_validation_several_concepts.plain +0 -0
  173. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/concept_validation_valid.plain +0 -0
  174. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/exported_concepts.plain +0 -0
  175. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/exported_concepts_base.plain +0 -0
  176. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/exported_concepts_example.plain +0 -0
  177. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/exported_concepts_missing.plain +0 -0
  178. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/exported_concepts_missing_example.plain +0 -0
  179. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/exported_concepts_nested.plain +0 -0
  180. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/exported_concepts_nested_example.plain +0 -0
  181. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/exported_concepts_transitive_example.plain +0 -0
  182. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +0 -0
  183. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +0 -0
  184. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/plain_file_parser_with_comments.plain +0 -0
  185. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/plain_file_with_comments_indented.plain +0 -0
  186. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/regular_plain_source.plain +0 -0
  187. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/required_concepts.plain +0 -0
  188. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/required_concepts_defs.plain +0 -0
  189. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/required_concepts_example.plain +0 -0
  190. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/required_concepts_l1.plain +0 -0
  191. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/required_concepts_l2.plain +0 -0
  192. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/required_concepts_missing.plain +0 -0
  193. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/required_concepts_module.plain +0 -0
  194. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/required_concepts_partial.plain +0 -0
  195. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +0 -0
  196. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/topological_sort.plain +0 -0
  197. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/plainfileparser/topological_sort_not_referenced.plain +0 -0
  198. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/circular_requires_main.plain +0 -0
  199. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/circular_requires_sub.plain +0 -0
  200. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/diamond_requires_1.plain +0 -0
  201. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/diamond_requires_2.plain +0 -0
  202. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/diamond_requires_common.plain +0 -0
  203. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/diamond_requires_main.plain +0 -0
  204. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/independent_requires_1.plain +0 -0
  205. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/independent_requires_2.plain +0 -0
  206. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/independent_requires_main.plain +0 -0
  207. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/non_existent_require.plain +0 -0
  208. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/normal_requires_1.plain +0 -0
  209. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/normal_requires_2.plain +0 -0
  210. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/normal_requires_common.plain +0 -0
  211. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/requires/normal_requires_main.plain +0 -0
  212. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/sample_base64_image.txt +0 -0
  213. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/simple.plain +0 -0
  214. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/templates/block_level_include.plain +0 -0
  215. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/templates/code_variables.plain +0 -0
  216. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/templates/header.plain +0 -0
  217. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/templates/implement.plain +0 -0
  218. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/templates/implement_2.plain +0 -0
  219. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/templates/template_include.plain +0 -0
  220. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/data/templates/test_hardest_problem.plain +0 -0
  221. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/e2e/Dockerfile +0 -0
  222. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/e2e/conftest.py +0 -0
  223. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/e2e/test_hello_world_python.py +0 -0
  224. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/e2e/test_hello_world_python_windows.py +0 -0
  225. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_arg_provenance.py +0 -0
  226. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_change_detection.py +0 -0
  227. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_cli_output.py +0 -0
  228. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_conformance_fix_journal.py +0 -0
  229. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_console_log_styles.py +0 -0
  230. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_distill_conformance_test_memory.py +0 -0
  231. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_dry_run_link_validation.py +0 -0
  232. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_file_utils.py +0 -0
  233. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_folder_path_resolution.py +0 -0
  234. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_git_utils.py +0 -0
  235. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_headless_logging.py +0 -0
  236. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_imports.py +0 -0
  237. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_log_file_name_resolution.py +0 -0
  238. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_logging_config_path_resolution.py +0 -0
  239. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_partial_rendering.py +0 -0
  240. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_path_resolution.py +0 -0
  241. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_plain2code.py +0 -0
  242. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_plain2code_state.py +0 -0
  243. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_plain2code_utils.py +0 -0
  244. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_plain_modules.py +0 -0
  245. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_plainfile.py +0 -0
  246. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_plainfileparser.py +0 -0
  247. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_plainspec.py +0 -0
  248. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_prepare_repositories_layout.py +0 -0
  249. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_requires.py +0 -0
  250. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_resolve_config_file.py +0 -0
  251. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_script_path_resolution.py +0 -0
  252. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_system_config.py +0 -0
  253. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_telemetry.py +0 -0
  254. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_tui_usage.py +0 -0
  255. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tests/test_usage_summary.py +0 -0
  256. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tui/__init__.py +0 -0
  257. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tui/components.py +0 -0
  258. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tui/models.py +0 -0
  259. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tui/plain2code_tui.py +0 -0
  260. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tui/plain_module_render_choice_tui.py +0 -0
  261. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tui/spinner.py +0 -0
  262. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tui/state_handlers.py +0 -0
  263. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tui/styles.css +0 -0
  264. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/tui/widget_helpers.py +0 -0
  265. {codeplain-0.3.10.dev5 → codeplain-0.3.11.dev6}/usage_summary.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codeplain
3
- Version: 0.3.10.dev5
3
+ Version: 0.3.11.dev6
4
4
  Summary: Transform plain language specifications into working code
5
5
  License-File: LICENSE
6
6
  Classifier: Environment :: Console
@@ -0,0 +1,175 @@
1
+ #!/bin/bash
2
+
3
+ set -euo pipefail
4
+
5
+ # Brand Colors (use exported colors if available, otherwise define them)
6
+ YELLOW="${YELLOW:-\033[38;2;224;255;110m}"
7
+ GREEN="${GREEN:-\033[38;2;121;252;150m}"
8
+ WHITE="${WHITE:-\033[38;2;255;255;255m}"
9
+ RED="${RED:-\033[38;2;239;68;68m}"
10
+ GRAY="${GRAY:-\033[38;2;128;128;128m}"
11
+ BOLD="${BOLD:-\033[1m}"
12
+ NC="${NC:-\033[0m}"
13
+
14
+ # Examples configuration
15
+ EXAMPLES_FOLDER_NAME="plainlang-examples"
16
+ EXAMPLES_DOWNLOAD_URL="https://codeplain.ai/examples/unix"
17
+
18
+ # Prompt the user, reading from the terminal when there is one. Falling back to
19
+ # stdin keeps the script usable in non-interactive environments instead of
20
+ # dying on an unreadable /dev/tty.
21
+ prompt_user() {
22
+ local prompt="$1"
23
+ local varname="$2"
24
+
25
+ # Test that /dev/tty can actually be opened: it exists but fails to open
26
+ # when the process has no controlling terminal.
27
+ if { : < /dev/tty; } 2>/dev/null; then
28
+ read -r -p "$prompt" "$varname" < /dev/tty || true
29
+ else
30
+ read -r -p "$prompt" "$varname" || true
31
+ fi
32
+ }
33
+
34
+ # Make the user acknowledge that the examples were not installed. The
35
+ # installation continues either way, but the failure must not scroll past
36
+ # unseen - the installer clears the screen in its next step.
37
+ confirm_continue_after_failure() {
38
+ echo ""
39
+ echo -e " ${YELLOW}The examples were not installed.${NC} ${GRAY}The installation will continue.${NC}"
40
+ echo ""
41
+ prompt_user "$(printf '%b' " Continue? Press ${WHITE}[Enter]${NC} to acknowledge: ")" _ACKNOWLEDGED
42
+ echo ""
43
+ }
44
+
45
+ # Tell the user how to get unzip on their system, then let the installer move on.
46
+ report_missing_unzip_tool() {
47
+ echo -e " ${RED}✗ Cannot extract the examples: no 'unzip' command found.${NC}"
48
+ echo ""
49
+ echo -e " ${GRAY}Install unzip and re-run the installer to get the examples:${NC}"
50
+ echo ""
51
+ case "$OSTYPE" in
52
+ darwin*)
53
+ echo -e " ${WHITE}${BOLD}brew install unzip${NC}"
54
+ ;;
55
+ *)
56
+ echo -e " ${WHITE}${BOLD}apt-get install unzip${NC} ${GRAY}(Debian/Ubuntu)${NC}"
57
+ echo -e " ${WHITE}${BOLD}dnf install unzip${NC} ${GRAY}(Fedora/RHEL)${NC}"
58
+ echo -e " ${WHITE}${BOLD}apk add unzip${NC} ${GRAY}(Alpine)${NC}"
59
+ ;;
60
+ esac
61
+ echo ""
62
+ echo -e " ${GRAY}The examples are also available at:${NC}"
63
+ echo -e " ${WHITE}https://github.com/Codeplain-ai/plainlang-examples${NC}"
64
+ echo ""
65
+ }
66
+
67
+ # Checked before anything is downloaded, so a missing unzip is reported up
68
+ # front instead of leaving the user with an installer that just stops.
69
+ if ! command -v unzip &> /dev/null; then
70
+ report_missing_unzip_tool
71
+ confirm_continue_after_failure
72
+ exit 0
73
+ fi
74
+
75
+ # Show current directory and ask for extraction path
76
+ CURRENT_DIR=$(pwd)
77
+ echo -e " Current folder: ${WHITE}${CURRENT_DIR}${NC}"
78
+ echo ""
79
+ echo -e " Extract examples here, or enter a different path:"
80
+ echo ""
81
+ prompt_user " [Enter for current, or type path]: " EXTRACT_PATH
82
+ echo ""
83
+
84
+ # Use current directory if empty
85
+ if [ -z "${EXTRACT_PATH:-}" ]; then
86
+ EXTRACT_PATH="$CURRENT_DIR"
87
+ fi
88
+
89
+ # Expand ~ to home directory
90
+ EXTRACT_PATH="${EXTRACT_PATH/#\~/$HOME}"
91
+
92
+ SKIP_DOWNLOAD=false
93
+
94
+ # Check if directory exists, create if not
95
+ if [ ! -d "$EXTRACT_PATH" ]; then
96
+ echo -e " ${GRAY}Creating directory...${NC}"
97
+ if ! mkdir -p "$EXTRACT_PATH" 2>/dev/null; then
98
+ echo -e " ${RED}✗ Failed to create directory: ${EXTRACT_PATH}${NC}"
99
+ confirm_continue_after_failure
100
+ SKIP_DOWNLOAD=true
101
+ fi
102
+ fi
103
+
104
+ EXAMPLES_INSTALLED=false
105
+
106
+ if [ "$SKIP_DOWNLOAD" = false ]; then
107
+ echo -e " ${GRAY}Downloading examples...${NC}"
108
+
109
+ # Download the zip file
110
+ TEMP_ZIP=$(mktemp)
111
+ DOWNLOAD_OK=false
112
+ DOWNLOAD_ERROR="Could not download ${EXAMPLES_DOWNLOAD_URL}"
113
+ if curl -L -s -o "$TEMP_ZIP" "$EXAMPLES_DOWNLOAD_URL" && [ -s "$TEMP_ZIP" ]; then
114
+ DOWNLOAD_OK=true
115
+ fi
116
+
117
+ # A server error page is a successful download of the wrong thing, so check
118
+ # for the zip magic bytes rather than handing unzip an HTML page.
119
+ if [ "$DOWNLOAD_OK" = true ] && [ "$(head -c 2 "$TEMP_ZIP")" != "PK" ]; then
120
+ DOWNLOAD_OK=false
121
+ DOWNLOAD_ERROR="The downloaded file is not a zip archive."
122
+ fi
123
+
124
+ if [ "$DOWNLOAD_OK" = true ]; then
125
+ echo -e " ${GRAY}Extracting to ${EXTRACT_PATH}...${NC}"
126
+
127
+ # Extract the zip file (contents are at the zip root, so extract into the target folder)
128
+ EXTRACTED_DIR="${EXTRACT_PATH}/${EXAMPLES_FOLDER_NAME}"
129
+ rm -rf "$EXTRACTED_DIR" 2>/dev/null || true # Remove existing if present
130
+
131
+ # Keep the extractor's own error output: it is the only clue about why
132
+ # extraction failed (corrupt download, no disk space, no permissions).
133
+ if EXTRACT_OUTPUT=$(unzip -q -o "$TEMP_ZIP" -d "$EXTRACTED_DIR" 2>&1); then
134
+ # Remove the .gitignore file from the root of the extracted directory
135
+ if [ -f "${EXTRACTED_DIR}/.gitignore" ]; then
136
+ rm -f "${EXTRACTED_DIR}/.gitignore"
137
+ fi
138
+
139
+ clear || true
140
+ echo ""
141
+ echo -e " ${GREEN}✓ Examples downloaded successfully!${NC}"
142
+ echo ""
143
+ echo -e " ${GRAY}Examples are in: ${EXTRACTED_DIR}${NC}"
144
+ echo ""
145
+ echo -e " ${WHITE}${BOLD}Try the hello, world example:${NC}"
146
+ echo ""
147
+ echo -e " ${GRAY}Example folder:${NC} ${WHITE}cd ${EXTRACTED_DIR}/hello-world/python${NC}"
148
+ echo ""
149
+ echo -e " ${GRAY}Render the example:${NC} ${WHITE}codeplain hello-world-python.plain${NC}"
150
+ echo ""
151
+ echo -e " ${GRAY}See hello-world/python/README.md for details.${NC}"
152
+ echo ""
153
+ EXAMPLES_INSTALLED=true
154
+ else
155
+ echo -e " ${RED}✗ Failed to extract examples.${NC}"
156
+ if [ -n "$EXTRACT_OUTPUT" ]; then
157
+ echo -e " ${GRAY}$(echo "$EXTRACT_OUTPUT" | tail -n 3)${NC}"
158
+ fi
159
+ fi
160
+
161
+ # Clean up temp file
162
+ rm -f "$TEMP_ZIP"
163
+ else
164
+ echo -e " ${RED}✗ Failed to download examples.${NC}"
165
+ echo -e " ${GRAY}${DOWNLOAD_ERROR}${NC}"
166
+ rm -f "$TEMP_ZIP"
167
+ fi
168
+
169
+ if [ "$EXAMPLES_INSTALLED" = true ]; then
170
+ echo ""
171
+ prompt_user "$(printf '%b' " Press ${WHITE}[Enter]${NC} to continue...")" _CONTINUE
172
+ else
173
+ confirm_continue_after_failure
174
+ fi
175
+ fi
@@ -425,9 +425,11 @@ else
425
425
  echo ""
426
426
  fi
427
427
 
428
- # Run examples download if user agrees
428
+ # Run examples download if user agrees. The examples are a nice-to-have, so a
429
+ # failure there must never abort the installation (set -e would otherwise take
430
+ # the whole installer down without printing anything).
429
431
  if [[ ! "${DOWNLOAD_EXAMPLES:-}" =~ ^[Nn]$ ]]; then
430
- run_script "examples.sh"
432
+ run_script "examples.sh" || echo -e "${GRAY}Example download did not complete. Continuing with the installation.${NC}"
431
433
  fi
432
434
 
433
435
  # Final verification: make sure the installed codeplain can actually run and
@@ -19,6 +19,39 @@ $CROSS = [char]0x2717
19
19
  $EXAMPLES_FOLDER_NAME = "plainlang-examples"
20
20
  $EXAMPLES_DOWNLOAD_URL = "https://codeplain.ai/examples/windows"
21
21
 
22
+ # Make the user acknowledge that the examples were not installed. The
23
+ # installation continues either way, but the failure must not scroll past
24
+ # unseen - the installer clears the screen in its next step.
25
+ function Confirm-ContinueAfterFailure {
26
+ Write-Host ""
27
+ Write-Host " ${YELLOW}The examples were not installed.${NC} ${GRAY}The installation will continue.${NC}"
28
+ Write-Host ""
29
+ Read-Host " Continue? Press ${WHITE}[Enter]${NC} to acknowledge"
30
+ Write-Host ""
31
+ }
32
+
33
+ # Expand-Archive lives in the Microsoft.PowerShell.Archive module, shipped with
34
+ # PowerShell 5.0 and later. Checked before anything is downloaded, so a machine
35
+ # without it is told what to do instead of just seeing an extraction failure.
36
+ function Show-MissingArchiveCmdletMessage {
37
+ Write-Host " ${RED}${CROSS} Cannot extract the examples: Expand-Archive is not available.${NC}"
38
+ Write-Host ""
39
+ Write-Host " ${GRAY}Expand-Archive requires PowerShell 5.0 or later. Install a newer${NC}"
40
+ Write-Host " ${GRAY}PowerShell and re-run the installer to get the examples:${NC}"
41
+ Write-Host ""
42
+ Write-Host " ${WHITE}${BOLD}https://aka.ms/powershell${NC}"
43
+ Write-Host ""
44
+ Write-Host " ${GRAY}The examples are also available at:${NC}"
45
+ Write-Host " ${WHITE}https://github.com/Codeplain-ai/plainlang-examples${NC}"
46
+ Write-Host ""
47
+ }
48
+
49
+ if (-not (Get-Command Expand-Archive -ErrorAction SilentlyContinue)) {
50
+ Show-MissingArchiveCmdletMessage
51
+ Confirm-ContinueAfterFailure
52
+ exit 0
53
+ }
54
+
22
55
  # Show current directory and ask for extraction path
23
56
  $CURRENT_DIR = Get-Location
24
57
  Write-Host " Current folder: ${WHITE}${CURRENT_DIR}${NC}"
@@ -47,11 +80,13 @@ if (-not (Test-Path $EXTRACT_PATH -PathType Container)) {
47
80
  New-Item -ItemType Directory -Path $EXTRACT_PATH -Force | Out-Null
48
81
  } catch {
49
82
  Write-Host " ${RED}${CROSS} Failed to create directory: ${EXTRACT_PATH}${NC}"
50
- Write-Host " ${GRAY}Skipping example download.${NC}"
83
+ Confirm-ContinueAfterFailure
51
84
  $SKIP_DOWNLOAD = $true
52
85
  }
53
86
  }
54
87
 
88
+ $EXAMPLES_INSTALLED = $false
89
+
55
90
  if (-not $SKIP_DOWNLOAD) {
56
91
  Write-Host " ${GRAY}Downloading examples...${NC}"
57
92
 
@@ -60,7 +95,26 @@ if (-not $SKIP_DOWNLOAD) {
60
95
  try {
61
96
  Invoke-WebRequest -Uri $EXAMPLES_DOWNLOAD_URL -OutFile $TEMP_ZIP -UseBasicParsing
62
97
 
98
+ # Check for the zip magic bytes rather than handing Expand-Archive a
99
+ # server error page. Read via a stream: 'Get-Content -Encoding Byte' is
100
+ # Windows PowerShell 5.1 only, '-AsByteStream' is PowerShell 6+ only.
101
+ $IS_ZIP = $false
63
102
  if (Test-Path $TEMP_ZIP) {
103
+ $HEADER = New-Object byte[] 2
104
+ $STREAM = [System.IO.File]::OpenRead($TEMP_ZIP)
105
+ try {
106
+ $BYTES_READ = $STREAM.Read($HEADER, 0, 2)
107
+ } finally {
108
+ $STREAM.Close()
109
+ }
110
+ $IS_ZIP = ($BYTES_READ -eq 2 -and $HEADER[0] -eq 0x50 -and $HEADER[1] -eq 0x4B)
111
+ }
112
+
113
+ if (-not $IS_ZIP -and (Test-Path $TEMP_ZIP)) {
114
+ Write-Host " ${RED}${CROSS} Failed to download examples.${NC}"
115
+ Write-Host " ${GRAY}The downloaded file is not a zip archive.${NC}"
116
+ Remove-Item -Path $TEMP_ZIP -Force -ErrorAction SilentlyContinue
117
+ } elseif ($IS_ZIP) {
64
118
  Write-Host " ${GRAY}Extracting to ${EXTRACT_PATH}...${NC}"
65
119
 
66
120
  try {
@@ -91,8 +145,12 @@ if (-not $SKIP_DOWNLOAD) {
91
145
  Write-Host ""
92
146
  Write-Host " ${GRAY}See hello-world/python/README.md for details.${NC}"
93
147
  Write-Host ""
148
+ $EXAMPLES_INSTALLED = $true
94
149
  } catch {
150
+ # Keep the cmdlet's own message: it is the only clue about why
151
+ # extraction failed (corrupt download, no space, no permissions).
95
152
  Write-Host " ${RED}${CROSS} Failed to extract examples.${NC}"
153
+ Write-Host " ${GRAY}$($_.Exception.Message)${NC}"
96
154
  }
97
155
 
98
156
  Remove-Item -Path $TEMP_ZIP -Force -ErrorAction SilentlyContinue
@@ -104,6 +162,10 @@ if (-not $SKIP_DOWNLOAD) {
104
162
  Remove-Item -Path $TEMP_ZIP -Force -ErrorAction SilentlyContinue
105
163
  }
106
164
 
107
- Write-Host ""
108
- Read-Host " Press ${WHITE}[Enter]${NC} to continue..."
165
+ if ($EXAMPLES_INSTALLED) {
166
+ Write-Host ""
167
+ Read-Host " Press ${WHITE}[Enter]${NC} to continue..."
168
+ } else {
169
+ Confirm-ContinueAfterFailure
170
+ }
109
171
  }
@@ -526,9 +526,16 @@ if ($nonInteractive) {
526
526
  Write-Host ""
527
527
  }
528
528
 
529
- # Run examples download if user agrees
529
+ # Run examples download if user agrees. The examples are a nice-to-have, so a
530
+ # failure there must never abort the installation: examples.ps1 runs in this
531
+ # runspace via the call operator, so a terminating error inside it would
532
+ # otherwise propagate here and take the whole installer down.
530
533
  if ($downloadExamples -notmatch '^[Nn]$') {
531
- Invoke-SubScript "examples.ps1"
534
+ try {
535
+ Invoke-SubScript "examples.ps1"
536
+ } catch {
537
+ Write-Host "${GRAY}Example download did not complete. Continuing with the installation.${NC}"
538
+ }
532
539
  }
533
540
 
534
541
  # Final verification: make sure the installed codeplain can actually run and
@@ -1,97 +0,0 @@
1
- #!/bin/bash
2
-
3
- set -euo pipefail
4
-
5
- # Brand Colors (use exported colors if available, otherwise define them)
6
- YELLOW="${YELLOW:-\033[38;2;224;255;110m}"
7
- GREEN="${GREEN:-\033[38;2;121;252;150m}"
8
- WHITE="${WHITE:-\033[38;2;255;255;255m}"
9
- RED="${RED:-\033[38;2;239;68;68m}"
10
- GRAY="${GRAY:-\033[38;2;128;128;128m}"
11
- BOLD="${BOLD:-\033[1m}"
12
- NC="${NC:-\033[0m}"
13
-
14
- # Examples configuration
15
- EXAMPLES_FOLDER_NAME="plainlang-examples"
16
- EXAMPLES_DOWNLOAD_URL="https://codeplain.ai/examples/unix"
17
-
18
- # Show current directory and ask for extraction path
19
- CURRENT_DIR=$(pwd)
20
- echo -e " Current folder: ${WHITE}${CURRENT_DIR}${NC}"
21
- echo ""
22
- echo -e " Extract examples here, or enter a different path:"
23
- echo ""
24
- read -r -p " [Enter for current, or type path]: " EXTRACT_PATH < /dev/tty
25
- echo ""
26
-
27
- # Use current directory if empty
28
- if [ -z "${EXTRACT_PATH:-}" ]; then
29
- EXTRACT_PATH="$CURRENT_DIR"
30
- fi
31
-
32
- # Expand ~ to home directory
33
- EXTRACT_PATH="${EXTRACT_PATH/#\~/$HOME}"
34
-
35
- SKIP_DOWNLOAD=false
36
-
37
- # Check if directory exists, create if not
38
- if [ ! -d "$EXTRACT_PATH" ]; then
39
- echo -e " ${GRAY}Creating directory...${NC}"
40
- mkdir -p "$EXTRACT_PATH" 2>/dev/null
41
- if [ $? -ne 0 ]; then
42
- echo -e " ${RED}✗ Failed to create directory: ${EXTRACT_PATH}${NC}"
43
- echo -e " ${GRAY}Skipping example download.${NC}"
44
- SKIP_DOWNLOAD=true
45
- fi
46
- fi
47
-
48
- if [ "$SKIP_DOWNLOAD" = false ]; then
49
- echo -e " ${GRAY}Downloading examples...${NC}"
50
-
51
- # Download the zip file
52
- TEMP_ZIP=$(mktemp)
53
- curl -L -s -o "$TEMP_ZIP" "$EXAMPLES_DOWNLOAD_URL"
54
-
55
- if [ $? -eq 0 ] && [ -s "$TEMP_ZIP" ]; then
56
- echo -e " ${GRAY}Extracting to ${EXTRACT_PATH}...${NC}"
57
-
58
- # Extract the zip file (contents are at the zip root, so extract into the target folder)
59
- EXTRACTED_DIR="${EXTRACT_PATH}/${EXAMPLES_FOLDER_NAME}"
60
- rm -rf "$EXTRACTED_DIR" 2>/dev/null # Remove existing if present
61
- unzip -q -o "$TEMP_ZIP" -d "$EXTRACTED_DIR" 2>/dev/null
62
-
63
- if [ $? -eq 0 ]; then
64
- # Remove the .gitignore file from the root of the extracted directory
65
- if [ -f "${EXTRACTED_DIR}/.gitignore" ]; then
66
- rm -f "${EXTRACTED_DIR}/.gitignore"
67
- fi
68
-
69
- clear
70
- echo ""
71
- echo -e " ${GREEN}✓ Examples downloaded successfully!${NC}"
72
- echo ""
73
- echo -e " ${GRAY}Examples are in: ${EXTRACTED_DIR}${NC}"
74
- echo ""
75
- echo -e " ${WHITE}${BOLD}Try the hello, world example:${NC}"
76
- echo ""
77
- echo -e " ${GRAY}Example folder:${NC} ${WHITE}cd ${EXTRACTED_DIR}/hello-world/python${NC}"
78
- echo ""
79
- echo -e " ${GRAY}Render the example:${NC} ${WHITE}codeplain hello-world-python.plain${NC}"
80
- echo ""
81
- echo -e " ${GRAY}See hello-world/python/README.md for details.${NC}"
82
- echo ""
83
- else
84
- echo -e " ${RED}✗ Failed to extract examples.${NC}"
85
- fi
86
-
87
- # Clean up temp file
88
- rm -f "$TEMP_ZIP"
89
- else
90
- echo -e " ${RED}✗ Failed to download examples.${NC}"
91
- rm -f "$TEMP_ZIP"
92
- fi
93
-
94
- echo ""
95
- PROMPT=$(printf '%b' " Press ${WHITE}[Enter]${NC} to continue...")
96
- read -r -p "$PROMPT" < /dev/tty
97
- fi
File without changes
File without changes