Category Archives: Unix

Easy Way to Create Colorful Bash Prompt

The Problem

I often want to fiddle with the bash prompt, but don’t want to deal with bash prompt escape sequences. I wish for a utility which simplify setting a bash prompt. I finally wrote that utility myself: mkprompt

Install

Copy mkprompt to a directory in the path.

Using mkprompt

The best way to show mkprompt usage is via a couple of examples.

PS1=$(mkprompt "red workdir" space dollar)  
PS1=$(mkprompt "cyan Workdir" space "green dollar")  
mkprompt # display help

For more information, see my shell_tools page.

What’s Next?

The following are improvements which I plan for mkprompt, depends on my free time:

  • Implement the rest of the prompt escape sequences
  • Improve the help output
  • Implement installation script

The Script

I current host my script as part of my shell_tools collection on GitHub.

Advertisements

New Life for Old Laptop

In this article, I am going to discuss ways I gave my five-year-old laptop a new life.

In 2007, I purchased a used laptop to learn .NET programming. Since it was an old laptop, the machine barely had enough horse power to run Windows Vista. Soon, my job no longer require .NET programming, I promptly wiped the hard drive and installed Ubuntu Linux on it. What a difference does that make! My laptop started much faster, ran applications quicker and I did not have to worry about malware, trojan, or virus. Life was good.

Fast forward to last year, after several updates, my laptop was running a current version of Linux Mint, but it seems not fast enough. At that time, I had two choices: upgrade my memory from 2GB to 4GB, or upgrade the hard drive to SSD. After a little research, I decided on the later. I ordered a 40GB SSD drive for about $100. Again, the new drive blew me away: I was able to boot up my system in about 37 seconds (including the time to type the password). Applications now start much more quickly than before. I even compare my laptop with those of my brothers and it blew the newer laptops away. Yes, I know I am comparing apple with orange (Linux vs. Windows, SSD vs. hard drives). My laptop now makes an excellent machine for daily use: Facebook, email, web, watching videos, and development (scripting, C, C++).

In summary, if you have an old laptop, don’t hesitate upgrade it to SSD and install Linux on it (I recommend Linux Mint for ease of use). You won’t be disappointed. Not only your machine will run much faster than before, you get peace of mind knowing that your machine is realatively safe from malware and the like (relatively because there is no such thing as absolutely safe operating system).

My Brief BSD Adventure

I was bored. My old laptop has been running Linux Mint for a while and now I want something different so I checked out BSD, PC-BSD to be more specific.

In the past, I have been flirting with BSD several times, and ended up abandon BSD for Linux. This time is no exception. Before going into the bad parts (at least for me), I would like to state that PC-BSD 8.2 is an excellent OS. The installation is smooth and trouble-free, unlike my previous encounters. The default KDE window dressing are attractive and clean looking. Overall, applications are fast.

There are a few things that I subjectively found not up to my taste; again, the keyword here is subjectively. The default shell for PC-BSD is csh, but my choice is bash, so I changed it at installation time. PC-BSD uses KDE as its primary window manager; personally, I like gnome better. The default installation includes Tcl 8.5, but it is called tclsh8.5, without any softlink to tclsh at all. I had to create that soft link myself. On most Linux systems and on the Mac, the shell is called tclsh, simply enough.

Now, comes the things that drove me nut for the two days I ran PC-BSD. First off, after installation, I ran software update. After reboot, I logged into KDE and found a screen with just a wall paper, nothing else. I tried alt-tab and saw a bunch of applications in the task list, but none of them is visible. I tried to fix it for two hours and finally gave up and ended up re-installing the OS from scratch.

I then left my laptop unplugged and went to sleep as it was late. The next day, I turned on my laptop and found that the battery was drained, so I plugged the power cord in and turned on the laptop. I thought the laptop was in hibernation; but it booted up as if it was turned off. That means I lost my works from the previous night (a couple of C++ files). I thought PC-BSD should have hibernate the system when battery went down. Furthermore, the power saving should have sleep, then hibernate the system, in order to save battery in the first place.

Worse yet, once booted up, I could no longer connected to my WIFI access point. Fast forward until the afternoon, I gave up my hope and gave up on BSD one more time. I was going to try Fedora 15 next.

Besides these annoyances, there are a few things about PC-BSD that I don’t like. On my 1.66GHz core duo laptop with a 40GB SSD, my Linux Mint 11.04 boots up in about 38 seconds. Fedora 15 does it for about 48 seconds. However PC-BSD took its sweet time to about 2 minutes and 37 seconds.

The default Linux Mint installation allows to use the right- and bottom edge of the trackpad to scroll. Fedora 15 allows to choose between using the edge or two fingers. However, PC-BSD does not allow to scroll using the trackpad. I am sure, eventually I will find out, but I wish they offer scrolling in the default installation.

