MacVim comes with a clever script called mvim which allows you to open files in MacVim via the command line (much like mate for TextMate). This is a wonderful tool, but does possess some idiosyncrasies. It creates a new window (rather than a new tab) when you invoke it and it also won’t take stdin as input unless you pass a dash1.
To fix this I modified the script to check for an existing macvim process, and if it exists attach tabs to it.2 Additionally, it checks for args and if none are present (or just -) the script invokes stdin. I am not much of a bash hacker though, so there are a few caveats…
- –remote-tab-silent doesn’t seem to work with listening on stdin, so the script always pops it out into a new window.
- You (apparently) can’t pass extra parameters when using –remote-tab-silent, so tricks like mvim /etc/hosts +5 to have it open with the cursor on line 5 will not work.
These are both irritating, but I feel the advantages outweigh the disadvantages. Hopefully someone can contribute fixes to these problems!
#!/bin/sh # # This shell script passes all its arguments to the binary inside the # MacVim.app application bundle. If you make links to this script as view, # gvim, etc., then it will peek at the name used to call it and set options # appropriately. # # Based on a script by Wout Mertens and suggestions from Laurent Bihanic. This # version is the fault of Benji Fisher, 16 May 2005 (with modifications by Nico # Weber and Bjorn Winckler, Aug 13 2007. Some mediocre hacking by Paul Kehrer Sep 30 2009). # First, check "All the Usual Suspects" for the location of the Vim.app bundle. # You can short-circuit this by setting the VIM_APP_DIR environment variable # or by un-commenting and editing the following line: # VIM_APP_DIR=/Applications if [ -z "$VIM_APP_DIR" ] then myDir="`dirname "$0"`" myAppDir="$myDir/../Applications" for i in ~/Applications ~/Applications/vim $myDir $myDir/vim $myAppDir $myAppDir/vim /Applications /Applications/vim /Applications/Utilities /Applications/Utilities/vim; do if [ -x "$i/MacVim.app" ]; then VIM_APP_DIR="$i" break fi done fi if [ -z "$VIM_APP_DIR" ] then echo "Sorry, cannot find MacVim.app. Try setting the VIM_APP_DIR environment variable to the directory containing MacVim.app." exit 1 fi binary="$VIM_APP_DIR/MacVim.app/Contents/MacOS/Vim" # Next, peek at the name used to invoke this script, and set options # accordingly. name="`basename "$0"`" gui= opts= # GUI mode, implies forking case "$name" in m*|g*|rg*) gui=true ;; esac # Restricted mode case "$name" in r*) opts="$opts -Z";; esac # vimdiff and view case "$name" in *vimdiff) opts="$opts -dO" ;; *view) opts="$opts -R" ;; esac tabs=true stdinoption=false #let's see if we need to read from stdin #script currently assumes NO PARAMETERS if [ -z "$1" ] || [[ $1 == \- ]]; then stdinoption=true fi # Last step: fire up vim. # The program should fork by default when started in GUI mode, but it does # not; we work around this when this script is invoked as "gvim" or "rgview" # etc., but not when it is invoked as "vim -g". if [ "$gui" ]; then # Note: this isn't perfect, because any error output goes to the # terminal instead of the console log. # But if you use open instead, you will need to fully qualify the # path names for any filenames you specify, which is hard. if $stdinoption; then exec "$binary" -g - else if $tabs && [ `ps x|grep 'MacOS/MacVim'|grep -v grep|wc -l` = "1" ] && [[ `$binary --serverlist` = "VIM" ]]; then #when using remote tabs you can't pass things like +5. exec "$binary" -g $opts --remote-tab-silent ${1:+"$@"} else exec "$binary" -g $opts ${1:+"$@"} fi fi else exec "$binary" $opts ${1:+"$@"} fi
Thank you for this script.
I’m not sure if this is bad practice, but I wanted to silence the output for the mvim script, so I appended 2> /dev/null to all the exec statements.
For example:
exec “$binary” -g $opts ${1:+”$@”} 2> /dev/null
Not sure if it works in all circumstances (though I don’t see why not) .. but it’s enough for my uses.
Here’s my version of that first loop that is more complete. I don’t know if all the strange bash characters will work. You can always use open -a MacVim .
if [ -z "$VIM_APP_DIR" ]; then myDir="`dirname "$0"`" declare -a apps=("/Applications" "$HOME/Applications" "$myDir/../Applications") utils="Utilities" declare -a vims=("MacVim" "vim") declare -a all=( "${apps[@]}" "${apps[@]/%//$utils}" ) declare -a more for i in "${vims[@]}"; do more=( "${more[@]}" "${all[@]/%//$i}" ) done for i in "${all[@]}" "${more[@]}"; do if [ -x "$i/MacVim.app" ]; then VIM_APP_DIR="$i" break fi done fiHey,
not sure this would be the right place to ask but it seems like you have a better understanding of this script than I do..
Whenever invoking MacVim thru the terminal via the mvim command, I get a errors detected while processing menu.vim. MacVim starts but i have to press enter a couple of times to clear the errors and be able to use the terminal again.. Would you have any idea how to stop these ?
Thanks,
Nicolas
Is there any reason you wouldn’t want to just do an: alias mvim=”open -a MacVim” in your .profile?
Just tried it out and it works great for me!