dissabte, d’abril 10, 2010

Commanding Firefox from Vim

1 - Install cygwin if not already installed

Get cygwin from http://www.cygwin.com/

2 - Install cygwin netcat, if not already installed

Just follow the directions in the page above. Netcat is a telnet-like tool, that is, a command line program for establishing TCP sessions with a remote server. The executable program is called nc.

3 - Set up gVim to use the cygwin shell instead of the Windows shell

Following the suggestion in vim.wikia.com, or alternativelly in http://www.zzapper.co.uk/vim-tips-blog, edit your _vimrc file in your initialization folder. Find out what your initialization folder is by issuing

:he initialization

in gVim and read out the relevant parts. In my case, this is $VIM/_vimrc. Add the following lines to your _vimrc file:

" Use cygwin shell
set shell=<Windows path to your cygwing installation>\bin\bash
set shellcmdflag=--login\ -c
set shellxquote=\"

Notice that you don't have to use quotes in the value of the "shell" variable above.

If you use the vimdiff command, it is possible that you have to redefine it to use the cygwin diff utilitiy:

set diffexpr=MyDiff()
function MyDiff()
let opt = ''
if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif
if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif
" The following line assumes that the cygwin shell is used, and that
" cygwin diff is also installed (and in the executable path)
silent execute '!' . 'diff -a ' . opt . '"' . v:fname_in . '" "' . v:fname_new . '" > "' . v:fname_out . '"'
endfunction

4 - Install the mozRepl Firefox extension

Get and learn the fundamentals of the mozRepl Firefox extension from http://wiki.github.com/bard/mozrepl/. In a nutshell, mozRepl opens an tcp port in Firefox that listen for javascript commands that excecute in the chrome context. This means that you can connect to a running Firefox instance via telnet and make it do whatever you want, for example, reloading the page in the tab with the current focus.

5 - Check that mozRepl is working

Open a cygwin shell and issue the following netcat command. MozRepl answers with a repl> prompt. Enter a javascript command as below, and lo!, youl see Firefox executing the command. You can leave the netcat session by hitting Ctrl-C or by issuing the MozRepl command repl.quit().

$ nc localhost 4242

Welcome to MozRepl.

- If you get stuck at the "...>" prompt, enter a semicolon (;) at the beginning
of the line to force evaluation.
- If you get errors after every character you type, see http://github.com/bard/
mozrepl/wikis/troubleshooting (short version: stop using Microsoft telnet, use n
etcat or putty instead)

Current working context: chrome://browser/content/browser.xul
Current input mode: syntax

repl> alert("Hello MozRepl!")
repl> repl.quit()

If things seems not to be working, just change the mozRepl port to something different that 4242. The only requirement is that the port must be higher than 1024.

6 - Check that mozRepl works from the cygwin shell

Open an cygwin shell and issue the following command:

echo "alert('Hello World'); repl.quit()" | nc localhost 4242 > /dev/null

This sends the following commands to the repl shell in Firefox:

alert('Hello World)
repl.quit()

The first command is passed unchanged to Firefox. The second is interpreted by the repl self and causes the tcp connection to be closed; otherwise you should either terminte netcat by force, which is unschön, or invoke netcat as "nc -w 1" in order to time out one second later, which is also unschön.
The "/dev/null" is just to get rid of the repl output in the console.

7 - Check that mozRepl works from gVim

From gVim, issue the following command:

:.!echo 'alert(\"Hello World\");repl.quit()' |nc localhost 4243

(you have to hit "!" twice in order to get ":!." )

8 - Define gVim commands to call mozRepl

The original idea comes (as far as I know) from http://d.hatena.ne.jp/iNo/20061005#1160031028. First, create a bash script as below. I stored it into a mozrepl subfolder of my $HOME folder ($HOME refers to the cygwin environtment variable)

esquifit> cd ~
esquifit> mkdir mozrepl
esquifit> cd mozrepl
esquifit> vim reload_firefox.sh

#!/usr/bin/bash
nc -w 1 localhost 4243 <<EOF > /dev/null
content.location.reload(true)
repl.quit()
EOF


Next, create a file firefox_reload.vim in the plugin folder of your VIMFILES folder:

if exists('g:reload_firefox')
finish
endif

command -nargs=0 Setreloadfirefox :call SetMozreplReloadFirefox()

function! ReloadFirefox()
" for Cygwin: path relative to home directory
let script_file = '/mozRepl/reload_firefox.sh'

if filereadable( $HOME . script_file)
call system("$HOME" . script_file)
else
echo "ERROR : File \"" . script_file . "\" is NOT found."
endif
endfunction

function! SetMozreplReloadFirefox()
if exists('g:reload_firefox')
autocmd! mozreplreloadfirefox
unlet g:reload_firefox
echo "\"mozreplreloadfirefox\" of augroup has been deleted."
else
augroup mozreplreloadfirefox
autocmd BufWritePost *.html,*.htm,*.php,*.js,*.css call ReloadFirefox()
augroup END
let g:reload_firefox=1
echo "Firefox browser content is reloaded when file(*.html,*htm,*.php,*.js,*.css) is saved."
endif
endfunction



9 - Enjoy

When using gVim for editing a file, you can now issue the Setreloadfirefox command to toggle auto reload in Firefox every time you save the file in gVim. Note that the file that you are editing in gVim and the page of the currently focused tab in Firefox are totally unrelated.
I use this to edit Greasemonkey scripts that apply to the currently loaded page. Of course, it is first necessary to install the script properly. Afterwards, when launching gVim as you editor of choice from Greasemonkey, everything is automatic (remember to invoke Setreloadfirefox in order to toggle the autoload feature, and once again to disable it).