output_spec.lua 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. local Screen = require('test.functional.ui.screen')
  2. local helpers = require('test.functional.helpers')(after_each)
  3. local child_session = require('test.functional.terminal.helpers')
  4. local mkdir, write_file, rmdir = helpers.mkdir, helpers.write_file, helpers.rmdir
  5. local eq = helpers.eq
  6. local eval = helpers.eval
  7. local feed = helpers.feed
  8. local feed_command = helpers.feed_command
  9. local iswin = helpers.iswin
  10. local clear = helpers.clear
  11. local command = helpers.command
  12. local nvim_dir = helpers.nvim_dir
  13. describe("shell command :!", function()
  14. if helpers.pending_win32(pending) then return end
  15. local screen
  16. before_each(function()
  17. clear()
  18. screen = child_session.screen_setup(0, '["'..helpers.nvim_prog..
  19. '", "-u", "NONE", "-i", "NONE", "--cmd", "'..helpers.nvim_set..'"]')
  20. screen:expect([[
  21. {1: } |
  22. {4:~ }|
  23. {4:~ }|
  24. {4:~ }|
  25. {4:~ }|
  26. |
  27. {3:-- TERMINAL --} |
  28. ]])
  29. end)
  30. after_each(function()
  31. child_session.feed_data("\3") -- Ctrl-C
  32. screen:detach()
  33. end)
  34. it("displays output without LF/EOF. #4646 #4569 #3772", function()
  35. -- NOTE: We use a child nvim (within a :term buffer)
  36. -- to avoid triggering a UI flush.
  37. child_session.feed_data(":!printf foo; sleep 200\n")
  38. screen:expect([[
  39. |
  40. {4:~ }|
  41. {4:~ }|
  42. {5: }|
  43. :!printf foo; sleep 200 |
  44. foo |
  45. {3:-- TERMINAL --} |
  46. ]])
  47. end)
  48. it("throttles shell-command output greater than ~10KB", function()
  49. if helpers.skip_fragile(pending) then
  50. return
  51. end
  52. child_session.feed_data(
  53. ":!for i in $(seq 2 30000); do echo XXXXXXXXXX $i; done\n")
  54. -- If we observe any line starting with a dot, then throttling occurred.
  55. -- Avoid false failure on slow systems.
  56. screen:expect{any="\n%.", timeout=20000}
  57. -- Final chunk of output should always be displayed, never skipped.
  58. -- (Throttling is non-deterministic, this test is merely a sanity check.)
  59. screen:expect([[
  60. XXXXXXXXXX 29997 |
  61. XXXXXXXXXX 29998 |
  62. XXXXXXXXXX 29999 |
  63. XXXXXXXXXX 30000 |
  64. |
  65. {10:Press ENTER or type command to continue}{1: } |
  66. {3:-- TERMINAL --} |
  67. ]], {
  68. -- test/functional/helpers.lua defaults to background=light.
  69. [1] = {reverse = true},
  70. [3] = {bold = true},
  71. [10] = {foreground = 2},
  72. })
  73. end)
  74. end)
  75. describe("shell command :!", function()
  76. before_each(function()
  77. clear()
  78. end)
  79. it("cat a binary file #4142", function()
  80. feed(":exe 'silent !cat '.shellescape(v:progpath)<CR>")
  81. eq(2, eval('1+1')) -- Still alive?
  82. end)
  83. it([[display \x08 char #4142]], function()
  84. feed(":silent !echo \08<CR>")
  85. eq(2, eval('1+1')) -- Still alive?
  86. end)
  87. it('handles control codes', function()
  88. if iswin() then
  89. pending('missing printf', function() end)
  90. return
  91. end
  92. local screen = Screen.new(50, 4)
  93. screen:attach()
  94. command("set display-=msgsep")
  95. -- Print TAB chars. #2958
  96. feed([[:!printf '1\t2\t3'<CR>]])
  97. screen:expect([[
  98. ~ |
  99. :!printf '1\t2\t3' |
  100. 1 2 3 |
  101. Press ENTER or type command to continue^ |
  102. ]])
  103. feed([[<CR>]])
  104. -- Print BELL control code. #4338
  105. screen.bell = false
  106. feed([[:!printf '\007\007\007\007text'<CR>]])
  107. screen:expect{grid=[[
  108. ~ |
  109. :!printf '\007\007\007\007text' |
  110. text |
  111. Press ENTER or type command to continue^ |
  112. ]], condition=function()
  113. eq(true, screen.bell)
  114. end}
  115. feed([[<CR>]])
  116. -- Print BS control code.
  117. feed([[:echo system('printf ''\010\n''')<CR>]])
  118. screen:expect([[
  119. ~ |
  120. ^H |
  121. |
  122. Press ENTER or type command to continue^ |
  123. ]])
  124. feed([[<CR>]])
  125. -- Print LF control code.
  126. feed([[:!printf '\n'<CR>]])
  127. screen:expect([[
  128. :!printf '\n' |
  129. |
  130. |
  131. Press ENTER or type command to continue^ |
  132. ]])
  133. feed([[<CR>]])
  134. end)
  135. describe('', function()
  136. local screen
  137. before_each(function()
  138. rmdir('bang_filter_spec')
  139. mkdir('bang_filter_spec')
  140. write_file('bang_filter_spec/f1', 'f1')
  141. write_file('bang_filter_spec/f2', 'f2')
  142. write_file('bang_filter_spec/f3', 'f3')
  143. screen = Screen.new(53,10)
  144. screen:set_default_attr_ids({
  145. [1] = {bold = true, foreground = Screen.colors.Blue1},
  146. [2] = {foreground = Screen.colors.Blue1},
  147. [3] = {bold = true, foreground = Screen.colors.SeaGreen4},
  148. [4] = {bold = true, reverse = true},
  149. })
  150. screen:attach()
  151. end)
  152. after_each(function()
  153. rmdir('bang_filter_spec')
  154. end)
  155. it("doesn't truncate Last line of shell output #3269", function()
  156. command(helpers.iswin()
  157. and [[nnoremap <silent>\l :!dir /b bang_filter_spec<cr>]]
  158. or [[nnoremap <silent>\l :!ls bang_filter_spec<cr>]])
  159. local result = (helpers.iswin()
  160. and [[:!dir /b bang_filter_spec]]
  161. or [[:!ls bang_filter_spec ]])
  162. feed([[\l]])
  163. screen:expect([[
  164. |
  165. {1:~ }|
  166. {1:~ }|
  167. {4: }|
  168. ]]..result..[[ |
  169. f1 |
  170. f2 |
  171. f3 |
  172. |
  173. {3:Press ENTER or type command to continue}^ |
  174. ]])
  175. end)
  176. it('handles binary and multibyte data', function()
  177. feed_command('!cat test/functional/fixtures/shell_data.txt')
  178. screen.bell = false
  179. screen:expect{grid=[[
  180. |
  181. {1:~ }|
  182. {4: }|
  183. :!cat test/functional/fixtures/shell_data.txt |
  184. {2:^@^A^B^C^D^E^F^H} |
  185. {2:^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_} |
  186. ö 한글 {2:<a5><c3>} |
  187. t {2:<ff>} |
  188. |
  189. {3:Press ENTER or type command to continue}^ |
  190. ]], condition=function()
  191. eq(true, screen.bell)
  192. end}
  193. end)
  194. it('handles multibyte sequences split over buffer boundaries', function()
  195. command('cd '..nvim_dir)
  196. local cmd
  197. if iswin() then
  198. cmd = '!shell-test UTF-8 '
  199. else
  200. cmd = '!./shell-test UTF-8'
  201. end
  202. feed_command(cmd)
  203. -- Note: only the first example of split composed char works
  204. screen:expect([[
  205. |
  206. {4: }|
  207. :]]..cmd..[[ |
  208. å |
  209. ref: å̲ |
  210. 1: å̲ |
  211. 2: å ̲ |
  212. 3: å ̲ |
  213. |
  214. {3:Press ENTER or type command to continue}^ |
  215. ]])
  216. end)
  217. end)
  218. end)