cursor_spec.lua 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. local helpers = require('test.functional.helpers')(after_each)
  2. local Screen = require('test.functional.ui.screen')
  3. local clear, meths = helpers.clear, helpers.meths
  4. local eq = helpers.eq
  5. local command = helpers.command
  6. describe('ui/cursor', function()
  7. local screen
  8. before_each(function()
  9. clear()
  10. screen = Screen.new(25, 5)
  11. screen:attach()
  12. end)
  13. it("'guicursor' is published as a UI event", function()
  14. local expected_mode_info = {
  15. [1] = {
  16. blinkoff = 0,
  17. blinkon = 0,
  18. blinkwait = 0,
  19. cell_percentage = 0,
  20. cursor_shape = 'block',
  21. name = 'normal',
  22. hl_id = 0,
  23. id_lm = 0,
  24. attr = {},
  25. attr_lm = {},
  26. mouse_shape = 0,
  27. short_name = 'n' },
  28. [2] = {
  29. blinkoff = 0,
  30. blinkon = 0,
  31. blinkwait = 0,
  32. cell_percentage = 0,
  33. cursor_shape = 'block',
  34. name = 'visual',
  35. hl_id = 0,
  36. id_lm = 0,
  37. attr = {},
  38. attr_lm = {},
  39. mouse_shape = 0,
  40. short_name = 'v' },
  41. [3] = {
  42. blinkoff = 0,
  43. blinkon = 0,
  44. blinkwait = 0,
  45. cell_percentage = 25,
  46. cursor_shape = 'vertical',
  47. name = 'insert',
  48. hl_id = 0,
  49. id_lm = 0,
  50. attr = {},
  51. attr_lm = {},
  52. mouse_shape = 0,
  53. short_name = 'i' },
  54. [4] = {
  55. blinkoff = 0,
  56. blinkon = 0,
  57. blinkwait = 0,
  58. cell_percentage = 20,
  59. cursor_shape = 'horizontal',
  60. name = 'replace',
  61. hl_id = 0,
  62. id_lm = 0,
  63. attr = {},
  64. attr_lm = {},
  65. mouse_shape = 0,
  66. short_name = 'r' },
  67. [5] = {
  68. blinkoff = 0,
  69. blinkon = 0,
  70. blinkwait = 0,
  71. cell_percentage = 0,
  72. cursor_shape = 'block',
  73. name = 'cmdline_normal',
  74. hl_id = 0,
  75. id_lm = 0,
  76. attr = {},
  77. attr_lm = {},
  78. mouse_shape = 0,
  79. short_name = 'c' },
  80. [6] = {
  81. blinkoff = 0,
  82. blinkon = 0,
  83. blinkwait = 0,
  84. cell_percentage = 25,
  85. cursor_shape = 'vertical',
  86. name = 'cmdline_insert',
  87. hl_id = 0,
  88. id_lm = 0,
  89. attr = {},
  90. attr_lm = {},
  91. mouse_shape = 0,
  92. short_name = 'ci' },
  93. [7] = {
  94. blinkoff = 0,
  95. blinkon = 0,
  96. blinkwait = 0,
  97. cell_percentage = 20,
  98. cursor_shape = 'horizontal',
  99. name = 'cmdline_replace',
  100. hl_id = 0,
  101. id_lm = 0,
  102. attr = {},
  103. attr_lm = {},
  104. mouse_shape = 0,
  105. short_name = 'cr' },
  106. [8] = {
  107. blinkoff = 0,
  108. blinkon = 0,
  109. blinkwait = 0,
  110. cell_percentage = 20,
  111. cursor_shape = 'horizontal',
  112. name = 'operator',
  113. hl_id = 0,
  114. id_lm = 0,
  115. attr = {},
  116. attr_lm = {},
  117. mouse_shape = 0,
  118. short_name = 'o' },
  119. [9] = {
  120. blinkoff = 0,
  121. blinkon = 0,
  122. blinkwait = 0,
  123. cell_percentage = 25,
  124. cursor_shape = 'vertical',
  125. name = 'visual_select',
  126. hl_id = 0,
  127. id_lm = 0,
  128. attr = {},
  129. attr_lm = {},
  130. mouse_shape = 0,
  131. short_name = 've' },
  132. [10] = {
  133. name = 'cmdline_hover',
  134. mouse_shape = 0,
  135. short_name = 'e' },
  136. [11] = {
  137. name = 'statusline_hover',
  138. mouse_shape = 0,
  139. short_name = 's' },
  140. [12] = {
  141. name = 'statusline_drag',
  142. mouse_shape = 0,
  143. short_name = 'sd' },
  144. [13] = {
  145. name = 'vsep_hover',
  146. mouse_shape = 0,
  147. short_name = 'vs' },
  148. [14] = {
  149. name = 'vsep_drag',
  150. mouse_shape = 0,
  151. short_name = 'vd' },
  152. [15] = {
  153. name = 'more',
  154. mouse_shape = 0,
  155. short_name = 'm' },
  156. [16] = {
  157. name = 'more_lastline',
  158. mouse_shape = 0,
  159. short_name = 'ml' },
  160. [17] = {
  161. blinkoff = 0,
  162. blinkon = 0,
  163. blinkwait = 0,
  164. cell_percentage = 0,
  165. cursor_shape = 'block',
  166. name = 'showmatch',
  167. hl_id = 0,
  168. id_lm = 0,
  169. attr = {},
  170. attr_lm = {},
  171. short_name = 'sm' },
  172. }
  173. screen:expect(function()
  174. -- Default 'guicursor', published on startup.
  175. eq(expected_mode_info, screen._mode_info)
  176. eq(true, screen._cursor_style_enabled)
  177. eq('normal', screen.mode)
  178. end)
  179. -- Event is published ONLY if the cursor style changed.
  180. screen._mode_info = nil
  181. command("echo 'test'")
  182. screen:expect{grid=[[
  183. ^ |
  184. ~ |
  185. ~ |
  186. ~ |
  187. test |
  188. ]], condition=function()
  189. eq(nil, screen._mode_info)
  190. end}
  191. -- Change the cursor style.
  192. helpers.command('hi Cursor guibg=DarkGray')
  193. helpers.command('set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr-o:hor20'
  194. ..',a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor'
  195. ..',sm:block-blinkwait175-blinkoff150-blinkon175')
  196. -- Update the expected values.
  197. for _, m in ipairs(expected_mode_info) do
  198. if m.name == 'showmatch' then
  199. if m.blinkon then m.blinkon = 175 end
  200. if m.blinkoff then m.blinkoff = 150 end
  201. if m.blinkwait then m.blinkwait = 175 end
  202. else
  203. if m.blinkon then m.blinkon = 250 end
  204. if m.blinkoff then m.blinkoff = 400 end
  205. if m.blinkwait then m.blinkwait = 700 end
  206. end
  207. if m.hl_id then
  208. m.hl_id = 56
  209. m.attr = {background = Screen.colors.DarkGray}
  210. end
  211. if m.id_lm then m.id_lm = 57 end
  212. end
  213. -- Assert the new expectation.
  214. screen:expect(function()
  215. eq(expected_mode_info, screen._mode_info)
  216. eq(true, screen._cursor_style_enabled)
  217. eq('normal', screen.mode)
  218. end)
  219. -- Change hl groups only, should update the styles
  220. helpers.command('hi Cursor guibg=Red')
  221. helpers.command('hi lCursor guibg=Green')
  222. -- Update the expected values.
  223. for _, m in ipairs(expected_mode_info) do
  224. if m.hl_id then
  225. m.attr = {background = Screen.colors.Red}
  226. end
  227. if m.id_lm then
  228. m.attr_lm = {background = Screen.colors.Green}
  229. end
  230. end
  231. -- Assert the new expectation.
  232. screen:expect(function()
  233. eq(expected_mode_info, screen._mode_info)
  234. eq(true, screen._cursor_style_enabled)
  235. eq('normal', screen.mode)
  236. end)
  237. -- update the highlight again to hide cursor
  238. helpers.command('hi Cursor blend=100')
  239. for _, m in ipairs(expected_mode_info) do
  240. if m.hl_id then
  241. m.attr = {background = Screen.colors.Red, blend = 100}
  242. end
  243. end
  244. screen:expect{grid=[[
  245. ^ |
  246. ~ |
  247. ~ |
  248. ~ |
  249. test |
  250. ]], condition=function()
  251. eq(expected_mode_info, screen._mode_info)
  252. end
  253. }
  254. -- Another cursor style.
  255. meths.set_option('guicursor', 'n-v-c:ver35-blinkwait171-blinkoff172-blinkon173'
  256. ..',ve:hor35,o:ver50,i-ci:block,r-cr:hor90,sm:ver42')
  257. screen:expect(function()
  258. local named = {}
  259. for _, m in ipairs(screen._mode_info) do
  260. named[m.name] = m
  261. end
  262. eq('vertical', named.normal.cursor_shape)
  263. eq(35, named.normal.cell_percentage)
  264. eq('horizontal', named.visual_select.cursor_shape)
  265. eq(35, named.visual_select.cell_percentage)
  266. eq('vertical', named.operator.cursor_shape)
  267. eq(50, named.operator.cell_percentage)
  268. eq('block', named.insert.cursor_shape)
  269. eq('vertical', named.showmatch.cursor_shape)
  270. eq(90, named.cmdline_replace.cell_percentage)
  271. eq(171, named.normal.blinkwait)
  272. eq(172, named.normal.blinkoff)
  273. eq(173, named.normal.blinkon)
  274. eq(42, named.showmatch.cell_percentage)
  275. end)
  276. -- If there is no setting for guicursor, it becomes the default setting.
  277. meths.set_option('guicursor', 'n:ver35-blinkwait171-blinkoff172-blinkon173-Cursor/lCursor')
  278. screen:expect(function()
  279. for _,m in ipairs(screen._mode_info) do
  280. if m.name ~= 'normal' then
  281. eq('block', m.cursor_shape or 'block')
  282. eq(0, m.blinkon or 0)
  283. eq(0, m.blinkoff or 0)
  284. eq(0, m.blinkwait or 0)
  285. eq(0, m.hl_id or 0)
  286. eq(0, m.id_lm or 0)
  287. end
  288. end
  289. end)
  290. end)
  291. it("empty 'guicursor' sets cursor_shape=block in all modes", function()
  292. meths.set_option('guicursor', '')
  293. screen:expect(function()
  294. -- Empty 'guicursor' sets enabled=false.
  295. eq(false, screen._cursor_style_enabled)
  296. for _, m in ipairs(screen._mode_info) do
  297. if m['cursor_shape'] ~= nil then
  298. eq('block', m.cursor_shape)
  299. eq(0, m.blinkon)
  300. eq(0, m.hl_id)
  301. eq(0, m.id_lm)
  302. end
  303. end
  304. end)
  305. end)
  306. end)