There are a number of ways to go about this, depending on what you actually want.
You can use wildcards, as mattb has already mentioned. If, however, these either cause ambiguities or you just don't want to type out the directory structure as wildcards, there's alternatives.
If you're only looking to open files, I highly recommend a fuzzy finder. There's a number of these available, but fzf (and the matching Vim plugin) does allow you to open in splits with a keybind. Unfortunately, both the above options don't really care about the directory of the file you're editing, unless it happens to be the current working directory. If you have several files relative to your current working directory with the same name, you may need to scroll or search for the path to find what you're actually looking for. Also note that FZF doesn't allow file creation or manipulation (see #107), which may be a problem if you have a .ts
file you'd like to make a test file from.
On the more visual side of things, there are a number of trees (such as NERDTree), which again don't care about the directory the file you're currently editing is in, but if you've browsed your way to the current file, the cursor should be right next to it when you switch back to the NERDTree buffer (or in general the buffer of whatever tree you end up using). NERDTree does allow file creation, as well as file manipulation, and different plugins may work differently with regard to the initially focused section of the tree. For a built-in solution, :Sexplore
(:Sex
for short) may also be useful.
And on the command side of things, we can get a bit more fancy. How fancy really depends on what the exact scope of your split needs are. All these options allow file creation.
For an instance, I have a general command for editing a file, which interprets the input relative to the file currently being edited. Modified to split instead of edit in the current buffer, you can have something like this:
command! -nargs=1 Sp :sp %:h/<args>
A caveat with this approach is that I don't really know how to set up file completion, as -complete=file
checks relative to the current working directory and not your current file.Custom completion sources are a thing that would work here, though, I just haven't taken the time to actually get into how that's done. See :h expand()
for the meaning of %:h
(TL;DR: take current file path relative to the current working directory without the file name, i.e. the current folder, and append the new extra path to it)
Note that you can also explicitly type out :sp %:h/somefile.ts
, if that's more your thing. Autocomplete (pressing tab) works provided you're in a real file, though it does that by expanding %:h
. It's a super handy shortcut if you're primarily looking to reduce your overall typing, and typing it explicitly gives you full control over the path, if that's something you feel you need.
And finally, if you just want to switch between .ts
and .test.ts
, there's yet another expand hack.
" This function is only necessary if you only want the maps in TS files. If you don't care, feel free to remove the function and just use the content of it directly.
" Note that the maps will probably do some weird stuff if you invoke it from an incompatible file
fun! TSMaps()
" Command explanation: 'sp ' is obvious. For the record, .. is string concatenation
" We need %:r:r to remove both extensions. Note that if the file name is file.ts, only .ts is removed in spite of double removal.
" Double removal is necessary here to strip file.test.ts down to "file",
" which we can better use to append the new file name.
" expand('%:e:e') == 'test.ts' is an alternative to the regex approach,
" but I didn't feel like throwing two double removal at it (largely for clarity).
" Note: if you're not including the autocmd and function for scoping, remember to remove -buffer, or it'll only be loaded for the first buffer
command! -buffer -nargs=0 TSSwitch execute 'sp ' .. expand('%:r:r') .. (expand('%') =~ '\v\.test\.ts$' ? '.ts' : '.test.ts')
nnoremap <buffer> INSERT A MAPPING HERE :TSSwitch<CR>
endfun
" If you only care about the command and/or mapping, this autocmd is also redundant.
autocmd FileMaps
autocmd FileType typescript call TSMaps()
autocmd END
Then running the command or using some mapping of your choice, you can switch directly between the .ts
and the .test.ts
- no file finder, no useful shortcuts, no registers, and no typing the file name. Note that for obvious reasons, if you're in handler.ts
and want to switch to someotherfile.ts
, this last approach obviously doesn't work. But it lets you switch between someotherfile.ts
and someotherfile.test.ts
without modifications.I use an equivalent bit of code for switching between .hpp
and .cpp
files, and I've really come to like it. Also note that this method can be abstracted to any file type pattern you may have, including files that are in equivalent folders, but with a slightly different root. (for an instance src/something.js
and test/something.test.js
- I'm leaving this as an exercise to the reader, however, as the number of variations makes it impractical to list)
Note that this type of approach is somewhat static in terms of buffer management - if you're looking to dynamically select split types, and you're not okay with copy-pasting the first command and making the sp
a vsp
, explicitly typing %:h
is still a perfectly good choice (and it works regardless of which command you use, be that e
, sp
, vsp
, tab<something>
, or a custom command (provided it has file completion enabled). Again, refer to :h expand()
for the other modifiers you can use.
:Sex
(:Sexplore
for the long form) be good enough? It opens netrw in a split window and you can then choose you file with<CR>
. Otherwise a fuzzy finder like fzf could work too.