< voriga

näxda >

Vim and Win (Revised)

vom Strehl Manuel

Gspeichad ois

Bapperln: , ,

In my first article I described a possibility to open files from the Windows Explorer in a terminal Vim instance. What bugged me most was, that I wasn’t able to use the same script from the command line, too.

A picture of the context menu in
  Explorer

I worked around a bit and would like to present you here my next iteration on the way to fully embed a terminal Vim in a Windows environment. Prerequisites are, as last time, Cygwin, MinTTY as terminal and screen running in MinTTY.

There are two files, that do the magic. The one must live in the Windows path and is called send_to_vim.bat. I assume it to be in C:\WINDOWS in the following. The other file is a Bash script send_to_vim.sh. This I put in /home/Manuel/bin (Cygwin path). The functionality for the Explorer is added by a registry setting:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\*\shell]

[HKEY_CLASSES_ROOT\*\shell\Send to vim]

[HKEY_CLASSES_ROOT\*\shell\Send to vim\command]
@="C:\\WINDOWS\\send_to_vim.bat \"%1\""

This adds a new entry “Send to vim” to each file (and folder) in the Windows Explorer context menu. A click calls the batch file send_to_vim.bat:

@echo off

:: bash.exe is in D:\cygwin\bin
D:
chdir \cygwin\bin

set FILE=%1
bash --login /home/Manuel/bin/send_to_vim.sh -w %FILE%

This does nothing more than calling the Bash file by starting a login Bash shell and invoking the script with two parameters, -w and the Windows path in question.

Now to the Bash script send_to_vim.sh:

#!/bin/bash

if ! ps -u "$USER" | grep -q "screen"; then
  # start mintty/xterm and screen
  if type mintty >/dev/null 2>/dev/null; then
    mintty -w max -t Terminal /bin/bash --login -c screen &
  else
    # bash_screen == "bash --login -c screen"
    xterm $HOME/bin/bash_screen &
  fi
  sleep 2
fi

for FILE in "$*"; do
  if type cygpath >/dev/null 2>/dev/null; then
    FILE=$(cygpath -u -a "${FILE/\\/\\\\}")
  elif [[ ${FILE:0:1} != / ]]; then
    FILE=$PWD/$FILE
  fi

  ESC=$(echo -n -e '\e')
  CR=$(echo -n -e '\r')
  screen -p vim -X stuff "$ESC:tabnew ${FILE/ /\\ }$CR"
done

screen -X select vim

Removing the quoting noise, the important line is the third-to-last. I use screen’s -p flag to select a window with title vim and the -X stuff method to stuff arbitrary strings in this window’s stdin. In my case, the “arbitrary string” is an ESC to get Vim into normal mode, followed by the :tabnew command.

This file has some improvements over the old version. While it works basically the same for the Windows > Explorer > Batch > Vim case, it can also be called from within a Cygwin/Bash console:

$ send_to_vim.sh /var/log/apache2/*.log

And yes, it handles multiple files just fine. Each file will be opened in a separate tab. I have set an alias vm to send_to_vim.sh. This way, when working in another screen window I just type vm file.ext and I’m instantly brought to my Vim instance waiting with the open file.