facets 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (1077) hide show
  1. data/AUTHORS +5 -2
  2. data/ProjectInfo +21 -12
  3. data/README +73 -44
  4. data/Rakefile +11 -11
  5. data/data/facets/index.yml +1 -0
  6. data/lib/facet/annotation.rb +1 -0
  7. data/lib/facet/ansicode.rb +1 -0
  8. data/lib/facet/array.rb +1 -34
  9. data/lib/facet/array/at_rand.rb +1 -52
  10. data/lib/facet/array/body.rb +1 -2
  11. data/lib/facet/array/delete_unless.rb +1 -35
  12. data/lib/facet/array/delete_values.rb +1 -38
  13. data/lib/facet/array/delete_values_at.rb +1 -57
  14. data/lib/facet/array/each_with_key.rb +1 -9
  15. data/lib/facet/array/first.rb +1 -84
  16. data/lib/facet/array/foot.rb +1 -2
  17. data/lib/facet/array/head.rb +1 -80
  18. data/lib/facet/array/last.rb +1 -2
  19. data/lib/facet/array/last_index.rb +1 -35
  20. data/lib/facet/array/merge.rb +1 -40
  21. data/lib/facet/array/mid.rb +1 -50
  22. data/lib/facet/array/middle.rb +1 -45
  23. data/lib/facet/array/op_fetch.rb +1 -40
  24. data/lib/facet/array/op_mod.rb +1 -16
  25. data/lib/facet/array/op_store.rb +1 -47
  26. data/lib/facet/array/pick.rb +1 -68
  27. data/lib/facet/array/pos.rb +1 -39
  28. data/lib/facet/array/pull.rb +1 -37
  29. data/lib/facet/array/rand_index.rb +1 -30
  30. data/lib/facet/array/rand_subset.rb +1 -56
  31. data/lib/facet/array/range.rb +1 -47
  32. data/lib/facet/array/rotate.rb +1 -67
  33. data/lib/facet/array/select.rb +1 -37
  34. data/lib/facet/array/shuffle.rb +1 -66
  35. data/lib/facet/array/slap.rb +1 -37
  36. data/lib/facet/array/store.rb +1 -7
  37. data/lib/facet/array/tail.rb +1 -2
  38. data/lib/facet/array/thru.rb +1 -38
  39. data/lib/facet/array/to_b.rb +1 -31
  40. data/lib/facet/array/to_h.rb +1 -57
  41. data/lib/facet/array/to_hash.rb +1 -46
  42. data/lib/facet/array/unzip.rb +1 -20
  43. data/lib/facet/association.rb +1 -0
  44. data/lib/facet/basicobject.rb +1 -0
  45. data/lib/facet/bbcode.rb +1 -0
  46. data/lib/facet/binaryreader.rb +1 -0
  47. data/lib/facet/binding.rb +1 -14
  48. data/lib/facet/binding/__DIR__.rb +1 -2
  49. data/lib/facet/binding/__FILE__.rb +1 -2
  50. data/lib/facet/binding/__LINE__.rb +1 -58
  51. data/lib/facet/binding/call_stack.rb +1 -42
  52. data/lib/facet/binding/called.rb +1 -41
  53. data/lib/facet/binding/caller.rb +1 -42
  54. data/lib/facet/binding/defined.rb +1 -41
  55. data/lib/facet/binding/eval.rb +1 -42
  56. data/lib/facet/binding/local_variables.rb +1 -45
  57. data/lib/facet/binding/method_name.rb +1 -48
  58. data/lib/facet/binding/op_fetch.rb +1 -45
  59. data/lib/facet/binding/op_store.rb +1 -46
  60. data/lib/facet/binding/self.rb +1 -41
  61. data/lib/facet/binding/self/of_caller.rb +1 -122
  62. data/lib/facet/bitmask.rb +1 -0
  63. data/lib/facet/blankslate.rb +1 -0
  64. data/lib/facet/bytes.rb +1 -0
  65. data/lib/facet/class.rb +1 -7
  66. data/lib/facet/class/by_name.rb +1 -1
  67. data/lib/facet/class/descendents.rb +1 -44
  68. data/lib/facet/class/method_name.rb +1 -33
  69. data/lib/facet/class/remove_descendents.rb +1 -46
  70. data/lib/facet/class/remove_subclasses.rb +1 -2
  71. data/lib/facet/class/subclasses.rb +1 -2
  72. data/lib/facet/class/unix_path.rb +1 -34
  73. data/lib/facet/classinherit.rb +1 -0
  74. data/lib/facet/classmethods.rb +1 -0
  75. data/lib/facet/cloneable.rb +1 -0
  76. data/lib/facet/comparable.rb +1 -5
  77. data/lib/facet/comparable/at_least.rb +1 -53
  78. data/lib/facet/comparable/at_most.rb +1 -2
  79. data/lib/facet/comparable/cap.rb +1 -2
  80. data/lib/facet/comparable/clip.rb +1 -72
  81. data/lib/facet/comparable/cmp.rb +1 -38
  82. data/lib/facet/consoleapp.rb +1 -0
  83. data/lib/facet/continuation.rb +1 -1
  84. data/lib/facet/continuation/self/create.rb +1 -71
  85. data/lib/facet/coroutine.rb +1 -0
  86. data/lib/facet/crypt.rb +1 -0
  87. data/lib/facet/date.rb +1 -0
  88. data/lib/facet/date/days_in_month.rb +1 -42
  89. data/lib/facet/date/days_of_month.rb +1 -34
  90. data/lib/facet/date/stamp.rb +1 -52
  91. data/lib/facet/date/to_date.rb +1 -36
  92. data/lib/facet/date/to_s.rb +1 -33
  93. data/lib/facet/date/to_time.rb +1 -36
  94. data/lib/facet/dictionary.rb +1 -0
  95. data/lib/facet/dir.rb +1 -4
  96. data/lib/facet/dir/self/ancestor.rb +1 -33
  97. data/lib/facet/dir/self/ascend.rb +1 -56
  98. data/lib/facet/dir/self/ls_r.rb +1 -76
  99. data/lib/facet/dir/self/recurse.rb +1 -2
  100. data/lib/facet/downloader.rb +1 -0
  101. data/lib/facet/enumerable.rb +1 -39
  102. data/lib/facet/enumerable/collect_with_counter.rb +1 -2
  103. data/lib/facet/enumerable/collect_with_index.rb +1 -51
  104. data/lib/facet/enumerable/commonality.rb +1 -63
  105. data/lib/facet/enumerable/compact_collect.rb +1 -50
  106. data/lib/facet/enumerable/compact_map.rb +1 -2
  107. data/lib/facet/enumerable/cross.rb +1 -44
  108. data/lib/facet/enumerable/each_by.rb +1 -2
  109. data/lib/facet/enumerable/each_combination.rb +1 -59
  110. data/lib/facet/enumerable/each_pair.rb +1 -50
  111. data/lib/facet/enumerable/each_permutation.rb +1 -2
  112. data/lib/facet/enumerable/each_slice.rb +1 -131
  113. data/lib/facet/enumerable/each_unique_pair.rb +1 -66
  114. data/lib/facet/enumerable/each_with_counter.rb +1 -8
  115. data/lib/facet/enumerable/elementwise.rb +1 -2
  116. data/lib/facet/enumerable/entropy.rb +1 -52
  117. data/lib/facet/enumerable/every.rb +1 -65
  118. data/lib/facet/enumerable/ew.rb +1 -64
  119. data/lib/facet/enumerable/filter_collect.rb +1 -58
  120. data/lib/facet/enumerable/filter_map.rb +1 -2
  121. data/lib/facet/enumerable/find_collisions.rb +1 -41
  122. data/lib/facet/enumerable/frequency.rb +1 -39
  123. data/lib/facet/enumerable/graph.rb +1 -59
  124. data/lib/facet/enumerable/ideal_entropy.rb +1 -49
  125. data/lib/facet/enumerable/map_with_counter.rb +1 -2
  126. data/lib/facet/enumerable/map_with_index.rb +1 -2
  127. data/lib/facet/enumerable/none.rb +1 -56
  128. data/lib/facet/enumerable/nonuniq.rb +1 -39
  129. data/lib/facet/enumerable/occur.rb +1 -62
  130. data/lib/facet/enumerable/one.rb +1 -65
  131. data/lib/facet/enumerable/op_pow.rb +1 -38
  132. data/lib/facet/enumerable/partition_by.rb +1 -55
  133. data/lib/facet/enumerable/permute.rb +1 -135
  134. data/lib/facet/enumerable/probability.rb +1 -59
  135. data/lib/facet/enumerable/project.rb +1 -11
  136. data/lib/facet/enumerable/self/combinations.rb +1 -68
  137. data/lib/facet/enumerable/self/cross.rb +1 -79
  138. data/lib/facet/enumerable/to_h.rb +1 -50
  139. data/lib/facet/enumerable/uniq_by.rb +1 -39
  140. data/lib/facet/enumerable/where.rb +1 -12
  141. data/lib/facet/enumerablepass.rb +1 -0
  142. data/lib/facet/expirable.rb +1 -0
  143. data/lib/facet/file.rb +1 -5
  144. data/lib/facet/file/self/create.rb +1 -52
  145. data/lib/facet/file/self/open_as_string.rb +1 -81
  146. data/lib/facet/file/self/read_list.rb +1 -47
  147. data/lib/facet/file/self/sanitize.rb +1 -50
  148. data/lib/facet/file/self/split_all.rb +1 -36
  149. data/lib/facet/filelist.rb +1 -0
  150. data/lib/facet/fileutils.rb +1 -0
  151. data/lib/facet/fileutils/head.rb +1 -2
  152. data/lib/facet/fileutils/safe_ln.rb +1 -38
  153. data/lib/facet/fileutils/slice.rb +1 -152
  154. data/lib/facet/fileutils/split_all.rb +1 -29
  155. data/lib/facet/fileutils/tail.rb +1 -2
  156. data/lib/facet/fileutils/wc.rb +1 -128
  157. data/lib/facet/fileutils/whereis.rb +1 -76
  158. data/lib/facet/fileutils/which.rb +1 -117
  159. data/lib/facet/float.rb +1 -3
  160. data/lib/facet/float/approx.rb +1 -42
  161. data/lib/facet/float/round_at.rb +1 -72
  162. data/lib/facet/float/round_to.rb +1 -73
  163. data/lib/facet/floatstring.rb +1 -0
  164. data/lib/facet/functor.rb +1 -41
  165. data/lib/facet/gem.rb +1 -3
  166. data/lib/facet/gem/self/active.rb +1 -9
  167. data/lib/facet/gem/self/gempath.rb +1 -10
  168. data/lib/facet/gem/self/gemspec.rb +1 -10
  169. data/lib/facet/hash.rb +1 -40
  170. data/lib/facet/hash/alias.rb +1 -54
  171. data/lib/facet/hash/assert_has_keys.rb +1 -38
  172. data/lib/facet/hash/assert_has_only_keys.rb +1 -38
  173. data/lib/facet/hash/at.rb +1 -26
  174. data/lib/facet/hash/collate.rb +1 -53
  175. data/lib/facet/hash/delete_unless.rb +1 -15
  176. data/lib/facet/hash/each.rb +1 -61
  177. data/lib/facet/hash/each_with_index.rb +1 -35
  178. data/lib/facet/hash/each_with_key.rb +1 -32
  179. data/lib/facet/hash/graph.rb +1 -31
  180. data/lib/facet/hash/has_keys.rb +1 -37
  181. data/lib/facet/hash/has_only_keys.rb +1 -37
  182. data/lib/facet/hash/inverse.rb +1 -51
  183. data/lib/facet/hash/join.rb +1 -19
  184. data/lib/facet/hash/keys_to_iv.rb +1 -60
  185. data/lib/facet/hash/keys_to_s.rb +1 -80
  186. data/lib/facet/hash/keys_to_sym.rb +1 -91
  187. data/lib/facet/hash/op_fetch.rb +1 -146
  188. data/lib/facet/hash/op_lshift.rb +1 -28
  189. data/lib/facet/hash/op_store.rb +1 -2
  190. data/lib/facet/hash/rand_key.rb +1 -47
  191. data/lib/facet/hash/rand_pair.rb +1 -50
  192. data/lib/facet/hash/rand_value.rb +1 -60
  193. data/lib/facet/hash/replace_each.rb +1 -33
  194. data/lib/facet/hash/self/zipnew.rb +1 -37
  195. data/lib/facet/hash/shuffle.rb +1 -53
  196. data/lib/facet/hash/slice.rb +1 -33
  197. data/lib/facet/hash/stringify_keys.rb +1 -2
  198. data/lib/facet/hash/swap.rb +1 -36
  199. data/lib/facet/hash/swapkey.rb +1 -44
  200. data/lib/facet/hash/symoblize_keys.rb +1 -2
  201. data/lib/facet/hash/to_h.rb +1 -35
  202. data/lib/facet/hash/to_ostruct.rb +1 -40
  203. data/lib/facet/hash/to_ostruct_recurse.rb +1 -45
  204. data/lib/facet/hash/traverse.rb +1 -63
  205. data/lib/facet/hash/update_each.rb +1 -43
  206. data/lib/facet/hash/update_keys.rb +1 -31
  207. data/lib/facet/hash/update_values.rb +1 -32
  208. data/lib/facet/hash/variablize_keys.rb +1 -2
  209. data/lib/facet/hash/weave.rb +1 -88
  210. data/lib/facet/heap.rb +1 -0
  211. data/lib/facet/inflect.rb +1 -70
  212. data/lib/facet/inheritor.rb +1 -0
  213. data/lib/facet/integer.rb +1 -9
  214. data/lib/facet/integer/even.rb +1 -2
  215. data/lib/facet/integer/fac.rb +1 -2
  216. data/lib/facet/integer/fact.rb +1 -2
  217. data/lib/facet/integer/factorial.rb +1 -61
  218. data/lib/facet/integer/multiple.rb +1 -69
  219. data/lib/facet/integer/odd.rb +1 -2
  220. data/lib/facet/integer/ordinal.rb +1 -41
  221. data/lib/facet/integer/times_collect.rb +1 -39
  222. data/lib/facet/integer/times_map.rb +1 -2
  223. data/lib/facet/interval.rb +1 -0
  224. data/lib/facet/ioredirect.rb +1 -0
  225. data/lib/facet/kernel.rb +1 -68
  226. data/lib/facet/kernel/__DIR__.rb +1 -11
  227. data/lib/facet/kernel/__class__.rb +1 -31
  228. data/lib/facet/kernel/__meta__.rb +1 -28
  229. data/lib/facet/kernel/adhoc.rb +1 -11
  230. data/lib/facet/kernel/as.rb +1 -91
  231. data/lib/facet/kernel/assign_from.rb +1 -82
  232. data/lib/facet/kernel/assign_with.rb +1 -75
  233. data/lib/facet/kernel/autoreload.rb +1 -124
  234. data/lib/facet/kernel/autoreload_files.rb +1 -2
  235. data/lib/facet/kernel/autoreload_glob.rb +1 -3
  236. data/lib/facet/kernel/bool.rb +1 -77
  237. data/lib/facet/kernel/bug.rb +1 -39
  238. data/lib/facet/kernel/call_stack.rb +1 -59
  239. data/lib/facet/kernel/called.rb +1 -40
  240. data/lib/facet/kernel/complete.rb +1 -6
  241. data/lib/facet/kernel/constant.rb +1 -52
  242. data/lib/facet/kernel/copy.rb +1 -48
  243. data/lib/facet/kernel/deep_copy.rb +1 -49
  244. data/lib/facet/kernel/demo.rb +1 -46
  245. data/lib/facet/kernel/eigenclass.rb +1 -17
  246. data/lib/facet/kernel/false.rb +1 -2
  247. data/lib/facet/kernel/fn.rb +1 -33
  248. data/lib/facet/kernel/generate_method_name.rb +1 -39
  249. data/lib/facet/kernel/get_by_id.rb +1 -33
  250. data/lib/facet/kernel/here.rb +1 -34
  251. data/lib/facet/kernel/in.rb +1 -35
  252. data/lib/facet/kernel/instance_assign.rb +1 -25
  253. data/lib/facet/kernel/instvar.rb +1 -13
  254. data/lib/facet/kernel/is.rb +1 -5
  255. data/lib/facet/kernel/maybe.rb +1 -41
  256. data/lib/facet/kernel/me.rb +1 -17
  257. data/lib/facet/kernel/meta.rb +1 -2
  258. data/lib/facet/kernel/metaclass.rb +1 -42
  259. data/lib/facet/kernel/method.rb +1 -76
  260. data/lib/facet/kernel/method_name.rb +1 -49
  261. data/lib/facet/kernel/methods.rb +1 -79
  262. data/lib/facet/kernel/nack.rb +1 -12
  263. data/lib/facet/kernel/new.rb +1 -40
  264. data/lib/facet/kernel/object_class.rb +1 -31
  265. data/lib/facet/kernel/object_hexid.rb +1 -35
  266. data/lib/facet/kernel/op_esc.rb +1 -37
  267. data/lib/facet/kernel/own.rb +1 -17
  268. data/lib/facet/kernel/p.rb +1 -12
  269. data/lib/facet/kernel/require_all.rb +1 -44
  270. data/lib/facet/kernel/require_esc.rb +1 -42
  271. data/lib/facet/kernel/require_facet.rb +1 -41
  272. data/lib/facet/kernel/require_local.rb +1 -25
  273. data/lib/facet/kernel/resc.rb +1 -32
  274. data/lib/facet/kernel/returning.rb +1 -49
  275. data/lib/facet/kernel/send_as.rb +1 -34
  276. data/lib/facet/kernel/set_from.rb +1 -69
  277. data/lib/facet/kernel/set_with.rb +1 -74
  278. data/lib/facet/kernel/silence_warnings.rb +1 -2
  279. data/lib/facet/kernel/silently.rb +1 -41
  280. data/lib/facet/kernel/singleton.rb +1 -47
  281. data/lib/facet/kernel/superior.rb +1 -53
  282. data/lib/facet/kernel/supermethod.rb +1 -44
  283. data/lib/facet/kernel/this.rb +1 -33
  284. data/lib/facet/kernel/to_b.rb +1 -41
  285. data/lib/facet/kernel/to_bool.rb +1 -47
  286. data/lib/facet/kernel/true.rb +1 -2
  287. data/lib/facet/kernel/unuri.rb +1 -2
  288. data/lib/facet/kernel/uri.rb +1 -38
  289. data/lib/facet/kernel/val.rb +1 -52
  290. data/lib/facet/kernel/warn_with_line.rb +1 -30
  291. data/lib/facet/kernel/with_accessor.rb +1 -94
  292. data/lib/facet/kernel/with_reader.rb +1 -2
  293. data/lib/facet/kernel/with_writer.rb +1 -2
  294. data/lib/facet/lisp.rb +1 -0
  295. data/lib/facet/lisp_format.rb +1 -0
  296. data/lib/facet/logger.rb +1 -0
  297. data/lib/facet/logger/format.rb +1 -28
  298. data/lib/facet/logger/format_message.rb +1 -1
  299. data/lib/facet/lrucache.rb +1 -0
  300. data/lib/facet/matchdata.rb +1 -3
  301. data/lib/facet/matchdata/match.rb +1 -37
  302. data/lib/facet/matchdata/matchset.rb +1 -2
  303. data/lib/facet/matchdata/matchtree.rb +1 -62
  304. data/lib/facet/mathconstants.rb +1 -0
  305. data/lib/facet/methodprobe.rb +1 -0
  306. data/lib/facet/mock.rb +1 -0
  307. data/lib/facet/module.rb +1 -40
  308. data/lib/facet/module/abstract.rb +1 -50
  309. data/lib/facet/module/alias_module_function.rb +1 -57
  310. data/lib/facet/module/ancestor.rb +1 -38
  311. data/lib/facet/module/attr.rb +1 -23
  312. data/lib/facet/module/attr_setter.rb +1 -48
  313. data/lib/facet/module/attr_tester.rb +1 -56
  314. data/lib/facet/module/basename.rb +1 -39
  315. data/lib/facet/module/by_name.rb +1 -68
  316. data/lib/facet/module/cattr_accessor.rb +1 -141
  317. data/lib/facet/module/cattr_reader.rb +1 -2
  318. data/lib/facet/module/cattr_writer.rb +1 -2
  319. data/lib/facet/module/clone_removing.rb +1 -2
  320. data/lib/facet/module/clone_renaming.rb +1 -2
  321. data/lib/facet/module/clone_using.rb +1 -87
  322. data/lib/facet/module/dirname.rb +1 -42
  323. data/lib/facet/module/equate_on.rb +1 -70
  324. data/lib/facet/module/generate_instance_method_name.rb +1 -47
  325. data/lib/facet/module/include_as.rb +1 -102
  326. data/lib/facet/module/initializer.rb +1 -65
  327. data/lib/facet/module/instance_methods.rb +1 -186
  328. data/lib/facet/module/integrate.rb +1 -51
  329. data/lib/facet/module/is.rb +1 -34
  330. data/lib/facet/module/memoize.rb +1 -95
  331. data/lib/facet/module/modspace.rb +1 -43
  332. data/lib/facet/module/namespace.rb +1 -61
  333. data/lib/facet/module/nesting.rb +1 -45
  334. data/lib/facet/module/redef.rb +1 -31
  335. data/lib/facet/module/redefine_method.rb +1 -57
  336. data/lib/facet/module/redirect.rb +1 -30
  337. data/lib/facet/module/redirect_method.rb +1 -64
  338. data/lib/facet/module/remove.rb +1 -29
  339. data/lib/facet/module/rename.rb +1 -31
  340. data/lib/facet/module/rename_method.rb +1 -38
  341. data/lib/facet/module/revisal.rb +1 -49
  342. data/lib/facet/module/shadow_all.rb +1 -17
  343. data/lib/facet/module/shadow_method.rb +1 -42
  344. data/lib/facet/module/sort_on.rb +1 -73
  345. data/lib/facet/module/undef.rb +1 -29
  346. data/lib/facet/module/wrap.rb +1 -30
  347. data/lib/facet/module/wrap_method.rb +1 -48
  348. data/lib/facet/multipliers.rb +1 -0
  349. data/lib/facet/multiton.rb +1 -0
  350. data/lib/facet/nackclass.rb +1 -0
  351. data/lib/facet/nil_as_emptiness.rb +1 -34
  352. data/lib/facet/nilclass.rb +1 -7
  353. data/lib/facet/nilclass/empty.rb +1 -32
  354. data/lib/facet/nilclass/include.rb +1 -32
  355. data/lib/facet/nilclass/length.rb +1 -2
  356. data/lib/facet/nilclass/op_fetch.rb +1 -37
  357. data/lib/facet/nilclass/size.rb +1 -44
  358. data/lib/facet/nilclass/to_f.rb +1 -32
  359. data/lib/facet/nilclass/to_h.rb +1 -33
  360. data/lib/facet/nilcomparable.rb +1 -0
  361. data/lib/facet/nullclass.rb +1 -0
  362. data/lib/facet/numeric.rb +1 -5
  363. data/lib/facet/numeric/ceil_multiple.rb +1 -40
  364. data/lib/facet/numeric/pred.rb +1 -2
  365. data/lib/facet/numeric/succ.rb +1 -69
  366. data/lib/facet/numeric/to_b.rb +1 -38
  367. data/lib/facet/one.rb +1 -0
  368. data/lib/facet/openobject.rb +1 -0
  369. data/lib/facet/orderedhash.rb +1 -0
  370. data/lib/facet/ormsupport.rb +1 -0
  371. data/lib/facet/ostruct.rb +1 -0
  372. data/lib/facet/ostruct/__merge__.rb +1 -52
  373. data/lib/facet/ostruct/__table__.rb +1 -17
  374. data/lib/facet/ostruct/__update__.rb +1 -45
  375. data/lib/facet/ostruct/op_fetch.rb +1 -40
  376. data/lib/facet/ostruct/op_store.rb +1 -42
  377. data/lib/facet/ostruct/to_h.rb +1 -8
  378. data/lib/facet/overload.rb +1 -0
  379. data/lib/facet/paramix.rb +1 -0
  380. data/lib/facet/pathlist.rb +1 -0
  381. data/lib/facet/pathname.rb +1 -2
  382. data/lib/facet/pathname/ascend.rb +1 -22
  383. data/lib/facet/pathname/descend.rb +1 -20
  384. data/lib/facet/pool.rb +1 -0
  385. data/lib/facet/preinitialize.rb +1 -0
  386. data/lib/facet/proc.rb +1 -3
  387. data/lib/facet/proc/compose.rb +1 -62
  388. data/lib/facet/proc/op_mul.rb +1 -2
  389. data/lib/facet/proc/to_method.rb +1 -74
  390. data/lib/facet/progressbar.rb +1 -0
  391. data/lib/facet/promoteself.rb +1 -0
  392. data/lib/facet/quaternion.rb +1 -0
  393. data/lib/facet/random.rb +1 -21
  394. data/lib/facet/range.rb +1 -4
  395. data/lib/facet/range/to_r.rb +1 -32
  396. data/lib/facet/range/to_range.rb +1 -36
  397. data/lib/facet/range/umbrella.rb +1 -67
  398. data/lib/facet/range/within.rb +1 -44
  399. data/lib/facet/reference.rb +1 -0
  400. data/lib/facet/regexp.rb +1 -3
  401. data/lib/facet/regexp/arity.rb +1 -41
  402. data/lib/facet/regexp/to_re.rb +1 -38
  403. data/lib/facet/regexp/to_regexp.rb +1 -36
  404. data/lib/facet/rtals.rb +1 -0
  405. data/lib/facet/semaphore.rb +1 -0
  406. data/lib/facet/snapshot.rb +1 -0
  407. data/lib/facet/stateparser.rb +1 -0
  408. data/lib/facet/statichash.rb +1 -0
  409. data/lib/facet/string.rb +1 -91
  410. data/lib/facet/string/align_center.rb +1 -87
  411. data/lib/facet/string/align_left.rb +1 -2
  412. data/lib/facet/string/align_right.rb +1 -2
  413. data/lib/facet/string/at.rb +1 -8
  414. data/lib/facet/string/at_rand.rb +1 -65
  415. data/lib/facet/string/basename.rb +1 -48
  416. data/lib/facet/string/blank.rb +1 -36
  417. data/lib/facet/string/bracket.rb +1 -70
  418. data/lib/facet/string/brief.rb +1 -33
  419. data/lib/facet/string/bytes.rb +1 -19
  420. data/lib/facet/string/camelcase.rb +1 -58
  421. data/lib/facet/string/camelize.rb +1 -35
  422. data/lib/facet/string/capitalized.rb +1 -38
  423. data/lib/facet/string/chars.rb +1 -34
  424. data/lib/facet/string/cmp.rb +1 -43
  425. data/lib/facet/string/demodulize.rb +1 -40
  426. data/lib/facet/string/dequote.rb +1 -29
  427. data/lib/facet/string/downcase.rb +1 -37
  428. data/lib/facet/string/dresner.rb +1 -49
  429. data/lib/facet/string/each_char.rb +1 -35
  430. data/lib/facet/string/each_word.rb +1 -50
  431. data/lib/facet/string/ends_with.rb +1 -2
  432. data/lib/facet/string/first.rb +1 -94
  433. data/lib/facet/string/first_char.rb +1 -20
  434. data/lib/facet/string/fold.rb +1 -67
  435. data/lib/facet/string/format.rb +1 -17
  436. data/lib/facet/string/frequency.rb +1 -39
  437. data/lib/facet/string/humanize.rb +1 -31
  438. data/lib/facet/string/indent.rb +1 -68
  439. data/lib/facet/string/index_all.rb +1 -40
  440. data/lib/facet/string/last.rb +1 -94
  441. data/lib/facet/string/last_char.rb +1 -22
  442. data/lib/facet/string/line_wrap.rb +1 -77
  443. data/lib/facet/string/lines.rb +1 -33
  444. data/lib/facet/string/lowercase.rb +1 -32
  445. data/lib/facet/string/margin.rb +1 -138
  446. data/lib/facet/string/methodize.rb +1 -44
  447. data/lib/facet/string/modulize.rb +1 -44
  448. data/lib/facet/string/mscan.rb +1 -42
  449. data/lib/facet/string/natcmp.rb +1 -108
  450. data/lib/facet/string/nchar.rb +1 -45
  451. data/lib/facet/string/ordinal.rb +1 -16
  452. data/lib/facet/string/pathize.rb +1 -46
  453. data/lib/facet/string/plural.rb +1 -2
  454. data/lib/facet/string/pop.rb +1 -54
  455. data/lib/facet/string/probability.rb +1 -34
  456. data/lib/facet/string/pull.rb +1 -17
  457. data/lib/facet/string/push.rb +1 -44
  458. data/lib/facet/string/quote.rb +1 -68
  459. data/lib/facet/string/rand_byte.rb +1 -55
  460. data/lib/facet/string/rand_index.rb +1 -29
  461. data/lib/facet/string/range.rb +1 -37
  462. data/lib/facet/string/range_all.rb +1 -48
  463. data/lib/facet/string/range_of_line.rb +1 -42
  464. data/lib/facet/string/regesc.rb +1 -32
  465. data/lib/facet/string/self/format.rb +1 -17
  466. data/lib/facet/string/self/interpolate.rb +1 -31
  467. data/lib/facet/string/self/patterns.rb +1 -51
  468. data/lib/facet/string/self/rand_letter.rb +1 -34
  469. data/lib/facet/string/self/random.rb +1 -37
  470. data/lib/facet/string/shatter.rb +1 -45
  471. data/lib/facet/string/shell_escape.rb +1 -0
  472. data/lib/facet/string/shift.rb +1 -42
  473. data/lib/facet/string/shuffle.rb +1 -42
  474. data/lib/facet/string/similarity.rb +1 -108
  475. data/lib/facet/string/singular.rb +1 -117
  476. data/lib/facet/string/slap.rb +1 -44
  477. data/lib/facet/string/soundex.rb +1 -102
  478. data/lib/facet/string/starts_with.rb +1 -24
  479. data/lib/facet/string/succ.rb +1 -38
  480. data/lib/facet/string/tab.rb +1 -2
  481. data/lib/facet/string/tabto.rb +1 -2
  482. data/lib/facet/string/to_a.rb +1 -35
  483. data/lib/facet/string/to_arr.rb +1 -55
  484. data/lib/facet/string/to_b.rb +1 -64
  485. data/lib/facet/string/to_const.rb +1 -39
  486. data/lib/facet/string/to_date.rb +1 -35
  487. data/lib/facet/string/to_proc.rb +1 -54
  488. data/lib/facet/string/to_re.rb +1 -46
  489. data/lib/facet/string/to_rx.rb +1 -2
  490. data/lib/facet/string/to_time.rb +1 -34
  491. data/lib/facet/string/unbracket.rb +1 -46
  492. data/lib/facet/string/underscore.rb +1 -18
  493. data/lib/facet/string/unix_crypt.rb +1 -41
  494. data/lib/facet/string/unpack.rb +1 -45
  495. data/lib/facet/string/unshift.rb +1 -42
  496. data/lib/facet/string/upcase.rb +1 -45
  497. data/lib/facet/string/uppercase.rb +1 -2
  498. data/lib/facet/string/whitespace.rb +1 -27
  499. data/lib/facet/string/word_filter.rb +1 -61
  500. data/lib/facet/string/word_wrap.rb +1 -90
  501. data/lib/facet/string/words.rb +1 -45
  502. data/lib/facet/string_as_array.rb +1 -16
  503. data/lib/facet/symbol.rb +1 -13
  504. data/lib/facet/symbol/camelcase.rb +1 -42
  505. data/lib/facet/symbol/camelize.rb +1 -33
  506. data/lib/facet/symbol/capitalize.rb +1 -31
  507. data/lib/facet/symbol/capitalized.rb +1 -33
  508. data/lib/facet/symbol/downcase.rb +1 -36
  509. data/lib/facet/symbol/not.rb +1 -40
  510. data/lib/facet/symbol/pad.rb +1 -43
  511. data/lib/facet/symbol/succ.rb +1 -42
  512. data/lib/facet/symbol/to_const.rb +1 -40
  513. data/lib/facet/symbol/to_proc.rb +1 -45
  514. data/lib/facet/symbol/to_str.rb +1 -39
  515. data/lib/facet/symbol/underscore.rb +1 -32
  516. data/lib/facet/symbol/upcase.rb +1 -37
  517. data/lib/facet/syncarray.rb +1 -0
  518. data/lib/facet/synchash.rb +1 -0
  519. data/lib/facet/system.rb +1 -0
  520. data/lib/facet/tagiterator.rb +1 -0
  521. data/lib/facet/time.rb +1 -8
  522. data/lib/facet/time/change.rb +1 -51
  523. data/lib/facet/time/elapse.rb +1 -41
  524. data/lib/facet/time/self/days_extrema.rb +1 -22
  525. data/lib/facet/time/self/stamp.rb +1 -2
  526. data/lib/facet/time/stamp.rb +1 -51
  527. data/lib/facet/time/to_date.rb +1 -37
  528. data/lib/facet/time/to_s.rb +1 -33
  529. data/lib/facet/time/to_time.rb +1 -36
  530. data/lib/facet/timer.rb +1 -0
  531. data/lib/facet/times.rb +1 -0
  532. data/lib/facet/tracepoint.rb +1 -0
  533. data/lib/facet/tuple.rb +1 -0
  534. data/lib/facet/typecast.rb +1 -0
  535. data/lib/facet/unboundmethod.rb +1 -1
  536. data/lib/facet/unboundmethod/name.rb +1 -8
  537. data/lib/facet/uninheritable.rb +1 -0
  538. data/lib/facet/units.rb +1 -0
  539. data/lib/facet/yamlstruct.rb +1 -0
  540. data/lib/facets.rb +77 -45
  541. data/lib/facets/core/array.rb +34 -0
  542. data/lib/facets/core/array/at_rand.rb +52 -0
  543. data/lib/facets/core/array/body.rb +2 -0
  544. data/lib/facets/core/array/delete_unless.rb +35 -0
  545. data/lib/facets/core/array/delete_values.rb +38 -0
  546. data/lib/facets/core/array/delete_values_at.rb +57 -0
  547. data/lib/facets/core/array/each_with_key.rb +9 -0
  548. data/lib/facets/core/array/first.rb +84 -0
  549. data/lib/facets/core/array/foot.rb +2 -0
  550. data/lib/facets/core/array/head.rb +80 -0
  551. data/lib/facets/core/array/last.rb +2 -0
  552. data/lib/facets/core/array/last_index.rb +35 -0
  553. data/lib/facets/core/array/merge.rb +40 -0
  554. data/lib/facets/core/array/mid.rb +50 -0
  555. data/lib/facets/core/array/middle.rb +45 -0
  556. data/lib/facets/core/array/op_fetch.rb +40 -0
  557. data/lib/facets/core/array/op_mod.rb +16 -0
  558. data/lib/facets/core/array/op_store.rb +47 -0
  559. data/lib/facets/core/array/pick.rb +68 -0
  560. data/lib/facets/core/array/pos.rb +39 -0
  561. data/lib/facets/core/array/pull.rb +37 -0
  562. data/lib/facets/core/array/rand_index.rb +30 -0
  563. data/lib/facets/core/array/rand_subset.rb +56 -0
  564. data/lib/facets/core/array/range.rb +47 -0
  565. data/lib/facets/core/array/rotate.rb +67 -0
  566. data/lib/facets/core/array/select.rb +37 -0
  567. data/lib/facets/core/array/shuffle.rb +66 -0
  568. data/lib/facets/core/array/slap.rb +37 -0
  569. data/lib/facets/core/array/store.rb +7 -0
  570. data/lib/facets/core/array/tail.rb +2 -0
  571. data/lib/facets/core/array/thru.rb +38 -0
  572. data/lib/facets/core/array/to_b.rb +31 -0
  573. data/lib/facets/core/array/to_h.rb +57 -0
  574. data/lib/facets/core/array/to_hash.rb +46 -0
  575. data/lib/facets/core/array/unzip.rb +20 -0
  576. data/lib/facets/core/binding.rb +14 -0
  577. data/lib/facets/core/binding/__DIR__.rb +2 -0
  578. data/lib/facets/core/binding/__FILE__.rb +2 -0
  579. data/lib/facets/core/binding/__LINE__.rb +58 -0
  580. data/lib/facets/core/binding/call_stack.rb +42 -0
  581. data/lib/facets/core/binding/called.rb +42 -0
  582. data/lib/facets/core/binding/caller.rb +42 -0
  583. data/lib/facets/core/binding/defined.rb +41 -0
  584. data/lib/facets/core/binding/eval.rb +42 -0
  585. data/lib/facets/core/binding/local_variables.rb +45 -0
  586. data/lib/facets/core/binding/method_name.rb +48 -0
  587. data/lib/facets/core/binding/op_fetch.rb +45 -0
  588. data/lib/facets/core/binding/op_store.rb +46 -0
  589. data/lib/facets/core/binding/self.rb +41 -0
  590. data/lib/facets/core/binding/self/of_caller.rb +122 -0
  591. data/lib/facets/core/class.rb +7 -0
  592. data/lib/facets/core/class/by_name.rb +1 -0
  593. data/lib/facets/core/class/descendents.rb +44 -0
  594. data/lib/facets/core/class/method_name.rb +33 -0
  595. data/lib/facets/core/class/remove_descendents.rb +46 -0
  596. data/lib/facets/core/class/remove_subclasses.rb +2 -0
  597. data/lib/facets/core/class/subclasses.rb +2 -0
  598. data/lib/facets/core/class/unix_path.rb +34 -0
  599. data/lib/facets/core/comparable.rb +5 -0
  600. data/lib/facets/core/comparable/at_least.rb +53 -0
  601. data/lib/facets/core/comparable/at_most.rb +2 -0
  602. data/lib/facets/core/comparable/cap.rb +2 -0
  603. data/lib/facets/core/comparable/clip.rb +72 -0
  604. data/lib/facets/core/comparable/cmp.rb +38 -0
  605. data/lib/facets/core/continuation.rb +1 -0
  606. data/lib/facets/core/continuation/self/create.rb +71 -0
  607. data/lib/facets/core/date.rb +0 -0
  608. data/lib/facets/core/date/days_in_month.rb +42 -0
  609. data/lib/facets/core/date/days_of_month.rb +34 -0
  610. data/lib/facets/core/date/stamp.rb +52 -0
  611. data/lib/facets/core/date/to_date.rb +36 -0
  612. data/lib/facets/core/date/to_s.rb +33 -0
  613. data/lib/facets/core/date/to_time.rb +36 -0
  614. data/lib/facets/core/dir.rb +4 -0
  615. data/lib/facets/core/dir/self/ancestor.rb +33 -0
  616. data/lib/facets/core/dir/self/ascend.rb +56 -0
  617. data/lib/facets/core/dir/self/ls_r.rb +76 -0
  618. data/lib/facets/core/dir/self/recurse.rb +2 -0
  619. data/lib/facets/core/enumerable.rb +39 -0
  620. data/lib/facets/core/enumerable/collect_with_counter.rb +2 -0
  621. data/lib/facets/core/enumerable/collect_with_index.rb +51 -0
  622. data/lib/facets/core/enumerable/commonality.rb +63 -0
  623. data/lib/facets/core/enumerable/compact_collect.rb +50 -0
  624. data/lib/facets/core/enumerable/compact_map.rb +2 -0
  625. data/lib/facets/core/enumerable/cross.rb +44 -0
  626. data/lib/facets/core/enumerable/each_by.rb +2 -0
  627. data/lib/facets/core/enumerable/each_combination.rb +59 -0
  628. data/lib/facets/core/enumerable/each_pair.rb +50 -0
  629. data/lib/facets/core/enumerable/each_permutation.rb +2 -0
  630. data/lib/facets/core/enumerable/each_slice.rb +131 -0
  631. data/lib/facets/core/enumerable/each_unique_pair.rb +66 -0
  632. data/lib/facets/core/enumerable/each_with_counter.rb +8 -0
  633. data/lib/facets/core/enumerable/elementwise.rb +2 -0
  634. data/lib/facets/core/enumerable/entropy.rb +52 -0
  635. data/lib/facets/core/enumerable/every.rb +65 -0
  636. data/lib/facets/core/enumerable/ew.rb +64 -0
  637. data/lib/facets/core/enumerable/filter_collect.rb +58 -0
  638. data/lib/facets/core/enumerable/filter_map.rb +2 -0
  639. data/lib/facets/core/enumerable/find_collisions.rb +41 -0
  640. data/lib/facets/core/enumerable/frequency.rb +39 -0
  641. data/lib/facets/core/enumerable/graph.rb +59 -0
  642. data/lib/facets/core/enumerable/ideal_entropy.rb +49 -0
  643. data/lib/facets/core/enumerable/map_with_counter.rb +2 -0
  644. data/lib/facets/core/enumerable/map_with_index.rb +2 -0
  645. data/lib/facets/core/enumerable/none.rb +56 -0
  646. data/lib/facets/core/enumerable/nonuniq.rb +39 -0
  647. data/lib/facets/core/enumerable/occur.rb +62 -0
  648. data/lib/facets/core/enumerable/one.rb +65 -0
  649. data/lib/facets/core/enumerable/op_pow.rb +38 -0
  650. data/lib/facets/core/enumerable/partition_by.rb +55 -0
  651. data/lib/facets/core/enumerable/permute.rb +135 -0
  652. data/lib/facets/core/enumerable/probability.rb +59 -0
  653. data/lib/facets/core/enumerable/project.rb +11 -0
  654. data/lib/facets/core/enumerable/self/combinations.rb +68 -0
  655. data/lib/facets/core/enumerable/self/cross.rb +79 -0
  656. data/lib/facets/core/enumerable/to_h.rb +50 -0
  657. data/lib/facets/core/enumerable/uniq_by.rb +39 -0
  658. data/lib/facets/core/enumerable/where.rb +12 -0
  659. data/lib/facets/core/file.rb +5 -0
  660. data/lib/facets/core/file/self/create.rb +52 -0
  661. data/lib/facets/core/file/self/open_as_string.rb +81 -0
  662. data/lib/facets/core/file/self/read_list.rb +47 -0
  663. data/lib/facets/core/file/self/sanitize.rb +50 -0
  664. data/lib/facets/core/file/self/split_all.rb +36 -0
  665. data/lib/facets/core/fileutils.rb +0 -0
  666. data/lib/facets/core/fileutils/head.rb +2 -0
  667. data/lib/facets/core/fileutils/safe_ln.rb +38 -0
  668. data/lib/facets/core/fileutils/slice.rb +152 -0
  669. data/lib/facets/core/fileutils/split_all.rb +29 -0
  670. data/lib/facets/core/fileutils/tail.rb +2 -0
  671. data/lib/facets/core/fileutils/wc.rb +128 -0
  672. data/lib/facets/core/fileutils/whereis.rb +76 -0
  673. data/lib/facets/core/fileutils/which.rb +117 -0
  674. data/lib/facets/core/float.rb +3 -0
  675. data/lib/facets/core/float/approx.rb +42 -0
  676. data/lib/facets/core/float/round_at.rb +72 -0
  677. data/lib/facets/core/float/round_to.rb +73 -0
  678. data/lib/facets/core/gem.rb +3 -0
  679. data/lib/facets/core/gem/self/active.rb +9 -0
  680. data/lib/facets/core/gem/self/gempath.rb +10 -0
  681. data/lib/facets/core/gem/self/gemspec.rb +10 -0
  682. data/lib/facets/core/hash.rb +40 -0
  683. data/lib/facets/core/hash/alias.rb +54 -0
  684. data/lib/facets/core/hash/assert_has_keys.rb +38 -0
  685. data/lib/facets/core/hash/assert_has_only_keys.rb +38 -0
  686. data/lib/facets/core/hash/at.rb +26 -0
  687. data/lib/facets/core/hash/collate.rb +53 -0
  688. data/lib/facets/core/hash/delete_unless.rb +15 -0
  689. data/lib/facets/core/hash/each.rb +61 -0
  690. data/lib/facets/core/hash/each_with_index.rb +35 -0
  691. data/lib/facets/core/hash/each_with_key.rb +32 -0
  692. data/lib/facets/core/hash/graph.rb +31 -0
  693. data/lib/facets/core/hash/has_keys.rb +37 -0
  694. data/lib/facets/core/hash/has_only_keys.rb +37 -0
  695. data/lib/facets/core/hash/inverse.rb +51 -0
  696. data/lib/facets/core/hash/join.rb +19 -0
  697. data/lib/facets/core/hash/keys_to_iv.rb +60 -0
  698. data/lib/facets/core/hash/keys_to_s.rb +80 -0
  699. data/lib/facets/core/hash/keys_to_sym.rb +91 -0
  700. data/lib/facets/core/hash/op_fetch.rb +146 -0
  701. data/lib/facets/core/hash/op_lshift.rb +28 -0
  702. data/lib/facets/core/hash/op_store.rb +2 -0
  703. data/lib/facets/core/hash/rand_key.rb +47 -0
  704. data/lib/facets/core/hash/rand_pair.rb +50 -0
  705. data/lib/facets/core/hash/rand_value.rb +60 -0
  706. data/lib/facets/core/hash/replace_each.rb +33 -0
  707. data/lib/facets/core/hash/self/zipnew.rb +37 -0
  708. data/lib/facets/core/hash/shuffle.rb +53 -0
  709. data/lib/facets/core/hash/slice.rb +33 -0
  710. data/lib/facets/core/hash/stringify_keys.rb +2 -0
  711. data/lib/facets/core/hash/swap.rb +36 -0
  712. data/lib/facets/core/hash/swapkey.rb +44 -0
  713. data/lib/facets/core/hash/symoblize_keys.rb +2 -0
  714. data/lib/facets/core/hash/to_h.rb +35 -0
  715. data/lib/facets/core/hash/to_ostruct.rb +40 -0
  716. data/lib/facets/core/hash/to_ostruct_recurse.rb +45 -0
  717. data/lib/facets/core/hash/traverse.rb +63 -0
  718. data/lib/facets/core/hash/update_each.rb +43 -0
  719. data/lib/facets/core/hash/update_keys.rb +31 -0
  720. data/lib/facets/core/hash/update_values.rb +32 -0
  721. data/lib/facets/core/hash/variablize_keys.rb +2 -0
  722. data/lib/facets/core/hash/weave.rb +88 -0
  723. data/lib/facets/core/inflect.rb +70 -0
  724. data/lib/facets/core/integer.rb +9 -0
  725. data/lib/facets/core/integer/even.rb +2 -0
  726. data/lib/facets/core/integer/fac.rb +2 -0
  727. data/lib/facets/core/integer/fact.rb +2 -0
  728. data/lib/facets/core/integer/factorial.rb +61 -0
  729. data/lib/facets/core/integer/multiple.rb +69 -0
  730. data/lib/facets/core/integer/odd.rb +2 -0
  731. data/lib/facets/core/integer/ordinal.rb +41 -0
  732. data/lib/facets/core/integer/times_collect.rb +39 -0
  733. data/lib/facets/core/integer/times_map.rb +2 -0
  734. data/lib/facets/core/kernel.rb +68 -0
  735. data/lib/facets/core/kernel/__DIR__.rb +11 -0
  736. data/lib/facets/core/kernel/__class__.rb +31 -0
  737. data/lib/facets/core/kernel/__meta__.rb +28 -0
  738. data/lib/facets/core/kernel/adhoc.rb +11 -0
  739. data/lib/facets/core/kernel/as.rb +87 -0
  740. data/lib/facets/core/kernel/assign_from.rb +82 -0
  741. data/lib/facets/core/kernel/assign_with.rb +75 -0
  742. data/lib/facets/core/kernel/autoreload.rb +124 -0
  743. data/lib/facets/core/kernel/autoreload_files.rb +2 -0
  744. data/lib/facets/core/kernel/autoreload_glob.rb +3 -0
  745. data/lib/facets/core/kernel/bool.rb +77 -0
  746. data/lib/facets/core/kernel/bug.rb +39 -0
  747. data/lib/facets/core/kernel/call_stack.rb +59 -0
  748. data/lib/facets/core/kernel/called.rb +40 -0
  749. data/lib/facets/core/kernel/complete.rb +6 -0
  750. data/lib/facets/core/kernel/constant.rb +52 -0
  751. data/lib/facets/core/kernel/copy.rb +48 -0
  752. data/lib/facets/core/kernel/deep_copy.rb +49 -0
  753. data/lib/facets/core/kernel/demo.rb +46 -0
  754. data/lib/facets/core/kernel/eigenclass.rb +17 -0
  755. data/lib/facets/core/kernel/false.rb +2 -0
  756. data/lib/facets/core/kernel/fn.rb +33 -0
  757. data/lib/facets/core/kernel/generate_method_name.rb +39 -0
  758. data/lib/facets/core/kernel/get_by_id.rb +33 -0
  759. data/lib/facets/core/kernel/here.rb +34 -0
  760. data/lib/facets/core/kernel/in.rb +35 -0
  761. data/lib/facets/core/kernel/instance_assign.rb +25 -0
  762. data/lib/facets/core/kernel/instvar.rb +13 -0
  763. data/lib/facets/core/kernel/is.rb +7 -0
  764. data/lib/facets/core/kernel/maybe.rb +41 -0
  765. data/lib/facets/core/kernel/me.rb +17 -0
  766. data/lib/facets/core/kernel/meta.rb +2 -0
  767. data/lib/facets/core/kernel/metaclass.rb +42 -0
  768. data/lib/facets/core/kernel/method.rb +76 -0
  769. data/lib/facets/core/kernel/method_name.rb +49 -0
  770. data/lib/facets/core/kernel/methods.rb +79 -0
  771. data/lib/facets/core/kernel/nack.rb +12 -0
  772. data/lib/facets/core/kernel/new.rb +40 -0
  773. data/lib/facets/core/kernel/object_class.rb +31 -0
  774. data/lib/facets/core/kernel/object_hexid.rb +35 -0
  775. data/lib/facets/core/kernel/op_esc.rb +37 -0
  776. data/lib/facets/core/kernel/own.rb +17 -0
  777. data/lib/facets/core/kernel/p.rb +12 -0
  778. data/lib/facets/core/kernel/require_all.rb +44 -0
  779. data/lib/facets/core/kernel/require_esc.rb +42 -0
  780. data/lib/facets/core/kernel/require_facet.rb +41 -0
  781. data/lib/facets/core/kernel/require_local.rb +25 -0
  782. data/lib/facets/core/kernel/resc.rb +32 -0
  783. data/lib/facets/core/kernel/returning.rb +49 -0
  784. data/lib/facets/core/kernel/send_as.rb +34 -0
  785. data/lib/facets/core/kernel/set_from.rb +69 -0
  786. data/lib/facets/core/kernel/set_with.rb +74 -0
  787. data/lib/facets/core/kernel/silence_warnings.rb +2 -0
  788. data/lib/facets/core/kernel/silently.rb +41 -0
  789. data/lib/facets/core/kernel/singleton.rb +47 -0
  790. data/lib/facets/core/kernel/superior.rb +53 -0
  791. data/lib/facets/core/kernel/supermethod.rb +44 -0
  792. data/lib/facets/core/kernel/this.rb +33 -0
  793. data/lib/facets/core/kernel/to_b.rb +41 -0
  794. data/lib/facets/core/kernel/to_bool.rb +47 -0
  795. data/lib/facets/core/kernel/true.rb +2 -0
  796. data/lib/facets/core/kernel/unuri.rb +2 -0
  797. data/lib/facets/core/kernel/uri.rb +38 -0
  798. data/lib/facets/core/kernel/val.rb +52 -0
  799. data/lib/facets/core/kernel/warn_with_line.rb +30 -0
  800. data/lib/facets/core/kernel/with_accessor.rb +94 -0
  801. data/lib/facets/core/kernel/with_reader.rb +2 -0
  802. data/lib/facets/core/kernel/with_writer.rb +2 -0
  803. data/lib/facets/core/logger.rb +0 -0
  804. data/lib/facets/core/logger/format.rb +28 -0
  805. data/lib/facets/core/logger/format_message.rb +1 -0
  806. data/lib/facets/core/matchdata.rb +3 -0
  807. data/lib/facets/core/matchdata/match.rb +37 -0
  808. data/lib/facets/core/matchdata/matchset.rb +2 -0
  809. data/lib/facets/core/matchdata/matchtree.rb +62 -0
  810. data/lib/facets/core/module.rb +40 -0
  811. data/lib/facets/core/module/abstract.rb +50 -0
  812. data/lib/facets/core/module/alias_module_function.rb +57 -0
  813. data/lib/facets/core/module/ancestor.rb +38 -0
  814. data/lib/facets/core/module/attr.rb +23 -0
  815. data/lib/facets/core/module/attr_setter.rb +48 -0
  816. data/lib/facets/core/module/attr_tester.rb +56 -0
  817. data/lib/facets/core/module/basename.rb +39 -0
  818. data/lib/facets/core/module/by_name.rb +68 -0
  819. data/lib/facets/core/module/cattr_accessor.rb +141 -0
  820. data/lib/facets/core/module/cattr_reader.rb +2 -0
  821. data/lib/facets/core/module/cattr_writer.rb +2 -0
  822. data/lib/facets/core/module/clone_removing.rb +2 -0
  823. data/lib/facets/core/module/clone_renaming.rb +2 -0
  824. data/lib/facets/core/module/clone_using.rb +87 -0
  825. data/lib/facets/core/module/dirname.rb +42 -0
  826. data/lib/facets/core/module/equate_on.rb +70 -0
  827. data/lib/facets/core/module/generate_instance_method_name.rb +47 -0
  828. data/lib/facets/core/module/include_as.rb +102 -0
  829. data/lib/facets/core/module/initializer.rb +65 -0
  830. data/lib/facets/core/module/instance_methods.rb +186 -0
  831. data/lib/facets/core/module/integrate.rb +51 -0
  832. data/lib/facets/core/module/is.rb +35 -0
  833. data/lib/facets/core/module/memoize.rb +95 -0
  834. data/lib/facets/core/module/modspace.rb +43 -0
  835. data/lib/facets/core/module/namespace.rb +61 -0
  836. data/lib/facets/core/module/nesting.rb +45 -0
  837. data/lib/facets/core/module/redef.rb +31 -0
  838. data/lib/facets/core/module/redefine_method.rb +57 -0
  839. data/lib/facets/core/module/redirect.rb +30 -0
  840. data/lib/facets/core/module/redirect_method.rb +64 -0
  841. data/lib/facets/core/module/remove.rb +29 -0
  842. data/lib/facets/core/module/rename.rb +31 -0
  843. data/lib/facets/core/module/rename_method.rb +38 -0
  844. data/lib/facets/core/module/revisal.rb +49 -0
  845. data/lib/facets/core/module/shadow_all.rb +17 -0
  846. data/lib/facets/core/module/shadow_method.rb +42 -0
  847. data/lib/facets/core/module/sort_on.rb +73 -0
  848. data/lib/facets/core/module/undef.rb +29 -0
  849. data/lib/facets/core/module/wrap.rb +30 -0
  850. data/lib/facets/core/module/wrap_method.rb +48 -0
  851. data/lib/facets/core/nil_as_emptiness.rb +34 -0
  852. data/lib/facets/core/nilclass.rb +7 -0
  853. data/lib/facets/core/nilclass/empty.rb +32 -0
  854. data/lib/facets/core/nilclass/include.rb +32 -0
  855. data/lib/facets/core/nilclass/length.rb +2 -0
  856. data/lib/facets/core/nilclass/op_fetch.rb +37 -0
  857. data/lib/facets/core/nilclass/size.rb +44 -0
  858. data/lib/facets/core/nilclass/to_f.rb +32 -0
  859. data/lib/facets/core/nilclass/to_h.rb +33 -0
  860. data/lib/facets/core/numeric.rb +5 -0
  861. data/lib/facets/core/numeric/ceil_multiple.rb +40 -0
  862. data/lib/facets/core/numeric/pred.rb +2 -0
  863. data/lib/facets/core/numeric/succ.rb +69 -0
  864. data/lib/facets/core/numeric/to_b.rb +38 -0
  865. data/lib/facets/core/ostruct.rb +0 -0
  866. data/lib/facets/core/ostruct/__merge__.rb +52 -0
  867. data/lib/facets/core/ostruct/__table__.rb +17 -0
  868. data/lib/facets/core/ostruct/__update__.rb +45 -0
  869. data/lib/facets/core/ostruct/op_fetch.rb +40 -0
  870. data/lib/facets/core/ostruct/op_store.rb +42 -0
  871. data/lib/facets/core/ostruct/to_h.rb +8 -0
  872. data/lib/facets/core/pathname.rb +2 -0
  873. data/lib/facets/core/pathname/ascend.rb +22 -0
  874. data/lib/facets/core/pathname/descend.rb +20 -0
  875. data/lib/facets/core/proc.rb +3 -0
  876. data/lib/facets/core/proc/compose.rb +62 -0
  877. data/lib/facets/core/proc/op_mul.rb +2 -0
  878. data/lib/facets/core/proc/to_method.rb +74 -0
  879. data/lib/facets/core/random.rb +21 -0
  880. data/lib/facets/core/range.rb +4 -0
  881. data/lib/facets/core/range/to_r.rb +32 -0
  882. data/lib/facets/core/range/to_range.rb +36 -0
  883. data/lib/facets/core/range/umbrella.rb +67 -0
  884. data/lib/facets/core/range/within.rb +44 -0
  885. data/lib/facets/core/regexp.rb +3 -0
  886. data/lib/facets/core/regexp/arity.rb +41 -0
  887. data/lib/facets/core/regexp/to_re.rb +38 -0
  888. data/lib/facets/core/regexp/to_regexp.rb +36 -0
  889. data/lib/facets/core/string.rb +92 -0
  890. data/lib/facets/core/string/align_center.rb +87 -0
  891. data/lib/facets/core/string/align_left.rb +2 -0
  892. data/lib/facets/core/string/align_right.rb +2 -0
  893. data/lib/facets/core/string/at.rb +8 -0
  894. data/lib/facets/core/string/at_rand.rb +65 -0
  895. data/lib/facets/core/string/basename.rb +48 -0
  896. data/lib/facets/core/string/blank.rb +36 -0
  897. data/lib/facets/core/string/bracket.rb +70 -0
  898. data/lib/facets/core/string/brief.rb +33 -0
  899. data/lib/facets/core/string/bytes.rb +19 -0
  900. data/lib/facets/core/string/camelcase.rb +58 -0
  901. data/lib/facets/core/string/camelize.rb +35 -0
  902. data/lib/facets/core/string/capitalized.rb +38 -0
  903. data/lib/facets/core/string/chars.rb +34 -0
  904. data/lib/facets/core/string/cmp.rb +43 -0
  905. data/lib/facets/core/string/demodulize.rb +40 -0
  906. data/lib/facets/core/string/dequote.rb +29 -0
  907. data/lib/facets/core/string/downcase.rb +37 -0
  908. data/lib/facets/core/string/dresner.rb +49 -0
  909. data/lib/facets/core/string/each_char.rb +35 -0
  910. data/lib/facets/core/string/each_word.rb +50 -0
  911. data/lib/facets/core/string/ends_with.rb +2 -0
  912. data/lib/facets/core/string/first.rb +94 -0
  913. data/lib/facets/core/string/first_char.rb +20 -0
  914. data/lib/facets/core/string/fold.rb +67 -0
  915. data/lib/facets/core/string/format.rb +17 -0
  916. data/lib/facets/core/string/frequency.rb +39 -0
  917. data/lib/facets/core/string/humanize.rb +31 -0
  918. data/lib/facets/core/string/indent.rb +68 -0
  919. data/lib/facets/core/string/index_all.rb +40 -0
  920. data/lib/facets/core/string/last.rb +94 -0
  921. data/lib/facets/core/string/last_char.rb +22 -0
  922. data/lib/facets/core/string/line_wrap.rb +77 -0
  923. data/lib/facets/core/string/lines.rb +33 -0
  924. data/lib/facets/core/string/lowercase.rb +32 -0
  925. data/lib/facets/core/string/margin.rb +138 -0
  926. data/lib/facets/core/string/methodize.rb +44 -0
  927. data/lib/facets/core/string/modulize.rb +44 -0
  928. data/lib/facets/core/string/mscan.rb +42 -0
  929. data/lib/facets/core/string/natcmp.rb +108 -0
  930. data/lib/facets/core/string/nchar.rb +45 -0
  931. data/lib/facets/core/string/ordinal.rb +16 -0
  932. data/lib/facets/core/string/pathize.rb +46 -0
  933. data/lib/facets/core/string/plural.rb +2 -0
  934. data/lib/facets/core/string/pop.rb +54 -0
  935. data/lib/facets/core/string/probability.rb +34 -0
  936. data/lib/facets/core/string/pull.rb +17 -0
  937. data/lib/facets/core/string/push.rb +44 -0
  938. data/lib/facets/core/string/quote.rb +68 -0
  939. data/lib/facets/core/string/rand_byte.rb +55 -0
  940. data/lib/facets/core/string/rand_index.rb +29 -0
  941. data/lib/facets/core/string/range.rb +37 -0
  942. data/lib/facets/core/string/range_all.rb +48 -0
  943. data/lib/facets/core/string/range_of_line.rb +42 -0
  944. data/lib/facets/core/string/regesc.rb +32 -0
  945. data/lib/facets/core/string/self/format.rb +17 -0
  946. data/lib/facets/core/string/self/interpolate.rb +31 -0
  947. data/lib/facets/core/string/self/patterns.rb +51 -0
  948. data/lib/facets/core/string/self/rand_letter.rb +34 -0
  949. data/lib/facets/core/string/self/random.rb +37 -0
  950. data/lib/facets/core/string/shatter.rb +45 -0
  951. data/lib/facets/core/string/shell_escape.rb +11 -0
  952. data/lib/facets/core/string/shift.rb +42 -0
  953. data/lib/facets/core/string/shuffle.rb +42 -0
  954. data/lib/facets/core/string/similarity.rb +108 -0
  955. data/lib/facets/core/string/singular.rb +117 -0
  956. data/lib/facets/core/string/slap.rb +44 -0
  957. data/lib/facets/core/string/soundex.rb +102 -0
  958. data/lib/facets/core/string/starts_with.rb +24 -0
  959. data/lib/facets/core/string/succ.rb +38 -0
  960. data/lib/facets/core/string/tab.rb +2 -0
  961. data/lib/facets/core/string/tabto.rb +2 -0
  962. data/lib/facets/core/string/to_a.rb +35 -0
  963. data/lib/facets/core/string/to_arr.rb +55 -0
  964. data/lib/facets/core/string/to_b.rb +64 -0
  965. data/lib/facets/core/string/to_const.rb +39 -0
  966. data/lib/facets/core/string/to_date.rb +35 -0
  967. data/lib/facets/core/string/to_proc.rb +54 -0
  968. data/lib/facets/core/string/to_re.rb +46 -0
  969. data/lib/facets/core/string/to_rx.rb +2 -0
  970. data/lib/facets/core/string/to_time.rb +34 -0
  971. data/lib/facets/core/string/unbracket.rb +46 -0
  972. data/lib/facets/core/string/underscore.rb +18 -0
  973. data/lib/facets/core/string/unix_crypt.rb +41 -0
  974. data/lib/facets/core/string/unpack.rb +45 -0
  975. data/lib/facets/core/string/unshift.rb +42 -0
  976. data/lib/facets/core/string/upcase.rb +45 -0
  977. data/lib/facets/core/string/uppercase.rb +2 -0
  978. data/lib/facets/core/string/whitespace.rb +27 -0
  979. data/lib/facets/core/string/word_filter.rb +61 -0
  980. data/lib/facets/core/string/word_wrap.rb +90 -0
  981. data/lib/facets/core/string/words.rb +45 -0
  982. data/lib/facets/core/string_as_array.rb +16 -0
  983. data/lib/facets/core/symbol.rb +13 -0
  984. data/lib/facets/core/symbol/camelcase.rb +42 -0
  985. data/lib/facets/core/symbol/camelize.rb +33 -0
  986. data/lib/facets/core/symbol/capitalize.rb +31 -0
  987. data/lib/facets/core/symbol/capitalized.rb +33 -0
  988. data/lib/facets/core/symbol/downcase.rb +36 -0
  989. data/lib/facets/core/symbol/not.rb +40 -0
  990. data/lib/facets/core/symbol/pad.rb +43 -0
  991. data/lib/facets/core/symbol/succ.rb +42 -0
  992. data/lib/facets/core/symbol/to_const.rb +40 -0
  993. data/lib/facets/core/symbol/to_proc.rb +45 -0
  994. data/lib/facets/core/symbol/to_str.rb +39 -0
  995. data/lib/facets/core/symbol/underscore.rb +32 -0
  996. data/lib/facets/core/symbol/upcase.rb +37 -0
  997. data/lib/facets/core/time.rb +8 -0
  998. data/lib/facets/core/time/change.rb +51 -0
  999. data/lib/facets/core/time/elapse.rb +41 -0
  1000. data/lib/facets/core/time/self/days_extrema.rb +22 -0
  1001. data/lib/facets/core/time/self/stamp.rb +2 -0
  1002. data/lib/facets/core/time/stamp.rb +51 -0
  1003. data/lib/facets/core/time/to_date.rb +37 -0
  1004. data/lib/facets/core/time/to_s.rb +33 -0
  1005. data/lib/facets/core/time/to_time.rb +36 -0
  1006. data/lib/facets/core/unboundmethod.rb +1 -0
  1007. data/lib/facets/core/unboundmethod/name.rb +8 -0
  1008. data/lib/facets/more/annotation.rb +580 -0
  1009. data/lib/facets/more/ansicode.rb +311 -0
  1010. data/lib/facets/more/aspects.rb +230 -0
  1011. data/lib/facets/more/association.rb +156 -0
  1012. data/lib/facets/more/basicobject.rb +135 -0
  1013. data/lib/facets/more/bbcode.rb +388 -0
  1014. data/lib/facets/more/binaryreader.rb +246 -0
  1015. data/lib/facets/more/bitmask.rb +112 -0
  1016. data/lib/facets/more/blankslate.rb +3 -0
  1017. data/lib/facets/more/bytes.rb +212 -0
  1018. data/lib/facets/more/classinherit.rb +216 -0
  1019. data/lib/facets/more/classmethods.rb +219 -0
  1020. data/lib/facets/more/cloneable.rb +55 -0
  1021. data/lib/facets/more/consoleapp.rb +123 -0
  1022. data/lib/facets/more/coroutine.rb +172 -0
  1023. data/lib/facets/more/crypt.rb +180 -0
  1024. data/lib/facets/more/dictionary.rb +436 -0
  1025. data/lib/facets/more/downloader.rb +272 -0
  1026. data/lib/facets/more/enumerablepass.rb +285 -0
  1027. data/lib/facets/more/expirable.rb +87 -0
  1028. data/lib/facets/more/filelist.rb +486 -0
  1029. data/lib/facets/more/floatstring.rb +179 -0
  1030. data/lib/facets/more/functor.rb +105 -0
  1031. data/lib/facets/more/heap.rb +226 -0
  1032. data/lib/facets/more/inheritor.rb +239 -0
  1033. data/lib/facets/more/interval.rb +424 -0
  1034. data/lib/facets/more/ioredirect.rb +130 -0
  1035. data/lib/facets/more/lisp.rb +387 -0
  1036. data/lib/facets/more/lisp_format.rb +1843 -0
  1037. data/lib/facets/more/lrucache.rb +183 -0
  1038. data/lib/facets/more/mathconstants.rb +320 -0
  1039. data/lib/facets/more/methodprobe.rb +215 -0
  1040. data/lib/facets/more/mock.rb +233 -0
  1041. data/lib/facets/more/multipliers.rb +192 -0
  1042. data/lib/facets/more/multiton.rb +359 -0
  1043. data/lib/facets/more/nackclass.rb +162 -0
  1044. data/lib/facets/more/nilcomparable.rb +133 -0
  1045. data/lib/facets/more/nullclass.rb +68 -0
  1046. data/lib/facets/more/one.rb +117 -0
  1047. data/lib/facets/more/openobject.rb +220 -0
  1048. data/lib/facets/more/orderedhash.rb +3 -0
  1049. data/lib/facets/more/ormsupport.rb +235 -0
  1050. data/lib/facets/more/overload.rb +110 -0
  1051. data/lib/facets/more/paramix.rb +243 -0
  1052. data/lib/facets/more/pathlist.rb +105 -0
  1053. data/lib/facets/more/pool.rb +98 -0
  1054. data/lib/facets/more/preinitialize.rb +152 -0
  1055. data/lib/facets/more/progressbar.rb +227 -0
  1056. data/lib/facets/more/promoteself.rb +104 -0
  1057. data/lib/facets/more/quaternion.rb +527 -0
  1058. data/lib/facets/more/reference.rb +83 -0
  1059. data/lib/facets/more/rtals.rb +14 -0
  1060. data/lib/facets/more/semaphore.rb +103 -0
  1061. data/lib/facets/more/snapshot.rb +190 -0
  1062. data/lib/facets/more/stateparser.rb +579 -0
  1063. data/lib/facets/more/statichash.rb +87 -0
  1064. data/lib/facets/more/syncarray.rb +144 -0
  1065. data/lib/facets/more/synchash.rb +173 -0
  1066. data/lib/facets/more/system.rb +169 -0
  1067. data/lib/facets/more/tagiterator.rb +387 -0
  1068. data/lib/facets/more/timer.rb +307 -0
  1069. data/lib/facets/more/times.rb +327 -0
  1070. data/lib/facets/more/tracepoint.rb +183 -0
  1071. data/lib/facets/more/tuple.rb +170 -0
  1072. data/lib/facets/more/typecast.rb +280 -0
  1073. data/lib/facets/more/uninheritable.rb +90 -0
  1074. data/lib/facets/more/units.rb +938 -0
  1075. data/lib/facets/more/yamlstruct.rb +90 -0
  1076. metadata +680 -39
  1077. data/data/facets/methods.yaml +0 -446
