mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	 2f85bbe615
			
		
	
	2f85bbe615
	
	
	
		
			
			Co-authored-by: wookayin <wookayin@gmail.com> Co-authored-by: clason <c.clason@uni-graz.at> Co-authored-by: Lewis Russell <me@lewisr.dev>
		
			
				
	
	
		
			371 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			371 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local Screen = require('test.functional.ui.screen')
 | |
| local helpers = require('test.functional.helpers')(after_each)
 | |
| 
 | |
| local clear = helpers.clear
 | |
| local exec = helpers.exec
 | |
| local exec_lua = helpers.exec_lua
 | |
| local eq = helpers.eq
 | |
| local fn = helpers.fn
 | |
| local api = helpers.api
 | |
| local insert = helpers.insert
 | |
| 
 | |
| local function html_syntax_match()
 | |
|   local styles =
 | |
|     vim.split(api.nvim_exec2([[/<style>/+,/<\/style>/-p]], { output = true }).output, '\n')
 | |
|   local attrnames = {
 | |
|     ['font%-weight: bold'] = 'bold',
 | |
|     ['text%-decoration%-line: [^;]*underline'] = 'underline',
 | |
|     ['font%-style: italic'] = 'italic',
 | |
|     ['text%-decoration%-line: [^;]*line%-through'] = 'strikethrough',
 | |
|   }
 | |
|   local hls = {}
 | |
|   for _, style in ipairs(styles) do
 | |
|     local attr = {}
 | |
|     for match, attrname in pairs(attrnames) do
 | |
|       if style:find(match) then
 | |
|         ---@type boolean
 | |
|         attr[attrname] = true
 | |
|       end
 | |
|     end
 | |
|     if style:find('text%-decoration%-style: wavy') and attr.underline then
 | |
|       ---@type boolean
 | |
|       attr.underline = nil
 | |
|       attr.undercurl = true
 | |
|     end
 | |
|     attr.bg = style:match('background%-color: #(%x+)')
 | |
|     if attr.bg then
 | |
|       attr.bg = tonumber(attr.bg, 16)
 | |
|     end
 | |
|     attr.fg = style:match('[^%-]color: #(%x+)')
 | |
|     if attr.fg then
 | |
|       attr.fg = tonumber(attr.fg, 16)
 | |
|     end
 | |
|     if style:match('^%.(%w+)') then
 | |
|       ---@type table
 | |
|       hls[style:match('^%.(%w+)')] = attr
 | |
|     end
 | |
|   end
 | |
|   local whitelist = {
 | |
|     'fg',
 | |
|     'bg',
 | |
|     --'sp',
 | |
|     --'blend',
 | |
|     'bold',
 | |
|     --'standout',
 | |
|     'underline',
 | |
|     'undercurl',
 | |
|     --'underdouble',
 | |
|     --'underdotted',
 | |
|     --'underdashed',
 | |
|     'strikethrough',
 | |
|     'italic',
 | |
|     --'reverse',
 | |
|     --'nocombine',
 | |
|   }
 | |
|   for name, attrs_old in
 | |
|     pairs(api.nvim_get_hl(0, { link = true }) --[[@as table<string,table>]])
 | |
|   do
 | |
|     ---@type table
 | |
|     local other = hls[name:gsub('%.', '-'):gsub('@', '-')]
 | |
|     if other then
 | |
|       local attrs = {}
 | |
|       for _, attrname in ipairs(whitelist) do
 | |
|         ---@type table
 | |
|         attrs[attrname] = attrs_old[attrname]
 | |
|       end
 | |
|       eq(attrs, other)
 | |
|     end
 | |
|   end
 | |
|   return hls
 | |
| end
 | |
| 
 | |
| local function html_to_extmarks()
 | |
|   local buf = api.nvim_get_current_buf()
 | |
|   local ns = api.nvim_create_namespace 'test-namespace'
 | |
|   api.nvim_buf_clear_namespace(buf, ns, 0, -1)
 | |
