Post-It Notes Resume

Introduction

I am currently searching for a job, as the result, I often carry in my “murse” (man-purse) a stack of paper resume. Due to the size of the bag (a Tom Bihn Small Cafe bag), I have to fold the pages in half. In addition, these pages add bulk in a bag where space is already at a premium.

john-doe-resume

To solve this problem, I put my resume online, then point people to it.

Posting Resume Online

I used Google Docs to create my resume. Consequently, they already available online. All I need to do is to make my document public and received a random (and long) URL. The next step is to shorten that URL using a URL-shortening service such as bit.ly. Now that I have a short, easy-to-type URL, the next step is how to give that URL to someone. Writing on a piece of paper is always an option, but there is a better way.

Post-It Note Resume

To easily hand out my resume, I print the URL for my resume, along with a QR code on Post-It notes and carry those notes with me. These notes take only a fraction of spaces compare to the full letter-size pages of my resume. They are easier to hand out as well.

To create the QR code, I searched online and found many places to do so. I used qstuff.com for my creation, but other sites work as well. Next, I searched online for a way to print onto Post-It notes and found many pointers as well. The one I used was from a site called One Good Thing.

How to type Vietnamese on Windows 7

Typing Vietnamese on Windows 7 does not require any third-party software. All we need is to enable the Vietnamese keyboard and learn how to type special characters.

Installation

Image

Open Control Panel and click on Clock, Language and Region.

Image

Click on Change keyboards or other input methods at the bottom of the right pane.

Image

Click Change keyboards…

Image

In the Text Services and Input Languages window, click Add…

Image

Select Vietnamese from the list and click OK.

Image

We will see the Vietnamese keyboard added. Click  OK and we are done with the installation.

 

How to Type Vietnamese Text

The first step is to switch the keyboard from English (or your current language) to Vietnamese.  Look at the bottom of right of the screen, we will see “EN” for English. Click on it and select “VI” for Vietnamese.

Image

 

Next, we will learn how to type special Vietnamese characters:

Huyền = 5
Hỏi = 6
Ngã = 7
Sắc = 8
Nặng = 9

ă = 1
â = 2
ê = 3
ô = 4
đ = 0
ư = [
ơ = ]

Good luck.

 

tcltest Part 9: Provides Exit Code

The Problem

One of the complains against tcltest is the fact that it does not return an exit code to communicate test pass/fail status.

Consider a simple scenario. In a directory, we have two files: all.tcl, which drives all the tests, and test1.test, which contains the actual tests. The contents of all.tcl is:

package require tcltest
tcltest::runAllTests

And the contents of test1.test is:

package require tcltest
namespace import ::tcltest::*

test fail_me {} -body { set foo 1 } -result 0
test pass_me {} -body { set foo 1 } -result 1

cleanupTests

In the scenario above, one of the tests will fail, but all.tcl will always return with exit code 0. It would be more useful if it returns 0 when all tests passed and 1 when not all tests passed.

The Solution

We looked into the tcltest source code and found an array, tcltest::numTests, which looks what we need. So, we modified all.tcl to see if we can use it:

package require tcltest
tcltest::runAllTests
parray tcltest::numTests

The result is disappointing:

(irrelevant output omitted)
tcltest::numTests(Failed)  = 0
tcltest::numTests(Passed)  = 0
tcltest::numTests(Skipped) = 0
tcltest::numTests(Total)   = 0

With one failed tests, we thought tcltest::numTests(Failed) should be 1, but it was not. we went back to the source code and dug a little deeper and found tcltest::cleanupTests resets these numbers after it finishes reporting.

Just when we was about to give up, we thought of asking Mr. Google for help. Sure enough, tcltest provides a hook into its tcltest::cleanupTests, which gives us access to the statistics variables before it resets them. Here is the final all.tcl:

package require tcltest

# Hook to determine if any of the tests failed. Then we can exit with
# proper exit code: 0=all passed, 1=one or more failed
proc tcltest::cleanupTestsHook {} {
    variable numTests
    set ::exitCode [expr {$numTests(Failed) > 0}]
}

tcltest::runAllTests
exit $exitCode

Discussion

The trick is to write a hook, tcltest::cleanupTestsHook. Before resetting the test statistics, tcltest::cleanupTests calls the hook function, which gives us the opportunity to access these statistics, and use them to determine the exit code.

Now that all.tcl returns the proper exit code, we can use it to determine pass/fail. Here is an example using the bash shell in Unix-like systems:

#!/bin/bash
if tclsh all.tcl; then
    echo Tests passed
else
    echo One or more tests failed
fi

For Windows environment:

tclsh all.tcl
if errorlevel 1 echo One or more tests failed

