-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CS2] Add #! support for executable scripts on Linux. #3946
Conversation
Pass arguments to executable script unchanged if using "#!/usr/bin/env coffee". (Previously, "./test.coffee -abck" would be turned into "-a -b -c -k", for example.) Fixes jashkenas#1752.
👍 to this. The current behavior also has it so that you can't pass
While it works correctly if you say |
src/optparse.coffee
Outdated
# systems, which do not parse the '--' argument in the first line correctly. | ||
if (args.indexOf '--' is -1) and | ||
(args.length > 0) and | ||
(isCoffee args[0]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rewrite this is as
if args.length isnt 0 and '--' in args and isCoffee(args[0])
Is there any chance that this could be a breaking change? If so please target the |
I think so, for linux hosts; the situation I described at the top won't matter if the script follows standard command line conventions (where |
How would it break? Would |
Sorry, the other way around; Invoking a script either like |
How will this affect traditional users running |
#!<SHEBANG LINE>
console.log process.argv then there are about two and a half cases it differs:
The solution above won't fix this, but we can detect the case where the user invokes the script with |
We should add some tests around this. I think it’s testable within our current framework, via stuff like |
74f9a2e
to
65f1e73
Compare
clean up parsing code and in the process fix oustanding bug where coffeescript modified arguments meant for an executable script
I think the previous option parsing code was convoluted and made it too easy to make mistakes like the
I can absolutely add some tests. I do not have time today, but will try to do so tomorrow. Let me know if there are any style changes I can make, I tried to follow the rest of the code as much as possible. |
src/optparse.coffee
Outdated
state = | ||
argsLeft: args[..] | ||
options: {} | ||
while (arg = state.argsLeft.shift())? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ve been trying to avoid assignments inside conditionals. Can we just use for arg in args
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that I think about it, I think we can just do a single pass over the arguments beforehand to 1. group arguments with values (-o [dir]
) 2. explode combined options (e.g. -abck
) 3. identify the first non-optional argument, then use a for
. I'll do that.
src/optparse.coffee
Outdated
normalized = "-#{multiArg}" for multiArg in multiMatch[1].split '' | ||
state.argsLeft.unshift(normalized...) | ||
else | ||
# the CS option parser is a little odd; options after the first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comments become the annotated source, so please use sentence case (capitalize first word, use periods).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, will fix. The first two lines are actually from the original source, so I wasn't sure whether I should change them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. Never too late to fix things 😄
src/optparse.coffee
Outdated
if arg in [rule.shortFlag, rule.longFlag] | ||
if rule.hasArgument | ||
value = state.argsLeft.shift() | ||
if not value? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unless
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, will change.
src/optparse.coffee
Outdated
else | ||
value = true | ||
|
||
addArgument(rule, state.options, value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid parentheses when possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, will fix.
src/optparse.coffee
Outdated
value = true | ||
|
||
addArgument(rule, state.options, value) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to avoid the implicit return?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If not, it would eventually leave the for loop and hit the throw statement. This was dealt with previously by keeping a boolean testing whether or not the rule was matched; I thought this was cleaner here since we don't then loop over the rest of the rules if we successfully match one.
Do you mind please submitting the “current state” tests of the CLI as it works now as a separate PR? So that we can see that they work before trying them against your refactor. |
baaf924
to
124d228
Compare
Yes! I'll make a separate PR for those sometime tomorrow. Thanks for your responsiveness. |
e2d7fe7
to
5f3edbe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry to give such minor notes. I would make the changes myself but I lack access to your branch.
@@ -0,0 +1,3 @@ | |||
#!/usr/bin/env coffee -- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The convention in this repo is to use underscores in filenames.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed all the files I have added to use underscores. The file test/argument-parsing.coffee
was one I made in the previous PR to test v1's command-line argument parsing, and I have changed that one to use underscores too.
If called without options, `coffee` will run your script. | ||
|
||
|
||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the blank lines before and after the text?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually screwed up the help text (see the most recent commit -- needed to change the help method to use @rules.ruleList
instead of just @rules
). I made that fix, changed this text, and have also added tests in test/option_parser.coffee
in the most recent commit to ensure the help text will always display the banner and the flags.
4 | ||
``` | ||
|
||
Due to a bug in the argument parsing of previous CoffeeScript versions, this used to fail when trying to pass arguments to the script. Some users on OSX worked around the problem by using `#!/usr/bin/env coffee --` at the top of the file instead. However, that won't work on Linux, which cannot parse shebang lines with more than a single argument. While these scripts will still run on OSX, CoffeeScript will now display a warning before compiling or evaluating files that begin with a too-long shebang line: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It’s “OS X”. Also the documentation uses curly quotes, e.g. “won’t”.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed both of those.
also add tests for help text
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also please merge in develop
and resolve conflicts.
-l, --literate treat stdio as literate style coffeescript | ||
-t, --tokens print out the tokens that the lexer/rewriter produce | ||
-v, --version display the version number | ||
-w, --watch watch scripts for changes and rerun commands |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already documented in http://coffeescript.org/v2/#usage. The Breaking Changes section should only discuss breaking changes from 1.x.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. I have noted only the changed usage line now and left an ...
to denote the rest of the help text.
@@ -45,7 +64,7 @@ console.log x | |||
4 | |||
``` | |||
|
|||
Due to a bug in the argument parsing of previous CoffeeScript versions, this used to fail when trying to pass arguments to the script. Some users on OSX worked around the problem by using `#!/usr/bin/env coffee --` at the top of the file instead. However, that won't work on Linux, which cannot parse shebang lines with more than a single argument. While these scripts will still run on OSX, CoffeeScript will now display a warning before compiling or evaluating files that begin with a too-long shebang line: | |||
Due to a bug in the argument parsing of previous CoffeeScript versions, this used to fail when trying to pass arguments to the script. Some users on OS X worked around the problem by using `#!/usr/bin/env coffee --` at the top of the file instead. However, that won’t work on Linux, which cannot parse shebang lines with more than a single argument. While these scripts will still run on OSX, CoffeeScript will now display a warning before compiling or evaluating files that begin with a too-long shebang line: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another “OS X”.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
test/option_parser.coffee
Outdated
ok bannerHelp.match bannerPattern | ||
for flag in flags | ||
linePat = flagPattern flag | ||
ok bannerHelp.match linePat |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tests that the option parser correctly outputs a banner text string, but not necessarily that coffee -h
actually outputs the correct help text. For that, you need to actually test opt.help()
against the help text, which should be written here in the test. I know it doesn’t feel DRY to repeat a string that is elsewhere in the codebase, but if that string changes in the main code, we want this test to fail—either to inform us that we unexpectedly changed the help text, or to remind us to update the test, too, so that we preserve this check for the future. The same applies to the list of switches.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that makes sense. I'll make that change.
Let me know if there are any issues with these changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you’d like to give me access to your branch, I could fix a bunch of these tiny issues.
' -o, --optional desc optional' | ||
' -l, --list desc list' | ||
'' | ||
].join('\n') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could just be a '''
string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly, except that '''
strings don't allow leading spaces unless one of the lines (e.g. the banner text) is not indented, so I don't think this would work as a '''
string.
test/option_parser.coffee
Outdated
test "outputs expected help text", -> | ||
expectedBanner = ''' | ||
|
||
banner text |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tests that the OptionParser class outputs the kind of help text that we expect, and not just the OptionParser instance that is used in command.coffee
. It also tests the output without a banner.
Due to a bug in the argument parsing of previous CoffeeScript versions, this used to fail when trying to pass arguments to the script. Some users on OS X worked around the problem by using `#!/usr/bin/env coffee --` at the top of the file instead. However, that won’t work on Linux, which cannot parse shebang lines with more than a single argument. While these scripts will still run on OSX, CoffeeScript will now display a warning before compiling or evaluating files that begin with a too-long shebang line: | ||
##### Incorrect Example | ||
|
||
Due to a bug in the argument parsing of previous CoffeeScript versions, this used to fail when trying to pass arguments to the script. Some users on OSX worked around the problem by using `#!/usr/bin/env coffee --` at the top of the file instead. However, that won’t work on Linux, which cannot parse shebang lines with more than a single argument. While these scripts will still run on OSX, CoffeeScript will now display a warning before compiling or evaluating files that begin with a too-long shebang line: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“OS X”
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what the issue is -- should I add quotes around OSX
? The space between OS
and X
was removed everywhere.
I have added you as a collaborator to my branch -- let me know if you have push access. |
…sidebar and body; add new output
Okay, I think we’re good now. I shortened the docs considerably, can you let me know if I took out anything important? We try to keep the docs as concise as possible. The generated output is here: Anyone else have any final notes before this gets merged in? |
src/command.coffee
Outdated
@@ -25,7 +25,7 @@ hidden = (file) -> /^\.|~$/.test file | |||
|
|||
# The help banner that is printed in conjunction with `-h`/`--help`. | |||
BANNER = ''' | |||
Usage: coffee [options] [--] path/to/script.coffee [args] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like removing [--]
, the new version does not say anything about how --
is parsed as an argument. gawk --help
uses [--]
in a very similar way.
test/argument_parsing.coffee
Outdated
@@ -115,7 +115,7 @@ test "throw on invalid options", -> | |||
test "has expected help text", -> | |||
ok optionParser.help() is ''' | |||
|
|||
Usage: coffee [options] [--] path/to/script.coffee [args] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in src/command.coffee
.
I really like the changes. My only concern is in the usage text, as noted inline. |
Why mention |
After thinking about it a bit, I think the main reason I wanted the |
I think it’s confusing to include the reference to it if we don’t define what it does (especially if the only thing it “does” is print a warning). If it did anything useful, then sure, let’s include it and describe its function like the other flags. @lydell or anyone else, any final notes? This is an old PR, thank you @cosmicexplorer for sticking with us for so long! |
I completely 100% agree with that. Let me know if anything weird happens with these changes -- I feel comfortable after all the test cases, but I'm still wary. Glad this change finally saw light, turned out to be much, much harder than I expected. |
Pass arguments to executable script unchanged if using "#!/usr/bin/env
coffee". (Previously, "./test.coffee -abck" would be turned into "-a -b -c -k",
for example.)
Fixes #1752.