periplus-map 0.2.1__py3-none-any.whl
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.
- periplus/__init__.py +70 -0
- periplus/checkmap.py +80 -0
- periplus/cli.py +658 -0
- periplus/contract/schema/map.schema.json +138 -0
- periplus/contract/schema/navigation.schema.json +200 -0
- periplus/contract/schema/pack-file.schema.json +1405 -0
- periplus/contract/schema/pack-manifest.schema.json +245 -0
- periplus/contract/schema/project-settings.schema.json +85 -0
- periplus/contract/spec/engine.md +151 -0
- periplus/contract/spec/rules.md +352 -0
- periplus/detect.py +228 -0
- periplus/engine/__init__.py +5 -0
- periplus/engine/check.py +481 -0
- periplus/engine/emit.py +368 -0
- periplus/engine/packload.py +2321 -0
- periplus/engine/pattern.py +27 -0
- periplus/engine/rules.py +1946 -0
- periplus/engine/select.py +491 -0
- periplus/engine/source.py +172 -0
- periplus/engine/tree.py +424 -0
- periplus/errors.py +332 -0
- periplus/init.py +358 -0
- periplus/layout.py +28 -0
- periplus/manifest.py +498 -0
- periplus/map.py +364 -0
- periplus/navigate/__init__.py +1 -0
- periplus/navigate/find.py +143 -0
- periplus/navigate/ids.py +30 -0
- periplus/navigate/listing.py +42 -0
- periplus/navigate/mapfile.py +189 -0
- periplus/navigate/path.py +175 -0
- periplus/navigate/show.py +175 -0
- periplus/navigate/types.py +83 -0
- periplus/navigate/walk.py +138 -0
- periplus/packs/advancedqueue_basic@0.0.1/pack.yaml +14 -0
- periplus/packs/advancedqueue_basic@0.0.1/queue_job_type/queue_job_type.yaml +9 -0
- periplus/packs/advancedqueue_basic@0.0.1/queue_job_type/queue_job_type_annotation.yaml +43 -0
- periplus/packs/advancedqueue_basic@0.0.1/queue_job_type/queue_job_type_attribute.yaml +43 -0
- periplus/packs/ai_basic@0.0.1/ai_agent/ai_agent.yaml +8 -0
- periplus/packs/ai_basic@0.0.1/ai_agent/ai_agent_attribute.yaml +43 -0
- periplus/packs/ai_basic@0.0.1/ai_function_call/ai_function_call.yaml +8 -0
- periplus/packs/ai_basic@0.0.1/ai_function_call/ai_function_call_attribute.yaml +43 -0
- periplus/packs/ai_basic@0.0.1/pack.yaml +15 -0
- periplus/packs/config_pages_basic@0.0.1/bundle/config_pages_bundle_config.yaml +54 -0
- periplus/packs/config_pages_basic@0.0.1/pack.yaml +11 -0
- periplus/packs/crop_basic@0.0.1/bundle/crop_bundle_config.yaml +54 -0
- periplus/packs/crop_basic@0.0.1/pack.yaml +11 -0
- periplus/packs/drupal@0.1.0/block/block_placement.yaml +25 -0
- periplus/packs/drupal@0.1.0/block/block_placement_code.yaml +58 -0
- periplus/packs/drupal@0.1.0/block/block_placement_config.yaml +53 -0
- periplus/packs/drupal@0.1.0/block/block_plugin.yaml +52 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_altered.yaml +61 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_annotation.yaml +69 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_attribute.yaml +56 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_content.yaml +46 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_derived.yaml +110 -0
- periplus/packs/drupal@0.1.0/block/block_plugin_deriver.yaml +30 -0
- periplus/packs/drupal@0.1.0/block/block_type.yaml +14 -0
- periplus/packs/drupal@0.1.0/block/block_type_code.yaml +43 -0
- periplus/packs/drupal@0.1.0/block/block_type_config.yaml +45 -0
- periplus/packs/drupal@0.1.0/cache/cache.yaml +18 -0
- periplus/packs/drupal@0.1.0/cache/cache_backend.yaml +31 -0
- periplus/packs/drupal@0.1.0/component/sdc.yaml +19 -0
- periplus/packs/drupal@0.1.0/component/sdc_definition.yaml +25 -0
- periplus/packs/drupal@0.1.0/component/sdc_use.yaml +25 -0
- periplus/packs/drupal@0.1.0/config/config_object.yaml +65 -0
- periplus/packs/drupal@0.1.0/display/display.yaml +32 -0
- periplus/packs/drupal@0.1.0/display/display_code.yaml +53 -0
- periplus/packs/drupal@0.1.0/display/display_config.yaml +95 -0
- periplus/packs/drupal@0.1.0/entity/entity.yaml +33 -0
- periplus/packs/drupal@0.1.0/entity/entity_class.yaml +60 -0
- periplus/packs/drupal@0.1.0/entity/entity_save.yaml +27 -0
- periplus/packs/drupal@0.1.0/entity/entity_type_annotation.yaml +85 -0
- periplus/packs/drupal@0.1.0/entity/entity_type_attribute.yaml +76 -0
- periplus/packs/drupal@0.1.0/field/field_instance_code.yaml +40 -0
- periplus/packs/drupal@0.1.0/field/field_instance_config.yaml +58 -0
- periplus/packs/drupal@0.1.0/field/field_storage.yaml +37 -0
- periplus/packs/drupal@0.1.0/field/field_storage_code.yaml +39 -0
- periplus/packs/drupal@0.1.0/field/field_storage_config.yaml +24 -0
- periplus/packs/drupal@0.1.0/form/form.yaml +48 -0
- periplus/packs/drupal@0.1.0/form/form_class.yaml +50 -0
- periplus/packs/drupal@0.1.0/form/form_id.yaml +48 -0
- periplus/packs/drupal@0.1.0/form/form_methods.yaml +39 -0
- periplus/packs/drupal@0.1.0/hook/hook.yaml +8 -0
- periplus/packs/drupal@0.1.0/hook/hook_attribute.yaml +28 -0
- periplus/packs/drupal@0.1.0/module/module.yaml +8 -0
- periplus/packs/drupal@0.1.0/module/module_info.yaml +50 -0
- periplus/packs/drupal@0.1.0/pack.yaml +184 -0
- periplus/packs/drupal@0.1.0/plugin/plugin.yaml +17 -0
- periplus/packs/drupal@0.1.0/plugin/plugin_annotation.yaml +120 -0
- periplus/packs/drupal@0.1.0/recommendations/recommendations.yaml +14 -0
- periplus/packs/drupal@0.1.0/service/service.yaml +19 -0
- periplus/packs/drupal@0.1.0/service/service_autowire.yaml +28 -0
- periplus/packs/drupal@0.1.0/service/service_definition.yaml +24 -0
- periplus/packs/drupal@0.1.0/service/service_use.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/action/action.yaml +9 -0
- periplus/packs/drupal_basic@0.3.0/action/action_annotation.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/action/action_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/block/block_placement.yaml +16 -0
- periplus/packs/drupal_basic@0.3.0/block/block_placement_config.yaml +51 -0
- periplus/packs/drupal_basic@0.3.0/block_plugin/block_plugin.yaml +14 -0
- periplus/packs/drupal_basic@0.3.0/block_plugin/block_plugin_annotation.yaml +47 -0
- periplus/packs/drupal_basic@0.3.0/block_plugin/block_plugin_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/block_type/block_type.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/block_type/block_type_config.yaml +54 -0
- periplus/packs/drupal_basic@0.3.0/boundary/boundary_types.yaml +19 -0
- periplus/packs/drupal_basic@0.3.0/bundle/bundle.yaml +20 -0
- periplus/packs/drupal_basic@0.3.0/bundle/bundle_config.yaml +393 -0
- periplus/packs/drupal_basic@0.3.0/call/call.yaml +349 -0
- periplus/packs/drupal_basic@0.3.0/component/component.yaml +30 -0
- periplus/packs/drupal_basic@0.3.0/config/config_object.yaml +119 -0
- periplus/packs/drupal_basic@0.3.0/constraint/constraint.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/constraint/constraint_annotation.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/constraint/constraint_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/display/display.yaml +30 -0
- periplus/packs/drupal_basic@0.3.0/display/display_config.yaml +203 -0
- periplus/packs/drupal_basic@0.3.0/display/display_mode_config.yaml +60 -0
- periplus/packs/drupal_basic@0.3.0/entity_type/config_entity_type_annotation.yaml +46 -0
- periplus/packs/drupal_basic@0.3.0/entity_type/config_entity_type_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/entity_type/content_entity_type_annotation.yaml +46 -0
- periplus/packs/drupal_basic@0.3.0/entity_type/content_entity_type_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/entity_type/entity_type.yaml +16 -0
- periplus/packs/drupal_basic@0.3.0/field/field_instance_config.yaml +116 -0
- periplus/packs/drupal_basic@0.3.0/field/field_storage.yaml +21 -0
- periplus/packs/drupal_basic@0.3.0/field/field_storage_config.yaml +45 -0
- periplus/packs/drupal_basic@0.3.0/field_formatter/field_formatter.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/field_formatter/field_formatter_annotation.yaml +46 -0
- periplus/packs/drupal_basic@0.3.0/field_formatter/field_formatter_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/field_type/field_type_annotation.yaml +46 -0
- periplus/packs/drupal_basic@0.3.0/field_type/field_type_attribute.yaml +50 -0
- periplus/packs/drupal_basic@0.3.0/field_widget/field_widget_annotation.yaml +46 -0
- periplus/packs/drupal_basic@0.3.0/field_widget/field_widget_attribute.yaml +50 -0
- periplus/packs/drupal_basic@0.3.0/form/form_id.yaml +80 -0
- periplus/packs/drupal_basic@0.3.0/hook/hook.yaml +100 -0
- periplus/packs/drupal_basic@0.3.0/hook/hook_attribute.yaml +64 -0
- periplus/packs/drupal_basic@0.3.0/hook/hook_theme_include.yaml +34 -0
- periplus/packs/drupal_basic@0.3.0/library/library.yaml +12 -0
- periplus/packs/drupal_basic@0.3.0/library/library_definition.yaml +58 -0
- periplus/packs/drupal_basic@0.3.0/local_action/local_action.yaml +12 -0
- periplus/packs/drupal_basic@0.3.0/local_action/local_action_definition.yaml +49 -0
- periplus/packs/drupal_basic@0.3.0/mail/mail.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/mail/mail_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/media_source/media_source.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/media_source/media_source_annotation.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/media_source/media_source_attribute.yaml +79 -0
- periplus/packs/drupal_basic@0.3.0/menu_link/menu_link.yaml +18 -0
- periplus/packs/drupal_basic@0.3.0/menu_link/menu_link_definition.yaml +48 -0
- periplus/packs/drupal_basic@0.3.0/module/module.yaml +7 -0
- periplus/packs/drupal_basic@0.3.0/module/module_info.yaml +58 -0
- periplus/packs/drupal_basic@0.3.0/pack.yaml +528 -0
- periplus/packs/drupal_basic@0.3.0/permission/permission.yaml +7 -0
- periplus/packs/drupal_basic@0.3.0/permission/permission_definition.yaml +27 -0
- periplus/packs/drupal_basic@0.3.0/queue_worker/queue_worker.yaml +9 -0
- periplus/packs/drupal_basic@0.3.0/queue_worker/queue_worker_annotation.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/queue_worker/queue_worker_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/rest_resource/rest_resource.yaml +8 -0
- periplus/packs/drupal_basic@0.3.0/rest_resource/rest_resource_annotation.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/rest_resource/rest_resource_attribute.yaml +43 -0
- periplus/packs/drupal_basic@0.3.0/role/role.yaml +14 -0
- periplus/packs/drupal_basic@0.3.0/role/role_config.yaml +44 -0
- periplus/packs/drupal_basic@0.3.0/route/route.yaml +42 -0
- periplus/packs/drupal_basic@0.3.0/route/route_definition.yaml +113 -0
- periplus/packs/drupal_basic@0.3.0/route/route_options.yaml +55 -0
- periplus/packs/drupal_basic@0.3.0/route/route_requirements.yaml +108 -0
- periplus/packs/drupal_basic@0.3.0/service/service.yaml +56 -0
- periplus/packs/drupal_basic@0.3.0/service/service_definition.yaml +181 -0
- periplus/packs/drupal_basic@0.3.0/template/template.yaml +86 -0
- periplus/packs/drupal_basic@0.3.0/template/template_route_link.yaml +30 -0
- periplus/packs/drupal_basic@0.3.0/theme/theme.yaml +15 -0
- periplus/packs/drupal_basic@0.3.0/theme/theme_info.yaml +61 -0
- periplus/packs/drupal_basic@0.3.0/theme_hook/template_suggestion.yaml +29 -0
- periplus/packs/drupal_basic@0.3.0/theme_hook/theme_hook.yaml +87 -0
- periplus/packs/drupal_basic@0.3.0/theme_hook/theme_hook_render.yaml +20 -0
- periplus/packs/drupal_basic@0.3.0/url/url.yaml +88 -0
- periplus/packs/drupal_basic@0.3.0/views_plugin/views_field_attribute.yaml +80 -0
- periplus/packs/drupal_basic@0.3.0/views_plugin/views_filter_attribute.yaml +80 -0
- periplus/packs/drupal_basic@0.3.0/views_plugin/views_plugin.yaml +15 -0
- periplus/packs/drupal_basic@0.3.0/views_plugin/views_style_attribute.yaml +80 -0
- periplus/packs/drupal_js_basic@0.0.1/attachment/attachment.yaml +12 -0
- periplus/packs/drupal_js_basic@0.0.1/attachment/attachment_in_php.yaml +15 -0
- periplus/packs/drupal_js_basic@0.0.1/attachment/attachment_in_php_array.yaml +52 -0
- periplus/packs/drupal_js_basic@0.0.1/attachment/attachment_in_twig.yaml +26 -0
- periplus/packs/drupal_js_basic@0.0.1/attachment/php_function_holder.yaml +13 -0
- periplus/packs/drupal_js_basic@0.0.1/behavior/behavior.yaml +198 -0
- periplus/packs/drupal_js_basic@0.0.1/pack.yaml +153 -0
- periplus/packs/drupal_js_basic@0.0.1/setting/setting.yaml +13 -0
- periplus/packs/drupal_js_basic@0.0.1/setting/setting_in_js.yaml +15 -0
- periplus/packs/drupal_js_basic@0.0.1/setting/setting_in_php.yaml +92 -0
- periplus/packs/drush_basic@0.0.1/command/command.yaml +15 -0
- periplus/packs/drush_basic@0.0.1/command/command_annotation.yaml +60 -0
- periplus/packs/drush_basic@0.0.1/command/command_attribute.yaml +88 -0
- periplus/packs/drush_basic@0.0.1/pack.yaml +29 -0
- periplus/packs/eck_basic@0.0.1/bundle/eck_bundle_config.yaml +56 -0
- periplus/packs/eck_basic@0.0.1/entity_type/eck_entity_type_config.yaml +26 -0
- periplus/packs/eck_basic@0.0.1/pack.yaml +28 -0
- periplus/packs/go@0.0.2/interfaces/satisfies.yaml +47 -0
- periplus/packs/go@0.0.2/pack.yaml +51 -0
- periplus/packs/go@0.0.2/types/find_declarations.yaml +137 -0
- periplus/packs/go@0.0.2/types/node_types.yaml +36 -0
- periplus/packs/go_basic@0.0.3/pack.yaml +104 -0
- periplus/packs/go_basic@0.0.3/rules/calls.yaml +25 -0
- periplus/packs/go_basic@0.0.3/rules/declarations.yaml +40 -0
- periplus/packs/go_basic@0.0.3/rules/imports.yaml +16 -0
- periplus/packs/go_basic@0.0.3/types/node_types.yaml +15 -0
- periplus/packs/js_basic@0.0.1/function/function.yaml +68 -0
- periplus/packs/js_basic@0.0.1/pack.yaml +50 -0
- periplus/packs/laravel_basic@0.0.5/pack.yaml +313 -0
- periplus/packs/laravel_basic@0.0.5/rules/classes.yaml +42 -0
- periplus/packs/laravel_basic@0.0.5/rules/config.yaml +229 -0
- periplus/packs/laravel_basic@0.0.5/rules/routes.yaml +210 -0
- periplus/packs/laravel_basic@0.0.5/rules/types.yaml +50 -0
- periplus/packs/laravel_basic@0.0.5/rules/views.yaml +100 -0
- periplus/packs/paragraphs_basic@0.0.1/bundle/paragraph_bundle_config.yaml +54 -0
- periplus/packs/paragraphs_basic@0.0.1/pack.yaml +12 -0
- periplus/packs/php@0.1.0/edges/edge_kinds.yaml +64 -0
- periplus/packs/php@0.1.0/edges/find_calls.yaml +34 -0
- periplus/packs/php@0.1.0/edges/find_imports.yaml +18 -0
- periplus/packs/php@0.1.0/edges/find_member_access.yaml +22 -0
- periplus/packs/php@0.1.0/edges/find_structure.yaml +38 -0
- periplus/packs/php@0.1.0/embedded/embedded_regions.yaml +19 -0
- periplus/packs/php@0.1.0/imports/imports.yaml +20 -0
- periplus/packs/php@0.1.0/pack.yaml +117 -0
- periplus/packs/php@0.1.0/resolution/excluded_tokens.yaml +23 -0
- periplus/packs/php@0.1.0/resolution/resolution.yaml +35 -0
- periplus/packs/php@0.1.0/types/find_declarations.yaml +102 -0
- periplus/packs/php@0.1.0/types/node_types.yaml +55 -0
- periplus/packs/php_basic@0.2.0/edges/edge_kinds.yaml +48 -0
- periplus/packs/php_basic@0.2.0/edges/find_structure.yaml +750 -0
- periplus/packs/php_basic@0.2.0/imports/imports.yaml +19 -0
- periplus/packs/php_basic@0.2.0/pack.yaml +94 -0
- periplus/packs/php_basic@0.2.0/types/find_declarations.yaml +267 -0
- periplus/packs/php_basic@0.2.0/types/node_types.yaml +55 -0
- periplus/packs/profile_basic@0.0.1/bundle/profile_bundle_config.yaml +54 -0
- periplus/packs/profile_basic@0.0.1/pack.yaml +12 -0
- periplus/packs/salesforce_basic@0.0.1/event/salesforce_event.yaml +36 -0
- periplus/packs/salesforce_basic@0.0.1/pack.yaml +31 -0
- periplus/packs/salesforce_basic@0.0.1/salesforce_mapping/salesforce_mapping.yaml +19 -0
- periplus/packs/salesforce_basic@0.0.1/salesforce_mapping/salesforce_mapping_config.yaml +83 -0
- periplus/packs/salesforce_basic@0.0.1/salesforce_mapping_field/salesforce_mapping_field.yaml +8 -0
- periplus/packs/salesforce_basic@0.0.1/salesforce_mapping_field/salesforce_mapping_field_annotation.yaml +43 -0
- periplus/packs/twig@0.0.1/pack.yaml +26 -0
- periplus/packs/twig@0.0.1/types/template.yaml +57 -0
- periplus/packs/twig_basic@0.1.0/pack.yaml +11 -0
- periplus/packs/twig_tweak_basic@0.0.1/pack.yaml +27 -0
- periplus/packs/twig_tweak_basic@0.0.1/rules/block.yaml +20 -0
- periplus/packs/twig_tweak_basic@0.0.1/rules/entity.yaml +35 -0
- periplus/packs/twig_tweak_basic@0.0.1/rules/field.yaml +21 -0
- periplus/packs/twig_tweak_basic@0.0.1/rules/menu.yaml +21 -0
- periplus/packs/webform_basic@0.0.1/bundle/webform_submission_bundle_config.yaml +54 -0
- periplus/packs/webform_basic@0.0.1/pack.yaml +20 -0
- periplus/packs/webform_basic@0.0.1/webform_handler/webform_handler.yaml +8 -0
- periplus/packs/webform_basic@0.0.1/webform_handler/webform_handler_annotation.yaml +43 -0
- periplus/packs/yaml@0.0.1/pack.yaml +72 -0
- periplus/packs/yaml@0.0.1/types/find_mapping_entry.yaml +21 -0
- periplus/packs/yaml@0.0.1/types/yaml_types.yaml +44 -0
- periplus/packs/yaml_basic@0.1.0/pack.yaml +10 -0
- periplus/packs.py +447 -0
- periplus/preflight.py +102 -0
- periplus/py.typed +0 -0
- periplus/report.py +596 -0
- periplus/resolution.py +355 -0
- periplus/settings.py +617 -0
- periplus/settings.stub.yml +99 -0
- periplus/spec.py +774 -0
- periplus/update.py +197 -0
- periplus/validate.py +655 -0
- periplus_map-0.2.1.dist-info/METADATA +566 -0
- periplus_map-0.2.1.dist-info/RECORD +272 -0
- periplus_map-0.2.1.dist-info/WHEEL +4 -0
- periplus_map-0.2.1.dist-info/entry_points.txt +2 -0
- periplus_map-0.2.1.dist-info/licenses/LICENSE +202 -0
- periplus_map-0.2.1.dist-info/licenses/NOTICE +2 -0
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: periplus-map
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: A schema-first, deterministic codebase mapper, configurable to any stack.
|
|
5
|
+
Project-URL: Homepage, https://github.com/camoa/periplus
|
|
6
|
+
Project-URL: Repository, https://github.com/camoa/periplus
|
|
7
|
+
Project-URL: Changelog, https://github.com/camoa/periplus/blob/main/CHANGELOG.md
|
|
8
|
+
Project-URL: Issues, https://github.com/camoa/periplus/issues
|
|
9
|
+
Author: camoa
|
|
10
|
+
License-Expression: Apache-2.0
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
License-File: NOTICE
|
|
13
|
+
Keywords: codebase,deterministic,map,static-analysis
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Requires-Dist: jsonschema==4.26.0
|
|
25
|
+
Requires-Dist: platformdirs==4.11.5
|
|
26
|
+
Requires-Dist: ruamel-yaml==0.19.1
|
|
27
|
+
Requires-Dist: tree-sitter-php==0.24.1
|
|
28
|
+
Requires-Dist: tree-sitter==0.26.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: mypy==2.3.1; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest==9.1.1; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff==0.15.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: types-jsonschema==4.26.0.20260518; extra == 'dev'
|
|
34
|
+
Provides-Extra: go
|
|
35
|
+
Requires-Dist: tree-sitter-go==0.25.0; extra == 'go'
|
|
36
|
+
Provides-Extra: js
|
|
37
|
+
Requires-Dist: tree-sitter-javascript==0.25.0; extra == 'js'
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
<div align="center">
|
|
41
|
+
|
|
42
|
+
# Periplus
|
|
43
|
+
|
|
44
|
+
**A map of a code base in one JSON file · rutters that say what to find · the same map every run**
|
|
45
|
+
|
|
46
|
+
[](https://github.com/camoa/periplus/actions/workflows/checks.yml)
|
|
47
|
+
[](LICENSE)
|
|
48
|
+
[](https://github.com/camoa/periplus/tags)
|
|
49
|
+
[](pyproject.toml)
|
|
50
|
+
<sub>The CI workflow, `.github/workflows/checks.yml`, installs the package with its `dev`
|
|
51
|
+
and `js` extras for the tests. It runs pytest on Python 3.11 to 3.14, ruff and mypy, and validates
|
|
52
|
+
every bundled pack. It does not run the end-to-end checks, and it never maps a Go project.</sub>
|
|
53
|
+
|
|
54
|
+
Status: **beta**, version 0.2.1, 592 tests.
|
|
55
|
+
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
> *periplus* (n.): an ancient coastal record of the ports and the distances between them.
|
|
59
|
+
>
|
|
60
|
+
> *rutter* (n.): a mariner's book of written sailing directions for one coast, from the French
|
|
61
|
+
> *routier*; it told a pilot what to look for before charts did.
|
|
62
|
+
|
|
63
|
+
Periplus makes a map of a code base: a JSON file of nodes and edges. Configuration files called
|
|
64
|
+
rutters tell it what to find. The same input always gives the same map, byte for byte. Periplus
|
|
65
|
+
never guesses. A thing that no rutter explains appears in the map as a marked unknown.
|
|
66
|
+
|
|
67
|
+
A **rutter** is a folder of YAML files for one stack, such as PHP, Drupal or Python. It declares
|
|
68
|
+
node types and edge kinds. It also says where to look, which files to read and how to name what it
|
|
69
|
+
finds. A new stack needs a new rutter, never a change to the engine. File names and settings call
|
|
70
|
+
a rutter a *pack*: a rutter lives in a folder named `<pack>@<version>`.
|
|
71
|
+
|
|
72
|
+
How it is meant to work: a person writes a rutter, often with help from an AI. Periplus then runs
|
|
73
|
+
it with no AI. A person or an AI reads the map, where every node and edge carries its file and
|
|
74
|
+
line. To improve a map, improve the rutters. The engine stays the same.
|
|
75
|
+
|
|
76
|
+
## Contents
|
|
77
|
+
|
|
78
|
+
- [Get started](#get-started)
|
|
79
|
+
- [Why Periplus](#why-periplus)
|
|
80
|
+
- [What the map holds](#what-the-map-holds)
|
|
81
|
+
- [Write a rutter](#write-a-rutter)
|
|
82
|
+
- [Read the map](#read-the-map)
|
|
83
|
+
- [CLI reference](#cli-reference)
|
|
84
|
+
- [Troubleshooting](#troubleshooting)
|
|
85
|
+
- [Tests and checks](#tests-and-checks)
|
|
86
|
+
- [Known limitations](#known-limitations)
|
|
87
|
+
- [License](#license)
|
|
88
|
+
|
|
89
|
+
## Get started
|
|
90
|
+
|
|
91
|
+
Periplus needs Python 3.11 or later. It declares support for 3.11 to 3.14.
|
|
92
|
+
|
|
93
|
+
### 1. Install Periplus
|
|
94
|
+
|
|
95
|
+
Install it from PyPI:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
uv tool install periplus-map # or: pip install periplus-map
|
|
99
|
+
uv tool install 'periplus-map[go,js]' # adds the grammars that go_basic and js_basic need
|
|
100
|
+
pip install 'periplus-map[go,js]' # the same with pip
|
|
101
|
+
periplus --version
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
To install a tagged version from the repository:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
uv tool install git+https://github.com/camoa/periplus@v0.2.1
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
To install from a local copy of this repository:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
uv tool install /path/to/periplus # or: pip install /path/to/periplus
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
To update a local install, pull the repository and run `uv tool install /path/to/periplus` again. A
|
|
117
|
+
local directory is rebuilt when `pyproject.toml` changes or a file under `src/periplus` does. Run
|
|
118
|
+
`uv tool install --reinstall /path/to/periplus` for the form that always rebuilds. The command
|
|
119
|
+
`periplus status` prints a `rutters:` digest of the bundled rutters, so you can compare two installs.
|
|
120
|
+
|
|
121
|
+
The distribution name is `periplus-map`. Its five runtime dependencies are pinned exactly. One
|
|
122
|
+
package that `jsonschema` brings is compiled, so your platform needs a prebuilt wheel or Rust.
|
|
123
|
+
|
|
124
|
+
To work on Periplus itself, run `uv sync --frozen --all-extras` in the repository. This installs
|
|
125
|
+
the development tools and the Go grammar into `.venv`.
|
|
126
|
+
|
|
127
|
+
### 2. Pin a rutter
|
|
128
|
+
|
|
129
|
+
Run `periplus init` in the project folder. It creates `.periplus/`, a pack folder and a commented
|
|
130
|
+
settings file, and pins a rutter when it recognises the stack:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
cd /path/to/project
|
|
134
|
+
periplus init
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The settings file, `.periplus/settings.yml`, names the rutters to load, each pinned to an exact
|
|
138
|
+
version:
|
|
139
|
+
|
|
140
|
+
```yaml
|
|
141
|
+
periplus_version: 0
|
|
142
|
+
packs:
|
|
143
|
+
- drupal_basic@0.3.0
|
|
144
|
+
folders:
|
|
145
|
+
config: ./config/default
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The `folders` line moves the config folder from `drupal_basic`'s default, `./config/sync`. Leave
|
|
149
|
+
it out when your site uses the default.
|
|
150
|
+
|
|
151
|
+
In a Drupal project, `periplus init` writes the `drupal_basic@0.3.0` pin for you. It looks for
|
|
152
|
+
`drupal/core` in `composer.json`, or for `web/core/lib/Drupal.php`. The rutters that
|
|
153
|
+
`drupal_basic` depends on load without a pin of their own. After you update Periplus, run
|
|
154
|
+
`periplus update` to bring the pins to the installed versions.
|
|
155
|
+
|
|
156
|
+
### 3. Map the project
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
periplus map --output map.json
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`periplus map` also prints a run report. It names each rule and how often it fired, and the files
|
|
163
|
+
no rule read. It also names folders it could not list, files that did not parse, and rules it
|
|
164
|
+
could not run. The [map report guide](docs/map-report-guide.md) reads each part in turn.
|
|
165
|
+
|
|
166
|
+
### 4. Ask the map
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
periplus types
|
|
170
|
+
periplus find TEXT
|
|
171
|
+
periplus show ID
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
[Read the map](#read-the-map) lists the six commands that answer a question about the map.
|
|
175
|
+
|
|
176
|
+
## Why Periplus
|
|
177
|
+
|
|
178
|
+
**The map is one file you commit, it is the same on every run, and nothing serves it.**
|
|
179
|
+
|
|
180
|
+
[`docs/principles.md`](docs/principles.md) gives the reasons for this design: why a new mapper,
|
|
181
|
+
and why rutters and not built-in support for each stack. The table compares Periplus with the
|
|
182
|
+
kinds of tool that page describes.
|
|
183
|
+
|
|
184
|
+
| | Periplus | A source indexer | A server-backed tool | An AI summary |
|
|
185
|
+
|---|---|---|---|---|
|
|
186
|
+
| Framework configuration and templates | Read by rutter rules, as the source files are | Little or nothing | Little or nothing | What the model happens to read |
|
|
187
|
+
| What you get | One JSON file to commit, compare and review | An index for the tool's own queries | A database behind a server or viewer | Ranked text made for one prompt, never saved |
|
|
188
|
+
| What it needs to run | The command line | The tool | A database, a server or a viewer | A model |
|
|
189
|
+
| A new stack | A new rutter, with no engine change | Code in the tool | Code in the tool | A new prompt |
|
|
190
|
+
|
|
191
|
+
## What the map holds
|
|
192
|
+
|
|
193
|
+
The map is one JSON file. It holds the nodes, the edges, counts by type and by kind, the packs
|
|
194
|
+
loaded and the settings file used. Each node has an `id`, a `type`, a `state` and its `locations`
|
|
195
|
+
(file and line). Its `provenance` names the pack, the rule and the rule's declared confidence.
|
|
196
|
+
|
|
197
|
+
The engine writes three states today:
|
|
198
|
+
|
|
199
|
+
- `mapped`: a rule found the thing in a file the project holds.
|
|
200
|
+
- `referenced`: a file names the thing, but no rule read where it is defined. Drupal core is an
|
|
201
|
+
example when only custom code is mapped.
|
|
202
|
+
- `unresolved`: a rule looked for a name and no rule maps it. The node records what was searched.
|
|
203
|
+
|
|
204
|
+
An unresolved node from a map of a Drupal site, shortened:
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{"id": "php.function::Drupal\\my_module\\Plugin\\Action\\json_decode",
|
|
208
|
+
"state": "unresolved", "type": "php.function",
|
|
209
|
+
"unresolved_detail": {"rule": "php_basic/calls_function", "found": "no mapped node of this name",
|
|
210
|
+
"searched_for": "Drupal\\my_module\\Plugin\\Action\\json_decode",
|
|
211
|
+
"types_tried": ["php.function"]}}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Each edge has `from`, `to`, `kind`, its locations, an `occurrences` count and its provenance.
|
|
215
|
+
|
|
216
|
+
**Determinism.** The check `scripts/demo.d/99j-readme-example.sh` maps the example under
|
|
217
|
+
[Write a rutter](#write-a-rutter) twice in one folder, and the two maps are byte-identical. This
|
|
218
|
+
ran on one Linux machine. The design aims for identical maps across machines, but no test has
|
|
219
|
+
compared two machines or two operating systems yet.
|
|
220
|
+
|
|
221
|
+
### The rutters provided
|
|
222
|
+
|
|
223
|
+
What the map holds depends on the rutters loaded. Bundled rutters load by name. Example rutters
|
|
224
|
+
are copied into a project's `.periplus/packs`. The tables group them by language and by framework.
|
|
225
|
+
|
|
226
|
+
<details>
|
|
227
|
+
<summary><strong>Languages and file types</strong></summary>
|
|
228
|
+
|
|
229
|
+
| Rutter | Version | What it finds |
|
|
230
|
+
|---|---|---|
|
|
231
|
+
| `php_basic` | 0.2.0 | PHP classes, interfaces, traits, enums, functions and methods. Inheritance, interfaces, traits, containment, and plain and static calls; a call to a PHP builtin function makes nothing. Reads a parse tree. |
|
|
232
|
+
| `js_basic` | 0.0.1 | JavaScript functions that have a name of their own, each under its script's path. Reads a parse tree. Needs the `js` extra. |
|
|
233
|
+
| `go_basic` | 0.0.3 | Go functions, methods, structs and interfaces, each under its package's import path. Calls written `f(x)` inside one package, and `pkg.F(x)` through an import, to another package of the module or to an unresolved function outside it. Reads a parse tree. Needs the `go` extra. |
|
|
234
|
+
| `yaml_basic` | 0.1.0 | Claims `.yml` and `.yaml` files for rutters that depend on it. No rules of its own. |
|
|
235
|
+
| `twig_basic` | 0.1.0 | Claims `.twig` files for rutters that depend on it. No rules of its own. |
|
|
236
|
+
|
|
237
|
+
</details>
|
|
238
|
+
|
|
239
|
+
<details>
|
|
240
|
+
<summary><strong>Drupal: 2 core rutters and 11 contributed-module rutters</strong></summary>
|
|
241
|
+
|
|
242
|
+
The two core rutters come first. Each contributed module has a rutter of its own, pinned
|
|
243
|
+
beside `drupal_basic` when the site uses that module.
|
|
244
|
+
|
|
245
|
+
| Rutter | Version | What it finds |
|
|
246
|
+
|---|---|---|
|
|
247
|
+
| `drupal_basic` | 0.3.0 | Configuration, modules, themes, services, routes, permissions, libraries, templates, hooks, entity types, fields, displays and plugins. The services and entity types that `\Drupal::service('x')`, `$container->get('x')`, `\Drupal::entityQuery('x')` and an entity type manager's `getStorage('x')` name in PHP functions and methods. Hooks from `Hook` attribute methods, and from procedural functions named by their file's name, such as `mymod_cron` in `mymod.module`. Depends on `php_basic`, `yaml_basic` and `twig_basic`. |
|
|
248
|
+
| `drupal_js_basic` | 0.0.1 | Drupal behaviors and the behaviors they attach, `drupalSettings` keys that PHP attaches and behaviors read, and the libraries that PHP and templates attach. Depends on `js_basic` and `drupal_basic`. |
|
|
249
|
+
| `ai_basic` | 0.0.1 | The AI module's agent plugins and function call plugins, by attribute, each joined to its class. |
|
|
250
|
+
| `advancedqueue_basic` | 0.0.1 | The Advanced Queue module's job type plugins, by attribute or annotation, each joined to its class. |
|
|
251
|
+
| `config_pages_basic` | 0.0.1 | Each Config Pages type, from its config file, as a bundle of the entity type `config_pages`. |
|
|
252
|
+
| `crop_basic` | 0.0.1 | Each Crop API crop type, from its config file, as a bundle of the entity type `crop`. |
|
|
253
|
+
| `drush_basic` | 0.0.1 | Drush commands in the custom modules, from the `Command` attribute or the `@command` tag, each joined to its method and class. |
|
|
254
|
+
| `eck_basic` | 0.0.1 | Each Entity Construction Kit entity type, and each of its bundles, from their config files. |
|
|
255
|
+
| `paragraphs_basic` | 0.0.1 | Each paragraph type, from its config file, as a bundle of the entity type `paragraph`. |
|
|
256
|
+
| `profile_basic` | 0.0.1 | Each Profile type, from its config file, as a bundle of the entity type `profile`. |
|
|
257
|
+
| `salesforce_basic` | 0.0.1 | Salesforce mapping field plugins; each mapping with its Salesforce object and its edges to the bundle, entity type and fields it maps; the Salesforce events that subscribers name. |
|
|
258
|
+
| `twig_tweak_basic` | 0.0.1 | The block plugins, menus, entity types and field storages that Twig Tweak functions such as `drupal_block('x')` name in templates. |
|
|
259
|
+
| `webform_basic` | 0.0.1 | Webform handler plugins, by annotation, and each webform, from its config file, as a bundle of `webform_submission`. |
|
|
260
|
+
|
|
261
|
+
</details>
|
|
262
|
+
|
|
263
|
+
<details>
|
|
264
|
+
<summary><strong>Laravel</strong></summary>
|
|
265
|
+
|
|
266
|
+
| Rutter | Version | What it finds |
|
|
267
|
+
|---|---|---|
|
|
268
|
+
| `laravel_basic` | 0.0.5 | Laravel routes with the prefixes and names of `Route::prefix()->name()->group()` groups, their controller methods, controllers, models, migrations, Blade views with their includes and component tags, and configuration files with the text keys of the array each returns. The views and keys that `view('x')` and `config('x.y')` calls name in PHP functions and methods. Depends on `php_basic`. Reads text, and a parse tree for the calls. |
|
|
269
|
+
|
|
270
|
+
</details>
|
|
271
|
+
|
|
272
|
+
<details>
|
|
273
|
+
<summary><strong>Examples</strong></summary>
|
|
274
|
+
|
|
275
|
+
| Rutter | Version | What it finds |
|
|
276
|
+
|---|---|---|
|
|
277
|
+
| `python_text` | 0.1.0 | Python modules, top-level classes and functions, imports and calls. Reads text. |
|
|
278
|
+
| `typer_text` | 0.1.0 | Typer apps, commands and mounts. Depends on `python_text`. |
|
|
279
|
+
| `speckitty` | 0.1.0 | spec-kitty missions and their templates. |
|
|
280
|
+
|
|
281
|
+
</details>
|
|
282
|
+
|
|
283
|
+
<details>
|
|
284
|
+
<summary><strong>Reference packs</strong></summary>
|
|
285
|
+
|
|
286
|
+
The bundle also holds five older reference packs. They pass `periplus validate`, but they hold
|
|
287
|
+
vocabulary only and cannot make a map.
|
|
288
|
+
|
|
289
|
+
| Pack | Version |
|
|
290
|
+
|---|---|
|
|
291
|
+
| `php` | 0.1.0 |
|
|
292
|
+
| `drupal` | 0.1.0 |
|
|
293
|
+
| `yaml` | 0.0.1 |
|
|
294
|
+
| `twig` | 0.0.1 |
|
|
295
|
+
| `go` | 0.0.2 |
|
|
296
|
+
|
|
297
|
+
</details>
|
|
298
|
+
|
|
299
|
+
The bundled rutters are in `src/periplus/packs`. The examples are in
|
|
300
|
+
`examples/second-stack/packs`. The manifest of every rutter in the tables above, except
|
|
301
|
+
`yaml_basic`, `twig_basic`, the examples and the reference packs, opens with a list of its known
|
|
302
|
+
gaps.
|
|
303
|
+
|
|
304
|
+
To map a Go module, install the `go` extra and run Periplus at the module's root. Give the module
|
|
305
|
+
path in the settings, because Periplus does not read `go.mod`:
|
|
306
|
+
|
|
307
|
+
```yaml
|
|
308
|
+
periplus_version: 0
|
|
309
|
+
packs:
|
|
310
|
+
- go_basic@0.0.3
|
|
311
|
+
values:
|
|
312
|
+
module: example.com/app
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
To map a Laravel application, pin `php_basic@0.2.0` and `laravel_basic@0.0.5` and run Periplus
|
|
316
|
+
at the application's root. The default Laravel folders need no settings. To move the templates,
|
|
317
|
+
set `views_root` under `folders`; a template is named by its path below `views_root`.
|
|
318
|
+
|
|
319
|
+
New in this release: `drupal_basic` 0.3.0, the 11 contributed-module rutters listed after it in
|
|
320
|
+
the Drupal table, and the two JavaScript rutters, `js_basic` and `drupal_js_basic`. The AI and
|
|
321
|
+
Advanced Queue plugins moved out of `drupal_basic` into their own rutters. Three new rutter
|
|
322
|
+
shapes: a resolution step that looks a written name up in a table the rutter declares under
|
|
323
|
+
`tables`, a call argument written as a class constant read through the grammar's
|
|
324
|
+
`constant_access` and `constant_declaration` keys, and a rule narrowed to one file ending by
|
|
325
|
+
`match.ending`. A rutter's `boundary` lists the framework classes the map never reads. Each one
|
|
326
|
+
an edge reaches becomes a `declared` node, and a class that descends from one may take the type
|
|
327
|
+
the list gives it. Settings `values` pass project facts, such as a Go module path, to a rutter.
|
|
328
|
+
|
|
329
|
+
## Write a rutter
|
|
330
|
+
|
|
331
|
+
A rutter for a new stack is a folder of YAML files in the project. You write it, map the
|
|
332
|
+
project, read what the map cannot explain, and write the next rule.
|
|
333
|
+
|
|
334
|
+
### The loop
|
|
335
|
+
|
|
336
|
+
1. Run `periplus init` in the project folder. It creates `.periplus/packs/` and the settings file
|
|
337
|
+
`.periplus/settings.yml`. It pins a bundled rutter when it recognises the stack. For a new
|
|
338
|
+
stack, write a first rutter and pin it, as in the example below.
|
|
339
|
+
2. Run `periplus map --output map.json --format json >report.json`. A map needs at least one
|
|
340
|
+
pinned rutter, and with none it stops at exit 17.
|
|
341
|
+
3. Read the unknowns. In the report, `unread` lists the files in the rules' folders that no rule
|
|
342
|
+
read. `skipped` lists each match whose rule could not build a node or edge it emits, with the
|
|
343
|
+
reason. `not_executed` lists the rules the engine cannot run, and why. In the map,
|
|
344
|
+
`counts.nodes_by_state` counts the `referenced` nodes, which a file names but no rule maps. It
|
|
345
|
+
also counts the `unresolved` nodes, which a rule looked for and did not find.
|
|
346
|
+
4. Write a rule for those names in a rutter under `.periplus/packs/`. Pin a new rutter under
|
|
347
|
+
`packs` in the settings. To build on a bundled rutter, name it in `depends`, as
|
|
348
|
+
`depends: [php_basic]`. Your rutter may then use its folders, file types and types, and add
|
|
349
|
+
rules. The bundled rutter's own files stay as installed.
|
|
350
|
+
5. Run `periplus validate <pack>`. It names each file and place that disagrees with the schemas. A
|
|
351
|
+
rutter that does not validate stops the map.
|
|
352
|
+
6. Map again. The unknowns you covered disappear. Go back to step 3.
|
|
353
|
+
|
|
354
|
+
### Where a rutter and its settings live
|
|
355
|
+
|
|
356
|
+
A project's own rutters sit in `.periplus/packs/`, one folder per rutter, named
|
|
357
|
+
`<pack>@<version>`. Each holds a manifest, `pack.yaml`, and pack files: every other `.yaml` or
|
|
358
|
+
`.yml` file, in any subfolder.
|
|
359
|
+
|
|
360
|
+
The settings file, `.periplus/settings.yml`, names:
|
|
361
|
+
|
|
362
|
+
- `packs`: the rutters to load, each pinned as `<pack>@<version>`. A pinned rutter's dependencies
|
|
363
|
+
load without a pin of their own.
|
|
364
|
+
- `folders`: a new place for a folder that a rutter names. A project that keeps the example's
|
|
365
|
+
lists in `todo` sets `folders: {lists: ./todo/**}`. The rules then read `todo` and every folder
|
|
366
|
+
below it.
|
|
367
|
+
- `values`: named text values that any template of any rutter may name, such as `{module}`.
|
|
368
|
+
- `pack_paths`: more folders to find rutters in, relative to the project folder.
|
|
369
|
+
- `re_include`: globs that take back the files a rutter's `files.exclude` leaves out.
|
|
370
|
+
|
|
371
|
+
`periplus status` lists where Periplus looks for a pinned rutter: the project's
|
|
372
|
+
`.periplus/packs`, the user's configuration folder, the bundled rutters and each `pack_paths`
|
|
373
|
+
folder. A bundled rutter, such as `php_basic`, loads by its pin alone.
|
|
374
|
+
|
|
375
|
+
### A complete small rutter
|
|
376
|
+
|
|
377
|
+
This rutter reads a line format invented for this example, a list of chores. A line
|
|
378
|
+
`chore <name>` declares a chore. `after <name>` at its end names the chore it waits for. Write
|
|
379
|
+
these four files in an empty folder.
|
|
380
|
+
|
|
381
|
+
<!-- example: .periplus/settings.yml -->
|
|
382
|
+
```yaml
|
|
383
|
+
periplus_version: 0
|
|
384
|
+
packs:
|
|
385
|
+
- chores@0.0.1
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
<!-- example: .periplus/packs/chores@0.0.1/pack.yaml -->
|
|
389
|
+
```yaml
|
|
390
|
+
pack: chores
|
|
391
|
+
version: 0.0.1
|
|
392
|
+
depends: []
|
|
393
|
+
folders:
|
|
394
|
+
lists: ./lists
|
|
395
|
+
files:
|
|
396
|
+
types:
|
|
397
|
+
chores:
|
|
398
|
+
endings: [chores]
|
|
399
|
+
reader: text
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
<!-- example: .periplus/packs/chores@0.0.1/rules/chores.yaml -->
|
|
403
|
+
```yaml
|
|
404
|
+
node_types:
|
|
405
|
+
- name: chores.chore
|
|
406
|
+
id_namespace: chores.chore
|
|
407
|
+
edge_kinds:
|
|
408
|
+
- kind: waits_for
|
|
409
|
+
from: chores.chore
|
|
410
|
+
to: chores.chore
|
|
411
|
+
rules:
|
|
412
|
+
- rule: chore
|
|
413
|
+
reads: file
|
|
414
|
+
in: [lists]
|
|
415
|
+
match: {file: '*', filetype: chores, text: '(?m)^chore (?<name>\w+)'}
|
|
416
|
+
id: {from: {capture: name}}
|
|
417
|
+
emits: [{node: {type: chores.chore}}]
|
|
418
|
+
confidence: declared
|
|
419
|
+
- rule: chore_waits
|
|
420
|
+
reads: file
|
|
421
|
+
in: [lists]
|
|
422
|
+
match: {file: '*', filetype: chores, text: '(?m)^chore (?<name>\w+) after (?<after>\w+)'}
|
|
423
|
+
id: {from: {capture: name}}
|
|
424
|
+
emits: [{edge: {kind: waits_for, from: this_node, to: {from: {capture: after}}}}]
|
|
425
|
+
confidence: declared
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
<!-- example: lists/home.chores -->
|
|
429
|
+
```text
|
|
430
|
+
# the week
|
|
431
|
+
chore dishes
|
|
432
|
+
chore laundry after dishes
|
|
433
|
+
chore floors after sweeping
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
`pack.yaml` gives the rutter's name and version, a folder `lists`, and a file type `chores` for
|
|
437
|
+
files ending in `.chores`, read as text. The pack file declares the node type `chores.chore` and
|
|
438
|
+
the edge kind `waits_for`. The rule `chore` fires once per match of its `text` pattern, and the
|
|
439
|
+
capture `name` gives the node's id. The rule `chore_waits` adds a `waits_for` edge from that node
|
|
440
|
+
to the name after `after`. `periplus validate` refuses one rule that emits both the node and the
|
|
441
|
+
edge, so the edge has its own rule. `confidence: declared` says the file states the thing.
|
|
442
|
+
|
|
443
|
+
Run `periplus validate chores`, then `periplus map --output map.json`. The map holds exactly these
|
|
444
|
+
nodes and edges, each with its state or kind and its file and line:
|
|
445
|
+
|
|
446
|
+
<!-- example-map -->
|
|
447
|
+
```text
|
|
448
|
+
node chores.chore::dishes mapped lists/home.chores:2
|
|
449
|
+
node chores.chore::laundry mapped lists/home.chores:3
|
|
450
|
+
node chores.chore::floors mapped lists/home.chores:4
|
|
451
|
+
node chores.chore::sweeping referenced
|
|
452
|
+
edge chores.chore::laundry waits_for chores.chore::dishes lists/home.chores:3
|
|
453
|
+
edge chores.chore::floors waits_for chores.chore::sweeping lists/home.chores:4
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
`sweeping` is `referenced`: line 4 names it, and no rule maps it. That is the kind of unknown
|
|
457
|
+
that step 3 of the loop finds. The check `scripts/demo.d/99j-readme-example.sh` runs this example
|
|
458
|
+
from this file and compares the map with the lines above.
|
|
459
|
+
|
|
460
|
+
### What to read next
|
|
461
|
+
|
|
462
|
+
| Read | For |
|
|
463
|
+
|---|---|
|
|
464
|
+
| `periplus spec` | The contract: the schemas, the rule format, the engine, and what the format cannot say yet. `periplus spec <pack>` adds what one rutter declares and inherits. |
|
|
465
|
+
| [`docs/rutter-author-guide.md`](docs/rutter-author-guide.md) | Start here: the files of a rutter, one rule of each shape, and how to check a rutter. |
|
|
466
|
+
| [`docs/rutter-author-guide-text.md`](docs/rutter-author-guide-text.md) | Text files: spans, values from enclosing spans, the line of a node, and a path below a folder. |
|
|
467
|
+
| [`docs/rutter-author-guide-drupal.md`](docs/rutter-author-guide-drupal.md) | Parse-tree rules, read through the PHP and Drupal rutters. |
|
|
468
|
+
| [`docs/rutter-author-guide-references.md`](docs/rutter-author-guide-references.md) | Calls read from a parse tree, and every key the schemas accept that the engine does not run. |
|
|
469
|
+
| [`docs/rutter-author-guide-imports.md`](docs/rutter-author-guide-imports.md) | Import paths and a call's arguments. |
|
|
470
|
+
| [`docs/rutter-author-guide-abilities.md`](docs/rutter-author-guide-abilities.md) | A condition on a second child, an id that must fit a pattern, a declared end, and a class constant as a call's argument. |
|
|
471
|
+
| [`docs/rutter-author-guide-map-rules.md`](docs/rutter-author-guide-map-rules.md) | Map rules: rules that read the map the file rules made, run in passes, one hop each. |
|
|
472
|
+
| `examples/second-stack/packs` | Three working text rutters to copy: `python_text`, `typer_text` and `speckitty`. |
|
|
473
|
+
| `periplus validate <pack>` | Checks one rutter's files. It names each disagreement with the schemas, by file and place. |
|
|
474
|
+
| [`docs/map-report-guide.md`](docs/map-report-guide.md) | Reading the map report: each part in the order to read it, what it means, and what to do when it is not empty. |
|
|
475
|
+
|
|
476
|
+
A parse-tree rutter pins its grammar under `grammar` in `pack.yaml`, as `php_basic` does.
|
|
477
|
+
Periplus installs the PHP grammar, and the Go grammar with the `go` extra. Another language needs
|
|
478
|
+
its `tree-sitter-<language>` package installed beside Periplus, or the map stops at exit 28.
|
|
479
|
+
|
|
480
|
+
An AI that writes a rutter reads `periplus spec` first, then the guide pages in the order above.
|
|
481
|
+
Then it runs the loop. The map's `referenced` and `unresolved` nodes say which rule to write next.
|
|
482
|
+
|
|
483
|
+
## Read the map
|
|
484
|
+
|
|
485
|
+
Six commands answer a question about a written map, and stop: `periplus types` counts the node
|
|
486
|
+
types and edge kinds, `periplus find TEXT` searches node ids, `periplus show ID` prints a node
|
|
487
|
+
and its edges, `periplus neighbors ID` and `periplus affected ID` follow edges out of and into a
|
|
488
|
+
node, and `periplus path FROM TO` prints the shortest chains between two. They read the ids the
|
|
489
|
+
map holds and nothing more. `periplus check-map` runs the full schema check that these commands
|
|
490
|
+
skip. The [navigation guide](docs/navigation.md) gives each command's options, output and exit
|
|
491
|
+
codes, with an example you can run.
|
|
492
|
+
|
|
493
|
+
## CLI reference
|
|
494
|
+
|
|
495
|
+
Run each command in the project folder.
|
|
496
|
+
|
|
497
|
+
```
|
|
498
|
+
periplus init # create .periplus/, a pack folder and a commented settings file
|
|
499
|
+
periplus status # report the settings, where each value came from, and the pack search path
|
|
500
|
+
periplus spec [PACK] [--summary] # print the rutter contract, and what one rutter declares and inherits
|
|
501
|
+
periplus validate PACK # check one rutter's files against the shipped schemas and name what disagrees
|
|
502
|
+
periplus update # move each pin to the installed version of that rutter
|
|
503
|
+
periplus map --output map.json # map this project and write the map, with a run report
|
|
504
|
+
periplus types # count the node types and edge kinds in the written map
|
|
505
|
+
periplus check-map # check every node and edge of the map against the map schema
|
|
506
|
+
periplus find TEXT # find the nodes whose id holds a text
|
|
507
|
+
periplus show ID # show one node and the edges at it
|
|
508
|
+
periplus neighbors ID # list the items an item's edges lead to
|
|
509
|
+
periplus affected ID # list the items whose edges lead to an item
|
|
510
|
+
periplus path FROM TO # show every shortest chain of edges from one item to another
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
`periplus validate` takes a bare `name`, or `name@version` to pick one of several copies.
|
|
514
|
+
`periplus update` leaves project-local and unknown pins as they are. Every command but `init`
|
|
515
|
+
takes `--format json`. The seven commands that read a map take `--map PATH`; the
|
|
516
|
+
[navigation guide](docs/navigation.md) gives their other options. `periplus --version` prints the
|
|
517
|
+
installed version, and `periplus <command> --help` gives each command's options.
|
|
518
|
+
|
|
519
|
+
## Troubleshooting
|
|
520
|
+
|
|
521
|
+
- **`periplus map` stops at exit 17.** The project pins no rutter, so there is nothing to map.
|
|
522
|
+
Run `periplus init`, or pin a rutter under `packs` in `.periplus/settings.yml`. Exit 17 also
|
|
523
|
+
marks a map that fails its own schema, which is an engine defect. Nothing is written in
|
|
524
|
+
either case.
|
|
525
|
+
- **`periplus map` stops at exit 28: a grammar mismatch.** A rutter's `grammar` in `pack.yaml`
|
|
526
|
+
pins a parser runtime or a grammar version other than the one installed, or one that is not
|
|
527
|
+
installed. The message names the rutter, the package, the version pinned and the version
|
|
528
|
+
found. Install the `go` or `js` extra for `go_basic` or `js_basic`. For another language,
|
|
529
|
+
install its `tree-sitter-<language>` package at the pinned version. The check runs before any
|
|
530
|
+
source file is opened.
|
|
531
|
+
- **A navigation command stops at exit 29, 30 or 31.** It found no map, the file is not a map,
|
|
532
|
+
or the id names no node. The [navigation guide](docs/navigation.md) gives the remedy for each.
|
|
533
|
+
|
|
534
|
+
## Tests and checks
|
|
535
|
+
|
|
536
|
+
The pytest suite holds 592 tests. `scripts/demo.sh` runs the 76 end-to-end checks in
|
|
537
|
+
`scripts/demo.d` and stops at the first failure. Each check maps a small project and compares the
|
|
538
|
+
result with what it expects. The CI workflow behind the checks badge does not run them.
|
|
539
|
+
|
|
540
|
+
To propose a change, read [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
|
541
|
+
|
|
542
|
+
## Known limitations
|
|
543
|
+
|
|
544
|
+
These are the limits a new user meets first. [`docs/known-limitations.md`](docs/known-limitations.md)
|
|
545
|
+
lists the rest, each rutter's among them.
|
|
546
|
+
|
|
547
|
+
- **Keys accepted but not executed.** The schemas accept more than the engine runs, for example
|
|
548
|
+
`resolution` and `excluded_tokens`. A rule with such a key does
|
|
549
|
+
not run. Such a key outside a rule stops the map. `rutter-author-guide-references.md` lists every key.
|
|
550
|
+
- **No order among rutters.** Two rules in one rutter on one parse-tree node: the last one wins.
|
|
551
|
+
Nothing settles two rutters that give one attribute two values.
|
|
552
|
+
- **One edge kind name for all rutters.** `php_basic`, `go_basic` and `python_text` each declare
|
|
553
|
+
`calls` with different ends. So one project cannot load `php_basic` beside either of the others.
|
|
554
|
+
- **Patterns run on Python's `re`, not RE2.** Nothing checks for the RE2 subset, and
|
|
555
|
+
`laravel_basic` uses backreferences and lookarounds. Python `re` refuses only what it cannot
|
|
556
|
+
compile, such as a variable-width lookbehind.
|
|
557
|
+
- **An unresolved end takes its first candidate type.** For example, `pathlib.Path` becomes a
|
|
558
|
+
`python.function`. The map states a type it cannot know.
|
|
559
|
+
- **One JSON file, and every run is a full run.** There is no split map and no incremental run.
|
|
560
|
+
- **No export.** There is no GraphML, Mermaid or DOT output yet.
|
|
561
|
+
|
|
562
|
+
## License
|
|
563
|
+
|
|
564
|
+
Apache License 2.0. See [`LICENSE`](LICENSE) and [`NOTICE`](NOTICE).
|
|
565
|
+
|
|
566
|
+
Built with AI assistance. Periplus uses no AI to make a map.
|