Conclusion

We wish tcltest automatically returns the correct exit code, but it does not. For now, we will stick with this solution and hope that whoever working on tcltest won’t make our code obsolete.

How to Install .apk File onto an Android Device

The Problem

I am new to the Android platform. At work, I need to side-load our app for testing. My device is an HTC one of 2012. At first, I installed and ran the HTC Sync Manager from my MacBook Pro with hope that it could help me, but after half an hour, I gave up: I copied the .apk file to the file section, sync, then check the phone: I could not find that .apk file anywhere. It could be me, but for the life of me, I could not find a way to copy the file in question onto the device. There must be a better way.

My Solution

As I stated before, the problem is with me being a novice. However, I did spend a good half an hour googling for solutions to no avail. Finally, an idea came to me: what if I can transfer the file from my Mac to the HTC One via HTTP? With that though, I opened up a terminal session, cd to the directory where my .apk file is, and issued the following command:

python -m SimpleHTTPServer

That command created an impromptu web server to serve all the files within the current directory. From the HTC One, I fired up a web browser and jumped to my server: haiv-mac1.local:8000 and expected to see the directory listing. However, I could not connect to my Mac at all. Frustrated, I tried again and again, prepending http:// to the address, check my spelling, knelt down and prayed… But nothing worked. I tried the same address using my iPhone and it works. So the problem was with the Android device. Finally, I was able to connect using my Mac’s IP address. How I love Android!

Once I downloaded the file, it was a simple matter of tapping the Downloads icon, find my file, and tap on it to install.

Conclusion

I like the Android platform for giving me the ability to side-load apps, which is great for testing. However, the process could be simpler. Veteran Android users and developers might laugh hearing this story, but it is no joke to me. Until I gain enough expertise, I’ll stay with my trusty iPhone.

Tcl: A Custom For Loop

The Problem

I often need to loop through a list of items and need both the index position, and the item itself. Typically:

set names {John Paul George Ringo}
set i 0
foreach name $names {
    puts "$i - $name"
    incr i
} 

Output:

0 - John
1 - Paul
2 - George
3 - Ringo

Initial Solution

Since I frequently do this, I decided to implement my own loop and call it for_item_index for lack of creativity. Here is my loop and a short code segment to test it:

proc for_index_item {index item iterable body } {
    uplevel 1 set $index 0
    foreach x $iterable {
        uplevel 1 set $item $x
        uplevel 1 $body
        uplevel 1 incr $index
    }
}

# Test it
set names {John Paul George Ringo}
for_index_item i name $names {
    puts "$i - $name"
}

I have tested it with break, and continue and found my new loop performs as expected. My concern is the excessive use of uplevel command in the code.

Here are my own review of my code:

  • Excessive use of uplevel – I don’t know what to do about it. If you have an idea, please send it my way.
  • The index always starts at zero. There are times when I want it to start at 1 or some other values. To add that feature, I will probably introduce another parameter, startValue
  • Likewise, the index always get incremented by 1. The user might want to increment it by a different values such as 2, or –1 to count backward. Again, introducing another parameter, step might help, but at this point, the loop is getting complicated.

Revised Solution

Shortly after the initial solution, I posted it on StackExchange’s CodeReview site. While waiting for comments, I started to revise the initial solution to include the start- and increment values. Here is the revised solution and code snippets to demonstrate:

proc for_index_item {indexexpr itemvar iterable body} {
    # Break down indexexpr
    set step 1
    set start 0
    if {[llength $indexexpr] == 3} {
        set step [lindex $indexexpr 2]
    }
    if {[llength $indexexpr] >= 2} {
        set start [lindex $indexexpr 1]
    }
    upvar 1 [lindex $indexexpr 0] index
    set index $start

    upvar 1 $itemvar item

    # Actual loop
    foreach item $iterable {
        uplevel 1 $body
        incr index $step
    }
}

#
# Test
#

puts "\nDefault, start with 0"
set names {John Paul George Ringo}
for_index_item i name $names {
    puts "  $i - $name"
}

puts "\nStarts from 1"
set names {John Paul George Ringo}
for_index_item {i 1} name $names {
    puts "  $i - $name"
}

puts "\nWith start value and increment"
set names {John Paul George Ringo}
for_index_item {i 110 10} name $names {
    puts "  $i - $name"
}

Output:

Default, start with 0
  0 - John
  1 - Paul
  2 - George
  3 - Ringo

Starts from 1
  1 - John
  2 - Paul
  3 - George
  4 - Ringo

With start value and increment
  110 - John
  120 - Paul
  130 - George
  140 - Ringo

