vim

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


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.


Solution

  • 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