These are a few things that prevent PC-BSD from becoming my primary OS. I hope that PC-BSD 9 will be much better. When it comes out, I will give it another try.

Better Font and Color for tkcon in Linux Mint 11

The Problem

In Linux Mint, the default font and background color for tkcon is terrible. I want to change that to something easier to read.

The Solution

Here is my ~/.tkconrc, which fixes it by choosing a better font and background color:

set ::tkcon::COLOR(bg) ivory
set ::tkcon::OPT(font) "{Liberation Mono} 10"

Discussion

The default font in Linux Mint is terrible: it is hard to read and pixelated. I found the Liberation Mono font works best for me; your mileage may vary. Also, the default background of gray is somewhat dark and drepressing, therefore I changed it to ivory, which is an off-white color (at least on my old laptop).

Automatically List a Directory’s Contents After Changing Dir

The Problem

After the cd command, the next command is almost always ls so we want to combine the two to automatically issuing the ls command right after the cd command.

The Solution

In bash, add the following line in either ~/.bash_profile or ~/.bashrc:

function cd() { builtin cd "${@:-$HOME}" && ls -l; }

If you are using csh or tcsh, add the following line to .cshrc:

alias cd 'cd \!*; ls -l'

Now, whenever we type a cd command, not only we are changing the work directory, but also list the files at the new location. I would like to thank Matt Jenkins for helping me out with the csh part.

Squeeze Multiple Blank Lines within vim

The Problem

I want to squeeze multiple blank lines into just one while editing in vim. I often receive source code which the author used multiple blank lines to separate functions. I don’t mind if functions or code block are one or two lines apart, but I have seen sources where functions are four or more blank lines from each other. This is annoying and I want to squeeze many of them into one.

The Solutions

The obvious solution is to use vim’s search-and-replace feature, as discussed in this post. However, my regular expression skill is very basic and I tend to forget the syntax when I need it. Hence, I devised my own solution, one which I have better luck memorizing.

My solution involes the cat command:

:%!cat -s

This short little command applies ‘cat -s’ on my entire file contents, which squeezes multiple blank lines down to one. Note that this solution will only work on Unix-like systems such as BSD, Linux, and Mac OS X. It does not work on Windows. This is one of the shortcoming of this method compare to the previous one.

How to Configure WGet to Work with Proxy Server

The Problem

I want to configure WGet to go through a proxy server without having to specify that on the command line

The Solutions

The first solution is easy: I can set a shell variable called http_proxy. Here is an example in bash:

$ http_proxy=http://proxy-server:8080
$ export http_proxy

Another solution is to place this information in a configuration file called ~/.wgetrc. Here is a sample:

http_proxy=http://proxy-server:8080

If you have administrative rights and want to configure the system-wide behavior, then place the above line into the file /etc/wgetrc.

Conclusion

This is a very simple configuration problem, but it took me a while to figure out because I assumed that my system came with proxy pre-configured, but it was not. If you use wget on your system and it took a long time to get some trivia file (for example http://google.com) and you are sure that your internet connection is working fine, then you might have a proxy problem. Normally, you only encounter proxy servers at work, school, or other organization, but not at home.

Simple Menu with Bash’s Select Command

The Problem

Sometimes, I need a simple menu in bash, but I don’t want to spend a good deal of time coding for one.

The Solution

Bash has a built-in command called select which gets the job done. To demonstrate this command, I am going to write a short bash script. This script lists all the files in the current directory, then prompts the user to make a choice. If the choice is valid, it invokes the editor on the file. It will ignore any invalid choice. Below is the source for that script:

#!/bin/sh
# Displays a list of files in current directory and prompt for which
# file to edit

# Set the prompt for the select command
PS3="Type a number or 'q' to quit: "

# Create a list of files to display
fileList=$(find . -maxdepth 1 -type f)

# Show a menu and ask for input. If the user entered a valid choice,
# then invoke the editor on that file
select fileName in $fileList; do
	if [ -n "$fileName" ]; then
		vim ${fileName}
	fi
	break
done

Explanation

Line 6 – By default the select commmand uses ‘#?’ as a menu prompt. If the variable PS3 is defined, it will use that variable instead.

Line 9 – The find command retrieves a list of files in the current directory. The script then stores the result in the variable fileList

Line 13 to 18 – The select .. do .. done command displays a menu using $fileList as a list of items.

Line 14 to 16 – This block of code check if the user’s choice was valid and invoke the editor accordingly

Line 17 – The select command acts like an endless loop unless a break command is encountered

Sample Run

Below is a sample run

	$ edit_files.sh
	1) ./arguments		        
	2) ./data		            
	3) ./for_example	        
	4) ./getopt_function.sh	   
	5) ./getopt_homemade.sh	   
	6) ./getopt_tryout
	Type a number or 'q' to quit: 3

