cd_spec.lua (10664B)
1 -- Specs for :cd, :tcd, :lcd and getcwd() 2 3 local t = require('test.testutil') 4 local n = require('test.functional.testnvim')() 5 6 local eq = t.eq 7 local call = n.call 8 local clear = n.clear 9 local command = n.command 10 local exc_exec = n.exc_exec 11 local pathsep = n.get_pathsep() 12 local skip = t.skip 13 local is_os = t.is_os 14 local mkdir = t.mkdir 15 16 -- These directories will be created for testing 17 local directories = { 18 tab = 'Xtest-functional-ex_cmds-cd_spec.tab', -- Tab 19 window = 'Xtest-functional-ex_cmds-cd_spec.window', -- Window 20 global = 'Xtest-functional-ex_cmds-cd_spec.global', -- New global 21 } 22 23 -- Shorthand writing to get the current working directory 24 local cwd = function(...) 25 return call('getcwd', ...) 26 end -- effective working dir 27 local wcwd = function() 28 return cwd(0) 29 end -- window dir 30 local tcwd = function() 31 return cwd(-1, 0) 32 end -- tab dir 33 34 -- Same, except these tell us if there is a working directory at all 35 local lwd = function(...) 36 return call('haslocaldir', ...) 37 end -- effective working dir 38 local wlwd = function() 39 return lwd(0) 40 end -- window dir 41 local tlwd = function() 42 return lwd(-1, 0) 43 end -- tab dir 44 --local glwd = function() return eval('haslocaldir(-1, -1)') end -- global dir 45 46 -- Test both the `cd` and `chdir` variants 47 for _, cmd in ipairs { 'cd', 'chdir' } do 48 describe(':' .. cmd, function() 49 before_each(function() 50 clear() 51 for _, d in pairs(directories) do 52 mkdir(d) 53 end 54 directories.start = cwd() 55 end) 56 57 after_each(function() 58 for _, d in pairs(directories) do 59 vim.uv.fs_rmdir(d) 60 end 61 end) 62 63 describe('using explicit scope', function() 64 it('for window', function() 65 local globalDir = directories.start 66 local globalwin = call('winnr') 67 local tabnr = call('tabpagenr') 68 69 -- Everything matches globalDir to start 70 eq(globalDir, cwd(globalwin)) 71 eq(globalDir, cwd(globalwin, tabnr)) 72 eq(0, lwd(globalwin)) 73 eq(0, lwd(globalwin, tabnr)) 74 75 command('bot split') 76 local localwin = call('winnr') 77 -- Initial window is still using globalDir 78 eq(globalDir, cwd(localwin)) 79 eq(globalDir, cwd(localwin, tabnr)) 80 eq(0, lwd(globalwin)) 81 eq(0, lwd(globalwin, tabnr)) 82 83 command('silent l' .. cmd .. ' ' .. directories.window) 84 -- From window with local dir, the original window 85 -- is still reporting the global dir 86 eq(globalDir, cwd(globalwin)) 87 eq(globalDir, cwd(globalwin, tabnr)) 88 eq(0, lwd(globalwin)) 89 eq(0, lwd(globalwin, tabnr)) 90 91 -- Window with local dir reports as such 92 eq(globalDir .. pathsep .. directories.window, cwd(localwin)) 93 eq(globalDir .. pathsep .. directories.window, cwd(localwin, tabnr)) 94 eq(1, lwd(localwin)) 95 eq(1, lwd(localwin, tabnr)) 96 97 command('tabnew') 98 -- From new tab page, original window reports global dir 99 eq(globalDir, cwd(globalwin, tabnr)) 100 eq(0, lwd(globalwin, tabnr)) 101 102 -- From new tab page, local window reports as such 103 eq(globalDir .. pathsep .. directories.window, cwd(localwin, tabnr)) 104 eq(1, lwd(localwin, tabnr)) 105 end) 106 107 it('for tab page', function() 108 local globalDir = directories.start 109 local globaltab = call('tabpagenr') 110 111 -- Everything matches globalDir to start 112 eq(globalDir, cwd(-1, 0)) 113 eq(globalDir, cwd(-1, globaltab)) 114 eq(0, lwd(-1, 0)) 115 eq(0, lwd(-1, globaltab)) 116 117 command('tabnew') 118 command('silent t' .. cmd .. ' ' .. directories.tab) 119 local localtab = call('tabpagenr') 120 121 -- From local tab page, original tab reports globalDir 122 eq(globalDir, cwd(-1, globaltab)) 123 eq(0, lwd(-1, globaltab)) 124 125 -- new tab reports local 126 eq(globalDir .. pathsep .. directories.tab, cwd(-1, 0)) 127 eq(globalDir .. pathsep .. directories.tab, cwd(-1, localtab)) 128 eq(1, lwd(-1, 0)) 129 eq(1, lwd(-1, localtab)) 130 131 command('tabnext') 132 -- From original tab page, local reports as such 133 eq(globalDir .. pathsep .. directories.tab, cwd(-1, localtab)) 134 eq(1, lwd(-1, localtab)) 135 end) 136 end) 137 138 describe('getcwd(-1, -1)', function() 139 it('works', function() 140 eq(directories.start, cwd(-1, -1)) 141 eq(0, lwd(-1, -1)) 142 end) 143 144 it('works with tab-local pwd', function() 145 command('silent t' .. cmd .. ' ' .. directories.tab) 146 eq(directories.start, cwd(-1, -1)) 147 eq(0, lwd(-1, -1)) 148 end) 149 150 it('works with window-local pwd', function() 151 command('silent l' .. cmd .. ' ' .. directories.window) 152 eq(directories.start, cwd(-1, -1)) 153 eq(0, lwd(-1, -1)) 154 end) 155 end) 156 157 describe('Local directory gets inherited', function() 158 it('by tabs', function() 159 local globalDir = directories.start 160 161 -- Create a new tab and change directory 162 command('tabnew') 163 command('silent t' .. cmd .. ' ' .. directories.tab) 164 eq(globalDir .. pathsep .. directories.tab, tcwd()) 165 166 -- Create a new tab and verify it has inherited the directory 167 command('tabnew') 168 eq(globalDir .. pathsep .. directories.tab, tcwd()) 169 170 -- Change tab and change back, verify that directories are correct 171 command('tabnext') 172 eq(globalDir, tcwd()) 173 command('tabprevious') 174 eq(globalDir .. pathsep .. directories.tab, tcwd()) 175 end) 176 end) 177 178 it('works', function() 179 local globalDir = directories.start 180 -- Create a new tab first and verify that is has the same working dir 181 command('tabnew') 182 eq(globalDir, cwd()) 183 eq(globalDir, tcwd()) -- has no tab-local directory 184 eq(0, tlwd()) 185 eq(globalDir, wcwd()) -- has no window-local directory 186 eq(0, wlwd()) 187 188 -- Change tab-local working directory and verify it is different 189 command('silent t' .. cmd .. ' ' .. directories.tab) 190 eq(globalDir .. pathsep .. directories.tab, cwd()) 191 eq(cwd(), tcwd()) -- working directory matches tab directory 192 eq(1, tlwd()) 193 eq(cwd(), wcwd()) -- still no window-directory 194 eq(0, wlwd()) 195 196 -- Create a new window in this tab to test `:lcd` 197 command('new') 198 eq(1, tlwd()) -- Still tab-local working directory 199 eq(0, wlwd()) -- Still no window-local working directory 200 eq(globalDir .. pathsep .. directories.tab, cwd()) 201 command('silent l' .. cmd .. ' ../' .. directories.window) 202 eq(globalDir .. pathsep .. directories.window, cwd()) 203 eq(globalDir .. pathsep .. directories.tab, tcwd()) 204 eq(1, wlwd()) 205 206 -- Verify the first window still has the tab local directory 207 command('wincmd w') 208 eq(globalDir .. pathsep .. directories.tab, cwd()) 209 eq(globalDir .. pathsep .. directories.tab, tcwd()) 210 eq(0, wlwd()) -- No window-local directory 211 212 -- Change back to initial tab and verify working directory has stayed 213 command('tabnext') 214 eq(globalDir, cwd()) 215 eq(0, tlwd()) 216 eq(0, wlwd()) 217 218 -- Verify global changes don't affect local ones 219 command('silent ' .. cmd .. ' ' .. directories.global) 220 eq(globalDir .. pathsep .. directories.global, cwd()) 221 command('tabnext') 222 eq(globalDir .. pathsep .. directories.tab, cwd()) 223 eq(globalDir .. pathsep .. directories.tab, tcwd()) 224 eq(0, wlwd()) -- Still no window-local directory in this window 225 226 -- Unless the global change happened in a tab with local directory 227 command('silent ' .. cmd .. ' ..') 228 eq(globalDir, cwd()) 229 eq(0, tlwd()) 230 eq(0, wlwd()) 231 -- Which also affects the first tab 232 command('tabnext') 233 eq(globalDir, cwd()) 234 235 -- But not in a window with its own local directory 236 command('tabnext | wincmd w') 237 eq(globalDir .. pathsep .. directories.window, cwd()) 238 eq(0, tlwd()) 239 eq(globalDir .. pathsep .. directories.window, wcwd()) 240 end) 241 end) 242 end 243 244 -- Test legal parameters for 'getcwd' and 'haslocaldir' 245 for _, cmd in ipairs { 'getcwd', 'haslocaldir' } do 246 describe(cmd .. '()', function() 247 before_each(function() 248 clear() 249 end) 250 251 -- Test invalid argument types 252 local err474 = 'Vim(call):E474: Invalid argument' 253 it('fails on string', function() 254 eq(err474, exc_exec('call ' .. cmd .. '("some string")')) 255 end) 256 it('fails on float', function() 257 eq(err474, exc_exec('call ' .. cmd .. '(1.0)')) 258 end) 259 it('fails on list', function() 260 eq(err474, exc_exec('call ' .. cmd .. '([1, 2])')) 261 end) 262 it('fails on dictionary', function() 263 eq(err474, exc_exec('call ' .. cmd .. '({"key": "value"})')) 264 end) 265 it('fails on funcref', function() 266 eq(err474, exc_exec('call ' .. cmd .. '(function("tr"))')) 267 end) 268 269 -- Test invalid numbers 270 it('fails on number less than -1', function() 271 eq(err474, exc_exec('call ' .. cmd .. '(-2)')) 272 end) 273 local err5001 = 'Vim(call):E5001: Higher scope cannot be -1 if lower scope is >= 0.' 274 it('fails on -1 if previous arg is >=0', function() 275 eq(err5001, exc_exec('call ' .. cmd .. '(0, -1)')) 276 end) 277 278 -- Test wrong number of arguments 279 local err118 = 'Vim(call):E118: Too many arguments for function: ' .. cmd 280 it('fails to parse more than one argument', function() 281 eq(err118, exc_exec('call ' .. cmd .. '(0, 0, 0)')) 282 end) 283 end) 284 end 285 286 describe('getcwd()', function() 287 before_each(function() 288 clear() 289 mkdir(directories.global) 290 end) 291 292 after_each(function() 293 n.rmdir(directories.global) 294 end) 295 296 it('returns empty string if working directory does not exist', function() 297 skip(is_os('win'), 'N/A for Windows') 298 command('cd ' .. directories.global) 299 command("call delete('../" .. directories.global .. "', 'd')") 300 eq('', n.eval('getcwd()')) 301 end) 302 303 it("works with 'autochdir' after local directory was set (#9892)", function() 304 local curdir = cwd() 305 command('lcd ' .. directories.global) 306 command('lcd -') 307 command('set autochdir') 308 command('edit ' .. directories.global .. '/foo') 309 eq(curdir .. pathsep .. directories.global, cwd()) 310 eq(curdir, wcwd()) 311 call('mkdir', 'bar') 312 command('edit ' .. 'bar/foo') 313 eq(curdir .. pathsep .. directories.global .. pathsep .. 'bar', cwd()) 314 eq(curdir, wcwd()) 315 command('lcd ..') 316 eq(curdir .. pathsep .. directories.global, cwd()) 317 eq(curdir .. pathsep .. directories.global, wcwd()) 318 command('edit') 319 eq(curdir .. pathsep .. directories.global .. pathsep .. 'bar', cwd()) 320 eq(curdir .. pathsep .. directories.global, wcwd()) 321 end) 322 end)