Compare commits

...

659 Commits
0.1.0 ... 0.5.2

Author SHA1 Message Date
Jeremy Ashkenas
05d95acfc3 docs for CoffeeScript 0.5.2, which is now out. 2010-02-25 00:26:59 -05:00
Jeremy Ashkenas
22674bc536 removing CoffeeScript.activate() simply including the tag will do for text/coffeescript 2010-02-24 23:57:39 -05:00
Jeremy Ashkenas
23c5ebb00f call it 'CoffeeScript' in the command_line, so that --run scripts may access it as such 2010-02-24 22:30:22 -05:00
Jeremy Ashkenas
c14869f008 implementing the inline javascript in the documentation page in text/coffeescript, switching from the closure compiler to the yui compressor for building the browser version -- the closure compiler had a bug for our input -- fixable by hand but not worth the tiny savings 2010-02-24 20:41:56 -05:00
Jeremy Ashkenas
c1427d6558 adding a minified combined coffee-script.js. Include it on the page, after any text/coffeescript tags, and call CoffeeScript.activate(); to run it 2010-02-24 19:57:29 -05:00
Jeremy Ashkenas
2a46e13d33 moving print_tokens (the pretty printer) from coffee_script to command_line 2010-02-24 18:56:32 -05:00
Jeremy Ashkenas
b26e577244 adding documentation for --stdio 2010-02-24 18:27:10 -05:00
Jeremy Ashkenas
9f8710b631 adding compilation over stdin/stdout. Use --stdio or -s, and pipe away. 2010-02-24 18:18:29 -05:00
Jeremy Ashkenas
aba8cb1b08 upgrading the optparse library to avoid having to register callbacks for each argument. It just returns a simple options hash. 2010-02-24 17:57:58 -05:00
Jeremy Ashkenas
92cd80226c bumping to 0.5.1 2010-02-24 00:54:07 -05:00
Jeremy Ashkenas
10d335ccb1 adding existence soaks for indexed-lookup property accesses: obj?['property'] 2010-02-24 00:06:01 -05:00
Jeremy Ashkenas
4eeb8c4bd2 adding conditional while loops with while ... when 2010-02-23 22:53:43 -05:00
Jeremy Ashkenas
4d146bacb1 fixing throwing an error string in the Rewriter, when it should have been an Error object 2010-02-23 21:59:29 -05:00
Jeremy Ashkenas
7de4caffca removing a shift-reduce error from the grammar that worked its way in 2010-02-23 21:22:28 -05:00
Jeremy Ashkenas
8db0cb9fa5 rebuilding with new for spacing 2010-02-23 21:12:44 -05:00
Jeremy Ashkenas
c30b3d3c48 updating to the latest Jison 2010-02-23 21:03:05 -05:00
Jeremy Ashkenas
52db4fbf8c merging Tim-Smart's branch 2010-02-23 20:52:03 -05:00
Jeremy Ashkenas
5cd8f2c52c Merge branch 'master' of git://github.com/Tim-Smart/coffee-script 2010-02-23 20:51:29 -05:00
Jeremy Ashkenas
5a1aa44393 going back to == undefined instead of == null to appease the angry JSLint. 2010-02-22 22:19:17 -05:00
Tim
432696d6eb nodes.coffee: ForNode: Small whitespace change in for_part 2010-02-22 20:19:00 -07:00
Jeremy Ashkenas
3df7bd98f4 fixing issue 196, better handling of soak/existence chains 2010-02-22 22:11:47 -05:00
Jeremy Ashkenas
1f870911c9 Merge branch 'master' of git://github.com/cehoffman/coffee-script 2010-02-22 20:28:41 -05:00
Jeremy Ashkenas
4bb9392753 adding warning about Node.js/Windows to the docs. 2010-02-22 20:25:15 -05:00
Chris Hoffman
fdffacfb40 Make trailing else on switch fix pass on to multiple when switches 2010-02-22 19:17:54 -06:00
Jeremy Ashkenas
a64afe6162 fixing the trailing-else-in-switch-getting-sucked-in-bug, Issue 195. 2010-02-22 19:22:09 -05:00
Jeremy Ashkenas
15b86a5f7a doc updates 2010-02-22 17:14:51 -05:00
Jeremy Ashkenas
9b78fb67cf allowing checked out versions of the source to use bin/cake and bin/coffee from any directory. 2010-02-22 09:12:52 -05:00
Jeremy Ashkenas
4817b96bac fixing the build:ultraviolet task in the Cakefile 2010-02-22 09:09:35 -05:00
Jeremy Ashkenas
6985802eb3 making the docs a little less jumpy with more stable menus 2010-02-21 23:29:31 -05:00
Jeremy Ashkenas
aad0ce162d ensuring that we don't write --eval scriptlets out to disk -- they should print, if nothing else 2010-02-21 22:41:19 -05:00
Chris Hoffman
f582b73035 Keep the correct state for watching files so the appropriate one is recompiled 2010-02-21 19:00:48 -06:00
Jeremy Ashkenas
e795f41bd2 wrapping up loose ends for 0.5.0 2010-02-21 19:28:12 -05:00
Jeremy Ashkenas
5d541232ef adding /usr/local/lib hardcoded versions of coffee and cake for the install script 2010-02-21 19:19:58 -05:00
Jeremy Ashkenas
07513ba928 documentation for Cake and Cakefiles 2010-02-21 18:37:52 -05:00
Jeremy Ashkenas
aded80c101 list padding for the docs 2010-02-21 17:59:17 -05:00
Jeremy Ashkenas
5d893947ea new version of the docs for 0.5.0 is done, or close to it. 2010-02-21 17:30:41 -05:00
Jeremy Ashkenas
535cf28220 one more documentation waypoint, now with running for Try CoffeeScript, and a recompiled Underscore.coffee -- wordsmithing next 2010-02-21 16:36:34 -05:00
Jeremy Ashkenas
dbe5328c33 removing the 'var' declaration from arguments-to-array conversions 2010-02-21 16:15:01 -05:00
Jeremy Ashkenas
6e15a4da0e waypoint on new coffeescript docs --they're coming along nicely 2010-02-21 16:13:09 -05:00
Jeremy Ashkenas
fc51f0ef6c first working draft of the new documentation 2010-02-21 14:30:21 -05:00
Jeremy Ashkenas
1f2c8df5fa updating to latest Node (0.1.3) API -- callbacks, not promises 2010-02-21 14:06:01 -05:00
Jeremy Ashkenas
bea40a7a92 re-enabling the --no-wrap flag, and cleaning up an unused method in command_line 2010-02-21 13:48:38 -05:00
Jeremy Ashkenas
f679590bef rengenerating documentation 2010-02-21 11:46:24 -05:00
Jeremy Ashkenas
bd61131f5c regenerating documentation 2010-02-21 11:45:03 -05:00
Jeremy Ashkenas
ff25361896 removing the build:parser -> build dependency in the Cakefile -- the asynchrony was breaking it anyway 2010-02-21 11:40:52 -05:00
Jeremy Ashkenas
08dcc7e107 removing commented-out parseerror 2010-02-21 11:22:49 -05:00
Jeremy Ashkenas
b027b5cf0d Allowing @[property] syntax. 2010-02-20 20:09:52 -05:00
Jeremy Ashkenas
0f2a2ee11e Improving soaks to avoid uncessesary parentheses. 2010-02-20 20:00:07 -05:00
Jeremy Ashkenas
a93229b14d fixing an off-by-one error in Splat compilation 2010-02-20 18:25:36 -05:00
Jeremy Ashkenas
2d3f6b80c1 Revert "fixing api changes (no more promises) for node v.0.1.29"
This reverts commit 9503ea3040.
2010-02-20 18:12:09 -05:00
alunny
9503ea3040 fixing api changes (no more promises) for node v.0.1.29 2010-02-20 14:45:16 -08:00
Jeremy Ashkenas
08539a156e merging cehoffman/master 2010-02-19 18:30:47 -05:00
Jeremy Ashkenas
b183b091ee removing redundant compile from command_line.coffee 2010-02-19 18:29:24 -05:00
Jeremy Ashkenas
c39415da44 using the new fs.writeFile API instead of fs.open -- much, much nicer 2010-02-19 18:27:50 -05:00
Chris Hoffman
2c461f6474 Simpler write method that assumes utf8 output like input reading does 2010-02-19 16:03:37 -06:00
Chris Hoffman
e213964793 No need to recompile the script for writing 2010-02-19 16:02:58 -06:00
Jeremy Ashkenas
dd753d3b78 Removing the notion of a ThisNode so that we don't have to worry about the special cases. Fixes Issue 180 2010-02-19 07:51:52 -05:00
Jeremy Ashkenas
45c0d4c2ea fixing standalone @ references 2010-02-18 21:50:42 -05:00
Jeremy Ashkenas
4f89f90dab adding syntax highlighting for standalone @ts 2010-02-18 21:32:54 -05:00
Jeremy Ashkenas
0270e48a01 using '== null' to check for soaked accessor chains instead of '== undefined' -- shorter, and slightly safer 2010-02-18 21:04:41 -05:00
Jeremy Ashkenas
a278d8f018 adding an extra pair of braces to the code produced by object comprehensions, so as to squeak by in JSLint's good graces 2010-02-18 20:22:53 -05:00
Jeremy Ashkenas
d4a180c413 carefully categorizing JS keywords from JS reserved words from Coffee keywords, so that we can throw syntax errors at compile time if JS keywords are getting assigned to. 2010-02-18 20:09:41 -05:00
Jeremy Ashkenas
28a8c05513 light refactor for repl.coffee 2010-02-17 23:51:43 -05:00
Jeremy Ashkenas
879b3d76bd light refactors to scope.coffee 2010-02-17 23:37:39 -05:00
Jeremy Ashkenas
138692183b removing the 'remote' parameter from Scope::find -- it wasn't used anymore 2010-02-17 23:26:03 -05:00
Jeremy Ashkenas
95f3e2f79f just namespacing the coffeescript compiler 2010-02-17 23:25:17 -05:00
Jeremy Ashkenas
dec9950649 Revert "namespacing CoffeeScript in the browser, and sniffing the 'require' function instead of the 'exports' object"
This reverts commit 2f6b69b580.
2010-02-17 23:22:05 -05:00
Jeremy Ashkenas
2f6b69b580 namespacing CoffeeScript in the browser, and sniffing the 'require' function instead of the 'exports' object 2010-02-17 23:15:37 -05:00
Jeremy Ashkenas
ff1fd97924 removing traces of Ruby from coffee-script.coffee, redoing narwhal support to use the new compiler (but untested) 2010-02-17 22:37:56 -05:00
Jeremy Ashkenas
87e60dccf0 starting to cache fancy switch values -- fixing issue #171 2010-02-17 21:23:59 -05:00
Jeremy Ashkenas
8ff977dc65 making 'no such task' errors a little nicer 2010-02-17 20:37:30 -05:00
Jeremy Ashkenas
fbfa12c733 moving 'throw' to a slightly higher level of precedence 2010-02-17 19:35:34 -05:00
Jeremy Ashkenas
6a45d25777 adding a test for parenthesized throws 2010-02-17 19:29:37 -05:00
Jeremy Ashkenas
2b5d596e10 allowing parenthetical nodes to wrap statements without necessarily expression-izing them -- tests are passing ... we'll see how this works in practice. 2010-02-17 19:19:51 -05:00
Jeremy Ashkenas
e2a71d3c2c removing the '--' from /usr/bin/env node, until we can find a workaround for linux. 2010-02-17 19:05:22 -05:00
Jeremy Ashkenas
807e0b479d add a note about installing Node.js first 2010-02-17 10:29:13 -05:00
Jeremy Ashkenas
dfa63839bb Updating fs module to the latest Node.js -- that's fs.readFile, not fs.cat, with string flags for fs.open 2010-02-17 08:51:27 -05:00
Jeremy Ashkenas
0490cb2920 added experimental (but working) method to install CoffeeScript: 'sudo bin/cake install' -- once you've done that, you can take cake and coffee out of their bin/ 2010-02-17 01:24:02 -05:00
Jeremy Ashkenas
2d0ad73af8 reorganizing lib/coffee_script to plain ol' lib 2010-02-17 00:55:56 -05:00
Jeremy Ashkenas
5a81fcd42e we don't need relative require's because the paths are set up correctly -- removing the unused runner.coffee script 2010-02-17 00:50:08 -05:00
Jeremy Ashkenas
6446e0004c The Great Purge. Removing the Ruby compiler, and all of its accoutrements. bin/coffee is now CoffeeScript-in-CoffeeScript 2010-02-17 00:33:55 -05:00
Jeremy Ashkenas
edf5f4947e removing all tasks from the Rakefile except for 'doc' ... we might need to keep that around for a while 2010-02-17 00:26:03 -05:00
Jeremy Ashkenas
b674163a40 adding build:ultraviolet and build:underscore tasks to the Cakefile 2010-02-17 00:22:06 -05:00
Jeremy Ashkenas
9f2badb3e9 got a really nice --watch flag for bin/node_coffee going, thanks to Node.js' process.watchFile. Can be used with --print, --lint, --tokens, --run, or whatever your needs may be 2010-02-16 23:59:32 -05:00
Jeremy Ashkenas
0610e20a3c fixing the extends keyword when the expressions are complex, and should only be run once -- not that it's good style -- ticket #143 2010-02-16 23:23:43 -05:00
Jeremy Ashkenas
bedc005d67 Adding a CoffeeScript equivalent to Rake/Make/Jake (Cake, naturally), and implementing all of our build and test tasks in the Cakefile. Run bin/cake to see the tasks. 2010-02-16 20:42:10 -05:00
Jeremy Ashkenas
a8a46257ae finished converting the test suite, to run it, do: bin/node_coffee -r tasks.coffee -- test 2010-02-16 19:45:25 -05:00
Jeremy Ashkenas
b41afe79b4 removed ruby tests, and started the process of converting the CoffeeScript tests over to use Node's assert() module 2010-02-16 19:38:52 -05:00
Jeremy Ashkenas
448ed36cd2 got a build script for rebuilding the compiler, too 2010-02-16 19:17:57 -05:00
Jeremy Ashkenas
c4d19cd1fa removing underscore.js from lib, and from the docs page 2010-02-16 18:39:31 -05:00
Jeremy Ashkenas
495ca64c46 removing underscore as a dependency for nodes.coffee -- let's be minimal 2010-02-16 18:38:03 -05:00
Jeremy Ashkenas
0f2cf552e9 using node's process.compile for better filename reporting on errors 2010-02-16 18:16:58 -05:00
Jeremy Ashkenas
f6a1f16146 Merge branch 'master' of git://github.com/olsonjeffery/coffee-script 2010-02-16 18:06:29 -05:00
Jeremy Ashkenas
db6bc0ba02 Implementing sethaurus' suggestion for better temp variable names -- getting rid of the numbers. 2010-02-16 18:00:40 -05:00
Jeremy Ashkenas
e4bb6c91e7 adding the list of javascript reserved words as syntax errors in CoffeeScript, so that no one uses them accidentally. 2010-02-16 17:41:38 -05:00
Jeremy Ashkenas
561a02c35f updating rewrite rules for jots multiline function case 2010-02-16 14:56:17 -05:00
Jeremy Ashkenas
51e80484e2 fixing an overzealous access in the rewriter 2010-02-16 10:12:40 -05:00
Jeremy Ashkenas
79fa4723ab use a temp var for range expansion, instead of 'i' 2010-02-16 08:58:29 -05:00
Jeremy Ashkenas
a3c8c0b492 allowing keywords as identifiers, when used as identifiers, because we've got more keywords than JavaScript does. 2010-02-16 08:43:58 -05:00
Jeremy Ashkenas
2f389f1d51 beginnings of a build script 2010-02-16 01:04:48 -05:00
Jeffery Olson
85e5dffad5 adding updated coffee.vim syntax file 2010-02-15 21:32:15 -08:00
Jeremy Ashkenas
fa63288f52 fixed the while-loop-condition-with-implicit-function-call bug 2010-02-15 23:05:54 -05:00
Jeremy Ashkenas
4ea8be8e0b switched from alphabetical __a __b temporary variables, to numeric _1, _2, which will be shorter in most cases 2010-02-15 21:55:57 -05:00
Jeremy Ashkenas
48c501a7a2 print_tokens should acutally, y'know, print 2010-02-15 20:46:36 -05:00
Jeremy Ashkenas
63c2b2bc64 adding paren wrappers for property accesses directly on object literals 2010-02-15 19:13:08 -05:00
Jeremy Ashkenas
639be2ff09 updating for Node.js' change from 'posix' to 'fs' 2010-02-15 19:08:14 -05:00
Jeremy Ashkenas
8b1b3ea402 updating docs with #coffeescript channel 2010-02-15 18:58:27 -05:00
Jeremy Ashkenas
9c3040b704 moving print_tokens into the actual coffee-script module, so we can use it separately from the command-line 2010-02-15 18:09:01 -05:00
Jeremy Ashkenas
e7291f57ba fixing allowing empty functions like () -> 2010-02-15 18:03:00 -05:00
Jeremy Ashkenas
3f6eceac77 whoops, screwed up the definition order in the inheritance example 2010-02-15 13:55:28 -05:00
Jeremy Ashkenas
ba7a454f92 adding a note to the docs about colon/equals equality 2010-02-15 13:43:35 -05:00
Jeremy Ashkenas
3092d74a08 updating the readme with a warning about the self-compiler 2010-02-14 23:40:18 -05:00
Jeremy Ashkenas
ff8e0c9751 added hugs' webserver example 2010-02-14 23:20:53 -05:00
Jeremy Ashkenas
3e518e3cf9 fixing long-flag-with-optional-part in optparse.coffee, and hiding bin/node_coffee --watch until we implement it 2010-02-14 20:50:45 -05:00
Jeremy Ashkenas
7667e16732 implementing grayrest's suggested cleanup for object comprehensions 2010-02-14 17:35:14 -05:00
Jeremy Ashkenas
e110042275 updated the rewriter to use @prop instead of this.prop -- compiled JS doesn't change 2010-02-14 16:09:11 -05:00
Jeremy Ashkenas
06677b0545 update the highlighted underscore to 0.5.8 2010-02-14 16:04:10 -05:00
Jeremy Ashkenas
20d105ba4e rename the repl id to try_coffe 2010-02-14 15:41:08 -05:00
Jeremy Ashkenas
e77f4f61aa removing the vendored optparse in favor of a pure-coffeescript optparse library 2010-02-14 15:16:33 -05:00
Jeremy Ashkenas
9de729e825 enabling the --eval option for the self-compiler 2010-02-13 23:27:13 -05:00
Jeremy Ashkenas
c39c2e3599 that's max-height 2010-02-13 19:14:28 -05:00
Jeremy Ashkenas
ecfa212189 updating Jison 2010-02-13 18:19:59 -05:00
Jeremy Ashkenas
97fd126a7f the improved error messages are still-to-be-improved 2010-02-13 16:28:07 -05:00
Jeremy Ashkenas
844c756940 working 'Try CoffeeScript' in the docs 2010-02-13 16:23:03 -05:00
Jeremy Ashkenas
a90bf75395 got coffeescript compiling in the browser 2010-02-13 15:25:04 -05:00
Jeremy Ashkenas
79bb0da153 add a -- to let us parse our own flags 2010-02-13 10:45:05 -05:00
Jeremy Ashkenas
c88b1f6a15 got the CoffeeScript-in-CoffeeScript REPL running, and boy is she fast 2010-02-13 10:27:18 -05:00
Jeremy Ashkenas
b224d58a36 don't make the command-line so OOP-y -- it's just a script 2010-02-13 10:16:28 -05:00
Jeremy Ashkenas
7d348b5eae display the usage message when called without arguments 2010-02-13 10:07:59 -05:00
Jeremy Ashkenas
02ac3edebf Nicer-looking --tokenize, more in line with what Ruby's doing 2010-02-13 09:59:13 -05:00
Jeremy Ashkenas
4bad3e0f4f nicer --tree printing, with values inlines to the right 2010-02-13 09:51:52 -05:00
Jeremy Ashkenas
8147ef554a after correctly recording objectnode's children, bin/node_coffee --tree is working pretty nicely 2010-02-13 09:46:07 -05:00
Jeremy Ashkenas
785c4fb5a0 recording else_body as a child of IfNode, when added after the face 2010-02-13 09:44:12 -05:00
Jeremy Ashkenas
13b2dc8d31 subtle bug in the order of the rewriter rules was causing some if/else chains to get confused by implicit indentation 2010-02-13 09:39:25 -05:00
Jeremy Ashkenas
a62923ff97 use Underscore's flatten -- start to make a nicer tree printer 2010-02-13 09:13:50 -05:00
Jeremy Ashkenas
dd6be80fca Use _.extend instead of the hand-rolled merge 2010-02-13 08:50:29 -05:00
Jeremy Ashkenas
8c077f0f65 using underscore's clone() for code generation 2010-02-13 02:32:17 -05:00
Jeremy Ashkenas
2c4c4cc93e using Underscore's compact in the code generation, insstead of our home-rolled one. 2010-02-13 02:30:47 -05:00
Jeremy Ashkenas
1ab3b183a8 Using underscore for an any() function. 2010-02-13 02:29:37 -05:00
Jeremy Ashkenas
e6a53bd852 fixing the lexer for indented files 2010-02-13 02:16:31 -05:00
Jeremy Ashkenas
b983b3fcdc moving Underscore.coffee from /examples to /src 2010-02-13 02:05:00 -05:00
Jeremy Ashkenas
89cac4071e updating underscore.coffee to 0.5.8 2010-02-13 02:03:48 -05:00
Jeremy Ashkenas
506ea8aa52 adding an if/else/chain test 2010-02-13 02:00:39 -05:00
Jeremy Ashkenas
b965fcf32d The moment of truth: CoffeeScript has now compiled itself ten times over. 2010-02-13 01:13:08 -05:00
Jeremy Ashkenas
126f6c2d88 use parseInt to make octal numbers to keep JSLint happy 2010-02-13 01:04:53 -05:00
Jeremy Ashkenas
3dc456572b finally, think we have this if/else/if/else/else thing licke 2010-02-13 01:02:10 -05:00
Jeremy Ashkenas
0f26072ad0 alright, really fixing the comments this time 2010-02-13 00:28:16 -05:00
Jeremy Ashkenas
dc9cec2611 fixing object/comment printing 2010-02-13 00:24:26 -05:00
Jeremy Ashkenas
c9aeae757b pulling the lexer and rewriter updates without the grammar change 2010-02-13 00:15:34 -05:00
Jeremy Ashkenas
094c2682bd Revert "one more bit to pass -- futzing with the if/else chains"
This reverts commit 066ee52615.
2010-02-13 00:11:14 -05:00
Jeremy Ashkenas
066ee52615 one more bit to pass -- futzing with the if/else chains 2010-02-12 23:35:03 -05:00
Jeremy Ashkenas
ee1c9b284a typo 2010-02-12 23:10:51 -05:00
Jeremy Ashkenas
d9fba94983 added coffee --lint to the self-compiler's resume 2010-02-12 23:09:57 -05:00
Jeremy Ashkenas
e02bedcf82 adding the ability to write out compiled coffeescript to the command line 2010-02-12 22:59:21 -05:00
Jeremy Ashkenas
1552470413 Happy Birthday, CoffeeScript-in-CoffeeScript, you just passed the entire test suite. 2010-02-12 22:24:57 -05:00
Jeremy Ashkenas
e2f3c2259b fix prototype_access lexing 2010-02-12 22:21:22 -05:00
Jeremy Ashkenas
249bd99656 fixing if/else rules 2010-02-12 22:16:26 -05:00
Jeremy Ashkenas
b36196286a safer lexing for ruby, too 2010-02-12 21:06:00 -05:00
Jeremy Ashkenas
b21780b738 safer lexing at the start of the files 2010-02-12 21:04:33 -05:00
Jeremy Ashkenas
207ec81821 waypoint ... somethings still a little off with the parser 2010-02-12 19:45:20 -05:00
Jeremy Ashkenas
d61aaf393a little further 2010-02-12 17:31:23 -05:00
Jeremy Ashkenas
19c44c9b62 self-compiling the arguments test 2010-02-12 16:44:29 -05:00
Jeremy Ashkenas
4deabf5e01 passing the funky comment test 2010-02-12 16:26:28 -05:00
Jeremy Ashkenas
1a6194e9f0 self-compiling switch statements 2010-02-12 16:23:52 -05:00
Jeremy Ashkenas
156a0b13d9 self-compiling closures as expressions 2010-02-12 14:26:01 -05:00
Jeremy Ashkenas
61a7f7a567 self-compiling the existential operator 2010-02-12 14:15:14 -05:00
Jeremy Ashkenas
dbcb9df22b correctly self-compiling @references 2010-02-12 13:56:58 -05:00
Jeremy Ashkenas
e2ad1190ac Array comprehensions are alive and well on the self-compiler 2010-02-12 13:52:57 -05:00
Jeremy Ashkenas
c0f9058f15 range comprehensions are working smooth 2010-02-12 13:51:44 -05:00
Jeremy Ashkenas
12859e575a recompiling with latest jison (modified) and passing codenode generation 2010-02-12 13:35:34 -05:00
Jeremy Ashkenas
3f765c356a Revert "upgrading to latest jison, rebuilding the parser"
This reverts commit fd8b540a66.
2010-02-12 00:15:09 -05:00
Jeremy Ashkenas
fd8b540a66 upgrading to latest jison, rebuilding the parser 2010-02-12 00:12:46 -05:00
Jeremy Ashkenas
29267593c2 fixed heredoc lexing regex for JS, now passing test_heredocs.coffee 2010-02-12 00:06:41 -05:00
Jeremy Ashkenas
1e74805aa4 test_operations.coffee is now compiling successfully 2010-02-11 23:59:56 -05:00
Jeremy Ashkenas
12685aa54a test_functions.coffee compiles and runs successfully. 2010-02-11 23:57:31 -05:00
Jeremy Ashkenas
04f07f4c15 empty functions are legal code 2010-02-11 23:39:25 -05:00
Jeremy Ashkenas
df386a3b3f updated to latest jison, rebuilt parser 2010-02-11 23:34:45 -05:00
Jeremy Ashkenas
13c49ad865 waypoint -- jison has a reverse order of operations from yacc 2010-02-11 23:29:12 -05:00
Jeremy Ashkenas
7c01bba4f4 added the ability to print the parse tree 2010-02-11 23:11:05 -05:00
Jeremy Ashkenas
950d1199c2 self-compiling ranges and expressions 2010-02-11 20:20:59 -05:00
Jeremy Ashkenas
38d1381c02 self-compiling pattern matching correctly 2010-02-11 20:11:11 -05:00
Jeremy Ashkenas
98f15d001f got pattern matching working 2010-02-11 18:44:00 -05:00
Jeremy Ashkenas
a379530d41 disabling traces in the jison parser fixes the performance problems -- ahh, much better 2010-02-11 18:34:30 -05:00
Jeremy Ashkenas
e19b67cb79 still not there 2010-02-11 02:52:41 -05:00
Jeremy Ashkenas
e883a559ca uncomment test 2010-02-11 02:41:24 -05:00
Jeremy Ashkenas
713f6f32e1 done for now 2010-02-11 02:39:57 -05:00
Jeremy Ashkenas
872b36c11d things are in motion -- bin/node_coffee is the new JS-only command line ... it can pass some of the tests 2010-02-11 01:57:33 -05:00
Jeremy Ashkenas
f761c25dcd It's beginning to come alive. 2010-02-10 23:24:05 -05:00
Jeremy Ashkenas
38e1991f82 and now with if/else statements, CoffeeScript-in-CoffeeScript is language-complete -- now for the shakedown cruise 2010-02-10 21:40:10 -05:00
Jeremy Ashkenas
13d3b3a3ce now self-compiling array/object/range comprehensions. 2010-02-10 20:19:59 -05:00
Jeremy Ashkenas
0c2a13b468 self-compiler handles throws, the existential operator, and parentheticals. 2010-02-10 19:13:11 -05:00
Jeremy Ashkenas
4e7408dc25 self-compiler: handles try/catch/finally blocks 2010-02-10 18:33:03 -05:00
Jeremy Ashkenas
76dac9c09c got about as far as I think I can with operator nodes for now, without zach's optimizations 2010-02-10 00:05:56 -05:00
Jeremy Ashkenas
9339058fc3 raising the precedence level of delete, instanceof, and typeof 2010-02-09 22:20:04 -05:00
Jeremy Ashkenas
8e3e06a6e9 Self-compiler: now does while loops 2010-02-09 22:05:17 -05:00
Jeremy Ashkenas
fd80d784f4 Self-compiler can compile splats. 2010-02-09 21:44:34 -05:00
Jeremy Ashkenas
ae4f6309e8 Self-compiler: can now compile functions. 2010-02-09 21:31:07 -05:00
Jeremy Ashkenas
c466537a26 Self-compiler: array literals 2010-02-09 21:01:25 -05:00
Jeremy Ashkenas
001c915c21 Self-compiler: object literals. 2010-02-09 20:53:25 -05:00
Jeremy Ashkenas
91a7102f11 Self-compiler: array slice literals. 2010-02-09 19:30:28 -05:00
Jeremy Ashkenas
a451e90374 upgrading the test harness 2010-02-09 08:15:11 -05:00
Jeremy Ashkenas
c6a6788694 removing the constructor safety check -- it wasn't safe enough (Issue 36) 2010-02-09 07:59:48 -05:00
Jeremy Ashkenas
522df2a355 CoffeeScript-in-CoffeeScript can compile @property references. 2010-02-08 23:51:34 -05:00
Jeremy Ashkenas
863de88671 CoffeeScript-in-CoffeeScript can compile object[indexes] 2010-02-08 23:45:46 -05:00
Jeremy Ashkenas
cb57a1ca1f CoffeeScript-in-CoffeeScript can compile dotted accessors 2010-02-08 23:42:03 -05:00
Jeremy Ashkenas
32098e5a13 CoffeeScript-in-CoffeeScript is now able to compile subClass extends superClass 2010-02-08 23:16:29 -05:00
Jeremy Ashkenas
210d673ef0 CoffeeScript-in-CoffeeScript is compiling function calls 2010-02-08 22:55:56 -05:00
Jeremy Ashkenas
0b5b6113ee CoffeeScript-in-CoffeeScript just had it's first self-compiled snippet. 2010-02-08 22:22:59 -05:00
Jeremy Ashkenas
d5c98165ea removed an old now-impossible branch of execution from ReturnNode 2010-02-08 21:16:14 -05:00
Jeremy Ashkenas
b8d22bc572 finished up the CoffeeScript version of the Scope object 2010-02-08 21:10:48 -05:00
Jeremy Ashkenas
69808ba523 trying out a new organizational scheme, with a quickie 'inherits' helper function 2010-02-08 20:20:11 -05:00
Jeremy Ashkenas
aabfba9599 nodes.coffee is continuing to roll along -- maybe a tenth implemented 2010-02-08 19:49:39 -05:00
Jeremy Ashkenas
135620b14a bumping up the existential operator to the highest precedence level 2010-02-08 11:56:46 -05:00
Jeremy Ashkenas
78a4974de9 allowing numbers to be used as object keys 2010-02-08 11:48:43 -05:00
Jeremy Ashkenas
e2d75e6771 CoffeeScript 0.3.2, just in time for the Github feature 2010-02-08 10:58:49 -05:00
Jeremy Ashkenas
1aa966bba6 merging jeff olson's work 2010-02-07 15:45:05 -05:00
Jeremy Ashkenas
a347183f3d waypoint -- parser.coffee can parse basic functions 2010-02-07 15:37:05 -05:00
Jeremy Ashkenas
56499984ca waypoint -- it's beginning to parser 2010-02-07 15:15:36 -05:00
Jeremy Ashkenas
7ec0a8d653 merging node into master -- you can now pass the --narwhal flag to use narwhal instead. All tests are executing successfully against both Node.js and Narwhal/Rhino backends 2010-02-07 12:52:07 -05:00
Jeremy Ashkenas
293c2ffb5b spacing 2010-02-07 11:59:19 -05:00
Jeremy Ashkenas
5ec096e40d merging all narwhal integration into a single file, so we can merge the node branch without breaking narwhal compatibility 2010-02-07 11:54:01 -05:00
Jeremy Ashkenas
47bc1d5fda added a blocks example 2010-02-07 11:33:29 -05:00
Jeremy Ashkenas
6a59c5c9a9 merging master 2010-02-06 10:15:03 -05:00
Jeremy Ashkenas
decaea0f5f adding 'by' to array comprehensions 2010-02-06 10:12:57 -05:00
Jeremy Ashkenas
0a1873dc42 adding assign and return like they should have been 2010-02-05 22:39:39 -05:00
Jeremy Ashkenas
96eb7e2339 merging master 2010-02-05 22:02:11 -05:00
Jeremy Ashkenas
b795ae7fe1 removing arguments as a keyword -- we can detect its use at code-generation time. 2010-02-05 22:01:11 -05:00
Jeffery Olson
74b9545dc8 work on nodes.coffee and adding scope.coffee 2010-02-04 10:36:33 -08:00
Jeremy Ashkenas
0d56b89d12 Merge branch 'master' into node 2010-02-03 18:16:43 -05:00
Jeremy Ashkenas
dc7d0f1568 fixing assigning to @properties within an expression 2010-02-03 18:16:31 -05:00
Jeremy Ashkenas
9b7cfe87b5 remove parens 2010-02-02 20:44:25 -05:00
Jeremy Ashkenas
1587901367 remove parens 2010-02-02 20:44:10 -05:00
Jeremy Ashkenas
df670d47d2 merging in master 2010-02-02 20:38:44 -05:00
Jeremy Ashkenas
cb7a1033fa adding @property for this.property 2010-02-02 20:36:46 -05:00
Jeremy Ashkenas
df588bc9e8 it's puts in node, not print 2010-02-02 10:43:23 -05:00
Jeremy Ashkenas
9648ae2de1 merged in master 2010-02-02 10:41:19 -05:00
Jeremy Ashkenas
c5c841f2fc fixing bug with mixed dot and soak accessors 2010-02-02 10:39:44 -05:00
Jeffery Olson
c8ac7f0533 starting port of nodes.rb to coffee-script.. Node only, so far 2010-02-01 20:57:03 -08:00
Jeremy Ashkenas
681d4f44f4 simplifying order of operations a bit 2010-02-01 18:31:23 -05:00
Jeremy Ashkenas
db00cd6ed4 adding precedence to the Jison parser 2010-01-31 12:55:00 -05:00
Jeremy Ashkenas
3a748755df removing the peg grammar 2010-01-31 01:25:07 -05:00
Jeremy Ashkenas
a0572f161d the parser seems too big to compile 2010-01-30 23:17:36 -05:00
Jeremy Ashkenas
bad50c9aee the rewriter is done 2010-01-30 18:29:53 -05:00
Jeremy Ashkenas
c6457e010d getting there with the rewriter 2010-01-30 17:47:19 -05:00
Jeremy Ashkenas
557cdbba71 rewriter is halfway done, and working 2010-01-30 17:24:48 -05:00
Jeremy Ashkenas
84feab3492 first little piece of the rewriter 2010-01-30 17:02:05 -05:00
Jeremy Ashkenas
e755188878 mixing in sys again, for the tests 2010-01-30 16:14:13 -05:00
Jeremy Ashkenas
babeebcc1a more progress with the lexer, perhaps it's done 2010-01-30 15:56:40 -05:00
Jeremy Ashkenas
f19360c6b9 waypoint on lexing... parses basic strings, no indentation yet 2010-01-30 14:00:23 -05:00
Jeremy Ashkenas
eff2f4b520 a little further on with the lexer 2010-01-30 00:37:38 -05:00
Jeremy Ashkenas
854c796fd6 first little bit of the lexer 2010-01-30 00:08:15 -05:00
Jeremy Ashkenas
b0ecb39e9f made the path handling a little more robust 2010-01-29 23:41:18 -05:00
Jeremy Ashkenas
f5a37035cf node conversion finished, narwhal removed. 2010-01-29 23:30:54 -05:00
Jeremy Ashkenas
e08e99a403 implementing the Node REPL. 2010-01-29 22:53:44 -05:00
Jeremy Ashkenas
ba2d9df25f first draft of node.js REPL 2010-01-29 22:51:51 -05:00
Jeremy Ashkenas
83285fe170 updating resources section with rack-coffee 2010-01-27 16:38:49 -05:00
Jeremy Ashkenas
5b2ab36246 CoffeeScript 0.3.1, quick patch for 'instanceof' 2010-01-27 08:01:18 -05:00
Jeremy Ashkenas
2f3a94678f fixing instanceof, with a quick test 2010-01-27 07:55:40 -05:00
Jeremy Ashkenas
ca0a65ab95 updating documentation for 0.3 2010-01-26 23:23:59 -05:00
Jeremy Ashkenas
3524d618d8 adding unary plus, new version of Underscore, still passes tests. Rebuilt Narwhal 2010-01-26 22:14:18 -05:00
Jeremy Ashkenas
386d3dd307 complete implicit functions, I think these are done. 2010-01-26 21:15:56 -05:00
Jeremy Ashkenas
e998a81b63 removing block literals in favor of implicit calls 2010-01-26 21:05:26 -05:00
Jeremy Ashkenas
aa93d3c387 first draft of whitespace-sensitive method calls and indexes. 2010-01-26 20:59:52 -05:00
Jeremy Ashkenas
ab4a4a5580 make nested implicit indentation just a little bit smarter about outdents and stack levels 2010-01-26 14:49:33 -05:00
Jeremy Ashkenas
3775f682de updated textmate highlighter for new function literal syntax 2010-01-26 10:54:49 -05:00
Jeremy Ashkenas
a9f016e292 trying out new arrows for function literals -> is a function, => is a bound function 2010-01-26 10:52:05 -05:00
Jeremy Ashkenas
55df898112 adding bound functions to the list of implicit call activator tokens 2010-01-26 10:41:28 -05:00
Jeremy Ashkenas
fb7fd53bdf enabling passed functions to fire implicit method calls 2010-01-26 02:27:19 -05:00
Jeremy Ashkenas
29e4043f26 tests passing with smarter block syntax with optional parens 2010-01-26 02:15:08 -05:00
Jeremy Ashkenas
460b3f6d8e first draft of mandatory parentheses around function definition param lists -- all tests pass 2010-01-26 00:40:58 -05:00
Jeremy Ashkenas
63b44a2b03 odd and even were backwards 2010-01-25 22:44:36 -05:00
Jeremy Ashkenas
8efcaf6eec moved CoffeeScript.tmbundle to extras and rewrote the installation instructions in plain text 2010-01-25 22:22:39 -05:00
Jeremy Ashkenas
a732e578ea Merge branch 'master' of git://github.com/olsonjeffery/coffee-script 2010-01-25 22:03:12 -05:00
Jeremy Ashkenas
d6e206b420 adding line number info to unclosed parens, objects, arrays, and indents 2010-01-25 21:07:18 -05:00
Jeremy Ashkenas
91e703052c fixing chained single-line if-elses with a smarter rewriter. 2010-01-25 20:52:33 -05:00
Jeffery Olson
f393b1c897 adding vim syntax file in a new "extras" folder
- also added a VIM-SYNTAX-HOWTO.md readme file
2010-01-25 07:48:06 -08:00
Jeremy Ashkenas
2875de5e73 changed the docs for optional parens 2010-01-25 00:14:00 -05:00
Jeremy Ashkenas
8d63d269b8 making all postfix forms close out implicit calls, as in Ruby 2010-01-24 23:56:27 -05:00
Jeremy Ashkenas
a5d39efdd2 converted the tests to use optional parentheses -- lot's of little subtleties to work out 2010-01-24 23:40:45 -05:00
Jeremy Ashkenas
70e3a6ef2f first draft of optional parentheses, with a couple tests ... more to follow 2010-01-24 22:32:06 -05:00
Jeremy Ashkenas
4b267b401a another poignant example 2010-01-24 20:04:28 -05:00
Jeremy Ashkenas
e6f010b983 adding more examples to the computer_science folder, and fiddling with operator precedence 2010-01-24 18:59:29 -05:00
Jeremy Ashkenas
af53a04932 added test for lexical scope sharing through generated closure wrappers, something uncommonly used, but that was a regression 2010-01-24 13:39:27 -05:00
Jeremy Ashkenas
817e8deb27 adding soaked method calls, with caching 2010-01-24 12:52:15 -05:00
Jeremy Ashkenas
d728c3d669 added existence chains with '?.' -- soaks up attempts to access undefined properties, returning 'undefined' 2010-01-23 23:30:55 -05:00
Jeremy Ashkenas
9160500e84 removing 'this' rewriting in favor of correctly calling generated closures 2010-01-23 21:11:27 -05:00
Jeremy Ashkenas
c3ce2ea9b1 added automatic safety closure wrapper for functions declared within for loops. 2010-01-23 17:53:07 -05:00
Jeremy Ashkenas
5f94186b40 adding the compiled parser back into the repo (after all that) so that it can be used as the source for the narwhal package 2010-01-23 12:44:36 -05:00
Jeremy Ashkenas
791d874058 fixing comments as the last line of a block 2010-01-20 20:36:31 -05:00
Jeremy Ashkenas
a8ae37a428 fixing bug with multiple linebreaks in heredocs 2010-01-19 09:49:23 -05:00
Jeremy Ashkenas
b9c09bfa4e doc updates -- widened the code segments for the sake of the JavaScript 2010-01-17 18:33:31 -05:00
Jeremy Ashkenas
63c9b5c2f0 CoffeeScript 0.2.6 is on the books 2010-01-17 18:12:59 -05:00
Jeremy Ashkenas
80fbe02fda ignoring the top-down parser that doesn't work 2010-01-17 17:41:38 -05:00
Jeremy Ashkenas
e514a39dd2 added binary search example -- chapter 6 of beautiful code 2010-01-17 16:18:24 -05:00
Jeremy Ashkenas
4a32c58221 added bentley's chapter from beautiful code to the examples/tests -- quicksort runtime analysis 2010-01-17 15:58:44 -05:00
Jeremy Ashkenas
4609ad78c2 added the first chapter of beautiful code as a coffeescript example 2010-01-17 15:36:46 -05:00
Jeremy Ashkenas
2d90a751f7 edits for clarity 2010-01-17 14:55:06 -05:00
Jeremy Ashkenas
8647b54a61 rename compile_double_reference to compile_reference 2010-01-17 14:26:00 -05:00
Jeremy Ashkenas
8e1f3c0eca generating multiple calls to the same function should use compile_double_reference to ensure a single evaluation of the call itself. 2010-01-17 14:23:41 -05:00
Jeremy Ashkenas
c4d0903e6a fixing assignment-in-condition 2010-01-17 10:40:59 -05:00
Jeremy Ashkenas
e72ef1a61a reverting change 2010-01-17 10:28:04 -05:00
Jeremy Ashkenas
d7d9cb8d28 only let returns stop an expression from being closure-ified -- breaks and continues may be valid 2010-01-17 10:21:24 -05:00
Jeremy Ashkenas
f6c8e81ea6 the existential operator can now be used infix as well 2010-01-16 23:03:54 -05:00
Jeremy Ashkenas
52539ae7d2 abbreviating the existential operator 2010-01-16 22:26:34 -05:00
Jeremy Ashkenas
95b362499f added the conditional existence operator 2010-01-16 22:17:55 -05:00
Jeremy Ashkenas
0bc4da2b51 ensure that functions are only called once, when chaining comparators 2010-01-16 22:04:08 -05:00
Jeremy Ashkenas
9679fc0b52 removing redundant unary check 2010-01-16 16:49:03 -05:00
Jeremy Ashkenas
9cb0564972 added Python's chainable comparisons, like: 10 > 5 > 1 2010-01-16 16:37:49 -05:00
Jeremy Ashkenas
c6c0c7d059 simplification of function and prototype naming -- last_assign, immediate_assign, and proto_assign are gone, in favor of 'name' and 'proto' properties on CodeNodes 2010-01-16 15:44:07 -05:00
Jeremy Ashkenas
62e946b8ce purely empty functions at the top level should be wrapped in parens, so as not to cause a JS syntax error 2010-01-16 15:02:04 -05:00
Jeremy Ashkenas
6c782b7723 fixes for syntax highlighting assignments and regexes 2010-01-16 14:28:42 -05:00
Jeremy Ashkenas
9eff443032 arguments no longer is just a find-and-replace -- it'll fix the arguments variable at the top of scope if you use it in a function body 2010-01-16 12:52:26 -05:00
Jeremy Ashkenas
8957feedb4 expression closure wrappers are now safer -- they won't be generated if there's a statement_only inside 2010-01-16 12:10:31 -05:00
Jeremy Ashkenas
1cd7fa8ebe added children macro to Node, using it so that all nodes now have a 'children' method -- used for safe references to 'this' within closure wrappers 2010-01-16 11:24:10 -05:00
Jeremy Ashkenas
701cdb4c13 never try to push a statement_only 2010-01-15 19:47:16 -05:00
Jeremy Ashkenas
8dc5da9cc9 adding coffee-haml-filter to the resources section 2010-01-14 14:44:03 -05:00
Jeremy Ashkenas
001cc29deb slightly shorter generated code for ==> 2010-01-14 08:55:09 -05:00
Jeremy Ashkenas
e77e520607 CoffeeScript 0.2.5 is on the books 2010-01-13 23:24:45 -05:00
Jeremy Ashkenas
ed8a54995d with splats allowed in destructuring assignment 2010-01-13 22:25:58 -05:00
Jeremy Ashkenas
2d206e7b60 pulling out pushes into a pushnode 2010-01-13 21:33:46 -05:00
Jeremy Ashkenas
bb9fdd3015 while loops can now be used as expressions -- they return an array containing the computed result of each iteration. 2010-01-13 21:27:22 -05:00
Jeremy Ashkenas
1e7d638435 adding bound functions, with test 2010-01-13 20:59:57 -05:00
Jeremy Ashkenas
0ceca0778c adding when clauses with multiple values 2010-01-13 19:56:35 -05:00
Jeremy Ashkenas
abd9ab5c71 unified ParamSplatNode and ArgSplatNode into SplatNode 2010-01-12 23:49:47 -05:00
Jeremy Ashkenas
ea349a1a59 more safety type-checks in nodes.rb 2010-01-12 23:26:35 -05:00
Jeremy Ashkenas
f0d5db7e66 fixing heredocs to use the left-most indent as the indentation guide -- not just the first line of the heredoc 2010-01-12 23:06:12 -05:00
Jeremy Ashkenas
914ba1c244 removing commented-out bit 2010-01-12 18:01:12 -05:00
Jeremy Ashkenas
844ea33274 mistaken commit 2010-01-12 17:45:06 -05:00
Jeremy Ashkenas
87e04e9952 nicer syntax error messages for newlines and indentation 2010-01-12 17:44:37 -05:00
Jeremy Ashkenas
197914bcf7 nicer syntax error messages for newlines and indentation 2010-01-12 17:44:03 -05:00
Jeremy Ashkenas
8dfbd1a2a8 using Object.prototype.hasOwnProperty.call instead of obj.hasOwnProperty, with an alias, for Rhino and java objects 2010-01-12 17:35:37 -05:00
Jeremy Ashkenas
c19647ad33 adding and fixing test for empty strings 2010-01-12 08:52:44 -05:00
Jeremy Ashkenas
27f7ef09af allow leading newlines in coffee scripts 2010-01-12 08:49:39 -05:00
Jeremy Ashkenas
9a61bbf005 CoffeeScript 0.2.4, with pattern matching and heredocs 2010-01-12 00:09:23 -05:00
Jeremy Ashkenas
c8d505e85d heredoc docs 2010-01-12 00:00:38 -05:00
Jeremy Ashkenas
477c510345 adding heredocs, with tests 2010-01-11 23:53:50 -05:00
Jeremy Ashkenas
c3029faca7 documentation for pattern matching 2010-01-11 22:55:01 -05:00
Jeremy Ashkenas
186797a745 got compile_pattern_match about as small as its going to get 2010-01-11 22:16:23 -05:00
Jeremy Ashkenas
d54fa2f2a1 a whole chunk of compile_pattern_match was redundant, axed it -- along with the array/vs/object split 2010-01-11 22:12:18 -05:00
Jeremy Ashkenas
5e1e949bf6 a passing test for destructuring assignment (it needs a better name) 2010-01-11 22:04:25 -05:00
Jeremy Ashkenas
6c980d8adc first draft of destructuring assignment -- working out the wrinkles -- not sure if we want to do the full spec 2010-01-11 21:44:47 -05:00
Jeremy Ashkenas
2f63439bff swapping around the order of variable declaration in array comprehensions, so that it comes out in the proper order: __a, __b, __c 2010-01-11 09:16:08 -05:00
Jeremy Ashkenas
c7cb308b6d adding note about parens-around-ambiguous-function-defs to the docs 2010-01-11 09:09:06 -05:00
Jeremy Ashkenas
9cc7d6af27 little lexer tweak 2010-01-11 08:46:50 -05:00
Jeremy Ashkenas
cfa357cbc3 CoffeeScript 0.2.3, with 'of', not 'ino' 2010-01-11 00:01:16 -05:00
Jeremy Ashkenas
9d8668f37f added a whole slew of nice Potion examples from the pamphlet -- CoffeeScript stacks up pretty well. 2010-01-10 23:27:57 -05:00
Jeremy Ashkenas
d1ddeacbe3 more refactors to nodes 2010-01-10 22:35:55 -05:00
Jeremy Ashkenas
d9d09a9a72 refactoring and commenting nodes.rb Expressions 2010-01-10 22:04:38 -05:00
Jeremy Ashkenas
a1528f3f19 rebuilt the narwhal interface 2010-01-10 20:25:09 -05:00
Jeremy Ashkenas
7d2a955e0a bumping the license to 2010 2010-01-10 17:57:29 -05:00
Jeremy Ashkenas
24408c785a caught a close call bug with object comprehensions and not specifying the value 2010-01-10 17:44:19 -05:00
Jeremy Ashkenas
bb5bf7f94f more docs, more tests 2010-01-10 17:36:06 -05:00
Jeremy Ashkenas
3e987de4a8 rebuilding underscore.coffee docs, adding a build task -- need to remember to copy over nicer headers 2010-01-10 17:23:07 -05:00
Jeremy Ashkenas
de74bce2cd more docs for 0.2.2 2010-01-10 17:14:20 -05:00
Jeremy Ashkenas
c265b7d5d6 updating comprehension speed test with the new normal comprehensions 2010-01-10 16:39:38 -05:00
Jeremy Ashkenas
ad18378f7e adding '::' as shorthand for '.prototype.' 2010-01-10 16:16:59 -05:00
Jeremy Ashkenas
902febb43a big commit -- adding back object comprehensions, using 'ino', versus 'in' for array comprehensions, fixing bug with dollar signs in identifiers 2010-01-10 15:52:23 -05:00
Jeremy Ashkenas
13fc8aea04 removing object comprehensions from CoffeeScript, they were necessitating the generation of too much ugly JS 2010-01-10 14:45:44 -05:00
Jeremy Ashkenas
8ea75290b5 better indentation for compile_closure 2010-01-10 13:18:44 -05:00
Jeremy Ashkenas
9498ef9fe4 ignoring 'presentation' folder 2010-01-10 12:21:06 -05:00
Jeremy Ashkenas
8e3922b6c6 allowing comments in the middle of switch statements 2010-01-09 13:25:44 -05:00
Jeremy Ashkenas
2319affa61 allowing chained calls broken up over multiple lines with periods at the front (jQuery-style) 2010-01-09 12:12:38 -05:00
Jeremy Ashkenas
7befbddae2 adding test for body-less while, using null as the body so JSLint doesn't get in a tizzy 2010-01-09 11:58:50 -05:00
Jeremy Ashkenas
ae58e2ec6c adding body-less while expressions 2010-01-09 11:51:32 -05:00
Jeremy Ashkenas
4c3f00cf77 fixing calling super from constructors 2010-01-08 10:54:44 -05:00
Jeremy Ashkenas
8b3926fb0c making extends equivalent to the Google Closure version 2010-01-08 09:35:02 -05:00
Jeremy Ashkenas
d416c184db separating out the --no-wrap and the --globals arguments, which shouldn't be jammed together 2010-01-07 21:10:25 -05:00
Jeremy Ashkenas
30dca132bd more node cleaning, using idt() instead of TAB 2010-01-07 20:57:23 -05:00
Jeremy Ashkenas
69908be85c cleaned up nodes.rb indentation code with an idt method 2010-01-07 20:55:30 -05:00
Jeremy Ashkenas
c70b6f39b1 weepy's new speedy comprehensions 2010-01-07 20:27:26 -05:00
Jeremy Ashkenas
fab98a2219 mentioning the racc gem in the readme 2010-01-07 09:43:44 -05:00
Jeremy Ashkenas
18c3e79a50 adding automatic 'return this' for constructors: functions that start with a Capital Letter 2010-01-06 23:47:36 -05:00
Jeremy Ashkenas
9ed8020b84 added the constructor fix for capitalized functions 2010-01-06 23:34:56 -05:00
Jeremy Ashkenas
cf7079a379 fixing the lexer to handle strings that end with a backslash character 2010-01-06 23:15:13 -05:00
Jeremy Ashkenas
3e33b4a618 adding a warning about parser.rb to the readme 2010-01-06 22:57:21 -05:00
Jeremy Ashkenas
a5c1922200 printing a warning when the parser goes missing 2010-01-06 22:41:09 -05:00
Jeremy Ashkenas
c49f2d8097 ignoring the generated parser.rb 2010-01-06 22:38:03 -05:00
Jeremy Ashkenas
eb9b18376e removing the parser.rb from revision control -- it's taking up too much space -- you'll have to generate it yourself with rake build:parser 2010-01-06 22:37:25 -05:00
Jeremy Ashkenas
fbcdc12a9c adding empty return statements -- they return null 2010-01-06 21:21:42 -05:00
Matt Lyon
41bb6edcd2 next time: don't copy the .tmDelta over the .tmLanguage 2010-01-06 00:11:20 -08:00
Matt Lyon
22d3238b2a if we escape the close-brackets, it won't think single-line objects need folding 2010-01-06 00:03:11 -08:00
Matt Lyon
3124869e1d add folding for multi-line object literals 2010-01-05 22:44:44 -08:00
Jeremy Ashkenas
de49465dc6 comments 2010-01-06 01:27:58 -05:00
Jeremy Ashkenas
4fc40e4841 adding the 'in' operator 2010-01-05 23:29:43 -05:00
Jeremy Ashkenas
0275e7775f fixing weepy's comment scenario 2010-01-05 23:15:32 -05:00
Jeremy Ashkenas
001e42b85c fixing range literals by making them values, not expressions, and adding tests 2010-01-05 22:49:51 -05:00
Jeremy Ashkenas
46f1977ea1 adding ranges as expressions, they get expanded into the equivalent array 2010-01-05 22:17:09 -05:00
Jeremy Ashkenas
c2bb93b5f8 ellipsis is the new splat 2010-01-05 21:40:36 -05:00
Jeremy Ashkenas
1040e52246 CoffeeScript 0.2.1 2010-01-05 09:30:48 -05:00
Jeremy Ashkenas
d555685030 docs for arguments conversion 2010-01-05 09:29:10 -05:00
Jeremy Ashkenas
5fe419b1ce automatic conversion of arguments into arrays 2010-01-05 09:10:45 -05:00
Jeremy Ashkenas
1ebc4d5f21 alright, done fiddling. CoffeeScript 0.2.0 2010-01-05 00:45:04 -05:00
Jeremy Ashkenas
6658250c8e more docs 2010-01-05 00:34:18 -05:00
Jeremy Ashkenas
724d4c9660 tweaking docs 2010-01-05 00:19:22 -05:00
Jeremy Ashkenas
0cf7801f36 more docs for 0.2 -- blocks and splats 2010-01-04 23:26:27 -05:00
Jeremy Ashkenas
ae603749be adding the complete underscore.coffee example to the docs 2010-01-04 22:51:02 -05:00
Jeremy Ashkenas
6e63a18f86 first pass at 0.2.0 docs 2010-01-04 22:19:45 -05:00
Jeremy Ashkenas
3e24cef69f minor doc updates -- let's try pulling in the underscore test suite 2010-01-04 19:15:24 -05:00
Jeremy Ashkenas
2c1033f5da removed the whole messy notions of looking downwards for returns or children -- ForNodes now peek at top-level status, and if they're being asked to return a value from the outside 2010-01-04 18:57:10 -05:00
Jeremy Ashkenas
da9e38808c nicer scope inspects 2010-01-04 09:43:50 -05:00
Jeremy Ashkenas
5efaff506c more underscore 2010-01-04 01:43:45 -05:00
Jeremy Ashkenas
94bc7c1f92 putting in a special check for returns within array comprehensions -- not very nice 2010-01-04 01:06:31 -05:00
Jeremy Ashkenas
f75d98e447 pretty amazing -- fully functional draft of underscore.js 0.5.2, all in CoffeeScript 2010-01-04 00:28:52 -05:00
Jeremy Ashkenas
69283fcadd fixing a nasty little bug with not dup'ing a string in Scope.rb, causing later functions to start their free_variables where previous functions left off, because they shared their ancestor's @temp_variable string 2010-01-04 00:16:38 -05:00
Jeremy Ashkenas
672dd70bdb more underscore examples raised a slight bug with a lexing ambiguity between leading whens (in switches), and trailing whens (in comprehensions) -- made two different tokens to distinguish them 2010-01-03 22:25:38 -05:00
Jeremy Ashkenas
32cd15f038 mo' expression examples 2010-01-03 19:08:41 -05:00
Jeremy Ashkenas
ecdb47107b -- 2010-01-03 19:00:08 -05:00
Jeremy Ashkenas
cb1815885c adding a statement-as-expression test, and returning null from while loops, if asked 2010-01-03 18:58:34 -05:00
Jeremy Ashkenas
d53d85d03e updating fixtures -- all tests now pass -- back to master 2010-01-03 18:49:00 -05:00
Jeremy Ashkenas
8e6486a1d7 logic error in Expressions was causing over-compilation by a factor of the depth of the tree 2010-01-03 18:47:23 -05:00
Jeremy Ashkenas
97f16c0e9c fixing comment-within-objecta-and-array-literal printing for the new expression regime. 2010-01-03 18:35:03 -05:00
Jeremy Ashkenas
bd2597c6b8 change lexical scoping example to use var names that haven't been already defined 2010-01-03 18:27:26 -05:00
Jeremy Ashkenas
56015bd23f subtle call order bug was preventing variable declarations 2010-01-03 18:22:10 -05:00
Jeremy Ashkenas
3724778989 lowering the precedence of if/else/while 2010-01-03 18:11:53 -05:00
Jeremy Ashkenas
bb0dfa5cd4 removing the silly newlines from comments 2010-01-03 18:07:03 -05:00
Jeremy Ashkenas
6160fe3c17 beautiful -- all examples, tests, and docs are now compiling without JSLint warnings 2010-01-03 16:32:59 -05:00
Jeremy Ashkenas
099944e0aa All execution tests are now passing with statements everywhere 2010-01-03 15:59:33 -05:00
Jeremy Ashkenas
4814d5baa5 more progress -- you can wrap parentheses around statements now 2010-01-03 15:13:59 -05:00
Jeremy Ashkenas
78c4957ba8 first rough rough rough draft of kamatsu's closure suggestion -- test.coffee runs, but probably nothing else 2010-01-03 13:59:17 -05:00
Jeremy Ashkenas
de4eddcad4 bumping version numbers to 0.2.0 in anticipation of release soon-ish 2010-01-03 11:01:50 -05:00
Jeremy Ashkenas
ba3c5298f7 adding a block test and using PARAM_SPLAT to remove the last shift/reduce conflict 2010-01-03 10:46:37 -05:00
Jeremy Ashkenas
21a0cc83ae Adding kamatsu's proposed block literal syntax 2010-01-03 10:19:39 -05:00
Jeremy Ashkenas
7eff8786bc todo 2010-01-02 01:00:03 -05:00
Jeremy Ashkenas
7ee5be674d adding splice literals, with tests 2010-01-02 00:20:24 -05:00
Jeremy Ashkenas
38520bfece rebuilding narwhal uncovered a bug with named functions 2010-01-01 22:00:34 -05:00
Jeremy Ashkenas
c3d0e50e8f fixing the food/eat array comprehension in the docs to not pretend like there's a made-up method on String.prototype 2010-01-01 17:16:34 -05:00
Jeremy Ashkenas
34add7d7bf adding consistent highlighting to variable assignment, whether functions or values 2010-01-01 17:11:48 -05:00
Jeremy Ashkenas
75d9e23df4 better existence test, with tests 2010-01-01 12:41:55 -05:00
Jeremy Ashkenas
ff80f8d423 adding the notion of existence -- postfixing an expression with a question mark will check if to see if it's not null or undefined 2010-01-01 12:31:05 -05:00
Jeremy Ashkenas
3489eec6ee commenting the lexer a bit more 2010-01-01 12:11:35 -05:00
Jeremy Ashkenas
2f69bc1708 expanding the list of tokens that regexes may not follow, according to the Mozilla JS 2.0 docs 2010-01-01 12:08:36 -05:00
Jeremy Ashkenas
0f81dbe913 adding steps to range comprehensions 2010-01-01 11:54:59 -05:00
Jeremy Ashkenas
e30a267c9d fixing precedence order, so that you can nest range comprehensions 2010-01-01 11:19:57 -05:00
Jeremy Ashkenas
305f883eab making range comprehensions compile safely, even when you assign to the same variable as your endposts. 2010-01-01 10:55:43 -05:00
Jeremy Ashkenas
f622fc43bc -- 2010-01-01 10:40:29 -05:00
Jeremy Ashkenas
a93a570603 allowing indentation within function calls 2010-01-01 10:38:28 -05:00
Jeremy Ashkenas
02fbd28e58 adding a test for expressions in range comprehensions 2010-01-01 10:20:29 -05:00
Jeremy Ashkenas
2cef93b381 test for uminus 2010-01-01 10:17:33 -05:00
Jeremy Ashkenas
caf9d627cb allowing expressions within range literals 2010-01-01 10:15:22 -05:00
Jeremy Ashkenas
ad5b5fa458 fixing the regex lexer to make it less agressive when we know it can't possibly be a regex 2010-01-01 09:49:18 -05:00
Jeremy Ashkenas
41056ca2bd fix for multiple splats in a function call 2009-12-31 20:02:15 -05:00
Jeremy Ashkenas
409283a30f adding splats as arguments to function calls 2009-12-31 19:52:13 -05:00
Jeremy Ashkenas
abfc9f5a2d adding a note in the docs about how to build the parser and install the gem 2009-12-31 18:22:51 -05:00
Jeremy Ashkenas
43edd29d22 comment about test_execution being the most important 2009-12-31 18:09:48 -05:00
Jeremy Ashkenas
26c89cef06 reserving variables for splats the regular way, not through a custom 'var' declaration 2009-12-31 18:03:39 -05:00
Jeremy Ashkenas
1d2bb3b2be adding splats to function definitions 2009-12-31 17:50:12 -05:00
Jeremy Ashkenas
f299972713 expressions nested in expressions made for some indentation issues -- statements are now responsible for their own leading indentation 2009-12-31 16:50:46 -05:00
Jeremy Ashkenas
bfd7455db4 adding a test for multiline-array-comprehension-with-filter 2009-12-31 16:13:52 -05:00
Jeremy Ashkenas
7ec91a1ee5 enabling multi-line array and object comprehensions 2009-12-31 16:09:27 -05:00
Jeremy Ashkenas
44fec922a4 adding a filtered object comprehension test 2009-12-31 15:08:54 -05:00
Jeremy Ashkenas
07d0044718 using push for comprehension results so that it works with object keys, and adding a test for object comprehensions 2009-12-31 15:03:32 -05:00
Jeremy Ashkenas
00538bd62c adding weepy's suggestion to use (for .. in) for array comprehensions, which means that they're now object comprehensions as well 2009-12-31 14:52:14 -05:00
Jeremy Ashkenas
4e8a12d70d done commenting the rewriter 2009-12-31 13:45:07 -05:00
Jeremy Ashkenas
edf1fc769f detailed scan_tokens so that the calling function can indicate the number of spaces to move forward (or backward) in the token stream 2009-12-31 13:43:24 -05:00
Jeremy Ashkenas
2231d67cef making assignment token detection a regex like all the others 2009-12-31 13:26:38 -05:00
Jeremy Ashkenas
a376e7f4a3 pulled out all token-stream-rewriting logic into the CoffeeScript::Rewriter -- let the lexer be simpleminded 2009-12-31 13:22:33 -05:00
Jeremy Ashkenas
20ade4f448 adding a rake:ultraviolet build syntax highlighter task, and regenerating the docs with correct highlighting 2009-12-31 13:01:10 -05:00
Jeremy Ashkenas
f9d630119d adding a test case for named functions 2009-12-31 10:52:00 -05:00
Jeremy Ashkenas
7f76c22894 updating docs -- need to get back on the computer that has the syntax highlighter for UV installed 2009-12-30 23:43:55 -05:00
Jeremy Ashkenas
b1fa06ff70 updating tests for named functions 2009-12-30 23:14:29 -05:00
Jeremy Ashkenas
e481a39a0d making all functions named functions, if children of an immediate assignment 2009-12-30 23:13:22 -05:00
Jeremy Ashkenas
8762162dff adding proper auto-newline escaping 2009-12-30 22:49:25 -05:00
Jeremy Ashkenas
a6539a030c allowing any manner of indentation in the comments, by adjusting them in the lexer 2009-12-30 22:24:40 -05:00
Jeremy Ashkenas
942572d081 don't print the confusing indentation numbers when raising ParseErrors for indentation 2009-12-30 21:57:03 -05:00
Jeremy Ashkenas
ec60205014 getting there, finally ... all tests are green for whitespace 2009-12-30 21:51:23 -05:00
Jeremy Ashkenas
dba8439425 the underscore example parses now -- added line number information to parenthetical nodes 2009-12-30 21:44:51 -05:00
Jeremy Ashkenas
774e3d3e31 moving the newline escaping detection up higher so indents don't overrule it 2009-12-30 21:41:01 -05:00
Jeremy Ashkenas
cae0b1a038 lex indents with higher precedence than comments 2009-12-30 21:20:30 -05:00
Jeremy Ashkenas
bbbfd92373 more fiddling with the lexer -- the indentation is super fragile 2009-12-30 21:15:54 -05:00
Jeremy Ashkenas
fd83759ef4 more fiddling with the lexer -- the indentation is super fragile 2009-12-30 21:11:54 -05:00
Jeremy Ashkenas
49714656e1 rolling back MULTI_DENT regex 2009-12-30 20:41:32 -05:00
Jeremy Ashkenas
d43d491561 regex cleanup -- eliminating some lookahead because Ruby regexps blow chunks (stackoverflows) when you look (ahead) at them funny. 2009-12-30 20:36:47 -05:00
Jeremy Ashkenas
c8711b419e fixed up the comment/assignment interleaving in nodes.rb 2009-12-30 20:24:24 -05:00
Jeremy Ashkenas
5c7b77aa4d rewrote 'rewrite_closing_parens' with an explicit loop -- there was a bug when adding to @tokens in the middle of scan_tokens' while loop -- consider scan_tokens to be on probation until further notice 2009-12-30 20:12:30 -05:00
Jeremy Ashkenas
dc821f2e4c be more vigorous about removing mid-expression newlines, 'when' closes implicit blocks, a better comment-detecting regex lexer that doesn't eat outdents 2009-12-30 19:26:37 -05:00
Jeremy Ashkenas
cd68f02981 big milestone. examples/code.coffee now compiles correctly under the new whitespace regime 2009-12-30 18:59:33 -05:00
Jeremy Ashkenas
e6cd32f2fc balancing parens closing single-line blocks 2009-12-30 18:52:03 -05:00
Jeremy Ashkenas
ed1c1f7a0e fixing up documents example 2009-12-30 18:28:16 -05:00
Jeremy Ashkenas
5659d1bd49 adding ')' as a SINGLE_CLOSER, although it's probably unsafe 2009-12-30 18:09:43 -05:00
Jeremy Ashkenas
9a7c075e06 parser and test tweaks for whitespace -- tests are coming along 2009-12-30 17:58:27 -05:00
Jeremy Ashkenas
62c51006a1 removed the final shift/reduce errors -- back to zero for the first time in a long time 2009-12-30 17:45:47 -05:00
Jeremy Ashkenas
d528db76e6 special case for 'else if' in the lexer 2009-12-30 17:41:14 -05:00
Jeremy Ashkenas
9a946d2ac5 execution tests still pass -- more lexer block insertion and 2 shift/reduces in the grammar now 2009-12-30 15:52:07 -05:00
Jeremy Ashkenas
c822f96145 patching up the lexer and adding a test with trailing whitespace (it was too string for trailing whitespace before) 2009-12-30 15:10:47 -05:00
Jeremy Ashkenas
9e3ef42c63 fixing up narwhal integration (again) 2009-12-30 15:05:05 -05:00
Jeremy Ashkenas
f93e552cb3 fixin up narwhal factory and adding more implicit blocks to the lexer 2009-12-30 14:32:59 -05:00
Jeremy Ashkenas
ea58be2838 patched up lexer to add indentation to single-line flavors of statements -- let's expand this idea 2009-12-30 13:58:00 -05:00
Jeremy Ashkenas
4d514f255b merged in master branch again 2009-12-30 13:38:50 -05:00
Jeremy Ashkenas
ce0e71f796 fixing the double-printing bug with coffee -r 2009-12-30 13:34:25 -05:00
Jeremy Ashkenas
7c97f32dd3 ignoring test.coffee 2009-12-30 12:59:05 -05:00
Jeremy Ashkenas
6ddd808f74 removing dots from whitespace examples 2009-12-30 00:22:27 -05:00
Jeremy Ashkenas
90051e9096 clean up a couple of test errors for whitespace 2009-12-30 00:08:49 -05:00
Jeremy Ashkenas
dd3c9abe15 touch-ups cleanups to the lexer and rebuilding the narwhal libs from whitespace'd versions 2009-12-29 23:01:08 -05:00
Jeremy Ashkenas
d3ab60df78 implementing kamatsu's debt-based lexer for closing delimiters 2009-12-29 22:24:52 -05:00
Jeremy Ashkenas
541291e2f3 whitespace parser down to 4 shift/reduce errors -- good enough for me 2009-12-29 21:46:15 -05:00
Jeremy Ashkenas
fd357871f2 put the commas on the outside of expression closers 2009-12-29 20:39:51 -05:00
Jeremy Ashkenas
f5aafc6591 don't break trailing commas with rewrite_closing_parens 2009-12-29 10:20:18 -05:00
Jeremy Ashkenas
96803d0129 killing some newlines in the execution tests, to test the lexer's newline suppression 2009-12-29 10:02:19 -05:00
Jeremy Ashkenas
ae112d6087 changing array comprehension filters from 'where' to 'when' to mirror case/when 2009-12-29 09:55:37 -05:00
Jeremy Ashkenas
a3129e05ae allowing indentation in object and array literals 2009-12-29 09:25:56 -05:00
Jeremy Ashkenas
f44443b58a still some kinks to work out -- mid-expression blocks 2009-12-29 09:18:41 -05:00
Jeremy Ashkenas
3fbb870d01 using 'where' for array comprehension filtering, after kamatsu's suggestion -- execution tests pass now with significant whitespace 2009-12-29 08:52:26 -05:00
Jeremy Ashkenas
cea417de02 moving along with whitespace 2009-12-28 23:08:02 -05:00
Jeremy Ashkenas
ddd52a1845 first draft of kamatsu's rewrite rules -- finally got whitespace to be flexible enough, I think. 2009-12-28 21:07:47 -05:00
Jeremy Ashkenas
50bdd2668c got lexer balancing parens, indent/outdents, brackets, and curlies 2009-12-28 21:02:40 -05:00
Jeremy Ashkenas
bb84a982ce merging in master 2009-12-28 20:06:23 -05:00
Jeremy Ashkenas
7b5b261743 removed unused example 2009-12-28 20:05:14 -05:00
Jeremy Ashkenas
c84bb0c875 fixing relative path for execution tests 2009-12-28 16:23:48 -05:00
Jeremy Ashkenas
a186e47e2c stop shifting args 2009-12-28 16:20:11 -05:00
Jeremy Ashkenas
41f3d54f4a rebuilding narwhal libs 2009-12-28 16:10:56 -05:00
Jeremy Ashkenas
9e47f6bd58 merging in tlrobinson's fix for package.json 2009-12-28 16:09:14 -05:00
tlrobinson
3762f4c680 Add package.json to gemspec files so Narwhal integrations works when installed as a gem. 2009-12-28 12:45:47 -08:00
Jeremy Ashkenas
845c8cba3b removing broken accidental commit 2009-12-28 09:02:55 -08:00
tlrobinson
a722b42eed Add package on command line in case it's not installed in a Narwhal packages path. 2009-12-28 01:49:07 -08:00
tlrobinson
78e08f316d Merge branch 'master' of git://github.com/jashkenas/coffee-script 2009-12-28 01:36:23 -08:00
tlrobinson
55616cf3b8 Fixed Narwhal integration. Cleaned up module organization, etc. 2009-12-28 01:16:57 -08:00
Jeremy Ashkenas
aa45456d7d part of the way to supporting multiline array comprehensions -- the grammar and parsing is there -- the code generation is tricky 2009-12-27 21:50:02 -08:00
Jeremy Ashkenas
ac00a19514 CoffeeScript 0.1.6 -- bugfixes 2009-12-27 12:49:11 -08:00
Jeremy Ashkenas
7ae8687a3e fixing paths for running
coffee compiles CoffeeScript source files into JavaScript.

