---@diagnostic disable: duplicate-set-field, need-check-nil, param-type-mismatch, assign-type-mismatch, redundant-parameter local highlight = require 'bugabinga.pivi.highlight' local render = require 'bugabinga.pivi.render' local entry = require 'bugabinga.pivi.entry' local transcript = require 'bugabinga.pivi.transcript' local fake = dofile 'tests/helpers/pivi_fake.lua' local of = function( name ) return vim.api.nvim_get_hl( 0, { name = name, link = false, } ) end local block = function( bufnr, kind, meta, lines ) local id = entry.open( bufnr, kind, meta ) for _, text in ipairs( lines ) do entry.line( bufnr, id, text ) end entry.close( bufnr, id ) render.decorate( bufnr, id ) return id end --- Every line highlight applied inside an entry, keyed by line. local lines_of = function( bufnr ) local found = {} for _, mark in ipairs( render.marks( bufnr ) ) do local group = ( mark[4] or {} ).line_hl_group if group then found[mark[2] + 1] = group end end return found end local texts_of = function( bufnr ) local found = {} for _, mark in ipairs( render.marks( bufnr ) ) do local details = mark[4] or {} for _, chunk in ipairs( details.virt_text or {} ) do table.insert( found, chunk[2] ) end for _, virtual in ipairs( details.virt_lines or {} ) do for _, chunk in ipairs( virtual ) do table.insert( found, chunk[2] ) end end end return found end describe( 'pivi highlight', function() local bufnr before_each( function() bufnr = transcript.ensure 'coloured' transcript.clear( bufnr ) end ) after_each( function() transcript.forget_all() fake.close_extra_windows() end ) it( 'defines a group for every role', function() for _, name in ipairs( highlight.names() ) do assert.is_true( next( of( name ) ) ~= nil, name .. ' has no colour' ) end end ) it( 'leaves a colour scheme in charge', function() vim.api.nvim_set_hl( 0, 'PiviUser', { bg = '#123456', } ) highlight.apply() assert.equal( tonumber( '123456', 16 ), of( 'PiviUser' ).bg ) end ) it( 'makes a user message the only one with a background', function() local prompt = block( bufnr, 'prompt', { text = 'find me', }, { 'find me', } ) local answer = block( bufnr, 'answer', {}, { 'an answer', 'over two lines', } ) local tool = block( bufnr, 'tool', { tool = 'read', }, { 'read a.lua', } ) local applied = lines_of( bufnr ) local first = select( 1, entry.range( bufnr, prompt ) ) local answered = select( 1, entry.range( bufnr, answer ) ) local worked = select( 1, entry.range( bufnr, tool ) ) assert.equal( 'PiviUser', applied[first] ) assert.is_nil( applied[answered] ) assert.equal( 'PiviTool', applied[worked] ) -- The background is what makes it findable, so it must actually be one. assert.is_truthy( of( 'PiviUser' ).bg ) assert.is_nil( of( 'PiviTool' ).bg ) end ) it( 'carries the user background across every line of the message', function() local prompt = block( bufnr, 'prompt', { text = 'two lines', }, { 'first', 'second', } ) local first, last = entry.range( bufnr, prompt ) local applied = lines_of( bufnr ) for row = first, last do assert.equal( 'PiviUser', applied[row], ( 'line %d is not marked' ):format( row ) ) end end ) it( 'gives each role its own labelling', function() block( bufnr, 'prompt', { text = 'a', }, { 'a', } ) block( bufnr, 'answer', {}, { 'b', } ) block( bufnr, 'tool', { tool = 'read', }, { 'read a.lua', } ) local used = {} for _, group in ipairs( texts_of( bufnr ) ) do used[group] = true end assert.is_true( used.PiviUserLabel ) assert.is_true( used.PiviUserBar ) assert.is_true( used.PiviAssistantLabel ) assert.is_true( used.PiviToolIcon ) end ) it( 'keeps tool work quieter than an answer', function() -- An answer is ordinary buffer text; tool output is deliberately dimmed. local answer = block( bufnr, 'answer', {}, { 'an answer', } ) local applied = lines_of( bufnr ) assert.is_nil( applied[select( 1, entry.range( bufnr, answer ) )] ) assert.is_truthy( of( 'PiviTool' ).fg ) end ) it( 'marks a failure without borrowing the tool colour', function() local failed = block( bufnr, 'error', { error = 'boom', }, { 'boom', } ) local applied = lines_of( bufnr ) assert.equal( 'PiviError', applied[select( 1, entry.range( bufnr, failed ) )] ) end ) end )