Archive for category Software

Linkgen – A webdev tool

During web development and debugging, developers often need to compare the locally modified version with what is in production. Most of the time this involves copy and paste to make the urls for dev and production in two side-by-side tabs on a browser. This is not only tedious, but poses serious ergonomic injury risk as well.

I figured that a bare bones html with a few bits of javascript can go a long way towards making a custom tool just for this task. So if you got a set of paths (e.g. /blog?p=23 or /blog/2009/05/12/hello-world) just put them in the tool alongwith two hostnames, and you will instantly get urls in pairs to be opened on sequential tabs.

The tool is now hosted here: http://joydutta.com/projects/linkgen/

Feedbacks are most welcome. I can add more features on request if they prove to be absolutely essential.

,

1 Comment

WordPress blog development tip

When I started this personal blog, it was a matter of a few clicks in a tool called fantastico and everything was up and running. Whatever development and style modifications I have done over the time were directly on the server. As a matter of fact, I still do.

Clearly, it is not the best idea for incremental development, not without inevitable “production downtime”. Working in a big internet company at least taught me this truth among other things. So, when I started my photoblog using pixelpost, I set everything up in my local MAMP stack and pushed the data to server one time.

joy@localhost ~ $ mysqldump -u user -ppass db > db.sql
joy@localhost ~ $ scp -C db.sql joy@server:
joy@server ~ $ mysql -u user -ppass db < db.sql

Afterwards all code pushes happen by rsync.

joy@localhost photoblog $ rsync -avz . joy@server:public_html/photoblog

This way, even though locally I have a small set of data, I can change code and test all features before doing a production push. Works very well for me. Also I check in my code in a local git repository. Double win.

I am in the middle of setting up another wordpress blog right now, and forgetting a small detail cost me a bunch of time. After getting the blog running locally, I took a mysql dump and synced it with the db in the server. It just won’t load. I mucked around here and there and figured that the blog url is set as “http://localhost:8888/newblog” in the local db. I modified the .sql file and re-synced to production and voila, it worked.

I suspect that I might need to do the db sync a few more times before I have enough volume of data to keep it growing in the server. I will probably set up a sed script to do the search-and-replace in command line.

, ,

No Comments

Epson 2200 in Snow Leopard

Printer manages colors in print dialog Advanced color settings for Epson 2200

The upgrade to Snow Leopard a few months back was smooth, except for one fatal thing. The colors from my Epson 2200 went from awesome in Leopard to downright awful, thanks to the third party Gutenprint driver. I only realized this mess today since I had been printing black and whites using the Quad Tone Rip (QTR) driver which kept producing neutral prints.

So I hit google and there it was, a pretty long forum thread on the very same issue. To my surprise I found that Epson indeed released Snow Leopard driver for the 2200 printer sometime in Nov 2009. I installed it, then removed and re-added the printer and voila, the colors are almost back to normal. The interface is actually much better than what I expected, and the advanced color setting panel actually worked (it was mangled up in the Gutenprint driver).

Now that I still had a little magenta cast (as opposed to horrible), I tweaked with the advanced color settings panel. Took down magenta to -9 and suddenly the grays started to look like gray. There is just one thing to be done in photoshop prior to printing. The brightness of the image has to be increased a little bit. A foolproof way to do this is to have a curves layer, with no adjustment, then setting the blending mode to screen with 50% opacity. That makes my color prints about same as what I see on my monitor. For black and white prints using QTR, the last step is not necessary, or maybe about 20% opacity will do.

Looking forward to some print sessions in the coming days.

Update: Magenta -12 works even better.

,

1 Comment

Stackoverflow.com: A programmer’s dream

While google has always served me to find answers to a wide array of programming and technical issues, I don’t recall any one tech QA site which was consistently reliable. I regularly dug out answers from google group discussions to some old bulletin board archives to the typical flashy QA sites infested with scammy ads.

Stackoverflow.com provides a spot-on solution to this very precise problem. Not only it is a clean and functional site free of annoying ads, it actually engages the users to help others more. The reputation scoring logic is a feedback loop, which gets a programmer addicted in no time. I think it works marvelously well.