|   exec 'silent! norm! ggd/^<pre>$\rddG3dk'
 | |
|   local stack = {}
 | |
|   exec [[set filetype=]]
 | |
|   exec [[silent! %s/</¤/g]]
 | |
|   exec [[silent! %s/"/"/g]]
 | |
|   exec [[silent! %s/&/\&/g]]
 | |
|   exec [[silent! %s/>/>/g]]
 | |
|   exec [[silent! %s/</</g]]
 | |
|   for _, match in
 | |
|     ipairs(
 | |
|       fn.matchbufline(buf, [[¤span class="\([^"]\+\)">\|¤/span>]], 1, '$', { submatches = true }) --[[@as (table[])]]
 | |
|     )
 | |
|   do
 | |
|     if match.text == '¤/span>' then
 | |
|       local val = table.remove(stack)
 | |
|       api.nvim_buf_set_extmark(buf, ns, val.lnum - 1, val.byteidx, {
 | |
|         hl_group = val.submatches[1],
 | |
|         end_row = match.lnum - 1,
 | |
|         end_col = match.byteidx,
 | |
|       })
 | |
|     else
 | |
|       table.insert(stack, match)
 | |
|     end
 | |
|   end
 | |
|   exec [[silent! %s/¤\/span>//g]]
 | |
|   exec [[silent! %s/¤span[^>]*>//g]]
 | |
| end
 | |
| 
 | |
| ---@param screen test.functional.ui.screen
 | |
| ---@param func function?
 | |
| local function run_tohtml_and_assert(screen, func)
 | |
|   exec('norm! ggO-;')
 | |
|   exec('norm! gg0f;:\r')
 | |
|   screen:sleep(10)
 | |
|   local snapshot = { grid = screen:get_snapshot().grid, attr_ids = screen:get_snapshot().attr_ids }
 | |
|   do
 | |
|     (func or exec)('TOhtml')
 | |
|   end
 | |
|   exec('only')
 | |
|   html_syntax_match()
 | |
|   html_to_extmarks()
 | |
|   exec('norm! gg0f;:\r')
 | |
|   screen:sleep(10)
 | |
|   eq(snapshot, { grid = screen:get_snapshot().grid, attr_ids = screen:get_snapshot().attr_ids })
 | |
| end
 | |
| 
 | |
| describe(':TOhtml', function()
 | |
|   --- @type test.functional.ui.screen
 | |
|   local screen
 | |
|   before_each(function()
 | |
|     clear({ args = { '--clean' } })
 | |
|     screen = Screen.new(80, 80)
 | |
|     screen:attach({ term_name = 'xterm' })
 | |
|     exec('colorscheme default')
 | |
|   end)
 | |
| 
 | |
|   it('expected internal html generated', function()
 | |
|     insert([[line]])
 | |
|     exec('set termguicolors')
 | |
|     local bg = fn.synIDattr(fn.hlID('Normal'), 'bg#', 'gui')
 | |
|     local fg = fn.synIDattr(fn.hlID('Normal'), 'fg#', 'gui')
 | |
|     exec_lua [[
 | |
|     local outfile = vim.fn.tempname() .. '.html'
 | |
|     local html = require('tohtml').tohtml(0,{title="title",font="dumyfont"})
 | |
|     vim.fn.writefile(html, outfile)
 | |
|     vim.cmd.split(outfile)
 | |
|     ]]
 | |
|     local out_file = api.nvim_buf_get_name(api.nvim_get_current_buf())
 | |
|     eq({
 | |
|       '<!DOCTYPE html>',
 | |
|       '<html>',
 | |
|       '<head>',
 | |
|       '<meta charset="UTF-8">',
 | |
|       '<title>title</title>',
 | |
|       ('<meta name="colorscheme" content="%s"></meta>'):format(api.nvim_get_var('colors_name')),
 | |
|       '<style>',
 | |
|       '* {font-family: dumyfont,monospace}',
 | |
|       ('body {background-color: %s; color: %s}'):format(bg, fg),
 | |
|       '</style>',
 | |
|       '</head>',
 | |
|       '<body style="display: flex">',
 | |
|       '<pre>',
 | |
|       'line',
 | |
|       '',
 | |
|       '</pre>',
 | |
|       '</body>',
 | |
|       '</html>',
 | |
|     }, fn.readfile(out_file))
 | |
|   end)
 | |
| 
 | |
|   it('highlight attributes generated', function()
 | |
|     --Make sure to uncomment the attribute in `html_syntax_match()`
 | |
|     exec('hi LINE gui=' .. table.concat({
 | |
|       'bold',
 | |
|       'underline',
 | |
|       'italic',
 | |
|       'strikethrough',
 | |
|     }, ','))
 | |
|     exec('hi UNDERCURL gui=undercurl')
 | |
|     exec('syn keyword LINE line')
 | |
|     exec('syn keyword UNDERCURL undercurl')
 | |
|     insert('line\nundercurl')
 | |
|     run_tohtml_and_assert(screen)
 | |
|   end)
 | |
| 
 | |
|   it('syntax', function()
 | |
|     insert [[
 | |
|     function main()
 | |
|       print("hello world")
 | |
|     end
 | |
|     ]]
 | |
|     exec('set termguicolors')
 | |
|     exec('syntax enable')
 | |
|     exec('setf lua')
 | |
|     run_tohtml_and_assert(screen)
 | |
|   end)
 | |
| 
 | |
|   it('diff', function()
 | |
|     exec('set diffopt=')
 | |
|     insert [[
 | |
|     diffadd
 | |
|     nochage
 | |
|     diffchange1
 | |
|     ]]
 | |
|     exec('new')
 | |
|     insert [[
 | |
|     nochage
 | |
|     diffchange2
 | |
|     diffremove
 | |
|     ]]
 | |
|     exec('set diff')
 | |
|     exec('close')
 | |
|     exec('set diff')
 | |
|     run_tohtml_and_assert(screen)
 | |
|   end)
 | |
| 
 | |
|   it('treesitter', function()
 | |
|     insert [[
 | |
|     function main()
 | |
|       print("hello world")
 | |
|     end
 | |
|     ]]
 | |
|     exec('setf lua')
 | |
|     exec_lua('vim.treesitter.start()')
 | |
|     run_tohtml_and_assert(screen)
 | |
|   end)
 | |
| 
 | |
|   it('matchadd', function()
 | |
|     insert [[
 | |
|     line
 | |
|     ]]
 | |
|     fn.matchadd('Visual', 'line')
 | |
|     run_tohtml_and_assert(screen)
 | |
|   end)
 | |
| 
 | |
|   describe('conceallevel', function()
 | |
|     local function run(level)
 | |
|       insert([[
 | |
|       line0
 | |
|       line1
 | |
|       line2
 | |
|       line3
 | |
|       ]])
 | |
|       local ns = api.nvim_create_namespace ''
 | |
|       fn.matchadd('Conceal', 'line1', 3, 5, { conceal = 'a' })
 | |
|       api.nvim_buf_set_extmark(0, ns, 2, 0, { conceal = 'a', end_col = 5 })
 | |
|       exec(':syntax match Conceal "line3" conceal cchar=a')
 | |
|       exec('set conceallevel=' .. level)
 | |
|       run_tohtml_and_assert(screen)
 | |
|     end
 | |
|     it('conceallevel=0', function()
 | |
|       run(0)
 | |
|     end)
 | |
|     it('conceallevel=1', function()
 | |
|       run(1)
 | |
|     end)
 | |
|     it('conceallevel=2', function()
 | |
|       run(2)
 | |
|     end)
 | |
|     it('conceallevel=3', function()
 | |
|       run(3)
 | |
|     end)
 | |
|   end)
 | |
| 
 | |
|   describe('extmarks', function()
 | |
|     it('virt_text', function()
 | |
|       insert [[
 | |
|       line1
 | |
|       line2
 | |
|       line3
 | |
|       line4
 | |
|       ]]
 | |
|       local ns = api.nvim_create_namespace ''
 | |
|       api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'foo' } } })
 | |
|       api.nvim_buf_set_extmark(
 | |
|         0,
 | |
|         ns,
 | |
|         1,
 | |
|         0,
 | |
|         { virt_text = { { 'foo' } }, virt_text_pos = 'overlay' }
 | |
|       )
 | |
|       api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = { { 'foo' } }, virt_text_pos = 'inline' })
 | |
|       --api.nvim_buf_set_extmark(0,ns,3,0,{virt_text={{'foo'}},virt_text_pos='right_align'})
 | |
|       run_tohtml_and_assert(screen)
 | |
|     end)
 | |
|     it('highlgith', function()
 | |
|       insert [[
 | |
|       line1
 | |
|       ]]
 | |
|       local ns = api.nvim_create_namespace ''
 | |
|       api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 2, hl_group = 'Visual' })
 | |
