highlight_spec.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local tt = require('test.functional.terminal.testutil')
  5. local feed, clear = n.feed, n.clear
  6. local api = n.api
  7. local testprg, command = n.testprg, n.command
  8. local nvim_prog_abs = n.nvim_prog_abs
  9. local fn = n.fn
  10. local nvim_set = n.nvim_set
  11. local is_os = t.is_os
  12. local skip = t.skip
  13. describe(':terminal highlight', function()
  14. local screen
  15. before_each(function()
  16. clear()
  17. screen = Screen.new(50, 7)
  18. screen:set_default_attr_ids({
  19. [1] = { foreground = 45 },
  20. [2] = { background = 46 },
  21. [3] = { foreground = 45, background = 46 },
  22. [4] = { bold = true, italic = true, underline = true, strikethrough = true },
  23. [5] = { bold = true },
  24. [6] = { foreground = 12 },
  25. [7] = { bold = true, reverse = true },
  26. [8] = { background = 11 },
  27. [9] = { foreground = 130 },
  28. [10] = { reverse = true },
  29. [11] = { background = 11 },
  30. [12] = { bold = true, underdouble = true },
  31. [13] = { italic = true, undercurl = true },
  32. })
  33. screen:attach({ rgb = false })
  34. command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
  35. feed('i')
  36. screen:expect([[
  37. tty ready |
  38. {10: } |
  39. |*4
  40. {5:-- TERMINAL --} |
  41. ]])
  42. end)
  43. local function descr(title, attr_num, set_attrs_fn)
  44. local function sub(s)
  45. local str = s:gsub('NUM', attr_num)
  46. return str
  47. end
  48. describe(title, function()
  49. before_each(function()
  50. set_attrs_fn()
  51. tt.feed_data('text')
  52. tt.clear_attrs()
  53. tt.feed_data('text')
  54. end)
  55. local function pass_attrs()
  56. skip(is_os('win'))
  57. screen:expect(sub([[
  58. tty ready |
  59. {NUM:text}text{10: } |
  60. |*4
  61. {5:-- TERMINAL --} |
  62. ]]))
  63. end
  64. it('will pass the corresponding attributes', pass_attrs)
  65. it('will pass the corresponding attributes on scrollback', function()
  66. skip(is_os('win'))
  67. pass_attrs()
  68. local lines = {}
  69. for i = 1, 8 do
  70. table.insert(lines, 'line' .. tostring(i))
  71. end
  72. table.insert(lines, '')
  73. tt.feed_data(lines)
  74. screen:expect([[
  75. line4 |
  76. line5 |
  77. line6 |
  78. line7 |
  79. line8 |
  80. {10: } |
  81. {5:-- TERMINAL --} |
  82. ]])
  83. feed('<c-\\><c-n>gg')
  84. screen:expect(sub([[
  85. ^tty ready |
  86. {NUM:text}textline1 |
  87. line2 |
  88. line3 |
  89. line4 |
  90. line5 |
  91. |
  92. ]]))
  93. end)
  94. end)
  95. end
  96. descr('foreground', 1, function()
  97. tt.set_fg(45)
  98. end)
  99. descr('background', 2, function()
  100. tt.set_bg(46)
  101. end)
  102. descr('foreground and background', 3, function()
  103. tt.set_fg(45)
  104. tt.set_bg(46)
  105. end)
  106. descr('bold, italics, underline and strikethrough', 4, function()
  107. tt.set_bold()
  108. tt.set_italic()
  109. tt.set_underline()
  110. tt.set_strikethrough()
  111. end)
  112. descr('bold and underdouble', 12, function()
  113. tt.set_bold()
  114. tt.set_underdouble()
  115. end)
  116. descr('italics and undercurl', 13, function()
  117. tt.set_italic()
  118. tt.set_undercurl()
  119. end)
  120. end)
  121. it(':terminal highlight has lower precedence than editor #9964', function()
  122. clear()
  123. local screen = Screen.new(30, 4)
  124. screen:set_default_attr_ids({
  125. -- "Normal" highlight emitted by the child nvim process.
  126. N_child = {
  127. foreground = tonumber('0x4040ff'),
  128. background = tonumber('0xffff40'),
  129. fg_indexed = true,
  130. bg_indexed = true,
  131. },
  132. -- "Search" highlight in the parent nvim process.
  133. S = { background = Screen.colors.Green, italic = true, foreground = Screen.colors.Red },
  134. -- "Question" highlight in the parent nvim process.
  135. -- note: bg is indexed as it comes from the (cterm) child, while fg isn't as it comes from (rgb) parent
  136. Q = {
  137. background = tonumber('0xffff40'),
  138. bold = true,
  139. foreground = Screen.colors.SeaGreen4,
  140. bg_indexed = true,
  141. },
  142. })
  143. screen:attach({ rgb = true })
  144. -- Child nvim process in :terminal (with cterm colors).
  145. fn.termopen({
  146. nvim_prog_abs(),
  147. '-n',
  148. '-u',
  149. 'NORC',
  150. '-i',
  151. 'NONE',
  152. '--cmd',
  153. nvim_set .. ' notermguicolors',
  154. '+hi Normal ctermfg=Blue ctermbg=Yellow',
  155. '+norm! ichild nvim',
  156. '+norm! oline 2',
  157. }, {
  158. env = {
  159. VIMRUNTIME = os.getenv('VIMRUNTIME'),
  160. },
  161. })
  162. screen:expect([[
  163. {N_child:^child nvim }|
  164. {N_child:line 2 }|
  165. {N_child: }|
  166. |
  167. ]])
  168. command('hi Search gui=italic guifg=Red guibg=Green cterm=italic ctermfg=Red ctermbg=Green')
  169. feed('/nvim<cr>')
  170. screen:expect([[
  171. {N_child:child }{S:^nvim}{N_child: }|
  172. {N_child:line 2 }|
  173. {N_child: }|
  174. /nvim |
  175. ]])
  176. command('syntax keyword Question line')
  177. screen:expect([[
  178. {N_child:child }{S:^nvim}{N_child: }|
  179. {Q:line}{N_child: 2 }|
  180. {N_child: }|
  181. /nvim |
  182. ]])
  183. end)
  184. it('CursorLine and CursorColumn work in :terminal buffer in Normal mode', function()
  185. clear()
  186. local screen = Screen.new(50, 7)
  187. screen:set_default_attr_ids({
  188. [1] = { background = Screen.colors.Grey90 }, -- CursorLine, CursorColumn
  189. [2] = { reverse = true }, -- TermCursor
  190. [3] = { bold = true }, -- ModeMsg
  191. [4] = { background = Screen.colors.Grey90, reverse = true },
  192. [5] = { background = Screen.colors.Red },
  193. })
  194. screen:attach()
  195. command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
  196. screen:expect([[
  197. ^tty ready |
  198. |*6
  199. ]])
  200. tt.feed_data((' foobar'):rep(30))
  201. screen:expect([[
  202. ^tty ready |
  203. foobar foobar foobar foobar foobar foobar foobar |
  204. foobar foobar foobar foobar foobar foobar foobar f|
  205. oobar foobar foobar foobar foobar foobar foobar fo|
  206. obar foobar foobar foobar foobar foobar foobar foo|
  207. bar foobar |
  208. |
  209. ]])
  210. command('set cursorline cursorcolumn')
  211. feed('j10w')
  212. screen:expect([[
  213. tty ready {1: } |
  214. foobar foobar{1: }foobar foobar foobar foobar foobar |
  215. {1:foobar foobar ^foobar foobar foobar foobar foobar f}|
  216. oobar foobar f{1:o}obar foobar foobar foobar foobar fo|
  217. obar foobar fo{1:o}bar foobar foobar foobar foobar foo|
  218. bar foobar {1: } |
  219. |
  220. ]])
  221. -- Entering terminal mode disables 'cursorline' and 'cursorcolumn'.
  222. feed('i')
  223. screen:expect([[
  224. tty ready |
  225. foobar foobar foobar foobar foobar foobar foobar |
  226. foobar foobar foobar foobar foobar foobar foobar f|
  227. oobar foobar foobar foobar foobar foobar foobar fo|
  228. obar foobar foobar foobar foobar foobar foobar foo|
  229. bar foobar{2: } |
  230. {3:-- TERMINAL --} |
  231. ]])
  232. -- Leaving terminal mode restores old values.
  233. feed([[<C-\><C-N>]])
  234. screen:expect([[
  235. tty ready{1: } |
  236. foobar f{1:o}obar foobar foobar foobar foobar foobar |
  237. foobar fo{1:o}bar foobar foobar foobar foobar foobar f|
  238. oobar foo{1:b}ar foobar foobar foobar foobar foobar fo|
  239. obar foob{1:a}r foobar foobar foobar foobar foobar foo|
  240. {1:bar fooba^r }|
  241. |
  242. ]])
  243. -- CursorLine and CursorColumn are combined with TermCursorNC.
  244. command('highlight TermCursorNC gui=reverse')
  245. screen:expect([[
  246. tty ready{1: } |
  247. foobar f{1:o}obar foobar foobar foobar foobar foobar |
  248. foobar fo{1:o}bar foobar foobar foobar foobar foobar f|
  249. oobar foo{1:b}ar foobar foobar foobar foobar foobar fo|
  250. obar foob{1:a}r foobar foobar foobar foobar foobar foo|
  251. {1:bar fooba^r}{4: }{1: }|
  252. |
  253. ]])
  254. feed('2gg11|')
  255. screen:expect([[
  256. tty ready {1: } |
  257. {1: foobar fo^obar foobar foobar foobar foobar foobar }|
  258. foobar foo{1:b}ar foobar foobar foobar foobar foobar f|
  259. oobar foob{1:a}r foobar foobar foobar foobar foobar fo|
  260. obar fooba{1:r} foobar foobar foobar foobar foobar foo|
  261. bar foobar{4: } |
  262. |
  263. ]])
  264. -- TermCursorNC has higher precedence.
  265. command('highlight TermCursorNC gui=NONE guibg=Red')
  266. screen:expect([[
  267. tty ready {1: } |
  268. {1: foobar fo^obar foobar foobar foobar foobar foobar }|
  269. foobar foo{1:b}ar foobar foobar foobar foobar foobar f|
  270. oobar foob{1:a}r foobar foobar foobar foobar foobar fo|
  271. obar fooba{1:r} foobar foobar foobar foobar foobar foo|
  272. bar foobar{5: } |
  273. |
  274. ]])
  275. feed('G$')
  276. screen:expect([[
  277. tty ready{1: } |
  278. foobar f{1:o}obar foobar foobar foobar foobar foobar |
  279. foobar fo{1:o}bar foobar foobar foobar foobar foobar f|
  280. oobar foo{1:b}ar foobar foobar foobar foobar foobar fo|
  281. obar foob{1:a}r foobar foobar foobar foobar foobar foo|
  282. {1:bar fooba^r}{5: }{1: }|
  283. |
  284. ]])
  285. end)
  286. describe(':terminal highlight forwarding', function()
  287. local screen
  288. before_each(function()
  289. clear()
  290. screen = Screen.new(50, 7)
  291. screen:set_rgb_cterm(true)
  292. screen:set_default_attr_ids({
  293. [1] = { { reverse = true }, { reverse = true } },
  294. [2] = { { bold = true }, { bold = true } },
  295. [3] = { { fg_indexed = true, foreground = tonumber('0xe0e000') }, { foreground = 3 } },
  296. [4] = { { foreground = tonumber('0xff8000') }, {} },
  297. })
  298. screen:attach()
  299. command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
  300. feed('i')
  301. screen:expect([[
  302. tty ready |
  303. {1: } |
  304. |*4
  305. {2:-- TERMINAL --} |
  306. ]])
  307. end)
  308. it('will handle cterm and rgb attributes', function()
  309. skip(is_os('win'))
  310. tt.set_fg(3)
  311. tt.feed_data('text')
  312. tt.feed_termcode('[38:2:255:128:0m')
  313. tt.feed_data('color')
  314. tt.clear_attrs()
  315. tt.feed_data('text')
  316. screen:expect {
  317. grid = [[
  318. tty ready |
  319. {3:text}{4:color}text{1: } |
  320. |*4
  321. {2:-- TERMINAL --} |
  322. ]],
  323. }
  324. end)
  325. end)
  326. describe(':terminal highlight with custom palette', function()
  327. local screen
  328. before_each(function()
  329. clear()
  330. screen = Screen.new(50, 7)
  331. screen:set_default_attr_ids({
  332. [1] = { foreground = tonumber('0x123456') }, -- no fg_indexed when overridden
  333. [2] = { foreground = 12 },
  334. [3] = { bold = true, reverse = true },
  335. [5] = { background = 11 },
  336. [6] = { foreground = 130 },
  337. [7] = { reverse = true },
  338. [8] = { background = 11 },
  339. [9] = { bold = true },
  340. })
  341. screen:attach({ rgb = true })
  342. api.nvim_set_var('terminal_color_3', '#123456')
  343. command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
  344. feed('i')
  345. screen:expect([[
  346. tty ready |
  347. {7: } |
  348. |*4
  349. {9:-- TERMINAL --} |
  350. ]])
  351. end)
  352. it('will use the custom color', function()
  353. skip(is_os('win'))
  354. tt.set_fg(3)
  355. tt.feed_data('text')
  356. tt.clear_attrs()
  357. tt.feed_data('text')
  358. screen:expect([[
  359. tty ready |
  360. {1:text}text{7: } |
  361. |*4
  362. {9:-- TERMINAL --} |
  363. ]])
  364. end)
  365. end)