Run help50 COMMAND as though COMMAND were typed directly - #247
Merged
Merged
Conversation
Students used to run `help50 make foo`. Help now arrives automatically after any failed command, so run COMMAND with the same exit status and let the prompt hook handle the rest: help50 make foo behaves exactly like make foo. Builtins go through bash -c with the shell's error wording preserved; an unknown command fails with the shell's own "command not found" message so helpers match it. Bare help50 prints usage (exit 0) explaining the new behaviour. The subcommands (start/stop/...) are unchanged; only they require non-root.
Within a help50 session, define help50 as a shell function that evals COMMAND in the calling shell, so aliases (rm -i), functions, and cd behave exactly as they would directly, and no stderr is rewritten through an unwaited sed. In the script (outside a session), route path-shaped names (./foo.c, ./dir) through bash -c so the shell's own Permission denied / Is a directory errors reach the helpers instead of a synthesized "command not found"; wait for sed before exiting; pass -- to type so option-like commands don't leak usage noise. In the prompt hook, treat `help50 COMMAND` as COMMAND when deriving argv, so helpers that look at positional words (e.g., `check 50`) and the ./ re-make hint still fire. Smoke-test the passthrough: exit statuses, exact error text for unknown, option-like, builtin, and path-shaped commands, usage, sudo, the in-shell function, and the hook's argv handling.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Students (and existing docs and videos) know
help50 make foo. On this branch that printedUsage: help50 [disable|enable|...]and exited 1, which in a codespace also triggered the duck nudge on help50's own usage text.Now
help50 COMMAND [ARGS...]runs COMMAND as though it had been typed directly, with the same output and exit status, and the prompt hook handles any failure exactly as it would have. Sohelp50 make fooandmake foobehave identically, and the old habit becomes harmless.Two mechanisms, depending on where the command is run:
Within a help50 session (i.e., the shell
help50 startwraps inscript, where the prompt hook and helpers live),/etc/profile.d/help50.shdefines ahelp50shell function. For anything other than the management subcommands, itevals the (%q-requoted) command line in the calling shell itself. Because it runs in the same process, aliases likerm -iandcd'sHOME=$WORKDIRapply, shell functions are visible, and builtins that change the shell (cd,export) actually take effect:help50 cd foochanges directory. Errors are the interactive shell's own, with no stderr rewriting.Outside a session (help50 disabled,
bash --login -c,sudo),/opt/cs50/bin/help50handles it:exec "$@"for anything onPATH, sohelp50 make fooreaches the samemakewrapper in/opt/cs50/binas typingmake foo.help50 ./foo.c,help50 cd nothere) go throughbash -c, so bash itself reportsPermission denied,Is a directory, orNo such file or directorywith the same exit status as a direct run;bash: line 1:is rewritten tobash:so the text matches what helpers expect, and the script waits for that rewrite to finish before exiting.bash: X: command not found(exit 127), so thebashhelper's regexes match (help50 1s-> "Did you mean to runls...").help50,-h,--helpprint a usage message explaining that help is now automatic (exit 0, so it doesn't trigger the duck).disable|enable|is-enabled|start|status|stopare unchanged; only they require non-root, sosudo help50 echo xstill runsecho x.The prompt hook treats
help50 COMMANDas COMMAND when deriving the command line it passes to helpers, so helpers that look at positional words (e.g.,check 50-> "Did you meancheck50") and the "foo.chas changed, runmakeagain" check still fire.Known, not fixed: keywords whose spelling
%qquotes (help50 [[ -f x ]]) fail ascommand not found.Testing
tests/smoke.sh(make smoke) now covers the passthrough: exit-status propagation; exact stderr text and exit codes for unknown (1s), option-like (--version), builtin (cd nothere), and path-shaped (./foo.c,./dir) commands; usage exiting 0;sudo help50 COMMANDworking whilesudo help50 is-enableddoes not; the in-session function applyingcdand aliases; and the hook reportinghelp50 ./slowas./slow.Under a pty in the built image,
help50 ./foo.c,help50 1s,help50 cd nothere,help50 ./dir,help50 make foo, andhelp50 check 50each produce the same advice as the direct command;help50 cd /tmpchanges directory;help50 statusstill reportsstarted.