The Hack

If you are reading this far, I hope you detected my hack (hint, look at the PS3 prompt). By experimenting with select, I found out that if the user entered an invalid choice (i.e. a letter ‘q’ instead of an integer) then select will set the control variable ($fileName in this case) to empty. Taking advantage of this feature (or bug?), I designed the prompt and check for non-empty variable (line 14-16) before invoking the editor.

Conclusion

The select command is easy to use, but it save the script writers from the tedious job of displaying the menu, the prompt, then ask for the user’s input. The only caveat programmers need to watch out for is the lack of input validation so be sure to check your control variable before using it.

Changing Directory Listing (ls) in RHEL

This is a follow-up to my previous post.

The Problem
The ls command in Redhat Enterprise Linux (RHEL) by default uses the dark blue to show directories. This color is hard to see, especially on laptops with dim screens. I would like an easy way to change that.


The Solution

The solution is similar to that in my previous post, but Redhat makes it a little easier. Here are the steps:

  1. Create a text file containing the color definitions by issue the following command: dircolors > ~/.dircolors
  2. Edit the file ~/.dircolors and change the colors to your taste
  3. Exit the shell and login again to see the changes

Explanation

When a user logs in, RHEL executes the start-up files in the /etc/profile.d directory. Among those start-up files, colorls.sh (for borne-family shells) and colorls.csh (for csh-family shells) are responsible for setting the ls colors. The scripts look in the user’s home directory for a file called .dircolors to overwrite the colors. By creating and tweaking this file, the user can change the colors of the ls command to his or her taste. Personally, I prefer the bright yellow for directory:

Display Weather from Command Line

Since I work on Linux/OSX command line all day, I prefer to get my information such as stock quote or weather via command line. Here is a script to do that.

A couple of notes:

  1. I use curl instead of the TclCurl package because my system does not come with TclCurl
  2. The script employs Google Weather API to retrieve weather data. The rest of the script deals with converting that data from XML format to human-readable format.
  3. I use this script as part of my geek tool output.

Here is a sample output of the script:

$ weather
Seattle, WA 98121 2009-05-08 22:15:09 +0000 
  Condition      : Overcast
  Temperature (F): 61
  Humidity       : 47%
  Wind           : NE at 2 mph

  Fri 63 45 Mostly Sunny 
  Sat 68 47 Mostly Sunny 
  Sun 67 49 Mostly Sunny 
  Mon 61 47 Chance of Showers 

Bothell, WA 98012 2009-05-08 22:18:51 +0000 
  Condition      : Cloudy
  Temperature (F): 55
  Humidity       : 58%
  Wind           : N at 2 mph

  Fri 59 41 Mostly Sunny 
  Sat 63 43 Mostly Sunny 
  Sun 65 45 Mostly Sunny 
  Mon 58 41 Chance of Showers 

Here is the script itself:

#!/usr/bin/env tclsh

package require tdom

# Provide the default zip codes of none specified
if {$argc == 0} { set argv {98121 98012} }

foreach location $argv {
    set xml [exec curl --silent http://www.google.com/ig/api?weather=$location]

    set doc [dom parse $xml]
    set root [$doc documentElement]

    #
    # Show Forecast Information
    #

    set inf [$doc getElementsByTagName forecast_information]
    set data ""
    append data "[[$inf selectNodes city] getAttribute data] "
    append data "[[$inf selectNodes postal_code] getAttribute data] "
    append data "[[$inf selectNodes current_date_time] getAttribute data] "
    puts "$data"


    #
    # Show Current Condition
    #
    set currentConditions [$doc getElementsByTagName current_conditions]

    set labels {
        condition      "Condition"
        temp_f         "Temperature (F)"
        humidity       "Humidity"
        wind_condition "Wind"
    }

    set longest 0
    foreach {tag labl} $labels {
        set length [string length $labl]
        if {$length > $longest} { set longest $length }
    }

    foreach {tag labl} $labels {
        set node [$currentConditions selectNodes $tag]
        set data [$node getAttribute data]
        regsub {[^:]*: *} $data "" data
        puts [format "  %-*s: %s" $longest $labl $data]
    }

    puts ""

    # Show Conditions for Next Days
    foreach cond [$doc getElementsByTagName forecast_conditions] {
        set data ""
        append data "[[$cond selectNodes day_of_week] getAttribute data] "
        append data "[[$cond selectNodes high] getAttribute data] "
        append data "[[$cond selectNodes low] getAttribute data] "
        append data "[[$cond selectNodes condition] getAttribute data] "
        puts "  $data"
    }
    puts ""
}