neovim

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

defaults_spec.lua (40648B)


      1 --
      2 -- Tests for default options and environment decisions.
      3 --
      4 -- See editor/defaults_spec.lua for default autocmds, mappings, commands, and menus.
      5 --
      6 
      7 local t = require('test.testutil')
      8 local n = require('test.functional.testnvim')()
      9 local Screen = require('test.functional.ui.screen')
     10 
     11 local assert_alive = n.assert_alive
     12 local assert_log = t.assert_log
     13 local api = n.api
     14 local command = n.command
     15 local clear = n.clear
     16 local exc_exec = n.exc_exec
     17 local eval = n.eval
     18 local eq = t.eq
     19 local ok = t.ok
     20 local fn = n.fn
     21 local insert = n.insert
     22 local neq = t.neq
     23 local mkdir = t.mkdir
     24 local rmdir = n.rmdir
     25 local tbl_contains = vim.tbl_contains
     26 local expect_exit = n.expect_exit
     27 local check_close = n.check_close
     28 local is_os = t.is_os
     29 
     30 local testlog = 'Xtest-defaults-log'
     31 
     32 describe('startup defaults', function()
     33  describe(':filetype', function()
     34    local function expect_filetype(expected)
     35      local screen = Screen.new(50, 4)
     36      command('filetype')
     37      screen:expect([[
     38        ^                                                  |
     39        {1:~                                                 }|*2
     40        ]] .. expected)
     41    end
     42 
     43    it('all ON after `-u NORC`', function()
     44      clear('-u', 'NORC')
     45      expect_filetype('filetype detection:ON  plugin:ON  indent:ON       |')
     46    end)
     47 
     48    it('all ON after `:syntax …` #7765', function()
     49      clear('-u', 'NORC', '--cmd', 'syntax on')
     50      expect_filetype('filetype detection:ON  plugin:ON  indent:ON       |')
     51      clear('-u', 'NORC', '--cmd', 'syntax off')
     52      expect_filetype('filetype detection:ON  plugin:ON  indent:ON       |')
     53    end)
     54 
     55    it('all OFF after `-u NONE`', function()
     56      clear('-u', 'NONE')
     57      expect_filetype('filetype detection:OFF  plugin:OFF  indent:OFF    |')
     58    end)
     59 
     60    it('explicit OFF stays OFF', function()
     61      clear('-u', 'NORC', '--cmd', 'syntax off | filetype off | filetype plugin indent off')
     62      expect_filetype('filetype detection:OFF  plugin:OFF  indent:OFF    |')
     63      clear('-u', 'NORC', '--cmd', 'syntax off | filetype plugin indent off')
     64      expect_filetype('filetype detection:ON  plugin:OFF  indent:OFF     |')
     65      clear('-u', 'NORC', '--cmd', 'filetype indent off')
     66      expect_filetype('filetype detection:ON  plugin:ON  indent:OFF      |')
     67      clear('-u', 'NORC', '--cmd', 'syntax off | filetype off')
     68      expect_filetype('filetype detection:OFF  plugin:(on)  indent:(on)  |')
     69      -- Swap the order.
     70      clear('-u', 'NORC', '--cmd', 'filetype off | syntax off')
     71      expect_filetype('filetype detection:OFF  plugin:(on)  indent:(on)  |')
     72    end)
     73 
     74    it('all ON after early `:filetype … on`', function()
     75      -- `:filetype … on` should not change the defaults. #7765
     76      -- Only an explicit `:filetype … off` sets OFF.
     77 
     78      clear('-u', 'NORC', '--cmd', 'filetype on')
     79      expect_filetype('filetype detection:ON  plugin:ON  indent:ON       |')
     80      clear('-u', 'NORC', '--cmd', 'filetype plugin on')
     81      expect_filetype('filetype detection:ON  plugin:ON  indent:ON       |')
     82      clear('-u', 'NORC', '--cmd', 'filetype indent on')
     83      expect_filetype('filetype detection:ON  plugin:ON  indent:ON       |')
     84    end)
     85 
     86    it('late `:filetype … off` stays OFF', function()
     87      clear('-u', 'NORC', '-c', 'filetype off')
     88      expect_filetype('filetype detection:OFF  plugin:(on)  indent:(on)  |')
     89      clear('-u', 'NORC', '-c', 'filetype plugin off')
     90      expect_filetype('filetype detection:ON  plugin:OFF  indent:ON      |')
     91      clear('-u', 'NORC', '-c', 'filetype indent off')
     92      expect_filetype('filetype detection:ON  plugin:ON  indent:OFF      |')
     93    end)
     94  end)
     95 
     96  describe('syntax', function()
     97    it('enabled by `-u NORC`', function()
     98      clear('-u', 'NORC')
     99      eq(1, eval('g:syntax_on'))
    100    end)
    101 
    102    it('disabled by `-u NONE`', function()
    103      clear('-u', 'NONE')
    104      eq(0, eval('exists("g:syntax_on")'))
    105    end)
    106 
    107    it('`:syntax off` stays off', function()
    108      -- early
    109      clear('-u', 'NORC', '--cmd', 'syntax off')
    110      eq(0, eval('exists("g:syntax_on")'))
    111      -- late
    112      clear('-u', 'NORC', '-c', 'syntax off')
    113      eq(0, eval('exists("g:syntax_on")'))
    114    end)
    115 
    116    it('":if 0|syntax on|endif" does not affect default #8728', function()
    117      clear('-u', 'NORC', '--cmd', ':if 0|syntax on|endif')
    118      eq(1, eval('exists("g:syntax_on")'))
    119      clear('-u', 'NORC', '--cmd', ':if 0|syntax off|endif')
    120      eq(1, eval('exists("g:syntax_on")'))
    121    end)
    122  end)
    123 
    124  describe("'fillchars'", function()
    125    it('vert/fold flags', function()
    126      clear()
    127      local screen = Screen.new(50, 5)
    128      command('set laststatus=0')
    129      insert([[
    130        1
    131        2
    132        3
    133        4]])
    134      command('normal! ggjzfj')
    135      command('vsp')
    136      screen:expect([[
    137        1                        1                       |
    138        {13:^+--  2 lines: 2··········}│{13:+--  2 lines: 2·········}|
    139        4                        │4                       |
    140        {1:~                        }│{1:~                       }|
    141                                                          |
    142      ]])
    143 
    144      -- ambiwidth=double defaults to single-byte fillchars.
    145      command('set ambiwidth=double')
    146      screen:expect([[
    147        1                        |1                       |
    148        {13:^+--  2 lines: 2----------}|{13:+--  2 lines: 2---------}|
    149        4                        |4                       |
    150        {1:~                        }|{1:~                       }|
    151                                                          |
    152      ]])
    153 
    154      -- change "vert" character to single-cell
    155      fn.setcellwidths({ { 0x2502, 0x2502, 1 } })
    156      screen:expect([[
    157        1                        1                       |
    158        {13:^+--  2 lines: 2----------}│{13:+--  2 lines: 2---------}|
    159        4                        │4                       |
    160        {1:~                        }│{1:~                       }|
    161                                                          |
    162      ]])
    163 
    164      -- change "vert" character to double-cell
    165      fn.setcellwidths({ { 0x2502, 0x2502, 2 } })
    166      screen:expect([[
    167        1                        |1                       |
    168        {13:^+--  2 lines: 2----------}|{13:+--  2 lines: 2---------}|
    169        4                        |4                       |
    170        {1:~                        }|{1:~                       }|
    171                                                          |
    172      ]])
    173 
    174      -- "vert" character should still default to single-byte fillchars because of setcellwidths().
    175      command('set ambiwidth=single')
    176      screen:expect([[
    177        1                        |1                       |
    178        {13:^+--  2 lines: 2··········}|{13:+--  2 lines: 2·········}|
    179        4                        |4                       |
    180        {1:~                        }|{1:~                       }|
    181                                                          |
    182      ]])
    183    end)
    184  end)
    185 
    186  it("'shadafile' ('viminfofile')", function()
    187    local env = {
    188      XDG_DATA_HOME = 'Xtest-userdata',
    189      XDG_STATE_HOME = 'Xtest-userstate',
    190      XDG_CONFIG_HOME = 'Xtest-userconfig',
    191    }
    192    finally(function()
    193      command('set shadafile=NONE') -- Avoid writing shada file on exit
    194      rmdir('Xtest-userstate')
    195      os.remove('Xtest-foo')
    196    end)
    197 
    198    clear { args = {}, args_rm = { '-i', '--cmd' }, env = env }
    199    -- Default 'shadafile' is empty.
    200    -- This means use the default location. :help shada-file-name
    201    eq('', api.nvim_get_option_value('shadafile', {}))
    202    eq('', api.nvim_get_option_value('viminfofile', {}))
    203    -- Handles viminfo/viminfofile as alias for shada/shadafile.
    204    eq('\n  shadafile=', eval('execute("set shadafile?")'))
    205    eq('\n  shadafile=', eval('execute("set viminfofile?")'))
    206    eq("\n  shada=!,'100,<50,s10,h,r/tmp/,r/private/", eval('execute("set shada?")'))
    207    eq("\n  shada=!,'100,<50,s10,h,r/tmp/,r/private/", eval('execute("set viminfo?")'))
    208 
    209    -- Remove /tmp/ exclusion so test works when run in temp directories.
    210    command("set shada=!,'100,<50,s10,h")
    211    -- Check that shada data (such as v:oldfiles) is saved/restored.
    212    command('edit Xtest-foo')
    213    command('write')
    214    local f = eval('fnamemodify(@%,":p")')
    215    assert(string.len(f) > 3)
    216    expect_exit(command, 'qall')
    217    clear { args = {}, args_rm = { '-i', '--cmd' }, env = env }
    218    eq({ f }, eval('v:oldfiles'))
    219  end)
    220 
    221  it("'packpath'", function()
    222    clear {
    223      args_rm = { 'runtimepath' },
    224    }
    225    -- Defaults to &runtimepath.
    226    eq(api.nvim_get_option_value('runtimepath', {}), api.nvim_get_option_value('packpath', {}))
    227 
    228    -- Does not follow modifications to runtimepath.
    229    command('set runtimepath+=foo')
    230    neq(api.nvim_get_option_value('runtimepath', {}), api.nvim_get_option_value('packpath', {}))
    231    command('set packpath+=foo')
    232    eq(api.nvim_get_option_value('runtimepath', {}), api.nvim_get_option_value('packpath', {}))
    233  end)
    234 
    235  it('v:progpath is set to the absolute path', function()
    236    clear()
    237    eq(eval("fnamemodify(v:progpath, ':p')"), eval('v:progpath'))
    238  end)
    239 
    240  describe('$NVIM_LOG_FILE', function()
    241    local xdgdir = 'Xtest-startup-xdg-logpath'
    242    local xdgstatedir = is_os('win') and xdgdir .. '/nvim-data' or xdgdir .. '/nvim'
    243    after_each(function()
    244      os.remove('Xtest-logpath')
    245      rmdir(xdgdir)
    246    end)
    247 
    248    it('is used if expansion succeeds', function()
    249      clear({ env = {
    250        NVIM_LOG_FILE = 'Xtest-logpath',
    251      } })
    252      eq('Xtest-logpath', eval('$NVIM_LOG_FILE'))
    253    end)
    254 
    255    it('defaults to stdpath("log")/nvim.log if empty', function()
    256      eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
    257      clear({
    258        env = {
    259          XDG_STATE_HOME = xdgdir,
    260          NVIM_LOG_FILE = '', -- Empty is invalid.
    261        },
    262      })
    263      eq(xdgstatedir .. '/nvim.log', t.fix_slashes(eval('$NVIM_LOG_FILE')))
    264    end)
    265 
    266    it('defaults to stdpath("log")/nvim.log if invalid', function()
    267      eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
    268      clear({
    269        env = {
    270          XDG_STATE_HOME = xdgdir,
    271          NVIM_LOG_FILE = '.', -- Any directory is invalid.
    272        },
    273      })
    274      eq(xdgstatedir .. '/nvim.log', t.fix_slashes(eval('$NVIM_LOG_FILE')))
    275      -- Avoid "failed to open $NVIM_LOG_FILE" noise in test output.
    276      expect_exit(command, 'qall!')
    277    end)
    278  end)
    279 end)
    280 
    281 describe('XDG defaults', function()
    282  -- Need separate describe() blocks to not run clear() twice.
    283  -- Do not put before_each() here for the same reasons.
    284 
    285  after_each(function()
    286    check_close()
    287    os.remove(testlog)
    288  end)
    289 
    290  it("&runtimepath data-dir matches stdpath('data') #9910", function()
    291    clear()
    292    local rtp = eval('split(&runtimepath, ",")')
    293    local rv = {}
    294    local expected = (
    295      is_os('win') and { [[\nvim-data\site]], [[\nvim-data\site\after]] }
    296      or { '/nvim/site', '/nvim/site/after' }
    297    )
    298 
    299    for _, v in ipairs(rtp) do
    300      local m = string.match(v, [=[[/\]nvim[^/\]*[/\]site.*$]=])
    301      if m and not tbl_contains(rv, m) then
    302        table.insert(rv, m)
    303      end
    304    end
    305    eq(expected, rv)
    306  end)
    307 
    308  describe('with empty/broken environment', function()
    309    it('sets correct defaults', function()
    310      clear({
    311        env = {
    312          XDG_CONFIG_HOME = nil,
    313          XDG_DATA_HOME = nil,
    314          XDG_CACHE_HOME = nil,
    315          XDG_STATE_HOME = nil,
    316          XDG_RUNTIME_DIR = nil,
    317          XDG_CONFIG_DIRS = nil,
    318          XDG_DATA_DIRS = nil,
    319          LOCALAPPDATA = nil,
    320          HOMEPATH = nil,
    321          HOMEDRIVE = nil,
    322          HOME = nil,
    323          TEMP = nil,
    324          VIMRUNTIME = nil,
    325          USER = nil,
    326        },
    327      })
    328 
    329      eq('.', api.nvim_get_option_value('backupdir', {}))
    330      eq('.', api.nvim_get_option_value('viewdir', {}))
    331      eq('.', api.nvim_get_option_value('directory', {}))
    332      eq('.', api.nvim_get_option_value('undodir', {}))
    333      ok((fn.tempname()):len() > 4)
    334    end)
    335  end)
    336 
    337  local function vimruntime_and_libdir()
    338    local vimruntime = eval('$VIMRUNTIME')
    339    -- libdir is hard to calculate reliably across various ci platforms
    340    -- local libdir = string.gsub(vimruntime, "share/nvim/runtime$", "lib/nvim")
    341    local libdir = api.nvim__get_lib_dir()
    342    return vimruntime, libdir
    343  end
    344 
    345  local env_sep = is_os('win') and ';' or ':'
    346  local data_dir = is_os('win') and 'nvim-data' or 'nvim'
    347  local state_dir = is_os('win') and 'nvim-data' or 'nvim'
    348  local root_path = is_os('win') and 'C:' or ''
    349 
    350  describe('with too long XDG vars', function()
    351    before_each(function()
    352      clear({
    353        -- Ensure valid --listen address despite broken XDG vars (else Nvim won't start).
    354        args = { '--listen', is_os('win') and '' or t.tmpname(false) },
    355        args_rm = { 'runtimepath' },
    356        env = {
    357          NVIM_LOG_FILE = testlog,
    358          XDG_CONFIG_HOME = (root_path .. ('/x'):rep(4096)),
    359          XDG_CONFIG_DIRS = (root_path .. ('/a'):rep(2048) .. env_sep .. root_path .. ('/b'):rep(
    360            2048
    361          ) .. (env_sep .. root_path .. '/c'):rep(512)),
    362          XDG_DATA_HOME = (root_path .. ('/X'):rep(4096)),
    363          XDG_RUNTIME_DIR = (root_path .. ('/X'):rep(4096)),
    364          XDG_STATE_HOME = (root_path .. ('/X'):rep(4096)),
    365          XDG_DATA_DIRS = (root_path .. ('/A'):rep(2048) .. env_sep .. root_path .. ('/B'):rep(
    366            2048
    367          ) .. (env_sep .. root_path .. '/C'):rep(512)),
    368        },
    369      })
    370    end)
    371 
    372    it('are correctly set', function()
    373      if not is_os('win') then
    374        -- Broken XDG vars cause serverstart() to fail (except on Windows, where servernames are not
    375        -- informed by $XDG_STATE_HOME).
    376        t.matches('Failed to start server: no such file or directory', t.pcall_err(fn.serverstart))
    377        assert_log('Failed to start server: no such file or directory: /X/X/X', testlog, 10)
    378      end
    379 
    380      local vimruntime, libdir = vimruntime_and_libdir()
    381 
    382      eq(
    383        (
    384          t.fix_slashes(
    385            root_path
    386              .. ('/x'):rep(4096)
    387              .. '/nvim'
    388              .. ','
    389              .. root_path
    390              .. ('/a'):rep(2048)
    391              .. '/nvim'
    392              .. ','
    393              .. root_path
    394              .. ('/b'):rep(2048)
    395              .. '/nvim'
    396              .. (',' .. root_path .. '/c/nvim')
    397              .. ','
    398              .. root_path
    399              .. ('/X'):rep(4096)
    400              .. '/'
    401              .. data_dir
    402              .. '/site'
    403              .. ','
    404              .. root_path
    405              .. ('/A'):rep(2048)
    406              .. '/nvim/site'
    407              .. ','
    408              .. root_path
    409              .. ('/B'):rep(2048)
    410              .. '/nvim/site'
    411              .. (',' .. root_path .. '/C/nvim/site')
    412              .. ','
    413              .. vimruntime
    414              .. ','
    415              .. libdir
    416              .. (',' .. root_path .. '/C/nvim/site/after')
    417              .. ','
    418              .. root_path
    419              .. ('/B'):rep(2048)
    420              .. '/nvim/site/after'
    421              .. ','
    422              .. root_path
    423              .. ('/A'):rep(2048)
    424              .. '/nvim/site/after'
    425              .. ','
    426              .. root_path
    427              .. ('/X'):rep(4096)
    428              .. '/'
    429              .. data_dir
    430              .. '/site/after'
    431              .. (',' .. root_path .. '/c/nvim/after')
    432              .. ','
    433              .. root_path
    434              .. ('/b'):rep(2048)
    435              .. '/nvim/after'
    436              .. ','
    437              .. root_path
    438              .. ('/a'):rep(2048)
    439              .. '/nvim/after'
    440              .. ','
    441              .. root_path
    442              .. ('/x'):rep(4096)
    443              .. '/nvim/after'
    444          )
    445        ),
    446        t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
    447      )
    448      command('set runtimepath&')
    449      command('set backupdir&')
    450      command('set directory&')
    451      command('set undodir&')
    452      command('set viewdir&')
    453      eq(
    454        (
    455          t.fix_slashes(
    456            root_path
    457              .. ('/x'):rep(4096)
    458              .. '/nvim'
    459              .. ','
    460              .. root_path
    461              .. ('/a'):rep(2048)
    462              .. '/nvim'
    463              .. ','
    464              .. root_path
    465              .. ('/b'):rep(2048)
    466              .. '/nvim'
    467              .. (',' .. root_path .. '/c/nvim')
    468              .. ','
    469              .. root_path
    470              .. ('/X'):rep(4096)
    471              .. '/'
    472              .. data_dir
    473              .. '/site'
    474              .. ','
    475              .. root_path
    476              .. ('/A'):rep(2048)
    477              .. '/nvim/site'
    478              .. ','
    479              .. root_path
    480              .. ('/B'):rep(2048)
    481              .. '/nvim/site'
    482              .. (',' .. root_path .. '/C/nvim/site')
    483              .. ','
    484              .. vimruntime
    485              .. ','
    486              .. libdir
    487              .. (',' .. root_path .. '/C/nvim/site/after')
    488              .. ','
    489              .. root_path
    490              .. ('/B'):rep(2048)
    491              .. '/nvim/site/after'
    492              .. ','
    493              .. root_path
    494              .. ('/A'):rep(2048)
    495              .. '/nvim/site/after'
    496              .. ','
    497              .. root_path
    498              .. ('/X'):rep(4096)
    499              .. '/'
    500              .. data_dir
    501              .. '/site/after'
    502              .. (',' .. root_path .. '/c/nvim/after')
    503              .. ','
    504              .. root_path
    505              .. ('/b'):rep(2048)
    506              .. '/nvim/after'
    507              .. ','
    508              .. root_path
    509              .. ('/a'):rep(2048)
    510              .. '/nvim/after'
    511              .. ','
    512              .. root_path
    513              .. ('/x'):rep(4096)
    514              .. '/nvim/after'
    515          )
    516        ),
    517        t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
    518      )
    519      eq(
    520        '.,' .. root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/backup//',
    521        t.fix_slashes(api.nvim_get_option_value('backupdir', {}))
    522      )
    523      eq(
    524        root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/swap//',
    525        t.fix_slashes(api.nvim_get_option_value('directory', {}))
    526      )
    527      eq(
    528        root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/undo//',
    529        t.fix_slashes(api.nvim_get_option_value('undodir', {}))
    530      )
    531      eq(
    532        root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/view//',
    533        t.fix_slashes(api.nvim_get_option_value('viewdir', {}))
    534      )
    535    end)
    536  end)
    537 
    538  describe('with expandable XDG vars', function()
    539    before_each(function()
    540      clear({
    541        -- Ensure valid --listen address despite broken XDG vars (else Nvim won't start).
    542        args = { '--listen', is_os('win') and '' or t.tmpname(false) },
    543        args_rm = { 'runtimepath' },
    544        env = {
    545          NVIM_LOG_FILE = testlog,
    546          XDG_CONFIG_HOME = '$XDG_DATA_HOME',
    547          XDG_CONFIG_DIRS = '$XDG_DATA_DIRS',
    548          XDG_DATA_HOME = '$XDG_CONFIG_HOME',
    549          XDG_RUNTIME_DIR = '$XDG_RUNTIME_DIR',
    550          XDG_STATE_HOME = '$XDG_CONFIG_HOME',
    551          XDG_DATA_DIRS = '$XDG_CONFIG_DIRS',
    552        },
    553      })
    554    end)
    555 
    556    after_each(function()
    557      command('set shadafile=NONE') -- Avoid writing shada file on exit
    558    end)
    559 
    560    it('are not expanded', function()
    561      if not is_os('win') then
    562        -- Broken XDG vars cause serverstart() to fail (except on Windows, where servernames are not
    563        -- informed by $XDG_STATE_HOME).
    564        t.matches('Failed to start server: no such file or directory', t.pcall_err(fn.serverstart))
    565        assert_log(
    566          'Failed to start server: no such file or directory: %$XDG_RUNTIME_DIR%/',
    567          testlog,
    568          10
    569        )
    570      end
    571 
    572      local vimruntime, libdir = vimruntime_and_libdir()
    573      eq(
    574        (
    575          t.fix_slashes(
    576            '$XDG_DATA_HOME/nvim'
    577              .. ',$XDG_DATA_DIRS/nvim'
    578              .. ',$XDG_CONFIG_HOME/'
    579              .. data_dir
    580              .. '/site'
    581              .. ',$XDG_CONFIG_DIRS/nvim/site'
    582              .. ','
    583              .. vimruntime
    584              .. ','
    585              .. libdir
    586              .. ',$XDG_CONFIG_DIRS/nvim/site/after'
    587              .. ',$XDG_CONFIG_HOME/'
    588              .. data_dir
    589              .. '/site/after'
    590              .. ',$XDG_DATA_DIRS/nvim/after'
    591              .. ',$XDG_DATA_HOME/nvim/after'
    592          )
    593        ),
    594        t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
    595      )
    596      command('set runtimepath&')
    597      command('set backupdir&')
    598      command('set directory&')
    599      command('set undodir&')
    600      command('set viewdir&')
    601      eq(
    602        (
    603          t.fix_slashes(
    604            '$XDG_DATA_HOME/nvim'
    605              .. ',$XDG_DATA_DIRS/nvim'
    606              .. ',$XDG_CONFIG_HOME/'
    607              .. data_dir
    608              .. '/site'
    609              .. ',$XDG_CONFIG_DIRS/nvim/site'
    610              .. ','
    611              .. vimruntime
    612              .. ','
    613              .. libdir
    614              .. ',$XDG_CONFIG_DIRS/nvim/site/after'
    615              .. ',$XDG_CONFIG_HOME/'
    616              .. data_dir
    617              .. '/site/after'
    618              .. ',$XDG_DATA_DIRS/nvim/after'
    619              .. ',$XDG_DATA_HOME/nvim/after'
    620          )
    621        ),
    622        t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
    623      )
    624      eq(
    625        ('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
    626        t.fix_slashes(api.nvim_get_option_value('backupdir', {}))
    627      )
    628      eq(
    629        ('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
    630        t.fix_slashes(api.nvim_get_option_value('directory', {}))
    631      )
    632      eq(
    633        ('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
    634        t.fix_slashes(api.nvim_get_option_value('undodir', {}))
    635      )
    636      eq(
    637        ('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
    638        t.fix_slashes(api.nvim_get_option_value('viewdir', {}))
    639      )
    640      command('set all&')
    641      eq(
    642        t.fix_slashes(
    643          '$XDG_DATA_HOME/nvim'
    644            .. ',$XDG_DATA_DIRS/nvim'
    645            .. ',$XDG_CONFIG_HOME/'
    646            .. data_dir
    647            .. '/site'
    648            .. ',$XDG_CONFIG_DIRS/nvim/site'
    649            .. ','
    650            .. vimruntime
    651            .. ','
    652            .. libdir
    653            .. ',$XDG_CONFIG_DIRS/nvim/site/after'
    654            .. ',$XDG_CONFIG_HOME/'
    655            .. data_dir
    656            .. '/site/after'
    657            .. ',$XDG_DATA_DIRS/nvim/after'
    658            .. ',$XDG_DATA_HOME/nvim/after'
    659        ),
    660        t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
    661      )
    662      eq(
    663        ('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
    664        t.fix_slashes(api.nvim_get_option_value('backupdir', {}))
    665      )
    666      eq(
    667        ('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
    668        t.fix_slashes(api.nvim_get_option_value('directory', {}))
    669      )
    670      eq(
    671        ('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
    672        t.fix_slashes(api.nvim_get_option_value('undodir', {}))
    673      )
    674      eq(
    675        ('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
    676        t.fix_slashes(api.nvim_get_option_value('viewdir', {}))
    677      )
    678      eq(nil, (fn.tempname()):match('XDG_RUNTIME_DIR'))
    679    end)
    680  end)
    681 
    682  describe('with commas', function()
    683    before_each(function()
    684      clear({
    685        args_rm = { 'runtimepath' },
    686        env = {
    687          XDG_CONFIG_HOME = ', , ,',
    688          XDG_CONFIG_DIRS = ',-,-,' .. env_sep .. '-,-,-',
    689          XDG_DATA_HOME = ',=,=,',
    690          XDG_STATE_HOME = ',=,=,',
    691          XDG_DATA_DIRS = ',≡,≡,' .. env_sep .. '≡,≡,≡',
    692        },
    693      })
    694    end)
    695 
    696    it('are escaped properly', function()
    697      local vimruntime, libdir = vimruntime_and_libdir()
    698      local path_sep = is_os('win') and '\\' or '/'
    699      eq(
    700        (
    701          '\\, \\, \\,'
    702          .. path_sep
    703          .. 'nvim'
    704          .. ',\\,-\\,-\\,'
    705          .. path_sep
    706          .. 'nvim'
    707          .. ',-\\,-\\,-'
    708          .. path_sep
    709          .. 'nvim'
    710          .. ',\\,=\\,=\\,'
    711          .. path_sep
    712          .. data_dir
    713          .. path_sep
    714          .. 'site'
    715          .. ',\\,≡\\,≡\\,'
    716          .. path_sep
    717          .. 'nvim'
    718          .. path_sep
    719          .. 'site'
    720          .. ',≡\\,≡\\,≡'
    721          .. path_sep
    722          .. 'nvim'
    723          .. path_sep
    724          .. 'site'
    725          .. ','
    726          .. vimruntime
    727          .. ','
    728          .. libdir
    729          .. ',≡\\,≡\\,≡'
    730          .. path_sep
    731          .. 'nvim'
    732          .. path_sep
    733          .. 'site'
    734          .. path_sep
    735          .. 'after'
    736          .. ',\\,≡\\,≡\\,'
    737          .. path_sep
    738          .. 'nvim'
    739          .. path_sep
    740          .. 'site'
    741          .. path_sep
    742          .. 'after'
    743          .. ',\\,=\\,=\\,'
    744          .. path_sep
    745          .. data_dir
    746          .. path_sep
    747          .. 'site'
    748          .. path_sep
    749          .. 'after'
    750          .. ',-\\,-\\,-'
    751          .. path_sep
    752          .. 'nvim'
    753          .. path_sep
    754          .. 'after'
    755          .. ',\\,-\\,-\\,'
    756          .. path_sep
    757          .. 'nvim'
    758          .. path_sep
    759          .. 'after'
    760          .. ',\\, \\, \\,'
    761          .. path_sep
    762          .. 'nvim'
    763          .. path_sep
    764          .. 'after'
    765        ),
    766        api.nvim_get_option_value('runtimepath', {})
    767      )
    768      command('set runtimepath&')
    769      command('set backupdir&')
    770      command('set directory&')
    771      command('set undodir&')
    772      command('set viewdir&')
    773      eq(
    774        (
    775          '\\, \\, \\,'
    776          .. path_sep
    777          .. 'nvim'
    778          .. ',\\,-\\,-\\,'
    779          .. path_sep
    780          .. 'nvim'
    781          .. ',-\\,-\\,-'
    782          .. path_sep
    783          .. 'nvim'
    784          .. ',\\,=\\,=\\,'
    785          .. path_sep
    786          .. ''
    787          .. data_dir
    788          .. ''
    789          .. path_sep
    790          .. 'site'
    791          .. ',\\,≡\\,≡\\,'
    792          .. path_sep
    793          .. 'nvim'
    794          .. path_sep
    795          .. 'site'
    796          .. ',≡\\,≡\\,≡'
    797          .. path_sep
    798          .. 'nvim'
    799          .. path_sep
    800          .. 'site'
    801          .. ','
    802          .. vimruntime
    803          .. ','
    804          .. libdir
    805          .. ',≡\\,≡\\,≡'
    806          .. path_sep
    807          .. 'nvim'
    808          .. path_sep
    809          .. 'site'
    810          .. path_sep
    811          .. 'after'
    812          .. ',\\,≡\\,≡\\,'
    813          .. path_sep
    814          .. 'nvim'
    815          .. path_sep
    816          .. 'site'
    817          .. path_sep
    818          .. 'after'
    819          .. ',\\,=\\,=\\,'
    820          .. path_sep
    821          .. ''
    822          .. data_dir
    823          .. ''
    824          .. path_sep
    825          .. 'site'
    826          .. path_sep
    827          .. 'after'
    828          .. ',-\\,-\\,-'
    829          .. path_sep
    830          .. 'nvim'
    831          .. path_sep
    832          .. 'after'
    833          .. ',\\,-\\,-\\,'
    834          .. path_sep
    835          .. 'nvim'
    836          .. path_sep
    837          .. 'after'
    838          .. ',\\, \\, \\,'
    839          .. path_sep
    840          .. 'nvim'
    841          .. path_sep
    842          .. 'after'
    843        ),
    844        api.nvim_get_option_value('runtimepath', {})
    845      )
    846      eq(
    847        '.,\\,=\\,=\\,' .. path_sep .. state_dir .. '' .. path_sep .. 'backup' .. (path_sep):rep(2),
    848        api.nvim_get_option_value('backupdir', {})
    849      )
    850      eq(
    851        '\\,=\\,=\\,'
    852          .. path_sep
    853          .. ''
    854          .. state_dir
    855          .. ''
    856          .. path_sep
    857          .. 'swap'
    858          .. (path_sep):rep(2),
    859        api.nvim_get_option_value('directory', {})
    860      )
    861      eq(
    862        '\\,=\\,=\\,'
    863          .. path_sep
    864          .. ''
    865          .. state_dir
    866          .. ''
    867          .. path_sep
    868          .. 'undo'
    869          .. (path_sep):rep(2),
    870        api.nvim_get_option_value('undodir', {})
    871      )
    872      eq(
    873        '\\,=\\,=\\,'
    874          .. path_sep
    875          .. ''
    876          .. state_dir
    877          .. ''
    878          .. path_sep
    879          .. 'view'
    880          .. (path_sep):rep(2),
    881        api.nvim_get_option_value('viewdir', {})
    882      )
    883    end)
    884  end)
    885 end)
    886 
    887 describe('stdpath()', function()
    888  after_each(function()
    889    check_close()
    890    os.remove(testlog)
    891  end)
    892 
    893  --- Windows appends 'nvim-data' instead of just 'nvim' to prevent collisions
    894  --- due to XDG_CONFIG_HOME, XDG_DATA_HOME and XDG_STATE_HOME being the same.
    895  --- @param name string
    896  local function maybe_data(name)
    897    return is_os('win') and name .. '-data' or name
    898  end
    899 
    900  local datadir = maybe_data('nvim')
    901  local statedir = maybe_data('nvim')
    902  local env_sep = is_os('win') and ';' or ':'
    903 
    904  it('works', function()
    905    clear() -- Do not explicitly set any env vars.
    906 
    907    eq('nvim', fn.fnamemodify(fn.stdpath('cache'), ':t'))
    908    eq('nvim', fn.fnamemodify(fn.stdpath('config'), ':t'))
    909    eq(datadir, fn.fnamemodify(fn.stdpath('data'), ':t'))
    910    eq(statedir, fn.fnamemodify(fn.stdpath('state'), ':t'))
    911    eq('table', type(fn.stdpath('config_dirs')))
    912    eq('table', type(fn.stdpath('data_dirs')))
    913    eq('string', type(fn.stdpath('run')))
    914    assert_alive() -- Check for crash. #8393
    915  end)
    916 
    917  it('failure modes', function()
    918    clear()
    919    eq('Vim(call):E6100: "capybara" is not a valid stdpath', exc_exec('call stdpath("capybara")'))
    920    eq('Vim(call):E6100: "" is not a valid stdpath', exc_exec('call stdpath("")'))
    921    eq('Vim(call):E6100: "23" is not a valid stdpath', exc_exec('call stdpath(23)'))
    922    eq('Vim(call):E731: Using a Dictionary as a String', exc_exec('call stdpath({"eris": 23})'))
    923    eq('Vim(call):E730: Using a List as a String', exc_exec('call stdpath([23])'))
    924  end)
    925 
    926  it('$NVIM_APPNAME', function()
    927    local appname = 'NVIM_APPNAME_TEST' .. ('_'):rep(106)
    928    clear({ env = { NVIM_APPNAME = appname, NVIM_LOG_FILE = testlog } })
    929    eq(appname, fn.fnamemodify(fn.stdpath('config'), ':t'))
    930    eq(appname, fn.fnamemodify(fn.stdpath('cache'), ':t'))
    931    eq(maybe_data(appname), fn.fnamemodify(fn.stdpath('log'), ':t'))
    932    eq(maybe_data(appname), fn.fnamemodify(fn.stdpath('data'), ':t'))
    933    eq(maybe_data(appname), fn.fnamemodify(fn.stdpath('state'), ':t'))
    934    -- config_dirs and data_dirs are empty on windows, so don't check them on
    935    -- that platform
    936    if not is_os('win') then
    937      eq(appname, fn.fnamemodify(fn.stdpath('config_dirs')[1], ':t'))
    938      eq(appname, fn.fnamemodify(fn.stdpath('data_dirs')[1], ':t'))
    939    end
    940    assert_alive() -- Check for crash. #8393
    941 
    942    -- Check that Nvim rejects invalid APPNAMEs
    943    local function test_appname(testAppname, expected_exitcode)
    944      local p = n.spawn_wait({
    945        args = { '--listen', 'x', '+qall!' },
    946        env = { NVIM_APPNAME = testAppname },
    947      })
    948      eq(expected_exitcode, p.status)
    949    end
    950    -- Invalid appnames:
    951    test_appname('a/../b', 1)
    952    test_appname('../a', 1)
    953    test_appname('a/..', 1)
    954    test_appname('..', 1)
    955    test_appname('.', 1)
    956    test_appname('/', 1)
    957    test_appname(is_os('win') and 'C:/a/b' or '/a/b', 1)
    958    -- Valid appnames:
    959    test_appname('a/b', 0)
    960    test_appname('a/b\\c', 0)
    961  end)
    962 
    963  it('$NVIM_APPNAME relative path', function()
    964    local tmpdir = t.tmpname(false)
    965    t.mkdir(tmpdir)
    966 
    967    clear({
    968      args_rm = { '--listen' },
    969      env = {
    970        NVIM_APPNAME = 'relative/appname',
    971        NVIM_LOG_FILE = testlog,
    972        TMPDIR = tmpdir,
    973      },
    974    })
    975 
    976    t.matches(vim.pesc(tmpdir), t.fix_slashes(fn.tempname()))
    977    t.assert_nolog('tempdir', testlog, 100)
    978    t.assert_nolog('TMPDIR', testlog, 100)
    979    t.matches([=[[/\\]relative%-appname.[^/\\]+]=], api.nvim_get_vvar('servername'))
    980  end)
    981 
    982  describe('returns a String', function()
    983    describe('with "config"', function()
    984      it('knows XDG_CONFIG_HOME', function()
    985        clear({
    986          env = {
    987            XDG_CONFIG_HOME = '/home/docwhat/.config',
    988          },
    989        })
    990        eq('/home/docwhat/.config/nvim', t.fix_slashes(fn.stdpath('config')))
    991      end)
    992 
    993      it('handles changes during runtime', function()
    994        clear({ env = {
    995          XDG_CONFIG_HOME = '/home/original',
    996        } })
    997        eq('/home/original/nvim', t.fix_slashes(fn.stdpath('config')))
    998        command("let $XDG_CONFIG_HOME='/home/new'")
    999        eq('/home/new/nvim', t.fix_slashes(fn.stdpath('config')))
   1000      end)
   1001 
   1002      it("doesn't expand $VARIABLES", function()
   1003        clear({
   1004          env = {
   1005            XDG_CONFIG_HOME = '$VARIABLES',
   1006            VARIABLES = 'this-should-not-happen',
   1007          },
   1008        })
   1009        eq('$VARIABLES/nvim', t.fix_slashes(fn.stdpath('config')))
   1010      end)
   1011 
   1012      it("doesn't expand ~/", function()
   1013        clear({ env = {
   1014          XDG_CONFIG_HOME = '~/frobnitz',
   1015        } })
   1016        eq('~/frobnitz/nvim', t.fix_slashes(fn.stdpath('config')))
   1017      end)
   1018    end)
   1019 
   1020    describe('with "data"', function()
   1021      it('knows XDG_DATA_HOME', function()
   1022        clear({ env = {
   1023          XDG_DATA_HOME = '/home/docwhat/.local',
   1024        } })
   1025        eq('/home/docwhat/.local/' .. datadir, t.fix_slashes(fn.stdpath('data')))
   1026      end)
   1027 
   1028      it('handles changes during runtime', function()
   1029        clear({ env = {
   1030          XDG_DATA_HOME = '/home/original',
   1031        } })
   1032        eq('/home/original/' .. datadir, t.fix_slashes(fn.stdpath('data')))
   1033        command("let $XDG_DATA_HOME='/home/new'")
   1034        eq('/home/new/' .. datadir, t.fix_slashes(fn.stdpath('data')))
   1035      end)
   1036 
   1037      it("doesn't expand $VARIABLES", function()
   1038        clear({
   1039          env = {
   1040            XDG_DATA_HOME = '$VARIABLES',
   1041            VARIABLES = 'this-should-not-happen',
   1042          },
   1043        })
   1044        eq('$VARIABLES/' .. datadir, t.fix_slashes(fn.stdpath('data')))
   1045      end)
   1046 
   1047      it("doesn't expand ~/", function()
   1048        clear({ env = {
   1049          XDG_DATA_HOME = '~/frobnitz',
   1050        } })
   1051        eq('~/frobnitz/' .. datadir, t.fix_slashes(fn.stdpath('data')))
   1052      end)
   1053    end)
   1054 
   1055    describe('with "state"', function()
   1056      it('knows XDG_STATE_HOME', function()
   1057        clear({
   1058          env = {
   1059            XDG_STATE_HOME = '/home/docwhat/.local',
   1060          },
   1061        })
   1062        eq('/home/docwhat/.local/' .. statedir, t.fix_slashes(fn.stdpath('state')))
   1063      end)
   1064 
   1065      it('handles changes during runtime', function()
   1066        clear({ env = {
   1067          XDG_STATE_HOME = '/home/original',
   1068        } })
   1069        eq('/home/original/' .. statedir, t.fix_slashes(fn.stdpath('state')))
   1070        command("let $XDG_STATE_HOME='" .. '/home/new' .. "'")
   1071        eq('/home/new/' .. statedir, t.fix_slashes(fn.stdpath('state')))
   1072      end)
   1073 
   1074      it("doesn't expand $VARIABLES", function()
   1075        clear({
   1076          env = {
   1077            XDG_STATE_HOME = '$VARIABLES',
   1078            VARIABLES = 'this-should-not-happen',
   1079          },
   1080        })
   1081        eq('$VARIABLES/' .. statedir, t.fix_slashes(fn.stdpath('state')))
   1082      end)
   1083 
   1084      it("doesn't expand ~/", function()
   1085        clear({ env = {
   1086          XDG_STATE_HOME = '~/frobnitz',
   1087        } })
   1088        eq('~/frobnitz/' .. statedir, t.fix_slashes(fn.stdpath('state')))
   1089      end)
   1090    end)
   1091 
   1092    describe('with "cache"', function()
   1093      it('knows XDG_CACHE_HOME', function()
   1094        clear({
   1095          env = {
   1096            XDG_CACHE_HOME = '/home/docwhat/.cache',
   1097          },
   1098        })
   1099        eq('/home/docwhat/.cache/nvim', t.fix_slashes(fn.stdpath('cache')))
   1100      end)
   1101 
   1102      it('handles changes during runtime', function()
   1103        clear({ env = {
   1104          XDG_CACHE_HOME = '/home/original',
   1105        } })
   1106        eq('/home/original/nvim', t.fix_slashes(fn.stdpath('cache')))
   1107        command("let $XDG_CACHE_HOME='" .. '/home/new' .. "'")
   1108        eq('/home/new/nvim', t.fix_slashes(fn.stdpath('cache')))
   1109      end)
   1110 
   1111      it("doesn't expand $VARIABLES", function()
   1112        clear({
   1113          env = {
   1114            XDG_CACHE_HOME = '$VARIABLES',
   1115            VARIABLES = 'this-should-not-happen',
   1116          },
   1117        })
   1118        eq('$VARIABLES/nvim', t.fix_slashes(fn.stdpath('cache')))
   1119      end)
   1120 
   1121      it("doesn't expand ~/", function()
   1122        clear({ env = {
   1123          XDG_CACHE_HOME = '~/frobnitz',
   1124        } })
   1125        eq('~/frobnitz/nvim', t.fix_slashes(fn.stdpath('cache')))
   1126      end)
   1127    end)
   1128  end)
   1129 
   1130  describe('returns a List', function()
   1131    -- Some OS specific variables the system would have set.
   1132    local function base_env()
   1133      if is_os('win') then
   1134        return {
   1135          HOME = 'C:\\Users\\docwhat', -- technically, is not a usual PATH
   1136          HOMEDRIVE = 'C:',
   1137          HOMEPATH = '\\Users\\docwhat',
   1138          LOCALAPPDATA = 'C:\\Users\\docwhat\\AppData\\Local',
   1139          NVIM_LOG_FILE = testlog,
   1140          TEMP = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
   1141          TMPDIR = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
   1142          TMP = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
   1143        }
   1144      else
   1145        return {
   1146          HOME = '/home/docwhat',
   1147          HOMEDRIVE = 'HOMEDRIVE-should-be-ignored',
   1148          HOMEPATH = 'HOMEPATH-should-be-ignored',
   1149          LOCALAPPDATA = 'LOCALAPPDATA-should-be-ignored',
   1150          NVIM_LOG_FILE = testlog,
   1151          TEMP = 'TEMP-should-be-ignored',
   1152          TMPDIR = 'TMPDIR-should-be-ignored',
   1153          TMP = 'TMP-should-be-ignored',
   1154        }
   1155      end
   1156    end
   1157 
   1158    local function set_paths_via_system(var_name, paths)
   1159      local env = base_env()
   1160      env[var_name] = table.concat(paths, env_sep)
   1161      clear({ env = env })
   1162    end
   1163 
   1164    local function set_paths_at_runtime(var_name, paths)
   1165      clear({ env = base_env() })
   1166      api.nvim_set_var('env_val', table.concat(paths, env_sep))
   1167      command(('let $%s=g:env_val'):format(var_name))
   1168    end
   1169 
   1170    local function behaves_like_dir_list_env(msg, stdpath_arg, env_var_name, paths, expected_paths)
   1171      describe(msg, function()
   1172        it('set via system', function()
   1173          set_paths_via_system(env_var_name, paths)
   1174          eq(expected_paths, t.fix_slashes(fn.stdpath(stdpath_arg)))
   1175          if not is_os('win') then
   1176            assert_log(
   1177              '$TMPDIR tempdir not a directory[^\n]*TMPDIR%-should%-be%-ignored',
   1178              testlog,
   1179              100
   1180            )
   1181          end
   1182        end)
   1183 
   1184        it('set at runtime', function()
   1185          set_paths_at_runtime(env_var_name, paths)
   1186          eq(expected_paths, t.fix_slashes(fn.stdpath(stdpath_arg)))
   1187          if not is_os('win') then
   1188            assert_log(
   1189              '$TMPDIR tempdir not a directory[^\n]*TMPDIR%-should%-be%-ignored',
   1190              testlog,
   1191              100
   1192            )
   1193          end
   1194        end)
   1195      end)
   1196    end
   1197 
   1198    describe('with "config_dirs"', function()
   1199      behaves_like_dir_list_env(
   1200        'handles XDG_CONFIG_DIRS with one path',
   1201        'config_dirs',
   1202        'XDG_CONFIG_DIRS',
   1203        {
   1204          t.fix_slashes('/home/docwhat/.config'),
   1205        },
   1206        {
   1207          t.fix_slashes('/home/docwhat/.config/nvim'),
   1208        }
   1209      )
   1210 
   1211      behaves_like_dir_list_env(
   1212        'handles XDG_CONFIG_DIRS with two paths',
   1213        'config_dirs',
   1214        'XDG_CONFIG_DIRS',
   1215        {
   1216          t.fix_slashes('/home/docwhat/.config'),
   1217          t.fix_slashes('/etc/config'),
   1218        },
   1219        {
   1220          t.fix_slashes('/home/docwhat/.config/nvim'),
   1221          t.fix_slashes('/etc/config/nvim'),
   1222        }
   1223      )
   1224 
   1225      behaves_like_dir_list_env(
   1226        "doesn't expand $VAR and $IBLES",
   1227        'config_dirs',
   1228        'XDG_CONFIG_DIRS',
   1229        { '$HOME', '$TMP' },
   1230        {
   1231          t.fix_slashes('$HOME/nvim'),
   1232          t.fix_slashes('$TMP/nvim'),
   1233        }
   1234      )
   1235 
   1236      behaves_like_dir_list_env("doesn't expand ~/", 'config_dirs', 'XDG_CONFIG_DIRS', {
   1237        t.fix_slashes('~/.oldconfig'),
   1238        t.fix_slashes('~/.olderconfig'),
   1239      }, {
   1240        t.fix_slashes('~/.oldconfig/nvim'),
   1241        t.fix_slashes('~/.olderconfig/nvim'),
   1242      })
   1243    end)
   1244 
   1245    describe('with "data_dirs"', function()
   1246      behaves_like_dir_list_env('knows XDG_DATA_DIRS with one path', 'data_dirs', 'XDG_DATA_DIRS', {
   1247        t.fix_slashes('/home/docwhat/.data'),
   1248      }, {
   1249        t.fix_slashes('/home/docwhat/.data/nvim'),
   1250      })
   1251 
   1252      behaves_like_dir_list_env(
   1253        'knows XDG_DATA_DIRS with two paths',
   1254        'data_dirs',
   1255        'XDG_DATA_DIRS',
   1256        {
   1257          t.fix_slashes('/home/docwhat/.data'),
   1258          t.fix_slashes('/etc/local'),
   1259        },
   1260        {
   1261          t.fix_slashes('/home/docwhat/.data/nvim'),
   1262          t.fix_slashes('/etc/local/nvim'),
   1263        }
   1264      )
   1265 
   1266      behaves_like_dir_list_env(
   1267        "doesn't expand $VAR and $IBLES",
   1268        'data_dirs',
   1269        'XDG_DATA_DIRS',
   1270        { '$HOME', '$TMP' },
   1271        {
   1272          t.fix_slashes('$HOME/nvim'),
   1273          t.fix_slashes('$TMP/nvim'),
   1274        }
   1275      )
   1276 
   1277      behaves_like_dir_list_env("doesn't expand ~/", 'data_dirs', 'XDG_DATA_DIRS', {
   1278        t.fix_slashes('~/.oldconfig'),
   1279        t.fix_slashes('~/.olderconfig'),
   1280      }, {
   1281        t.fix_slashes('~/.oldconfig/nvim'),
   1282        t.fix_slashes('~/.olderconfig/nvim'),
   1283      })
   1284    end)
   1285  end)
   1286 end)