39

Is there a way to let gVim only run a single instance, so that when a new file is opened with it it's automatically opened in a new tab in the currently running instance?

I know you can do that by passing --remote-tab-silent but I want to configure gvim so that this becomes the default behavior. i.e. I want to type gvim filename and make it act as if I passed the --remote-tab-silent option to it.

gVim 7.2

Edit

I'm on windows (vista)

hasen
  • 161,647
  • 65
  • 194
  • 231
  • I have written a wrapper script that does precisely this and a little more (like add context menu option to open files in the same GVim instance by right-clicking them). Here is the link: https://github.com/susam/vimer. It works on Windows, Linux and OS X. On Windows, just download the script and rename it to `gvim.cmd` and then all three frequently commands would work as you expect, i.e. `gvim` would launch a new GVim instance, `gvim foo.txt bar.txt` would open the files in a currently running instance (if it exists, new instance otherwise) and `dir | gvim -` would pipe the output into gvim. – Susam Pal Jan 07 '16 at 03:01
  • However, note that https://github.com/susam/vimer would open files in new *buffers* (instead of *tabs*) in an existing instance of GVim. To open them in new *tabs* instead, you'll have to use the `-t` option. This is explained further at https://github.com/susam/vimer#getting-started. Reason for making *buffers* the default instead of *tabs*: (1) http://stackoverflow.com/a/103590/303363 (2) http://stackoverflow.com/a/26710166/303363 (3) http://joshldavis.com/2014/04/05/vim-tab-madness-buffers-vs-tabs/ – Susam Pal Jan 07 '16 at 03:15

13 Answers13

39

If you are using the bash shell (on Linux/OS X/using Cygwin) is to add you ~/.bashrc file:

gvim () { command gvim --remote-silent "$@" || command gvim "$@"; }

On Windows I think you could have a gvim.bat batch-script to achieve the same..

gvim.exe -p --remote-tab-silent %1 %*

If gvim.exe isn't in your path

Run > Search "Environment"

Edit PATH var for current user or system.

rickerbh
  • 9,731
  • 1
  • 31
  • 35