Usage:
  coffee path/to/script.coffee
    -i, --interactive                run a CoffeeScript REPL (requires Narwhal)
    -r, --run                        compile and run a script (requires Narwhal)
    -o, --output [DIR]               set the directory for compiled JavaScript
    -w, --watch                      watch scripts for changes, and recompile
    -p, --print                      print the compiled JavaScript to stdout
    -l, --lint                       pipe the compiled JavaScript through JSLint
    -e, --eval                       compile a cli scriptlet or read from stdin
    -t, --tokens                     print the tokens that the lexer produces
    -v, --verbose                    print at every step of code generation
    -n, --no-wrap                    raw output, no safety wrapper or vars
        --install-bundle             install the CoffeeScript TextMate bundle
        --version                    display CoffeeScript version
    -h, --help                       display this help message outside of the coffee-script directory
2009-12-27 12:43:05 -08:00
Jeremy Ashkenas
55e736cb27 more underscore examples 2009-12-27 11:01:19 -08:00
Jeremy Ashkenas
3ee4e98ccc more underscore and bugfix edits to code generation 2009-12-26 22:24:21 -08:00
Jeremy Ashkenas
d7dd18b476 more underscore, and removing custom_assign and return from conditional compilation 2009-12-26 21:55:56 -08:00
Jeremy Ashkenas
097bede5c8 coffeescript 0.1.5, just for kicks 2009-12-26 21:25:37 -08:00
Jeremy Ashkenas
983dac84a2 docs for range comprehensiosn 2009-12-26 20:46:31 -08:00
Jeremy Ashkenas
eeef8d3612 got negative ranges working with (much, much) uglier compiled code 2009-12-26 20:35:43 -08:00
Jeremy Ashkenas
b4250c0f02 that's it for now for significant whitespace -- I really just can't make flexible enough 2009-12-26 19:29:59 -08:00
Jeremy Ashkenas
cc0c92d20d smarter but uglier lexer -- now handles most significant whitespace cases. Clean it up though... (newlines after outdents) 2009-12-26 13:22:53 -08:00
Jeremy Ashkenas
694833dbd0 removing no_paren -- it was optimizing away order of operations 2009-12-26 11:55:34 -08:00
Jeremy Ashkenas
fde9852090 removing no_paren -- can cause order of operations errors 2009-12-26 11:10:59 -08:00
Jeremy Ashkenas
191875a85b got a lexer working along the lines of what kamatsu proposes 2009-12-26 10:59:47 -08:00
Jeremy Ashkenas
556f8cb68a little more progress on whitespace 2009-12-26 10:49:11 -08:00
Jeremy Ashkenas
5bed5646be merging in master 2009-12-26 09:59:06 -08:00
Jeremy Ashkenas
08dddb27a0 adding newline escaping, with tests 2009-12-26 09:29:03 -08:00
Jeremy Ashkenas
2a1fc4b1b7 docs 2009-12-26 09:05:57 -08:00
Jeremy Ashkenas
3c67d54bbe changed bin/coffee-script to bin/coffee 2009-12-26 08:57:13 -08:00
Jeremy Ashkenas
6a30d48ced fixed range comprehension indexing 2009-12-26 00:27:49 -08:00
Jeremy Ashkenas
d59ef71642 trading the cs> prompt for the coffee> prompt 2009-12-26 00:18:24 -08:00
Jeremy Ashkenas
ff78546465 added array comprehensions over ranges 2009-12-26 00:16:40 -08:00
Jeremy Ashkenas
834442148b docs for assignment-as-expression 2009-12-25 23:17:34 -08:00
Jeremy Ashkenas
adaae0ccae major internal reworking -- all variable declarations have been pushed up to the first line of the block scope -- all assignment is now an inherent expression 2009-12-25 22:57:33 -08:00
Jeremy Ashkenas
7c132d65dc started raising syntax errors for parens wrapped around expressions (they used to silently be ignored) 2009-12-25 20:36:22 -08:00
Jeremy Ashkenas
b58102c514 don't add the no_wrap key to the options hash unless we're going to use it 2009-12-25 19:48:47 -08:00
Jeremy Ashkenas
52700ca922 comment 2009-12-25 19:34:40 -08:00
Jeremy Ashkenas
dd5317ebe9 documenting ranges and slices 2009-12-25 16:35:57 -08:00
Jeremy Ashkenas
1ba7c77136 reorganizing test fixtures and adding range literals for array slices 2009-12-25 16:20:28 -08:00
Jeremy Ashkenas
62485c2b8c CoffeeScript 0.1.4 2009-12-25 14:43:24 -08:00
Jeremy Ashkenas
d46bf8ee71 moved the coffeescript extension over from .cs to .coffee -- let's leave C# in peace. Changed array comprehensions to always return their mapped result, even when unassigned 2009-12-25 14:18:05 -08:00
Jeremy Ashkenas
e494d520ea stopped using __proto__, instead, using a variant of goog.inherits for extends and super() 2009-12-25 13:57:47 -08:00
Jeremy Ashkenas
f55b4cd8b6 ForBody is really the ForSource 2009-12-25 13:40:57 -08:00
Jeremy Ashkenas
763e04fec9 cleaned up the for grammar and eliminated a shift/reduce conflict 2009-12-25 13:39:33 -08:00
Jeremy Ashkenas
4b5db1181c make equals signs full equals of colons -- you can use them inside of object literals now too 2009-12-25 13:21:17 -08:00
Jeremy Ashkenas
bc6ec37272 allowing = to assign 2009-12-25 07:42:27 -08:00
Jeremy Ashkenas
55bf0a2c61 going back to familiar operators +: is just too strange 2009-12-25 07:31:51 -08:00
Jeremy Ashkenas
968aeec523 added a test to make sure that chained calls work 2009-12-25 07:16:59 -08:00
Jeremy Ashkenas
851ec82495 allowing chained function calls, one right after another 2009-12-25 07:08:57 -08:00
Jeremy Ashkenas
c4ba971d39 bumping to 0.1.3 ... here we go 2009-12-25 00:16:56 -08:00
Jeremy Ashkenas
e7e8e243a2 better error warnings on the command line 2009-12-25 00:02:27 -08:00
Jeremy Ashkenas
73aaf127c8 removed bin/cs in favor of a more comprehensive coffee-script command ... now with --interactive and --run 2009-12-24 23:57:27 -08:00
Jeremy Ashkenas
7a0de52c96 majorly cleaned up the CoffeeScript that defines the Narwhal integration 2009-12-24 23:28:01 -08:00
Jeremy Ashkenas
2d57ee693b the narwhal integration written in JavaScript has been replaced with CoffeeScript, and compiler-generated variable names now start with '__' 2009-12-24 23:09:24 -08:00
Jeremy Ashkenas
d8ceb3b4bb sped up the execution test a good deal by running it all in one pass 2009-12-24 22:29:30 -08:00
Jeremy Ashkenas
beae912a91 making all assignment-y operators use a colon -- now it's +: -: *: /:, and friends 2009-12-24 22:25:29 -08:00
Jeremy Ashkenas
6865f5be92 removed dependency on v8 in favor of bin/cs 2009-12-24 22:08:32 -08:00
tlrobinson
2f35bba083 Print compiler errors to stderr 2009-12-24 19:34:17 -08:00
Jeremy Ashkenas
378e156e11 fixed the bin/cs repl to save assignment between commands by using the new --no-wrap 2009-12-24 17:45:23 -08:00
Jeremy Ashkenas
9b2326492b the --no-wrap option now disables top-level var declarations 2009-12-24 17:37:24 -08:00
Jeremy Ashkenas
93009e07f6 updating docs for isnt 2009-12-24 17:22:46 -08:00
Jeremy Ashkenas
985e0a080b trading aint for isnt -- let's be serious 2009-12-24 17:21:20 -08:00
Jeremy Ashkenas
95bfb0b45c allowing quoted strings within object assignment, a in JS and JSON 2009-12-24 17:14:53 -08:00
Jeremy Ashkenas
65e9ba4c30 bumping to 0.1.2 to get the super()/extends fix out there 2009-12-24 17:05:55 -08:00
Jeremy Ashkenas
1c83e68292 got extends back in the language -- use it together with super 2009-12-24 16:49:23 -08:00
Jeremy Ashkenas
47812d9ea6 fixing super() calls, thanks to tolmasky 2009-12-24 16:23:23 -08:00
Jeremy Ashkenas
a80b532a05 removing the special-case std-reading in favor of '--eval' 2009-12-24 15:49:42 -08:00
Jeremy Ashkenas
42ca566d26 document that -e can read from stdin 2009-12-24 15:35:58 -08:00
Jeremy Ashkenas
e27756cee8 with a working -n --no-wrap option to disable the top-level function safety wrapper 2009-12-24 15:31:00 -08:00
Jeremy Ashkenas
46f81c2de1 Merge branch 'master' of git://github.com/tlrobinson/coffee-script 2009-12-24 15:05:56 -08:00
Jeremy Ashkenas
c3ff752c40 ... 2009-12-24 15:05:14 -08:00
Jeremy Ashkenas
73a0777705 outdent lexing is correct now, I think 2009-12-24 14:51:53 -08:00
tlrobinson
9f80998415 Command line CoffeeScript 2009-12-24 14:42:57 -08:00
tlrobinson
dbccc1fa4f Narwhal support for CoffeeScript 2009-12-24 14:41:35 -08:00
tlrobinson
08248180f9 Read from stdin if source is "-" 2009-12-24 14:40:39 -08:00
Jeremy Ashkenas
ed504ea6be added and -> &&, or -> || to the docs (they were missing) 2009-12-24 14:37:30 -08:00
Jeremy Ashkenas
da84906d1e this might not work for ))) outdent cases 2009-12-24 14:34:48 -08:00
Jeremy Ashkenas
aafd3cd6ea first, totally broken branch of significant whitespace -- it can handle examples/whitespace.cs though 2009-12-24 13:48:46 -08:00
Jeremy Ashkenas
39ceca477d docs for 0.1.1 2009-12-24 12:02:28 -08:00
Jeremy Ashkenas
bfb24c6b5d bumping to 0.1.1 2009-12-24 11:59:19 -08:00
Jeremy Ashkenas
7f502543d2 added the typeof operater as an OpNode 2009-12-24 11:50:44 -08:00
Jeremy Ashkenas
5d1ec9d2a9 added the instanceof operator to the grammar as an operation node 2009-12-24 11:46:51 -08:00
Jeremy Ashkenas
2e8f03b4cc another wish 2009-12-24 10:31:44 -08:00
Jeremy Ashkenas
840e2b89fc docs 2009-12-24 09:56:44 -08:00
Jeremy Ashkenas
c438123a3d added a wish list to the docs 2009-12-24 09:54:12 -08:00
Jeremy Ashkenas
726a9b229e doc tweaks 2009-12-24 01:38:32 -08:00
Jeremy Ashkenas
8d76f4bd3f changing switch/case to switch/when -- it's a better word 2009-12-24 01:33:59 -08:00
Jeremy Ashkenas
849f0e4192 added comprehensive linting to the test suit 2009-12-24 00:49:11 -08:00
Jeremy Ashkenas
47928ca952 fixed the broken try/catch grammar 2009-12-24 00:45:16 -08:00
Jeremy Ashkenas
fb13a303f2 with a more comprehensive execution test that uncovered some missing spots 2009-12-24 00:41:12 -08:00
Jeremy Ashkenas
b743e3219a added some execution test 2009-12-24 00:12:07 -08:00
Jeremy Ashkenas
417753bd62 added readme 2009-12-23 23:12:29 -08:00
Jeremy Ashkenas
705b293982 first draft of docs are done 2009-12-23 23:01:39 -08:00
Jeremy Ashkenas
0a58eeef2b waypoint 2009-12-24 01:22:41 -05:00
Jeremy Ashkenas
b1f3ad24a2 added git st with the new operator regex 2009-12-24 00:37:33 -05:00
Jeremy Ashkenas
2b94849429 ported over a little more underscore 2009-12-23 21:09:32 -05:00
Jeremy Ashkenas
eae53d4787 added the ! sign as an allowed operator 2009-12-23 21:00:04 -05:00
Jeremy Ashkenas
5f9a190683 ... 2009-12-23 20:57:35 -05:00
Jeremy Ashkenas
cdfb5091be more better super docs, better switch docs 2009-12-23 20:48:55 -05:00
Jeremy Ashkenas
64879cdc66 added yes, no, on and off as boolean aliases and a nice aliases section to the docs 2009-12-23 20:24:55 -05:00
Jeremy Ashkenas
a4d014549b broken waypoint, but fixed line numbers with the new JS comments 2009-12-23 19:42:44 -05:00
Jeremy Ashkenas
60eabf63cf broken waypoint, but fixed line numbers with the new JS comments 2009-12-23 19:42:18 -05:00
Jeremy Ashkenas
6555473788 for whatever reason, don't need to force else-bodies to compile as statements anymore ... let them do what they want 2009-12-22 12:18:27 -05:00
Jeremy Ashkenas
e916d4648d removed all traces of 'extends' -- it's not any shorter or more convenient than just setting the prototype 2009-12-22 12:08:29 -05:00
Jeremy Ashkenas
ec58d6fda2 got comments within object and array literals working out 2009-12-22 11:50:43 -05:00
Jeremy Ashkenas
65809d08f6 first draft of parsing and printing along comments -- unfortunately, not yet working within objects and arrays 2009-12-22 11:27:19 -05:00
Jeremy Ashkenas
d45643c527 passing through comments as tags on Values, but not printing them out quite yet... 2009-12-22 10:48:58 -05:00
Jeremy Ashkenas
9b8f018646 nice -- it's pushing down assignments properly (recursively) now 2009-12-22 10:16:53 -05:00
Jeremy Ashkenas
2f211196a2 moderate refactor of nodes.rb -- tests pass and examples compile without warnings 2009-12-22 10:11:41 -05:00
Jeremy Ashkenas
9bb3e3fbe8 clean up children at exit -- had about twenty processes all watching and recompiling the docs 2009-12-21 12:15:13 -05:00
Jeremy Ashkenas
c7fa9c320a documentation waypoint 2009-12-21 11:41:45 -05:00
Jeremy Ashkenas
dcc70e5ab0 added full complement of bitwise operators 2009-12-19 22:56:27 -05:00
Jeremy Ashkenas
93bdfcb72a added full complement of bitwise operators 2009-12-19 22:55:58 -05:00
Jeremy Ashkenas
9ba1ffde21 making the each fixture a little more like underscore, and avoiding passing assignment into functions from the outside 2009-12-19 00:45:36 -05:00
Jeremy Ashkenas
0b2e7f1e59 added the verbose option to the CLI 2009-12-19 00:37:54 -05:00
Jeremy Ashkenas
b2e6a34d40 more little fixes, lots of subtle things, added a verbose logging mode 2009-12-19 00:33:34 -05:00
Jeremy Ashkenas
ad3b887df4 lots of tweaks make the tests pass again 2009-12-18 23:13:59 -05:00
Jeremy Ashkenas
6f81ac3684 patched up array comprehensions somewhat. Parens are still a necessary evil, and there's still probably plenty of edge cases 2009-12-18 22:30:09 -05:00
Jeremy Ashkenas
2f75854a61 little fixes more examples 2009-12-18 09:55:31 -05:00
Jeremy Ashkenas
253e45fc54 adding css for syntax highlighting 2009-12-18 08:36:20 -05:00
Jeremy Ashkenas
31639d7d1a todo to-done 2009-12-18 07:40:26 -05:00
Jeremy Ashkenas
6ba5d45cbe finished the first draft of the parser test 2009-12-18 07:28:26 -05:00
Jeremy Ashkenas
f154ab3d15 adding comprehensive attr_readers to the AST for testing 2009-12-18 07:21:59 -05:00
Jeremy Ashkenas
669c065dd7 parser test raises some minor improvements (remove unnecessary ValueNode arrays, etc 2009-12-18 07:11:01 -05:00
Jeremy Ashkenas
92adabdddc adding an initial lexer test 2009-12-18 06:59:06 -05:00
Jeremy Ashkenas
049358d006 after a lot of grammar wrestling, got the if-else chains to parse unambiguously. Now you only need a single period to close chains of any length. 2009-12-18 00:49:23 -05:00
Jeremy Ashkenas
a50446a0ca finally got the function/object/variable assignment indentation straightened out, I think 2009-12-17 23:45:24 -05:00
Jeremy Ashkenas
67bb49ed04 compiling if-else chains into nice flat ones 2009-12-17 23:34:52 -05:00
Jeremy Ashkenas
1395b05d36 first major rework of the nodes -- still need more comments and templatish cleanup, but character tagging is all settled 2009-12-17 23:22:02 -05:00
Jeremy Ashkenas
83944950ac renamed Nodes to Expressions 2009-12-17 22:58:40 -05:00
Jeremy Ashkenas
d124f7fc0d finished commenting everything but the nodes -- they're up next 2009-12-17 22:54:24 -05:00
Jeremy Ashkenas
77704d24a2 finished commenting the grammar 2009-12-17 22:22:35 -05:00
Jeremy Ashkenas
68bc68c1ac many more comments, plus a fix for inner-assignment indentation 2009-12-17 22:13:29 -05:00
Jeremy Ashkenas
8511a33b1e commented the command-line interface 2009-12-17 21:57:21 -05:00
Jeremy Ashkenas
6050cad0f8 moved the TextMate bundle into the gem, added a command to install it 2009-12-17 21:46:12 -05:00
Jeremy Ashkenas
9976de76f5 added the 'delete' operator 2009-12-17 21:21:07 -05:00
Jeremy Ashkenas
0dc445138b removed the 'default' keyword in favor of an 'else' 2009-12-17 21:14:36 -05:00
Jeremy Ashkenas
3ffbf541df removed class checks in favor of statement? 2009-12-17 21:10:49 -05:00
Jeremy Ashkenas
e3c667d49d number examples 2009-12-17 21:00:31 -05:00
Jeremy Ashkenas
2c90e8b002 added exponential and hex numbers 2009-12-17 20:59:19 -05:00
Jeremy Ashkenas
398251ff90 added a nice --watch mode to continually recompile or relint (or reprint) your coffeescripts 2009-12-17 20:37:39 -05:00
Jeremy Ashkenas
9249ceaef5 cleanups getting underscore to compile 2009-12-17 10:33:57 -05:00
Jeremy Ashkenas
1eec05d23a added nice syntax errors 2009-12-17 10:04:43 -05:00
Jeremy Ashkenas
1590713576 passing through values with line number information that look and act like Ruby natives 2009-12-17 09:37:42 -05:00
Jeremy Ashkenas
146b5694c2 cleaned up lexer in order to add line numbers 2009-12-17 09:29:49 -05:00
Jeremy Ashkenas
1d35910567 added the ability to super() 2009-12-17 09:07:42 -05:00
Jeremy Ashkenas
1a8311b9d0 allowing inner slashes in regexes 2009-12-17 08:29:19 -05:00
Jeremy Ashkenas
4e1e119f58 supporting escaped quotes in strings 2009-12-17 08:26:46 -05:00
Jeremy Ashkenas
3dac0f6d84 supporting escaped quotes in strings 2009-12-17 08:26:20 -05:00
Jeremy Ashkenas
962885444e multiline strings 2009-12-17 08:23:17 -05:00
Jeremy Ashkenas
d1682f5b3f multiline strings 2009-12-17 08:23:07 -05:00
Jeremy Ashkenas
c6f11fbfeb built the first gem -- works just fine 2009-12-16 23:10:03 -05:00
Jeremy Ashkenas
290aa257de completely reorganized for a gem and the 'coffee-script' command 2009-12-16 22:42:53 -05:00
230 changed files with 21369 additions and 3336 deletions

7
.gitignore vendored
View File

@@ -1 +1,6 @@
parser.output
presentation
test.coffee
parser.output
test/fixtures/underscore
examples/beautiful_code/parse.coffee
*.gem

65
Cakefile Normal file
View File

@@ -0,0 +1,65 @@
fs: require 'fs'
coffee: require 'coffee-script'
# Run a CoffeeScript through our node/coffee interpreter.
run: (args) ->
proc: process.createChildProcess 'bin/coffee', args
proc.addListener 'error', (err) -> if err then puts err
task 'install', 'install CoffeeScript into /usr/local', ->
exec([
'mkdir -p /usr/local/lib/coffee-script'
'cp -rf bin lib LICENSE README package.json src vendor /usr/local/lib/coffee-script'
'ln -sf /usr/local/lib/coffee-script/lib/bin/coffee /usr/local/bin/coffee'
'ln -sf /usr/local/lib/coffee-script/lib/bin/cake /usr/local/bin/cake'
].join(' && '))
task 'build', 'build the CoffeeScript language from source', ->
fs.readdir 'src', (err, files) ->
files: 'src/' + file for file in files when file.match(/\.coffee$/)
run ['-o', 'lib'].concat(files)
task 'build:parser', 'rebuild the Jison parser (run build first)', ->
parser: require('grammar').parser
js: parser.generate()
parser_path: 'lib/parser.js'
fs.writeFile parser_path, js
task 'build:ultraviolet', 'build and install the Ultraviolet syntax highlighter', ->
exec 'plist2syntax extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage', (err) ->
exec 'sudo mv coffeescript.yaml /usr/local/lib/ruby/gems/1.8/gems/ultraviolet-0.10.2/syntax/coffeescript.syntax'
task 'build:underscore', 'rebuild the Underscore.coffee documentation page', ->
exec 'uv -s coffeescript -t idle -h examples/underscore.coffee > documentation/underscore.html'
task 'build:browser', 'rebuild the merged script for inclusion in the browser', ->
exec 'rake browser'
task 'doc', 'watch and continually rebuild the documentation', ->
exec 'rake doc'
task 'test', 'run the CoffeeScript language test suite', ->
process.mixin require 'assert'
test_count: 0
start_time: new Date()
[original_ok, original_throws]: [ok, throws]
process.mixin {
ok: (args...) -> test_count += 1; original_ok(args...)
throws: (args...) -> test_count += 1; original_throws(args...)
}
process.addListener 'exit', ->
time: ((new Date() - start_time) / 1000).toFixed(2)
puts '\033[0;32mpassed ' + test_count + ' tests in ' + time + ' seconds\033[0m'
fs.readdir 'test', (err, files) ->
for file in files
fs.readFile 'test/' + file, (err, source) ->
js: coffee.compile source
process.compile js, file

22
LICENSE Normal file
View File

@@ -0,0 +1,22 @@
Copyright (c) 2010 Jeremy Ashkenas
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
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.

41
README Normal file
View File

@@ -0,0 +1,41 @@
=
{
} } {
{ { } }
} }{ {
{ }{ } } _____ __ __
( }{ }{ { ) / ____| / _|/ _|
.- { { } { }} -. | | ___ | |_| |_ ___ ___
( ( } { } { } } ) | | / _ \| _| _/ _ \/ _ \
|`-..________ ..-'| | |___| (_) | | | || __/ __/
| | \_____\___/|_| |_| \___|\___|
| ;--.
| (__ \ _____ _ _
| | ) ) / ____| (_) | |
| |/ / | (___ ___ _ __ _ _ __ | |_
| ( / \___ \ / __| '__| | '_ \| __|
| |/ ____) | (__| | | | |_) | |_
| | |_____/ \___|_| |_| .__/ \__|
`-.._________..-' | |
|_|
CoffeeScript is a little language that compiles into JavaScript.
Install Node.js, and then the CoffeeScript compiler:
sudo bin/cake install
Compile a script:
coffee /path/to/script.coffee
For documentation, usage, and examples, see:
http://coffeescript.org/
To suggest a feature, report a bug, or general discussion:
http://github.com/jashkenas/coffee-script/issues/
If you'd like to chat, drop by #coffeescript on Freenode.
The source repository:
git://github.com/jashkenas/coffee-script.git

31
Rakefile Normal file
View File

@@ -0,0 +1,31 @@
require 'erb'
require 'fileutils'
require 'rake/testtask'
require 'rubygems'
require 'yui/compressor'
desc "Build the documentation page"
task :doc do
source = 'documentation/index.html.erb'
child = fork { exec "bin/coffee documentation/coffee/*.coffee -o documentation/js -w" }
at_exit { Process.kill("INT", child) }
Signal.trap("INT") { exit }
loop do
mtime = File.stat(source).mtime
if !@mtime || mtime > @mtime
rendered = ERB.new(File.read(source)).result(binding)
File.open('index.html', 'w+') {|f| f.write(rendered) }
end
@mtime = mtime
sleep 1
end
end
desc "Build the single concatenated and minified script for the browser"
task :browser do
sources = %w(rewriter.js lexer.js parser.js scope.js nodes.js coffee-script.js)
code = sources.map {|s| File.read('lib/' + s) }.join('')
code = YUI::JavaScriptCompressor.new.compress(code)
File.open('extras/coffee-script.js', 'w+') {|f| f.write(code) }
end

30
SYNTAX
View File

@@ -1,30 +0,0 @@
Every line is an expression. Multiple expressions on a single line can be
separated by a ";" character.
NUM: 1
1.0
STRING: "hello"
'hello'
OBJECT: {one : 1, two : 2}
ARRAY: [1, 2, 3]
CODE: a, b => a * b.
IF: return x if x > 1
if (x > 1) return x
ASSIGN: a : b
LOGICAL: x && y
x and y
x || y
x or y

View File

@@ -1,6 +0,0 @@
* Is it possible to close blocks (functions, ifs, trys) without an explicit
block delimiter or significant whitespace?
* Is it possible to pass comments through cleanly and have them show up on
the other end? This includes comments in the middle of array and object
literals, and argument lists.

7
bin/cake Executable file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env node
process.mixin(require('sys'));
require.paths.unshift(__dirname + '/../lib');
require('cake').run();

7
bin/coffee Executable file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env node
process.mixin(require('sys'));
require.paths.unshift(__dirname + '/../lib');
require('command_line').run();

126
code.cs
View File

@@ -1,126 +0,0 @@
# TODO: Add range indexing: array[5..7] => array.slice(5, 7)
# Functions:
square: x => x * x.
sum: x, y => x + y.
odd: x => x % 2 is 0.
even: x => x % 2 aint 0.
run_loop: =>
fire_events( e => e.stopPropagation(). )
listen()
wait().
# Objects:
dense_object_literal: {one: 1, two: 2, three: 3}
spaced_out_multiline_object: {
pi: 3.14159
list: [1, 2, 3, 4]
three: new Idea()
inner_obj: {
freedom: => _.freedom().
}
}
# Arrays:
stooges : [{moe: 45}, {curly: 43}, {larry: 46}]
exponents : [x => x., x => x * x., x => x * x * x.]
empty: []
# Conditionals and ternaries.
if submarine.shields_up
full_speed_ahead()
fire_torpedos()
else
run_away().
eldest: if 25 > 21 then liz else marge.
decoration: medal_of_honor if war_hero
go_to_sleep() unless coffee
# Returning early:
race: =>
run()
walk()
crawl()
if tired then return sleep().
race().
# Conditional operators:
good ||= evil
wine &&= cheese
# Nested property access and calls.
((moon.turn(360))).shapes[3].move({x: 45, y: 30}).position
a: b: c: 5
# Embedded JavaScript.
callback(
`function(e) { e.stop(); }`
)
# Try/Catch/Finally/Throw.
try
all_hell_breaks_loose()
dogs_and_cats_living_together()
throw "up"
catch error
print( error )
finally
clean_up().
try all_hell_breaks_loose() catch error print(error) finally clean_up().
# While loops.
while demand > supply
sell()
restock().
while supply > demand then buy().
# Unary operators.
!!true
# Lexical scoping.
a: 5
change_a_and_set_b: =>
a: 10
b: 15.
b: 20
# Array comprehensions.
supper: food.capitalize() for food in ['toast', 'cheese', 'wine'].
drink(bottle) for bottle, i in ['soda', 'wine', 'lemonade'] if even(i).
# Switch statements.
switch day
case "Tuesday" then eat_breakfast()
case "Sunday" then go_to_church()
case "Saturday" then go_to_the_park()
case "Wednesday"
eat_breakfast()
go_to_work()
eat_dinner()
default go_to_work().
# Semicolons can optionally be used instead of newlines.
wednesday: => eat_breakfast(); go_to_work(); eat_dinner(); .
# Array slice literals.
zero_to_nine: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
three_to_six: zero_to_nine[3, 6]

View File

@@ -0,0 +1,9 @@
launch() if ignition is on
volume: 10 if band isnt spinal_tap
let_the_wild_rumpus_begin() unless answer is no
if car.speed < speed_limit then accelerate()
print "My name is " + @name

View File

@@ -0,0 +1,4 @@
backwards: ->
alert arguments.reverse()
backwards "stairway", "to", "heaven"

View File

@@ -0,0 +1,7 @@
# Eat lunch.
lunch: eat(food) for food in ['toast', 'cheese', 'wine']
# Naive collision detection.
for roid in asteroids
for roid2 in asteroids when roid isnt roid2
roid.explode() if roid.overlaps roid2

View File

@@ -0,0 +1,2 @@
greeting: "Hello CoffeeScript"
difficulty: 0.5

View File

@@ -0,0 +1,5 @@
process.mixin require 'assert'
task 'test', 'run each of the unit tests', ->
for test in test_files
fs.readFile test, (err, code) -> eval coffee.compile code

View File

@@ -0,0 +1,5 @@
cholesterol: 127
healthy: 200 > cholesterol > 60

View File

@@ -0,0 +1,9 @@
mood: greatly_improved if singing
if happy and knows_it
claps_hands()
cha_cha_cha()
date: if friday then sue else jill
expensive ||= do_the_math()

View File

@@ -0,0 +1,5 @@
hi: `function() {
return [document.title, "Hello JavaScript"].join(": ");
}`

View File

@@ -0,0 +1,8 @@
solipsism: true if mind? and not world?
speed ?= 140

View File

@@ -0,0 +1,9 @@
grade: (student) ->
if student.excellent_work
"A+"
else if student.okay_stuff
if student.tried_hard then "B" else "B-"
else
"C"
eldest: if 24 > 21 then "Liz" else "Ike"

View File

@@ -0,0 +1 @@
six: (one: 1) + (two: 2) + (three: 3)

View File

@@ -0,0 +1,3 @@
# The first ten global properties.
globals: (name for name of window)[0...10]

View File

@@ -0,0 +1,6 @@
alert(
try
nonexistent / undefined
catch error
"And the error is ... " + error
)

View File

@@ -0,0 +1,6 @@
Account: (customer, cart) ->
@customer: customer
@cart: cart
$('.shopping_cart').bind 'click', (event) =>
@customer.purchase @cart

View File

@@ -0,0 +1,2 @@
square: (x) -> x * x
cube: (x) -> square(x) * x

View File

@@ -0,0 +1,5 @@
html: '''
<strong>
cup of coffeescript
</strong>
'''

View File

@@ -0,0 +1,5 @@
weather_report: (location) ->
# Make an Ajax request to fetch the weather...
[location, 72, "Mostly Sunny"]
[city, temp, forecast]: weather_report "Berkeley, CA"

View File

@@ -0,0 +1,4 @@
years_old: {max: 10, ida: 9, tim: 11}
ages: for child, age of years_old
child + " is " + age

View File

@@ -0,0 +1,13 @@
futurists: {
sculptor: "Umberto Boccioni"
painter: "Vladimir Burliuk"
poet: {
name: "F.T. Marinetti"
address: [
"Via Roma 42R"
"Bellagio, Italy 22021"
]
}
}
{poet: {name: poet, address: [street, city]}}: futurists

View File

@@ -0,0 +1,13 @@
song: ["do", "re", "mi", "fa", "so"]
ages: {
max: 10
ida: 9
tim: 11
}
matrix: [
1, 0, 1
0, 0, 1
1, 1, 0
]

View File

@@ -0,0 +1,29 @@
# Assignment:
number: 42
opposite_day: true
# Conditions:
number: -42 if opposite_day
# Functions:
square: (x) -> x * x
# Arrays:
list: [1, 2, 3, 4, 5]
# Objects:
math: {
root: Math.sqrt
square: square
cube: (x) -> x * square x
}
# Splats:
race: (winner, runners...) ->
print winner, runners
# Existence:
alert "I knew it!" if elvis?
# Array comprehensions:
cubed_list: math.cube num for num in list

View File

@@ -0,0 +1,4 @@
bait: 1000
and_switch: 0
[bait, and_switch]: [and_switch, bait]

View File

@@ -0,0 +1,6 @@
countdown: num for num in [10..1]
egg_delivery: ->
for i in [0...eggs.length] by 12
dozen_eggs: eggs[i...i+12]
deliver new egg_carton(dozen)

View File

@@ -0,0 +1,5 @@
num: 1
change_numbers: ->
new_num: -1
num: 10
new_num: change_numbers()

View File

@@ -0,0 +1,6 @@
numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
three_to_six: numbers[3..6]
numbers_copy: numbers[0...numbers.length]

View File

@@ -0,0 +1 @@
lottery.draw_winner()?.address?.zipcode

View File

@@ -0,0 +1,25 @@
gold: silver: the_field: "unknown"
award_medals: (first, second, rest...) ->
gold: first
silver: second
the_field: rest
contenders: [
"Michael Phelps"
"Liu Xiang"
"Yao Ming"
"Allyson Felix"
"Shawn Johnson"
"Roman Sebrle"
"Guo Jingjing"
"Tyson Gay"
"Asafa Powell"
"Usain Bolt"
]
award_medals contenders...
alert "Gold: " + gold
alert "Silver: " + silver
alert "The Field: " + the_field

View File

@@ -0,0 +1,5 @@
numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
numbers[3..6]: [-3, -4, -5, -6]

View File

@@ -0,0 +1,8 @@
moby_dick: "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

@@ -0,0 +1,34 @@
Animal: ->
Animal::move: (meters) ->
alert @name + " moved " + meters + "m."
Snake: (name) ->
@name: name
this
Snake extends Animal
Snake::move: ->
alert "Slithering..."
super 5
Horse: (name) ->
@name: name
this
Horse extends Animal
Horse::move: ->
alert "Galloping..."
super 45
sam: new Snake "Sammy the Python"
tom: new Horse "Tommy the Palomino"
sam.move()
tom.move()

View File

@@ -0,0 +1,10 @@
switch day
when "Mon" then go_to_work()
when "Tue" then go_to_the_park()
when "Thu" then go_ice_fishing()
when "Fri", "Sat"
if day is bingo_day
go_to_bingo()
go_dancing()
when "Sun" then go_to_church()
else go_to_work()

View File

@@ -0,0 +1,7 @@
try
all_hell_breaks_loose()
cats_and_dogs_living_together()
catch error
print error
finally
clean_up()

View File

@@ -0,0 +1,10 @@
# Econ 101
if this.studying_economics
while supply > demand then buy()
while supply < demand then sell()
# Nursery Rhyme
num: 6
lyrics: while num -= 1
num + " little monkeys, jumping on the bed.
One fell out and bumped his head."

213
documentation/css/docs.css Normal file
View File

@@ -0,0 +1,213 @@
body {
font-size: 14px;
line-height: 20px;
color: #191933;
font-family: Arial, Helvetica, sans-serif;
}
div.container {
width: 950px;
margin: 100px 0 50px 50px;
}
p {
width: 625px;
}
a {
color: #000055;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 40px;
}
br.clear {
height: 0;
clear: both;
}
ul {
padding-left: 20px;
}
b.header {
color: #000055;
display: block;
margin: 40px 0 5px 0;
font-size: 16px;
}
li {
margin-bottom: 10px;
}
table {
margin: 16px 0 0 13px; padding: 0;
width: 625px;
}
tr, td {
margin: 0; padding: 0;
}
td {
padding: 9px 15px 9px 0;
}
code, pre, tt, textarea {
font-family: Monaco, Consolas, "Lucida Console", monospace;
font-size: 12px;
line-height: 18px;
color: #191955;
white-space: pre-wrap;
word-wrap: break-word;
}
tt {
background: #f8f8ff;
border: 1px solid #dedede;
font-size: 85%;
padding: 0px 0.2em;
}
pre {
border-left: 6px solid #222255;
margin-left: 13px;
padding: 3px 0 3px 12px;
font-size: 12px;
}
pre.no_bar {
border-left: 0;
margin-left: 0;
padding-left: 0;
}
div.code {
position: relative;
border: 1px solid #cacaca;
background: #fafaff;
padding: 7px 0 10px 0;
-moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px;
-webkit-box-shadow: 0px 0px 7px #cacaca;
}
div.code button {
position: absolute;
right: 8px; bottom: 8px;
}
div.code pre, div.code textarea {
float: left;
width: 450px;
background: #fafaff;
border-left: 1px dotted #559;
padding: 0 0 0 12px;
margin: 0;
}
div.code pre:first-child {
border-left: 0;
}
#fadeout {
z-index: 50;
position: fixed;
left: 0; top: 0; right: 0;
height: 100px;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 255, 255)), to(rgba(255, 255, 255, 0)));
background: -moz-linear-gradient(top, rgba(255, 255, 255, 255), rgba(255, 255, 255, 0));
}
#flybar {
position: fixed;
z-index: 100;
height: 50px;
left: 40px; right: 40px; top: 25px;
background: #ddd;
padding-left: 235px;
background: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#d0d0d0));
background: -moz-linear-gradient(top, #f5f5f5, #d0d0d0);
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#F5F5F5', EndColorStr='#D0D0D0');
-webkit-border-radius: 20px; -moz-border-radius: 20px; border-radius: 20px;
-webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
}
#logo {
display: block;
width: 215px; height: 50px;
background: url('logo.png');
position: absolute;
top: 0px; left: 10px;
}
.navigation {
height: 50px;
font: bold 11px/50px Arial;
text-transform: uppercase;
position: relative;
float: left;
padding: 0 20px;
border: 1px solid #bbb;
border-top: 0; border-bottom: 0;
cursor: pointer;
}
.navigation.try {
border-left: 0;
}
.navigation:hover,
.navigation.active {
background: #d0d0d0;
background: -webkit-gradient(linear, left top, left bottom, from(#f0f0f0), to(#c0c0c0));
background: -moz-linear-gradient(top, #f0f0f0, #c0c0c0);
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#F0F0F0', EndColorStr='#C0C0C0');
}
.navigation .contents {
display: none;
position: absolute;
background: #fff;
top: 50px; left: 0;
padding: 5px 0;
-webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px;
-webkit-border-top-left-radius: 0; -moz-border-radius-topleft: 0;
-webkit-border-top-right-radius: 0; -moz-border-radius-topright: 0;
-webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
}
.navigation.active .contents {
display: block;
}
.navigation .contents.repl_wrapper {
left: -162px;
width: 700px;
padding: 0;
}
.navigation .contents.repl_wrapper .code {
-webkit-box-shadow: none; -moz-box-shadow: none;
background: transparent;
border: 0;
}
.navigation .code button {
bottom: 10px;
}
.navigation .compile {
left: 240px; right: auto;
}
.navigation .contents a {
display: block;
width: 300px;
text-transform: none;
text-decoration: none;
font-weight: normal;
height: 12px;
line-height: 12px;
padding: 4px 10px;
}
.navigation .contents a:hover {
background: #f0f0f0;
}
.bookmark {
display: block;
width: 0; height: 0;
position: relative;
top: -90px;
}
#repl_source, #repl_results {
background: transparent;
}
#repl_source {
border: 0;
padding: 5px 7px;
margin-left: 5px;
min-height: 250px;
resize: none;
width: 295px;
}
#repl_results {
font-family: Monaco, Consolas, "Lucida Console", monospace;
text-transform: none;
font-weight: normal;
min-height: 260px;
width: 355px;
}

