Block.coffee 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. Layout = require '../../src/Layout'
  2. merge = require 'lodash/merge'
  3. {cloneAndMergeDeep} = require '../../src/tools'
  4. {open, get, conf} = do ->
  5. show = (layout) ->
  6. got = layout.get()
  7. got = got.replace /<[^>]+>/g, ''
  8. defaultBlockConfig =
  9. linePrependor: options: amount: 2
  10. c = (add = {}) ->
  11. cloneAndMergeDeep defaultBlockConfig, add
  12. ret = {}
  13. ret.open = (block, name, top = 0, bottom = 0) ->
  14. config = c
  15. blockPrependor: options: amount: top
  16. blockAppendor: options: amount: bottom
  17. b = block.openBlock config, name
  18. b.write name + ' | top ' + top + ' bottom ' + bottom
  19. b
  20. ret.get = (layout) ->
  21. layout.get().replace(/<[^>]+>/g, '')
  22. ret.conf = (props) ->
  23. config = {}
  24. if props.left?
  25. merge config, linePrependor: options: amount: props.left
  26. if props.right?
  27. merge config, lineAppendor: options: amount: props.right
  28. if props.top?
  29. merge config, blockPrependor: options: amount: props.top
  30. if props.bottom?
  31. merge config, blockAppendor: options: amount: props.bottom
  32. if props.width?
  33. merge config, width: props.width
  34. if props.bullet is yes
  35. merge config, linePrependor: options: bullet: {char: '-', alignment: 'left'}
  36. config
  37. ret
  38. describe "Layout", ->
  39. describe "inline inputs", ->
  40. it "should be merged", ->
  41. l = new Layout
  42. l.write 'a'
  43. l.write 'b'
  44. get(l).should.equal 'ab'
  45. it "should be correctly wrapped", ->
  46. l = new Layout
  47. block = l.openBlock conf width: 20
  48. block.write '123456789012345678901234567890'
  49. block.close()
  50. get(l).should.equal '12345678901234567890\n1234567890'
  51. it "should trim from left when wrapping to a new line", ->
  52. l = new Layout
  53. block = l.openBlock conf width: 20
  54. block.write '12345678901234567890 \t 123456789012345678901'
  55. block.close()
  56. get(l).should.equal '12345678901234567890\n12345678901234567890\n1'
  57. it "should handle line breaks correctly", ->
  58. l = new Layout
  59. block = l.openBlock conf width: 20
  60. block.write '\na\n\nb\n'
  61. block.close()
  62. get(l).should.equal '\na\n\nb\n'
  63. it "should not put extra line breaks when a line is already broken", ->
  64. l = new Layout
  65. block = l.openBlock conf width: 20
  66. block.write '01234567890123456789\n0123456789'
  67. block.close()
  68. get(l).should.equal '01234567890123456789\n0123456789'
  69. describe "horizontal margins", ->
  70. it "should account for left margins", ->
  71. l = new Layout
  72. block = l.openBlock conf width: 20, left: 2
  73. block.write '01'
  74. block.close()
  75. get(l).should.equal ' 01'
  76. it "should account for right margins", ->
  77. l = new Layout
  78. block = l.openBlock conf width: 20, right: 2
  79. block.write '01'
  80. block.close()
  81. get(l).should.equal '01 '
  82. it "should account for both margins", ->
  83. l = new Layout
  84. block = l.openBlock conf width: 20, right: 2, left: 1
  85. block.write '01'
  86. block.close()
  87. get(l).should.equal ' 01 '
  88. it "should break lines according to left margins", ->
  89. l = new Layout
  90. global.tick = yes
  91. block = l.openBlock conf width: 20, left: 2
  92. block.write '01234567890123456789'
  93. block.close()
  94. global.tick = no
  95. get(l).should.equal ' 01234567890123456789'
  96. it "should break lines according to right margins", ->
  97. l = new Layout
  98. block = l.openBlock conf width: 20, right: 2
  99. block.write '01234567890123456789'
  100. block.close()
  101. get(l).should.equal '01234567890123456789 '
  102. it "should break lines according to both margins", ->
  103. l = new Layout
  104. block = l.openBlock conf width: 20, right: 2, left: 1
  105. block.write '01234567890123456789'
  106. block.close()
  107. get(l).should.equal ' 01234567890123456789 '
  108. it "should break lines according to terminal width", ->
  109. l = new Layout terminalWidth: 20
  110. block = l.openBlock conf right: 2, left: 1
  111. block.write '01234567890123456789'
  112. block.close()
  113. # Note: We don't expect ' 01234567890123456 \n 789 ',
  114. # since the first line (' 01234567890123456 ') is a full line
  115. # according to layout.config.terminalWidth and doesn't need
  116. # a break line.
  117. get(l).should.equal ' 01234567890123456 789 '
  118. describe "lines and blocks", ->
  119. it "should put one break line between: line, block", ->
  120. l = new Layout
  121. l.write 'a'
  122. l.openBlock().write('b').close()
  123. get(l).should.equal 'a\nb'
  124. it "should put one break line between: block, line", ->
  125. l = new Layout
  126. l.openBlock().write('a').close()
  127. l.write 'b'
  128. get(l).should.equal 'a\nb'
  129. it "should put one break line between: line, block, line", ->
  130. l = new Layout
  131. l.write 'a'
  132. l.openBlock().write('b').close()
  133. l.write 'c'
  134. get(l).should.equal 'a\nb\nc'
  135. it "margin top should work for: line, block", ->
  136. l = new Layout
  137. l.write 'a'
  138. l.openBlock(conf top: 2).write('b').close()
  139. get(l).should.equal 'a\n\n\nb'
  140. it "margin top should work for: block, line", ->
  141. l = new Layout
  142. l.openBlock(conf top: 1).write('a').close()
  143. l.write 'b'
  144. get(l).should.equal '\na\nb'
  145. it "margin top should work for: block, line, when block starts with a break", ->
  146. l = new Layout
  147. l.openBlock(conf top: 1).write('\na').close()
  148. l.write 'b'
  149. get(l).should.equal '\n\na\nb'
  150. it "margin top should work for: line, block, when line ends with a break", ->
  151. l = new Layout
  152. l.write 'a\n'
  153. l.openBlock(conf top: 1).write('b').close()
  154. get(l).should.equal 'a\n\n\nb'
  155. it "margin top should work for: line, block, when there are two breaks in between", ->
  156. l = new Layout
  157. l.write 'a\n'
  158. l.openBlock(conf top: 1).write('\nb').close()
  159. get(l).should.equal 'a\n\n\n\nb'
  160. it "margin bottom should work for: line, block", ->
  161. l = new Layout
  162. l.write 'a'
  163. l.openBlock(conf bottom: 1).write('b').close()
  164. get(l).should.equal 'a\nb\n'
  165. it "margin bottom should work for: block, line", ->
  166. l = new Layout
  167. l.openBlock(conf bottom: 1).write('a').close()
  168. l.write 'b'
  169. get(l).should.equal 'a\n\nb'
  170. it "margin bottom should work for: block, line, when block ends with a break", ->
  171. l = new Layout
  172. l.openBlock(conf bottom: 1).write('a\n').close()
  173. l.write 'b'
  174. get(l).should.equal 'a\n\n\nb'
  175. it "margin bottom should work for: block, line, when line starts with a break", ->
  176. l = new Layout
  177. l.openBlock(conf bottom: 1).write('a').close()
  178. l.write '\nb'
  179. get(l).should.equal 'a\n\n\nb'
  180. it "margin bottom should work for: block, line, when there are two breaks in between", ->
  181. l = new Layout
  182. l.openBlock(conf bottom: 1).write('a\n').close()
  183. l.write '\nb'
  184. get(l).should.equal 'a\n\n\n\nb'
  185. describe "blocks and blocks", ->
  186. it "should not get extra break lines for full-width lines", ->
  187. l = new Layout
  188. l.openBlock(conf width: 20).write('01234567890123456789').close()
  189. l.openBlock().write('b').close()
  190. get(l).should.equal '01234567890123456789\nb'
  191. it "should not get extra break lines for full-width lines followed by a margin", ->
  192. l = new Layout
  193. l.openBlock(conf width: 20, bottom: 1).write('01234567890123456789').close()
  194. l.openBlock().write('b').close()
  195. get(l).should.equal '01234567890123456789\n\nb'
  196. it "a(top: 0, bottom: 0) b(top: 0, bottom: 0)", ->
  197. l = new Layout
  198. l.openBlock().write('a').close()
  199. l.openBlock().write('b').close()
  200. get(l).should.equal 'a\nb'
  201. it "a(top: 0, bottom: 0) b(top: 1, bottom: 0)", ->
  202. l = new Layout
  203. l.openBlock().write('a').close()
  204. l.openBlock(conf(top: 1)).write('b').close()
  205. get(l).should.equal 'a\n\nb'
  206. it "a(top: 0, bottom: 1) b(top: 0, bottom: 0)", ->
  207. l = new Layout
  208. l.openBlock(conf(bottom: 1)).write('a').close()
  209. l.openBlock().write('b').close()
  210. get(l).should.equal 'a\n\nb'
  211. it "a(top: 0, bottom: 1 ) b( top: 1, bottom: 0)", ->
  212. l = new Layout
  213. l.openBlock(conf(bottom: 1)).write('a').close()
  214. l.openBlock(conf(top: 1)).write('b').close()
  215. get(l).should.equal 'a\n\n\nb'
  216. it "a(top: 0, bottom: 1 br) b(br top: 1, bottom: 0)", ->
  217. l = new Layout
  218. l.openBlock(conf(bottom: 1)).write('a\n').close()
  219. l.openBlock(conf(top: 1)).write('\nb').close()
  220. get(l).should.equal 'a\n\n\n\n\nb'
  221. it "a(top: 2, bottom: 3 a1-br-a2) b(br-b1-br-br-b2-br top: 2, bottom: 3)", ->
  222. l = new Layout
  223. l.openBlock(conf(top: 2, bottom: 3)).write('a1\na2').close()
  224. l.openBlock(conf(top: 2, bottom: 3)).write('\nb1\n\nb2\n').close()
  225. get(l).should.equal '\n\na1\na2\n\n\n\n\n\n\nb1\n\nb2\n\n\n\n'
  226. describe "nesting", ->
  227. it "should break one line for nested blocks", ->
  228. l = new Layout
  229. l.write 'a'
  230. b = l.openBlock()
  231. c = b.openBlock().write('c').close()
  232. b.close()
  233. get(l).should.equal 'a\nc'
  234. it "a(left: 2) > b(top: 2)", ->
  235. l = new Layout
  236. a = l.openBlock(conf(left: 2))
  237. a.openBlock(conf(top: 2)).write('b').close()
  238. a.close()
  239. get(l).should.equal ' \n \n b'
  240. it "a(left: 2) > b(bottom: 2)", ->
  241. l = new Layout
  242. a = l.openBlock(conf(left: 2))
  243. a.openBlock(conf(bottom: 2)).write('b').close()
  244. a.close()
  245. get(l).should.equal ' b\n \n '
  246. describe "bullets", ->
  247. it "basic bullet", ->
  248. l = new Layout
  249. l.openBlock(conf(left: 3, bullet: yes)).write('a').close()
  250. get(l).should.equal '- a'
  251. it "a(left: 3, bullet) > b(top:1)", ->
  252. l = new Layout
  253. a = l.openBlock(conf(left: 3, bullet: yes))
  254. b = a.openBlock(conf(top: 1)).write('b').close()
  255. a.close()
  256. get(l).should.equal '- \n b'