Compare commits

..

204 Commits
1.6.2 ... 1.6.3

Author SHA1 Message Date
Jeremy Ashkenas
84b8b5ccee CoffeeScript 1.6.3 2013-06-02 09:37:45 +04:00
Jeremy Ashkenas
7b14a6aad2 Fixing browser build boilerplate. 2013-06-02 09:21:36 +04:00
Jeremy Ashkenas
342306587c Removing out of date testing cruft 2013-06-02 09:13:16 +04:00
Jeremy Ashkenas
3298c9caad merge 2013-06-02 09:10:16 +04:00
Jeremy Ashkenas
7089b02a74 Merging in a monkey-patching of Module::load, unfortunately. 2013-06-02 09:03:54 +04:00
Jeremy Ashkenas
bd451800bf Merge pull request #3000 from sgentle/require-extensions
Patch module.prototype.load to enable multiple extensions like .coffee.md
2013-06-01 21:44:02 -07:00
Jeremy Ashkenas
5e06f7e859 Removing Ultraviolet workaround 2013-06-02 07:50:03 +04:00
Michael Ficarra
0f5ae54014 Merge pull request #2930 from marchaefner/Issue1057
Fixes #1057: Allow catch/finally in single line functions.
2013-05-31 14:56:04 -07:00
Michael Ficarra
5496a189bc fixes #2934 2013-05-31 16:51:30 -05:00
Michael Ficarra
2e6a781014 remove cake build:ultraviolet 2013-05-31 15:49:48 -05:00
Michael Ficarra
b85cf5355f Merge pull request #2085 from stepheneb/ruby-1-9-generate-coffeescript-syntax
rake task creates/installs coffeescript.syntax
2013-05-31 13:48:22 -07:00
Jeremy Ashkenas
f038d0514a Merge pull request #2984 from xixixao/literatetest
Fixes tabbed code test in literate
2013-05-26 04:08:01 -07:00
Jeremy Ashkenas
7c4128ee3b Merge pull request #3002 from Nami-Doc/issue3001
Disallowed `for own in`
2013-05-26 03:43:22 -07:00
Sam Gentle
012e3c019c fix style problems part 3 2013-05-26 15:59:49 +10:00
Nami-Doc
b3ffd25339 Disallowed for own in 2013-05-26 00:29:26 +02:00
Sam Gentle
46a0dc6dce Didn't mean to commit testsymlink 2013-05-26 02:33:11 +10:00
Sam Gentle
30b2af820a Early exit + refactor findExtension 2013-05-26 02:17:34 +10:00
Sam Gentle
e7d01b903f New tests for module importing 2013-05-26 02:09:52 +10:00
Sam Gentle
e4407dd73c fix style problems part 2 2013-05-26 00:50:18 +10:00
Sam Gentle
2fd956d8d4 fix style problems 2013-05-26 00:10:07 +10:00
Sam Gentle
c0aac8e598 use helpers.isCoffee in test runner 2013-05-26 00:04:18 +10:00
Sam Gentle
d46a44ac48 Patch node module loader to handle multiple extensions - fixes #2928 & #2855 2013-05-25 23:22:27 +10:00
Sam Gentle
9b1bdd4b36 Add test for .coffee.md loading 2013-05-25 23:06:44 +10:00
Michal Srb
fd47920c63 Fixes tabbed code test in literate 2013-05-15 10:30:20 +01:00
Michael Ficarra
088b8b3ec5 Merge pull request #2978 from pushrax/master
Fix 'propeties' typo in docs
2013-05-08 17:44:53 -07:00
Justin Li
afd9b44dea Fix 'propeties' typo in docs 2013-05-08 15:57:46 -04:00
In-Ho Yi
b54db2ea07 keep track of source map information for require()d coffee files 2013-04-29 17:06:22 +10:00
Michael Ficarra
3650d6eb4e Merge pull request #2933 from marchaefner/master
Fix implicit calls with preceding herecomment
2013-04-28 21:07:52 -07:00
Marc Häfner
05b74f3743 Merge remote-tracking branch 'refs/remotes/upstream/master' 2013-04-29 05:27:13 +02:00
Michael Ficarra
174cd7eaa0 rebuild for some unneccessary parentheses changes
rebuild of 3921e3db34
2013-04-28 22:09:46 -05:00
Nami-Doc
3921e3db34 Merge pull request #2965 from Nami-Doc/style-cleanup1
Style cleanup
2013-04-28 16:20:53 -07:00
Nami-Doc
63bc7fe354 final style edits 2013-04-29 01:19:24 +02:00
Nami-Doc
ba01e36cc2 partly revert 7be996c 2013-04-28 22:34:56 +02:00
Marc Häfner
40d2761bd8 Fixes #2916 -- implicit calls with preceding herecomment 2013-04-28 10:30:03 +02:00
Nami-Doc
4ff7fef3bb remove jsl config file and the doc line about it 2013-04-28 00:58:34 +02:00
Nami-Doc
7be996c010 code cleanup 2013-04-28 00:56:44 +02:00
Michael Ficarra
f4332475b5 Merge pull request #2963 from Nami-Doc/lint-flag-removal
Lint flag removal
2013-04-27 15:13:38 -07:00
Nami-Doc
4da00e8296 Fix docs : modify source file instead of built file 2013-04-27 20:55:37 +02:00
Nami-Doc
e8fae286be remove --lint. #2894 : rebuild and fix docs 2013-04-27 19:35:32 +02:00
Nami-Doc
f451bb5f61 Merge pull request #2894 from billymoon/master
Literate flag
2013-04-27 10:29:03 -07:00
Billy Moon
d8d7495767 give the -l flag to literate
remove `-l` from lint, allowing it to be used for literate
2013-04-27 10:42:10 +03:00
Michael Ficarra
4b4f6ac222 Merge pull request #2951 from xixixao/issue1437
Fix #1437. Unneeded ref in existential assignment.
2013-04-22 13:04:32 -07:00
Michal Srb
7b9699c5fa Fix #1437. Unneeded ref in existential assignment. 2013-04-22 21:58:49 +02:00
Jeremy Ashkenas
8a59558e2d Merge pull request #2946 from Nami-Doc/issue2944
Fix #2944
2013-04-21 08:15:15 -07:00
Nami-Doc
5162472f16 Fix REPL when env.HOME isn't available - #2945 2013-04-21 16:03:30 +02:00
Nami-Doc
1917bb69ed Fix #2944 2013-04-21 12:33:00 +02:00
Michael Ficarra
3b38153759 Merge pull request #2940 from jiangmiao/issue2908
Fixes #2908, add "\n" between pure literal header and function body.
2013-04-20 12:03:25 -07:00
Michael Ficarra
e06a17d929 Merge pull request #2943 from bobbydavid/master
fix warning in REPL tests about memory leak.
2013-04-20 12:00:37 -07:00
Robert Martin
71aea4b862 Fix bug in REPL where history file was closed late.
The history file was set to close on process exit, when it
should close on REPL exit. Listening to the process exit
event causes a warning when more than 10 CoffeeScript REPL
instances are opened in the same program, which happens in
the test.
2013-04-20 14:49:54 -04:00
Nami-Doc
4b4818d819 Fix missing ` `` - #2926 2013-04-20 00:11:29 +02:00
Michael Ficarra
c785e00a15 Merge pull request #2929 from lucasb-eyer/master
Keep a single-line herecomment as a single-line js comment.
2013-04-15 13:12:43 -07:00
Michael Ficarra
c6398e16b1 Merge pull request #2925 from marchaefner/master
Fix error reporting for invalid object key.
2013-04-15 13:07:16 -07:00
lucasb-eyer
ccc7c4404d Keep the js comment on a single line if the herecomment is on a single line. 2013-04-15 21:45:55 +02:00
Marc Häfner
69d66a1d4d Fixes #1057: Allow catch/finally in single line functions.
* Don't end single-line functions at `catch` or `finally`.
* Remove unused `IMPLICIT_BLOCK` and superfluous test for `IF`.
2013-04-15 20:20:52 +02:00
Marc Häfner
af81f6de70 Fix error reporting for invalid object key. 2013-04-12 18:10:26 +02:00
Jeremy Ashkenas
f21dc7a96e Merge pull request #2924 from marchaefner/master
Parameter-less catch clause.
2013-04-12 08:57:01 -07:00
Marc Häfner
cf07fcb4b1 #2900 -- parameter-less catch clause.
Plus some minor cleanup after f8c6b494aa
2013-04-12 17:50:45 +02:00
Jeremy Ashkenas
740a7bcb45 Merge pull request #2914 from danielgtaylor/repl-history
repl history implementation improvements
2013-04-07 21:47:16 -07:00
Daniel G. Taylor
0e2d2ea637 Move lastLine setter into conditional block to prevent .commands and blank lines from setting lastLine 2013-04-07 11:28:59 -07:00
Daniel G. Taylor
feaea49eac Replace large comprehension with much simpler code; fix comment to reference maxSize instead of previous 10KB limit; only pop a history entry if the file size is actually bigger than maxSize; only add items to the history if they are different from the last item by storing the last line and loading it on startup. 2013-04-06 22:10:08 -07:00
Jeremy Ashkenas
170f311101 Merge branch 'master' of https://github.com/jashkenas/coffee-script 2013-04-06 09:31:30 +08:00
Jeremy Ashkenas
0cadcdc097 Fix regression with executable class bodies and prototypal attachment. 2013-04-06 09:31:24 +08:00
Miao Jiang
337ebd3ce9 Fixes #2908, add "\n" between pure literal header and function body. 2013-04-05 13:20:59 +08:00
Billy Moon
5d5920c5d0 Literate flag
Add `-L` or `--literate` command line flags (lowercase `l` is already taken) to allow literate coffee script to be read in from `stdio`
2013-03-28 10:28:12 +03:00
Jeremy Ashkenas
8be65dee93 Merge pull request #2886 from danielgtaylor/repl-history
Add history to the coffee interactive interpreter that persists between ...
2013-03-27 15:55:15 -07:00
Daniel G. Taylor
4dbd9dc264 Pop off partial line if input history file was truncated; make maximum input history file size configurable via repl start options 2013-03-25 20:50:56 -07:00
Daniel G. Taylor
2d0e45c46d Use string interpolation for .history command; rename out variable to history an store the history in it as an array in the proper order so that printing it is just a join operation 2013-03-25 20:34:04 -07:00
Michael Ficarra
cc84d6ea67 Merge pull request #2890 from Nami-Doc/issue2846
fix #2846
2013-03-25 11:14:07 -07:00
Nami-Doc
53a5f26430 fix #2846 2013-03-25 18:56:24 +01:00
Daniel G. Taylor
a1ff4ae7b8 Use separate variable for fd used to read history file; use string interpolation to print code lines; do not use unit test to remove temporary file and instead use a process exit event handler 2013-03-25 09:49:59 -07:00
Daniel G. Taylor
3251efa9c6 Add unit test to read and run a line from the interpreter history file and remove the dummy history file after tests have completed. 2013-03-25 08:47:34 -07:00
Daniel G. Taylor
17a1cdb2cf Make history file optional and configurable via the opts passed to repl.start 2013-03-25 08:46:40 -07:00
Daniel G. Taylor
1643f7df7a Remove explicit catch that did nothing 2013-03-25 07:49:25 -07:00
Daniel G. Taylor
3c0344b954 Rebuild to remove debugging log statement 2013-03-25 07:28:55 -07:00
Daniel G. Taylor
9bfafb88cb Add history to the coffee interactive interpreter that persists between sessions using a ~/.coffee_history file in a similar way to bash. Code based on repl.history and Node pull request 3178 with modifications. 2013-03-24 22:44:35 -07:00
Michael Ficarra
718224f99a Merge pull request #2867 from hden/2853
encode unicode src, test added
2013-03-24 12:17:10 -07:00
Hao-kang Den
b2d6997eff encode unicode src, test added 2013-03-21 09:04:23 +08:00
Michael Ficarra
e26f982c24 Merge pull request #2869 from marchaefner/master
Fix Windows path separator issue in `baseFileName`.
2013-03-20 17:25:54 -07:00
Marc Häfner
1b2fe69a18 Fix Windows path separator issue in baseFileName.
Windows accepts forward and backward slashes as path separator.
2013-03-20 22:38:29 +01:00
Jeremy Ashkenas
c159a64b58 Merge pull request #2865 from hden/inline
quick-fix
2013-03-20 00:46:32 -07:00
Hao-kang Den
e091c9d6b4 quick-fix with a different approach 2013-03-20 15:23:33 +08:00
Jeremy Ashkenas
57d3cfd67f Merge pull request #2851 from toots/master
More explicit window context.
2013-03-18 18:52:31 -07:00
Romain Beauxis
6dd61626d2 Rebuild. 2013-03-18 14:16:05 -05:00
Romain Beauxis
1e99f887e7 More explicit window context in src/browser.coffee. 2013-03-18 11:16:26 -05:00
Jeremy Ashkenas
78d10f30a0 removing sourceColumn reset 2013-03-18 21:50:40 +08:00
Jeremy Ashkenas
7f0610d0bd better docs for source maps 2013-03-18 19:46:43 +08:00
Jeremy Ashkenas
4bef435e0e better docs for source maps 2013-03-18 19:46:30 +08:00
Jeremy Ashkenas
194baa0bd7 better docs for source maps 2013-03-18 19:46:19 +08:00
Jeremy Ashkenas
c8b8beb500 slimming SourceMap slightly further 2013-03-18 19:36:34 +08:00
Jeremy Ashkenas
6786bab2ba Big refactor of SourceMap class. Literate CoffeeScript. Purdy. 2013-03-18 19:23:05 +08:00
Jeremy Ashkenas
566a7dabb2 Fixing erroneous whitespace fix in generated JS 2013-03-18 17:47:55 +08:00
Jeremy Ashkenas
a3e8de338a CoffeeScript 1.6.2 2013-03-18 13:06:33 +08:00
Jeremy Ashkenas
4f815ea978 Fixes #2737, fix fork() for both .js and .coffee, revised. 2013-03-18 11:46:54 +08:00
Michael Ficarra
417008a030 be a little more descriptive, as per @epidemian's suggestion 2013-03-17 21:53:46 -05:00
Michael Ficarra
84c44c0099 small stylistic change and optimisation to code from #2847 2013-03-17 21:50:20 -05:00
Jeremy Ashkenas
2d6a856d61 Merge pull request #2847 from hden/browser-source-map
Browser source map
2013-03-17 19:39:36 -07:00
Hao-kang Den
011d7dc245 better naming by @michaelficarra 2013-03-18 10:23:33 +08:00
Hao-kang Den
b2aa1798b1 safer browser check 2013-03-18 09:31:12 +08:00
Hao-kang Den
5fb047930e fixed lineno 2013-03-18 09:31:12 +08:00
Hao-kang Den
c24e957f17 use btoa as base64 encoder, inspired by @ashtuchkin 2013-03-18 09:31:12 +08:00
Jeremy Ashkenas
fd0b1ffc4d Fixes #2478 -- mention js2coffee in docs 2013-03-17 19:34:00 +08:00
Jeremy Ashkenas
0bfe6394a4 whitespace 2013-03-17 19:31:06 +08:00
Jeremy Ashkenas
9d025df9e3 Merge pull request #2827 from hden/lineno
Lineno
2013-03-17 04:29:44 -07:00
Jeremy Ashkenas
2f5b11b295 Fixes #2555 2013-03-17 19:27:16 +08:00
Jeremy Ashkenas
c44826acc7 Merge pull request #2838 from marchaefner/master
Improve literal mode.
2013-03-17 03:49:06 -07:00
Jeremy Ashkenas
4386f2abc7 Merge pull request #2840 from MattKunze/windows_paths
fix path handling on Windows
2013-03-17 03:09:28 -07:00
Matt Kunze
f217a10721 fix path handling on Windows 2013-03-15 16:13:04 -06:00
Marc Häfner
b8d695a4e1 Compiled JavaScript files for improved literal mode. 2013-03-15 03:26:12 +01:00
Marc Häfner
44c2b4aa7f Test case for literal mode: Code blocks must be preceded by blank line. 2013-03-15 03:23:09 +01:00
Marc Häfner
52ca531b7c Improve literate mode.
* Expect a blank line as delimiter between text and code (#2821).
* Don't change indentation of code. It is not necessary and leads to
  erroneous locationData. (#2835)
* Don't modify blank lines and reverse the change in the lexer.
* Don't ignore indentation with mixed whitespace.
2013-03-15 00:17:10 +01:00
Hao-kang Den
d4254a40a9 Apply modifications by @jwalton 2013-03-14 08:36:07 +08:00
Hao-kang Den
052e3cc8eb found a linear shift of lineno, dirty patch for now
It seems that js -> coffee line mapping has a linear shifting.
Dirty patch by applying linear correction.
Dumb, but maybe a hint.
2013-03-14 08:36:07 +08:00
Jeremy Ashkenas
56413ba3b4 Merge pull request #2817 from epidemian/keep-repl-running
Keep REPL running on runtime errors
2013-03-13 01:56:33 -07:00
Jeremy Ashkenas
71bb6108fb Merge pull request #2819 from hden/fix-path
Quick fix for node v0.10 path
2013-03-13 01:03:57 -07:00
Hao-kang Den
7d08dbb86c build 2013-03-13 16:00:57 +08:00
Hao-kang Den
a8b65565dd roll back to options.filename 2013-03-13 15:58:39 +08:00
Jeremy Ashkenas
54258e441d Merge pull request #2826 from epidemian/bump-engines-node
Bump engines.node version on package.json to 0.8
2013-03-13 00:40:56 -07:00
Michael Ficarra
4ac223b684 minor cleanup of parent commit 2013-03-12 21:11:48 -05:00
Michael Ficarra
707655daef Merge pull request #2824 from iamwilhelm/master
added warning that repl needs node.js >= 0.8
2013-03-12 18:46:19 -07:00
Wil Chung
70e83030a7 added warning that we need node 0.8+ to run repl
remove unnecessary parens and else statement in repl

we do this by convention of the main coffee source

fix: exit should be process.exit

compiled and build full
2013-03-12 18:28:48 -07:00
Demian Ferreiro
9787ce543d Bump engines.node version on package.json to 0.8 2013-03-12 21:46:48 -03:00
Hao-kang Den
22595424a8 manually add the newline at EOF 2013-03-12 21:28:48 +08:00
Hao-kang Den
601189ea2d Merge branch 'fix-path' of https://github.com/hden/coffee-script into fix-path 2013-03-12 20:54:12 +08:00
Hao-kang Den
d3263dc35b fix node v0.10 path 2013-03-12 20:53:13 +08:00
Jeremy Ashkenas
e1c6b083f8 Merge pull request #2820 from hden/source-maps-in-node
Source maps in node
2013-03-12 05:35:39 -07:00
Michael Ficarra
f56f5f234e @epidemian typo 2013-03-12 15:32:52 +08:00
Demian Ferreiro
4ca6da4a95 Add REPL scoping tests 2013-03-12 15:32:52 +08:00
Demian Ferreiro
b0cbd90e64 Fixes #1829. Preserve variable scope in the REPL 2013-03-12 15:32:52 +08:00
Hao-kang Den
9b6772a390 accept override 2013-03-12 15:29:13 +08:00
Hao-kang Den
b7f0653a0e port patchStackTrace from Redux 2013-03-12 15:29:13 +08:00
Demian Ferreiro
45bcd9fa2f Keep REPL running on runtime errors 2013-03-11 23:58:00 -03:00
Michael Ficarra
20d98c7106 @epidemian typo 2013-03-11 21:48:21 -05:00
Michael Ficarra
5ec658c55d Merge remote-tracking branch 'epidemian/issue1829' 2013-03-11 21:47:19 -05:00
Hao-kang Den
64301d0d08 fix node v0.10 path 2013-03-12 09:09:07 +08:00
Demian Ferreiro
119ec16e5e Add REPL scoping tests 2013-03-11 20:16:48 -03:00
Jeremy Ashkenas
decc0f18fc Merge pull request #2814 from epidemian/issue1829
Fixes #1829. Preserve variable scope in the REPL
2013-03-11 16:15:34 -07:00
Demian Ferreiro
5a004425ca Fixes #1829. Preserve variable scope in the REPL 2013-03-11 19:52:18 -03:00
Jeremy Ashkenas
69f6500ba9 rebuilt source code documentation with new version of Docco. 2013-03-11 11:37:22 +08:00
Jeremy Ashkenas
97980ffc7f Merge pull request #2723 from epidemian/improved-error-messages
Improved error messages
2013-03-10 16:46:25 -07:00
Demian Ferreiro
f0fcf4aee0 Merge branch 'master' of git://github.com/jashkenas/coffee-script into improved-error-messages
Conflicts:
	lib/coffee-script/coffee-script.js
	lib/coffee-script/command.js
	lib/coffee-script/helpers.js
	lib/coffee-script/lexer.js
	lib/coffee-script/nodes.js
	lib/coffee-script/repl.js
	src/coffee-script.coffee
	src/command.coffee
	src/helpers.coffee
	src/lexer.coffee
	src/nodes.coffee
	test/helpers.coffee
2013-03-10 20:29:36 -03:00
Michael Ficarra
838e5e1163 Merge pull request #2810 from SonicHedgehog/master
Fix typo in documentation
2013-03-10 11:58:01 -07:00
Jakob Krigovsky
af0bdae675 Fix typo in documentation 2013-03-10 19:09:03 +01:00
Jeremy Ashkenas
0d45287057 Fixes #2808. Remove --require flag. 2013-03-10 17:17:04 +08:00
Demian Ferreiro
09f8df9640 Add check for end of input on parseError handler 2013-03-10 00:30:27 -03:00
Jeremy Ashkenas
dbb99f31a7 Reverting #2490 2013-03-10 07:21:00 +08:00
Jeremy Ashkenas
c7da623d4b #2490. A bit more of the style. 2013-03-10 06:55:52 +08:00
Jeremy Ashkenas
b44435ab8a #2490 -- implementing a conditional in terms of the guard style. 2013-03-10 06:44:45 +08:00
Jeremy Ashkenas
c53df12ec1 disallow multiple else blocks in if/guard syntax 2013-03-09 15:44:45 +08:00
Jeremy Ashkenas
13fae12f69 Fixes #2490 -- adding guard-style if blocks 2013-03-09 10:40:37 +08:00
Jeremy Ashkenas
0120db0efc Merge pull request #2803 from benbria/master
Rework source map files and paths
2013-03-08 07:19:48 -08:00
Jason Walton
c4f50b52d7 Merge remote-tracking branch 'upstream/master'
Conflicts:
	lib/coffee-script/helpers.js
	test/helpers.coffee
2013-03-08 10:17:47 -05:00
Jason Walton
242f397bfa Remove dead variables. 2013-03-07 21:30:04 -05:00
Jason Walton
f85d19b459 Rework API for sourcemap filenames and paths. 2013-03-07 21:26:09 -05:00
Jeremy Ashkenas
8f7f3627e0 Fixes #2796, by adding a test for it. 2013-03-07 23:13:22 +13:00
Jeremy Ashkenas
8b134cf348 Add an additonal test, courtesy @matehat 2013-03-07 23:10:39 +13:00
Jeremy Ashkenas
67de35ff29 Fixes #2781, fixes #2782. Reverting to old method of instance method binding. 2013-03-07 23:09:32 +13:00
Jeremy Ashkenas
774ee6a554 merge 2013-03-07 22:59:23 +13:00
Jeremy Ashkenas
4be4ea3623 Merge pull request #2795 from fahad19/master
Fix: compiling `coffee.coffee` produces `.js` file.
2013-03-07 01:30:07 -08:00
Fahad Ibnay Heylaal
18fec7e202 tests for baseFileName helper for files with only coffee-script extensions as the file name. 2013-03-07 10:23:36 +06:00
Fahad Ibnay Heylaal
072df5ecc9 more test coverage for baseFileName helper. 2013-03-07 10:15:01 +06:00
Fahad Ibnay Heylaal
4d7151aa5d fix: compiling coffee.coffee produces .js file. 2013-03-07 03:41:34 +06:00
Jason Walton
185b2ce632 Code inspect fixes from the inimitable Nami-Doc 2013-03-06 16:26:34 -05:00
Jason Walton
ce6772f2be Better fix for sourceRoot and relative path for .coffee files in source maps. 2013-03-06 15:45:47 -05:00
Jason Walton
d6e1a979e4 Fix sourceRoot and relative path for .coffee files in generated source maps. 2013-03-06 11:05:57 -05:00
Jeremy Ashkenas
de8ec2beb0 Fixes #1066 -- interpolated strings are not implicit funcs 2013-03-05 21:28:29 +13:00
Demian Ferreiro
342a796cc0 Remove column number from online editor error box 2013-03-05 05:16:29 -03:00
Jeremy Ashkenas
355754ed20 Fixes #1055 -- disallow invalid keys in object literals ... but allow them where the implicit object is being used as a class defn' or a destructuring 2013-03-05 21:10:56 +13:00
Jeremy Ashkenas
fbe07f1fce Removing debugging source location output from --nodes. It shouldn't have snuck in there. 2013-03-05 20:50:03 +13:00
Jeremy Ashkenas
304432c197 Merge pull request #2417 from gabehollombe/doc_for_switch_with_no_control_expression
Documentation for switch statements with no control expression
2013-03-04 22:27:38 -08:00
Demian Ferreiro
5da7f6a488 Get rid of CompilationError and instead have a couple of functions on helpers.coffee 2013-03-05 01:13:46 -03:00
Jeremy Ashkenas
f8c6b494aa Fixes #2422 -- Catch clause scoping plus old IE 2013-03-05 16:13:22 +13:00
Jeremy Ashkenas
1b573412d3 cleaning up the previous merge -- moving it out to helpers.invertLiterate 2013-03-05 15:45:57 +13:00
Demian Ferreiro
b400047045 Merge branch 'master' of git://github.com/jashkenas/coffee-script into improved-error-messages
Conflicts:
	Cakefile
	lib/coffee-script/coffee-script.js
	lib/coffee-script/command.js
	lib/coffee-script/nodes.js
	lib/coffee-script/repl.js
	src/coffee-script.coffee
	src/helpers.coffee
	src/nodes.coffee
	src/repl.coffee
2013-03-04 23:42:47 -03:00
Jeremy Ashkenas
51b1affbc5 Merge pull request #2776 from mintplant/fix-2768
Fix #2768: support --join'ing mixed literate and non-literate CoffeeScript source files
2013-03-04 18:39:30 -08:00
Jeremy Ashkenas
903e9c994c Fixes #2773 -- tricky dependency ordering when overriding bound functions. 2013-03-05 15:35:02 +13:00
Michael Smith
fca68717ff Fix #2768: rewrite literate code before the join 2013-03-04 18:30:24 -08:00
Michael Ficarra
22d6a4b255 Merge pull request #2770 from benbria/master
Move sourceMappingURL to bottom of generated JavaScript file.
2013-03-04 17:45:16 -08:00
Jeremy Ashkenas
26102a0970 Merge pull request #2772 from marchaefner/master
Minor improvements for locationData of tokens and some clean up.
2013-03-04 17:43:09 -08:00
Jason Walton
add84bfddc Add multiline horrible kludge for IE 2013-03-04 19:08:33 -05:00
Marc Häfner
dcd74d3e59 Clean up unused parameter. 2013-03-05 01:02:16 +01:00
Jason Walton
2684737b66 Move sourceMappingURL line to bottom of file 2013-03-04 18:43:49 -05:00
Marc Häfner
74181c0ec0 Improve locationData of implicit object braces.
Set location of generated left brace to start of content, so the corresponding AST nodes don't span preceding spaces, blank lines or comments.
2013-03-05 00:12:51 +01:00
Marc Häfner
ebff9fbc31 Exclude preceding newlines from INDENT tokens.
Produces more meanignful locationData.
2013-03-05 00:03:08 +01:00
Marc Häfner
97a41adf0c Fix location of tokens with no length
by actually using the computed offset.
2013-03-05 00:01:17 +01:00
Demian Ferreiro
9ea4268b92 Make duplicate param name errors mark the actual duplicate parameter
Before:

    coffee> foo = (bar, baz, bar, qux) ->
    repl:1:7: error: multiple parameters named 'bar'
    foo = (bar, baz, bar, qux) ->
          ^^^^^^^^^^^^^^^^^^^^^^^

Now:

    coffee> foo = (bar, baz, bar, qux) ->
    repl:1:18: error: multiple parameters named 'bar'
    foo = (bar, baz, bar, qux) ->
                     ^^^

Also works with destructuring parameters and what have you.
2013-03-04 15:39:03 -03:00
Demian Ferreiro
589d67d8b7 Remove a couple of TODOs (WONTDOs really) 2013-03-04 13:11:34 -03:00
Demian Ferreiro
3127e76f4b Integrate error messages on the site editor
Nothing really fancy here; mostly preserves the old format. Maybe if we had a more full-fledged test editor we could show the errors in-line =D

  Also, i couldn't get the `rake doc` task running properly, so i mostly test this editing the index.html directly (ups!).
2013-03-04 13:00:25 -03:00
Demian Ferreiro
0affb4f936 Integrate error messages on the REPL 2013-03-03 22:08:41 -03:00
Demian Ferreiro
55c99dfaec Show colorized error messages 2013-03-01 22:42:26 -03:00
Michael Smith
c98fae59fc Patch child_process.fork to run .coffee files 2013-03-01 16:19:05 -08:00
Demian Ferreiro
3182475207 Make error messages show only first line on multi-line errors 2013-03-01 13:10:04 -03:00
Demian Ferreiro
5115fcb162 Add CompilationError.fromLocationData 2013-02-26 23:03:33 -03:00
Demian Ferreiro
1db89d1589 Optimized repeat and its tests 2013-02-26 14:41:01 -03:00
Demian Ferreiro
fbc8417263 Fix failing parser error message test 2013-02-26 05:55:09 -03:00
Demian Ferreiro
44e3a76881 Add some error formatting tests
Thanks to them i discovered that the parser errors where indicating the wrong token ¬¬
2013-02-26 01:30:23 -03:00
Demian Ferreiro
f2efada0d4 Improved compiler error messages 2013-02-25 23:37:30 -03:00
Demian Ferreiro
5f00d6478a Remove redundant filename in error message 2013-02-25 19:20:37 -03:00
Demian Ferreiro
7e5f1b14a3 Pass 0-based indexes to CompilerError 2013-02-25 15:12:25 -03:00
Demian Ferreiro
caacd892cc Improved parser error messages 2013-02-25 15:09:42 -03:00
Demian Ferreiro
25091fb2a0 Improved lexer error messages 2013-02-25 14:41:34 -03:00
Gabe Hollombe
334dcbd162 Updated example using @epidemian's suggestion 2012-10-16 16:41:14 +11:00
Gabe Hollombe
7065538224 add documentation for using switch without a control expression 2012-07-04 11:57:20 +07:00
Gabe Hollombe
7fdd21b26d Add example of destructuring assignment in class constructors for options 2012-06-10 11:19:54 +07:00
Stephen Bannasch
deae3e53f5 rake task creates/installs coffeescript.syntax
The ultraviolet gem doesn't work with Ruby 1.9, instead
we need to use the updated 'spox' versions of ultraviolet
and plist:

  spox-ultraviolet, spox-plist

This new rake task: install_coffeescript_syntax loads
either the original gems if running Ruby < 1.9 or the
'spox' versions if running on Ruby >= 1.9.

Load CoffeeScript.tmLanguage directly from the github repo
for the TextMate bundle.

Parse and write the yaml-format syntax file directly
into the correct location in the ultraviolet gem.
2012-01-31 17:15:46 -05:00
126 changed files with 9354 additions and 7770 deletions

View File

@@ -85,20 +85,15 @@ task 'build:parser', 'rebuild the Jison parser (run build first)', ->
fs.writeFile 'lib/coffee-script/parser.js', parser.generate()
task 'build:ultraviolet', 'build and install the Ultraviolet syntax highlighter', ->
exec 'plist2syntax ../coffee-script-tmbundle/Syntaxes/CoffeeScript.tmLanguage', (err) ->
throw err if err
exec 'sudo mv coffeescript.yaml /usr/local/lib/ruby/gems/1.8/gems/ultraviolet-0.10.2/syntax/coffeescript.syntax'
task 'build:browser', 'rebuild the merged script for inclusion in the browser', ->
code = ''
for name in ['helpers', 'rewriter', 'lexer', 'parser', 'scope', 'nodes', 'sourcemap', 'coffee-script', 'browser']
code += """
require['./#{name}'] = new function() {
var exports = this;
require['./#{name}'] = (function() {
var exports = {}, module = {exports: exports};
#{fs.readFileSync "lib/coffee-script/#{name}.js"}
};
return module.exports;
})();
"""
code = """
(function(root) {
@@ -211,20 +206,15 @@ runTests = (CoffeeScript) ->
log "failed #{failures.length} and #{message}", red
for fail in failures
{error, filename, description, source} = fail
jsFilename = filename.replace(/\.coffee$/,'.js')
match = error.stack?.match(new RegExp(fail.file+":(\\d+):(\\d+)"))
match = error.stack?.match(/on line (\d+):/) unless match
[match, line, col] = match if match
console.log ''
log " #{description}", red if description
log " #{error.stack}", red
log " #{jsFilename}: line #{line ? 'unknown'}, column #{col ? 'unknown'}", red
console.log " #{source}" if source
return
# Run every test in the `test` folder, recording failures.
files = fs.readdirSync 'test'
for file in files when file.match /\.(lit)?coffee$/i
for file in files when helpers.isCoffee file
literate = helpers.isLiterate file
currentFile = filename = path.join 'test', file
code = fs.readFileSync filename

View File

@@ -1,4 +1,4 @@
Copyright (c) 2009-2012 Jeremy Ashkenas
Copyright (c) 2009-2013 Jeremy Ashkenas
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@@ -19,4 +19,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,5 +1,5 @@
###
CoffeeScript Compiler v1.6.1
SkinnyMochaHalfCaffScript Compiler v1.0
Released under the MIT License
###

View File

@@ -0,0 +1,4 @@
class Person
constructor: (options) ->
{@name, @age, @height} = options

View File

@@ -0,0 +1,8 @@
score = 76
grade = switch
when score < 60 then 'F'
when score < 70 then 'D'
when score < 80 then 'C'
when score < 90 then 'B'
else 'A'
# grade == 'C'

View File

@@ -85,7 +85,7 @@
<a class="source" href="sourcemap.html">
sourcemap.coffee
sourcemap.litcoffee
</a>
</div>
@@ -108,15 +108,18 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
</div>
<p>Override exported methods for non-Node.js engines.
<p>This <strong>Browser</strong> compatibility layer extends core CoffeeScript functions
to make things work smoothly when compiling code directly in the browser.
We add support for loading remote Coffee scripts via <strong>XHR</strong>, and
<code>text/coffeescript</code> script tags, source maps via data-URLs, and so on.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">&#39;./coffee-script&#39;</span>
<span class="nv">CoffeeScript.require = </span><span class="nx">require</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
CoffeeScript = require <span class="string">'./coffee-script'</span>
CoffeeScript.require = require
compile = CoffeeScript.compile</pre></div></div>
</li>
@@ -127,16 +130,14 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>Use standard JavaScript <code>eval</code> to eval code.
<p>Use standard JavaScript <code>eval</code> to eval code.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">CoffeeScript.eval = </span><span class="nf">(code, options = {}) -&gt;</span>
<span class="nx">options</span><span class="p">.</span><span class="nx">bare</span> <span class="o">?=</span> <span class="kc">on</span>
<span class="nb">eval</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span></pre></div></div>
<div class="content"><div class='highlight'><pre>CoffeeScript.<span class="function"><span class="title">eval</span></span> = (code, options = {}) -&gt;
options.bare ?= <span class="literal">on</span>
eval compile code, options</pre></div></div>
</li>
@@ -147,16 +148,15 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>Running code does not provide access to this scope.
<p>Running code does not provide access to this scope.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">CoffeeScript.run = </span><span class="nf">(code, options = {}) -&gt;</span>
<span class="nv">options.bare = </span><span class="kc">on</span>
<span class="nb">Function</span><span class="p">(</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)()</span></pre></div></div>
<div class="content"><div class='highlight'><pre>CoffeeScript.<span class="function"><span class="title">run</span></span> = (code, options = {}) -&gt;
options.bare = <span class="literal">on</span>
options.shiftLine = <span class="literal">on</span>
Function(compile code, options)()</pre></div></div>
</li>
@@ -167,14 +167,12 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>If we&#39;re not in a browser environment, we&#39;re finished with the public API.
<p>If we&#39;re not in a browser environment, we&#39;re finished with the public API.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="k">return</span> <span class="k">unless</span> <span class="nb">window</span><span class="o">?</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="keyword">return</span> <span class="keyword">unless</span> window?</pre></div></div>
</li>
@@ -185,28 +183,19 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>Load a remote script from the current domain via XHR.
<p>Include source maps where possible. If we&#39;ve got a base64 encoder, a
JSON serializer, and tools for escaping unicode characters, we&#39;re good to go.
Ported from <a href="https://developer.mozilla.org/en-US/docs/DOM/window.btoa">https://developer.mozilla.org/en-US/docs/DOM/window.btoa</a>
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">CoffeeScript.load = </span><span class="nf">(url, callback, options = {}) -&gt;</span>
<span class="nv">xhr = </span><span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span>
<span class="k">new</span> <span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span><span class="p">(</span><span class="s">&#39;Microsoft.XMLHTTP&#39;</span><span class="p">)</span>
<span class="k">else</span>
<span class="k">new</span> <span class="nx">XMLHttpRequest</span><span class="p">()</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span> <span class="s">&#39;GET&#39;</span><span class="p">,</span> <span class="nx">url</span><span class="p">,</span> <span class="kc">true</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">overrideMimeType</span> <span class="s">&#39;text/plain&#39;</span> <span class="k">if</span> <span class="s">&#39;overrideMimeType&#39;</span> <span class="k">of</span> <span class="nx">xhr</span>
<span class="nv">xhr.onreadystatechange = </span><span class="nf">-&gt;</span>
<span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">is</span> <span class="mi">4</span>
<span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">status</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">200</span><span class="p">]</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span><span class="p">,</span> <span class="nx">options</span>
<span class="k">else</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;Could not load </span><span class="si">#{</span><span class="nx">url</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">callback</span><span class="p">()</span> <span class="k">if</span> <span class="nx">callback</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">send</span> <span class="kc">null</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="keyword">if</span> btoa? <span class="keyword">and</span> JSON? <span class="keyword">and</span> unescape? <span class="keyword">and</span> encodeURIComponent?
<span class="function"><span class="title">compile</span></span> = (code, options = {}) -&gt;
options.sourceMap = <span class="literal">true</span>
options.inline = <span class="literal">true</span>
{js, v3SourceMap} = CoffeeScript.compile code, options
<span class="string">"<span class="subst">#{js}</span>\n//@ sourceMappingURL=data:application/json;base64,<span class="subst">#{btoa unescape encodeURIComponent v3SourceMap}</span>\n//@ sourceURL=coffeescript"</span></pre></div></div>
</li>
@@ -217,32 +206,27 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>Activate CoffeeScript in the browser by having it compile and evaluate
all script tags with a content-type of <code>text/coffeescript</code>.
This happens on page load.
<p>Load a remote script from the current domain via XHR.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">runScripts = </span><span class="nf">-&gt;</span>
<span class="nv">scripts = </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span> <span class="s">&#39;script&#39;</span>
<span class="nv">coffeetypes = </span><span class="p">[</span><span class="s">&#39;text/coffeescript&#39;</span><span class="p">,</span> <span class="s">&#39;text/literate-coffeescript&#39;</span><span class="p">]</span>
<span class="nv">coffees = </span><span class="p">(</span><span class="nx">s</span> <span class="k">for</span> <span class="nx">s</span> <span class="k">in</span> <span class="nx">scripts</span> <span class="k">when</span> <span class="nx">s</span><span class="p">.</span><span class="nx">type</span> <span class="k">in</span> <span class="nx">coffeetypes</span><span class="p">)</span>
<span class="nv">index = </span><span class="mi">0</span>
<span class="nv">length = </span><span class="nx">coffees</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">do</span> <span class="nv">execute = </span><span class="nf">-&gt;</span>
<span class="nv">script = </span><span class="nx">coffees</span><span class="p">[</span><span class="nx">index</span><span class="o">++</span><span class="p">]</span>
<span class="nv">mediatype = </span><span class="nx">script</span><span class="o">?</span><span class="p">.</span><span class="nx">type</span>
<span class="k">if</span> <span class="nx">mediatype</span> <span class="k">in</span> <span class="nx">coffeetypes</span>
<span class="nv">options = </span><span class="p">{</span><span class="nv">literate: </span><span class="nx">mediatype</span> <span class="o">is</span> <span class="s">&#39;text/literate-coffeescript&#39;</span><span class="p">}</span>
<span class="k">if</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">load</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span><span class="p">,</span> <span class="nx">execute</span><span class="p">,</span> <span class="nx">options</span>
<span class="k">else</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">script</span><span class="p">.</span><span class="nx">innerHTML</span><span class="p">,</span> <span class="nx">options</span>
<span class="nx">execute</span><span class="p">()</span>
<span class="kc">null</span></pre></div></div>
<div class="content"><div class='highlight'><pre>CoffeeScript.<span class="function"><span class="title">load</span></span> = (url, callback, options = {}) -&gt;
options.sourceFiles = [url]
xhr = <span class="keyword">if</span> window.ActiveXObject
<span class="keyword">new</span> window.ActiveXObject(<span class="string">'Microsoft.XMLHTTP'</span>)
<span class="keyword">else</span>
<span class="keyword">new</span> window.XMLHttpRequest()
xhr.open <span class="string">'GET'</span>, url, <span class="literal">true</span>
xhr.overrideMimeType <span class="string">'text/plain'</span> <span class="keyword">if</span> <span class="string">'overrideMimeType'</span> <span class="keyword">of</span> xhr
xhr.<span class="function"><span class="title">onreadystatechange</span></span> = -&gt;
<span class="keyword">if</span> xhr.readyState <span class="keyword">is</span> <span class="number">4</span>
<span class="keyword">if</span> xhr.status <span class="keyword">in</span> [<span class="number">0</span>, <span class="number">200</span>]
CoffeeScript.run xhr.responseText, options
<span class="keyword">else</span>
<span class="keyword">throw</span> <span class="keyword">new</span> Error <span class="string">"Could not load <span class="subst">#{url}</span>"</span>
callback() <span class="keyword">if</span> callback
xhr.send <span class="literal">null</span></pre></div></div>
</li>
@@ -253,18 +237,50 @@ This happens on page load.
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Listen for window load, both in browsers and in IE.
<p>Activate CoffeeScript in the browser by having it compile and evaluate
all script tags with a content-type of <code>text/coffeescript</code>.
This happens on page load.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span>
<span class="nx">addEventListener</span> <span class="s">&#39;DOMContentLoaded&#39;</span><span class="p">,</span> <span class="nx">runScripts</span><span class="p">,</span> <span class="kc">no</span>
<span class="k">else</span>
<span class="nx">attachEvent</span> <span class="s">&#39;onload&#39;</span><span class="p">,</span> <span class="nx">runScripts</span>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">runScripts</span></span> = -&gt;
scripts = window.document.getElementsByTagName <span class="string">'script'</span>
coffeetypes = [<span class="string">'text/coffeescript'</span>, <span class="string">'text/literate-coffeescript'</span>]
coffees = (s <span class="keyword">for</span> s <span class="keyword">in</span> scripts <span class="keyword">when</span> s.type <span class="keyword">in</span> coffeetypes)
index = <span class="number">0</span>
length = coffees.length
<span class="keyword">do</span> <span class="function"><span class="title">execute</span></span> = -&gt;
script = coffees[index++]
mediatype = script?.type
<span class="keyword">if</span> mediatype <span class="keyword">in</span> coffeetypes
options = {literate: mediatype <span class="keyword">is</span> <span class="string">'text/literate-coffeescript'</span>}
<span class="keyword">if</span> script.src
CoffeeScript.load script.src, execute, options
<span class="keyword">else</span>
options.sourceFiles = [<span class="string">'embedded'</span>]
CoffeeScript.run script.innerHTML, options
execute()
<span class="literal">null</span></pre></div></div>
</li>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Listen for window load, both in decent browsers and in IE.
</p>
</pre></div></div>
</div>
<div class="content"><div class='highlight'><pre><span class="keyword">if</span> window.addEventListener
window.addEventListener <span class="string">'DOMContentLoaded'</span>, runScripts, <span class="literal">no</span>
<span class="keyword">else</span>
window.attachEvent <span class="string">'onload'</span>, runScripts</pre></div></div>
</li>

View File

@@ -85,7 +85,7 @@
<a class="source" href="sourcemap.html">
sourcemap.coffee
sourcemap.litcoffee
</a>
</div>
@@ -116,22 +116,10 @@ and can call them from the command line, or invoke them from other tasks.
</p>
<p>Running <code>cake</code> with no arguments will print out a list of all the tasks in the
current directory&#39;s Cakefile.
</p>
<p>External dependencies.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s">&#39;fs&#39;</span>
<span class="nv">path = </span><span class="nx">require</span> <span class="s">&#39;path&#39;</span>
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s">&#39;./helpers&#39;</span>
<span class="nv">optparse = </span><span class="nx">require</span> <span class="s">&#39;./optparse&#39;</span>
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">&#39;./coffee-script&#39;</span>
<span class="nv">existsSync = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">existsSync</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">existsSync</span></pre></div></div>
</li>
@@ -141,17 +129,18 @@ current directory&#39;s Cakefile.
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>Keep track of the list of defined tasks, the accepted options, and so on.
<p>External dependencies.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">tasks = </span><span class="p">{}</span>
<span class="nv">options = </span><span class="p">{}</span>
<span class="nv">switches = </span><span class="p">[]</span>
<span class="nv">oparse = </span><span class="kc">null</span></pre></div></div>
<div class="content"><div class='highlight'><pre>fs = require <span class="string">'fs'</span>
path = require <span class="string">'path'</span>
helpers = require <span class="string">'./helpers'</span>
optparse = require <span class="string">'./optparse'</span>
CoffeeScript = require <span class="string">'./coffee-script'</span>
existsSync = fs.existsSync <span class="keyword">or</span> path.existsSync</pre></div></div>
</li>
@@ -162,14 +151,15 @@ current directory&#39;s Cakefile.
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>Mixin the top-level Cake functions for Cakefiles to use directly.
<p>Keep track of the list of defined tasks, the accepted options, and so on.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">global</span><span class="p">,</span></pre></div></div>
<div class="content"><div class='highlight'><pre>tasks = {}
options = {}
switches = []
oparse = <span class="literal">null</span></pre></div></div>
</li>
@@ -180,17 +170,12 @@ current directory&#39;s Cakefile.
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>Define a Cake task with a short name, an optional sentence description,
and the function to run as the action itself.
<p>Mixin the top-level Cake functions for Cakefiles to use directly.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">task: </span><span class="nf">(name, description, action) -&gt;</span>
<span class="p">[</span><span class="nx">action</span><span class="p">,</span> <span class="nx">description</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">]</span> <span class="k">unless</span> <span class="nx">action</span>
<span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="nx">name</span><span class="p">,</span> <span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">}</span></pre></div></div>
<div class="content"><div class='highlight'><pre>helpers.extend global,</pre></div></div>
</li>
@@ -201,17 +186,15 @@ and the function to run as the action itself.
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>Define an option that the Cakefile accepts. The parsed options hash,
containing all of the command-line options passed, will be made available
as the first argument to the action.
<p>Define a Cake task with a short name, an optional sentence description,
and the function to run as the action itself.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">option: </span><span class="nf">(letter, flag, description) -&gt;</span>
<span class="nx">switches</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="nx">letter</span><span class="p">,</span> <span class="nx">flag</span><span class="p">,</span> <span class="nx">description</span><span class="p">]</span></pre></div></div>
<div class="content"><div class='highlight'><pre> task: (name, description, action) -&gt;
[action, description] = [description, action] <span class="keyword">unless</span> action
tasks[name] = {name, description, action}</pre></div></div>
</li>
@@ -222,16 +205,15 @@ as the first argument to the action.
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>Invoke another task in the current Cakefile.
<p>Define an option that the Cakefile accepts. The parsed options hash,
containing all of the command-line options passed, will be made available
as the first argument to the action.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">invoke: </span><span class="nf">(name) -&gt;</span>
<span class="nx">missingTask</span> <span class="nx">name</span> <span class="k">unless</span> <span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
<span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">].</span><span class="nx">action</span> <span class="nx">options</span></pre></div></div>
<div class="content"><div class='highlight'><pre> option: (letter, flag, description) -&gt;
switches.push [letter, flag, description]</pre></div></div>
</li>
@@ -242,28 +224,14 @@ as the first argument to the action.
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Run <code>cake</code>. Executes all of the tasks you pass, in order. Note that Node&#39;s
asynchrony may cause tasks to execute in a different order than you&#39;d expect.
If no tasks are passed, print the help screen. Keep a reference to the
original directory name, when running Cake tasks from subdirectories.
<p>Invoke another task in the current Cakefile.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.run = </span><span class="nf">-&gt;</span>
<span class="nv">global.__originalDirname = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="s">&#39;.&#39;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">chdir</span> <span class="nx">cakefileDirectory</span> <span class="nx">__originalDirname</span>
<span class="nv">args = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">..]</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="s">&#39;Cakefile&#39;</span><span class="p">).</span><span class="nx">toString</span><span class="p">(),</span> <span class="nv">filename: </span><span class="s">&#39;Cakefile&#39;</span>
<span class="nv">oparse = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">switches</span>
<span class="k">return</span> <span class="nx">printTasks</span><span class="p">()</span> <span class="k">unless</span> <span class="nx">args</span><span class="p">.</span><span class="nx">length</span>
<span class="k">try</span>
<span class="nv">options = </span><span class="nx">oparse</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span>
<span class="k">catch</span> <span class="nx">e</span>
<span class="k">return</span> <span class="nx">fatalError</span> <span class="s">&quot;</span><span class="si">#{</span><span class="nx">e</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">invoke</span> <span class="nx">arg</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span></pre></div></div>
<div class="content"><div class='highlight'><pre> invoke: (name) -&gt;
missingTask name <span class="keyword">unless</span> tasks[name]
tasks[name].action options</pre></div></div>
</li>
@@ -274,23 +242,26 @@ original directory name, when running Cake tasks from subdirectories.
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Display the list of Cake tasks in a format similar to <code>rake -T</code>
<p>Run <code>cake</code>. Executes all of the tasks you pass, in order. Note that Node&#39;s
asynchrony may cause tasks to execute in a different order than you&#39;d expect.
If no tasks are passed, print the help screen. Keep a reference to the
original directory name, when running Cake tasks from subdirectories.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">printTasks = </span><span class="nf">-&gt;</span>
<span class="nv">relative = </span><span class="nx">path</span><span class="p">.</span><span class="nx">relative</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span>
<span class="nv">cakefilePath = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">relative</span><span class="p">(</span><span class="nx">__originalDirname</span><span class="p">,</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()),</span> <span class="s">&#39;Cakefile&#39;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">&quot;</span><span class="si">#{</span><span class="nx">cakefilePath</span><span class="si">}</span><span class="s"> defines the following tasks:\n&quot;</span>
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">task</span> <span class="k">of</span> <span class="nx">tasks</span>
<span class="nv">spaces = </span><span class="mi">20</span> <span class="o">-</span> <span class="nx">name</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s">&#39; &#39;</span><span class="p">)</span> <span class="k">else</span> <span class="s">&#39;&#39;</span>
<span class="nv">desc = </span><span class="k">if</span> <span class="nx">task</span><span class="p">.</span><span class="nx">description</span> <span class="k">then</span> <span class="s">&quot;</span><span class="err">#</span><span class="s"> </span><span class="si">#{</span><span class="nx">task</span><span class="p">.</span><span class="nx">description</span><span class="si">}</span><span class="s">&quot;</span> <span class="k">else</span> <span class="s">&#39;&#39;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">&quot;cake </span><span class="si">#{</span><span class="nx">name</span><span class="si">}#{</span><span class="nx">spaces</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">desc</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">oparse</span><span class="p">.</span><span class="nx">help</span><span class="p">()</span> <span class="k">if</span> <span class="nx">switches</span><span class="p">.</span><span class="nx">length</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">run</span></span> = -&gt;
global.__originalDirname = fs.realpathSync <span class="string">'.'</span>
process.chdir cakefileDirectory __originalDirname
args = process.argv[<span class="number">2.</span>.]
CoffeeScript.run fs.readFileSync(<span class="string">'Cakefile'</span>).toString(), filename: <span class="string">'Cakefile'</span>
oparse = <span class="keyword">new</span> optparse.OptionParser switches
<span class="keyword">return</span> printTasks() <span class="keyword">unless</span> args.length
<span class="keyword">try</span>
options = oparse.parse(args)
<span class="keyword">catch</span> e
<span class="keyword">return</span> fatalError <span class="string">"<span class="subst">#{e}</span>"</span>
invoke arg <span class="keyword">for</span> arg <span class="keyword">in</span> options.arguments</pre></div></div>
</li>
@@ -301,19 +272,21 @@ original directory name, when running Cake tasks from subdirectories.
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>Print an error and exit when attempting to use an invalid task/option.
<p>Display the list of Cake tasks in a format similar to <code>rake -T</code>
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">fatalError = </span><span class="nf">(message) -&gt;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span> <span class="nx">message</span> <span class="o">+</span> <span class="s">&#39;\n&#39;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">&#39;To see a list of all tasks/options, run &quot;cake&quot;&#39;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span>
<span class="nv">missingTask = </span><span class="nf">(task) -&gt;</span> <span class="nx">fatalError</span> <span class="s">&quot;No such task: </span><span class="si">#{</span><span class="nx">task</span><span class="si">}</span><span class="s">&quot;</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">printTasks</span></span> = -&gt;
relative = path.relative <span class="keyword">or</span> path.resolve
cakefilePath = path.join relative(__originalDirname, process.cwd()), <span class="string">'Cakefile'</span>
console.log <span class="string">"<span class="subst">#{cakefilePath}</span> defines the following tasks:\n"</span>
<span class="keyword">for</span> name, task <span class="keyword">of</span> tasks
spaces = <span class="number">20</span> - name.length
spaces = <span class="keyword">if</span> spaces &gt; <span class="number">0</span> <span class="keyword">then</span> Array(spaces + <span class="number">1</span>).join(<span class="string">' '</span>) <span class="keyword">else</span> <span class="string">''</span>
desc = <span class="keyword">if</span> task.description <span class="keyword">then</span> <span class="string">"# <span class="subst">#{task.description}</span>"</span> <span class="keyword">else</span> <span class="string">''</span>
console.log <span class="string">"cake <span class="subst">#{name}</span><span class="subst">#{spaces}</span> <span class="subst">#{desc}</span>"</span>
console.log oparse.help() <span class="keyword">if</span> switches.length</pre></div></div>
</li>
@@ -324,20 +297,38 @@ original directory name, when running Cake tasks from subdirectories.
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>Print an error and exit when attempting to use an invalid task/option.
</p>
</div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">fatalError</span></span> = (message) -&gt;
console.error message + <span class="string">'\n'</span>
console.log <span class="string">'To see a list of all tasks/options, run "cake"'</span>
process.exit <span class="number">1</span>
<span class="function"><span class="title">missingTask</span></span> = (task) -&gt; fatalError <span class="string">"No such task: <span class="subst">#{task}</span>"</span></pre></div></div>
</li>
<li id="section-11">
<div class="annotation">
<p>When <code>cake</code> is invoked, search in the current and all parent directories
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>When <code>cake</code> is invoked, search in the current and all parent directories
to find the relevant Cakefile.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">cakefileDirectory = </span><span class="nf">(dir) -&gt;</span>
<span class="k">return</span> <span class="nx">dir</span> <span class="k">if</span> <span class="nx">existsSync</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="s">&#39;Cakefile&#39;</span>
<span class="nv">parent = </span><span class="nx">path</span><span class="p">.</span><span class="nx">normalize</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="s">&#39;..&#39;</span>
<span class="k">return</span> <span class="nx">cakefileDirectory</span> <span class="nx">parent</span> <span class="k">unless</span> <span class="nx">parent</span> <span class="o">is</span> <span class="nx">dir</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;Cakefile not found in </span><span class="si">#{</span><span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span><span class="si">}</span><span class="s">&quot;</span>
</pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">cakefileDirectory</span></span> = (dir) -&gt;
<span class="keyword">return</span> dir <span class="keyword">if</span> existsSync path.join dir, <span class="string">'Cakefile'</span>
parent = path.normalize path.join dir, <span class="string">'..'</span>
<span class="keyword">return</span> cakefileDirectory parent <span class="keyword">unless</span> parent <span class="keyword">is</span> dir
<span class="keyword">throw</span> <span class="keyword">new</span> Error <span class="string">"Cakefile not found in <span class="subst">#{process.cwd()}</span>"</span></pre></div></div>
</li>

View File

@@ -85,7 +85,7 @@
<a class="source" href="sourcemap.html">
sourcemap.coffee
sourcemap.litcoffee
</a>
</div>
@@ -109,26 +109,22 @@
<a class="pilcrow" href="#section-1">&#182;</a>
</div>
<p>CoffeeScript can be used both on the server, as a command-line compiler based
on Node.js/V8, or to run CoffeeScripts directly in the browser. This module
on Node.js/V8, or to run CoffeeScript directly in the browser. This module
contains the main entry functions for tokenizing, parsing, and compiling
source CoffeeScript into JavaScript.
</p>
<p>If included on a webpage, it will automatically sniff out, compile, and
execute all scripts present in <code>text/coffeescript</code> tags.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s">&#39;fs&#39;</span>
<span class="nv">path = </span><span class="nx">require</span> <span class="s">&#39;path&#39;</span>
<span class="p">{</span><span class="nx">Lexer</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">&#39;./lexer&#39;</span>
<span class="p">{</span><span class="nx">parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">&#39;./parser&#39;</span>
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s">&#39;./helpers&#39;</span>
<span class="nv">vm = </span><span class="nx">require</span> <span class="s">&#39;vm&#39;</span>
<span class="nv">sourcemap = </span><span class="nx">require</span> <span class="s">&#39;./sourcemap&#39;</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
fs = require <span class="string">'fs'</span>
vm = require <span class="string">'vm'</span>
path = require <span class="string">'path'</span>
child_process = require <span class="string">'child_process'</span>
{Lexer} = require <span class="string">'./lexer'</span>
{parser} = require <span class="string">'./parser'</span>
helpers = require <span class="string">'./helpers'</span>
SourceMap = require <span class="string">'./sourcemap'</span></pre></div></div>
</li>
@@ -139,21 +135,12 @@ execute all scripts present in <code>text/coffeescript</code> tags.
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>Load and run a CoffeeScript file for Node, stripping any <code>BOM</code>s.
<p>The current CoffeeScript version number.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">loadFile = </span><span class="nf">(module, filename) -&gt;</span>
<span class="nv">raw = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span> <span class="nx">filename</span><span class="p">,</span> <span class="s">&#39;utf8&#39;</span>
<span class="nv">stripped = </span><span class="k">if</span> <span class="nx">raw</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="mh">0xFEFF</span> <span class="k">then</span> <span class="nx">raw</span><span class="p">.</span><span class="nx">substring</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">raw</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">stripped</span><span class="p">,</span> <span class="p">{</span><span class="nx">filename</span><span class="p">,</span> <span class="nv">literate: </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">isLiterate</span> <span class="nx">filename</span><span class="p">}),</span> <span class="nx">filename</span>
<span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
<span class="k">for</span> <span class="nx">ext</span> <span class="k">in</span> <span class="p">[</span><span class="s">&#39;.coffee&#39;</span><span class="p">,</span> <span class="s">&#39;.litcoffee&#39;</span><span class="p">,</span> <span class="s">&#39;.md&#39;</span><span class="p">,</span> <span class="s">&#39;.coffee.md&#39;</span><span class="p">]</span>
<span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span><span class="p">[</span><span class="nx">ext</span><span class="p">]</span> <span class="o">=</span> <span class="nx">loadFile</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.VERSION = <span class="string">'1.6.3'</span></pre></div></div>
</li>
@@ -164,14 +151,12 @@ execute all scripts present in <code>text/coffeescript</code> tags.
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>The current CoffeeScript version number.
<p>Expose helpers for testing.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.VERSION = </span><span class="s">&#39;1.6.1&#39;</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.helpers = helpers</pre></div></div>
</li>
@@ -182,14 +167,35 @@ execute all scripts present in <code>text/coffeescript</code> tags.
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>Expose helpers for testing.
<p>Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
</p>
<p>If <code>options.sourceMap</code> is specified, then <code>options.filename</code> must also be specified. All
options that can be passed to <code>SourceMap#generate</code> may also be passed here.
</p>
<p>This returns a javascript string, unless <code>options.sourceMap</code> is passed,
in which case this returns a <code>{js, v3SourceMap, sourceMap}</code>
object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for doing programatic
lookups.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.helpers = </span><span class="nx">helpers</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.compile = <span class="function"><span class="title">compile</span></span> = (code, options = {}) -&gt;
{merge} = helpers
<span class="keyword">if</span> options.sourceMap
map = <span class="keyword">new</span> SourceMap
fragments = parser.parse(lexer.tokenize code, options).compileToFragments options
currentLine = <span class="number">0</span>
currentLine += <span class="number">1</span> <span class="keyword">if</span> options.header
currentLine += <span class="number">1</span> <span class="keyword">if</span> options.shiftLine
currentColumn = <span class="number">0</span>
js = <span class="string">""</span>
<span class="keyword">for</span> fragment <span class="keyword">in</span> fragments</pre></div></div>
</li>
@@ -200,39 +206,20 @@ execute all scripts present in <code>text/coffeescript</code> tags.
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
</p>
<p>If <code>options.sourceMap</code> is specified, then <code>options.filename</code> must also be specified.
</p>
<p>This returns a javascript string, unless <code>options.sourceMap</code> is passed,
in which case this returns a `{js, v3SourceMap, sourceMap}
object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for doing programatic
lookups.
<p>Update the sourcemap with data from each fragment
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.compile = compile = </span><span class="nf">(code, options = {}) -&gt;</span>
<span class="p">{</span><span class="nx">merge</span><span class="p">}</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">helpers</span>
<span class="k">try</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sourceMap</span>
<span class="nv">coffeeFile = </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">baseFileName</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span>
<span class="nv">jsFile = </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">baseFileName</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">,</span> <span class="kc">yes</span><span class="p">)</span> <span class="o">+</span> <span class="s">&quot;.js&quot;</span>
<span class="nv">sourceMap = </span><span class="k">new</span> <span class="nx">sourcemap</span><span class="p">.</span><span class="nx">SourceMap</span><span class="p">()</span>
<span class="nv">fragments = </span><span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)).</span><span class="nx">compileToFragments</span> <span class="nx">options</span>
<span class="nv">currentLine = </span><span class="mi">0</span>
<span class="nx">currentLine</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">header</span>
<span class="nx">currentLine</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sourceMap</span>
<span class="nv">currentColumn = </span><span class="mi">0</span>
<span class="nv">js = </span><span class="s">&quot;&quot;</span>
<span class="k">for</span> <span class="nx">fragment</span> <span class="k">in</span> <span class="nx">fragments</span></pre></div></div>
<div class="content"><div class='highlight'><pre> <span class="keyword">if</span> options.sourceMap
<span class="keyword">if</span> fragment.locationData
map.add(
[fragment.locationData.first_line, fragment.locationData.first_column]
[currentLine, currentColumn]
{noReplace: <span class="literal">true</span>})
newLines = helpers.count fragment.code, <span class="string">"\n"</span>
currentLine += newLines
currentColumn = fragment.code.length - (<span class="keyword">if</span> newLines <span class="keyword">then</span> fragment.code.lastIndexOf <span class="string">"\n"</span> <span class="keyword">else</span> <span class="number">0</span>)</pre></div></div>
</li>
@@ -243,22 +230,24 @@ lookups.
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>Update the sourcemap with data from each fragment
<p>Copy the code from each fragment into the final JavaScript.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="k">if</span> <span class="nx">sourceMap</span>
<span class="k">if</span> <span class="nx">fragment</span><span class="p">.</span><span class="nx">locationData</span>
<span class="nx">sourceMap</span><span class="p">.</span><span class="nx">addMapping</span><span class="p">(</span>
<span class="p">[</span><span class="nx">fragment</span><span class="p">.</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">first_line</span><span class="p">,</span> <span class="nx">fragment</span><span class="p">.</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">first_column</span><span class="p">],</span>
<span class="p">[</span><span class="nx">currentLine</span><span class="p">,</span> <span class="nx">currentColumn</span><span class="p">],</span>
<span class="p">{</span><span class="nv">noReplace: </span><span class="kc">true</span><span class="p">})</span>
<span class="nv">newLines = </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">count</span> <span class="nx">fragment</span><span class="p">.</span><span class="nx">code</span><span class="p">,</span> <span class="s">&quot;\n&quot;</span>
<span class="nx">currentLine</span> <span class="o">+=</span> <span class="nx">newLines</span>
<span class="nv">currentColumn = </span><span class="nx">fragment</span><span class="p">.</span><span class="nx">code</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="k">if</span> <span class="nx">newLines</span> <span class="k">then</span> <span class="nx">fragment</span><span class="p">.</span><span class="nx">code</span><span class="p">.</span><span class="nx">lastIndexOf</span> <span class="s">&quot;\n&quot;</span> <span class="k">else</span> <span class="mi">0</span><span class="p">)</span></pre></div></div>
<div class="content"><div class='highlight'><pre> js += fragment.code
<span class="keyword">if</span> options.header
header = <span class="string">"Generated by CoffeeScript <span class="subst">#{@VERSION}</span>"</span>
js = <span class="string">"// <span class="subst">#{header}</span>\n<span class="subst">#{js}</span>"</span>
<span class="keyword">if</span> options.sourceMap
answer = {js}
answer.sourceMap = map
answer.v3SourceMap = map.generate(options, code)
answer
<span class="keyword">else</span>
js</pre></div></div>
</li>
@@ -269,31 +258,13 @@ lookups.
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Copy the code from each fragment into the final JavaScript.
<p>Tokenize a string of CoffeeScript code, and return the array of tokens.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nx">js</span> <span class="o">+=</span> <span class="nx">fragment</span><span class="p">.</span><span class="nx">code</span>
<span class="k">catch</span> <span class="nx">err</span>
<span class="nv">err.message = </span><span class="s">&quot;In </span><span class="si">#{</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="si">}</span><span class="s">, </span><span class="si">#{</span><span class="nx">err</span><span class="p">.</span><span class="nx">message</span><span class="si">}</span><span class="s">&quot;</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span>
<span class="k">throw</span> <span class="nx">err</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">header</span>
<span class="nv">header = </span><span class="s">&quot;Generated by CoffeeScript </span><span class="si">#{</span><span class="nx">@VERSION</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nv">js = </span><span class="s">&quot;// </span><span class="si">#{</span><span class="nx">header</span><span class="si">}</span><span class="s">\n</span><span class="si">#{</span><span class="nx">js</span><span class="si">}</span><span class="s">&quot;</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sourceMap</span>
<span class="nv">answer = </span><span class="p">{</span><span class="nx">js</span><span class="p">}</span>
<span class="k">if</span> <span class="nx">sourceMap</span>
<span class="nv">answer.sourceMap = </span><span class="nx">sourceMap</span>
<span class="nv">answer.v3SourceMap = </span><span class="nx">sourcemap</span><span class="p">.</span><span class="nx">generateV3SourceMap</span> <span class="nx">sourceMap</span><span class="p">,</span> <span class="nx">coffeeFile</span><span class="p">,</span> <span class="nx">jsFile</span>
<span class="nx">answer</span>
<span class="k">else</span>
<span class="nx">js</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">tokens</span></span> = (code, options) -&gt;
lexer.tokenize code, options</pre></div></div>
</li>
@@ -304,15 +275,18 @@ lookups.
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Tokenize a string of CoffeeScript code, and return the array of tokens.
<p>Parse a string of CoffeeScript code or an array of lexed tokens, and
return the AST. You can then compile it by calling <code>.compile()</code> on the root,
or traverse it by using <code>.traverseChildren()</code> with a callback.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.tokens = </span><span class="nf">(code, options) -&gt;</span>
<span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">nodes</span></span> = (source, options) -&gt;
<span class="keyword">if</span> <span class="keyword">typeof</span> source <span class="keyword">is</span> <span class="string">'string'</span>
parser.parse lexer.tokenize source, options
<span class="keyword">else</span>
parser.parse source</pre></div></div>
</li>
@@ -323,20 +297,15 @@ lookups.
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>Parse a string of CoffeeScript code or an array of lexed tokens, and
return the AST. You can then compile it by calling <code>.compile()</code> on the root,
or traverse it by using <code>.traverseChildren()</code> with a callback.
<p>Compile and execute a string of CoffeeScript (on the server), correctly
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.nodes = </span><span class="nf">(source, options) -&gt;</span>
<span class="k">if</span> <span class="k">typeof</span> <span class="nx">source</span> <span class="o">is</span> <span class="s">&#39;string&#39;</span>
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">options</span>
<span class="k">else</span>
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">source</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">run</span></span> = (code, options = {}) -&gt;
mainModule = require.main
options.sourceMap ?= <span class="literal">true</span></pre></div></div>
</li>
@@ -347,16 +316,13 @@ or traverse it by using <code>.traverseChildren()</code> with a callback.
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>Compile and execute a string of CoffeeScript (on the server), correctly
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.
<p>Set the filename.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.run = </span><span class="nf">(code, options = {}) -&gt;</span>
<span class="nv">mainModule = </span><span class="nx">require</span><span class="p">.</span><span class="nx">main</span></pre></div></div>
<div class="content"><div class='highlight'><pre> mainModule.filename = process.argv[<span class="number">1</span>] =
<span class="keyword">if</span> options.filename <span class="keyword">then</span> fs.realpathSync(options.filename) <span class="keyword">else</span> <span class="string">'.'</span></pre></div></div>
</li>
@@ -367,15 +333,12 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>Set the filename.
<p>Clear the module cache.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">mainModule.filename = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="k">else</span> <span class="s">&#39;.&#39;</span></pre></div></div>
<div class="content"><div class='highlight'><pre> mainModule.moduleCache <span class="keyword">and</span>= {}</pre></div></div>
</li>
@@ -386,14 +349,12 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>Clear the module cache.
<p>Assign paths for node_modules loading
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">moduleCache</span> <span class="o">and=</span> <span class="p">{}</span></pre></div></div>
<div class="content"><div class='highlight'><pre> mainModule.paths = require(<span class="string">'module'</span>)._nodeModulePaths path.dirname fs.realpathSync options.filename <span class="keyword">or</span> <span class="string">'.'</span></pre></div></div>
</li>
@@ -404,14 +365,13 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>Assign paths for node_modules loading
<p>Compile.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">mainModule.paths = </span><span class="nx">require</span><span class="p">(</span><span class="s">&#39;module&#39;</span><span class="p">).</span><span class="nx">_nodeModulePaths</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span></pre></div></div>
<div class="content"><div class='highlight'><pre> <span class="keyword">if</span> <span class="keyword">not</span> helpers.isCoffee(mainModule.filename) <span class="keyword">or</span> require.extensions
answer = compile(code, options)</pre></div></div>
</li>
@@ -422,17 +382,17 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>Compile.
<p>Attach sourceMap object to sourceMaps[options.filename] so that
it is accessible by Error.prepareStackTrace.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="k">if</span> <span class="o">not</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">isCoffee</span><span class="p">(</span><span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="o">or</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
<span class="nx">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span>
<span class="k">else</span>
<span class="nx">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span></pre></div></div>
<div class="content"><div class='highlight'><pre> <span class="keyword">do</span> patchStackTrace
sourceMaps[mainModule.filename] = answer.sourceMap
mainModule._compile answer.js, mainModule.filename
<span class="keyword">else</span>
mainModule._compile code, mainModule.filename</pre></div></div>
</li>
@@ -443,29 +403,27 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
<p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
The CoffeeScript REPL uses this to run the input.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.eval = </span><span class="nf">(code, options = {}) -&gt;</span>
<span class="k">return</span> <span class="k">unless</span> <span class="nv">code = </span><span class="nx">code</span><span class="p">.</span><span class="nx">trim</span><span class="p">()</span>
<span class="nv">Script = </span><span class="nx">vm</span><span class="p">.</span><span class="nx">Script</span>
<span class="k">if</span> <span class="nx">Script</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span><span class="o">?</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span> <span class="k">instanceof</span> <span class="nx">Script</span><span class="p">.</span><span class="nx">createContext</span><span class="p">().</span><span class="nx">constructor</span>
<span class="nv">sandbox = </span><span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span>
<span class="k">else</span>
<span class="nv">sandbox = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">createContext</span><span class="p">()</span>
<span class="nx">sandbox</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="k">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span>
<span class="nv">sandbox.global = sandbox.root = sandbox.GLOBAL = </span><span class="nx">sandbox</span>
<span class="k">else</span>
<span class="nv">sandbox = </span><span class="nx">global</span>
<span class="nv">sandbox.__filename = </span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="o">||</span> <span class="s">&#39;eval&#39;</span>
<span class="nv">sandbox.__dirname = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">eval</span></span> = (code, options = {}) -&gt;
<span class="keyword">return</span> <span class="keyword">unless</span> code = code.trim()
Script = vm.Script
<span class="keyword">if</span> Script
<span class="keyword">if</span> options.sandbox?
<span class="keyword">if</span> options.sandbox <span class="keyword">instanceof</span> Script.createContext().constructor
sandbox = options.sandbox
<span class="keyword">else</span>
sandbox = Script.createContext()
sandbox[k] = v <span class="keyword">for</span> own k, v <span class="keyword">of</span> options.sandbox
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox
<span class="keyword">else</span>
sandbox = global
sandbox.__filename = options.filename || <span class="string">'eval'</span>
sandbox.__dirname = path.dirname sandbox.__filename</pre></div></div>
</li>
@@ -476,19 +434,17 @@ The CoffeeScript REPL uses this to run the input.
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>define module/require only if they chose not to specify their own
<p>define module/require only if they chose not to specify their own
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="k">unless</span> <span class="nx">sandbox</span> <span class="o">isnt</span> <span class="nx">global</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">module</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">require</span>
<span class="nv">Module = </span><span class="nx">require</span> <span class="s">&#39;module&#39;</span>
<span class="nv">sandbox.module = _module = </span><span class="k">new</span> <span class="nx">Module</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">modulename</span> <span class="o">||</span> <span class="s">&#39;eval&#39;</span><span class="p">)</span>
<span class="nv">sandbox.require = _require = </span><span class="nf">(path) -&gt;</span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_load</span> <span class="nx">path</span><span class="p">,</span> <span class="nx">_module</span><span class="p">,</span> <span class="kc">true</span>
<span class="nv">_module.filename = </span><span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span>
<span class="nx">_require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="o">=</span> <span class="nx">require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">require</span> <span class="k">when</span> <span class="nx">r</span> <span class="o">isnt</span> <span class="s">&#39;paths&#39;</span></pre></div></div>
<div class="content"><div class='highlight'><pre> <span class="keyword">unless</span> sandbox <span class="keyword">isnt</span> global <span class="keyword">or</span> sandbox.module <span class="keyword">or</span> sandbox.require
Module = require <span class="string">'module'</span>
sandbox.module = _module = <span class="keyword">new</span> Module(options.modulename || <span class="string">'eval'</span>)
sandbox.require = <span class="function"><span class="title">_require</span></span> = (path) -&gt; Module._load path, _module, <span class="literal">true</span>
_module.filename = sandbox.__filename
_require[r] = require[r] <span class="keyword">for</span> r <span class="keyword">in</span> Object.getOwnPropertyNames require <span class="keyword">when</span> r <span class="keyword">isnt</span> <span class="string">'paths'</span></pre></div></div>
</li>
@@ -499,23 +455,21 @@ The CoffeeScript REPL uses this to run the input.
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>use the same hack node currently uses for their own REPL
<p>use the same hack node currently uses for their own REPL
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">_require.paths = _module.paths = </span><span class="nx">Module</span><span class="p">.</span><span class="nx">_nodeModulePaths</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
<span class="nv">_require.resolve = </span><span class="nf">(request) -&gt;</span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_resolveFilename</span> <span class="nx">request</span><span class="p">,</span> <span class="nx">_module</span>
<span class="nv">o = </span><span class="p">{}</span>
<span class="nx">o</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="k">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span>
<span class="nv">o.bare = </span><span class="kc">on</span> <span class="c1"># ensure return value</span>
<span class="nv">js = </span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">o</span>
<span class="k">if</span> <span class="nx">sandbox</span> <span class="o">is</span> <span class="nx">global</span>
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="nx">js</span>
<span class="k">else</span>
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInContext</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">sandbox</span></pre></div></div>
<div class="content"><div class='highlight'><pre> _require.paths = _module.paths = Module._nodeModulePaths process.cwd()
_require.<span class="function"><span class="title">resolve</span></span> = (request) -&gt; Module._resolveFilename request, _module
o = {}
o[k] = v <span class="keyword">for</span> own k, v <span class="keyword">of</span> options
o.bare = <span class="literal">on</span> <span class="comment"># ensure return value</span>
js = compile code, o
<span class="keyword">if</span> sandbox <span class="keyword">is</span> global
vm.runInThisContext js
<span class="keyword">else</span>
vm.runInContext js, sandbox</pre></div></div>
</li>
@@ -526,14 +480,17 @@ The CoffeeScript REPL uses this to run the input.
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>Instantiate a Lexer for our use here.
<p>Load and run a CoffeeScript file for Node, stripping any <code>BOM</code>s.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">loadFile</span></span> = (module, filename) -&gt;
raw = fs.readFileSync filename, <span class="string">'utf8'</span>
stripped = <span class="keyword">if</span> raw.charCodeAt(<span class="number">0</span>) <span class="keyword">is</span> <span class="number">0xFEFF</span> <span class="keyword">then</span> raw.substring <span class="number">1</span> <span class="keyword">else</span> raw
answer = compile(stripped, {filename, sourceMap: <span class="literal">true</span>, literate: helpers.isLiterate filename})
sourceMaps[filename] = answer.sourceMap
module._compile answer.js, filename</pre></div></div>
</li>
@@ -544,32 +501,370 @@ The CoffeeScript REPL uses this to run the input.
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>If the installed version of Node supports <code>require.extensions</code>, register
CoffeeScript as an extension.
</p>
</div>
<div class="content"><div class='highlight'><pre><span class="keyword">if</span> require.extensions
<span class="keyword">for</span> ext <span class="keyword">in</span> [<span class="string">'.coffee'</span>, <span class="string">'.litcoffee'</span>, <span class="string">'.coffee.md'</span>]
require.extensions[ext] = loadFile</pre></div></div>
</li>
<li id="section-20">
<div class="annotation">
<p>The real Lexer produces a generic stream of tokens. This object provides a
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<p>Patch Node&#39;s module loader to be able to handle mult-dot extensions.
This is a horrible thing that should not be required. Perhaps, one day,
when a truly benevolent dictator comes to rule over the Republik of Node,
it won&#39;t be.
</p>
</div>
<div class="content"><div class='highlight'><pre> Module = require <span class="string">'module'</span>
<span class="function"><span class="title">findExtension</span></span> = (filename) -&gt;
extensions = path.basename(filename).split <span class="string">'.'</span></pre></div></div>
</li>
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
</div>
<p>Remove the initial dot from dotfiles.
</p>
</div>
<div class="content"><div class='highlight'><pre> extensions.shift() <span class="keyword">if</span> extensions[<span class="number">0</span>] <span class="keyword">is</span> <span class="string">''</span></pre></div></div>
</li>
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
</div>
<p>Start with the longest possible extension and work our way shortwards.
</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="keyword">while</span> extensions.shift()
curExtension = <span class="string">'.'</span> + extensions.join <span class="string">'.'</span>
<span class="keyword">return</span> curExtension <span class="keyword">if</span> Module._extensions[curExtension]
<span class="string">'.js'</span>
Module::<span class="function"><span class="title">load</span></span> = (filename) -&gt;
<span class="property">@filename</span> = filename
<span class="property">@paths</span> = Module._nodeModulePaths path.dirname filename
extension = findExtension filename
Module._extensions[extension](<span class="keyword">this</span>, filename)
<span class="property">@loaded</span> = <span class="literal">true</span></pre></div></div>
</li>
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>If we&#39;re on Node, patch <code>child_process.fork</code> so that Coffee scripts are able
to fork both CoffeeScript files, and JavaScript files, directly.
</p>
</div>
<div class="content"><div class='highlight'><pre><span class="keyword">if</span> child_process
{fork} = child_process
child_process.<span class="function"><span class="title">fork</span></span> = (path, args = [], options = {}) -&gt;
execPath = <span class="keyword">if</span> helpers.isCoffee(path) <span class="keyword">then</span> <span class="string">'coffee'</span> <span class="keyword">else</span> <span class="literal">null</span>
<span class="keyword">if</span> <span class="keyword">not</span> Array.isArray args
args = []
options = args <span class="keyword">or</span> {}
options.execPath <span class="keyword">or</span>= execPath
fork path, args, options</pre></div></div>
</li>
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<p>Instantiate a Lexer for our use here.
</p>
</div>
<div class="content"><div class='highlight'><pre>lexer = <span class="keyword">new</span> Lexer</pre></div></div>
</li>
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
</div>
<p>The real Lexer produces a generic stream of tokens. This object provides a
thin wrapper around it, compatible with the Jison API. We can then pass it
directly as a &quot;Jison lexer&quot;.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">parser.lexer =</span>
<span class="nv">lex: </span><span class="nf">-&gt;</span>
<span class="nv">token = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">@pos</span><span class="o">++</span><span class="p">]</span>
<span class="k">if</span> <span class="nx">token</span>
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">@yytext</span><span class="p">,</span> <span class="nx">@yylloc</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
<span class="vi">@yylineno = </span><span class="nx">@yylloc</span><span class="p">.</span><span class="nx">first_line</span>
<span class="k">else</span>
<span class="nv">tag = </span><span class="s">&#39;&#39;</span>
<div class="content"><div class='highlight'><pre>parser.lexer =
lex: -&gt;
token = <span class="property">@tokens</span>[<span class="property">@pos</span>++]
<span class="keyword">if</span> token
[tag, <span class="property">@yytext</span>, <span class="property">@yylloc</span>] = token
<span class="property">@yylineno</span> = <span class="property">@yylloc</span>.first_line
<span class="keyword">else</span>
tag = <span class="string">''</span>
<span class="nx">tag</span>
<span class="nv">setInput: </span><span class="nf">(@tokens) -&gt;</span>
<span class="vi">@pos = </span><span class="mi">0</span>
<span class="nv">upcomingInput: </span><span class="nf">-&gt;</span>
<span class="s">&quot;&quot;</span>
tag
setInput: (<span class="property">@tokens</span>) -&gt;
<span class="property">@pos</span> = <span class="number">0</span>
upcomingInput: -&gt;
<span class="string">""</span></pre></div></div>
</li>
<li id="section-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
</div>
<p>Make all the AST nodes visible to the parser.
</p>
<span class="nv">parser.yy = </span><span class="nx">require</span> <span class="s">&#39;./nodes&#39;</span>
</div>
<div class="content"><div class='highlight'><pre>parser.yy = require <span class="string">'./nodes'</span></pre></div></div>
</li>
<li id="section-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
</div>
<p>Override Jison&#39;s default error handling function.
</p>
</pre></div></div>
</div>
<div class="content"><div class='highlight'><pre>parser.yy.<span class="function"><span class="title">parseError</span></span> = (message, {token}) -&gt;</pre></div></div>
</li>
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a>
</div>
<p>Disregard Jison&#39;s message, it contains redundant line numer information.
</p>
</div>
<div class="content"><div class='highlight'><pre> message = <span class="string">"unexpected <span class="subst">#{<span class="keyword">if</span> token <span class="keyword">is</span> <span class="number">1</span> <span class="keyword">then</span> 'end <span class="keyword">of</span> input' <span class="keyword">else</span> token}</span>"</span></pre></div></div>
</li>
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
</div>
<p>The second argument has a <code>loc</code> property, which should have the location
data for this token. Unfortunately, Jison seems to send an outdated <code>loc</code>
(from the previous token), so we take the location information directly
from the lexer.
</p>
</div>
<div class="content"><div class='highlight'><pre> helpers.throwSyntaxError message, parser.lexer.yylloc</pre></div></div>
</li>
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-30">&#182;</a>
</div>
<p>Based on <a href="http://goo.gl/ZTx1p">michaelficarra/CoffeeScriptRedux</a>
NodeJS / V8 have no support for transforming positions in stack traces using
sourceMap, so we must monkey-patch Error to display CoffeeScript source
positions.
</p>
</div>
<div class="content"><div class='highlight'><pre>
patched = <span class="literal">false</span></pre></div></div>
</li>
<li id="section-31">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-31">&#182;</a>
</div>
<p>Map of filenames -&gt; sourceMap object.
</p>
</div>
<div class="content"><div class='highlight'><pre>sourceMaps = {}
<span class="function"><span class="title">patchStackTrace</span></span> = -&gt;
<span class="keyword">return</span> <span class="keyword">if</span> patched
patched = <span class="literal">true</span>
mainModule = require.main</pre></div></div>
</li>
<li id="section-32">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-32">&#182;</a>
</div>
<p>(Assigning to a property of the Module object in the normal module cache is
unsuitable, because node deletes those objects from the cache if an
exception is thrown in the module body.)
</p>
</div>
<div class="content"><div class='highlight'><pre>
Error.<span class="function"><span class="title">prepareStackTrace</span></span> = (err, stack) -&gt;
sourceFiles = {}
<span class="function"><span class="title">getSourceMapping</span></span> = (filename, line, column) -&gt;
sourceMap = sourceMaps[filename]
answer = sourceMap.sourceLocation [line - <span class="number">1</span>, column - <span class="number">1</span>] <span class="keyword">if</span> sourceMap
<span class="keyword">if</span> answer <span class="keyword">then</span> [answer[<span class="number">0</span>] + <span class="number">1</span>, answer[<span class="number">1</span>] + <span class="number">1</span>] <span class="keyword">else</span> <span class="literal">null</span>
frames = <span class="keyword">for</span> frame <span class="keyword">in</span> stack
<span class="keyword">break</span> <span class="keyword">if</span> frame.getFunction() <span class="keyword">is</span> exports.run
<span class="string">" at <span class="subst">#{formatSourcePosition frame, getSourceMapping}</span>"</span>
<span class="string">"<span class="subst">#{err.name}</span>: <span class="subst">#{err.message ? ''}</span>\n<span class="subst">#{frames.join '\n'}</span>\n"</span></pre></div></div>
</li>
<li id="section-33">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-33">&#182;</a>
</div>
<p>Based on <a href="http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js">http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js</a>
Modified to handle sourceMap
</p>
</div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">formatSourcePosition</span></span> = (frame, getSourceMapping) -&gt;
fileName = <span class="literal">undefined</span>
fileLocation = <span class="string">''</span>
<span class="keyword">if</span> frame.isNative()
fileLocation = <span class="string">"native"</span>
<span class="keyword">else</span>
<span class="keyword">if</span> frame.isEval()
fileName = frame.getScriptNameOrSourceURL()
fileLocation = <span class="string">"<span class="subst">#{frame.getEvalOrigin()}</span>, "</span> <span class="keyword">unless</span> fileName
<span class="keyword">else</span>
fileName = frame.getFileName()
fileName <span class="keyword">or</span>= <span class="string">"&lt;anonymous&gt;"</span>
line = frame.getLineNumber()
column = frame.getColumnNumber()</pre></div></div>
</li>
<li id="section-34">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-34">&#182;</a>
</div>
<p>Check for a sourceMap position
</p>
</div>
<div class="content"><div class='highlight'><pre> source = getSourceMapping fileName, line, column
fileLocation =
<span class="keyword">if</span> source
<span class="string">"<span class="subst">#{fileName}</span>:<span class="subst">#{source[<span class="number">0</span>]}</span>:<span class="subst">#{source[<span class="number">1</span>]}</span>, &lt;js&gt;:<span class="subst">#{line}</span>:<span class="subst">#{column}</span>"</span>
<span class="keyword">else</span>
<span class="string">"<span class="subst">#{fileName}</span>:<span class="subst">#{line}</span>:<span class="subst">#{column}</span>"</span>
functionName = frame.getFunctionName()
isConstructor = frame.isConstructor()
isMethodCall = <span class="keyword">not</span> (frame.isToplevel() <span class="keyword">or</span> isConstructor)
<span class="keyword">if</span> isMethodCall
methodName = frame.getMethodName()
typeName = frame.getTypeName()
<span class="keyword">if</span> functionName
tp = as = <span class="string">''</span>
<span class="keyword">if</span> typeName <span class="keyword">and</span> functionName.indexOf typeName
tp = <span class="string">"<span class="subst">#{typeName}</span>."</span>
<span class="keyword">if</span> methodName <span class="keyword">and</span> functionName.indexOf(<span class="string">".<span class="subst">#{methodName}</span>"</span>) <span class="keyword">isnt</span> functionName.length - methodName.length - <span class="number">1</span>
as = <span class="string">" [as <span class="subst">#{methodName}</span>]"</span>
<span class="string">"<span class="subst">#{tp}</span><span class="subst">#{functionName}</span><span class="subst">#{as}</span> (<span class="subst">#{fileLocation}</span>)"</span>
<span class="keyword">else</span>
<span class="string">"<span class="subst">#{typeName}</span>.<span class="subst">#{methodName <span class="keyword">or</span> '&lt;anonymous&gt;'}</span> (<span class="subst">#{fileLocation}</span>)"</span>
<span class="keyword">else</span> <span class="keyword">if</span> isConstructor
<span class="string">"new <span class="subst">#{functionName <span class="keyword">or</span> '&lt;anonymous&gt;'}</span> (<span class="subst">#{fileLocation}</span>)"</span>
<span class="keyword">else</span> <span class="keyword">if</span> functionName
<span class="string">"<span class="subst">#{functionName}</span> (<span class="subst">#{fileLocation}</span>)"</span>
<span class="keyword">else</span>
fileLocation</pre></div></div>
</li>

View File

@@ -85,7 +85,7 @@
<a class="source" href="sourcemap.html">
sourcemap.coffee
sourcemap.litcoffee
</a>
</div>
@@ -109,28 +109,14 @@
<a class="pilcrow" href="#section-1">&#182;</a>
</div>
<p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript
into various forms: saved into <code>.js</code> files or printed to stdout, piped to
<a href="http://javascriptlint.com/">JavaScript Lint</a> or recompiled every time the source is
saved, printed as a token stream or as the syntax tree, or launch an
into various forms: saved into <code>.js</code> files or printed to stdout
or recompiled every time the source is saved,
printed as a token stream or as the syntax tree, or launch an
interactive REPL.
</p>
<p>External dependencies.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s">&#39;fs&#39;</span>
<span class="nv">path = </span><span class="nx">require</span> <span class="s">&#39;path&#39;</span>
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s">&#39;./helpers&#39;</span>
<span class="nv">optparse = </span><span class="nx">require</span> <span class="s">&#39;./optparse&#39;</span>
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">&#39;./coffee-script&#39;</span>
<span class="p">{</span><span class="nx">spawn</span><span class="p">,</span> <span class="nx">exec</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">&#39;child_process&#39;</span>
<span class="p">{</span><span class="nx">EventEmitter</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">&#39;events&#39;</span>
<span class="nv">exists = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">exists</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">exists</span></pre></div></div>
</li>
@@ -140,19 +126,21 @@ interactive REPL.
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>Allow CoffeeScript to emit Node.js events.
<p>External dependencies.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">CoffeeScript</span><span class="p">,</span> <span class="k">new</span> <span class="nx">EventEmitter</span>
<div class="content"><div class='highlight'><pre>fs = require <span class="string">'fs'</span>
path = require <span class="string">'path'</span>
helpers = require <span class="string">'./helpers'</span>
optparse = require <span class="string">'./optparse'</span>
CoffeeScript = require <span class="string">'./coffee-script'</span>
{spawn, exec} = require <span class="string">'child_process'</span>
{EventEmitter} = require <span class="string">'events'</span>
<span class="nv">printLine = </span><span class="nf">(line) -&gt;</span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s">&#39;\n&#39;</span>
<span class="nv">printWarn = </span><span class="nf">(line) -&gt;</span> <span class="nx">process</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s">&#39;\n&#39;</span>
<span class="nv">hidden = </span><span class="nf">(file) -&gt;</span> <span class="o">/^</span><span class="err">\</span><span class="p">.</span><span class="o">|~</span><span class="nx">$</span><span class="o">/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">file</span></pre></div></div>
exists = fs.exists <span class="keyword">or</span> path.exists
useWinPathSep = path.sep <span class="keyword">is</span> <span class="string">'\\'</span></pre></div></div>
</li>
@@ -163,18 +151,17 @@ interactive REPL.
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>The help banner that is printed when <code>coffee</code> is called without arguments.
<p>Allow CoffeeScript to emit Node.js events.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">BANNER = </span><span class="s">&#39;&#39;&#39;</span>
<span class="s"> Usage: coffee [options] path/to/script.coffee -- [args]</span>
<div class="content"><div class='highlight'><pre>helpers.extend CoffeeScript, <span class="keyword">new</span> EventEmitter
<span class="s"> If called without options, `coffee` will run your script.</span>
<span class="s">&#39;&#39;&#39;</span></pre></div></div>
<span class="function"><span class="title">printLine</span></span> = (line) -&gt; process.stdout.write line + <span class="string">'\n'</span>
<span class="function"><span class="title">printWarn</span></span> = (line) -&gt; process.stderr.write line + <span class="string">'\n'</span>
<span class="function"><span class="title">hidden</span></span> = (file) -&gt; <span class="regexp">/^\.|~$/</span>.test file</pre></div></div>
</li>
@@ -185,31 +172,16 @@ interactive REPL.
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>The list of all the valid option flags that <code>coffee</code> knows how to handle.
<p>The help banner that is printed when <code>coffee</code> is called without arguments.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">SWITCHES = </span><span class="p">[</span>
<span class="p">[</span><span class="s">&#39;-b&#39;</span><span class="p">,</span> <span class="s">&#39;--bare&#39;</span><span class="p">,</span> <span class="s">&#39;compile without a top-level function wrapper&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-c&#39;</span><span class="p">,</span> <span class="s">&#39;--compile&#39;</span><span class="p">,</span> <span class="s">&#39;compile to JavaScript and save as .js files&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-e&#39;</span><span class="p">,</span> <span class="s">&#39;--eval&#39;</span><span class="p">,</span> <span class="s">&#39;pass a string from the command line as input&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-h&#39;</span><span class="p">,</span> <span class="s">&#39;--help&#39;</span><span class="p">,</span> <span class="s">&#39;display this help message&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-i&#39;</span><span class="p">,</span> <span class="s">&#39;--interactive&#39;</span><span class="p">,</span> <span class="s">&#39;run an interactive CoffeeScript REPL&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-j&#39;</span><span class="p">,</span> <span class="s">&#39;--join [FILE]&#39;</span><span class="p">,</span> <span class="s">&#39;concatenate the source CoffeeScript before compiling&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-l&#39;</span><span class="p">,</span> <span class="s">&#39;--lint&#39;</span><span class="p">,</span> <span class="s">&#39;pipe the compiled JavaScript through JavaScript Lint&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-m&#39;</span><span class="p">,</span> <span class="s">&#39;--map&#39;</span><span class="p">,</span> <span class="s">&#39;generate source map and save as .map files&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-n&#39;</span><span class="p">,</span> <span class="s">&#39;--nodes&#39;</span><span class="p">,</span> <span class="s">&#39;print out the parse tree that the parser produces&#39;</span><span class="p">]</span>
<span class="p">[</span> <span class="s">&#39;--nodejs [ARGS]&#39;</span><span class="p">,</span> <span class="s">&#39;pass options directly to the &quot;node&quot; binary&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-o&#39;</span><span class="p">,</span> <span class="s">&#39;--output [DIR]&#39;</span><span class="p">,</span> <span class="s">&#39;set the output directory for compiled JavaScript&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-p&#39;</span><span class="p">,</span> <span class="s">&#39;--print&#39;</span><span class="p">,</span> <span class="s">&#39;print out the compiled JavaScript&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-s&#39;</span><span class="p">,</span> <span class="s">&#39;--stdio&#39;</span><span class="p">,</span> <span class="s">&#39;listen for and compile scripts over stdio&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-t&#39;</span><span class="p">,</span> <span class="s">&#39;--tokens&#39;</span><span class="p">,</span> <span class="s">&#39;print out the tokens that the lexer/rewriter produce&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-v&#39;</span><span class="p">,</span> <span class="s">&#39;--version&#39;</span><span class="p">,</span> <span class="s">&#39;display the version number&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-w&#39;</span><span class="p">,</span> <span class="s">&#39;--watch&#39;</span><span class="p">,</span> <span class="s">&#39;watch scripts for changes and rerun commands&#39;</span><span class="p">]</span>
<span class="p">]</span></pre></div></div>
<div class="content"><div class='highlight'><pre>BANNER = '''
Usage: coffee [options] path/to/script.coffee -- [args]
If called without options, `coffee` will run your script.
'''</pre></div></div>
</li>
@@ -220,19 +192,29 @@ interactive REPL.
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>Top-level objects shared by all the functions.
<p>The list of all the valid option flags that <code>coffee</code> knows how to handle.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">opts = </span><span class="p">{}</span>
<span class="nv">sources = </span><span class="p">[]</span>
<span class="nv">sourceCode = </span><span class="p">[]</span>
<span class="nv">notSources = </span><span class="p">{}</span>
<span class="nv">watchers = </span><span class="p">{}</span>
<span class="nv">optionParser = </span><span class="kc">null</span></pre></div></div>
<div class="content"><div class='highlight'><pre>SWITCHES = [
[<span class="string">'-b'</span>, <span class="string">'--bare'</span>, <span class="string">'compile without a top-level function wrapper'</span>]
[<span class="string">'-c'</span>, <span class="string">'--compile'</span>, <span class="string">'compile to JavaScript and save as .js files'</span>]
[<span class="string">'-e'</span>, <span class="string">'--eval'</span>, <span class="string">'pass a string from the command line as input'</span>]
[<span class="string">'-h'</span>, <span class="string">'--help'</span>, <span class="string">'display this help message'</span>]
[<span class="string">'-i'</span>, <span class="string">'--interactive'</span>, <span class="string">'run an interactive CoffeeScript REPL'</span>]
[<span class="string">'-j'</span>, <span class="string">'--join [FILE]'</span>, <span class="string">'concatenate the source CoffeeScript before compiling'</span>]
[<span class="string">'-m'</span>, <span class="string">'--map'</span>, <span class="string">'generate source map and save as .map files'</span>]
[<span class="string">'-n'</span>, <span class="string">'--nodes'</span>, <span class="string">'print out the parse tree that the parser produces'</span>]
[ <span class="string">'--nodejs [ARGS]'</span>, <span class="string">'pass options directly to the "node" binary'</span>]
[<span class="string">'-o'</span>, <span class="string">'--output [DIR]'</span>, <span class="string">'set the output directory for compiled JavaScript'</span>]
[<span class="string">'-p'</span>, <span class="string">'--print'</span>, <span class="string">'print out the compiled JavaScript'</span>]
[<span class="string">'-s'</span>, <span class="string">'--stdio'</span>, <span class="string">'listen for and compile scripts over stdio'</span>]
[<span class="string">'-l'</span>, <span class="string">'--literate'</span>, <span class="string">'treat stdio as literate style coffee-script'</span>]
[<span class="string">'-t'</span>, <span class="string">'--tokens'</span>, <span class="string">'print out the tokens that the lexer/rewriter produce'</span>]
[<span class="string">'-v'</span>, <span class="string">'--version'</span>, <span class="string">'display the version number'</span>]
[<span class="string">'-w'</span>, <span class="string">'--watch'</span>, <span class="string">'watch scripts for changes and rerun commands'</span>]
]</pre></div></div>
</li>
@@ -243,31 +225,17 @@ interactive REPL.
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>Run <code>coffee</code> by parsing passed options and determining what action to take.
Many flags cause us to divert before compiling anything. Flags passed after
<code>--</code> will be passed verbatim to your script as arguments in <code>process.argv</code>
<p>Top-level objects shared by all the functions.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.run = </span><span class="nf">-&gt;</span>
<span class="nx">parseOptions</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">forkNode</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">nodejs</span>
<span class="k">return</span> <span class="nx">usage</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">help</span>
<span class="k">return</span> <span class="nx">version</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">version</span>
<span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s">&#39;./repl&#39;</span><span class="p">).</span><span class="nx">start</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">interactive</span>
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span> <span class="o">and</span> <span class="o">!</span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span>
<span class="k">return</span> <span class="nx">printWarn</span> <span class="s">&quot;The --watch feature depends on Node v0.6.0+. You are running </span><span class="si">#{</span><span class="nx">process</span><span class="p">.</span><span class="nx">version</span><span class="si">}</span><span class="s">.&quot;</span>
<span class="k">return</span> <span class="nx">compileStdio</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">stdio</span>
<span class="k">return</span> <span class="nx">compileScript</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nb">eval</span>
<span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s">&#39;./repl&#39;</span><span class="p">).</span><span class="nx">start</span><span class="p">()</span> <span class="k">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">literals = </span><span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">run</span> <span class="k">then</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">splice</span> <span class="mi">1</span> <span class="k">else</span> <span class="p">[]</span>
<span class="nv">process.argv = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">..</span><span class="mi">1</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">literals</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;coffee&#39;</span>
<span class="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span>
<span class="nx">compilePath</span> <span class="nx">source</span><span class="p">,</span> <span class="kc">yes</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">normalize</span> <span class="nx">source</span></pre></div></div>
<div class="content"><div class='highlight'><pre>opts = {}
sources = []
sourceCode = []
notSources = {}
watchers = {}
optionParser = <span class="literal">null</span></pre></div></div>
</li>
@@ -278,41 +246,29 @@ Many flags cause us to divert before compiling anything. Flags passed after
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Compile a path, which could be a script or a directory. If a directory
is passed, recursively compile all &#39;.coffee&#39;, &#39;.litcoffee&#39;, and &#39;.coffee.md&#39;
extension source files in it and all subdirectories.
<p>Run <code>coffee</code> by parsing passed options and determining what action to take.
Many flags cause us to divert before compiling anything. Flags passed after
<code>--</code> will be passed verbatim to your script as arguments in <code>process.argv</code>
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">compilePath = </span><span class="nf">(source, topLevel, base) -&gt;</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, stats) -&gt;</span>
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="k">if</span> <span class="nx">err</span><span class="o">?</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span> <span class="s">&quot;File not found: </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span>
<span class="k">if</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">()</span> <span class="o">and</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">&#39;node_modules&#39;</span>
<span class="nx">watchDir</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readdir</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, files) -&gt;</span>
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">err</span><span class="o">?</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="nv">index = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">source</span>
<span class="nv">files = </span><span class="nx">files</span><span class="p">.</span><span class="nx">filter</span> <span class="nf">(file) -&gt;</span> <span class="o">not</span> <span class="nx">hidden</span> <span class="nx">file</span>
<span class="nx">sources</span><span class="p">[</span><span class="nx">index</span><span class="p">..</span><span class="nx">index</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">file</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</span><span class="p">)</span>
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">index</span><span class="p">..</span><span class="nx">index</span><span class="p">]</span> <span class="o">=</span> <span class="nx">files</span><span class="p">.</span><span class="nx">map</span> <span class="nf">-&gt;</span> <span class="kc">null</span>
<span class="nx">files</span><span class="p">.</span><span class="nx">forEach</span> <span class="nf">(file) -&gt;</span>
<span class="nx">compilePath</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">file</span><span class="p">),</span> <span class="kc">no</span><span class="p">,</span> <span class="nx">base</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">topLevel</span> <span class="o">or</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">isCoffee</span> <span class="nx">source</span>
<span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, code) -&gt;</span>
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">err</span><span class="o">?</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="nx">compileScript</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span>
<span class="k">else</span>
<span class="nx">notSources</span><span class="p">[</span><span class="nx">source</span><span class="p">]</span> <span class="o">=</span> <span class="kc">yes</span>
<span class="nx">removeSource</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">run</span></span> = -&gt;
parseOptions()
<span class="keyword">return</span> forkNode() <span class="keyword">if</span> opts.nodejs
<span class="keyword">return</span> usage() <span class="keyword">if</span> opts.help
<span class="keyword">return</span> version() <span class="keyword">if</span> opts.version
<span class="keyword">return</span> require(<span class="string">'./repl'</span>).start() <span class="keyword">if</span> opts.interactive
<span class="keyword">if</span> opts.watch <span class="keyword">and</span> <span class="keyword">not</span> fs.watch
<span class="keyword">return</span> printWarn <span class="string">"The --watch feature depends on Node v0.6.0+. You are running <span class="subst">#{process.version}</span>."</span>
<span class="keyword">return</span> compileStdio() <span class="keyword">if</span> opts.stdio
<span class="keyword">return</span> compileScript <span class="literal">null</span>, sources[<span class="number">0</span>] <span class="keyword">if</span> opts.eval
<span class="keyword">return</span> require(<span class="string">'./repl'</span>).start() <span class="keyword">unless</span> sources.length
literals = <span class="keyword">if</span> opts.run <span class="keyword">then</span> sources.splice <span class="number">1</span> <span class="keyword">else</span> []
process.argv = process.argv[<span class="number">0.</span><span class="number">.1</span>].concat literals
process.argv[<span class="number">0</span>] = <span class="string">'coffee'</span>
<span class="keyword">for</span> source <span class="keyword">in</span> sources
compilePath source, <span class="literal">yes</span>, path.normalize source</pre></div></div>
</li>
@@ -323,47 +279,39 @@ extension source files in it and all subdirectories.
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Compile a single source script, containing the given code, according to the
requested options. If evaluating the script directly sets <code>__filename</code>,
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the script&#39;s path.
<p>Compile a path, which could be a script or a directory. If a directory
is passed, recursively compile all &#39;.coffee&#39;, &#39;.litcoffee&#39;, and &#39;.coffee.md&#39;
extension source files in it and all subdirectories.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">compileScript = </span><span class="nf">(file, input, base) -&gt;</span>
<span class="nv">o = </span><span class="nx">opts</span>
<span class="nv">options = </span><span class="nx">compileOptions</span> <span class="nx">file</span>
<span class="k">try</span>
<span class="nv">t = task = </span><span class="p">{</span><span class="nx">file</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">options</span><span class="p">}</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s">&#39;compile&#39;</span><span class="p">,</span> <span class="nx">task</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">tokens</span> <span class="k">then</span> <span class="nx">printTokens</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">tokens</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">nodes</span> <span class="k">then</span> <span class="nx">printLine</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">nodes</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span><span class="p">).</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">run</span> <span class="k">then</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">join</span> <span class="o">and</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span> <span class="o">isnt</span> <span class="nx">o</span><span class="p">.</span><span class="nx">join</span>
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">)]</span> <span class="o">=</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span>
<span class="nx">compileJoin</span><span class="p">()</span>
<span class="k">else</span>
<span class="nv">compiled = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
<span class="nv">t.output = </span><span class="nx">compiled</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">map</span>
<span class="nv">t.output = </span><span class="nx">compiled</span><span class="p">.</span><span class="nx">js</span>
<span class="nv">t.sourceMap = </span><span class="nx">compiled</span><span class="p">.</span><span class="nx">v3SourceMap</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s">&#39;success&#39;</span><span class="p">,</span> <span class="nx">task</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span>
<span class="nx">printLine</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">trim</span><span class="p">()</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">||</span> <span class="nx">o</span><span class="p">.</span><span class="nx">map</span>
<span class="nx">writeJs</span> <span class="nx">base</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">sourceMap</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span>
<span class="nx">lint</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span>
<span class="k">catch</span> <span class="nx">err</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s">&#39;failure&#39;</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">task</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s">&#39;failure&#39;</span><span class="p">).</span><span class="nx">length</span>
<span class="k">return</span> <span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="o">+</span> <span class="s">&#39;\x07&#39;</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">printWarn</span> <span class="nx">err</span> <span class="k">instanceof</span> <span class="nb">Error</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="s">&quot;ERROR: </span><span class="si">#{</span><span class="nx">err</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">compilePath</span></span> = (source, topLevel, base) -&gt;
fs.stat source, (err, stats) -&gt;
<span class="keyword">throw</span> err <span class="keyword">if</span> err <span class="keyword">and</span> err.code <span class="keyword">isnt</span> <span class="string">'ENOENT'</span>
<span class="keyword">if</span> err?.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
console.error <span class="string">"File not found: <span class="subst">#{source}</span>"</span>
process.exit <span class="number">1</span>
<span class="keyword">if</span> stats.isDirectory() <span class="keyword">and</span> path.dirname(source) <span class="keyword">isnt</span> <span class="string">'node_modules'</span>
watchDir source, base <span class="keyword">if</span> opts.watch
fs.readdir source, (err, files) -&gt;
<span class="keyword">throw</span> err <span class="keyword">if</span> err <span class="keyword">and</span> err.code <span class="keyword">isnt</span> <span class="string">'ENOENT'</span>
<span class="keyword">return</span> <span class="keyword">if</span> err?.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
index = sources.indexOf source
files = files.filter (file) -&gt; <span class="keyword">not</span> hidden file
sources[index..index] = (path.join source, file <span class="keyword">for</span> file <span class="keyword">in</span> files)
sourceCode[index..index] = files.map -&gt; <span class="literal">null</span>
files.forEach (file) -&gt;
compilePath (path.join source, file), <span class="literal">no</span>, base
<span class="keyword">else</span> <span class="keyword">if</span> topLevel <span class="keyword">or</span> helpers.isCoffee source
watch source, base <span class="keyword">if</span> opts.watch
fs.readFile source, (err, code) -&gt;
<span class="keyword">throw</span> err <span class="keyword">if</span> err <span class="keyword">and</span> err.code <span class="keyword">isnt</span> <span class="string">'ENOENT'</span>
<span class="keyword">return</span> <span class="keyword">if</span> err?.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
compileScript(source, code.toString(), base)
<span class="keyword">else</span>
notSources[source] = <span class="literal">yes</span>
removeSource source, base</pre></div></div>
</li>
@@ -374,21 +322,48 @@ requested options. If evaluating the script directly sets <code>__filename</code
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
and write them back to <strong>stdout</strong>.
<p>Compile a single source script, containing the given code, according to the
requested options. If evaluating the script directly sets <code>__filename</code>,
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the script&#39;s path.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">compileStdio = </span><span class="nf">-&gt;</span>
<span class="nv">code = </span><span class="s">&#39;&#39;</span>
<span class="nv">stdin = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span> <span class="s">&#39;data&#39;</span><span class="p">,</span> <span class="nf">(buffer) -&gt;</span>
<span class="nx">code</span> <span class="o">+=</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="k">if</span> <span class="nx">buffer</span>
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span> <span class="s">&#39;end&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span>
<span class="nx">compileScript</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">code</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">compileScript</span></span> = (file, input, base=<span class="literal">null</span>) -&gt;
o = opts
options = compileOptions file, base
<span class="keyword">try</span>
t = task = {file, input, options}
CoffeeScript.emit <span class="string">'compile'</span>, task
<span class="keyword">if</span> o.tokens <span class="keyword">then</span> printTokens CoffeeScript.tokens t.input, t.options
<span class="keyword">else</span> <span class="keyword">if</span> o.nodes <span class="keyword">then</span> printLine CoffeeScript.nodes(t.input, t.options).toString().trim()
<span class="keyword">else</span> <span class="keyword">if</span> o.run <span class="keyword">then</span> CoffeeScript.run t.input, t.options
<span class="keyword">else</span> <span class="keyword">if</span> o.join <span class="keyword">and</span> t.file <span class="keyword">isnt</span> o.join
t.input = helpers.invertLiterate t.input <span class="keyword">if</span> helpers.isLiterate file
sourceCode[sources.indexOf(t.file)] = t.input
compileJoin()
<span class="keyword">else</span>
compiled = CoffeeScript.compile t.input, t.options
t.output = compiled
<span class="keyword">if</span> o.map
t.output = compiled.js
t.sourceMap = compiled.v3SourceMap
CoffeeScript.emit <span class="string">'success'</span>, task
<span class="keyword">if</span> o.print
printLine t.output.trim()
<span class="keyword">else</span> <span class="keyword">if</span> o.compile <span class="keyword">or</span> o.map
writeJs base, t.file, t.output, options.jsPath, t.sourceMap
<span class="keyword">catch</span> err
CoffeeScript.emit <span class="string">'failure'</span>, err, task
<span class="keyword">return</span> <span class="keyword">if</span> CoffeeScript.listeners(<span class="string">'failure'</span>).length
useColors = process.stdout.isTTY <span class="keyword">and</span> <span class="keyword">not</span> process.env.NODE_DISABLE_COLORS
message = helpers.prettyErrorMessage err, file <span class="keyword">or</span> <span class="string">'[stdin]'</span>, input, useColors
<span class="keyword">if</span> o.watch
printLine message + <span class="string">'\x07'</span>
<span class="keyword">else</span>
printWarn message
process.exit <span class="number">1</span></pre></div></div>
</li>
@@ -399,21 +374,19 @@ and write them back to <strong>stdout</strong>.
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>If all of the source files are done being read, concatenate and compile
them together.
<p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
and write them back to <strong>stdout</strong>.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">joinTimeout = </span><span class="kc">null</span>
<span class="nv">compileJoin = </span><span class="nf">-&gt;</span>
<span class="k">return</span> <span class="k">unless</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
<span class="k">unless</span> <span class="nx">sourceCode</span><span class="p">.</span><span class="nx">some</span><span class="p">(</span><span class="nf">(code) -&gt;</span> <span class="nx">code</span> <span class="o">is</span> <span class="kc">null</span><span class="p">)</span>
<span class="nx">clearTimeout</span> <span class="nx">joinTimeout</span>
<span class="nv">joinTimeout = </span><span class="nx">wait</span> <span class="mi">100</span><span class="p">,</span> <span class="nf">-&gt;</span>
<span class="nx">compileScript</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span><span class="p">,</span> <span class="nx">sourceCode</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">&#39;\n&#39;</span><span class="p">),</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">compileStdio</span></span> = -&gt;
code = <span class="string">''</span>
stdin = process.openStdin()
stdin.<span class="literal">on</span> <span class="string">'data'</span>, (buffer) -&gt;
code += buffer.toString() <span class="keyword">if</span> buffer
stdin.<span class="literal">on</span> <span class="string">'end'</span>, -&gt;
compileScript <span class="literal">null</span>, code</pre></div></div>
</li>
@@ -424,52 +397,19 @@ them together.
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>Watch a source CoffeeScript file using <code>fs.watch</code>, recompiling it every
time the file is updated. May be used in combination with other options,
such as <code>--lint</code> or <code>--print</code>.
<p>If all of the source files are done being read, concatenate and compile
them together.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">watch = </span><span class="nf">(source, base) -&gt;</span>
<span class="nv">prevStats = </span><span class="kc">null</span>
<span class="nv">compileTimeout = </span><span class="kc">null</span>
<span class="nv">watchErr = </span><span class="nf">(e) -&gt;</span>
<span class="k">if</span> <span class="nx">e</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">is</span> <span class="o">-</span><span class="mi">1</span>
<span class="k">try</span>
<span class="nx">rewatch</span><span class="p">()</span>
<span class="nx">compile</span><span class="p">()</span>
<span class="k">catch</span> <span class="nx">e</span>
<span class="nx">removeSource</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span><span class="p">,</span> <span class="kc">yes</span>
<span class="nx">compileJoin</span><span class="p">()</span>
<span class="k">else</span> <span class="k">throw</span> <span class="nx">e</span>
<span class="nv">compile = </span><span class="nf">-&gt;</span>
<span class="nx">clearTimeout</span> <span class="nx">compileTimeout</span>
<span class="nv">compileTimeout = </span><span class="nx">wait</span> <span class="mi">25</span><span class="p">,</span> <span class="nf">-&gt;</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, stats) -&gt;</span>
<span class="k">return</span> <span class="nx">watchErr</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
<span class="k">return</span> <span class="nx">rewatch</span><span class="p">()</span> <span class="k">if</span> <span class="nx">prevStats</span> <span class="o">and</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">size</span> <span class="o">is</span> <span class="nx">prevStats</span><span class="p">.</span><span class="nx">size</span> <span class="o">and</span>
<span class="nx">stats</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">is</span> <span class="nx">prevStats</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span>
<span class="nv">prevStats = </span><span class="nx">stats</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, code) -&gt;</span>
<span class="k">return</span> <span class="nx">watchErr</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
<span class="nx">compileScript</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span>
<span class="nx">rewatch</span><span class="p">()</span>
<span class="k">try</span>
<span class="nv">watcher = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">compile</span>
<span class="k">catch</span> <span class="nx">e</span>
<span class="nx">watchErr</span> <span class="nx">e</span>
<span class="nv">rewatch = </span><span class="nf">-&gt;</span>
<span class="nx">watcher</span><span class="o">?</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span>
<span class="nv">watcher = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">compile</span></pre></div></div>
<div class="content"><div class='highlight'><pre>joinTimeout = <span class="literal">null</span>
<span class="function"><span class="title">compileJoin</span></span> = -&gt;
<span class="keyword">return</span> <span class="keyword">unless</span> opts.join
<span class="keyword">unless</span> sourceCode.some((code) -&gt; code <span class="keyword">is</span> <span class="literal">null</span>)
clearTimeout joinTimeout
joinTimeout = wait <span class="number">100</span>, -&gt;
compileScript opts.join, sourceCode.join(<span class="string">'\n'</span>), opts.join</pre></div></div>
</li>
@@ -480,39 +420,50 @@ such as <code>--lint</code> or <code>--print</code>.
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>Watch a directory of files for new additions.
<p>Watch a source CoffeeScript file using <code>fs.watch</code>, recompiling it every
time the file is updated. May be used in combination with other options,
such as <code>--print</code>.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">watchDir = </span><span class="nf">(source, base) -&gt;</span>
<span class="nv">readdirTimeout = </span><span class="kc">null</span>
<span class="k">try</span>
<span class="nv">watcher = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">-&gt;</span>
<span class="nx">clearTimeout</span> <span class="nx">readdirTimeout</span>
<span class="nv">readdirTimeout = </span><span class="nx">wait</span> <span class="mi">25</span><span class="p">,</span> <span class="nf">-&gt;</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readdir</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, files) -&gt;</span>
<span class="k">if</span> <span class="nx">err</span>
<span class="k">throw</span> <span class="nx">err</span> <span class="k">unless</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="nx">watcher</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">unwatchDir</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span>
<span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</span> <span class="k">when</span> <span class="o">not</span> <span class="nx">hidden</span><span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">notSources</span><span class="p">[</span><span class="nx">file</span><span class="p">]</span>
<span class="nv">file = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">file</span>
<span class="k">continue</span> <span class="k">if</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">some</span> <span class="nf">(s) -&gt;</span> <span class="nx">s</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span>
<span class="nx">sources</span><span class="p">.</span><span class="nx">push</span> <span class="nx">file</span>
<span class="nx">sourceCode</span><span class="p">.</span><span class="nx">push</span> <span class="kc">null</span>
<span class="nx">compilePath</span> <span class="nx">file</span><span class="p">,</span> <span class="kc">no</span><span class="p">,</span> <span class="nx">base</span>
<span class="k">catch</span> <span class="nx">e</span>
<span class="k">throw</span> <span class="nx">e</span> <span class="k">unless</span> <span class="nx">e</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">&#39;ENOENT&#39;</span>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">watch</span></span> = (source, base) -&gt;
<span class="nv">unwatchDir = </span><span class="nf">(source, base) -&gt;</span>
<span class="nv">prevSources = </span><span class="nx">sources</span><span class="p">[..]</span>
<span class="nv">toRemove = </span><span class="p">(</span><span class="nx">file</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">sources</span> <span class="k">when</span> <span class="nx">file</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span>
<span class="nx">removeSource</span> <span class="nx">file</span><span class="p">,</span> <span class="nx">base</span><span class="p">,</span> <span class="kc">yes</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">toRemove</span>
<span class="k">return</span> <span class="k">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">some</span> <span class="nf">(s, i) -&gt;</span> <span class="nx">prevSources</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">isnt</span> <span class="nx">s</span>
<span class="nx">compileJoin</span><span class="p">()</span></pre></div></div>
prevStats = <span class="literal">null</span>
compileTimeout = <span class="literal">null</span>
<span class="function"><span class="title">watchErr</span></span> = (e) -&gt;
<span class="keyword">if</span> e.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
<span class="keyword">return</span> <span class="keyword">if</span> sources.indexOf(source) <span class="keyword">is</span> -<span class="number">1</span>
<span class="keyword">try</span>
rewatch()
compile()
<span class="keyword">catch</span> e
removeSource source, base, <span class="literal">yes</span>
compileJoin()
<span class="keyword">else</span> <span class="keyword">throw</span> e
<span class="function"><span class="title">compile</span></span> = -&gt;
clearTimeout compileTimeout
compileTimeout = wait <span class="number">25</span>, -&gt;
fs.stat source, (err, stats) -&gt;
<span class="keyword">return</span> watchErr err <span class="keyword">if</span> err
<span class="keyword">return</span> rewatch() <span class="keyword">if</span> prevStats <span class="keyword">and</span> stats.size <span class="keyword">is</span> prevStats.size <span class="keyword">and</span>
stats.mtime.getTime() <span class="keyword">is</span> prevStats.mtime.getTime()
prevStats = stats
fs.readFile source, (err, code) -&gt;
<span class="keyword">return</span> watchErr err <span class="keyword">if</span> err
compileScript(source, code.toString(), base)
rewatch()
<span class="keyword">try</span>
watcher = fs.watch source, compile
<span class="keyword">catch</span> e
watchErr e
<span class="function"><span class="title">rewatch</span></span> = -&gt;
watcher?.close()
watcher = fs.watch source, compile</pre></div></div>
</li>
@@ -523,25 +474,37 @@ such as <code>--lint</code> or <code>--print</code>.
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>Remove a file from our source list, and source code cache. Optionally remove
the compiled JS version as well.
<p>Watch a directory of files for new additions.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">removeSource = </span><span class="nf">(source, base, removeJs) -&gt;</span>
<span class="nv">index = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">source</span>
<span class="nx">sources</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">index</span><span class="p">,</span> <span class="mi">1</span>
<span class="nx">sourceCode</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">index</span><span class="p">,</span> <span class="mi">1</span>
<span class="k">if</span> <span class="nx">removeJs</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
<span class="nv">jsPath = </span><span class="nx">outputPath</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span>
<span class="nx">exists</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nf">(itExists) -&gt;</span>
<span class="k">if</span> <span class="nx">itExists</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">unlink</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nf">(err) -&gt;</span>
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="nx">timeLog</span> <span class="s">&quot;removed </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">&quot;</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">watchDir</span></span> = (source, base) -&gt;
readdirTimeout = <span class="literal">null</span>
<span class="keyword">try</span>
watcher = fs.watch source, -&gt;
clearTimeout readdirTimeout
readdirTimeout = wait <span class="number">25</span>, -&gt;
fs.readdir source, (err, files) -&gt;
<span class="keyword">if</span> err
<span class="keyword">throw</span> err <span class="keyword">unless</span> err.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
watcher.close()
<span class="keyword">return</span> unwatchDir source, base
<span class="keyword">for</span> file <span class="keyword">in</span> files <span class="keyword">when</span> <span class="keyword">not</span> hidden(file) <span class="keyword">and</span> <span class="keyword">not</span> notSources[file]
file = path.join source, file
<span class="keyword">continue</span> <span class="keyword">if</span> sources.some (s) -&gt; s.indexOf(file) &gt;= <span class="number">0</span>
sources.push file
sourceCode.push <span class="literal">null</span>
compilePath file, <span class="literal">no</span>, base
<span class="keyword">catch</span> e
<span class="keyword">throw</span> e <span class="keyword">unless</span> e.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
<span class="function"><span class="title">unwatchDir</span></span> = (source, base) -&gt;
prevSources = sources[..]
toRemove = (file <span class="keyword">for</span> file <span class="keyword">in</span> sources <span class="keyword">when</span> file.indexOf(source) &gt;= <span class="number">0</span>)
removeSource file, base, <span class="literal">yes</span> <span class="keyword">for</span> file <span class="keyword">in</span> toRemove
<span class="keyword">return</span> <span class="keyword">unless</span> sources.some (s, i) -&gt; prevSources[i] <span class="keyword">isnt</span> s
compileJoin()</pre></div></div>
</li>
@@ -552,19 +515,23 @@ the compiled JS version as well.
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>Get the corresponding output JavaScript path for a source file.
<p>Remove a file from our source list, and source code cache. Optionally remove
the compiled JS version as well.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">outputPath = </span><span class="nf">(source, base, extension=&quot;.js&quot;) -&gt;</span>
<span class="nv">basename = </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">baseFileName</span> <span class="nx">source</span><span class="p">,</span> <span class="kc">yes</span>
<span class="nv">srcDir = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">source</span>
<span class="nv">baseDir = </span><span class="k">if</span> <span class="nx">base</span> <span class="o">is</span> <span class="s">&#39;.&#39;</span> <span class="k">then</span> <span class="nx">srcDir</span> <span class="k">else</span> <span class="nx">srcDir</span><span class="p">.</span><span class="nx">substring</span> <span class="nx">base</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">dir = </span><span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">output</span> <span class="k">then</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">baseDir</span> <span class="k">else</span> <span class="nx">srcDir</span>
<span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="nx">basename</span> <span class="o">+</span> <span class="nx">extension</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">removeSource</span></span> = (source, base, removeJs) -&gt;
index = sources.indexOf source
sources.splice index, <span class="number">1</span>
sourceCode.splice index, <span class="number">1</span>
<span class="keyword">if</span> removeJs <span class="keyword">and</span> <span class="keyword">not</span> opts.join
jsPath = outputPath source, base
exists jsPath, (itExists) -&gt;
<span class="keyword">if</span> itExists
fs.unlink jsPath, (err) -&gt;
<span class="keyword">throw</span> err <span class="keyword">if</span> err <span class="keyword">and</span> err.code <span class="keyword">isnt</span> <span class="string">'ENOENT'</span>
timeLog <span class="string">"removed <span class="subst">#{source}</span>"</span></pre></div></div>
</li>
@@ -575,38 +542,17 @@ the compiled JS version as well.
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>Write out a JavaScript source file with the compiled code. By default, files
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
directory can be customized with <code>--output</code>.
</p>
<p>If <code>generatedSourceMap</code> is provided, this will write a <code>.map</code> file into the
same directory as the <code>.js</code> file.
<p>Get the corresponding output JavaScript path for a source file.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">writeJs = </span><span class="nf">(base, sourcePath, js, generatedSourceMap = null) -&gt;</span>
<span class="nv">jsPath = </span><span class="nx">outputPath</span> <span class="nx">sourcePath</span><span class="p">,</span> <span class="nx">base</span>
<span class="nv">sourceMapPath = </span><span class="nx">outputPath</span> <span class="nx">sourcePath</span><span class="p">,</span> <span class="nx">base</span><span class="p">,</span> <span class="s">&quot;.map&quot;</span>
<span class="nv">jsDir = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">jsPath</span>
<span class="nv">compile = </span><span class="nf">-&gt;</span>
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span>
<span class="nv">js = </span><span class="s">&#39; &#39;</span> <span class="k">if</span> <span class="nx">js</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;=</span> <span class="mi">0</span>
<span class="k">if</span> <span class="nx">generatedSourceMap</span> <span class="k">then</span> <span class="nv">js = </span><span class="s">&quot;//@ sourceMappingURL=</span><span class="si">#{</span><span class="nx">helpers</span><span class="p">.</span><span class="nx">baseFileName</span> <span class="nx">sourceMapPath</span><span class="si">}</span><span class="s">\n</span><span class="si">#{</span><span class="nx">js</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="nf">(err) -&gt;</span>
<span class="k">if</span> <span class="nx">err</span>
<span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span> <span class="o">and</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">timeLog</span> <span class="s">&quot;compiled </span><span class="si">#{</span><span class="nx">sourcePath</span><span class="si">}</span><span class="s">&quot;</span>
<span class="k">if</span> <span class="nx">generatedSourceMap</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">sourceMapPath</span><span class="p">,</span> <span class="nx">generatedSourceMap</span><span class="p">,</span> <span class="nf">(err) -&gt;</span>
<span class="k">if</span> <span class="nx">err</span>
<span class="nx">printLine</span> <span class="s">&quot;Could not write source map: </span><span class="si">#{</span><span class="nx">err</span><span class="p">.</span><span class="nx">message</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">exists</span> <span class="nx">jsDir</span><span class="p">,</span> <span class="nf">(itExists) -&gt;</span>
<span class="k">if</span> <span class="nx">itExists</span> <span class="k">then</span> <span class="nx">compile</span><span class="p">()</span> <span class="k">else</span> <span class="nx">exec</span> <span class="s">&quot;mkdir -p </span><span class="si">#{</span><span class="nx">jsDir</span><span class="si">}</span><span class="s">&quot;</span><span class="p">,</span> <span class="nx">compile</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">outputPath</span></span> = (source, base, extension=<span class="string">".js"</span>) -&gt;
basename = helpers.baseFileName source, <span class="literal">yes</span>, useWinPathSep
srcDir = path.dirname source
baseDir = <span class="keyword">if</span> base <span class="keyword">is</span> <span class="string">'.'</span> <span class="keyword">then</span> srcDir <span class="keyword">else</span> srcDir.substring base.length
dir = <span class="keyword">if</span> opts.output <span class="keyword">then</span> path.join opts.output, baseDir <span class="keyword">else</span> srcDir
path.join dir, basename + extension</pre></div></div>
</li>
@@ -617,14 +563,35 @@ same directory as the <code>.js</code> file.
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>Convenience for cleaner setTimeouts.
<p>Write out a JavaScript source file with the compiled code. By default, files
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
directory can be customized with <code>--output</code>.
</p>
<p>If <code>generatedSourceMap</code> is provided, this will write a <code>.map</code> file into the
same directory as the <code>.js</code> file.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">wait = </span><span class="nf">(milliseconds, func) -&gt;</span> <span class="nx">setTimeout</span> <span class="nx">func</span><span class="p">,</span> <span class="nx">milliseconds</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">writeJs</span></span> = (base, sourcePath, js, jsPath, generatedSourceMap = <span class="literal">null</span>) -&gt;
sourceMapPath = outputPath sourcePath, base, <span class="string">".map"</span>
jsDir = path.dirname jsPath
<span class="function"><span class="title">compile</span></span> = -&gt;
<span class="keyword">if</span> opts.compile
js = <span class="string">' '</span> <span class="keyword">if</span> js.length &lt;= <span class="number">0</span>
<span class="keyword">if</span> generatedSourceMap <span class="keyword">then</span> js = <span class="string">"<span class="subst">#{js}</span>\n/*\n//@ sourceMappingURL=<span class="subst">#{helpers.baseFileName sourceMapPath, <span class="literal">no</span>, useWinPathSep}</span>\n*/\n"</span>
fs.writeFile jsPath, js, (err) -&gt;
<span class="keyword">if</span> err
printLine err.message
<span class="keyword">else</span> <span class="keyword">if</span> opts.compile <span class="keyword">and</span> opts.watch
timeLog <span class="string">"compiled <span class="subst">#{sourcePath}</span>"</span>
<span class="keyword">if</span> generatedSourceMap
fs.writeFile sourceMapPath, generatedSourceMap, (err) -&gt;
<span class="keyword">if</span> err
printLine <span class="string">"Could not write source map: <span class="subst">#{err.message}</span>"</span>
exists jsDir, (itExists) -&gt;
<span class="keyword">if</span> itExists <span class="keyword">then</span> compile() <span class="keyword">else</span> exec <span class="string">"mkdir -p <span class="subst">#{jsDir}</span>"</span>, compile</pre></div></div>
</li>
@@ -635,15 +602,12 @@ same directory as the <code>.js</code> file.
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>When watching scripts, it&#39;s useful to log changes with the timestamp.
<p>Convenience for cleaner setTimeouts.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">timeLog = </span><span class="nf">(message) -&gt;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">&quot;</span><span class="si">#{</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">).</span><span class="nx">toLocaleTimeString</span><span class="p">()</span><span class="si">}</span><span class="s"> - </span><span class="si">#{</span><span class="nx">message</span><span class="si">}</span><span class="s">&quot;</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">wait</span></span> = (milliseconds, func) -&gt; setTimeout func, milliseconds</pre></div></div>
</li>
@@ -654,22 +618,13 @@ same directory as the <code>.js</code> file.
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>Pipe compiled JS through JSLint (requires a working <code>jsl</code> command), printing
any errors or warnings that arise.
<p>When watching scripts, it&#39;s useful to log changes with the timestamp.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">lint = </span><span class="nf">(file, js) -&gt;</span>
<span class="nv">printIt = </span><span class="nf">(buffer) -&gt;</span> <span class="nx">printLine</span> <span class="nx">file</span> <span class="o">+</span> <span class="s">&#39;:\t&#39;</span> <span class="o">+</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span>
<span class="nv">conf = </span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s">&#39;/../../extras/jsl.conf&#39;</span>
<span class="nv">jsl = </span><span class="nx">spawn</span> <span class="s">&#39;jsl&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s">&#39;-nologo&#39;</span><span class="p">,</span> <span class="s">&#39;-stdin&#39;</span><span class="p">,</span> <span class="s">&#39;-conf&#39;</span><span class="p">,</span> <span class="nx">conf</span><span class="p">]</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">on</span> <span class="s">&#39;data&#39;</span><span class="p">,</span> <span class="nx">printIt</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">on</span> <span class="s">&#39;data&#39;</span><span class="p">,</span> <span class="nx">printIt</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">write</span> <span class="nx">js</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">end</span><span class="p">()</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">timeLog</span></span> = (message) -&gt;
console.log <span class="string">"<span class="subst">#{(<span class="keyword">new</span> Date).toLocaleTimeString()}</span> - <span class="subst">#{message}</span>"</span></pre></div></div>
</li>
@@ -680,19 +635,17 @@ any errors or warnings that arise.
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>Pretty-print a stream of tokens, sans location data.
<p>Pretty-print a stream of tokens, sans location data.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">printTokens = </span><span class="nf">(tokens) -&gt;</span>
<span class="nv">strings = </span><span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">tokens</span>
<span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="nv">value = </span><span class="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">toString</span><span class="p">().</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\n/</span><span class="p">,</span> <span class="s">&#39;\\n&#39;</span><span class="p">)</span>
<span class="s">&quot;[</span><span class="si">#{</span><span class="nx">tag</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s">]&quot;</span>
<span class="nx">printLine</span> <span class="nx">strings</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">&#39; &#39;</span><span class="p">)</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">printTokens</span></span> = (tokens) -&gt;
strings = <span class="keyword">for</span> token <span class="keyword">in</span> tokens
tag = token[<span class="number">0</span>]
value = token[<span class="number">1</span>].toString().replace(<span class="regexp">/\n/</span>, <span class="string">'\\n'</span>)
<span class="string">"[<span class="subst">#{tag}</span> <span class="subst">#{value}</span>]"</span>
printLine strings.join(<span class="string">' '</span>)</pre></div></div>
</li>
@@ -703,23 +656,21 @@ any errors or warnings that arise.
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
<p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
<code>process.argv</code> that are specified in <code>SWITCHES</code>.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">parseOptions = </span><span class="nf">-&gt;</span>
<span class="nv">optionParser = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span>
<span class="nv">o = opts = </span><span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">..]</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or=</span> <span class="o">!!</span><span class="nx">o</span><span class="p">.</span><span class="nx">output</span>
<span class="nv">o.run = </span><span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">map</span><span class="p">)</span>
<span class="nv">o.print = </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span>
<span class="nv">sources = </span><span class="nx">o</span><span class="p">.</span><span class="nx">arguments</span>
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="kc">null</span> <span class="k">for</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">sources</span>
<span class="k">return</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">parseOptions</span></span> = -&gt;
optionParser = <span class="keyword">new</span> optparse.OptionParser SWITCHES, BANNER
o = opts = optionParser.parse process.argv[<span class="number">2.</span>.]
o.compile <span class="keyword">or</span>= !!o.output
o.run = <span class="keyword">not</span> (o.compile <span class="keyword">or</span> o.print <span class="keyword">or</span> o.map)
o.print = !! (o.print <span class="keyword">or</span> (o.eval <span class="keyword">or</span> o.stdio <span class="keyword">and</span> o.compile))
sources = o.arguments
sourceCode[i] = <span class="literal">null</span> <span class="keyword">for</span> source, i <span class="keyword">in</span> sources
<span class="keyword">return</span></pre></div></div>
</li>
@@ -730,21 +681,36 @@ any errors or warnings that arise.
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
</div>
<p>The compile-time options to pass to the CoffeeScript compiler.
<p>The compile-time options to pass to the CoffeeScript compiler.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">compileOptions = </span><span class="nf">(filename) -&gt;</span>
<span class="p">{</span>
<span class="nx">filename</span>
<span class="nv">literate: </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">isLiterate</span><span class="p">(</span><span class="nx">filename</span><span class="p">)</span>
<span class="nv">bare: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">bare</span>
<span class="nv">header: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span>
<span class="nv">sourceMap: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">map</span>
<span class="p">}</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">compileOptions</span></span> = (filename, base) -&gt;
answer = {
filename
literate: opts.literate <span class="keyword">or</span> helpers.isLiterate(filename)
bare: opts.bare
header: opts.compile
sourceMap: opts.map
}
<span class="keyword">if</span> filename
<span class="keyword">if</span> base
cwd = process.cwd()
jsPath = outputPath filename, base
jsDir = path.dirname jsPath
answer = helpers.merge answer, {
jsPath
sourceRoot: path.relative jsDir, cwd
sourceFiles: [path.relative cwd, filename]
generatedFile: helpers.baseFileName(jsPath, <span class="literal">no</span>, useWinPathSep)
}
<span class="keyword">else</span>
answer = helpers.merge answer,
sourceRoot: <span class="string">""</span>
sourceFiles: [helpers.baseFileName filename, <span class="literal">no</span>, useWinPathSep]
generatedFile: helpers.baseFileName(filename, <span class="literal">yes</span>, useWinPathSep) + <span class="string">".js"</span>
answer</pre></div></div>
</li>
@@ -755,22 +721,20 @@ any errors or warnings that arise.
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
</div>
<p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
<p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
the <code>node</code> binary, preserving the other options.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">forkNode = </span><span class="nf">-&gt;</span>
<span class="nv">nodeArgs = </span><span class="nx">opts</span><span class="p">.</span><span class="nx">nodejs</span><span class="p">.</span><span class="nx">split</span> <span class="sr">/\s+/</span>
<span class="nv">args = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">..]</span>
<span class="nx">args</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">args</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s">&#39;--nodejs&#39;</span><span class="p">),</span> <span class="mi">2</span>
<span class="nx">spawn</span> <span class="nx">process</span><span class="p">.</span><span class="nx">execPath</span><span class="p">,</span> <span class="nx">nodeArgs</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">args</span><span class="p">),</span>
<span class="nv">cwd: </span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
<span class="nv">env: </span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span>
<span class="nv">customFds: </span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">forkNode</span></span> = -&gt;
nodeArgs = opts.nodejs.split <span class="regexp">/\s+/</span>
args = process.argv[<span class="number">1.</span>.]
args.splice args.indexOf(<span class="string">'--nodejs'</span>), <span class="number">2</span>
spawn process.execPath, nodeArgs.concat(args),
cwd: process.cwd()
env: process.env
customFds: [<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>]</pre></div></div>
</li>
@@ -781,16 +745,14 @@ the <code>node</code> binary, preserving the other options.
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
<p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
shown.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">usage = </span><span class="nf">-&gt;</span>
<span class="nx">printLine</span> <span class="p">(</span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span><span class="p">).</span><span class="nx">help</span><span class="p">()</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">usage</span></span> = -&gt;
printLine (<span class="keyword">new</span> optparse.OptionParser SWITCHES, BANNER).help()</pre></div></div>
</li>
@@ -801,16 +763,13 @@ shown.
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<p>Print the <code>--version</code> message and exit.
<p>Print the <code>--version</code> message and exit.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">version = </span><span class="nf">-&gt;</span>
<span class="nx">printLine</span> <span class="s">&quot;CoffeeScript version </span><span class="si">#{</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">VERSION</span><span class="si">}</span><span class="s">&quot;</span>
</pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">version</span></span> = -&gt;
printLine <span class="string">"CoffeeScript version <span class="subst">#{CoffeeScript.VERSION}</span>"</span></pre></div></div>
</li>

View File

@@ -51,9 +51,17 @@ b, strong {
font-family: "aller-bold";
}
p, ul, ol {
p {
margin: 15px 0 0px;
}
.annotation ul, .annotation ol {
margin: 25px 0;
}
.annotation ul li, .annotation ol li {
font-size: 14px;
line-height: 18px;
margin: 10px 0;
}
h1, h2, h3, h4, h5, h6 {
color: #112233;
@@ -99,12 +107,12 @@ pre, tt, code {
blockquote {
border-left: 5px solid #ccc;
margin-left: 0;
margin: 0;
padding: 1px 0 1px 1em;
}
.sections blockquote p {
font-family: Menlo, Consolas, Monaco, monospace;
font-size: 14px; line-height: 19px;
font-size: 12px; line-height: 16px;
color: #999;
margin: 10px 0 0;
white-space: pre-wrap;
@@ -361,66 +369,141 @@ ul.sections > li > div {
}
/*---------------------- Syntax Highlighting -----------------------------*/
td.linenos { background-color: #f0f0f0; padding-right: 10px; }
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
body .hll { background-color: #ffffcc }
body .c { color: #408080; font-style: italic } /* Comment */
body .err { border: 1px solid #FF0000 } /* Error */
body .k { color: #954121 } /* Keyword */
body .o { color: #666666 } /* Operator */
body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
body .cp { color: #BC7A00 } /* Comment.Preproc */
body .c1 { color: #408080; font-style: italic } /* Comment.Single */
body .cs { color: #408080; font-style: italic } /* Comment.Special */
body .gd { color: #A00000 } /* Generic.Deleted */
body .ge { font-style: italic } /* Generic.Emph */
body .gr { color: #FF0000 } /* Generic.Error */
body .gh { color: #000080; font-weight: bold } /* Generic.Heading */
body .gi { color: #00A000 } /* Generic.Inserted */
body .go { color: #808080 } /* Generic.Output */
body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
body .gs { font-weight: bold } /* Generic.Strong */
body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
body .gt { color: #0040D0 } /* Generic.Traceback */
body .kc { color: #954121 } /* Keyword.Constant */
body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */
body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */
body .kp { color: #954121 } /* Keyword.Pseudo */
body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */
body .kt { color: #B00040 } /* Keyword.Type */
body .m { color: #666666 } /* Literal.Number */
body .s { color: #219161 } /* Literal.String */
body .na { color: #7D9029 } /* Name.Attribute */
body .nb { color: #954121 } /* Name.Builtin */
body .nc { color: #0000FF; font-weight: bold } /* Name.Class */
body .no { color: #880000 } /* Name.Constant */
body .nd { color: #AA22FF } /* Name.Decorator */
body .ni { color: #999999; font-weight: bold } /* Name.Entity */
body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
body .nf { color: #0000FF } /* Name.Function */
body .nl { color: #A0A000 } /* Name.Label */
body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
body .nt { color: #954121; font-weight: bold } /* Name.Tag */
body .nv { color: #19469D } /* Name.Variable */
body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
body .w { color: #bbbbbb } /* Text.Whitespace */
body .mf { color: #666666 } /* Literal.Number.Float */
body .mh { color: #666666 } /* Literal.Number.Hex */
body .mi { color: #666666 } /* Literal.Number.Integer */
body .mo { color: #666666 } /* Literal.Number.Oct */
body .sb { color: #219161 } /* Literal.String.Backtick */
body .sc { color: #219161 } /* Literal.String.Char */
body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
body .s2 { color: #219161 } /* Literal.String.Double */
body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
body .sh { color: #219161 } /* Literal.String.Heredoc */
body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
body .sx { color: #954121 } /* Literal.String.Other */
body .sr { color: #BB6688 } /* Literal.String.Regex */
body .s1 { color: #219161 } /* Literal.String.Single */
body .ss { color: #19469D } /* Literal.String.Symbol */
body .bp { color: #954121 } /* Name.Builtin.Pseudo */
body .vc { color: #19469D } /* Name.Variable.Class */
body .vg { color: #19469D } /* Name.Variable.Global */
body .vi { color: #19469D } /* Name.Variable.Instance */
body .il { color: #666666 } /* Literal.Number.Integer.Long */
/*
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
*/
pre code {
display: block; padding: 0.5em;
color: #000;
background: #f8f8ff
}
pre .comment,
pre .template_comment,
pre .diff .header,
pre .javadoc {
color: #408080;
font-style: italic
}
pre .keyword,
pre .assignment,
pre .literal,
pre .css .rule .keyword,
pre .winutils,
pre .javascript .title,
pre .lisp .title,
pre .subst,
pre .reserved {
color: #954121;
/*font-weight: bold*/
}
pre .number,
pre .hexcolor {
color: #40a070
}
pre .string,
pre .tag .value,
pre .phpdoc,
pre .tex .formula {
color: #219161;
}
pre .title,
pre .id {
color: #19469D;
}
pre .params {
color: #00F;
}
pre .javascript .title,
pre .lisp .title,
pre .subst {
font-weight: normal
}
pre .class .title,
pre .haskell .label,
pre .tex .command {
color: #458;
font-weight: bold
}
pre .tag,
pre .tag .title,
pre .rules .property,
pre .django .tag .keyword {
color: #000080;
font-weight: normal
}
pre .attribute,
pre .variable,
pre .instancevar,
pre .lisp .body {
color: #008080
}
pre .regexp {
color: #B68
}
pre .class {
color: #458;
font-weight: bold
}
pre .symbol,
pre .ruby .symbol .string,
pre .ruby .symbol .keyword,
pre .ruby .symbol .keymethods,
pre .lisp .keyword,
pre .tex .special,
pre .input_number {
color: #990073
}
pre .builtin,
pre .constructor,
pre .built_in,
pre .lisp .title {
color: #0086b3
}
pre .preprocessor,
pre .pi,
pre .doctype,
pre .shebang,
pre .cdata {
color: #999;
font-weight: bold
}
pre .deletion {
background: #fdd
}
pre .addition {
background: #dfd
}
pre .diff .change {
background: #0086b3
}
pre .chunk {
color: #aaa
}
pre .tex .formula {
opacity: 0.5;
}

File diff suppressed because it is too large Load Diff

View File

@@ -85,7 +85,7 @@
<a class="source" href="sourcemap.html">
sourcemap.coffee
sourcemap.litcoffee
</a>
</div>
@@ -111,17 +111,10 @@
<p>This file contains the common helper functions that we&#39;d like to share among
the <strong>Lexer</strong>, <strong>Rewriter</strong>, and the <strong>Nodes</strong>. Merge objects, flatten
arrays, count characters, that sort of thing.
</p>
<p>Peek at the beginning of a given string to see if it matches a sequence.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.starts = </span><span class="nf">(string, literal, start) -&gt;</span>
<span class="nx">literal</span> <span class="o">is</span> <span class="nx">string</span><span class="p">.</span><span class="nx">substr</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span></pre></div></div>
</li>
@@ -131,16 +124,13 @@ arrays, count characters, that sort of thing.
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>Peek at the end of a given string to see if it matches a sequence.
<p>Peek at the beginning of a given string to see if it matches a sequence.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.ends = </span><span class="nf">(string, literal, back) -&gt;</span>
<span class="nv">len = </span><span class="nx">literal</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">literal</span> <span class="o">is</span> <span class="nx">string</span><span class="p">.</span><span class="nx">substr</span> <span class="nx">string</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="nx">len</span> <span class="o">-</span> <span class="p">(</span><span class="nx">back</span> <span class="o">or</span> <span class="mi">0</span><span class="p">),</span> <span class="nx">len</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">starts</span></span> = (string, literal, start) -&gt;
literal <span class="keyword">is</span> string.substr start, literal.length</pre></div></div>
</li>
@@ -151,15 +141,14 @@ arrays, count characters, that sort of thing.
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>Trim out all falsy values from an array.
<p>Peek at the end of a given string to see if it matches a sequence.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.compact = </span><span class="nf">(array) -&gt;</span>
<span class="nx">item</span> <span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span> <span class="k">when</span> <span class="nx">item</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">ends</span></span> = (string, literal, back) -&gt;
len = literal.length
literal <span class="keyword">is</span> string.substr string.length - len - (back <span class="keyword">or</span> <span class="number">0</span>), len</pre></div></div>
</li>
@@ -170,18 +159,12 @@ arrays, count characters, that sort of thing.
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>Count the number of occurrences of a string in a string.
<p>Repeat a string <code>n</code> times.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.count = </span><span class="nf">(string, substr) -&gt;</span>
<span class="nv">num = pos = </span><span class="mi">0</span>
<span class="k">return</span> <span class="mi">1</span><span class="o">/</span><span class="mi">0</span> <span class="k">unless</span> <span class="nx">substr</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">num</span><span class="o">++</span> <span class="k">while</span> <span class="nv">pos = </span><span class="mi">1</span> <span class="o">+</span> <span class="nx">string</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">substr</span><span class="p">,</span> <span class="nx">pos</span>
<span class="nx">num</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.repeat = <span class="function"><span class="title">repeat</span></span> = (str, n) -&gt;</pre></div></div>
</li>
@@ -192,17 +175,17 @@ arrays, count characters, that sort of thing.
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>Merge objects, returning a fresh copy with attributes from both sides.
Used every time <code>Base#compile</code> is called, to allow properties in the
options hash to propagate down the tree without polluting other branches.
<p>Use clever algorithm to have O(log(n)) string concatenation operations.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.merge = </span><span class="nf">(options, overrides) -&gt;</span>
<span class="nx">extend</span> <span class="p">(</span><span class="nx">extend</span> <span class="p">{},</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">overrides</span></pre></div></div>
<div class="content"><div class='highlight'><pre> res = <span class="string">''</span>
<span class="keyword">while</span> n &gt; <span class="number">0</span>
res += str <span class="keyword">if</span> n &amp; <span class="number">1</span>
n &gt;&gt;&gt;= <span class="number">1</span>
str += str
res</pre></div></div>
</li>
@@ -213,17 +196,13 @@ options hash to propagate down the tree without polluting other branches.
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>Extend a source object with the properties of another object (shallow copy).
<p>Trim out all falsy values from an array.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">extend = exports.extend = </span><span class="nf">(object, properties) -&gt;</span>
<span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">properties</span>
<span class="nx">object</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span>
<span class="nx">object</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">compact</span></span> = (array) -&gt;
item <span class="keyword">for</span> item <span class="keyword">in</span> array <span class="keyword">when</span> item</pre></div></div>
</li>
@@ -234,22 +213,16 @@ options hash to propagate down the tree without polluting other branches.
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Return a flattened version of an array.
Handy for getting a list of <code>children</code> from the nodes.
<p>Count the number of occurrences of a string in a string.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.flatten = flatten = </span><span class="nf">(array) -&gt;</span>
<span class="nv">flattened = </span><span class="p">[]</span>
<span class="k">for</span> <span class="nx">element</span> <span class="k">in</span> <span class="nx">array</span>
<span class="k">if</span> <span class="nx">element</span> <span class="k">instanceof</span> <span class="nb">Array</span>
<span class="nv">flattened = </span><span class="nx">flattened</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">flatten</span> <span class="nx">element</span>
<span class="k">else</span>
<span class="nx">flattened</span><span class="p">.</span><span class="nx">push</span> <span class="nx">element</span>
<span class="nx">flattened</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">count</span></span> = (string, substr) -&gt;
num = pos = <span class="number">0</span>
<span class="keyword">return</span> <span class="number">1</span>/<span class="number">0</span> <span class="keyword">unless</span> substr.length
num++ <span class="keyword">while</span> pos = <span class="number">1</span> + string.indexOf substr, pos
num</pre></div></div>
</li>
@@ -260,18 +233,15 @@ Handy for getting a list of <code>children</code> from the nodes.
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Delete a key from an object, returning the value. Useful when a node is
looking for a particular method in an options hash.
<p>Merge objects, returning a fresh copy with attributes from both sides.
Used every time <code>Base#compile</code> is called, to allow properties in the
options hash to propagate down the tree without polluting other branches.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.del = </span><span class="nf">(obj, key) -&gt;</span>
<span class="nv">val = </span> <span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
<span class="k">delete</span> <span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
<span class="nx">val</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">merge</span></span> = (options, overrides) -&gt;
extend (extend {}, options), overrides</pre></div></div>
</li>
@@ -282,14 +252,15 @@ looking for a particular method in an options hash.
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>Gets the last item of an array(-like) object.
<p>Extend a source object with the properties of another object (shallow copy).
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.last = </span><span class="nf">(array, back) -&gt;</span> <span class="nx">array</span><span class="p">[</span><span class="nx">array</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="nx">back</span> <span class="o">or</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span></pre></div></div>
<div class="content"><div class='highlight'><pre>extend = exports.<span class="function"><span class="title">extend</span></span> = (object, properties) -&gt;
<span class="keyword">for</span> key, val <span class="keyword">of</span> properties
object[key] = val
object</pre></div></div>
</li>
@@ -300,16 +271,20 @@ looking for a particular method in an options hash.
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>Typical Array::some
<p>Return a flattened version of an array.
Handy for getting a list of <code>children</code> from the nodes.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.some = </span><span class="nb">Array</span><span class="o">::</span><span class="nx">some</span> <span class="o">?</span> <span class="nf">(fn) -&gt;</span>
<span class="k">return</span> <span class="kc">true</span> <span class="k">for</span> <span class="nx">e</span> <span class="k">in</span> <span class="k">this</span> <span class="k">when</span> <span class="nx">fn</span> <span class="nx">e</span>
<span class="kc">false</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.flatten = <span class="function"><span class="title">flatten</span></span> = (array) -&gt;
flattened = []
<span class="keyword">for</span> element <span class="keyword">in</span> array
<span class="keyword">if</span> element <span class="keyword">instanceof</span> Array
flattened = flattened.concat flatten element
<span class="keyword">else</span>
flattened.push element
flattened</pre></div></div>
</li>
@@ -320,22 +295,16 @@ looking for a particular method in an options hash.
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>Merge two jison-style location data objects together.
If <code>last</code> is not provided, this will simply return <code>first</code>.
<p>Delete a key from an object, returning the value. Useful when a node is
looking for a particular method in an options hash.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">buildLocationData = </span><span class="nf">(first, last) -&gt;</span>
<span class="k">if</span> <span class="o">not</span> <span class="nx">last</span>
<span class="nx">first</span>
<span class="k">else</span>
<span class="nv">first_line: </span><span class="nx">first</span><span class="p">.</span><span class="nx">first_line</span>
<span class="nv">first_column: </span><span class="nx">first</span><span class="p">.</span><span class="nx">first_column</span>
<span class="nv">last_line: </span><span class="nx">last</span><span class="p">.</span><span class="nx">last_line</span>
<span class="nv">last_column: </span><span class="nx">last</span><span class="p">.</span><span class="nx">last_column</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">del</span></span> = (obj, key) -&gt;
val = obj[key]
<span class="keyword">delete</span> obj[key]
val</pre></div></div>
</li>
@@ -346,20 +315,12 @@ If <code>last</code> is not provided, this will simply return <code>first</code>
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>This returns a function which takes an object as a parameter, and if that object is an AST node,
updates that object&#39;s locationData. The object is returned either way.
<p>Gets the last item of an array(-like) object.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.addLocationDataFn = </span><span class="nf">(first, last) -&gt;</span>
<span class="nf">(obj) -&gt;</span>
<span class="k">if</span> <span class="p">((</span><span class="k">typeof</span> <span class="nx">obj</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;object&#39;</span><span class="p">)</span> <span class="o">and</span> <span class="p">(</span><span class="o">!!</span><span class="nx">obj</span><span class="p">[</span><span class="s">&#39;updateLocationDataIfMissing&#39;</span><span class="p">])</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">updateLocationDataIfMissing</span> <span class="nx">buildLocationData</span><span class="p">(</span><span class="nx">first</span><span class="p">,</span> <span class="nx">last</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">obj</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.last = <span class="function"><span class="title">last</span></span> = (array, back) -&gt; array[array.length - (back <span class="keyword">or</span> <span class="number">0</span>) - <span class="number">1</span>]</pre></div></div>
</li>
@@ -370,23 +331,14 @@ updates that object&#39;s locationData. The object is returned either way.
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>Convert jison location data to a string.
<code>obj</code> can be a token, or a locationData.
<p>Typical Array::some
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.locationDataToString = </span><span class="nf">(obj) -&gt;</span>
<span class="k">if</span> <span class="p">(</span><span class="s">&quot;2&quot;</span> <span class="k">of</span> <span class="nx">obj</span><span class="p">)</span> <span class="o">and</span> <span class="p">(</span><span class="s">&quot;first_line&quot;</span> <span class="k">of</span> <span class="nx">obj</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="k">then</span> <span class="nv">locationData = </span><span class="nx">obj</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
<span class="k">else</span> <span class="k">if</span> <span class="s">&quot;first_line&quot;</span> <span class="k">of</span> <span class="nx">obj</span> <span class="k">then</span> <span class="nv">locationData = </span><span class="nx">obj</span>
<span class="k">if</span> <span class="nx">locationData</span>
<span class="s">&quot;</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">first_line</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">:</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">first_column</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">-&quot;</span> <span class="o">+</span>
<span class="s">&quot;</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">last_line</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">:</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">last_column</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">&quot;</span>
<span class="k">else</span>
<span class="s">&quot;No location data&quot;</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.some = Array::some ? (fn) -&gt;
<span class="keyword">return</span> <span class="literal">true</span> <span class="keyword">for</span> e <span class="keyword">in</span> <span class="keyword">this</span> <span class="keyword">when</span> fn e
<span class="literal">false</span></pre></div></div>
</li>
@@ -397,21 +349,23 @@ updates that object&#39;s locationData. The object is returned either way.
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>A <code>.coffee.md</code> compatible version of <code>basename</code>, that returns the file sans-extension.
<p>Simple function for inverting Literate CoffeeScript code by putting the
documentation in comments, producing a string of CoffeeScript code that
can be compiled &quot;normally&quot;.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.baseFileName = </span><span class="nf">(file, stripExt = no) -&gt;</span>
<span class="nv">parts = </span><span class="nx">file</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="nv">file = </span><span class="nx">parts</span><span class="p">[</span><span class="nx">parts</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<span class="k">return</span> <span class="nx">file</span> <span class="k">unless</span> <span class="nx">stripExt</span>
<span class="nv">parts = </span><span class="nx">file</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s">&#39;.&#39;</span><span class="p">)</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">parts</span><span class="p">[</span><span class="nx">parts</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">is</span> <span class="s">&#39;coffee&#39;</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">&#39;.&#39;</span><span class="p">)</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">invertLiterate</span></span> = (code) -&gt;
maybe_code = <span class="literal">true</span>
lines = <span class="keyword">for</span> line <span class="keyword">in</span> code.split(<span class="string">'\n'</span>)
<span class="keyword">if</span> maybe_code <span class="keyword">and</span> <span class="regexp">/^([ ]{4}|[ ]{0,3}\t)/</span>.test line
line
<span class="keyword">else</span> <span class="keyword">if</span> maybe_code = <span class="regexp">/^\s*$/</span>.test line
line
<span class="keyword">else</span>
<span class="string">'# '</span> + line
lines.join <span class="string">'\n'</span></pre></div></div>
</li>
@@ -422,14 +376,20 @@ updates that object&#39;s locationData. The object is returned either way.
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>Determine if a filename represents a CoffeeScript file.
<p>Merge two jison-style location data objects together.
If <code>last</code> is not provided, this will simply return <code>first</code>.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.isCoffee = </span><span class="nf">(file) -&gt;</span> <span class="o">/</span><span class="err">\</span><span class="p">.((</span><span class="nx">lit</span><span class="p">)</span><span class="o">?</span><span class="nx">coffee</span><span class="o">|</span><span class="nx">coffee</span><span class="err">\</span><span class="p">.</span><span class="nx">md</span><span class="p">)</span><span class="nx">$</span><span class="o">/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">file</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">buildLocationData</span></span> = (first, last) -&gt;
<span class="keyword">if</span> <span class="keyword">not</span> last
first
<span class="keyword">else</span>
first_line: first.first_line
first_column: first.first_column
last_line: last.last_line
last_column: last.last_column</pre></div></div>
</li>
@@ -440,15 +400,192 @@ updates that object&#39;s locationData. The object is returned either way.
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>Determine if a filename represents a Literate CoffeeScript file.
<p>This returns a function which takes an object as a parameter, and if that
object is an AST node, updates that object&#39;s locationData.
The object is returned either way.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.isLiterate = </span><span class="nf">(file) -&gt;</span> <span class="o">/</span><span class="err">\</span><span class="p">.(</span><span class="nx">litcoffee</span><span class="o">|</span><span class="nx">coffee</span><span class="err">\</span><span class="p">.</span><span class="nx">md</span><span class="p">)</span><span class="nx">$</span><span class="o">/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">file</span>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">addLocationDataFn</span></span> = (first, last) -&gt;
(obj) -&gt;
<span class="keyword">if</span> ((<span class="keyword">typeof</span> obj) <span class="keyword">is</span> <span class="string">'object'</span>) <span class="keyword">and</span> (!!obj[<span class="string">'updateLocationDataIfMissing'</span>])
obj.updateLocationDataIfMissing buildLocationData(first, last)
</pre></div></div>
<span class="keyword">return</span> obj</pre></div></div>
</li>
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>Convert jison location data to a string.
<code>obj</code> can be a token, or a locationData.
</p>
</div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">locationDataToString</span></span> = (obj) -&gt;
<span class="keyword">if</span> (<span class="string">"2"</span> <span class="keyword">of</span> obj) <span class="keyword">and</span> (<span class="string">"first_line"</span> <span class="keyword">of</span> obj[<span class="number">2</span>]) <span class="keyword">then</span> locationData = obj[<span class="number">2</span>]
<span class="keyword">else</span> <span class="keyword">if</span> <span class="string">"first_line"</span> <span class="keyword">of</span> obj <span class="keyword">then</span> locationData = obj
<span class="keyword">if</span> locationData
<span class="string">"<span class="subst">#{locationData.first_line + <span class="number">1</span>}</span>:<span class="subst">#{locationData.first_column + <span class="number">1</span>}</span>-"</span> +
<span class="string">"<span class="subst">#{locationData.last_line + <span class="number">1</span>}</span>:<span class="subst">#{locationData.last_column + <span class="number">1</span>}</span>"</span>
<span class="keyword">else</span>
<span class="string">"No location data"</span></pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>A <code>.coffee.md</code> compatible version of <code>basename</code>, that returns the file sans-extension.
</p>
</div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">baseFileName</span></span> = (file, stripExt = <span class="literal">no</span>, useWinPathSep = <span class="literal">no</span>) -&gt;
pathSep = <span class="keyword">if</span> useWinPathSep <span class="keyword">then</span> <span class="regexp">/\\|\// else /\//</span>
parts = file.split(pathSep)
file = parts[parts.length - <span class="number">1</span>]
<span class="keyword">return</span> file <span class="keyword">unless</span> stripExt
parts = file.split(<span class="string">'.'</span>)
parts.pop()
parts.pop() <span class="keyword">if</span> parts[parts.length - <span class="number">1</span>] <span class="keyword">is</span> <span class="string">'coffee'</span> <span class="keyword">and</span> parts.length &gt; <span class="number">1</span>
parts.join(<span class="string">'.'</span>)</pre></div></div>
</li>
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>Determine if a filename represents a CoffeeScript file.
</p>
</div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">isCoffee</span></span> = (file) -&gt; <span class="regexp">/\.((lit)?coffee|coffee\.md)$/</span>.test file</pre></div></div>
</li>
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<p>Determine if a filename represents a Literate CoffeeScript file.
</p>
</div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">isLiterate</span></span> = (file) -&gt; <span class="regexp">/\.(litcoffee|coffee\.md)$/</span>.test file</pre></div></div>
</li>
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
</div>
<p>Throws a SyntaxError with a source file location data attached to it in a
property called <code>location</code>.
</p>
</div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">throwSyntaxError</span></span> = (message, location) -&gt;
location.last_line ?= location.first_line
location.last_column ?= location.first_column
error = <span class="keyword">new</span> SyntaxError message
error.location = location
<span class="keyword">throw</span> error</pre></div></div>
</li>
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
</div>
<p>Creates a nice error message like, following the &quot;standard&quot; format
</p>
<p><filename>:<line>:<col>: <message> plus the line with the error and a marker
showing where the error is.
</p>
</div>
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">prettyErrorMessage</span></span> = (error, fileName, code, useColors) -&gt;
<span class="keyword">return</span> error.stack <span class="keyword">or</span> <span class="string">"<span class="subst">#{error}</span>"</span> <span class="keyword">unless</span> error.location
{first_line, first_column, last_line, last_column} = error.location
codeLine = code.split(<span class="string">'\n'</span>)[first_line]
start = first_column</pre></div></div>
</li>
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>Show only the first line on multi-line errors.
</p>
</div>
<div class="content"><div class='highlight'><pre> end = <span class="keyword">if</span> first_line <span class="keyword">is</span> last_line <span class="keyword">then</span> last_column + <span class="number">1</span> <span class="keyword">else</span> codeLine.length
marker = repeat(<span class="string">' '</span>, start) + repeat(<span class="string">'^'</span>, end - start)
<span class="keyword">if</span> useColors
<span class="function"><span class="title">colorize</span></span> = (str) -&gt; <span class="string">"\x1B[1;31m<span class="subst">#{str}</span>\x1B[0m"</span>
codeLine = codeLine[...start] + colorize(codeLine[start...end]) + codeLine[end..]
marker = colorize marker
message = <span class="string">"""
<span class="subst">#{fileName}</span>:<span class="subst">#{first_line + <span class="number">1</span>}</span>:<span class="subst">#{first_column + <span class="number">1</span>}</span>: error: <span class="subst">#{error.message}</span>
<span class="subst">#{codeLine}</span>
<span class="subst">#{marker}</span>
"""</span></pre></div></div>
</li>
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<p>Uncomment to add stacktrace.
message += &quot;\n#{error.stack}&quot;
</p>
</div>
<div class="content"><div class='highlight'><pre>
message</pre></div></div>
</li>

View File

@@ -85,7 +85,7 @@
<a class="source" href="sourcemap.html">
sourcemap.coffee
sourcemap.litcoffee
</a>
</div>
@@ -113,9 +113,7 @@
</div>
<div class="content"><div class="highlight"><pre><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">require</span> <span class="s">&#39;./coffee-script&#39;</span>
</pre></div></div>
<div class="content"><div class='highlight'><pre>exports[key] = val <span class="keyword">for</span> key, val <span class="keyword">of</span> require <span class="string">'./coffee-script'</span></pre></div></div>
</li>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -85,7 +85,7 @@
<a class="source" href="sourcemap.html">
sourcemap.coffee
sourcemap.litcoffee
</a>
</div>
@@ -108,20 +108,10 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
</div>
<p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line.
Use it like so:
</p>
<pre><code>parser = new OptionParser switches, helpBanner
options = parser.parse process.argv</code></pre>
<p>The first non-option is considered to be the start of the file (and file
option) list, and all subsequent arguments are left unparsed.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.OptionParser = </span><span class="k">class</span> <span class="nx">OptionParser</span></pre></div></div>
<div class="content"><div class='highlight'><pre>{repeat} = require <span class="string">'./helpers'</span></pre></div></div>
</li>
@@ -132,19 +122,19 @@ option) list, and all subsequent arguments are left unparsed.
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>Initialize with a list of valid options, in the form:
<p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line.
Use it like so:
</p>
<pre><code>[short-flag, long-flag, description]</code></pre>
<p>Along with an an optional banner for the usage help.
<pre><code>parser = new OptionParser switches, helpBanner
options = parser.parse process.argv</code></pre>
<p>The first non-option is considered to be the start of the file (and file
option) list, and all subsequent arguments are left unparsed.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">constructor: </span><span class="nf">(rules, @banner) -&gt;</span>
<span class="vi">@rules = </span><span class="nx">buildRules</span> <span class="nx">rules</span></pre></div></div>
<div class="content"><div class='highlight'><pre>exports.OptionParser = <span class="class"><span class="keyword">class</span> <span class="title">OptionParser</span></span></pre></div></div>
</li>
@@ -155,32 +145,17 @@ option) list, and all subsequent arguments are left unparsed.
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>Parse the list of arguments, populating an <code>options</code> object with all of the
specified options, and return it. Options after the first non-option
argument are treated as arguments. <code>options.arguments</code> will be an array
containing the remaining arguments. This is a simpler API than many option
parsers that allow you to attach callback actions for every flag. Instead,
you&#39;re responsible for interpreting the options object.
<p>Initialize with a list of valid options, in the form:
</p>
<pre><code>[short-flag, long-flag, description]</code></pre>
<p>Along with an an optional banner for the usage help.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">parse: </span><span class="nf">(args) -&gt;</span>
<span class="nv">options = arguments: </span><span class="p">[]</span>
<span class="nv">skippingArgument = </span><span class="kc">no</span>
<span class="nv">originalArgs = </span><span class="nx">args</span>
<span class="nv">args = </span><span class="nx">normalizeArguments</span> <span class="nx">args</span>
<span class="k">for</span> <span class="nx">arg</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">args</span>
<span class="k">if</span> <span class="nx">skippingArgument</span>
<span class="nv">skippingArgument = </span><span class="kc">no</span>
<span class="k">continue</span>
<span class="k">if</span> <span class="nx">arg</span> <span class="o">is</span> <span class="s">&#39;--&#39;</span>
<span class="nv">pos = </span><span class="nx">originalArgs</span><span class="p">.</span><span class="nx">indexOf</span> <span class="s">&#39;--&#39;</span>
<span class="nv">options.arguments = </span><span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">originalArgs</span><span class="p">[(</span><span class="nx">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)..]</span>
<span class="k">break</span>
<span class="nv">isOption = </span><span class="o">!!</span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LONG_FLAG</span><span class="p">)</span> <span class="o">or</span> <span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SHORT_FLAG</span><span class="p">))</span></pre></div></div>
<div class="content"><div class='highlight'><pre> constructor: (rules, <span class="property">@banner</span>) -&gt;
<span class="property">@rules</span> = buildRules rules</pre></div></div>
</li>
@@ -191,30 +166,30 @@ you&#39;re responsible for interpreting the options object.
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>the CS option parser is a little odd; options after the first
non-option argument are treated as non-option arguments themselves
<p>Parse the list of arguments, populating an <code>options</code> object with all of the
specified options, and return it. Options after the first non-option
argument are treated as arguments. <code>options.arguments</code> will be an array
containing the remaining arguments. This is a simpler API than many option
parsers that allow you to attach callback actions for every flag. Instead,
you&#39;re responsible for interpreting the options object.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">seenNonOptionArg = </span><span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span>
<span class="k">unless</span> <span class="nx">seenNonOptionArg</span>
<span class="nv">matchedRule = </span><span class="kc">no</span>
<span class="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="nx">@rules</span>
<span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="o">is</span> <span class="nx">arg</span> <span class="o">or</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span> <span class="o">is</span> <span class="nx">arg</span>
<span class="nv">value = </span><span class="kc">true</span>
<span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">hasArgument</span>
<span class="nv">skippingArgument = </span><span class="kc">yes</span>
<span class="nv">value = </span><span class="nx">args</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
<span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">isList</span> <span class="k">then</span> <span class="p">(</span><span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">or</span> <span class="p">[]).</span><span class="nx">concat</span> <span class="nx">value</span> <span class="k">else</span> <span class="nx">value</span>
<span class="nv">matchedRule = </span><span class="kc">yes</span>
<span class="k">break</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;unrecognized option: </span><span class="si">#{</span><span class="nx">arg</span><span class="si">}</span><span class="s">&quot;</span> <span class="k">if</span> <span class="nx">isOption</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">matchedRule</span>
<span class="k">if</span> <span class="nx">seenNonOptionArg</span> <span class="o">or</span> <span class="o">not</span> <span class="nx">isOption</span>
<span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">arg</span>
<span class="nx">options</span></pre></div></div>
<div class="content"><div class='highlight'><pre> parse: (args) -&gt;
options = arguments: []
skippingArgument = <span class="literal">no</span>
originalArgs = args
args = normalizeArguments args
<span class="keyword">for</span> arg, i <span class="keyword">in</span> args
<span class="keyword">if</span> skippingArgument
skippingArgument = <span class="literal">no</span>
<span class="keyword">continue</span>
<span class="keyword">if</span> arg <span class="keyword">is</span> <span class="string">'--'</span>
pos = originalArgs.indexOf <span class="string">'--'</span>
options.arguments = options.arguments.concat originalArgs[(pos + <span class="number">1</span>)..]
<span class="keyword">break</span>
isOption = !!(arg.match(LONG_FLAG) <span class="keyword">or</span> arg.match(SHORT_FLAG))</pre></div></div>
</li>
@@ -225,23 +200,28 @@ non-option argument are treated as non-option arguments themselves
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>Return the help text for this <strong>OptionParser</strong>, listing and describing all
of the valid options, for <code>--help</code> and such.
<p>the CS option parser is a little odd; options after the first
non-option argument are treated as non-option arguments themselves
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">help: </span><span class="nf">-&gt;</span>
<span class="nv">lines = </span><span class="p">[]</span>
<span class="nx">lines</span><span class="p">.</span><span class="nx">unshift</span> <span class="s">&quot;</span><span class="si">#{</span><span class="nx">@banner</span><span class="si">}</span><span class="s">\n&quot;</span> <span class="k">if</span> <span class="nx">@banner</span>
<span class="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="nx">@rules</span>
<span class="nv">spaces = </span><span class="mi">15</span> <span class="o">-</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s">&#39; &#39;</span><span class="p">)</span> <span class="k">else</span> <span class="s">&#39;&#39;</span>
<span class="nv">letPart = </span><span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="k">then</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="o">+</span> <span class="s">&#39;, &#39;</span> <span class="k">else</span> <span class="s">&#39; &#39;</span>
<span class="nx">lines</span><span class="p">.</span><span class="nx">push</span> <span class="s">&#39; &#39;</span> <span class="o">+</span> <span class="nx">letPart</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span> <span class="o">+</span> <span class="nx">spaces</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">description</span>
<span class="s">&quot;\n</span><span class="si">#{</span> <span class="nx">lines</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">&#39;\n&#39;</span><span class="p">)</span> <span class="si">}</span><span class="s">\n&quot;</span></pre></div></div>
<div class="content"><div class='highlight'><pre> seenNonOptionArg = options.arguments.length &gt; <span class="number">0</span>
<span class="keyword">unless</span> seenNonOptionArg
matchedRule = <span class="literal">no</span>
<span class="keyword">for</span> rule <span class="keyword">in</span> <span class="property">@rules</span>
<span class="keyword">if</span> rule.shortFlag <span class="keyword">is</span> arg <span class="keyword">or</span> rule.longFlag <span class="keyword">is</span> arg
value = <span class="literal">true</span>
<span class="keyword">if</span> rule.hasArgument
skippingArgument = <span class="literal">yes</span>
value = args[i + <span class="number">1</span>]
options[rule.name] = <span class="keyword">if</span> rule.isList <span class="keyword">then</span> (options[rule.name] <span class="keyword">or</span> []).concat value <span class="keyword">else</span> value
matchedRule = <span class="literal">yes</span>
<span class="keyword">break</span>
<span class="keyword">throw</span> <span class="keyword">new</span> Error <span class="string">"unrecognized option: <span class="subst">#{arg}</span>"</span> <span class="keyword">if</span> isOption <span class="keyword">and</span> <span class="keyword">not</span> matchedRule
<span class="keyword">if</span> seenNonOptionArg <span class="keyword">or</span> <span class="keyword">not</span> isOption
options.arguments.push arg
options</pre></div></div>
</li>
@@ -249,35 +229,38 @@ of the valid options, for <code>--help</code> and such.
<li id="section-6">
<div class="annotation">
<div class="pilwrap for-h2">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<h2>Helpers</h2>
<p>Return the help text for this <strong>OptionParser</strong>, listing and describing all
of the valid options, for <code>--help</code> and such.
</p>
</div>
<div class="content"><div class='highlight'><pre> help: -&gt;
lines = []
lines.unshift <span class="string">"<span class="subst">#{@banner}</span>\n"</span> <span class="keyword">if</span> <span class="property">@banner</span>
<span class="keyword">for</span> rule <span class="keyword">in</span> <span class="property">@rules</span>
spaces = <span class="number">15</span> - rule.longFlag.length
spaces = <span class="keyword">if</span> spaces &gt; <span class="number">0</span> <span class="keyword">then</span> repeat <span class="string">' '</span>, spaces <span class="keyword">else</span> <span class="string">''</span>
letPart = <span class="keyword">if</span> rule.shortFlag <span class="keyword">then</span> rule.shortFlag + <span class="string">', '</span> <span class="keyword">else</span> <span class="string">' '</span>
lines.push <span class="string">' '</span> + letPart + rule.longFlag + spaces + rule.description
<span class="string">"\n<span class="subst">#{ lines.join('\n') }</span>\n"</span></pre></div></div>
</li>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<div class="pilwrap for-h2">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Regex matchers for option flags.
</p>
<h2>Helpers</h2>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">LONG_FLAG = </span><span class="sr">/^(--\w[\w\-]*)/</span>
<span class="nv">SHORT_FLAG = </span><span class="sr">/^(-\w)$/</span>
<span class="nv">MULTI_FLAG = </span><span class="sr">/^-(\w{2,})/</span>
<span class="nv">OPTIONAL = </span><span class="sr">/\[(\w+(\*?))\]/</span></pre></div></div>
</li>
@@ -288,18 +271,8 @@ of the valid options, for <code>--help</code> and such.
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Build and return the list of option rules. If the optional <em>short-flag</em> is
unspecified, leave it out by padding with <code>null</code>.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">buildRules = </span><span class="nf">(rules) -&gt;</span>
<span class="k">for</span> <span class="nx">tuple</span> <span class="k">in</span> <span class="nx">rules</span>
<span class="nx">tuple</span><span class="p">.</span><span class="nx">unshift</span> <span class="kc">null</span> <span class="k">if</span> <span class="nx">tuple</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;</span> <span class="mi">3</span>
<span class="nx">buildRule</span> <span class="nx">tuple</span><span class="p">...</span></pre></div></div>
</li>
@@ -309,25 +282,15 @@ unspecified, leave it out by padding with <code>null</code>.
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>Build a rule from a <code>-o</code> short flag, a <code>--output [DIR]</code> long flag, and the
description of what the option does.
<p>Regex matchers for option flags.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">buildRule = </span><span class="nf">(shortFlag, longFlag, description, options = {}) -&gt;</span>
<span class="nv">match = </span><span class="nx">longFlag</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">OPTIONAL</span><span class="p">)</span>
<span class="nv">longFlag = </span><span class="nx">longFlag</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LONG_FLAG</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>
<span class="p">{</span>
<span class="nv">name: </span> <span class="nx">longFlag</span><span class="p">.</span><span class="nx">substr</span> <span class="mi">2</span>
<span class="nv">shortFlag: </span> <span class="nx">shortFlag</span>
<span class="nv">longFlag: </span> <span class="nx">longFlag</span>
<span class="nv">description: </span> <span class="nx">description</span>
<span class="nv">hasArgument: </span> <span class="o">!!</span><span class="p">(</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="nv">isList: </span> <span class="o">!!</span><span class="p">(</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
<span class="p">}</span></pre></div></div>
<div class="content"><div class='highlight'><pre>LONG_FLAG = <span class="regexp">/^(--\w[\w\-]*)/</span>
SHORT_FLAG = <span class="regexp">/^(-\w)$/</span>
MULTI_FLAG = <span class="regexp">/^-(\w{2,})/</span>
OPTIONAL = <span class="regexp">/\[(\w+(\*?))\]/</span></pre></div></div>
</li>
@@ -338,24 +301,68 @@ description of what the option does.
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>Build and return the list of option rules. If the optional <em>short-flag</em> is
unspecified, leave it out by padding with <code>null</code>.
</p>
</div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">buildRules</span></span> = (rules) -&gt;
<span class="keyword">for</span> tuple <span class="keyword">in</span> rules
tuple.unshift <span class="literal">null</span> <span class="keyword">if</span> tuple.length &lt; <span class="number">3</span>
buildRule tuple...</pre></div></div>
</li>
<li id="section-11">
<div class="annotation">
<p>Normalize arguments by expanding merged flags into multiple flags. This allows
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>Build a rule from a <code>-o</code> short flag, a <code>--output [DIR]</code> long flag, and the
description of what the option does.
</p>
</div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">buildRule</span></span> = (shortFlag, longFlag, description, options = {}) -&gt;
match = longFlag.match(OPTIONAL)
longFlag = longFlag.match(LONG_FLAG)[<span class="number">1</span>]
{
name: longFlag.substr <span class="number">2</span>
shortFlag: shortFlag
longFlag: longFlag
description: description
hasArgument: !!(match <span class="keyword">and</span> match[<span class="number">1</span>])
isList: !!(match <span class="keyword">and</span> match[<span class="number">2</span>])
}</pre></div></div>
</li>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>Normalize arguments by expanding merged flags into multiple flags. This allows
you to have <code>-wl</code> be the same as <code>--watch --lint</code>.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">normalizeArguments = </span><span class="nf">(args) -&gt;</span>
<span class="nv">args = </span><span class="nx">args</span><span class="p">[..]</span>
<span class="nv">result = </span><span class="p">[]</span>
<span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">args</span>
<span class="k">if</span> <span class="nv">match = </span><span class="nx">arg</span><span class="p">.</span><span class="nx">match</span> <span class="nx">MULTI_FLAG</span>
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span> <span class="s">&#39;-&#39;</span> <span class="o">+</span> <span class="nx">l</span> <span class="k">for</span> <span class="nx">l</span> <span class="k">in</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">split</span> <span class="s">&#39;&#39;</span>
<span class="k">else</span>
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span> <span class="nx">arg</span>
<span class="nx">result</span>
</pre></div></div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">normalizeArguments</span></span> = (args) -&gt;
args = args[..]
result = []
<span class="keyword">for</span> arg <span class="keyword">in</span> args
<span class="keyword">if</span> match = arg.match MULTI_FLAG
result.push <span class="string">'-'</span> + l <span class="keyword">for</span> l <span class="keyword">in</span> match[<span class="number">1</span>].split <span class="string">''</span>
<span class="keyword">else</span>
result.push arg
result</pre></div></div>
</li>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -85,7 +85,7 @@
<a class="source" href="sourcemap.html">
sourcemap.coffee
sourcemap.litcoffee
</a>
</div>
@@ -111,14 +111,18 @@
</div>
<div class="content"><div class="highlight"><pre><span class="nv">vm = </span><span class="nx">require</span> <span class="s">&#39;vm&#39;</span>
<span class="nv">nodeREPL = </span><span class="nx">require</span> <span class="s">&#39;repl&#39;</span>
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">&#39;./coffee-script&#39;</span>
<span class="p">{</span><span class="nx">merge</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">&#39;./helpers&#39;</span>
<div class="content"><div class='highlight'><pre>fs = require <span class="string">'fs'</span>
path = require <span class="string">'path'</span>
vm = require <span class="string">'vm'</span>
nodeREPL = require <span class="string">'repl'</span>
CoffeeScript = require <span class="string">'./coffee-script'</span>
{merge, prettyErrorMessage} = require <span class="string">'./helpers'</span>
<span class="nv">replDefaults =</span>
<span class="nv">prompt: </span><span class="s">&#39;coffee&gt; &#39;</span><span class="p">,</span>
<span class="nb">eval</span><span class="o">:</span> <span class="nf">(input, context, filename, cb) -&gt;</span></pre></div></div>
replDefaults =
prompt: <span class="string">'coffee&gt; '</span>,
historyFile: path.join process.env.HOME, <span class="string">'.coffee_history'</span> <span class="keyword">if</span> process.env.HOME
historyMaxInputSize: <span class="number">10240</span>
eval: (input, context, filename, cb) -&gt;</pre></div></div>
</li>
@@ -129,14 +133,12 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>XXX: multiline hack
<p>XXX: multiline hack.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">input = </span><span class="nx">input</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\uFF00/g</span><span class="p">,</span> <span class="s">&#39;\n&#39;</span></pre></div></div>
<div class="content"><div class='highlight'><pre> input = input.replace <span class="regexp">/\uFF00/g</span>, <span class="string">'\n'</span></pre></div></div>
</li>
@@ -147,14 +149,13 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>strip single-line comments
<p>Node&#39;s REPL sends the input ending with a newline and then wrapped in
parens. Unwrap all that.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">input = </span><span class="nx">input</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/</span><span class="p">,</span> <span class="s">&#39;$1$2$3&#39;</span></pre></div></div>
<div class="content"><div class='highlight'><pre> input = input.replace <span class="regexp">/^\(([\s\S]*)\n\)$/m</span>, <span class="string">'$1'</span></pre></div></div>
</li>
@@ -165,14 +166,14 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>empty command
<p>Require AST nodes to do some AST manipulation.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="k">return</span> <span class="nx">cb</span> <span class="kc">null</span> <span class="k">if</span> <span class="sr">/^(\s*|\(\s*\))$/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">input</span></pre></div></div>
<div class="content"><div class='highlight'><pre> {Block, Assign, Value, Literal} = require <span class="string">'./nodes'</span>
<span class="keyword">try</span></pre></div></div>
</li>
@@ -183,27 +184,12 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>TODO: fix #1829: pass in-scope vars and avoid accidentally shadowing them by omitting those declarations
<p>Generate the AST of the clean input.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="k">try</span>
<span class="nv">js = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="s">&quot;_=(</span><span class="si">#{</span><span class="nx">input</span><span class="si">}</span><span class="s">\n)&quot;</span><span class="p">,</span> <span class="p">{</span><span class="nx">filename</span><span class="p">,</span> <span class="nv">bare: </span><span class="kc">yes</span><span class="p">}</span>
<span class="nx">cb</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">vm</span><span class="p">.</span><span class="nx">runInContext</span><span class="p">(</span><span class="nx">js</span><span class="p">,</span> <span class="nx">context</span><span class="p">,</span> <span class="nx">filename</span><span class="p">)</span>
<span class="k">catch</span> <span class="nx">err</span>
<span class="nx">cb</span> <span class="nx">err</span>
<span class="nv">addMultilineHandler = </span><span class="nf">(repl) -&gt;</span>
<span class="p">{</span><span class="nx">rli</span><span class="p">,</span> <span class="nx">inputStream</span><span class="p">,</span> <span class="nx">outputStream</span><span class="p">}</span> <span class="o">=</span> <span class="nx">repl</span>
<span class="nv">multiline =</span>
<span class="nv">enabled: </span><span class="kc">off</span>
<span class="nv">initialPrompt: </span><span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/^[^&gt; ]*/</span><span class="p">,</span> <span class="nf">(x) -&gt;</span> <span class="nx">x</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/./g</span><span class="p">,</span> <span class="s">&#39;-&#39;</span><span class="p">)</span>
<span class="nv">prompt: </span><span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/^[^&gt; ]*&gt;?/</span><span class="p">,</span> <span class="nf">(x) -&gt;</span> <span class="nx">x</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/./g</span><span class="p">,</span> <span class="s">&#39;.&#39;</span><span class="p">)</span>
<span class="nv">buffer: </span><span class="s">&#39;&#39;</span></pre></div></div>
<div class="content"><div class='highlight'><pre> ast = CoffeeScript.nodes input</pre></div></div>
</li>
@@ -214,23 +200,27 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>Proxy node&#39;s line listener
<p>Add assignment to <code>_</code> variable to force the input to be an expression.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">nodeLineListener = </span><span class="nx">rli</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s">&#39;line&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="nx">rli</span><span class="p">.</span><span class="nx">removeListener</span> <span class="s">&#39;line&#39;</span><span class="p">,</span> <span class="nx">nodeLineListener</span>
<span class="nx">rli</span><span class="p">.</span><span class="nx">on</span> <span class="s">&#39;line&#39;</span><span class="p">,</span> <span class="nf">(cmd) -&gt;</span>
<span class="k">if</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">enabled</span>
<span class="nx">multiline</span><span class="p">.</span><span class="nx">buffer</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="si">#{</span><span class="nx">cmd</span><span class="si">}</span><span class="s">\n&quot;</span>
<span class="nx">rli</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">prompt</span>
<span class="nx">rli</span><span class="p">.</span><span class="nx">prompt</span> <span class="kc">true</span>
<span class="k">else</span>
<span class="nx">nodeLineListener</span> <span class="nx">cmd</span>
<span class="k">return</span></pre></div></div>
<div class="content"><div class='highlight'><pre> ast = <span class="keyword">new</span> Block [
<span class="keyword">new</span> Assign (<span class="keyword">new</span> Value <span class="keyword">new</span> Literal <span class="string">'_'</span>), ast, <span class="string">'='</span>
]
js = ast.compile bare: <span class="literal">yes</span>, locals: Object.keys(context)
cb <span class="literal">null</span>, vm.runInContext(js, context, filename)
<span class="keyword">catch</span> err
cb prettyErrorMessage(err, filename, input, <span class="literal">yes</span>)
<span class="function"><span class="title">addMultilineHandler</span></span> = (repl) -&gt;
{rli, inputStream, outputStream} = repl
multiline =
enabled: <span class="literal">off</span>
initialPrompt: repl.prompt.replace <span class="regexp">/^[^&gt; ]*/, (x) -&gt; x.replace /./g</span>, <span class="string">'-'</span>
prompt: repl.prompt.replace <span class="regexp">/^[^&gt; ]*&gt;?/, (x) -&gt; x.replace /./g</span>, <span class="string">'.'</span>
buffer: <span class="string">''</span></pre></div></div>
</li>
@@ -241,16 +231,21 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Handle Ctrl-v
<p>Proxy node&#39;s line listener
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nx">inputStream</span><span class="p">.</span><span class="nx">on</span> <span class="s">&#39;keypress&#39;</span><span class="p">,</span> <span class="nf">(char, key) -&gt;</span>
<span class="k">return</span> <span class="k">unless</span> <span class="nx">key</span> <span class="o">and</span> <span class="nx">key</span><span class="p">.</span><span class="nx">ctrl</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">key</span><span class="p">.</span><span class="nx">meta</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">key</span><span class="p">.</span><span class="nx">shift</span> <span class="o">and</span> <span class="nx">key</span><span class="p">.</span><span class="nx">name</span> <span class="o">is</span> <span class="s">&#39;v&#39;</span>
<span class="k">if</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">enabled</span></pre></div></div>
<div class="content"><div class='highlight'><pre> nodeLineListener = rli.listeners(<span class="string">'line'</span>)[<span class="number">0</span>]
rli.removeListener <span class="string">'line'</span>, nodeLineListener
rli.<span class="literal">on</span> <span class="string">'line'</span>, (cmd) -&gt;
<span class="keyword">if</span> multiline.enabled
multiline.buffer += <span class="string">"<span class="subst">#{cmd}</span>\n"</span>
rli.setPrompt multiline.prompt
rli.prompt <span class="literal">true</span>
<span class="keyword">else</span>
nodeLineListener cmd
<span class="keyword">return</span></pre></div></div>
</li>
@@ -261,18 +256,14 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>allow arbitrarily switching between modes any time before multiple lines are entered
<p>Handle Ctrl-v
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="k">unless</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">buffer</span><span class="p">.</span><span class="nx">match</span> <span class="sr">/\n/</span>
<span class="nv">multiline.enabled = </span><span class="o">not</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">enabled</span>
<span class="nx">rli</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span>
<span class="nx">rli</span><span class="p">.</span><span class="nx">prompt</span> <span class="kc">true</span>
<span class="k">return</span></pre></div></div>
<div class="content"><div class='highlight'><pre> inputStream.<span class="literal">on</span> <span class="string">'keypress'</span>, (char, key) -&gt;
<span class="keyword">return</span> <span class="keyword">unless</span> key <span class="keyword">and</span> key.ctrl <span class="keyword">and</span> <span class="keyword">not</span> key.meta <span class="keyword">and</span> <span class="keyword">not</span> key.shift <span class="keyword">and</span> key.name <span class="keyword">is</span> <span class="string">'v'</span>
<span class="keyword">if</span> multiline.enabled</pre></div></div>
</li>
@@ -283,14 +274,16 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>no-op unless the current line is empty
<p>allow arbitrarily switching between modes any time before multiple lines are entered
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="k">return</span> <span class="k">if</span> <span class="nx">rli</span><span class="p">.</span><span class="nx">line</span><span class="o">?</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">rli</span><span class="p">.</span><span class="nx">line</span><span class="p">.</span><span class="nx">match</span> <span class="sr">/^\s*$/</span></pre></div></div>
<div class="content"><div class='highlight'><pre> <span class="keyword">unless</span> multiline.buffer.match <span class="regexp">/\n/</span>
multiline.enabled = <span class="keyword">not</span> multiline.enabled
rli.setPrompt repl.prompt
rli.prompt <span class="literal">true</span>
<span class="keyword">return</span></pre></div></div>
</li>
@@ -301,18 +294,12 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>eval, print, loop
<p>no-op unless the current line is empty
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">multiline.enabled = </span><span class="o">not</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">enabled</span>
<span class="nv">rli.line = </span><span class="s">&#39;&#39;</span>
<span class="nv">rli.cursor = </span><span class="mi">0</span>
<span class="nx">rli</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">cursorTo</span> <span class="mi">0</span>
<span class="nx">rli</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">clearLine</span> <span class="mi">1</span></pre></div></div>
<div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="keyword">if</span> rli.line? <span class="keyword">and</span> <span class="keyword">not</span> rli.line.match <span class="regexp">/^\s*$/</span></pre></div></div>
</li>
@@ -323,30 +310,201 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>XXX: multiline hack
<p>eval, print, loop
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">multiline.buffer = </span><span class="nx">multiline</span><span class="p">.</span><span class="nx">buffer</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\n/g</span><span class="p">,</span> <span class="s">&#39;\uFF00&#39;</span>
<span class="nx">rli</span><span class="p">.</span><span class="nx">emit</span> <span class="s">&#39;line&#39;</span><span class="p">,</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">buffer</span>
<span class="nv">multiline.buffer = </span><span class="s">&#39;&#39;</span>
<span class="k">else</span>
<span class="nv">multiline.enabled = </span><span class="o">not</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">enabled</span>
<span class="nx">rli</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">initialPrompt</span>
<span class="nx">rli</span><span class="p">.</span><span class="nx">prompt</span> <span class="kc">true</span>
<span class="k">return</span>
<div class="content"><div class='highlight'><pre> multiline.enabled = <span class="keyword">not</span> multiline.enabled
rli.line = <span class="string">''</span>
rli.cursor = <span class="number">0</span>
rli.output.cursorTo <span class="number">0</span>
rli.output.clearLine <span class="number">1</span></pre></div></div>
</li>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>XXX: multiline hack
</p>
<span class="nv">module.exports =</span>
<span class="nv">start: </span><span class="nf">(opts = {}) -&gt;</span>
<span class="nv">opts = </span><span class="nx">merge</span> <span class="nx">replDefaults</span><span class="p">,</span> <span class="nx">opts</span>
<span class="nv">repl = </span><span class="nx">nodeREPL</span><span class="p">.</span><span class="nx">start</span> <span class="nx">opts</span>
<span class="nx">repl</span><span class="p">.</span><span class="nx">on</span> <span class="s">&#39;exit&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">repl</span><span class="p">.</span><span class="nx">outputStream</span><span class="p">.</span><span class="nx">write</span> <span class="s">&#39;\n&#39;</span>
<span class="nx">addMultilineHandler</span> <span class="nx">repl</span>
<span class="nx">repl</span>
</div>
<div class="content"><div class='highlight'><pre> multiline.buffer = multiline.buffer.replace <span class="regexp">/\n/g</span>, <span class="string">'\uFF00'</span>
rli.emit <span class="string">'line'</span>, multiline.buffer
multiline.buffer = <span class="string">''</span>
<span class="keyword">else</span>
multiline.enabled = <span class="keyword">not</span> multiline.enabled
rli.setPrompt multiline.initialPrompt
rli.prompt <span class="literal">true</span>
<span class="keyword">return</span></pre></div></div>
</li>
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>Store and load command history from a file
</p>
</pre></div></div>
</div>
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">addHistory</span></span> = (repl, filename, maxSize) -&gt;
lastLine = <span class="literal">null</span>
<span class="keyword">try</span></pre></div></div>
</li>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>Get file info and at most maxSize of command history
</p>
</div>
<div class="content"><div class='highlight'><pre> stat = fs.statSync filename
size = Math.min maxSize, stat.size</pre></div></div>
</li>
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>Read last <code>size</code> bytes from the file
</p>
</div>
<div class="content"><div class='highlight'><pre> readFd = fs.openSync filename, <span class="string">'r'</span>
buffer = <span class="keyword">new</span> Buffer(size)
fs.readSync readFd, buffer, <span class="number">0</span>, size, stat.size - size</pre></div></div>
</li>
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>Set the history on the interpreter
</p>
</div>
<div class="content"><div class='highlight'><pre> repl.rli.history = buffer.toString().split(<span class="string">'\n'</span>).reverse()</pre></div></div>
</li>
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>If the history file was truncated we should pop off a potential partial line
</p>
</div>
<div class="content"><div class='highlight'><pre> repl.rli.history.pop() <span class="keyword">if</span> stat.size &gt; maxSize</pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>Shift off the final blank newline
</p>
</div>
<div class="content"><div class='highlight'><pre> repl.rli.history.shift() <span class="keyword">if</span> repl.rli.history[<span class="number">0</span>] <span class="keyword">is</span> <span class="string">''</span>
repl.rli.historyIndex = -<span class="number">1</span>
lastLine = repl.rli.history[<span class="number">0</span>]
fd = fs.openSync filename, <span class="string">'a'</span>
repl.rli.addListener <span class="string">'line'</span>, (code) -&gt;
<span class="keyword">if</span> code <span class="keyword">and</span> code.length <span class="keyword">and</span> code <span class="keyword">isnt</span> <span class="string">'.history'</span> <span class="keyword">and</span> lastLine <span class="keyword">isnt</span> code</pre></div></div>
</li>
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>Save the latest command in the file
</p>
</div>
<div class="content"><div class='highlight'><pre> fs.write fd, <span class="string">"<span class="subst">#{code}</span>\n"</span>
lastLine = code
repl.rli.<span class="literal">on</span> <span class="string">'exit'</span>, -&gt; fs.close fd</pre></div></div>
</li>
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<p>Add a command to show the history stack
</p>
</div>
<div class="content"><div class='highlight'><pre> repl.commands[<span class="string">'.history'</span>] =
help: <span class="string">'Show command history'</span>
action: -&gt;
repl.outputStream.write <span class="string">"<span class="subst">#{repl.rli.history[..].reverse().join '\n'}</span>\n"</span>
repl.displayPrompt()
module.exports =
start: (opts = {}) -&gt;
[major, minor, build] = process.versions.node.split(<span class="string">'.'</span>).map (n) -&gt; parseInt(n)
<span class="keyword">if</span> major <span class="keyword">is</span> <span class="number">0</span> <span class="keyword">and</span> minor &lt; <span class="number">8</span>
console.warn <span class="string">"Node 0.8.0+ required for CoffeeScript REPL"</span>
process.exit <span class="number">1</span>
opts = merge replDefaults, opts
repl = nodeREPL.start opts
repl.<span class="literal">on</span> <span class="string">'exit'</span>, -&gt; repl.outputStream.write <span class="string">'\n'</span>
addMultilineHandler repl
addHistory repl, opts.historyFile, opts.historyMaxInputSize <span class="keyword">if</span> opts.historyFile
repl</pre></div></div>
</li>

File diff suppressed because it is too large Load Diff

View File

@@ -85,7 +85,7 @@
<a class="source" href="sourcemap.html">
sourcemap.coffee
sourcemap.litcoffee
</a>
</div>
@@ -114,19 +114,10 @@ function bodies. Each scope knows about the variables declared within it,
and has a reference to its parent enclosing scope. In this way, we know which
variables are new and need to be declared with <code>var</code>, and which are shared
with external scopes.
</p>
<p>Import the helpers we plan to use.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="p">{</span><span class="nx">extend</span><span class="p">,</span> <span class="nx">last</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">&#39;./helpers&#39;</span>
<span class="nv">exports.Scope = </span><span class="k">class</span> <span class="nx">Scope</span></pre></div></div>
</li>
@@ -136,15 +127,15 @@ with external scopes.
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>The <code>root</code> is the top-level <strong>Scope</strong> object for a given file.
<p>Import the helpers we plan to use.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="vi">@root: </span><span class="kc">null</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
{extend, last} = require <span class="string">'./helpers'</span>
exports.Scope = <span class="class"><span class="keyword">class</span> <span class="title">Scope</span></span></pre></div></div>
</li>
@@ -155,21 +146,13 @@ with external scopes.
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>Initialize a scope with its parent, for lookups up the chain,
as well as a reference to the <strong>Block</strong> node it belongs to, which is
where it should declare its variables, and a reference to the function that
it belongs to.
<p>The <code>root</code> is the top-level <strong>Scope</strong> object for a given file.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">constructor: </span><span class="nf">(@parent, @expressions, @method) -&gt;</span>
<span class="vi">@variables = </span><span class="p">[{</span><span class="nv">name: </span><span class="s">&#39;arguments&#39;</span><span class="p">,</span> <span class="nv">type: </span><span class="s">&#39;arguments&#39;</span><span class="p">}]</span>
<span class="vi">@positions = </span><span class="p">{}</span>
<span class="nv">Scope.root = </span><span class="k">this</span> <span class="k">unless</span> <span class="nx">@parent</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
<span class="property">@root</span>: <span class="literal">null</span></pre></div></div>
</li>
@@ -180,20 +163,19 @@ it belongs to.
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>Adds a new variable or overrides an existing one.
<p>Initialize a scope with its parent, for lookups up the chain,
as well as a reference to the <strong>Block</strong> node it belongs to, which is
where it should declare its variables, and a reference to the function that
it belongs to.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">add: </span><span class="nf">(name, type, immediate) -&gt;</span>
<span class="k">return</span> <span class="nx">@parent</span><span class="p">.</span><span class="nx">add</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">immediate</span> <span class="k">if</span> <span class="nx">@shared</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">immediate</span>
<span class="k">if</span> <span class="nb">Object</span><span class="o">::</span><span class="nx">hasOwnProperty</span><span class="p">.</span><span class="nx">call</span> <span class="nx">@positions</span><span class="p">,</span> <span class="nx">name</span>
<span class="nx">@variables</span><span class="p">[</span><span class="nx">@positions</span><span class="p">[</span><span class="nx">name</span><span class="p">]].</span><span class="nv">type = </span><span class="nx">type</span>
<span class="k">else</span>
<span class="nx">@positions</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@variables</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">})</span> <span class="o">-</span> <span class="mi">1</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
constructor: (<span class="property">@parent</span>, <span class="property">@expressions</span>, <span class="property">@method</span>) -&gt;
<span class="property">@variables</span> = [{name: <span class="string">'arguments'</span>, type: <span class="string">'arguments'</span>}]
<span class="property">@positions</span> = {}
Scope.root = <span class="keyword">this</span> <span class="keyword">unless</span> <span class="property">@parent</span></pre></div></div>
</li>
@@ -204,21 +186,18 @@ it belongs to.
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>When <code>super</code> is called, we need to find the name of the current method we&#39;re
in, so that we know how to invoke the same method of the parent class. This
can get complicated if super is being called from an inner function.
<code>namedMethod</code> will walk up the scope tree until it either finds the first
function object that has a name filled in, or bottoms out.
<p>Adds a new variable or overrides an existing one.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">namedMethod: </span><span class="nf">-&gt;</span>
<span class="k">return</span> <span class="nx">@method</span> <span class="k">if</span> <span class="nx">@method</span><span class="o">?</span><span class="p">.</span><span class="nx">name</span> <span class="o">or</span> <span class="o">!</span><span class="nx">@parent</span>
<span class="nx">@parent</span><span class="p">.</span><span class="nx">namedMethod</span><span class="p">()</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
add: (name, type, immediate) -&gt;
<span class="keyword">return</span> <span class="property">@parent</span>.add name, type, immediate <span class="keyword">if</span> <span class="property">@shared</span> <span class="keyword">and</span> <span class="keyword">not</span> immediate
<span class="keyword">if</span> Object::hasOwnProperty.call <span class="property">@positions</span>, name
<span class="property">@variables</span>[<span class="property">@positions</span>[name]].type = type
<span class="keyword">else</span>
<span class="property">@positions</span>[name] = <span class="property">@variables</span>.push({name, type}) - <span class="number">1</span></pre></div></div>
</li>
@@ -229,19 +208,19 @@ function object that has a name filled in, or bottoms out.
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>Look up a variable name in lexical scope, and declare it if it does not
already exist.
<p>When <code>super</code> is called, we need to find the name of the current method we&#39;re
in, so that we know how to invoke the same method of the parent class. This
can get complicated if super is being called from an inner function.
<code>namedMethod</code> will walk up the scope tree until it either finds the first
function object that has a name filled in, or bottoms out.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">find: </span><span class="nf">(name) -&gt;</span>
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">@check</span> <span class="nx">name</span>
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s">&#39;var&#39;</span>
<span class="kc">no</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
namedMethod: -&gt;
<span class="keyword">return</span> <span class="property">@method</span> <span class="keyword">if</span> <span class="property">@method</span>?.name <span class="keyword">or</span> !<span class="property">@parent</span>
<span class="property">@parent</span>.namedMethod()</pre></div></div>
</li>
@@ -252,18 +231,17 @@ already exist.
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Reserve a variable name as originating from a function parameter for this
scope. No <code>var</code> required for internal references.
<p>Look up a variable name in lexical scope, and declare it if it does not
already exist.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">parameter: </span><span class="nf">(name) -&gt;</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">@shared</span> <span class="o">and</span> <span class="nx">@parent</span><span class="p">.</span><span class="nx">check</span> <span class="nx">name</span><span class="p">,</span> <span class="kc">yes</span>
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s">&#39;param&#39;</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
find: (name) -&gt;
<span class="keyword">return</span> <span class="literal">yes</span> <span class="keyword">if</span> <span class="property">@check</span> name
<span class="property">@add</span> name, <span class="string">'var'</span>
<span class="literal">no</span></pre></div></div>
</li>
@@ -274,17 +252,16 @@ scope. No <code>var</code> required for internal references.
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Just check to see if a variable has already been declared, without reserving,
walks up to the root scope.
<p>Reserve a variable name as originating from a function parameter for this
scope. No <code>var</code> required for internal references.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">check: </span><span class="nf">(name) -&gt;</span>
<span class="o">!!</span><span class="p">(</span><span class="nx">@type</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">or</span> <span class="nx">@parent</span><span class="o">?</span><span class="p">.</span><span class="nx">check</span><span class="p">(</span><span class="nx">name</span><span class="p">))</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
parameter: (name) -&gt;
<span class="keyword">return</span> <span class="keyword">if</span> <span class="property">@shared</span> <span class="keyword">and</span> <span class="property">@parent</span>.check name, <span class="literal">yes</span>
<span class="property">@add</span> name, <span class="string">'param'</span></pre></div></div>
</li>
@@ -295,19 +272,15 @@ walks up to the root scope.
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>Generate a temporary variable name at the given index.
<p>Just check to see if a variable has already been declared, without reserving,
walks up to the root scope.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">temporary: </span><span class="nf">(name, index) -&gt;</span>
<span class="k">if</span> <span class="nx">name</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">1</span>
<span class="s">&#39;_&#39;</span> <span class="o">+</span> <span class="nx">name</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">index</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="k">then</span> <span class="nx">index</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="s">&#39;&#39;</span>
<span class="k">else</span>
<span class="s">&#39;_&#39;</span> <span class="o">+</span> <span class="p">(</span><span class="nx">index</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="nx">name</span><span class="p">,</span> <span class="mi">36</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="mi">36</span><span class="p">).</span><span class="nx">replace</span> <span class="sr">/\d/g</span><span class="p">,</span> <span class="s">&#39;a&#39;</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
check: (name) -&gt;
!!(<span class="property">@type</span>(name) <span class="keyword">or</span> <span class="property">@parent</span>?.check(name))</pre></div></div>
</li>
@@ -318,17 +291,17 @@ walks up to the root scope.
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>Gets the type of a variable.
<p>Generate a temporary variable name at the given index.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">type: </span><span class="nf">(name) -&gt;</span>
<span class="k">return</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span> <span class="o">is</span> <span class="nx">name</span>
<span class="kc">null</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
temporary: (name, index) -&gt;
<span class="keyword">if</span> name.length &gt; <span class="number">1</span>
<span class="string">'_'</span> + name + <span class="keyword">if</span> index &gt; <span class="number">1</span> <span class="keyword">then</span> index - <span class="number">1</span> <span class="keyword">else</span> <span class="string">''</span>
<span class="keyword">else</span>
<span class="string">'_'</span> + (index + parseInt name, <span class="number">36</span>).toString(<span class="number">36</span>).replace <span class="regexp">/\d/g</span>, <span class="string">'a'</span></pre></div></div>
</li>
@@ -339,20 +312,15 @@ walks up to the root scope.
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>If we need to store an intermediate result, find an available name for a
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...
<p>Gets the type of a variable.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">freeVariable: </span><span class="nf">(name, reserve=true) -&gt;</span>
<span class="nv">index = </span><span class="mi">0</span>
<span class="nx">index</span><span class="o">++</span> <span class="k">while</span> <span class="nx">@check</span><span class="p">((</span><span class="nv">temp = </span><span class="nx">@temporary</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">index</span><span class="p">))</span>
<span class="nx">@add</span> <span class="nx">temp</span><span class="p">,</span> <span class="s">&#39;var&#39;</span><span class="p">,</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">reserve</span>
<span class="nx">temp</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
type: (name) -&gt;
<span class="keyword">return</span> v.type <span class="keyword">for</span> v <span class="keyword">in</span> <span class="property">@variables</span> <span class="keyword">when</span> v.name <span class="keyword">is</span> name
<span class="literal">null</span></pre></div></div>
</li>
@@ -363,18 +331,18 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>Ensure that an assignment is made at the top of this scope
(or at the top-level scope, if requested).
<p>If we need to store an intermediate result, find an available name for a
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">assign: </span><span class="nf">(name, value) -&gt;</span>
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="p">{</span><span class="nx">value</span><span class="p">,</span> <span class="nv">assigned: </span><span class="kc">yes</span><span class="p">},</span> <span class="kc">yes</span>
<span class="vi">@hasAssignments = </span><span class="kc">yes</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
freeVariable: (name, reserve=<span class="literal">true</span>) -&gt;
index = <span class="number">0</span>
index++ <span class="keyword">while</span> <span class="property">@check</span>((temp = <span class="property">@temporary</span> name, index))
<span class="property">@add</span> temp, <span class="string">'var'</span>, <span class="literal">yes</span> <span class="keyword">if</span> reserve
temp</pre></div></div>
</li>
@@ -385,16 +353,16 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>Does this scope have any declared variables?
<p>Ensure that an assignment is made at the top of this scope
(or at the top-level scope, if requested).
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">hasDeclarations: </span><span class="nf">-&gt;</span>
<span class="o">!!</span><span class="nx">@declaredVariables</span><span class="p">().</span><span class="nx">length</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
assign: (name, value) -&gt;
<span class="property">@add</span> name, {value, assigned: <span class="literal">yes</span>}, <span class="literal">yes</span>
<span class="property">@hasAssignments</span> = <span class="literal">yes</span></pre></div></div>
</li>
@@ -405,20 +373,14 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>Return the list of variables first declared in this scope.
<p>Does this scope have any declared variables?
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">declaredVariables: </span><span class="nf">-&gt;</span>
<span class="nv">realVars = </span><span class="p">[]</span>
<span class="nv">tempVars = </span><span class="p">[]</span>
<span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s">&#39;var&#39;</span>
<span class="p">(</span><span class="k">if</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;_&#39;</span> <span class="k">then</span> <span class="nx">tempVars</span> <span class="k">else</span> <span class="nx">realVars</span><span class="p">).</span><span class="nx">push</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span>
<span class="nx">realVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">().</span><span class="nx">concat</span> <span class="nx">tempVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">()</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
hasDeclarations: -&gt;
!!<span class="property">@declaredVariables</span>().length</pre></div></div>
</li>
@@ -429,18 +391,37 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>Return the list of assignments that are supposed to be made at the top
of this scope.
<p>Return the list of variables first declared in this scope.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">assignedVariables: </span><span class="nf">-&gt;</span>
<span class="s">&quot;</span><span class="si">#{</span><span class="nx">v</span><span class="p">.</span><span class="nx">name</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">v</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">value</span><span class="si">}</span><span class="s">&quot;</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">assigned</span>
<div class="content"><div class='highlight'><pre>
declaredVariables: -&gt;
realVars = []
tempVars = []
<span class="keyword">for</span> v <span class="keyword">in</span> <span class="property">@variables</span> <span class="keyword">when</span> v.type <span class="keyword">is</span> <span class="string">'var'</span>
(<span class="keyword">if</span> v.name.charAt(<span class="number">0</span>) <span class="keyword">is</span> <span class="string">'_'</span> <span class="keyword">then</span> tempVars <span class="keyword">else</span> realVars).push v.name
realVars.sort().concat tempVars.sort()</pre></div></div>
</li>
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>Return the list of assignments that are supposed to be made at the top
of this scope.
</p>
</pre></div></div>
</div>
<div class="content"><div class='highlight'><pre>
assignedVariables: -&gt;
<span class="string">"<span class="subst">#{v.name}</span> = <span class="subst">#{v.type.value}</span>"</span> <span class="keyword">for</span> v <span class="keyword">in</span> <span class="property">@variables</span> <span class="keyword">when</span> v.type.assigned</pre></div></div>
</li>

View File

@@ -2,7 +2,7 @@
<html>
<head>
<title>sourcemap.coffee</title>
<title>sourcemap.litcoffee</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
<link rel="stylesheet" media="all" href="docco.css" />
@@ -85,7 +85,7 @@
<a class="source" href="sourcemap.html">
sourcemap.coffee
sourcemap.litcoffee
</a>
</div>
@@ -96,7 +96,7 @@
<li id="title">
<div class="annotation">
<h1>sourcemap.coffee</h1>
<h1>sourcemap.litcoffee</h1>
</div>
</li>
@@ -108,16 +108,14 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
</div>
<p>Hold data about mappings for one line of generated source code.
<p>Source maps allow JavaScript runtimes to match running JavaScript back to
the original source code that corresponds to it. This can be minified
JavaScript, but in our case, we&#39;re concerned with mapping pretty-printed
JavaScript back to CoffeeScript.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="k">class</span> <span class="nx">LineMapping</span>
<span class="nv">constructor: </span><span class="nf">(@generatedLine) -&gt;</span></pre></div></div>
</li>
@@ -127,36 +125,28 @@
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>columnMap keeps track of which columns we&#39;ve already mapped.
<p>In order to produce maps, we must keep track of positions (line number, column number)
that originated every node in the syntax tree, and be able to generate a
<a href="https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit">map file</a>
— which is a compact, VLQ-encoded representation of the JSON serialization
of this information — to write out alongside the generated JavaScript.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="vi">@columnMap = </span><span class="p">{}</span></pre></div></div>
</li>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<div class="pilwrap for-h2">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>columnMappings is an array of all column mappings, sorted by generated-column.
</p>
<h2>LineMap</h2>
</div>
<div class="content"><div class="highlight"><pre> <span class="vi">@columnMappings = </span><span class="p">[]</span>
<span class="nv">addMapping: </span><span class="nf">(generatedColumn, [sourceLine, sourceColumn], options={}) -&gt;</span>
<span class="k">if</span> <span class="nx">@columnMap</span><span class="p">[</span><span class="nx">generatedColumn</span><span class="p">]</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">noReplace</span></pre></div></div>
</li>
@@ -167,60 +157,36 @@
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>We already have a mapping for this column.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="k">return</span>
<span class="nx">@columnMap</span><span class="p">[</span><span class="nx">generatedColumn</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
<span class="nv">generatedLine: </span><span class="nx">@generatedLine</span>
<span class="nx">generatedColumn</span>
<span class="nx">sourceLine</span>
<span class="nx">sourceColumn</span>
<span class="p">}</span>
<span class="nx">@columnMappings</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@columnMap</span><span class="p">[</span><span class="nx">generatedColumn</span><span class="p">]</span>
<span class="nx">@columnMappings</span><span class="p">.</span><span class="nx">sort</span> <span class="nf">(a,b) -&gt;</span> <span class="nx">a</span><span class="p">.</span><span class="nx">generatedColumn</span> <span class="o">-</span> <span class="nx">b</span><span class="p">.</span><span class="nx">generatedColumn</span>
<span class="nv">getSourcePosition: </span><span class="nf">(generatedColumn) -&gt;</span>
<span class="nv">answer = </span><span class="kc">null</span>
<span class="nv">lastColumnMapping = </span><span class="kc">null</span>
<span class="k">for</span> <span class="nx">columnMapping</span> <span class="k">in</span> <span class="nx">@columnMappings</span>
<span class="k">if</span> <span class="nx">columnMapping</span><span class="p">.</span><span class="nx">generatedColumn</span> <span class="o">&gt;</span> <span class="nx">generatedColumn</span>
<span class="k">break</span>
<span class="k">else</span>
<span class="nv">lastColumnMapping = </span><span class="nx">columnMapping</span>
<span class="k">if</span> <span class="nx">lastColumnMapping</span>
<span class="nv">answer = </span><span class="p">[</span><span class="nx">lastColumnMapping</span><span class="p">.</span><span class="nx">sourceLine</span><span class="p">,</span> <span class="nx">lastColumnMapping</span><span class="p">.</span><span class="nx">sourceColumn</span><span class="p">]</span></pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="pilwrap for-h3">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<h3>SourceMap</h3>
<p>Maps locations in a generated source file back to locations in the original source file.
</p>
<p>This is intentionally agnostic towards how a source map might be represented on disk. A
SourceMap can be converted to a &quot;v3&quot; style sourcemap with <code>#generateV3SourceMap()</code>, for example
but the SourceMap class itself knows nothing about v3 source maps.
<p>A <strong>LineMap</strong> object keeps track of information about original line and column
positions for a single line of output JavaScript code.
<strong>SourceMaps</strong> are implemented in terms of <strong>LineMaps</strong>.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="k">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">SourceMap</span>
<span class="nv">constructor: </span><span class="p">()</span> <span class="nf">-&gt;</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
<span class="class"><span class="keyword">class</span> <span class="title">LineMap</span></span>
constructor: (<span class="property">@line</span>) -&gt;
<span class="property">@columns</span> = []
add: (column, [sourceLine, sourceColumn], options={}) -&gt;
<span class="keyword">return</span> <span class="keyword">if</span> <span class="property">@columns</span>[column] <span class="keyword">and</span> options.noReplace
<span class="property">@columns</span>[column] = {line: <span class="property">@line</span>, column, sourceLine, sourceColumn}
sourceLocation: (column) -&gt;
column-- <span class="keyword">until</span> (mapping = <span class="property">@columns</span>[column]) <span class="keyword">or</span> (column &lt;= <span class="number">0</span>)
mapping <span class="keyword">and</span> [mapping.sourceLine, mapping.sourceColumn]</pre></div></div>
</li>
@@ -228,18 +194,13 @@ but the SourceMap class itself knows nothing about v3 source maps.
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<div class="pilwrap for-h2">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p><code>generatedLines</code> is an array of LineMappings, one per generated line.
</p>
<h2>SourceMap</h2>
</div>
<div class="content"><div class="highlight"><pre> <span class="vi">@generatedLines = </span><span class="p">[]</span></pre></div></div>
</li>
@@ -250,28 +211,8 @@ but the SourceMap class itself knows nothing about v3 source maps.
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Adds a mapping to this SourceMap.
</p>
<p><code>sourceLocation</code> and <code>generatedLocation</code> are both [line, column] arrays.
</p>
<p>If <code>options.noReplace</code> is true, then if there is already a mapping for
the specified <code>generatedLine</code> and <code>generatedColumn</code>, this will have no effect.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">addMapping: </span><span class="nf">(sourceLocation, generatedLocation, options={}) -&gt;</span>
<span class="p">[</span><span class="nx">generatedLine</span><span class="p">,</span> <span class="nx">generatedColumn</span><span class="p">]</span> <span class="o">=</span> <span class="nx">generatedLocation</span>
<span class="nv">lineMapping = </span><span class="nx">@generatedLines</span><span class="p">[</span><span class="nx">generatedLine</span><span class="p">]</span>
<span class="k">if</span> <span class="o">not</span> <span class="nx">lineMapping</span>
<span class="nv">lineMapping = </span><span class="nx">@generatedLines</span><span class="p">[</span><span class="nx">generatedLine</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">LineMapping</span><span class="p">(</span><span class="nx">generatedLine</span><span class="p">)</span>
<span class="nx">lineMapping</span><span class="p">.</span><span class="nx">addMapping</span> <span class="nx">generatedColumn</span><span class="p">,</span> <span class="nx">sourceLocation</span><span class="p">,</span> <span class="nx">options</span></pre></div></div>
</li>
@@ -281,18 +222,12 @@ the specified <code>generatedLine</code> and <code>generatedColumn</code>, this
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Returns [sourceLine, sourceColumn], or null if no mapping could be found.
<p>Maps locations in a single generated JavaScript file back to locations in
the original CoffeeScript source file.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">getSourcePosition: </span><span class="nf">([generatedLine, generatedColumn]) -&gt;</span>
<span class="nv">answer = </span><span class="kc">null</span>
<span class="nv">lineMapping = </span><span class="nx">@generatedLines</span><span class="p">[</span><span class="nx">generatedLine</span><span class="p">]</span>
<span class="k">if</span> <span class="o">not</span> <span class="nx">lineMapping</span></pre></div></div>
</li>
@@ -302,17 +237,17 @@ the specified <code>generatedLine</code> and <code>generatedColumn</code>, this
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>TODO: Search backwards for the line?
<p>This is intentionally agnostic towards how a source map might be represented on
disk. Once the compiler is ready to produce a &quot;v3&quot;-style source map, we can walk
through the arrays of line and column buffer to produce it.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="k">else</span>
<span class="nv">answer = </span><span class="nx">lineMapping</span><span class="p">.</span><span class="nx">getSourcePosition</span> <span class="nx">generatedColumn</span>
<span class="nx">answer</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
<span class="class"><span class="keyword">class</span> <span class="title">SourceMap</span></span>
constructor: -&gt;
<span class="property">@lines</span> = []</pre></div></div>
</li>
@@ -323,21 +258,19 @@ the specified <code>generatedLine</code> and <code>generatedColumn</code>, this
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p><code>fn</code> will be called once for every recorded mapping, in the order in
which they occur in the generated source. <code>fn</code> will be passed an object
with four properties: sourceLine, sourceColumn, generatedLine, and
generatedColumn.
<p>Adds a mapping to this SourceMap. <code>sourceLocation</code> and <code>generatedLocation</code>
are both <code>[line, column]</code> arrays. If <code>options.noReplace</code> is true, then if there
is already a mapping for the specified <code>line</code> and <code>column</code>, this will have no
effect.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">forEachMapping: </span><span class="nf">(fn) -&gt;</span>
<span class="k">for</span> <span class="nx">lineMapping</span><span class="p">,</span> <span class="nx">generatedLineNumber</span> <span class="k">in</span> <span class="nx">@generatedLines</span>
<span class="k">if</span> <span class="nx">lineMapping</span>
<span class="k">for</span> <span class="nx">columnMapping</span> <span class="k">in</span> <span class="nx">lineMapping</span><span class="p">.</span><span class="nx">columnMappings</span>
<span class="nx">fn</span><span class="p">(</span><span class="nx">columnMapping</span><span class="p">)</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
add: (sourceLocation, generatedLocation, options = {}) -&gt;
[line, column] = generatedLocation
lineMap = (<span class="property">@lines</span>[line] <span class="keyword">or</span>= <span class="keyword">new</span> LineMap(line))
lineMap.add column, sourceLocation, options</pre></div></div>
</li>
@@ -345,34 +278,19 @@ generatedColumn.
<li id="section-11">
<div class="annotation">
<div class="pilwrap for-h3">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<h3>generateV3SourceMap</h3>
<p>Builds a V3 source map from a SourceMap object.
Returns the generated JSON as a string.
<p>Look up the original position of a given <code>line</code> and <code>column</code> in the generated
code.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.generateV3SourceMap = </span><span class="nf">(sourceMap, sourceFile=null, generatedFile=null) -&gt;</span>
<span class="nv">writingGeneratedLine = </span><span class="mi">0</span>
<span class="nv">lastGeneratedColumnWritten = </span><span class="mi">0</span>
<span class="nv">lastSourceLineWritten = </span><span class="mi">0</span>
<span class="nv">lastSourceColumnWritten = </span><span class="mi">0</span>
<span class="nv">needComma = </span><span class="kc">no</span>
<span class="nv">mappings = </span><span class="s">&quot;&quot;</span>
<span class="nx">sourceMap</span><span class="p">.</span><span class="nx">forEachMapping</span> <span class="nf">(mapping) -&gt;</span>
<span class="k">while</span> <span class="nx">writingGeneratedLine</span> <span class="o">&lt;</span> <span class="nx">mapping</span><span class="p">.</span><span class="nx">generatedLine</span>
<span class="nv">lastGeneratedColumnWritten = </span><span class="mi">0</span>
<span class="nv">needComma = </span><span class="kc">no</span>
<span class="nx">mappings</span> <span class="o">+=</span> <span class="s">&quot;;&quot;</span>
<span class="nx">writingGeneratedLine</span><span class="o">++</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
sourceLocation: ([line, column]) -&gt;
line-- <span class="keyword">until</span> (lineMap = <span class="property">@lines</span>[line]) <span class="keyword">or</span> (line &lt;= <span class="number">0</span>)
lineMap <span class="keyword">and</span> lineMap.sourceLocation column</pre></div></div>
</li>
@@ -380,20 +298,13 @@ Returns the generated JSON as a string.
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<div class="pilwrap for-h2">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>Write a comma if we&#39;ve already written a segment on this line.
</p>
<h2>V3 SourceMap Generation</h2>
</div>
<div class="content"><div class="highlight"><pre> <span class="k">if</span> <span class="nx">needComma</span>
<span class="nx">mappings</span> <span class="o">+=</span> <span class="s">&quot;,&quot;</span>
<span class="nv">needComma = </span><span class="kc">no</span></pre></div></div>
</li>
@@ -404,28 +315,8 @@ Returns the generated JSON as a string.
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>Write the next segment.
Segments can be 1, 4, or 5 values. If just one, then it is a generated column which
doesn&#39;t match anything in the source code.
</p>
<p>Fields are all zero-based, and relative to the previous occurence unless otherwise noted:
<em> starting-column in generated source, relative to previous occurence for the current line.
</em> index into the &quot;sources&quot; list
<em> starting line in the original source
</em> starting column in the original source
* index into the &quot;names&quot; list associated with this segment.
</p>
<p>Add the generated start-column
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nx">mappings</span> <span class="o">+=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">vlqEncodeValue</span><span class="p">(</span><span class="nx">mapping</span><span class="p">.</span><span class="nx">generatedColumn</span> <span class="o">-</span> <span class="nx">lastGeneratedColumnWritten</span><span class="p">)</span>
<span class="nv">lastGeneratedColumnWritten = </span><span class="nx">mapping</span><span class="p">.</span><span class="nx">generatedColumn</span></pre></div></div>
</li>
@@ -435,14 +326,30 @@ doesn&#39;t match anything in the source code.
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>Add the index into the sources list
<p>Builds up a V3 source map, returning the generated JSON as a string.
<code>options.sourceRoot</code> may be used to specify the sourceRoot written to the source
map. Also, <code>options.sourceFiles</code> and <code>options.generatedFile</code> may be passed to
set &quot;sources&quot; and &quot;file&quot;, respectively.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nx">mappings</span> <span class="o">+=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">vlqEncodeValue</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
generate: (options = {}, code = <span class="literal">null</span>) -&gt;
writingline = <span class="number">0</span>
lastColumn = <span class="number">0</span>
lastSourceLine = <span class="number">0</span>
lastSourceColumn = <span class="number">0</span>
needComma = <span class="literal">no</span>
buffer = <span class="string">""</span>
<span class="keyword">for</span> lineMap, lineNumber <span class="keyword">in</span> <span class="property">@lines</span> <span class="keyword">when</span> lineMap
<span class="keyword">for</span> mapping <span class="keyword">in</span> lineMap.columns <span class="keyword">when</span> mapping
<span class="keyword">while</span> writingline &lt; mapping.line
lastColumn = <span class="number">0</span>
needComma = <span class="literal">no</span>
buffer += <span class="string">";"</span>
writingline++</pre></div></div>
</li>
@@ -453,15 +360,15 @@ doesn&#39;t match anything in the source code.
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>Add the source start-line
<p>Write a comma if we&#39;ve already written a segment on this line.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nx">mappings</span> <span class="o">+=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">vlqEncodeValue</span><span class="p">(</span><span class="nx">mapping</span><span class="p">.</span><span class="nx">sourceLine</span> <span class="o">-</span> <span class="nx">lastSourceLineWritten</span><span class="p">)</span>
<span class="nv">lastSourceLineWritten = </span><span class="nx">mapping</span><span class="p">.</span><span class="nx">sourceLine</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
<span class="keyword">if</span> needComma
buffer += <span class="string">","</span>
needComma = <span class="literal">no</span></pre></div></div>
</li>
@@ -472,16 +379,12 @@ doesn&#39;t match anything in the source code.
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>Add the source start-column
<p>Write the next segment. Segments can be 1, 4, or 5 values. If just one, then it
is a generated column which doesn&#39;t match anything in the source code.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nx">mappings</span> <span class="o">+=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">vlqEncodeValue</span><span class="p">(</span><span class="nx">mapping</span><span class="p">.</span><span class="nx">sourceColumn</span> <span class="o">-</span> <span class="nx">lastSourceColumnWritten</span><span class="p">)</span>
<span class="nv">lastSourceColumnWritten = </span><span class="nx">mapping</span><span class="p">.</span><span class="nx">sourceColumn</span></pre></div></div>
</li>
@@ -491,26 +394,15 @@ doesn&#39;t match anything in the source code.
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>TODO: Do we care about symbol names for CoffeeScript? Probably not.
<p>The starting column in the generated source, relative to any previous recorded
column for the current line:
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">needComma = </span><span class="kc">yes</span>
<span class="nv">answer = </span><span class="p">{</span>
<span class="nv">version: </span><span class="mi">3</span>
<span class="nv">file: </span><span class="nx">generatedFile</span>
<span class="nv">sourceRoot: </span><span class="s">&quot;&quot;</span>
<span class="nv">sources: </span><span class="k">if</span> <span class="nx">sourceFile</span> <span class="k">then</span> <span class="p">[</span><span class="nx">sourceFile</span><span class="p">]</span> <span class="k">else</span> <span class="p">[]</span>
<span class="nv">names: </span><span class="p">[]</span>
<span class="nx">mappings</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span> <span class="nx">answer</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="mi">2</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
buffer += <span class="property">@encodeVlq</span> mapping.column - lastColumn
lastColumn = mapping.column</pre></div></div>
</li>
@@ -521,15 +413,13 @@ doesn&#39;t match anything in the source code.
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>Load a SourceMap from a JSON string. Returns the SourceMap object.
<p>The index into the list of sources:
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.loadV3SourceMap = </span><span class="nf">(sourceMap) -&gt;</span>
<span class="nx">todo</span><span class="p">()</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
buffer += <span class="property">@encodeVlq</span> <span class="number">0</span></pre></div></div>
</li>
@@ -537,29 +427,17 @@ doesn&#39;t match anything in the source code.
<li id="section-19">
<div class="annotation">
<div class="pilwrap for-h3">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<h3>Base64 encoding helpers</h3>
<p>The starting line in the original source, relative to the previous source line.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">BASE64_CHARS = </span><span class="s">&#39;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#39;</span>
<span class="nv">MAX_BASE64_VALUE = </span><span class="nx">BASE64_CHARS</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
<span class="nv">encodeBase64Char = </span><span class="nf">(value) -&gt;</span>
<span class="k">if</span> <span class="nx">value</span> <span class="o">&gt;</span> <span class="nx">MAX_BASE64_VALUE</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;Cannot encode value </span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s"> &gt; </span><span class="si">#{</span><span class="nx">MAX_BASE64_VALUE</span><span class="si">}</span><span class="s">&quot;</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">&lt;</span> <span class="mi">0</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;Cannot encode value </span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s"> &lt; 0&quot;</span>
<span class="nx">BASE64_CHARS</span><span class="p">[</span><span class="nx">value</span><span class="p">]</span>
<span class="nv">decodeBase64Char = </span><span class="nf">(char) -&gt;</span>
<span class="nv">value = </span><span class="nx">BASE64_CHARS</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">char</span>
<span class="k">if</span> <span class="nx">value</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;Invalid Base 64 character: </span><span class="si">#{</span><span class="nx">char</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">value</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
buffer += <span class="property">@encodeVlq</span> mapping.sourceLine - lastSourceLine
lastSourceLine = mapping.sourceLine</pre></div></div>
</li>
@@ -567,25 +445,18 @@ doesn&#39;t match anything in the source code.
<li id="section-20">
<div class="annotation">
<div class="pilwrap for-h3">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<h3>Base 64 VLQ encoding/decoding helpers</h3>
<p>Note that SourceMap VLQ encoding is &quot;backwards&quot;. MIDI style VLQ encoding puts the
most-significant-bit (MSB) from the original value into the MSB of the VLQ encoded value
(see <a href="http://en.wikipedia.org/wiki/File:Uintvar_coding.svg">http://en.wikipedia.org/wiki/File:Uintvar_coding.svg</a>). SourceMap VLQ does things
the other way around, with the least significat four bits of the original value encoded
into the first byte of the VLQ encoded value.
<p>The starting column in the original source, relative to the previous column.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">VLQ_SHIFT = </span><span class="mi">5</span>
<span class="nv">VLQ_CONTINUATION_BIT = </span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="nx">VLQ_SHIFT</span> <span class="c1"># 0010 0000</span>
<span class="nv">VLQ_VALUE_MASK = </span><span class="nx">VLQ_CONTINUATION_BIT</span> <span class="o">-</span> <span class="mi">1</span> <span class="c1"># 0001 1111</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
buffer += <span class="property">@encodeVlq</span> mapping.sourceColumn - lastSourceColumn
lastSourceColumn = mapping.sourceColumn
needComma = <span class="literal">yes</span></pre></div></div>
</li>
@@ -596,14 +467,23 @@ into the first byte of the VLQ encoded value.
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
</div>
<p>Encode a value as Base 64 VLQ.
<p>Produce the canonical JSON object format for a &quot;v3&quot; source map.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.vlqEncodeValue = </span><span class="nf">(value) -&gt;</span></pre></div></div>
<div class="content"><div class='highlight'><pre>
v3 =
version: <span class="number">3</span>
file: options.generatedFile <span class="keyword">or</span> <span class="string">''</span>
sourceRoot: options.sourceRoot <span class="keyword">or</span> <span class="string">''</span>
sources: options.sourceFiles <span class="keyword">or</span> [<span class="string">''</span>]
names: []
mappings: buffer
v3.sourcesContent = [code] <span class="keyword">if</span> options.inline
JSON.stringify v3, <span class="literal">null</span>, <span class="number">2</span></pre></div></div>
</li>
@@ -611,18 +491,13 @@ into the first byte of the VLQ encoded value.
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<div class="pilwrap for-h2">
<a class="pilcrow" href="#section-22">&#182;</a>
</div>
<p>Least significant bit represents the sign.
</p>
<h2>Base64 VLQ Encoding</h2>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">signBit = </span><span class="k">if</span> <span class="nx">value</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="k">then</span> <span class="mi">1</span> <span class="k">else</span> <span class="mi">0</span></pre></div></div>
</li>
@@ -633,16 +508,8 @@ into the first byte of the VLQ encoded value.
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>Next bits are the actual value
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">valueToEncode = </span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">abs</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="nx">signBit</span>
<span class="nv">answer = </span><span class="s">&quot;&quot;</span></pre></div></div>
</li>
@@ -652,23 +519,22 @@ into the first byte of the VLQ encoded value.
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<p>Make sure we encode at least one character, even if valueToEncode is 0.
<p>Note that SourceMap VLQ encoding is &quot;backwards&quot;. MIDI-style VLQ encoding puts
the most-significant-bit (MSB) from the original value into the MSB of the VLQ
encoded value (see <a href="http://en.wikipedia.org/wiki/File:Uintvar_coding.svg">Wikipedia</a>).
SourceMap VLQ does things the other way around, with the least significat four
bits of the original value encoded into the first byte of the VLQ encoded value.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="k">while</span> <span class="nx">valueToEncode</span> <span class="o">||</span> <span class="o">!</span><span class="nx">answer</span>
<span class="nv">nextVlqChunk = </span><span class="nx">valueToEncode</span> <span class="o">&amp;</span> <span class="nx">VLQ_VALUE_MASK</span>
<span class="nv">valueToEncode = </span><span class="nx">valueToEncode</span> <span class="o">&gt;&gt;</span> <span class="nx">VLQ_SHIFT</span>
<div class="content"><div class='highlight'><pre>
VLQ_SHIFT = <span class="number">5</span>
VLQ_CONTINUATION_BIT = <span class="number">1</span> &lt;&lt; VLQ_SHIFT <span class="comment"># 0010 0000</span>
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - <span class="number">1</span> <span class="comment"># 0001 1111</span>
<span class="k">if</span> <span class="nx">valueToEncode</span>
<span class="nx">nextVlqChunk</span> <span class="o">|=</span> <span class="nx">VLQ_CONTINUATION_BIT</span>
<span class="nx">answer</span> <span class="o">+=</span> <span class="nx">encodeBase64Char</span><span class="p">(</span><span class="nx">nextVlqChunk</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">answer</span></pre></div></div>
encodeVlq: (value) -&gt;
answer = <span class="string">''</span></pre></div></div>
</li>
@@ -679,32 +545,12 @@ into the first byte of the VLQ encoded value.
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
</div>
<p>Decode a Base 64 VLQ value.
</p>
<p>Returns <code>[value, consumed]</code> where <code>value</code> is the decoded value, and <code>consumed</code> is the number
of characters consumed from <code>str</code>.
<p>Least significant bit represents the sign.
</p>
</div>
<div class="content"><div class="highlight"><pre><span class="nv">exports.vlqDecodeValue = </span><span class="nf">(str, offset=0) -&gt;</span>
<span class="nv">position = </span><span class="nx">offset</span>
<span class="nv">done = </span><span class="kc">false</span>
<span class="nv">value = </span><span class="mi">0</span>
<span class="nv">continuationShift = </span><span class="mi">0</span>
<span class="k">while</span> <span class="o">!</span><span class="nx">done</span>
<span class="nv">nextVlqChunk = </span><span class="nx">decodeBase64Char</span><span class="p">(</span><span class="nx">str</span><span class="p">[</span><span class="nx">position</span><span class="p">])</span>
<span class="nx">position</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nv">nextChunkValue = </span><span class="nx">nextVlqChunk</span> <span class="o">&amp;</span> <span class="nx">VLQ_VALUE_MASK</span>
<span class="nx">value</span> <span class="o">+=</span> <span class="p">(</span><span class="nx">nextChunkValue</span> <span class="o">&lt;&lt;</span> <span class="nx">continuationShift</span><span class="p">)</span>
<span class="k">if</span> <span class="o">!</span><span class="p">(</span><span class="nx">nextVlqChunk</span> <span class="o">&amp;</span> <span class="nx">VLQ_CONTINUATION_BIT</span><span class="p">)</span></pre></div></div>
<div class="content"><div class='highlight'><pre> signBit = <span class="keyword">if</span> value &lt; <span class="number">0</span> <span class="keyword">then</span> <span class="number">1</span> <span class="keyword">else</span> <span class="number">0</span></pre></div></div>
</li>
@@ -715,14 +561,12 @@ of characters consumed from <code>str</code>.
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
</div>
<p>We&#39;ll be done after this character.
<p>The next bits are the actual value.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">done = </span><span class="kc">true</span></pre></div></div>
<div class="content"><div class='highlight'><pre> valueToEncode = (Math.abs(value) &lt;&lt; <span class="number">1</span>) + signBit</pre></div></div>
</li>
@@ -733,17 +577,18 @@ of characters consumed from <code>str</code>.
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
</div>
<p>Bits are encoded least-significant first (opposite of MIDI VLQ). Increase the
continuationShift, so the next byte will end up where it should in the value.
<p>Make sure we encode at least one character, even if valueToEncode is 0.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nx">continuationShift</span> <span class="o">+=</span> <span class="nx">VLQ_SHIFT</span>
<div class="content"><div class='highlight'><pre> <span class="keyword">while</span> valueToEncode <span class="keyword">or</span> <span class="keyword">not</span> answer
nextChunk = valueToEncode &amp; VLQ_VALUE_MASK
valueToEncode = valueToEncode &gt;&gt; VLQ_SHIFT
nextChunk |= VLQ_CONTINUATION_BIT <span class="keyword">if</span> valueToEncode
answer += <span class="property">@encodeBase64</span> nextChunk
<span class="nv">consumed = </span><span class="nx">position</span> <span class="o">-</span> <span class="nx">offset</span></pre></div></div>
answer</pre></div></div>
</li>
@@ -751,23 +596,47 @@ continuationShift, so the next byte will end up where it should in the value.
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<div class="pilwrap for-h2">
<a class="pilcrow" href="#section-28">&#182;</a>
</div>
<h2>Regular Base64 Encoding</h2>
</div>
</li>
<li id="section-29">
<div class="annotation">
<p>Least significant bit represents the sign.
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
</div>
</div>
<div class="content"><div class='highlight'><pre>
BASE64_CHARS = <span class="string">'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'</span>
encodeBase64: (value) -&gt;
BASE64_CHARS[value] <span class="keyword">or</span> <span class="keyword">throw</span> <span class="keyword">new</span> Error <span class="string">"Cannot Base64 encode value: <span class="subst">#{value}</span>"</span></pre></div></div>
</li>
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-30">&#182;</a>
</div>
<p>Our API for source maps is just the <code>SourceMap</code> class.
</p>
</div>
<div class="content"><div class="highlight"><pre> <span class="nv">signBit = </span><span class="nx">value</span> <span class="o">&amp;</span> <span class="mi">1</span>
<span class="nv">value = </span><span class="nx">value</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span>
<span class="k">if</span> <span class="nx">signBit</span> <span class="k">then</span> <span class="nv">value = </span><span class="o">-</span><span class="nx">value</span>
<span class="k">return</span> <span class="p">[</span><span class="nx">value</span><span class="p">,</span> <span class="nx">consumed</span><span class="p">]</span>
</pre></div></div>
<div class="content"><div class='highlight'><pre>
module.exports = SourceMap</pre></div></div>
</li>

File diff suppressed because one or more lines are too long

View File

@@ -131,15 +131,13 @@
compiles one-to-one into the equivalent JS, and there is
no interpretation at runtime. You can use any existing JavaScript library
seamlessly from CoffeeScript (and vice-versa). The compiled output is
readable and pretty-printed, passes through
<a href="http://www.javascriptlint.com/">JavaScript Lint</a>
without warnings, will work in every JavaScript runtime, and tends
readable and pretty-printed, will work in every JavaScript runtime, and tends
to run as fast or faster than the equivalent handwritten JavaScript.
</p>
<p>
<b>Latest Version:</b>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.6.1">1.6.1</a>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.6.3">1.6.3</a>
</p>
<pre>
@@ -266,16 +264,6 @@ sudo bin/cake install</pre>
directly to <b>stdout</b>.
</td>
</tr>
<tr>
<td><code>-l, --lint</code></td>
<td>
If the <tt>jsl</tt>
(<a href="http://www.javascriptlint.com/">JavaScript Lint</a>)
command is installed, use it
to check the compilation of a CoffeeScript file. (Handy in
conjunction with <br /> <tt>--watch</tt>)
</td>
</tr>
<tr>
<td><code>-s, --stdio</code></td>
<td>
@@ -284,6 +272,14 @@ sudo bin/cake install</pre>
<tt>cat src/cake.coffee | coffee -sc</tt>
</td>
</tr>
<tr>
<td><code>-l, --literate</code></td>
<td>
Parses the code as Literate CoffeeScript. You only need to specify
this when passing in code directly over <b>stdio</b>, or using some sort
of extension-less file name.
</td>
</tr>
<tr>
<td><code>-e, --eval</code></td>
<td>
@@ -291,13 +287,6 @@ sudo bin/cake install</pre>
command line. For example:<br /><tt>coffee -e "console.log num for num in [10..1]"</tt>
</td>
</tr>
<tr>
<td><code>-r, --require</code></td>
<td>
Load a library before compiling or executing your script. Can be used
to hook in to the compiler (to add Growl notifications, for example).
</td>
</tr>
<tr>
<td><code>-b, --bare</code></td>
<td>
@@ -812,6 +801,11 @@ Expressions
Destructuring assignment can even be combined with splats.
</p>
<%= code_for('patterns_and_splats', 'contents.join("")') %>
<p>
Destructuring assignment is also useful when combined with class constructors
to assign properties to your instance from an options object passed to the constructor.
</p>
<%= code_for('constructor_destructuring', 'contents.join("")') %>
<p>
<span id="fat-arrow" class="bookmark"></span>
@@ -869,6 +863,11 @@ Expressions
</p>
<%= code_for('switch') %>
<p>
Switch statements can also be used without a control expression, turning them in to a cleaner alternative to if/else chains.
</p>
<%= code_for('switch_with_no_expression') %>
<p>
<span id="try" class="bookmark"></span>
<b class="header">Try/Catch/Finally</b>
@@ -922,7 +921,7 @@ Expressions
<b class="header">Block Regular Expressions</b>
Similar to block strings and comments, CoffeeScript supports block regexes &mdash;
extended regular expressions that ignore internal whitespace and can contain
comments and interpolation. Modeled after Perl's <tt>/x</tt> modifier, CoffeeSctipt's
comments and interpolation. Modeled after Perl's <tt>/x</tt> modifier, CoffeeScript's
block regexes are delimited by <tt>///</tt> and go a long way towards making complex
regular expressions readable. To quote from the CoffeeScript source:
</p>
@@ -1165,6 +1164,13 @@ Expressions
<a href="http://github.com/jashkenas/coffee-script/wiki/FAQ">The FAQ</a><br />
Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
</li>
<li>
<a href="http://js2coffee.org">JS2Coffee</a><br />
Is a very well done reverse JavaScript-to-CoffeeScript compiler. It's
not going to be perfect (infer what your JavaScript classes are, when
you need bound functions, and so on...) &mdash; but it's a great starting
point for converting simple scripts.
</li>
<li>
<a href="https://github.com/jashkenas/coffee-script/downloads">High-Rez Logo</a><br />
The CoffeeScript logo is available in Illustrator, EPS and PSD formats, for use
@@ -1192,6 +1198,64 @@ Expressions
Change Log
</h2>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.6.2...1.6.3">1.6.3</a>
<span class="timestamp"> &ndash; <small>June 2, 2013</small></span>
</b>
<ul>
<li>
The CoffeeScript REPL now remembers your history between sessions.
Just like a proper REPL should.
</li>
<li>
You can now use <tt>require</tt> in Node to load <tt>.coffee.md</tt>
Literate CoffeeScript files. In the browser,
<tt>text/literate-coffeescript</tt> script tags.
</li>
<li>
The old <tt>coffee --lint</tt> command has been removed. It was useful
while originally working on the compiler, but has been surpassed by
JSHint. You may now use <tt>-l</tt> to pass literate files in over
<b>stdio</b>.
</li>
<li>
Bugfixes for Windows path separators, <tt>catch</tt> without naming
the error, and executable-class-bodies-with-
prototypal-property-attachment.
</li>
</ul>
</p>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.6.1...1.6.2">1.6.2</a>
<span class="timestamp"> &ndash; <small>March 18, 2013</small></span>
</b>
<ul>
<li>
Source maps have been used to provide automatic line-mapping when
running CoffeeScript directly via the <tt>coffee</tt> command, and
for automatic line-mapping when running CoffeeScript directly in the
browser. Also, to provide better error messages for semantic errors
thrown by the compiler &mdash;
<a href="http://cl.ly/NdOA">with colors, even</a>.
</li>
<li>
Improved support for mixed literate/vanilla-style CoffeeScript projects,
and generating source maps for both at the same time.
</li>
<li>
Fixes for <b>1.6.x</b> regressions with overriding inherited bound
functions, and for Windows file path management.
</li>
<li>
The <tt>coffee</tt> command can now correctly <tt>fork()</tt>
both <tt>.coffee</tt> and <tt>.js</tt> files. (Requires Node.js 0.9+)
</li>
</ul>
</p>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.5.0...1.6.1">1.6.1</a>
@@ -1939,8 +2003,10 @@ Expressions
else
$(el).text window.compiledJS
$('#error').hide()
catch error
$('#error').text(error.message).show()
catch {location, message}
if location?
message = "Error on line #{location.first_line + 1}: #{message}"
$('#error').text(message).show()
# Update permalink
$('#repl_permalink').attr 'href', "##{sourceFragment}#{encodeURIComponent source}"

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var volume, winner;
if (ignition === true) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var courses, dish, food, foods, i, _i, _j, _k, _len, _len1, _len2, _ref;
_ref = ['toast', 'cheese', 'wine'];

View File

@@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
/*
CoffeeScript Compiler v1.6.1
SkinnyMochaHalfCaffScript Compiler v1.0
Released under the MIT License
*/

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var fs;
fs = require('fs');

View File

@@ -1,10 +1,9 @@
// Generated by CoffeeScript 1.6.1
var Animal, Horse, Snake, sam, tom,
// Generated by CoffeeScript 1.6.3
var Animal, Horse, Snake, sam, tom, _ref, _ref1,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Animal = (function() {
function Animal(name) {
this.name = name;
}
@@ -18,11 +17,11 @@ Animal = (function() {
})();
Snake = (function(_super) {
__extends(Snake, _super);
function Snake() {
return Snake.__super__.constructor.apply(this, arguments);
_ref = Snake.__super__.constructor.apply(this, arguments);
return _ref;
}
Snake.prototype.move = function() {
@@ -35,11 +34,11 @@ Snake = (function(_super) {
})(Animal);
Horse = (function(_super) {
__extends(Horse, _super);
function Horse() {
return Horse.__super__.constructor.apply(this, arguments);
_ref1 = Horse.__super__.constructor.apply(this, arguments);
return _ref1;
}
Horse.prototype.move = function() {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var cholesterol, healthy;
cholesterol = 127;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var date, mood;
if (singing) {

View File

@@ -0,0 +1,11 @@
// Generated by CoffeeScript 1.6.3
var Person;
Person = (function() {
function Person(options) {
this.name = options.name, this.age = options.age, this.height = options.height;
}
return Person;
})();

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var fill;
fill = function(container, liquid) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var filename, _fn, _i, _len;
_fn = function(filename) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var hi;
hi = function() {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var footprints, solipsism, speed;
if ((typeof mind !== "undefined" && mind !== null) && (typeof world === "undefined" || world === null)) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var eldest, grade;
grade = function(student) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var one, six, three, two;
six = (one = 1) + (two = 2) + (three = 3);

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var globals, name;
globals = ((function() {

View File

@@ -1,9 +1,11 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var error;
alert((function() {
try {
return nonexistent / void 0;
} catch (error) {
} catch (_error) {
error = _error;
return "And the error is ... " + error;
}
})());

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var Account;
Account = function(customer, cart) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var cube, square;
square = function(x) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var html;
html = "<strong>\n cup of coffeescript\n</strong>";

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var OPERATOR;
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var author, quote, sentence;
author = "Wittgenstein";

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var city, forecast, temp, weatherReport, _ref;
weatherReport = function(location) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var age, ages, child, yearsOld;
yearsOld = {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var city, futurists, name, street, _ref, _ref1;
futurists = {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var bitlist, kids, singers, song;
song = ["do", "re", "mi", "fa", "so"];

View File

@@ -1,5 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
$('.account').attr({
"class": 'active'
});

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var cubes, list, math, num, number, opposite, race, square,
__slice = [].slice;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var theBait, theSwitch, _ref;
theBait = 1000;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var close, contents, open, tag, _i, _ref,
__slice = [].slice;

View File

@@ -1,5 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
String.prototype.dasherize = function() {
return this.replace(/_/g, "-");
};

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var countdown, num;
countdown = (function() {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var changeNumbers, inner, outer;
outer = 1;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var copy, end, middle, numbers, start;
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var zip, _ref;
zip = typeof lottery.drawWinner === "function" ? (_ref = lottery.drawWinner().address) != null ? _ref.zipcode : void 0 : void 0;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var awardMedals, contenders, gold, rest, silver,
__slice = [].slice;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var numbers, _ref;
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var mobyDick;
mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...";

View File

@@ -1,5 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
switch (day) {
case "Mon":
go(work);

View File

@@ -0,0 +1,19 @@
// Generated by CoffeeScript 1.6.3
var grade, score;
score = 76;
grade = (function() {
switch (false) {
case !(score < 60):
return 'F';
case !(score < 70):
return 'D';
case !(score < 80):
return 'C';
case !(score < 90):
return 'B';
default:
return 'A';
}
})();

View File

@@ -1,9 +1,11 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var error;
try {
allHellBreaksLoose();
catsAndDogsLivingTogether();
} catch (error) {
} catch (_error) {
error = _error;
print(error);
} finally {
cleanUp();

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
var lyrics, num;
if (this.studyingEconomics) {

File diff suppressed because one or more lines are too long

View File

@@ -1,44 +0,0 @@
# JavaScriptLint configuration file for CoffeeScript.
+no_return_value # function {0} does not always return a value
+duplicate_formal # duplicate formal argument {0}
-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
+var_hides_arg # variable {0} hides argument
+redeclared_var # redeclaration of {0} {1}
-anon_no_return_value # anonymous function does not always return a value
+missing_semicolon # missing semicolon
+meaningless_block # meaningless block; curly braces have no impact
-comma_separated_stmts # multiple statements separated by commas (use semicolons?)
+unreachable_code # unreachable code
+missing_break # missing break statement
-missing_break_for_last_case # missing break statement for last case in switch
-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
-useless_void # use of the void type may be unnecessary (void is always undefined)
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
+use_of_label # use of label
-block_without_braces # block statement without curly braces
+leading_decimal_point # leading decimal point may indicate a number or an object member
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
+octal_number # leading zeros make an octal number
+nested_comment # nested comment
+misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
+empty_statement # empty statement or extra semicolon
-missing_option_explicit # the "option explicit" control comment is missing
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
+dup_option_explicit # duplicate "option explicit" control comment
+useless_assign # useless assignment
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
-missing_default_case # missing default case in switch statement
+duplicate_case_in_switch # duplicate case in switch statements
+default_not_at_end # the default case is not at the end of the switch statement
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
+useless_comparison # useless comparison; comparing identical expressions
+with_statement # with statement hides undeclared variables; use temporary variable instead
+trailing_comma_in_array # extra comma is not recommended in array initializers
+assign_to_function_call # assignment to a function call
+parseint_missing_radix # parseInt missing radix parameter
+lambda_assign_requires_semicolon

View File

@@ -108,15 +108,13 @@
compiles one-to-one into the equivalent JS, and there is
no interpretation at runtime. You can use any existing JavaScript library
seamlessly from CoffeeScript (and vice-versa). The compiled output is
readable and pretty-printed, passes through
<a href="http://www.javascriptlint.com/">JavaScript Lint</a>
without warnings, will work in every JavaScript runtime, and tends
readable and pretty-printed, will work in every JavaScript runtime, and tends
to run as fast or faster than the equivalent handwritten JavaScript.
</p>
<p>
<b>Latest Version:</b>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.6.1">1.6.1</a>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.6.3">1.6.3</a>
</p>
<pre>
@@ -359,16 +357,6 @@ sudo bin/cake install</pre>
directly to <b>stdout</b>.
</td>
</tr>
<tr>
<td><code>-l, --lint</code></td>
<td>
If the <tt>jsl</tt>
(<a href="http://www.javascriptlint.com/">JavaScript Lint</a>)
command is installed, use it
to check the compilation of a CoffeeScript file. (Handy in
conjunction with <br /> <tt>--watch</tt>)
</td>
</tr>
<tr>
<td><code>-s, --stdio</code></td>
<td>
@@ -377,6 +365,14 @@ sudo bin/cake install</pre>
<tt>cat src/cake.coffee | coffee -sc</tt>
</td>
</tr>
<tr>
<td><code>-l, --literate</code></td>
<td>
Parses the code as Literate CoffeeScript. You only need to specify
this when passing in code directly over <b>stdio</b>, or using some sort
of extension-less file name.
</td>
</tr>
<tr>
<td><code>-e, --eval</code></td>
<td>
@@ -384,13 +380,6 @@ sudo bin/cake install</pre>
command line. For example:<br /><tt>coffee -e "console.log num for num in [10..1]"</tt>
</td>
</tr>
<tr>
<td><code>-r, --require</code></td>
<td>
Load a library before compiling or executing your script. Can be used
to hook in to the compiler (to add Growl notifications, for example).
</td>
</tr>
<tr>
<td><code>-b, --bare</code></td>
<td>
@@ -671,8 +660,7 @@ kids = {
log object.<span class="Storage">class</span>
</pre><pre class="idle">
<span class="Keyword">$</span>(<span class="String"><span class="String">'</span>.account<span class="String">'</span></span>).attr({
</pre><pre class="idle"><span class="Keyword">$</span>(<span class="String"><span class="String">'</span>.account<span class="String">'</span></span>).attr({
<span class="String"><span class="String">&quot;</span>class<span class="String">&quot;</span></span>: <span class="String"><span class="String">'</span>active<span class="String">'</span></span>
});
@@ -1272,19 +1260,23 @@ globals = ((function() {
<span class="String"><span class="String">&quot;</span>And the error is ... <span class="String"><span class="String">#{</span>error<span class="String">}</span></span><span class="String">&quot;</span></span>
)
</pre><pre class="idle">
</pre><pre class="idle"><span class="Storage">var</span> error;
<span class="LibraryFunction">alert</span>((<span class="Storage">function</span>() {
<span class="Keyword">try</span> {
<span class="Keyword">return</span> nonexistent / <span class="Storage">void</span> <span class="Number">0</span>;
} <span class="Keyword">catch</span> (error) {
} <span class="Keyword">catch</span> (_error) {
error <span class="Keyword">=</span> _error;
<span class="Keyword">return</span> <span class="String"><span class="String">&quot;</span>And the error is ... <span class="String">&quot;</span></span> <span class="Keyword">+</span> error;
}
})());
</pre><script>window.example19 = "alert(\n try\n nonexistent / undefined\n catch error\n \"And the error is ... #{error}\"\n)\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example19);'>load</div><div class='minibutton ok' onclick='javascript:
</pre><script>window.example19 = "alert(\n try\n nonexistent / undefined\n catch error\n \"And the error is ... #{error}\"\n)\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example19);'>load</div><div class='minibutton ok' onclick='javascript: var error;
alert((function() {
try {
return nonexistent / void 0;
} catch (error) {
} catch (_error) {
error = _error;
return "And the error is ... " + error;
}
})());
@@ -1509,12 +1501,11 @@ tom.move()
</pre><pre class="idle"><span class="Storage">var</span> Animal, Horse, Snake, sam, tom,
</pre><pre class="idle"><span class="Storage">var</span> Animal, Horse, Snake, sam, tom, _ref, _ref1,
__hasProp <span class="Keyword">=</span> {}.hasOwnProperty,
<span class="FunctionName">__extends</span> = <span class="Storage">function</span>(<span class="FunctionArgument">child, parent</span>) { <span class="Keyword">for</span> (<span class="Storage">var</span> key <span class="Keyword">in</span> parent) { <span class="Keyword">if</span> (__hasProp.<span class="LibraryFunction">call</span>(parent, key)) child[key] <span class="Keyword">=</span> parent[key]; } <span class="Storage">function</span> <span class="FunctionName">ctor</span>() { <span class="Variable">this</span>.<span class="LibraryConstant">constructor</span> <span class="Keyword">=</span> child; } <span class="LibraryClassType">ctor</span>.<span class="LibraryConstant">prototype</span> = parent.<span class="LibraryConstant">prototype</span>; <span class="LibraryClassType">child</span>.<span class="LibraryConstant">prototype</span> = <span class="Keyword">new</span> <span class="TypeName">ctor</span>(); child.__super__ <span class="Keyword">=</span> parent.<span class="LibraryConstant">prototype</span>; <span class="Keyword">return</span> child; };
Animal <span class="Keyword">=</span> (<span class="Storage">function</span>() {
<span class="Storage">function</span> <span class="FunctionName">Animal</span>(<span class="FunctionArgument">name</span>) {
<span class="Variable">this</span>.<span class="LibraryConstant">name</span> <span class="Keyword">=</span> name;
}
@@ -1528,11 +1519,11 @@ Animal <span class="Keyword">=</span> (<span class="Storage">function</span>() {
})();
Snake <span class="Keyword">=</span> (<span class="Storage">function</span>(_super) {
__extends(Snake, _super);
<span class="Storage">function</span> <span class="FunctionName">Snake</span>() {
<span class="Keyword">return</span> Snake.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
_ref <span class="Keyword">=</span> Snake.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
<span class="Keyword">return</span> _ref;
}
<span class="LibraryClassType">Snake</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
@@ -1545,11 +1536,11 @@ Snake <span class="Keyword">=</span> (<span class="Storage">function</span>(_sup
})(Animal);
Horse <span class="Keyword">=</span> (<span class="Storage">function</span>(_super) {
__extends(Horse, _super);
<span class="Storage">function</span> <span class="FunctionName">Horse</span>() {
<span class="Keyword">return</span> Horse.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
_ref1 <span class="Keyword">=</span> Horse.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
<span class="Keyword">return</span> _ref1;
}
<span class="LibraryClassType">Horse</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
@@ -1568,12 +1559,11 @@ tom <span class="Keyword">=</span> <span class="Keyword">new</span> <span class=
sam.move();
tom.move();
</pre><script>window.example23 = "class Animal\n constructor: (@name) ->\n\n move: (meters) ->\n alert @name + \" moved #{meters}m.\"\n\nclass Snake extends Animal\n move: ->\n alert \"Slithering...\"\n super 5\n\nclass Horse extends Animal\n move: ->\n alert \"Galloping...\"\n super 45\n\nsam = new Snake \"Sammy the Python\"\ntom = new Horse \"Tommy the Palomino\"\n\nsam.move()\ntom.move()\n\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example23);'>load</div><div class='minibutton ok' onclick='javascript: var Animal, Horse, Snake, sam, tom,
</pre><script>window.example23 = "class Animal\n constructor: (@name) ->\n\n move: (meters) ->\n alert @name + \" moved #{meters}m.\"\n\nclass Snake extends Animal\n move: ->\n alert \"Slithering...\"\n super 5\n\nclass Horse extends Animal\n move: ->\n alert \"Galloping...\"\n super 45\n\nsam = new Snake \"Sammy the Python\"\ntom = new Horse \"Tommy the Palomino\"\n\nsam.move()\ntom.move()\n\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example23);'>load</div><div class='minibutton ok' onclick='javascript: var Animal, Horse, Snake, sam, tom, _ref, _ref1,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Animal = (function() {
function Animal(name) {
this.name = name;
}
@@ -1587,11 +1577,11 @@ Animal = (function() {
})();
Snake = (function(_super) {
__extends(Snake, _super);
function Snake() {
return Snake.__super__.constructor.apply(this, arguments);
_ref = Snake.__super__.constructor.apply(this, arguments);
return _ref;
}
Snake.prototype.move = function() {
@@ -1604,11 +1594,11 @@ Snake = (function(_super) {
})(Animal);
Horse = (function(_super) {
__extends(Horse, _super);
function Horse() {
return Horse.__super__.constructor.apply(this, arguments);
_ref1 = Horse.__super__.constructor.apply(this, arguments);
return _ref1;
}
Horse.prototype.move = function() {
@@ -1639,12 +1629,10 @@ tom.move();
<div class='code'><pre class="idle"><span class="FunctionName">String::dasherize </span><span class="Keyword">=</span> <span class="Keyword">-</span><span class="Keyword">&gt;</span>
<span class="Variable">this</span>.replace <span class="String">/_/g</span>, <span class="String"><span class="String">&quot;</span>-<span class="String">&quot;</span></span>
</pre><pre class="idle">
<span class="LibraryClassType">String</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">dasherize</span> = <span class="Storage">function</span>() {
</pre><pre class="idle"><span class="LibraryClassType">String</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">dasherize</span> = <span class="Storage">function</span>() {
<span class="Keyword">return</span> <span class="Variable">this</span>.<span class="LibraryFunction">replace</span>(<span class="String"><span class="String">/</span>_<span class="String">/</span>g</span>, <span class="String"><span class="String">&quot;</span>-<span class="String">&quot;</span></span>);
};
</pre><script>window.example24 = "String::dasherize = ->\n this.replace /_/g, \"-\"\n\nalert \"one_two\".dasherize()"</script><div class='minibutton load' onclick='javascript: loadConsole(example24);'>load</div><div class='minibutton ok' onclick='javascript:
String.prototype.dasherize = function() {
</pre><script>window.example24 = "String::dasherize = ->\n this.replace /_/g, \"-\"\n\nalert \"one_two\".dasherize()"</script><div class='minibutton load' onclick='javascript: loadConsole(example24);'>load</div><div class='minibutton ok' onclick='javascript: String.prototype.dasherize = function() {
return this.replace(/_/g, "-");
};
;alert("one_two".dasherize());'>run: "one_two".dasherize()</div><br class='clear' /></div>
@@ -1786,6 +1774,35 @@ _ref <span class="Keyword">=</span> tag.<span class="LibraryFunction">split</spa
tag = "<impossible>";
_ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call(_ref, 1, _i = _ref.length - 1) : (_i = 1, []), close = _ref[_i++];
;alert(contents.join(""));'>run: contents.join("")</div><br class='clear' /></div>
<p>
Destructuring assignment is also useful when combined with class constructors
to assign properties to your instance from an options object passed to the constructor.
</p>
<div class='code'><pre class="idle"><span class="Storage">class</span> <span class="TypeName">Person</span>
<span class="FunctionName">constructor</span><span class="Keyword">:</span> <span class="FunctionArgument">(options)</span> <span class="Storage">-&gt;</span>
<span class="Keyword">{</span><span class="Variable">@name</span>, <span class="Variable">@age</span>, <span class="Variable">@height</span><span class="Keyword">} =</span> options
</pre><pre class="idle"><span class="Storage">var</span> Person;
Person <span class="Keyword">=</span> (<span class="Storage">function</span>() {
<span class="Storage">function</span> <span class="FunctionName">Person</span>(<span class="FunctionArgument">options</span>) {
<span class="Variable">this</span>.<span class="LibraryConstant">name</span> <span class="Keyword">=</span> options.<span class="LibraryConstant">name</span>, <span class="Variable">this</span>.age <span class="Keyword">=</span> options.age, <span class="Variable">this</span>.<span class="LibraryConstant">height</span> <span class="Keyword">=</span> options.<span class="LibraryConstant">height</span>;
}
<span class="Keyword">return</span> Person;
})();
</pre><script>window.example29 = "class Person\n constructor: (options) -> \n {@name, @age, @height} = options\n\nalert contents.join(\"\")"</script><div class='minibutton load' onclick='javascript: loadConsole(example29);'>load</div><div class='minibutton ok' onclick='javascript: var Person;
Person = (function() {
function Person(options) {
this.name = options.name, this.age = options.age, this.height = options.height;
}
return Person;
})();
;alert(contents.join(""));'>run: contents.join("")</div><br class='clear' /></div>
<p>
@@ -1822,7 +1839,7 @@ _ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call
<span class="Keyword">return</span> _this.customer.purchase(_this.cart);
});
};
</pre><script>window.example29 = "Account = (customer, cart) ->\n @customer = customer\n @cart = cart\n\n $('.shopping_cart').bind 'click', (event) =>\n @customer.purchase @cart"</script><div class='minibutton load' onclick='javascript: loadConsole(example29);'>load</div><br class='clear' /></div>
</pre><script>window.example30 = "Account = (customer, cart) ->\n @customer = customer\n @cart = cart\n\n $('.shopping_cart').bind 'click', (event) =>\n @customer.purchase @cart"</script><div class='minibutton load' onclick='javascript: loadConsole(example30);'>load</div><br class='clear' /></div>
<p>
If we had used <tt>-&gt;</tt> in the callback above, <tt>@customer</tt> would
have referred to the undefined "customer" property of the DOM element,
@@ -1852,7 +1869,7 @@ _ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call
<span class="FunctionName">hi</span> = <span class="Storage">function</span>() {
<span class="Keyword">return</span> [<span class="LibraryClassType">document</span>.<span class="LibraryConstant">title</span>, <span class="String"><span class="String">&quot;</span>Hello JavaScript<span class="String">&quot;</span></span>].<span class="LibraryFunction">join</span>(<span class="String"><span class="String">&quot;</span>: <span class="String">&quot;</span></span>);
};
</pre><script>window.example30 = "hi = `function() {\n return [document.title, \"Hello JavaScript\"].join(\": \");\n}`\n\nalert hi()"</script><div class='minibutton load' onclick='javascript: loadConsole(example30);'>load</div><div class='minibutton ok' onclick='javascript: var hi;
</pre><script>window.example31 = "hi = `function() {\n return [document.title, \"Hello JavaScript\"].join(\": \");\n}`\n\nalert hi()"</script><div class='minibutton load' onclick='javascript: loadConsole(example31);'>load</div><div class='minibutton ok' onclick='javascript: var hi;
hi = function() {
return [document.title, "Hello JavaScript"].join(": ");
@@ -1884,8 +1901,7 @@ hi = function() {
go dancing
<span class="Keyword">when</span> <span class="String"><span class="String">&quot;</span>Sun<span class="String">&quot;</span></span> <span class="Keyword">then</span> go church
<span class="Keyword">else</span> go work
</pre><pre class="idle">
<span class="Keyword">switch</span> (day) {
</pre><pre class="idle"><span class="Keyword">switch</span> (day) {
<span class="Keyword">case</span> <span class="String"><span class="String">&quot;</span>Mon<span class="String">&quot;</span></span>:
<span class="LibraryFunction">go</span>(work);
<span class="Keyword">break</span>;
@@ -1908,7 +1924,38 @@ hi = function() {
<span class="Keyword">default</span>:
<span class="LibraryFunction">go</span>(work);
}
</pre><script>window.example31 = "switch day\n when \"Mon\" then go work\n when \"Tue\" then go relax\n when \"Thu\" then go iceFishing\n when \"Fri\", \"Sat\"\n if day is bingoDay\n go bingo\n go dancing\n when \"Sun\" then go church\n else go work"</script><div class='minibutton load' onclick='javascript: loadConsole(example31);'>load</div><br class='clear' /></div>
</pre><script>window.example32 = "switch day\n when \"Mon\" then go work\n when \"Tue\" then go relax\n when \"Thu\" then go iceFishing\n when \"Fri\", \"Sat\"\n if day is bingoDay\n go bingo\n go dancing\n when \"Sun\" then go church\n else go work"</script><div class='minibutton load' onclick='javascript: loadConsole(example32);'>load</div><br class='clear' /></div>
<p>
Switch statements can also be used without a control expression, turning them in to a cleaner alternative to if/else chains.
</p>
<div class='code'><pre class="idle">score <span class="Keyword">=</span> <span class="Number">76</span>
grade <span class="Keyword">=</span> <span class="Keyword">switch</span>
<span class="Keyword">when</span> score <span class="Keyword">&lt;</span> <span class="Number">60</span> <span class="Keyword">then</span> <span class="String"><span class="String">'</span>F<span class="String">'</span></span>
<span class="Keyword">when</span> score <span class="Keyword">&lt;</span> <span class="Number">70</span> <span class="Keyword">then</span> <span class="String"><span class="String">'</span>D<span class="String">'</span></span>
<span class="Keyword">when</span> score <span class="Keyword">&lt;</span> <span class="Number">80</span> <span class="Keyword">then</span> <span class="String"><span class="String">'</span>C<span class="String">'</span></span>
<span class="Keyword">when</span> score <span class="Keyword">&lt;</span> <span class="Number">90</span> <span class="Keyword">then</span> <span class="String"><span class="String">'</span>B<span class="String">'</span></span>
<span class="Keyword">else</span> <span class="String"><span class="String">'</span>A<span class="String">'</span></span>
<span class="Comment"><span class="Comment">#</span> grade == 'C'</span>
</pre><pre class="idle"><span class="Storage">var</span> grade, score;
score <span class="Keyword">=</span> <span class="Number">76</span>;
grade <span class="Keyword">=</span> (<span class="Storage">function</span>() {
<span class="Keyword">switch</span> (<span class="BuiltInConstant">false</span>) {
<span class="Keyword">case</span> <span class="Keyword">!</span>(score <span class="Keyword">&lt;</span> <span class="Number">60</span>):
<span class="Keyword">return</span> <span class="String"><span class="String">'</span>F<span class="String">'</span></span>;
<span class="Keyword">case</span> <span class="Keyword">!</span>(score <span class="Keyword">&lt;</span> <span class="Number">70</span>):
<span class="Keyword">return</span> <span class="String"><span class="String">'</span>D<span class="String">'</span></span>;
<span class="Keyword">case</span> <span class="Keyword">!</span>(score <span class="Keyword">&lt;</span> <span class="Number">80</span>):
<span class="Keyword">return</span> <span class="String"><span class="String">'</span>C<span class="String">'</span></span>;
<span class="Keyword">case</span> <span class="Keyword">!</span>(score <span class="Keyword">&lt;</span> <span class="Number">90</span>):
<span class="Keyword">return</span> <span class="String"><span class="String">'</span>B<span class="String">'</span></span>;
<span class="Keyword">default</span>:
<span class="Keyword">return</span> <span class="String"><span class="String">'</span>A<span class="String">'</span></span>;
}
})();
</pre><script>window.example33 = "score = 76\ngrade = switch\n when score < 60 then 'F'\n when score < 70 then 'D'\n when score < 80 then 'C'\n when score < 90 then 'B'\n else 'A'\n# grade == 'C'\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example33);'>load</div><br class='clear' /></div>
<p>
<span id="try" class="bookmark"></span>
@@ -1924,16 +1971,18 @@ hi = function() {
<span class="Keyword">finally</span>
cleanUp()
</pre><pre class="idle">
</pre><pre class="idle"><span class="Storage">var</span> error;
<span class="Keyword">try</span> {
allHellBreaksLoose();
catsAndDogsLivingTogether();
} <span class="Keyword">catch</span> (error) {
} <span class="Keyword">catch</span> (_error) {
error <span class="Keyword">=</span> _error;
<span class="LibraryFunction">print</span>(error);
} <span class="Keyword">finally</span> {
cleanUp();
}
</pre><script>window.example32 = "try\n allHellBreaksLoose()\n catsAndDogsLivingTogether()\ncatch error\n print error\nfinally\n cleanUp()\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example32);'>load</div><br class='clear' /></div>
</pre><script>window.example34 = "try\n allHellBreaksLoose()\n catsAndDogsLivingTogether()\ncatch error\n print error\nfinally\n cleanUp()\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example34);'>load</div><br class='clear' /></div>
<p>
<span id="comparisons" class="bookmark"></span>
@@ -1953,7 +2002,7 @@ healthy <span class="Keyword">=</span> <span class="Number">200</span> <span cla
cholesterol <span class="Keyword">=</span> <span class="Number">127</span>;
healthy <span class="Keyword">=</span> (<span class="Number">200</span> <span class="Keyword">&gt;</span> cholesterol <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> cholesterol <span class="Keyword">&gt;</span> <span class="Number">60</span>);
</pre><script>window.example33 = "cholesterol = 127\n\nhealthy = 200 > cholesterol > 60\n\nalert healthy"</script><div class='minibutton load' onclick='javascript: loadConsole(example33);'>load</div><div class='minibutton ok' onclick='javascript: var cholesterol, healthy;
</pre><script>window.example35 = "cholesterol = 127\n\nhealthy = 200 > cholesterol > 60\n\nalert healthy"</script><div class='minibutton load' onclick='javascript: loadConsole(example35);'>load</div><div class='minibutton ok' onclick='javascript: var cholesterol, healthy;
cholesterol = 127;
@@ -1983,7 +2032,7 @@ author <span class="Keyword">=</span> <span class="String"><span class="String">
quote <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>A picture is a fact. -- <span class="String">&quot;</span></span> <span class="Keyword">+</span> author;
sentence <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span><span class="String">&quot;</span></span> <span class="Keyword">+</span> (<span class="Number">22</span> / <span class="Number">7</span>) <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> is a decent approximation of π<span class="String">&quot;</span></span>;
</pre><script>window.example34 = "author = \"Wittgenstein\"\nquote = \"A picture is a fact. -- #{ author }\"\n\nsentence = \"#{ 22 / 7 } is a decent approximation of π\"\n\nalert sentence"</script><div class='minibutton load' onclick='javascript: loadConsole(example34);'>load</div><div class='minibutton ok' onclick='javascript: var author, quote, sentence;
</pre><script>window.example36 = "author = \"Wittgenstein\"\nquote = \"A picture is a fact. -- #{ author }\"\n\nsentence = \"#{ 22 / 7 } is a decent approximation of π\"\n\nalert sentence"</script><div class='minibutton load' onclick='javascript: loadConsole(example36);'>load</div><div class='minibutton ok' onclick='javascript: var author, quote, sentence;
author = "Wittgenstein";
@@ -2005,7 +2054,7 @@ sentence = "" + (22 / 7) + " is a decent approximation of π";
</pre><pre class="idle"><span class="Storage">var</span> mobyDick;
mobyDick <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...<span class="String">&quot;</span></span>;
</pre><script>window.example35 = "mobyDick = \"Call me Ishmael. Some years ago --\n never mind how long precisely -- having little\n or no money in my purse, and nothing particular\n to interest me on shore, I thought I would sail\n about a little and see the watery part of the\n world...\"\n\nalert mobyDick"</script><div class='minibutton load' onclick='javascript: loadConsole(example35);'>load</div><div class='minibutton ok' onclick='javascript: var mobyDick;
</pre><script>window.example37 = "mobyDick = \"Call me Ishmael. Some years ago --\n never mind how long precisely -- having little\n or no money in my purse, and nothing particular\n to interest me on shore, I thought I would sail\n about a little and see the watery part of the\n world...\"\n\nalert mobyDick"</script><div class='minibutton load' onclick='javascript: loadConsole(example37);'>load</div><div class='minibutton ok' onclick='javascript: var mobyDick;
mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...";
;alert(mobyDick);'>run: mobyDick</div><br class='clear' /></div>
@@ -2024,7 +2073,7 @@ mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely --
</pre><pre class="idle"><span class="Storage">var</span> html;
html <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>&lt;strong&gt;<span class="UserDefinedConstant">\n</span> cup of coffeescript<span class="UserDefinedConstant">\n</span>&lt;/strong&gt;<span class="String">&quot;</span></span>;
</pre><script>window.example36 = "html = \"\"\"\n <strong>\n cup of coffeescript\n </strong>\n \"\"\"\n\nalert html"</script><div class='minibutton load' onclick='javascript: loadConsole(example36);'>load</div><div class='minibutton ok' onclick='javascript: var html;
</pre><script>window.example38 = "html = \"\"\"\n <strong>\n cup of coffeescript\n </strong>\n \"\"\"\n\nalert html"</script><div class='minibutton load' onclick='javascript: loadConsole(example38);'>load</div><div class='minibutton ok' onclick='javascript: var html;
html = "<strong>\n cup of coffeescript\n</strong>";
;alert(html);'>run: html</div><br class='clear' /></div>
@@ -2038,25 +2087,25 @@ html = "<strong>\n cup of coffeescript\n</strong>";
are preserved in the generated code.
</p>
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">###</span></span>
<span class="Comment">CoffeeScript Compiler v1.6.1</span>
<span class="Comment">SkinnyMochaHalfCaffScript Compiler v1.0</span>
<span class="Comment">Released under the MIT License</span>
<span class="Comment"><span class="Comment">###</span></span>
</pre><pre class="idle"><span class="Comment"><span class="Comment">/*</span></span>
<span class="Comment">CoffeeScript Compiler v1.6.1</span>
<span class="Comment">SkinnyMochaHalfCaffScript Compiler v1.0</span>
<span class="Comment">Released under the MIT License</span>
<span class="Comment"><span class="Comment">*/</span></span>
</pre><script>window.example37 = "###\nCoffeeScript Compiler v1.6.1\nReleased under the MIT License\n###\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example37);'>load</div><br class='clear' /></div>
</pre><script>window.example39 = "###\nSkinnyMochaHalfCaffScript Compiler v1.0\nReleased under the MIT License\n###\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example39);'>load</div><br class='clear' /></div>
<p>
<span id="regexes" class="bookmark"></span>
<b class="header">Block Regular Expressions</b>
Similar to block strings and comments, CoffeeScript supports block regexes &mdash;
extended regular expressions that ignore internal whitespace and can contain
comments and interpolation. Modeled after Perl's <tt>/x</tt> modifier, CoffeeSctipt's
comments and interpolation. Modeled after Perl's <tt>/x</tt> modifier, CoffeeScript's
block regexes are delimited by <tt>///</tt> and go a long way towards making complex
regular expressions readable. To quote from the CoffeeScript source:
</p>
@@ -2074,7 +2123,7 @@ html = "<strong>\n cup of coffeescript\n</strong>";
</pre><pre class="idle"><span class="Storage">var</span> OPERATOR;
OPERATOR <span class="Keyword">=</span><span class="String"> <span class="String">/</span>^(?:[-=]&gt;|[-+*<span class="UserDefinedConstant">\/</span>%&lt;&gt;&amp;|^!?=]=|&gt;&gt;&gt;=?|([-+:])<span class="UserDefinedConstant">\1</span>|([&amp;|&lt;&gt;])<span class="UserDefinedConstant">\2</span>=?|<span class="UserDefinedConstant">\?</span><span class="UserDefinedConstant">\.</span>|<span class="UserDefinedConstant">\.</span>{2,3})<span class="String">/</span></span>;
</pre><script>window.example38 = "OPERATOR = /// ^ (\n ?: [-=]> # function\n | [-+*/%<>&|^!?=]= # compound assign / compare\n | >>>=? # zero-fill right shift\n | ([-+:])\\1 # doubles\n | ([&|<>])\\2=? # logic / shift\n | \\?\\. # soak access\n | \\.{2,3} # range or splat\n) ///\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example38);'>load</div><br class='clear' /></div>
</pre><script>window.example40 = "OPERATOR = /// ^ (\n ?: [-=]> # function\n | [-+*/%<>&|^!?=]= # compound assign / compare\n | >>>=? # zero-fill right shift\n | ([-+:])\\1 # doubles\n | ([&|<>])\\2=? # logic / shift\n | \\?\\. # soak access\n | \\.{2,3} # range or splat\n) ///\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example40);'>load</div><br class='clear' /></div>
<h2>
@@ -2122,7 +2171,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
dir <span class="Keyword">=</span> options.output <span class="Keyword">||</span> <span class="String"><span class="String">'</span>lib<span class="String">'</span></span>;
<span class="Keyword">return</span> fs.writeFile(<span class="String"><span class="String">&quot;</span><span class="String">&quot;</span></span> <span class="Keyword">+</span> dir <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span>/parser.js<span class="String">&quot;</span></span>, code);
});
</pre><script>window.example39 = "fs = require 'fs'\n\noption '-o', '--output [DIR]', 'directory for compiled code'\n\ntask 'build:parser', 'rebuild the Jison parser', (options) ->\n require 'jison'\n code = require('./lib/grammar').parser.generate()\n dir = options.output or 'lib'\n fs.writeFile \"#{dir}/parser.js\", code"</script><div class='minibutton load' onclick='javascript: loadConsole(example39);'>load</div><br class='clear' /></div>
</pre><script>window.example41 = "fs = require 'fs'\n\noption '-o', '--output [DIR]', 'directory for compiled code'\n\ntask 'build:parser', 'rebuild the Jison parser', (options) ->\n require 'jison'\n code = require('./lib/grammar').parser.generate()\n dir = options.output or 'lib'\n fs.writeFile \"#{dir}/parser.js\", code"</script><div class='minibutton load' onclick='javascript: loadConsole(example41);'>load</div><br class='clear' /></div>
<p>
If you need to invoke one task before another &mdash; for example, running
<tt>build</tt> before <tt>test</tt>, you can use the <tt>invoke</tt> function:
@@ -2335,6 +2384,13 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
<a href="http://github.com/jashkenas/coffee-script/wiki/FAQ">The FAQ</a><br />
Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
</li>
<li>
<a href="http://js2coffee.org">JS2Coffee</a><br />
Is a very well done reverse JavaScript-to-CoffeeScript compiler. It's
not going to be perfect (infer what your JavaScript classes are, when
you need bound functions, and so on...) &mdash; but it's a great starting
point for converting simple scripts.
</li>
<li>
<a href="https://github.com/jashkenas/coffee-script/downloads">High-Rez Logo</a><br />
The CoffeeScript logo is available in Illustrator, EPS and PSD formats, for use
@@ -2362,6 +2418,64 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
Change Log
</h2>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.6.2...1.6.3">1.6.3</a>
<span class="timestamp"> &ndash; <small>June 2, 2013</small></span>
</b>
<ul>
<li>
The CoffeeScript REPL now remembers your history between sessions.
Just like a proper REPL should.
</li>
<li>
You can now use <tt>require</tt> in Node to load <tt>.coffee.md</tt>
Literate CoffeeScript files. In the browser,
<tt>text/literate-coffeescript</tt> script tags.
</li>
<li>
The old <tt>coffee --lint</tt> command has been removed. It was useful
while originally working on the compiler, but has been surpassed by
JSHint. You may now use <tt>-l</tt> to pass literate files in over
<b>stdio</b>.
</li>
<li>
Bugfixes for Windows path separators, <tt>catch</tt> without naming
the error, and executable-class-bodies-with-
prototypal-property-attachment.
</li>
</ul>
</p>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.6.1...1.6.2">1.6.2</a>
<span class="timestamp"> &ndash; <small>March 18, 2013</small></span>
</b>
<ul>
<li>
Source maps have been used to provide automatic line-mapping when
running CoffeeScript directly via the <tt>coffee</tt> command, and
for automatic line-mapping when running CoffeeScript directly in the
browser. Also, to provide better error messages for semantic errors
thrown by the compiler &mdash;
<a href="http://cl.ly/NdOA">with colors, even</a>.
</li>
<li>
Improved support for mixed literate/vanilla-style CoffeeScript projects,
and generating source maps for both at the same time.
</li>
<li>
Fixes for <b>1.6.x</b> regressions with overriding inherited bound
functions, and for Windows file path management.
</li>
<li>
The <tt>coffee</tt> command can now correctly <tt>fork()</tt>
both <tt>.coffee</tt> and <tt>.js</tt> files. (Requires Node.js 0.9+)
</li>
</ul>
</p>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.5.0...1.6.1">1.6.1</a>
@@ -3109,8 +3223,10 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
else
$(el).text window.compiledJS
$('#error').hide()
catch error
$('#error').text(error.message).show()
catch {location, message}
if location?
message = "Error on line #{location.first_line + 1}: #{message}"
$('#error').text(message).show()
# Update permalink
$('#repl_permalink').attr 'href', "##{sourceFragment}#{encodeURIComponent source}"

View File

@@ -1,21 +1,22 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var CoffeeScript, runScripts,
var CoffeeScript, compile, runScripts,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
CoffeeScript = require('./coffee-script');
CoffeeScript.require = require;
compile = CoffeeScript.compile;
CoffeeScript["eval"] = function(code, options) {
var _ref;
if (options == null) {
options = {};
}
if ((_ref = options.bare) == null) {
if (options.bare == null) {
options.bare = true;
}
return eval(CoffeeScript.compile(code, options));
return eval(compile(code, options));
};
CoffeeScript.run = function(code, options) {
@@ -23,19 +24,34 @@
options = {};
}
options.bare = true;
return Function(CoffeeScript.compile(code, options))();
options.shiftLine = true;
return Function(compile(code, options))();
};
if (typeof window === "undefined" || window === null) {
return;
}
if ((typeof btoa !== "undefined" && btoa !== null) && (typeof JSON !== "undefined" && JSON !== null) && (typeof unescape !== "undefined" && unescape !== null) && (typeof encodeURIComponent !== "undefined" && encodeURIComponent !== null)) {
compile = function(code, options) {
var js, v3SourceMap, _ref;
if (options == null) {
options = {};
}
options.sourceMap = true;
options.inline = true;
_ref = CoffeeScript.compile(code, options), js = _ref.js, v3SourceMap = _ref.v3SourceMap;
return "" + js + "\n//@ sourceMappingURL=data:application/json;base64," + (btoa(unescape(encodeURIComponent(v3SourceMap)))) + "\n//@ sourceURL=coffeescript";
};
}
CoffeeScript.load = function(url, callback, options) {
var xhr;
if (options == null) {
options = {};
}
xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
options.sourceFiles = [url];
xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') : new window.XMLHttpRequest();
xhr.open('GET', url, true);
if ('overrideMimeType' in xhr) {
xhr.overrideMimeType('text/plain');
@@ -58,7 +74,7 @@
runScripts = function() {
var coffees, coffeetypes, execute, index, length, s, scripts;
scripts = document.getElementsByTagName('script');
scripts = window.document.getElementsByTagName('script');
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript'];
coffees = (function() {
var _i, _len, _ref, _results;
@@ -84,6 +100,7 @@
if (script.src) {
return CoffeeScript.load(script.src, execute, options);
} else {
options.sourceFiles = ['embedded'];
CoffeeScript.run(script.innerHTML, options);
return execute();
}
@@ -93,9 +110,9 @@
};
if (window.addEventListener) {
addEventListener('DOMContentLoaded', runScripts, false);
window.addEventListener('DOMContentLoaded', runScripts, false);
} else {
attachEvent('onload', runScripts);
window.attachEvent('onload', runScripts);
}
}).call(this);

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var CoffeeScript, cakefileDirectory, existsSync, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
@@ -46,7 +46,7 @@
});
exports.run = function() {
var arg, args, _i, _len, _ref, _results;
var arg, args, e, _i, _len, _ref, _results;
global.__originalDirname = fs.realpathSync('.');
process.chdir(cakefileDirectory(__originalDirname));
args = process.argv.slice(2);
@@ -59,7 +59,8 @@
}
try {
options = oparse.parse(args);
} catch (e) {
} catch (_error) {
e = _error;
return fatalError("" + e);
}
_ref = options["arguments"];

View File

@@ -1,85 +1,60 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var Lexer, compile, ext, fs, helpers, lexer, loadFile, parser, path, sourcemap, vm, _i, _len, _ref,
var Lexer, Module, SourceMap, child_process, compile, ext, findExtension, fork, formatSourcePosition, fs, helpers, lexer, loadFile, parser, patchStackTrace, patched, path, sourceMaps, vm, _i, _len, _ref,
__hasProp = {}.hasOwnProperty;
fs = require('fs');
vm = require('vm');
path = require('path');
child_process = require('child_process');
Lexer = require('./lexer').Lexer;
parser = require('./parser').parser;
helpers = require('./helpers');
vm = require('vm');
SourceMap = require('./sourcemap');
sourcemap = require('./sourcemap');
loadFile = function(module, filename) {
var raw, stripped;
raw = fs.readFileSync(filename, 'utf8');
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
return module._compile(compile(stripped, {
filename: filename,
literate: helpers.isLiterate(filename)
}), filename);
};
if (require.extensions) {
_ref = ['.coffee', '.litcoffee', '.md', '.coffee.md'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
ext = _ref[_i];
require.extensions[ext] = loadFile;
}
}
exports.VERSION = '1.6.1';
exports.VERSION = '1.6.3';
exports.helpers = helpers;
exports.compile = compile = function(code, options) {
var answer, coffeeFile, currentColumn, currentLine, fragment, fragments, header, js, jsFile, merge, newLines, sourceMap, _j, _len1;
var answer, currentColumn, currentLine, fragment, fragments, header, js, map, merge, newLines, _i, _len;
if (options == null) {
options = {};
}
merge = exports.helpers.merge;
try {
merge = helpers.merge;
if (options.sourceMap) {
map = new SourceMap;
}
fragments = parser.parse(lexer.tokenize(code, options)).compileToFragments(options);
currentLine = 0;
if (options.header) {
currentLine += 1;
}
if (options.shiftLine) {
currentLine += 1;
}
currentColumn = 0;
js = "";
for (_i = 0, _len = fragments.length; _i < _len; _i++) {
fragment = fragments[_i];
if (options.sourceMap) {
coffeeFile = helpers.baseFileName(options.filename);
jsFile = helpers.baseFileName(options.filename, true) + ".js";
sourceMap = new sourcemap.SourceMap();
}
fragments = (parser.parse(lexer.tokenize(code, options))).compileToFragments(options);
currentLine = 0;
if (options.header) {
currentLine += 1;
}
if (options.sourceMap) {
currentLine += 1;
}
currentColumn = 0;
js = "";
for (_j = 0, _len1 = fragments.length; _j < _len1; _j++) {
fragment = fragments[_j];
if (sourceMap) {
if (fragment.locationData) {
sourceMap.addMapping([fragment.locationData.first_line, fragment.locationData.first_column], [currentLine, currentColumn], {
noReplace: true
});
}
newLines = helpers.count(fragment.code, "\n");
currentLine += newLines;
currentColumn = fragment.code.length - (newLines ? fragment.code.lastIndexOf("\n") : 0);
if (fragment.locationData) {
map.add([fragment.locationData.first_line, fragment.locationData.first_column], [currentLine, currentColumn], {
noReplace: true
});
}
js += fragment.code;
newLines = helpers.count(fragment.code, "\n");
currentLine += newLines;
currentColumn = fragment.code.length - (newLines ? fragment.code.lastIndexOf("\n") : 0);
}
} catch (err) {
if (options.filename) {
err.message = "In " + options.filename + ", " + err.message;
}
throw err;
js += fragment.code;
}
if (options.header) {
header = "Generated by CoffeeScript " + this.VERSION;
@@ -89,10 +64,8 @@
answer = {
js: js
};
if (sourceMap) {
answer.sourceMap = sourceMap;
answer.v3SourceMap = sourcemap.generateV3SourceMap(sourceMap, coffeeFile, jsFile);
}
answer.sourceMap = map;
answer.v3SourceMap = map.generate(options, code);
return answer;
} else {
return js;
@@ -112,23 +85,29 @@
};
exports.run = function(code, options) {
var mainModule;
var answer, mainModule;
if (options == null) {
options = {};
}
mainModule = require.main;
if (options.sourceMap == null) {
options.sourceMap = true;
}
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.';
mainModule.moduleCache && (mainModule.moduleCache = {});
mainModule.paths = require('module')._nodeModulePaths(path.dirname(fs.realpathSync(options.filename)));
mainModule.paths = require('module')._nodeModulePaths(path.dirname(fs.realpathSync(options.filename || '.')));
if (!helpers.isCoffee(mainModule.filename) || require.extensions) {
return mainModule._compile(compile(code, options), mainModule.filename);
answer = compile(code, options);
patchStackTrace();
sourceMaps[mainModule.filename] = answer.sourceMap;
return mainModule._compile(answer.js, mainModule.filename);
} else {
return mainModule._compile(code, mainModule.filename);
}
};
exports["eval"] = function(code, options) {
var Module, Script, js, k, o, r, sandbox, v, _j, _len1, _module, _ref1, _ref2, _require;
var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref, _ref1, _require;
if (options == null) {
options = {};
}
@@ -142,10 +121,10 @@
sandbox = options.sandbox;
} else {
sandbox = Script.createContext();
_ref1 = options.sandbox;
for (k in _ref1) {
if (!__hasProp.call(_ref1, k)) continue;
v = _ref1[k];
_ref = options.sandbox;
for (k in _ref) {
if (!__hasProp.call(_ref, k)) continue;
v = _ref[k];
sandbox[k] = v;
}
}
@@ -162,9 +141,9 @@
return Module._load(path, _module, true);
};
_module.filename = sandbox.__filename;
_ref2 = Object.getOwnPropertyNames(require);
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
r = _ref2[_j];
_ref1 = Object.getOwnPropertyNames(require);
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
r = _ref1[_i];
if (r !== 'paths') {
_require[r] = require[r];
}
@@ -190,6 +169,70 @@
}
};
loadFile = function(module, filename) {
var answer, raw, stripped;
raw = fs.readFileSync(filename, 'utf8');
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
answer = compile(stripped, {
filename: filename,
sourceMap: true,
literate: helpers.isLiterate(filename)
});
sourceMaps[filename] = answer.sourceMap;
return module._compile(answer.js, filename);
};
if (require.extensions) {
_ref = ['.coffee', '.litcoffee', '.coffee.md'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
ext = _ref[_i];
require.extensions[ext] = loadFile;
}
Module = require('module');
findExtension = function(filename) {
var curExtension, extensions;
extensions = path.basename(filename).split('.');
if (extensions[0] === '') {
extensions.shift();
}
while (extensions.shift()) {
curExtension = '.' + extensions.join('.');
if (Module._extensions[curExtension]) {
return curExtension;
}
}
return '.js';
};
Module.prototype.load = function(filename) {
var extension;
this.filename = filename;
this.paths = Module._nodeModulePaths(path.dirname(filename));
extension = findExtension(filename);
Module._extensions[extension](this, filename);
return this.loaded = true;
};
}
if (child_process) {
fork = child_process.fork;
child_process.fork = function(path, args, options) {
var execPath;
if (args == null) {
args = [];
}
if (options == null) {
options = {};
}
execPath = helpers.isCoffee(path) ? 'coffee' : null;
if (!Array.isArray(args)) {
args = [];
options = args || {};
}
options.execPath || (options.execPath = execPath);
return fork(path, args, options);
};
}
lexer = new Lexer;
parser.lexer = {
@@ -215,4 +258,101 @@
parser.yy = require('./nodes');
parser.yy.parseError = function(message, _arg) {
var token;
token = _arg.token;
message = "unexpected " + (token === 1 ? 'end of input' : token);
return helpers.throwSyntaxError(message, parser.lexer.yylloc);
};
patched = false;
sourceMaps = {};
patchStackTrace = function() {
var mainModule;
if (patched) {
return;
}
patched = true;
mainModule = require.main;
return Error.prepareStackTrace = function(err, stack) {
var frame, frames, getSourceMapping, sourceFiles, _ref1;
sourceFiles = {};
getSourceMapping = function(filename, line, column) {
var answer, sourceMap;
sourceMap = sourceMaps[filename];
if (sourceMap) {
answer = sourceMap.sourceLocation([line - 1, column - 1]);
}
if (answer) {
return [answer[0] + 1, answer[1] + 1];
} else {
return null;
}
};
frames = (function() {
var _j, _len1, _results;
_results = [];
for (_j = 0, _len1 = stack.length; _j < _len1; _j++) {
frame = stack[_j];
if (frame.getFunction() === exports.run) {
break;
}
_results.push(" at " + (formatSourcePosition(frame, getSourceMapping)));
}
return _results;
})();
return "" + err.name + ": " + ((_ref1 = err.message) != null ? _ref1 : '') + "\n" + (frames.join('\n')) + "\n";
};
};
formatSourcePosition = function(frame, getSourceMapping) {
var as, column, fileLocation, fileName, functionName, isConstructor, isMethodCall, line, methodName, source, tp, typeName;
fileName = void 0;
fileLocation = '';
if (frame.isNative()) {
fileLocation = "native";
} else {
if (frame.isEval()) {
fileName = frame.getScriptNameOrSourceURL();
if (!fileName) {
fileLocation = "" + (frame.getEvalOrigin()) + ", ";
}
} else {
fileName = frame.getFileName();
}
fileName || (fileName = "<anonymous>");
line = frame.getLineNumber();
column = frame.getColumnNumber();
source = getSourceMapping(fileName, line, column);
fileLocation = source ? "" + fileName + ":" + source[0] + ":" + source[1] + ", <js>:" + line + ":" + column : "" + fileName + ":" + line + ":" + column;
}
functionName = frame.getFunctionName();
isConstructor = frame.isConstructor();
isMethodCall = !(frame.isToplevel() || isConstructor);
if (isMethodCall) {
methodName = frame.getMethodName();
typeName = frame.getTypeName();
if (functionName) {
tp = as = '';
if (typeName && functionName.indexOf(typeName)) {
tp = "" + typeName + ".";
}
if (methodName && functionName.indexOf("." + methodName) !== functionName.length - methodName.length - 1) {
as = " [as " + methodName + "]";
}
return "" + tp + functionName + as + " (" + fileLocation + ")";
} else {
return "" + typeName + "." + (methodName || '<anonymous>') + " (" + fileLocation + ")";
}
} else if (isConstructor) {
return "new " + (functionName || '<anonymous>') + " (" + fileLocation + ")";
} else if (functionName) {
return "" + functionName + " (" + fileLocation + ")";
} else {
return fileLocation;
}
};
}).call(this);

View File

@@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, exists, forkNode, fs, helpers, hidden, joinTimeout, lint, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, sourceCode, sources, spawn, timeLog, unwatchDir, usage, version, wait, watch, watchDir, watchers, writeJs, _ref;
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, exists, forkNode, fs, helpers, hidden, joinTimeout, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, sourceCode, sources, spawn, timeLog, unwatchDir, usage, useWinPathSep, version, wait, watch, watchDir, watchers, writeJs, _ref;
fs = require('fs');
@@ -18,6 +18,8 @@
exists = fs.exists || path.exists;
useWinPathSep = path.sep === '\\';
helpers.extend(CoffeeScript, new EventEmitter);
printLine = function(line) {
@@ -34,7 +36,7 @@
BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.';
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-m', '--map', 'generate source map and save as .map files'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-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']];
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .map files'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffee-script'], ['-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']];
opts = {};
@@ -148,9 +150,12 @@
};
compileScript = function(file, input, base) {
var compiled, o, options, t, task;
var compiled, err, message, o, options, t, task, useColors;
if (base == null) {
base = null;
}
o = opts;
options = compileOptions(file);
options = compileOptions(file, base);
try {
t = task = {
file: file,
@@ -165,6 +170,9 @@
} else if (o.run) {
return CoffeeScript.run(t.input, t.options);
} else if (o.join && t.file !== o.join) {
if (helpers.isLiterate(file)) {
t.input = helpers.invertLiterate(t.input);
}
sourceCode[sources.indexOf(t.file)] = t.input;
return compileJoin();
} else {
@@ -178,21 +186,23 @@
if (o.print) {
return printLine(t.output.trim());
} else if (o.compile || o.map) {
return writeJs(base, t.file, t.output, t.sourceMap);
} else if (o.lint) {
return lint(t.file, t.output);
return writeJs(base, t.file, t.output, options.jsPath, t.sourceMap);
}
}
} catch (err) {
} catch (_error) {
err = _error;
CoffeeScript.emit('failure', err, task);
if (CoffeeScript.listeners('failure').length) {
return;
}
useColors = process.stdout.isTTY && !process.env.NODE_DISABLE_COLORS;
message = helpers.prettyErrorMessage(err, file || '[stdin]', input, useColors);
if (o.watch) {
return printLine(err.message + '\x07');
return printLine(message + '\x07');
} else {
printWarn(message);
return process.exit(1);
}
printWarn(err instanceof Error && err.stack || ("ERROR: " + err));
return process.exit(1);
}
};
@@ -227,7 +237,7 @@
};
watch = function(source, base) {
var compile, compileTimeout, prevStats, rewatch, watchErr, watcher;
var compile, compileTimeout, e, prevStats, rewatch, watchErr, watcher;
prevStats = null;
compileTimeout = null;
watchErr = function(e) {
@@ -238,7 +248,8 @@
try {
rewatch();
return compile();
} catch (e) {
} catch (_error) {
e = _error;
removeSource(source, base, true);
return compileJoin();
}
@@ -269,7 +280,8 @@
};
try {
watcher = fs.watch(source, compile);
} catch (e) {
} catch (_error) {
e = _error;
watchErr(e);
}
return rewatch = function() {
@@ -281,7 +293,7 @@
};
watchDir = function(source, base) {
var readdirTimeout, watcher;
var e, readdirTimeout, watcher;
readdirTimeout = null;
try {
return watcher = fs.watch(source, function() {
@@ -316,7 +328,8 @@
});
});
});
} catch (e) {
} catch (_error) {
e = _error;
if (e.code !== 'ENOENT') {
throw e;
}
@@ -374,19 +387,18 @@
if (extension == null) {
extension = ".js";
}
basename = helpers.baseFileName(source, true);
basename = helpers.baseFileName(source, true, useWinPathSep);
srcDir = path.dirname(source);
baseDir = base === '.' ? srcDir : srcDir.substring(base.length);
dir = opts.output ? path.join(opts.output, baseDir) : srcDir;
return path.join(dir, basename + extension);
};
writeJs = function(base, sourcePath, js, generatedSourceMap) {
var compile, jsDir, jsPath, sourceMapPath;
writeJs = function(base, sourcePath, js, jsPath, generatedSourceMap) {
var compile, jsDir, sourceMapPath;
if (generatedSourceMap == null) {
generatedSourceMap = null;
}
jsPath = outputPath(sourcePath, base);
sourceMapPath = outputPath(sourcePath, base, ".map");
jsDir = path.dirname(jsPath);
compile = function() {
@@ -395,7 +407,7 @@
js = ' ';
}
if (generatedSourceMap) {
js = "//@ sourceMappingURL=" + (helpers.baseFileName(sourceMapPath)) + "\n" + js;
js = "" + js + "\n/*\n//@ sourceMappingURL=" + (helpers.baseFileName(sourceMapPath, false, useWinPathSep)) + "\n*/\n";
}
fs.writeFile(jsPath, js, function(err) {
if (err) {
@@ -430,19 +442,6 @@
return console.log("" + ((new Date).toLocaleTimeString()) + " - " + message);
};
lint = function(file, js) {
var conf, jsl, printIt;
printIt = function(buffer) {
return printLine(file + ':\t' + buffer.toString().trim());
};
conf = __dirname + '/../../extras/jsl.conf';
jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]);
jsl.stdout.on('data', printIt);
jsl.stderr.on('data', printIt);
jsl.stdin.write(js);
return jsl.stdin.end();
};
printTokens = function(tokens) {
var strings, tag, token, value;
strings = (function() {
@@ -464,7 +463,7 @@
optionParser = new optparse.OptionParser(SWITCHES, BANNER);
o = opts = optionParser.parse(process.argv.slice(2));
o.compile || (o.compile = !!o.output);
o.run = !(o.compile || o.print || o.lint || o.map);
o.run = !(o.compile || o.print || o.map);
o.print = !!(o.print || (o["eval"] || o.stdio && o.compile));
sources = o["arguments"];
for (i = _i = 0, _len = sources.length; _i < _len; i = ++_i) {
@@ -473,14 +472,35 @@
}
};
compileOptions = function(filename) {
return {
compileOptions = function(filename, base) {
var answer, cwd, jsDir, jsPath;
answer = {
filename: filename,
literate: helpers.isLiterate(filename),
literate: opts.literate || helpers.isLiterate(filename),
bare: opts.bare,
header: opts.compile,
sourceMap: opts.map
};
if (filename) {
if (base) {
cwd = process.cwd();
jsPath = outputPath(filename, base);
jsDir = path.dirname(jsPath);
answer = helpers.merge(answer, {
jsPath: jsPath,
sourceRoot: path.relative(jsDir, cwd),
sourceFiles: [path.relative(cwd, filename)],
generatedFile: helpers.baseFileName(jsPath, false, useWinPathSep)
});
} else {
answer = helpers.merge(answer, {
sourceRoot: "",
sourceFiles: [helpers.baseFileName(filename, false, useWinPathSep)],
generatedFile: helpers.baseFileName(filename, true, useWinPathSep) + ".js"
});
}
}
return answer;
};
forkNode = function() {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
@@ -350,6 +350,8 @@
return [$2, $3];
}), o('CATCH Object Block', function() {
return [LOC(2)(new Value($2)), $3];
}), o('CATCH Block', function() {
return [null, $2];
})
],
Throw: [

View File

@@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var buildLocationData, extend, flatten, _ref;
var buildLocationData, extend, flatten, last, repeat, _ref;
exports.starts = function(string, literal, start) {
return literal === string.substr(start, literal.length);
@@ -12,6 +12,19 @@
return literal === string.substr(string.length - len - (back || 0), len);
};
exports.repeat = repeat = function(str, n) {
var res;
res = '';
while (n > 0) {
if (n & 1) {
res += str;
}
n >>>= 1;
str += str;
}
return res;
};
exports.compact = function(array) {
var item, _i, _len, _results;
_results = [];
@@ -70,7 +83,7 @@
return val;
};
exports.last = function(array, back) {
exports.last = last = function(array, back) {
return array[array.length - (back || 0) - 1];
};
@@ -85,6 +98,28 @@
return false;
};
exports.invertLiterate = function(code) {
var line, lines, maybe_code;
maybe_code = true;
lines = (function() {
var _i, _len, _ref1, _results;
_ref1 = code.split('\n');
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
line = _ref1[_i];
if (maybe_code && /^([ ]{4}|[ ]{0,3}\t)/.test(line)) {
_results.push(line);
} else if (maybe_code = /^\s*$/.test(line)) {
_results.push(line);
} else {
_results.push('# ' + line);
}
}
return _results;
})();
return lines.join('\n');
};
buildLocationData = function(first, last) {
if (!last) {
return first;
@@ -121,19 +156,23 @@
}
};
exports.baseFileName = function(file, stripExt) {
var parts;
exports.baseFileName = function(file, stripExt, useWinPathSep) {
var parts, pathSep;
if (stripExt == null) {
stripExt = false;
}
parts = file.split('/');
if (useWinPathSep == null) {
useWinPathSep = false;
}
pathSep = useWinPathSep ? /\\|\// : /\//;
parts = file.split(pathSep);
file = parts[parts.length - 1];
if (!stripExt) {
return file;
}
parts = file.split('.');
parts.pop();
if (parts[parts.length - 1] === 'coffee') {
if (parts[parts.length - 1] === 'coffee' && parts.length > 1) {
parts.pop();
}
return parts.join('.');
@@ -147,4 +186,38 @@
return /\.(litcoffee|coffee\.md)$/.test(file);
};
exports.throwSyntaxError = function(message, location) {
var error;
if (location.last_line == null) {
location.last_line = location.first_line;
}
if (location.last_column == null) {
location.last_column = location.first_column;
}
error = new SyntaxError(message);
error.location = location;
throw error;
};
exports.prettyErrorMessage = function(error, fileName, code, useColors) {
var codeLine, colorize, end, first_column, first_line, last_column, last_line, marker, message, start, _ref1;
if (!error.location) {
return error.stack || ("" + error);
}
_ref1 = error.location, first_line = _ref1.first_line, first_column = _ref1.first_column, last_line = _ref1.last_line, last_column = _ref1.last_column;
codeLine = code.split('\n')[first_line];
start = first_column;
end = first_line === last_line ? last_column + 1 : codeLine.length;
marker = repeat(' ', start) + repeat('^', end - start);
if (useColors) {
colorize = function(str) {
return "\x1B[1;31m" + str + "\x1B[0m";
};
codeLine = codeLine.slice(0, start) + colorize(codeLine.slice(start, end)) + codeLine.slice(end);
marker = colorize(marker);
}
message = "" + fileName + ":" + (first_line + 1) + ":" + (first_column + 1) + ": error: " + error.message + "\n" + codeLine + "\n" + marker;
return message;
};
}).call(this);

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var key, val, _ref;

View File

@@ -1,14 +1,13 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LITERATE, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, locationDataToString, starts, _ref, _ref1,
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, invertLiterate, key, last, locationDataToString, repeat, starts, throwSyntaxError, _ref, _ref1,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
_ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES;
_ref1 = require('./helpers'), count = _ref1.count, starts = _ref1.starts, compact = _ref1.compact, last = _ref1.last, locationDataToString = _ref1.locationDataToString;
_ref1 = require('./helpers'), count = _ref1.count, starts = _ref1.starts, compact = _ref1.compact, last = _ref1.last, repeat = _ref1.repeat, invertLiterate = _ref1.invertLiterate, locationDataToString = _ref1.locationDataToString, throwSyntaxError = _ref1.throwSyntaxError;
exports.Lexer = Lexer = (function() {
function Lexer() {}
Lexer.prototype.tokenize = function(code, opts) {
@@ -43,7 +42,6 @@
};
Lexer.prototype.clean = function(code) {
var line, lines, match;
if (code.charCodeAt(0) === BOM) {
code = code.slice(1);
}
@@ -53,21 +51,7 @@
this.chunkLine--;
}
if (this.literate) {
lines = (function() {
var _i, _len, _ref2, _results;
_ref2 = code.split('\n');
_results = [];
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
line = _ref2[_i];
if (match = LITERATE.exec(line)) {
_results.push(line.slice(match[0].length));
} else {
_results.push('# ' + line);
}
}
return _results;
})();
code = lines.join('\n');
code = invertLiterate(code);
}
return code;
};
@@ -171,10 +155,10 @@
}
lexedLength = number.length;
if (octalLiteral = /^0o([0-7]+)/.exec(number)) {
number = '0x' + (parseInt(octalLiteral[1], 8)).toString(16);
number = '0x' + parseInt(octalLiteral[1], 8).toString(16);
}
if (binaryLiteral = /^0b([01]+)/.exec(number)) {
number = '0x' + (parseInt(binaryLiteral[1], 2)).toString(16);
number = '0x' + parseInt(binaryLiteral[1], 2).toString(16);
}
this.token('NUMBER', number, 0, lexedLength);
return lexedLength;
@@ -244,7 +228,7 @@
if (here) {
this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
herecomment: true,
indent: Array(this.indent + 1).join(' ')
indent: repeat(' ', this.indent)
}), 0, comment.length);
}
return comment.length;
@@ -363,7 +347,7 @@
return indent.length;
}
diff = size - this.indent + this.outdebt;
this.token('INDENT', diff, 0, indent.length);
this.token('INDENT', diff, indent.length - size, size);
this.indents.push(diff);
this.ends.push('OUTDENT');
this.outdebt = this.indebt = 0;
@@ -527,9 +511,6 @@
if (indent) {
doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
}
if (this.literate) {
doc = doc.replace(/\n# \n/g, '\n\n');
}
if (!herecomment) {
doc = doc.replace(/^\n/, '');
}
@@ -605,7 +586,7 @@
};
Lexer.prototype.interpolateString = function(str, options) {
var column, expr, heredoc, i, inner, interpolated, len, letter, lexedLength, line, locationToken, nested, offsetInChunk, pi, plusToken, popped, regex, strOffset, tag, token, tokens, value, _i, _len, _ref2, _ref3, _ref4;
var column, expr, heredoc, i, inner, interpolated, len, letter, lexedLength, line, locationToken, nested, offsetInChunk, pi, plusToken, popped, regex, rparen, strOffset, tag, token, tokens, value, _i, _len, _ref2, _ref3, _ref4;
if (options == null) {
options = {};
}
@@ -695,7 +676,9 @@
}
}
if (interpolated) {
this.token(')', ')', offsetInChunk + lexedLength, 0);
rparen = this.makeToken(')', ')', offsetInChunk + lexedLength, 0);
rparen.stringEnd = true;
this.tokens.push(rparen);
}
return tokens;
};
@@ -727,7 +710,7 @@
column = this.chunkColumn;
if (lineCount > 0) {
lines = string.split('\n');
column = (last(lines)).length;
column = last(lines).length;
} else {
column += string.length;
}
@@ -745,7 +728,7 @@
locationData = {};
_ref2 = this.getLineAndColumnFromChunk(offsetInChunk), locationData.first_line = _ref2[0], locationData.first_column = _ref2[1];
lastCharacter = Math.max(0, length - 1);
_ref3 = this.getLineAndColumnFromChunk(offsetInChunk + (length - 1)), locationData.last_line = _ref3[0], locationData.last_column = _ref3[1];
_ref3 = this.getLineAndColumnFromChunk(offsetInChunk + lastCharacter), locationData.last_line = _ref3[0], locationData.last_column = _ref3[1];
token = [tag, value, locationData];
return token;
};
@@ -792,7 +775,10 @@
};
Lexer.prototype.error = function(message) {
throw SyntaxError("" + message + " on line " + (this.chunkLine + 1));
return throwSyntaxError(message, {
first_line: this.chunkLine,
first_column: this.chunkColumn
});
};
return Lexer;
@@ -850,8 +836,6 @@
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)$)|^(?:\s*#(?!##[^#]).*)+/;
LITERATE = /^([ ]{4}|\t)/;
CODE = /^[-=]>/;
MULTI_DENT = /^(?:\n[^\n\S]*)+/;
@@ -892,9 +876,9 @@
BOOL = ['TRUE', 'FALSE'];
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--', ']'];
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--'];
NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');
NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING', ']');
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,10 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat;
repeat = require('./helpers').repeat;
exports.OptionParser = OptionParser = (function() {
function OptionParser(rules, banner) {
this.banner = banner;
this.rules = buildRules(rules);
@@ -67,7 +68,7 @@
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
rule = _ref[_i];
spaces = 15 - rule.longFlag.length;
spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
spaces = spaces > 0 ? repeat(' ', spaces) : '';
letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' ';
lines.push(' ' + letPart + rule.longFlag + spaces + rule.description);
}

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,10 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var CoffeeScript, addMultilineHandler, merge, nodeREPL, replDefaults, vm;
var CoffeeScript, addHistory, addMultilineHandler, fs, merge, nodeREPL, path, prettyErrorMessage, replDefaults, vm, _ref;
fs = require('fs');
path = require('path');
vm = require('vm');
@@ -8,25 +12,28 @@
CoffeeScript = require('./coffee-script');
merge = require('./helpers').merge;
_ref = require('./helpers'), merge = _ref.merge, prettyErrorMessage = _ref.prettyErrorMessage;
replDefaults = {
prompt: 'coffee> ',
historyFile: process.env.HOME ? path.join(process.env.HOME, '.coffee_history') : void 0,
historyMaxInputSize: 10240,
"eval": function(input, context, filename, cb) {
var js;
var Assign, Block, Literal, Value, ast, err, js, _ref1;
input = input.replace(/\uFF00/g, '\n');
input = input.replace(/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, '$1$2$3');
if (/^(\s*|\(\s*\))$/.test(input)) {
return cb(null);
}
input = input.replace(/^\(([\s\S]*)\n\)$/m, '$1');
_ref1 = require('./nodes'), Block = _ref1.Block, Assign = _ref1.Assign, Value = _ref1.Value, Literal = _ref1.Literal;
try {
js = CoffeeScript.compile("_=(" + input + "\n)", {
filename: filename,
bare: true
ast = CoffeeScript.nodes(input);
ast = new Block([new Assign(new Value(new Literal('_')), ast, '=')]);
js = ast.compile({
bare: true,
locals: Object.keys(context)
});
return cb(null, vm.runInContext(js, context, filename));
} catch (err) {
return cb(err);
} catch (_error) {
err = _error;
return cb(prettyErrorMessage(err, filename, input, true));
}
}
};
@@ -85,18 +92,66 @@
});
};
addHistory = function(repl, filename, maxSize) {
var buffer, fd, lastLine, readFd, size, stat;
lastLine = null;
try {
stat = fs.statSync(filename);
size = Math.min(maxSize, stat.size);
readFd = fs.openSync(filename, 'r');
buffer = new Buffer(size);
fs.readSync(readFd, buffer, 0, size, stat.size - size);
repl.rli.history = buffer.toString().split('\n').reverse();
if (stat.size > maxSize) {
repl.rli.history.pop();
}
if (repl.rli.history[0] === '') {
repl.rli.history.shift();
}
repl.rli.historyIndex = -1;
lastLine = repl.rli.history[0];
} catch (_error) {}
fd = fs.openSync(filename, 'a');
repl.rli.addListener('line', function(code) {
if (code && code.length && code !== '.history' && lastLine !== code) {
fs.write(fd, "" + code + "\n");
return lastLine = code;
}
});
repl.rli.on('exit', function() {
return fs.close(fd);
});
return repl.commands['.history'] = {
help: 'Show command history',
action: function() {
repl.outputStream.write("" + (repl.rli.history.slice(0).reverse().join('\n')) + "\n");
return repl.displayPrompt();
}
};
};
module.exports = {
start: function(opts) {
var repl;
var build, major, minor, repl, _ref1;
if (opts == null) {
opts = {};
}
_ref1 = process.versions.node.split('.').map(function(n) {
return parseInt(n);
}), major = _ref1[0], minor = _ref1[1], build = _ref1[2];
if (major === 0 && minor < 8) {
console.warn("Node 0.8.0+ required for CoffeeScript REPL");
process.exit(1);
}
opts = merge(replDefaults, opts);
repl = nodeREPL.start(opts);
repl.on('exit', function() {
return repl.outputStream.write('\n');
});
addMultilineHandler(repl);
if (opts.historyFile) {
addHistory(repl, opts.historyFile, opts.historyMaxInputSize);
}
return repl;
}
};

View File

@@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, left, rite, _i, _len, _ref,
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, left, rite, _i, _len, _ref,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
__slice = [].slice;
@@ -12,7 +12,6 @@
};
exports.Rewriter = (function() {
function Rewriter() {}
Rewriter.prototype.rewrite = function(tokens) {
@@ -267,14 +266,14 @@
}
stack.pop();
}
if ((__indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (__indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || __indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !((_ref = tokens[i + 1]) != null ? _ref.spaced : void 0) && !((_ref1 = tokens[i + 1]) != null ? _ref1.newLine : void 0))) {
if ((__indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced && !token.stringEnd || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (__indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || __indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !((_ref = tokens[i + 1]) != null ? _ref.spaced : void 0) && !((_ref1 = tokens[i + 1]) != null ? _ref1.newLine : void 0))) {
if (tag === '?') {
tag = token[0] = 'FUNC_EXIST';
}
startImplicitCall(i + 1);
return forward(2);
}
if (this.matchTags(i, IMPLICIT_FUNC, 'INDENT', null, ':') && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
if (__indexOf.call(IMPLICIT_FUNC, tag) >= 0 && this.matchTags(i + 1, 'INDENT', null, ':') && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
startImplicitCall(i + 1);
stack.push(['INDENT', i + 2]);
return forward(3);
@@ -331,22 +330,25 @@
Rewriter.prototype.addLocationDataToGeneratedTokens = function() {
return this.scanTokens(function(token, i, tokens) {
var last_column, last_line, _ref, _ref1, _ref2;
var column, line, nextLocation, prevLocation, _ref, _ref1;
if (token[2]) {
return 1;
}
if (!(token.generated || token.explicit)) {
return 1;
}
_ref2 = (_ref = (_ref1 = tokens[i - 1]) != null ? _ref1[2] : void 0) != null ? _ref : {
last_line: 0,
last_column: 0
}, last_line = _ref2.last_line, last_column = _ref2.last_column;
if (token[0] === '{' && (nextLocation = (_ref = tokens[i + 1]) != null ? _ref[2] : void 0)) {
line = nextLocation.first_line, column = nextLocation.first_column;
} else if (prevLocation = (_ref1 = tokens[i - 1]) != null ? _ref1[2] : void 0) {
line = prevLocation.last_line, column = prevLocation.last_column;
} else {
line = column = 0;
}
token[2] = {
first_line: last_line,
first_column: last_column,
last_line: last_line,
last_column: last_column
first_line: line,
first_column: column,
last_line: line,
last_column: column
};
return 1;
});
@@ -356,30 +358,35 @@
var action, condition, indent, outdent, starter;
starter = indent = outdent = null;
condition = function(token, i) {
var _ref;
return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
var _ref, _ref1;
return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && starter !== 'THEN') && !(((_ref1 = token[0]) === 'CATCH' || _ref1 === 'FINALLY') && (starter === '->' || starter === '=>'));
};
action = function(token, i) {
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
};
return this.scanTokens(function(token, i, tokens) {
var tag, _ref, _ref1;
var j, tag, _i, _ref, _ref1;
tag = token[0];
if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {
tokens.splice(i, 1);
return 0;
}
if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation(token))));
tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation())));
return 2;
}
if (tag === 'CATCH' && ((_ref = this.tag(i + 2)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) {
tokens.splice.apply(tokens, [i + 2, 0].concat(__slice.call(this.indentation(token))));
return 4;
if (tag === 'CATCH') {
for (j = _i = 1; _i <= 2; j = ++_i) {
if (!((_ref = this.tag(i + j)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) {
continue;
}
tokens.splice.apply(tokens, [i + j, 0].concat(__slice.call(this.indentation())));
return 2 + j;
}
}
if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
starter = tag;
_ref1 = this.indentation(token, true), indent = _ref1[0], outdent = _ref1[1];
_ref1 = this.indentation(true), indent = _ref1[0], outdent = _ref1[1];
if (starter === 'THEN') {
indent.fromThen = true;
}
@@ -398,8 +405,10 @@
var action, condition, original;
original = null;
condition = function(token, i) {
var _ref;
return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT';
var prevTag, tag;
tag = token[0];
prevTag = this.tokens[i - 1][0];
return tag === 'TERMINATOR' || (tag === 'INDENT' && __indexOf.call(SINGLE_LINERS, prevTag) < 0);
};
action = function(token, i) {
if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
@@ -416,7 +425,7 @@
});
};
Rewriter.prototype.indentation = function(token, implicit) {
Rewriter.prototype.indentation = function(implicit) {
var indent, outdent;
if (implicit == null) {
implicit = false;
@@ -461,12 +470,10 @@
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
IMPLICIT_UNSPACED_CALL = ['+', '-'];
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];

View File

@@ -1,11 +1,10 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var Scope, extend, last, _ref;
_ref = require('./helpers'), extend = _ref.extend, last = _ref.last;
exports.Scope = Scope = (function() {
Scope.root = null;
function Scope(parent, expressions, method) {

View File

@@ -1,237 +1,161 @@
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.3
(function() {
var BASE64_CHARS, LineMapping, MAX_BASE64_VALUE, VLQ_CONTINUATION_BIT, VLQ_SHIFT, VLQ_VALUE_MASK, decodeBase64Char, encodeBase64Char;
var LineMap, SourceMap;
LineMapping = (function() {
function LineMapping(generatedLine) {
this.generatedLine = generatedLine;
this.columnMap = {};
this.columnMappings = [];
LineMap = (function() {
function LineMap(line) {
this.line = line;
this.columns = [];
}
LineMapping.prototype.addMapping = function(generatedColumn, _arg, options) {
LineMap.prototype.add = function(column, _arg, options) {
var sourceColumn, sourceLine;
sourceLine = _arg[0], sourceColumn = _arg[1];
if (options == null) {
options = {};
}
if (this.columnMap[generatedColumn] && options.noReplace) {
if (this.columns[column] && options.noReplace) {
return;
}
this.columnMap[generatedColumn] = {
generatedLine: this.generatedLine,
generatedColumn: generatedColumn,
return this.columns[column] = {
line: this.line,
column: column,
sourceLine: sourceLine,
sourceColumn: sourceColumn
};
this.columnMappings.push(this.columnMap[generatedColumn]);
return this.columnMappings.sort(function(a, b) {
return a.generatedColumn - b.generatedColumn;
});
};
LineMapping.prototype.getSourcePosition = function(generatedColumn) {
var answer, columnMapping, lastColumnMapping, _i, _len, _ref;
answer = null;
lastColumnMapping = null;
_ref = this.columnMappings;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
columnMapping = _ref[_i];
if (columnMapping.generatedColumn > generatedColumn) {
break;
} else {
lastColumnMapping = columnMapping;
}
}
if (lastColumnMapping) {
return answer = [lastColumnMapping.sourceLine, lastColumnMapping.sourceColumn];
LineMap.prototype.sourceLocation = function(column) {
var mapping;
while (!((mapping = this.columns[column]) || (column <= 0))) {
column--;
}
return mapping && [mapping.sourceLine, mapping.sourceColumn];
};
return LineMapping;
return LineMap;
})();
exports.SourceMap = (function() {
SourceMap = (function() {
var BASE64_CHARS, VLQ_CONTINUATION_BIT, VLQ_SHIFT, VLQ_VALUE_MASK;
function SourceMap() {
this.generatedLines = [];
this.lines = [];
}
SourceMap.prototype.addMapping = function(sourceLocation, generatedLocation, options) {
var generatedColumn, generatedLine, lineMapping;
SourceMap.prototype.add = function(sourceLocation, generatedLocation, options) {
var column, line, lineMap, _base;
if (options == null) {
options = {};
}
generatedLine = generatedLocation[0], generatedColumn = generatedLocation[1];
lineMapping = this.generatedLines[generatedLine];
if (!lineMapping) {
lineMapping = this.generatedLines[generatedLine] = new LineMapping(generatedLine);
}
return lineMapping.addMapping(generatedColumn, sourceLocation, options);
line = generatedLocation[0], column = generatedLocation[1];
lineMap = ((_base = this.lines)[line] || (_base[line] = new LineMap(line)));
return lineMap.add(column, sourceLocation, options);
};
SourceMap.prototype.getSourcePosition = function(_arg) {
var answer, generatedColumn, generatedLine, lineMapping;
generatedLine = _arg[0], generatedColumn = _arg[1];
answer = null;
lineMapping = this.generatedLines[generatedLine];
if (!lineMapping) {
SourceMap.prototype.sourceLocation = function(_arg) {
var column, line, lineMap;
line = _arg[0], column = _arg[1];
while (!((lineMap = this.lines[line]) || (line <= 0))) {
line--;
}
return lineMap && lineMap.sourceLocation(column);
};
} else {
answer = lineMapping.getSourcePosition(generatedColumn);
SourceMap.prototype.generate = function(options, code) {
var buffer, lastColumn, lastSourceColumn, lastSourceLine, lineMap, lineNumber, mapping, needComma, v3, writingline, _i, _j, _len, _len1, _ref, _ref1;
if (options == null) {
options = {};
}
if (code == null) {
code = null;
}
writingline = 0;
lastColumn = 0;
lastSourceLine = 0;
lastSourceColumn = 0;
needComma = false;
buffer = "";
_ref = this.lines;
for (lineNumber = _i = 0, _len = _ref.length; _i < _len; lineNumber = ++_i) {
lineMap = _ref[lineNumber];
if (lineMap) {
_ref1 = lineMap.columns;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
mapping = _ref1[_j];
if (!(mapping)) {
continue;
}
while (writingline < mapping.line) {
lastColumn = 0;
needComma = false;
buffer += ";";
writingline++;
}
if (needComma) {
buffer += ",";
needComma = false;
}
buffer += this.encodeVlq(mapping.column - lastColumn);
lastColumn = mapping.column;
buffer += this.encodeVlq(0);
buffer += this.encodeVlq(mapping.sourceLine - lastSourceLine);
lastSourceLine = mapping.sourceLine;
buffer += this.encodeVlq(mapping.sourceColumn - lastSourceColumn);
lastSourceColumn = mapping.sourceColumn;
needComma = true;
}
}
}
v3 = {
version: 3,
file: options.generatedFile || '',
sourceRoot: options.sourceRoot || '',
sources: options.sourceFiles || [''],
names: [],
mappings: buffer
};
if (options.inline) {
v3.sourcesContent = [code];
}
return JSON.stringify(v3, null, 2);
};
VLQ_SHIFT = 5;
VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT;
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1;
SourceMap.prototype.encodeVlq = function(value) {
var answer, nextChunk, signBit, valueToEncode;
answer = '';
signBit = value < 0 ? 1 : 0;
valueToEncode = (Math.abs(value) << 1) + signBit;
while (valueToEncode || !answer) {
nextChunk = valueToEncode & VLQ_VALUE_MASK;
valueToEncode = valueToEncode >> VLQ_SHIFT;
if (valueToEncode) {
nextChunk |= VLQ_CONTINUATION_BIT;
}
answer += this.encodeBase64(nextChunk);
}
return answer;
};
SourceMap.prototype.forEachMapping = function(fn) {
var columnMapping, generatedLineNumber, lineMapping, _i, _len, _ref, _results;
_ref = this.generatedLines;
_results = [];
for (generatedLineNumber = _i = 0, _len = _ref.length; _i < _len; generatedLineNumber = ++_i) {
lineMapping = _ref[generatedLineNumber];
if (lineMapping) {
_results.push((function() {
var _j, _len1, _ref1, _results1;
_ref1 = lineMapping.columnMappings;
_results1 = [];
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
columnMapping = _ref1[_j];
_results1.push(fn(columnMapping));
}
return _results1;
})());
} else {
_results.push(void 0);
}
}
return _results;
BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
SourceMap.prototype.encodeBase64 = function(value) {
return BASE64_CHARS[value] || (function() {
throw new Error("Cannot Base64 encode value: " + value);
})();
};
return SourceMap;
})();
exports.generateV3SourceMap = function(sourceMap, sourceFile, generatedFile) {
var answer, lastGeneratedColumnWritten, lastSourceColumnWritten, lastSourceLineWritten, mappings, needComma, writingGeneratedLine;
if (sourceFile == null) {
sourceFile = null;
}
if (generatedFile == null) {
generatedFile = null;
}
writingGeneratedLine = 0;
lastGeneratedColumnWritten = 0;
lastSourceLineWritten = 0;
lastSourceColumnWritten = 0;
needComma = false;
mappings = "";
sourceMap.forEachMapping(function(mapping) {
while (writingGeneratedLine < mapping.generatedLine) {
lastGeneratedColumnWritten = 0;
needComma = false;
mappings += ";";
writingGeneratedLine++;
}
if (needComma) {
mappings += ",";
needComma = false;
}
mappings += exports.vlqEncodeValue(mapping.generatedColumn - lastGeneratedColumnWritten);
lastGeneratedColumnWritten = mapping.generatedColumn;
mappings += exports.vlqEncodeValue(0);
mappings += exports.vlqEncodeValue(mapping.sourceLine - lastSourceLineWritten);
lastSourceLineWritten = mapping.sourceLine;
mappings += exports.vlqEncodeValue(mapping.sourceColumn - lastSourceColumnWritten);
lastSourceColumnWritten = mapping.sourceColumn;
return needComma = true;
});
answer = {
version: 3,
file: generatedFile,
sourceRoot: "",
sources: sourceFile ? [sourceFile] : [],
names: [],
mappings: mappings
};
return JSON.stringify(answer, null, 2);
};
exports.loadV3SourceMap = function(sourceMap) {
return todo();
};
BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
MAX_BASE64_VALUE = BASE64_CHARS.length - 1;
encodeBase64Char = function(value) {
if (value > MAX_BASE64_VALUE) {
throw new Error("Cannot encode value " + value + " > " + MAX_BASE64_VALUE);
} else if (value < 0) {
throw new Error("Cannot encode value " + value + " < 0");
}
return BASE64_CHARS[value];
};
decodeBase64Char = function(char) {
var value;
value = BASE64_CHARS.indexOf(char);
if (value === -1) {
throw new Error("Invalid Base 64 character: " + char);
}
return value;
};
VLQ_SHIFT = 5;
VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT;
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1;
exports.vlqEncodeValue = function(value) {
var answer, nextVlqChunk, signBit, valueToEncode;
signBit = value < 0 ? 1 : 0;
valueToEncode = (Math.abs(value) << 1) + signBit;
answer = "";
while (valueToEncode || !answer) {
nextVlqChunk = valueToEncode & VLQ_VALUE_MASK;
valueToEncode = valueToEncode >> VLQ_SHIFT;
if (valueToEncode) {
nextVlqChunk |= VLQ_CONTINUATION_BIT;
}
answer += encodeBase64Char(nextVlqChunk);
}
return answer;
};
exports.vlqDecodeValue = function(str, offset) {
var consumed, continuationShift, done, nextChunkValue, nextVlqChunk, position, signBit, value;
if (offset == null) {
offset = 0;
}
position = offset;
done = false;
value = 0;
continuationShift = 0;
while (!done) {
nextVlqChunk = decodeBase64Char(str[position]);
position += 1;
nextChunkValue = nextVlqChunk & VLQ_VALUE_MASK;
value += nextChunkValue << continuationShift;
if (!(nextVlqChunk & VLQ_CONTINUATION_BIT)) {
done = true;
}
continuationShift += VLQ_SHIFT;
}
consumed = position - offset;
signBit = value & 1;
value = value >> 1;
if (signBit) {
value = -value;
}
return [value, consumed];
};
module.exports = SourceMap;
}).call(this);

View File

@@ -3,13 +3,13 @@
"description": "Unfancy JavaScript",
"keywords": ["javascript", "language", "coffeescript", "compiler"],
"author": "Jeremy Ashkenas",
"version": "1.6.1",
"version": "1.6.3",
"licenses": [{
"type": "MIT",
"url": "https://raw.github.com/jashkenas/coffee-script/master/LICENSE"
}],
"engines": {
"node": ">=0.4.0"
"node": ">=0.8.0"
},
"directories" : {
"lib" : "./lib/coffee-script"

View File

@@ -1,27 +1,43 @@
# Override exported methods for non-Node.js engines.
# This **Browser** compatibility layer extends core CoffeeScript functions
# to make things work smoothly when compiling code directly in the browser.
# We add support for loading remote Coffee scripts via **XHR**, and
# `text/coffeescript` script tags, source maps via data-URLs, and so on.
CoffeeScript = require './coffee-script'
CoffeeScript.require = require
compile = CoffeeScript.compile
# Use standard JavaScript `eval` to eval code.
CoffeeScript.eval = (code, options = {}) ->
options.bare ?= on
eval CoffeeScript.compile code, options
eval compile code, options
# Running code does not provide access to this scope.
CoffeeScript.run = (code, options = {}) ->
options.bare = on
Function(CoffeeScript.compile code, options)()
options.shiftLine = on
Function(compile code, options)()
# If we're not in a browser environment, we're finished with the public API.
return unless window?
# Include source maps where possible. If we've got a base64 encoder, a
# JSON serializer, and tools for escaping unicode characters, we're good to go.
# Ported from https://developer.mozilla.org/en-US/docs/DOM/window.btoa
if btoa? and JSON? and unescape? and encodeURIComponent?
compile = (code, options = {}) ->
options.sourceMap = true
options.inline = true
{js, v3SourceMap} = CoffeeScript.compile code, options
"#{js}\n//@ sourceMappingURL=data:application/json;base64,#{btoa unescape encodeURIComponent v3SourceMap}\n//@ sourceURL=coffeescript"
# Load a remote script from the current domain via XHR.
CoffeeScript.load = (url, callback, options = {}) ->
options.sourceFiles = [url]
xhr = if window.ActiveXObject
new window.ActiveXObject('Microsoft.XMLHTTP')
else
new XMLHttpRequest()
new window.XMLHttpRequest()
xhr.open 'GET', url, true
xhr.overrideMimeType 'text/plain' if 'overrideMimeType' of xhr
xhr.onreadystatechange = ->
@@ -37,7 +53,7 @@ CoffeeScript.load = (url, callback, options = {}) ->
# all script tags with a content-type of `text/coffeescript`.
# This happens on page load.
runScripts = ->
scripts = document.getElementsByTagName 'script'
scripts = window.document.getElementsByTagName 'script'
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript']
coffees = (s for s in scripts when s.type in coffeetypes)
index = 0
@@ -50,12 +66,13 @@ runScripts = ->
if script.src
CoffeeScript.load script.src, execute, options
else
options.sourceFiles = ['embedded']
CoffeeScript.run script.innerHTML, options
execute()
null
# Listen for window load, both in browsers and in IE.
# Listen for window load, both in decent browsers and in IE.
if window.addEventListener
addEventListener 'DOMContentLoaded', runScripts, no
window.addEventListener 'DOMContentLoaded', runScripts, no
else
attachEvent 'onload', runScripts
window.attachEvent 'onload', runScripts

View File

@@ -1,77 +1,59 @@
# CoffeeScript can be used both on the server, as a command-line compiler based
# on Node.js/V8, or to run CoffeeScripts directly in the browser. This module
# on Node.js/V8, or to run CoffeeScript directly in the browser. This module
# contains the main entry functions for tokenizing, parsing, and compiling
# source CoffeeScript into JavaScript.
#
# If included on a webpage, it will automatically sniff out, compile, and
# execute all scripts present in `text/coffeescript` tags.
fs = require 'fs'
path = require 'path'
{Lexer} = require './lexer'
{parser} = require './parser'
helpers = require './helpers'
vm = require 'vm'
sourcemap = require './sourcemap'
# Load and run a CoffeeScript file for Node, stripping any `BOM`s.
loadFile = (module, filename) ->
raw = fs.readFileSync filename, 'utf8'
stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw
module._compile compile(stripped, {filename, literate: helpers.isLiterate filename}), filename
if require.extensions
for ext in ['.coffee', '.litcoffee', '.md', '.coffee.md']
require.extensions[ext] = loadFile
fs = require 'fs'
vm = require 'vm'
path = require 'path'
child_process = require 'child_process'
{Lexer} = require './lexer'
{parser} = require './parser'
helpers = require './helpers'
SourceMap = require './sourcemap'
# The current CoffeeScript version number.
exports.VERSION = '1.6.1'
exports.VERSION = '1.6.3'
# Expose helpers for testing.
exports.helpers = helpers
# Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
#
# If `options.sourceMap` is specified, then `options.filename` must also be specified.
# If `options.sourceMap` is specified, then `options.filename` must also be specified. All
# options that can be passed to `SourceMap#generate` may also be passed here.
#
# This returns a javascript string, unless `options.sourceMap` is passed,
# in which case this returns a `{js, v3SourceMap, sourceMap}
# in which case this returns a `{js, v3SourceMap, sourceMap}`
# object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for doing programatic
# lookups.
exports.compile = compile = (code, options = {}) ->
{merge} = exports.helpers
try
{merge} = helpers
if options.sourceMap
map = new SourceMap
fragments = parser.parse(lexer.tokenize code, options).compileToFragments options
currentLine = 0
currentLine += 1 if options.header
currentLine += 1 if options.shiftLine
currentColumn = 0
js = ""
for fragment in fragments
# Update the sourcemap with data from each fragment
if options.sourceMap
coffeeFile = helpers.baseFileName options.filename
jsFile = helpers.baseFileName(options.filename, yes) + ".js"
sourceMap = new sourcemap.SourceMap()
if fragment.locationData
map.add(
[fragment.locationData.first_line, fragment.locationData.first_column]
[currentLine, currentColumn]
{noReplace: true})
newLines = helpers.count fragment.code, "\n"
currentLine += newLines
currentColumn = fragment.code.length - (if newLines then fragment.code.lastIndexOf "\n" else 0)
fragments = (parser.parse lexer.tokenize(code, options)).compileToFragments options
currentLine = 0
currentLine += 1 if options.header
currentLine += 1 if options.sourceMap
currentColumn = 0
js = ""
for fragment in fragments
# Update the sourcemap with data from each fragment
if sourceMap
if fragment.locationData
sourceMap.addMapping(
[fragment.locationData.first_line, fragment.locationData.first_column],
[currentLine, currentColumn],
{noReplace: true})
newLines = helpers.count fragment.code, "\n"
currentLine += newLines
currentColumn = fragment.code.length - (if newLines then fragment.code.lastIndexOf "\n" else 0)
# Copy the code from each fragment into the final JavaScript.
js += fragment.code
catch err
err.message = "In #{options.filename}, #{err.message}" if options.filename
throw err
# Copy the code from each fragment into the final JavaScript.
js += fragment.code
if options.header
header = "Generated by CoffeeScript #{@VERSION}"
@@ -79,9 +61,8 @@ exports.compile = compile = (code, options = {}) ->
if options.sourceMap
answer = {js}
if sourceMap
answer.sourceMap = sourceMap
answer.v3SourceMap = sourcemap.generateV3SourceMap sourceMap, coffeeFile, jsFile
answer.sourceMap = map
answer.v3SourceMap = map.generate(options, code)
answer
else
js
@@ -103,20 +84,25 @@ exports.nodes = (source, options) ->
# setting `__filename`, `__dirname`, and relative `require()`.
exports.run = (code, options = {}) ->
mainModule = require.main
options.sourceMap ?= true
# Set the filename.
mainModule.filename = process.argv[1] =
if options.filename then fs.realpathSync(options.filename) else '.'
if options.filename then fs.realpathSync(options.filename) else '.'
# Clear the module cache.
mainModule.moduleCache and= {}
# Assign paths for node_modules loading
mainModule.paths = require('module')._nodeModulePaths path.dirname fs.realpathSync options.filename
mainModule.paths = require('module')._nodeModulePaths path.dirname fs.realpathSync options.filename or '.'
# Compile.
if not helpers.isCoffee(mainModule.filename) or require.extensions
mainModule._compile compile(code, options), mainModule.filename
answer = compile(code, options)
# Attach sourceMap object to sourceMaps[options.filename] so that
# it is accessible by Error.prepareStackTrace.
do patchStackTrace
sourceMaps[mainModule.filename] = answer.sourceMap
mainModule._compile answer.js, mainModule.filename
else
mainModule._compile code, mainModule.filename
@@ -156,6 +142,55 @@ exports.eval = (code, options = {}) ->
else
vm.runInContext js, sandbox
# Load and run a CoffeeScript file for Node, stripping any `BOM`s.
loadFile = (module, filename) ->
raw = fs.readFileSync filename, 'utf8'
stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw
answer = compile(stripped, {filename, sourceMap: true, literate: helpers.isLiterate filename})
sourceMaps[filename] = answer.sourceMap
module._compile answer.js, filename
# If the installed version of Node supports `require.extensions`, register
# CoffeeScript as an extension.
if require.extensions
for ext in ['.coffee', '.litcoffee', '.coffee.md']
require.extensions[ext] = loadFile
# Patch Node's module loader to be able to handle mult-dot extensions.
# This is a horrible thing that should not be required. Perhaps, one day,
# when a truly benevolent dictator comes to rule over the Republik of Node,
# it won't be.
Module = require 'module'
findExtension = (filename) ->
extensions = path.basename(filename).split '.'
# Remove the initial dot from dotfiles.
extensions.shift() if extensions[0] is ''
# Start with the longest possible extension and work our way shortwards.
while extensions.shift()
curExtension = '.' + extensions.join '.'
return curExtension if Module._extensions[curExtension]
'.js'
Module::load = (filename) ->
@filename = filename
@paths = Module._nodeModulePaths path.dirname filename
extension = findExtension filename
Module._extensions[extension](this, filename)
@loaded = true
# If we're on Node, patch `child_process.fork` so that Coffee scripts are able
# to fork both CoffeeScript files, and JavaScript files, directly.
if child_process
{fork} = child_process
child_process.fork = (path, args = [], options = {}) ->
execPath = if helpers.isCoffee(path) then 'coffee' else null
if not Array.isArray args
args = []
options = args or {}
options.execPath or= execPath
fork path, args, options
# Instantiate a Lexer for our use here.
lexer = new Lexer
@@ -177,4 +212,103 @@ parser.lexer =
upcomingInput: ->
""
# Make all the AST nodes visible to the parser.
parser.yy = require './nodes'
# Override Jison's default error handling function.
parser.yy.parseError = (message, {token}) ->
# Disregard Jison's message, it contains redundant line numer information.
message = "unexpected #{if token is 1 then 'end of input' else token}"
# The second argument has a `loc` property, which should have the location
# data for this token. Unfortunately, Jison seems to send an outdated `loc`
# (from the previous token), so we take the location information directly
# from the lexer.
helpers.throwSyntaxError message, parser.lexer.yylloc
# Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p)
# NodeJS / V8 have no support for transforming positions in stack traces using
# sourceMap, so we must monkey-patch Error to display CoffeeScript source
# positions.
patched = false
# Map of filenames -> sourceMap object.
sourceMaps = {}
patchStackTrace = ->
return if patched
patched = true
mainModule = require.main
# (Assigning to a property of the Module object in the normal module cache is
# unsuitable, because node deletes those objects from the cache if an
# exception is thrown in the module body.)
Error.prepareStackTrace = (err, stack) ->
sourceFiles = {}
getSourceMapping = (filename, line, column) ->
sourceMap = sourceMaps[filename]
answer = sourceMap.sourceLocation [line - 1, column - 1] if sourceMap
if answer then [answer[0] + 1, answer[1] + 1] else null
frames = for frame in stack
break if frame.getFunction() is exports.run
" at #{formatSourcePosition frame, getSourceMapping}"
"#{err.name}: #{err.message ? ''}\n#{frames.join '\n'}\n"
# Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js
# Modified to handle sourceMap
formatSourcePosition = (frame, getSourceMapping) ->
fileName = undefined
fileLocation = ''
if frame.isNative()
fileLocation = "native"
else
if frame.isEval()
fileName = frame.getScriptNameOrSourceURL()
fileLocation = "#{frame.getEvalOrigin()}, " unless fileName
else
fileName = frame.getFileName()
fileName or= "<anonymous>"
line = frame.getLineNumber()
column = frame.getColumnNumber()
# Check for a sourceMap position
source = getSourceMapping fileName, line, column
fileLocation =
if source
"#{fileName}:#{source[0]}:#{source[1]}, <js>:#{line}:#{column}"
else
"#{fileName}:#{line}:#{column}"
functionName = frame.getFunctionName()
isConstructor = frame.isConstructor()
isMethodCall = not (frame.isToplevel() or isConstructor)
if isMethodCall
methodName = frame.getMethodName()
typeName = frame.getTypeName()
if functionName
tp = as = ''
if typeName and functionName.indexOf typeName
tp = "#{typeName}."
if methodName and functionName.indexOf(".#{methodName}") isnt functionName.length - methodName.length - 1
as = " [as #{methodName}]"
"#{tp}#{functionName}#{as} (#{fileLocation})"
else
"#{typeName}.#{methodName or '<anonymous>'} (#{fileLocation})"
else if isConstructor
"new #{functionName or '<anonymous>'} (#{fileLocation})"
else if functionName
"#{functionName} (#{fileLocation})"
else
fileLocation

View File

@@ -1,7 +1,7 @@
# The `coffee` utility. Handles command-line compilation of CoffeeScript
# into various forms: saved into `.js` files or printed to stdout, piped to
# [JavaScript Lint](http://javascriptlint.com/) or recompiled every time the source is
# saved, printed as a token stream or as the syntax tree, or launch an
# into various forms: saved into `.js` files or printed to stdout
# or recompiled every time the source is saved,
# printed as a token stream or as the syntax tree, or launch an
# interactive REPL.
# External dependencies.
@@ -14,6 +14,7 @@ CoffeeScript = require './coffee-script'
{EventEmitter} = require 'events'
exists = fs.exists or path.exists
useWinPathSep = path.sep is '\\'
# Allow CoffeeScript to emit Node.js events.
helpers.extend CoffeeScript, new EventEmitter
@@ -38,13 +39,13 @@ SWITCHES = [
['-h', '--help', 'display this help message']
['-i', '--interactive', 'run an interactive CoffeeScript REPL']
['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling']
['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint']
['-m', '--map', 'generate source map and save as .map files']
['-n', '--nodes', 'print out the parse tree that the parser produces']
[ '--nodejs [ARGS]', 'pass options directly to the "node" binary']
['-o', '--output [DIR]', 'set the output directory for compiled JavaScript']
['-p', '--print', 'print out the compiled JavaScript']
['-s', '--stdio', 'listen for and compile scripts over stdio']
['-l', '--literate', 'treat stdio as literate style coffee-script']
['-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']
@@ -67,7 +68,7 @@ exports.run = ->
return usage() if opts.help
return version() if opts.version
return require('./repl').start() if opts.interactive
if opts.watch and !fs.watch
if opts.watch and not fs.watch
return printWarn "The --watch feature depends on Node v0.6.0+. You are running #{process.version}."
return compileStdio() if opts.stdio
return compileScript null, sources[0] if opts.eval
@@ -112,9 +113,9 @@ compilePath = (source, topLevel, base) ->
# Compile a single source script, containing the given code, according to the
# requested options. If evaluating the script directly sets `__filename`,
# `__dirname` and `module.filename` to be correct relative to the script's path.
compileScript = (file, input, base) ->
compileScript = (file, input, base=null) ->
o = opts
options = compileOptions file
options = compileOptions file, base
try
t = task = {file, input, options}
CoffeeScript.emit 'compile', task
@@ -122,6 +123,7 @@ compileScript = (file, input, base) ->
else if o.nodes then printLine CoffeeScript.nodes(t.input, t.options).toString().trim()
else if o.run then CoffeeScript.run t.input, t.options
else if o.join and t.file isnt o.join
t.input = helpers.invertLiterate t.input if helpers.isLiterate file
sourceCode[sources.indexOf(t.file)] = t.input
compileJoin()
else
@@ -134,16 +136,18 @@ compileScript = (file, input, base) ->
CoffeeScript.emit 'success', task
if o.print
printLine t.output.trim()
else if o.compile || o.map
writeJs base, t.file, t.output, t.sourceMap
else if o.lint
lint t.file, t.output
else if o.compile or o.map
writeJs base, t.file, t.output, options.jsPath, t.sourceMap
catch err
CoffeeScript.emit 'failure', err, task
return if CoffeeScript.listeners('failure').length
return printLine err.message + '\x07' if o.watch
printWarn err instanceof Error and err.stack or "ERROR: #{err}"
process.exit 1
useColors = process.stdout.isTTY and not process.env.NODE_DISABLE_COLORS
message = helpers.prettyErrorMessage err, file or '[stdin]', input, useColors
if o.watch
printLine message + '\x07'
else
printWarn message
process.exit 1
# Attach the appropriate listeners to compile scripts incoming over **stdin**,
# and write them back to **stdout**.
@@ -167,7 +171,7 @@ compileJoin = ->
# Watch a source CoffeeScript file using `fs.watch`, recompiling it every
# time the file is updated. May be used in combination with other options,
# such as `--lint` or `--print`.
# such as `--print`.
watch = (source, base) ->
prevStats = null
@@ -251,7 +255,7 @@ removeSource = (source, base, removeJs) ->
# Get the corresponding output JavaScript path for a source file.
outputPath = (source, base, extension=".js") ->
basename = helpers.baseFileName source, yes
basename = helpers.baseFileName source, yes, useWinPathSep
srcDir = path.dirname source
baseDir = if base is '.' then srcDir else srcDir.substring base.length
dir = if opts.output then path.join opts.output, baseDir else srcDir
@@ -263,14 +267,13 @@ outputPath = (source, base, extension=".js") ->
#
# If `generatedSourceMap` is provided, this will write a `.map` file into the
# same directory as the `.js` file.
writeJs = (base, sourcePath, js, generatedSourceMap = null) ->
jsPath = outputPath sourcePath, base
writeJs = (base, sourcePath, js, jsPath, generatedSourceMap = null) ->
sourceMapPath = outputPath sourcePath, base, ".map"
jsDir = path.dirname jsPath
compile = ->
if opts.compile
js = ' ' if js.length <= 0
if generatedSourceMap then js = "//@ sourceMappingURL=#{helpers.baseFileName sourceMapPath}\n#{js}"
if generatedSourceMap then js = "#{js}\n/*\n//@ sourceMappingURL=#{helpers.baseFileName sourceMapPath, no, useWinPathSep}\n*/\n"
fs.writeFile jsPath, js, (err) ->
if err
printLine err.message
@@ -290,17 +293,6 @@ wait = (milliseconds, func) -> setTimeout func, milliseconds
timeLog = (message) ->
console.log "#{(new Date).toLocaleTimeString()} - #{message}"
# Pipe compiled JS through JSLint (requires a working `jsl` command), printing
# any errors or warnings that arise.
lint = (file, js) ->
printIt = (buffer) -> printLine file + ':\t' + buffer.toString().trim()
conf = __dirname + '/../../extras/jsl.conf'
jsl = spawn 'jsl', ['-nologo', '-stdin', '-conf', conf]
jsl.stdout.on 'data', printIt
jsl.stderr.on 'data', printIt
jsl.stdin.write js
jsl.stdin.end()
# Pretty-print a stream of tokens, sans location data.
printTokens = (tokens) ->
strings = for token in tokens
@@ -315,21 +307,38 @@ parseOptions = ->
optionParser = new optparse.OptionParser SWITCHES, BANNER
o = opts = optionParser.parse process.argv[2..]
o.compile or= !!o.output
o.run = not (o.compile or o.print or o.lint or o.map)
o.run = not (o.compile or o.print or o.map)
o.print = !! (o.print or (o.eval or o.stdio and o.compile))
sources = o.arguments
sourceCode[i] = null for source, i in sources
return
# The compile-time options to pass to the CoffeeScript compiler.
compileOptions = (filename) ->
{
compileOptions = (filename, base) ->
answer = {
filename
literate: helpers.isLiterate(filename)
literate: opts.literate or helpers.isLiterate(filename)
bare: opts.bare
header: opts.compile
sourceMap: opts.map
}
if filename
if base
cwd = process.cwd()
jsPath = outputPath filename, base
jsDir = path.dirname jsPath
answer = helpers.merge answer, {
jsPath
sourceRoot: path.relative jsDir, cwd
sourceFiles: [path.relative cwd, filename]
generatedFile: helpers.baseFileName(jsPath, no, useWinPathSep)
}
else
answer = helpers.merge answer,
sourceRoot: ""
sourceFiles: [helpers.baseFileName filename, no, useWinPathSep]
generatedFile: helpers.baseFileName(filename, yes, useWinPathSep) + ".js"
answer
# Start up a new Node.js instance with the arguments in `--nodejs` passed to
# the `node` binary, preserving the other options.

View File

@@ -401,6 +401,7 @@ grammar =
Catch: [
o 'CATCH Identifier Block', -> [$2, $3]
o 'CATCH Object Block', -> [LOC(2)(new Value($2)), $3]
o 'CATCH Block', -> [null, $2]
]
# Throw an exception object.

View File

@@ -11,6 +11,16 @@ exports.ends = (string, literal, back) ->
len = literal.length
literal is string.substr string.length - len - (back or 0), len
# Repeat a string `n` times.
exports.repeat = repeat = (str, n) ->
# Use clever algorithm to have O(log(n)) string concatenation operations.
res = ''
while n > 0
res += str if n & 1
n >>>= 1
str += str
res
# Trim out all falsy values from an array.
exports.compact = (array) ->
item for item in array when item
@@ -53,13 +63,27 @@ exports.del = (obj, key) ->
val
# Gets the last item of an array(-like) object.
exports.last = (array, back) -> array[array.length - (back or 0) - 1]
exports.last = last = (array, back) -> array[array.length - (back or 0) - 1]
# Typical Array::some
exports.some = Array::some ? (fn) ->
return true for e in this when fn e
false
# Simple function for inverting Literate CoffeeScript code by putting the
# documentation in comments, producing a string of CoffeeScript code that
# can be compiled "normally".
exports.invertLiterate = (code) ->
maybe_code = true
lines = for line in code.split('\n')
if maybe_code and /^([ ]{4}|[ ]{0,3}\t)/.test line
line
else if maybe_code = /^\s*$/.test line
line
else
'# ' + line
lines.join '\n'
# Merge two jison-style location data objects together.
# If `last` is not provided, this will simply return `first`.
buildLocationData = (first, last) ->
@@ -71,8 +95,9 @@ buildLocationData = (first, last) ->
last_line: last.last_line
last_column: last.last_column
# This returns a function which takes an object as a parameter, and if that object is an AST node,
# updates that object's locationData. The object is returned either way.
# This returns a function which takes an object as a parameter, and if that
# object is an AST node, updates that object's locationData.
# The object is returned either way.
exports.addLocationDataFn = (first, last) ->
(obj) ->
if ((typeof obj) is 'object') and (!!obj['updateLocationDataIfMissing'])
@@ -93,13 +118,14 @@ exports.locationDataToString = (obj) ->
"No location data"
# A `.coffee.md` compatible version of `basename`, that returns the file sans-extension.
exports.baseFileName = (file, stripExt = no) ->
parts = file.split('/')
exports.baseFileName = (file, stripExt = no, useWinPathSep = no) ->
pathSep = if useWinPathSep then /\\|\// else /\//
parts = file.split(pathSep)
file = parts[parts.length - 1]
return file unless stripExt
parts = file.split('.')
parts.pop()
parts.pop() if parts[parts.length - 1] is 'coffee'
parts.pop() if parts[parts.length - 1] is 'coffee' and parts.length > 1
parts.join('.')
# Determine if a filename represents a CoffeeScript file.
@@ -108,4 +134,40 @@ exports.isCoffee = (file) -> /\.((lit)?coffee|coffee\.md)$/.test file
# Determine if a filename represents a Literate CoffeeScript file.
exports.isLiterate = (file) -> /\.(litcoffee|coffee\.md)$/.test file
# Throws a SyntaxError with a source file location data attached to it in a
# property called `location`.
exports.throwSyntaxError = (message, location) ->
location.last_line ?= location.first_line
location.last_column ?= location.first_column
error = new SyntaxError message
error.location = location
throw error
# Creates a nice error message like, following the "standard" format
# <filename>:<line>:<col>: <message> plus the line with the error and a marker
# showing where the error is.
exports.prettyErrorMessage = (error, fileName, code, useColors) ->
return error.stack or "#{error}" unless error.location
{first_line, first_column, last_line, last_column} = error.location
codeLine = code.split('\n')[first_line]
start = first_column
# Show only the first line on multi-line errors.
end = if first_line is last_line then last_column + 1 else codeLine.length
marker = repeat(' ', start) + repeat('^', end - start)
if useColors
colorize = (str) -> "\x1B[1;31m#{str}\x1B[0m"
codeLine = codeLine[...start] + colorize(codeLine[start...end]) + codeLine[end..]
marker = colorize marker
message = """
#{fileName}:#{first_line + 1}:#{first_column + 1}: error: #{error.message}
#{codeLine}
#{marker}
"""
# Uncomment to add stacktrace.
#message += "\n#{error.stack}"
message

View File

@@ -5,16 +5,15 @@
#
# [tag, value, locationData]
#
# The locationData is in the form:
# `{first_line, first_column, last_line, last_column}`, which is a
# format that can be fed directly into [Jison](http://github.com/zaach/jison).
# These are read by Jison in the `parser.lexer` function defined in
# coffee-script.coffee.
# where locationData is {first_line, first_column, last_line, last_column}, which is a
# format that can be fed directly into [Jison](http://github.com/zaach/jison). These
# are read by jison in the `parser.lexer` function defined in coffee-script.coffee.
{Rewriter, INVERSES} = require './rewriter'
# Import the helpers we need.
{count, starts, compact, last, locationDataToString} = require './helpers'
{count, starts, compact, last, repeat, invertLiterate,
locationDataToString, throwSyntaxError} = require './helpers'
# The Lexer Class
# ---------------
@@ -42,7 +41,7 @@ exports.Lexer = class Lexer
@outdebt = 0 # The under-outdentation at the current level.
@indents = [] # The stack of all current indentation levels.
@ends = [] # The stack for pairing up tokens.
@tokens = [] # Stream of parsed tokens in the form `['TYPE', value, line]`.
@tokens = [] # Stream of parsed tokens in the form `['TYPE', value, location data]`.
@chunkLine =
opts.line or 0 # The start line for the current @chunk.
@@ -86,13 +85,7 @@ exports.Lexer = class Lexer
if WHITESPACE.test code
code = "\n#{code}"
@chunkLine--
if @literate
lines = for line in code.split('\n')
if match = LITERATE.exec line
line[match[0].length..]
else
'# ' + line
code = lines.join '\n'
code = invertLiterate code if @literate
code
# Tokenizers
@@ -183,9 +176,9 @@ exports.Lexer = class Lexer
@error "octal literal '#{number}' must be prefixed with '0o'"
lexedLength = number.length
if octalLiteral = /^0o([0-7]+)/.exec number
number = '0x' + (parseInt octalLiteral[1], 8).toString 16
number = '0x' + parseInt(octalLiteral[1], 8).toString 16
if binaryLiteral = /^0b([01]+)/.exec number
number = '0x' + (parseInt binaryLiteral[1], 2).toString 16
number = '0x' + parseInt(binaryLiteral[1], 2).toString 16
@token 'NUMBER', number, 0, lexedLength
lexedLength
@@ -229,7 +222,7 @@ exports.Lexer = class Lexer
if here
@token 'HERECOMMENT',
(@sanitizeHeredoc here,
herecomment: true, indent: Array(@indent + 1).join(' ')),
herecomment: true, indent: repeat ' ', @indent),
0, comment.length
comment.length
@@ -330,7 +323,7 @@ exports.Lexer = class Lexer
@suppressNewlines()
return indent.length
diff = size - @indent + @outdebt
@token 'INDENT', diff, 0, indent.length
@token 'INDENT', diff, indent.length - size, size
@indents.push diff
@ends.push 'OUTDENT'
@outdebt = @indebt = 0
@@ -445,7 +438,6 @@ exports.Lexer = class Lexer
attempt = match[1]
indent = attempt if indent is null or 0 < attempt.length < indent.length
doc = doc.replace /// \n #{indent} ///g, '\n' if indent
doc = doc.replace /\n# \n/g, '\n\n' if @literate
doc = doc.replace /^\n/, '' unless herecomment
doc
@@ -597,7 +589,10 @@ exports.Lexer = class Lexer
@tokens.push token
else
@error "Unexpected #{tag}"
@token ')', ')', offsetInChunk + lexedLength, 0 if interpolated
if interpolated
rparen = @makeToken ')', ')', offsetInChunk + lexedLength, 0
rparen.stringEnd = true
@tokens.push rparen
tokens
# Pairs up a closing token, ensuring that all listed pairs of tokens are
@@ -635,7 +630,7 @@ exports.Lexer = class Lexer
column = @chunkColumn
if lineCount > 0
lines = string.split '\n'
column = (last lines).length
column = last(lines).length
else
column += string.length
@@ -652,7 +647,7 @@ exports.Lexer = class Lexer
# so if last_column == first_column, then we're looking at a character of length 1.
lastCharacter = Math.max 0, length - 1
[locationData.last_line, locationData.last_column] =
@getLineAndColumnFromChunk offsetInChunk + (length - 1)
@getLineAndColumnFromChunk offsetInChunk + lastCharacter
token = [tag, value, locationData]
@@ -695,11 +690,11 @@ exports.Lexer = class Lexer
body = body.replace /// #{quote} ///g, '\\$&'
quote + @escapeLines(body, heredoc) + quote
# Throws a syntax error on the current `@line`.
# Throws a compiler error on the current position.
error: (message) ->
# TODO: Are there some cases we could improve the error line number by
# passing the offset in the chunk where the error happened?
throw SyntaxError "#{message} on line #{ @chunkLine + 1 }"
throwSyntaxError message, first_line: @chunkLine, first_column: @chunkColumn
# Constants
# ---------
@@ -781,8 +776,6 @@ WHITESPACE = /^[^\n\S]+/
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)$)|^(?:\s*#(?!##[^#]).*)+/
LITERATE = /^([ ]{4}|\t)/
CODE = /^[-=]>/
MULTI_DENT = /^(?:\n[^\n\S]*)+/
@@ -853,11 +846,11 @@ BOOL = ['TRUE', 'FALSE']
# See: http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions
#
# Our list is shorter, due to sans-parentheses method calls.
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--', ']']
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--']
# If the previous token is not spaced, there are more preceding tokens that
# force a division parse:
NOT_SPACED_REGEX = NOT_REGEX.concat ')', '}', 'THIS', 'IDENTIFIER', 'STRING'
NOT_SPACED_REGEX = NOT_REGEX.concat ')', '}', 'THIS', 'IDENTIFIER', 'STRING', ']'
# Tokens which could legitimately be invoked or indexed. An opening
# parentheses or bracket following these tokens will be recorded as the start

View File

@@ -9,7 +9,8 @@ Error.stackTraceLimit = Infinity
{RESERVED, STRICT_PROSCRIBED} = require './lexer'
# Import the helpers we plan to use.
{compact, flatten, extend, merge, del, starts, ends, last, some, addLocationDataFn, locationDataToString} = require './helpers'
{compact, flatten, extend, merge, del, starts, ends, last, some,
addLocationDataFn, locationDataToString, throwSyntaxError} = require './helpers'
# Functions required by parser
exports.extend = extend
@@ -33,8 +34,8 @@ exports.CodeFragment = class CodeFragment
@locationData = parent?.locationData
@type = parent?.constructor?.name or 'unknown'
toString: () ->
"#{@code}#{[if @locationData then ": " + locationDataToString(@locationData)]}"
toString: ->
"#{@code}#{if @locationData then ": " + locationDataToString(@locationData) else ''}"
# Convert an array of CodeFragments into a string.
fragmentsToText = (fragments) ->
@@ -75,8 +76,8 @@ exports.Base = class Base
# Statements converted into expressions via closure-wrapping share a scope
# object with their parent closure, to preserve the expected lexical scope.
compileClosure: (o) ->
if @jumps()
throw SyntaxError 'cannot use a pure statement in an expression.'
if jumpNode = @jumps()
jumpNode.error 'cannot use a pure statement in an expression'
o.sharedScope = yes
Closure.wrap(this).compileNode o
@@ -110,20 +111,16 @@ exports.Base = class Base
new Return me
# Does this node, or any of its children, contain a node of a certain kind?
# Recursively traverses down the *children* of the nodes, yielding to a block
# and returning true when the block finds a match. `contains` does not cross
# Recursively traverses down the *children* nodes and returns the first one
# that verifies `pred`. Otherwise return undefined. `contains` does not cross
# scope boundaries.
contains: (pred) ->
contains = no
@traverseChildren no, (node) ->
if pred node
contains = yes
node = undefined
@traverseChildren no, (n) ->
if pred n
node = n
return no
contains
# Is this node of a certain type, or does it contain the type?
containsType: (type) ->
this instanceof type or @contains (node) -> node instanceof type
node
# Pull out the last non-comment node of a node list.
lastNonComment: (list) ->
@@ -134,8 +131,7 @@ exports.Base = class Base
# `toString` representation of the node, for inspecting the parse tree.
# This is what `coffee --nodes` prints out.
toString: (idt = '', name = @constructor.name) ->
location = if @locationData then locationDataToString @locationData else "??"
tree = '\n' + idt + location + ": " + name
tree = '\n' + idt + name
tree += '?' if @soak
@eachChild (node) -> tree += node.toString idt + TAB
tree
@@ -150,8 +146,8 @@ exports.Base = class Base
traverseChildren: (crossScope, func) ->
@eachChild (child) ->
return false if func(child) is false
child.traverseChildren crossScope, func
recur = func(child)
child.traverseChildren(crossScope, func) unless recur is no
invert: ->
new Op '!', this
@@ -177,16 +173,18 @@ exports.Base = class Base
# Is this node used to assign a certain variable?
assigns: NO
# For this node and all descendents, set the location data to `locationData` if the location
# data is not already set.
# For this node and all descendents, set the location data to `locationData`
# if the location data is not already set.
updateLocationDataIfMissing: (locationData) ->
if not @locationData
@locationData = {}
extend @locationData, locationData
@locationData or= locationData
@eachChild (child) ->
child.updateLocationDataIfMissing locationData
# Throw a SyntaxError associated with this node's location.
error: (message) ->
throwSyntaxError message, @locationData
makeCode: (code) ->
new CodeFragment this, code
@@ -290,7 +288,7 @@ exports.Block = class Block extends Base
compiledNodes.push node.compileToFragments o, LEVEL_LIST
if top
if @spaced
return [].concat @makeCode("\n"), @joinFragmentArrays(compiledNodes, '\n\n'), @makeCode("\n")
return [].concat @joinFragmentArrays(compiledNodes, '\n\n'), @makeCode("\n")
else
return @joinFragmentArrays(compiledNodes, '\n')
if compiledNodes.length
@@ -305,9 +303,12 @@ exports.Block = class Block extends Base
# clean up obvious double-parentheses.
compileRoot: (o) ->
o.indent = if o.bare then '' else TAB
o.scope = new Scope null, this, null
o.level = LEVEL_TOP
@spaced = yes
o.scope = new Scope null, this, null
# Mark given local variables in the root scope as parameters so they don't
# end up being declared on this block.
o.scope.parameter name for name in o.locals or []
prelude = []
unless o.bare
preludeExps = for exp, i in @expressions
@@ -335,7 +336,7 @@ exports.Block = class Block extends Base
if i
rest = @expressions.splice i, 9e9
[spaced, @spaced] = [@spaced, no]
[fragments, @spaced] = [(@compileNode o), spaced]
[fragments, @spaced] = [@compileNode(o), spaced]
@expressions = rest
post = @compileNode o
{scope} = o
@@ -346,11 +347,13 @@ exports.Block = class Block extends Base
fragments.push @makeCode '\n' if i
fragments.push @makeCode "#{@tab}var "
if declars
fragments.push @makeCode(scope.declaredVariables().join ', ')
fragments.push @makeCode scope.declaredVariables().join(', ')
if assigns
fragments.push @makeCode ",\n#{@tab + TAB}" if declars
fragments.push @makeCode (scope.assignedVariables().join ",\n#{@tab + TAB}")
fragments.push @makeCode ';\n'
fragments.push @makeCode scope.assignedVariables().join(",\n#{@tab + TAB}")
fragments.push @makeCode ";\n#{if @spaced then '\n' else ''}"
else if fragments.length and post.length
fragments.push @makeCode "\n"
fragments.concat post
# Wrap up the given nodes as a **Block**, unless it already happens
@@ -436,9 +439,9 @@ exports.Return = class Return extends Base
compileNode: (o) ->
answer = []
# TODO: If we call expression.compile() here twice, we'll sometimes get back different results!
answer.push @makeCode(@tab + "return#{[" " if @expression]}")
answer.push @makeCode @tab + "return#{if @expression then " " else ""}"
if @expression
answer = answer.concat @expression.compileToFragments(o, LEVEL_PAREN)
answer = answer.concat @expression.compileToFragments o, LEVEL_PAREN
answer.push @makeCode ";"
return answer
@@ -552,7 +555,7 @@ exports.Comment = class Comment extends Base
makeReturn: THIS
compileNode: (o, level) ->
code = '/*' + multident(@comment, @tab) + "\n#{@tab}*/\n"
code = "/*#{multident @comment, @tab}#{if '\n' in @comment then "\n#{@tab}" else ''}*/\n"
code = o.indent + code if (level or o.level) is LEVEL_TOP
[@makeCode code]
@@ -589,7 +592,7 @@ exports.Call = class Call extends Base
else if method?.ctor
"#{method.name}.__super__.constructor"
else
throw SyntaxError 'cannot call super outside of an instance method.'
@error 'cannot call super outside of an instance method.'
# The appropriate `this` value for a `super` call.
superThis : (o) ->
@@ -646,7 +649,7 @@ exports.Call = class Call extends Base
fragments.push @makeCode preface
else
if @isNew then fragments.push @makeCode 'new '
fragments.push (@variable.compileToFragments(o, LEVEL_ACCESS))...
fragments.push @variable.compileToFragments(o, LEVEL_ACCESS)...
fragments.push @makeCode "("
fragments.push compiledArgs...
fragments.push @makeCode ")"
@@ -738,7 +741,7 @@ exports.Index = class Index extends Base
children: ['index']
compileToFragments: (o) ->
[].concat @makeCode("["), (@index.compileToFragments o, LEVEL_PAREN), @makeCode("]")
[].concat @makeCode("["), @index.compileToFragments(o, LEVEL_PAREN), @makeCode("]")
isComplex: ->
@index.isComplex()
@@ -883,7 +886,7 @@ exports.Obj = class Obj extends Base
return [@makeCode(if @front then '({})' else '{}')] unless props.length
if @generated
for node in props when node instanceof Value
throw new Error 'cannot have an implicit value in an implicit object'
node.error 'cannot have an implicit value in an implicit object'
idt = o.indent += TAB
lastNoncom = @lastNonComment @properties
answer = []
@@ -895,6 +898,8 @@ exports.Obj = class Obj extends Base
else
',\n'
indent = if prop instanceof Comment then '' else idt
if prop instanceof Assign and prop.variable instanceof Value and prop.variable.hasProperties()
prop.variable.error 'Invalid object key'
if prop instanceof Value and prop.this
prop = new Assign prop.properties[0].name, prop, 'object'
if prop not instanceof Comment
@@ -933,7 +938,7 @@ exports.Arr = class Arr extends Base
if index
answer.push @makeCode ", "
answer.push fragments...
if (fragmentsToText answer).indexOf('\n') >= 0
if fragmentsToText(answer).indexOf('\n') >= 0
answer.unshift @makeCode "[\n#{o.indent}"
answer.push @makeCode "\n#{@tab}]"
else
@@ -965,7 +970,7 @@ exports.Class = class Class extends Base
else
@variable.base.value
if decl in STRICT_PROSCRIBED
throw SyntaxError "variable name may not be #{decl}"
@variable.error "class variable name may not be #{decl}"
decl and= IDENTIFIER.test(decl) and decl
# For all `this`-references and bound functions in the class definition,
@@ -982,14 +987,9 @@ exports.Class = class Class extends Base
# Ensure that all functions bound to the instance are proxied in the
# constructor.
addBoundFunctions: (o) ->
if @boundFuncs.length
o.scope.assign '_this', 'this'
for [name, func] in @boundFuncs
lhs = new Value (new Literal "this"), [new Access name]
body = new Block [new Return new Literal "#{@ctor.name}.prototype.#{name.value}.apply(_this, arguments)"]
rhs = new Code func.params, body, 'boundfunc'
bound = new Assign lhs, rhs
@ctor.body.unshift bound
for bvar in @boundFuncs
lhs = (new Value (new Literal "this"), [new Access bvar]).compile o
@ctor.body.unshift new Literal "#{lhs} = #{utility 'bind'}(#{lhs}, this)"
return
# Merge the properties from a top-level object as prototypal properties
@@ -1003,9 +1003,9 @@ exports.Class = class Class extends Base
func = assign.value
if base.value is 'constructor'
if @ctor
throw new Error 'cannot define more than one constructor in a class'
assign.error 'cannot define more than one constructor in a class'
if func.bound
throw new Error 'cannot define a constructor as a bound function'
assign.error 'cannot define a constructor as a bound function'
if func instanceof Code
assign = @ctor = func
else
@@ -1017,9 +1017,9 @@ exports.Class = class Class extends Base
if func.bound
func.context = name
else
assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), new Access base ])
assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), new Access base])
if func instanceof Code and func.bound
@boundFuncs.push [base, func]
@boundFuncs.push base
func.bound = no
assign
compact exprs
@@ -1049,16 +1049,26 @@ exports.Class = class Class extends Base
# Make sure that a constructor is defined for the class, and properly
# configured.
ensureConstructor: (name) ->
if not @ctor
@ctor = new Code
@ctor.body.push new Literal "#{name}.__super__.constructor.apply(this, arguments)" if @parent
@ctor.body.push new Literal "#{@externalCtor}.apply(this, arguments)" if @externalCtor
@ctor.body.makeReturn()
@body.expressions.unshift @ctor
@ctor.ctor = @ctor.name = name
@ctor.klass = null
ensureConstructor: (name, o) ->
missing = not @ctor
@ctor or= new Code
@ctor.ctor = @ctor.name = name
@ctor.klass = null
@ctor.noReturn = yes
if missing
superCall = new Literal "#{name}.__super__.constructor.apply(this, arguments)" if @parent
superCall = new Literal "#{@externalCtor}.apply(this, arguments)" if @externalCtor
if superCall
ref = new Literal o.scope.freeVariable 'ref'
@ctor.body.unshift new Assign ref, superCall
@addBoundFunctions o
if superCall
@ctor.body.push ref
@ctor.body.makeReturn()
@body.expressions.unshift @ctor
else
@addBoundFunctions o
# Instead of generating the JavaScript string directly, we build up the
# equivalent syntax tree and compile that, in pieces. You can see the
@@ -1072,12 +1082,11 @@ exports.Class = class Class extends Base
@hoistDirectivePrologue()
@setContext name
@walkBody name, o
@ensureConstructor name
@ensureConstructor name, o
@body.spaced = yes
@body.expressions.unshift @ctor unless @ctor instanceof Code
@body.expressions.push lname
@body.expressions.unshift @directives...
@addBoundFunctions o
call = Closure.wrap @body
@@ -1102,7 +1111,7 @@ exports.Assign = class Assign extends Base
@subpattern = options and options.subpattern
forbidden = (name = @variable.unwrapAll().value) in STRICT_PROSCRIBED
if forbidden and @context isnt 'object'
throw SyntaxError "variable name may not be \"#{name}\""
@variable.error "variable name may not be \"#{name}\""
children: ['variable', 'value']
@@ -1127,8 +1136,9 @@ exports.Assign = class Assign extends Base
compiledName = @variable.compileToFragments o, LEVEL_LIST
name = fragmentsToText compiledName
unless @context
unless (varBase = @variable.unwrapAll()).isAssignable()
throw SyntaxError "\"#{ @variable.compile o }\" cannot be assigned."
varBase = @variable.unwrapAll()
unless varBase.isAssignable()
@variable.error "\"#{@variable.compile o}\" cannot be assigned"
unless varBase.hasProperties?()
if @param
o.scope.add name, 'var'
@@ -1167,7 +1177,7 @@ exports.Assign = class Assign extends Base
value = new Value value
value.properties.push new (if acc then Access else Index) idx
if obj.unwrap().value in RESERVED
throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{value.compile o}"
obj.error "assignment to a reserved word: #{obj.compile o}"
return new Assign(obj, value, null, param: @param).compileToFragments o, LEVEL_TOP
vvar = value.compileToFragments o, LEVEL_LIST
vvarText = fragmentsToText vvar
@@ -1205,9 +1215,7 @@ exports.Assign = class Assign extends Base
else
name = obj.unwrap().value
if obj instanceof Splat
obj = obj.name.compileToFragments o
throw new SyntaxError \
"multiple splats are disallowed in an assignment: #{obj}..."
obj.error "multiple splats are disallowed in an assignment"
if typeof idx is 'number'
idx = new Literal splat or idx
acc = no
@@ -1215,7 +1223,7 @@ exports.Assign = class Assign extends Base
acc = isObject and IDENTIFIER.test idx.unwrap().value or 0
val = new Value new Literal(vvarText), [new (if acc then Access else Index) idx]
if name? and name in RESERVED
throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{val.compile o}"
obj.error "assignment to a reserved word: #{obj.compile o}"
assigns.push new Assign(obj, val, null, param: @param, subpattern: yes).compileToFragments o, LEVEL_LIST
assigns.push vvar unless top or @subpattern
fragments = @joinFragmentArrays assigns, ', '
@@ -1229,9 +1237,9 @@ exports.Assign = class Assign extends Base
# Disallow conditional assignment of undefined variables.
if not left.properties.length and left.base instanceof Literal and
left.base.value != "this" and not o.scope.check left.base.value
throw new Error "the variable \"#{left.base.value}\" can't be assigned with #{@context} because it has not been defined."
@variable.error "the variable \"#{left.base.value}\" can't be assigned with #{@context} because it has not been declared before"
if "?" in @context then o.isExistentialEquals = true
new Op(@context[...-1], left, new Assign(right, @value, '=') ).compileToFragments o
new Op(@context[...-1], left, new Assign(right, @value, '=')).compileToFragments o
# Compile the assignment from an array splice literal, using JavaScript's
# `Array#splice` method.
@@ -1286,7 +1294,7 @@ exports.Code = class Code extends Base
delete o.isExistentialEquals
params = []
exprs = []
for name in @paramNames() # this step must be performed before the others
@eachParamName (name) -> # this step must be performed before the others
unless o.scope.check name then o.scope.parameter name
for param in @params when param.splat
for {name: p} in @params
@@ -1314,8 +1322,8 @@ exports.Code = class Code extends Base
params[i] = p.compileToFragments o
o.scope.parameter fragmentsToText params[i]
uniqs = []
for name in @paramNames()
throw SyntaxError "multiple parameters named '#{name}'" if name in uniqs
@eachParamName (name, node) ->
node.error "multiple parameters named '#{name}'" if name in uniqs
uniqs.push name
@body.makeReturn() unless wasEmpty or @noReturn
if @bound
@@ -1338,11 +1346,8 @@ exports.Code = class Code extends Base
return [@makeCode(@tab), answer...] if @ctor
if @front or (o.level >= LEVEL_ACCESS) then @wrapInBraces answer else answer
# A list of parameter names, excluding those generated by the compiler.
paramNames: ->
names = []
names.push param.names()... for param in @params
names
eachParamName: (iterator) ->
param.eachName iterator for param in @params
# Short-circuit `traverseChildren` method to prevent it from crossing scope boundaries
# unless `crossScope` is `true`.
@@ -1357,7 +1362,7 @@ exports.Code = class Code extends Base
exports.Param = class Param extends Base
constructor: (@name, @value, @splat) ->
if (name = @name.unwrapAll().value) in STRICT_PROSCRIBED
throw SyntaxError "parameter name \"#{name}\" is not allowed"
@name.error "parameter name \"#{name}\" is not allowed"
children: ['name', 'value']
@@ -1380,41 +1385,40 @@ exports.Param = class Param extends Base
isComplex: ->
@name.isComplex()
# Finds the name or names of a `Param`; useful for detecting duplicates.
# In a sense, a destructured parameter represents multiple JS parameters,
# thus this method returns an `Array` of names.
# Reserved words used as param names, as well as the Object and Array
# literals used for destructured params, get a compiler generated name
# during the `Code` compilation step, so this is necessarily an incomplete
# list of a parameter's names.
names: (name = @name)->
# Iterates the name or names of a `Param`.
# In a sense, a destructured parameter represents multiple JS parameters. This
# method allows to iterate them all.
# The `iterator` function will be called as `iterator(name, node)` where
# `name` is the name of the parameter and `node` is the AST node corresponding
# to that name.
eachName: (iterator, name = @name)->
atParam = (obj) ->
{value} = obj.properties[0].name
return if value.reserved then [] else [value]
node = obj.properties[0].name
iterator node.value, node unless node.value.reserved
# * simple literals `foo`
return [name.value] if name instanceof Literal
return iterator name.value, name if name instanceof Literal
# * at-params `@foo`
return atParam(name) if name instanceof Value
names = []
return atParam name if name instanceof Value
for obj in name.objects
# * assignments within destructured parameters `{foo:bar}`
if obj instanceof Assign
names.push @names(obj.value.unwrap())...
@eachName iterator, obj.value.unwrap()
# * splats within destructured parameters `[xs...]`
else if obj instanceof Splat
names.push obj.name.unwrap().value
node = obj.name.unwrap()
iterator node.value, node
else if obj instanceof Value
# * destructured parameters within destructured parameters `[{a}]`
if obj.isArray() or obj.isObject()
names.push @names(obj.base)...
@eachName iterator, obj.base
# * at-params within destructured parameters `{@foo}`
else if obj.this
names.push atParam(obj)...
atParam obj
# * simple destructured parameters {foo}
else names.push obj.base.value
else iterator obj.base.value, obj.base
else
throw SyntaxError "illegal parameter #{obj.compile()}"
names
obj.error "illegal parameter #{obj.compile()}"
return
#### Splat
@@ -1502,7 +1506,7 @@ exports.While = class While extends Base
set = ''
{body} = this
if body.isEmpty()
body = ''
body = @makeCode ''
else
if @returns
body.makeReturn rvar = o.scope.freeVariable 'results'
@@ -1556,7 +1560,7 @@ exports.Op = class Op extends Base
not @second
isComplex: ->
not (@isUnary() and (@operator in ['+', '-'])) or @first.isComplex()
not (@isUnary() and @operator in ['+', '-']) or @first.isComplex()
# Am I capable of
# [Python-style comparison chaining](http://docs.python.org/reference/expressions.html#notin)?
@@ -1615,9 +1619,9 @@ exports.Op = class Op extends Base
# as the chained expression is wrapped.
@first.front = @front unless isChain
if @operator is 'delete' and o.scope.check(@first.unwrapAll().value)
throw SyntaxError 'delete operand may not be argument or var'
@error 'delete operand may not be argument or var'
if @operator in ['--', '++'] and @first.unwrapAll().value in STRICT_PROSCRIBED
throw SyntaxError 'prefix increment/decrement may not have eval or arguments operand'
@error "cannot increment/decrement \"#{@first.unwrapAll().value}\""
return @compileUnary o if @isUnary()
return @compileChain o if isChain
return @compileExistence o if @operator is '?'
@@ -1637,8 +1641,9 @@ exports.Op = class Op extends Base
(shared.compileToFragments o), @makeCode(" #{@operator} "), (@second.compileToFragments o, LEVEL_OP)
@wrapInBraces fragments
# Keep reference to the left expression, unless this an existential assignment
compileExistence: (o) ->
if @first.isComplex()
if !o.isExistentialEquals and @first.isComplex()
ref = new Literal o.scope.freeVariable 'ref'
fst = new Parens new Assign ref, @first
else
@@ -1659,7 +1664,7 @@ exports.Op = class Op extends Base
plusMinus = op in ['+', '-']
parts.push [@makeCode(' ')] if op in ['new', 'typeof', 'delete'] or
plusMinus and @first instanceof Op and @first.operator is op
if (plusMinus && @first instanceof Op) or (op is 'new' and @first.isStatement o)
if (plusMinus and @first instanceof Op) or (op is 'new' and @first.isStatement o)
@first = new Parens @first
parts.push @first.compileToFragments o, LEVEL_OP
parts.reverse() if @flip
@@ -1699,7 +1704,7 @@ exports.In = class In extends Base
[sub, ref] = @object.cache o, LEVEL_LIST
fragments = [].concat @makeCode(utility('indexOf') + ".call("), @array.compileToFragments(o, LEVEL_LIST),
@makeCode(", "), ref, @makeCode(") " + if @negated then '< 0' else '>= 0')
return fragments if (fragmentsToText sub) is (fragmentsToText ref)
return fragments if fragmentsToText(sub) is fragmentsToText(ref)
fragments = sub.concat @makeCode(', '), fragments
if o.level < LEVEL_LIST then fragments else @wrapInBraces fragments
@@ -1710,7 +1715,7 @@ exports.In = class In extends Base
# A classic *try/catch/finally* block.
exports.Try = class Try extends Base
constructor: (@attempt, @error, @recovery, @ensure) ->
constructor: (@attempt, @errorVariable, @recovery, @ensure) ->
children: ['attempt', 'recovery', 'ensure']
@@ -1730,21 +1735,17 @@ exports.Try = class Try extends Base
tryPart = @attempt.compileToFragments o, LEVEL_TOP
catchPart = if @recovery
if @error.isObject?()
placeholder = new Literal '_error'
@recovery.unshift new Assign @error, placeholder
@error = placeholder
if @error.value in STRICT_PROSCRIBED
throw SyntaxError "catch variable may not be \"#{@error.value}\""
o.scope.add @error.value, 'param' unless o.scope.check @error.value
[].concat @makeCode(" catch ("), @error.compileToFragments(o), @makeCode(") {\n"),
placeholder = new Literal '_error'
@recovery.unshift new Assign @errorVariable, placeholder if @errorVariable
[].concat @makeCode(" catch ("), placeholder.compileToFragments(o), @makeCode(") {\n"),
@recovery.compileToFragments(o, LEVEL_TOP), @makeCode("\n#{@tab}}")
else unless @ensure or @recovery
[@makeCode(' catch (_error) {}')]
else
[]
ensurePart = if @ensure then ([].concat @makeCode(" finally {\n"), (@ensure.compileToFragments o, LEVEL_TOP), @makeCode("\n#{@tab}}")) else []
ensurePart = if @ensure then ([].concat @makeCode(" finally {\n"), @ensure.compileToFragments(o, LEVEL_TOP),
@makeCode("\n#{@tab}}")) else []
[].concat @makeCode("#{@tab}try {\n"),
tryPart,
@@ -1765,7 +1766,7 @@ exports.Throw = class Throw extends Base
makeReturn: THIS
compileNode: (o) ->
[].concat @makeCode(@tab + "throw "), (@expression.compileToFragments o), @makeCode(";")
[].concat @makeCode(@tab + "throw "), @expression.compileToFragments(o), @makeCode(";")
#### Existence
@@ -1831,11 +1832,12 @@ exports.For = class For extends While
@own = !!source.own
@object = !!source.object
[@name, @index] = [@index, @name] if @object
throw SyntaxError 'index cannot be a pattern matching expression' if @index instanceof Value
@index.error 'index cannot be a pattern matching expression' if @index instanceof Value
@range = @source instanceof Value and @source.base instanceof Range and not @source.properties.length
@pattern = @name instanceof Value
throw SyntaxError 'indexes do not apply to range loops' if @range and @index
throw SyntaxError 'cannot pattern match over range loops' if @range and @pattern
@index.error 'indexes do not apply to range loops' if @range and @index
@name.error 'cannot pattern match over range loops' if @range and @pattern
@index.error 'cannot use own with for-in' if @own and not @object
@returns = false
children: ['body', 'source', 'guard', 'step']
@@ -1962,7 +1964,7 @@ exports.Switch = class Switch extends Base
idt1 = o.indent + TAB
idt2 = o.indent = idt1 + TAB
fragments = [].concat @makeCode(@tab + "switch ("),
(if @subject then @subject.compileToFragments(o, LEVEL_PAREN) else @makeCode("false")),
(if @subject then @subject.compileToFragments(o, LEVEL_PAREN) else @makeCode "false"),
@makeCode(") {\n")
for [conditions, block], i in @cases
for cond in flatten [conditions]
@@ -2077,21 +2079,22 @@ Closure =
return expressions if expressions.jumps()
func = new Code [], Block.wrap [expressions]
args = []
if (mentionsArgs = expressions.contains @literalArgs) or expressions.contains @literalThis
if mentionsArgs and expressions.classBody
throw SyntaxError "Class bodies shouldn't reference arguments"
meth = new Literal if mentionsArgs then 'apply' else 'call'
argumentsNode = expressions.contains @isLiteralArguments
if argumentsNode and expressions.classBody
argumentsNode.error "Class bodies shouldn't reference arguments"
if argumentsNode or expressions.contains @isLiteralThis
meth = new Literal if argumentsNode then 'apply' else 'call'
args = [new Literal 'this']
args.push new Literal 'arguments' if mentionsArgs
args.push new Literal 'arguments' if argumentsNode
func = new Value func, [new Access meth]
func.noReturn = noReturn
call = new Call func, args
if statement then Block.wrap [call] else call
literalArgs: (node) ->
isLiteralArguments: (node) ->
node instanceof Literal and node.value is 'arguments' and not node.asKey
literalThis: (node) ->
isLiteralThis: (node) ->
(node instanceof Literal and node.value is 'this' and not node.asKey) or
(node instanceof Code and node.bound) or
(node instanceof Call and node.isSuper)
@@ -2114,6 +2117,11 @@ UTILITIES =
function(child, parent) { for (var key in parent) { if (#{utility 'hasProp'}.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }
"""
# Create a function bound to the current value of "this".
bind: -> '''
function(fn, me){ return function(){ return fn.apply(me, arguments); }; }
'''
# Discover if an item is in an array.
indexOf: -> """
[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }

View File

@@ -1,3 +1,5 @@
{repeat} = require './helpers'
# A simple **OptionParser** class to parse option flags from the command-line.
# Use it like so:
#
@@ -62,7 +64,7 @@ exports.OptionParser = class OptionParser
lines.unshift "#{@banner}\n" if @banner
for rule in @rules
spaces = 15 - rule.longFlag.length
spaces = if spaces > 0 then Array(spaces + 1).join(' ') else ''
spaces = if spaces > 0 then repeat ' ', spaces else ''
letPart = if rule.shortFlag then rule.shortFlag + ', ' else ' '
lines.push ' ' + letPart + rule.longFlag + spaces + rule.description
"\n#{ lines.join('\n') }\n"

View File

@@ -1,31 +1,43 @@
fs = require 'fs'
path = require 'path'
vm = require 'vm'
nodeREPL = require 'repl'
CoffeeScript = require './coffee-script'
{merge} = require './helpers'
{merge, prettyErrorMessage} = require './helpers'
replDefaults =
prompt: 'coffee> ',
historyFile: path.join process.env.HOME, '.coffee_history' if process.env.HOME
historyMaxInputSize: 10240
eval: (input, context, filename, cb) ->
# XXX: multiline hack
# XXX: multiline hack.
input = input.replace /\uFF00/g, '\n'
# strip single-line comments
input = input.replace /(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, '$1$2$3'
# empty command
return cb null if /^(\s*|\(\s*\))$/.test input
# TODO: fix #1829: pass in-scope vars and avoid accidentally shadowing them by omitting those declarations
# Node's REPL sends the input ending with a newline and then wrapped in
# parens. Unwrap all that.
input = input.replace /^\(([\s\S]*)\n\)$/m, '$1'
# Require AST nodes to do some AST manipulation.
{Block, Assign, Value, Literal} = require './nodes'
try
js = CoffeeScript.compile "_=(#{input}\n)", {filename, bare: yes}
# Generate the AST of the clean input.
ast = CoffeeScript.nodes input
# Add assignment to `_` variable to force the input to be an expression.
ast = new Block [
new Assign (new Value new Literal '_'), ast, '='
]
js = ast.compile bare: yes, locals: Object.keys(context)
cb null, vm.runInContext(js, context, filename)
catch err
cb err
cb prettyErrorMessage(err, filename, input, yes)
addMultilineHandler = (repl) ->
{rli, inputStream, outputStream} = repl
multiline =
enabled: off
initialPrompt: repl.prompt.replace(/^[^> ]*/, (x) -> x.replace /./g, '-')
prompt: repl.prompt.replace(/^[^> ]*>?/, (x) -> x.replace /./g, '.')
initialPrompt: repl.prompt.replace /^[^> ]*/, (x) -> x.replace /./g, '-'
prompt: repl.prompt.replace /^[^> ]*>?/, (x) -> x.replace /./g, '.'
buffer: ''
# Proxy node's line listener
@@ -68,10 +80,54 @@ addMultilineHandler = (repl) ->
rli.prompt true
return
# Store and load command history from a file
addHistory = (repl, filename, maxSize) ->
lastLine = null
try
# Get file info and at most maxSize of command history
stat = fs.statSync filename
size = Math.min maxSize, stat.size
# Read last `size` bytes from the file
readFd = fs.openSync filename, 'r'
buffer = new Buffer(size)
fs.readSync readFd, buffer, 0, size, stat.size - size
# Set the history on the interpreter
repl.rli.history = buffer.toString().split('\n').reverse()
# If the history file was truncated we should pop off a potential partial line
repl.rli.history.pop() if stat.size > maxSize
# Shift off the final blank newline
repl.rli.history.shift() if repl.rli.history[0] is ''
repl.rli.historyIndex = -1
lastLine = repl.rli.history[0]
fd = fs.openSync filename, 'a'
repl.rli.addListener 'line', (code) ->
if code and code.length and code isnt '.history' and lastLine isnt code
# Save the latest command in the file
fs.write fd, "#{code}\n"
lastLine = code
repl.rli.on 'exit', -> fs.close fd
# Add a command to show the history stack
repl.commands['.history'] =
help: 'Show command history'
action: ->
repl.outputStream.write "#{repl.rli.history[..].reverse().join '\n'}\n"
repl.displayPrompt()
module.exports =
start: (opts = {}) ->
[major, minor, build] = process.versions.node.split('.').map (n) -> parseInt(n)
if major is 0 and minor < 8
console.warn "Node 0.8.0+ required for CoffeeScript REPL"
process.exit 1
opts = merge replDefaults, opts
repl = nodeREPL.start opts
repl.on 'exit', -> repl.outputStream.write '\n'
addMultilineHandler repl
addHistory repl, opts.historyFile, opts.historyMaxInputSize if opts.historyFile
repl

View File

@@ -16,6 +16,7 @@ generate = (tag, value) ->
class exports.Rewriter
# Helpful snippet for debugging:
#
# console.log (t[0] + '/' + t[1] for t in @tokens).join ' '
# Rewrite the token stream in multiple passes, one logical filter at
@@ -186,9 +187,12 @@ class exports.Rewriter
return forward(1)
if tag is 'INDENT' and inImplicit()
# An INDENT closes an implicit call unless
# 1. We have seen a CONTROL argument on the line.
# 2. The last token before the indent is part of the list below
# An `INDENT` closes an implicit call unless
#
# 1. We have seen a `CONTROL` argument on the line.
# 2. The last token before the indent is part of the list below
#
if prevTag not in ['=>', '->', '[', '(', ',', '{', 'TRY', 'ELSE', '=']
endImplicitCall() while inImplicitCall()
stack.pop() if inImplicitControl()
@@ -213,7 +217,7 @@ class exports.Rewriter
# Recognize standard implicit calls like
# f a, f() b, f? c, h[0] d etc.
if (tag in IMPLICIT_FUNC and token.spaced or
if (tag in IMPLICIT_FUNC and token.spaced and not token.stringEnd or
tag is '?' and i > 0 and not tokens[i - 1].spaced) and
(nextTag in IMPLICIT_CALL or
nextTag in IMPLICIT_UNSPACED_CALL and
@@ -223,24 +227,31 @@ class exports.Rewriter
return forward(2)
# Implicit call taking an implicit indented object as first argument.
# f
# a: b
# c: d
#
# f
# a: b
# c: d
#
# and
# f
# 1
# a: b
# b: c
#
# f
# 1
# a: b
# b: c
#
# Don't accept implicit calls of this type, when on the same line
# as the control strucutures below as that may misinterpret constructs like:
# if f
# a: 1
#
# if f
# a: 1
# as
# if f(a: 1)
#
# if f(a: 1)
#
# which is probably always unintended.
# Furthermore don't allow this in literal arrays, as
# that creates grammatical ambiguities.
if @matchTags(i, IMPLICIT_FUNC, 'INDENT', null, ':') and
if tag in IMPLICIT_FUNC and @matchTags(i + 1, 'INDENT', null, ':') and
not @findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH',
'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])
startImplicitCall i + 1
@@ -266,11 +277,13 @@ class exports.Rewriter
# End implicit calls when chaining method calls
# like e.g.:
# f ->
# a
# .g b, ->
# c
# .h a
#
# f ->
# a
# .g b, ->
# c
# .h a
#
if prevTag is 'OUTDENT' and inImplicitCall() and tag in ['.', '?.', '::', '?::']
endImplicitCall()
return forward(1)
@@ -299,14 +312,16 @@ class exports.Rewriter
# Close implicit object if comma is the last character
# and what comes after doesn't look like it belongs.
# This is used for trailing commas and calls, like:
# x =
# a: b,
# c: d,
# e = 2
#
# x =
# a: b,
# c: d,
# e = 2
#
# and
#
# f a, b: c, d: e, f, g: h: i, j
# f a, b: c, d: e, f, g: h: i, j
#
if tag is ',' and not @looksObjectish(i + 1) and inImplicitObject() and
(nextTag isnt 'TERMINATOR' or not @looksObjectish(i + 2))
# When nextTag is OUTDENT the comma is insignificant and
@@ -325,13 +340,18 @@ class exports.Rewriter
@scanTokens (token, i, tokens) ->
return 1 if token[2]
return 1 unless token.generated or token.explicit
{last_line, last_column} = tokens[i - 1]?[2] ? last_line: 0, last_column: 0
if token[0] is '{' and nextLocation=tokens[i + 1]?[2]
{first_line: line, first_column: column} = nextLocation
else if prevLocation = tokens[i - 1]?[2]
{last_line: line, last_column: column} = prevLocation
else
line = column = 0
token[2] =
first_line: last_line
first_column: last_column
last_line: last_line
last_column: last_column
1
first_line: line
first_column: column
last_line: line
last_column: column
return 1
# Because our grammar is LALR(1), it can't handle some single-line
# expressions that lack ending delimiters. The **Rewriter** adds the implicit
@@ -342,7 +362,8 @@ class exports.Rewriter
condition = (token, i) ->
token[1] isnt ';' and token[0] in SINGLE_CLOSERS and
not (token[0] is 'ELSE' and starter not in ['IF', 'THEN'])
not (token[0] is 'ELSE' and starter isnt 'THEN') and
not (token[0] in ['CATCH', 'FINALLY'] and starter in ['->', '=>'])
action = (token, i) ->
@tokens.splice (if @tag(i - 1) is ',' then i - 1 else i), 0, outdent
@@ -353,15 +374,16 @@ class exports.Rewriter
tokens.splice i, 1
return 0
if tag is 'ELSE' and @tag(i - 1) isnt 'OUTDENT'
tokens.splice i, 0, @indentation(token)...
tokens.splice i, 0, @indentation()...
return 2
if tag is 'CATCH' and @tag(i + 2) in ['OUTDENT', 'TERMINATOR', 'FINALLY']
tokens.splice i + 2, 0, @indentation(token)...
return 4
if tag is 'CATCH'
for j in [1..2] when @tag(i + j) in ['OUTDENT', 'TERMINATOR', 'FINALLY']
tokens.splice i + j, 0, @indentation()...
return 2 + j
if tag in SINGLE_LINERS and @tag(i + 1) isnt 'INDENT' and
not (tag is 'ELSE' and @tag(i + 1) is 'IF')
starter = tag
[indent, outdent] = @indentation token, yes
[indent, outdent] = @indentation yes
indent.fromThen = true if starter is 'THEN'
tokens.splice i + 1, 0, indent
@detectEnd i + 2, condition, action
@@ -376,7 +398,9 @@ class exports.Rewriter
original = null
condition = (token, i) ->
token[0] in ['TERMINATOR', 'INDENT']
[tag] = token
[prevTag] = @tokens[i - 1]
tag is 'TERMINATOR' or (tag is 'INDENT' and prevTag not in SINGLE_LINERS)
action = (token, i) ->
if token[0] isnt 'INDENT' or (token.generated and not token.fromThen)
@@ -386,10 +410,10 @@ class exports.Rewriter
return 1 unless token[0] is 'IF'
original = token
@detectEnd i + 1, condition, action
1
return 1
# Generate the indentation tokens, based on another token on the same line.
indentation: (token, implicit = no) ->
indentation: (implicit = no) ->
indent = ['INDENT', 2]
outdent = ['OUTDENT', 2]
indent.generated = outdent.generated = yes if implicit
@@ -437,14 +461,11 @@ IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@
IMPLICIT_CALL = [
'IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS'
'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'SUPER'
'@', '->', '=>', '[', '(', '{', '--', '++'
'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'
]
IMPLICIT_UNSPACED_CALL = ['+', '-']
# Tokens indicating that the implicit call must enclose a block of expressions.
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ',']
# Tokens that always mark the end of an implicit call for single-liners.
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY',
'LOOP', 'TERMINATOR']

View File

@@ -1,244 +0,0 @@
# Hold data about mappings for one line of generated source code.
class LineMapping
constructor: (@generatedLine) ->
# columnMap keeps track of which columns we've already mapped.
@columnMap = {}
# columnMappings is an array of all column mappings, sorted by generated-column.
@columnMappings = []
addMapping: (generatedColumn, [sourceLine, sourceColumn], options={}) ->
if @columnMap[generatedColumn] and options.noReplace
# We already have a mapping for this column.
return
@columnMap[generatedColumn] = {
generatedLine: @generatedLine
generatedColumn
sourceLine
sourceColumn
}
@columnMappings.push @columnMap[generatedColumn]
@columnMappings.sort (a,b) -> a.generatedColumn - b.generatedColumn
getSourcePosition: (generatedColumn) ->
answer = null
lastColumnMapping = null
for columnMapping in @columnMappings
if columnMapping.generatedColumn > generatedColumn
break
else
lastColumnMapping = columnMapping
if lastColumnMapping
answer = [lastColumnMapping.sourceLine, lastColumnMapping.sourceColumn]
#### SourceMap
# Maps locations in a generated source file back to locations in the original source file.
#
# This is intentionally agnostic towards how a source map might be represented on disk. A
# SourceMap can be converted to a "v3" style sourcemap with `#generateV3SourceMap()`, for example
# but the SourceMap class itself knows nothing about v3 source maps.
class exports.SourceMap
constructor: () ->
# `generatedLines` is an array of LineMappings, one per generated line.
@generatedLines = []
# Adds a mapping to this SourceMap.
#
# `sourceLocation` and `generatedLocation` are both [line, column] arrays.
#
# If `options.noReplace` is true, then if there is already a mapping for
# the specified `generatedLine` and `generatedColumn`, this will have no effect.
addMapping: (sourceLocation, generatedLocation, options={}) ->
[generatedLine, generatedColumn] = generatedLocation
lineMapping = @generatedLines[generatedLine]
if not lineMapping
lineMapping = @generatedLines[generatedLine] = new LineMapping(generatedLine)
lineMapping.addMapping generatedColumn, sourceLocation, options
# Returns [sourceLine, sourceColumn], or null if no mapping could be found.
getSourcePosition: ([generatedLine, generatedColumn]) ->
answer = null
lineMapping = @generatedLines[generatedLine]
if not lineMapping
# TODO: Search backwards for the line?
else
answer = lineMapping.getSourcePosition generatedColumn
answer
# `fn` will be called once for every recorded mapping, in the order in
# which they occur in the generated source. `fn` will be passed an object
# with four properties: sourceLine, sourceColumn, generatedLine, and
# generatedColumn.
forEachMapping: (fn) ->
for lineMapping, generatedLineNumber in @generatedLines
if lineMapping
for columnMapping in lineMapping.columnMappings
fn(columnMapping)
#### generateV3SourceMap
# Builds a V3 source map from a SourceMap object.
# Returns the generated JSON as a string.
exports.generateV3SourceMap = (sourceMap, sourceFile=null, generatedFile=null) ->
writingGeneratedLine = 0
lastGeneratedColumnWritten = 0
lastSourceLineWritten = 0
lastSourceColumnWritten = 0
needComma = no
mappings = ""
sourceMap.forEachMapping (mapping) ->
while writingGeneratedLine < mapping.generatedLine
lastGeneratedColumnWritten = 0
needComma = no
mappings += ";"
writingGeneratedLine++
# Write a comma if we've already written a segment on this line.
if needComma
mappings += ","
needComma = no
# Write the next segment.
# Segments can be 1, 4, or 5 values. If just one, then it is a generated column which
# doesn't match anything in the source code.
#
# Fields are all zero-based, and relative to the previous occurence unless otherwise noted:
# * starting-column in generated source, relative to previous occurence for the current line.
# * index into the "sources" list
# * starting line in the original source
# * starting column in the original source
# * index into the "names" list associated with this segment.
# Add the generated start-column
mappings += exports.vlqEncodeValue(mapping.generatedColumn - lastGeneratedColumnWritten)
lastGeneratedColumnWritten = mapping.generatedColumn
# Add the index into the sources list
mappings += exports.vlqEncodeValue(0)
# Add the source start-line
mappings += exports.vlqEncodeValue(mapping.sourceLine - lastSourceLineWritten)
lastSourceLineWritten = mapping.sourceLine
# Add the source start-column
mappings += exports.vlqEncodeValue(mapping.sourceColumn - lastSourceColumnWritten)
lastSourceColumnWritten = mapping.sourceColumn
# TODO: Do we care about symbol names for CoffeeScript? Probably not.
needComma = yes
answer = {
version: 3
file: generatedFile
sourceRoot: ""
sources: if sourceFile then [sourceFile] else []
names: []
mappings
}
return JSON.stringify answer, null, 2
# Load a SourceMap from a JSON string. Returns the SourceMap object.
exports.loadV3SourceMap = (sourceMap) ->
todo()
#### Base64 encoding helpers
BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
MAX_BASE64_VALUE = BASE64_CHARS.length - 1
encodeBase64Char = (value) ->
if value > MAX_BASE64_VALUE
throw new Error "Cannot encode value #{value} > #{MAX_BASE64_VALUE}"
else if value < 0
throw new Error "Cannot encode value #{value} < 0"
BASE64_CHARS[value]
decodeBase64Char = (char) ->
value = BASE64_CHARS.indexOf char
if value == -1
throw new Error "Invalid Base 64 character: #{char}"
value
#### Base 64 VLQ encoding/decoding helpers
# Note that SourceMap VLQ encoding is "backwards". MIDI style VLQ encoding puts the
# most-significant-bit (MSB) from the original value into the MSB of the VLQ encoded value
# (see http://en.wikipedia.org/wiki/File:Uintvar_coding.svg). SourceMap VLQ does things
# the other way around, with the least significat four bits of the original value encoded
# into the first byte of the VLQ encoded value.
VLQ_SHIFT = 5
VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT # 0010 0000
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1 # 0001 1111
# Encode a value as Base 64 VLQ.
exports.vlqEncodeValue = (value) ->
# Least significant bit represents the sign.
signBit = if value < 0 then 1 else 0
# Next bits are the actual value
valueToEncode = (Math.abs(value) << 1) + signBit
answer = ""
# Make sure we encode at least one character, even if valueToEncode is 0.
while valueToEncode || !answer
nextVlqChunk = valueToEncode & VLQ_VALUE_MASK
valueToEncode = valueToEncode >> VLQ_SHIFT
if valueToEncode
nextVlqChunk |= VLQ_CONTINUATION_BIT
answer += encodeBase64Char(nextVlqChunk)
return answer
# Decode a Base 64 VLQ value.
#
# Returns `[value, consumed]` where `value` is the decoded value, and `consumed` is the number
# of characters consumed from `str`.
exports.vlqDecodeValue = (str, offset=0) ->
position = offset
done = false
value = 0
continuationShift = 0
while !done
nextVlqChunk = decodeBase64Char(str[position])
position += 1
nextChunkValue = nextVlqChunk & VLQ_VALUE_MASK
value += (nextChunkValue << continuationShift)
if !(nextVlqChunk & VLQ_CONTINUATION_BIT)
# We'll be done after this character.
done = true
# Bits are encoded least-significant first (opposite of MIDI VLQ). Increase the
# continuationShift, so the next byte will end up where it should in the value.
continuationShift += VLQ_SHIFT
consumed = position - offset
# Least significant bit represents the sign.
signBit = value & 1
value = value >> 1
if signBit then value = -value
return [value, consumed]

180
src/sourcemap.litcoffee Normal file
View File

@@ -0,0 +1,180 @@
Source maps allow JavaScript runtimes to match running JavaScript back to
the original source code that corresponds to it. This can be minified
JavaScript, but in our case, we're concerned with mapping pretty-printed
JavaScript back to CoffeeScript.
In order to produce maps, we must keep track of positions (line number, column number)
that originated every node in the syntax tree, and be able to generate a
[map file](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit)
— which is a compact, VLQ-encoded representation of the JSON serialization
of this information — to write out alongside the generated JavaScript.
LineMap
-------
A **LineMap** object keeps track of information about original line and column
positions for a single line of output JavaScript code.
**SourceMaps** are implemented in terms of **LineMaps**.
class LineMap
constructor: (@line) ->
@columns = []
add: (column, [sourceLine, sourceColumn], options={}) ->
return if @columns[column] and options.noReplace
@columns[column] = {line: @line, column, sourceLine, sourceColumn}
sourceLocation: (column) ->
column-- until (mapping = @columns[column]) or (column <= 0)
mapping and [mapping.sourceLine, mapping.sourceColumn]
SourceMap
---------
Maps locations in a single generated JavaScript file back to locations in
the original CoffeeScript source file.
This is intentionally agnostic towards how a source map might be represented on
disk. Once the compiler is ready to produce a "v3"-style source map, we can walk
through the arrays of line and column buffer to produce it.
class SourceMap
constructor: ->
@lines = []
Adds a mapping to this SourceMap. `sourceLocation` and `generatedLocation`
are both `[line, column]` arrays. If `options.noReplace` is true, then if there
is already a mapping for the specified `line` and `column`, this will have no
effect.
add: (sourceLocation, generatedLocation, options = {}) ->
[line, column] = generatedLocation
lineMap = (@lines[line] or= new LineMap(line))
lineMap.add column, sourceLocation, options
Look up the original position of a given `line` and `column` in the generated
code.
sourceLocation: ([line, column]) ->
line-- until (lineMap = @lines[line]) or (line <= 0)
lineMap and lineMap.sourceLocation column
V3 SourceMap Generation
-----------------------
Builds up a V3 source map, returning the generated JSON as a string.
`options.sourceRoot` may be used to specify the sourceRoot written to the source
map. Also, `options.sourceFiles` and `options.generatedFile` may be passed to
set "sources" and "file", respectively.
generate: (options = {}, code = null) ->
writingline = 0
lastColumn = 0
lastSourceLine = 0
lastSourceColumn = 0
needComma = no
buffer = ""
for lineMap, lineNumber in @lines when lineMap
for mapping in lineMap.columns when mapping
while writingline < mapping.line
lastColumn = 0
needComma = no
buffer += ";"
writingline++
Write a comma if we've already written a segment on this line.
if needComma
buffer += ","
needComma = no
Write the next segment. Segments can be 1, 4, or 5 values. If just one, then it
is a generated column which doesn't match anything in the source code.
The starting column in the generated source, relative to any previous recorded
column for the current line:
buffer += @encodeVlq mapping.column - lastColumn
lastColumn = mapping.column
The index into the list of sources:
buffer += @encodeVlq 0
The starting line in the original source, relative to the previous source line.
buffer += @encodeVlq mapping.sourceLine - lastSourceLine
lastSourceLine = mapping.sourceLine
The starting column in the original source, relative to the previous column.
buffer += @encodeVlq mapping.sourceColumn - lastSourceColumn
lastSourceColumn = mapping.sourceColumn
needComma = yes
Produce the canonical JSON object format for a "v3" source map.
v3 =
version: 3
file: options.generatedFile or ''
sourceRoot: options.sourceRoot or ''
sources: options.sourceFiles or ['']
names: []
mappings: buffer
v3.sourcesContent = [code] if options.inline
JSON.stringify v3, null, 2
Base64 VLQ Encoding
-------------------
Note that SourceMap VLQ encoding is "backwards". MIDI-style VLQ encoding puts
the most-significant-bit (MSB) from the original value into the MSB of the VLQ
encoded value (see [Wikipedia](http://en.wikipedia.org/wiki/File:Uintvar_coding.svg)).
SourceMap VLQ does things the other way around, with the least significat four
bits of the original value encoded into the first byte of the VLQ encoded value.
VLQ_SHIFT = 5
VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT # 0010 0000
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1 # 0001 1111
encodeVlq: (value) ->
answer = ''
# Least significant bit represents the sign.
signBit = if value < 0 then 1 else 0
# The next bits are the actual value.
valueToEncode = (Math.abs(value) << 1) + signBit
# Make sure we encode at least one character, even if valueToEncode is 0.
while valueToEncode or not answer
nextChunk = valueToEncode & VLQ_VALUE_MASK
valueToEncode = valueToEncode >> VLQ_SHIFT
nextChunk |= VLQ_CONTINUATION_BIT if valueToEncode
answer += @encodeBase64 nextChunk
answer
Regular Base64 Encoding
-----------------------
BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
encodeBase64: (value) ->
BASE64_CHARS[value] or throw new Error "Cannot Base64 encode value: #{value}"
Our API for source maps is just the `SourceMap` class.
module.exports = SourceMap

View File

@@ -337,6 +337,18 @@ test "#2502: parenthesizing inner object values", ->
eq (new A).sections.default, 0
test "conditional prototype property assignment", ->
debug = false
class Person
if debug
age: -> 10
else
age: -> 20
eq (new Person).age(), 20
test "mild metaprogramming", ->
class Base
@@ -730,13 +742,52 @@ test "#2359: extending native objects that use other typed constructors requires
eq 'yes!', workingArray.method()
test "#2489: removing __bind", ->
test "#2782: non-alphanumeric-named bound functions", ->
class A
'b:c': =>
'd'
class Thing
foo: (a, b, c) ->
bar: (a, b, c) =>
eq (new A)['b:c'](), 'd'
thing = new Thing
eq thing.foo.length, 3
eq thing.bar.length, 3
test "#2781: overriding bound functions", ->
class A
a: ->
@b()
b: =>
1
class B extends A
b: =>
2
b = (new A).b
eq b(), 1
b = (new B).b
eq b(), 2
test "#2791: bound function with destructured argument", ->
class Foo
method: ({a}) => 'Bar'
eq (new Foo).method({a: 'Bar'}), 'Bar'
test "#2796: ditto, ditto, ditto", ->
answer = null
outsideMethod = (func) ->
func.call message: 'wrong!'
class Base
constructor: ->
@message = 'right!'
outsideMethod @echo
echo: =>
answer = @message
new Base
eq answer, 'right!'

15
test/cluster.coffee Normal file
View File

@@ -0,0 +1,15 @@
# Cluster Module
# ---------
return if testingBrowser?
cluster = require 'cluster'
if cluster.isMaster
test "#2737 - cluster module can spawn workers from a coffeescript process", ->
cluster.once 'exit', (worker, code) ->
eq code, 0
cluster.fork()
else
process.exit 0

Some files were not shown because too many files have changed in this diff Show More