Wednesday, December 30, 2009

Print documents to pdf on the commandline

sudo apt-get install cups-pdf

# Find out pdf printer name under "System > Administration > Printing"
# In my case it's named "PDF" -norestore -nofirststartwizard -nologo -headless -pt PDF test.odt

Thursday, November 26, 2009

[Solved] No sound on external speaker for eeePc running Ubuntu

My Ubuntu netbook suddenly stopped having sound from its external speakers. No such problem if using headphone jack.

The solution is simple --> I have accidentally switched "iSpeaker" off in "Volume Control > Preferences"

Tuesday, November 24, 2009

Joining 2 videos in Ubuntu

sudo apt-get install mencoder

cat video1.mpg video2.mpg > video12.mpg

Friday, November 20, 2009

Delete remote tracking branch in git

# Show remote branches tracked
git branch -r

# Delete one by one
git branch -d -r origin/branch

# Delete with one swoop
git remote prune origin

Tuesday, November 17, 2009

Authlogic login in rails functional tests

# Place this at the top of test/test_helper.rb
require "authlogic/test_case"

# Activating authlogic in before each test
def setup

Monday, November 16, 2009

Manually mount USB hard disk


# Find details of the hard disk
fdisk -l

# Create directory in /media
sudo mkdir /media/external

# Mount drive
# FAT16 or FAT32
sudo mount -t vfat /dev/sdb1 /media/external -o uid=1000,gid=100,utf8,dmask=027,fmask=137

sudo mount -t ntfs-3g /dev/sdb1 /media/external

# Unmount before plugging out
sudo umount /media/external

Sunday, November 15, 2009

ignore files that are already tracked in git


"log/test.log" has already been "git added" but I wanna ignore any further modifications made to the file.

Solution: Update .gitignore and run "git update-index"

# .gitignore


# run git update-index

git update-index --assume-unchanged log/test.log

Wednesday, November 11, 2009

git date spec, ordinal spec, carrot parent, tilde spec

Date Spec

The Ref Log that git keeps will allow you to do some relative stuff locally, such as:


master@{1 month ago}

Which is shorthand for 'where the master branch head was yesterday', etc. Note that this format can result in different shas on different computers, even if the master branch is currently pointing to the same place.

Ordinal Spec

This format will give you the Nth previous value of a particular reference. For example:


will give you the 5th prior value of the master head ref.

Carrot Parent

This will give you the Nth parent of a particular commit. This format is only useful on merge commits - commit objects that have more than one direct parent.


Tilde Spec

The tilde spec will give you the Nth grandparent of a commit object. For example,


will give us the first parent of the first parent of the commit that master points to. It is equivalent to:


You can keep doing this, too. The following specs will point to the same commit:


Narrow down to a bad commit with git bisect

Finding Issues - Git Bisect

Suppose version 2.6.18 of your project worked, but the version at "master" crashes. Sometimes the best way to find the cause of such a regression is to perform a brute-force search through the project's history to find the particular commit that caused the problem. The git bisect command can help you do this:

