Skip to content

Commit

Permalink
[CS2] Add #! support for executable scripts on Linux. (#3946)
Browse files Browse the repository at this point in the history
* Add #! support for executable scripts on Linux.

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.

* refactor option parsing

clean up parsing code and in the process fix oustanding bug where coffeescript
modified arguments meant for an executable script

* address comments

* intermediate save

* add note saying where OptionParser is used in coffee command

* add some more work

* fix flatten functions

* refactor tests

* make argument processing less confusing

* add basic test

* remove unused file

* compilation now hangs

* remove unnecessary changes

* add tests!!!

* add/fix some tests

* clarify a test

* fix helpers

* fix opt parsing

* fix infinite loop

* make rule building easier to read

* add tests for flag overlap

* revamp argument parsing again and add more thorough testing

* add tests, comment, clean unused method

* address review comments

* add test for direct invocation of shebang scripts

* move shebang parsing test to separate file and check for browser

* remove TODO

* example backwards compatible warnings

* add correct tests for warning 1

* add tests for warnings

* commit output js libs and update docs

* respond to review comments

also add tests for help text

* respond to review comments

* fix example output

* Rewrite argument parsing documentation to be more concise; add it to sidebar and body; add new output

* Don’t mention deprecated syntax; clean up variable names
  • Loading branch information
Danny McClanahan authored and GeoffreyBooth committed Jul 19, 2017
1 parent d287a79 commit 4e57ca6
Show file tree
Hide file tree
Showing 22 changed files with 672 additions and 213 deletions.
38 changes: 32 additions & 6 deletions docs/v2/index.html
Expand Up @@ -306,15 +306,15 @@
white-space: nowrap;
}