A few comments:

  • I took in a suggestion and used upvar instead of uplevel, which makes the logic a little cleanner.
  • Half of my code is now devoted to parsing
  • The word index is miss-leading: it has nothing to do with the index as in a list index. It is just part of a sequence of numbers. In the future, I might rename it to remove confusion.

Let the Mac Speak for Me

The Problem

I often lose my voice temporarily due to allergy. During that time, my main mode of communication is a notepad, or the electronic equivalent: Zen Brush. I was looking for a solution that can convert what I type into spoken words.

The Solution

Since I am using Mac both at home and at work, and Mac has the say command which is useful for this purpose; I decided to roll my own solution. It turned out that the solution is a very simple bash script, which I named speak4me.sh, which I saved in my ~/bin directory:

#!/bin/bash
while read line
do
    say -v Alex $line
done

To make the script executable, I issued the following command:

$ chmod +x ~/bin/speak4me.sh

Using speak4me.sh

To use speak4me.sh, from the terminal, issue the following command:

$ speak4me.sh

After that, start typing your message. As soon as you hit the return key, the script will “say” what you type. You can keep on typing and hitting return. To end the script, just type Ctrl+C.

Discussion

The script is very simple, pragmatic and free from bells and whistles, but it works the way I like it. The -v Alex part of the say command specifies a voice from Alex. OS X comes with a few voices which you can experiment with yourself. To list the voices your system has, issue the following command:

$ say -v ?
Agnes               en_US    # Isn't it nice to have a computer that will talk to you?
Albert              en_US    #  I have a frog in my throat. No, I mean a real frog!
Alex                en_US    # Most people recognize me by my voice.
Bad News            en_US    # The light you see at the end of the tunnel is the headlamp of a fast approaching train.
Bahh                en_US    # Do not pull the wool over my eyes.
Bells               en_US    # Time flies when you are having fun.
Boing               en_US    # Spring has sprung, fall has fell, winter's here and it's colder than usual.
Bruce               en_US    # I sure like being inside this fancy computer
Bubbles             en_US    # Pull the plug! I'm drowning!
Cellos              en_US    # Doo da doo da dum dee dee doodly doo dum dum dum doo da doo da doo da doo da doo da doo da doo
Deranged            en_US    # I need to go on a really long vacation.
Fred                en_US    # I sure like being inside this fancy computer
Good News           en_US    # Congratulations you just won the sweepstakes and you don't have to pay income tax again.
Hysterical          en_US    # Please stop tickling me!
Junior              en_US    # My favorite food is pizza.
Kathy               en_US    # Isn't it nice to have a computer that will talk to you?
Pipe Organ          en_US    # We must rejoice in this morbid voice.
Princess            en_US    # When I grow up I'm going to be a scientist.
Ralph               en_US    # The sum of the squares of the legs of a right triangle is equal to the square of the hypotenuse.
Trinoids            en_US    # We cannot communicate with these carbon units.
Vicki               en_US    # Isn't it nice to have a computer that will talk to you?
Victoria            en_US    # Isn't it nice to have a computer that will talk to you?
Whisper             en_US    # Pssssst, hey you, Yeah you, Who do ya think I'm talking to, the mouse?
Zarvox              en_US    # That looks like a peaceful planet.

Python: Making Complex Regular Expression Easier to Read

In my last post, I shared a way to created regular expression with embedded comments for the Tcl scripting language. It turns out that Python also offers similar feature.

The Problem

I often need to deal with complex regular expression while scripting in Python. The problem is, the expression syntax is terse, cryptic and hard to understand and debug. There must be a better way to deal with regular expression, a way to add comments would be nice.

The Solution

As with my last post, I will use the same example: fishing out email addresses from a chunk of text. Below is the Python counterpart of my previous solution:

import re

if __name__ == '__main__':
    test_data = '''
            This is a bunch of text
            within it, there are some emails such as foo@bar.com
            or one@two.three.net
            What about mixed case: John.Doe@services.company.ws...
            Let see if we can extract them out
            '''
    email_pattern = r'''
            # The part before the @
            [a-z0-9._%-]+

            # The ampersand itself
            @

            # The domain, not including the last dot
            [a-z0-9.-]+

            # The last dot
            \.

            # The top-level domain (TLD), which ranges from 
            # 2 to 4 characters
            [a-z]{2,4}
            '''
    print 'START'
    result = re.findall(email_pattern, 
            test_data, 
            re.IGNORECASE|re.VERBOSE)
    print '\n'.join(result)
    print 'END'

The output:

START
foo@bar.com
one@two.three.net
John.Doe@services.company.ws
END

Conclusion

With the re.VERBOSE flag, I can embed white spaces and comments in the regular expression, making it easier to read and understand.