smart_word_wrap.t 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #!perl -T
  2. use utf8;
  3. use 5.006;
  4. use strict;
  5. use warnings;
  6. use Test::More;
  7. plan tests => 1;
  8. use Sidef;
  9. my $code = <<'EOT';
  10. class SmartWordWrap {
  11. has width = 80
  12. method prepare_words(array, depth=0, callback) {
  13. var root = []
  14. var len = 0
  15. for (var(i, limit) = (0, array.end); i <= limit; ++i) {
  16. len += (var word_len = array[i].len)
  17. if (len > width) {
  18. if (word_len > width) {
  19. len -= word_len
  20. array.splice(i, 1, array[i].split(width)...)
  21. limit = array.end
  22. --i; next
  23. }
  24. break
  25. }
  26. root << [
  27. array.first(i+1).join(' '),
  28. self.prepare_words(array.slice(i+1), depth+1, callback)
  29. ]
  30. if (depth.is_zero) {
  31. callback(root[0])
  32. root = []
  33. }
  34. break if (++len >= width)
  35. }
  36. root
  37. }
  38. method combine(root, path, callback) {
  39. var key = path.shift
  40. path.each { |value|
  41. root << key
  42. if (value.is_empty) {
  43. callback(root)
  44. }
  45. else {
  46. value.each { |item|
  47. self.combine(root, item, callback)
  48. }
  49. }
  50. root.pop
  51. }
  52. }
  53. method smart_wrap(text, width) {
  54. self.width = width
  55. var words = (text.kind_of(Array) ? text : text.words)
  56. var best = Hash(
  57. score => Inf,
  58. value => [],
  59. )
  60. self.prepare_words(words, callback: { |path|
  61. self.combine([], path, { |combination|
  62. var score = 0
  63. combination.slice(0, -1).each { |line|
  64. score += (width - line.len -> sqr)
  65. }
  66. if (score < best{:score}) {
  67. best{:score} = score
  68. best{:value} = []+combination
  69. }
  70. })
  71. })
  72. best{:value}.join("\n")
  73. }
  74. }
  75. EOT
  76. my $sidef = Sidef->new(name => 'smart_word_wrap');
  77. my $class = $sidef->execute_code($code);
  78. my $sww = $class->call;
  79. my $text = Sidef::Types::String::String->new('Lorem ipsum dolor sit amet, consectetur adipiscing elit.');
  80. my $width = Sidef::Types::Number::Number->new(20);
  81. my $wrapped = $sww->smart_wrap($text, $width);
  82. my $expected = 'Lorem ipsum
  83. dolor sit amet,
  84. consectetur
  85. adipiscing elit.';
  86. is("$wrapped", $expected);