View File

@@ -0,0 +1,63 @@
pre.idle .InheritedClass {
}
pre.idle .TypeName {
color: #21439C;
}
pre.idle .Number {
}
pre.idle .LibraryVariable {
color: #A535AE;
}
pre.idle .Storage {
color: #FF5600;
}
pre.idle .line-numbers {
background-color: #BAD6FD;
color: #000000;
}
pre.idle {
background-color: #FFFFFF;
color: #000000;
}
pre.idle .StringInterpolation {
color: #990000;
}
pre.idle .TagName {
}
pre.idle .LibraryConstant {
color: #A535AE;
}
pre.idle .FunctionArgument {
color: #0076ad;
}
pre.idle .BuiltInConstant {
color: #A535AE;
}
pre.idle .Invalid {
background-color: #990000;
color: #FFFFFF;
}
pre.idle .LibraryClassType {
color: #A535AE;
}
pre.idle .LibraryFunction {
color: #A535AE;
}
pre.idle .TagAttribute {
}
pre.idle .Keyword {
color: #FF5600;
}
pre.idle .UserDefinedConstant {
}
pre.idle .String {
color: #00A33F;
}
pre.idle .FunctionName {
color: #21439C;
}
pre.idle .Variable {
}
pre.idle .Comment {
color: #919191;
}

