Friday, July 30, 2010

Python in Vim

What if your favorite editor can interpret your favorite language!!! That would make writing code a piece of cake. This is what happened to me recently. I knew Vim could interpret Python. Only after I tried it out, I found how easy it is.

Simply go to normal mode and do :py print 'Vim Roxx' to see what I am trying to tell. You have to include a :py at the start of the line and it runs in Vim just as if it were running on a Python interpreter.

I know how you are feeling. I felt the same way too. Isn't there a way to specify start of python code and end. There is one.
:py << EOF
print "This is cool"
print "I'm lovin it"

does the job for you. The EOF here is only a name and any variable_name can be used. You can also specify a file to execute by using :pyfile file_name

Here is a quick snippet. I would like to run the Python code from my current buffer. I want to go over a line and press f4 and expect Vim to execute that command by adding a ":py" in the start.

Hence I first do
:py << EOF
import vim
def run_line():
cmd = ":py " + vim.curent.line
So now every time I go over a line and type :py run_line() in the normal mode, the current line is run as a line of python code. All I now have to do is bind this function to the required key and nmap <f4> :py run_line() <CR> does the job for me.

Happy Vimming with Python :) :)

Thursday, July 22, 2010

Adding Polynomials

Imagine a polynomial like 2x3 - 3x2 + 5 was represented as a list of coefficients in a list like [1, -3, 0, 5]

My goal is to write a function that takes two lists and does polynomial addition on them. Ex: poly_add( [1, -2, 0, 3, 5] , [3, -1, 2] ) should return [1, -2, 3, 2, 7]

After a little brainstorming, I got this cute idea, which I felt was so cute that I should blog about it. Moreover it has been a while since I have written something.

Here is the function

def poly_add( x, y):
min_len = min( len(x), len(y))
return x[: -min_len] + y[: -min_len] + [ x[i] + y[i] for i in range(-min_len,0) ]

If this is trivial then great. If it is not so trivial, you will love the beauty behind this function and hence python itself.

I use Python and I am loving it :) :) :)

Friday, February 19, 2010

My daily routine ( monitor )

Here is how I spend my typical day
  1. wake up early in the afternoon at 11:30
  2. go online and check mail for 20 min
  3. get ready for lunch by 13:00
  4. go to the lab and spend time with my lappy till 20:00
  5. dinner
  6. again spend time in front of lappy
  7. go to bed
Looks like I spend most of the time in front of my lappy. Wonder what I do and for how long!!!
What if we had a program that monitors for how much time do we spend looking at each window on our machine. Actually why don't we write one. This brilliant idea was not mine but my friend Puneeth's. We tried to write this program long back ( on the night of 1st day, PyCon India ). But python Xlib documentation sucks. Atleast that is what I felt when I tried to refer it. Anyways luckily that night punch got quite close to finishing this program. Dunno if he finished it later on. But I wanted to try it out. I actually saw this documentation long before we started coding for this program. I wanted to have an option on right click menu to close the current window. I found something called NACT for adding options to right click on nautilus and a program called xclose that closes window using window display name. I could get xclose running and NACT configured but forgot about it later on.

Now I start googling. I found this link that got me started.Punch figured out that there is something called display and then screen and then window. Luckily I remembered those words. The blog post also talks about the same. I tried my hands on Xlib using ipython and found out what all this window thingy is all about.

Here is a small intro to Xlib that must get you started.

from Xlib.display import Display

# initialize the display
disp = Display()

# list no of screens available
disp.screen_count() # only one in my case.. my laptop screen..
# get the screen to work on
screen = disp.screen() # disp.screen(0) also works

## everything we see is a hierarchy of windows

root_window = screen.root
# this window object will have its parent equal to zero

print root_window.get_wm_name() ## the obvious

root_tree = root_window.query_tree()
root_tree.children ## gives you a list of window objects, its children
root_tree.parent ## lets you access its parent

