fancy 0.8.0 → 0.9.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.
- data/LICENSE +1 -1
- data/README.md +5 -4
- data/bin/fspec +19 -1
- data/bin/ifancy +139 -35
- data/boot/README +2 -9
- data/boot/extconf.rb +0 -1
- data/boot/fancy_ext/module.rb +5 -15
- data/boot/fancy_ext/thread.rb +22 -9
- data/boot/rbx-compiler/README +0 -4
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/parser.y +1 -0
- data/doc/api/fancy.css +1 -6
- data/doc/api/fancy.jsonp +1 -1
- data/doc/api/fdoc.js +2 -4
- data/doc/api/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/doc/api/images/ui-bg_flat_0_eeeeee_40x100.png +0 -0
- data/doc/api/images/ui-bg_flat_55_ffffff_40x100.png +0 -0
- data/doc/api/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/doc/api/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/doc/api/images/ui-bg_highlight-soft_100_f6f6f6_1x100.png +0 -0
- data/doc/api/images/ui-bg_highlight-soft_25_0073ea_1x100.png +0 -0
- data/doc/api/images/ui-bg_highlight-soft_50_dddddd_1x100.png +0 -0
- data/doc/api/images/ui-icons_0073ea_256x240.png +0 -0
- data/doc/api/images/ui-icons_454545_256x240.png +0 -0
- data/doc/api/images/ui-icons_666666_256x240.png +0 -0
- data/doc/api/images/ui-icons_ff0084_256x240.png +0 -0
- data/doc/api/images/ui-icons_ffffff_256x240.png +0 -0
- data/doc/api/index.html +5 -4
- data/doc/api/jquery-1.8.2.min.js +2 -0
- data/doc/api/jquery-ui-1.9.0.custom.min.css +5 -0
- data/doc/api/jquery-ui-1.9.0.custom.min.js +6 -0
- data/doc/features.md +8 -3
- data/examples/argv.fy +1 -1
- data/examples/closures.fy +1 -4
- data/examples/echo.fy +2 -2
- data/examples/guess_number.fy +18 -0
- data/examples/nested_classes.fy +3 -15
- data/lib/argv.fy +23 -18
- data/lib/array.fy +18 -37
- data/lib/block.fy +125 -0
- data/lib/boot.fy +1 -0
- data/lib/compiler/ast/block.fy +1 -1
- data/lib/compiler/ast/identifier.fy +1 -1
- data/lib/compiler/ast/message_send.fy +0 -13
- data/lib/compiler/ast/method_def.fy +1 -1
- data/lib/compiler/ast/singleton_method_def.fy +1 -0
- data/lib/compiler/ast/tuple_literal.fy +1 -1
- data/lib/compiler/command.fy +1 -1
- data/lib/compiler/compiler.fy +8 -6
- data/lib/contracts.fy +1 -1
- data/lib/directory.fy +1 -1
- data/lib/dynamic_slot_object.fy +1 -1
- data/lib/enumerable.fy +316 -25
- data/lib/enumerator.fy +11 -8
- data/lib/eval.fy +0 -3
- data/lib/fancy_spec.fy +27 -0
- data/lib/fdoc.fy +8 -8
- data/lib/file.fy +25 -1
- data/lib/hash.fy +91 -0
- data/lib/html.fy +40 -11
- data/lib/integer.fy +4 -0
- data/lib/main.fy +18 -11
- data/lib/object.fy +33 -7
- data/lib/option_parser.fy +20 -1
- data/lib/package/dependency.fy +8 -0
- data/lib/package/dependency_installer.fy +3 -6
- data/lib/package/handler.fy +4 -4
- data/lib/package/installer.fy +2 -5
- data/lib/package/list.fy +3 -4
- data/lib/parser/ext/parser.y +1 -0
- data/lib/proxies.fy +0 -2
- data/lib/queue.fy +7 -0
- data/lib/rbx.fy +1 -0
- data/lib/rbx/actor.fy +3 -1
- data/lib/rbx/alpha.fy +24 -0
- data/lib/rbx/array.fy +3 -1
- data/lib/rbx/class.fy +5 -8
- data/lib/rbx/date_time.fy +14 -0
- data/lib/rbx/file.fy +6 -0
- data/lib/rbx/hash.fy +42 -0
- data/lib/rbx/thread.fy +5 -7
- data/lib/string.fy +56 -4
- data/lib/symbol.fy +29 -1
- data/lib/time.fy +17 -0
- data/lib/vars.fy +4 -3
- data/lib/version.fy +1 -1
- data/ruby_lib/interactive/hilight.rb +125 -0
- data/tests/array.fy +19 -7
- data/tests/block.fy +103 -4
- data/tests/class.fy +31 -26
- data/tests/control_flow.fy +0 -1
- data/tests/dynamic_key_hash.fy +22 -1
- data/tests/enumerable.fy +239 -7
- data/tests/enumerator.fy +7 -0
- data/tests/file.fy +16 -0
- data/tests/future.fy +1 -11
- data/tests/future_proxy.fy +8 -0
- data/tests/hash.fy +132 -9
- data/tests/html.fy +30 -13
- data/tests/integer.fy +3 -0
- data/tests/method.fy +6 -11
- data/tests/object.fy +12 -5
- data/tests/option_parser.fy +12 -3
- data/tests/string.fy +69 -1
- data/tests/symbol.fy +24 -0
- metadata +42 -12
- data/boot/rsexp_pretty_printer.rb +0 -76
- data/doc/api/jquery-ui.min.js +0 -401
- data/doc/api/jquery.tools.min.js +0 -192
- data/doc/api/themeswitchertool.js +0 -250
- data/examples/future_sends.fy +0 -15
data/lib/string.fy
CHANGED
|
@@ -57,10 +57,9 @@ class String {
|
|
|
57
57
|
Indicates, if a @String@ consists only of whitespace.
|
|
58
58
|
"""
|
|
59
59
|
|
|
60
|
-
self
|
|
61
|
-
true
|
|
62
|
-
|
|
63
|
-
false
|
|
60
|
+
match self {
|
|
61
|
+
case /^\s*$/ -> true
|
|
62
|
+
case _ -> false
|
|
64
63
|
}
|
|
65
64
|
}
|
|
66
65
|
|
|
@@ -232,4 +231,57 @@ class String {
|
|
|
232
231
|
|
|
233
232
|
if: main? then: main_block else: else_block
|
|
234
233
|
}
|
|
234
|
+
|
|
235
|
+
def snake_cased {
|
|
236
|
+
"""
|
|
237
|
+
Returns a snake cased version of @self.
|
|
238
|
+
"""
|
|
239
|
+
|
|
240
|
+
r1 = Regexp new("([A-Z]+)([A-Z][a-z])")
|
|
241
|
+
r2 = Regexp new("([a-z\d])([A-Z])")
|
|
242
|
+
gsub(r1,"\1_\2") gsub(r2,"\1_\2") tr("-", "_") lowercase
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
def camel_cased {
|
|
246
|
+
"""
|
|
247
|
+
Returns camel cased version of @self which is expected
|
|
248
|
+
to be a snake cased @String@.
|
|
249
|
+
"""
|
|
250
|
+
|
|
251
|
+
self split: "_" . map: @{ capitalize } . join
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
def uppercase? {
|
|
255
|
+
"""
|
|
256
|
+
@return @true if @self is completely uppercase, @false otherwise.
|
|
257
|
+
|
|
258
|
+
Example:
|
|
259
|
+
\"F\" uppercase? # => true
|
|
260
|
+
\"FOO\" uppercase? # => true
|
|
261
|
+
\"f\” uppercase? # => false
|
|
262
|
+
\"Foo\" uppercase? # => false
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
{ return false } if: blank?
|
|
266
|
+
uppercase == self
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
def lowercase? {
|
|
270
|
+
"""
|
|
271
|
+
@return @true if @self is completely lowercase, @false otherwise.
|
|
272
|
+
|
|
273
|
+
Example:
|
|
274
|
+
\"f\” lowercase? # => true
|
|
275
|
+
\"foo\" lowercase? # => true
|
|
276
|
+
\"F\" lowercase? # => false
|
|
277
|
+
\"Foo\" lowercase? # => false
|
|
278
|
+
"""
|
|
279
|
+
|
|
280
|
+
{ return false } if: blank?
|
|
281
|
+
lowercase == self
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
def starts_with?: string {
|
|
285
|
+
from: 0 to: (string size - 1) == string
|
|
286
|
+
}
|
|
235
287
|
}
|
data/lib/symbol.fy
CHANGED
|
@@ -45,11 +45,39 @@ class Symbol {
|
|
|
45
45
|
recv receive_message: self
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
def call_with_receiver: receiver {
|
|
49
|
+
call: [receiver]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
def call: args with_receiver: receiver {
|
|
53
|
+
call: $ args unshift: receiver
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
def arity {
|
|
49
|
-
|
|
57
|
+
m = message_name to_s
|
|
58
|
+
match m {
|
|
59
|
+
case /^:[a-zA-Z0-9_]+$/ -> m count: |c| { c == ":" }
|
|
60
|
+
case /^:\W+$/ -> 2
|
|
61
|
+
case _ -> m count: |c| { c == ":" } + 1
|
|
62
|
+
}
|
|
50
63
|
}
|
|
51
64
|
|
|
52
65
|
def to_sym {
|
|
53
66
|
self
|
|
54
67
|
}
|
|
68
|
+
|
|
69
|
+
def to_block {
|
|
70
|
+
"""
|
|
71
|
+
@return @Block@ that sends @self to its first argument, passing along any remaining arguments.
|
|
72
|
+
|
|
73
|
+
Example:
|
|
74
|
+
'inspect to_block
|
|
75
|
+
# is equal to:
|
|
76
|
+
@{ inspect }
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
|args| {
|
|
80
|
+
call: args
|
|
81
|
+
}
|
|
82
|
+
}
|
|
55
83
|
}
|
data/lib/time.fy
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class Time {
|
|
2
|
+
def Time duration: block {
|
|
3
|
+
"""
|
|
4
|
+
@block @Block to be called & timed.
|
|
5
|
+
@return @Float@ that is the duration (in seconds) of calling @block.
|
|
6
|
+
|
|
7
|
+
Calls @block and times the runtime duration of doing so in seconds.
|
|
8
|
+
|
|
9
|
+
Example:
|
|
10
|
+
Time duration: { Thread sleep: 1 } # => >= 1.0
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
start = Time now
|
|
14
|
+
block call
|
|
15
|
+
Time now - start
|
|
16
|
+
}
|
|
17
|
+
}
|
data/lib/vars.fy
CHANGED
data/lib/version.fy
CHANGED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module CodeRay
|
|
3
|
+
module Scanners
|
|
4
|
+
|
|
5
|
+
# Fancy scanner by swarley.
|
|
6
|
+
class Fancy < Scanner
|
|
7
|
+
|
|
8
|
+
register_for :fancy
|
|
9
|
+
file_extension 'fy'
|
|
10
|
+
|
|
11
|
+
SPECIAL_FORMS = %w[
|
|
12
|
+
def throw try catch class
|
|
13
|
+
] # :nodoc:
|
|
14
|
+
|
|
15
|
+
CORE_FORMS = %w[
|
|
16
|
+
+ - > < == != >= <= % ** * = && || =~
|
|
17
|
+
] # :nodoc:
|
|
18
|
+
|
|
19
|
+
PREDEFINED_CONSTANTS = %w[
|
|
20
|
+
true false nil
|
|
21
|
+
] # :nodoc:
|
|
22
|
+
|
|
23
|
+
IDENT_KIND = WordList.new(:ident).
|
|
24
|
+
add(SPECIAL_FORMS, :keyword).
|
|
25
|
+
add(CORE_FORMS, :keyword).
|
|
26
|
+
add(PREDEFINED_CONSTANTS, :predefined_constant)
|
|
27
|
+
|
|
28
|
+
KEYWORD_NEXT_TOKEN_KIND = WordList.new(nil).
|
|
29
|
+
add(%w[ def defn defn- definline defmacro defmulti defmethod defstruct defonce declare ], :function).
|
|
30
|
+
add(%w[ ns ], :namespace).
|
|
31
|
+
add(%w[ defprotocol defrecord ], :class)
|
|
32
|
+
|
|
33
|
+
BASIC_IDENTIFIER = /[a-zA-Z$%*\/_+!?&<>\-=]=?[a-zA-Z0-9$&*+!\/_?<>\-\#]*/
|
|
34
|
+
CLASS_IDENTIFIER = /[A-Z]+[A-Za-z0-9]*|[A-Z]+[A-Za-z0-9]\:\:|\:\:[A-Z]+[A-Za-z0-9]*/
|
|
35
|
+
IDENTIFIER = /(?!-\d)(?:(?:#{BASIC_IDENTIFIER}\.)*#{BASIC_IDENTIFIER}(?:\/#{BASIC_IDENTIFIER})?\.?)|\.\.?/
|
|
36
|
+
SYMBOL = /\'[A-z]+[A-z0-9\:\!\%\^\&\*\_\-\+\=\|\?\\\/\>\<\.]*/o
|
|
37
|
+
DIGIT = /\d+/
|
|
38
|
+
DIGIT10 = DIGIT
|
|
39
|
+
DIGIT16 = /[0-9a-f]/i
|
|
40
|
+
DIGIT8 = /[0-7]/
|
|
41
|
+
DIGIT2 = /[01]/
|
|
42
|
+
DECIMAL = /#{DIGIT}\.#{DIGIT}|-#{DIGIT}\.#{DIGIT}/
|
|
43
|
+
NUM = /(?:\-)*(?:#{DIGIT}|#{DIGIT16}|#{DIGIT8}|#{DIGIT2}|#{DECIMAL})/
|
|
44
|
+
MESSAGE = /[A-Za-z0-9\&\_]+?(?:\:|\?\:)/
|
|
45
|
+
CAPTURE = /\|.+?\|/
|
|
46
|
+
|
|
47
|
+
protected
|
|
48
|
+
|
|
49
|
+
def scan_tokens(encoder, options)
|
|
50
|
+
state = :initial
|
|
51
|
+
kind = nil
|
|
52
|
+
|
|
53
|
+
until eos?
|
|
54
|
+
case state
|
|
55
|
+
when :initial
|
|
56
|
+
if match = scan(/ \s+ | \n | , /x)
|
|
57
|
+
encoder.text_token match, :space
|
|
58
|
+
elsif match = scan(/\#.+?$/)
|
|
59
|
+
encoder.text_token match, :comment
|
|
60
|
+
elsif match = scan(/\{|\}|\@\{|\[|\]|\(|\)/)
|
|
61
|
+
encoder.text_token match, :operator
|
|
62
|
+
elsif match = scan(Regexp.new((%W(+ - @ > < == != >= <= % ** * = && || =~).map {|x| Regexp.escape x }).join '|'))
|
|
63
|
+
encoder.text_token match, :operator
|
|
64
|
+
elsif match = scan(/\.|\$/)
|
|
65
|
+
encoder.text_token match, :predefined_constant
|
|
66
|
+
elsif match = scan(CAPTURE)
|
|
67
|
+
encoder.text_token match, :predefined_constant
|
|
68
|
+
elsif match = scan(CLASS_IDENTIFIER)
|
|
69
|
+
encoder.text_token match, :constant
|
|
70
|
+
elsif match = scan(/\:\:/)
|
|
71
|
+
encoder.text_token match, :constant
|
|
72
|
+
elsif match = scan(MESSAGE)
|
|
73
|
+
encoder.text_token match, :keyword
|
|
74
|
+
elsif match = scan(/#{IDENTIFIER}/o)
|
|
75
|
+
kind = IDENT_KIND[match]
|
|
76
|
+
encoder.text_token match, kind
|
|
77
|
+
if rest? && kind == :keyword
|
|
78
|
+
if kind = KEYWORD_NEXT_TOKEN_KIND[match]
|
|
79
|
+
encoder.text_token match, :space if match = scan(/\s+/o)
|
|
80
|
+
encoder.text_token match, kind if match = scan(/#{IDENTIFIER}/o)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
elsif match = scan(MESSAGE)
|
|
84
|
+
encoder.text_token match, :keyword
|
|
85
|
+
elsif match = scan(/#{SYMBOL}/o)
|
|
86
|
+
encoder.text_token match, :symbol
|
|
87
|
+
elsif match = scan(/\./)
|
|
88
|
+
encoder.text_token match, :operator
|
|
89
|
+
elsif match = scan(/ \# \^ #{IDENTIFIER} /ox)
|
|
90
|
+
encoder.text_token match, :type
|
|
91
|
+
elsif match = scan(/ (\#)? " /x)
|
|
92
|
+
state = self[1] ? :regexp : :string
|
|
93
|
+
encoder.begin_group state
|
|
94
|
+
encoder.text_token match, :delimiter
|
|
95
|
+
elsif match = scan(/#{NUM}/o) and not matched.empty?
|
|
96
|
+
encoder.text_token match, match[/[.e\/]/i] ? :float : :integer
|
|
97
|
+
else
|
|
98
|
+
encoder.text_token getch, :error
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
when :string, :regexp
|
|
102
|
+
if match = scan(/[^"\\]+|\\.?/)
|
|
103
|
+
encoder.text_token match, :content
|
|
104
|
+
elsif match = scan(/"/)
|
|
105
|
+
encoder.text_token match, :delimiter
|
|
106
|
+
encoder.end_group state
|
|
107
|
+
state = :initial
|
|
108
|
+
else
|
|
109
|
+
raise_inspect "else case \" reached; %p not handled." % peek(1),
|
|
110
|
+
encoder, state
|
|
111
|
+
end
|
|
112
|
+
else
|
|
113
|
+
raise 'else case reached'
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
if [:string, :regexp].include? state
|
|
118
|
+
encoder.end_group state
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
encoder
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
data/tests/array.fy
CHANGED
|
@@ -356,10 +356,6 @@ FancySpec describe: Array with: {
|
|
|
356
356
|
[1,2,3,4] any?: |x| { x > 4 } . is: false
|
|
357
357
|
}
|
|
358
358
|
|
|
359
|
-
it: "is selected from it with each index" with: 'select_with_index: when: {
|
|
360
|
-
["yooo",2,3,1,'foo,"bar"] select_with_index: |x i| { x is_a?: Fixnum } . is: [[2,1], [3,2], [1,3]]
|
|
361
|
-
}
|
|
362
|
-
|
|
363
359
|
it: "returns its remaining (all but the first) elements as a new Array" with: 'rest when: {
|
|
364
360
|
[1,2,3,4] rest is: [2,3,4]
|
|
365
361
|
[] rest is: []
|
|
@@ -529,15 +525,20 @@ FancySpec describe: Array with: {
|
|
|
529
525
|
arr is: [1,5,4,2,3]
|
|
530
526
|
}
|
|
531
527
|
|
|
532
|
-
it: "sorts the array with a given comparison block" with: '
|
|
528
|
+
it: "sorts the array with a given comparison block" with: 'sort: when: {
|
|
533
529
|
arr = [1,5,4,2,3]
|
|
534
530
|
sorted = [1,2,3,4,5]
|
|
535
|
-
arr
|
|
531
|
+
arr sort: |a b| { a <=> b } . is: sorted
|
|
536
532
|
arr is: [1,5,4,2,3]
|
|
537
533
|
|
|
538
534
|
arr = [(1,2), (0,1), (3,0)]
|
|
539
535
|
sorted = [(3,0), (0,1), (1,2)]
|
|
540
|
-
arr
|
|
536
|
+
arr sort: |a b| { a second <=> (b second) } . is: sorted
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
it: "sorts the array by a given block" with: 'sort_by: when: {
|
|
540
|
+
arr = [(1,2), (0,1), (3,0)]
|
|
541
|
+
sorted = [(3,0), (0,1), (1,2)]
|
|
541
542
|
arr sort_by: 'second . is: sorted
|
|
542
543
|
}
|
|
543
544
|
|
|
@@ -550,4 +551,15 @@ FancySpec describe: Array with: {
|
|
|
550
551
|
[] to_hash: @{ size } . is: <[]>
|
|
551
552
|
[[1,2],[3,4,5]] to_hash: @{ size } . is: <[2 => [1,2], 3 => [3,4,5]]>
|
|
552
553
|
}
|
|
554
|
+
|
|
555
|
+
it: "returns an sub-array within a given range" with: 'from:to: when: {
|
|
556
|
+
[] from: 0 to: 1 . is: []
|
|
557
|
+
[1] from: 0 to: 0 . is: [1]
|
|
558
|
+
[1] from: 0 to: 1 . is: [1]
|
|
559
|
+
[1] from: 0 to: 2 . is: [1]
|
|
560
|
+
[1] from: 0 to: -1 . is: [1]
|
|
561
|
+
[1] from: 0 to: -2 . is: []
|
|
562
|
+
[0,1,2,3] from: 0 to: 3 . is: [0,1,2,3]
|
|
563
|
+
[0,1,2,3] from: -1 to: 3 . is: [3]
|
|
564
|
+
}
|
|
553
565
|
}
|
data/tests/block.fy
CHANGED
|
@@ -32,6 +32,24 @@ FancySpec describe: Block with: {
|
|
|
32
32
|
i is be: { i >= 10 }
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
it: "calls a block while another is true or calls the alternative" with: 'while_true:else: when: {
|
|
36
|
+
i = 0
|
|
37
|
+
{ i < 10 } while_true: {
|
|
38
|
+
i = i + 1
|
|
39
|
+
} else: {
|
|
40
|
+
i = "nope"
|
|
41
|
+
}
|
|
42
|
+
i is: 10
|
|
43
|
+
|
|
44
|
+
i = 0
|
|
45
|
+
{ i > 10 } while_true: {
|
|
46
|
+
i = i + 1
|
|
47
|
+
} else: {
|
|
48
|
+
i = "nope"
|
|
49
|
+
}
|
|
50
|
+
i is: "nope"
|
|
51
|
+
}
|
|
52
|
+
|
|
35
53
|
it: "calls a block while another is not true (boolean false)" with: 'while_false: when: {
|
|
36
54
|
i = 0
|
|
37
55
|
{i == 10} while_false: {
|
|
@@ -206,17 +224,17 @@ FancySpec describe: Block with: {
|
|
|
206
224
|
block call: [42] with_receiver: (ClassD new) . is: "in ClassD#inspect: 42"
|
|
207
225
|
}
|
|
208
226
|
|
|
209
|
-
it: "calls a block using
|
|
227
|
+
it: "calls a block using []" with: '[] when: {
|
|
210
228
|
b = |x y| {
|
|
211
229
|
x + y
|
|
212
230
|
}
|
|
213
231
|
|
|
214
232
|
b call: [2,3] . is: 5
|
|
215
|
-
b(2,3) . is: 5
|
|
233
|
+
b[(2,3)] . is: 5
|
|
216
234
|
|
|
217
235
|
b2 = |x| { x * 5 }
|
|
218
|
-
b2
|
|
219
|
-
b2
|
|
236
|
+
b2["hello"] is: ("hello" * 5)
|
|
237
|
+
b2["foo"] is: (b2 call: ["foo"])
|
|
220
238
|
}
|
|
221
239
|
|
|
222
240
|
it: "dynamically creates a object with slots defined in a Block" with: 'to_object when: {
|
|
@@ -239,6 +257,26 @@ FancySpec describe: Block with: {
|
|
|
239
257
|
}
|
|
240
258
|
}
|
|
241
259
|
|
|
260
|
+
it: "dynamically creates a new object with slots recursively defined in blocks" with: 'to_object_deep when: {
|
|
261
|
+
o = {
|
|
262
|
+
name: "Sarah Connor"
|
|
263
|
+
age: 42
|
|
264
|
+
city: "Los Angeles"
|
|
265
|
+
persecuted_by: {
|
|
266
|
+
name: "The Terminator"
|
|
267
|
+
age: 'unknown
|
|
268
|
+
}
|
|
269
|
+
} to_object_deep
|
|
270
|
+
|
|
271
|
+
o name is: "Sarah Connor"
|
|
272
|
+
o age is: 42
|
|
273
|
+
o city is: "Los Angeles"
|
|
274
|
+
o persecuted_by do: {
|
|
275
|
+
name is: "The Terminator"
|
|
276
|
+
age is: 'unknown
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
242
280
|
it: "dynamically creates a hash with keys and values defined in a Block" with: 'to_hash when: {
|
|
243
281
|
{ } to_hash is: <[]>
|
|
244
282
|
{ foo: "bar" } to_hash is: <['foo => "bar"]>
|
|
@@ -302,4 +340,65 @@ FancySpec describe: Block with: {
|
|
|
302
340
|
['city, "San Francisco"],
|
|
303
341
|
'male, 'programmer, 'happy]
|
|
304
342
|
}
|
|
343
|
+
|
|
344
|
+
it: "returns a Block that calls self then a given Block" with: 'then: when: {
|
|
345
|
+
a = []
|
|
346
|
+
block = { a << 1 } then: { a << 2 }
|
|
347
|
+
block call
|
|
348
|
+
a is: [1,2]
|
|
349
|
+
block call
|
|
350
|
+
a is: [1,2,1,2]
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
it: "returns a Block that calls itself after a given Block" with: 'after: when: {
|
|
354
|
+
a = []
|
|
355
|
+
block = { a << 1 } after: { a << 2}
|
|
356
|
+
block call
|
|
357
|
+
a is: [2,1]
|
|
358
|
+
block call
|
|
359
|
+
a is: [2,1,2,1]
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
it: "calls itself while logging errors to *stdout*" with: 'call_with_errors_logged when: {
|
|
363
|
+
io = StringIO new
|
|
364
|
+
let: '*stdout* be: io in: {
|
|
365
|
+
{
|
|
366
|
+
"hello" println
|
|
367
|
+
2 / 0
|
|
368
|
+
} call_with_errors_logged
|
|
369
|
+
}
|
|
370
|
+
io string is: "hello\ndivided by 0\n"
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
it: "calls itself with arguments while logging errors to *stdout*" with: 'call_with_errors_logged: when: {
|
|
374
|
+
io = StringIO new
|
|
375
|
+
let: '*stdout* be: io in: {
|
|
376
|
+
|x y| {
|
|
377
|
+
"x: #{x} y: #{y}" println
|
|
378
|
+
2 / 0
|
|
379
|
+
} call_with_errors_logged: [10, 20]
|
|
380
|
+
}
|
|
381
|
+
io string is: "x: 10 y: 20\ndivided by 0\n"
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
it: "calls itself while logging errors to a given IO object" with: 'call_with_errors_logged_to: when: {
|
|
385
|
+
io = StringIO new
|
|
386
|
+
{
|
|
387
|
+
2 / 0
|
|
388
|
+
} call_with_errors_logged_to: io
|
|
389
|
+
io string is: "divided by 0\n"
|
|
390
|
+
|
|
391
|
+
io = StringIO new
|
|
392
|
+
{ "fail!" raise! } call_with_errors_logged_to: io
|
|
393
|
+
io string is: "fail!\n"
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
it: "calls itself with arguments while logging errors to a given IO object" with: 'call:with_errors_logged_to: when: {
|
|
397
|
+
io = StringIO new
|
|
398
|
+
|x y| {
|
|
399
|
+
io println: "x: #{x} y: #{y}"
|
|
400
|
+
2 / 0
|
|
401
|
+
} call: [10, 20] with_errors_logged_to: io
|
|
402
|
+
io string is: "x: 10 y: 20\ndivided by 0\n"
|
|
403
|
+
}
|
|
305
404
|
}
|