BIN
documentation/css/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

1002
documentation/index.html.erb Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
(function(){
var volume;
if (ignition === true) {
launch();
}
if (band !== spinal_tap) {
volume = 10;
}
if (!(answer === false)) {
let_the_wild_rumpus_begin();
}
car.speed < speed_limit ? accelerate() : null;
print("My name is " + this.name);
})();

View File

@@ -0,0 +1,8 @@
(function(){
var backwards;
backwards = function backwards() {
arguments = Array.prototype.slice.call(arguments, 0);
return alert(arguments.reverse());
};
backwards("stairway", "to", "heaven");
})();

View File

@@ -0,0 +1,26 @@
(function(){
var _a, _b, _c, _d, _e, _f, _g, food, lunch, roid, roid2;
// Eat lunch.
lunch = (function() {
_a = []; _b = ['toast', 'cheese', 'wine'];
for (_c = 0; _c < _b.length; _c++) {
food = _b[_c];
_a.push(eat(food));
}
return _a;
}).call(this);
// Naive collision detection.
_d = asteroids;
for (_e = 0; _e < _d.length; _e++) {
roid = _d[_e];
_f = asteroids;
for (_g = 0; _g < _f.length; _g++) {
roid2 = _f[_g];
if (roid !== roid2) {
if (roid.overlaps(roid2)) {
roid.explode();
}
}
}
}
})();

View File

@@ -0,0 +1,5 @@
(function(){
var difficulty, greeting;
greeting = "Hello CoffeeScript";
difficulty = 0.5;
})();

View File

@@ -0,0 +1,14 @@
(function(){
process.mixin(require('assert'));
task('test', 'run each of the unit tests', function() {
var _a, _b, _c, test;
_a = []; _b = test_files;
for (_c = 0; _c < _b.length; _c++) {
test = _b[_c];
_a.push(fs.readFile(test, function(err, code) {
return eval(coffee.compile(code));
}));
}
return _a;
});
})();

