fancy 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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