neovim

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

dirchanged_spec.lua (13622B)


      1 local t = require('test.testutil')
      2 local n = require('test.functional.testnvim')()
      3 
      4 local clear = n.clear
      5 local command = n.command
      6 local eq = t.eq
      7 local eval = n.eval
      8 local request = n.request
      9 local is_os = t.is_os
     10 
     11 describe('autocmd DirChanged and DirChangedPre', function()
     12  local curdir = t.fix_slashes(vim.uv.cwd())
     13  local dirs = {
     14    curdir .. '/Xtest-functional-autocmd-dirchanged.dir1',
     15    curdir .. '/Xtest-functional-autocmd-dirchanged.dir2',
     16    curdir .. '/Xtest-functional-autocmd-dirchanged.dir3',
     17  }
     18  local win_dirs = {
     19    curdir .. '\\XTEST-FUNCTIONAL-AUTOCMD-DIRCHANGED.DIR1',
     20    curdir .. '\\XTEST-FUNCTIONAL-AUTOCMD-DIRCHANGED.DIR2',
     21    curdir .. '\\XTEST-FUNCTIONAL-AUTOCMD-DIRCHANGED.DIR3',
     22  }
     23 
     24  setup(function()
     25    for _, dir in pairs(dirs) do
     26      t.mkdir(dir)
     27    end
     28  end)
     29  teardown(function()
     30    for _, dir in pairs(dirs) do
     31      n.rmdir(dir)
     32    end
     33  end)
     34 
     35  before_each(function()
     36    clear()
     37    command(
     38      'autocmd DirChangedPre * let [g:evpre, g:amatchpre, g:cdprecount] '
     39        .. '= [copy(v:event), expand("<amatch>"), 1 + get(g:, "cdprecount", 0)]'
     40    )
     41    command(
     42      'autocmd DirChanged * let [g:getcwd, g:ev, g:amatch, g:cdcount] '
     43        .. '= [getcwd(), copy(v:event), expand("<amatch>"), 1 + get(g:, "cdcount", 0)]'
     44    )
     45    -- Normalize path separators.
     46    command(
     47      [[autocmd DirChangedPre * let g:evpre['directory'] = substitute(g:evpre['directory'], '\\', '/', 'g')]]
     48    )
     49    command([[autocmd DirChanged * let g:ev['cwd'] = substitute(g:ev['cwd'], '\\', '/', 'g')]])
     50    command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]])
     51  end)
     52 
     53  it('set v:event and <amatch>', function()
     54    command('lcd ' .. dirs[1])
     55    eq({ directory = dirs[1], scope = 'window', changed_window = false }, eval('g:evpre'))
     56    eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev'))
     57    eq('window', eval('g:amatchpre'))
     58    eq('window', eval('g:amatch'))
     59    eq(1, eval('g:cdprecount'))
     60    eq(1, eval('g:cdcount'))
     61 
     62    command('tcd ' .. dirs[2])
     63    eq({ directory = dirs[2], scope = 'tabpage', changed_window = false }, eval('g:evpre'))
     64    eq({ cwd = dirs[2], scope = 'tabpage', changed_window = false }, eval('g:ev'))
     65    eq('tabpage', eval('g:amatchpre'))
     66    eq('tabpage', eval('g:amatch'))
     67    eq(2, eval('g:cdprecount'))
     68    eq(2, eval('g:cdcount'))
     69 
     70    command('cd ' .. dirs[3])
     71    eq({ directory = dirs[3], scope = 'global', changed_window = false }, eval('g:evpre'))
     72    eq({ cwd = dirs[3], scope = 'global', changed_window = false }, eval('g:ev'))
     73    eq('global', eval('g:amatchpre'))
     74    eq('global', eval('g:amatch'))
     75    eq(3, eval('g:cdprecount'))
     76    eq(3, eval('g:cdcount'))
     77  end)
     78 
     79  it('DirChanged set getcwd() during event #6260', function()
     80    command('lcd ' .. dirs[1])
     81    eq(dirs[1], eval('g:getcwd'))
     82 
     83    command('tcd ' .. dirs[2])
     84    eq(dirs[2], eval('g:getcwd'))
     85 
     86    command('cd ' .. dirs[3])
     87    eq(dirs[3], eval('g:getcwd'))
     88  end)
     89 
     90  it('disallow recursion', function()
     91    command('set shellslash')
     92    -- Set up a _nested_ handler.
     93    command('autocmd DirChanged * nested lcd ' .. dirs[3])
     94    command('lcd ' .. dirs[1])
     95    eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev'))
     96    eq(1, eval('g:cdcount'))
     97    -- autocmd changed to dirs[3], but did NOT trigger another DirChanged.
     98    eq(dirs[3], eval('getcwd()'))
     99  end)
    100 
    101  it('only DirChangedPre is triggered if :cd fails', function()
    102    command('let g:ev = {}')
    103    command('let g:cdcount = 0')
    104 
    105    local status1, err1 = pcall(function()
    106      command('lcd ' .. dirs[1] .. '/doesnotexist')
    107    end)
    108    eq(
    109      { directory = dirs[1] .. '/doesnotexist', scope = 'window', changed_window = false },
    110      eval('g:evpre')
    111    )
    112    eq({}, eval('g:ev'))
    113    eq('window', eval('g:amatchpre'))
    114    eq(1, eval('g:cdprecount'))
    115    eq(0, eval('g:cdcount'))
    116 
    117    local status2, err2 = pcall(function()
    118      command('lcd ' .. dirs[2] .. '/doesnotexist')
    119    end)
    120    eq(
    121      { directory = dirs[2] .. '/doesnotexist', scope = 'window', changed_window = false },
    122      eval('g:evpre')
    123    )
    124    eq({}, eval('g:ev'))
    125    eq('window', eval('g:amatchpre'))
    126    eq(2, eval('g:cdprecount'))
    127    eq(0, eval('g:cdcount'))
    128 
    129    local status3, err3 = pcall(function()
    130      command('lcd ' .. dirs[3] .. '/doesnotexist')
    131    end)
    132    eq(
    133      { directory = dirs[3] .. '/doesnotexist', scope = 'window', changed_window = false },
    134      eval('g:evpre')
    135    )
    136    eq({}, eval('g:ev'))
    137    eq('window', eval('g:amatchpre'))
    138    eq(3, eval('g:cdprecount'))
    139    eq(0, eval('g:cdcount'))
    140 
    141    eq(false, status1)
    142    eq(false, status2)
    143    eq(false, status3)
    144 
    145    eq('E344:', string.match(err1, 'E%d*:'))
    146    eq('E344:', string.match(err2, 'E%d*:'))
    147    eq('E344:', string.match(err3, 'E%d*:'))
    148  end)
    149 
    150  it("are triggered by 'autochdir'", function()
    151    command('set autochdir')
    152 
    153    command('split ' .. dirs[1] .. '/foo')
    154    eq({ directory = dirs[1], scope = 'window', changed_window = false }, eval('g:evpre'))
    155    eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev'))
    156    eq('auto', eval('g:amatchpre'))
    157    eq('auto', eval('g:amatch'))
    158    eq(1, eval('g:cdprecount'))
    159    eq(1, eval('g:cdcount'))
    160 
    161    command('split ' .. dirs[2] .. '/bar')
    162    eq({ directory = dirs[2], scope = 'window', changed_window = false }, eval('g:evpre'))
    163    eq({ cwd = dirs[2], scope = 'window', changed_window = false }, eval('g:ev'))
    164    eq('auto', eval('g:amatch'))
    165    eq(2, eval('g:cdprecount'))
    166    eq(2, eval('g:cdcount'))
    167  end)
    168 
    169  it('do not trigger if directory has not changed', function()
    170    command('lcd ' .. dirs[1])
    171    eq({ directory = dirs[1], scope = 'window', changed_window = false }, eval('g:evpre'))
    172    eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev'))
    173    eq('window', eval('g:amatchpre'))
    174    eq('window', eval('g:amatch'))
    175    eq(1, eval('g:cdprecount'))
    176    eq(1, eval('g:cdcount'))
    177    command('let g:evpre = {}')
    178    command('let g:ev = {}')
    179    command('lcd ' .. dirs[1])
    180    eq({}, eval('g:evpre'))
    181    eq({}, eval('g:ev'))
    182    eq(1, eval('g:cdprecount'))
    183    eq(1, eval('g:cdcount'))
    184 
    185    if is_os('win') then
    186      command('lcd ' .. win_dirs[1])
    187      eq({}, eval('g:evpre'))
    188      eq({}, eval('g:ev'))
    189      eq(1, eval('g:cdprecount'))
    190      eq(1, eval('g:cdcount'))
    191    end
    192 
    193    command('tcd ' .. dirs[2])
    194    eq({ directory = dirs[2], scope = 'tabpage', changed_window = false }, eval('g:evpre'))
    195    eq({ cwd = dirs[2], scope = 'tabpage', changed_window = false }, eval('g:ev'))
    196    eq('tabpage', eval('g:amatchpre'))
    197    eq('tabpage', eval('g:amatch'))
    198    eq(2, eval('g:cdprecount'))
    199    eq(2, eval('g:cdcount'))
    200    command('let g:evpre = {}')
    201    command('let g:ev = {}')
    202    command('tcd ' .. dirs[2])
    203    eq({}, eval('g:evpre'))
    204    eq({}, eval('g:ev'))
    205    eq(2, eval('g:cdprecount'))
    206    eq(2, eval('g:cdcount'))
    207 
    208    if is_os('win') then
    209      command('tcd ' .. win_dirs[2])
    210      eq({}, eval('g:evpre'))
    211      eq({}, eval('g:ev'))
    212      eq(2, eval('g:cdprecount'))
    213      eq(2, eval('g:cdcount'))
    214    end
    215 
    216    command('cd ' .. dirs[3])
    217    eq({ directory = dirs[3], scope = 'global', changed_window = false }, eval('g:evpre'))
    218    eq({ cwd = dirs[3], scope = 'global', changed_window = false }, eval('g:ev'))
    219    eq('global', eval('g:amatch'))
    220    eq(3, eval('g:cdprecount'))
    221    eq(3, eval('g:cdcount'))
    222    command('let g:evpre = {}')
    223    command('let g:ev = {}')
    224    command('cd ' .. dirs[3])
    225    eq({}, eval('g:evpre'))
    226    eq({}, eval('g:ev'))
    227    eq(3, eval('g:cdprecount'))
    228    eq(3, eval('g:cdcount'))
    229 
    230    if is_os('win') then
    231      command('cd ' .. win_dirs[3])
    232      eq({}, eval('g:evpre'))
    233      eq({}, eval('g:ev'))
    234      eq(3, eval('g:cdprecount'))
    235      eq(3, eval('g:cdcount'))
    236    end
    237 
    238    command('set autochdir')
    239 
    240    command('split ' .. dirs[1] .. '/foo')
    241    eq({ directory = dirs[1], scope = 'window', changed_window = false }, eval('g:evpre'))
    242    eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev'))
    243    eq('auto', eval('g:amatchpre'))
    244    eq('auto', eval('g:amatch'))
    245    eq(4, eval('g:cdprecount'))
    246    eq(4, eval('g:cdcount'))
    247    command('let g:evpre = {}')
    248    command('let g:ev = {}')
    249    command('split ' .. dirs[1] .. '/bar')
    250    eq({}, eval('g:evpre'))
    251    eq({}, eval('g:ev'))
    252    eq(4, eval('g:cdprecount'))
    253    eq(4, eval('g:cdcount'))
    254 
    255    if is_os('win') then
    256      command('split ' .. win_dirs[1] .. '/baz')
    257      eq({}, eval('g:evpre'))
    258      eq({}, eval('g:ev'))
    259      eq(4, eval('g:cdprecount'))
    260      eq(4, eval('g:cdcount'))
    261    end
    262  end)
    263 
    264  it('are triggered by switching to win/tab with different CWD #6054', function()
    265    command('lcd ' .. dirs[3]) -- window 3
    266    command('split ' .. dirs[2] .. '/foo') -- window 2
    267    command('lcd ' .. dirs[2])
    268    command('split ' .. dirs[1] .. '/bar') -- window 1
    269    command('lcd ' .. dirs[1])
    270 
    271    command('2wincmd w') -- window 2
    272    eq({ directory = dirs[2], scope = 'window', changed_window = true }, eval('g:evpre'))
    273    eq({ cwd = dirs[2], scope = 'window', changed_window = true }, eval('g:ev'))
    274    eq('window', eval('g:amatchpre'))
    275    eq('window', eval('g:amatch'))
    276 
    277    eq(4, eval('g:cdprecount'))
    278    eq(4, eval('g:cdcount'))
    279    command('tabnew') -- tab 2 (tab-local CWD)
    280    eq(4, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    281    eq(4, eval('g:cdcount')) -- same CWD, no DirChanged event
    282    command('tcd ' .. dirs[3])
    283    command('tabnext') -- tab 1 (no tab-local CWD)
    284    eq({ directory = dirs[2], scope = 'window', changed_window = true }, eval('g:evpre'))
    285    eq({ cwd = dirs[2], scope = 'window', changed_window = true }, eval('g:ev'))
    286    eq('window', eval('g:amatchpre'))
    287    eq('window', eval('g:amatch'))
    288    command('tabnext') -- tab 2
    289    eq({ directory = dirs[3], scope = 'tabpage', changed_window = true }, eval('g:evpre'))
    290    eq({ cwd = dirs[3], scope = 'tabpage', changed_window = true }, eval('g:ev'))
    291    eq('tabpage', eval('g:amatchpre'))
    292    eq('tabpage', eval('g:amatch'))
    293    eq(7, eval('g:cdprecount'))
    294    eq(7, eval('g:cdcount'))
    295 
    296    command('tabnext') -- tab 1
    297    command('3wincmd w') -- window 3
    298    eq(9, eval('g:cdprecount'))
    299    eq(9, eval('g:cdcount'))
    300    command('tabnext') -- tab 2 (has the *same* CWD)
    301    eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    302    eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    303 
    304    if is_os('win') then
    305      command('tabnew') -- tab 3
    306      eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    307      eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    308      command('tcd ' .. win_dirs[3])
    309      eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    310      eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    311      command('tabnext') -- tab 1
    312      eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    313      eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    314      command('tabprevious') -- tab 3
    315      eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    316      eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    317      command('tabprevious') -- tab 2
    318      eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    319      eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    320      command('tabprevious') -- tab 1
    321      eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    322      eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    323      command('lcd ' .. win_dirs[3]) -- window 3
    324      eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    325      eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    326      command('tabnext') -- tab 2
    327      eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    328      eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    329      command('tabnext') -- tab 3
    330      eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    331      eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    332      command('tabnext') -- tab 1
    333      eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    334      eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    335      command('tabprevious') -- tab 3
    336      eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
    337      eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
    338    end
    339  end)
    340 
    341  it('are triggered by nvim_set_current_dir()', function()
    342    request('nvim_set_current_dir', dirs[1])
    343    eq({ directory = dirs[1], scope = 'global', changed_window = false }, eval('g:evpre'))
    344    eq({ cwd = dirs[1], scope = 'global', changed_window = false }, eval('g:ev'))
    345    eq(1, eval('g:cdprecount'))
    346    eq(1, eval('g:cdcount'))
    347 
    348    request('nvim_set_current_dir', dirs[2])
    349    eq({ directory = dirs[2], scope = 'global', changed_window = false }, eval('g:evpre'))
    350    eq({ cwd = dirs[2], scope = 'global', changed_window = false }, eval('g:ev'))
    351    eq(2, eval('g:cdprecount'))
    352    eq(2, eval('g:cdcount'))
    353 
    354    eq(
    355      'Vim:E344: Can\'t find directory "/doesnotexist" in cdpath',
    356      t.pcall_err(request, 'nvim_set_current_dir', '/doesnotexist')
    357    )
    358    eq({ directory = '/doesnotexist', scope = 'global', changed_window = false }, eval('g:evpre'))
    359    eq(3, eval('g:cdprecount'))
    360    eq(2, eval('g:cdcount'))
    361  end)
    362 
    363  it('work when local to buffer', function()
    364    command('let g:triggeredpre = 0')
    365    command('let g:triggered = 0')
    366    command('autocmd DirChangedPre <buffer> let g:triggeredpre = 1')
    367    command('autocmd DirChanged <buffer> let g:triggered = 1')
    368    command('cd ' .. dirs[1])
    369    eq(1, eval('g:triggeredpre'))
    370    eq(1, eval('g:triggered'))
    371  end)
    372 end)