Visitar URL original
Skip an option value in the verb slot of command words by Aaronontheweb · Pull Request #238 · Aaronontheweb/ShellSyntaxTree · GitHub
Skip to content

Skip an option value in the verb slot of command words - #238

Merged
Aaronontheweb merged 2 commits into
devfrom
fix/verb-slot-option-value
Oct 6, 2026
Merged

Aaronontheweb merged 2 commits into
devfrom
fix/verb-slot-option-value

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Owner

Fixes #237

What changed

  • Owner rule. In CommandOccurrence.CommandWords, a plain word directly after an option is that option's value everywhere, also in the verb slot. The next plain word is the verb. Before, the verb slot kept the word: ilspycmd -t Mattermost.MattermostClient /p/x.dll gave ilspycmd Mattermost.MattermostClient. It now gives ilspycmd.
  • Bare --. In the verb slot, -- takes no value, as before: git -- push gives git push. After the verb slot, the word after -- is still skipped (git checkout -- main gives git checkout). That rule does not change here.
  • Fail closed, no change. A dynamic word or a bare glob in the verb slot gives Unknown, also after an option. A dynamic option word stays conservative: cmd $opt value sub and cmd "$opt" value sub (unknown opt) give Unknown. An exact binding is a static option: o=-x; cmd "$o" value sub gives cmd sub.
  • Accepted trade-off. A switch without a value hides the plain word after it: docker --debug run gives docker, and docker --debug run img gives docker img. Wrappers are affected too: xargs -0 rm gives xargs, and env -i rm gives env. SPEC and the consumer guide tell consumers not to let a wrapper grant cover the program that the wrapper runs.
  • Prepare 0.4.0-beta.20 (version, release notes, README, SPEC, consumer guide, plan).

Red tests (before the fix)

New tests in CommandWordsTests failed on dev with 14 failures:

Source Expected
ilspycmd -t Mattermost.MattermostClient /p/x.dll ilspycmd
ilspycmd -t A.B -o out x.dll ilspycmd x.dll (a consumer can drop the file word)
git -c user.name=x commit -m msg git commit
dotnet --verbosity q build Foo.sln dotnet build Foo.sln
kubectl -n prod get pods kubectl get pods
docker --debug run / docker --debug run img docker / docker img
git --no-pager log -1, git -p filter-branch --force HEAD git
o=-x; cmd "$o" value sub cmd sub
PowerShell: ilspycmd -t A.B /p/x.dll, kubectl -n prod get pods, Get-Process -Name foo, docker --debug run ilspycmd, kubectl get pods, Get-Process, docker

These already passed and stay pinned: gh -R owner/repo pr view 12, gh --repo owner/repo pr view, git -C ~/repo log --oneline, git -C repo push, cmd --flag=value sub, cmd -- sub, cmd -x 5 sub, cmd -x ./* sub, git push origin main, gh pr view, the fail-closed cases, and git checkout -- main.

Existing tests changed (30 failures after the fix)

  • Bash_owner_table: git --no-pager log -1 → git, pgrep -x name → pgrep, git -p filter-branch (with and without --force HEAD) → git. Owner rule.
  • Bash_verb_slot_keeps_a_plain_word_after_an_option → renamed Bash_verb_slot_skips_a_plain_word_after_an_option. Same inputs, new values (git push for git -c x=y push, gh logout for gh --debug auth logout). The quoted-verb cases stay.
  • Bash_after_verb_slot_skips_option_values_and_arguments: input git -p filter-branch --force HEAD → git filter-branch --force HEAD. It keeps the after-slot coverage. The old input moves to the trade-off test.
  • Bash_hiding_attempts_keep_the_real_verb: git -c x=y push → git push (better). gh --debug auth logout moves to the trade-off test.
  • PowerShell_hiding_attempts_keep_the_real_verb: git --no-pager log -1 and gh --debug auth logout move to PowerShell_verb_slot_skips_an_option_value with the new values. Add git -c x=y push → git push.
  • PowerShell_position_rule and PowerShell_words: Get-Process -Name foo → Get-Process. gh --debug auth logout → gh logout.
  • Bash_quoted_exact_binding_gives_its_value_as_a_word: r=push; git -p "$r" → git, and x=-p; git "$x" log → git. Both still prove a static binding word (not Unknown). Add r=push; git -C . "$r" → git push and x=-p; git "$x" -- log → git log.
  • Option_order_does_not_change_the_words: switches without a value (--web, -q) move from the prefix to the suffix only. The prefix gets -X value. A switch before the verb now takes pr as its value.
  • LaunchEnvironmentTests.Launch_values_in_the_verb_slot_and_program_word_resolve: git -p "$SUB" → git. Add git -C . "$SUB" → git push.

No test was deleted.

Evidence

  • dotnet test -c Release: 4614 passed, 0 failed (beta.19: 4575). Build: 0 warnings. Header check passes. Pack gives ShellSyntaxTree.0.4.0-beta.20.nupkg.
  • Output comparison against dev (0.4.0-beta.19 code): 6,057 inputs (corpus, design corpus, test literals, PowerShell test literals, manual extras), each initial-state mode, both authored-fact settings, two working directories, with and without launch facts (109,960 records). Only CommandWords changes. 186 inputs change, and each has an option (or an exact option binding) before the old verb word. In 166 word lists the old verb-slot word drops. In 22 PowerShell word lists a script block or an expansion moves into the verb slot, so the words become Unknown (fail closed).
  • Replay of 11,063 Netclaw shell calls: 1,581 calls change words. Most are find . -type f (find f → find), grep -v obj, jq -r .x, and curl -w FORMAT. Wrapper examples: xargs -0 du → xargs, xargs -I{} gh api → xargs api, command -v pwsh → command.
  • Manual mutants (each built and run): 12 killed, 0 survived. They cover the old position rule, no option-value skip, no -- exception, the -- exception everywhere, the -- exception after the slot only, no inline-value check, a skipped value that also skips the next word, a value or path that takes a value, a dynamic option value skipped in the slot, -- matched as any long option, -- never matched, and the slot filled at one word.
  • Public API: no change.

@Aaronontheweb
Aaronontheweb merged commit ec3292f into dev Oct 6, 2026
3 of 4 checks passed
@Aaronontheweb
Aaronontheweb deleted the fix/verb-slot-option-value branch October 6, 2026 00:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Command words: skip an option value in the verb slot

1 participant