There's three main steps in accomplishing what you're asking:
- getting the alternate file's name
- opening that file in the current window or in another window as desired
- restoring cursor position within that file
To find the alternate file name you want to break the current file name into the "root" and the "extension." A simple way to do this is:
let parts = split(expand("%:p"), "[.]");
let root = parts
let extension = parts
If you know you're only ever switching between
.cpp files, you can change the extension from one to the other easily:
if extension == "h"
let extension = "cpp"
let extension = "h"
Alternatively, create a dictionary mapping known extensions to potentially valid alternate extensions. Or use
globpath() to get all possible alternates for the current file:
let alternates = globpath(expand("%:h"), root . ".*")
and pick the first one, or whatever. I prefer the
globpath approach, with some extra smarts I'll describe later. Once you have picked the target extension, form the full target path:
let target = root . "." . alternates[whicheverAlternateExtensionYouWant]
Now you can open the alternate file in the current window:
execute "edit " . target
winnr() to get the "other window" number (
winnr("#") is the window that
<C-W>p would jump to, or you can hard-code it if you know it will always be the same for your setup) and do something like:
let window = winnr("#")
execute window . "wincmd w"
execute "edit " . target
This gives you a really basic solution to opening alternate files. There's a few deficiencies with the above approach, since I wrote it to be straightforward and it's a bit off-the-cuff. I've written a plugin that does alternate file switching "the way I wanted," (cycling through all available
globpath() results). It addresses some of the problems with the simplicity of the above, you can check out its implementation if you're interested in exploring more.
Finally, the "restore cursor position" point. I saved it for last since it's orthogonal to the alternate switching thing (my plugin doesn't handle it for example), but you could put it into your function if you're going to roll your own.
:help line() has an autocommand that is useful for restoring the cursor position to where it was when the file was last opened:
:au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
I just put that, or something very similar, in my
.vimrc since I prefer the behavior all the time. You could easily just put the code elsewhere though.