Now I could not achieve what I exactly wanted. Figuring out what we concentrate on, looking at the cascade of windows and their sizes involves AI. All I wanted was the window that had focus and for how long. There is a method called event notify that notifies a focus change event but It involves a lot more digging into Xlib documentation and some patience to try out all that on ipython. For now, all I am going with the brute force method, polling the Xserver every n seconds. I ran the script while I was writing the blog post and here are the results.
02/19/10-16:10:58 -> ans@ans-laptop: ~/Desktop/xlib
02/19/10-16:11:08 -> Google Docs�-�Upload a File - Vimperator
02/19/10-16:11:18 -> Google Docs - All items - Vimperator
02/19/10-16:11:28 -> - Google Docs - Vimperator
02/19/10-16:11:38 -> - Google Docs - Vimperator
02/19/10-16:11:48 -> - Google Docs - Vimperator
02/19/10-16:11:58 -> Blogger: me, myself and py - Create Post - Google Chrome
02/19/10-16:12:08 -> Blogger: me, myself and py - Create Post - Google Chrome
02/19/10-16:12:18 -> Blogger: me, myself and py - Create Post - Google Chrome
02/19/10-16:12:28 -> Blogger: me, myself and py - Create Post - Google Chrome
02/19/10-16:12:38 -> Blogger: me, myself and py - Create Post - Google Chrome

I find them pretty satisfactory. Here is the code in case some one wants to hav a luk.
Happy Coding :)

Wednesday, February 17, 2010

File browser using Python

I always wanted to have a file browser ( like nautilus ) on my shell. Something like the image on the left.
I prefer to have my hands on the keyboard than shifting between keyboard and the tailed buddy.
I saw my friend Lee use something called Midnight Commander. I googled and found other alternatives here. But only MC was appealing to me. I started using it and it is a decent one. But I was not satisfied with its display. It shows all the files with in one big column and displays all the details as if some had typed "ls -l". And recently after switching to vi mode, I am finding it hard to access the arrow keys and would prefer something similar to vi. One way of achieving it is actually remapping keys in MC. But still the concept of moving left and right does not have a meaning in MC context. Moreover, we are used to things that behave like nautilus. I wanted a file browser that displays folders and files like nautilus and makes it possible to navigate using hjkl keys. I also wanted a mechanism where I could tag files just like in delicious. I finally decided I want a new file browser and I am going to write it :) .

My obvious and only choice is python. Although there is bash scripting with zenity to make your life easy, I went for python for the obvious reason. I also want the fun of coding in python. I also wanted to try out coding in python on my newly configured Vim. My idea of programming on terminals was limited to printing something on terminal. I tried out something like that long back using strings. But it was a very naive way of doing things and I didn't like it. One day I tried out something called bpython. It is another command line interpreter for python. I was fascinated by the way the program works. It is simply amazing and behaves like a proper GUI IDE on shell. Luckily my friend Madhu told me that this is written using ncurses. The word curses caught me. I thought may be it can help me out in writing my file browser. But I didnt give it much thought. I actually tried out some stuff only to see that it requires special way of approach.

So now here I am, decided to write a file browser and know a word ncurses. Where do I start... obvious google. I found a few links on ncurses and learnt that it also has a wrapper in python called "curses". But then I realised this is exactly what I did when I tried ncurses for the first time and got no where. I looked back and found out that the reason I stopped is because the moment you try to manipulate your terminal, the default behaviour of your python interpreter is lost and it gets really annoying to proceed. All you can do is write code in a file and run it every time. I wondered how would bpython behave!!. I tried basic importing and initialising screen and to my delight, it did not have any effect on bpython console. bpython being written using curses, overwrites all my actions. My interpreter is working fine. So this also has a disadvantage. Although you can see all the attributes available for any object since bpython displays attributes after you type a dot, you cant really see any change that you make. Anyways I still will have to stick to my old way of doing, writing in a file and executing.

I found a few links on how to program in curses using python.
These links got me started and python curses man page helped me through the process.

And that is how I end up with something that suits perfectly to my requirements.
Currently this is the key mapping on my PyBrowser that opens with files in current directory.
  • h - move left
  • j - move down
  • k - move up
  • l - move right
  • b - back one directory
  • o - open the directory or file( programs are mapped to filenames in a different conf file )
  • H - Toggle hidden files
  • q - close or quit
All this in 200 lines of code and 2 days of work with loooots of breaks. Now you know why I code in Python ;) .Shall add more functionality later on.

Monday, February 15, 2010

The Vim mode

Vim Forever...

It all started when I saw Venkatesh Choppella working without taking his fingers off the keyboard to do many things which usually required shifting my hand between keyboard and my tailed friend, mouse. I knew for sure that he was using emacs. It was cool and I was fascinated about this cute little tool. My friend Puneeth uses it all the time for editing. He also has some crazy extension on firefox that troubles me while using. It is emacs extension.

