coffee-script 0.3.2 → 1.0.0

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