dbr
  • 165,801
  • 69
  • 278
  • 343
  • 2
    You'll need `alias gvim="gvim --remote-tab-silent || gvim"` to avoid `Argument missing after: "--remote-tab-silent"` when you call without a filename to open a blank document. – Tom Viner Mar 22 '11 at 15:44
  • 1
    or rather to put `gvim --remote-tab-silent $@ || gvim $@` in an executable in ~/bin/gvimt or similar. – Tom Viner Mar 23 '11 at 12:11
  • @TomViner Now I realize that even with these solutions, the message "Arguement missing after..." still appears, but then gvim is able to open (which is *not* the case normally.) It is the alias suggested above that does not work, it only ever opens a new instance of gvim. However, your suggestion to use an executable file worked, as did adding the following in my .bashrc: `gvimt () { command gvim --remote-silent $@ || command gvim $@; }`. – Johann Mar 29 '12 at 17:17
  • @Johann updated answer with your function (there seems [to be some issue](http://www.cyberciti.biz/faq/linux-unix-pass-argument-to-alias-command/) using `$@` in aliases) – dbr Mar 30 '12 at 04:24
  • 1
    Even though this works it still prints the error Argument missing after: "--remote-tab-silent" So I redirected stderr to /dev/null like this ```gvim () { command mvim $@ --remote-silent 2> /dev/null || command mvim $@; }``` – blockloop Jul 05 '13 at 19:31
  • 1
    Coming late to the party: always quote `"$@"` to protect filenames with spaces (or other chars in $IFS) – glenn jackman Jul 19 '13 at 14:36
  • I'm curious about %* in the Windows command line. From what I can tell that expands to all arguments. So wouldn't including %1 as well as %* cause %1 to be repeated? – Owen Nov 12 '15 at 23:15
11

It depends on your operating system and shell. Using linux you can always set up an alias like:

alias gvim='gvim --remote-tab-silent'

in your .bashrc (if you use bash as your login shell).

On windows see the Vim wiki for solution: http://vim.wikia.com/wiki/Launch_files_in_new_tabs_under_Windows .

Zsolt Botykai
  • 50,406
  • 14
  • 85
  • 110
5

I've found the --remote-tab-silent option in an alias to work for the most part except when I've wanted to pass options to gvim (e.g. gvim --serverlist) - in which case gvim treats the option as a literal filename which is no good as firstly that's not what you wanted and secondly you have to clean up the buffers from your now tainted vim session.

It's not practical to use another alias or resolve vim/gvim differently for some cases such as the following.

  • gvim
  • gvim /path/to/files
  • gvim --serverlist
  • gvim -p /path/to/file1 /path/to/file2
  • gvim -t tag filename

My solution is the following wrapper script around gvim (~/.bin/gvim) as Tom Veiner suggests but this will only use an existing server if none of the arguments are gvim options - otherwise, a new server is created.

#!/usr/bin/perl

use v5.10;

sub gvim { exec { '/usr/bin/gvim' } '/usr/bin/gvim', @_; }

if (scalar @ARGV) {
  unshift @ARGV, '--remote-tab-silent' unless /^--?/ ~~ @ARGV;
  gvim @ARGV 
}
else {
  chomp(my $serverlist = `gvim --serverlist`);
  if (length $serverlist) {
    gvim '--remote-send', '<Esc>:tabnew<CR>'
  } else { gvim }
}
Community
  • 1
  • 1
shalomb
  • 3,456
  • 2
  • 23
  • 19
3

Portable Wrapper Script:

I got a little tired of working around this in cygwin + windows so I finally did something about it. I started with the wrapper script defined above but I wound up making it a lot more robust and multi-env capable for *nix and Win.


#!/bin/bash
#bash wrapper for windows/cygwin gvim

#####################################################################
## Cygwin/*nix and Windows gvim wrapper script, alias friendly, path friendly
## Author: Matt Gregory (skyleach (AT) geemale (dot) com)
## Version: 1.5
## Date: Thu Jun 12 10:02:54 2014
## Known Bugs:
## Changes:
##      Thu Jun 12 10:04:08 2014 : Initital posting to StackOverflow
#####################################################################

[[ -z ${WINVIM} ]] && WINVIM=true
[[ -z ${VIMRUN} ]] && export VIMRUN='' #scoping
if [[ ${WINVIM} = false ]]; then
    [[ ! ${VIMRUN} ]] && VIMRUN='/bin/gvim'
    ANS=$("${VIMRUN}" --serverlist | grep GVIM)
else
    [[ ! "${VIMRUN}" ]] && VIMRUN='/cygdrive/c/Program Files/vim/vim74/gvim'
    ANS=$(ps -Wsl | grep "${VIMRUN}" | sed -e "s/\s\+\([0-9]\+\).*/\1/g")
fi
[[ ! -z ${VIM} && ${WINVIM} = true ]] && export VIM=$(cygpath -wal "${VIM}")
RT="--remote-tab"
[[ $ANS ]] || unset RT
if [ ! -z ${DEBUG} ]; then
    echo "WINVIM: ${WINVIM}"
    echo "VIMRUN: ${VIMRUN}"
    echo "ANS: ${ANS}"
    echo "VIM: ${VIM}"
fi
#process arguments or stdin
if [ ${#} -ne 0 ]; then
    [[ ! -z ${DEBUG} ]] && echo "Got arguments [${#}]:'${@}'"
    for OFILE in "${@}"; do # if [ -f "${OFILE}" ] || [ -d "${OFILE}" ]; then
        [[ -h ${OFILE} ]] && OFILE="$(readlink -f "${OFILE}")"
        [[ ${WINVIM} == true ]] && OFILE=$(cygpath -wal "${OFILE}")
        echo "\"${VIMRUN}\" --servername GVIM $RT \"${OFILE}\""
        "${VIMRUN}" --servername GVIM $RT "${OFILE}" &
        if [[ -z ${RT} ]] || [[ ! "${RT}" ]]; then
            RT="--remote-tab"
            sleep 5 #give gvim time to start up, running too fast messes things up
        else
            sleep .3 #shorter sleep for tabs
        fi
        #fi
    done
else
    while read OFILE; do
        [[ -h ${OFILE} ]] && OFILE="$(readlink -f "${OFILE}")"
        [[ ${WINVIM} == true ]] && OFILE=$(cygpath -wal "${OFILE}")
        echo "\"${VIMRUN}\" --servername GVIM $RT \"${OFILE}\""
        "${VIMRUN}" --servername GVIM $RT "${OFILE}" &
        if [[ -z ${RT} ]] || [[ ! "${RT}" ]]; then
            RT="--remote-tab"
            sleep 3 #give gvim time to start up, running too fast messes things up
        else
            sleep .3 #shorter sleep for tabs
        fi
    done
fi
# vim: set filetype=sh:

How to use it effectively:

  • Install the above code into a script file on yor path somewhere
  • Add a WINVIM environment variable to windows or your ~/.bashrc file in order to set the default script behavior. true/use windows. false/use x11
  • alias some command to cygwin and/or windows gvim like so:

    echo "alias gwrap='WINVIM=false ~/src/localscripts/wgwrap'" >> ~/.bashrc echo "alias wgvim='wgwrap'" >> ~/.bashrc

  • NOTE: If the hard-coded paths to gvim are incorrect for your system you can edit the script directly, the alias(s) and/or add the environment variables WINVIM and/or VIMRUN. You can set them in the alias as I do above for gwrap or you can add them to your .bashrc or Windows system environment.

SkyLeach
  • 1,363
  • 13
  • 15
  • I read the below replies and I suggest the authors read the details on this script and the code. It's far more portable and useful than the others. Paths, windows AND cygwin servers at the same time on the same machine, process checking for windows (can't use --listservers with windows gvim and get the results back to the shell. Mine doesn't spawn a windows command shell when executing and more – SkyLeach Jun 12 '14 at 15:08
3
alias tvim="gvim --servername `gvim --serverlist | head -1` --remote-tab"

This make vim open a new file in new tab on same instance of vim. Source: http://eustaquiorangel.com/posts/477

SergioAraujo
  • 11,069
  • 3
  • 50
  • 40
2

I'm using TotalCommander for file browsing. It lets you press "F4" to edit the file. So in the "Editor for F4" option window, you just need to do the following:

C:\Program Files (x86)\Vim\vim73\gvim.exe --remote-tab-silent

Works on my win7 64bit machine.

AZ.
  • 7,333
  • 6
  • 44
  • 62
2

The solutions above don't launch the gvim server on first execution, so I use:

ANS=`pgrep -fx "$VIM"`

# Launch server if needed
if [[ ! $ANS ]]; then
   $VIM
fi

# Now open the file
if [[ $1 ]]; then
    $VIM --remote-tab "$@"
fi

modified from https://stackoverflow.com/a/15335004/214686

Community
  • 1
  • 1
Stefan van der Walt
  • 7,165
  • 1
  • 32
  • 41
2

NOT For WINDOWS

I use MacVim (snapshot 73).

Add this to your .bash_profile.

It won't generate "NO NAME" and error message.

vi() {

    if [[ `mvim --serverlist` == 'VIM' ]]; then
        command mvim --remote-tab-silent "$@"
    else
        command mvim "$@"
    fi
}
zclin
  • 21
  • 2
2

I often find that I want to go to a specific place in a file. The only way I found to do this was:

gvim --remote-send '^[:tabnew +$lineno $filename ^M'

where ^[ is esc (typed ctrl-v esc) and ^M is enter (ctrl-v enter).

Hope this helps. If anyone understands how to use --remote-expr, give me a shout.

lucapette
  • 20,564
  • 6
  • 65
  • 59
alsuren
  • 168
  • 1
  • 2
1
gvimt () { [ $# -ne 0 ] && command gvim --remote-silent-tab $@ || command gvim $@; }
Sven
  • 11
  • 1
1

I'm actually using

  gvim () { 
    if [ "$#" -gt 0 ]
    then
      gvim --remote-tab-silent "$@" &
    else
      gvim "$@" &
    fi
  }

It kills errors and only used the flag when there is a parameter

blockloop
  • 5,565
  • 5
  • 30
  • 31
1

Using MacVim, I discovered the default servername was simply VIM. Sticking with that theme, I threw the following function in my bashrc and it works like a charm:

mvim() { ~/bin/mvim --servername VIM --remote-tab-wait-silent $* & }
Benjamin Riggs
  • 648
  • 1
  • 7
  • 13
0

Change your path in registry

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Applications\gvim.exe\shell\edit\command

"Path2gvim\gvim.exe" "%1" -->
"Path2gvim\gvim.exe" --remote-tab-silent "%1"

Reman
  • 7,931
  • 11
  • 55
  • 97