Anyways now I wanted to use something cool like that. I know for sure that Vi is the competitor and so I started by googling for editor wars. I found many links that support emacs. So I started learning emacs rather looking at emacs. First thing I didnt like was the use of control key so often which required shifting of my fingers way down the home row. Then I had problem shifting my fingers to use the arrow keys for navigating through the file.

So here I am left with no other option than vi. I have used vi for quite a while and am pretty comfortable with it. But all I do in vi is first get into insert mode and edit the file as if I am using notepad. I started searching for tutorials on vi and found one that is so simple yet so amazing. I thank Swaroop CH, yes the same guy who wrote the book "A Byte of Python", for another amazing book "A Byte of Vim". It was so amazing and I started using vi like a novice vimmer.

Now editing a text file is something I do only once in a while. Most of the time I either code in Python or browse on Firefox. Ofcourse watching stuff and listening to music is also there but doesn't make sense in this context. So now what is this emacs plugin for firefox and is there something similar for Vim???. Yes there is one and it is called Vimperator. It transforms firefox into something that behaves similar to Vim editor and hence very seldom do I need the mouse. It is a totally different experience using firefox in Vim mode.

Now comes the most important job. Making Vim an ide for Python.
Let me start by listing a few things one does on a typical ide.
  1. A file browser that stays on left of screen and enables opening files on one click
  2. Ability to show multiple files in one screen
  3. Syntax highlighting and code folding
  4. Taglist that displays all the functions, classes and stuff in one place
  5. Auto Indentation
  6. Code completion
  7. Debugging
Phew!! finally the list ended.
Lets start with the first, The File browser
Vim has a very simple and light file browser plugin called NERDTree.
Installing is as simple as extracting the files into ~/.vim directory.
Using :NERDTree brings up the nerdtree and a tree structure is displayed.
Moving between files is the same as it is in normal mode. The usual hjkl work and <CR> or the enter key is used to expand or collapse a directory. Clicking enter on a file opens the file in edit mode. 'o' key can also be used to do the same. <ctrl+w> <ctrl+w> is used to switch context between nerdtree and the file buffer. 'i' opens the file in a new screen.

Showing multiple files.
This is as simple as splitting the screen into parts and showing different files on each screen.
:sp splits the screen horizontally and :vsp splits vertically.
If you notice, we have seen something similar while using nerdtree. What it is doing is simply opening another buffer for itself.
<ctrl+w> <ctrl+w> can be used to switch context. The usual vim way of prepending a number also works here. so 4 <ctrl+w> would execute <ctrl+w> command four times. can also be mixed with hjkl.

syntax highlighting and code folding
vim takes care of syntax and all we have to do is :syntax on. You can also download a syntax file from here or write one of your own and name it python.vim. Installing is as simple as placing it in ~/.vim/syntax folder.
code folding is a little different for different contexts. For python, the obvious is indentation. First do :foldmethod=indent. Then scroll to your block of code and za toggles the folding of code.

taglist is a plugin for vim that supports many languages. It requires a package called "exuberate ctags" which should be directly available on repo for any distro. Then download the zip file and extract contents to ~/.vim and you have your plugin.
The visibility of taglist can be toggled using :TlistToggle and it works similar to nerdtree.

following pep8, here are a few settings that should make your life easy.
  • set expandtab
  • set textwidth=79
  • set tabstop=8
  • set softtabstop=4
  • set shiftwidth=4
  • set autoindent
at this point you will notice that you have to type the 4 spaces or tab for the first time and then the code is auto indented from the next line.
Wouldn't it be great if we didn't have to bother about even touching the tab key and the editor does that depending on the context. All that is just one step away. Download this script and place it in ~/.vim/indent folder. Now use the command ":filetype plugin indent on" or add the line "filetype plugin indent on" to your .vimrc file in home folder and there you go. Vim does all your indenting.

If you would have noticed, we have to type in all these conf settings every time we start vim. We don't want vi to do these settings for all the files either. What if we could set things only for files that end in .py. There is a very simple way of accomplishing that. Change the "set" to "setlocal" and put all your settings in a python.vim file and place it in ~/.vim/ftplugin.
So your python.vim would look like this:

setlocal expandtab
setlocal textwidth=79
setlocal tabstop=8
setlocal softtabstop=4
setlocal shiftwidth=4
setlocal autoindent

Code completion and Debugging are for a different set of audience ( not me ).
But shall blog about it soon.