Open CptStubing opened 11 years ago
Good point, however :ls
may return the full path (/path/to/file.txt
), which would break the regex you suggest. let buffername = bufname(a:filename . '$')
would solve most cases, but perhaps not all. I'll look into filename parsing a little more...
Initially, I had wrongly assumed that bufname()
would always return an absolute path with the filename, but both :ls
and bufname("file.txt")
seem to either show you an absolute path or a relative path based on whether or not the value of pwd matches the path to the file. So, you might want to either break the name returned by bufname()
down to just a filename and then prepend the path yourself, or store the value of pwd, chdir
to /, call bufname()
, then chdir
back to the user's original pwd.... Whoo, that was a mouthful. Anyway, good luck in your endeavors.
OK, I think I have a solution using a different regex:
let buffername = bufname('\(^\|\/\)' . a:filename . '$')
which ensures that either it's the whole pathname (i.e., /path/to/thing.txt
) or just the filename (thing.txt
).
The bufname
approach is also good, though. Hm.
I think the bufname
is actually not even necessary for this. I was having issues with bufnr
before, and thought that it wasn't working if I passed it an absolute path and the buffer name (as displayed by bufname
) was relative. I didn't realize that my windows file names in double quotes were actually getting interpreted, so "c:\foo" becomes 'c:^Lfoo'. I really need to investigate some of the vimscript debugging solutions out there.
Can you have skim send the filename with an absolute path to your bash script? Then bufno
should find the correct buffer number regardless of what the pwd is at the time on the mvim server. So, all you need is this:
function! WhichTabAbs(filenameAbs)
if (a:filenameAbs == "")
return 0
endif
let bufNo = bufnr("^" . a:filenameAbs . "$")
if (bufNo < 1)
return 0
endif
for tabNo in range(1, tabpagenr("$"))
for bufInTab in tabpagebuflist(tabNo)
if (bufInTab == bufNo)
return tabNo
endif
endfor
endfor
return 0
endfunction
I'm not sure if Skim can send the full path... it's been a long time since I looked, but I think last time I did the answer was "no" and that was why I had to make WhichTab
minimally smart.
Does Skim.app
exist for windows? I thought not - which is why you don't have to worry about windows-type paths.
Also, in what cases does the solution I posted - let buffername = bufname('\(^\|\/\)' . a:filename . '$')
- still fail? Since it's just doing a regexp search, it doesn't matter what the current path is - if the file is in the cwd, it will match ^filename$
, or if it's not, it will match /filename$
. Are there any other cases?
Yep, no Skim.app on windows. I've been using vim forever, but never bothered to learn vim script until now, so the string interpolation thing with double quotes was just something I didn't realize was happening with my paths on windows while I was testing various things, that's all.
I think you are good with that regex. Even if filename is a relative path, it will still match properly as ^filename$. The only thing I could think that might throw it off is if Skim.app is using a relative path that's relative to a different pwd than vim's, but you'd have to check and see if Skim.app even sends paths or relative paths at all.
I just wanted to point out that the call to bufname
and subsequent call to bufnr
is not necessary. They both do the same pattern match on the expression that's passed to them, and the rest of the logic is depending on the buffer number, so you really need to just call bufnr
. The check that the parameter to the function is not an empty string is because bufnr("")
tells you the number of the current buffer.
function! WhichTab(filename)
if (a:filename == "")
return 0
endif
let bufNo = bufnr('\v(^|/)' . a:filename . "$") " see :he magic for \v
if (bufNo < 1)
return 0
endif
for tabNo in range(1, tabpagenr("$"))
for bufInTab in tabpagebuflist(tabNo)
if (bufInTab == bufNo)
return tabNo
endif
endfor
endfor
return 0
endfunction
Ah, got it, that's quite true. As it stands, if a:filename
is a blank string or if the buffer isn't open in any tab, 0
is returned anyway, so I didn't even bother with the extra checks.
According to :help bufname()
bufname({expr}) *bufname()* The result is the name of a buffer, as it is displayed by the ":ls" command. If {expr} is a Number, that buffer number's name is given. Number zero is the alternate buffer for the current window. If {expr} is a String, it is used as a |file-pattern| to match with the buffer names. This is always done like 'magic' is set and 'cpoptions' is empty. When there is more than one match an empty string is returned.
Since the string is used as a pattern, it might match part of another buffer name. The 'magic'-like behavior will save you in a lot of common cases, but there are still some gotchas. To avoid them, instead of calling:
let buffername = bufname(a:filename)
You can call:let buffername = bufname("^" . a:filename . "$")
i.e., a regex that says the entire buffer must match the filename.