neovim

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

cursor_spec.lua (10644B)


      1 local t = require('test.testutil')
      2 local n = require('test.functional.testnvim')()
      3 local Screen = require('test.functional.ui.screen')
      4 
      5 local clear, api = n.clear, n.api
      6 local eq = t.eq
      7 local command = n.command
      8 
      9 describe('ui/cursor', function()
     10  local screen
     11 
     12  before_each(function()
     13    clear()
     14    screen = Screen.new(25, 5)
     15  end)
     16 
     17  it("'guicursor' is published as a UI event", function()
     18    local expected_mode_info = {
     19      [1] = {
     20        blinkoff = 0,
     21        blinkon = 0,
     22        blinkwait = 0,
     23        cell_percentage = 0,
     24        cursor_shape = 'block',
     25        name = 'normal',
     26        hl_id = 0,
     27        id_lm = 0,
     28        attr = {},
     29        attr_lm = {},
     30        mouse_shape = 0,
     31        short_name = 'n',
     32      },
     33      [2] = {
     34        blinkoff = 0,
     35        blinkon = 0,
     36        blinkwait = 0,
     37        cell_percentage = 0,
     38        cursor_shape = 'block',
     39        name = 'visual',
     40        hl_id = 0,
     41        id_lm = 0,
     42        attr = {},
     43        attr_lm = {},
     44        mouse_shape = 0,
     45        short_name = 'v',
     46      },
     47      [3] = {
     48        blinkoff = 0,
     49        blinkon = 0,
     50        blinkwait = 0,
     51        cell_percentage = 25,
     52        cursor_shape = 'vertical',
     53        name = 'insert',
     54        hl_id = 0,
     55        id_lm = 0,
     56        attr = {},
     57        attr_lm = {},
     58        mouse_shape = 0,
     59        short_name = 'i',
     60      },
     61      [4] = {
     62        blinkoff = 0,
     63        blinkon = 0,
     64        blinkwait = 0,
     65        cell_percentage = 20,
     66        cursor_shape = 'horizontal',
     67        name = 'replace',
     68        hl_id = 0,
     69        id_lm = 0,
     70        attr = {},
     71        attr_lm = {},
     72        mouse_shape = 0,
     73        short_name = 'r',
     74      },
     75      [5] = {
     76        blinkoff = 0,
     77        blinkon = 0,
     78        blinkwait = 0,
     79        cell_percentage = 0,
     80        cursor_shape = 'block',
     81        name = 'cmdline_normal',
     82        hl_id = 0,
     83        id_lm = 0,
     84        attr = {},
     85        attr_lm = {},
     86        mouse_shape = 0,
     87        short_name = 'c',
     88      },
     89      [6] = {
     90        blinkoff = 0,
     91        blinkon = 0,
     92        blinkwait = 0,
     93        cell_percentage = 25,
     94        cursor_shape = 'vertical',
     95        name = 'cmdline_insert',
     96        hl_id = 0,
     97        id_lm = 0,
     98        attr = {},
     99        attr_lm = {},
    100        mouse_shape = 0,
    101        short_name = 'ci',
    102      },
    103      [7] = {
    104        blinkoff = 0,
    105        blinkon = 0,
    106        blinkwait = 0,
    107        cell_percentage = 20,
    108        cursor_shape = 'horizontal',
    109        name = 'cmdline_replace',
    110        hl_id = 0,
    111        id_lm = 0,
    112        attr = {},
    113        attr_lm = {},
    114        mouse_shape = 0,
    115        short_name = 'cr',
    116      },
    117      [8] = {
    118        blinkoff = 0,
    119        blinkon = 0,
    120        blinkwait = 0,
    121        cell_percentage = 20,
    122        cursor_shape = 'horizontal',
    123        name = 'operator',
    124        hl_id = 0,
    125        id_lm = 0,
    126        attr = {},
    127        attr_lm = {},
    128        mouse_shape = 0,
    129        short_name = 'o',
    130      },
    131      [9] = {
    132        blinkoff = 0,
    133        blinkon = 0,
    134        blinkwait = 0,
    135        cell_percentage = 25,
    136        cursor_shape = 'vertical',
    137        name = 'visual_select',
    138        hl_id = 0,
    139        id_lm = 0,
    140        attr = {},
    141        attr_lm = {},
    142        mouse_shape = 0,
    143        short_name = 've',
    144      },
    145      [10] = {
    146        name = 'cmdline_hover',
    147        mouse_shape = 0,
    148        short_name = 'e',
    149      },
    150      [11] = {
    151        name = 'statusline_hover',
    152        mouse_shape = 0,
    153        short_name = 's',
    154      },
    155      [12] = {
    156        name = 'statusline_drag',
    157        mouse_shape = 0,
    158        short_name = 'sd',
    159      },
    160      [13] = {
    161        name = 'vsep_hover',
    162        mouse_shape = 0,
    163        short_name = 'vs',
    164      },
    165      [14] = {
    166        name = 'vsep_drag',
    167        mouse_shape = 0,
    168        short_name = 'vd',
    169      },
    170      [15] = {
    171        name = 'more',
    172        mouse_shape = 0,
    173        short_name = 'm',
    174      },
    175      [16] = {
    176        name = 'more_lastline',
    177        mouse_shape = 0,
    178        short_name = 'ml',
    179      },
    180      [17] = {
    181        blinkoff = 0,
    182        blinkon = 0,
    183        blinkwait = 0,
    184        cell_percentage = 0,
    185        cursor_shape = 'block',
    186        name = 'showmatch',
    187        hl_id = 0,
    188        id_lm = 0,
    189        attr = {},
    190        attr_lm = {},
    191        short_name = 'sm',
    192      },
    193      [18] = {
    194        blinkoff = 500,
    195        blinkon = 500,
    196        blinkwait = 0,
    197        cell_percentage = 0,
    198        cursor_shape = 'block',
    199        name = 'terminal',
    200        hl_id = 3,
    201        id_lm = 3,
    202        attr = { reverse = true },
    203        attr_lm = { reverse = true },
    204        short_name = 't',
    205      },
    206    }
    207 
    208    screen:expect(function()
    209      -- Default 'guicursor', published on startup.
    210      eq(expected_mode_info, screen._mode_info)
    211      eq(true, screen._cursor_style_enabled)
    212      eq('normal', screen.mode)
    213    end)
    214 
    215    -- Event is published ONLY if the cursor style changed.
    216    screen._mode_info = nil
    217    command("echo 'test'")
    218    screen:expect {
    219      grid = [[
    220      ^                         |
    221      {1:~                        }|*3
    222      test                     |
    223    ]],
    224      condition = function()
    225        eq(nil, screen._mode_info)
    226      end,
    227    }
    228 
    229    -- Change the cursor style.
    230    n.command('hi Cursor guibg=DarkGray')
    231    n.command(
    232      'set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr-o:hor20'
    233        .. ',a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor'
    234        .. ',sm:block-blinkwait175-blinkoff150-blinkon175'
    235    )
    236 
    237    -- Update the expected values.
    238    for _, m in ipairs(expected_mode_info) do
    239      if m.name == 'showmatch' then
    240        if m.blinkon then
    241          m.blinkon = 175
    242        end
    243        if m.blinkoff then
    244          m.blinkoff = 150
    245        end
    246        if m.blinkwait then
    247          m.blinkwait = 175
    248        end
    249      else
    250        if m.blinkon then
    251          m.blinkon = 250
    252        end
    253        if m.blinkoff then
    254          m.blinkoff = 400
    255        end
    256        if m.blinkwait then
    257          m.blinkwait = 700
    258        end
    259      end
    260      if m.hl_id then
    261        m.hl_id = 67
    262        m.attr = { background = Screen.colors.DarkGray }
    263      end
    264      if m.id_lm then
    265        m.id_lm = 78
    266        m.attr_lm = {}
    267      end
    268    end
    269 
    270    -- Assert the new expectation.
    271    screen:expect(function()
    272      for i, v in ipairs(expected_mode_info) do
    273        eq(v, screen._mode_info[i])
    274      end
    275      eq(true, screen._cursor_style_enabled)
    276      eq('normal', screen.mode)
    277    end)
    278 
    279    -- Change hl groups only, should update the styles
    280    n.command('hi Cursor guibg=Red')
    281    n.command('hi lCursor guibg=Green')
    282 
    283    -- Update the expected values.
    284    for _, m in ipairs(expected_mode_info) do
    285      if m.hl_id then
    286        m.attr = { background = Screen.colors.Red }
    287      end
    288      if m.id_lm then
    289        m.attr_lm = { background = Screen.colors.Green }
    290      end
    291    end
    292    -- Assert the new expectation.
    293    screen:expect(function()
    294      eq(expected_mode_info, screen._mode_info)
    295      eq(true, screen._cursor_style_enabled)
    296      eq('normal', screen.mode)
    297    end)
    298 
    299    -- update the highlight again to hide cursor
    300    n.command('hi Cursor blend=100')
    301 
    302    for _, m in ipairs(expected_mode_info) do
    303      if m.hl_id then
    304        m.attr = { background = Screen.colors.Red, blend = 100 }
    305      end
    306    end
    307    screen:expect {
    308      grid = [[
    309      ^                         |
    310      {1:~                        }|*3
    311      test                     |
    312    ]],
    313      condition = function()
    314        eq(expected_mode_info, screen._mode_info)
    315      end,
    316    }
    317 
    318    -- Another cursor style.
    319    api.nvim_set_option_value(
    320      'guicursor',
    321      'n-v-c:ver35-blinkwait171-blinkoff172-blinkon173'
    322        .. ',ve:hor35,o:ver50,i-ci:block,r-cr:hor90,sm:ver42',
    323      {}
    324    )
    325    screen:expect(function()
    326      local named = {}
    327      for _, m in ipairs(screen._mode_info) do
    328        named[m.name] = m
    329      end
    330      eq('vertical', named.normal.cursor_shape)
    331      eq(35, named.normal.cell_percentage)
    332      eq('horizontal', named.visual_select.cursor_shape)
    333      eq(35, named.visual_select.cell_percentage)
    334      eq('vertical', named.operator.cursor_shape)
    335      eq(50, named.operator.cell_percentage)
    336      eq('block', named.insert.cursor_shape)
    337      eq('vertical', named.showmatch.cursor_shape)
    338      eq(90, named.cmdline_replace.cell_percentage)
    339      eq(171, named.normal.blinkwait)
    340      eq(172, named.normal.blinkoff)
    341      eq(173, named.normal.blinkon)
    342      eq(42, named.showmatch.cell_percentage)
    343    end)
    344 
    345    -- If there is no setting for guicursor, it becomes the default setting.
    346    api.nvim_set_option_value(
    347      'guicursor',
    348      'n:ver35-blinkwait171-blinkoff172-blinkon173-Cursor/lCursor',
    349      {}
    350    )
    351    screen:expect(function()
    352      for _, m in ipairs(screen._mode_info) do
    353        if m.name ~= 'normal' then
    354          eq('block', m.cursor_shape or 'block')
    355          eq(0, m.blinkon or 0)
    356          eq(0, m.blinkoff or 0)
    357          eq(0, m.blinkwait or 0)
    358          eq(0, m.hl_id or 0)
    359          eq(0, m.id_lm or 0)
    360        end
    361      end
    362    end)
    363  end)
    364 
    365  it("empty 'guicursor' sets cursor_shape=block in all modes", function()
    366    api.nvim_set_option_value('guicursor', '', {})
    367    screen:expect(function()
    368      -- Empty 'guicursor' sets enabled=false.
    369      eq(false, screen._cursor_style_enabled)
    370      for _, m in ipairs(screen._mode_info) do
    371        if m['cursor_shape'] ~= nil then
    372          eq('block', m.cursor_shape)
    373          eq(0, m.blinkon)
    374          eq(0, m.hl_id)
    375          eq(0, m.id_lm)
    376        end
    377      end
    378    end)
    379  end)
    380 
    381  it(':sleep does not hide cursor when sleeping', function()
    382    n.feed(':sleep 300m | echo 42')
    383    screen:expect([[
    384                               |
    385      {1:~                        }|*3
    386      :sleep 300m | echo 42^    |
    387    ]])
    388    n.feed('\n')
    389    screen:expect({
    390      grid = [[
    391      ^                         |
    392      {1:~                        }|*3
    393      :sleep 300m | echo 42    |
    394    ]],
    395      timeout = 100,
    396    })
    397    screen:expect([[
    398      ^                         |
    399      {1:~                        }|*3
    400      42                       |
    401    ]])
    402  end)
    403 
    404  it(':sleep! hides cursor when sleeping', function()
    405    n.feed(':sleep! 300m | echo 42')
    406    screen:expect([[
    407                               |
    408      {1:~                        }|*3
    409      :sleep! 300m | echo 42^   |
    410    ]])
    411    n.feed('\n')
    412    screen:expect({
    413      grid = [[
    414                               |
    415      {1:~                        }|*3
    416      :sleep! 300m | echo 42   |
    417    ]],
    418      timeout = 100,
    419    })
    420    screen:expect([[
    421      ^                         |
    422      {1:~                        }|*3
    423      42                       |
    424    ]])
    425  end)
    426 end)