neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

hl_spec.lua (13476B)


      1 local t = require('test.testutil')
      2 local n = require('test.functional.testnvim')()
      3 local Screen = require('test.functional.ui.screen')
      4 
      5 local exec_lua = n.exec_lua
      6 local eq = t.eq
      7 local eval = n.eval
      8 local command = n.command
      9 local clear = n.clear
     10 local api = n.api
     11 
     12 describe('vim.hl.range', function()
     13  local screen
     14 
     15  before_each(function()
     16    clear()
     17    screen = Screen.new(60, 6)
     18    screen:add_extra_attr_ids({
     19      [100] = { foreground = Screen.colors.Blue, background = Screen.colors.Yellow, bold = true },
     20    })
     21    api.nvim_set_option_value('list', true, {})
     22    api.nvim_set_option_value('listchars', 'eol:$', {})
     23    api.nvim_buf_set_lines(0, 0, -1, true, {
     24      'asdfghjkl',
     25      '«口=口»',
     26      'qwertyuiop',
     27      '口口=口口',
     28      'zxcvbnm',
     29    })
     30    screen:expect([[
     31      ^asdfghjkl{1:$}                                                  |
     32      «口=口»{1:$}                                                    |
     33      qwertyuiop{1:$}                                                 |
     34      口口=口口{1:$}                                                  |
     35      zxcvbnm{1:$}                                                    |
     36                                                                  |
     37    ]])
     38  end)
     39 
     40  it('works with charwise selection', function()
     41    exec_lua(function()
     42      local ns = vim.api.nvim_create_namespace('')
     43      vim.hl.range(0, ns, 'Search', { 1, 5 }, { 3, 10 })
     44    end)
     45    screen:expect([[
     46      ^asdfghjkl{1:$}                                                  |
     47      «口{10:=口»}{100:$}                                                    |
     48      {10:qwertyuiop}{100:$}                                                 |
     49      {10:口口=}{1:$}                                                  |
     50      zxcvbnm{1:$}                                                    |
     51                                                                  |
     52    ]])
     53  end)
     54 
     55  it('works with linewise selection', function()
     56    exec_lua(function()
     57      local ns = vim.api.nvim_create_namespace('')
     58      vim.hl.range(0, ns, 'Search', { 0, 0 }, { 4, 0 }, { regtype = 'V' })
     59    end)
     60    screen:expect([[
     61      {10:^asdfghjkl}{100:$}                                                  |
     62      {10:«口=口»}{100:$}                                                    |
     63      {10:qwertyuiop}{100:$}                                                 |
     64      {10:口口=口口}{100:$}                                                  |
     65      {10:zxcvbnm}{100:$}                                                    |
     66                                                                  |
     67    ]])
     68  end)
     69 
     70  it('works with blockwise selection', function()
     71    exec_lua(function()
     72      local ns = vim.api.nvim_create_namespace('')
     73      vim.hl.range(0, ns, 'Search', { 0, 0 }, { 4, 4 }, { regtype = '\022' })
     74    end)
     75    screen:expect([[
     76      {10:^asdf}ghjkl{1:$}                                                  |
     77      {10:«口=}口»{1:$}                                                    |
     78      {10:qwer}tyuiop{1:$}                                                 |
     79      {10:口口}=口口{1:$}                                                  |
     80      {10:zxcv}bnm{1:$}                                                    |
     81                                                                  |
     82    ]])
     83  end)
     84 
     85  it('works with blockwise selection with width', function()
     86    exec_lua(function()
     87      local ns = vim.api.nvim_create_namespace('')
     88      vim.hl.range(0, ns, 'Search', { 0, 4 }, { 4, 7 }, { regtype = '\0226' })
     89    end)
     90    screen:expect([[
     91      ^asdf{10:ghjkl}{1:$}                                                  |
     92      «口={10:口»}{1:$}                                                    |
     93      qwer{10:tyuiop}{1:$}                                                 |
     94      口口{10:=口口}{1:$}                                                  |
     95      zxcv{10:bnm}{1:$}                                                    |
     96                                                                  |
     97    ]])
     98  end)
     99 
    100  it('can use -1 or v:maxcol to indicate end of line', function()
    101    exec_lua(function()
    102      local ns = vim.api.nvim_create_namespace('')
    103      vim.hl.range(0, ns, 'Search', { 0, 4 }, { 1, -1 }, {})
    104      vim.hl.range(0, ns, 'Search', { 2, 6 }, { 3, vim.v.maxcol }, {})
    105    end)
    106    screen:expect([[
    107      ^asdf{10:ghjkl}{100:$}                                                  |
    108      {10:«口=口»}{100:$}                                                    |
    109      qwerty{10:uiop}{100:$}                                                 |
    110      {10:口口=口口}{1:$}                                                  |
    111      zxcvbnm{1:$}                                                    |
    112                                                                  |
    113    ]])
    114  end)
    115 
    116  it('removes highlight after given `timeout`', function()
    117    local timeout = 300
    118    exec_lua(function()
    119      local ns = vim.api.nvim_create_namespace('')
    120      vim.hl.range(0, ns, 'Search', { 0, 0 }, { 4, 0 }, { timeout = timeout })
    121    end)
    122    screen:expect({
    123      grid = [[
    124      {10:^asdfghjkl}{100:$}                                                  |
    125      {10:«口=口»}{100:$}                                                    |
    126      {10:qwertyuiop}{100:$}                                                 |
    127      {10:口口=口口}{1:$}                                                  |
    128      zxcvbnm{1:$}                                                    |
    129                                                                  |
    130    ]],
    131      timeout = timeout / 3,
    132    })
    133    screen:expect([[
    134      ^asdfghjkl{1:$}                                                  |
    135      «口=口»{1:$}                                                    |
    136      qwertyuiop{1:$}                                                 |
    137      口口=口口{1:$}                                                  |
    138      zxcvbnm{1:$}                                                    |
    139                                                                  |
    140    ]])
    141  end)
    142 
    143  it('shows multiple highlights with different timeouts simultaneously', function()
    144    local timeout1 = 300
    145    local timeout2 = 600
    146    exec_lua(function()
    147      local ns = vim.api.nvim_create_namespace('')
    148      vim.hl.range(0, ns, 'Search', { 0, 0 }, { 4, 0 }, { timeout = timeout1 })
    149      vim.hl.range(0, ns, 'Search', { 2, 6 }, { 3, 5 }, { timeout = timeout2 })
    150    end)
    151    screen:expect({
    152      grid = [[
    153        {10:^asdfghjkl}{100:$}                                                  |
    154        {10:«口=口»}{100:$}                                                    |
    155        {10:qwertyuiop}{100:$}                                                 |
    156        {10:口口=口口}{1:$}                                                  |
    157        zxcvbnm{1:$}                                                    |
    158                                                                    |
    159      ]],
    160      timeout = timeout1 / 3,
    161    })
    162    screen:expect({
    163      grid = [[
    164        ^asdfghjkl{1:$}                                                  |
    165        «口=口»{1:$}                                                    |
    166        qwerty{10:uiop}{100:$}                                                 |
    167        {10:口口}=口口{1:$}                                                  |
    168        zxcvbnm{1:$}                                                    |
    169                                                                    |
    170      ]],
    171      timeout = timeout1 + ((timeout2 - timeout1) / 3),
    172    })
    173    screen:expect([[
    174      ^asdfghjkl{1:$}                                                  |
    175      «口=口»{1:$}                                                    |
    176      qwertyuiop{1:$}                                                 |
    177      口口=口口{1:$}                                                  |
    178      zxcvbnm{1:$}                                                    |
    179                                                                  |
    180    ]])
    181  end)
    182 
    183  it('allows cancelling a highlight that has not timed out', function()
    184    exec_lua(function()
    185      local timeout = 3000
    186      local range_timer
    187      local range_hl_clear
    188      local ns = vim.api.nvim_create_namespace('')
    189      range_timer, range_hl_clear = vim.hl.range(
    190        0,
    191        ns,
    192        'Search',
    193        { 0, 0 },
    194        { 4, 0 },
    195        { timeout = timeout }
    196      )
    197      if range_timer and not range_timer:is_closing() then
    198        range_timer:close()
    199        assert(range_hl_clear)
    200        range_hl_clear()
    201        range_hl_clear() -- Exercise redundant call
    202      end
    203    end)
    204    screen:expect({
    205      grid = [[
    206        ^asdfghjkl{1:$}                                                  |
    207        «口=口»{1:$}                                                    |
    208        qwertyuiop{1:$}                                                 |
    209        口口=口口{1:$}                                                  |
    210        zxcvbnm{1:$}                                                    |
    211                                                                    |
    212      ]],
    213      unchanged = true,
    214    })
    215  end)
    216 end)
    217 
    218 describe('vim.hl.on_yank', function()
    219  before_each(function()
    220    clear()
    221  end)
    222 
    223  it('does not show errors even if buffer is wiped before timeout', function()
    224    command('new')
    225    n.feed('ifoo<esc>') -- set '[, ']
    226    exec_lua(function()
    227      vim.hl.on_yank({
    228        timeout = 10,
    229        on_macro = true,
    230        event = { operator = 'y', regtype = 'v' },
    231      })
    232      vim.cmd('bwipeout!')
    233    end)
    234    vim.uv.sleep(10)
    235    n.feed('<cr>') -- avoid hang if error message exists
    236    eq('', eval('v:errmsg'))
    237  end)
    238 
    239  it('does not close timer twice', function()
    240    exec_lua(function()
    241      vim.hl.on_yank({ timeout = 10, on_macro = true, event = { operator = 'y' } })
    242      vim.uv.sleep(10)
    243      vim.schedule(function()
    244        vim.hl.on_yank({ timeout = 0, on_macro = true, event = { operator = 'y' } })
    245      end)
    246    end)
    247    eq('', eval('v:errmsg'))
    248  end)
    249 
    250  it('does not show in another window', function()
    251    command('vsplit')
    252    exec_lua(function()
    253      vim.api.nvim_buf_set_mark(0, '[', 1, 1, {})
    254      vim.api.nvim_buf_set_mark(0, ']', 1, 1, {})
    255      vim.hl.on_yank({ timeout = math.huge, on_macro = true, event = { operator = 'y' } })
    256    end)
    257    local ns = api.nvim_create_namespace('nvim.hlyank')
    258    local win = api.nvim_get_current_win()
    259    eq({ win }, api.nvim__ns_get(ns).wins)
    260    command('wincmd w')
    261    eq({ win }, api.nvim__ns_get(ns).wins)
    262    -- Use a new vim.hl.on_yank() call to cancel the previous timer
    263    exec_lua(function()
    264      vim.hl.on_yank({ timeout = 0, on_macro = true, event = { operator = 'y' } })
    265    end)
    266  end)
    267 
    268  it('removes old highlight if new one is created before old one times out', function()
    269    command('vnew')
    270    exec_lua(function()
    271      vim.api.nvim_buf_set_mark(0, '[', 1, 1, {})
    272      vim.api.nvim_buf_set_mark(0, ']', 1, 1, {})
    273      vim.hl.on_yank({ timeout = math.huge, on_macro = true, event = { operator = 'y' } })
    274    end)
    275    local ns = api.nvim_create_namespace('nvim.hlyank')
    276    eq(api.nvim_get_current_win(), api.nvim__ns_get(ns).wins[1])
    277    command('wincmd w')
    278    exec_lua(function()
    279      vim.api.nvim_buf_set_mark(0, '[', 1, 1, {})
    280      vim.api.nvim_buf_set_mark(0, ']', 1, 1, {})
    281      vim.hl.on_yank({ timeout = math.huge, on_macro = true, event = { operator = 'y' } })
    282    end)
    283    local win = api.nvim_get_current_win()
    284    eq({ win }, api.nvim__ns_get(ns).wins)
    285    command('wincmd w')
    286    eq({ win }, api.nvim__ns_get(ns).wins)
    287    -- Use a new vim.hl.on_yank() call to cancel the previous timer
    288    exec_lua(function()
    289      vim.hl.on_yank({ timeout = 0, on_macro = true, event = { operator = 'y' } })
    290    end)
    291  end)
    292 
    293  it('highlights last character with exclusive motion', function()
    294    local screen = Screen.new(60, 4)
    295    screen:add_extra_attr_ids({
    296      [100] = { foreground = Screen.colors.Blue, background = Screen.colors.Yellow, bold = true },
    297    })
    298    command('autocmd TextYankPost * lua vim.hl.on_yank{timeout=100000}')
    299    api.nvim_buf_set_lines(0, 0, -1, true, {
    300      [[foo(bar) 'baz']],
    301      [[foo(bar) 'baz']],
    302    })
    303    n.feed('yw')
    304    screen:expect([[
    305      {2:^foo}(bar) 'baz'                                              |
    306      foo(bar) 'baz'                                              |
    307      {1:~                                                           }|
    308                                                                  |
    309    ]])
    310    n.feed("yi'")
    311    screen:expect([[
    312      foo(bar) '{2:^baz}'                                              |
    313      foo(bar) 'baz'                                              |
    314      {1:~                                                           }|
    315                                                                  |
    316    ]])
    317    n.feed('yvj')
    318    screen:expect([[
    319      foo(bar) '{2:^baz'}                                              |
    320      {2:foo(bar) '}baz'                                              |
    321      {1:~                                                           }|
    322                                                                  |
    323    ]])
    324    -- Use a new vim.hl.on_yank() call to cancel the previous timer
    325    exec_lua(function()
    326      vim.hl.on_yank({ timeout = 0, on_macro = true, event = { operator = 'y' } })
    327    end)
    328  end)
    329 end)