To top it off, Joel Spolsky and Jeff Atwood, the founders of stackoverflow made their software reusable. There is also superuser.com and serverfault.com based on the same platform but geared more towards sysadmin crowd. And slowly, many other sites are adopting this very successful platform, for example: answers.onstartups.com.

I am very happy to be involved with helping the programming community and learning at the same time. I guess I have nearly stopped spending time on facebook and twitter. I recommend all my coworkers and techie friends to start contributing in these platforms already.

No Comments

WordPress fusion theme: twitter widget link problem

The twitter sidebar widget in the fusion theme of wordpress shows weird in Firefox browser, due to the encoding of the double quotes in the href attribute. For example, a link from a twitter post shows like this in source:

  1. <a href=&quot;http://bit.ly/foo123&quot;>bar</a>

Safari in quite intelligent regarding this and displays the links right.

A look in the code revealed that the output from twitter webservice call is not completely decoded. The function fusion_TwitterWidget() in wp-content/themes/fusion/functions.php looks like this after an easy fix:

  1. // theme widget: Twitter
  2. function fusion_TwitterWidget($args){
  3.  extract($args);
  4.  echo $before_widget;
  5.  print $before_title.__(‘Twitter posts’,'fusion’).$after_title; ?>
  6.  
  7.  <?php
  8.  $username = get_option(‘fusion_twitterid’);
  9.  $limit = get_option(‘fusion_twitterentries’);
  10.  if($username<>) {
  11.   $feed = file_get_contents("http://search.twitter.com/search.atom?q=from:" . $username . "&rpp=" . $limit);
  12.  
  13.   // joyd: fix for the broken hyperlinks of twitter plugin due to encoded quotes
  14.   // $feed = str_replace("&lt;", "< ", $feed);
  15.   // $feed = str_replace("&gt;", ">", $feed);
  16.   $feed = html_entity_decode($feed);
  17.  
  18.   $clean = explode("<content type=\"html\">", $feed);
  19.   $amount = count($clean) - 1;
  20.   print ‘<ul id="twitterupdates">’;
  21.   for ($i = 1; $i < = $amount; $i++) {
  22.    $cleaner = explode("</content>", $clean[$i]);
  23.    print ‘<li class="entry">’;
  24.    echo $cleaner[0];
  25.    print ‘</li>’;
  26.   }
  27.   print ‘</ul>’;
  28.  }
  29.  
  30.  echo $after_widget;
  31. }

Thanks a lot to Francesco to point this out !

,

5 Comments

Pixelpost mod: Edit image link

As my pixelpost photoblog is growing by the day, it is pretty painful to edit info for images that are a little old. In the admin page, go to the images section, then navigate a couple pages to find the image from the small thumbnail then click edit. Too much work for me. A simple tag expansion should solve this.

So I made this new tag and inserted it right after the Admin link in the footer page (my template is theworldin35mm):

<EDIT_IMAGE_LINK_ITEM>

And then the following piece of code in index.php to ensure expansion of the tag only on a image page and when logged in:

  1. if($image_id && isset($_SESSION["pixelpost_admin"])) {
  2.   $edit_image_link_item = "<li><a href=\"<SITE_URL>admin/index.php?view=images&id=$image_id\" title=
  3.     \"Edit Image\">Edit Image</a></li>";
  4.   $tpl = ereg_replace("<edit_image_link_item>",$edit_image_link_item,$tpl);
  5. } else {
  6.    $tpl = ereg_replace("</edit_image_link_item><edit_image_link_item>","<!– Edit image link only for image page when logged in –>",$tpl);
  7. }

The above code goes right after the following block:

  1. if(!isset($_GET[‘x’])) {
  2.    
  3. }

Image management (editing category/tags) is a breeze now.

No Comments

Testing binary compatibility in C++

The task of developing libraries is always associated with the concern of binary compatibility with future releases of the library. Here is a nice summary of rules to ensure binary compatibility: http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++

Nonetheless, I wanted to make a simple framework test environment to quickly test out a particular type of change in a library.

~/bincompat/lib $ cat fun.h

  1. int fun(int a);

~/bincompat/lib $ cat fun.cc

  1. #include "fun.h"
  2.  
  3. int fun(int a) {
  4.   return a*a;
  5. }

~/bincompat/lib $ cat Makefile

  1. libfun.so.1: fun.o
  2.         g++ -shared -Wl,-soname,libfun.so -o libfun.so.1 fun.o
  3.         ln -s libfun.so.1 libfun.so
  4.  
  5. fun.o: fun.cc fun.h
  6.         g++ -fPIC -g -c -Wall fun.cc
  7.  
  8. clean:
  9.         rm -f *.o *.so*

~/bincompat $ cat testfun.cc

  1. #include "lib/fun.h"
  2. #include <iostream>
  3.  
  4. int main() {
  5.   cout < < fun(2) << endl;
  6.   return 0;
  7. }

~/bincompat $ cat Makefile

  1. testfun: testfun.cc
  2.         g++ testfun.cc -o testfun -L./lib -lfun
  3.  
  4. clean:
  5.         rm -f testfun

~/bincompat $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./lib
~/bincompat $ ./testfun
4

Now lets change the library by adding a variant of the function fun() without breaking compatibility and run our test program again:

~/bincompat/lib $ cat fun.h

  1. int fun(int a, int b); // added
  2. int fun(int a);

~/bincompat/lib $ cat fun.cc

  1. #include "fun.h"
  2.  
  3. int fun(int a) {
  4.   return fun(a, 1); // call the more specific version with default value for the missing param
  5. }
  6. int fun(int a, int b) {
  7.   return a*a + b*b;
  8. }

~/bincompat $ ./testfun
5

2 Comments

The importance of keyboard navigation

While browsing online portfolios of a few well known photographers I noticed how desperately those fancy designs needed a very basic feature – keyboard navigation. Thanks to the deluge of digital photos everywhere and the tendency of people to upload a gazillion of them after every party or a trip, we no more have the time or patience to point and click the “next” link. Picasa, smugmug and facebook among a few others have already put this most important feature in place, making it a pleasure to browse images quickly. Too bad flickr did not yet, but it is nothing a greasemonkey userscript can’t fix.

Then I wanted this on my own photoblog as well. I thought about using jQuery but since pixelpost uses prototype, I looked up the syntax and quickly came up with this small piece of code:

  1. Event.observe(document, "keypress", function(e) {
  2.   // 37 for left, 39 for right
  3.   var cur = location.href;
  4.   var prev = $$("#image-nav-prevlink a")[0].href;
  5.   var next = $$("#image-nav-nextlink a")[0].href;
  6.   switch(e.keyCode) {
  7.     case 37:
  8.       if(cur != prev) { location.href = prev; }
  9.       break;
  10.     case 39:
  11.       if(cur != next) { location.href = next; }
  12.       break;
  13.   }
  14. });

10 minutes of effort. 10x better usability.


Update: I made a flickr photostream navigator userscript in a similar fashion but had a critical bug. When an input box is focused, arrow keys should not trigger another page load. The same bug is present in the above code as well. Thanks to my good friend Francesco for catching this early. I fixed them both. The above code after correction looks like:

  1. var PB = { Globals:{} };
  2. PB.Globals.inputHasFocus = false;
  3.  
  4. Event.observe(document, "keydown", function(e) {
  5.   // console.log("any input has focus: " + PB.Globals.inputHasFocus);
  6.   if(PB.Globals.inputHasFocus) { return; }
  7.   // 37 for left, 39 for right
  8.   var cur = location.href;
  9.   var prev = $$("#image-nav-prevlink a")[0].href;
  10.   var next = $$("#image-nav-nextlink a")[0].href;
  11.   switch(e.keyCode) {
  12.     case 37:
  13.       // for some reason the inactive link looks like "…showimage="
  14.       if(cur != prev && prev.match("showimage=[0-9]")) { location.href = prev; }
  15.       break;
  16.     case 39:
  17.       if(cur != next && next.match("showimage=[0-9]")) { location.href = next; }
  18.       break;
  19.   }
  20. });
  21.  
  22. Event.observe(window, "load", function() {
  23.   $$("input.input, textarea").each(function(inp){
  24.     inp.observe(‘focus’, function(e){
  25.       // console.log(e);
  26.       PB.Globals.inputHasFocus = true;
  27.     });
  28.     inp.observe(‘blur’, function(e){
  29.       // console.log(e);
  30.       PB.Globals.inputHasFocus = false;
  31.     });
  32.   });
  33. });

1 Comment

git rocks !

I just set up my brand new git repository at github: http://github.com/jdutta. Don’t know what took me so long to embrace git but I am glad to be ready to move out of my CVS based workflow for personal projects.

A quick look at the tutorial was all I needed to convince myself towards this change. Now I can work on my personal projects from anywhere without worrying about merge issues later on. I just published my favorite config files under repository dotfiles. Could not be an easier backup/version-control mechanism.

Some good resources to learn git:
1. http://www-cs-students.stanford.edu/~blynn/gitmagic/book.pdf
2. http://git-scm.com/documentation
3. http://www.eecs.harvard.edu/~cduan/technical/git/

1 Comment

Efficient Software Development – Part 1

I have been meaning to write something on this topic for a while. The motivation largely comes from the experience of working in a large company and getting work done amidst a mindless number of context switches. It kind of reminds me of the term “thrashing” where the CPU spends most of the time switching between tasks than doing the tasks themselves.

Slow development is a major pain point of every developer I would imagine. To reduce stress I have setup my own environment to minimize the time it takes to reload the brain with the context of the task at hand.

At work I primarily have to develop stuff that can used/tested/mucked-with in a browser so I primarily just need a shell and browser. My work laptop is a macbookpro so I am all set with Terminal, Firefox, Safari and Thunderbird. And Adium, ofcourse.

1. Screen
Regardless of whether the terminal supports tabs or not, screen is a must-have tool to group several shell sessions together. With a nifty .screenrc and a few memorized shortcuts, it is probably better than sliced bread. Whenever I start a new project, screen -S projectname will start a screen and it will exist till the end of the project. Using different tabs on the terminal it is cool to switch between different screen sessions. Here is my .screenrc:

# .screenrc

startup_message off
escape “

hardstatus alwayslastline
hardstatus string ‘%{= kG}%-Lw%{= kW}%50> %n%f* %t%{= kG}%+Lw%< %{= kG}%-=%c:%s%{-}'

screen 1
screen 2
screen 3
screen 4

2. Vim
I am a vim guy and I understand there is an equally strong crowd of emacs folks. I have been using vim since 1998 and every time I see someone straining with a text editor and mounted remote drive I feel really sorry about the pain. I am not going to list all the cool features of vim, but the most used setup is in my .vimrc as below. A big monitor can make using split screens a dream, even on a remote server and using vim in text mode (non gui).

# .vimrc

syntax on
set ai nu showmatch
set incsearch hlsearch ignorecase
set shiftwidth=2

"formatoptions extra to make big comment lines easier
set fo+=ro

"show the command as it is typed
set showcmd

"customized key mapping - v to comment, z to uncomment
:map v I// ^[
map z I<Del><Del><Del>^[<Right>

3. Aliases
I lost track of wasted time typing "tail -f /foo/blah/blah/yapache/error" in a remote box, so I made a list of aliases that I will actually remember to use. Before using a remote box, copy the .bashrc one time and be done with it. Some of mine:

# .bashrc

PS1="\u@\h \w \$ "

alias a='alias'
alias ls='ls -pF'
alias l='ls'
alias ll='ls -ltr'
alias rm='rm -i'
alias c='clear'
alias src='source ~/.bashrc'
alias xvi='gvim -rv'
alias f='find . -name'
alias cnu='cvs -n up 2>/dev/null'
alias cdi='cvs di 2>/dev/null'
alias pd='pushd'
alias ppd='popd'
alias ..='cd ..'
alias ...='cd ../..'
alias sls='screen -ls'

alias ht='cd /foo/blah/share/htdocs'
alias ta='tail -f /foo/blah/logs/yapache/access'
alias te='tail -f /foo/blah/logs/yapache/error'

4. ssh-agent
If you often ssh to remote boxes, then setup ssh-agent. Typing password multiple times in one terminal session is totally dumb.

First generate the public-private key pair using ssh-keygen.
Concat the public keys to ~/.ssh/authorized_keys and copy it to the remote box. Now do this:

$ eval `ssh-agent`
$ ssh-add

To be continued and/or edited...

1 Comment