tan-cli 0.7.0__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.
- tan/__init__.py +0 -0
- tan/__main__.py +120 -0
- tan/cli.py +939 -0
- tan/command_table.py +265 -0
- tan/commands/__init__.py +8 -0
- tan/commands/bootstrap_cmd.py +4856 -0
- tan/commands/bootstrap_patches.py +164 -0
- tan/commands/bootstrap_toolchain_fetch.py +155 -0
- tan/commands/bootstrap_toolchain_pin.py +36 -0
- tan/commands/build/__init__.py +1 -0
- tan/commands/build/configure_inputs.py +277 -0
- tan/commands/build/execute.py +1852 -0
- tan/commands/build/host_python.py +59 -0
- tan/commands/build/link_stale.py +78 -0
- tan/commands/build/manifest.py +428 -0
- tan/commands/build/materialise.py +81 -0
- tan/commands/build/token_substitution.py +381 -0
- tan/commands/build/toolchain.py +482 -0
- tan/commands/build/user_defines_wipe.py +115 -0
- tan/commands/build/workspace_patches.py +65 -0
- tan/commands/build_cmd.py +2236 -0
- tan/commands/build_output.py +331 -0
- tan/commands/clean_cmd.py +1183 -0
- tan/commands/completion_cmd.py +786 -0
- tan/commands/debug_config_cmd.py +2425 -0
- tan/commands/diff_cmd.py +940 -0
- tan/commands/doctor_cmd.py +4767 -0
- tan/commands/examples_cmd.py +644 -0
- tan/commands/explain_cmd.py +1319 -0
- tan/commands/faultdecode_cmd.py +931 -0
- tan/commands/flash_atoc_guard.py +240 -0
- tan/commands/flash_cmd.py +5731 -0
- tan/commands/flash_mram_guard.py +150 -0
- tan/commands/flash_ram.py +578 -0
- tan/commands/flash_raw.py +583 -0
- tan/commands/generate_cmd.py +1456 -0
- tan/commands/image_cmd.py +753 -0
- tan/commands/init_cmd.py +1740 -0
- tan/commands/inspect_cmd.py +377 -0
- tan/commands/kconfig_cmd.py +734 -0
- tan/commands/model_cmd.py +1514 -0
- tan/commands/model_device_cmd.py +351 -0
- tan/commands/model_device_live.py +234 -0
- tan/commands/model_host_cmd.py +430 -0
- tan/commands/model_zoo_cmd.py +363 -0
- tan/commands/monitor_actions.py +125 -0
- tan/commands/monitor_cmd.py +626 -0
- tan/commands/monitor_session.py +505 -0
- tan/commands/new_som_cmd.py +1522 -0
- tan/commands/pinmux_cmd.py +568 -0
- tan/commands/presets_cmd.py +1123 -0
- tan/commands/probe_cmd.py +421 -0
- tan/commands/reset_cmd.py +354 -0
- tan/commands/reset_confirm.py +168 -0
- tan/commands/run_cmd.py +637 -0
- tan/commands/scaffold_cmd.py +490 -0
- tan/commands/sdk_cmd.py +1723 -0
- tan/commands/size_cmd.py +1020 -0
- tan/commands/support_bundle_cmd.py +1073 -0
- tan/commands/trace_cmd.py +341 -0
- tan/commands/validate_cmd.py +2009 -0
- tan/commands/west_forward_cmd.py +736 -0
- tan/commands/workspace_patch_check.py +296 -0
- tan/core/__init__.py +1 -0
- tan/core/alp_conf_pregen.py +100 -0
- tan/core/artifact_provenance.py +240 -0
- tan/core/atoc_guard.py +276 -0
- tan/core/atoc_guard_messages.py +232 -0
- tan/core/atoc_replacement.py +118 -0
- tan/core/atomic_write.py +178 -0
- tan/core/board_context.py +351 -0
- tan/core/board_diagnostic.py +111 -0
- tan/core/board_files.py +221 -0
- tan/core/board_validator.py +542 -0
- tan/core/board_validator_compat.py +196 -0
- tan/core/board_validator_run.py +129 -0
- tan/core/board_validator_schema.py +186 -0
- tan/core/board_validator_skew.py +46 -0
- tan/core/board_yaml_edit.py +295 -0
- tan/core/board_yaml_pos.py +118 -0
- tan/core/bootstrap.py +2572 -0
- tan/core/build_plan.py +625 -0
- tan/core/consent.py +104 -0
- tan/core/console_filter.py +245 -0
- tan/core/debug_launch.py +1803 -0
- tan/core/devicetree_lint.py +168 -0
- tan/core/dir_removal.py +229 -0
- tan/core/doctor_git.py +172 -0
- tan/core/doctor_libraries.py +253 -0
- tan/core/doctor_render.py +185 -0
- tan/core/doctor_scope.py +66 -0
- tan/core/doctor_setools.py +237 -0
- tan/core/doctor_stale.py +180 -0
- tan/core/document_guards.py +723 -0
- tan/core/dp_id.py +97 -0
- tan/core/elf_load.py +63 -0
- tan/core/error_catalog.py +171 -0
- tan/core/example_catalog.py +499 -0
- tan/core/example_facets.py +151 -0
- tan/core/faultdecode.py +521 -0
- tan/core/flash_plan.py +2501 -0
- tan/core/flow_d_report.py +381 -0
- tan/core/flow_d_uptime.py +164 -0
- tan/core/fs_confine.py +130 -0
- tan/core/global_flags.py +230 -0
- tan/core/host_python.py +210 -0
- tan/core/image_bundle.py +247 -0
- tan/core/inert.py +147 -0
- tan/core/jlink_binary.py +128 -0
- tan/core/jlink_probe.py +481 -0
- tan/core/jsonc_splice.py +404 -0
- tan/core/launch_provenance.py +257 -0
- tan/core/link_refusal.py +76 -0
- tan/core/metadata_schema.py +376 -0
- tan/core/model_check.py +227 -0
- tan/core/model_device.py +449 -0
- tan/core/model_doctor.py +198 -0
- tan/core/model_host.py +48 -0
- tan/core/model_list.py +112 -0
- tan/core/model_zoo.py +353 -0
- tan/core/module_template.py +340 -0
- tan/core/mram_link.py +87 -0
- tan/core/new_som_ospi.py +94 -0
- tan/core/os_class.py +159 -0
- tan/core/patch_paths.py +87 -0
- tan/core/pending.py +40 -0
- tan/core/plain_zephyr_plan.py +138 -0
- tan/core/plan_exec.py +373 -0
- tan/core/plan_tokens.py +600 -0
- tan/core/probe.py +155 -0
- tan/core/probe_plan.py +237 -0
- tan/core/proxy.py +168 -0
- tan/core/publish.py +31 -0
- tan/core/python_floor.py +178 -0
- tan/core/ram_run.py +694 -0
- tan/core/ram_watch.py +231 -0
- tan/core/raw_write.py +160 -0
- tan/core/reset_plan.py +56 -0
- tan/core/run.py +161 -0
- tan/core/scaffold.py +2203 -0
- tan/core/scaffold_selftest_identity.py +225 -0
- tan/core/sdk_default_registry.py +565 -0
- tan/core/sdk_discovery.py +996 -0
- tan/core/sdk_removal.py +465 -0
- tan/core/serial_actions.py +175 -0
- tan/core/serial_capture.py +185 -0
- tan/core/serial_url.py +45 -0
- tan/core/setools.py +608 -0
- tan/core/setools_scratch.py +243 -0
- tan/core/shapes.py +194 -0
- tan/core/size.py +610 -0
- tan/core/som_buildability.py +204 -0
- tan/core/som_schema_version.py +62 -0
- tan/core/subprocess_env.py +201 -0
- tan/core/sysbuild_image.py +94 -0
- tan/core/system_manifest.py +827 -0
- tan/core/text_layout.py +73 -0
- tan/core/timestamp.py +182 -0
- tan/core/tool_lookup.py +383 -0
- tan/core/toolchain_pin.py +117 -0
- tan/core/toolchain_provision.py +1224 -0
- tan/core/trusted_path.py +134 -0
- tan/core/uboot_breakin.py +154 -0
- tan/core/uri_reference.py +415 -0
- tan/core/user_defines.py +152 -0
- tan/core/venv.py +332 -0
- tan/core/west_patches.py +143 -0
- tan/core/west_workspace_refusal.py +159 -0
- tan/core/zephyr_env.py +124 -0
- tan/env.py +185 -0
- tan/envelope.py +647 -0
- tan/exit_codes.py +12 -0
- tan/lazy_typer.py +185 -0
- tan/model/__init__.py +2 -0
- tan/model/_gen_fixture.py +132 -0
- tan/model/adapters/__init__.py +116 -0
- tan/model/adapters/cpu.py +26 -0
- tan/model/adapters/deepx.py +94 -0
- tan/model/adapters/drpai.py +242 -0
- tan/model/adapters/ethos_u.py +951 -0
- tan/model/adapters/executorch.py +55 -0
- tan/model/analyze.py +694 -0
- tan/model/build.py +304 -0
- tan/model/check.py +682 -0
- tan/model/manifest.py +625 -0
- tan/model/measure.py +216 -0
- tan/model/npu_ops_validate.py +130 -0
- tan/model/package.py +125 -0
- tan/model/perf.py +635 -0
- tan/model/perf_apply.py +721 -0
- tan/model/prep.py +193 -0
- tan/model/sram_fit.py +502 -0
- tan/model/targets.py +374 -0
- tan/model/tensorio.py +287 -0
- tan/net.py +73 -0
- tan/output_format.py +213 -0
- tan/planner/__init__.py +219 -0
- tan/planner/aperture.py +202 -0
- tan/planner/buildplan.py +1092 -0
- tan/planner/camera_owner.py +192 -0
- tan/planner/cameras.py +132 -0
- tan/planner/carveout.py +755 -0
- tan/planner/cli.py +274 -0
- tan/planner/headers.py +315 -0
- tan/planner/kconfig.py +2435 -0
- tan/planner/kconfig_symbols.py +473 -0
- tan/planner/libraries.py +677 -0
- tan/planner/link_target.py +237 -0
- tan/planner/linux_ownership.py +216 -0
- tan/planner/loader.py +1525 -0
- tan/planner/manifest.py +116 -0
- tan/planner/memory.py +161 -0
- tan/planner/memregion.py +56 -0
- tan/planner/models.py +533 -0
- tan/planner/orchestrator.py +874 -0
- tan/planner/ownership.py +203 -0
- tan/planner/partition.py +1160 -0
- tan/planner/paths.py +32 -0
- tan/planner/plain_slice.py +139 -0
- tan/planner/project_emit/__init__.py +60 -0
- tan/planner/project_emit/bom_netlist.py +375 -0
- tan/planner/project_emit/dts.py +580 -0
- tan/planner/project_emit/hw_info.py +221 -0
- tan/planner/project_emit/native_sim.py +136 -0
- tan/planner/project_emit/west_libs.py +213 -0
- tan/planner/project_loader.py +264 -0
- tan/planner/sdk_capability.py +203 -0
- tan/planner/sdk_compat.py +395 -0
- tan/planner/secure.py +350 -0
- tan/planner/slugs.py +394 -0
- tan/planner/som_metadata.py +325 -0
- tan/planner/strict_loaders.py +131 -0
- tan/planner/template.py +1037 -0
- tan/planner/template_pins.py +535 -0
- tan/planner/template_rewrite.py +714 -0
- tan/planner/topology.py +208 -0
- tan/planner/validate.py +365 -0
- tan/planner/whole_device_alias.py +67 -0
- tan/planner/zephyr_board.py +3510 -0
- tan/planner_cli.py +97 -0
- tan/planner_emit.py +617 -0
- tan/planner_root.py +119 -0
- tan/soc_ref.py +58 -0
- tan/templates/__init__.py +34 -0
- tan/templates/vendored/MANIFEST.md +1862 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/README.md +112 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/board.yaml +38 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/boards/native_sim_native_64.conf +11 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/boards/native_sim_native_64.overlay +29 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/prj.conf +5 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/src/main.c +266 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/testcase.yaml +53 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/CMakeLists.txt +8 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/README.md +112 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/board.yaml +38 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/boards/native_sim_native_64.conf +11 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/boards/native_sim_native_64.overlay +29 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/prj.conf +5 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/src/main.c +266 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/testcase.yaml +53 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/CMakeLists.txt +10 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/README.md +75 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/board.yaml +38 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/prj.conf +8 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/src/cold_chain.c +371 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/src/cold_chain.h +178 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/src/main.c +373 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/testcase.yaml +62 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/CMakeLists.txt +10 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/README.md +75 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/board.yaml +37 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/prj.conf +8 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/src/cold_chain.c +371 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/src/cold_chain.h +178 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/src/main.c +373 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/testcase.yaml +62 -0
- tan/templates/vendored/iot/E1M-AEN801/CMakeLists.txt +14 -0
- tan/templates/vendored/iot/E1M-AEN801/README.md +103 -0
- tan/templates/vendored/iot/E1M-AEN801/board.yaml +69 -0
- tan/templates/vendored/iot/E1M-AEN801/prj.conf +15 -0
- tan/templates/vendored/iot/E1M-AEN801/src/cc3501e_bridge.c +196 -0
- tan/templates/vendored/iot/E1M-AEN801/src/cc3501e_bridge.h +173 -0
- tan/templates/vendored/iot/E1M-AEN801/src/main.c +262 -0
- tan/templates/vendored/iot/E1M-AEN801/testcase.yaml +68 -0
- tan/templates/vendored/minimal/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/minimal/E1M-AEN801/README.md +108 -0
- tan/templates/vendored/minimal/E1M-AEN801/board.yaml +32 -0
- tan/templates/vendored/minimal/E1M-AEN801/prj.conf +8 -0
- tan/templates/vendored/minimal/E1M-AEN801/src/main.c +111 -0
- tan/templates/vendored/minimal/E1M-AEN801/testcase.yaml +49 -0
- tan/templates/vendored/minimal/E1M-V2N101/CMakeLists.txt +8 -0
- tan/templates/vendored/minimal/E1M-V2N101/README.md +108 -0
- tan/templates/vendored/minimal/E1M-V2N101/board.yaml +32 -0
- tan/templates/vendored/minimal/E1M-V2N101/prj.conf +8 -0
- tan/templates/vendored/minimal/E1M-V2N101/src/main.c +111 -0
- tan/templates/vendored/minimal/E1M-V2N101/testcase.yaml +49 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/README.md +120 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/board.yaml +57 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/boards/native_sim_native_64.overlay +40 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/CMakeLists.txt +13 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/main.c +171 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/prj.conf +17 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/testcase.yaml +23 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/prj.conf +22 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/src/main.c +185 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/testcase.yaml +26 -0
- tan/templates/vendored/sensor/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/sensor/E1M-AEN801/README.md +112 -0
- tan/templates/vendored/sensor/E1M-AEN801/board.yaml +57 -0
- tan/templates/vendored/sensor/E1M-AEN801/boards/native_sim_native_64.conf +10 -0
- tan/templates/vendored/sensor/E1M-AEN801/boards/native_sim_native_64.overlay +28 -0
- tan/templates/vendored/sensor/E1M-AEN801/prj.conf +5 -0
- tan/templates/vendored/sensor/E1M-AEN801/src/main.c +186 -0
- tan/templates/vendored/sensor/E1M-AEN801/testcase.yaml +52 -0
- tan/templates/vendored/sensor/E1M-V2N101/CMakeLists.txt +8 -0
- tan/templates/vendored/sensor/E1M-V2N101/README.md +112 -0
- tan/templates/vendored/sensor/E1M-V2N101/board.yaml +57 -0
- tan/templates/vendored/sensor/E1M-V2N101/boards/native_sim_native_64.conf +10 -0
- tan/templates/vendored/sensor/E1M-V2N101/boards/native_sim_native_64.overlay +28 -0
- tan/templates/vendored/sensor/E1M-V2N101/prj.conf +5 -0
- tan/templates/vendored/sensor/E1M-V2N101/src/main.c +186 -0
- tan/templates/vendored/sensor/E1M-V2N101/testcase.yaml +52 -0
- tan/version.py +102 -0
- tan_cli-0.7.0.dist-info/METADATA +125 -0
- tan_cli-0.7.0.dist-info/RECORD +330 -0
- tan_cli-0.7.0.dist-info/WHEEL +5 -0
- tan_cli-0.7.0.dist-info/entry_points.txt +2 -0
- tan_cli-0.7.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,786 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""`tan completion` -- emit a shell completion script for bash, zsh, or fish.
|
|
3
|
+
|
|
4
|
+
Mirrors `crates/tan-cli/src/commands/completion.rs`. The three scripts below
|
|
5
|
+
are embedded verbatim: byte-for-byte captures of the reference Rust oracle's
|
|
6
|
+
own `data.script` field (`target/debug/tan.exe completion --shell
|
|
7
|
+
<bash|zsh|fish> --format json`), the same "captured, not generated" contract
|
|
8
|
+
the oracle's own module docstring describes (there it is `include_str!` over a
|
|
9
|
+
committed `.bash`/`.zsh`/`.fish` file; here it is a literal, since this unit's
|
|
10
|
+
file allowlist is `completion_cmd.py` alone).
|
|
11
|
+
|
|
12
|
+
**One deliberate exception to that, tan-cli#403: the `--format` value lists.**
|
|
13
|
+
The captures hardcoded `text json` in all three scripts, so `tan validate
|
|
14
|
+
--format <TAB>` offered two of the four values `validate` really accepts and
|
|
15
|
+
actively taught an IDE integrator that `diagnostic-v1` and `sarif` do not
|
|
16
|
+
exist. Those lists are now placeholders spliced from `tan.output_format`'s
|
|
17
|
+
enums by `_fill_formats` -- the same declarations the parser and `--help`
|
|
18
|
+
derive from, so the surfaces cannot disagree again. Everything else in the
|
|
19
|
+
scripts is still the oracle's own bytes; the emitted `data.script` therefore
|
|
20
|
+
diverges from v0.4.1's exactly where v0.4.1 was wrong about this port's own
|
|
21
|
+
format/target surface.
|
|
22
|
+
|
|
23
|
+
**A second splice, tan-cli#503: `generate --target`'s value list.** The fish
|
|
24
|
+
capture hardcoded 9 of the 12 real `--target` values, silently missing
|
|
25
|
+
`os-topology` (a member of the default/`--all` set, so a bare `tan generate`
|
|
26
|
+
runs it), `composed-route-table` and `ipc-contract-h` (both explicit-only, but
|
|
27
|
+
real). Also spliced from `generate_cmd`'s own tables now, same mechanism and
|
|
28
|
+
same reasoning as `--format` above. bash and zsh publish no `--target` value
|
|
29
|
+
list at all, so fish was (and is) the only surface this touches.
|
|
30
|
+
|
|
31
|
+
**A third, hand-edited exception, tan-cli#503: `doctor` drops
|
|
32
|
+
`--target-kind`/`--server`.** The oracle's `doctor` declared both
|
|
33
|
+
(`crates/tan-cli/src/cli.rs`), so the captured scripts still offer them, but
|
|
34
|
+
`doctor_cmd.py` deliberately did NOT port that debug half (see its own module
|
|
35
|
+
docstring) -- `support-bundle` and `debug-config` genuinely still take both.
|
|
36
|
+
Completing a flag `tan doctor` rejects at exit 2 is worse than not offering
|
|
37
|
+
it, so the three `doctor` arms had the two flags (and, in zsh/fish, their
|
|
38
|
+
value lists) removed by hand.
|
|
39
|
+
|
|
40
|
+
**A fourth, hand-edited exception, tan-cli#503: none of the three scripts
|
|
41
|
+
found the subcommand reliably.** All three defects are the same shape -- a
|
|
42
|
+
positional or state assumption that a real invocation breaks -- and all three
|
|
43
|
+
were measured in a real shell (bash 5.2.21, zsh 5.9 under a pty, fish 3.7.0
|
|
44
|
+
via `complete -C`), before and after.
|
|
45
|
+
|
|
46
|
+
- **bash keyed every decision off `${COMP_WORDS[1]}`**, which is the
|
|
47
|
+
subcommand only when nothing precedes it. Before: `tan --sdk-root /x <TAB>`
|
|
48
|
+
offered not one of the 31 command names (the `$cword -eq 1` gate missed) and
|
|
49
|
+
`tan --sdk-root /x size --<TAB>` offered no
|
|
50
|
+
`--build-root`/`--board`/`--fail-over-budget` (the per-command `case`
|
|
51
|
+
missed). Both now read one `$subcmd` scanned once at the top of
|
|
52
|
+
`_tan_complete`. That scan also has to survive `$COMP_WORDBREAKS`: bash
|
|
53
|
+
re-splits argv on `=` and `:`, so `--sdk-root=/x` reaches the function as
|
|
54
|
+
three words and `C:/proj` as three more -- see the scan's own comment.
|
|
55
|
+
- **zsh's `args`-state `case $words[2]` never matched anything.** In that
|
|
56
|
+
state `_arguments` has REINDEXED `words`, so `words[1]` is the subcommand
|
|
57
|
+
and `words[2]` is the word being completed: instrumented in zsh 5.9,
|
|
58
|
+
`tan size --<TAB>` arrived with `words=(size --)`, `CURRENT=2`. All 21 arms
|
|
59
|
+
were unreachable and every subcommand fell to `*)` -- `tan size --<TAB>`
|
|
60
|
+
offered the 12 global flags and none of `size`'s own three, `tan doctor
|
|
61
|
+
--<TAB>` offered neither `--build` nor `--fix`. Now `case $subcmd`, the same
|
|
62
|
+
value bash uses, which that probe confirmed is in scope and correct there
|
|
63
|
+
(`subcmd_scan=size`).
|
|
64
|
+
- **fish's command list was gated on `__fish_use_subcommand`**, which returns
|
|
65
|
+
false at the first non-switch token -- and a global flag's VALUE is one. So
|
|
66
|
+
`complete -C 'tan --sdk-root /x '` returned NOTHING at all: no command
|
|
67
|
+
names, and no flags either, because fish offers options only when the
|
|
68
|
+
current token starts with `-`. Now gated on `not
|
|
69
|
+
__fish_seen_subcommand_from <the 31>`, which ignores flag values. (fish's
|
|
70
|
+
per-command flags were already correct -- `__fish_seen_subcommand_from`
|
|
71
|
+
scans every word -- so only the command-list half was broken.)
|
|
72
|
+
|
|
73
|
+
The `$cword -eq 1` gate, the per-command `case`es and the fish condition were
|
|
74
|
+
all the oracle's own captured bytes; `crates/` was deleted in tan-cli#269, so
|
|
75
|
+
this port owns them now and they are fixed rather than preserved.
|
|
76
|
+
|
|
77
|
+
**A fifth, hand-edited exception, tan-cli#503: `--version` is offered at the
|
|
78
|
+
root only.** All three captures listed it in the always-available flag set, so
|
|
79
|
+
it was offered on all 31 subcommands, and no subcommand prints a version for
|
|
80
|
+
it: measured, 29 answer Click's `No such option: --version (Possible options:
|
|
81
|
+
--verbose)`, `lock` forwards it to `west` (`unexpected arguments:
|
|
82
|
+
['--version']`), and `quality`/`migrate` refuse earlier on their own required
|
|
83
|
+
flag and only reach `west` once that is supplied. It is root-only by design
|
|
84
|
+
(`cli.py`: "it lives on `Cli` directly in clap, not `GlobalArgs`, and is
|
|
85
|
+
root-only on both sides already"), and `tan.core.global_flags.GLOBAL_FLAGS` --
|
|
86
|
+
the one table the parser and `accept_global_flags` both read -- does not
|
|
87
|
+
contain it. bash splits `root_flags` out of `global_flags`; zsh splices it
|
|
88
|
+
into the root `_arguments -C` call and no arm; fish gates it on the same
|
|
89
|
+
`not __fish_seen_subcommand_from` condition as the command list. Inherited
|
|
90
|
+
from the oracle's capture, same as the reads above, and owned here for the
|
|
91
|
+
same reason.
|
|
92
|
+
|
|
93
|
+
**Why hand-captured and not Typer/Click's own shell-completion machinery.**
|
|
94
|
+
Typer ships one (`click.shell_completion`, gated off here via `app =
|
|
95
|
+
typer.Typer(add_completion=False)` in `cli.py`), but it is not a substitute:
|
|
96
|
+
it activates through a completely different mechanism -- sourcing eval output
|
|
97
|
+
from an `_TAN_COMPLETE=<shell>_source tan` environment-variable trigger
|
|
98
|
+
Click's own dispatcher special-cases at import time, not a static script this
|
|
99
|
+
command prints -- and it introspects THIS PROCESS's live Click command tree
|
|
100
|
+
rather than emitting the oracle's fixed command/flag tables. Even
|
|
101
|
+
functionally equivalent tab-completion from it would not reproduce
|
|
102
|
+
`data.script` byte-for-byte, which is the wire contract this command's JSON
|
|
103
|
+
envelope carries (an extension or script that diffs/hashes that field would
|
|
104
|
+
see every invocation as a regression). Hand-captured scripts are therefore
|
|
105
|
+
the only way to be a faithful port here, not a shortcut around one.
|
|
106
|
+
|
|
107
|
+
Every failure is an envelope, never a traceback: the ONLY failure this
|
|
108
|
+
command has is an unsupported `--shell` value, mirroring `resolve_shell` in
|
|
109
|
+
the Rust 1:1 (default `bash`; trim + lowercase; anything else is
|
|
110
|
+
`completion.shell-unsupported`, exit `RUNTIME_FAILURE`). There is no project
|
|
111
|
+
resolution, no SDK checkout, no filesystem read and no subprocess -- `project`
|
|
112
|
+
stays `null`/`null` in every envelope, matching the oracle's `null_project()`.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
from __future__ import annotations
|
|
116
|
+
|
|
117
|
+
import sys
|
|
118
|
+
|
|
119
|
+
import typer
|
|
120
|
+
|
|
121
|
+
from tan.commands.generate_cmd import (
|
|
122
|
+
ALL_EMIT_MODES,
|
|
123
|
+
COMPOSED_ROUTE_TABLE,
|
|
124
|
+
IPC_CONTRACT_H,
|
|
125
|
+
ZEPHYR_BOARD,
|
|
126
|
+
)
|
|
127
|
+
from tan.envelope import Envelope, Issue, Project, emit
|
|
128
|
+
from tan.exit_codes import ExitCode
|
|
129
|
+
from tan.output_format import (
|
|
130
|
+
FORMAT_HELP,
|
|
131
|
+
WIDE_FORMAT_COMMANDS,
|
|
132
|
+
OutputFormat,
|
|
133
|
+
ValidateOutputFormat,
|
|
134
|
+
format_values,
|
|
135
|
+
resolve_format,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
#: `data.schemaVersion` for this command's payload.
|
|
139
|
+
DATA_SCHEMA_VERSION = "1"
|
|
140
|
+
|
|
141
|
+
#: The frozen issue code for an unsupported `--shell` value
|
|
142
|
+
#: (`contract/issue-codes.json`; `emittedBy` there already names this file).
|
|
143
|
+
SHELL_UNSUPPORTED_CODE = "completion.shell-unsupported"
|
|
144
|
+
#: Verbatim from `completion.rs`'s `Issue.message` -- the JSON-mode wording.
|
|
145
|
+
SHELL_UNSUPPORTED_MESSAGE = "Unsupported shell. Allowed values: bash, zsh, fish."
|
|
146
|
+
#: Verbatim from `completion.rs`'s `text` line -- the text-mode (stderr) wording.
|
|
147
|
+
SHELL_UNSUPPORTED_TEXT_LINE = "completion: unsupported shell. Use --shell bash|zsh|fish."
|
|
148
|
+
|
|
149
|
+
#: Where the captured scripts had a hardcoded `--format` value list, they now
|
|
150
|
+
#: carry a placeholder `_fill_formats` (below) substitutes from the CLI's own
|
|
151
|
+
#: enums -- tan-cli#403. The scripts are otherwise still byte-for-byte oracle
|
|
152
|
+
#: captures; these five markers are the ONLY derived text in them.
|
|
153
|
+
_FORMATS_MARK = "@FORMATS@"
|
|
154
|
+
_WIDE_FORMATS_MARK = "@WIDE_FORMATS@"
|
|
155
|
+
#: The commands with the wider domain, as a bash/zsh `case` alternation
|
|
156
|
+
#: (`a|b`) and as fish's space-separated argument list respectively.
|
|
157
|
+
_WIDE_COMMANDS_ALT_MARK = "@WIDE_COMMANDS_ALT@"
|
|
158
|
+
_WIDE_COMMANDS_LIST_MARK = "@WIDE_COMMANDS_LIST@"
|
|
159
|
+
#: `generate --target`'s value list (tan-cli#503): the fish capture hardcoded
|
|
160
|
+
#: 9 of the 12 real values, missing `os-topology` (a bare `tan generate`
|
|
161
|
+
#: default target) plus the explicit-only `composed-route-table` and
|
|
162
|
+
#: `ipc-contract-h`. Spliced from `generate_cmd`'s own tables, same as the
|
|
163
|
+
#: `--format` lists above, so this cannot go stale a second time.
|
|
164
|
+
_TARGETS_MARK = "@TARGETS@"
|
|
165
|
+
#: `ALL_EMIT_MODES` is the default/`--all` set; `ZEPHYR_BOARD`,
|
|
166
|
+
#: `COMPOSED_ROUTE_TABLE` and `IPC_CONTRACT_H` are the explicit-only targets
|
|
167
|
+
#: it excludes (`generate_cmd.EXPLICIT_ONLY_TARGETS`) but `--target` still
|
|
168
|
+
#: accepts by name.
|
|
169
|
+
_TARGET_VALUES = " ".join(
|
|
170
|
+
(*ALL_EMIT_MODES, ZEPHYR_BOARD, COMPOSED_ROUTE_TABLE, IPC_CONTRACT_H)
|
|
171
|
+
)
|
|
172
|
+
#: The 31 subcommand names, in the captured scripts' own order (tan-cli#503).
|
|
173
|
+
#: fish needs them TWICE -- once as the command list it offers, and once as
|
|
174
|
+
#: the `not __fish_seen_subcommand_from ...` condition that decides whether a
|
|
175
|
+
#: subcommand has been typed yet -- so they are spliced rather than written
|
|
176
|
+
#: out a second time. `tests/commands/test_completion_command.py` diffs this
|
|
177
|
+
#: against `tan.cli._SUBCOMMAND_NAMES`; the module itself cannot import
|
|
178
|
+
#: `tan.cli` (import cycle -- see the docstring), the test can.
|
|
179
|
+
_COMMANDS_MARK = "@COMMANDS@"
|
|
180
|
+
_COMMAND_NAMES = (
|
|
181
|
+
"validate generate init scaffold examples doctor completion diff presets "
|
|
182
|
+
"pinmux explain inspect trace debug-config support-bundle sdk bootstrap "
|
|
183
|
+
"build kconfig image flash run clean size migrate lock quality "
|
|
184
|
+
"model monitor new-som faultdecode probe reset"
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _fill_formats(template: str) -> str:
|
|
189
|
+
"""Splice the declared `--format`/`--target` value lists into one captured
|
|
190
|
+
script.
|
|
191
|
+
|
|
192
|
+
The oracle generated its completions from the same clap `ValueEnum` that
|
|
193
|
+
fed its parser and its `--help`, so all three surfaces agreed by
|
|
194
|
+
construction. This port emits TEXT rather than walking a live command
|
|
195
|
+
graph (`completion_cmd` cannot import `tan.cli` -- that is an import
|
|
196
|
+
cycle), so the equivalent guarantee is: never type a value list into the
|
|
197
|
+
script text, splice it from the enum, and let
|
|
198
|
+
`tests/commands/test_output_format.py` diff the emitted script against
|
|
199
|
+
what the parser really accepts, per command.
|
|
200
|
+
"""
|
|
201
|
+
return (
|
|
202
|
+
template.replace(_FORMATS_MARK, " ".join(format_values(OutputFormat)))
|
|
203
|
+
.replace(_WIDE_FORMATS_MARK, " ".join(format_values(ValidateOutputFormat)))
|
|
204
|
+
.replace(_WIDE_COMMANDS_ALT_MARK, "|".join(WIDE_FORMAT_COMMANDS))
|
|
205
|
+
.replace(_WIDE_COMMANDS_LIST_MARK, " ".join(WIDE_FORMAT_COMMANDS))
|
|
206
|
+
.replace(_TARGETS_MARK, _TARGET_VALUES)
|
|
207
|
+
.replace(_COMMANDS_MARK, _COMMAND_NAMES)
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
#: Verbatim bash completion script, captured from the reference oracle.
|
|
212
|
+
_BASH_TEMPLATE = """# tan CLI bash completion
|
|
213
|
+
_tan_complete() {
|
|
214
|
+
local cur prev words cword
|
|
215
|
+
|
|
216
|
+
COMPREPLY=()
|
|
217
|
+
cur="${COMP_WORDS[COMP_CWORD]}"
|
|
218
|
+
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
219
|
+
cword=${COMP_CWORD}
|
|
220
|
+
|
|
221
|
+
local commands="validate generate init scaffold examples doctor completion diff presets pinmux explain inspect trace debug-config support-bundle sdk bootstrap build kconfig image flash run clean size migrate lock quality model monitor new-som faultdecode probe reset"
|
|
222
|
+
# `--version` is deliberately NOT in `global_flags` but IS in `root_flags`
|
|
223
|
+
# (tan-cli#503): it is root-only, and no subcommand prints a version for it
|
|
224
|
+
# -- see the module docstring's fifth exception for the measurement on all
|
|
225
|
+
# 32. Known and NOT fixed here: the root list is offered wherever no
|
|
226
|
+
# subcommand has been typed, yet the bare root command accepts far less than
|
|
227
|
+
# it offers (`tan --sdk-root /x --version`, `tan --verbose --version` and
|
|
228
|
+
# `tan --ci --version` all exit 2 -- `cli._reorder_global_flags` relocates a
|
|
229
|
+
# global flag ONTO the subcommand, and there is none here). Narrowing that
|
|
230
|
+
# list changes what `tan <TAB>` offers, which is beyond tan-cli#503's
|
|
231
|
+
# report, and it behaves identically before and after this change.
|
|
232
|
+
local global_flags="--project --board-yaml --sdk-root --target --all --format --verbose --quiet --no-color --non-interactive --ci --help"
|
|
233
|
+
local root_flags="$global_flags --version"
|
|
234
|
+
|
|
235
|
+
# ONE subcommand scan, three consumers below (tan-cli#503). A fixed word
|
|
236
|
+
# index is only the subcommand when nothing precedes it -- but every global
|
|
237
|
+
# flag is typeable BEFORE the subcommand (`tan --sdk-root /x validate
|
|
238
|
+
# --format <TAB>`, the exact pre-subcommand shape `output_format.py`'s
|
|
239
|
+
# docstring names as the one alp-sdk-vscode's `withSdkRoot` actually uses),
|
|
240
|
+
# so word 1 there is `--sdk-root`. That mis-selected the `--format` value
|
|
241
|
+
# list (fixed already), AND made `$cword -eq 1` miss, so `tan --sdk-root /x
|
|
242
|
+
# <TAB>` offered not one subcommand name, AND made the per-command `case`
|
|
243
|
+
# miss, so `tan --sdk-root /x size --<TAB>` offered no `--build-root`.
|
|
244
|
+
# Scan for the real subcommand instead of assuming its position: skip every
|
|
245
|
+
# global flag that consumes a following value, and the first bare word left
|
|
246
|
+
# is the subcommand (or "" if none was typed yet).
|
|
247
|
+
#
|
|
248
|
+
# bash does NOT hand this function argv: it hands it argv re-split on
|
|
249
|
+
# `$COMP_WORDBREAKS`, which contains `=` and `:` by default. Measured in
|
|
250
|
+
# bash 5.2.21 under a pty, `tan --sdk-root=/x size --<TAB>` arrives as
|
|
251
|
+
# `(tan --sdk-root = /x size --)` with `COMP_CWORD=5`, and
|
|
252
|
+
# `tan --sdk-root C:/proj size --<TAB>` as `(tan --sdk-root C : /proj size
|
|
253
|
+
# --)` with `COMP_CWORD=6`. Plain skip-N arithmetic lands on `=` or `:` in
|
|
254
|
+
# both, so the scan has to step over a `=` that follows a value flag, and
|
|
255
|
+
# to treat a bare word as the subcommand only when it IS one of the 31.
|
|
256
|
+
# `--sdk-root=/x` is a supported argv (`tan --sdk-root=/nonexistent
|
|
257
|
+
# validate` parses and runs), so this is not a hypothetical shape.
|
|
258
|
+
local value_flags="--project --board-yaml --sdk-root --target --format"
|
|
259
|
+
local subcmd="" at_value=0 i=1 w skip vf c
|
|
260
|
+
while [[ $i -lt $cword ]]; do
|
|
261
|
+
w="${COMP_WORDS[$i]}"
|
|
262
|
+
if [[ "$w" == --*=* ]]; then
|
|
263
|
+
# Self-contained; only reachable with a `$COMP_WORDBREAKS` that drops
|
|
264
|
+
# `=`, since the default splits this into three words instead.
|
|
265
|
+
i=$((i + 1))
|
|
266
|
+
continue
|
|
267
|
+
fi
|
|
268
|
+
if [[ "$w" == --* ]]; then
|
|
269
|
+
skip=0
|
|
270
|
+
for vf in $value_flags; do
|
|
271
|
+
[[ "$w" == "$vf" ]] && skip=1 && break
|
|
272
|
+
done
|
|
273
|
+
# `--flag` `=` `value`: step over the separator as well as the value.
|
|
274
|
+
[[ $skip -eq 1 && "${COMP_WORDS[$((i + 1))]}" == "=" ]] && skip=2
|
|
275
|
+
i=$((i + 1 + skip))
|
|
276
|
+
continue
|
|
277
|
+
fi
|
|
278
|
+
for c in $commands; do
|
|
279
|
+
[[ "$w" == "$c" ]] && subcmd="$w" && break
|
|
280
|
+
done
|
|
281
|
+
[[ -n "$subcmd" ]] && break
|
|
282
|
+
# A bare word that is not a command name is a wordbreak fragment of some
|
|
283
|
+
# value (`C`, `:`, `/proj`); step over it rather than mistake it for the
|
|
284
|
+
# subcommand. The positional skip above still protects a value that
|
|
285
|
+
# happens to BE a command name (`tan --sdk-root size validate`).
|
|
286
|
+
i=$((i + 1))
|
|
287
|
+
done
|
|
288
|
+
# The word being completed sits in a flag's VALUE slot (`tan --sdk-root
|
|
289
|
+
# <TAB>` -- a path, and `tan --sdk-root=<TAB>`, whose `prev` is the split-off
|
|
290
|
+
# `=`), not the subcommand slot. Offering 31 command names there would be a
|
|
291
|
+
# new wrong answer, so this shape keeps the pre-existing fall-through.
|
|
292
|
+
for vf in $value_flags; do
|
|
293
|
+
[[ "$prev" == "$vf" ]] && at_value=1 && break
|
|
294
|
+
done
|
|
295
|
+
[[ "$prev" == "=" ]] && at_value=1
|
|
296
|
+
|
|
297
|
+
if [[ "$prev" == "--format" ]]; then
|
|
298
|
+
local formats="@FORMATS@"
|
|
299
|
+
case "$subcmd" in
|
|
300
|
+
@WIDE_COMMANDS_ALT@) formats="@WIDE_FORMATS@" ;;
|
|
301
|
+
esac
|
|
302
|
+
COMPREPLY=( $(compgen -W "$formats" -- "$cur") )
|
|
303
|
+
return
|
|
304
|
+
fi
|
|
305
|
+
|
|
306
|
+
if [[ "$prev" == "--shell" ]]; then
|
|
307
|
+
COMPREPLY=( $(compgen -W "bash zsh fish" -- "$cur") )
|
|
308
|
+
return
|
|
309
|
+
fi
|
|
310
|
+
|
|
311
|
+
if [[ -z "$subcmd" && $at_value -eq 0 ]]; then
|
|
312
|
+
COMPREPLY=( $(compgen -W "$commands $root_flags" -- "$cur") )
|
|
313
|
+
return
|
|
314
|
+
fi
|
|
315
|
+
|
|
316
|
+
case "$subcmd" in
|
|
317
|
+
validate)
|
|
318
|
+
COMPREPLY=( $(compgen -W "$global_flags --offline" -- "$cur") )
|
|
319
|
+
;;
|
|
320
|
+
generate)
|
|
321
|
+
COMPREPLY=( $(compgen -W "$global_flags --force --core" -- "$cur") )
|
|
322
|
+
;;
|
|
323
|
+
explain)
|
|
324
|
+
COMPREPLY=( $(compgen -W "$global_flags --template --code" -- "$cur") )
|
|
325
|
+
;;
|
|
326
|
+
init)
|
|
327
|
+
COMPREPLY=( $(compgen -W "$global_flags --template --from-example --name --destination --som --cores --preview --force" -- "$cur") )
|
|
328
|
+
;;
|
|
329
|
+
scaffold)
|
|
330
|
+
COMPREPLY=( $(compgen -W "$global_flags --template --name --destination --preview --force" -- "$cur") )
|
|
331
|
+
;;
|
|
332
|
+
probe)
|
|
333
|
+
COMPREPLY=( $(compgen -W "identify read $global_flags --core --project --build-root --probe-serial --probe-usb-path --jlink" -- "$cur") )
|
|
334
|
+
;;
|
|
335
|
+
reset)
|
|
336
|
+
COMPREPLY=( $(compgen -W "$global_flags --project --pulse-ms --confirm-console --expect --confirm-baud --confirm-timeout --confirm-window --probe-serial --probe-usb-path --jlink" -- "$cur") )
|
|
337
|
+
;;
|
|
338
|
+
diff|presets)
|
|
339
|
+
COMPREPLY=( $(compgen -W "$global_flags" -- "$cur") )
|
|
340
|
+
;;
|
|
341
|
+
examples)
|
|
342
|
+
COMPREPLY=( $(compgen -W "$global_flags --filter" -- "$cur") )
|
|
343
|
+
;;
|
|
344
|
+
completion)
|
|
345
|
+
COMPREPLY=( $(compgen -W "$global_flags --shell" -- "$cur") )
|
|
346
|
+
;;
|
|
347
|
+
pinmux)
|
|
348
|
+
COMPREPLY=( $(compgen -W "$global_flags --sku --family" -- "$cur") )
|
|
349
|
+
;;
|
|
350
|
+
doctor)
|
|
351
|
+
COMPREPLY=( $(compgen -W "$global_flags --build --fix" -- "$cur") )
|
|
352
|
+
;;
|
|
353
|
+
inspect)
|
|
354
|
+
COMPREPLY=( $(compgen -W "$global_flags --path --show-origin" -- "$cur") )
|
|
355
|
+
;;
|
|
356
|
+
trace)
|
|
357
|
+
COMPREPLY=( $(compgen -W "$global_flags --path" -- "$cur") )
|
|
358
|
+
;;
|
|
359
|
+
debug-config)
|
|
360
|
+
COMPREPLY=( $(compgen -W "$global_flags --target-kind --server --core --pre-launch-task --svd --preview" -- "$cur") )
|
|
361
|
+
;;
|
|
362
|
+
support-bundle)
|
|
363
|
+
COMPREPLY=( $(compgen -W "$global_flags --destination --target-kind --server --path" -- "$cur") )
|
|
364
|
+
;;
|
|
365
|
+
sdk)
|
|
366
|
+
COMPREPLY=( $(compgen -W "$global_flags list install current switch --destination --global" -- "$cur") )
|
|
367
|
+
;;
|
|
368
|
+
bootstrap)
|
|
369
|
+
COMPREPLY=( $(compgen -W "$global_flags --no-pip --no-west --print-env --allow-partial --workspace" -- "$cur") )
|
|
370
|
+
;;
|
|
371
|
+
build)
|
|
372
|
+
COMPREPLY=( $(compgen -W "$global_flags --plan-from --materialise --native --no-auto-bootstrap --pristine" -- "$cur") )
|
|
373
|
+
;;
|
|
374
|
+
kconfig)
|
|
375
|
+
COMPREPLY=( $(compgen -W "$global_flags --core" -- "$cur") )
|
|
376
|
+
;;
|
|
377
|
+
image)
|
|
378
|
+
COMPREPLY=( $(compgen -W "$global_flags --build-root" -- "$cur") )
|
|
379
|
+
;;
|
|
380
|
+
flash)
|
|
381
|
+
COMPREPLY=( $(compgen -W "$global_flags --build-root --dry-run --core --helper --skip-missing-tools" -- "$cur") )
|
|
382
|
+
;;
|
|
383
|
+
run)
|
|
384
|
+
COMPREPLY=( $(compgen -W "$global_flags --flash --core" -- "$cur") )
|
|
385
|
+
;;
|
|
386
|
+
clean)
|
|
387
|
+
COMPREPLY=( $(compgen -W "$global_flags --build-root --dry-run" -- "$cur") )
|
|
388
|
+
;;
|
|
389
|
+
size)
|
|
390
|
+
COMPREPLY=( $(compgen -W "$global_flags --build-root --board --fail-over-budget" -- "$cur") )
|
|
391
|
+
;;
|
|
392
|
+
*)
|
|
393
|
+
COMPREPLY=( $(compgen -W "$global_flags" -- "$cur") )
|
|
394
|
+
;;
|
|
395
|
+
esac
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
complete -F _tan_complete tan
|
|
399
|
+
"""
|
|
400
|
+
|
|
401
|
+
#: Verbatim zsh completion script, captured from the reference oracle.
|
|
402
|
+
_ZSH_TEMPLATE = """#compdef tan
|
|
403
|
+
|
|
404
|
+
_tan() {
|
|
405
|
+
local -a commands
|
|
406
|
+
commands=(
|
|
407
|
+
'validate:Validate board.yaml config'
|
|
408
|
+
'generate:Generate derived artifacts'
|
|
409
|
+
'init:Initialize a starter project'
|
|
410
|
+
'scaffold:Scaffold module files'
|
|
411
|
+
'examples:List SDK example projects'
|
|
412
|
+
'doctor:Run debug and environment checks'
|
|
413
|
+
'completion:Generate shell completion script'
|
|
414
|
+
'diff:Show board normalization diff'
|
|
415
|
+
'presets:List SDK presets'
|
|
416
|
+
'probe:Read-only J-Link identity and memory read'
|
|
417
|
+
'reset:One bare nRESET pulse through J-Link'
|
|
418
|
+
'pinmux:Show pinmux capability table'
|
|
419
|
+
'explain:Explain templates and targets'
|
|
420
|
+
'inspect:Inspect effective resolved values'
|
|
421
|
+
'trace:Trace generation decisions'
|
|
422
|
+
'debug-config:Generate a launch.json debug configuration'
|
|
423
|
+
'support-bundle:Export support bundle payload'
|
|
424
|
+
'sdk:Manage local SDK installs'
|
|
425
|
+
'bootstrap:Set up the SDK build environment'
|
|
426
|
+
'build:Build the project natively'
|
|
427
|
+
'kconfig:Show the board-scoped Kconfig symbol menu'
|
|
428
|
+
'image:Assemble a flashable image bundle'
|
|
429
|
+
'flash:Flash slices and helper MCUs onto the device'
|
|
430
|
+
'run:Build then run the project'
|
|
431
|
+
'clean:Remove the build dir and state cache'
|
|
432
|
+
'size:Report per-slice firmware footprint'
|
|
433
|
+
'migrate:Migrate board.yaml to the current schema'
|
|
434
|
+
'lock:Pin/lock library dependencies'
|
|
435
|
+
'quality:Run board.yaml quality checks'
|
|
436
|
+
'model:Compile and package board.yaml models'
|
|
437
|
+
'monitor:Open a serial console to the board'
|
|
438
|
+
'new-som:Scaffold a new SoM metadata skeleton'
|
|
439
|
+
'faultdecode:Decode an ARM Cortex-M fault dump'
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
# Every flag `GlobalArgs` marks `global = true` (cli.rs) is accepted by
|
|
443
|
+
# clap on EVERY subcommand — AND on the root command itself, before any
|
|
444
|
+
# subcommand word is even typed — so every arm below splices this in, and
|
|
445
|
+
# so does the root `_arguments -C` call a few lines down. Unlike bash's
|
|
446
|
+
# single `$global_flags` string var, zsh's per-arm `_arguments` has no
|
|
447
|
+
# inheritance of its own (issue #92 MAJOR 2) — a flag left out of an arm
|
|
448
|
+
# here is simply not completable for that subcommand (or, left out of the
|
|
449
|
+
# root call, not completable at `tan --<TAB>` before a subcommand: issue
|
|
450
|
+
# #92 round-3 FINDING 1).
|
|
451
|
+
#
|
|
452
|
+
# `--version` is the ONE flag that is not in that set (tan-cli#503): it is
|
|
453
|
+
# root-only, refused by all 31 subcommands, so it is spliced into the root
|
|
454
|
+
# `_arguments -C` call below and into no arm.
|
|
455
|
+
local -a global_args
|
|
456
|
+
global_args=(
|
|
457
|
+
'--project[Project root]:path:_files -/'
|
|
458
|
+
'--board-yaml[board.yaml path]:path:_files'
|
|
459
|
+
'--sdk-root[SDK root]:path:_files -/'
|
|
460
|
+
'--target[Generation target]'
|
|
461
|
+
'--all[Generate all targets]'
|
|
462
|
+
'--verbose[Verbose output]'
|
|
463
|
+
'--quiet[Quiet output]'
|
|
464
|
+
'--no-color[Disable color output]'
|
|
465
|
+
'--non-interactive[Disable prompts]'
|
|
466
|
+
'--ci[CI mode]'
|
|
467
|
+
'--help[Show help]'
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
# `--format` is appended rather than listed above because its value list is
|
|
471
|
+
# not the same for every command (tan-cli#403): `validate` also completes
|
|
472
|
+
# the two IDE-oriented documents. Chosen here, once, so every `_arguments`
|
|
473
|
+
# call below still splices exactly one `${global_args[@]}` and no arm can
|
|
474
|
+
# drift.
|
|
475
|
+
#
|
|
476
|
+
# `$words[2]` is only the subcommand when nothing precedes it -- but
|
|
477
|
+
# `--format` is itself a global flag typeable BEFORE the subcommand
|
|
478
|
+
# (`tan --sdk-root /x validate --format <TAB>`), so this read at the
|
|
479
|
+
# function top (before `_arguments` reindexes `words`) used to silently
|
|
480
|
+
# fall back to the narrow list for that shape (tan-cli#503). Scan for the
|
|
481
|
+
# real subcommand: skip every global flag that consumes a following value,
|
|
482
|
+
# and the first bare word left is the subcommand.
|
|
483
|
+
local subcmd="" i=2
|
|
484
|
+
while (( i <= ${#words[@]} )); do
|
|
485
|
+
case "$words[i]" in
|
|
486
|
+
--project|--board-yaml|--sdk-root|--target|--format) (( i += 2 )); continue ;;
|
|
487
|
+
--*) (( i += 1 )); continue ;;
|
|
488
|
+
esac
|
|
489
|
+
subcmd="$words[i]"
|
|
490
|
+
break
|
|
491
|
+
done
|
|
492
|
+
case "$subcmd" in
|
|
493
|
+
@WIDE_COMMANDS_ALT@) global_args+=('--format[Output format]:format:(@WIDE_FORMATS@)') ;;
|
|
494
|
+
*) global_args+=('--format[Output format]:format:(@FORMATS@)') ;;
|
|
495
|
+
esac
|
|
496
|
+
|
|
497
|
+
_arguments -C '1:command:->command' '*::arg:->args' "${global_args[@]}" '--version[Show version]'
|
|
498
|
+
|
|
499
|
+
case $state in
|
|
500
|
+
command)
|
|
501
|
+
_describe 'command' commands
|
|
502
|
+
;;
|
|
503
|
+
args)
|
|
504
|
+
# `$subcmd`, not `$words[2]` (tan-cli#503). In this state `_arguments`
|
|
505
|
+
# has REINDEXED `words` so that `words[1]` is the subcommand and
|
|
506
|
+
# `words[2]` is the word being completed -- measured in zsh 5.9 under a
|
|
507
|
+
# pty, `tan size --<TAB>` reaches here with `words=(size --)` and
|
|
508
|
+
# `CURRENT=2`, so `$words[2]` was `--`. It never matched a subcommand
|
|
509
|
+
# name, so all 21 arms below were unreachable and every command fell to
|
|
510
|
+
# `*)`: `tan size --<TAB>` offered the 12 global flags and none of
|
|
511
|
+
# `--build-root`/`--board`/`--fail-over-budget`. `$subcmd` is computed
|
|
512
|
+
# from the ORIGINAL `words` at the top of this function and is still in
|
|
513
|
+
# scope here (same probe: `subcmd_scan=size`), so it is right both for
|
|
514
|
+
# this reindexing and for a leading global flag.
|
|
515
|
+
case $subcmd in
|
|
516
|
+
validate)
|
|
517
|
+
_arguments '--offline[Offline structural validation only]' "${global_args[@]}"
|
|
518
|
+
;;
|
|
519
|
+
completion)
|
|
520
|
+
_arguments '--shell[Shell type]:shell:(bash zsh fish)' "${global_args[@]}"
|
|
521
|
+
;;
|
|
522
|
+
generate)
|
|
523
|
+
_arguments '--force[Overwrite existing files]' '--core[Core id (zephyr-board target)]' "${global_args[@]}"
|
|
524
|
+
;;
|
|
525
|
+
explain)
|
|
526
|
+
_arguments '--template[Template id]' '--code[Diagnostic or error code]' "${global_args[@]}"
|
|
527
|
+
;;
|
|
528
|
+
examples)
|
|
529
|
+
_arguments '--filter[Substring match on id/title]' "${global_args[@]}"
|
|
530
|
+
;;
|
|
531
|
+
init)
|
|
532
|
+
_arguments '--template[Template id]' '--from-example[Example source dir]' '--name[Name value]' '--destination[Output directory]:path:_files -/' '--som[SoM SKU]' '--cores[Cores list]' '--preview[Preview only]' '--force[Overwrite existing files]' "${global_args[@]}"
|
|
533
|
+
;;
|
|
534
|
+
scaffold)
|
|
535
|
+
_arguments '--template[Template id]' '--name[Name value]' '--destination[Output directory]:path:_files -/' '--preview[Preview only]' '--force[Overwrite existing files]' "${global_args[@]}"
|
|
536
|
+
;;
|
|
537
|
+
pinmux)
|
|
538
|
+
_arguments '--sku[SoM SKU]' '--family[Pinmux family]' "${global_args[@]}"
|
|
539
|
+
;;
|
|
540
|
+
doctor)
|
|
541
|
+
_arguments '--build[Build readiness preflight]' '--fix[Auto-repair a fixable blocker]' "${global_args[@]}"
|
|
542
|
+
;;
|
|
543
|
+
inspect)
|
|
544
|
+
_arguments '--path[Field path]' '--show-origin[Include source metadata]' "${global_args[@]}"
|
|
545
|
+
;;
|
|
546
|
+
trace)
|
|
547
|
+
_arguments '--path[Field path]' "${global_args[@]}"
|
|
548
|
+
;;
|
|
549
|
+
debug-config)
|
|
550
|
+
_arguments '--target-kind[Debug target]:target:(zephyr-mcu baremetal-mcu yocto-userspace native-host)' '--server[Debug server]:server:(jlink openocd pyocd gdbserver none)' '--core[Build slice core id]' '--pre-launch-task[VS Code task to run before launching]' '--svd[Path to a user-supplied SVD for the peripheral view]:svd:_files -g "*.svd"' '--preview[Preview only]' "${global_args[@]}"
|
|
551
|
+
;;
|
|
552
|
+
support-bundle)
|
|
553
|
+
_arguments '--destination[Output directory]:path:_files -/' '--target-kind[Debug target]:target:(zephyr-mcu baremetal-mcu yocto-userspace native-host)' '--server[Debug server]:server:(jlink openocd pyocd gdbserver none)' '--path[Field path]' "${global_args[@]}"
|
|
554
|
+
;;
|
|
555
|
+
sdk)
|
|
556
|
+
_arguments '1:subcommand:(list install current switch)' '--destination[Cache root]:path:_files -/' '--global[Pin the machine-global default]' "${global_args[@]}"
|
|
557
|
+
;;
|
|
558
|
+
bootstrap)
|
|
559
|
+
_arguments '--no-pip[Skip pip install]' '--no-west[Skip west init/update]' '--print-env[Print environment lines only]' '--allow-partial[Report success despite a failed dependency install]' '--workspace[Build the workspace at this path]:path:_files -/' "${global_args[@]}"
|
|
560
|
+
;;
|
|
561
|
+
build)
|
|
562
|
+
_arguments '--plan-from[Read build plan from file]:path:_files' '--materialise[Materialise plan files]' '--native[Build natively]' '--no-auto-bootstrap[Never bootstrap implicitly]' '--pristine[Force-wipe build dirs before dispatch]' "${global_args[@]}"
|
|
563
|
+
;;
|
|
564
|
+
kconfig)
|
|
565
|
+
_arguments '--core[Core id to scope the menu to]' "${global_args[@]}"
|
|
566
|
+
;;
|
|
567
|
+
image)
|
|
568
|
+
_arguments '--build-root[Override build root]:path:_files -/' "${global_args[@]}"
|
|
569
|
+
;;
|
|
570
|
+
flash)
|
|
571
|
+
_arguments '--build-root[Override build root]:path:_files -/' '--dry-run[Print planned commands only]' '--core[Flash only this core]' '--helper[Flash only this helper MCU]' '--skip-missing-tools[Skip entries with no tool on PATH]' "${global_args[@]}"
|
|
572
|
+
;;
|
|
573
|
+
run)
|
|
574
|
+
_arguments '--flash[Flash the board after building]' '--core[Flash only this core]' "${global_args[@]}"
|
|
575
|
+
;;
|
|
576
|
+
clean)
|
|
577
|
+
_arguments '--build-root[Override build root]:path:_files -/' '--dry-run[List targets without removing]' "${global_args[@]}"
|
|
578
|
+
;;
|
|
579
|
+
size)
|
|
580
|
+
_arguments '--build-root[Override build root]:path:_files -/' '--board[Override SoM SKU]' '--fail-over-budget[Exit non-zero over budget]' "${global_args[@]}"
|
|
581
|
+
;;
|
|
582
|
+
*)
|
|
583
|
+
_arguments "${global_args[@]}"
|
|
584
|
+
;;
|
|
585
|
+
esac
|
|
586
|
+
;;
|
|
587
|
+
esac
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
compdef _tan tan
|
|
591
|
+
"""
|
|
592
|
+
|
|
593
|
+
#: Verbatim fish completion script, captured from the reference oracle.
|
|
594
|
+
_FISH_TEMPLATE = """complete -c tan -f
|
|
595
|
+
complete -c tan -n 'not __fish_seen_subcommand_from @COMMANDS@' -a '@COMMANDS@'
|
|
596
|
+
complete -c tan -l project -d 'Project root'
|
|
597
|
+
complete -c tan -l board-yaml -d 'board.yaml path'
|
|
598
|
+
complete -c tan -l sdk-root -d 'SDK root path'
|
|
599
|
+
complete -c tan -l target -d 'Generation target' -a '@TARGETS@'
|
|
600
|
+
complete -c tan -l all -d 'Generate all targets'
|
|
601
|
+
complete -c tan -n 'not __fish_seen_subcommand_from @WIDE_COMMANDS_LIST@' -l format -d 'Output format' -a '@FORMATS@'
|
|
602
|
+
complete -c tan -n '__fish_seen_subcommand_from @WIDE_COMMANDS_LIST@' -l format -d 'Output format' -a '@WIDE_FORMATS@'
|
|
603
|
+
complete -c tan -l verbose -d 'Verbose output'
|
|
604
|
+
complete -c tan -l quiet -d 'Quiet output'
|
|
605
|
+
complete -c tan -l no-color -d 'Disable color output'
|
|
606
|
+
complete -c tan -l non-interactive -d 'Disable prompts'
|
|
607
|
+
complete -c tan -l ci -d 'CI mode'
|
|
608
|
+
complete -c tan -l help -d 'Show help'
|
|
609
|
+
complete -c tan -n 'not __fish_seen_subcommand_from @COMMANDS@' -l version -d 'Show version'
|
|
610
|
+
complete -c tan -n '__fish_seen_subcommand_from validate' -l offline -d 'Offline structural validation only'
|
|
611
|
+
complete -c tan -n '__fish_seen_subcommand_from generate' -l force -d 'Overwrite existing files'
|
|
612
|
+
complete -c tan -n '__fish_seen_subcommand_from generate' -l core -d 'Core id (zephyr-board target)'
|
|
613
|
+
complete -c tan -n '__fish_seen_subcommand_from explain' -l template -d 'Template id'
|
|
614
|
+
complete -c tan -n '__fish_seen_subcommand_from explain' -l code -d 'Diagnostic or error code'
|
|
615
|
+
complete -c tan -n '__fish_seen_subcommand_from examples' -l filter -d 'Substring match on id/title'
|
|
616
|
+
complete -c tan -n '__fish_seen_subcommand_from init scaffold' -l template -d 'Template id'
|
|
617
|
+
complete -c tan -n '__fish_seen_subcommand_from init' -l from-example -d 'Example source dir'
|
|
618
|
+
complete -c tan -n '__fish_seen_subcommand_from init scaffold' -l name -d 'Name value'
|
|
619
|
+
complete -c tan -n '__fish_seen_subcommand_from init scaffold' -l destination -d 'Destination path'
|
|
620
|
+
complete -c tan -n '__fish_seen_subcommand_from init' -l som -d 'SoM SKU'
|
|
621
|
+
complete -c tan -n '__fish_seen_subcommand_from init' -l cores -d 'Cores list'
|
|
622
|
+
complete -c tan -n '__fish_seen_subcommand_from init scaffold' -l preview -d 'Preview only'
|
|
623
|
+
complete -c tan -n '__fish_seen_subcommand_from init scaffold' -l force -d 'Overwrite existing files'
|
|
624
|
+
complete -c tan -n '__fish_seen_subcommand_from pinmux' -l sku -d 'SoM SKU'
|
|
625
|
+
complete -c tan -n '__fish_seen_subcommand_from pinmux' -l family -d 'Pinmux family'
|
|
626
|
+
complete -c tan -n '__fish_seen_subcommand_from doctor' -l build -d 'Build readiness preflight'
|
|
627
|
+
complete -c tan -n '__fish_seen_subcommand_from doctor' -l fix -d 'Auto-repair a fixable blocker'
|
|
628
|
+
complete -c tan -n '__fish_seen_subcommand_from inspect trace support-bundle' -l path -d 'Field path'
|
|
629
|
+
complete -c tan -n '__fish_seen_subcommand_from inspect' -l show-origin -d 'Include source metadata'
|
|
630
|
+
complete -c tan -n '__fish_seen_subcommand_from debug-config' -l target-kind -d 'Debug target kind' -a 'zephyr-mcu baremetal-mcu yocto-userspace native-host'
|
|
631
|
+
complete -c tan -n '__fish_seen_subcommand_from debug-config' -l server -d 'Debug server' -a 'jlink openocd pyocd gdbserver none'
|
|
632
|
+
complete -c tan -n '__fish_seen_subcommand_from debug-config' -l core -d 'Build slice core id'
|
|
633
|
+
complete -c tan -n '__fish_seen_subcommand_from debug-config' -l pre-launch-task -d 'VS Code task to run before launching'
|
|
634
|
+
complete -c tan -n '__fish_seen_subcommand_from debug-config' -l svd -r -d 'Path to a user-supplied SVD for the peripheral view'
|
|
635
|
+
complete -c tan -n '__fish_seen_subcommand_from debug-config' -l preview -d 'Preview only'
|
|
636
|
+
complete -c tan -n '__fish_seen_subcommand_from support-bundle' -l destination -d 'Destination path'
|
|
637
|
+
complete -c tan -n '__fish_seen_subcommand_from support-bundle' -l target-kind -d 'Debug target kind' -a 'zephyr-mcu baremetal-mcu yocto-userspace native-host'
|
|
638
|
+
complete -c tan -n '__fish_seen_subcommand_from support-bundle' -l server -d 'Debug server' -a 'jlink openocd pyocd gdbserver none'
|
|
639
|
+
complete -c tan -n '__fish_seen_subcommand_from completion' -l shell -d 'Shell type' -a 'bash zsh fish'
|
|
640
|
+
complete -c tan -n '__fish_seen_subcommand_from sdk' -a 'list install current switch'
|
|
641
|
+
complete -c tan -n '__fish_seen_subcommand_from sdk' -l destination -d 'Cache root'
|
|
642
|
+
complete -c tan -n '__fish_seen_subcommand_from sdk' -l global -d 'Pin the machine-global default'
|
|
643
|
+
complete -c tan -n '__fish_seen_subcommand_from bootstrap' -l no-pip -d 'Skip pip install'
|
|
644
|
+
complete -c tan -n '__fish_seen_subcommand_from bootstrap' -l no-west -d 'Skip west init/update'
|
|
645
|
+
complete -c tan -n '__fish_seen_subcommand_from bootstrap' -l print-env -d 'Print environment lines only'
|
|
646
|
+
complete -c tan -n '__fish_seen_subcommand_from bootstrap' -l allow-partial -d 'Report success despite a failed dependency install'
|
|
647
|
+
complete -c tan -n '__fish_seen_subcommand_from bootstrap' -l workspace -d 'Build the workspace at this path'
|
|
648
|
+
complete -c tan -n '__fish_seen_subcommand_from build' -l plan-from -d 'Read build plan from file'
|
|
649
|
+
complete -c tan -n '__fish_seen_subcommand_from build' -l materialise -d 'Materialise plan files'
|
|
650
|
+
complete -c tan -n '__fish_seen_subcommand_from build' -l native -d 'Build natively'
|
|
651
|
+
complete -c tan -n '__fish_seen_subcommand_from build' -l no-auto-bootstrap -d 'Never bootstrap implicitly'
|
|
652
|
+
complete -c tan -n '__fish_seen_subcommand_from build' -l pristine -d 'Force-wipe build dirs before dispatch'
|
|
653
|
+
complete -c tan -n '__fish_seen_subcommand_from kconfig' -l core -d 'Core id to scope the menu to'
|
|
654
|
+
complete -c tan -n '__fish_seen_subcommand_from image flash clean size' -l build-root -d 'Override build root'
|
|
655
|
+
complete -c tan -n '__fish_seen_subcommand_from flash' -l dry-run -d 'Print planned commands only'
|
|
656
|
+
complete -c tan -n '__fish_seen_subcommand_from flash' -l core -d 'Flash only this core'
|
|
657
|
+
complete -c tan -n '__fish_seen_subcommand_from flash' -l helper -d 'Flash only this helper MCU'
|
|
658
|
+
complete -c tan -n '__fish_seen_subcommand_from flash' -l skip-missing-tools -d 'Skip entries with no tool on PATH'
|
|
659
|
+
complete -c tan -n '__fish_seen_subcommand_from run' -l flash -d 'Flash the board after building'
|
|
660
|
+
complete -c tan -n '__fish_seen_subcommand_from run' -l core -d 'Flash only this core'
|
|
661
|
+
complete -c tan -n '__fish_seen_subcommand_from clean' -l dry-run -d 'List targets without removing'
|
|
662
|
+
complete -c tan -n '__fish_seen_subcommand_from size' -l board -d 'Override SoM SKU'
|
|
663
|
+
complete -c tan -n '__fish_seen_subcommand_from size' -l fail-over-budget -d 'Exit non-zero over budget'
|
|
664
|
+
"""
|
|
665
|
+
|
|
666
|
+
#: The three scripts as EMITTED: the captures above with their `--format`
|
|
667
|
+
#: value lists spliced in from the CLI's own enums (tan-cli#403).
|
|
668
|
+
BASH_SCRIPT = _fill_formats(_BASH_TEMPLATE)
|
|
669
|
+
ZSH_SCRIPT = _fill_formats(_ZSH_TEMPLATE)
|
|
670
|
+
FISH_SCRIPT = _fill_formats(_FISH_TEMPLATE)
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
def resolve_shell(raw: str | None) -> str | None:
|
|
674
|
+
"""Mirror Rust's `resolve_shell`: default `bash`; trim + lowercase; else
|
|
675
|
+
`None` (unsupported)."""
|
|
676
|
+
normalized = (raw if raw is not None else "bash").strip().lower()
|
|
677
|
+
if normalized in ("bash", "zsh", "fish"):
|
|
678
|
+
return normalized
|
|
679
|
+
return None
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
def script_for(shell: str) -> str:
|
|
683
|
+
"""Select the embedded script for a resolved `shell` name. Mirrors Rust's
|
|
684
|
+
`script_for`, including its fallback: an unrecognised value (unreachable
|
|
685
|
+
from `completion()` below, since that already rejected it) falls back to
|
|
686
|
+
bash rather than raising."""
|
|
687
|
+
if shell == "zsh":
|
|
688
|
+
return ZSH_SCRIPT
|
|
689
|
+
if shell == "fish":
|
|
690
|
+
return FISH_SCRIPT
|
|
691
|
+
return BASH_SCRIPT
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
def _null_project() -> Project:
|
|
695
|
+
"""`completion` is project-agnostic: no root, no board.yaml, ever."""
|
|
696
|
+
return Project(root=None, board_yaml=None)
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
def completion(
|
|
700
|
+
ctx: typer.Context,
|
|
701
|
+
shell: str = typer.Option(
|
|
702
|
+
None,
|
|
703
|
+
"--shell",
|
|
704
|
+
metavar="SHELL",
|
|
705
|
+
help="Target shell (bash, zsh, or fish). Defaults to bash.",
|
|
706
|
+
),
|
|
707
|
+
project: str = typer.Option(
|
|
708
|
+
None, "--project", metavar="PATH", help="Project root (defaults to '.')."
|
|
709
|
+
),
|
|
710
|
+
board_yaml: str = typer.Option(
|
|
711
|
+
None, "--board-yaml", metavar="PATH", help="Explicit board.yaml path."
|
|
712
|
+
),
|
|
713
|
+
sdk_root: str = typer.Option(
|
|
714
|
+
None, "--sdk-root", metavar="PATH", help="alp-sdk checkout root."
|
|
715
|
+
),
|
|
716
|
+
output_format: OutputFormat = typer.Option(None, "--format", help=FORMAT_HELP),
|
|
717
|
+
quiet: bool = typer.Option(False, "--quiet", hidden=True),
|
|
718
|
+
verbose: bool = typer.Option(False, "--verbose", hidden=True),
|
|
719
|
+
no_color: bool = typer.Option(False, "--no-color", hidden=True),
|
|
720
|
+
non_interactive: bool = typer.Option(False, "--non-interactive", hidden=True),
|
|
721
|
+
ci: bool = typer.Option(False, "--ci", hidden=True),
|
|
722
|
+
target: str = typer.Option(None, "--target", hidden=True),
|
|
723
|
+
all_targets: bool = typer.Option(False, "--all", hidden=True),
|
|
724
|
+
) -> None:
|
|
725
|
+
"""Emit a shell completion script (bash, zsh, or fish)."""
|
|
726
|
+
# `project`/`board_yaml`/`sdk_root` are clap `GlobalArgs` (`global = true`)
|
|
727
|
+
# this command never reads -- `completion` is project-agnostic on the
|
|
728
|
+
# oracle too (see `_null_project` above). `quiet`/`verbose`/`no_color`/
|
|
729
|
+
# `non_interactive`/`ci`/`target`/`all_targets` are the rest of that same
|
|
730
|
+
# set: declared ONLY so the argv surface matches clap (`tan completion
|
|
731
|
+
# --ci` must exit 0, not a Click usage error), never read. Mirrors
|
|
732
|
+
# `clean_cmd.clean`'s identical block.
|
|
733
|
+
del project, board_yaml, sdk_root
|
|
734
|
+
del quiet, verbose, no_color, non_interactive, ci, target, all_targets
|
|
735
|
+
|
|
736
|
+
# `--format` is accepted BEFORE the subcommand too (clap's `global =
|
|
737
|
+
# true`; verified against the oracle: `tan --format json completion
|
|
738
|
+
# --shell zsh` reaches this command and emits the envelope). The root
|
|
739
|
+
# callback (`cli.py`) records a leading value on `ctx.obj`; this option
|
|
740
|
+
# overrides it when repeated after the subcommand name -- that precedence
|
|
741
|
+
# is `resolve_format`'s, written once for the eleven commands that honour
|
|
742
|
+
# the leading position. An explicit `--format ""` still exits 2 (measured
|
|
743
|
+
# against the oracle: `tan completion --format ""` -> rc 2); since
|
|
744
|
+
# tan-cli#403 the declared enum refuses it at PARSE time, so no truthiness
|
|
745
|
+
# test in this body can mistake it for an absent flag.
|
|
746
|
+
resolved_format = resolve_format(output_format, ctx.obj, choices=OutputFormat)
|
|
747
|
+
json_mode = resolved_format == "json"
|
|
748
|
+
|
|
749
|
+
resolved_shell = resolve_shell(shell)
|
|
750
|
+
if resolved_shell is None:
|
|
751
|
+
if json_mode:
|
|
752
|
+
emit(
|
|
753
|
+
Envelope(
|
|
754
|
+
"completion",
|
|
755
|
+
_null_project(),
|
|
756
|
+
{"schemaVersion": DATA_SCHEMA_VERSION, "shell": "bash", "script": ""},
|
|
757
|
+
[Issue(SHELL_UNSUPPORTED_CODE, "error", SHELL_UNSUPPORTED_MESSAGE)],
|
|
758
|
+
ExitCode.RUNTIME_FAILURE,
|
|
759
|
+
)
|
|
760
|
+
)
|
|
761
|
+
else:
|
|
762
|
+
# stderr, like every other command's text-mode error line; stdout
|
|
763
|
+
# stays empty on this path (matches the oracle, measured).
|
|
764
|
+
print(SHELL_UNSUPPORTED_TEXT_LINE, file=sys.stderr)
|
|
765
|
+
raise typer.Exit(int(ExitCode.RUNTIME_FAILURE))
|
|
766
|
+
|
|
767
|
+
script = script_for(resolved_shell)
|
|
768
|
+
if json_mode:
|
|
769
|
+
emit(
|
|
770
|
+
Envelope(
|
|
771
|
+
"completion",
|
|
772
|
+
_null_project(),
|
|
773
|
+
{"schemaVersion": DATA_SCHEMA_VERSION, "shell": resolved_shell, "script": script},
|
|
774
|
+
[],
|
|
775
|
+
ExitCode.SUCCESS,
|
|
776
|
+
)
|
|
777
|
+
)
|
|
778
|
+
else:
|
|
779
|
+
# The script IS the payload (README: "tan completion --shell zsh
|
|
780
|
+
# emits a completion script"), and the only sane way to consume it is
|
|
781
|
+
# `eval "$(tan completion --shell zsh)"` / `> file` stdout capture --
|
|
782
|
+
# so print it straight to stdout, not through the stderr-only
|
|
783
|
+
# text-line convention every other command's text mode uses. Mirrors
|
|
784
|
+
# `completion.rs`'s own `println!` plus its comment on why.
|
|
785
|
+
print(script)
|
|
786
|
+
raise typer.Exit(int(ExitCode.SUCCESS))
|