$ git bisect start
$ git bisect good v2.6.18
$ git bisect bad master
Bisecting: 3537 revisions left to test after this
[65934a9a028b88e83e2b0f8b36618fe503349f8e] BLOCK: Make USB storage depend on SCSI rather than selecting it [try #6]

If you run "git branch" at this point, you'll see that git has temporarily moved you to a new branch named "bisect". This branch points to a commit (with commit id 65934...) that is reachable from "master" but not from v2.6.18. Compile and test it, and see whether it crashes. Assume it does crash. Then:

$ git bisect bad
Bisecting: 1769 revisions left to test after this
[7eff82c8b1511017ae605f0c99ac275a7e21b867] i2c-core: Drop useless bitmaskings

checks out an older version. Continue like this, telling git at each stage whether the version it gives you is good or bad, and notice that the number of revisions left to test is cut approximately in half each time.

After about 13 tests (in this case), it will output the commit id of the guilty commit. You can then examine the commit with git show, find out who wrote it, and mail them your bug report with the commit id. Finally, run

$ git bisect reset

to return you to the branch you were on before and delete the temporary "bisect" branch.

Note that the version which git-bisect checks out for you at each point is just a suggestion, and you're free to try a different version if you think it would be a good idea. For example, occasionally you may land on a commit that broke something unrelated; run

$ git bisect visualize

which will run gitk and label the commit it chose with a marker that says "bisect". Choose a safe-looking commit nearby, note its commit id, and check it out with:

$ git reset --hard fb47ddb2db...

then test, run "bisect good" or "bisect bad" as appropriate, and continue.

View commit difference with breakdown of commit details of individual changes files in each commit

git whatchanged BRANCH..ANOTHER_BRANCH

Show only difference in commit logs between 2 git branches


# with diff output

Friday, October 30, 2009

Update rubygems using gem

sudo gem install rubygems-update; sudo update_rubygems

Wednesday, October 28, 2009

String value not displayed in input text field in a form

If you have the following,

<% form_tag '/index' do %>
<% text_field_tag 'date', '2009-01-01' %>
<% submit_tag 'Go' %>
<% end %>

You would think the textfield above would have "2009-01-01" string displayed. But it is not so. Need to specify "GET" method.

<% form_tag '/index', :method => :get do %>

Sunday, October 25, 2009

Format string for titles

How to change "ClassTest" to "Class Tests"?




Specify form method when generating url route for edit form

Scratch head moment when I didn't specify ":method => :put" for edit form coz the form keeps leading me to "create" action.

<% form_for @class_test, :url => class_test_path(@class_test) do |f| -%>
<%= render :partial => f %>
<%= f.submit "Save" %>
<% end -%>

This was resolved after specifying the "put" method.

<% form_for @class_test, :url => class_test_path(@class_test), :html => {:method => :put} do |f| -%>
<%= render :partial => f %>
<%= f.submit "Save" %>
<% end -%>

Monday, October 19, 2009

Error using validation hooks with before_save callback

# This will throw "Schedule can't be blank" error as any changes made in before_save callback somehow gets lost
class Assessment < ActiveRecord
validates_presence_of :schedule

attr_accessor :date, :time
before_save :set_schedule_from_date_and_time


def set_schedule_from_date_and_time
if && self.time
self.schedule = Time.parse("#{date} #{time}")

# The trick is to use before_validation
before_validation :set_schedule_from_date_and_time

Sunday, October 18, 2009

Deleting a word backwards in Bash and Vim

# To delete one word back
CTRL + w

# To paste deleted word
CTRL + y


I've been using swapping CAPS LOCK with ESC key configuration. Trying out swapping CAPS LOCK with CONTROL key now.

- not having my pinkie wrangled to reach CONTROL Key at the bottom --> easier to do CTRL-C, CTRL-V, CTRL-A

- a big rewiring of finger memory as I've been using normal CONTROL key for years
- I need another keystroke for ESC sequence (CAPS LOCK + [) as compared to previous configuration (CAPS LOCK)

Reloading ALSA

I've encountered some errors while running Ardour and Hydrogen. The fix is simple --> restart/reload ALSA.

sudo /sbin/alsa force-reload

Thursday, October 15, 2009

Uncompressing 7zip (.7z) files in Ubuntu

# Install p7zip package
sudo apt-get install p7zip-full

# uncompress a file named production.7z
7z x production.7z

Wednesday, October 14, 2009

Select commits from another branch using git cherry-pick

Assuming the following commits in my 123-feature-blah_blah branch

commit eff75535f3eaa42dbc41cdaa3e8e404298fcce58
Author: NgTzeYang
Date: Tue Oct 13 12:58:09 2009 +0800

[#1467448] Fix unit test failure for course management

commit 19651c61957f2b5cab9614948fe68c4fd505da04
Author: Jason Ong
Date: Thu Oct 15 14:36:08 2009 +0800

Upgraded cucumber gem to version 0.4.2

commit 534585c488628e0c434399d700ae0e8637afb868
Author: NgTzeYang
Date: Tue Oct 13 12:11:20 2009 +0800

[#1467375] Use different database for unit & integration testing

I wanna push 2nd commit to origin/master so others can benefit from this commit while I work on the blah blah feature

- create another branch from local master
- find SHA id of commit to cherry pick
- use git cherry-pick to select 2nd commit into the branch
- rebase into local master
- push to origin/master

git checkout master && git checkout -b upgrade_cucumber_gem
git log 123-feature-blah_blah
git cherry-pick 19651c61957f2b5cab9614948fe68c4fd505da04
git checkout master && git rebase upgrade_cucumber_gem
git push origin master

Tuesday, October 13, 2009

Share simple internet web browsing via SSH X forwarding

You forgot to bring your access to the world wide web for your laptop. ie. didn't bring iPhone, 3G dongle, etc. But your friend wasn't careless and had brought his.

You can get your friend to "share" his internet connection via his firefox. Better for him to create a firefox profile for you in this case
- Connect both yours and your friend's laptop to the same network. Either wifi or lan cable.
- ssh -X friend_login@friend_ip_address
- firefox -P your_profile -no-remote &

Sunday, October 11, 2009

Fix static noise problem in Skype on Ubuntu

I have this problem on my netbook where Skype another Skype user can hear only loud static noises when trying to reconnect to him/her. Not sure what the real problem is (most probably to do with Pulseaudio?) but the solution is simple.

1. Go to Gnome volume applet
2. Click on "Volume Control"
3. Select "HDA Intel (Alsa mixer)" as Device
4. Go to "Recording" tab
5. Make sure none of the capture slider is set to zero

That's all!

Record & playback a Vim macro

# q{register} when in normal mode will start recording into register

# q will stop recording

# Playback = @{register}

Thursday, October 8, 2009

Stash changes away in Git to work on urgent matters first


- you've made some changes in your current branch but realized you're in the wrong branch
- you've gone off track in making changes that doesn't relate to the branch story
- you need to drop whatever you're doing right now and apply some urgent patch

Git stash to the rescue!

# Stash changes
git stash save "message for later reference"

# List stashes
git stash list

# Apply stash
git stash apply stash@{STASH_ID}

# Drop/delete a stash
git stash drop stash@{STASH_ID}

# Drop/delete last stash
git stash pop

# Clear all stashes
git stash clear

# Quick & dirty stashing
git stash
git stash pop

Insert Pivotal Tracker story id into Git commit messages

# Story id of feature from Pivotal Tracker is in feature file
# Example: features/course_management/admin_deletes_course.feature
Feature: Admin Deletes Course
In order to manage course as a resource
As the admin
I should be able to delete a course

# Using head and sed to insert story id into commit message
git commit -am "[#`head -n 1 features/course_management/admin_deletes_course.feature | sed 's/.*\///'`] Replacing button ids to confirm to convention."

Check git log for a particular branch

# To changelog for upstream origin/master changes
git fetch origin
git log origin/master

View changes made by upstream in Git

# Fetch the changes from origin
git fetch origin

# View difference between local master branch and origin's master branch
git diff master origin/master

Wednesday, October 7, 2009

Restart Gnome session from command line

sudo /etc/init.d/gdm restart

Tuesday, October 6, 2009

Be careful with button_to in RESTful routes

# This will be default use POST method which in this context be sent as a create resource
<% form_for @course do |f| %>
<% end %>
<%= button_to 'Cancel', courses_path %>

# Specify GET method explicitly so it will call index resource instead
<%= button_to 'Cancel', courses_path, :method => :get %>

Monday, October 5, 2009

Rename current branch in Git

# Accidentally created branch with name "1234"
git checkout -b 1234

# Renames current branch to "1234-feature-admin_looks_good"
git branch -m 1234-feature-admin_looks_good

Friday, October 2, 2009

Reload vimrc in Vim

# :so or :source
:so ~/.vimrc

Insert contents from clipboard into Vim

# This usually works in insert mode

# However sometimes my "CTRL + c" on other application doesn't get contents into Vim's "clipboard".
# The solution is to use Vim's multiline insert mode

:i or :in or :insert

# This will bring up lines which you can paste from Ubuntu's clipboard by "CTRL + SHIFT + v" to you heart's content.
# Finish the multilines with a "." at the end
# NOTE: better to turn off Vim's "autoindent" with "!"


This is first line
This is 2nd line
This is last line

# A similar method would be append instead of insert

:a, :append

Yank all lines in Vim

3 methods.

# 1. Highlight select all lines before yanking
:0, SHIFT + v, G, y

# 2. State range to yank: G - the last line

# 3. State range to yank: $ - end of text

Thursday, October 1, 2009

Git branching and merging workflow for agile team

# Ref Url:
# 1. We use the following convention throughout the rest of this doc:
# * ... id of story/chore/bug as provided by pivotal tracker
# * ... story, chore or bug
# * ... a very short description of the story, chore or bug
# * ... a description of the story, chore or bug

1. To start working on a feature:

$ cd
$ git checkout master
$ git fetch origin master
$ git rebase origin/master

a. Assuming i'm working on something new:

$ git checkout -b --


$ git checkout -b 889900-feature-admin_reboots_system
$ git checkout -b 889901-chore-cleanup_config_environment
$ git checkout -b 889902-bug-cannot_shutdown_until_all_system_tasks_complete

b. Assuming i'm already onto something:

$ git checkout --
$ git rebase origin/master

* Remember to run test after rebase, nothing new should break

3. Continue to work on my feature & finish it & commit frequently

4. Squash commits with interactive rebase:

$ git rebase -i origin/master

Suggested final commited message after squashing would be:

> [#]

5. Checkout master & merge with branch:

$ git checkout master
$ git merge --
$ git push origin/master

Resize Gnu Screen window

Screen intelligently resize your Screen window to a resolution that suits all machines viewing the screen session. That might result in a window size that's less than optimum for yourself.

# Screen window readjusted to fit my paired programmer viewing my screen session

# To readjust size for my optimum
CTRL + a, F

Setup object first before testing validates_uniqueness_of in Shoulda

# This will complain
class SubjectTest < ActiveSupport::TestCase
should_validate_uniqueness_of :name

# Error
1) Failure:
test: Subject should require case sensitive unique value for name. (SubjectTest)
[/usr/lib/ruby/gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/assertions.rb:55:in `assert_accepts'
/usr/lib/ruby/gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/active_record/macros.rb:74:in `__bind_1254386647_780301'
/usr/lib/ruby/gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:351:in `call'
/usr/lib/ruby/gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:351:in `test: Subject should require case sensitive unique value for name. ']:
Can't find first Subject

# Setup object first
class SubjectTest < ActiveSupport::TestCase
setup { Factory(:subject) }
should_validate_uniqueness_of :name

Wednesday, September 30, 2009

Using %\\ for strings instead of "" or ''

string = %\This 'string' is so "boomz"!\

Clicking on links in Webrat using XPath

If for some reason you wanna use XPath instead of CSS Selector to click on a link

# Cucumber step
And I follow "Edit" for "John Woo"

# Using Css Selector
within(%\...\) do

# Using XPath
response.should have_xpath(%\//td[normalize-space(text())="#{name}"]/parent::tr//a[normalize-space(text())="#{link}"]/@id\) do |link_id|

Monday, September 28, 2009

Problem with nested attributes for has one relation in form view


# app/models/teacher.rb
has_one :profile
accepts_nested_attributes_for :profile

# app/controllers/teachers_controller.rb
def new
@teacher =
@teacher.profile =

If the following view give you error.

# app/views/teachers/_form.html.erb
<% form.fields_for :profile do |profile_form| %>
<% end %>

# Error in console
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.new_record? (ActionView::TemplateError)
On line #1 of app/views/teachers/_form.erb

1: <% form.fields_for :profile do |profile_form| %>

Then it means you don't have any fields for parent object

<%= form.text_field :login %>
<% form.fields_for :profile do |profile_form| %>
<% end %>

Sunday, September 27, 2009

Best built in Vim color theme for Rails

# Seems like Evening's the best
colorscheme Evening

Run windows maximized by default in Ubuntu

# Install maximus window manager which
# - runs windows as maximized
# - hides windows titlebar
sudo apt-get install maximus

# Toggle maximized (metacity)
ALT + F10

Saturday, September 26, 2009

Make Gnome Panel autohide 100%

Setting my netbook's top and bottom Gnome panel to autohide still leaves some pixels visible.

# Hide top panel completely
gconftool-2 --set --type integer /apps/panel/toplevels/top_panel_screen0/auto_hide_size 0

# Hide bottom panel completely
gconftool-2 --set --type integer /apps/panel/toplevels/bottom_panel_screen0/auto_hide_size 0

# Access configurations through GUI
ALT-F2 > "gconf-editor" > apps > panel > toplevels > top_panel_screen0 > auto_hide_size > 0


Friday, September 25, 2009

Rip video or audio from Youtube video

# Install youtube-dl to download video into flv file
sudo apt-get install youtube-dl
youtube-dl http://

# Install ffmpeg to do the conversions
sudo apt-get install ffmpeg

# Convert to mp3 audio
sudo apt-get install libavcodec-unstripped-52
ffmpeg -i input.flv -ac 2 -ab 128000 -ar 44100 output.mp3

# Convert to mpeg video
ffmpeg -i input.flv output.mpg


Using Irssi

Strangely I couldn't find a simple "howto" article on using Irssi except for this

# Connect to irc server

# Joining a channel
/join #linuxnus

# Parting a channel

# Change nick

# Highlight keywords

# Set away message

# Cancel away status

# Send private message

# Open up private chatroom

# Closing windows

# Disconnect from server

# Exit irssi

% and # in Vim

# '%' represents current filename in buffer
# Eg. insert current file contents in Vim
:!!cat %

# '#' represents previous filename in buffer
# Eg. git commit current and previous file
:! git commit -m "Message for commit" % #

Thursday, September 24, 2009

Select last tab in Firefox

# Goto last tab
ALT + 9

# Goto first tab
ALT + 1

# Alternative longer method of going to last tab
ALT + 1, CTRL + PageDown

Insert shell output into Vim

# Insert date

# Insert directory listing
!!ls -l

How to use Git tags

# Lightweight tagging
git tag stable-1 1b2e1d63ff

# Annotated tagging
git tag stable-1 1b2e1d63ff -a -m "This is a explanation of this tag."

# Signed tags
git tag -s -m "Tagging release 2.0" v2.0

# List tags
git tag -l

# Pushing tags to repository
git push origin --tags

refs: tag -l -n1visited/

Wednesday, September 23, 2009

Record & playback Screen session

It works like this:

script -t 2> demo.timing -a demo.session
Script started, file is demo.session

Script done, file is demo.session

And later you replay your session like this:

scriptreplay demo.timing demo.session


Git fetch remote branches

# Fetch histories of all remote branches
git fetch remote

# Fetch histories of only remote master branch
git fetch remote master

# Rebase with remote branch
git rebase remote/branch

Aborting a Git rebase

# If for some reason your git rebase is failing, git rebase abort to the rescue!
git rebase --abort

Tuesday, September 22, 2009

Monday, September 21, 2009

Intel Core 2 Duo vs AMD Turion X2 Ultra

It seems Core 2 Duo outperforms in terms of speed, heat dissipation and battery life.


Sunday, September 20, 2009

Use rtcwake to "wake up" from sleep mode at a given time

Note that if you try this whilst in X, your laptop/pc will resume with X garbled. Therefore go into another Ubuntu session and execute the commands.

# Login to another session

# Put laptop to sleep and automatically resume after 10 seconds
sudo rtcwake -m mem -u -v -s 10

# After resume from sleep go back to original xsession

View difference between Ubuntu date and Bios clock

# Display date by Ubuntu

# Display date from Bios
sudo hwclock

Using Rsync to synchronize folders between machines

# The below will sync my Music folder on both my laptop and desktop
rsync --verbose --progress --stats --compress --rsh=/usr/bin/ssh \
--recursive --times --perms --links --delete \
--exclude "*bak" --exclude "*~" \
../Music/* jasonong-desktop:~/Music/


Installing PADevchooser gui for pulseaudio

sudo apt-get install paman paprefs pavucontrol pavumeter

Finding CPU info in terminal

cat /proc/cpuinfo

Friday, September 18, 2009

Find files & directories in terminal

# Simple method to find files recursively from path with which matches expression
find ./ -name "*.rb"

# find directories recursively which matches expression (directory type)
find ./ -name 'specs*' -type d

List of bash shortcuts

Taken from the following article

* Ctrl + a – go to the start of the command line
* Ctrl + e – go to the end of the command line
* Ctrl + k – delete from cursor to the end of the command line
* Ctrl + u – delete from cursor to the start of the command line
* Ctrl + w – delete from cursor to start of word (i.e. delete backwards one word)
* Ctrl + y – paste word or text that was cut using one of the deletion shortcuts (such as the one above) after the cursor
* Ctrl + xx – move between start of command line and current cursor position (and back again)
* Alt + b – move backward one word (or go to start of word the cursor is currently on)
* Alt + f – move forward one word (or go to end of word the cursor is currently on)
* Alt + d – delete to end of word starting at cursor (whole word if cursor is at the beginning of word)
* Alt + c – capitalize to end of word starting at cursor (whole word if cursor is at the beginning of word)
* Alt + u – make uppercase from cursor to end of word
* Alt + l – make lowercase from cursor to end of word
* Alt + t – swap current word with previous
* Ctrl + f – move forward one character
* Ctrl + b – move backward one character
* Ctrl + d – delete character under the cursor
* Ctrl + h – delete character before the cursor
* Ctrl + t – swap character under cursor with the previous one
* Ctrl + ] - search forward for character
* Ctrl + Alt + ] - search backwards for character

Command Recall Shortcuts

* Ctrl + r – search the history backwards
* Ctrl + g – escape from history searching mode
* Ctrl + p – previous command in history (i.e. walk back through the command history)
* Ctrl + n – next command in history (i.e. walk forward through the command history)
* Alt + . – use the last word of the previous command

Command Control Shortcuts

* Ctrl + l – clear the screen
* Ctrl + s – stops the output to the screen (for long running verbose command)
* Ctrl + q – allow output to the screen (if previously stopped using command above)
* Ctrl + c – terminate the command
* Ctrl + z – suspend/stop the command

Bash Bang (!) Commands

Bash also has some handy features that use the ! (bang) to allow you to do some funky stuff with bash commands.

* !! - run last command
* !blah – run the most recent command that starts with ‘blah’ (e.g. !ls)
* !blah:p – print out the command that !blah would run (also adds it as the latest command in the command history)
* !$ – the last word of the previous command (same as Alt + .)
* !$:p – print out the word that !$ would substitute
* !* – the previous command except for the last word (e.g. if you type ‘find some_file.txt /‘, then !* would give you ‘find some_file.txt‘)
* !*:p – print out what !* would substitute

Make long multiple system commands in ruby more readable

# Instead of this long line of system command
system "pkill firefox & echo 'To Reboot: #{}' >> #{log_file} & echo #{PASSWORD} | sudo shutdown -r now"

# Have a readable array of the commands and join them into a string
system [
"pkill firefox",
"echo 'To Reboot: #{}' >> #{log_file}",
"echo #{PASSWORD} | sudo shutdown -r now"
].join(" & ")

Thursday, September 17, 2009

Adding digital signature to a Office document


- Take a picture of signature on a piece of paper
- Download into laptop
- Use Gimp to edit the image
- Make the signature black & white with "Destaturate" > "By Luminosity"
- Make improve contrast between signature & background by going into "Brightness & Contrast" & adjusting the brightness & contrast to a suitable level
- Then make the signature bolder & more obvious by going into "Brightness & Contrast" > "Edit these settings as levels" & adjusting to desired effect

Best way to edit pdf files in Linux

First convert pdf to a text file

sudo apt-get install poppler-utils
pdftotext file.pdf

The above will create a file.txt which you can then use OpenOffice to edit to your hearts content and save it back into a pdf file.


I've found another way to edit pdf file.

- Use gimp
- Split & merge using pdftk **

Can use gs command tool too
gs -q -sPAPERSIZE=letter -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf in1.pdf in2.pdf in3.pdf ...

Annotate over PDF files using flpsed in Linux


flpsed is a WYSIWYG PostScript annotator. You can't remove or modify existing elements of a document. But flpsed lets you add arbitrary text lines to existing PostScript documents (PostScript is a registered trademark of Adobe Systems Incorporated).

sudo apt-get install flpsed


- Only text annotation
- Cannot add image files. --> digital signatures

Copy into global clipboard in Vim

# Yanking in Vim will only copy into Vim buffer

# Get into command history mode and copy into clipboard instead

Tuesday, September 15, 2009

An example .screenrc file

screen -t "bzr"
stuff "bzr diff | colordiff"
screen -t "misc"
screen -t "devsvr"
stuff "cd ~/google_appengine^M"
stuff "./ -p 8084 ~/shared/appengine/conquer-on-contact/root/"
screen -t "update"
stuff "cd ~/google_appengine^M"
stuff "./ update ~/shared/appengine/conquer-on-contact/root/"

#change the hardstatus settings to give an window list at the bottom of the
#screen, with the time and date and with the current window highlighted
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %d/%m %{W}%c %{g}]'
vbell on
defscrollback 1024
startup_message off
autodetach on
defutf8 on

Searching in Less

# Opening manuals in terminal will usually be piped with less

man git

# Search forward in less. n --> forward, N --> backwards

# Search backward in less,

# View help for less

Screen profile in Ubuntu

When you start Screen for the first time, you'll be presented with the Screen profile helper. Choosing a profile other than "plain" will give you an awesome bottom toolbar which you can toggle nice notifications.

If for some reason, you've chosen "plain" and want to change screen profile, enter the following in terminal

select-screen-profile -s ubuntu-black

Monday, September 14, 2009

Using single Screen session with multiple windows

You can do Vim "buffer-like" windows on a Screen session.

Create new window: CTRL + a, c
List windows: CTRL + a, "
Prompt to open window n: CTRL + a, '
Window info: CTRL + a, i
Create new window with "title": screen -t "title"
Kill window: CTRL + a, k
Kill all windows: CTRL + a, \
Set current window title: CTRL + a, A

Open window n: CTRL + a, n
Open next window: CTRL + a, CTRL + n OR CTRL + a, Spacebar
Open previous window: CTRL + a, CTRL + a OR CTRL + a, Backspace

Go into copy mode: CTRL + a, [
Select mode: CTRL + a, spacebar
Move: h, j, k, l, w, e, b
Copy: Enter
Paste: CTRL + a, ]

Page up: CTRL + a, [, PageUp
Page down: CTRL + a, [, PageDown

Detach session: CTRL + a, :detach OR CTRL + a, d

Execute shell commands in Vim

# :! to execute shell commands directly in Vim
:! git status

# % specifies current file
:! git commit -m "Added changes" %

Scrolling in Screen session

# To enable scrolling in Screen session you have to get into 'Copy mode'
CTRL + a + [
CTRL + a + ESC

# To scroll, use VIM methods

Left, down, up, right --> h, j, k, l,
Page up, page down --> Ctrl + f, Ctrl + b

Sunday, September 13, 2009

Status flags in Mutt

Taken from the online Mutt manual

Status Flags

In addition to who sent the message and the subject, a short summary of the disposition of each message is printed beside the message number. Zero or more of the following ``flags'' may appear, which mean:


message is deleted (is marked for deletion)


message have attachments marked for deletion


contains a PGP public key


message is new


message is old


message is PGP encrypted


message has been replied to


message is PGP signed, and the signature is succesfully verified


message is PGP signed


message is flagged


message is tagged

Some of the status flags can be turned on or off using

  • set-flag (default: w)
  • clear-flag (default: W)

Furthermore, the following flags reflect who the message is addressed to. They can be customized with the $to_chars variable.

+       message is to you and you only
T message is to you, but also to or cc'ed to others
C message is cc'ed to you
F message is from you
L message is sent to a subscribed mailing list

List files with human readable filesize

# Keep forgetting this one
ls --help
-h, --human-readable with -l, print sizes in human readable format
(e.g., 1K 234M 2G)

# List files with human readable filesize
ls -lh

Pipe less with colors

# Normal pipe will not output ANSI colors
ruby twitpow.rb history | less

# There is an entry in "less --help" that says
-r -R .... --raw-control-chars --RAW-CONTROL-CHARS
Output "raw" control characters.

# Pipe less with ANSI colors!
ruby twitpow.rb history | less -r

Share screen session on iPhone

There's a screen package in Cydia. That means I can set up screen session on the iPhone terminal!

To set up screen session sharing follow my previous post.

Possible applications:
- Remote paired programming where one will code on normal laptop while the other observes on the iPhone

Things to note:
- Must run screen session as root user on iPhone
- Might be better to ssh into iPhone from laptop to set up the session rather than setting it up straight from iPhone Terminal as the latter's much harder to type

Saturday, September 12, 2009

Share terminal session to remote user using screen

Taken from the following article.

Case Scenario:

Assume user jsmith wants to share his terminal session with remote user bjones for training or troubleshooting purposes, but does not want to use VNC or other full-blown GUI remote control access.

- GNU Screen
- Local account on host computer for remote user (i.e. bjones requires local account)

1. Install screen
sudo apt-get install screen
2. Set the screen binary (/usr/bin/screen) setuid root. By default, screen is installed with the setuid bit turned off, as this is a potential security hole.
sudo chmod +s /usr/bin/screen
sudo chmod 755 /var/run/screen
3. The host starts screen in a local xterm, using the command screen -S SessionName. The -S switch gives the session a name, which makes multiple screen sessions easier to manage.
screen -S screen-test
4. The remote user (bjones) uses SSH to connect to the host computer (jsmith).
5. The host (jsmith) then has to allow multiuser access in the screen session via the command CTRL-A :multiuser on (all 'screen' commands start with the screen escape sequence, CTRL-A).
:multiuser on
6. Next, the host (jsmith) must grant permission to the remote user (bjones) to access the screen session using the commadn CTRL-A :acladd user_name where user_name is the remote user's login ID.
:acladd bjones
7. The remote user can now connect to the hosts 'screen' session. The syntax to connect to another user's screen session is screen -x host_username/sessionname.
screen -x jsmith/screen-test

Ruby Case statements

Some Ruby Case statement tips taken from the following article.

print "Enter your grade: "
grade = gets.chomp
case grade
when "A"
puts 'Well done!'
when "B"
puts 'Try harder!'
when "C"
puts 'You need help!!!'
puts "You just making it up!"

print "Enter your grade: "
grade = gets.chomp
case grade
when "A", "B"
puts 'You pretty smart!'
when "C", "D"
puts 'You pretty dumb!!'
puts "You can't even use a computer!"

print "Enter a string: "
some_string = gets.chomp
when some_string.match(/\d/)
puts 'String has numbers'
when some_string.match(/[a-zA-Z]/)
puts 'String has letters'
puts 'String has no numbers or letters'

Ruby metaprogramming toolbox

An article that lists and explains all the ruby metaprogramming techniniques.

What is Metaprogramming?

Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data, or that do part of the work at compile time that would otherwise be done at runtime. In many cases, this allows programmers to get more done in the same amount of time as they would take to write all the code manually, or it gives programs greater flexibility to efficiently handle new situations without recompilation. (via Wikipedia)

The following tutorial lists all the methods from the Ruby core that are useful for metaprogramming as well as demonstrates common usage scenarios you will find helpful to get started. In conclution, an example is presented showing how to develop a dynamic database class like ActiveRecord which automatically generates classes for database tables and populates each model class with getters and setters for its fields.

The Metaprogramming Tool Box

Ruby gives us many methods that help us generate code dynamically. Its important to familiarize yourself with them.

Getting, setting, and destroying variables

Getting, setting, and destroying constants (like classes)

Adding and removing methods

Running dynamic code

Reflection methods

Reflection is an important part of metaprogramming as it allows us to look at objects and peer at their contents and structure.

Evaluating strings and blocks

You may be familiar with the eval method which allows you to evaluate a string or block as ruby code. When you need to eval within the scope of a particular object you can use the instance_eval and module_eval (synonymous for class_eval) methods.

The instance_eval method works on the scope of an instantiated object.

[1,2,3,4].instance_eval('size') # returns 4

In the above example we passed instance_eval the string ‘size’ which is interpreted against the receiving object. It is equivalent to writing:


You can also pass instance_eval a block.

# Get the average of an array of integers
[1,2,3,4].instance_eval { inject(:+) / size.to_f } # returns 2.5

Notice how the inject(:+) and size.to_f methods just float in the air with no receiving objects? Well because they are executed within the instance context they are evaluated as self.inject(:+) / self.size.to_f where self is the receiving object array.

Whereas instance_eval evaluates code against an instantiated object module_eval evals code against a Module or Class.

Fixnum.module_eval do
def to_word
if (0..3).include? self
['none', 'one', 'a couple', 'a few'][self]
elsif self > 3
elsif self < 0
1.to_word # returns 'one'
2.to_word # returns 'a couple'

We can see how module_eval re-opened the existing class Fixnum and appended a new method. Now this in itself is nothing special as there are other ways to do this for instance:

class Fixnum
def to_word

The real advantage is to evaluate strings that generate dynamic code. Here we are using a class method create_multiplier to dynamically generate a method with a name of your choosing.

class Fixnum
def self.create_multiplier(name, num)
module_eval "def #{name}; self * #{num}; end"

Fixnum.create_multiplier('multiply_by_pi', Math::PI)
4.multiply_by_pi # returns 12.5663706143592

The above example creates a class method (or ‘singleton method’) which when called, generates instance methods which any Fixnum object can use.

Using send

Using send works much like instance_eval in that it sends a method name to a receiving object. It is useful when you are dynamically getting a method name to call from a string or symbol.

method_name = 'size'
[1,2,3,4].send(method_name) # returns 4

You can specify the method name as a string or a symbol ‘size’ or :size

One potential benefit of send is that it bypasses method access control and can be used to run private methods like Module#define_method.

Array.define_method(:ducky) { puts 'ducky' } 
# NoMethodError: private method `define_method' called for Array:Class

Using the send hack:

Array.send(:define_method, :ducky) { puts 'ducky' }

Defining Methods

As we just saw in the example above we can use define_method to add methods to classes.

class Array
define_method(:multiply) do |arg|
collect{|i| i * arg}

[1,2,3,4].multiply(16) # returns [16, 32, 48, 64]


When included in a class, method_missing is invoked when the class instance receives a method that does not exist. It can be used to catch these missing methods instead of raising a NoMethodError.

class Fixnum
def method_missing(meth)
method_name = meth.id2name
if method_name =~ /^multiply_by_(\d+)$/
self * $1.to_i
raise NoMethodError, "undefined method `#{method_name}' for #{self}:#{self.class}"

16.multiply_by_64 # returns 1024
16.multiply_by_x # NoMethodError

How does attr_accessor work?

Most of us use attr_accessor in our classes, but not everyone understands what it does behind the scenes. attr_accessor dynamically generates a getter and a setter for an instance variable. Lets take a closer look.

class Person
attr_accessor :first_name

john =
john.first_name = 'John'

# returns ["@first_name"]

john.methods.grep /first_name/
# returns ["first_name", "first_name="]

We can see that attr_accessor actually created an instance variable @first_name as well as two instance methods, a getter and a setter, first_name and first_name=


All classes inherit class methods from Module so we will put the mock methods here.

class Module
# First using define_method
def attr1(symbol)
instance_var = ('@' + symbol.to_s)
define_method(symbol) { instance_variable_get(instance_var) }
define_method(symbol.to_s + "=") { |val| instance_variable_set(instance_var, val) }

# Second using module_eval
def attr2(symbol)
module_eval "def #{symbol}; @#{symbol}; end"
module_eval "def #{symbol}=(val); @#{symbol} = val; end"

class Person
attr1 :name
attr2 :phone

person = = 'John Smith' = '555-2344'
person # returns

Both define_method and module_eval produced the same result.

Example Usage: Poor Man’s Active Record

For those familiar with RubyonRails it is easy to see how one might go about implementing an ActiveRecord class which would look up field names in a database and add getters and setters to a class.

We could take it one step further and have the Model classes generated dynamically as well.

In this example we are going to generate a poor man’s ActiveRecord. The class will connect to the MySQL database, generate a dynamic class for every table it finds, and populate the classes with getters and setters the table fields they contain.

require 'rubygems'
require 'mysql'

class PoorMan
# store list of generated classes in a class instance variable
class << self; attr_reader :generated_classes; end
@generated_classes = []

def initialize(attributes = nil)
if attributes
attributes.each_pair do |key, value|
instance_variable_set('@'+key, value)

def self.connect(host, user, password, database)
@@db =, user, password, database)

# go through the list of database tables and create classes for them
@@db.list_tables.each do |table_name|
class_name = table_name.split('_').collect { |word| word.capitalize }.join

# create new class for table with Module#const_set
@generated_classes << klass =" Object.const_set(class_name,

klass.module_eval do
@@fields = []
@@table_name = table_name
def fields; @@fields; end

# go through the list of table fields and create getters and setters for them
@@db.list_fields(table_name).fetch_fields.each do |field|
# add getters and setters
klass.send :attr_accessor,

# add field name to list
klass.module_eval { @@fields << }

# finds row by id
def self.find(id)
result = @@db.query("select * from #{@@table_name} where id = #{id} limit 1")
attributes = result.fetch_hash
new(attributes) if attributes

# finds all rows
def self.all
result = @@db.query("select * from #{@@table_name}")
found = []
while(attributes = result.fetch_hash) do
found << new(attributes)

# connect PoorMan to your database, it will do the rest of the work for you
PoorMan::connect('host', 'user', 'password', 'database')

# print a list generated classes
p PoorMan::generated_classes

# find user with id:1
user = Users.find(1)

# find all users

Dir.glob to get filenames in directory

# Glob for filenames in path

# Use File.join for pathname which autocorrects for Windows
Dir.glob(File.join(File.dirname(__FILE__), 'some', 'path', 'name'))

Use File.join to state file pathname

# Straight naming of pathname for "file.rb"
require 'path/name/for/file'

# Using File.join. Advantage --> auto forward slash on windows
require File.join('path', 'name', 'for', file')

# Even better way which takes care of relative paths
require File.join(File.dirname(__FILE__), 'path', 'name', 'for', 'file')

Linux: './path/name/for/file'
Windows: '.\path\name\for\file'

# Full path instead of relative path
require File.expand_path(File.join(File.dirname(__FILE__), 'path', 'name', 'for', 'file'))

Linux: '/home/jasonong/path/name/for/file'
Windows: 'c:\users\jasonong\path\name\for\file'

Thursday, September 10, 2009

Highlight line in Vim

# Highlight line that cursor is on

# Highlight line and then tab it

Open shell in Vim

# Open shell inside vim to do shell operations

# Exit shell

Use "p" instead of "puts Object.inspect"

@whatever = Whatever.blah

# Old way
puts @whatever.inspect

# Convenient way (achieve same thing)
p @whatever

# Can even print multiple
p @whatever, @another, @forever

Autocomplete in Vim

# Autocomplete string in buffer
CTRL + p

# Autocomplete line in buffer
CTRL + x + l

Tuesday, September 8, 2009

Better testing of form elements in Cucumber using form fieldsets

# Scenario:
# Sometimes too form elements --> messy!
# Also elements have same label names --> webrat won't know how to distinguish them
# Solution:
# Separate logical groupings of elements into fieldsets
# Cucumber test the fieldsets

# In feature file
When /../ do
Given I focus on XXX section

# In step definition file
Given /^I focus on "([^\"]*)" section do |section|

Using a factory name that doesn't correspond to a model

# Model

class GradeScaleRange < ActiveRecord::Base

# Factory

# Normally case -> OK!
Factory.define :grade_scale_range do

# This will scream!
Factory.define :grade_scale_range_a do

# Correct it with class name
Factory.define :grade_scale_range_a, :class => 'grade_scale_range' do

# Although the below seems ok in documentation. It will spew "dup NilClass" error
Factory.define :grade_scale_range_a, :class => GradeScaleRange do

Use TightVNC viewer with Vino

Vinagre that comes with Ubuntu cannot be configured for compression, faster response etc. Need to use TightVNC viewer instead to connect to a vino desktop session

xtightvncviewer -depth 8 -compresslevel 9 -quality 0 -nocursorshape IP_ADDRESS:0

Monday, September 7, 2009

Batch remove/rename files in terminal

# Batch git remove files

for f in `ls *.feature`
do git rm ${f}

# Batch git rename files

for f in `ls *.feature`
do git mv ${f}

Installing Hamachi for remote desktop (VNC) over VPN

Install Hamachi on Ubuntu 9.04

1. To being we must turn on the ‘tun’ module to enable IP Tunneling support for the Linux kernel. Most do not have this setup by default.

$ sudo modprobe tun

2. Open the modules file and add ‘tun’ to the list

$ sudo vi /etc/modules

3. Your file should look similar to the example below.

# /etc/modules: kernel modules to load at boot time.
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.


4. Save the file and exit out of vi, lets move on and verify that a tunneling node has been created. (*If you have compiled your own kernel you likely need to recompile it with IP Tunneling support if you receive an error with modprobe. This is not covered in this guide. And if you are unsure, you most likely did not compile yourself and you would definitely remember doing so.)

$ ls /dev/net/tun

5. You should recieve a response like the example below


6. If you received something along the lines of “No Such File or Directory” you may need to manually create the node in step 6. If you received the same response as I did, jump to step 7.

$ sudo tuncfg

Jump back to Step 4 and you should now receive the correct response.
7. With our IP Tunnel node created, it is time to install Hamachi itself. First download the latest version. As of writing this guide, the latest version is

$ wget

Expected output below

--2009-07-31 20:28:25--
Connecting to||:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 344866 (337K) [text/plain]
Saving to: `hamachi-'

100%[====================================================================>] 344,866 448K/s in 0.8s

2009-07-31 20:28:26 (448 KB/s) - `hamachi-' saved [344866/344866]

8. Extract our newly downloaded archive

$ tar zxvf hamachi-

Expected output below


9. Navigate into the extracted directory

$ cd hamachi-

10. Start the installation

$ sudo make install

Expected output below

Copying hamachi into /usr/bin ..
Creating hamachi-init symlink ..
Compiling tuncfg ..
Copying tuncfg into /sbin ..

Hamachi is installed. See README for what to do next.

11. Run the tunnel

$ sudo tuncfg

12. This should complete the install, we will now configure the user permission in order for it to run correctly. Create a ‘hamachi’ user group

$ sudo groupadd hamachi

13. Add youself as a user to the ‘hamachi’ group. Be sure to replace your user name where appropriate.

$ sudo gpasswd -a YOURUSERNAME hamachi

14. Add the root user to the ‘hamachi’ group

$ sudo gpasswd -a root hamachi

15. Set the correct permissions for the tuncfg socket

$ sudo chmod 777 /var/run/tuncfg.sock

16. Change the ownership of the socket file

$ sudo chgrp hamachi /var/run/tuncfg.sock

17. That should do it for the permissions, Now onto setting Hamachi up & configuring it to start as a system service.

$ hamachi-init

Expected output

Initializing Hamachi configuration (/home/jasonong). Please wait ..

generating 2048-bit RSA keypair .. ok
making /home/jasonong directory .. ok
saving /home/jasonong/ .. ok
saving /home/jasonong/client.pri .. ok
saving /home/jasonong/state .. ok

Authentication information has been created. Hamachi can now be started with
'hamachi start' command and then brought online with 'hamachi login'.

18. Start hamachi

$ hamachi start

Expected output

Starting Hamachi hamachi-lnx- .. ok

19. Set your computer’s nickname

$ hamachi set-nick "COMPUTERNICKNAME"

20. Login to the Hamachi network

$ hamachi login

21. To join an existing network (optional) “NETWORKNAME” and “PASSKEY” should be replaced with your network name and network password


22. To create a new network (optional) “NETWORKNAME” and “PASSKEY” should be replaced with your network name and network password

$ hamachi create NETWORKNAME PASSKEY

23. If you joined an existing network you must tell hamachi to then “go-online”. Be sure to replace NETWORKNAME with your relevant network name.

$ hamachi go-online NETWORKNAME

24. Check your hamachi status to verify everything is as it should be

$ hamachi

Expected outputhamachi -c /etc/hamachi start

Hamachi, a zero-config virtual private networking utility, ver

version : hamachi-lnx-
pid : 5472
status : logged in
nickname : JasonOng

Known Issues

And that pretty much completes the install. Just some words of advice from some small issues that I’ve run into. I’ve found it best to create a network with a Windows computer. The windows client supports network messaging, where the OS X and Linux clients do not. This is important because if you later choose to move control to , only the windows client will be able to receive the network message and reply to it. Allowing administrative controls to be transfered and managed from the website. OS X and Linux clients cannot do this at this point in time.

Install gHamachi GUI

First, visit the Hamachi forums and download the most recent version of the gHamachi frontend for either gtk 2.0 or gtk 1.2 (whichever you prefer).

gHamachi can be found here.

Second, simply unpack the gHamachi tarball, copy the binary to /usr/bin, and give it permission to run (chmod +x).


tar xfz gHamachi_gtk2.tar.gz
sudo mv ghamachi /usr/bin/
sudo chmod +x /usr/bin/ghamachi

Once that is done, the Hamachi GUI is completely installed.

Start the GUI like this:


Sunday, September 6, 2009

Formatting of date in bash terminal

$ date
Mon Sep 7 08:45:53 SGT 2009

$ date +'%m-%d-%y'

$ date +'%D'

$ date +'%H:%M%P'

Ruby regular expression

I'm not a regular expression expert nor am I a fan of its cryptic syntaxes. Nevertheless it's a useful tool to have in your programming toolbox

# String to match
message = "3798536196 Sun 10:02pm Jason Ong jasonong: @nazroll Dude, any possibility of some Wave action via uStream on that day? :) "

# Match sequence
message =~ /[\s]?[\w]+:[\s]/

# String with matches highlighted
3798536196 Sun 10:02pm Jason Ong jasonong: @nazroll Dude, any possibility of some Wave action via uStream on that day? :)

A good place to test out your ruby regex dynamically is

A ruby cheatsheet with good regex reference.

Saturday, September 5, 2009

Parse timestamp string to ruby Time object

# Require time to get parse() method
$ irb
>> require 'time'
>> true
>> Time.parse('Tue Apr 07 22:52:51 +0000 2009')
>> Tue Apr 07 22:52:51 0800 2009

Friday, September 4, 2009

Building a command line twitter client

Just to scratch my own itch.

I've been using twidge BUT...

- Needs me to leave my twitter password lying around in plain text config file
- Doesn't store my friends updates locally (at least for a week?)
- No easy way to RT, reply or even DM for that matter
- Doesn't display with colors (hard to read statuses)
- Doesn't display Name + Screen Name
- Not written in Ruby!

Hence I've started my own command line twitter client project using Ruby




- Retrieve friend's statuses
  • - Keeps track of last status id on a ~/.twitter file
  • - Gets only statuses that are tweeted later than the last status id

# Get recent new tweets since last get
ruby twitpow.rb friends

- Retrieve a user profile

# Show profile for @jasonong
ruby twitpow.rb user jasonong

- Statuses are stored & searchable in a PStore file

# Get all stored tweets
ruby twitpow.rb history

# Get last 20 stored tweets
ruby twitpow.rb history 20

# Search for "jasonong" in stored tweets
ruby twitpow.rb history search jasonong

- Update a tweet!

# Tweeeeet!
ruby twitpow.rb update "I can haz send a tweeet!"

- Reply to friend's status

# Reply to friend's status with status_id = 31122333
ruby twitpow.rb reply 31122333

# Prompt to key in your reply
Reply to: 31122333 01:00pm Jason Ong jasonong: This is my status lah!
>> This is my reply!

# @screen_name is prepended to your reply
@jasonong This is my reply!

- Retweet a friend's status

# Retweet friend's status with status_id = 31122333
ruby twitpow.rb retweet 31122333

# Prompt to key in a message to prepend the retweet
31122333 01:00pm Jason Ong jasonong: This is my status lah!
>> Awesome my friend!

# Message and @screen_name are prepended to the retweet
Awesome my friend! RT@jasonong This is my reply!

Libraries Used:
- Httparty for REST api
- Highline for password prompt
- Term-Ansi for text color output

- Get replies
- Get DMs
- Get conversation threads
- Get user details
- Post updates
- Post replies
- Post retweets
- Post DMs
- Display status time
- Even better reply
- Even better retweet

Using ruby to output ansi colors in terminal

# Install ansi color gem
sudo gem install term-ansicolor

# Usage example
puts "#{} #{}"

Commandline password prompt in ruby

require 'rubygems'
require 'highline/import'

def get_password(prompt="Enter Password")
ask(prompt) {|q| q.echo = false}

password = get_password()

Thursday, September 3, 2009

Use nmap to scan for open ports

# Install nmap
sudo apt-get install nmap

# Scan for open ports
nmap IP-address ( for localhost)

# Check if port is open
nmap -p port-no IP-address

How to use irssi

# Connect to irc server

# Join a channel
/join #hackerspacesg

# List users in channel

# Switch to next window
CTRL + n

# Switch to previous window
CTRL + p

Tips to use mobileterminal on iPhone


Hide the Keyboard

Tap twice quickly on the screen to hide the keyboard. Repeat to bring it back.

Control Characters

You can send a control-C by pressing the "bullet" key (First press ".?123", then "#+=", then the circle on the middle right), then press the C key. This can be useful when you want to escape out of a long running program such as ping. Control-C can also be accessed with a short Up-Right and Control is a short Down-Right swipe, after which the cursor will turn highlight red, from here press any character q, x, c, A to complete or the delete button to exit Control mode.

Escape is control-[ or a short Up-Left swip, which may come in handy with vi. Tab is control-I or a short Down-Left swip (yay tab completion).

Swipe Controls

Swipe Type Direction Action
Short Up-Right Control-C
Short Down-Right Control-
Short Up-Left Esc
Short Down-Left Tab
Short up/down/left/right arrow keys (respectively)
Long Up None (functions as up-arrow)
Long Down Enter
Long Left None
Long Right None
Two Finger Up Config
Two Finger Down Hide Keyboard
Two Finger Left Page-Up/Next
Two Finger Right Page-Down/PREV

None of the Two Finger Swipes seem to work right in 2.0 firmware

Multiple Terminals

Terminal comes with four terminal windows. Tap on the battery icon to go right, tap directally on the time to go left, and tap on the carrier name (AT&T or iPod) to crash Terminal (or do a really quick killall Terminal depending on how you look at it).

Wednesday, September 2, 2009

Cucumber feature template


In order to [Business Value]
As a [Role]
I want to [Some Action]

Tuesday, September 1, 2009

Do not use Ruby's Enumerable find() method in Rails

According to ruby doc.

find enumObj.find {| obj | block } -> anObject or nil

Synonym for Enumerable#detect .

However if you ever try to use Enumerable#find in Rails, you'll get a "cannot find object without object id" error.

Better to use Enumerable#detect

The problem with using Rail's try() method

@jasonong Try not to use Rail's try() method; makes debugging
difficult coz error not thrown.

Git: creating, pushing & deleting remote branches

I work on multiple machines. Need temporary remote branches that I can sync them with.

# create remote branch from a local branch
git push origin LOCAL_BRANCH:refs/heads/REMOTE_BRANCH

# push commits to remote branch

# pull commits from remote brance
git pull origin REMOTE_BRANCH

# delete remote branch
git push origin :REMOTE_BRANCH

Hidden features of Ruby

Monday, August 31, 2009

Open previously closed tabs in Firefox

@cheeaun Hmm.. how do I undo close window on Firefox?

@chuyeow @cheeaun Look in your History menu or hit Cmd-Shift-N.

@sengming @cheeaun on windows and linux its control-shift T. Just
one finger away from add new tab.

Using Mutt to manage your Gmail

sudo apt-get install openssl mutt

# ~/.muttrc

set imap_user = ""
set imap_pass = "password"

set smtp_url = "smtp://"
set smtp_pass = "password"
set from = ""
set realname = "Your Real Name"

set folder = "imaps://"
set spoolfile = "+INBOX"
set postponed="+[Gmail]/Drafts"

set header_cache=~/.mutt/cache/headers
set message_cachedir=~/.mutt/cache/bodies
set certificate_file=~/.mutt/certificates

set move = no

# Keymaps
j = next message
k = prev message
/ = search emails
c = change mail folder

Thursday, August 27, 2009

Create & serve a Sinatra app on your iPhone

Taking tips from this article on "Building a iPhone web app in under 50 lines with Sinatra and iUI", I've toyed around with building and serving one right from my iPhone.


gem install sinatra -v --no-ri --no-rdoc
# Latest gem needs fcgi gem which cannot be compiled properly

BUILD YOUR sinatra_app.rb

ruby -rubygems sinatra_app.rb

Question: So far I've got the V & C in MVC. What's the best way to build the M using Sinatra on iPhone? ActiveRecord?

Tuesday, August 18, 2009

Search and Replace in VIM




# Search & replace in current line

# Search & replace in lines 8 to 10
:8,10 s/search/replace/

# Global search & replace

# Global search & replace with prompt

More awesome search and replace tips at

Breaking Cucumber feature tests into separate smaller files

Previous I had the following Cucumber feature tests in a single file

# features/webrat/edit_enrollment_table

Feature: Editing of enrollment details from enrollment table
In order to edit enrollment details easily
As an admin
I want to edit enrollment details from enrollment table

Scenario: Admin should be able to enter entry test date
Scenario: Admin should be able to edit entry test date
Scenario: Admin should be able to enter entry test status
Scenario: Admin should be able to edit entry test status
Scenario: Admin should be able to enter interview test date
Scenario: Admin should be able to edit interview test date
Scenario: Admin should be able to enter interview test status
Scenario: Admin should be able to edit interview test status

Pretty massive. Why not split them up into manageable bits?

# features/webrat/edit_entry_test_details

Feature: Editing of entry test details from enrollment table
In order to edit entry test details easily
As an admin
I want to edit entry test details from enrollment table

Scenario: Admin should be able to enter entry test date
Scenario: Admin should be able to edit entry test date
Scenario: Admin should be able to enter entry test status
Scenario: Admin should be able to edit entry test status

# features/webrat/edit_interview_test_details

Feature: Editing of interview test details from enrollment table
In order to edit interview test details easily
As an admin
I want to edit interview test details from enrollment table

Scenario: Admin should be able to enter interview test date
Scenario: Admin should be able to edit interview test date
Scenario: Admin should be able to enter interview test status
Scenario: Admin should be able to edit interview test status

So here's what I think the advantages are:

- Cleaner code in a single file. Well, at least not so chunky!
- Running small number of tests is much FASTER,
- Can still run full quite with proper tagging. ie. @edit_enrollment_details

Blog Archive