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.
Files changed (165) hide show
  1. data/README.md +38 -86
  2. data/bin/fdoc +2 -22
  3. data/bin/fspec +8 -3
  4. data/bin/ifancy +1 -1
  5. data/boot/fancy_ext.rb +1 -0
  6. data/boot/fancy_ext/array.rb +19 -0
  7. data/boot/fancy_ext/class.rb +2 -4
  8. data/boot/fancy_ext/module.rb +2 -0
  9. data/boot/fancy_ext/object.rb +0 -17
  10. data/boot/rbx-compiler/compiler/ast/method_def.rb +0 -4
  11. data/boot/rbx-compiler/compiler/ast/singleton_method_def.rb +0 -7
  12. data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
  13. data/boot/rbx-compiler/parser/fancy_parser.c +1 -0
  14. data/doc/api/fancy.css +10 -1
  15. data/doc/api/fancy.jsonp +1 -1
  16. data/doc/api/fdoc.js +22 -9
  17. data/doc/api/octocat.png +0 -0
  18. data/doc/features.md +1 -2
  19. data/examples/actors.fy +1 -2
  20. data/examples/armstrong_numbers.fy +7 -3
  21. data/examples/blocks.fy +3 -3
  22. data/examples/distributing_proxy.fy +31 -0
  23. data/examples/future_sends.fy +15 -0
  24. data/examples/person.fy +1 -2
  25. data/lib/argv.fy +1 -7
  26. data/lib/array.fy +7 -11
  27. data/lib/block.fy +15 -0
  28. data/lib/boot.fy +4 -3
  29. data/lib/class.fy +354 -10
  30. data/lib/compiler.fy +1 -1
  31. data/lib/compiler/ast/assign.fy +4 -8
  32. data/lib/compiler/ast/async_send.fy +1 -2
  33. data/lib/compiler/ast/block.fy +5 -0
  34. data/lib/compiler/ast/class_def.fy +2 -1
  35. data/lib/compiler/ast/expression_list.fy +1 -2
  36. data/lib/compiler/ast/future_send.fy +1 -2
  37. data/lib/compiler/ast/identifier.fy +34 -17
  38. data/lib/compiler/ast/literals.fy +31 -19
  39. data/lib/compiler/ast/match.fy +5 -4
  40. data/lib/compiler/ast/message_send.fy +3 -5
  41. data/lib/compiler/ast/method_def.fy +0 -3
  42. data/lib/compiler/ast/range.fy +2 -4
  43. data/lib/compiler/ast/return.fy +2 -4
  44. data/lib/compiler/ast/script.fy +2 -4
  45. data/lib/compiler/ast/singleton_method_def.fy +0 -3
  46. data/lib/compiler/ast/string_interpolation.fy +2 -2
  47. data/lib/compiler/ast/super.fy +2 -4
  48. data/lib/compiler/ast/try_catch.fy +13 -9
  49. data/lib/compiler/ast/tuple_literal.fy +1 -2
  50. data/lib/compiler/compiler.fy +2 -2
  51. data/lib/compiler/stages.fy +3 -6
  52. data/lib/contracts.fy +89 -57
  53. data/lib/dynamic_slot_object.fy +21 -3
  54. data/lib/enumerable.fy +140 -4
  55. data/lib/enumerator.fy +1 -1
  56. data/lib/eval.fy +23 -9
  57. data/lib/exception.fy +16 -0
  58. data/lib/false_class.fy +36 -5
  59. data/lib/fancy_spec.fy +64 -34
  60. data/lib/fdoc.fy +85 -24
  61. data/lib/file.fy +19 -0
  62. data/lib/future.fy +4 -46
  63. data/lib/hash.fy +113 -0
  64. data/lib/integer.fy +25 -6
  65. data/lib/iteration.fy +3 -3
  66. data/lib/main.fy +5 -0
  67. data/lib/matchers.fy +79 -0
  68. data/lib/nil_class.fy +8 -0
  69. data/lib/object.fy +109 -18
  70. data/lib/option_parser.fy +118 -0
  71. data/lib/package/dependency.fy +4 -8
  72. data/lib/package/dependency_installer.fy +1 -1
  73. data/lib/package/handler.fy +6 -0
  74. data/lib/package/installer.fy +43 -16
  75. data/lib/package/list.fy +1 -2
  76. data/lib/package/specification.fy +5 -5
  77. data/lib/package/uninstaller.fy +9 -2
  78. data/lib/parser.fy +1 -3
  79. data/lib/parser/ext/ext.c +1 -0
  80. data/lib/parser/ext/lexer.lex +5 -0
  81. data/lib/parser/methods.fy +48 -46
  82. data/lib/proxies.fy +151 -0
  83. data/lib/rbx.fy +1 -0
  84. data/lib/rbx/actor.fy +16 -18
  85. data/lib/rbx/array.fy +18 -3
  86. data/lib/rbx/block.fy +1 -7
  87. data/lib/rbx/class.fy +54 -9
  88. data/lib/rbx/code_loader.fy +2 -5
  89. data/lib/rbx/compiled_method.fy +31 -0
  90. data/lib/rbx/debugger.fy +66 -0
  91. data/lib/rbx/directory.fy +8 -3
  92. data/lib/rbx/documentation.fy +1 -1
  93. data/lib/rbx/file.fy +22 -0
  94. data/lib/rbx/integer.fy +1 -1
  95. data/lib/rbx/match_data.fy +2 -1
  96. data/lib/rbx/method.fy +26 -0
  97. data/lib/rbx/object.fy +8 -3
  98. data/lib/rbx/regexp.fy +6 -3
  99. data/lib/rbx/string.fy +9 -1
  100. data/lib/rbx/stringio.fy +12 -0
  101. data/lib/rbx/symbol.fy +4 -0
  102. data/lib/stack.fy +1 -1
  103. data/lib/string.fy +34 -0
  104. data/lib/stringio.fy +1 -1
  105. data/lib/symbol.fy +6 -2
  106. data/lib/system.fy +15 -1
  107. data/lib/tuple.fy +5 -2
  108. data/lib/version.fy +1 -1
  109. data/ruby_lib/fdoc +2 -22
  110. data/tests/array.fy +3 -17
  111. data/tests/class.fy +312 -10
  112. data/tests/contracts.fy +51 -0
  113. data/tests/distributing_proxy.fy +28 -0
  114. data/tests/enumerable.fy +104 -1
  115. data/tests/exception.fy +35 -0
  116. data/tests/fixnum.fy +1 -1
  117. data/tests/hash.fy +81 -1
  118. data/tests/integer.fy +9 -0
  119. data/tests/matchers.fy +18 -0
  120. data/tests/method.fy +8 -14
  121. data/tests/object.fy +76 -2
  122. data/tests/option_parser.fy +80 -0
  123. data/tests/string.fy +21 -0
  124. data/tests/stringio.fy +1 -1
  125. data/tests/tuple.fy +1 -1
  126. metadata +21 -44
  127. data/examples/arithmetic.fy +0 -7
  128. data/examples/array.fy +0 -50
  129. data/examples/boolean.fy +0 -24
  130. data/examples/class.fy +0 -68
  131. data/examples/constant_access.fy +0 -15
  132. data/examples/default_args.fy +0 -20
  133. data/examples/define_methods.fy +0 -15
  134. data/examples/dynamic_output.fy +0 -15
  135. data/examples/empty_catch.fy +0 -4
  136. data/examples/exception.fy +0 -9
  137. data/examples/files.fy +0 -23
  138. data/examples/finally.fy +0 -5
  139. data/examples/future.fy +0 -30
  140. data/examples/future_composition.fy +0 -20
  141. data/examples/futures.fy +0 -9
  142. data/examples/game_of_life.fy +0 -148
  143. data/examples/html_generator.fy +0 -84
  144. data/examples/implicit_return.fy +0 -3
  145. data/examples/matchers.fy +0 -6
  146. data/examples/nested_try.fy +0 -9
  147. data/examples/numbers.fy +0 -12
  148. data/examples/rbx/and_or.fy +0 -7
  149. data/examples/rbx/blocks.fy +0 -22
  150. data/examples/rbx/classes.fy +0 -32
  151. data/examples/rbx/hello.fy +0 -8
  152. data/examples/rbx/include.fy +0 -12
  153. data/examples/rbx/inherit.fy +0 -11
  154. data/examples/rbx/methods.fy +0 -15
  155. data/examples/rbx/nested_classes.fy +0 -9
  156. data/examples/rbx/require.fy +0 -3
  157. data/examples/rbx/strings.fy +0 -5
  158. data/examples/require.fy +0 -7
  159. data/examples/return.fy +0 -13
  160. data/examples/singleton_methods.fy +0 -21
  161. data/examples/threads.fy +0 -18
  162. data/examples/tuple.fy +0 -8
  163. data/examples/webserver/webserver.fy +0 -15
  164. data/lib/proxy.fy +0 -86
  165. data/lib/thread_pool.fy +0 -102
