## October 14, 2007

### the GoF patterns implemented in Ruby

I just finished implementing almost all of the GoF patterns in Ruby.

You can also go straight to the code:

## October 11, 2007

### vim as an IDE

So I like vim a lot, and I've been using it on and off for a few years, but recently I've been using it full-time to code in Python. I learned a few things along the way and I made vim a better IDE for myself. Here's how.

You can follow along or go straight to download my .vimrc file. Place the .vimrc file in your home folder and enjoy the goodies.

The first step is to make sure you have the equivalent power of jedit, textpad, gedit and the like.

### Syntax highlighting, indentation, stats...

Make sure you install the full vim package. That will give you syntax highlighting for free, for every language you'll ever code in.

Then you can tweak the indent and the tabs as you wish. see vim's help (:help 'searchterm') for tabstop and autoindent. Also make sure your vimrc starts with:

set nocompatible " must be the first line
filetype on
filetype indent on
filetype plugin on
set laststatus=2
set statusline=%<%f\%h%m%r%=%-20.(line=%l\ \ col=%c%V\ \ totlin=%L%)\ \ \%h%m%r%=%-40(bytval=0x%B,%n%Y%)\%P

The last line will make vim display stats of the file in the status bar.

You want to see the line numbers? set nu

You want to highlight the cursor's line? set cul

Having problems pasting text into your buffer now that autoindent is on? see :set paste

### File exploring

Alright. You need two plugins, NERDTree and BufExplorer.

NERDTree is started by typing :NERDTree and it will give you a much better file explorer than any other IDE. BufExplorer is started by typing \be and it will allow you to access a list of recently used files, and switch between them quickly.

You might also want to bone up on windows and tabs (:help windows and :help tabs)

### Completion

This one is the first complicated item so I will leave it to you to figure it out. Just know that Vim has got all sorts of completion: keywords/filenames/current buffer/previous lines. The easiest one is to type Ctrl-X-N in insert mode. It will give you a list of the words in the current buffer that start with what you just typed.

### Search

You need incsearch set to show search matches as you type. Also, use * on a word to search for it in the current document. Use # to search backwards.

You should also copy this following code into your vimrc. It will allow you to place the cursor on a word, type \* and see a list of files that contain the word, recursively from your working directory. If it takes too long, you can change the cwd with the :cd command.

Once you can see the list of files, just type the number of the file you want to visit, and vim will take you there, at the line where the match occurred.

This function will also ask you for a second pattern, which you can use to make the search better/faster. For example if you know you are looking for a Python function definition, specify 'def' as the second pattern. (credits to a vim script that I can't find anymore)

map \* "syiw:Grep^Rs<cr>
function! Grep(name)
let l:pattern = input("Other pattern: ")
"let l:_name = substitute(a:name, "\\s", "*", "g")
let l:list=system("grep -nIR '".a:name."' * | grep -v 'svn-base' | grep '" .l:pattern. "' | cat -n -")
let l:num=strlen(substitute(l:list, "[^\n]", "", "g"))
if l:num < 1
return
endif

echo l:list
let l:input=input("Which?\n")

if strlen(l:input)==0
return
endif

if strlen(substitute(l:input, "[0-9]", "", "g"))>0
echo "Not a number"
return
endif

if l:input<1 || l:input>l:num
echo "Out of range"
return
endif

let l:line=matchstr("\n".l:list, "".l:input."\t[^\n]*")
let l:lineno=matchstr(l:line,":[0-9]*:")
let l:lineno=substitute(l:lineno,":","","g")
"echo "".l:line
let l:line=substitute(l:line, "^[^\t]*\t", "", "")
"echo "".l:line
let l:line=substitute(l:line, "\:.*", "", "")
"echo "".l:line
"echo "\n".l:line
execute ":e ".l:line
execute "normal ".l:lineno."gg"
endfunction
command! -nargs=1 Grep :call Grep("<args>")

A similar feat can be accomplished with Find instead of Grep. Use this to find all files that contain the word under cursor in their names (mapped to \f).

map \f "syiw:Find^Rs<cr>
function! Find(name)
let l:_name = substitute(a:name, "\\s", "*", "g")
let l:list=system("find . -iname '*".l:_name."*' -not -name \"*.class\" -and -not -name \"*.swp\" | perl -ne 'print \"$.\\t$_\"'")
let l:num=strlen(substitute(l:list, "[^\n]", "", "g"))
if l:num < 1
return
endif

if l:num != 1
echo l:list
let l:input=input("Which ? (=nothing)\n")

if strlen(l:input)==0
return
endif

if strlen(substitute(l:input, "[0-9]", "", "g"))>0
echo "Not a number"
return
endif

if l:input<1 || l:input>l:num
echo "Out of range"
return
endif

let l:line=matchstr("\n".l:list, "\n".l:input."\t[^\n]*")
else
let l:line=l:list
endif

let l:line=substitute(l:line, "^[^\t]*\t./", "", "")
"echo "".l:line
execute ":e ".l:line
endfunction
command! -nargs=1 Find :call Find("<args>")

### Others

By now you should have almost everything a bloated IDE has to offer, except you can use all of vim's capabilities for the nasty tasks. Some other notes:

• You can press '!' on a file name in NERDTree to access a bash command line. Priceless to quickly add files to SVN or copy/rename

• You can download snippetsEmu to get TextMate-like snippets for a slew of languages

• Go back and forth in your 'edit list' with g; and g, (just like a browser's back and forward buttons)

• Same thing for jumps with Ctrl-O and Ctrl-I

• You can fold whatever you want: select text in visual mode (v) and press :fo

Now if I could only put my hands on a refactoring tool plugin...

[edit: the comments are turning into a 'miscellaneous and advanced' section for this post... check them out!]