facets 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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