@@ -135,7 +135,7 @@ class Fancy {
135
135
  loop: {
136
136
  try {
137
137
  block call: [next]
138
- } catch (Fancy StopIteration) => ex {
138
+ } catch Fancy StopIteration {
139
139
  return self
140
140
  }
141
141
  }
@@ -1,28 +1,42 @@
1
1
  require: "compiler"
2
2
 
3
- def Fancy eval: code binding: bnd (nil) file: file ("(fancy-eval)") line: line (1) {
4
- bnd if_nil: {
5
- bnd = Binding setup(Rubinius VariableScope of_sender(),
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: (bnd variables()) file: file line: line
12
- cm scope=(bnd static_scope() dup())
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=(bnd)
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(bnd variables(), cm)
36
+ be under_context(binding variables(), cm)
23
37
 
24
- if: (bnd from_proc?()) then: {
25
- be proc_environment=(bnd proc_environment)
38
+ if: (binding from_proc?()) then: {
39
+ be proc_environment=(binding proc_environment)
26
40
  }
27
41
 
28
42
  be from_eval!()
@@ -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
+ }
@@ -10,45 +10,76 @@ class FalseClass {
10
10
  }
11
11
 
12
12
  def if_true: block {
13
- "Returns @nil."
13
+ """
14
+ @return @nil.
15
+ """
16
+
14
17
  nil
15
18
  }
16
19
 
17
20
  def if_true: then_block else: else_block {
18
- "Calls @else_block."
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
- "Returns @true."
61
+ """
62
+ @return @true.
63
+ """
64
+
40
65
  true
41
66
  }
42
67
 
43
68
  def to_s {
44
- "Returns @false as a @String@."
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
- "Returns an empty @Array@."
79
+ """
80
+ @return An empty @Array@.
81
+ """
82
+
52
83
  []
53
84
  }
54
85
 
@@ -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##describe:with: but also taking an explicit @test_obj.
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 == true
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 == true
76
+ arr empty? is: true
75
77
  }
76
78
  """
77
79
 
78
80
  test = SpecTest new: spec_info_string block: spec_block
79
- # try {
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
- @@failed_positive each: |test_obj failed_tests| {
180
- failed_tests each: |t| {
181
- Console newline
182
- "> FAILED: " ++ test_obj ++ " " ++ (t info_str) print
183
- t print_failed_positive
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
- @@failed_negative each: |test_obj failed_tests| {
188
- failed_tests each: |t| {
189
- Console newline
190
- "> FAILED: " ++ test_obj ++ " " ++ (t info_str) print
191
- t print_failed_negative
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 Exception => e {
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
- @failed_positive << (actual_and_expected, caller(5) at: 0)
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
- @failed_negative << (value, caller(6) at: 0)
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
- location = f second gsub(/:(\d+):in `[^']+'/, " +\1")
255
- location = location split: "/" . from: -2 to: -1 . join: "/"
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 Exception => e {
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 Exception => e {
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 Exception => e {
393
+ } catch StandardError {
364
394
  true
365
395
  # ok
366
396
  }
@@ -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
- FDoc will load all .fy files you give to it, and optionally run
29
- any specified FancySpec, and later produce documentation output.
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
- ARGV for_option: "-o" do: |d| { output_dir = d }
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 { obj to_s inspect }
72
- def symbol_to_json: obj { obj to_s }
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]: $ [lines[3], lines[3]]
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() { " ++ name ++ "(" ++ json ++ "); })();"
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
- "<div class=\"doctag\"><label> @" ++ name ++ .
303
- " </label><div>" ++ value ++ "</div></div>"
349
+ # make argument names all align nicely:
350
+ name = name + ("&nbsp;" * (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 gsub(/@([^\s,\]\)\{\}\.]+)/,
310
- "<code data-lang=\"fancy\">\\1</code>")
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