View File

@@ -0,0 +1,5 @@
(function(){
var cholesterol, healthy;
cholesterol = 127;
healthy = (200 > cholesterol) && (cholesterol > 60);
})();

View File

@@ -0,0 +1,12 @@
(function(){
var date, expensive, mood;
if (singing) {
mood = greatly_improved;
}
if (happy && knows_it) {
claps_hands();
cha_cha_cha();
}
date = friday ? sue : jill;
expensive = expensive || do_the_math();
})();

View File

@@ -0,0 +1,6 @@
(function(){
var hi;
hi = function() {
return [document.title, "Hello JavaScript"].join(": ");
};
})();

View File

@@ -0,0 +1,7 @@
(function(){
var solipsism, speed;
if ((typeof mind !== "undefined" && mind !== null) && !(typeof world !== "undefined" && world !== null)) {
solipsism = true;
}
speed = (typeof speed !== "undefined" && speed !== null) ? speed : 140;
})();

View File

@@ -0,0 +1,13 @@
(function(){
var eldest, grade;
grade = function grade(student) {
if (student.excellent_work) {
return "A+";
} else if (student.okay_stuff) {
return student.tried_hard ? "B" : "B-";
} else {
return "C";
}
};
eldest = 24 > 21 ? "Liz" : "Ike";
})();

View File

@@ -0,0 +1,4 @@
(function(){
var one, six, three, two;
six = ((one = 1)) + ((two = 2)) + ((three = 3));
})();

View File

@@ -0,0 +1,12 @@
(function(){
var _a, _b, globals, name;
var __hasProp = Object.prototype.hasOwnProperty;
// The first ten global properties.
globals = (function() {
_a = []; _b = window;
for (name in _b) { if (__hasProp.call(_b, name)) {
_a.push(name);
}}
return _a;
}).call(this).slice(0, 10);
})();

View File

@@ -0,0 +1,9 @@
(function(){
alert((function() {
try {
return nonexistent / undefined;
} catch (error) {
return "And the error is ... " + error;
}
}).call(this));
})();

View File

@@ -0,0 +1,15 @@
(function(){
var Account;
Account = function Account(customer, cart) {
this.customer = customer;
this.cart = cart;
return $('.shopping_cart').bind('click', (function(__this) {
var __func = function(event) {
return this.customer.purchase(this.cart);
};
return (function() {
return __func.apply(__this, arguments);
});
})(this));
};
})();

View File

@@ -0,0 +1,9 @@
(function(){
var cube, square;
square = function square(x) {
return x * x;
};
cube = function cube(x) {
return square(x) * x;
};
})();

View File

@@ -0,0 +1,4 @@
(function(){
var html;
html = "<strong>\n cup of coffeescript\n</strong>";
})();

View File

@@ -0,0 +1,7 @@
(function(){
// CoffeeScript on the left, JS on the right.
var square = function(x) {
return x * x;
};
})();

View File

@@ -0,0 +1,11 @@
(function(){
var _a, city, forecast, temp, weather_report;
weather_report = function weather_report(location) {
// Make an Ajax request to fetch the weather...
return [location, 72, "Mostly Sunny"];
};
_a = weather_report("Berkeley, CA");
city = _a[0];
temp = _a[1];
forecast = _a[2];
})();

View File

@@ -0,0 +1,17 @@
(function(){
var _a, _b, age, ages, child, years_old;
var __hasProp = Object.prototype.hasOwnProperty;
years_old = {
max: 10,
ida: 9,
tim: 11
};
ages = (function() {
_a = []; _b = years_old;
for (child in _b) { if (__hasProp.call(_b, child)) {
age = _b[child];
_a.push(child + " is " + age);
}}
return _a;
}).call(this);
})();

View File

@@ -0,0 +1,17 @@
(function(){
var _a, _b, _c, city, futurists, poet, street;
futurists = {
sculptor: "Umberto Boccioni",
painter: "Vladimir Burliuk",
poet: {
name: "F.T. Marinetti",
address: ["Via Roma 42R", "Bellagio, Italy 22021"]
}
};
_a = futurists;
_b = _a.poet;
poet = _b.name;
_c = _b.address;
street = _c[0];
city = _c[1];
})();

View File

@@ -0,0 +1,10 @@
(function(){
var ages, matrix, song;
song = ["do", "re", "mi", "fa", "so"];
ages = {
max: 10,
ida: 9,
tim: 11
};
matrix = [1, 0, 1, 0, 0, 1, 1, 1, 0];
})();

View File

@@ -0,0 +1,43 @@
(function(){
var _a, _b, _c, cubed_list, list, math, num, number, opposite_day, race, square;
// Assignment:
number = 42;
opposite_day = true;
// Conditions:
if (opposite_day) {
number = -42;
}
// Functions:
square = function square(x) {
return x * x;
};
// Arrays:
list = [1, 2, 3, 4, 5];
// Objects:
math = {
root: Math.sqrt,
square: square,
cube: function cube(x) {
return x * square(x);
}
};
// Splats:
race = function race(winner) {
var runners;
runners = Array.prototype.slice.call(arguments, 1);
return print(winner, runners);
};
// Existence:
if ((typeof elvis !== "undefined" && elvis !== null)) {
alert("I knew it!");
}
// Array comprehensions:
cubed_list = (function() {
_a = []; _b = list;
for (_c = 0; _c < _b.length; _c++) {
num = _b[_c];
_a.push(math.cube(num));
}
return _a;
}).call(this);
})();

View File

@@ -0,0 +1,8 @@
(function(){
var _a, and_switch, bait;
bait = 1000;
and_switch = 0;
_a = [and_switch, bait];
bait = _a[0];
and_switch = _a[1];
})();

View File

@@ -0,0 +1,8 @@
(function(){
// Comments start with hash marks. Periods mark the end of a block.
var left_hand = raining ? umbrella : parasol;
// To signal the beginning of the next expression,
// use "then", or a newline.
left_hand = raining ? umbrella : parasol;
})();

View File

@@ -0,0 +1,21 @@
(function(){
var _a, _b, _c, _d, _e, countdown, egg_delivery, num;
countdown = (function() {
_a = []; _d = 10; _e = 1;
for (_c = 0, num=_d; (_d <= _e ? num <= _e : num >= _e); (_d <= _e ? num += 1 : num -= 1), _c++) {
_a.push(num);
}
return _a;
}).call(this);
egg_delivery = function egg_delivery() {
var _f, _g, _h, _i, _j, dozen_eggs, i;
_f = []; _i = 0; _j = eggs.length;
for (_h = 0, i=_i; (_i <= _j ? i < _j : i > _j); (_i <= _j ? i += 12 : i -= 12), _h++) {
_f.push((function() {
dozen_eggs = eggs.slice(i, i + 12);
return deliver(new egg_carton(dozen));
}).call(this));
}
return _f;
};
})();

10
documentation/js/scope.js Normal file
View File

@@ -0,0 +1,10 @@
(function(){
var change_numbers, new_num, num;
num = 1;
change_numbers = function change_numbers() {
var new_num;
new_num = -1;
return num = 10;
};
new_num = change_numbers();
})();

View File

@@ -0,0 +1,6 @@
(function(){
var numbers, numbers_copy, three_to_six;
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
three_to_six = numbers.slice(3, 6 + 1);
numbers_copy = numbers.slice(0, numbers.length);
})();

View File

@@ -0,0 +1,4 @@
(function(){
var _a;
(_a = lottery.draw_winner()) == undefined ? undefined : _a.address == undefined ? undefined : _a.address.zipcode;
})();

View File

@@ -0,0 +1,16 @@
(function(){
var award_medals, contenders, gold, silver, the_field;
gold = (silver = (the_field = "unknown"));
award_medals = function award_medals(first, second) {
var rest;
rest = Array.prototype.slice.call(arguments, 2);
gold = first;
silver = second;
return the_field = rest;
};
contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"];
award_medals.apply(this, contenders);
alert("Gold: " + gold);
alert("Silver: " + silver);
alert("The Field: " + the_field);
})();

View File

@@ -0,0 +1,5 @@
(function(){
var numbers;
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
numbers.splice.apply(numbers, [3, 6 - 3 + 1].concat([-3, -4, -5, -6]));
})();

View File

@@ -0,0 +1,9 @@
(function(){
var moby_dick;
moby_dick = "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...";
})();

37
documentation/js/super.js Normal file
View File

@@ -0,0 +1,37 @@
(function(){
var Animal, Horse, Snake, _a, _b, sam, tom;
Animal = function Animal() { };
Animal.prototype.move = function move(meters) {
return alert(this.name + " moved " + meters + "m.");
};
Snake = function Snake(name) {
this.name = name;
return this;
};
_a = function(){};
_a.prototype = Animal.prototype;
Snake.__superClass__ = Animal.prototype;
Snake.prototype = new _a();
Snake.prototype.constructor = Snake;
Snake.prototype.move = function move() {
alert("Slithering...");
return Snake.__superClass__.move.call(this, 5);
};
Horse = function Horse(name) {
this.name = name;
return this;
};
_b = function(){};
_b.prototype = Animal.prototype;
Horse.__superClass__ = Animal.prototype;
Horse.prototype = new _b();
Horse.prototype.constructor = Horse;
Horse.prototype.move = function move() {
alert("Galloping...");
return Horse.__superClass__.move.call(this, 45);
};
sam = new Snake("Sammy the Python");
tom = new Horse("Tommy the Palomino");
sam.move();
tom.move();
})();

View File

@@ -0,0 +1,18 @@
(function(){
if (day === "Mon") {
go_to_work();
} else if (day === "Tue") {
go_to_the_park();
} else if (day === "Thu") {
go_ice_fishing();
} else if (day === "Fri" || day === "Sat") {
if (day === bingo_day) {
go_to_bingo();
go_dancing();
}
} else if (day === "Sun") {
go_to_church();
} else {
go_to_work();
}
})();

10
documentation/js/try.js Normal file
View File

@@ -0,0 +1,10 @@
(function(){
try {
all_hell_breaks_loose();
cats_and_dogs_living_together();
} catch (error) {
print(error);
} finally {
clean_up();
}
})();

22
documentation/js/while.js Normal file
View File

@@ -0,0 +1,22 @@
(function(){
var _a, lyrics, num;
// Econ 101
if (this.studying_economics) {
while (supply > demand) {
buy();
}
while (supply < demand) {
sell();
}
}
// Nursery Rhyme
num = 6;
lyrics = (function() {
_a = [];
while (num -= 1) {
_a.push(num + " little monkeys, jumping on the bed. \
One fell out and bumped his head.");
}
return _a;
}).call(this);
})();

View File

