coffee-script 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ require "coffee_script/lexer"
3
+ require "coffee_script/parser"
4
+ require "coffee_script/nodes"
5
+ require "coffee_script/value"
6
+ require "coffee_script/scope"
7
+ require "coffee_script/parse_error"
8
+
9
+ # Namespace for all CoffeeScript internal classes.
10
+ module CoffeeScript
11
+
12
+ VERSION = '0.1.0' # Keep in sync with the gemspec.
13
+
14
+ # Compile a script (String or IO) to JavaScript.
15
+ def self.compile(script)
16
+ script = script.read if script.respond_to?(:read)
17
+ Parser.new.parse(script).compile
18
+ end
19
+
20
+ end
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>name</key>
6
+ <string>comments</string>
7
+ <key>scope</key>
8
+ <string>source.cs</string>
9
+ <key>settings</key>
10
+ <dict>
11
+ <key>shellVariables</key>
12
+ <array>
13
+ <dict>
14
+ <key>name</key>
15
+ <string>TM_COMMENT_START</string>
16
+ <key>value</key>
17
+ <string># </string>
18
+ </dict>
19
+ </array>
20
+ </dict>
21
+ <key>uuid</key>
22
+ <string>0A92C6F6-4D73-4859-B38C-4CC19CBC191F</string>
23
+ </dict>
24
+ </plist>
@@ -0,0 +1,329 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>comment</key>
6
+ <string>CoffeeScript Syntax: version 1</string>
7
+ <key>fileTypes</key>
8
+ <array>
9
+ <string>cs</string>
10
+ <string>coffeescript</string>
11
+ </array>
12
+ <key>name</key>
13
+ <string>CoffeeScript</string>
14
+ <key>patterns</key>
15
+ <array>
16
+ <dict>
17
+ <key>captures</key>
18
+ <dict>
19
+ <key>1</key>
20
+ <dict>
21
+ <key>name</key>
22
+ <string>entity.name.function.cs</string>
23
+ </dict>
24
+ <key>2</key>
25
+ <dict>
26
+ <key>name</key>
27
+ <string>keyword.operator.cs</string>
28
+ </dict>
29
+ <key>3</key>
30
+ <dict>
31
+ <key>name</key>
32
+ <string>variable.parameter.function.cs</string>
33
+ </dict>
34
+ <key>4</key>
35
+ <dict>
36
+ <key>name</key>
37
+ <string>storage.type.function.cs</string>
38
+ </dict>
39
+ </dict>
40
+ <key>comment</key>
41
+ <string>match stuff like: funcName: =&gt; … </string>
42
+ <key>match</key>
43
+ <string>([a-zA-Z_?.$]*)\s*(=|:)\s*([\w,\s]*?)\s*(=&gt;)</string>
44
+ <key>name</key>
45
+ <string>meta.function.cs</string>
46
+ </dict>
47
+ <dict>
48
+ <key>captures</key>
49
+ <dict>
50
+ <key>1</key>
51
+ <dict>
52
+ <key>name</key>
53
+ <string>variable.parameter.function.cs</string>
54
+ </dict>
55
+ <key>2</key>
56
+ <dict>
57
+ <key>name</key>
58
+ <string>storage.type.function.cs</string>
59
+ </dict>
60
+ </dict>
61
+ <key>comment</key>
62
+ <string>match stuff like: a =&gt; … </string>
63
+ <key>match</key>
64
+ <string>([a-zA-Z_?., $]*)\s*(=&gt;)</string>
65
+ <key>name</key>
66
+ <string>meta.inline.function.cs</string>
67
+ </dict>
68
+ <dict>
69
+ <key>captures</key>
70
+ <dict>
71
+ <key>1</key>
72
+ <dict>
73
+ <key>name</key>
74
+ <string>keyword.operator.new.cs</string>
75
+ </dict>
76
+ <key>2</key>
77
+ <dict>
78
+ <key>name</key>
79
+ <string>entity.name.type.instance.cs</string>
80
+ </dict>
81
+ </dict>
82
+ <key>match</key>
83
+ <string>(new)\s+(\w+(?:\.\w*)?)</string>
84
+ <key>name</key>
85
+ <string>meta.class.instance.constructor</string>
86
+ </dict>
87
+ <dict>
88
+ <key>match</key>
89
+ <string>\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?))\b</string>
90
+ <key>name</key>
91
+ <string>constant.numeric.cs</string>
92
+ </dict>
93
+ <dict>
94
+ <key>begin</key>
95
+ <string>'</string>
96
+ <key>beginCaptures</key>
97
+ <dict>
98
+ <key>0</key>
99
+ <dict>
100
+ <key>name</key>
101
+ <string>punctuation.definition.string.begin.cs</string>
102
+ </dict>
103
+ </dict>
104
+ <key>end</key>
105
+ <string>'</string>
106
+ <key>endCaptures</key>
107
+ <dict>
108
+ <key>0</key>
109
+ <dict>
110
+ <key>name</key>
111
+ <string>punctuation.definition.string.end.cs</string>
112
+ </dict>
113
+ </dict>
114
+ <key>name</key>
115
+ <string>string.quoted.single.cs</string>
116
+ <key>patterns</key>
117
+ <array>
118
+ <dict>
119
+ <key>match</key>
120
+ <string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)</string>
121
+ <key>name</key>
122
+ <string>constant.character.escape.cs</string>
123
+ </dict>
124
+ </array>
125
+ </dict>
126
+ <dict>
127
+ <key>begin</key>
128
+ <string>"</string>
129
+ <key>beginCaptures</key>
130
+ <dict>
131
+ <key>0</key>
132
+ <dict>
133
+ <key>name</key>
134
+ <string>punctuation.definition.string.begin.cs</string>
135
+ </dict>
136
+ </dict>
137
+ <key>end</key>
138
+ <string>"</string>
139
+ <key>endCaptures</key>
140
+ <dict>
141
+ <key>0</key>
142
+ <dict>
143
+ <key>name</key>
144
+ <string>punctuation.definition.string.end.cs</string>
145
+ </dict>
146
+ </dict>
147
+ <key>name</key>
148
+ <string>string.quoted.double.cs</string>
149
+ <key>patterns</key>
150
+ <array>
151
+ <dict>
152
+ <key>match</key>
153
+ <string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)</string>
154
+ <key>name</key>
155
+ <string>constant.character.escape.cs</string>
156
+ </dict>
157
+ </array>
158
+ </dict>
159
+ <dict>
160
+ <key>begin</key>
161
+ <string>`</string>
162
+ <key>beginCaptures</key>
163
+ <dict>
164
+ <key>0</key>
165
+ <dict>
166
+ <key>name</key>
167
+ <string>punctuation.definition.string.begin.cs</string>
168
+ </dict>
169
+ </dict>
170
+ <key>end</key>
171
+ <string>`</string>
172
+ <key>endCaptures</key>
173
+ <dict>
174
+ <key>0</key>
175
+ <dict>
176
+ <key>name</key>
177
+ <string>punctuation.definition.string.end.cs</string>
178
+ </dict>
179
+ </dict>
180
+ <key>name</key>
181
+ <string>string.quoted.script.cs</string>
182
+ <key>patterns</key>
183
+ <array>
184
+ <dict>
185
+ <key>match</key>
186
+ <string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)</string>
187
+ <key>name</key>
188
+ <string>constant.character.escape.cs</string>
189
+ </dict>
190
+ </array>
191
+ </dict>
192
+ <dict>
193
+ <key>captures</key>
194
+ <dict>
195
+ <key>1</key>
196
+ <dict>
197
+ <key>name</key>
198
+ <string>punctuation.definition.comment.cs</string>
199
+ </dict>
200
+ </dict>
201
+ <key>match</key>
202
+ <string>(#).*$\n?</string>
203
+ <key>name</key>
204
+ <string>comment.line.cs</string>
205
+ </dict>
206
+ <dict>
207
+ <key>match</key>
208
+ <string>\b(break|when|catch|continue|else|finally|for|if|return|switch|then|throw|try|unless|while)\b</string>
209
+ <key>name</key>
210
+ <string>keyword.control.cs</string>
211
+ </dict>
212
+ <dict>
213
+ <key>match</key>
214
+ <string>\b(true|on|yes)\b</string>
215
+ <key>name</key>
216
+ <string>constant.language.boolean.true.cs</string>
217
+ </dict>
218
+ <dict>
219
+ <key>match</key>
220
+ <string>\b(false|off|no)\b</string>
221
+ <key>name</key>
222
+ <string>constant.language.boolean.false.cs</string>
223
+ </dict>
224
+ <dict>
225
+ <key>match</key>
226
+ <string>\bnull\b</string>
227
+ <key>name</key>
228
+ <string>constant.language.null.cs</string>
229
+ </dict>
230
+ <dict>
231
+ <key>match</key>
232
+ <string>\b(super|this)\b</string>
233
+ <key>name</key>
234
+ <string>variable.language.cs</string>
235
+ </dict>
236
+ <dict>
237
+ <key>match</key>
238
+ <string>\b(debugger)\b</string>
239
+ <key>name</key>
240
+ <string>keyword.other.cs</string>
241
+ </dict>
242
+ <dict>
243
+ <key>match</key>
244
+ <string>!|\$|%|&amp;|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|&lt;=|&gt;=|&lt;&lt;=|&gt;&gt;=|&gt;&gt;&gt;=|&lt;&gt;|&lt;|&gt;|!|&amp;&amp;|\?|\|\||\:|\*=|(?&lt;!\()/=|%=|\+=|\-=|&amp;=|\^=|\b(in|instanceof|new|delete|typeof|and|or|is|aint|not)\b</string>
245
+ <key>name</key>
246
+ <string>keyword.operator.cs</string>
247
+ </dict>
248
+ <dict>
249
+ <key>match</key>
250
+ <string>\b(Infinity|NaN|undefined)\b</string>
251
+ <key>name</key>
252
+ <string>constant.language.cs</string>
253
+ </dict>
254
+ <dict>
255
+ <key>begin</key>
256
+ <string>(?&lt;=[=(:]|^|return)\s*(/)(?![/*+{}?])</string>
257
+ <key>beginCaptures</key>
258
+ <dict>
259
+ <key>1</key>
260
+ <dict>
261
+ <key>name</key>
262
+ <string>punctuation.definition.string.begin.cs</string>
263
+ </dict>
264
+ </dict>
265
+ <key>end</key>
266
+ <string>(/)[igm]*</string>
267
+ <key>endCaptures</key>
268
+ <dict>
269
+ <key>1</key>
270
+ <dict>
271
+ <key>name</key>
272
+ <string>punctuation.definition.string.end.cs</string>
273
+ </dict>
274
+ </dict>
275
+ <key>name</key>
276
+ <string>string.regexp.cs</string>
277
+ <key>patterns</key>
278
+ <array>
279
+ <dict>
280
+ <key>match</key>
281
+ <string>\\.</string>
282
+ <key>name</key>
283
+ <string>constant.character.escape.cs</string>
284
+ </dict>
285
+ </array>
286
+ </dict>
287
+ <dict>
288
+ <key>match</key>
289
+ <string>\;</string>
290
+ <key>name</key>
291
+ <string>punctuation.terminator.statement.cs</string>
292
+ </dict>
293
+ <dict>
294
+ <key>match</key>
295
+ <string>,[ |\t]*</string>
296
+ <key>name</key>
297
+ <string>meta.delimiter.object.comma.cs</string>
298
+ </dict>
299
+ <dict>
300
+ <key>match</key>
301
+ <string>\.</string>
302
+ <key>name</key>
303
+ <string>meta.delimiter.method.period.cs</string>
304
+ </dict>
305
+ <dict>
306
+ <key>match</key>
307
+ <string>\{|\}</string>
308
+ <key>name</key>
309
+ <string>meta.brace.curly.cs</string>
310
+ </dict>
311
+ <dict>
312
+ <key>match</key>
313
+ <string>\(|\)</string>
314
+ <key>name</key>
315
+ <string>meta.brace.round.cs</string>
316
+ </dict>
317
+ <dict>
318
+ <key>match</key>
319
+ <string>\[|\]</string>
320
+ <key>name</key>
321
+ <string>meta.brace.square.cs</string>
322
+ </dict>
323
+ </array>
324
+ <key>scopeName</key>
325
+ <string>source.cs</string>
326
+ <key>uuid</key>
327
+ <string>5B520980-A7D5-4E10-8582-1A4C889A8DE5</string>
328
+ </dict>
329
+ </plist>
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>name</key>
6
+ <string>CoffeeScript</string>
7
+ <key>uuid</key>
8
+ <string>A46E4382-F1AC-405B-8F22-65FF470F34D7</string>
9
+ </dict>
10
+ </plist>
@@ -0,0 +1,183 @@
1
+ require 'optparse'
2
+ require 'fileutils'
3
+ require 'open3'
4
+ require File.expand_path(File.dirname(__FILE__) + '/../coffee-script')
5
+
6
+ module CoffeeScript
7
+
8
+ # The CommandLine handles all of the functionality of the `coffee-script`
9
+ # utility.
10
+ class CommandLine
11
+
12
+ BANNER = <<-EOS
13
+ coffee-script compiles CoffeeScript source files into JavaScript.
14
+
15
+ Usage:
16
+ coffee-script path/to/script.cs
17
+ EOS
18
+
19
+ # Seconds to pause between checks for changed source files.
20
+ WATCH_INTERVAL = 0.5
21
+
22
+ # Run the CommandLine off the contents of ARGV.
23
+ def initialize
24
+ @mtimes = {}
25
+ parse_options
26
+ return eval_scriptlet if @options[:eval]
27
+ check_sources
28
+ @sources.each {|source| compile_javascript(source) }
29
+ watch_coffee_scripts if @options[:watch]
30
+ end
31
+
32
+ # The "--help" usage message.
33
+ def usage
34
+ puts "\n#{@option_parser}\n"
35
+ exit
36
+ end
37
+
38
+
39
+ private
40
+
41
+ # Compiles (or partially compiles) the source CoffeeScript file, returning
42
+ # the desired JS, tokens, or lint results.
43
+ def compile_javascript(source)
44
+ script = File.read(source)
45
+ return tokens(script) if @options[:tokens]
46
+ js = compile(script, source)
47
+ return unless js
48
+ return puts(js) if @options[:print]
49
+ return lint(js) if @options[:lint]
50
+ File.open(path_for(source), 'w+') {|f| f.write(js) }
51
+ end
52
+
53
+ # Spins up a watcher thread to keep track of the modification times of the
54
+ # source files, recompiling them whenever they're saved.
55
+ def watch_coffee_scripts
56
+ watch_thread = Thread.start do
57
+ loop do
58
+ @sources.each do |source|
59
+ mtime = File.stat(source).mtime
60
+ @mtimes[source] ||= mtime
61
+ if mtime > @mtimes[source]
62
+ @mtimes[source] = mtime
63
+ compile_javascript(source)
64
+ end
65
+ end
66
+ sleep WATCH_INTERVAL
67
+ end
68
+ end
69
+ Signal.trap("INT") { watch_thread.kill }
70
+ watch_thread.join
71
+ end
72
+
73
+ # Ensure that all of the source files exist.
74
+ def check_sources
75
+ usage if @sources.empty?
76
+ missing = @sources.detect {|s| !File.exists?(s) }
77
+ if missing
78
+ STDERR.puts("File not found: '#{missing}'")
79
+ exit(1)
80
+ end
81
+ end
82
+
83
+ # Pipe compiled JS through JSLint (requires a working 'jsl' command).
84
+ def lint(js)
85
+ stdin, stdout, stderr = Open3.popen3('jsl -nologo -stdin')
86
+ stdin.write(js)
87
+ stdin.close
88
+ puts stdout.read.tr("\n", '')
89
+ errs = stderr.read.chomp
90
+ puts errs unless errs.empty?
91
+ stdout.close and stderr.close
92
+ end
93
+
94
+ # Eval a little piece of CoffeeScript directly from the command line.
95
+ def eval_scriptlet
96
+ script = STDIN.tty? ? @sources.join(' ') : STDIN.read
97
+ return tokens(script) if @options[:tokens]
98
+ js = compile(script)
99
+ return lint(js) if @options[:lint]
100
+ puts js
101
+ end
102
+
103
+ # Print the tokens that the lexer generates from a source script.
104
+ def tokens(script)
105
+ puts Lexer.new.tokenize(script).inspect
106
+ end
107
+
108
+ # Compile a single source file to JavaScript.
109
+ def compile(script, source='')
110
+ begin
111
+ CoffeeScript.compile(script)
112
+ rescue CoffeeScript::ParseError => e
113
+ STDERR.puts e.message(source)
114
+ exit(1) unless @options[:watch]
115
+ nil
116
+ end
117
+ end
118
+
119
+ # Write out JavaScript alongside CoffeeScript unless an output directory
120
+ # is specified.
121
+ def path_for(source)
122
+ filename = File.basename(source, File.extname(source)) + '.js'
123
+ dir = @options[:output] || File.dirname(source)
124
+ File.join(dir, filename)
125
+ end
126
+
127
+ # Install the CoffeeScript TextMate bundle to ~/Library.
128
+ def install_bundle
129
+ bundle_dir = File.expand_path('~/Library/Application Support/TextMate/Bundles/')
130
+ FileUtils.cp_r(File.dirname(__FILE__) + '/CoffeeScript.tmbundle', bundle_dir)
131
+ end
132
+
133
+ # Use OptionParser for all the options.
134
+ def parse_options
135
+ @options = {}
136
+ @option_parser = OptionParser.new do |opts|
137
+ opts.on('-o', '--output [DIR]', 'set the directory for compiled JavaScript') do |d|
138
+ @options[:output] = d
139
+ FileUtils.mkdir_p(d) unless File.exists?(d)
140
+ end
141
+ opts.on('-w', '--watch', 'watch scripts for changes, and recompile') do |w|
142
+ @options[:watch] = true
143
+ end
144
+ opts.on('-p', '--print', 'print the compiled JavaScript to stdout') do |d|
145
+ @options[:print] = true
146
+ end
147
+ opts.on('-l', '--lint', 'pipe the compiled JavaScript through JSLint') do |l|
148
+ @options[:lint] = true
149
+ end
150
+ opts.on('-e', '--eval', 'eval a little scriptlet directly from the cli') do |e|
151
+ @options[:eval] = true
152
+ end
153
+ opts.on('-t', '--tokens', 'print the tokens that the lexer produces') do |t|
154
+ @options[:tokens] = true
155
+ end
156
+ opts.on('-v', '--verbose', 'print at every step of code generation') do |v|
157
+ ENV['VERBOSE'] = 'true'
158
+ end
159
+ opts.on_tail('--install-bundle', 'install the CoffeeScript TextMate bundle') do |i|
160
+ install_bundle
161
+ exit
162
+ end
163
+ opts.on_tail('--version', 'display coffee-script version') do
164
+ puts "coffee-script version #{CoffeeScript::VERSION}"
165
+ exit
166
+ end
167
+ opts.on_tail('-h', '--help', 'display this help message') do
168
+ usage
169
+ end
170
+ end
171
+ @option_parser.banner = BANNER
172
+ begin
173
+ @option_parser.parse!(ARGV)
174
+ rescue OptionParser::InvalidOption => e
175
+ puts e.message
176
+ exit(1)
177
+ end
178
+ @sources = ARGV
179
+ end
180
+
181
+ end
182
+
183
+ end