|       run_tohtml_and_assert(screen)
 | |
|     end)
 | |
|     it('virt_line', function()
 | |
|       insert [[
 | |
|       line1
 | |
|       line2
 | |
|       ]]
 | |
|       local ns = api.nvim_create_namespace ''
 | |
|       api.nvim_buf_set_extmark(0, ns, 1, 0, { end_col = 2, virt_lines = { { { 'foo' } } } })
 | |
|       run_tohtml_and_assert(screen)
 | |
|     end)
 | |
|   end)
 | |
| 
 | |
|   it('listchars', function()
 | |
|     exec('setlocal list')
 | |
|     exec(
 | |
|       'setlocal listchars=eol:$,tab:<->,space:-,multispace:++,lead:_,leadmultispace:##,trail:&,nbsp:%'
 | |
|     )
 | |
|     fn.setline(1, '\tfoo\t')
 | |
|     fn.setline(2, ' foo foo ')
 | |
|     fn.setline(3, '  foo  foo  ')
 | |
|     fn.setline(4, 'foo\x2cfoo')
 | |
|     run_tohtml_and_assert(screen)
 | |
|     exec('new|only')
 | |
|     fn.setline(1, '\tfoo\t')
 | |
|     exec('setlocal list')
 | |
|     exec('setlocal listchars=tab:a-')
 | |
|     run_tohtml_and_assert(screen)
 | |
|   end)
 | |
