Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VIM: Check if a file is open in current tab? window? (and activate it)

Tags:

vim

In vim, you can check if a file is open in the current buffer with bufexists. For a short filename (not full path), you can check if it's open using bufexists(bufname('filename')).

Is there any way to check if a file is open in a tab?

My closest workaround is to do something like:

:tabdo if bufnr(bufname('filename')) in tabpagebuflist(): echo "Yes"

However, that's sort of pythonic pseudocode... I'm not sure how to get that to work in vim. My goal is for an external applescript to check if a file is already open and if so go to a line in that file.

Ideally, I'd like to be able to search through different GUI windows too, but I've gathered (e.g. Open vim tab in new (GUI) window?) that working with different GUI windows is very challenging / impossible in VIM.

like image 507
keflavich Avatar asked Jan 12 '12 17:01

keflavich


People also ask

How to check which file is opened in vim?

Vim offers several commands for searching for files by name: :find, :sfind, :tabfind on the command-line, several normal-mode commands like gf, and others. If you just enter :find filename , Vim will directly open the first file found in your 'path' matching "filename".


2 Answers

My impatience and good documentation got the better of me... here's the solution (greatly aided by Check if current tab is empty in vim and Open vim tab in new (GUI) window?). The source is at https://github.com/keflavich/macvim-skim

function! WhichTab(filename)
    " Try to determine whether file is open in any tab.  
    " Return number of tab it's open in
    let buffername = bufname(a:filename)
    if buffername == ""
        return 0
    endif
    let buffernumber = bufnr(buffername)

    " tabdo will loop through pages and leave you on the last one;
    " this is to make sure we don't leave the current page
    let currenttab = tabpagenr()
    let tab_arr = []
    tabdo let tab_arr += tabpagebuflist()

    " return to current page
    exec "tabnext ".currenttab

    " Start checking tab numbers for matches
    let i = 0
    for tnum in tab_arr
        let i += 1
        echo "tnum: ".tnum." buff: ".buffernumber." i: ".i
        if tnum == buffernumber
            return i
        endif
    endfor

endfunction

function! WhichWindow(filename)
    " Try to determine whether the file is open in any GVIM *window*
    let serverlist = split(serverlist(),"\n")

    "let currentserver = ????
    for server in serverlist
        let remotetabnum = remote_expr(server, 
            \"WhichTab('".a:filename."')")
        if remotetabnum != 0
            return server
        endif
    endfor

endfunction

then use like so:

exec "tabnext ".WhichTab('my_filename')

echo remote_foreground( WhichWindow('my_filename') )

or, from the command line, here's a script to go to a particular line of a file using WhichTab:

#!/bin/bash

file="$1"
line="$2"

for server in `mvim --serverlist` 
do
    foundfile=`mvim --servername $server --remote-expr "WhichTab('$file')"`
    if [[ $foundfile > 0 ]]
    then
        mvim --servername $server --remote-expr "foreground()" 
        mvim --servername $server --remote-send ":exec \"tabnext $foundfile\" <CR>"
        mvim --servername $server --remote-send ":$line <CR>"
    fi
done
like image 59
keflavich Avatar answered Nov 15 '22 09:11

keflavich


I'd reply to keflavich, but I can't yet...

I was working on a similar problem where I wanted to mimic the behavior of gvim --remote-tab-silent when opening files inside of gvim. I found this WhichTab script of yours, but ran into problems when there is more than one window open in any given tab. If you split windows inside of tabs, then you will have more than one buffer returned by tabpagebuflist(), so your method of using the buffer number's position in the List doesn't work. Here's my solution that accounts for that possibility.

" Note: returns a list of tabnos where the buf is found or 0 for none.
"               tabnos start at 1, so 0 is always invalid
function! WhichTabNo(bufNo)
    let tabNos = []
    for tabNo in range(1, tabpagenr("$"))
        for bufInTab in tabpagebuflist(tabNo)
            if (bufInTab == a:bufNo)
                call add(tabNos, tabNo)
            endif
        endfor
    endfor
    let numBufsFound = len(tabNos)
    return (numBufsFound == 0) ? 0 : tabNos
endfunction

I think I can just return tabNos which will be an empty list that gets evaluated as a scalar 0, but I just learned vimscript and am not that comfortable with the particulars of its dynamic typing behavior yet, so I'm leaving it like that for now.

like image 24
cptstubing06 Avatar answered Nov 15 '22 08:11

cptstubing06