cd_spec.lua 10 KB

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