h2, h3 {
h2, h3, h4 {
margin-top: 1.3em;
margin-bottom: 0.6em;
font-family: 'Alegreya Sans';
}
h2 {
font-weight: 800;
}
h3, h2 time {
h3, h4, h2 time {
font-weight: 400;
}

Expand Down Expand Up @@ -734,6 +734,9 @@
<li class="nav-item">
<a href="#breaking-changes-literate-coffeescript" class="nav-link" data-action="sidebar-nav">Literate CoffeeScript Parsing</a>
</li>
<li class="nav-item">
<a href="#breaking-changes-argument-parsing-and-shebang-lines" class="nav-link" data-action="sidebar-nav">Argument Parsing and <code>#!</code> Lines</a>
</li>
</ul>
</li>
<li class="nav-item">
Expand Down Expand Up @@ -858,7 +861,7 @@ <h2>Overview</h2>
<section id="coffeescript-2">
<h2>CoffeeScript 2</h2>
<h3>What’s New In CoffeeScript 2?</h3>
<p>The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern, ES2015+ JavaScript. A CoffeeScript <code>=&gt;</code> becomes an ES <code>=&gt;</code>, a CoffeeScript <code>class</code> becomes an ES <code>class</code> and so on. With the exception of modules (<code>import</code> and <code>export</code> statements), all the ES2015+ features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScript’s output without any further processing required. You can <a href="http://coffeescript.org/v2/test.html">run the tests in your browser</a> to see if your browser can do the same; Chrome has supported all features since version 55.</p>
<p>The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern, ES2015+ JavaScript. A CoffeeScript <code>=&gt;</code> becomes an ES <code>=&gt;</code>, a CoffeeScript <code>class</code> becomes an ES <code>class</code> and so on. With the exception of <a href="#modules">modules</a> (<code>import</code> and <code>export</code> statements) and <a href="#jsx">JSX</a>, all the ES2015+ features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScript’s output without any further processing required. You can <a href="http://coffeescript.org/v2/test.html">run the tests in your browser</a> to see if your browser can do the same; Chrome has supported all features since version 55.</p>
<p>Support for ES2015+ syntax is important to ensure compatibility with frameworks that assume ES2015. Now that CoffeeScript compiles classes to the ES <code>class</code> keyword, it’s possible to <code>extend</code> an ES class; that wasn’t possible in CoffeeScript 1. Parity in how language features work is also important on its own; CoffeeScript “is just JavaScript,” and so things like <a href="#breaking-changes-default-values">function parameter default values</a> should behave the same in CoffeeScript as in JavaScript.</p>
<p>Many ES2015+ features have been backported to CoffeeScript 1.11 and 1.12, including <a href="#modules">modules</a>, <a href="#generator-iteration"><code>for…of</code></a>, and <a href="#tagged-template-literals">tagged template literals</a>. Major new features unique to CoffeeScript 2 are support for ES2017’s <a href="#async-functions">async functions</a> and for <a href="#jsx">JSX</a>. More details are in the <a href="#changelog">changelog</a>.</p>
<p>There are very few <a href="#breaking-changes">breaking changes from CoffeeScript 1.x to 2</a>; we hope the upgrade process is smooth for most projects.</p>
Expand Down Expand Up @@ -3244,7 +3247,7 @@ <h2>JSX</h2>
</div>

</aside>
<p>Older plugins or forks of CoffeeScript supported JSX syntax and referred to it as CSX or CJSX. They also often used a <code>.cjsx</code> file extension, but this is no longer necessary; regalar <code>.coffee</code> will do.</p>
<p>Older plugins or forks of CoffeeScript supported JSX syntax and referred to it as CSX or CJSX. They also often used a <code>.cjsx</code> file extension, but this is no longer necessary; regular <code>.coffee</code> will do.</p>

</section>
</section>
Expand Down Expand Up @@ -3619,7 +3622,7 @@ <h3>Classes are compiled to ES2015 classes</h3>
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span></span>
constructor: <span class="function">-&gt;</span> <span class="keyword">this</span> <span class="comment"># Throws a compiler error</span>
</code></pre>
</blockquote><p>ES2015 classes don’t allow bound (fat arrow) methods. The CoffeeScript compiler goes through some contortions to preserve support for them, but one thing that can’t be accomodated is calling a bound method before it is bound:</p>
</blockquote><p>ES2015 classes don’t allow bound (fat arrow) methods. The CoffeeScript compiler goes through some contortions to preserve support for them, but one thing that can’t be accommodated is calling a bound method before it is bound:</p>
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="class"><span class="keyword">class</span> <span class="title">Base</span></span>
constructor: <span class="function">-&gt;</span>
@onClick() <span class="comment"># This works</span>
Expand Down Expand Up @@ -3787,7 +3790,7 @@ <h3><code>super</code> and <code>extends</code></h3>

</section>
<section id="breaking-changes-jsx-and-the-less-than-and-greater-than-operators">
<h3>JSX and the <code>&lt;</code> and <code>&gt;</code> Operators</h3>
<h3>JSX and the <code>&lt;</code> and <code>&gt;</code> operators</h3>
<p>With the addition of <a href="#jsx">JSX</a>, the <code>&lt;</code> and <code>&gt;</code> characters serve as both the “less than” and “greater than” operators and as the delimiters for XML tags, like <code>&lt;div&gt;</code>. For best results, in general you should always wrap the operators in spaces to distinguish them from XML tags: <code>i &lt; len</code>, not <code>i&lt;len</code>. The compiler tries to be forgiving when it can be sure what you intend, but always putting spaces around the “less than” and “greater than” operators will remove ambiguity.</p>

</section>
Expand All @@ -3797,6 +3800,29 @@ <h3>Literate CoffeeScript parsing</h3>
<p>Code blocks should also now maintain a consistent indentation level—so an indentation of one tab (or whatever you consider to be a tab stop, like 2 spaces or 4 spaces) should be treated as your code’s “left margin,” with all code in the file relative to that column.</p>
<p>Code blocks that you want to be part of the commentary, and not executed, must have at least one line (ideally the first line of the block) completely unindented.</p>

</section>
<section id="breaking-changes-argument-parsing-and-shebang-lines">
<h3>Argument parsing and shebang (<code>#!</code>) lines</h3>
<p>In CoffeeScript 1.x, <code>--</code> was required after the path and filename of the script to be run, but before any arguments passed to that script. This convention is now deprecated. So instead of:</p>
<blockquote class="uneditable-code-block"><pre><code class="language-bash">coffee [options] path/to/script.coffee -- [args]
</code></pre>
</blockquote><p>Now you would just type:</p>
<blockquote class="uneditable-code-block"><pre><code class="language-bash">coffee [options] path/to/script.coffee [args]
</code></pre>
</blockquote><p>The deprecated version will still work, but it will print a warning before running the script.</p>
<p>On non-Windows platforms, a <code>.coffee</code> file can be made executable by adding a shebang (<code>#!</code>) line at the top of the file and marking the file as executable. For example:</p>
<blockquote class="uneditable-code-block"><pre><code class="language-coffee"><span class="comment">#!/usr/bin/env coffee</span>

x = <span class="number">2</span> + <span class="number">2</span>
<span class="built_in">console</span>.log x
</code></pre>
</blockquote><p>If this were saved as <code>executable.coffee</code>, it could be made executable and run:</p>
<blockquote class="uneditable-code-block"><pre><code class="language-bash">▶ chmod +x ./executable.coffee
▶ ./executable.coffee
4
</code></pre>
</blockquote><p>In CoffeeScript 1.x, this used to fail when trying to pass arguments to the script. Some users on OS X worked around the problem by using <code>#!/usr/bin/env coffee --</code> as the first line of the file. That didn’t work on Linux, however, which cannot parse shebang lines with more than a single argument. While such scripts will still run on OS X, CoffeeScript will now display a warning before compiling or evaluating files that begin with a too-long shebang line. Now that CoffeeScript 2 supports passing arguments without needing <code>--</code>, we recommend simply changing the shebang lines in such scripts to just <code>#!/usr/bin/env coffee</code>.</p>

</section>
</section>
<section id="changelog">
Expand Down
@@ -0,0 +1,34 @@
### Argument parsing and shebang (`#!`) lines

In CoffeeScript 1.x, `--` was required after the path and filename of the script to be run, but before any arguments passed to that script. This convention is now deprecated. So instead of:

```bash
coffee [options] path/to/script.coffee -- [args]
```

Now you would just type:

```bash
coffee [options] path/to/script.coffee [args]
```

The deprecated version will still work, but it will print a warning before running the script.

On non-Windows platforms, a `.coffee` file can be made executable by adding a shebang (`#!`) line at the top of the file and marking the file as executable. For example:

```coffee
#!/usr/bin/env coffee

x = 2 + 2
console.log x
```

If this were saved as `executable.coffee`, it could be made executable and run:

```bash
▶ chmod +x ./executable.coffee
▶ ./executable.coffee
4
```

In CoffeeScript 1.x, 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 --` as the first line of the file. That didn’t work on Linux, however, which cannot parse shebang lines with more than a single argument. While such scripts will still run on OS X, CoffeeScript will now display a warning before compiling or evaluating files that begin with a too-long shebang line. Now that CoffeeScript 2 supports passing arguments without needing `--`, we recommend simply changing the shebang lines in such scripts to just `#!/usr/bin/env coffee`.
@@ -1,3 +1,3 @@
### JSX and the `<` and `>` Operators
### JSX and the `<` and `>` operators

With the addition of [JSX](#jsx), the `<` and `>` characters serve as both the “less than” and “greater than” operators and as the delimiters for XML tags, like `<div>`. For best results, in general you should always wrap the operators in spaces to distinguish them from XML tags: `i < len`, not `i<len`. The compiler tries to be forgiving when it can be sure what you intend, but always putting spaces around the “less than” and “greater than” operators will remove ambiguity.
2 changes: 1 addition & 1 deletion documentation/sections/coffeescript_2.md
Expand Up @@ -2,7 +2,7 @@

### What’s New In CoffeeScript 2?

The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern, ES2015+ JavaScript. A CoffeeScript `=>` becomes an ES `=>`, a CoffeeScript `class` becomes an ES `class` and so on. With the exception of modules (`import` and `export` statements), all the ES2015+ features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScript’s output without any further processing required. You can [run the tests in your browser](http://coffeescript.org/v<%= majorVersion %>/test.html) to see if your browser can do the same; Chrome has supported all features since version 55.
The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern, ES2015+ JavaScript. A CoffeeScript `=>` becomes an ES `=>`, a CoffeeScript `class` becomes an ES `class` and so on. With the exception of [modules](#modules) (`import` and `export` statements) and [JSX](#jsx), all the ES2015+ features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScript’s output without any further processing required. You can [run the tests in your browser](http://coffeescript.org/v<%= majorVersion %>/test.html) to see if your browser can do the same; Chrome has supported all features since version 55.

Support for ES2015+ syntax is important to ensure compatibility with frameworks that assume ES2015. Now that CoffeeScript compiles classes to the ES `class` keyword, it’s possible to `extend` an ES class; that wasn’t possible in CoffeeScript 1. Parity in how language features work is also important on its own; CoffeeScript “is just JavaScript,” and so things like [function parameter default values](#breaking-changes-default-values) should behave the same in CoffeeScript as in JavaScript.

Expand Down
3 changes: 3 additions & 0 deletions documentation/v2/body.html
Expand Up @@ -178,6 +178,9 @@
<section id="breaking-changes-literate-coffeescript">
<%= htmlFor('breaking_changes_literate_coffeescript') %>
</section>
<section id="breaking-changes-argument-parsing-and-shebang-lines">
<%= htmlFor('breaking_changes_argument_parsing_and_shebang_lines') %>
</section>
</section>
<section id="changelog">
<%= htmlFor('changelog') %>
Expand Down
4 changes: 2 additions & 2 deletions documentation/v2/docs.css
Expand Up @@ -286,15 +286,15 @@ td code {
white-space: nowrap;
}

h2, h3 {
h2, h3, h4 {
margin-top: 1.3em;
margin-bottom: 0.6em;
font-family: 'Alegreya Sans';
}
h2 {
font-weight: 800;
}
h3, h2 time {
h3, h4, h2 time {
font-weight: 400;
}

Expand Down
3 changes: 3 additions & 0 deletions documentation/v2/sidebar.html
Expand Up @@ -171,6 +171,9 @@
<li class="nav-item">
<a href="#breaking-changes-literate-coffeescript" class="nav-link" data-action="sidebar-nav">Literate CoffeeScript Parsing</a>
</li>
<li class="nav-item">
<a href="#breaking-changes-argument-parsing-and-shebang-lines" class="nav-link" data-action="sidebar-nav">Argument Parsing and <code>#!</code> Lines</a>
</li>
</ul>
</li>
<li class="nav-item">
Expand Down
17 changes: 16 additions & 1 deletion lib/coffeescript/coffeescript.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 14 additions & 3 deletions lib/coffeescript/command.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4e57ca6

Please sign in to comment.