| 
 | |
|   it('folds', function()
 | |
|     insert([[
 | |
|     line1
 | |
|     line2
 | |
|     ]])
 | |
|     exec('set foldtext=foldtext()')
 | |
|     exec('%fo')
 | |
|     run_tohtml_and_assert(screen)
 | |
|   end)
 | |
| 
 | |
|   it('statuscol', function()
 | |
|     local function run()
 | |
|       local buf = api.nvim_get_current_buf()
 | |
|       run_tohtml_and_assert(screen, function()
 | |
|         exec_lua [[
 | |
|         local outfile = vim.fn.tempname() .. '.html'
 | |
|         local html = require('tohtml').tohtml(0,{number_lines=true})
 | |
|         vim.fn.writefile(html, outfile)
 | |
|         vim.cmd.split(outfile)
 | |
|         ]]
 | |
|       end)
 | |
|       api.nvim_set_current_buf(buf)
 | |
|     end
 | |
|     insert([[
 | |
|     line1
 | |
|     line2
 | |
|     ]])
 | |
|     exec('setlocal relativenumber')
 | |
|     run()
 | |
|     exec('setlocal norelativenumber')
 | |
|     exec('setlocal number')
 | |
|     run()
 | |
|     exec('setlocal relativenumber')
 | |
|     run()
 | |
|     exec('setlocal signcolumn=yes:2')
 | |
|     run()
 | |
|     exec('setlocal foldcolumn=2')
 | |
|     run()
 | |
|     exec('setlocal norelativenumber')
 | |
|     run()
 | |
|     exec('setlocal signcolumn=no')
 | |
|     run()
 | |
|   end)
 | |
| end)
 |