@@ -0,0 +1,627 @@
<!DOCTYPE html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" media="screen,projection,print" href="css/idle.css" />
<title>Underscore.coffee</title>
</head>
<body>
<pre class="idle"><span class="line-numbers"> 1 </span>
<span class="line-numbers"> 2 </span> <span class="Comment"><span class="Comment">#</span> Underscore.coffee</span>
<span class="line-numbers"> 3 </span> <span class="Comment"><span class="Comment">#</span> (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.</span>
<span class="line-numbers"> 4 </span> <span class="Comment"><span class="Comment">#</span> Underscore is freely distributable under the terms of the MIT license.</span>
<span class="line-numbers"> 5 </span> <span class="Comment"><span class="Comment">#</span> Portions of Underscore are inspired by or borrowed from Prototype.js,</span>
<span class="line-numbers"> 6 </span> <span class="Comment"><span class="Comment">#</span> Oliver Steele's Functional, and John Resig's Micro-Templating.</span>
<span class="line-numbers"> 7 </span> <span class="Comment"><span class="Comment">#</span> For all details and documentation:</span>
<span class="line-numbers"> 8 </span> <span class="Comment"><span class="Comment">#</span> http://documentcloud.github.com/underscore/</span>
<span class="line-numbers"> 9 </span>
<span class="line-numbers"> 10 </span>
<span class="line-numbers"> 11 </span> <span class="Comment"><span class="Comment">#</span> ------------------------- Baseline setup ---------------------------------</span>
<span class="line-numbers"> 12 </span>
<span class="line-numbers"> 13 </span> <span class="Comment"><span class="Comment">#</span> Establish the root object, &quot;window&quot; in the browser, or &quot;global&quot; on the server.</span>
<span class="line-numbers"> 14 </span> <span class="FunctionName">root</span><span class="Keyword">:</span> <span class="Variable">this</span>
<span class="line-numbers"> 15 </span>
<span class="line-numbers"> 16 </span>
<span class="line-numbers"> 17 </span> <span class="Comment"><span class="Comment">#</span> Save the previous value of the &quot;_&quot; variable.</span>
<span class="line-numbers"> 18 </span> <span class="FunctionName">previousUnderscore</span><span class="Keyword">:</span> root._
<span class="line-numbers"> 19 </span>
<span class="line-numbers"> 20 </span>
<span class="line-numbers"> 21 </span> <span class="Comment"><span class="Comment">#</span> If Underscore is called as a function, it returns a wrapped object that</span>
<span class="line-numbers"> 22 </span> <span class="Comment"><span class="Comment">#</span> can be used OO-style. This wrapper holds altered versions of all the</span>
<span class="line-numbers"> 23 </span> <span class="Comment"><span class="Comment">#</span> underscore functions. Wrapped objects may be chained.</span>
<span class="line-numbers"> 24 </span> <span class="FunctionName">wrapper</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 25 </span> <span class="FunctionName">this._wrapped</span><span class="Keyword">:</span> obj
<span class="line-numbers"> 26 </span> <span class="Variable">this</span>
<span class="line-numbers"> 27 </span>
<span class="line-numbers"> 28 </span>
<span class="line-numbers"> 29 </span> <span class="Comment"><span class="Comment">#</span> Establish the object that gets thrown to break out of a loop iteration.</span>
<span class="line-numbers"> 30 </span> <span class="FunctionName">breaker</span><span class="Keyword">:</span> <span class="Keyword">if</span> <span class="Keyword">typeof</span>(StopIteration) <span class="Keyword">is</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span> <span class="Keyword">then</span> <span class="String"><span class="String">'</span>__break__<span class="String">'</span></span> <span class="Keyword">else</span> StopIteration
<span class="line-numbers"> 31 </span>
<span class="line-numbers"> 32 </span>
<span class="line-numbers"> 33 </span> <span class="Comment"><span class="Comment">#</span> Create a safe reference to the Underscore object forreference below.</span>
<span class="line-numbers"> 34 </span> <span class="FunctionName">_</span><span class="Keyword">:</span> <span class="FunctionName">root._</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> <span class="Keyword">new</span> <span class="TypeName">wrapper</span>(obj)
<span class="line-numbers"> 35 </span>
<span class="line-numbers"> 36 </span>
<span class="line-numbers"> 37 </span> <span class="Comment"><span class="Comment">#</span> Export the Underscore object for CommonJS.</span>
<span class="line-numbers"> 38 </span> <span class="Keyword">if</span> <span class="Keyword">typeof</span>(exports) <span class="Keyword">!</span><span class="Keyword">=</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span> <span class="Keyword">then</span> <span class="FunctionName">exports._</span><span class="Keyword">:</span> _
<span class="line-numbers"> 39 </span>
<span class="line-numbers"> 40 </span>
<span class="line-numbers"> 41 </span> <span class="Comment"><span class="Comment">#</span> Create quick reference variables for speed access to core prototypes.</span>
<span class="line-numbers"> 42 </span> <span class="FunctionName">slice</span><span class="Keyword">:</span> <span class="FunctionName">Array:</span><span class="Keyword">:</span>slice
<span class="line-numbers"> 43 </span> <span class="FunctionName">unshift</span><span class="Keyword">:</span> <span class="FunctionName">Array:</span><span class="Keyword">:</span>unshift
<span class="line-numbers"> 44 </span> <span class="FunctionName">toString</span><span class="Keyword">:</span> <span class="FunctionName">Object:</span><span class="Keyword">:</span>toString
<span class="line-numbers"> 45 </span> <span class="FunctionName">hasOwnProperty</span><span class="Keyword">:</span> <span class="FunctionName">Object:</span><span class="Keyword">:</span>hasOwnProperty
<span class="line-numbers"> 46 </span> <span class="FunctionName">propertyIsEnumerable</span><span class="Keyword">:</span> <span class="FunctionName">Object:</span><span class="Keyword">:</span>propertyIsEnumerable
<span class="line-numbers"> 47 </span>
<span class="line-numbers"> 48 </span>
<span class="line-numbers"> 49 </span> <span class="Comment"><span class="Comment">#</span> Current version.</span>
<span class="line-numbers"> 50 </span> <span class="FunctionName">_.VERSION</span><span class="Keyword">:</span> <span class="String"><span class="String">'</span>0.5.8<span class="String">'</span></span>
<span class="line-numbers"> 51 </span>
<span class="line-numbers"> 52 </span>
<span class="line-numbers"> 53 </span> <span class="Comment"><span class="Comment">#</span> ------------------------ Collection Functions: ---------------------------</span>
<span class="line-numbers"> 54 </span>
<span class="line-numbers"> 55 </span> <span class="Comment"><span class="Comment">#</span> The cornerstone, an each implementation.</span>
<span class="line-numbers"> 56 </span> <span class="Comment"><span class="Comment">#</span> Handles objects implementing forEach, arrays, and raw objects.</span>
<span class="line-numbers"> 57 </span> <span class="FunctionName">_.each</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 58 </span> <span class="FunctionName">index</span><span class="Keyword">:</span> <span class="Number">0</span>
<span class="line-numbers"> 59 </span> <span class="Keyword">try</span>
<span class="line-numbers"> 60 </span> <span class="Keyword">return</span> obj.forEach(iterator, context) <span class="Keyword">if</span> obj.forEach
<span class="line-numbers"> 61 </span> <span class="Keyword">if</span> _.isNumber(obj.length)
<span class="line-numbers"> 62 </span> <span class="Keyword">return</span> iterator.call(context, obj[i], i, obj) <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...obj.length]
<span class="line-numbers"> 63 </span> iterator.call(context, val, key, obj) <span class="Keyword">for</span> key, val <span class="Keyword">of</span> obj
<span class="line-numbers"> 64 </span> <span class="Keyword">catch</span> e
<span class="line-numbers"> 65 </span> <span class="Keyword">throw</span> e <span class="Keyword">if</span> e <span class="Keyword">isnt</span> breaker
<span class="line-numbers"> 66 </span> obj
<span class="line-numbers"> 67 </span>
<span class="line-numbers"> 68 </span>
<span class="line-numbers"> 69 </span> <span class="Comment"><span class="Comment">#</span> Return the results of applying the iterator to each element. Use JavaScript</span>
<span class="line-numbers"> 70 </span> <span class="Comment"><span class="Comment">#</span> 1.6's version of map, if possible.</span>
<span class="line-numbers"> 71 </span> <span class="FunctionName">_.map</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 72 </span> <span class="Keyword">return</span> obj.map(iterator, context) <span class="Keyword">if</span> (obj <span class="Keyword">and</span> _.isFunction(obj.map))
<span class="line-numbers"> 73 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
<span class="line-numbers"> 74 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 75 </span> results.push(iterator.call(context, value, index, list))
<span class="line-numbers"> 76 </span> results
<span class="line-numbers"> 77 </span>
<span class="line-numbers"> 78 </span>
<span class="line-numbers"> 79 </span> <span class="Comment"><span class="Comment">#</span> Reduce builds up a single result from a list of values. Also known as</span>
<span class="line-numbers"> 80 </span> <span class="Comment"><span class="Comment">#</span> inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.</span>
<span class="line-numbers"> 81 </span> <span class="FunctionName">_.reduce</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, memo, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 82 </span> <span class="Keyword">return</span> obj.reduce(_.bind(iterator, context), memo) <span class="Keyword">if</span> (obj <span class="Keyword">and</span> _.isFunction(obj.reduce))
<span class="line-numbers"> 83 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 84 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> iterator.call(context, memo, value, index, list)
<span class="line-numbers"> 85 </span> memo
<span class="line-numbers"> 86 </span>
<span class="line-numbers"> 87 </span>
<span class="line-numbers"> 88 </span> <span class="Comment"><span class="Comment">#</span> The right-associative version of reduce, also known as foldr. Uses</span>
<span class="line-numbers"> 89 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.8's version of reduceRight, if available.</span>
<span class="line-numbers"> 90 </span> <span class="FunctionName">_.reduceRight</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, memo, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 91 </span> <span class="Keyword">return</span> obj.reduceRight(_.bind(iterator, context), memo) <span class="Keyword">if</span> (obj <span class="Keyword">and</span> _.isFunction(obj.reduceRight))
<span class="line-numbers"> 92 </span> _.each _.clone(_.toArray(obj)).reverse(), <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 93 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> iterator.call(context, memo, value, index, obj)
<span class="line-numbers"> 94 </span> memo
<span class="line-numbers"> 95 </span>
<span class="line-numbers"> 96 </span>
<span class="line-numbers"> 97 </span> <span class="Comment"><span class="Comment">#</span> Return the first value which passes a truth test.</span>
<span class="line-numbers"> 98 </span> <span class="FunctionName">_.detect</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 99 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">null</span>
<span class="line-numbers"> 100 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 101 </span> <span class="Keyword">if</span> iterator.call(context, value, index, list)
<span class="line-numbers"> 102 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> value
<span class="line-numbers"> 103 </span> _.breakLoop()
<span class="line-numbers"> 104 </span> result
<span class="line-numbers"> 105 </span>
<span class="line-numbers"> 106 </span>
<span class="line-numbers"> 107 </span> <span class="Comment"><span class="Comment">#</span> Return all the elements that pass a truth test. Use JavaScript 1.6's</span>
<span class="line-numbers"> 108 </span> <span class="Comment"><span class="Comment">#</span> filter(), if it exists.</span>
<span class="line-numbers"> 109 </span> <span class="FunctionName">_.select</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 110 </span> <span class="Keyword">if</span> obj <span class="Keyword">and</span> _.isFunction(obj.filter) <span class="Keyword">then</span> <span class="Keyword">return</span> obj.filter(iterator, context)
<span class="line-numbers"> 111 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
<span class="line-numbers"> 112 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 113 </span> results.push(value) <span class="Keyword">if</span> iterator.call(context, value, index, list)
<span class="line-numbers"> 114 </span> results
<span class="line-numbers"> 115 </span>
<span class="line-numbers"> 116 </span>
<span class="line-numbers"> 117 </span> <span class="Comment"><span class="Comment">#</span> Return all the elements for which a truth test fails.</span>
<span class="line-numbers"> 118 </span> <span class="FunctionName">_.reject</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 119 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
<span class="line-numbers"> 120 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 121 </span> results.push(value) <span class="Keyword">if</span> <span class="Keyword">not</span> iterator.call(context, value, index, list)
<span class="line-numbers"> 122 </span> results
<span class="line-numbers"> 123 </span>
<span class="line-numbers"> 124 </span>
<span class="line-numbers"> 125 </span> <span class="Comment"><span class="Comment">#</span> Determine whether all of the elements match a truth test. Delegate to</span>
<span class="line-numbers"> 126 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.6's every(), if it is present.</span>
<span class="line-numbers"> 127 </span> <span class="FunctionName">_.all</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 128 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
<span class="line-numbers"> 129 </span> <span class="Keyword">return</span> obj.every(iterator, context) <span class="Keyword">if</span> obj <span class="Keyword">and</span> _.isFunction(obj.every)
<span class="line-numbers"> 130 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
<span class="line-numbers"> 131 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 132 </span> _.breakLoop() <span class="Keyword">unless</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> result <span class="Keyword">and</span> iterator.call(context, value, index, list))
<span class="line-numbers"> 133 </span> result
<span class="line-numbers"> 134 </span>
<span class="line-numbers"> 135 </span>
<span class="line-numbers"> 136 </span> <span class="Comment"><span class="Comment">#</span> Determine if at least one element in the object matches a truth test. Use</span>
<span class="line-numbers"> 137 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.6's some(), if it exists.</span>
<span class="line-numbers"> 138 </span> <span class="FunctionName">_.any</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 139 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
<span class="line-numbers"> 140 </span> <span class="Keyword">return</span> obj.some(iterator, context) <span class="Keyword">if</span> obj <span class="Keyword">and</span> _.isFunction(obj.some)
<span class="line-numbers"> 141 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">false</span>
<span class="line-numbers"> 142 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 143 </span> _.breakLoop() <span class="Keyword">if</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> iterator.call(context, value, index, list))
<span class="line-numbers"> 144 </span> result
<span class="line-numbers"> 145 </span>
<span class="line-numbers"> 146 </span>
<span class="line-numbers"> 147 </span> <span class="Comment"><span class="Comment">#</span> Determine if a given value is included in the array or object,</span>
<span class="line-numbers"> 148 </span> <span class="Comment"><span class="Comment">#</span> based on '==='.</span>
<span class="line-numbers"> 149 </span> <span class="FunctionName">_.include</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, target</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 150 </span> <span class="Keyword">return</span> _.indexOf(obj, target) <span class="Keyword">isnt</span> <span class="Keyword">-</span><span class="Number">1</span> <span class="Keyword">if</span> obj <span class="Keyword">and</span> _.isFunction(obj.indexOf)
<span class="line-numbers"> 151 </span> <span class="Keyword">for</span> key, val <span class="Keyword">of</span> obj
<span class="line-numbers"> 152 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> val <span class="Keyword">is</span> target
<span class="line-numbers"> 153 </span> <span class="BuiltInConstant">false</span>
<span class="line-numbers"> 154 </span>
<span class="line-numbers"> 155 </span>
<span class="line-numbers"> 156 </span> <span class="Comment"><span class="Comment">#</span> Invoke a method with arguments on every item in a collection.</span>
<span class="line-numbers"> 157 </span> <span class="FunctionName">_.invoke</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, method</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 158 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
<span class="line-numbers"> 159 </span> (<span class="Keyword">if</span> method <span class="Keyword">then</span> val[method] <span class="Keyword">else</span> val).apply(val, args) <span class="Keyword">for</span> val <span class="Keyword">in</span> obj
<span class="line-numbers"> 160 </span>
<span class="line-numbers"> 161 </span>
<span class="line-numbers"> 162 </span> <span class="Comment"><span class="Comment">#</span> Convenience version of a common use case of map: fetching a property.</span>
<span class="line-numbers"> 163 </span> <span class="FunctionName">_.pluck</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, key</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 164 </span> _.map(obj, (<span class="FunctionArgument">(</span><span class="FunctionArgument">val</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> val[key]))
<span class="line-numbers"> 165 </span>
<span class="line-numbers"> 166 </span>
<span class="line-numbers"> 167 </span> <span class="Comment"><span class="Comment">#</span> Return the maximum item or (item-based computation).</span>
<span class="line-numbers"> 168 </span> <span class="FunctionName">_.max</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 169 </span> <span class="Keyword">return</span> Math.max.apply(Math, obj) <span class="Keyword">if</span> <span class="Keyword">not</span> iterator <span class="Keyword">and</span> _.isArray(obj)
<span class="line-numbers"> 170 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">-</span><span class="BuiltInConstant">Infinity</span>}
<span class="line-numbers"> 171 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 172 </span> <span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">if</span> iterator <span class="Keyword">then</span> iterator.call(context, value, index, list) <span class="Keyword">else</span> value
<span class="line-numbers"> 173 </span> computed <span class="Keyword">&gt;=</span> result.computed <span class="Keyword">and</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">computed</span><span class="Keyword">:</span> computed})
<span class="line-numbers"> 174 </span> result.value
<span class="line-numbers"> 175 </span>
<span class="line-numbers"> 176 </span>
<span class="line-numbers"> 177 </span> <span class="Comment"><span class="Comment">#</span> Return the minimum element (or element-based computation).</span>
<span class="line-numbers"> 178 </span> <span class="FunctionName">_.min</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 179 </span> <span class="Keyword">return</span> Math.min.apply(Math, obj) <span class="Keyword">if</span> <span class="Keyword">not</span> iterator <span class="Keyword">and</span> _.isArray(obj)
<span class="line-numbers"> 180 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="BuiltInConstant">Infinity</span>}
<span class="line-numbers"> 181 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 182 </span> <span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">if</span> iterator <span class="Keyword">then</span> iterator.call(context, value, index, list) <span class="Keyword">else</span> value
<span class="line-numbers"> 183 </span> computed <span class="Keyword">&lt;</span> result.computed <span class="Keyword">and</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">computed</span><span class="Keyword">:</span> computed})
<span class="line-numbers"> 184 </span> result.value
<span class="line-numbers"> 185 </span>
<span class="line-numbers"> 186 </span>
<span class="line-numbers"> 187 </span> <span class="Comment"><span class="Comment">#</span> Sort the object's values by a criteria produced by an iterator.</span>
<span class="line-numbers"> 188 </span> <span class="FunctionName">_.sortBy</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 189 </span> _.pluck(((_.map obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 190 </span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">criteria</span><span class="Keyword">:</span> iterator.call(context, value, index, list)}
<span class="line-numbers"> 191 </span> ).sort(<span class="FunctionArgument">(</span><span class="FunctionArgument">left, right</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 192 </span> <span class="FunctionName">a</span><span class="Keyword">:</span> left.criteria; <span class="FunctionName">b</span><span class="Keyword">:</span> right.criteria
<span class="line-numbers"> 193 </span> <span class="Keyword">if</span> a <span class="Keyword">&lt;</span> b <span class="Keyword">then</span> <span class="Keyword">-</span><span class="Number">1</span> <span class="Keyword">else</span> <span class="Keyword">if</span> a <span class="Keyword">&gt;</span> b <span class="Keyword">then</span> <span class="Number">1</span> <span class="Keyword">else</span> <span class="Number">0</span>
<span class="line-numbers"> 194 </span> )), <span class="String"><span class="String">'</span>value<span class="String">'</span></span>)
<span class="line-numbers"> 195 </span>
<span class="line-numbers"> 196 </span>
<span class="line-numbers"> 197 </span> <span class="Comment"><span class="Comment">#</span> Use a comparator function to figure out at what index an object should</span>
<span class="line-numbers"> 198 </span> <span class="Comment"><span class="Comment">#</span> be inserted so as to maintain order. Uses binary search.</span>
<span class="line-numbers"> 199 </span> <span class="FunctionName">_.sortedIndex</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, obj, iterator</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 200 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
<span class="line-numbers"> 201 </span> <span class="FunctionName">low</span><span class="Keyword">:</span> <span class="Number">0</span>; <span class="FunctionName">high</span><span class="Keyword">:</span> array.length
<span class="line-numbers"> 202 </span> <span class="Keyword">while</span> low <span class="Keyword">&lt;</span> high
<span class="line-numbers"> 203 </span> <span class="FunctionName">mid</span><span class="Keyword">:</span> (low <span class="Keyword">+</span> high) <span class="Keyword">&gt;</span><span class="Keyword">&gt;</span> <span class="Number">1</span>
<span class="line-numbers"> 204 </span> <span class="Keyword">if</span> iterator(array[mid]) <span class="Keyword">&lt;</span> iterator(obj) <span class="Keyword">then</span> <span class="FunctionName">low</span><span class="Keyword">:</span> mid <span class="Keyword">+</span> <span class="Number">1</span> <span class="Keyword">else</span> <span class="FunctionName">high</span><span class="Keyword">:</span> mid
<span class="line-numbers"> 205 </span> low
<span class="line-numbers"> 206 </span>
<span class="line-numbers"> 207 </span>
<span class="line-numbers"> 208 </span> <span class="Comment"><span class="Comment">#</span> Convert anything iterable into a real, live array.</span>
<span class="line-numbers"> 209 </span> <span class="FunctionName">_.toArray</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">iterable</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 210 </span> <span class="Keyword">return</span> [] <span class="Keyword">if</span> (<span class="Keyword">!</span>iterable)
<span class="line-numbers"> 211 </span> <span class="Keyword">return</span> iterable.toArray() <span class="Keyword">if</span> (iterable.toArray)
<span class="line-numbers"> 212 </span> <span class="Keyword">return</span> iterable <span class="Keyword">if</span> (_.isArray(iterable))
<span class="line-numbers"> 213 </span> <span class="Keyword">return</span> slice.call(iterable) <span class="Keyword">if</span> (_.isArguments(iterable))
<span class="line-numbers"> 214 </span> _.values(iterable)
<span class="line-numbers"> 215 </span>
<span class="line-numbers"> 216 </span>
<span class="line-numbers"> 217 </span> <span class="Comment"><span class="Comment">#</span> Return the number of elements in an object.</span>
<span class="line-numbers"> 218 </span> <span class="FunctionName">_.size</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> _.toArray(obj).length
<span class="line-numbers"> 219 </span>
<span class="line-numbers"> 220 </span>
<span class="line-numbers"> 221 </span> <span class="Comment"><span class="Comment">#</span> -------------------------- Array Functions: ------------------------------</span>
<span class="line-numbers"> 222 </span>
<span class="line-numbers"> 223 </span> <span class="Comment"><span class="Comment">#</span> Get the first element of an array. Passing &quot;n&quot; will return the first N</span>
<span class="line-numbers"> 224 </span> <span class="Comment"><span class="Comment">#</span> values in the array. Aliased as &quot;head&quot;. The &quot;guard&quot; check allows it to work</span>
<span class="line-numbers"> 225 </span> <span class="Comment"><span class="Comment">#</span> with _.map.</span>
<span class="line-numbers"> 226 </span> <span class="FunctionName">_.first</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, n, guard</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 227 </span> <span class="Keyword">if</span> n <span class="Keyword">and</span> <span class="Keyword">not</span> guard <span class="Keyword">then</span> slice.call(array, <span class="Number">0</span>, n) <span class="Keyword">else</span> array[<span class="Number">0</span>]
<span class="line-numbers"> 228 </span>
<span class="line-numbers"> 229 </span>
<span class="line-numbers"> 230 </span> <span class="Comment"><span class="Comment">#</span> Returns everything but the first entry of the array. Aliased as &quot;tail&quot;.</span>
<span class="line-numbers"> 231 </span> <span class="Comment"><span class="Comment">#</span> Especially useful on the arguments object. Passing an &quot;index&quot; will return</span>
<span class="line-numbers"> 232 </span> <span class="Comment"><span class="Comment">#</span> the rest of the values in the array from that index onward. The &quot;guard&quot;</span>
<span class="line-numbers"> 233 </span> <span class="Comment"><span class="Comment">#</span> check allows it to work with _.map.</span>
<span class="line-numbers"> 234 </span> <span class="FunctionName">_.rest</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, index, guard</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 235 </span> slice.call(array, <span class="Keyword">if</span> _.isUndefined(index) <span class="Keyword">or</span> guard <span class="Keyword">then</span> <span class="Number">1</span> <span class="Keyword">else</span> index)
<span class="line-numbers"> 236 </span>
<span class="line-numbers"> 237 </span>
<span class="line-numbers"> 238 </span> <span class="Comment"><span class="Comment">#</span> Get the last element of an array.</span>
<span class="line-numbers"> 239 </span> <span class="FunctionName">_.last</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> array[array.length <span class="Keyword">-</span> <span class="Number">1</span>]
<span class="line-numbers"> 240 </span>
<span class="line-numbers"> 241 </span>
<span class="line-numbers"> 242 </span> <span class="Comment"><span class="Comment">#</span> Trim out all falsy values from an array.</span>
<span class="line-numbers"> 243 </span> <span class="FunctionName">_.compact</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> item <span class="Keyword">for</span> item <span class="Keyword">in</span> array <span class="Keyword">when</span> item
<span class="line-numbers"> 244 </span>
<span class="line-numbers"> 245 </span>
<span class="line-numbers"> 246 </span> <span class="Comment"><span class="Comment">#</span> Return a completely flattened version of an array.</span>
<span class="line-numbers"> 247 </span> <span class="FunctionName">_.flatten</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 248 </span> _.reduce array, [], <span class="FunctionArgument">(</span><span class="FunctionArgument">memo, value</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 249 </span> <span class="Keyword">return</span> memo.concat(_.flatten(value)) <span class="Keyword">if</span> _.isArray(value)
<span class="line-numbers"> 250 </span> memo.push(value)
<span class="line-numbers"> 251 </span> memo
<span class="line-numbers"> 252 </span>
<span class="line-numbers"> 253 </span>
<span class="line-numbers"> 254 </span> <span class="Comment"><span class="Comment">#</span> Return a version of the array that does not contain the specified value(s).</span>
<span class="line-numbers"> 255 </span> <span class="FunctionName">_.without</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 256 </span> <span class="FunctionName">values</span><span class="Keyword">:</span> _.rest(arguments)
<span class="line-numbers"> 257 </span> val <span class="Keyword">for</span> val <span class="Keyword">in</span> _.toArray(array) <span class="Keyword">when</span> <span class="Keyword">not</span> _.include(values, val)
<span class="line-numbers"> 258 </span>
<span class="line-numbers"> 259 </span>
<span class="line-numbers"> 260 </span> <span class="Comment"><span class="Comment">#</span> Produce a duplicate-free version of the array. If the array has already</span>
<span class="line-numbers"> 261 </span> <span class="Comment"><span class="Comment">#</span> been sorted, you have the option of using a faster algorithm.</span>
<span class="line-numbers"> 262 </span> <span class="FunctionName">_.uniq</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, isSorted</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 263 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> []
<span class="line-numbers"> 264 </span> <span class="Keyword">for</span> el, i <span class="Keyword">in</span> _.toArray(array)
<span class="line-numbers"> 265 </span> memo.push(el) <span class="Keyword">if</span> i <span class="Keyword">is</span> <span class="Number">0</span> <span class="Keyword">||</span> (<span class="Keyword">if</span> isSorted <span class="Keyword">is</span> <span class="BuiltInConstant">true</span> <span class="Keyword">then</span> _.last(memo) <span class="Keyword">isnt</span> el <span class="Keyword">else</span> <span class="Keyword">not</span> _.include(memo, el))
<span class="line-numbers"> 266 </span> memo
<span class="line-numbers"> 267 </span>
<span class="line-numbers"> 268 </span>
<span class="line-numbers"> 269 </span> <span class="Comment"><span class="Comment">#</span> Produce an array that contains every item shared between all the</span>
<span class="line-numbers"> 270 </span> <span class="Comment"><span class="Comment">#</span> passed-in arrays.</span>
<span class="line-numbers"> 271 </span> <span class="FunctionName">_.intersect</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 272 </span> <span class="FunctionName">rest</span><span class="Keyword">:</span> _.rest(arguments)
<span class="line-numbers"> 273 </span> _.select _.uniq(array), <span class="FunctionArgument">(</span><span class="FunctionArgument">item</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 274 </span> _.all rest, <span class="FunctionArgument">(</span><span class="FunctionArgument">other</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 275 </span> _.indexOf(other, item) <span class="Keyword">&gt;=</span> <span class="Number">0</span>
<span class="line-numbers"> 276 </span>
<span class="line-numbers"> 277 </span>
<span class="line-numbers"> 278 </span> <span class="Comment"><span class="Comment">#</span> Zip together multiple lists into a single array -- elements that share</span>
<span class="line-numbers"> 279 </span> <span class="Comment"><span class="Comment">#</span> an index go together.</span>
<span class="line-numbers"> 280 </span> <span class="FunctionName">_.zip</span><span class="Keyword">:</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 281 </span> <span class="FunctionName">length</span><span class="Keyword">:</span> _.max(_.pluck(arguments, <span class="String"><span class="String">'</span>length<span class="String">'</span></span>))
<span class="line-numbers"> 282 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Array</span>(length)
<span class="line-numbers"> 283 </span> <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...length]
<span class="line-numbers"> 284 </span> results[i]<span class="Keyword">:</span> _.pluck(arguments, String(i))
<span class="line-numbers"> 285 </span> results
<span class="line-numbers"> 286 </span>
<span class="line-numbers"> 287 </span>
<span class="line-numbers"> 288 </span> <span class="Comment"><span class="Comment">#</span> If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),</span>
<span class="line-numbers"> 289 </span> <span class="Comment"><span class="Comment">#</span> we need this function. Return the position of the first occurence of an</span>
<span class="line-numbers"> 290 </span> <span class="Comment"><span class="Comment">#</span> item in an array, or -1 if the item is not included in the array.</span>
<span class="line-numbers"> 291 </span> <span class="FunctionName">_.indexOf</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, item</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 292 </span> <span class="Keyword">return</span> array.indexOf(item) <span class="Keyword">if</span> array.indexOf
<span class="line-numbers"> 293 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> <span class="Number">0</span>; <span class="FunctionName">l</span><span class="Keyword">:</span> array.length
<span class="line-numbers"> 294 </span> <span class="Keyword">while</span> l <span class="Keyword">-</span> i
<span class="line-numbers"> 295 </span> <span class="Keyword">if</span> array[i] <span class="Keyword">is</span> item <span class="Keyword">then</span> <span class="Keyword">return</span> i <span class="Keyword">else</span> i<span class="Keyword">++</span>
<span class="line-numbers"> 296 </span> <span class="Keyword">-</span><span class="Number">1</span>
<span class="line-numbers"> 297 </span>
<span class="line-numbers"> 298 </span>
<span class="line-numbers"> 299 </span> <span class="Comment"><span class="Comment">#</span> Provide JavaScript 1.6's lastIndexOf, delegating to the native function,</span>
<span class="line-numbers"> 300 </span> <span class="Comment"><span class="Comment">#</span> if possible.</span>
<span class="line-numbers"> 301 </span> <span class="FunctionName">_.lastIndexOf</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, item</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 302 </span> <span class="Keyword">return</span> array.lastIndexOf(item) <span class="Keyword">if</span> array.lastIndexOf
<span class="line-numbers"> 303 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> array.length
<span class="line-numbers"> 304 </span> <span class="Keyword">while</span> i
<span class="line-numbers"> 305 </span> <span class="Keyword">if</span> array[i] <span class="Keyword">is</span> item <span class="Keyword">then</span> <span class="Keyword">return</span> i <span class="Keyword">else</span> i<span class="Keyword">--</span>
<span class="line-numbers"> 306 </span> <span class="Keyword">-</span><span class="Number">1</span>
<span class="line-numbers"> 307 </span>
<span class="line-numbers"> 308 </span>
<span class="line-numbers"> 309 </span> <span class="Comment"><span class="Comment">#</span> Generate an integer Array containing an arithmetic progression. A port of</span>
<span class="line-numbers"> 310 </span> <span class="Comment"><span class="Comment">#</span> the native Python range() function. See:</span>
<span class="line-numbers"> 311 </span> <span class="Comment"><span class="Comment">#</span> http://docs.python.org/library/functions.html#range</span>
<span class="line-numbers"> 312 </span> <span class="FunctionName">_.range</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">start, stop, step</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 313 </span> <span class="FunctionName">a</span><span class="Keyword">:</span> arguments
<span class="line-numbers"> 314 </span> <span class="FunctionName">solo</span><span class="Keyword">:</span> a.length <span class="Keyword">&lt;=</span> <span class="Number">1</span>
<span class="line-numbers"> 315 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> <span class="FunctionName">start</span><span class="Keyword">:</span> <span class="Keyword">if</span> solo <span class="Keyword">then</span> <span class="Number">0</span> <span class="Keyword">else</span> a[<span class="Number">0</span>]
<span class="line-numbers"> 316 </span> <span class="FunctionName">stop</span><span class="Keyword">:</span> <span class="Keyword">if</span> solo <span class="Keyword">then</span> a[<span class="Number">0</span>] <span class="Keyword">else</span> a[<span class="Number">1</span>]
<span class="line-numbers"> 317 </span> <span class="FunctionName">step</span><span class="Keyword">:</span> a[<span class="Number">2</span>] <span class="Keyword">or</span> <span class="Number">1</span>
<span class="line-numbers"> 318 </span> <span class="FunctionName">len</span><span class="Keyword">:</span> Math.ceil((stop <span class="Keyword">-</span> start) <span class="Keyword">/</span> step)
<span class="line-numbers"> 319 </span> <span class="Keyword">return</span> [] <span class="Keyword">if</span> len <span class="Keyword">&lt;=</span> <span class="Number">0</span>
<span class="line-numbers"> 320 </span> <span class="FunctionName">range</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Array</span>(len)
<span class="line-numbers"> 321 </span> <span class="FunctionName">idx</span><span class="Keyword">:</span> <span class="Number">0</span>
<span class="line-numbers"> 322 </span> <span class="Keyword">while</span> <span class="BuiltInConstant">true</span>
<span class="line-numbers"> 323 </span> <span class="Keyword">return</span> range <span class="Keyword">if</span> (<span class="Keyword">if</span> step <span class="Keyword">&gt;</span> <span class="Number">0</span> <span class="Keyword">then</span> i <span class="Keyword">-</span> stop <span class="Keyword">else</span> stop <span class="Keyword">-</span> i) <span class="Keyword">&gt;=</span> <span class="Number">0</span>
<span class="line-numbers"> 324 </span> range[idx]<span class="Keyword">:</span> i
<span class="line-numbers"> 325 </span> idx<span class="Keyword">++</span>
<span class="line-numbers"> 326 </span> i<span class="Keyword">+</span><span class="Keyword">=</span> step
<span class="line-numbers"> 327 </span>
<span class="line-numbers"> 328 </span>
<span class="line-numbers"> 329 </span> <span class="Comment"><span class="Comment">#</span> ----------------------- Function Functions: -----------------------------</span>
<span class="line-numbers"> 330 </span>
<span class="line-numbers"> 331 </span> <span class="Comment"><span class="Comment">#</span> Create a function bound to a given object (assigning 'this', and arguments,</span>
<span class="line-numbers"> 332 </span> <span class="Comment"><span class="Comment">#</span> optionally). Binding with arguments is also known as 'curry'.</span>
<span class="line-numbers"> 333 </span> <span class="FunctionName">_.bind</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func, obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 334 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
<span class="line-numbers"> 335 </span> <span class="Storage">-&gt;</span> func.apply(obj <span class="Keyword">or</span> root, args.concat(arguments))
<span class="line-numbers"> 336 </span>
<span class="line-numbers"> 337 </span>
<span class="line-numbers"> 338 </span> <span class="Comment"><span class="Comment">#</span> Bind all of an object's methods to that object. Useful for ensuring that</span>
<span class="line-numbers"> 339 </span> <span class="Comment"><span class="Comment">#</span> all callbacks defined on an object belong to it.</span>
<span class="line-numbers"> 340 </span> <span class="FunctionName">_.bindAll</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 341 </span> <span class="FunctionName">funcs</span><span class="Keyword">:</span> <span class="Keyword">if</span> arguments.length <span class="Keyword">&gt;</span> <span class="Number">1</span> <span class="Keyword">then</span> _.rest(arguments) <span class="Keyword">else</span> _.functions(obj)
<span class="line-numbers"> 342 </span> _.each(funcs, <span class="FunctionArgument">(</span><span class="FunctionArgument">f</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> obj[f]<span class="Keyword">:</span> _.bind(obj[f], obj))
<span class="line-numbers"> 343 </span> obj
<span class="line-numbers"> 344 </span>
<span class="line-numbers"> 345 </span>
<span class="line-numbers"> 346 </span> <span class="Comment"><span class="Comment">#</span> Delays a function for the given number of milliseconds, and then calls</span>
<span class="line-numbers"> 347 </span> <span class="Comment"><span class="Comment">#</span> it with the arguments supplied.</span>
<span class="line-numbers"> 348 </span> <span class="FunctionName">_.delay</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func, wait</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 349 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
<span class="line-numbers"> 350 </span> setTimeout((<span class="Storage">-&gt;</span> func.apply(func, args)), wait)
<span class="line-numbers"> 351 </span>
<span class="line-numbers"> 352 </span>
<span class="line-numbers"> 353 </span> <span class="Comment"><span class="Comment">#</span> Defers a function, scheduling it to run after the current call stack has</span>
<span class="line-numbers"> 354 </span> <span class="Comment"><span class="Comment">#</span> cleared.</span>
<span class="line-numbers"> 355 </span> <span class="FunctionName">_.defer</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 356 </span> _.delay.apply(_, [func, <span class="Number">1</span>].concat(_.rest(arguments)))
<span class="line-numbers"> 357 </span>
<span class="line-numbers"> 358 </span>
<span class="line-numbers"> 359 </span> <span class="Comment"><span class="Comment">#</span> Returns the first function passed as an argument to the second,</span>
<span class="line-numbers"> 360 </span> <span class="Comment"><span class="Comment">#</span> allowing you to adjust arguments, run code before and after, and</span>
<span class="line-numbers"> 361 </span> <span class="Comment"><span class="Comment">#</span> conditionally execute the original function.</span>
<span class="line-numbers"> 362 </span> <span class="FunctionName">_.wrap</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func, wrapper</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 363 </span> <span class="Storage">-&gt;</span> wrapper.apply(wrapper, [func].concat(arguments))
<span class="line-numbers"> 364 </span>
<span class="line-numbers"> 365 </span>
<span class="line-numbers"> 366 </span> <span class="Comment"><span class="Comment">#</span> Returns a function that is the composition of a list of functions, each</span>
<span class="line-numbers"> 367 </span> <span class="Comment"><span class="Comment">#</span> consuming the return value of the function that follows.</span>
<span class="line-numbers"> 368 </span> <span class="FunctionName">_.compose</span><span class="Keyword">:</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 369 </span> <span class="FunctionName">funcs</span><span class="Keyword">:</span> arguments
<span class="line-numbers"> 370 </span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 371 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> arguments
<span class="line-numbers"> 372 </span> <span class="Keyword">for</span> i <span class="Keyword">in</span> [(funcs.length <span class="Keyword">-</span> <span class="Number">1</span>)..<span class="Number">0</span>]
<span class="line-numbers"> 373 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> [funcs[i].apply(<span class="Variable">this</span>, args)]
<span class="line-numbers"> 374 </span> args[<span class="Number">0</span>]
<span class="line-numbers"> 375 </span>
<span class="line-numbers"> 376 </span>
<span class="line-numbers"> 377 </span> <span class="Comment"><span class="Comment">#</span> ------------------------- Object Functions: ----------------------------</span>
<span class="line-numbers"> 378 </span>
<span class="line-numbers"> 379 </span> <span class="Comment"><span class="Comment">#</span> Retrieve the names of an object's properties.</span>
<span class="line-numbers"> 380 </span> <span class="FunctionName">_.keys</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 381 </span> <span class="Keyword">return</span> _.range(<span class="Number">0</span>, obj.length) <span class="Keyword">if</span> _.isArray(obj)
<span class="line-numbers"> 382 </span> key <span class="Keyword">for</span> key, val <span class="Keyword">of</span> obj
<span class="line-numbers"> 383 </span>
<span class="line-numbers"> 384 </span>
<span class="line-numbers"> 385 </span> <span class="Comment"><span class="Comment">#</span> Retrieve the values of an object's properties.</span>
<span class="line-numbers"> 386 </span> <span class="FunctionName">_.values</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 387 </span> _.map(obj, _.identity)
<span class="line-numbers"> 388 </span>
<span class="line-numbers"> 389 </span>
<span class="line-numbers"> 390 </span> <span class="Comment"><span class="Comment">#</span> Return a sorted list of the function names available in Underscore.</span>
<span class="line-numbers"> 391 </span> <span class="FunctionName">_.functions</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 392 </span> _.select(_.keys(obj), <span class="FunctionArgument">(</span><span class="FunctionArgument">key</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> _.isFunction(obj[key])).sort()
<span class="line-numbers"> 393 </span>
<span class="line-numbers"> 394 </span>
<span class="line-numbers"> 395 </span> <span class="Comment"><span class="Comment">#</span> Extend a given object with all of the properties in a source object.</span>
<span class="line-numbers"> 396 </span> <span class="FunctionName">_.extend</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">destination, source</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 397 </span> <span class="Keyword">for</span> key, val <span class="Keyword">of</span> source
<span class="line-numbers"> 398 </span> destination[key]<span class="Keyword">:</span> val
<span class="line-numbers"> 399 </span> destination
<span class="line-numbers"> 400 </span>
<span class="line-numbers"> 401 </span>
<span class="line-numbers"> 402 </span> <span class="Comment"><span class="Comment">#</span> Create a (shallow-cloned) duplicate of an object.</span>
<span class="line-numbers"> 403 </span> <span class="FunctionName">_.clone</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 404 </span> <span class="Keyword">return</span> obj.slice(<span class="Number">0</span>) <span class="Keyword">if</span> _.isArray(obj)
<span class="line-numbers"> 405 </span> _.extend({}, obj)
<span class="line-numbers"> 406 </span>
<span class="line-numbers"> 407 </span>
<span class="line-numbers"> 408 </span> <span class="Comment"><span class="Comment">#</span> Invokes interceptor with the obj, and then returns obj.</span>
<span class="line-numbers"> 409 </span> <span class="Comment"><span class="Comment">#</span> The primary purpose of this method is to &quot;tap into&quot; a method chain, in order to perform operations on intermediate results within the chain.</span>
<span class="line-numbers"> 410 </span> <span class="FunctionName">_.tap</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, interceptor</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 411 </span> interceptor(obj)
<span class="line-numbers"> 412 </span> obj
<span class="line-numbers"> 413 </span>
<span class="line-numbers"> 414 </span>
<span class="line-numbers"> 415 </span> <span class="Comment"><span class="Comment">#</span> Perform a deep comparison to check if two objects are equal.</span>
<span class="line-numbers"> 416 </span> <span class="FunctionName">_.isEqual</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">a, b</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 417 </span> <span class="Comment"><span class="Comment">#</span> Check object identity.</span>
<span class="line-numbers"> 418 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> a <span class="Keyword">is</span> b
<span class="line-numbers"> 419 </span> <span class="Comment"><span class="Comment">#</span> Different types?</span>
<span class="line-numbers"> 420 </span> <span class="FunctionName">atype</span><span class="Keyword">:</span> <span class="Keyword">typeof</span>(a); <span class="FunctionName">btype</span><span class="Keyword">:</span> <span class="Keyword">typeof</span>(b)
<span class="line-numbers"> 421 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> atype <span class="Keyword">isnt</span> btype
<span class="line-numbers"> 422 </span> <span class="Comment"><span class="Comment">#</span> Basic equality test (watch out for coercions).</span>
<span class="line-numbers"> 423 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> <span class="String"><span class="String">`</span>a == b<span class="String">`</span></span>
<span class="line-numbers"> 424 </span> <span class="Comment"><span class="Comment">#</span> One is falsy and the other truthy.</span>
<span class="line-numbers"> 425 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> (<span class="Keyword">!</span>a <span class="Keyword">and</span> b) <span class="Keyword">or</span> (a <span class="Keyword">and</span> <span class="Keyword">!</span>b)
<span class="line-numbers"> 426 </span> <span class="Comment"><span class="Comment">#</span> One of them implements an isEqual()?</span>
<span class="line-numbers"> 427 </span> <span class="Keyword">return</span> a.isEqual(b) <span class="Keyword">if</span> a.isEqual
<span class="line-numbers"> 428 </span> <span class="Comment"><span class="Comment">#</span> Check dates' integer values.</span>
<span class="line-numbers"> 429 </span> <span class="Keyword">return</span> a.getTime() <span class="Keyword">is</span> b.getTime() <span class="Keyword">if</span> _.isDate(a) <span class="Keyword">and</span> _.isDate(b)
<span class="line-numbers"> 430 </span> <span class="Comment"><span class="Comment">#</span> Both are NaN?</span>
<span class="line-numbers"> 431 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> _.isNaN(a) <span class="Keyword">and</span> _.isNaN(b)
<span class="line-numbers"> 432 </span> <span class="Comment"><span class="Comment">#</span> Compare regular expressions.</span>
<span class="line-numbers"> 433 </span> <span class="Keyword">if</span> _.isRegExp(a) <span class="Keyword">and</span> _.isRegExp(b)
<span class="line-numbers"> 434 </span> <span class="Keyword">return</span> a.source <span class="Keyword">is</span> b.source <span class="Keyword">and</span>
<span class="line-numbers"> 435 </span> a.global <span class="Keyword">is</span> b.global <span class="Keyword">and</span>
<span class="line-numbers"> 436 </span> a.ignoreCase <span class="Keyword">is</span> b.ignoreCase <span class="Keyword">and</span>
<span class="line-numbers"> 437 </span> a.multiline <span class="Keyword">is</span> b.multiline
<span class="line-numbers"> 438 </span> <span class="Comment"><span class="Comment">#</span> If a is not an object by this point, we can't handle it.</span>
<span class="line-numbers"> 439 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> atype <span class="Keyword">isnt</span> <span class="String"><span class="String">'</span>object<span class="String">'</span></span>
<span class="line-numbers"> 440 </span> <span class="Comment"><span class="Comment">#</span> Check for different array lengths before comparing contents.</span>
<span class="line-numbers"> 441 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> a.length <span class="Keyword">and</span> (a.length <span class="Keyword">isnt</span> b.length)
<span class="line-numbers"> 442 </span> <span class="Comment"><span class="Comment">#</span> Nothing else worked, deep compare the contents.</span>
<span class="line-numbers"> 443 </span> <span class="FunctionName">aKeys</span><span class="Keyword">:</span> _.keys(a); <span class="FunctionName">bKeys</span><span class="Keyword">:</span> _.keys(b)
<span class="line-numbers"> 444 </span> <span class="Comment"><span class="Comment">#</span> Different object sizes?</span>
<span class="line-numbers"> 445 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> aKeys.length <span class="Keyword">isnt</span> bKeys.length
<span class="line-numbers"> 446 </span> <span class="Comment"><span class="Comment">#</span> Recursive comparison of contents.</span>
<span class="line-numbers"> 447 </span> <span class="Comment"><span class="Comment">#</span> for (var key in a) if (!_.isEqual(a[key], b[key])) return false;</span>
<span class="line-numbers"> 448 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span>
<span class="line-numbers"> 449 </span>
<span class="line-numbers"> 450 </span>
<span class="line-numbers"> 451 </span> <span class="Comment"><span class="Comment">#</span> Is a given array or object empty?</span>
<span class="line-numbers"> 452 </span> <span class="FunctionName">_.isEmpty</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> _.keys(obj).length <span class="Keyword">is</span> <span class="Number">0</span>
<span class="line-numbers"> 453 </span>
<span class="line-numbers"> 454 </span>
<span class="line-numbers"> 455 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a DOM element?</span>
<span class="line-numbers"> 456 </span> <span class="FunctionName">_.isElement</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> obj <span class="Keyword">and</span> obj.nodeType <span class="Keyword">is</span> <span class="Number">1</span>
<span class="line-numbers"> 457 </span>
<span class="line-numbers"> 458 </span>
<span class="line-numbers"> 459 </span> <span class="Comment"><span class="Comment">#</span> Is a given value an array?</span>
<span class="line-numbers"> 460 </span> <span class="FunctionName">_.isArray</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.concat <span class="Keyword">and</span> obj.unshift)
<span class="line-numbers"> 461 </span>
<span class="line-numbers"> 462 </span>
<span class="line-numbers"> 463 </span> <span class="Comment"><span class="Comment">#</span> Is a given variable an arguments object?</span>
<span class="line-numbers"> 464 </span> <span class="FunctionName">_.isArguments</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> obj <span class="Keyword">and</span> _.isNumber(obj.length) <span class="Keyword">and</span> <span class="Keyword">not</span> obj.concat <span class="Keyword">and</span>
<span class="line-numbers"> 465 </span> <span class="Keyword">not</span> obj.substr <span class="Keyword">and</span> <span class="Keyword">not</span> obj.apply <span class="Keyword">and</span> <span class="Keyword">not</span> propertyIsEnumerable.call(obj, <span class="String"><span class="String">'</span>length<span class="String">'</span></span>)
<span class="line-numbers"> 466 </span>
<span class="line-numbers"> 467 </span>
<span class="line-numbers"> 468 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a function?</span>
<span class="line-numbers"> 469 </span> <span class="FunctionName">_.isFunction</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.constructor <span class="Keyword">and</span> obj.call <span class="Keyword">and</span> obj.apply)
<span class="line-numbers"> 470 </span>
<span class="line-numbers"> 471 </span>
<span class="line-numbers"> 472 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a string?</span>
<span class="line-numbers"> 473 </span> <span class="FunctionName">_.isString</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">is</span> <span class="String"><span class="String">'</span><span class="String">'</span></span> <span class="Keyword">or</span> (obj <span class="Keyword">and</span> obj.charCodeAt <span class="Keyword">and</span> obj.substr))
<span class="line-numbers"> 474 </span>
<span class="line-numbers"> 475 </span>
<span class="line-numbers"> 476 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a number?</span>
<span class="line-numbers"> 477 </span> <span class="FunctionName">_.isNumber</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> (obj <span class="Keyword">is</span> <span class="Keyword">+</span>obj) <span class="Keyword">or</span> toString.call(obj) <span class="Keyword">is</span> <span class="String"><span class="String">'</span>[object Number]<span class="String">'</span></span>
<span class="line-numbers"> 478 </span>
<span class="line-numbers"> 479 </span>
<span class="line-numbers"> 480 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a Date?</span>
<span class="line-numbers"> 481 </span> <span class="FunctionName">_.isDate</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.getTimezoneOffset <span class="Keyword">and</span> obj.setUTCFullYear)
<span class="line-numbers"> 482 </span>
<span class="line-numbers"> 483 </span>
<span class="line-numbers"> 484 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a regular expression?</span>
<span class="line-numbers"> 485 </span> <span class="FunctionName">_.isRegExp</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.exec <span class="Keyword">and</span> (obj.ignoreCase <span class="Keyword">or</span> obj.ignoreCase <span class="Keyword">is</span> <span class="BuiltInConstant">false</span>))
<span class="line-numbers"> 486 </span>
<span class="line-numbers"> 487 </span>
<span class="line-numbers"> 488 </span> <span class="Comment"><span class="Comment">#</span> Is the given value NaN -- this one is interesting. NaN != NaN, and</span>
<span class="line-numbers"> 489 </span> <span class="Comment"><span class="Comment">#</span> isNaN(undefined) == true, so we make sure it's a number first.</span>
<span class="line-numbers"> 490 </span> <span class="FunctionName">_.isNaN</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> _.isNumber(obj) <span class="Keyword">and</span> window.isNaN(obj)
<span class="line-numbers"> 491 </span>
<span class="line-numbers"> 492 </span>
<span class="line-numbers"> 493 </span> <span class="Comment"><span class="Comment">#</span> Is a given value equal to null?</span>
<span class="line-numbers"> 494 </span> <span class="FunctionName">_.isNull</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> obj <span class="Keyword">is</span> <span class="BuiltInConstant">null</span>
<span class="line-numbers"> 495 </span>
<span class="line-numbers"> 496 </span>
<span class="line-numbers"> 497 </span> <span class="Comment"><span class="Comment">#</span> Is a given variable undefined?</span>
<span class="line-numbers"> 498 </span> <span class="FunctionName">_.isUndefined</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> <span class="Keyword">typeof</span> obj <span class="Keyword">is</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span>
<span class="line-numbers"> 499 </span>
<span class="line-numbers"> 500 </span>
<span class="line-numbers"> 501 </span> <span class="Comment"><span class="Comment">#</span> -------------------------- Utility Functions: --------------------------</span>
<span class="line-numbers"> 502 </span>
<span class="line-numbers"> 503 </span> <span class="Comment"><span class="Comment">#</span> Run Underscore.js in noConflict mode, returning the '_' variable to its</span>
<span class="line-numbers"> 504 </span> <span class="Comment"><span class="Comment">#</span> previous owner. Returns a reference to the Underscore object.</span>
<span class="line-numbers"> 505 </span> <span class="FunctionName">_.noConflict</span><span class="Keyword">:</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 506 </span> <span class="FunctionName">root._</span><span class="Keyword">:</span> previousUnderscore
<span class="line-numbers"> 507 </span> <span class="Variable">this</span>
<span class="line-numbers"> 508 </span>
<span class="line-numbers"> 509 </span>
<span class="line-numbers"> 510 </span> <span class="Comment"><span class="Comment">#</span> Keep the identity function around for default iterators.</span>
<span class="line-numbers"> 511 </span> <span class="FunctionName">_.identity</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">value</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> value
<span class="line-numbers"> 512 </span>
<span class="line-numbers"> 513 </span>
<span class="line-numbers"> 514 </span> <span class="Comment"><span class="Comment">#</span> Break out of the middle of an iteration.</span>
<span class="line-numbers"> 515 </span> <span class="FunctionName">_.breakLoop</span><span class="Keyword">:</span> <span class="Storage">-&gt;</span> <span class="Keyword">throw</span> breaker
<span class="line-numbers"> 516 </span>
<span class="line-numbers"> 517 </span>
<span class="line-numbers"> 518 </span> <span class="Comment"><span class="Comment">#</span> Generate a unique integer id (unique within the entire client session).</span>
<span class="line-numbers"> 519 </span> <span class="Comment"><span class="Comment">#</span> Useful for temporary DOM ids.</span>
<span class="line-numbers"> 520 </span> <span class="FunctionName">idCounter</span><span class="Keyword">:</span> <span class="Number">0</span>
<span class="line-numbers"> 521 </span> <span class="FunctionName">_.uniqueId</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">prefix</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 522 </span> (prefix <span class="Keyword">or</span> <span class="String"><span class="String">'</span><span class="String">'</span></span>) <span class="Keyword">+</span> idCounter<span class="Keyword">++</span>
<span class="line-numbers"> 523 </span>
<span class="line-numbers"> 524 </span>
<span class="line-numbers"> 525 </span> <span class="Comment"><span class="Comment">#</span> By default, Underscore uses ERB-style template delimiters, change the</span>
<span class="line-numbers"> 526 </span> <span class="Comment"><span class="Comment">#</span> following template settings to use alternative delimiters.</span>
<span class="line-numbers"> 527 </span> <span class="FunctionName">_.templateSettings</span><span class="Keyword">:</span> {
<span class="line-numbers"> 528 </span> <span class="FunctionName">start</span><span class="Keyword">:</span> <span class="String"><span class="String">'</span>&lt;%<span class="String">'</span></span>
<span class="line-numbers"> 529 </span> <span class="FunctionName">end</span><span class="Keyword">:</span> <span class="String"><span class="String">'</span>%&gt;<span class="String">'</span></span>
<span class="line-numbers"> 530 </span> <span class="FunctionName">interpolate</span><span class="Keyword">:</span><span class="String"> <span class="String">/</span>&lt;%=(.+?)%&gt;<span class="String">/</span>g</span>
<span class="line-numbers"> 531 </span> }
<span class="line-numbers"> 532 </span>
<span class="line-numbers"> 533 </span>
<span class="line-numbers"> 534 </span> <span class="Comment"><span class="Comment">#</span> JavaScript templating a-la ERB, pilfered from John Resig's</span>
<span class="line-numbers"> 535 </span> <span class="Comment"><span class="Comment">#</span> &quot;Secrets of the JavaScript Ninja&quot;, page 83.</span>
<span class="line-numbers"> 536 </span> <span class="Comment"><span class="Comment">#</span> Single-quote fix from Rick Strahl's version.</span>
<span class="line-numbers"> 537 </span> <span class="FunctionName">_.template</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">str, data</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 538 </span> <span class="FunctionName">c</span><span class="Keyword">:</span> _.templateSettings
<span class="line-numbers"> 539 </span> <span class="FunctionName">fn</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Function</span> <span class="String"><span class="String">'</span>obj<span class="String">'</span></span>,
<span class="line-numbers"> 540 </span> <span class="String"><span class="String">'</span>var p=[],print=function(){p.push.apply(p,arguments);};<span class="String">'</span></span> <span class="Keyword">+</span>
<span class="line-numbers"> 541 </span> <span class="String"><span class="String">'</span>with(obj){p.push(<span class="UserDefinedConstant">\'</span><span class="String">'</span></span> <span class="Keyword">+</span>
<span class="line-numbers"> 542 </span> str.replace(<span class="String"><span class="String">/</span>[<span class="UserDefinedConstant">\r</span><span class="UserDefinedConstant">\t</span><span class="UserDefinedConstant">\n</span>]<span class="String">/</span>g</span>, <span class="String"><span class="String">&quot;</span> <span class="String">&quot;</span></span>)
<span class="line-numbers"> 543 </span> .replace(<span class="Keyword">new</span> <span class="TypeName">RegExp</span>(<span class="String"><span class="String">&quot;</span>'(?=[^<span class="String">&quot;</span></span><span class="Keyword">+</span>c.end[<span class="Number">0</span>]<span class="Keyword">+</span><span class="String"><span class="String">&quot;</span>]*<span class="String">&quot;</span></span><span class="Keyword">+</span>c.end<span class="Keyword">+</span><span class="String"><span class="String">&quot;</span>)<span class="String">&quot;</span></span>,<span class="String"><span class="String">&quot;</span>g<span class="String">&quot;</span></span>),<span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\t</span><span class="String">&quot;</span></span>)
<span class="line-numbers"> 544 </span> .split(<span class="String"><span class="String">&quot;</span>'<span class="String">&quot;</span></span>).join(<span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>'<span class="String">&quot;</span></span>)
<span class="line-numbers"> 545 </span> .split(<span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\t</span><span class="String">&quot;</span></span>).join(<span class="String"><span class="String">&quot;</span>'<span class="String">&quot;</span></span>)
<span class="line-numbers"> 546 </span> .replace(c.interpolate, <span class="String"><span class="String">&quot;</span>',$1,'<span class="String">&quot;</span></span>)
<span class="line-numbers"> 547 </span> .split(c.start).join(<span class="String"><span class="String">&quot;</span>');<span class="String">&quot;</span></span>)
<span class="line-numbers"> 548 </span> .split(c.end).join(<span class="String"><span class="String">&quot;</span>p.push('<span class="String">&quot;</span></span>) <span class="Keyword">+</span>
<span class="line-numbers"> 549 </span> <span class="String"><span class="String">&quot;</span>');}return p.join('');<span class="String">&quot;</span></span>
<span class="line-numbers"> 550 </span> <span class="Keyword">if</span> data <span class="Keyword">then</span> fn(data) <span class="Keyword">else</span> fn
<span class="line-numbers"> 551 </span>
<span class="line-numbers"> 552 </span>
<span class="line-numbers"> 553 </span> <span class="Comment"><span class="Comment">#</span> ------------------------------- Aliases ----------------------------------</span>
<span class="line-numbers"> 554 </span>
<span class="line-numbers"> 555 </span> <span class="FunctionName">_.forEach</span><span class="Keyword">:</span> _.each
<span class="line-numbers"> 556 </span> <span class="FunctionName">_.foldl</span><span class="Keyword">:</span> <span class="FunctionName">_.inject</span><span class="Keyword">:</span> _.reduce
<span class="line-numbers"> 557 </span> <span class="FunctionName">_.foldr</span><span class="Keyword">:</span> _.reduceRight
<span class="line-numbers"> 558 </span> <span class="FunctionName">_.filter</span><span class="Keyword">:</span> _.select
<span class="line-numbers"> 559 </span> <span class="FunctionName">_.every</span><span class="Keyword">:</span> _.all
<span class="line-numbers"> 560 </span> <span class="FunctionName">_.some</span><span class="Keyword">:</span> _.any
<span class="line-numbers"> 561 </span> <span class="FunctionName">_.head</span><span class="Keyword">:</span> _.first
<span class="line-numbers"> 562 </span> <span class="FunctionName">_.tail</span><span class="Keyword">:</span> _.rest
<span class="line-numbers"> 563 </span> <span class="FunctionName">_.methods</span><span class="Keyword">:</span> _.functions
<span class="line-numbers"> 564 </span>
<span class="line-numbers"> 565 </span>
<span class="line-numbers"> 566 </span> <span class="Comment"><span class="Comment">#</span> ------------------------ Setup the OOP Wrapper: --------------------------</span>
<span class="line-numbers"> 567 </span>
<span class="line-numbers"> 568 </span> <span class="Comment"><span class="Comment">#</span> Helper function to continue chaining intermediate results.</span>
<span class="line-numbers"> 569 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, chain</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 570 </span> <span class="Keyword">if</span> chain <span class="Keyword">then</span> _(obj).chain() <span class="Keyword">else</span> obj
<span class="line-numbers"> 571 </span>
<span class="line-numbers"> 572 </span>
<span class="line-numbers"> 573 </span> <span class="Comment"><span class="Comment">#</span> Add all of the Underscore functions to the wrapper object.</span>
<span class="line-numbers"> 574 </span> _.each _.functions(_), <span class="FunctionArgument">(</span><span class="FunctionArgument">name</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 575 </span> <span class="FunctionName">method</span><span class="Keyword">:</span> _[name]
<span class="line-numbers"> 576 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 577 </span> unshift.call(arguments, <span class="Variable">this</span>._wrapped)
<span class="line-numbers"> 578 </span> result(method.apply(_, arguments), <span class="Variable">this</span>._chain)
<span class="line-numbers"> 579 </span>
<span class="line-numbers"> 580 </span>
<span class="line-numbers"> 581 </span> <span class="Comment"><span class="Comment">#</span> Add all mutator Array functions to the wrapper.</span>
<span class="line-numbers"> 582 </span> _.each [<span class="String"><span class="String">'</span>pop<span class="String">'</span></span>, <span class="String"><span class="String">'</span>push<span class="String">'</span></span>, <span class="String"><span class="String">'</span>reverse<span class="String">'</span></span>, <span class="String"><span class="String">'</span>shift<span class="String">'</span></span>, <span class="String"><span class="String">'</span>sort<span class="String">'</span></span>, <span class="String"><span class="String">'</span>splice<span class="String">'</span></span>, <span class="String"><span class="String">'</span>unshift<span class="String">'</span></span>], <span class="FunctionArgument">(</span><span class="FunctionArgument">name</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 583 </span> <span class="FunctionName">method</span><span class="Keyword">:</span> Array.prototype[name]
<span class="line-numbers"> 584 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 585 </span> method.apply(<span class="Variable">this</span>._wrapped, arguments)
<span class="line-numbers"> 586 </span> result(<span class="Variable">this</span>._wrapped, <span class="Variable">this</span>._chain)
<span class="line-numbers"> 587 </span>
<span class="line-numbers"> 588 </span>
<span class="line-numbers"> 589 </span> <span class="Comment"><span class="Comment">#</span> Add all accessor Array functions to the wrapper.</span>
<span class="line-numbers"> 590 </span> _.each [<span class="String"><span class="String">'</span>concat<span class="String">'</span></span>, <span class="String"><span class="String">'</span>join<span class="String">'</span></span>, <span class="String"><span class="String">'</span>slice<span class="String">'</span></span>], <span class="FunctionArgument">(</span><span class="FunctionArgument">name</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 591 </span> <span class="FunctionName">method</span><span class="Keyword">:</span> Array.prototype[name]
<span class="line-numbers"> 592 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 593 </span> result(method.apply(<span class="Variable">this</span>._wrapped, arguments), <span class="Variable">this</span>._chain)
<span class="line-numbers"> 594 </span>
<span class="line-numbers"> 595 </span>
<span class="line-numbers"> 596 </span> <span class="Comment"><span class="Comment">#</span> Start chaining a wrapped Underscore object.</span>
<span class="line-numbers"> 597 </span> <span class="FunctionName">wrapper::chain</span><span class="Keyword">:</span> <span class="Storage">-&gt;</span>
<span class="line-numbers"> 598 </span> <span class="FunctionName">this._chain</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
<span class="line-numbers"> 599 </span> <span class="Variable">this</span>
<span class="line-numbers"> 600 </span>
<span class="line-numbers"> 601 </span>
<span class="line-numbers"> 602 </span> <span class="Comment"><span class="Comment">#</span> Extracts the result from a wrapped and chained object.</span>
<span class="line-numbers"> 603 </span> <span class="FunctionName">wrapper::value</span><span class="Keyword">:</span> <span class="Storage">-&gt;</span> <span class="Variable">this</span>._wrapped
</pre> <p>
<a href="http://validator.w3.org/check?uri=referer">
<img style="border:0"
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Strict" height="31" width="88" />
</a>
<a href="http://jigsaw.w3.org/css-validator/check?uri=referer">
<img style="border:0;width:88px;height:31px"
src="http://jigsaw.w3.org/css-validator/images/vcss"
alt="Valid CSS!" />
</a>
</p>
</body>
</html>

View File

@@ -1,72 +0,0 @@
# Document Model
dc.model.Document: dc.Model.extend({
constructor: attributes => this.base(attributes).
# For display, show either the highlighted search results, or the summary,
# if no highlights are available.
# The import process will take care of this in the future, but the inline
# version of the summary has all runs of whitespace squeezed out.
displaySummary: =>
text: this.get('highlight') or this.get('summary') or ''
text and text.replace(/\s+/g, ' ').
# Return a list of the document's metadata. Think about caching this on the
# document by binding to Metadata, instead of on-the-fly.
metadata: =>
docId: this.id
_.select(Metadata.models()
meta => _.any(meta.get('instances')
instance => instance.document_id is docId.).).
bookmark: pageNumber =>
bookmark: new dc.model.Bookmark({title: this.get('title'), page_number: pageNumber, document_id: this.id})
Bookmarks.create(bookmark).
# Inspect.
toString: => 'Document ' + this.id + ' "' + this.get('title') + '"'.
})
# Document Set
dc.model.DocumentSet: dc.model.RESTfulSet.extend({
resource: 'documents'
SELECTION_CHANGED: 'documents:selection_changed'
constructor: options =>
this.base(options)
_.bindAll(this, 'downloadSelectedViewers', 'downloadSelectedPDF', 'downloadSelectedFullText').
selected: => _.select(this.models(), m => m.get('selected').).
selectedIds: => _.pluck(this.selected(), 'id').
countSelected: => this.selected().length.
downloadSelectedViewers: =>
dc.app.download('/download/' + this.selectedIds().join('/') + '/document_viewer.zip').
downloadSelectedPDF: =>
if this.countSelected() <= 1 then return window.open(this.selected()[0].get('pdf_url')).
dc.app.download('/download/' + this.selectedIds().join('/') + '/document_pdfs.zip').
downloadSelectedFullText: =>
if this.countSelected() <= 1 then return window.open(this.selected()[0].get('full_text_url')).
dc.app.download('/download/' + this.selectedIds().join('/') + '/document_text.zip').
# We override "_onModelEvent" to fire selection changed events when documents
# change their selected state.
_onModelEvent: e, model =>
this.base(e, model)
fire: e == dc.Model.CHANGED and model.hasChanged('selected')
if fire then _.defer(_(this.fire).bind(this, this.SELECTION_CHANGED, this))..
})
# The main set of Documents, used by the search tab.
window.Documents: new dc.model.DocumentSet()
# The set of documents that is used to look at a particular label.
dc.app.LabeledDocuments: new dc.model.DocumentSet()

View File

@@ -0,0 +1,16 @@
# Beautiful Code, Chapter 6.
# The implementation of binary search that is tested.
# Return the index of an element in a sorted list. (or -1, if not present)
index: (list, target) ->
[low, high]: [0, list.length]
while low < high
mid: (low + high) >> 1
val: list[mid]
return mid if val is target
if val < target then low: mid + 1 else high: mid
return -1
puts 2 is index([10, 20, 30, 40, 50], 30)
puts 4 is index([-97, 35, 67, 88, 1200], 1200)
puts 0 is index([0, 45, 70], 0)

View File

@@ -0,0 +1,13 @@
# Beautiful Code, Chapter 3.
# Produces the expected runtime of Quicksort, for every integer from 1 to N.
runtime: (N) ->
[sum, t]: [0, 0]
for n in [1..N]
sum += 2 * t
t: n - 1 + sum / n
t
puts runtime(3) is 2.6666666666666665
puts runtime(5) is 7.4
puts runtime(8) is 16.92142857142857

View File

@@ -0,0 +1,34 @@
# Beautiful Code, Chapter 1.
# Implements a regular expression matcher that supports character matches,
# '.', '^', '$', and '*'.
# Search for the regexp anywhere in the text.
match: (regexp, text) ->
return match_here(regexp.slice(1), text) if regexp[0] is '^'
while text
return true if match_here(regexp, text)
text: text.slice(1)
false
# Search for the regexp at the beginning of the text.
match_here: (regexp, text) ->
[cur, next]: [regexp[0], regexp[1]]
if regexp.length is 0 then return true
if next is '*' then return match_star(cur, regexp.slice(2), text)
if cur is '$' and not next then return text.length is 0
if text and (cur is '.' or cur is text[0]) then return match_here(regexp.slice(1), text.slice(1))
false
# Search for a kleene star match at the beginning of the text.
match_star: (c, regexp, text) ->
while true
return true if match_here(regexp, text)
return false unless text and (text[0] is c or c is '.')
text: text.slice(1)
puts match("ex", "some text")
puts match("s..t", "spit")
puts match("^..t", "buttercup")
puts match("i..$", "cherries")
puts match("o*m", "vrooooommm!")
puts match("^hel*o$", "hellllllo")

57
examples/blocks.coffee Normal file
View File

@@ -0,0 +1,57 @@
# After wycats' http://yehudakatz.com/2010/02/07/the-building-blocks-of-ruby/
# Sinatra.
get '/hello', ->
'Hello World'
# Append.
append: (location, data) ->
path: new Pathname location
throw new Error("Location does not exist") unless path.exists()
File.open path, 'a', (file) ->
file.puts YAML.dump data
data
# Rubinius' File.open implementation.
File.open: (path, mode, block) ->
io: new File path, mode
return io unless block
try
block io
finally
try
io.close() unless io.closed()
catch error
# nothing, just swallow them.
# Write.
write: (location, data) ->
path = new Pathname location
raise "Location does not exist" unless path.exists()
File.open path, 'w', (file) ->
return false if Digest.MD5.hexdigest(file.read()) is data.hash()
file.puts YAML.dump data
true
# Rails' respond_to.
index: ->
people: Person.find 'all'
respond_to (format) ->
format.html()
format.xml -> render { xml: people.xml() }
# Synchronization.
synchronize: (block) ->
lock()
try block() finally unlock()

173
examples/code.coffee Normal file
View File

@@ -0,0 +1,173 @@
# Functions:
square: (x) -> x * x
sum: (x, y) -> x + y
odd: (x) -> x % 2 isnt 0
even: (x) -> x % 2 is 0
run_loop: ->
fire_events((e) -> e.stopPropagation())
listen()
wait()
# Objects:
dense_object_literal: {one: 1, two: 2, three: 3}
spaced_out_multiline_object: {
pi: 3.14159
list: [1, 2, 3, 4]
regex: /match[ing](every|thing|\/)/gi
three: new Idea()
inner_obj: {
freedom: -> _.freedom()
}
}
# Arrays:
stooges: [{moe: 45}, {curly: 43}, {larry: 46}]
exponents: [(x) -> x, (x) -> x * x, (x) -> x * x * x]
empty: []
multiline: [
'line one'
'line two'
]
# Conditionals and ternaries.
if submarine.shields_up
full_speed_ahead()
fire_torpedos()
else if submarine.sinking
abandon_ship()
else
run_away()
eldest: if 25 > 21 then liz else marge
decoration: medal_of_honor if war_hero
go_to_sleep() unless coffee
# Returning early:
race: ->
run()
walk()
crawl()
if tired then return sleep()
race()
# Conditional assignment:
good ||= evil
wine &&= cheese
# Nested property access and calls.
((moon.turn(360))).shapes[3].move({x: 45, y: 30}).position['top'].offset('x')
a: b: c: 5
# Embedded JavaScript.
callback(
`function(e) { e.stop(); }`
)
# Try/Catch/Finally/Throw.
try
all_hell_breaks_loose()
dogs_and_cats_living_together()
throw "up"
catch error
print(error)
finally
clean_up()
try all_hell_breaks_loose() catch error then print(error) finally clean_up()
# While loops, break and continue.
while demand > supply
sell()
restock()
while supply > demand then buy()
while true
break if broken
continue if continuing
# Unary operators.
!!true
# Lexical scoping.
v_1: 5
change_a_and_set_b: ->
v_1: 10
v_2: 15
v_2: 20
# Array comprehensions.
supper: food.capitalize() for food in ['toast', 'cheese', 'wine']
drink(bottle) for bottle, i in ['soda', 'wine', 'lemonade'] when even(i)
# Switch statements ("else" serves as a default).
activity: switch day
when "Tuesday" then eat_breakfast()
when "Sunday" then go_to_church()
when "Saturday" then go_to_the_park()
when "Wednesday"
if day is bingo_day
go_to_bingo()
else
eat_breakfast()
go_to_work()
eat_dinner()
else go_to_work()
# Semicolons can optionally be used instead of newlines.
wednesday: -> eat_breakfast(); go_to_work(); eat_dinner()
# Array slice literals.
zero_to_nine: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
three_to_six: zero_to_nine[3..6]
# Multiline strings with inner quotes.
story: "Lorem ipsum dolor \"sit\" amet, consectetuer adipiscing elit,
sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna
aliquam erat volutpat. Ut wisi enim ad."
# Inheritance and calling super.
Animal: ->
Animal::move: (meters) ->
alert(this.name + " moved " + meters + "m.")
Snake: (name) -> this.name: name
Snake extends Animal
Snake::move: ->
alert('Slithering...')
super(5)
Horse: (name) -> this.name: name
Horse extends Animal
Horse::move: ->
alert('Galloping...')
super(45)
sam: new Snake("Sammy the Snake")
tom: new Horse("Tommy the Horse")
sam.move()
tom.move()
# Numbers.
a_googol: 1e100
hex: 0xff0000
negative: -1.0
infinity: Infinity
nan: NaN
# Deleting.
delete secret.identity

View File

@@ -0,0 +1,4 @@
Ported from Nicholas Zakas' collection of computer science fundamentals, written
in JavaScript. Originals available here:
http://github.com/nzakas/computer-science-in-javascript

View File

@@ -0,0 +1,25 @@
# Uses a binary search algorithm to locate a value in the specified array.
binary_search: (items, value) ->
start: 0
stop: items.length - 1
pivot: Math.floor((start + stop) / 2)
while items[pivot] isnt value and start < stop
# Adjust the search area.
stop: pivot - 1 if value < items[pivot]
start: pivot + 1 if value > items[pivot]
# Recalculate the pivot.
pivot: Math.floor((stop + start) / 2)
# Make sure we've found the correct value.
if items[pivot] is value then pivot else -1
# Test the function.
puts(2 is binary_search([10, 20, 30, 40, 50], 30))
puts(4 is binary_search([-97, 35, 67, 88, 1200], 1200))
puts(0 is binary_search([0, 45, 70], 0))
puts(-1 is binary_search([0, 45, 70], 10))

View File

@@ -0,0 +1,11 @@
# A bubble sort implementation, sorting the given array in-place.
bubble_sort: (list) ->
for i in [0...list.length]
for j in [0...list.length - i]
[list[j], list[j+1]]: [list[j+1], list[j]] if list[j] > list[j+1]
list
# Test the function.
puts(bubble_sort([3, 2, 1]).join(' ') is '1 2 3')
puts(bubble_sort([9, 2, 7, 0, 1]).join(' ') is '0 1 2 7 9')

View File

@@ -0,0 +1,106 @@
# "Classic" linked list implementation that doesn't keep track of its size.
LinkedList: ->
this._head: null # Pointer to the first item in the list.
# Appends some data to the end of the list. This method traverses the existing
# list and places the value at the end in a new node.
LinkedList::add: (data) ->
# Create a new node object to wrap the data.
node: {data: data, next: null}
current: this._head ||= node
if this._head isnt node
current: current.next while current.next
current.next: node
this
# Retrieves the data at the given position in the list.
LinkedList::item: (index) ->
# Check for out-of-bounds values.
return null if index < 0
current: this._head or null
i: -1
# Advance through the list.
current: current.next while current and index > (i += 1)
# Return null if we've reached the end.
current and current.data
# Remove the item from the given location in the list.
LinkedList::remove: (index) ->
# Check for out-of-bounds values.
return null if index < 0
current: this._head or null
i: -1
# Special case: removing the first item.
if index is 0
this._head: current.next
else
# Find the right location.
[previous, current]: [current, current.next] while index > (i += 1)
# Skip over the item to remove.
previous.next: current.next
# Return the value.
current and current.data
# Calculate the number of items in the list.
LinkedList::size: ->
current: this._head
count: 0
while current
count += 1
current: current.next
count
# Convert the list into an array.
LinkedList::toArray: ->
result: []
current: this._head
while current
result.push(current.data)
current: current.next
result
# The string representation of the linked list.
LinkedList::toString: -> this.toArray().toString()
# Tests.
list: new LinkedList()
list.add("Hi")
puts(list.size() is 1)
puts(list.item(0) is "Hi")
puts(list.item(1) is null)
list: new LinkedList()
list.add("zero").add("one").add("two")
puts(list.size() is 3)
puts(list.item(2) is "two")
puts(list.remove(1) is "one")
puts(list.item(0) is "zero")
puts(list.item(1) is "two")
puts(list.size() is 2)
puts(list.item(-10) is null)

View File

@@ -0,0 +1,36 @@
# Use the Luhn algorithm to validate a numeric identifier, such as credit card
# numbers, national insurance numbers, etc.
# See: http://en.wikipedia.org/wiki/Luhn_algorithm
is_valid_identifier: (identifier) ->
sum: 0
alt: false
for i in [(identifier.length - 1)..0]
# Get the next digit.
num: parseInt(identifier.charAt(i), 10)
# If it's not a valid number, abort.
return false if isNaN(num)
# If it's an alternate number...
if alt
num *= 2
num: (num % 10) + 1 if num > 9
# Flip the alternate bit.
alt: !alt
# Add to the rest of the sum.
sum += num
# Determine if it's valid.
sum % 10 is 0
# Tests.
puts(is_valid_identifier("49927398716") is true)
puts(is_valid_identifier("4408041234567893") is true)
puts(is_valid_identifier("4408041234567890") is false)

View File

@@ -0,0 +1,19 @@
# Sorts an array in ascending natural order using merge sort.
merge_sort: (list) ->
return list if list.length is 1
result: []
pivot: Math.floor(list.length / 2)
left: merge_sort(list.slice(0, pivot))
right: merge_sort(list.slice(pivot))
while left.length and right.length
result.push(if left[0] < right[0] then left.shift() else right.shift())
result.concat(left).concat(right)
# Test the function.
puts(merge_sort([3, 2, 1]).join(' ') is '1 2 3')
puts(merge_sort([9, 2, 7, 0, 1]).join(' ') is '0 1 2 7 9')

View File

@@ -0,0 +1,23 @@
# An in-place selection sort.
selection_sort: (list) ->
len: list.length
# For each item in the list.
for i in [0...len]
# Set the minimum to this position.
min: i
# Check the rest of the array to see if anything is smaller.
(min: j if list[j] < list[min]) for j in [(i+1)...len]
# Swap if a smaller item has been found.
[list[i], list[min]]: [list[min], list[i]] if i isnt min
# The list is now sorted.
list
# Test the function.
puts(selection_sort([3, 2, 1]).join(' ') is '1 2 3')
puts(selection_sort([9, 2, 7, 0, 1]).join(' ') is '0 1 2 7 9')

186
examples/poignant.coffee Normal file
View File

@@ -0,0 +1,186 @@
# Examples from the Poignant Guide.
# ['toast', 'cheese', 'wine'].each { |food| print food.capitalize }
['toast', 'wine', 'cheese'].each (food) -> print(food.capitalize())
# class LotteryTicket
# def picks; @picks; end
# def picks=(var); @picks = var; end
# def purchased; @purchased; end
# def purchased=(var); @purchased = var; end
# end
LotteryTicket: {
get_picks: -> this.picks
set_picks: (nums) -> this.picks: nums
get_purchase: -> this.purchase
set_purchase: (amount) -> this.purchase: amount
}
# class << LotteryDraw
# def play
# result = LotteryTicket.new_random
# winners = {}
# @@tickets.each do |buyer, ticket_list|
# ticket_list.each do |ticket|
# score = ticket.score( result )
# next if score.zero?
# winners[buyer] ||= []
# winners[buyer] << [ ticket, score ]
# end
# end
# @@tickets.clear
# winners
# end
# end
LotteryDraw: {
play: ->
result: LotteryTicket.new_random()
winners: {}
this.tickets.each (buyer, ticket_list) ->
ticket_list.each (ticket) ->
score: ticket.score(result)
return if score is 0
winners[buyer] ||= []
winners[buyer].push([ticket, score])
this.tickets: {}
winners
}
# module WishScanner
# def scan_for_a_wish
# wish = self.read.detect do |thought|
# thought.index( 'wish: ' ) == 0
# end
# wish.gsub( 'wish: ', '' )
# end
# end
WishScanner: {
scan_for_a_wish: ->
wish: this.read().detect((thought) -> thought.index('wish: ') is 0)
wish.replace('wish: ', '')
}
# class Creature
#
# # This method applies a hit taken during a fight.
# def hit( damage )
# p_up = rand( charisma )
# if p_up % 9 == 7
# @life += p_up / 4
# puts "[#{ self.class } magick powers up #{ p_up }!]"
# end
# @life -= damage
# puts "[#{ self.class } has died.]" if @life <= 0
# end
#
# # This method takes one turn in a fight.
# def fight( enemy, weapon )
# if life <= 0
# puts "[#{ self.class } is too dead to fight!]"
# return
# end
#
# # Attack the opponent
# your_hit = rand( strength + weapon )
# puts "[You hit with #{ your_hit } points of damage!]"
# enemy.hit( your_hit )
#
# # Retaliation
# p enemy
# if enemy.life > 0
# enemy_hit = rand( enemy.strength + enemy.weapon )
# puts "[Your enemy hit with #{ enemy_hit } points of damage!]"
# self.hit( enemy_hit )
# end
# end
#
# end
Creature : {
# This method applies a hit taken during a fight.
hit: (damage) ->
p_up: Math.rand(this.charisma)
if p_up % 9 is 7
this.life += p_up / 4
puts("[" + this.name + " magick powers up " + p_up + "!]")
this.life -= damage
if this.life <= 0 then puts("[" + this.name + " has died.]")
# This method takes one turn in a fight.
fight: (enemy, weapon) ->
if this.life <= 0 then return puts("[" + this.name + "is too dead to fight!]")
# Attack the opponent.
your_hit: Math.rand(this.strength + weapon)
puts("[You hit with " + your_hit + "points of damage!]")
enemy.hit(your_hit)
# Retaliation.
puts(enemy)
if enemy.life > 0
enemy_hit: Math.rand(enemy.strength + enemy.weapon)
puts("[Your enemy hit with " + enemy_hit + "points of damage!]")
this.hit(enemy_hit)
}
# # Get evil idea and swap in code words
# print "Enter your new idea: "
# idea = gets
# code_words.each do |real, code|
# idea.gsub!( real, code )
# end
#
# # Save the jibberish to a new file
# print "File encoded. Please enter a name for this idea: "
# idea_name = gets.strip
# File::open( "idea-" + idea_name + ".txt", "w" ) do |f|
# f << idea
# end
# Get evil idea and swap in code words
print("Enter your new idea: ")
idea: gets()
code_words.each((real, code) -> idea.replace(real, code))
# Save the jibberish to a new file
print("File encoded. Please enter a name for this idea: ")
idea_name: gets().strip()
File.open("idea-" + idea_name + '.txt', 'w', (file) -> file.write(idea))
# def wipe_mutterings_from( sentence )
# unless sentence.respond_to? :include?
# raise ArgumentError,
# "cannot wipe mutterings from a #{ sentence.class }"
# end
# while sentence.include? '('
# open = sentence.index( '(' )
# close = sentence.index( ')', open )
# sentence[open..close] = '' if close
# end
# end
wipe_mutterings_from: (sentence) ->
throw new Error("cannot wipe mutterings") unless sentence.indexOf
while sentence.indexOf('(') >= 0
open: sentence.indexOf('(') - 1
close: sentence.indexOf(')') + 1
sentence: sentence[0..open] + sentence[close..sentence.length]
sentence

205
examples/potion.coffee Normal file
View File

@@ -0,0 +1,205 @@
# Examples from _why's Potion, the Readme and "Potion: A Short Pamphlet".
# 5 times: "Odelay!" print.
print("Odelay!") for i in [1..5]
# add = (x, y): x + y.
# add(2, 4) string print
add: (x, y) -> x + y
print(add(2, 4))
# loop: 'quaff' print.
while true
print('quaff')
# ('cheese', 'bread', 'mayo') at (1) print
print(['cheese', 'bread', 'mayo'][1])
# (language='Potion', pointless=true) at (key='language') print
print({language: 'Potion', pointless: true}['language'])
# minus = (x, y): x - y.
# minus (y=10, x=6)
minus: (x, y) -> x - y
minus(6, 10)
# foods = ('cheese', 'bread', 'mayo')
# foods (2)
foods: ['cheese', 'bread', 'mayo']
foods[2]
# (dog='canine', cat='feline', fox='vulpine') each (key, val):
# (key, ' is a ', val) join print.
for key, val of {dog: 'canine', cat: 'feline', fox: 'vulpine'}
print(key + ' is a ' + val)
# Person = class: /name, /age, /sex.
# Person print = ():
# ('My name is ', /name, '.') join print.
Person: ->
Person::print: ->
print('My name is ' + this.name + '.')
# p = Person ()
# p /name string print
p: new Person()
print(p.name)
# Policeman = Person class (rank): /rank = rank.
# Policeman print = ():
# ('My name is ', /name, ' and I'm a ', /rank, '.') join print.
#
# Policeman ('Constable') print
Policeman: (rank) -> this.rank: rank
Policeman extends Person
Policeman::print: ->
print('My name is ' + this.name + " and I'm a " + this.rank + '.')
print(new Policeman('Constable'))
# app = [window (width=200, height=400)
# [para 'Welcome.', button 'OK']]
# app first name
app = {
window: {width: 200, height: 200}
para: 'Welcome.'
button: 'OK'
}
app.window
# x = 1
# y = 2
#
# x = 1, y = 2
x: 1
y: 2
x: 1; y: 2
# table = (language='Potion'
# pointless=true)
table: {
language: 'Potion'
pointless: yes
}
# # this foul business...
# String length = (): 10.
# this foul business...
String::length: -> 10
# block = :
# 'potion' print.
block: ->
print('potion')
# if (age > 100): 'ancient'.
if age > 100 then 'ancient'
# author =
# if (title == 'Jonathan Strange & Mr. Norrell'):
# 'Susanna Clarke'.
# elsif (title == 'The Star Diaries'):
# 'Stanislaw Lem'.
# elsif (title == 'The Slynx'):
# 'Tatyana Tolstaya'.
# else:
# '... probably Philip K. Dick'.
switch author
when 'Jonathan Strange & Mr. Norrell'
'Susanna Clarke'
when 'The Star Diaries'
'Stanislaw Lem'
when 'The Slynx'
'Tatyana Tolstaya'
else
'... probably Philip K. Dick'
# count = 8
# while (count > 0):
# 'quaff' print
# count--.
count: 8
while count > 0
print('quaff')
count--
# 1 to 5 (a):
# a string print.
print(a) for a in [1..5]
# if (3 ?gender):
# "Huh? Numbers are sexed? That's amazing." print.
if (3).gender?
print("Huh? Numbers are sexed? That's amazing.")
# HomePage get = (url):
# session = url query ? at ('session').
HomePage::get: (url) ->
session: url.query.session if url.query?
# BTree = class: /left, /right.
# b = BTree ()
# b /left = BTree ()
# b /right = BTree ()
BTree: ->
b: new BTree()
b.left: new BTree()
b.right: new BTree()
# BTree = class: /left, /right.
# b = BTree ()
#
# if (b ? /left):
# 'left path found!' print.
BTree: ->
b: new BTree()
print('left path found!') if b.left?

603
examples/underscore.coffee Normal file
View File

@@ -0,0 +1,603 @@
# Underscore.coffee
# (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
# Underscore is freely distributable under the terms of the MIT license.
# Portions of Underscore are inspired by or borrowed from Prototype.js,
# Oliver Steele's Functional, and John Resig's Micro-Templating.
# For all details and documentation:
# http://documentcloud.github.com/underscore/
# ------------------------- Baseline setup ---------------------------------
# Establish the root object, "window" in the browser, or "global" on the server.
root: this
# Save the previous value of the "_" variable.
previousUnderscore: root._
# If Underscore is called as a function, it returns a wrapped object that
# can be used OO-style. This wrapper holds altered versions of all the
# underscore functions. Wrapped objects may be chained.
wrapper: (obj) ->
this._wrapped: obj
this
# Establish the object that gets thrown to break out of a loop iteration.
breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
# Create a safe reference to the Underscore object forreference below.
_: root._: (obj) -> new wrapper(obj)
# Export the Underscore object for CommonJS.
if typeof(exports) != 'undefined' then exports._: _
# Create quick reference variables for speed access to core prototypes.
slice: Array::slice
unshift: Array::unshift
toString: Object::toString
hasOwnProperty: Object::hasOwnProperty
propertyIsEnumerable: Object::propertyIsEnumerable
# Current version.
_.VERSION: '0.5.8'
# ------------------------ Collection Functions: ---------------------------
# The cornerstone, an each implementation.
# Handles objects implementing forEach, arrays, and raw objects.
_.each: (obj, iterator, context) ->
index: 0
try
return obj.forEach(iterator, context) if obj.forEach
if _.isNumber(obj.length)
return iterator.call(context, obj[i], i, obj) for i in [0...obj.length]
iterator.call(context, val, key, obj) for key, val of obj
catch e
throw e if e isnt breaker
obj
# Return the results of applying the iterator to each element. Use JavaScript
# 1.6's version of map, if possible.
_.map: (obj, iterator, context) ->
return obj.map(iterator, context) if (obj and _.isFunction(obj.map))
results: []
_.each obj, (value, index, list) ->
results.push(iterator.call(context, value, index, list))
results
# Reduce builds up a single result from a list of values. Also known as
# inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.
_.reduce: (obj, memo, iterator, context) ->
return obj.reduce(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduce))
_.each obj, (value, index, list) ->
memo: iterator.call(context, memo, value, index, list)
memo
# The right-associative version of reduce, also known as foldr. Uses
# JavaScript 1.8's version of reduceRight, if available.
_.reduceRight: (obj, memo, iterator, context) ->
return obj.reduceRight(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduceRight))
_.each _.clone(_.toArray(obj)).reverse(), (value, index) ->
memo: iterator.call(context, memo, value, index, obj)
memo
# Return the first value which passes a truth test.
_.detect: (obj, iterator, context) ->
result: null
_.each obj, (value, index, list) ->
if iterator.call(context, value, index, list)
result: value
_.breakLoop()
result
# Return all the elements that pass a truth test. Use JavaScript 1.6's
# filter(), if it exists.
_.select: (obj, iterator, context) ->
if obj and _.isFunction(obj.filter) then return obj.filter(iterator, context)
results: []
_.each obj, (value, index, list) ->
results.push(value) if iterator.call(context, value, index, list)
results
# Return all the elements for which a truth test fails.
_.reject: (obj, iterator, context) ->
results: []
_.each obj, (value, index, list) ->
results.push(value) if not iterator.call(context, value, index, list)
results
# Determine whether all of the elements match a truth test. Delegate to
# JavaScript 1.6's every(), if it is present.
_.all: (obj, iterator, context) ->
iterator ||= _.identity
return obj.every(iterator, context) if obj and _.isFunction(obj.every)
result: true
_.each obj, (value, index, list) ->
_.breakLoop() unless (result: result and iterator.call(context, value, index, list))
result
# Determine if at least one element in the object matches a truth test. Use
# JavaScript 1.6's some(), if it exists.
_.any: (obj, iterator, context) ->
iterator ||= _.identity
return obj.some(iterator, context) if obj and _.isFunction(obj.some)
result: false
_.each obj, (value, index, list) ->
_.breakLoop() if (result: iterator.call(context, value, index, list))
result
# Determine if a given value is included in the array or object,
# based on '==='.
_.include: (obj, target) ->
return _.indexOf(obj, target) isnt -1 if obj and _.isFunction(obj.indexOf)
for key, val of obj
return true if val is target
false
# Invoke a method with arguments on every item in a collection.
_.invoke: (obj, method) ->
args: _.rest(arguments, 2)
(if method then val[method] else val).apply(val, args) for val in obj
# Convenience version of a common use case of map: fetching a property.
_.pluck: (obj, key) ->
_.map(obj, ((val) -> val[key]))
# Return the maximum item or (item-based computation).
_.max: (obj, iterator, context) ->
return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
result: {computed: -Infinity}
_.each obj, (value, index, list) ->
computed: if iterator then iterator.call(context, value, index, list) else value
computed >= result.computed and (result: {value: value, computed: computed})
result.value
# Return the minimum element (or element-based computation).
_.min: (obj, iterator, context) ->
return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
result: {computed: Infinity}
_.each obj, (value, index, list) ->
computed: if iterator then iterator.call(context, value, index, list) else value
computed < result.computed and (result: {value: value, computed: computed})
result.value
# Sort the object's values by a criteria produced by an iterator.
_.sortBy: (obj, iterator, context) ->
_.pluck(((_.map obj, (value, index, list) ->
{value: value, criteria: iterator.call(context, value, index, list)}
).sort((left, right) ->
a: left.criteria; b: right.criteria
if a < b then -1 else if a > b then 1 else 0
)), 'value')
# Use a comparator function to figure out at what index an object should
# be inserted so as to maintain order. Uses binary search.
_.sortedIndex: (array, obj, iterator) ->
iterator ||= _.identity
low: 0; high: array.length
while low < high
mid: (low + high) >> 1
if iterator(array[mid]) < iterator(obj) then low: mid + 1 else high: mid
low
# Convert anything iterable into a real, live array.
_.toArray: (iterable) ->
return [] if (!iterable)
return iterable.toArray() if (iterable.toArray)
return iterable if (_.isArray(iterable))
return slice.call(iterable) if (_.isArguments(iterable))
_.values(iterable)
# Return the number of elements in an object.
_.size: (obj) -> _.toArray(obj).length
# -------------------------- Array Functions: ------------------------------
# Get the first element of an array. Passing "n" will return the first N
# values in the array. Aliased as "head". The "guard" check allows it to work
# with _.map.
_.first: (array, n, guard) ->
if n and not guard then slice.call(array, 0, n) else array[0]
# Returns everything but the first entry of the array. Aliased as "tail".
# Especially useful on the arguments object. Passing an "index" will return
# the rest of the values in the array from that index onward. The "guard"
# check allows it to work with _.map.
_.rest: (array, index, guard) ->
slice.call(array, if _.isUndefined(index) or guard then 1 else index)
# Get the last element of an array.
_.last: (array) -> array[array.length - 1]
# Trim out all falsy values from an array.
_.compact: (array) -> item for item in array when item
# Return a completely flattened version of an array.
_.flatten: (array) ->
_.reduce array, [], (memo, value) ->
return memo.concat(_.flatten(value)) if _.isArray(value)
memo.push(value)
memo
# Return a version of the array that does not contain the specified value(s).
_.without: (array) ->
values: _.rest(arguments)
val for val in _.toArray(array) when not _.include(values, val)
# Produce a duplicate-free version of the array. If the array has already
# been sorted, you have the option of using a faster algorithm.
_.uniq: (array, isSorted) ->
memo: []
for el, i in _.toArray(array)
memo.push(el) if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
memo
# Produce an array that contains every item shared between all the
# passed-in arrays.
_.intersect: (array) ->
rest: _.rest(arguments)
_.select _.uniq(array), (item) ->
_.all rest, (other) ->
_.indexOf(other, item) >= 0
# Zip together multiple lists into a single array -- elements that share
# an index go together.
_.zip: ->
length: _.max(_.pluck(arguments, 'length'))
results: new Array(length)
for i in [0...length]
results[i]: _.pluck(arguments, String(i))
results
# If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
# we need this function. Return the position of the first occurence of an
# item in an array, or -1 if the item is not included in the array.
_.indexOf: (array, item) ->
return array.indexOf(item) if array.indexOf
i: 0; l: array.length
while l - i
if array[i] is item then return i else i++
-1
# Provide JavaScript 1.6's lastIndexOf, delegating to the native function,
# if possible.
_.lastIndexOf: (array, item) ->
return array.lastIndexOf(item) if array.lastIndexOf
i: array.length
while i
if array[i] is item then return i else i--
-1
# Generate an integer Array containing an arithmetic progression. A port of
# the native Python range() function. See:
# http://docs.python.org/library/functions.html#range
_.range: (start, stop, step) ->
a: arguments
solo: a.length <= 1
i: start: if solo then 0 else a[0]
stop: if solo then a[0] else a[1]
step: a[2] or 1
len: Math.ceil((stop - start) / step)
return [] if len <= 0
range: new Array(len)
idx: 0
while true
return range if (if step > 0 then i - stop else stop - i) >= 0
range[idx]: i
idx++
i+= step
# ----------------------- Function Functions: -----------------------------
# Create a function bound to a given object (assigning 'this', and arguments,
# optionally). Binding with arguments is also known as 'curry'.
_.bind: (func, obj) ->
args: _.rest(arguments, 2)
-> func.apply(obj or root, args.concat(arguments))
# Bind all of an object's methods to that object. Useful for ensuring that
# all callbacks defined on an object belong to it.
_.bindAll: (obj) ->
funcs: if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
_.each(funcs, (f) -> obj[f]: _.bind(obj[f], obj))
obj
# Delays a function for the given number of milliseconds, and then calls
# it with the arguments supplied.
_.delay: (func, wait) ->
args: _.rest(arguments, 2)
setTimeout((-> func.apply(func, args)), wait)
# Defers a function, scheduling it to run after the current call stack has
# cleared.
_.defer: (func) ->
_.delay.apply(_, [func, 1].concat(_.rest(arguments)))
# Returns the first function passed as an argument to the second,
# allowing you to adjust arguments, run code before and after, and
# conditionally execute the original function.
_.wrap: (func, wrapper) ->
-> wrapper.apply(wrapper, [func].concat(arguments))
# Returns a function that is the composition of a list of functions, each
# consuming the return value of the function that follows.
_.compose: ->
funcs: arguments
->
args: arguments
for i in [(funcs.length - 1)..0]
args: [funcs[i].apply(this, args)]
args[0]
# ------------------------- Object Functions: ----------------------------
# Retrieve the names of an object's properties.
_.keys: (obj) ->
return _.range(0, obj.length) if _.isArray(obj)
key for key, val of obj
# Retrieve the values of an object's properties.
_.values: (obj) ->
_.map(obj, _.identity)
# Return a sorted list of the function names available in Underscore.
_.functions: (obj) ->
_.select(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()
# Extend a given object with all of the properties in a source object.
_.extend: (destination, source) ->
for key, val of source
destination[key]: val
destination
# Create a (shallow-cloned) duplicate of an object.
_.clone: (obj) ->
return obj.slice(0) if _.isArray(obj)
_.extend({}, obj)
# Invokes interceptor with the obj, and then returns obj.
# The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
_.tap: (obj, interceptor) ->
interceptor(obj)
obj
# Perform a deep comparison to check if two objects are equal.
_.isEqual: (a, b) ->
# Check object identity.
return true if a is b
# Different types?
atype: typeof(a); btype: typeof(b)
return false if atype isnt btype
# Basic equality test (watch out for coercions).
return true if `a == b`
# One is falsy and the other truthy.
return false if (!a and b) or (a and !b)
# One of them implements an isEqual()?
return a.isEqual(b) if a.isEqual
# Check dates' integer values.
return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
# Both are NaN?
return true if _.isNaN(a) and _.isNaN(b)
# Compare regular expressions.
if _.isRegExp(a) and _.isRegExp(b)
return a.source is b.source and
a.global is b.global and
a.ignoreCase is b.ignoreCase and
a.multiline is b.multiline
# If a is not an object by this point, we can't handle it.
return false if atype isnt 'object'
# Check for different array lengths before comparing contents.
return false if a.length and (a.length isnt b.length)
# Nothing else worked, deep compare the contents.
aKeys: _.keys(a); bKeys: _.keys(b)
# Different object sizes?
return false if aKeys.length isnt bKeys.length
# Recursive comparison of contents.
# for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
return true
# Is a given array or object empty?
_.isEmpty: (obj) -> _.keys(obj).length is 0
# Is a given value a DOM element?
_.isElement: (obj) -> obj and obj.nodeType is 1
# Is a given value an array?
_.isArray: (obj) -> !!(obj and obj.concat and obj.unshift)
# Is a given variable an arguments object?
_.isArguments: (obj) -> obj and _.isNumber(obj.length) and not obj.concat and
not obj.substr and not obj.apply and not propertyIsEnumerable.call(obj, 'length')
# Is the given value a function?
_.isFunction: (obj) -> !!(obj and obj.constructor and obj.call and obj.apply)
# Is the given value a string?
_.isString: (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))
# Is a given value a number?
_.isNumber: (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'
# Is a given value a Date?
_.isDate: (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
# Is the given value a regular expression?
_.isRegExp: (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
# Is the given value NaN -- this one is interesting. NaN != NaN, and
# isNaN(undefined) == true, so we make sure it's a number first.
_.isNaN: (obj) -> _.isNumber(obj) and window.isNaN(obj)
# Is a given value equal to null?
_.isNull: (obj) -> obj is null
# Is a given variable undefined?
_.isUndefined: (obj) -> typeof obj is 'undefined'
# -------------------------- Utility Functions: --------------------------
# Run Underscore.js in noConflict mode, returning the '_' variable to its
# previous owner. Returns a reference to the Underscore object.
_.noConflict: ->
root._: previousUnderscore
this
# Keep the identity function around for default iterators.
_.identity: (value) -> value
# Break out of the middle of an iteration.
_.breakLoop: -> throw breaker
# Generate a unique integer id (unique within the entire client session).
# Useful for temporary DOM ids.
idCounter: 0
_.uniqueId: (prefix) ->
(prefix or '') + idCounter++
# By default, Underscore uses ERB-style template delimiters, change the
# following template settings to use alternative delimiters.
_.templateSettings: {
start: '<%'
end: '%>'
interpolate: /<%=(.+?)%>/g
}
# JavaScript templating a-la ERB, pilfered from John Resig's
# "Secrets of the JavaScript Ninja", page 83.
# Single-quote fix from Rick Strahl's version.
_.template: (str, data) ->
c: _.templateSettings
fn: new Function 'obj',
'var p=[],print=function(){p.push.apply(p,arguments);};' +
'with(obj){p.push(\'' +
str.replace(/[\r\t\n]/g, " ")
.replace(new RegExp("'(?=[^"+c.end[0]+"]*"+c.end+")","g"),"\t")
.split("'").join("\\'")
.split("\t").join("'")
.replace(c.interpolate, "',$1,'")
.split(c.start).join("');")
.split(c.end).join("p.push('") +
"');}return p.join('');"
if data then fn(data) else fn
# ------------------------------- Aliases ----------------------------------
_.forEach: _.each
_.foldl: _.inject: _.reduce
_.foldr: _.reduceRight
_.filter: _.select
_.every: _.all
_.some: _.any
_.head: _.first
_.tail: _.rest
_.methods: _.functions
# ------------------------ Setup the OOP Wrapper: --------------------------
# Helper function to continue chaining intermediate results.
result: (obj, chain) ->
if chain then _(obj).chain() else obj
# Add all of the Underscore functions to the wrapper object.
_.each _.functions(_), (name) ->
method: _[name]
wrapper.prototype[name]: ->
unshift.call(arguments, this._wrapped)
result(method.apply(_, arguments), this._chain)
# Add all mutator Array functions to the wrapper.
_.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) ->
method: Array.prototype[name]
wrapper.prototype[name]: ->
method.apply(this._wrapped, arguments)
result(this._wrapped, this._chain)
# Add all accessor Array functions to the wrapper.
_.each ['concat', 'join', 'slice'], (name) ->
method: Array.prototype[name]
wrapper.prototype[name]: ->
result(method.apply(this._wrapped, arguments), this._chain)
# Start chaining a wrapped Underscore object.
wrapper::chain: ->
this._chain: true
this
# Extracts the result from a wrapped and chained object.
wrapper::value: -> this._wrapped

View File

@@ -0,0 +1,12 @@
# Contributed by Jason Huggins
http: require 'http'
server: http.createServer (req, res) ->
res.sendHeader 200, {'Content-Type': 'text/plain'}
res.sendBody 'Hello, World!'
res.finish()
server.listen 3000
puts "Server running at http://localhost:3000/"

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