fancy 0.7.0 → 0.8.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/README.md +38 -86
- data/bin/fdoc +2 -22
- data/bin/fspec +8 -3
- data/bin/ifancy +1 -1
- data/boot/fancy_ext.rb +1 -0
- data/boot/fancy_ext/array.rb +19 -0
- data/boot/fancy_ext/class.rb +2 -4
- data/boot/fancy_ext/module.rb +2 -0
- data/boot/fancy_ext/object.rb +0 -17
- data/boot/rbx-compiler/compiler/ast/method_def.rb +0 -4
- data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +0 -7
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/fancy_parser.c +1 -0
- data/doc/api/fancy.css +10 -1
- data/doc/api/fancy.jsonp +1 -1
- data/doc/api/fdoc.js +22 -9
- data/doc/api/octocat.png +0 -0
- data/doc/features.md +1 -2
- data/examples/actors.fy +1 -2
- data/examples/armstrong_numbers.fy +7 -3
- data/examples/blocks.fy +3 -3
- data/examples/distributing_proxy.fy +31 -0
- data/examples/future_sends.fy +15 -0
- data/examples/person.fy +1 -2
- data/lib/argv.fy +1 -7
- data/lib/array.fy +7 -11
- data/lib/block.fy +15 -0
- data/lib/boot.fy +4 -3
- data/lib/class.fy +354 -10
- data/lib/compiler.fy +1 -1
- data/lib/compiler/ast/assign.fy +4 -8
- data/lib/compiler/ast/async_send.fy +1 -2
- data/lib/compiler/ast/block.fy +5 -0
- data/lib/compiler/ast/class_def.fy +2 -1
- data/lib/compiler/ast/expression_list.fy +1 -2
- data/lib/compiler/ast/future_send.fy +1 -2
- data/lib/compiler/ast/identifier.fy +34 -17
- data/lib/compiler/ast/literals.fy +31 -19
- data/lib/compiler/ast/match.fy +5 -4
- data/lib/compiler/ast/message_send.fy +3 -5
- data/lib/compiler/ast/method_def.fy +0 -3
- data/lib/compiler/ast/range.fy +2 -4
- data/lib/compiler/ast/return.fy +2 -4
- data/lib/compiler/ast/script.fy +2 -4
- data/lib/compiler/ast/singleton_method_def.fy +0 -3
- data/lib/compiler/ast/string_interpolation.fy +2 -2
- data/lib/compiler/ast/super.fy +2 -4
- data/lib/compiler/ast/try_catch.fy +13 -9
- data/lib/compiler/ast/tuple_literal.fy +1 -2
- data/lib/compiler/compiler.fy +2 -2
- data/lib/compiler/stages.fy +3 -6
- data/lib/contracts.fy +89 -57
- data/lib/dynamic_slot_object.fy +21 -3
- data/lib/enumerable.fy +140 -4
- data/lib/enumerator.fy +1 -1
- data/lib/eval.fy +23 -9
- data/lib/exception.fy +16 -0
- data/lib/false_class.fy +36 -5
- data/lib/fancy_spec.fy +64 -34
- data/lib/fdoc.fy +85 -24
- data/lib/file.fy +19 -0
- data/lib/future.fy +4 -46
- data/lib/hash.fy +113 -0
- data/lib/integer.fy +25 -6
- data/lib/iteration.fy +3 -3
- data/lib/main.fy +5 -0
- data/lib/matchers.fy +79 -0
- data/lib/nil_class.fy +8 -0
- data/lib/object.fy +109 -18
- data/lib/option_parser.fy +118 -0
- data/lib/package/dependency.fy +4 -8
- data/lib/package/dependency_installer.fy +1 -1
- data/lib/package/handler.fy +6 -0
- data/lib/package/installer.fy +43 -16
- data/lib/package/list.fy +1 -2
- data/lib/package/specification.fy +5 -5
- data/lib/package/uninstaller.fy +9 -2
- data/lib/parser.fy +1 -3
- data/lib/parser/ext/ext.c +1 -0
- data/lib/parser/ext/lexer.lex +5 -0
- data/lib/parser/methods.fy +48 -46
- data/lib/proxies.fy +151 -0
- data/lib/rbx.fy +1 -0
- data/lib/rbx/actor.fy +16 -18
- data/lib/rbx/array.fy +18 -3
- data/lib/rbx/block.fy +1 -7
- data/lib/rbx/class.fy +54 -9
- data/lib/rbx/code_loader.fy +2 -5
- data/lib/rbx/compiled_method.fy +31 -0
- data/lib/rbx/debugger.fy +66 -0
- data/lib/rbx/directory.fy +8 -3
- data/lib/rbx/documentation.fy +1 -1
- data/lib/rbx/file.fy +22 -0
- data/lib/rbx/integer.fy +1 -1
- data/lib/rbx/match_data.fy +2 -1
- data/lib/rbx/method.fy +26 -0
- data/lib/rbx/object.fy +8 -3
- data/lib/rbx/regexp.fy +6 -3
- data/lib/rbx/string.fy +9 -1
- data/lib/rbx/stringio.fy +12 -0
- data/lib/rbx/symbol.fy +4 -0
- data/lib/stack.fy +1 -1
- data/lib/string.fy +34 -0
- data/lib/stringio.fy +1 -1
- data/lib/symbol.fy +6 -2
- data/lib/system.fy +15 -1
- data/lib/tuple.fy +5 -2
- data/lib/version.fy +1 -1
- data/ruby_lib/fdoc +2 -22
- data/tests/array.fy +3 -17
- data/tests/class.fy +312 -10
- data/tests/contracts.fy +51 -0
- data/tests/distributing_proxy.fy +28 -0
- data/tests/enumerable.fy +104 -1
- data/tests/exception.fy +35 -0
- data/tests/fixnum.fy +1 -1
- data/tests/hash.fy +81 -1
- data/tests/integer.fy +9 -0
- data/tests/matchers.fy +18 -0
- data/tests/method.fy +8 -14
- data/tests/object.fy +76 -2
- data/tests/option_parser.fy +80 -0
- data/tests/string.fy +21 -0
- data/tests/stringio.fy +1 -1
- data/tests/tuple.fy +1 -1
- metadata +21 -44
- data/examples/arithmetic.fy +0 -7
- data/examples/array.fy +0 -50
- data/examples/boolean.fy +0 -24
- data/examples/class.fy +0 -68
- data/examples/constant_access.fy +0 -15
- data/examples/default_args.fy +0 -20
- data/examples/define_methods.fy +0 -15
- data/examples/dynamic_output.fy +0 -15
- data/examples/empty_catch.fy +0 -4
- data/examples/exception.fy +0 -9
- data/examples/files.fy +0 -23
- data/examples/finally.fy +0 -5
- data/examples/future.fy +0 -30
- data/examples/future_composition.fy +0 -20
- data/examples/futures.fy +0 -9
- data/examples/game_of_life.fy +0 -148
- data/examples/html_generator.fy +0 -84
- data/examples/implicit_return.fy +0 -3
- data/examples/matchers.fy +0 -6
- data/examples/nested_try.fy +0 -9
- data/examples/numbers.fy +0 -12
- data/examples/rbx/and_or.fy +0 -7
- data/examples/rbx/blocks.fy +0 -22
- data/examples/rbx/classes.fy +0 -32
- data/examples/rbx/hello.fy +0 -8
- data/examples/rbx/include.fy +0 -12
- data/examples/rbx/inherit.fy +0 -11
- data/examples/rbx/methods.fy +0 -15
- data/examples/rbx/nested_classes.fy +0 -9
- data/examples/rbx/require.fy +0 -3
- data/examples/rbx/strings.fy +0 -5
- data/examples/require.fy +0 -7
- data/examples/return.fy +0 -13
- data/examples/singleton_methods.fy +0 -21
- data/examples/threads.fy +0 -18
- data/examples/tuple.fy +0 -8
- data/examples/webserver/webserver.fy +0 -15
- data/lib/proxy.fy +0 -86
- data/lib/thread_pool.fy +0 -102
data/lib/enumerator.fy
CHANGED
data/lib/eval.fy
CHANGED
|
@@ -1,28 +1,42 @@
|
|
|
1
1
|
require: "compiler"
|
|
2
2
|
|
|
3
|
-
def Fancy eval: code binding:
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
def Fancy eval: code binding: binding (nil) file: file ("(fancy-eval)") line: line (1) {
|
|
4
|
+
"""
|
|
5
|
+
@code @String@ of Fancy code to be evaluated.
|
|
6
|
+
@binding @Binding@ to evaluate @code in.
|
|
7
|
+
@file @String that is the name of @File@ from which @code is evaluated from (if any).
|
|
8
|
+
@line Starting line, defaults to 1.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
binding if_nil: {
|
|
12
|
+
binding = Binding setup(Rubinius VariableScope of_sender(),
|
|
6
13
|
Rubinius CompiledMethod of_sender(),
|
|
7
14
|
Rubinius StaticScope of_sender())
|
|
8
15
|
}
|
|
9
16
|
|
|
10
17
|
# The compiled method
|
|
11
|
-
cm = Fancy Compiler compile_code: code vars: (
|
|
12
|
-
|
|
18
|
+
cm = Fancy Compiler compile_code: code vars: (binding variables()) file: file line: line
|
|
19
|
+
|
|
20
|
+
# Binding#static_scope was renamed to Binding#constant_scope a while ago.
|
|
21
|
+
# if the new version fails, retry with the old name for backwards compatibility (for now).
|
|
22
|
+
try {
|
|
23
|
+
cm scope=(binding constant_scope() dup())
|
|
24
|
+
} catch NoMethodError {
|
|
25
|
+
cm scope=(binding static_scope() dup())
|
|
26
|
+
}
|
|
13
27
|
cm name=('__fancy_eval__)
|
|
14
28
|
|
|
15
29
|
script = Rubinius CompiledMethod Script new(cm, file, true)
|
|
16
|
-
script eval_binding=(
|
|
30
|
+
script eval_binding=(binding)
|
|
17
31
|
script eval_source=(code)
|
|
18
32
|
|
|
19
33
|
cm scope() script=(script)
|
|
20
34
|
|
|
21
35
|
be = Rubinius BlockEnvironment new()
|
|
22
|
-
be under_context(
|
|
36
|
+
be under_context(binding variables(), cm)
|
|
23
37
|
|
|
24
|
-
if: (
|
|
25
|
-
be proc_environment=(
|
|
38
|
+
if: (binding from_proc?()) then: {
|
|
39
|
+
be proc_environment=(binding proc_environment)
|
|
26
40
|
}
|
|
27
41
|
|
|
28
42
|
be from_eval!()
|
data/lib/exception.fy
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class StandardError {
|
|
2
|
+
def self raise: message {
|
|
3
|
+
"""
|
|
4
|
+
Raises new @Exception@ with @message.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
StandardError raise: \"Error!\"
|
|
8
|
+
ArgumentError raise: \"Missing argument!\"
|
|
9
|
+
# is the same as:
|
|
10
|
+
StandardError new: \"Error!\” . raise!
|
|
11
|
+
ArgumentError new: \"Missing argument!\" . raise!
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
new: message . raise!
|
|
15
|
+
}
|
|
16
|
+
}
|
data/lib/false_class.fy
CHANGED
|
@@ -10,45 +10,76 @@ class FalseClass {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
def if_true: block {
|
|
13
|
-
"
|
|
13
|
+
"""
|
|
14
|
+
@return @nil.
|
|
15
|
+
"""
|
|
16
|
+
|
|
14
17
|
nil
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
def if_true: then_block else: else_block {
|
|
18
|
-
"
|
|
21
|
+
"""
|
|
22
|
+
Calls @else_block.
|
|
23
|
+
"""
|
|
24
|
+
|
|
19
25
|
else_block call
|
|
20
26
|
}
|
|
21
27
|
|
|
22
28
|
def if_false: block {
|
|
29
|
+
"""
|
|
30
|
+
Calls @block with @self.
|
|
31
|
+
"""
|
|
32
|
+
|
|
23
33
|
block call: [self]
|
|
24
34
|
}
|
|
25
35
|
|
|
26
36
|
def if_false: then_block else: else_block {
|
|
37
|
+
"""
|
|
38
|
+
Calls @then_block with @self.
|
|
39
|
+
"""
|
|
40
|
+
|
|
27
41
|
then_block call: [self]
|
|
28
42
|
}
|
|
29
43
|
|
|
30
44
|
def if_nil: then_block {
|
|
45
|
+
"""
|
|
46
|
+
@return @nil.
|
|
47
|
+
"""
|
|
48
|
+
|
|
31
49
|
nil
|
|
32
50
|
}
|
|
33
51
|
|
|
34
52
|
def if_nil: then_block else: else_block {
|
|
53
|
+
"""
|
|
54
|
+
Calls @else_block with @self.
|
|
55
|
+
"""
|
|
56
|
+
|
|
35
57
|
else_block call: [self]
|
|
36
58
|
}
|
|
37
59
|
|
|
38
60
|
def false? {
|
|
39
|
-
"
|
|
61
|
+
"""
|
|
62
|
+
@return @true.
|
|
63
|
+
"""
|
|
64
|
+
|
|
40
65
|
true
|
|
41
66
|
}
|
|
42
67
|
|
|
43
68
|
def to_s {
|
|
44
|
-
"
|
|
69
|
+
"""
|
|
70
|
+
@return @false as a @String@.
|
|
71
|
+
"""
|
|
72
|
+
|
|
45
73
|
"false"
|
|
46
74
|
}
|
|
47
75
|
|
|
48
76
|
alias_method: 'inspect for: 'to_s
|
|
49
77
|
|
|
50
78
|
def to_a {
|
|
51
|
-
"
|
|
79
|
+
"""
|
|
80
|
+
@return An empty @Array@.
|
|
81
|
+
"""
|
|
82
|
+
|
|
52
83
|
[]
|
|
53
84
|
}
|
|
54
85
|
|
data/lib/fancy_spec.fy
CHANGED
|
@@ -20,6 +20,7 @@ class FancySpec {
|
|
|
20
20
|
Factory method for creating FancySpec instances.
|
|
21
21
|
Calls @block with the new FancySpec instance as the receiver, then runs it.
|
|
22
22
|
|
|
23
|
+
Example:
|
|
23
24
|
FancySpec describe: MyTestClass with: {
|
|
24
25
|
# test cases using it:for:when: here.
|
|
25
26
|
}
|
|
@@ -32,8 +33,9 @@ class FancySpec {
|
|
|
32
33
|
|
|
33
34
|
def FancySpec describe: description for: test_obj with: block {
|
|
34
35
|
"""
|
|
35
|
-
Similar to FancySpec
|
|
36
|
+
Similar to @FancySpec~describe:with:@ but also taking an explicit @test_obj.
|
|
36
37
|
|
|
38
|
+
Example:
|
|
37
39
|
FancySpec describe: \"My cool class\" for: MyCoolClass with: {
|
|
38
40
|
# test cases using it:for:when: here.
|
|
39
41
|
}
|
|
@@ -53,7 +55,7 @@ class FancySpec {
|
|
|
53
55
|
it: \"should be an empty Array\" when: {
|
|
54
56
|
arr = [1,2,3]
|
|
55
57
|
3 times: { arr pop }
|
|
56
|
-
arr empty? is
|
|
58
|
+
arr empty? is: true
|
|
57
59
|
}
|
|
58
60
|
"""
|
|
59
61
|
|
|
@@ -71,19 +73,23 @@ class FancySpec {
|
|
|
71
73
|
it: \"should be an empty Array\" with: 'empty? when: {
|
|
72
74
|
arr = [1,2,3]
|
|
73
75
|
3 times: { arr pop }
|
|
74
|
-
arr empty? is
|
|
76
|
+
arr empty? is: true
|
|
75
77
|
}
|
|
76
78
|
"""
|
|
77
79
|
|
|
78
80
|
test = SpecTest new: spec_info_string block: spec_block
|
|
79
|
-
|
|
80
|
-
# @test_obj method: method_name . if_true: |method| {
|
|
81
|
-
# method tests << test
|
|
82
|
-
# }
|
|
83
|
-
# } catch MethodNotFoundError => e {
|
|
84
|
-
# # ignore errors
|
|
85
|
-
# }
|
|
81
|
+
|
|
86
82
|
@spec_tests << test
|
|
83
|
+
|
|
84
|
+
match @test_obj {
|
|
85
|
+
case Class ->
|
|
86
|
+
has_method? = @test_obj has_method?: method_name
|
|
87
|
+
{ has_method? = @test_obj metaclass has_method?: method_name } unless: has_method?
|
|
88
|
+
|
|
89
|
+
unless: has_method? do: {
|
|
90
|
+
SpecTest method_not_found: method_name for: @test_obj
|
|
91
|
+
}
|
|
92
|
+
}
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
alias_method: 'it:for:when: for: 'it:with:when:
|
|
@@ -142,6 +148,7 @@ class FancySpec {
|
|
|
142
148
|
@@failed_count = 0
|
|
143
149
|
@@total_tests = 0
|
|
144
150
|
@@total_expectations = 0
|
|
151
|
+
@@methods_not_found = <[]>
|
|
145
152
|
|
|
146
153
|
def SpecTest add_expectation {
|
|
147
154
|
@@total_expectations = @@total_expectations + 1
|
|
@@ -171,29 +178,43 @@ class FancySpec {
|
|
|
171
178
|
@@failed_count = @@failed_count + 1
|
|
172
179
|
}
|
|
173
180
|
|
|
181
|
+
def SpecTest method_not_found: method_name for: type {
|
|
182
|
+
{ @@methods_not_found[type]: []} unless: $ @@methods_not_found[type]
|
|
183
|
+
@@methods_not_found[type] << method_name
|
|
184
|
+
}
|
|
185
|
+
|
|
174
186
|
def SpecTest current {
|
|
175
187
|
@@current
|
|
176
188
|
}
|
|
177
189
|
|
|
178
190
|
def SpecTest print_failures: start_time no_failures: ok_block else: error_block {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
191
|
+
let: '*stdout* be: *stderr* in: {
|
|
192
|
+
@@failed_positive each: |test_obj failed_tests| {
|
|
193
|
+
failed_tests each: |t| {
|
|
194
|
+
"\n> FAILED: " ++ test_obj ++ " " ++ (t info_str) print
|
|
195
|
+
t print_failed_positive
|
|
196
|
+
}
|
|
184
197
|
}
|
|
185
|
-
}
|
|
186
198
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
199
|
+
@@failed_negative each: |test_obj failed_tests| {
|
|
200
|
+
failed_tests each: |t| {
|
|
201
|
+
"\n> FAILED: " ++ test_obj ++ " " ++ (t info_str) print
|
|
202
|
+
t print_failed_negative
|
|
203
|
+
}
|
|
192
204
|
}
|
|
205
|
+
|
|
206
|
+
unless: (@@methods_not_found empty? ) do: {
|
|
207
|
+
"The following methods were referenced in tests but could not be found:" println
|
|
208
|
+
max_size = @@methods_not_found keys map: @{ to_s size } . max
|
|
209
|
+
@@methods_not_found each: |type, methods| {
|
|
210
|
+
*stdout* printf("%-#{max_size}s : ", type)
|
|
211
|
+
methods map: @{ to_fancy_message } . join: ", " . println
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
"\nRan #{@@total_tests} tests (#{@@total_expectations} expectations) with #{@@failed_count} failures in #{Time now - start_time} seconds." println
|
|
193
216
|
}
|
|
194
217
|
|
|
195
|
-
Console newline
|
|
196
|
-
"Ran #{@@total_tests} tests (#{@@total_expectations} expectations) with #{@@failed_count} failures in #{Time now - start_time} seconds." println
|
|
197
218
|
if: (@@failed_count == 0) then: ok_block else: error_block
|
|
198
219
|
}
|
|
199
220
|
|
|
@@ -210,8 +231,8 @@ class FancySpec {
|
|
|
210
231
|
@@total_tests = @@total_tests + 1
|
|
211
232
|
try {
|
|
212
233
|
@block call_with_receiver: self
|
|
213
|
-
} catch
|
|
214
|
-
failed: (e, "No Exception")
|
|
234
|
+
} catch StandardError => e {
|
|
235
|
+
failed: (e, "No Exception") location: (e backtrace)
|
|
215
236
|
}
|
|
216
237
|
|
|
217
238
|
if: failed? then: {
|
|
@@ -221,14 +242,18 @@ class FancySpec {
|
|
|
221
242
|
}
|
|
222
243
|
}
|
|
223
244
|
|
|
224
|
-
def failed: actual_and_expected {
|
|
225
|
-
|
|
245
|
+
def failed: actual_and_expected location: location (nil) {
|
|
246
|
+
unless: location do: {
|
|
247
|
+
location = caller() find: |l| { l =~ /__script__/ }
|
|
248
|
+
}
|
|
249
|
+
@failed_positive << (actual_and_expected, location)
|
|
226
250
|
SpecTest failed_test: self
|
|
227
251
|
}
|
|
228
252
|
|
|
229
253
|
def failed_negative: value {
|
|
230
254
|
{ value = [value, 'negative_failure] } unless: $ value responds_to?: 'at:
|
|
231
|
-
|
|
255
|
+
location = caller() find: |l| { l =~ /__script__/ }
|
|
256
|
+
@failed_negative << (value, location)
|
|
232
257
|
SpecTest failed_negative_test: self
|
|
233
258
|
}
|
|
234
259
|
|
|
@@ -251,10 +276,15 @@ class FancySpec {
|
|
|
251
276
|
def print_failed_common: failures {
|
|
252
277
|
failures each: |f| {
|
|
253
278
|
actual, expected = f first
|
|
254
|
-
|
|
255
|
-
|
|
279
|
+
locations = f second
|
|
280
|
+
|
|
281
|
+
locations to_a map: |loc| {
|
|
282
|
+
loc = loc gsub(/:(\d+):in `[^']+'/, " +\1")
|
|
283
|
+
file, line = loc split: " +"
|
|
284
|
+
loc = "#{file} +#{line to_i - 1}" # somehow line is off by +1
|
|
285
|
+
loc = loc split: (Directory pwd + "/") . second
|
|
286
|
+
} . compact println
|
|
256
287
|
|
|
257
|
-
location println
|
|
258
288
|
unless: (expected == 'negative_failure) do: {
|
|
259
289
|
" Expected: #{expected inspect}" println
|
|
260
290
|
" Received: #{actual inspect}" println
|
|
@@ -296,7 +326,7 @@ class FancySpec {
|
|
|
296
326
|
SpecTest current failed: (nil, exception_class)
|
|
297
327
|
} catch exception_class {
|
|
298
328
|
# ok
|
|
299
|
-
} catch
|
|
329
|
+
} catch StandardError => e {
|
|
300
330
|
SpecTest current failed: (e class, exception_class)
|
|
301
331
|
}
|
|
302
332
|
}
|
|
@@ -309,7 +339,7 @@ class FancySpec {
|
|
|
309
339
|
} catch exception_class => e {
|
|
310
340
|
block call: [e]
|
|
311
341
|
# ok
|
|
312
|
-
} catch
|
|
342
|
+
} catch StandardError => e {
|
|
313
343
|
SpecTest current failed: (e class, exception_class)
|
|
314
344
|
}
|
|
315
345
|
}
|
|
@@ -360,7 +390,7 @@ class FancySpec {
|
|
|
360
390
|
@actual_value call
|
|
361
391
|
} catch exception_class {
|
|
362
392
|
SpecTest current failed_negative: (exception_class, nil)
|
|
363
|
-
} catch
|
|
393
|
+
} catch StandardError {
|
|
364
394
|
true
|
|
365
395
|
# ok
|
|
366
396
|
}
|
data/lib/fdoc.fy
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# Load all of fancy.
|
|
2
|
+
require: "rbx/documentation"
|
|
3
|
+
require: "fdoc_hook"
|
|
2
4
|
require: "boot"
|
|
5
|
+
require: "option_parser"
|
|
6
|
+
require: "fancy_spec"
|
|
3
7
|
|
|
4
8
|
class Fancy FDoc {
|
|
5
9
|
"""
|
|
6
|
-
|
|
7
10
|
FDoc is a tool to generate API documentation from Fancy source.
|
|
8
11
|
|
|
9
12
|
Works as follows:
|
|
@@ -18,30 +21,72 @@ class Fancy FDoc {
|
|
|
18
21
|
4. Generate output file.
|
|
19
22
|
Currently the plan is to output a json formatted object.
|
|
20
23
|
To be loaded by an html file and use jquery to build a GUI from it.
|
|
21
|
-
|
|
22
24
|
"""
|
|
23
25
|
|
|
24
26
|
OUTPUT_DIR = "doc/api/"
|
|
27
|
+
FANCY_ROOT_DIR = __FILE__ relative_path: "../"
|
|
25
28
|
|
|
26
29
|
def self main {
|
|
27
30
|
"""
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
FDoc will load all .fy files you give to it, and optionally run
|
|
32
|
+
any specified FancySpec, and later produce documentation output.
|
|
30
33
|
"""
|
|
31
34
|
|
|
32
35
|
output_dir = OUTPUT_DIR
|
|
33
|
-
|
|
36
|
+
with_stdlib = false
|
|
37
|
+
add_github_links = false
|
|
38
|
+
github_repo = "bakkdoor/fancy"
|
|
39
|
+
|
|
40
|
+
OptionParser new: @{
|
|
41
|
+
remove_after_parsed: true
|
|
42
|
+
banner: "Usage: fdoc [options] [source_files]\nOptions:"
|
|
43
|
+
|
|
44
|
+
with: "-o [output_dir]" doc: "Sets output directory of generated documentation page, defaults to #{output_dir}" do: |dir| {
|
|
45
|
+
output_dir = dir
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
with: "-github-repo [repo_url]" doc: "Sets the Github repository to link to method definitions. Example: -github-repo bakkdoor/redis.fy" do: |url| {
|
|
49
|
+
github_repo = url
|
|
50
|
+
add_github_links = true
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
with: "--with-stdlib" doc: "Include Fancy's standard library in generated documentation" do: {
|
|
54
|
+
with_stdlib = true
|
|
55
|
+
}
|
|
56
|
+
} . parse: ARGV
|
|
57
|
+
|
|
58
|
+
output_dir = File absolute_path: output_dir . + "/"
|
|
59
|
+
|
|
34
60
|
require("fileutils")
|
|
35
61
|
FileUtils mkdir_p(output_dir)
|
|
36
62
|
|
|
63
|
+
# check if we're in Fancy's root dir
|
|
64
|
+
# if not, copy fdoc related files over to output_dir
|
|
65
|
+
if: (output_dir relative_path: "../" == FANCY_ROOT_DIR) then: {
|
|
66
|
+
# add stdlib by default when in FANCY_ROOT_DIR
|
|
67
|
+
with_stdlib = true
|
|
68
|
+
add_github_links = true
|
|
69
|
+
} else: {
|
|
70
|
+
files = Dir list: "#{FANCY_ROOT_DIR}/doc/api/*" . reject: |f| { f =~ /fancy\.jsonp$/ }
|
|
71
|
+
FileUtils cp(files, output_dir)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if: with_stdlib then: {
|
|
75
|
+
@objects_to_remove = <[]>
|
|
76
|
+
} else: {
|
|
77
|
+
@objects_to_remove = @documented_objects dup
|
|
78
|
+
}
|
|
79
|
+
|
|
37
80
|
# Currently we just load any files given on ARGV.
|
|
38
81
|
ARGV each: |file| { Fancy CodeLoader load_compiled_file(file) }
|
|
39
82
|
|
|
83
|
+
@documented_objects = @documented_objects select_keys: |k| { @objects_to_remove includes?: k . not }
|
|
84
|
+
|
|
40
85
|
# by now simply produce a apidoc/fancy.jsonp file.
|
|
41
|
-
json = JSON new: @documented_objects
|
|
86
|
+
json = JSON new: @documented_objects add_github_links: add_github_links github_repo: github_repo
|
|
42
87
|
json write: (File expand_path("fancy.jsonp", output_dir))
|
|
43
88
|
|
|
44
|
-
["Open your browser at " ++ output_dir ++ "index.html
|
|
89
|
+
["Open your browser at " ++ output_dir ++ "index.html ",
|
|
45
90
|
" " ++ (json classes size) ++ " classes. ",
|
|
46
91
|
" " ++ (json methods size) ++ " methods. ",
|
|
47
92
|
" " ++ (json objects size) ++ " other objects. "] println
|
|
@@ -49,10 +94,9 @@ class Fancy FDoc {
|
|
|
49
94
|
|
|
50
95
|
|
|
51
96
|
class JSON {
|
|
52
|
-
|
|
53
97
|
read_slots: ['classes, 'methods, 'blocks, 'objects]
|
|
54
98
|
|
|
55
|
-
def initialize: documented {
|
|
99
|
+
def initialize: documented add_github_links: @add_github_links github_repo: @github_repo {
|
|
56
100
|
@documented_objects = documented
|
|
57
101
|
|
|
58
102
|
is_class = |o| { o kind_of?: Module }
|
|
@@ -68,8 +112,13 @@ class Fancy FDoc {
|
|
|
68
112
|
@objects = @documented_objects keys select: all_other
|
|
69
113
|
}
|
|
70
114
|
|
|
71
|
-
def string_to_json: obj {
|
|
72
|
-
|
|
115
|
+
def string_to_json: obj {
|
|
116
|
+
obj to_s inspect
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
def symbol_to_json: obj {
|
|
120
|
+
obj to_s
|
|
121
|
+
}
|
|
73
122
|
|
|
74
123
|
def array_to_json: obj {
|
|
75
124
|
str = ["["]
|
|
@@ -125,7 +174,7 @@ class Fancy FDoc {
|
|
|
125
174
|
mattr['file]: $ relative_file
|
|
126
175
|
# TODO calculate line numbers from compiled method
|
|
127
176
|
# right now we only use the first line of code in the body.
|
|
128
|
-
mattr['lines]: $ [
|
|
177
|
+
mattr['lines]: $ [exec definition_line, exec last_line]
|
|
129
178
|
}
|
|
130
179
|
attr[(type ++ "s") intern()] [n]: mattr
|
|
131
180
|
}
|
|
@@ -170,17 +219,14 @@ class Fancy FDoc {
|
|
|
170
219
|
map
|
|
171
220
|
}
|
|
172
221
|
|
|
173
|
-
|
|
174
222
|
def write: filename call: name ("fancy.fdoc") {
|
|
175
223
|
map = generate_map
|
|
176
224
|
json = to_json: map
|
|
177
|
-
js = "(function() {
|
|
225
|
+
js = "(function() { #{name}(#{@add_github_links}, #{@github_repo inspect}, #{json}); })();"
|
|
178
226
|
File open: filename modes: ['write] with: |out| { out print: js }
|
|
179
227
|
}
|
|
180
|
-
|
|
181
228
|
}
|
|
182
229
|
|
|
183
|
-
|
|
184
230
|
class Formatter {
|
|
185
231
|
"""
|
|
186
232
|
A documentation formater intended to be used by @FDoc@.
|
|
@@ -191,7 +237,6 @@ class Fancy FDoc {
|
|
|
191
237
|
|
|
192
238
|
Fancy Documentation formatter: 'fdoc is: |d| { format: d }
|
|
193
239
|
|
|
194
|
-
|
|
195
240
|
def self format: doc {
|
|
196
241
|
str = doc to_s
|
|
197
242
|
tags = <[ ]>
|
|
@@ -200,8 +245,8 @@ class Fancy FDoc {
|
|
|
200
245
|
str = create_tags: str with: tags
|
|
201
246
|
str = create_class_references: str
|
|
202
247
|
str = create_method_references: str
|
|
203
|
-
str = create_code: str
|
|
204
248
|
str = htmlize: str
|
|
249
|
+
str = create_code: str
|
|
205
250
|
str
|
|
206
251
|
}
|
|
207
252
|
|
|
@@ -240,6 +285,7 @@ class Fancy FDoc {
|
|
|
240
285
|
A singleton method:
|
|
241
286
|
@Fancy::FDoc::Formatter~format:@
|
|
242
287
|
"""
|
|
288
|
+
|
|
243
289
|
str gsub(/@[A-Z][^\r\n\s]+?@/) |cstr| {
|
|
244
290
|
names = cstr slice(1, cstr size() - 2) split("::")
|
|
245
291
|
refs = []
|
|
@@ -296,18 +342,35 @@ class Fancy FDoc {
|
|
|
296
342
|
}
|
|
297
343
|
|
|
298
344
|
def self create_tags: str with: map {
|
|
345
|
+
max_width = map map: @{ first size } . max
|
|
299
346
|
tags = map map: |pair| {
|
|
300
347
|
name = pair[0]
|
|
301
348
|
value = pair[1]
|
|
302
|
-
|
|
303
|
-
|
|
349
|
+
# make argument names all align nicely:
|
|
350
|
+
name = name + (" " * (max_width - (name size)))
|
|
351
|
+
"<div class=\"doctag\"><label> @#{name} </label><div>#{value}</div></div>"
|
|
304
352
|
}
|
|
305
353
|
str ++ "\n<div class=\"doctags\">" ++ (tags join()) ++ "</div>"
|
|
306
354
|
}
|
|
307
355
|
|
|
308
356
|
def self create_code: str {
|
|
309
|
-
str
|
|
310
|
-
|
|
357
|
+
md = /<pre>/ match: str
|
|
358
|
+
if: md then: {
|
|
359
|
+
md = /<pre>/ match: str
|
|
360
|
+
pre_code = md pre_match
|
|
361
|
+
md = /</pre>/ match: $ md post_match
|
|
362
|
+
code, post_code = md pre_match, md post_match
|
|
363
|
+
|
|
364
|
+
pre_code = pre_code gsub(/@([^\s,@\]\)\{\}\.]+)/,
|
|
365
|
+
"<code data-lang=\"fancy\">\\1</code>")
|
|
366
|
+
post_code = post_code gsub(/@([^\s,@\]\)\{\}\.]+)/,
|
|
367
|
+
"<code data-lang=\"fancy\">\\1</code>")
|
|
368
|
+
|
|
369
|
+
"#{pre_code}<pre>#{code}</pre>#{post_code}"
|
|
370
|
+
} else: {
|
|
371
|
+
str gsub(/@([^\s,@\]\)\{\}\.]+)/,
|
|
372
|
+
"<code data-lang=\"fancy\">\\1</code>")
|
|
373
|
+
}
|
|
311
374
|
}
|
|
312
375
|
|
|
313
376
|
def self htmlize: str {
|
|
@@ -324,9 +387,7 @@ class Fancy FDoc {
|
|
|
324
387
|
gsub(/@:([a-z_]+)@/,
|
|
325
388
|
"<code data-lang=\"fancy\" data-method=\":\\1\" class=\"selectable\">\\1</code>")
|
|
326
389
|
}
|
|
327
|
-
|
|
328
390
|
}
|
|
329
|
-
|
|
330
391
|
}
|
|
331
392
|
|
|
332
393
|
Fancy FDoc main
|