dimarts, de novembre 30, 2010

:w !bash

When working with several files in a folder, one often wishes it would be great if one could rename all those files with a couple of good old editor commands. This is how I do this in Windows with gvim for Windows and cygwin bash. The basic idea is suggested in the vim help system (:he rename-files). Basically the process amount to:
1) Creating a buffer with a list of all the files to rename, one per line
2) Using the native editing capabilities of vim to change these lines into shell commands; each line contains a rename (shell) command
3) Issuing :w !bash to pipe the buffer to the shell

In order to be able to this with cygwin bash, a minimal configuration is suggested in a number of sites:


" http://vim.wikia.com/wiki/Use_cygwin_shell
set shell=D:\foo\cygwin\bin\bash
set shellcmdflag=--login\ -c
set shellxquote=\"

Problem:

1. if --login is used to invoke the shell, it opens in the home directory, not in the current file's directory.

2. if --login is not used, it opens in the current file's directory, but /etc/profile is not read.

In the second case, the cygwin $PATH (/usr/local/bin:usr/bin:bin) is not appended to the Windows %PATH%. As a consequence, only internal commands can be passed to the shell (pwd, cd, etc) but not a program name, since the shell is unable to find the executable. This means that something line :.!bash will fail.

Solution:

The best solution I came up to is a slight modification of the variant of this tip given in http://www.mail-archive.com/vim@vim.org/msg02138.html.
The idea is to use .bashrc to set the path when necessary instead of modifying /etc/profile as suggested here. Since .bashrc is source for non-login shells, do not use --login. Bash will then open in the file's directory (or whatever the current directory happens to be, that is, :pwd). In order to have the path correctly set only when vim requires it, set an environment variable from .vimrc when calling the shell and check its value in .bashrc; if the variable is set, then set the path as in /etc/profile (of course you could set the path directly in .vimrc, but this is would be out of sync if you happen to change something in cygwin or in vim; in other words, it would not be portable).

In .vimrc:

set shell=D:\\cygwin\bin\bash
let $BASH_ENV = '~/.bashrc'
let $FROMVIM = 'X'

In .bashrc:

if [ -n "$FROMVIM" ]; then
PATH="/usr/local/bin:/usr/bin:/bin:$PATH"
fi


By the way: you might want to change the file format of the vim buffer from dos to unix (:se ff=unix) if cygwin is expecting this. Otherwise you'll get a non-printable "\r" appended to each file name.

diumenge, d’octubre 03, 2010

ZenCoding and wget

I recently discovered ZenCoding.vim. It includes a nice feature for building an html anchor from an url; the anchor text is being directly retrieved from the web, specifically the <title> tag of the web page:

Say your file contains a line

http://www.amazon.com

If you position the cursor on the url and press (Crtl Y + a), ZenCoding transforms it into

<a href="http://www.amazon.com">Amazon.com: Online Shopping for Electronics, Apparel, Computers, Books, DVDs &amp; more</a>

Unfortunately, this feature relies on curl for retrieving information from the web. I use wget instead (for no reason, I just happen to know this tools and it suffices for my modest needs).

In order to get ZenCoding to work with wget you have to change two lines of code as follows:


"silent! exec '0r!curl -s -L "'.substitute(a:
url, '#.*', '', '').'"'

silent! exec '0r!
wget -q -O - "'.substitute(a:url, '#.*', '', '').'"'

and


"let hex = substitute(system('curl -s "'.
fn.'" | xxd -p'), '\n', '', 'g')

let hex = substitute(system('wget -q -O - "'.
fn.'" | xxd -p'), '\n', '', 'g')


At least this is what GNU wget running on Windows + Cygwin expects.



Update 05.10.2013

Emmet, the current incarnation of ZenCoding, makes this configuration even simpler. It defines a global variable than can be set in your .vimrc file:

let g:emmet_curl_command= 'wget -q -O - '

That's it. You are non longer required to touch the plugin's source code.


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).