diff --git a/Rakefile b/Rakefile index 432a9d16..0616f0fc 100644 --- a/Rakefile +++ b/Rakefile @@ -17,8 +17,16 @@ end desc "Build the documentation page" task :doc do - rendered = ERB.new(File.read('documentation/index.html.erb')).result(binding) - File.open('index.html', 'w+') {|f| f.write(rendered) } + source = 'documentation/index.html.erb' + 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 namespace :gem do diff --git a/TODO b/TODO index 7761c3a3..7ec3b61e 100644 --- a/TODO +++ b/TODO @@ -7,10 +7,12 @@ TODO: * Figure out a generic way to transform statements into expressions, and use it recursively for returns and assigns on whiles, fors, ifs, etc. -* If we manage to get array comprehensions working ... object comprehensions? - * Create the documentation page. (amy, idle) uv -c . -s coffeescript -t amy --no-lines examples/code.cs > code.html + +* Object comprehensions would be easy to add to array comprehensions -- if + we knew that the variable in question is, indeed, an object. Check for + length? Special syntax to tag it? * Is it possible to close blocks (functions, ifs, trys) without an explicit block delimiter or significant whitespace? diff --git a/documentation/css/docs.css b/documentation/css/docs.css new file mode 100644 index 00000000..f50ad3b1 --- /dev/null +++ b/documentation/css/docs.css @@ -0,0 +1,59 @@ +body { + font-size: 16px; + line-height: 24px; + background: #f0f0e5; + color: #252519; + font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif; +} +div.container { + width: 720px; + margin: 50px 0 50px 50px; +} +p { + width: 550px; +} + #documentation p { + margin-bottom: 4px; + } +a, a:visited { + padding: 0 2px; + text-decoration: none; + background: #dadaba; + color: #252519; +} +a:active, a:hover { + color: #000; + background: #f0c095; +} +h1, h2, h3, h4, h5, h6 { + margin-top: 40px; +} +b.header { + font-size: 18px; +} +span.alias { + font-size: 14px; + font-style: italic; + margin-left: 20px; +} +table, tr, td { + margin: 0; padding: 0; +} + td { + padding: 2px 12px 2px 0; + } +code, pre, tt { + font-family: Monaco, Consolas, "Lucida Console", monospace; + font-size: 12px; + line-height: 18px; + color: #555529; +} + code { + margin-left: 20px; + } + pre { + font-size: 12px; + padding: 2px 0 2px 12px; + border-left: 6px solid #aaaa99; + margin: 0px 0 30px; + } \ No newline at end of file diff --git a/documentation/index.html.erb b/documentation/index.html.erb new file mode 100644 index 00000000..cb032b44 --- /dev/null +++ b/documentation/index.html.erb @@ -0,0 +1,23 @@ + + + + + CoffeeScript + + + + +
+ +

CoffeeScript

+ +

+ CoffeeScript is a little language that compiles into JavaScript. Think + of it as JavaScript's simpleminded kid brother — the same genes, + the same accent, but another kind of way of doing things. +

+ +
+ + + diff --git a/index.html b/index.html new file mode 100644 index 00000000..cb032b44 --- /dev/null +++ b/index.html @@ -0,0 +1,23 @@ + + + + + CoffeeScript + + + + +
+ +

CoffeeScript

+ +

+ CoffeeScript is a little language that compiles into JavaScript. Think + of it as JavaScript's simpleminded kid brother — the same genes, + the same accent, but another kind of way of doing things. +

+ +
+ + + diff --git a/lib/coffee_script/command_line.rb b/lib/coffee_script/command_line.rb index bee6e079..105292dd 100644 --- a/lib/coffee_script/command_line.rb +++ b/lib/coffee_script/command_line.rb @@ -23,6 +23,7 @@ Usage: def initialize @mtimes = {} parse_options + return eval_scriptlet if @options[:eval] check_sources @sources.each {|source| compile_javascript(source) } watch_coffee_scripts if @options[:watch] @@ -88,6 +89,11 @@ Usage: stdout.close and stderr.close end + # Eval a little piece of CoffeeScript directly from the command line. + def eval_scriptlet + puts CoffeeScript.compile(@sources.join(' ')) + end + # Print the tokens that the lexer generates from a source script. def tokens(source) puts Lexer.new.tokenize(File.read(source)).inspect @@ -135,6 +141,9 @@ Usage: opts.on('-l', '--lint', 'pipe the compiled JavaScript through JSLint') do |l| @options[:lint] = true end + opts.on('-e', '--eval', 'eval a little scriptlet directly from the cli') do |e| + @options[:eval] = true + end opts.on('-t', '--tokens', 'print the tokens that the lexer produces') do |t| @options[:tokens] = true end diff --git a/lib/coffee_script/grammar.y b/lib/coffee_script/grammar.y index b7cdfc21..39be9602 100644 --- a/lib/coffee_script/grammar.y +++ b/lib/coffee_script/grammar.y @@ -17,9 +17,11 @@ token JS # Declare order of operations. prechigh - nonassoc UMINUS NOT '!' + nonassoc UMINUS NOT '!' '~' left '*' '/' '%' left '+' '-' + left '<<' '>>' '>>>' + left '&' '|' '^' left '<=' '<' '>' '>=' right '==' '!=' IS AINT left '&&' '||' AND OR @@ -127,6 +129,7 @@ rule '!' Expression { result = OpNode.new(val[0], val[1]) } | '-' Expression = UMINUS { result = OpNode.new(val[0], val[1]) } | NOT Expression { result = OpNode.new(val[0], val[1]) } + | '~' Expression { result = OpNode.new(val[0], val[1]) } | Expression '*' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '/' Expression { result = OpNode.new(val[1], val[0], val[2]) } @@ -135,6 +138,14 @@ rule | Expression '+' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '-' Expression { result = OpNode.new(val[1], val[0], val[2]) } + | Expression '<<' Expression { result = OpNode.new(val[1], val[0], val[2]) } + | Expression '>>' Expression { result = OpNode.new(val[1], val[0], val[2]) } + | Expression '>>>' Expression { result = OpNode.new(val[1], val[0], val[2]) } + + | Expression '&' Expression { result = OpNode.new(val[1], val[0], val[2]) } + | Expression '|' Expression { result = OpNode.new(val[1], val[0], val[2]) } + | Expression '^' Expression { result = OpNode.new(val[1], val[0], val[2]) } + | Expression '<=' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '<' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '>' Expression { result = OpNode.new(val[1], val[0], val[2]) } diff --git a/lib/coffee_script/nodes.rb b/lib/coffee_script/nodes.rb index 7825dbca..f91e7589 100644 --- a/lib/coffee_script/nodes.rb +++ b/lib/coffee_script/nodes.rb @@ -68,8 +68,8 @@ module CoffeeScript "(function(){\n#{compile(TAB, Scope.new)}\n})();" end - # The extra fancy is to handle pushing down returns recursively to the - # final lines of inner statements (so as to make expressions out of them). + # The extra fancy is to handle pushing down returns and assignments + # recursively to the final lines of inner statements. def compile(indent='', scope=nil, opts={}) return root_compile unless scope code = @expressions.map { |n| @@ -171,7 +171,7 @@ module CoffeeScript end end - # A value, indexed or dotted into or vanilla. + # A value, indexed or dotted into, or vanilla. class ValueNode < Node attr_reader :literal, :properties, :last