fix --help being skipped for bin routes that only partially resolve to a file (#6788)

* fix `--help` being skipped for bin routes that only partially resolve to a file

* Add regression tests for --help on partially resolved routes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Stop help-flag scanning at -- and match --json as an exact token

A `--` marks the rest of the args as belonging to the command itself, so
neither --help nor --json past it should be treated as router flags. The
--json check also matched substrings of flattened args, so a --json inside
one quoted argument switched --help output to JSON.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: David Heinemeier Hansson <david@hey.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erwin Francisco Macias Ghiglione
2026-08-13 09:53:31 +02:00
committed by GitHub
co-authored by Claude Fable 5 David Heinemeier Hansson
parent 38542a1f51
commit 9672d852f0
2 changed files with 81 additions and 4 deletions
+29 -4
View File
@@ -122,6 +122,31 @@ append_pipe_value() {
fi
}
# A route can resolve to a binary before all args are consumed (`update aur` only matches the `update` binary, leaving `aur` and `--help` as leftovers)
# --help must never be lost among those leftovers and get forwarded into the real command, so this checks the whole remainder rather than just the first token.
# A `--` marks everything after it as belonging to the command itself, so scanning stops there.
remaining_has_help_flag() {
local token=""
for token in "$@"; do
[[ $token == "--" ]] && break
[[ $token == "--help" || $token == "-h" ]] && return 0
done
return 1
}
remaining_has_json_flag() {
local token=""
for token in "$@"; do
[[ $token == "--" ]] && break
[[ $token == "--json" ]] && return 0
done
return 1
}
register_route() {
local route="$1"
local key="$2"
@@ -930,7 +955,7 @@ dispatch_fast_or_help() {
remaining=("${args[@]:DIRECT_RESOLVED_COUNT}")
binary_path="$OMARCHY_BIN_DIR/$DIRECT_RESOLVED_BINARY"
if (( ${#remaining[@]} > 0 )) && [[ ${remaining[0]} == "--help" || ${remaining[0]} == "-h" ]]; then
if remaining_has_help_flag "${remaining[@]}"; then
if ! load_command_by_binary "$DIRECT_RESOLVED_BINARY"; then
echo "Binary is missing or not executable: $DIRECT_RESOLVED_BINARY" >&2
return 127
@@ -941,7 +966,7 @@ dispatch_fast_or_help() {
fi
key="${BINARY_TO_KEY[$DIRECT_RESOLVED_BINARY]}"
if [[ " ${remaining[*]} " == *" --json "* ]]; then
if remaining_has_json_flag "${remaining[@]}"; then
show_command_json "$key"
else
show_command_help "$key"
@@ -994,8 +1019,8 @@ dispatch_or_help() {
key="$RESOLVED_KEY"
remaining=("${args[@]:RESOLVED_COUNT}")
if (( ${#remaining[@]} > 0 )) && [[ ${remaining[0]} == "--help" || ${remaining[0]} == "-h" ]]; then
if [[ " ${remaining[*]} " == *" --json "* ]]; then
if remaining_has_help_flag "${remaining[@]}"; then
if remaining_has_json_flag "${remaining[@]}"; then
show_command_json "$key"
else
show_command_help "$key"
+52
View File
@@ -755,3 +755,55 @@ assert_output_contains "partial metadata command dispatches" "$output" "partial-
output=$("$TMPDIR/omarchy" body metadata test)
assert_output_contains "body metadata command dispatches by filename" "$output" "body-metadata-ok"
# A trailing --help must render help even when the route only partially
# resolves, leaving unresolved words ahead of the flag (e.g. `update aur --help`
# used to start a real update because only the first leftover token was checked).
{
printf '#!/bin/bash\n\n'
printf '# omarchy:summary=Partial resolution help test parent\n'
printf '# omarchy:alias=omarchy parenthelp-alias\n'
printf 'echo "parenthelp-parent-ran args=[$*]"\n'
} >"$TMPDIR/omarchy-parenthelp"
chmod +x "$TMPDIR/omarchy-parenthelp"
{
printf '#!/bin/bash\n\n'
printf '# omarchy:summary=Partial resolution help test child\n'
printf 'echo parenthelp-child-ran\n'
} >"$TMPDIR/omarchy-parenthelp-child"
chmod +x "$TMPDIR/omarchy-parenthelp-child"
output=$("$TMPDIR/omarchy" parenthelp bogus --help)
assert_output_contains "trailing --help after an unresolved word renders help" "$output" "omarchy-parenthelp"
assert_output_contains "partial resolution help lists related commands" "$output" "omarchy parenthelp child"
if [[ $output == *"parenthelp-parent-ran"* ]]; then
fail "trailing --help after an unresolved word does not execute the command"
fi
pass "trailing --help after an unresolved word does not execute the command"
output=$("$TMPDIR/omarchy" parenthelp bogus -h)
assert_output_contains "trailing -h after an unresolved word renders help" "$output" "omarchy-parenthelp"
output=$("$TMPDIR/omarchy" parenthelp-alias bogus --help)
assert_output_contains "trailing --help after an unresolved word renders help via alias route" "$output" "omarchy-parenthelp"
if [[ $output == *"parenthelp-parent-ran"* ]]; then
fail "trailing --help on an alias route does not execute the command"
fi
pass "trailing --help on an alias route does not execute the command"
output=$("$TMPDIR/omarchy" parenthelp bogus --json --help)
grep -q '"ok": true' <<<"$output" || fail "--json with --help renders JSON help"
pass "--json with --help renders JSON help"
output=$("$TMPDIR/omarchy" parenthelp "explain --json output" --help)
assert_output_contains "a --json embedded inside one argument does not switch help to JSON" "$output" "Partial resolution help test parent"
output=$("$TMPDIR/omarchy" parenthelp bogus trailing)
assert_output_contains "leftover args without a help flag still forward" "$output" "parenthelp-parent-ran args=[bogus trailing]"
output=$("$TMPDIR/omarchy" parenthelp run -- --help)
assert_output_contains "a --help behind -- belongs to the command and still forwards" "$output" "parenthelp-parent-ran args=[run -- --help]"
output=$("$TMPDIR/omarchy" parenthelp --helpme x--help)
assert_output_contains "help lookalike tokens do not trigger help" "$output" "parenthelp-parent-ran args=[--helpme x--help]"