@@ -0,0 +1,1843 @@
1
+ #:title: Lisp Format
2
+ #--
3
+ # Lisp Format
4
+ # v 0.3
5
+ #
6
+ # Copyright (C) 2003 Nikolai Weibull <source@pcppopper.org>.
7
+ #
8
+ # This library is free software; you can redistribute it and/or
9
+ # modify it under the terms of the GNU Lesser General Public
10
+ # License as published by the Free Software Foundation; either
11
+ # version 2.1 of the License, or (at your option) any later version.
12
+ #
13
+ # This library is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ # Lesser General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public
19
+ # License along with this library; if not, write to the Free Software
20
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
+ #
22
+ # ==========================================================================
23
+ # Revision History ::
24
+ # --------------------------------------------------------------------------
25
+ # 2004-11-16 0.3 TO * Ported en-masse as a "sub-space" of Lisp.
26
+ # 2003-12-08 0.2 NW * Releasing version 0.2.
27
+ # ==========================================================================
28
+ # To Do ::
29
+ # * the floating point functions are rather horendous
30
+ # ==========================================================================
31
+ #++
32
+
33
+ # = Description
34
+ #
35
+ # "So what is *ruby-lisp*?", you ask. Well, it is a module for implementing nice
36
+ # Lisp features for use in Ruby. Currently the only sub-module that exists is
37
+ # Lisp::Format, which implements Lisp's (format) function and its formatting
38
+ # language. For people not familiar with this language, it is a very expressive
39
+ # string formatting language, much like sprintf()'s, but much more powerful. It
40
+ # allows for iteration, case conversion, conditionals, and much more. If you
41
+ # have ever felt stupid while creating a string iteratively, to print an array or
42
+ # some such, this is definitely for you!
43
+ #
44
+ # This module contains various Lisp facilities that are of general usefulness.
45
+ # Lisp's rich string formatting language is implemented in the Format module.
46
+ # More modules may be added later.
47
+ #
48
+ # This has been (very simply) integrated into the namespace of Lsip from lisp.rb.
49
+ #
50
+ # == Author(s)
51
+ #
52
+ # * Nikolai Weibull <source@pcppopper.org>
53
+ #
54
+ # == More Information
55
+ #
56
+ # The project website for ruby-lisp is currently located at
57
+ # http://ned.rubyforge.org/.
58
+ #
59
+
60
+ #--
61
+ # This module contains various Lisp facilities that are of general usefulness.
62
+ # Lisp's rich string formatting language is implemented in the Format module.
63
+ # More modules may be added later.
64
+ #
65
+ # TODO: the floating point functions are rather horendous.
66
+ #++
67
+
68
+ module Lisp
69
+
70
+ # This module implements the Common Lisp (format) function and it's language.
71
+ module Format
72
+
73
+ # An error, positioned somewhere in the input format. This is used to be
74
+ # able to show the user exactly where something failed in the input format
75
+ # string.
76
+ module Positioned
77
+ # Create at a given position.
78
+ def initialize(pos = -1)
79
+ @pos = pos
80
+ end
81
+
82
+ # The position at which the error occured.
83
+ attr :pos, true
84
+ end
85
+
86
+ # An argument was of the wrong type, or there aren't enough arguments.
87
+ class ArgumentError < ArgumentError; include Positioned; end
88
+
89
+ # An index was not valid. Used for argument jumping errors.
90
+ class IndexError < IndexError; include Positioned; end
91
+
92
+ # A parameter was wrong in some sense.
93
+ class ParameterError < ArgumentError; include Positioned; end
94
+
95
+ # The format string contained a syntax error.
96
+ class SyntaxError < SyntaxError; include Positioned; end
97
+
98
+ # The format string was ended before a parameter could be read.
99
+ class MissingParameterError < SyntaxError; end
100
+
101
+ # The format string was ended before a parameter could be completed.
102
+ class IncompleteParameterError < SyntaxError; end
103
+
104
+ # The format string was malformed somehow.
105
+ class MalformedError < SyntaxError; end
106
+
107
+ # A modifier was wrongly given, or there were too many of the same.
108
+ class ModifierError < SyntaxError; end
109
+
110
+ # Represents output for a State object.
111
+ class Output
112
+ # Create a new Output object.
113
+ def initialize(str = '', col = 0)
114
+ @output, @col = str, col
115
+ end
116
+
117
+ # Add +str+ to the output.
118
+ def <<(str)
119
+ if str.is_a? Fixnum
120
+ @output << str.chr
121
+ # How should tabs be handled here? They should perhaps be
122
+ # interpreted as eight (8) characters wide? This of course depends
123
+ # on where @col is already at (8 - @col % 8).
124
+ @col = str == ?\n ? 0 : @col + 1
125
+ else
126
+ @output << str
127
+ @col += str.length - (str.rindex(?\n) or 0)
128
+ end
129
+ end
130
+
131
+ # Convert this object to its string representation, which is the output
132
+ # gathered so far.
133
+ # TODO: this is rather silly
134
+ def to_s
135
+ @output
136
+ end
137
+
138
+ # The current output column.
139
+ attr :col, true
140
+ end
141
+
142
+ # This class represents the state of a given Formatter. It keeps track of
143
+ # output gathered and arguments left to be processed.
144
+ class State
145
+ # Create a state from arguments and a destination output
146
+ def initialize(args, output)
147
+ @args = args
148
+ @arg_pos = 0
149
+ @outputs = [output]
150
+ @case_conv = nil
151
+ end
152
+
153
+ # Push a new Output buffer to collect output in.
154
+ def push_output
155
+ @outputs << Output.new('', @outputs.last.col)
156
+ end
157
+
158
+ # Pop and return the latest output buffer.
159
+ def pop_output
160
+ @outputs.pop
161
+ end
162
+
163
+ # Delegates output to the top-most output buffer.
164
+ def output(str)
165
+ @outputs.last << str
166
+ end
167
+
168
+ # Retrieve the current output column.
169
+ def col
170
+ @outputs.last.col
171
+ end
172
+
173
+ # Retrieve the latest output buffer.
174
+ def latest_output
175
+ @outputs.last
176
+ end
177
+
178
+ # Move +n+ steps forward or backward depending on sign amongst the
179
+ # arguments. Movement is relative or absolute depending on the boolean
180
+ # value of +relative+.
181
+ def args_move(n = 1, relative = true)
182
+ @arg_pos = relative ? @arg_pos + n : n
183
+ raise IndexError.new,
184
+ 'too few arguments' if @arg_pos > @args.size
185
+ raise IndexError.new,
186
+ 'cannot move past first argument' if @arg_pos < 0
187
+ end
188
+
189
+ # Get the current argument and move forward one argument.
190
+ def next_arg
191
+ args_move(1, true)
192
+ @args[@arg_pos - 1]
193
+ end
194
+
195
+ # Get the previously returned argument, without moving.
196
+ def previous_arg
197
+ args_move(-1, relative)
198
+ next_arg
199
+ end
200
+
201
+ # Push back the previously returned argument.
202
+ def push_back_arg
203
+ args_move(-1, true)
204
+ end
205
+
206
+ # Get the number of arguments left to process
207
+ def args_left
208
+ @args.size - @arg_pos
209
+ end
210
+
211
+ attr :case_conv, true
212
+ end
213
+
214
+ # Given a format string, this class lexes it and returns directives it
215
+ # finds. This includes gathering parameters and modifiers for the coming
216
+ # directives. The necessary information to create a directive is gathered
217
+ # and then passed to Directives::Factory#build. Error checking
218
+ # is performed, so that incomplete parameters are caught and malformed
219
+ # modifiers are supressed.
220
+ class Lexer
221
+ @@errorstates = {
222
+ :START => [MissingParameterError,
223
+ 'format string ended before parameter was found'],
224
+ :CHAR => [IncompleteParameterError,
225
+ 'format string ended before character parameter could be read'],
226
+ :INTEGER => [IncompleteParameterError,
227
+ 'format string ended before integer parameter could be read'],
228
+ }
229
+
230
+ # Create a new Lexer using the given format string +format+.
231
+ def initialize(format)
232
+ @format = format
233
+ @pos = 0
234
+ end
235
+
236
+ # Read the next token, given the previous one in +previous+, and return
237
+ # it. This may either be a 'real' directive created by
238
+ # Directives::Factory#build, or a Literal created in-line. If no more
239
+ # tokens remain, +nil+ is returned.
240
+ def next_token(previous)
241
+ if have_more_input
242
+ ch = next_char
243
+ if ch == ?~
244
+ return Directives::Factory.build(params, modifiers, directive,
245
+ previous, @pos)
246
+ else
247
+ literal = Directives::Literal.new(ch.chr)
248
+ while have_more_input and (ch = peek_char) != ?~
249
+ literal << next_char.chr
250
+ end
251
+ literal << ch.chr if not have_more_input and ch == ?~
252
+ return [literal, 0]
253
+ end
254
+ else
255
+ return nil
256
+ end
257
+ end
258
+
259
+ private
260
+
261
+ # Returns +true+ if more input exists.
262
+ def have_more_input
263
+ @pos < @format.length
264
+ end
265
+
266
+ # Reads next character in input.
267
+ def next_char
268
+ @pos += 1
269
+ @format[@pos - 1]
270
+ end
271
+
272
+ # View the next character in input.
273
+ def peek_char
274
+ @format[@pos]
275
+ end
276
+
277
+ # Unread previously read character in input.
278
+ def unget_char
279
+ @pos -= 1
280
+ end
281
+
282
+ # Read parameters to the coming directive. Raises various errors
283
+ # sub-classed from PositionedError when given incomplete
284
+ # parameters, e.g. when it runs out of input.
285
+ def params
286
+ params = []
287
+ sign = 1
288
+ value = 0
289
+ state = :START
290
+ while have_more_input
291
+ ch = next_char
292
+ case state
293
+ when :START
294
+ case ch
295
+ when ?'
296
+ state = :CHAR
297
+ when ?V, ?v
298
+ params << Parameters::Argument.new(@pos)
299
+ state = :DONE
300
+ when ?#
301
+ params << Parameters::ArgumentCount.new(@pos)
302
+ state = :DONE
303
+ when ?,
304
+ params << Parameters::Default.new(@pos)
305
+ state = :START
306
+ when ?+, ?-, ?0, ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9
307
+ sign = (ch == ?-) ? -1 : 1
308
+ value = (ch == ?+ or ch == ?-) ? 0 : (ch - ?0)
309
+ state = :INTEGER
310
+ else
311
+ unget_char
312
+ state = :DONE
313
+ end
314
+ when :INTEGER
315
+ if (?0..?9).to_a.include? ch
316
+ value = value * 10 + (ch - ?0)
317
+ else
318
+ unget_char
319
+ value *= sign
320
+ params << Parameters::Integer.new(@pos, value)
321
+ state = :DONE
322
+ end
323
+ when :CHAR
324
+ params << Parameters::Character.new(@pos, ch)
325
+ state = :DONE
326
+ when :DONE
327
+ if ch == ?,
328
+ state = :START
329
+ else
330
+ unget_char
331
+ break
332
+ end
333
+ end
334
+ end
335
+ unless state == :DONE
336
+ raise @@errorstates[state][0].new(@pos), @@errorstates[state][1]
337
+ end
338
+ return params
339
+ end
340
+
341
+ # Read modifiers to the coming directive. Raises ModifierError if
342
+ # a specific modifier is given more than once.
343
+ def modifiers
344
+ modifiers = []
345
+ while have_more_input
346
+ ch = next_char
347
+ if ch == ?: or ch == ?@
348
+ unless modifiers.include? ch
349
+ modifiers << ch
350
+ else
351
+ raise ModifierError.new(@pos), "duplicate #{ch.chr} modifier"
352
+ end
353
+ else
354
+ unget_char
355
+ break
356
+ end
357
+ end
358
+ return modifiers
359
+ end
360
+
361
+ # Reads the directive. Raises MalformedFormatError if no input
362
+ # remains to read the directive from.
363
+ def directive
364
+ unless have_more_input
365
+ raise MalformedFormatError.new(@pos),
366
+ 'format string ended before directive was found'
367
+ end
368
+ next_char
369
+ end
370
+ end
371
+
372
+ # Given a lexer, parses the tokens it constructs.
373
+ # It works, quite simply, by maintaining a stack of nesting levels and
374
+ # directives/tokens are added to the current stack level. When a directive
375
+ # removes a level of nesting the previous level's last directive gets
376
+ # connected, using Directive#connect.
377
+ class Parser
378
+ # Create a Parser, given a Lexer, +lexer+.
379
+ def initialize(lexer)
380
+ @lexer = lexer
381
+ end
382
+
383
+ # Do the actual parsing of the tokens. Returns a list of the
384
+ # top-level tokens to run.
385
+ def parse
386
+ stacks = [[]]
387
+ level = 0
388
+ until (token = @lexer.next_token(stacks[level>0?level-1:0].last)).nil?
389
+ directive = token[0]
390
+ nesting = token[1]
391
+ ntop = stacks[level].last.nil? ?
392
+ directive : stacks[level].last.join(directive)
393
+ stacks[level] << directive
394
+ if nesting > 0
395
+ stacks.push []
396
+ level += 1
397
+ elsif nesting < 0
398
+ directives = stacks.pop
399
+ level -= 1
400
+ stacks[level].last.connect directives
401
+ end
402
+ end
403
+ if stacks.size > 1
404
+ raise SyntaxError.new(stacks[-2].last.pos), 'unterminated directive'
405
+ end
406
+ return stacks[0]
407
+ end
408
+ end
409
+
410
+ # Engine for the format Lexer and Parser. Given an input format string and
411
+ # an initial State, it lets the Parser create the directives and then
412
+ # simply iterates over them, Directive#execute:ing them each.
413
+ class Formatter
414
+ # Create a Formatter from a String +format+ and a State +state+.
415
+ def initialize(format, state)
416
+ @parser, @state = Parser.new(Lexer.new(format)), state
417
+ end
418
+
419
+ # Parse and run the result.
420
+ def run
421
+ Format.execute_directives(@state, @parser.parse)
422
+ return @state.latest_output.to_s
423
+ end
424
+ end
425
+
426
+ # This module includes format parameter representation classes. These are
427
+ # passed to directives when they are created.
428
+ module Parameters
429
+ # Base class from which the sub-classes get their behavior. Every
430
+ # parameter should sub-class from this class.
431
+ class Parameter
432
+ # Create a parameter, found at +pos+ in the input format, and with
433
+ # +value+ as its value - if it has one.
434
+ def initialize(pos, value = nil)
435
+ @pos, @value = pos, value
436
+ end
437
+
438
+ # Retrieve this parameters value in the given State, using +default+ if
439
+ # it is not defined.
440
+ def value(state, default)
441
+ @value or default
442
+ end
443
+
444
+ # Position in the input format that this parameter was found.
445
+ attr :pos
446
+ end
447
+
448
+ # Represents the +V+ and +v+ parameters, which retrieve their value from
449
+ # the current argument.
450
+ class Argument < Parameter
451
+ # Retrieve this parameters value by getting the value of the current
452
+ # arguments integral value.
453
+ def value(state, default)
454
+ begin
455
+ arg = state.next_arg
456
+ rescue => e
457
+ e.pos = @pos if e.respond_to?(:pos) and e.pos == -1
458
+ raise
459
+ end
460
+ if arg.nil?
461
+ default
462
+ elsif arg.respond_to? :to_i
463
+ arg.to_i
464
+ else
465
+ raise ArgumentError.new(@pos),
466
+ 'argument not a number or a number string'
467
+ end
468
+ end
469
+ end
470
+
471
+ # Represents the <tt>#</tt> parameter, which retrieves the number of
472
+ # arguments left to process.
473
+ class ArgumentCount < Parameter
474
+ # Retrieve this parameters value by getting the number of arguments
475
+ # left to process.
476
+ def value(state, default)
477
+ state.args_left
478
+ end
479
+ end
480
+
481
+ # Parameter used when the parameter was not specified, so use its default
482
+ # value.
483
+ class Default < Parameter; end
484
+
485
+ # Represents integral parameters, specified directly in the input format.
486
+ class Integer < Parameter; end
487
+
488
+ # Represents character parameters, specified directly in the input
489
+ # format.
490
+ class Character < Parameter; end
491
+ end
492
+
493
+ # This module contains all the formatting directives that are defined in
494
+ # the Lisp formatting embedded language. The base class for all directives
495
+ # is aptly named Directive, and all directive classes should sub-class from
496
+ # it.
497
+ module Directives
498
+ # An unknown directive was found in the format string.
499
+ class UnknownDirectiveError < SyntaxError; end
500
+
501
+ # Represents a string literal in the input format. This is used for
502
+ # combining running lengths of characters with a single pseudo-directive.
503
+ class Literal < String
504
+ # Outputs the string literal this instance represents to the output
505
+ # stream.
506
+ def execute(state)
507
+ state.output self
508
+ end
509
+
510
+ # If the following directive is also a Literal, its contents is simply
511
+ # added to this ones, and returns self. Otherwise the other directive
512
+ # is returned.
513
+ def join(other)
514
+ other.is_a?(Literal) ? self << other : other
515
+ end
516
+ end
517
+
518
+ # Base class for formatting directives. This class makes it easy for
519
+ # sub-classes to access the parameters and modifiers that were given to
520
+ # it when created.
521
+ class Directive
522
+ # Given a set of parameters, modifiers, an owning directive if
523
+ # available, and a position in the output string, create a new
524
+ # Directive.
525
+ def initialize(params, modifiers, top, pos)
526
+ @params, @modifiers, @pos = params, modifiers, pos
527
+ end
528
+
529
+ # This method should be overridden in sub-classes. It gets called when
530
+ # the directive is to be executed. It does nothing by default.
531
+ def execute(state); end
532
+
533
+ # Join this directive with the following one, given in +other+. The
534
+ # default is to simply return +other+. The only known use for this is
535
+ # in SkipWhitespace, where some processing of other is done if it is a
536
+ # Literal.
537
+ def join(other)
538
+ other
539
+ end
540
+
541
+ # The position at which this directive occurs in the input string.
542
+ attr :pos
543
+
544
+ protected
545
+
546
+ # Read the +param+:th parameter in the Lisp::Format::State +state+,
547
+ # using +default+ as a default value if the parameter was not given.
548
+ def param(param, state, default)
549
+ param < @params.size ? @params[param].value(state, default) : default
550
+ end
551
+
552
+ # Check if the colon (<tt>:</tt>) modifier was given.
553
+ def colon_mod?
554
+ modifier? ?:
555
+ end
556
+
557
+ # Check if the at (<tt>@</tt>) modifier was given.
558
+ def at_mod?
559
+ modifier? ?@
560
+ end
561
+
562
+ # Check if the given +modifier+ was given. This method should not
563
+ # generally be called, as #colon_mod? and #at_mod? are easier and
564
+ # better to use.
565
+ def modifier?(modifier)
566
+ @modifiers.include? modifier
567
+ end
568
+
569
+ def arg_error(message)
570
+ raise ArgumentError.new(@pos), message
571
+ end
572
+
573
+ def param_error(pnum, message)
574
+ raise ParameterError.new(@params[pnum].pos), message
575
+ end
576
+ end
577
+
578
+ # Super-class for 'printing' directives, namely ~A (Ascii) and ~S
579
+ # (SExpression). These directives print, in some sense, their argument
580
+ # in a Ruby friendly manner. This means that their argument is either
581
+ # converted to a string using Object#to_s or Object#inspect.
582
+ class Print < Directive
583
+ # All parameters except +inspect+ are simply passed on to
584
+ # Directive#initialize. If +inspect+ is true, string arguments are
585
+ # inspected as well as all other objects.
586
+ def initialize(params, modifiers, top, pos, inspect = false)
587
+ super params, modifiers, top, pos
588
+ @inspect = inspect
589
+ end
590
+
591
+ # Output the given argument as it generally prints in Ruby. The full
592
+ # form is:
593
+ # ~mincol,colinc,minpad,padchar:@[AS]
594
+ # with the following interpretations
595
+ # [+mincol+ (0)]
596
+ # minimum number of columns to output,
597
+ # [+colinc+ (1)]
598
+ # number of columns to increase by, until +mincol+ is reached,
599
+ # [+minpad+ (0)]
600
+ # minimum amount of padding to add (added before +mincol+ is
601
+ # checked),
602
+ # [+padchar+ (?\s)]
603
+ # character to pad with,
604
+ # [:]
605
+ # +nil+ is output as +nil+ (In Lisp, this outputs +nil+ as
606
+ # <tt>()</tt>, which isn't generally useful in Ruby. TODO: come up
607
+ # with better use for this modifier),
608
+ # [@]
609
+ # padding is done on the right.
610
+ def execute(state)
611
+ padmethod = at_mod? ? :rjust : :ljust
612
+ mincol = param(0, state, 0)
613
+ colinc = param(1, state, 1)
614
+ minpad = param(2, state, 0)
615
+ padchar = param(3, state, ?\s).chr
616
+ arg = state.next_arg
617
+ # XXX: this needs checking use .to_s here?
618
+ str = (arg.is_a? String and not @inspect) ? arg.to_s : arg.inspect
619
+ str = str.send(padmethod, str.length + minpad, padchar)
620
+ k = ((mincol - str.length) / colinc.to_f).ceil
621
+ if k > 0
622
+ str = str.send(padmethod, str.length + colinc * k, padchar)
623
+ end
624
+ state.output str
625
+ end
626
+ end
627
+
628
+ # Represents the ~A (Ascii) directive.
629
+ class Ascii < Print; end
630
+
631
+ # Represents the ~S (S-Expression) directive.
632
+ class SExpression < Print
633
+ # Sets +inspect+ to +true+ in the argument list.
634
+ def initialize(*args)
635
+ super(*args << true)
636
+ end
637
+ end
638
+
639
+ # Super-class for number printing directives, namely ~D (Decimal, ~B
640
+ # (Binary), ~O (Octal), and ~X (Hexadecimal). The only difference
641
+ # between these directives is the output radix, which defaults to ten
642
+ # (10), which is decimal.
643
+ class Number < Directive
644
+ # Create a Number directive, using the given output radix +radix+.
645
+ def initialize(params, modifiers, top, pos, radix = 10)
646
+ super params, modifiers, top, pos
647
+ @radix = radix
648
+ end
649
+
650
+ # Output the given argument using its integral representation. The
651
+ # argument must respond to the :to_int message, or else it isn't
652
+ # considered an integer. This is the normal way in which Ruby
653
+ # operates. The full form is
654
+ # ~mincol,padchar,commachar,commainterval:@[DBOX]
655
+ # with the following interpretations
656
+ # [+mincol+ (0)]
657
+ # minimum number of columns to output,
658
+ # [+padchar+ (?\s)]
659
+ # character to pad with,
660
+ # [+commachar+ (,)]
661
+ # character to use for number grouping (see : below),
662
+ # [+commainterval+ (3)]
663
+ # how often to output +commachar+ above,
664
+ # [:]
665
+ # the number is output, with numbers grouped into +commainterval+
666
+ # sized groups of numbers, using +commachar+ as separator,
667
+ # [@]
668
+ # numbers are always output with sign prepended.
669
+ #
670
+ # An ArgumentError is raised if the argument does not respond to the
671
+ # #to_int message.
672
+ def execute(state)
673
+ mincol = param(0, state, 0)
674
+ padchar = param(1, state, ?\s).chr
675
+ commachar = param(2, state, ?,).chr
676
+ interval = param(3, state, 3)
677
+ arg = state.next_arg
678
+ if arg.respond_to? :to_int
679
+ num = arg.to_int
680
+ str = num.to_s(@radix)
681
+ if colon_mod?
682
+ str.gsub!(/(\d)(?=(\d{#{interval}})+(?!\d))/, "\\1#{commachar}")
683
+ end
684
+ str = '+' + str if at_mod? and num >= 0
685
+ # puts(str.rjust(mincol, '-'))
686
+ state.output str.rjust(mincol, padchar)
687
+ else
688
+ arg_error 'argument is not an integer'
689
+ end
690
+ end
691
+ end
692
+
693
+ # Represents the ~D (Decimal) directive.
694
+ class Decimal < Number; end
695
+
696
+ # Represents the ~B (Binary) directive.
697
+ class Binary < Number
698
+ # Set +radix+ to 2.
699
+ def initialize(args)
700
+ super(*args << 2)
701
+ end
702
+ end
703
+
704
+ # Represents the ~O (Octal) directive.
705
+ class Octal < Number
706
+ # Set +radix+ to 8.
707
+ def initialize(args)
708
+ super(*args << 8)
709
+ end
710
+ end
711
+
712
+ # Represents the ~X (Hexadecimal) directive.
713
+ class Hexadecimal < Number
714
+ # Set +radix+ to 16.
715
+ def initialize(args)
716
+ super(*args << 16)
717
+ end
718
+ end
719
+
720
+ # Represents the ~R (Radix) directive. This outputs numbers in a given
721
+ # radix, or using alternative forms, such as Roman numerals or
722
+ # cardinal/ordinal English numbers.
723
+ class Radix < Directive
724
+ @@names = {
725
+ 1 => 'one', 2 => 'two', 3 => 'three',
726
+ 4 => 'four', 5 => 'five', 6 => 'six',
727
+ 7 => 'seven', 8 => 'eight', 9 => 'nine',
728
+ 10 => 'ten', 11 => 'eleven', 12 => 'twelve',
729
+ 13 => 'thirteen', 14 => 'fourteen', 15 => 'fifteen',
730
+ 16 => 'sixteen', 17 => 'seventeen', 18 => 'eighteen',
731
+ 19 => 'nineteen', 20 => 'twenty', 30 => 'thirty',
732
+ 40 => 'forty', 50 => 'fifty', 60 => 'sixty',
733
+ 70 => 'seventy', 80 => 'eighty', 90 => 'ninety'
734
+ }
735
+ @@illions = %w[ \
736
+ thousand million billion trillion
737
+ quadrillion quintillion sextillion septillion
738
+ octillion nonillion decillion undecillion
739
+ duodecillion tredecillion quattuordecillion quindecillion
740
+ sexdecillion septendecillion octodecillion novemdecillion
741
+ vigintillion
742
+ ]
743
+ @@ordinal_ones = %w[
744
+ \ first second third fourth
745
+ fifth sixth seventh eight ninth
746
+ tenth eleventh twelfth thirteenth fourteenth
747
+ fifteenth sixteenth seventeenth eighteenth nineteenth
748
+ ]
749
+ @@ordinal_tens = %w[
750
+ \ \ twentieth thirtieth fortieth
751
+ fiftieth sixtieth seventieth eightieth ninetieth
752
+ ]
753
+ @@romans = [
754
+ [1000, 'M'], [900, 'CM'], [500, 'D'], [400, 'CD'], [100, 'C'],
755
+ [90, 'XC'], [50, 'L'], [40, 'XL'], [10, 'X'], [9, 'IX'],
756
+ [5, 'V'], [4, 'IV'], [1, 'I']
757
+ ]
758
+ @@old_romans = [
759
+ [1000, 'M'], [900, 'DCCCC'], [500, 'D'], [400, 'CCCC'],
760
+ [100, 'C'], [90, 'LXXXX'], [50, 'L'], [40, 'XXXX'],
761
+ [10, 'X'], [9, 'VIIII'], [5, 'V'], [4, 'IIII'],
762
+ [1, 'I']
763
+ ]
764
+
765
+ # Output the given argument using one of a variety of methods. Either
766
+ # the argument is output using a specific radix, using cardinal or
767
+ # ordinal English numbers, or Roman numerals. The full form is
768
+ # ~radix,mincol,padchar,commachar,commainterval:@R
769
+ # with the same interpretation as for ~D (Decimal / Number), but using
770
+ # the given +radix+ instead. An ArgumentError is raised if the
771
+ # argument is not an integer, or, in the case of Roman numerals, if the
772
+ # argument is not a Fixnum value.
773
+ #
774
+ # If none of the parameters are given the output instead depends on the
775
+ # combination of modifiers:
776
+ # [<em>no modifiers</em>]
777
+ # the number is output as a cardinal English number,
778
+ # [:]
779
+ # the number is output as an ordinal English number,
780
+ # [@]
781
+ # the number is output as a Roman numeral,
782
+ # [:@]
783
+ # the number is output as an old Roman numeral.
784
+ #
785
+ # An ArgumentError is raised if the argument is not an integer.
786
+ def execute(state)
787
+ if @params.size > 0
788
+ # XXX: may be ugly to modify these
789
+ n = @params.shift.value
790
+ Factory.build(@params, @modifiers, nil, @pos, n).execute(state)
791
+ else
792
+ arg = state.next_arg
793
+ if arg.respond_to? :to_int
794
+ conversion = :cardinal
795
+ conversion = :ordinal if colon_mod?
796
+ conversion = :roman if at_mod?
797
+ conversion = :old_roman if colon_mod? and at_mod?
798
+ state.output self.send(conversion, arg.to_int)
799
+ else
800
+ arg_error 'argument is not an integer'
801
+ end
802
+ end
803
+ end
804
+
805
+ private
806
+
807
+ # Convert the given number to a cardinal English number string.
808
+ def cardinal(n)
809
+ return 'zero' if n.zero?
810
+ out = []
811
+ negative = n < 0
812
+ n = n.abs
813
+ power = 0
814
+ while n > 0
815
+ before, after = n.divmod(1000)
816
+ if after > 0
817
+ block = cardinal_100s(after) + (power.zero? ? '' : ' ')
818
+ if power < @@illions.size
819
+ block << @@illions[power]
820
+ else
821
+ block << 'times ten to the ' + (power * 3).to_s + ' power'
822
+ end
823
+ out << block
824
+ end
825
+ n = before
826
+ power += 1
827
+ end
828
+ negative and out << 'minus'
829
+ out.reverse.join(', ')
830
+ end
831
+
832
+ # Deal with hundreds for cardinals.
833
+ def cardinal_100s(n)
834
+ out = []
835
+ q, r = n.divmod(100)
836
+ out << @@names[q] + ' hundred' if q > 0
837
+ if r >= 20
838
+ out << @@names[r / 10 * 10] + (r%10>0 ? '-' + @@names[r % 10] : '')
839
+ elsif r > 0
840
+ out << @@names[r]
841
+ end
842
+ out.join(' ')
843
+ end
844
+
845
+ # Convert the given number to an ordinal English number string.
846
+ def ordinal(n)
847
+ return 'zeroth' if n.zero?
848
+ out = []
849
+ if n < 0
850
+ out << 'minus'
851
+ n = n.abs
852
+ end
853
+ hundreds, tens_ones = n.divmod(100)
854
+ if hundreds > 0
855
+ out << cardinal(hundreds * 100) + (tens_ones.zero? ? 'th' : '')
856
+ end
857
+ if tens_ones >= 20
858
+ tens, ones = tens_ones.divmod(10)
859
+ if ones.zero?
860
+ out << @@ordinal_tens[tens]
861
+ else
862
+ out << @@names[tens * 10] + '-' + @@ordinal_ones[ones]
863
+ end
864
+ elsif tens_ones > 0
865
+ out << @@ordinal_ones[tens_ones]
866
+ end
867
+ out.join(' ')
868
+ end
869
+
870
+ # Helper method for roman numerals.
871
+ def roman_helper(n, table)
872
+ unless n.is_a? Fixnum
873
+ arg_error 'only Fixnum values can be converted to roman numerals'
874
+ end
875
+ out = []
876
+ table.each do |decimal, roman|
877
+ q, r = n.divmod(decimal)
878
+ if q > 0
879
+ out << roman * q
880
+ n = r
881
+ end
882
+ end
883
+ out.join('')
884
+ end
885
+
886
+ # Convert the given number to a Roman numeral.
887
+ def roman(n)
888
+ roman_helper(n, @@romans)
889
+ end
890
+
891
+ # Convert the given number to an old Roman numeral.
892
+ def old_roman(n)
893
+ roman_helper(n, @@old_romans)
894
+ end
895
+ end
896
+
897
+ # Represents the ~R (Plural) directive. It outputs English plural
898
+ # suffixes depending on the given argument.
899
+ class Plural < Directive
900
+ # Outputs the given argument as an English plural suffix depending on
901
+ # the arguments value. If arg is not #eql? to 1, a lowercase +s+ is
902
+ # output, else nothing is output. The meaning of modifiers are:
903
+ # [:]
904
+ # backs up one argument before checking,
905
+ # [@]
906
+ # outputs +y+ or +ies+ instead of +s+ and _nothing_,
907
+ # [:@]
908
+ # a combination of the two above.
909
+ def execute(state)
910
+ arg = colon_mod? ? state.previous_arg : state.next_arg
911
+ if at_mod?
912
+ state.output((arg.eql? 1) ? 'y' : 'ies')
913
+ else
914
+ state.output(?s) unless arg.eql? 1
915
+ end
916
+ end
917
+ end
918
+
919
+ # Represents the ~C (Character) directive. It outputs a character
920
+ # argument in one of several different representations depending on given
921
+ # modifiers.
922
+ # TODO: UNICODE this shit.
923
+ class Character < Directive
924
+ # Outputs the given argument in one of the ways described in the table
925
+ # below depending on given modifiers:
926
+ # [<tt>no modifiers</tt>]
927
+ # simply output the character as a normal character,
928
+ # [:]
929
+ # spells out control-bits on the input character, such as
930
+ # Control-Meta-X,
931
+ # [@]
932
+ # outputs the character in such as way that it can be read in by the
933
+ # Ruby interpreter again as input, using the ?_char_ syntax,
934
+ # [:@]
935
+ # has the same effect as : only. The CLTL2 suggests that this
936
+ # outputs unusual shift keys in a manner to make it easy to locate
937
+ # them on a keyboard, but since no such standard has arisen, this is
938
+ # not done.
939
+ def execute(state)
940
+ arg = state.next_arg
941
+ arg_error 'argument not a Fixnum' unless arg.is_a? Fixnum
942
+ ch = arg & 0xff
943
+ if colon_mod?
944
+ state.output('Control-') if (ch & 0x7f) < 0x1f
945
+ state.output('Meta-') if ch >= 0x7f
946
+ state.output(ch & 0x7f | 0x60)
947
+ elsif at_mod?
948
+ state.output('?' + convert_char(ch))
949
+ else
950
+ state.output ch
951
+ end
952
+ end
953
+
954
+ private
955
+
956
+ # Convert a character to a escaped character string if possible.
957
+ # XXX: This should perhaps only use \x or \NNN syntax
958
+ def convert_char(ch)
959
+ if [?\\, ?\n, ?\t, ?\r, ?\f, ?\v, ?\a, ?\e, ?\b, ?\s].include? ch
960
+ ch.chr.inspect[1..-2]
961
+ else
962
+ if (ch & 0x7f) < 0x1f
963
+ "\\C-" + convert_char(ch | 0x60)
964
+ elsif ch >= 0x7f
965
+ "\\M-" + convert_char(ch & 0x7f | 0x60)
966
+ else
967
+ ch
968
+ end
969
+ end
970
+ end
971
+ end
972
+
973
+ # Represents the ~F (Fixed-format floating-point) directive. This
974
+ # outputs floating point values with various kinds of padding and such.
975
+ class FFFP < Directive
976
+ # Outputs the given argument using a floating-point representation.
977
+ # The full form is
978
+ # ~w,d,k,overflowchar,padchar@F
979
+ # with the following interpretations
980
+ # [+w+ (+nil+)]
981
+ # if non-+nil+, the output will be exactly +w+ characters long,
982
+ # [+d+ (+nil+)]
983
+ # if non-+nil+, this is the number of digits output after the decimal
984
+ # point (<tt>.</tt>),
985
+ # [+k+ (0)]
986
+ # scaling factor - the number is first scaled using this value,
987
+ # [+overflowchar+ (+nil+)]
988
+ # if non-+nil+, this character is used when this directive would
989
+ # produce output longer than that specified with the +w+ directive,
990
+ # [+padchar+ (?\s)]
991
+ # character to pad with if +w+ is non-nil and output isn't wide
992
+ # enough yet,
993
+ # [@]
994
+ # numbers are always output with sign prepended.
995
+ #
996
+ # An ArgumentError is raised if the argument is not a number or a
997
+ # string that can be converted to a number.
998
+ def execute(state)
999
+ width = param(0, state, nil)
1000
+ digits = param(1, state, nil)
1001
+ scale = param(2, state, 0)
1002
+ overflowchar = param(3, state, nil)
1003
+ padchar = param(4, state, ?\s)
1004
+ arg = state.next_arg
1005
+ if arg.respond_to? :to_f
1006
+ num = arg.to_f * (10 ** scale)
1007
+ str = (at_mod? and num >= 0) ? '+' : ''
1008
+ str = sign + (digits.nil? ? num.to_s : sprintf("%.#{digits}f",num))
1009
+ str = sign + sprintf("%.#{$1}f", num) if str =~ /e-([0-9]+)$/
1010
+ unless width.nil?
1011
+ if not digits.nil? and width == digits + 1
1012
+ str.sub!(/^([+-]?)0\./, '\1.')
1013
+ end
1014
+ str = str.rjust(width, padchar.chr) if str.length < width
1015
+ if str.length > width and digits.nil?
1016
+ prec = width - (str.index(/\./) + 1)
1017
+ str = sign + sprintf("%#.#{prec}f", num)
1018
+ end
1019
+ str.sub!(/\.$/, '') if str.length > width and digits.nil?
1020
+ if str.length > width and not overflowchar.nil?
1021
+ str = overflowchar.chr * width
1022
+ end
1023
+ end
1024
+ state.output str
1025
+ elsif arg.respond_to? :to_int
1026
+ state.push_back_arg
1027
+ parameters = @params[0].nil? ? [] : [@params[0]]
1028
+ Factory.build(parameters, [], ?D, nil, @pos).execute(state)
1029
+ else
1030
+ arg_error 'argument is not a number or a number string'
1031
+ end
1032
+ end
1033
+ end
1034
+
1035
+ # Represents the ~E (Exponential floating-point) directive. This outputs
1036
+ # floating point values in what is known as exponential or scientific
1037
+ # floating point format, such as 1.0e+3 for 1000.
1038
+ class ExpFP < Directive
1039
+
1040
+ # Outputs the argument using exponential floating-point format. The
1041
+ # full form is
1042
+ # ~w,d,e,k,overflowchar,padchar,exponentchar@E
1043
+ # with the following interpretations
1044
+ # [+w+ (+nil+)]
1045
+ # if non-+nil+, the output will be exactly +w+ characters long,
1046
+ # [+d+ (+nil+)]
1047
+ # if non-+nil+, this is the number of digits output after the decimal
1048
+ # point (<tt>.</tt>),
1049
+ # [+e+ (+nil+)]
1050
+ # if non-+nil+, the exponent part of the output will be exactly +e+
1051
+ # characters long,
1052
+ # [+k+ (1)]
1053
+ # scaling factor - the number is first scaled using this value,
1054
+ # [+overflowchar+ (+nil+)]
1055
+ # if non-+nil+, this character is used when this directive would
1056
+ # produce output longer than that specified with the +w+ directive,
1057
+ # [+padchar+ (?\s)]
1058
+ # character to pad with if +w+ is non-nil and output isn't wide
1059
+ # enough yet,
1060
+ # [+exponentchar+ (?e)]
1061
+ # character to use for exponent divider,
1062
+ # [@]
1063
+ # numbers are always output with sign prepended.
1064
+ #
1065
+ # An ArgumentError is raised if the argument is not a number or a
1066
+ # string that can be converted to a number.
1067
+ def execute(state)
1068
+ width = param(0, state, nil)
1069
+ digits = param(1, state, nil)
1070
+ edigits = param(2, state, nil)
1071
+ scale = param(3, state, 1)
1072
+ overflowchar = param(4, state, nil)
1073
+ padchar = param(5, state, ?\s).chr
1074
+ exponentchar = param(6, state, ?e).chr
1075
+ arg = state.next_arg
1076
+ if arg.respond_to? :to_f
1077
+ num = arg.to_f
1078
+ sign = (num >= 0 and at_mod?) ? '+' : ''
1079
+ exp = Math.log10(num.abs).floor - (scale - 1)
1080
+ exp_str = exponentchar + (exp >= 0 ? '+' : '-') +
1081
+ (edigits.nil? ? exp.abs.to_s : exp.abs.to_s.rjust(edigits, '0'))
1082
+ if digits.nil? and width.nil? and edigits.nil?
1083
+ str = sign + (num * (10 ** -exp)).to_s + exp_str
1084
+ else
1085
+ if digits.nil?
1086
+ prec = width - sign.length -
1087
+ ((num * (10 ** -exp)).to_s.index(/\./) + 1) - exp_str.length
1088
+ str = sign + sprintf("%#.#{prec}f", num) + exp_str
1089
+ else
1090
+ if scale > 0
1091
+ if scale < digits + 2
1092
+ prec = digits - scale + 1
1093
+ else
1094
+ param_error 3, 'scale must be < digits + 2'
1095
+ end
1096
+ else
1097
+ prec = -scale + (digits + scale)
1098
+ end
1099
+ str = sign + sprintf("%#.#{prec}f", num * (10**-exp)) + exp_str
1100
+ end
1101
+ unless width.nil?
1102
+ if scale <= 0 and str.length > width
1103
+ str.sub!(/^([+-]?)0\./, '\1.')
1104
+ end
1105
+ str = str.rjust(width, padchar) if str.length < width
1106
+ end
1107
+ unless width.nil? and overflowchar.nil?
1108
+ if not edigits.nil? and (exp_str.length - 2) > edigits
1109
+ str = overflowchar.chr * width
1110
+ end
1111
+ end
1112
+ end
1113
+ state.output str
1114
+ elsif arg.respond_to? :to_int
1115
+ state.push_back_arg
1116
+ parameters = @params[0].nil? ? [] : [@params[0]]
1117
+ Factory.build(parameters, [], ?D, nil, @pos).execute(state)
1118
+ else
1119
+ arg_error 'argument is not a number or a number string'
1120
+ end
1121
+ end
1122
+ end
1123
+
1124
+ # Represents the ~G (General floating-point) directive. This outputs its
1125
+ # argument using either a format like ~F or ~E depending upon given
1126
+ # parameters and the magnitude of the argument.
1127
+ class GeneralFP < Directive
1128
+ # Outputs the argument using exponential floating-point format. The
1129
+ # algorithm to decide what format to use looks something like
1130
+ # let
1131
+ # 10^n-1 <= arg < 10^n, or n = 0 if arg = 0,
1132
+ # ee = e + 2, or ee = 4 if e undefined,
1133
+ # ww = w - ee, or ww = nil if w undefined,
1134
+ # dd = d - n, or dd = max(q, min(n, 7)) where q = number of
1135
+ # characters necessary to print arg without loss of information
1136
+ # in
1137
+ # 0 <= dd <= d, and print using
1138
+ # ~ww,dd,,overflowchar,padcharF~ee@T
1139
+ # or print using
1140
+ # ~w,d,e,k,overflowchar,padchar,exponentcharG
1141
+ # Use of the @ modifier in the directives above depends on if it was
1142
+ # passed to ~G in the first place.
1143
+ #
1144
+ # The full form is
1145
+ # ~w,d,e,k,overflowchar,padchar,exponentchar@G
1146
+ # with the following interpretations
1147
+ # [+w+ (+nil+)]
1148
+ # if non-+nil+, the output will be exactly +w+ characters long,
1149
+ # [+d+ (+nil+)]
1150
+ # if non-+nil+, this is the number of digits output after the decimal
1151
+ # point (<tt>.</tt>),
1152
+ # [+e+ (+nil+)]
1153
+ # if non-+nil+, the exponent part of the output will be exactly +e+
1154
+ # characters long,
1155
+ # [+k+ (1)]
1156
+ # scaling factor - the number is first scaled using this value,
1157
+ # [+overflowchar+ (+nil+)]
1158
+ # if non-+nil+, this character is used when this directive would
1159
+ # produce output longer than that specified with the +w+ directive,
1160
+ # [+padchar+ (?\s)]
1161
+ # character to pad with if +w+ is non-nil and output isn't wide
1162
+ # enough yet,
1163
+ # [+exponentchar+ (?e)]
1164
+ # character to use for exponent divider,
1165
+ # [@]
1166
+ # numbers are always output with sign prepended.
1167
+ #
1168
+ # An ArgumentError is raised if the argument is not a number or a
1169
+ # string that can be converted to a number.
1170
+ def execute(state)
1171
+ width = param(0, state, nil)
1172
+ digits = param(1, state, nil)
1173
+ edigits = param(2, state, nil)
1174
+ scale = param(3, state, 1)
1175
+ overflowchar = param(4, state, nil)
1176
+ padchar = param(5, state, ?\s)
1177
+ exponentchar = param(6, state, nil)
1178
+ arg = state.next_arg
1179
+ if arg.respond_to? :to_f
1180
+ num = arg.to_f
1181
+ n = num == 0.0 ? 0 : Math.log10(num.abs).floor + 1
1182
+ ee = edigits.nil? ? 4 : edigits + 2
1183
+ ww = w.nil? ? nil : w - ee
1184
+ if d.nil?
1185
+ q = num.to_s.length
1186
+ d = Math.max(q, Math.min(n, 7))
1187
+ end
1188
+ dd = d - n
1189
+ if 0 <= dd and dd <= d
1190
+ state.push_back_arg
1191
+ parameters = [
1192
+ Parameters::Integer.new(@pos, ww),
1193
+ Parameters::Integer.new(@pos, dd),
1194
+ Parameters::Default.new(@pos),
1195
+ overflowchar.nil? ?
1196
+ Parameters::Default.new(@pos) :
1197
+ Parameters::Character.new(@pos, overflowchar),
1198
+ padchar.nil? ?
1199
+ Parameters::Default.new(@pos) :
1200
+ Parameters::Character.new(@pos, padchar),
1201
+ ]
1202
+ Factory.build(parameters, @modifiers, ?F, nil,
1203
+ @pos).execute(state)
1204
+ Factory.build([Parameters::Integere.new(@pos, ee)], @modifiers,
1205
+ ?T, nil, @pos).execute(state)
1206
+ else
1207
+ state.push_back_arg
1208
+ Factory.build(@params, @modifiers, ?E, nil, @pos).execute(state)
1209
+ end
1210
+ elsif arg.respond_to? :to_int
1211
+ state.push_back_arg
1212
+ parameters = @params[0].nil? ? [] : [@params[0]]
1213
+ Factory.build(parameters, [], ?D, nil, @pos).execute(state)
1214
+ else
1215
+ arg_error 'argument is not a number or a number string'
1216
+ end
1217
+ end
1218
+ end
1219
+
1220
+ # Represents the ~$ (Dollars floating-point) directive. This directive
1221
+ # outputs a floating point argument
1222
+ class DollarFP < Directive
1223
+ # Outputs the argument using a floating point format that suits dollar
1224
+ # values. The full form is
1225
+ # ~d,n,w,padchar:@$
1226
+ # with the following interpretations
1227
+ # [+d+ (2)]
1228
+ # number of digits to print after the decimal point (<tt>.</tt>),
1229
+ # [+n+ (1)]
1230
+ # number of digits to print before the decimal point (<tt>.</tt>),
1231
+ # [+w+ (0)]
1232
+ # minimum width of the field,
1233
+ # [+padchar+ (?\s)]
1234
+ # character used to produce right-adjusting padding with,
1235
+ # [:]
1236
+ # the sign of the value is output before any padding,
1237
+ # [@]
1238
+ # numbers are always output with sign prepended.
1239
+ def execute(state)
1240
+ digits = param(0, state, 2)
1241
+ idigits = param(1, state, 1)
1242
+ width = param(2, state, 0)
1243
+ padchar = param(3, state, ?\s)
1244
+ arg = state.next_arg
1245
+ if arg.respond_to :to_int
1246
+ sign = (arg >= 0 ? (at_mod? ? '+' : '') : '-')
1247
+ str = sprintf("%0#{idigits + digits + 1}.#{digits}f", arg.abs)
1248
+ if colon_mod?
1249
+ str = sign + str.rjust(width, padchar.chr)
1250
+ else
1251
+ str = (sign + str).rjust(width, padchar.chr)
1252
+ end
1253
+ state.output str
1254
+ elsif arg.respond_to? :to_i
1255
+ state.push_back_arg
1256
+ parameters = @params[2].nil? ? [] : [@params[2]]
1257
+ Factory.build(?D, parameters, [], nil, @pos).execute(state)
1258
+ else
1259
+ arg_error 'argument is not a number or a number string'
1260
+ end
1261
+ end
1262
+ end
1263
+
1264
+ # Parent class for character outputting directives, such as ~% (NewLine),
1265
+ # ~| (NewPage), and ~~ (Tilde), which output the same character a given
1266
+ # number of times.
1267
+ class CharacterDirective < Directive
1268
+ # Create and set the character to use to +ch+.
1269
+ def initialize(params, modifiers, top, pos, ch)
1270
+ super params, modifiers, top, pos
1271
+ @ch = ch
1272
+ end
1273
+
1274
+ # Outputs the specific character (depending on the
1275
+ # sub-classing directive) a given number of times. The full form is
1276
+ # ~n[%|~]
1277
+ # with the following interpretations
1278
+ # [+n+ (1)]
1279
+ # number of times to output the specific character.
1280
+ def execute(state)
1281
+ n = param(0, state, 1)
1282
+ state.output(@ch.chr * n)
1283
+ end
1284
+ end
1285
+
1286
+ # Represents the ~% (Newline) directive. This outputs a new-line (?\n)
1287
+ # character a given number of times.
1288
+ class NewLine < CharacterDirective
1289
+ # Set the output character to a new-line (?\n).
1290
+ def initialize(*args)
1291
+ super(*args << ?\n)
1292
+ end
1293
+ end
1294
+
1295
+ # Represents the ~% (Freshline) directive. This outputs a new-line (?\n)
1296
+ # character a given number of times, depending on if it is already at the
1297
+ # first output column or not.
1298
+ class FreshLine < Directive
1299
+ # Outputs a new-line character a given number of times depending on if
1300
+ # it is already at the first output column or not. If it is it outputs
1301
+ # it the given number minus one (1). The full form is
1302
+ # ~n&
1303
+ # with the following interpretations
1304
+ # [+n+ (1)]
1305
+ # number of times to output the specific character (maybe minus one).
1306
+ def execute(state)
1307
+ n = param(0, state, 1)
1308
+ return if n.zero?
1309
+ state.output(?\n) if state._col > 0
1310
+ (n - 1).times do state.output(?\n) end
1311
+ end
1312
+ end
1313
+
1314
+ # Represents the ~| (Newpage) directive. This outputs a new-page (?\f)
1315
+ # character a given number of times.
1316
+ class NewPage < CharacterDirective
1317
+ # Set the output character to a new-page (?\f).
1318
+ def initialize(*args)
1319
+ super(*args << ?\f)
1320
+ end
1321
+ end
1322
+
1323
+ # Represents the ~~ (Tilde) directive. This outputs a tilde (~)
1324
+ # character a given number of times.
1325
+ class Tilde < CharacterDirective
1326
+ # Set the output character to a tilde (~).
1327
+ def initialize(*args)
1328
+ super(*args << ?~)
1329
+ end
1330
+ end
1331
+
1332
+ # Represents the ~?\n (Real new-line) directive. This is used to skip
1333
+ # the new-line and any following white-space characters in the input
1334
+ # format. This is useful in long format strings, where the string has to
1335
+ # be split into multiple lines without ruining indentation.
1336
+ class SkipWhitespace < Directive
1337
+ # Join this directive with the following. This removes any new-line
1338
+ # and/or following white-space from the directive that follows, if it
1339
+ # is a string Literal.
1340
+ def join(other)
1341
+ return other if not other.is_a?(FormatLiteral) or colon_mod?
1342
+ other.sub!(/^[\s\t]+/, '')
1343
+ other[0,0] = '\n' if at_mod?
1344
+ other
1345
+ end
1346
+ end
1347
+
1348
+ # Represents the ~T (Tabulate) directive. This tabulates to a given
1349
+ # position in the output using white-space.
1350
+ class Tabulate < Directive
1351
+ # The output is spaced over to a given position, depending on where it
1352
+ # already is and parameters given to this directive.
1353
+ # ~colnum,colinc:@T
1354
+ # with the following interpretations
1355
+ # [+colnum+ (1)]
1356
+ # column to move to,
1357
+ # [+colinc+ (1)]
1358
+ # number of columns to space over by if already at or beyond
1359
+ # +colnum+,
1360
+ # [@]
1361
+ # performs relative tabulation. +colnum+ is treated as the column to
1362
+ # begin from (spacing over to it if necessary), and then moves over
1363
+ # to a column that is the smallest multiple of +colinc+.
1364
+ #
1365
+ # If output is already at or beyond +colnum+, then output is spaced
1366
+ # over to column <em>colnum + k * colinc</em>, for the smallest _k_
1367
+ # possible. An example of the @ modifiers effect is for the instance
1368
+ # of the ~T directive ~3,8@T, which moves over three columns, and then
1369
+ # to the first eight-sized tab-stop.
1370
+ def execute(state)
1371
+ colnum = param(0, state, 1)
1372
+ colinc = param(1, state, 1)
1373
+ padchar = ?\s.chr
1374
+ if at_mod?
1375
+ state.output(padchar * colnum)
1376
+ state.output(padchar * (colinc - state.col % colinc))
1377
+ else
1378
+ if state.col < colnum
1379
+ state.output(padchar * (colnum - state.col))
1380
+ elsif colinc > 0
1381
+ k = 1 + (state.col - colnum) / colinc
1382
+ state.output(padchar * ((colnum + k * colinc) - state.col))
1383
+ end
1384
+ end
1385
+ end
1386
+ end
1387
+
1388
+ # Represents the ~* (Argument jumping) directive. This moves arbitrarily
1389
+ # amongst the arguments passed to the formatting engine.
1390
+ class ArgJump < Directive
1391
+ # Moves backwards or forwards, relative or absolute, among the
1392
+ # formatting arguments. The full form is
1393
+ # ~n:@*
1394
+ # with the following interpretations
1395
+ # [+n+ (1)]
1396
+ # the amount of arguments to move or the argument to move to if
1397
+ # moving to an absolute position, indexed from zero (0),
1398
+ # [:]
1399
+ # move backwards +n+ arguments
1400
+ # [@]
1401
+ # move to the +n+:th argument, using zero-based indexing (absolute).
1402
+ def execute(state)
1403
+ n = param(0, state, 1)
1404
+ state.args_move(colon_mod? ? -n : n, !at_mod?)
1405
+ end
1406
+ end
1407
+
1408
+ # Represents the ~? (Indirection) directive. This takes the two
1409
+ # following arguments and formats them, using the first as the formatting
1410
+ # string, and the second as its arguments and inserts it into the output.
1411
+ class Indirection < Directive
1412
+ # Uses the next argument as a formatting string and then, depending on
1413
+ # modifiers specified, uses one of a set of different arguments as
1414
+ # input to this formatting. The full form is
1415
+ # ~@?
1416
+ # with the following interpretations
1417
+ # [@]
1418
+ # the formatting string is, much like a macro, inserted into the
1419
+ # formatting stream, so to speak, and consumes arguments and so on
1420
+ # from the current state, instead, as per default, consuming a second
1421
+ # argument and reading arguments from it.
1422
+ def execute(state)
1423
+ if at_mod?
1424
+ formatter = Formatter.new(state.next_arg, state)
1425
+ else
1426
+ format = state.next_arg
1427
+ state = State.new(state.next_arg, state.latest_output)
1428
+ formatter = Formatter.new(format, state)
1429
+ end
1430
+ formatter.run
1431
+ end
1432
+ end
1433
+
1434
+ # Represents the ~( (Begin case-conversion) directive. Everything
1435
+ # contained within it and its matching pair ~) (End case-conversion)
1436
+ # directive is subject to case conversion, such as upcasing or
1437
+ # capitalization.
1438
+ class BeginCaseConversion < Directive
1439
+ # Outputs the contained output case converted using some method that
1440
+ # depends on the combination of modifiers given to this directive. The
1441
+ # full form is
1442
+ # ~:@(
1443
+ # with the following interpretations
1444
+ # [<em>no modifiers</em>]
1445
+ # output is downcased,
1446
+ # [:]
1447
+ # every word is capitalized in the output,
1448
+ # [@]
1449
+ # the first word is capitalized in the output,
1450
+ # [:@]
1451
+ # output is upcased.
1452
+ def execute(state)
1453
+ conv = :DOWN
1454
+ conv = :CAP if colon_mod?
1455
+ conv = :CAP_FIRST if at_mod?
1456
+ conv = :UP if colon_mod? and at_mod?
1457
+ state.case_conv = conv
1458
+ state.push_output
1459
+ end
1460
+ end
1461
+
1462
+ # Represents the ~) (End case-conversion) directive. Everything
1463
+ # contained within it and its matching pair ~( (Begin case-conversion)
1464
+ # directive is subject to case conversion, such as upcasing or
1465
+ # capitalization.
1466
+ class EndCaseConversion < Directive
1467
+ # This does the actual work for the ~( directive, in that it collects
1468
+ # all the output between its matching directive (~() and outputs it
1469
+ # using one of the conversions set up by the ~( (BeginCaseConversion)
1470
+ # directive.
1471
+ def execute(state)
1472
+ output = state.pop_output.to_s
1473
+ state.output(
1474
+ case state.case_conv
1475
+ when :DOWN
1476
+ output.downcase
1477
+ when :CAP
1478
+ output.gsub(/\w+/) do |w| w.capitalize end
1479
+ when :CAP_FIRST
1480
+ output.capitalize
1481
+ when :UP
1482
+ output.upcase
1483
+ end
1484
+ )
1485
+ end
1486
+ end
1487
+
1488
+ # Represents the ~[ (Begin conditional expression) directive. This is
1489
+ # useful to choose among a set of directives depending on arguments and
1490
+ # numbers.
1491
+ class BeginConditional < Directive
1492
+ # Set up some variables and basically pass on to super.
1493
+ def initialize(*args)
1494
+ super(*args)
1495
+ if (colon_mod? or at_mod?) and @params.size > 0
1496
+ param_error 0, 'no parameters allowed together with' +
1497
+ ': and/or @ modifiers'
1498
+ end
1499
+ @clauses = []
1500
+ @default = -1
1501
+ end
1502
+
1503
+ # Process one of the given clauses, depending on the numeric value of
1504
+ # the given argument, or a specified parameter. The full form is
1505
+ # ~n[clause0~;clause1~:;clause2~]
1506
+ # or
1507
+ # ~:[clause0~;clause1~]
1508
+ # or
1509
+ # ~@[clause0~]
1510
+ # with the following interpretations
1511
+ # [+n+ (nil)]
1512
+ # if given, this value will be used to choose a clause instead of
1513
+ # reading an arguments value. This is only useful if +n+ is in fact
1514
+ # the arguments left parameter (<tt>#</tt>). An error is raised if
1515
+ # this argument does not #respond_to? :to_int,
1516
+ # [:]
1517
+ # instead of choosing a clause by number, the argument is tested as a
1518
+ # boolean value, and if false, then first clause is executed, else
1519
+ # the second one is,
1520
+ # [@]
1521
+ # instead of choosing a clause by number, the argument is tested as a
1522
+ # boolean value, and if true, the single clause is executed.
1523
+ def execute(state)
1524
+ test = state.next_arg if colon_mod? or at_mod?
1525
+ if colon_mod?
1526
+ c = test ? 1 : 0
1527
+ elsif at_mod?
1528
+ if test
1529
+ state.push_back_arg
1530
+ c = 0
1531
+ end
1532
+ else
1533
+ n = param(0, state, nil)
1534
+ if n.nil?
1535
+ arg = state.next_arg
1536
+ if arg.respond_to? :to_int
1537
+ n = arg.to_int
1538
+ else
1539
+ arg_error 'argument is not an integral value'
1540
+ end
1541
+ end
1542
+ if n < @clauses.size
1543
+ c = n
1544
+ elsif @default != -1
1545
+ c = @default
1546
+ end
1547
+ end
1548
+ Format.execute_directives(state, @clauses[c]) unless c.nil?
1549
+ end
1550
+
1551
+ # Connect a set of directives to this conditional directive.
1552
+ # A SyntaxError is raised if multiple clauses have been marked as
1553
+ # 'default', or if too many clauses have been specified for a given
1554
+ # set of modifiers.
1555
+ def connect(directives)
1556
+ @clauses = []
1557
+ clause = []
1558
+ directives.each do |d|
1559
+ if d.is_a? ClauseSeparator
1560
+ @clauses << clause
1561
+ clause = []
1562
+ if d.colon_mod?
1563
+ if @default == -1
1564
+ @default = @clauses.size
1565
+ else
1566
+ raise SyntaxError.new(d.pos),
1567
+ 'default clause has already been set'
1568
+ end
1569
+ end
1570
+ elsif d.is_a? EndConditional
1571
+ @clauses << clause
1572
+ break
1573
+ else
1574
+ clause << d
1575
+ end
1576
+ end
1577
+ must = 'two' if colon_mod? and @clauses.size != 2
1578
+ must = 'one' if at_mod? and @clauses.size != 1
1579
+ unless must.nil?
1580
+ raise SyntaxError.new(@pos), "must specify exactly #{must} clauses"
1581
+ end
1582
+ end
1583
+ end
1584
+
1585
+ # Represents the ~; (Clause separator) directive. It separates clauses
1586
+ # inside conditional and justifying directives (~[...~] and ~<...~>). It
1587
+ # may not appear anywhere else.
1588
+ class ClauseSeparator < Directive
1589
+ # Check that +top+ is either a BeginConditional or a
1590
+ # BeginJustification. If not, a SyntaxError is raised.
1591
+ def initialize(params, modifiers, top, pos)
1592
+ super params, modifiers, top, pos
1593
+ unless top.is_a? BeginConditional
1594
+ raise SyntaxError.new(@pos),
1595
+ '~; directive must be contained within a conditional (~[...~])' +
1596
+ ' or a justification (~<...~>)'
1597
+ end
1598
+ end
1599
+ end
1600
+
1601
+ # Represents the ~] (End conditional expression) directive. It ends a
1602
+ # conditional expression, and is an error if it appears without a
1603
+ # matching opening conditional expression.
1604
+ class EndConditional < Directive
1605
+ def initialize(params, modifiers, top, pos)
1606
+ super params, modifiers, top, pos
1607
+ unless top.is_a? BeginConditional
1608
+ raise SyntaxError.new(@pos), '~) without matching ~('
1609
+ end
1610
+ end
1611
+ end
1612
+
1613
+ # Represents the ~{ (Begin iteration) directive. A given set of
1614
+ # directives is used iteratively over a set of arguments (depends on the
1615
+ # modifiers specified) a given number of times, or until it runs out of
1616
+ # arguments.
1617
+ class BeginIteration < Directive
1618
+ # Create and set up some private variables
1619
+ def initialize(params, modifiers, top, pos)
1620
+ super params, modifiers, top, pos
1621
+ @directives = []
1622
+ end
1623
+
1624
+ # Iteratively run the contained directives using sets of arguments
1625
+ # depending upon what modifiers where given. The full form is
1626
+ # ~n:@{...~}
1627
+ # with the following interpretations
1628
+ # [n]
1629
+ # maximum number of times the iteration should be performed,
1630
+ # [<em>no modifiers</em>]
1631
+ # the iteration reads an argument, which must be an Array, and uses
1632
+ # it as the arguments to the contained directives,
1633
+ # [:]
1634
+ # the iteration reads an argument, which must be an Array
1635
+ # containing sub-arrays, and uses the sub-arrays as the arguments to
1636
+ # the contained directives, moving to the next one on each iteration,
1637
+ # [@]
1638
+ # the iteration uses the rest of the arguments as arguments to the
1639
+ # contained directives,
1640
+ # [:@]
1641
+ # the iteration uses the rest of the arguments, which must be Arrays,
1642
+ # using each Array as the set of arguments to the contained
1643
+ # directives.
1644
+ def execute(state)
1645
+ n = param(0, state, nil)
1646
+ return if not n.nil? and n == 0
1647
+ if colon_mod? and at_mod?
1648
+ execute_sets(n, state, false)
1649
+ elsif at_mod?
1650
+ execute_args(n, nil, state, false)
1651
+ elsif colon_mod?
1652
+ execute_sets(n, state, true)
1653
+ else
1654
+ execute_args(n, state.next_arg, state, true)
1655
+ end
1656
+ end
1657
+
1658
+ # Connect a set of directives to this iteration directive.
1659
+ def connect(directives)
1660
+ directives.pop
1661
+ @directives = directives
1662
+ end
1663
+
1664
+ private
1665
+
1666
+ # Execute the iteration using sub-lists either from the following
1667
+ # argument or from the remaining arguments.
1668
+ def execute_sets(n, state, use_next_arg)
1669
+ if use_next_arg
1670
+ sets = state.next_arg
1671
+ arg_error 'argument not an array' unless sets.is_a? Array
1672
+ sets = sets[0...n] unless n.nil?
1673
+ else
1674
+ m = n
1675
+ sets = []
1676
+ while state.args_left > 0 and (m.nil? or m > 0)
1677
+ sets << state.next_arg
1678
+ m -= 1 unless m.nil?
1679
+ end
1680
+ end
1681
+ sets.each do |set|
1682
+ execute_args(nil, set, state, true)
1683
+ end
1684
+ end
1685
+
1686
+ # Execute the iteration while there are arguments left and we haven't
1687
+ # reached our limit of iterations.
1688
+ def execute_args(n, args, state, use_new_state)
1689
+ if use_new_state
1690
+ arg_error 'argument not an array' unless args.is_a? Array
1691
+ state = State.new(args, state.latest_output)
1692
+ end
1693
+ while state.args_left > 0 and (n.nil? or n > 0)
1694
+ Format.execute_directives(state, @directives)
1695
+ n -= 1 unless n.nil?
1696
+ end
1697
+ end
1698
+ end
1699
+
1700
+ # Represents the ~} (End iteration) directive. See BeginIteration for an
1701
+ # explanation of how these directives work together.
1702
+ class EndIteration < Directive
1703
+ # Raise a SyntaxError if +top+ is not a BeginIteration.
1704
+ def initialize(params, modifiers, top, pos)
1705
+ super params, modifiers, top, pos
1706
+ unless top.is_a? BeginIteration
1707
+ raise SynaxError, '~} without matching ~{'
1708
+ end
1709
+ end
1710
+ end
1711
+
1712
+ # Factory for directives. Formatting directives should be created using
1713
+ # singleton methods in this class.
1714
+ class Factory
1715
+ @@directives = {
1716
+ ?A => [Ascii, 4, [], 0],
1717
+ ?S => [SExpression, 4, [], 0],
1718
+ ?D => [Decimal, 4, [], 0],
1719
+ ?B => [Binary, 4, [], 0],
1720
+ ?O => [Octal, 4, [], 0],
1721
+ ?X => [Hexadecimal, 4, [], 0],
1722
+ ?R => [Radix, 5, [], 0],
1723
+ ?P => [Plural, 0, [], 0],
1724
+ ?C => [Character, 0, [], 0],
1725
+ ?F => [FFFP, 5, [?:], 0],
1726
+ ?E => [ExpFP, 7, [?:], 0],
1727
+ ?G => [GeneralFP, 7, [?:], 0],
1728
+ ?$ => [DollarFP, 4, [], 0],
1729
+ ?% => [NewLine, 1, [?:, ?@], 0],
1730
+ ?& => [FreshLine, 1, [?:, ?@], 0],
1731
+ ?| => [NewPage, 1, [?:, ?@], 0],
1732
+ ?~ => [Tilde, 0, [?:, ?@], 0],
1733
+ ?\n => [SkipWhitespace, 0, [[?:, ?@]], 0],
1734
+ ?T => [Tabulate, 2, [], 0],
1735
+ ?* => [ArgJump, 1, [[?:, ?@]], 0],
1736
+ ?? => [Indirection, 0, [?:], 0],
1737
+ ?( => [BeginCaseConversion, 0, [], 0],
1738
+ ?) => [EndCaseConversion, 0, [?:, ?@], 0],
1739
+ ?[ => [BeginConditional, 1, [[?:, ?@]], 1],
1740
+ ?; => [ClauseSeparator, 0, [?@], 0],
1741
+ ?] => [EndConditional, 0, [?@], -1],
1742
+ ?{ => [BeginIteration, 1, [], 1],
1743
+ ?} => [EndIteration, 0, [?:, ?@], -1],
1744
+ }
1745
+
1746
+ # Create a directive given a set of paramaters, modifiers, the
1747
+ # character representing the directive, possible owning directive, and
1748
+ # position in the format string.
1749
+ def self.build(params, modifiers, directive, top, pos)
1750
+ @@directives.include? directive or
1751
+ raise UnknownDirectiveError.new(pos), 'unknown format directive'
1752
+ idx = directive.chr.upcase[0]
1753
+ params.size <= @@directives[idx][1] or
1754
+ raise ParameterError.new(pos),
1755
+ 'too many parameters given, expected no more than ' +
1756
+ @@directives[idx][1].to_s
1757
+ @@directives[idx][2].each do |illegal|
1758
+ if illegal.is_a? Array and (modifiers == illegal or
1759
+ modifiers.reverse == illegal)
1760
+ raise ModifierError.new(pos),
1761
+ 'cannot specify both : and @ modifiers'
1762
+ elsif modifiers.include? illegal
1763
+ raise ModifierError.new(pos),
1764
+ 'cannot specify the ' + mod.chr + 'modifier'
1765
+ end
1766
+ end
1767
+ return [
1768
+ @@directives[idx][0].new(params, modifiers, top, pos),
1769
+ @@directives[idx][3]
1770
+ ]
1771
+ end
1772
+ end #class Factory
1773
+
1774
+ end #module Directives
1775
+
1776
+ private
1777
+
1778
+ # Execute a set of directives in a given state.
1779
+ def self.execute_directives(state, directives)
1780
+ directives.each do |directive|
1781
+ begin
1782
+ directive.execute state
1783
+ rescue => e
1784
+ e.pos = d.pos if e.respond_to?(:pos) and e.pos == -1
1785
+ raise
1786
+ end
1787
+ end
1788
+ end
1789
+
1790
+ end #module Format
1791
+
1792
+ def Lisp.format(format, *args)
1793
+ begin
1794
+ state = Format::State.new(args, Format::Output.new)
1795
+ formatter = Format::Formatter.new(format, state)
1796
+ formatter.run
1797
+ rescue => e
1798
+ puts 'Format error: ' + e.message
1799
+ puts format
1800
+ puts ' ' * (e.pos - 1) + '^' if e.respond_to? :pos
1801
+ raise
1802
+ end
1803
+ end
1804
+
1805
+ def format(format, *args)
1806
+ Lisp.format(format, *args)
1807
+ end
1808
+
1809
+ end #module Lisp
1810
+
1811
+
1812
+
1813
+ # _____ _
1814
+ # |_ _|__ ___| |_
1815
+ # | |/ _ \/ __| __|
1816
+ # | | __/\__ \ |_
1817
+ # |_|\___||___/\__|
1818
+ #
1819
+
1820
+ =begin test
1821
+
1822
+ require 'test/unit'
1823
+
1824
+ class FormatTest < Test::Unit::TestCase
1825
+
1826
+ def test_decimal
1827
+ assert( Lisp.format("~D", 1) == "1" )
1828
+ end
1829
+
1830
+ def test_decimal_params
1831
+ assert( Lisp.format("~5,'-D~6D", 1, 2) == "----1 2" )
1832
+ end
1833
+
1834
+ def test_decimal_modifiers
1835
+ assert( Lisp.format("~5,'-,'.:@D~@D", 1013, 2) == "+1.013+2" )
1836
+ assert( Lisp.format("~7,,,2:@D~@D", 1013, 2) == " +10,13+2" )
1837
+ end
1838
+
1839
+ # Tests for ~v, ~V, ~#
1840
+
1841
+ end
1842
+
1843
+ =end