InfiniteRed

art.through(code)

The last Vim color scheme you'll ever need

Vim Logo
Color Scheme

This color scheme is based off of my popular IR_Black theme for TextMate.

When thinking of vim or vi, visually appealing UI doesn't normally enter your mind. But that isn't due to a lack of features, because its support for syntax coloring is one the best I've seen; the only thing slightly better is TextMate. It's due to the poor color schemes many people use.

In gVim or MacVim you have access to all colors, and in the shell you have access to the 16 ANSI colors (well at least in my 16 color terminal, you can have up to 256 colors in some terminals).

Examples

All the following examples use the Monaco font.

Ruby and blank file - MacVim (same as gVim) - full color
Ruby example

Ruby and blank file - vim in shell - 16 colors - note: I'm using my terminal theme
Ruby example

Other Examples

 Java example

 HTML example

 Windows and popup example

Install

  • Download the color scheme
  • Place that file (ir_black.vim) in your ~/.vim/colors folder
  • Change your color scheme using :colorscheme ir_black

18 comments

Artists keep scrapbooks of art and designs they like. You, developer, should do the same

It's common for artists, such as graphic designers, to keep scrapbooks of designs that catch their eye. This could be a logo, typeface, color scheme, page layout, or whatever else they deem of high quality. They use these scrapbooks (which traditionally were books with scraps of paper in them) to get inspiration, to help them develop their own style (by identifying likes and dislikes), or simply to browse.

Why does this matter to you, a developer?

That's a good question, and at first when I started to keep a scrapbook, I did it mainly for visual designs like web-pages. But once I started I realized it would work really well for diagrams, code, clever UI elements, or really any content that I think is exceptional.

If I'm working on a task, and feel bogged down and un-creative, I'll browse my scrapbook, getting inspiration. I look for little things that make the scraps great. I ask myself, why is this particularly good? This works just as well for a sort routine in code, as it does for logo design.

The main benefits of keeping a scrapbook are:

  • creating the habit of looking for, and identifying, content that you like, and
  • browsing the scrapbook at a later time to get your creative juices flowing

Development is a craft, half artistry, half engineering. Often in a community things become stagnant, old ideas are taken as dogma, and people stop innovating. Sometimes it's good to look at other crafts, study the techniques they use, and apply them to your work.

Creating your scrapbook

Obviously you can create a physical book to keep your 'scraps' in, but that seems a tad silly. What I did was create a folder (called scrapbook) in my dev folder (~/Dev).

In this folder, I place text files, screenshots of design or layout, or image files.

Browsing your 'book'

Coverflow screenshot

I browse my scrapbook using Finder's (OS X's file browser) Cover Flow view, and Quick Look; which works well as it displays text, images, PDFs, etc.

If you're using Linux or Windows, you can browse your images using a slide show app or just use Nautilus or Explorer.

Whatever you use, keep it simple, there is no need to over design your scrapbook.

How to organize, or better yet, not organize your scrapbook

I started with a folder structure that was complex, with a tree of categories and sub categories. After a while this became hard to use, and provided little value.

A scrapbook isn't a wiki, the important part is looking for what you like and storing it for later browsing. It isn't important to catalog all the information.

I ended up with the following folders in my scrapbook:

  • code
  • graphic_design
  • ui
  • web_design
  • words

Your needs will differ, that's a guarantee. The important part is to only organize what you need to, but go no further. I used those categories, so that I can browse my scrapbook depending on what task I'm working on. If I'm writing code, then the code folder makes sense. If I'm creating a logo, I look in the graphic_design folder. Inside each is just a bunch of files. I sort them by date when browsing.

Keep it simple

Complexity kills this technique. Make sure it's dead simple to add a new item to your scrapbook, taking no more than 5 seconds. If it takes more than that, you will stop doing it, and an empty scrapbook is a sad scrapbook indeed.

When I started keeping a scrapbook, I made things too complicated. When I found a webpage I liked, I would save the entire page (HTML, images, etc). This was hard to deal with, hard to browse, and not very valuable. It's much simpler and more valuable to simply take a screen shot of the page or part of the page (command-shift-4 in OS X).

I've been keeping a scrapbook for the last few months, and I find it useful. Give it a try, perhaps you will too.

6 comments

A black OS X Leopard Terminal theme that is actually readable

OS X Leopard was released with an updated Terminal application, which now has tabs, window groups, and many other new features. My excitement to replace the often slow iTerm was quickly extinguished as I realized that the new Terminal.app has some glaring problems:

  • The first is the inability to set the title of the tab as you do in iTerm, gnome-terminal, etc. That one I can live with, as there are work-arounds.
  • The other major problem is the horrible black themes that come with it (bad and worse). Apple is one of those companies who pay very close attention to visual details such as these, so it's surprising that they gave us such horrible choices.

So I decided to make a new theme, based on a subset of my popular TextMate theme IR_Black. The problem is the new Terminal app provides no way to set the ANSI colors; even though you can create your own themes (Settings), you can't change the colors. Ciarán Walsh provides a great solution to this on his blog, which uses the also great SIMBL.

Install Theme

  • Install SIMBL and TerminalColors following the instructions on Ciarán Walsh's blog. This is required for the color changes in my theme to work.
  • Download the theme file here.
  • Double click the IR_Black.terminal file, you downloaded, to install it.
  • Set it to be the default (if you want to always use these settings).

Screenshots

Example colors screenshot Example vim colors screenshot

Test Script

The following script will display the 16 colors in the terminal:

#!/bin/bash
echo -e "\\e[0mCOLOR_NC (No color)"
echo -e "\\e[1;37mCOLOR_WHITE\\t\\e[0;30mCOLOR_BLACK"
echo -e "\\e[0;34mCOLOR_BLUE\\t\\e[1;34mCOLOR_LIGHT_BLUE"
echo -e "\\e[0;32mCOLOR_GREEN\\t\\e[1;32mCOLOR_LIGHT_GREEN"
echo -e "\\e[0;36mCOLOR_CYAN\\t\\e[1;36mCOLOR_LIGHT_CYAN"
echo -e "\\e[0;31mCOLOR_RED\\t\\e[1;31mCOLOR_LIGHT_RED"
echo -e "\\e[0;35mCOLOR_PURPLE\\t\\e[1;35mCOLOR_LIGHT_PURPLE"
echo -e "\\e[0;33mCOLOR_YELLOW\\t\\e[1;33mCOLOR_LIGHT_YELLOW"
echo -e "\\e[1;30mCOLOR_GRAY\\t\\e[0;37mCOLOR_LIGHT_GRAY"

To install script:

  • Copy the script to your workstation, name it colors
  • Make it executable: chmod +x colors
  • Run it: ./colors

If there is an easier way to change the ANSI colors in Terminal, please let me know. Although I have had no problems with SIMBL, it's always better, if possible, not to use hacks.

Note: the color scheme I use for Vim in the screenshot above can be found here.

35 comments

A simple Ruby command-line application skeleton

To write a command-line application in Ruby is very simple, the following two-line application converts everything in the standard input to upper case and then outputs it:

#!/usr/bin/env ruby 
puts STDIN.read.upcase

Although complete, this is hardly a proper application, which should include options, arguments, help, input error trapping, etc. I've created a skeleton for such a command-line application.

Hoe and Gems

I intentionally put the entire application in one file, to make it easy for you to distribute. With this setup, your users only need the file in their path, and Ruby installed; no gems or anything else are required

Although a single file is convenient, it is proper to package your Ruby application as a gem, and distribute it via RubyForge. This way, someone can install your application with gem install YourApp.

If your users will have gems installed and you prefer to distribute your application that way, I recommend using the Hoe project to setup your directory structure:

sudo gem install hoe
sow your_app

You can also distribute your application in a variety of other ways, such as apt-get in Debian/Ubuntu or Ports in OS X/BSD. I chose the simplest route to start, which is one file, in your path.

Helping your users

There are many ways to provide help to your users, including simply puts "Your help...". The one I prefer is to use rdoc/usage , which uses the RDoc documentation you should already have in your code. This way, you only have to document your options once. RDoc documentation is very readable in the actual code, as well as when it's rendered to HTML.

In the following example, I list all the sections of my help using RDoc notation:

# == Synopsis 
#   This is a sample description of the application.
#   Blah blah blah.
#
# == Examples
#   This command does blah blah blah.
#     ruby_cl_skeleton foo.txt
#
#   Other examples:
#     ruby_cl_skeleton -q bar.doc
#     ruby_cl_skeleton --verbose foo.html
#
# == Usage 
#   ruby_cl_skeleton [options] source_file
#
#   For help use: ruby_cl_skeleton -h
#
# == Options
#   -h, --help          Displays help message
#   -v, --version       Display the version, then exit
#   -q, --quiet         Output as little as possible, overrides verbose
#   -V, --verbose       Verbose output
#   TO DO - add additional options
#
# == Author
#   YourName
#
# == Copyright
#   Copyright (c) 2007 YourName. Licensed under the MIT License:
#   http://www.opensource.org/licenses/mit-license.php

To create RDoc documentation from these comments use the following command:

rdoc my_file

The documentation that is produced can be seen here.

You can output help, to your users at runtime, using the RDoc documentation, with the following method:

RDoc::usage() #exits app

This will format your RDoc comments as plain text, output it, then close the application.

If you just want to output the usage section, you can do so with the following method call:

RDoc::usage('usage')

Many options for options

There are many ways to parse options (also known as a switch, flag, or parameter). I chose to use OptionParser. To parse basic options is as simple as the following:

opts = OptionParser.new 
opts.on('-v', '--version')    { output_version ; exit 0 }
opts.on('-h', '--help')       { output_help }
opts.on('-V', '--verbose')    { @options.verbose = true }  
opts.on('-q', '--quiet')      { @options.quiet = true }
# TO DO - add additional options
            
opts.parse!(@arguments)

You can use OptionParser to parse complex options also, including mandatory options, a list of values {start | stop | restart}, boolean switches --[no-]verbose, etc.

I chose to store my options using an OpenStruct object, which is a very convenient and clever alternative to a hash. I initialize them like so:

# Set defaults
@options = OpenStruct.new
@options.verbose = false
@options.quiet = false
# TO DO - add additional defaults

Creating a command-line application

To create your application, follow these steps:

  1. Make a copy of the skeleton code
  2. Make your file executable ( chmod +x your_file )
  3. Replace all instances of ruby_cl_skeleton with your application name
  4. Locate all the "# TO DO"s and make your changes
  5. Insert your functionality
  6. Distribute your application by placing the file anywhere in the user's path ( ~/bin /usr/bin )

A nice addition would be to make a rails type build command that creates the file for you, inserting the application name, etc.

Grab the skeleton code below. Happy coding.

Plain text file here.

#!/usr/bin/env ruby 

# == Synopsis 
#   This is a sample description of the application.
#   Blah blah blah.
#
# == Examples
#   This command does blah blah blah.
#     ruby_cl_skeleton foo.txt
#
#   Other examples:
#     ruby_cl_skeleton -q bar.doc
#     ruby_cl_skeleton --verbose foo.html
#
# == Usage 
#   ruby_cl_skeleton [options] source_file
#
#   For help use: ruby_cl_skeleton -h
#
# == Options
#   -h, --help          Displays help message
#   -v, --version       Display the version, then exit
#   -q, --quiet         Output as little as possible, overrides verbose
#   -V, --verbose       Verbose output
#   TO DO - add additional options
#
# == Author
#   YourName
#
# == Copyright
#   Copyright (c) 2007 YourName. Licensed under the MIT License:
#   http://www.opensource.org/licenses/mit-license.php


# TO DO - replace all ruby_cl_skeleton with your app name
# TO DO - replace all YourName with your actual name
# TO DO - update Synopsis, Examples, etc
# TO DO - change license if necessary



require 'optparse' 
require 'rdoc/usage'
require 'ostruct'
require 'date'


class App
  VERSION = '0.0.1'
  
  attr_reader :options

  def initialize(arguments, stdin)
    @arguments = arguments
    @stdin = stdin
    
    # Set defaults
    @options = OpenStruct.new
    @options.verbose = false
    @options.quiet = false
    # TO DO - add additional defaults
  end

  # Parse options, check arguments, then process the command
  def run
        
    if parsed_options? && arguments_valid? 
      
      puts "Start at #{DateTime.now}\\n\\n" if @options.verbose
      
      output_options if @options.verbose # [Optional]
            
      process_arguments            
      process_command
      
      puts "\\nFinished at #{DateTime.now}" if @options.verbose
      
    else
      output_usage
    end
      
  end
  
  protected
  
    def parsed_options?
      
      # Specify options
      opts = OptionParser.new 
      opts.on('-v', '--version')    { output_version ; exit 0 }
      opts.on('-h', '--help')       { output_help }
      opts.on('-V', '--verbose')    { @options.verbose = true }  
      opts.on('-q', '--quiet')      { @options.quiet = true }
      # TO DO - add additional options
            
      opts.parse!(@arguments) rescue return false
      
      process_options
      true      
    end

    # Performs post-parse processing on options
    def process_options
      @options.verbose = false if @options.quiet
    end
    
    def output_options
      puts "Options:\\n"
      
      @options.marshal_dump.each do |name, val|        
        puts "  #{name} = #{val}"
      end
    end

    # True if required arguments were provided
    def arguments_valid?
      # TO DO - implement your real logic here
      true if @arguments.length == 1 
    end
    
    # Setup the arguments
    def process_arguments
      # TO DO - place in local vars, etc
    end
    
    def output_help
      output_version
      RDoc::usage() #exits app
    end
    
    def output_usage
      RDoc::usage('usage') # gets usage from comments above
    end
    
    def output_version
      puts "#{File.basename(__FILE__)} version #{VERSION}"
    end
    
    def process_command
      # TO DO - do whatever this app does
      
      #process_standard_input # [Optional]
    end

    def process_standard_input
      input = @stdin.read      
      # TO DO - process input
      
      # [Optional]
      # @stdin.each do |line| 
      #  # TO DO - process each line
      #end
    end
end


# TO DO - Add your Modules, Classes, etc


# Create and run the application
app = App.new(ARGV, STDIN)
app.run

15 comments

Fun and profit by modifying your Bash startup files in OS X, Linux, and other fine unices

If you've been learning the command-line and you have the basics down (you should be, as the most effective way to use a computer is a combination of a GUI and command-line), the next step is to customize your environment.

Beginner's Tip: "command-line" and "shell" are often used synonymously. In unix, technically speaking, the shell is what processes the command-line, but usually, they mean the same thing

The ability to fully customize your shell is one of the most powerful things about the command-line. It's a dry subject, and mastering it won't get you favors from the opposite sex (although it should), but it can be very useful.

There are many ways to customize your shell, but the first one you should learn is modifying your Bash startup files (assuming your shell is Bash, which is the default in OS X, Linux, and many other unices).

When I first learned how to customize bash, I found an overwhelming amount of information and opinion, which made it difficult. This article is intended to give you the fundamental concepts so that you can create your own startup files, and understand how they work. To give you an example, I go through a subset of my own files, section by section.

Let's install the example startup files

Beginner's Tip: Directory and folder are synonymous. Often folder is used in Windows and OS X and directory is used in Linux, however even Linux represents a directory as a folder graphically

Below are the two example startup files: .bashrc and .bash_profile.

If you would like to use these as your startup files, follow the following directions for your OS.

OS X:

  1. If you want a backup of your existing files, use the following commands (if the files don't already exist, you will get an error. The files will be named .bashrc_ORIGINAL and .bash_profile_ORIGINAL in your home folder):

    cp ~/.bashrc ~/.bashrc_ORIGINAL ; cp ~/.bash_profile ~/.bash_profile_ORIGINAL
  2. Copy .bash_profile and .bashrc to your home folder.
    There are a variety of ways to do this, but the simplest is to use the curl command:

    curl -o ~/.bash#1 "http://www.infinitered.com/settings/dotfiles/osx/.bash{rc,_profile}"
  3. You do not need to log out, just create a new window or tab in iTerm, or a new window in Terminal.

Linux and other unices:

  1. If you want a backup of your existing files, use the following commands (if the files don't already exist, you will get an error. The files will be named .bashrc_ORIGINAL and .bash_profile_ORIGINAL in your home folder):

    cp ~/.bashrc ~/.bashrc_ORIGINAL ; cp ~/.bash_profile ~/.bash_profile_ORIGINAL
  2. Copy .bash_profile and .bashrc to your home directory.
    There are a variety of ways to do this, but the simplest is to use the wget (or curl for BSD and others) commands:

    wget -O ~/.bashrc "http://www.infinitered.com/settings/dotfiles/generic/.bashrc"
    wget -O ~/.bash_profile "http://www.infinitered.com/settings/dotfiles/generic/.bash_profile"
    or
    curl -o ~/.bash#1 "http://www.infinitered.com/settings/dotfiles/generic/.bash{rc,_profile}"
  3. Log out then log back in in order to load .bash_profile. Alternatively, you can do a source ~/.bash_profile to run the files.

What the heck are bash Startup Files?

Beginner's Tip: ~ represents your home folder, it is short-hand notation so that you don't have to type the whole thing; it is also used when you don't know the home folder; for example, my code above works, no matter where your home folder/directory is.

Bash, as well as other unix shells, have files that run when they start. You can modify these files to set preferences, create aliases and functions (a kind of micro-script), and other such fun.

When you start an interactive shell (log into the console, open terminal/xterm/iTerm, or create a new tab in iTerm) the following files are read and run, in this order:

  1. /etc/profile
  2. /etc/bashrc
  3. ~/.bash_profile
  4. ~/.bashrc (Note: only if you call it in .bash_profile or somewhere else)

When an interactive shell, that is not a login shell, is started (when you call "bash" from inside a login shell, or open a new tab in Linux) the following files are read and executed, in this order:

  1. /etc/bashrc
  2. ~/.bashrc
Beginner's Tip: Normally you can't see the . files (files that start with a period) because they are hidden. Depending on your OS, you can simply turn on hidden files. Another option is to open the file in the command-line. Here are a few examples:
In shell: pico .bashrc
In shell: vi .bashrc
In OS X: open .bashrc
In GNOME: gedit .bashrc

/etc/profile and /etc/bashrc are run for all users on the system. Often on your workstation, there is only one user, you. But in systems with more than one user, these files can be used to set generic settings for all users. The files in your home folder, ~/.bashrc and ~/.bash_profile, are only for your particular user (since /etc/bashrc is run before ~/.bashrc, you can override anything in /etc/bashrc by simply setting it again in ~/.bashrc). Normally I only change these, since they are in your home folder, and only you have rights to them, you can change them without worry of affecting anyone else.

When your session starts, these files are run, just as if you typed the commands in yourself. Anything that normally works in the shell works in these files. Since .bash_profile only runs when you first login, you set very little there; the only important thing is your PATH. bashrc is where the meat goes, and will be where you spend all your time.

Comments, export, and aliases, the tools of the trade

The most common commands you use in your .bashrc and .bash_profile files are the following:

  • comments: A # starts a comment, which continues until the end of a line. The comments are not run by the system, and are only there for your information. Use them to make notes to yourself for future reference.

    For example:

    # A very interesting comment, sure to be read by everyone
    alias foo='bar'  # Another comment, dangling at the end of a line
  • alias: An alias is simply substituting one piece of text for another. When you run an alias, it simply replaces what you typed with what the alias is equal to.

    For example, if you create an alias called foo and set it to "cd /etc":

    alias foo='cd /etc'

    Beginner's Tip: To test your startup files, use the source command (. also works). It loads and executes a file in your current process (rather than starting a new process, which is normally what happens):
    source .bashrc

    In the command-line every time you type foo it is replaced by cd /etc. If you type foo ; ls it will be run as cd /etc ; ls.

    To see what aliases are set on your system use the alias command. If run without any parameters it will list all the aliases.

    Note: You can create a temporary alias by setting it in the command-line rather than in a bash startup file. Lets say you're typing the same command over and over as you're working on some task. Just set an alias (alias foo=ThingImDoingOverAndOver). It will only exist in your current session.

  • export: Export sets an environment variable. Various environment variables are used by the system, or other applications, such as grep, or bash itself. They simply are a way of setting parameters that any application/script can read. If you set a variable without the export command, that variable only exists for that particular process (for example if you set a variable in a script, only that script can access it). You do this like so:

    FOO=1234

    If you want that variable to be accessible by other child processes (which is a fancy way of saying by everything) then you simply use the export command to make it permanent (technically it isn't permanent, but if you set it in your bash startup scripts it will be available to everything you run in bash, which basically means everything.). To make FOO, which we just set, permanent, we do the following in our .bashrc file:

    export FOO=1234

    It is common to make environment variables all upper case, as shown in the example.

    Bash has a set of environment variables you can set, such as the prompts (see below). Other applications use them too, such as GREP_OPTIONS for grep (see below). You can also create your own, to be used by you in the command-line or in scripts. In the color section below I create common colors to be used in the startup files, as well in other scripts I write.

    To see what environment variables are set on your system use the set command. If run without any parameters it will list them.

    To use an environment variable, you preface it with a $. A simple way to test this (assuming you set FOO already) is to print out the value using the echo command, like so:

    echo $FOO

Creating your .bash_profile

The .bash_profile file runs when you first login. You can put everything in this file, but since it only runs once and doesn't run when you start a non-login session, it is best that you put only the bare minimum, and then run the .bashrc file. With this approach, your .bashrc gets run every-time to start a new session, because it is called from .bash_profile on login, and it also gets run by bash automatically when starting a non-login shell.

The first thing to setup is your PATH. A path will already be set by the system, so you don't want to overwrite that. You can add to the path like this:

# Add to original path	
export PATH=/foo:/foo/bar:$PATH 

The $PATH at the end represents the existing path; in otherwords, you are taking the existing path, whatever that is set to, and adding the paths /foo and /foo/bar to it.

It is a good idea to add your bin directory to your path, if you have it. It's a standard place to add all of your scripts. The following lines will add the bin folder in your home folder to the path. The if statement simply checks to make sure it exists first before it adds it. This is safe to use even if there is no bin folder:

if [ -d ~/bin ]; then
    export PATH=:~/bin:$PATH
fi

Next, we will run the .bashrc file. The source command reads and runs another file in the same session you're in (the . command does the same thing and is synonymous with source).

source ~/.bashrc

If you like, you can show a welcome message. This only runs when you first log in. The following is an example welcome message (note the colors, which are set in .bashrc below):

echo -e "Kernel Information: " `uname -smr`
echo -e "${COLOR_BROWN}`bash --version`"
echo -ne "${COLOR_GRAY}Uptime: "; uptime
echo -ne "${COLOR_GRAY}Server time is: "; date	

On my workstation, it displays the following:

	Last login: Wed Aug 29 09:55:37 on ttyp1
	Welcome to Darwin!
	Kernel Information:  Darwin 8.10.1 i386
	GNU bash, version 2.05b.0(1)-release (powerpc-apple-darwin8.0)
	Copyright (C) 2002 Free Software Foundation, Inc.
	Uptime: 10:41  up 47 mins, 3 users, load averages: 0.01 0.02 0.00
	Server time is: Sat Sep 29 18:41:12 PDT 2007

Now the fun* begins, creating your .bashrc

* The word "fun" is used for entertainment purposes only. "Fun" or any other type of amusement is neither guaranteed nor expressly implied.

The .bashrc file is where the meat of your customization goes.

Normally it doesn't matter in which order various items go, so the way the file is laid out is an individual preference. There are many ways to setup a .bashrc file, and many things you can use it for, there is no "right" way; only opinions on which is the right way.

In this section I'm going to go over some of the more common things you would use it for, as well as some things that are less common, but that I personally like. You can include as little or as much as you like in your own file.

ColorsTM

Colors aren't the most important thing, truly, however because I use colors throughout the entire file, I need them to be created first.

I'll start by turning on colors for misc things, the following set your terminal to be the color variant of xterm, turn on colors in grep, etc:

export TERM=xterm-color

export GREP_OPTIONS='--color=auto' GREP_COLOR='1;32'

export CLICOLOR=1 

OS X and BSD - The following command turns on colors in ls:

alias ls='ls -G'  

Linux, etc - uses the following to turn on colors in ls. You can specify exactly what color is used for what, which is very nice. See http://www.linux-sxs.org/housekeeping/lscolors.html for more information on setting specific colors:

alias ls='ls --color=auto' 
export LS_COLORS='di=1:fi=0:ln=31:pi=5:so=5:bd=5:cd=5:or=31:mi=0:ex=35:*.rb=90'

Some standard colors, to make adding colors later in this file, or in scripts, easier:

export COLOR_NC='\e[0m' # No Color
export COLOR_WHITE='\e[1;37m'
export COLOR_BLACK='\e[0;30m'
export COLOR_BLUE='\e[0;34m'
export COLOR_LIGHT_BLUE='\e[1;34m'
export COLOR_GREEN='\e[0;32m'
export COLOR_LIGHT_GREEN='\e[1;32m'
export COLOR_CYAN='\e[0;36m'
export COLOR_LIGHT_CYAN='\e[1;36m'
export COLOR_RED='\e[0;31m'
export COLOR_LIGHT_RED='\e[1;31m'
export COLOR_PURPLE='\e[0;35m'
export COLOR_LIGHT_PURPLE='\e[1;35m'
export COLOR_BROWN='\e[0;33m'
export COLOR_YELLOW='\e[1;33m'
export COLOR_GRAY='\e[0;30m'
export COLOR_LIGHT_GRAY='\e[0;37m'
alias colorslist="set | egrep 'COLOR_\w*'"  # lists all the colors

Here is an example of using a color in a script (note, the -e is required):

echo -e "The color ${COLOR_GREEN}green${COLOR_NC} is nice."		

Prompts ~/bin >

Beginner's Tip: If you use different systems, a good trick is to check or import your startup files (and any other . files you like [. or dot files are hidden files and often used for settings]) into a source code repository, such as subversion. Then no matter what system you are on, assuming your subversion server is accessible, you can simply "checkout" your files with one command. Alternatively, you can store them on your website.

You can also do this with your ~/bin folder so you have your scripts too. It takes only a second to get them, and saves you time configuring the environment.

In the shell, every line begins with the prompt, right before the area you can type into. You can put a variety of different things in your prompt, from simply characters such as > to your user name, the name of the machine, or a ridiculous number of other things.

Some people's prompts are, frankly, silly; do you really need your prompt to say something like this (note, the answer is "no")?
juser@myMachine 1/1/2007 12:31:02 PM - "Funny quote of the day" - /home/juser>

I make my prompt as simple as possible, normally all you see is
~ >, which is just the path of the current folder followed by a ">".

Knowing what user I am logged in as and which machine I'm on is also useful, but I put that in the window of my terminal (see below). For this very simple prompt, I use the following:

export PS1="\[${COLOR_GREEN}\]\w > \[${COLOR_NC}\]"

Since you can setup a .bashrc for each user, I normally set my regular user's prompt to be green, and then I change it to red for root. This gives me a visual reminder that I'm logged in as root, and to be careful.

The following runs before the prompt and sets the title of the terminal window. If you set the window title in the prompt, weird wrapping errors occur on some systems, so this method is superior:

export PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*} ${PWD}"; echo -ne "\007"' 	

Note: PROMPT_COMMAND, used in this way, causes problems when you are using the command-line directly (a non-graphical terminal, such as the system console). Simply disable this in those circumstances. You can also write a little if to check for that if you like.

Here is an alternative prompt, with the user and machine name:

export PS1="\[${COLOR_GRAY}\]\u@\h \[${COLOR_GREEN}\]\w > \[${COLOR_NC}\]"  # Primary prompt with user, host, and path 

Now I just set prompts 2 through 4. There is a lot of information on setting prompts, but to cover that would be a whole other article. I wanted to give you just the basics, if you want more in depth information follow this link.

export PS2='> '    # Secondary prompt
export PS3='#? '   # Prompt 3
export PS4='+'     # Prompt 4	

Navigation

In the command-line, you have to move around a lot. The following aliases are designed to help you navigate your file system with ease.

Here is a very simple and useful way to move back up the directory tree, two dots moves you up one, and three dots moves you up two levels in your path:

alias ..='cd ..'
alias ...='cd .. ; cd ..'

A lot of people create a home alias, but this isn't necessary. cd by itself, without any parameters takes you back to your home.

Another tip is to use cd - which takes you to the previous folder.

The following is very cool; I got it from this site. I modified it slightly to make it work a little better:

if [ ! -f ~/.dirs ]; then  # if doesn't exist, create it
	touch ~/.dirs
fi

alias show='cat ~/.dirs'
save (){
	command sed "/!$/d" ~/.dirs > ~/.dirs1; \mv ~/.dirs1 ~/.dirs; echo "$@"=\"`pwd`\" >> ~/.dirs; source ~/.dirs ; 
}
source ~/.dirs  # Initialization for the above 'save' facility: source the .sdirs file
shopt -s cdable_vars # set the bash option so that no '$' is required when using the above facility

It basically allows you to save bookmarks to folders. If you constantly go to a particular directory, you can just set it as a bookmark like so:

save foo

This will set the current folder you are in as the bookmark foo. To get back to the folder, just type this:

cd foo

You can list your "bookmarks" with the show command:

show
foo="/Users/joebob/foo"

The bookmarks are stored in the ~/dirs file, so you can edit them there too if you like.

Editors

If an application, such as Subversion, needs you to edit text. It will often launch an external editor and load the text into it. You can modify which application is launched by setting the EDITOR variable. I've listed various options below depending on your system:

#export EDITOR='mate -w'  # OS-X SPECIFIC - TextMate, w is to wait for TextMate window to close
#export EDITOR='gedit'  #Linux/gnome
#export EDITOR='vim'  #Command line
export EDITOR='pico'  #Command line

Misc

Common ls commands. Many people use these. ll shows the long listing, and lla shows the long listing with hidden files:

alias ll='ls -hl'
alias la='ls -a'
alias lla='ls -lah'

Some very useful settings I like to set:

export HISTCONTROL=ignoredups # Ignores dupes in the history
shopt -s checkwinsize # After each command, checks the windows size and changes lines and columns

# bash completion settings (actually, these are readline settings)
bind "set completion-ignore-case on" # note: bind is used instead of setting these in .inputrc.  This ignores case in bash completion
bind "set bell-style none" # No bell, because it's damn annoying
bind "set show-all-if-ambiguous On" # this allows you to automatically show completion without double tab-ing

# Turn on advanced bash completion if the file exists (get it here: http://www.caliban.org/bash/index.shtml#completion)
if [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
fi

Others you may find useful:

alias g='grep -i'  #case insensitive grep
alias f='find . -iname'
alias ducks='du -cks * | sort -rn|head -11' # Lists the size of all the folders and files
alias top='top -o cpu'
alias systail='tail -f /var/log/system.log'

Shows the commands you use most, it's a cool script I got this from this site. It's useful to show you what you should create aliases for:

alias profileme="history | awk '{print \$2}' | awk 'BEGIN{FS=\"|\"}{print \$1}' | sort | uniq -c | sort -n | tail -n 20 | sort -nr"

Subversion and Diff

This section is only useful if you use Subversion and diff. However, it highlights various things you can do with aliases and functions.

The basic concept is to wrap a bunch of commands, giving them a new naming convention. In this case the command is svn, and it has many options, such as svn status. By wrapping these commands, you can set common parameters that you use all the time. Also since they are aliases, you can use bash completion (set above) to get a nice list of the commands. For the following, if I just type sv and tab, I get a list of commands.

Some of these aliases simply wrap the original commands, without modifying them. I do this for consistency, and it gives me the opportunity to change them later.

First we set some standard settings for Subversion:

export SV_USER='juser' # Change this to your username that you normally use on Subversion (only if it is different from your logged in name)
export SVN_EDITOR='${EDITOR}'

The next alias is interesting, as I'm basically using it to provide help to myself. Of course if you know subversion well, you don't need this, but it may be useful when you're first starting out and learning. When you type svshowcommands, it prints out a nice colored description of all the commands. Notice how you can have one alias on multiple lines:

alias svshowcommands="echo -e '${COLOR_BROWN}Available commands: 
   ${COLOR_GREEN}sv
   ${COLOR_GREEN}sv${COLOR_NC}help
   ${COLOR_GREEN}sv${COLOR_NC}import    ${COLOR_GRAY}Example: import ~/projects/my_local_folder http://svn.foo.com/bar
   ${COLOR_GREEN}sv${COLOR_NC}checkout  ${COLOR_GRAY}Example: svcheckout http://svn.foo.com/bar
   ${COLOR_GREEN}sv${COLOR_NC}status    
   ${COLOR_GREEN}sv${COLOR_NC}status${COLOR_GREEN}on${COLOR_NC}server
   ${COLOR_GREEN}sv${COLOR_NC}add       ${COLOR_GRAY}Example: svadd your_file
   ${COLOR_GREEN}sv${COLOR_NC}add${COLOR_GREEN}all${COLOR_NC}    ${COLOR_GRAY}Note: adds all files not in repository [recursively]
   ${COLOR_GREEN}sv${COLOR_NC}delete    ${COLOR_GRAY}Example: svdelete your_file
   ${COLOR_GREEN}sv${COLOR_NC}diff      ${COLOR_GRAY}Example: svdiff your_file
   ${COLOR_GREEN}sv${COLOR_NC}commit    ${COLOR_GRAY}Example: svcommit
   ${COLOR_GREEN}sv${COLOR_NC}update    ${COLOR_GRAY}Example: svupdate
   ${COLOR_GREEN}sv${COLOR_NC}get${COLOR_GREEN}info${COLOR_NC}   ${COLOR_GRAY}Example: svgetinfo your_file
   ${COLOR_GREEN}sv${COLOR_NC}blame     ${COLOR_GRAY}Example: svblame your_file
'"

Here I wrap each command:

alias sv='svn --username ${SV_USER}'
alias svimport='sv import'
alias svcheckout='sv checkout'
alias svstatus='sv status'
alias svupdate='sv update'
alias svstatusonserver='sv status --show-updates' # Show status here and on the server
alias svcommit='sv commit'
alias svadd='svn add'
alias svaddall='svn status | grep "^\?" | awk "{print \$2}" | xargs svn add'
alias svdelete='sv delete'
alias svhelp='svn help' 
alias svblame='sv blame'
alias svdiff='sv diff'

You may have noticed I added a few commands too, such as svaddall; this isn't part of standard Subversion. This command, for example, adds all files that aren't already in the repository.

OS X specific: The following alias allows you to use the FileMerge OS X app for your diffs. You need to create fmdiff and fmresolve, which can be found at this site.

Note: Use diff for command line diff, use fmdiff for gui diff, and svdiff for subversion diff.

alias svdiff='sv diff --diff-cmd fmdiff' # OS-X SPECIFIC

Functions

Functions deserve their own article. But basically they are used when an alias isn't enough. The following is a simple example of a function, it is used to show the both the info and the log of a file in subversion in one command (svgetinfo):

svgetinfo (){
    sv info $@
    sv log $@
}	

All done... finally

That is a lot of information, and to fully cover everything it could be ten times longer.

I hope you found something of use, I got rid of the cruft, and tried to only include truly useful things. There are tons of other things you can do to customize bash, happy bashing.

6 comments

Converting a black TextMate theme to white using a simple Ruby application

TextMate theme
Download Theme (once downloaded, simply double click on the file to install) I created the IR_Black theme, and some people asked for a white version of it. So instead of doing it manually I thought a quick Ruby script to make all the colors darker would work well. I started by creating a new theme, then I changed all the foreground colors to their negative. This worked well and maintained the contrast between the different colors, but it changed the whole look of the theme (changing blues to reds, etc.), which I didn't want. Then I tried converting the colors from RGB into HSL and then inverting the L (which is lightness or luminance depending on what you read); this did what I wanted. TextMate stores its colors in HTML Hex triplet format (#FF0000), so all I needed to do was parse those out of the original file, convert the color into HSL, then invert it by subtracting it from its max (which is 1). I used the color-tools gem to do the color manipulation, and it worked well.
require 'rubygems'
require 'color'  # gem install color-tools

regx = /(foregrounds*?)(#.+?)()/

new_xml = STDIN.read.gsub(regx) do
    hsl = Color::RGB.from_html($2).to_hsl
    hsl.l = 1 - hsl.l

    $1 + hsl.html + $3
end

puts new_xml
After I created the script above (which I named c_theme.rb), I just piped the original theme to it and created the new theme:
cat IR_Black.tmTheme | ruby c_theme.rb >> IR_White.tmTheme
I then changed the backcolors to white, and manually tweaked it some. It's much harder to make a white theme, because you don't see the color difference as easily, so it's hard to find colors that stand out, without being too glaring. I personally don't like white themes much, but I think I captured the essence of the black theme with my conversion. Example Ruby code using the theme:
Ruby example

2 comments

The last TextMate theme you'll ever need

TextMate theme
Download Theme (once downloaded, simply double click on the file to install)

This theme is based off of the Succulent and Brilliance Dull themes. I wanted a black theme that had different colors for a wide variety of items, with coordinated colors between like items.

Ruby
Ruby example

Java
Java example

HTML
HTML example

XML
XML example

9 comments

Installing Ruby and Ruby On Rails from scratch on OS X using DarwinPorts / MacPorts

Ruby OS X graphic

I've created a screencast that shows you how to setup the following from a fresh install of Mac OS X Tiger (10.4.8):

I started by installing OS X on a firewire drive, then I setup the basic stuff you'll need to develop in Ruby and Ruby on Rails. Although Locomotive does a good job of getting you started fast, this screencast shows you how to move past that and install the latest versions of everything via DarwinPorts / MacPorts in the command-line.

Here is the profile shown in the screencast. For more information on how to completely customize your bash startup files, read my article here.

I set the resolution to 800x600 and I recorded the whole screen, so that you see everything that I do, without missing pieces.

InfiniteRed Screencast 001
68.9mb Quicktime file, 28 minutes long

Note: I set, in the screencast, the path and aliases in the /etc/profile file. That was intentional; I do realize the the best way to do this is to put the path in the profile (or ~/.bash_profile), and the aliases and such in the /etc/bashrc (or ~/.bashrc) file, and then reference bashrc from the profile. However, this approach, although ideal, is complicated and mostly isn't necessary in OS X for a new command-line user. In OS X, the profile is read every-time a new Terminal window or tab is created; which is different behavior from some other Unices. The only time, in OS X, that using only the profile is a problem is when you create a new non-login shell by calling "bash" from inside an existing shell. For more information on how to completely customize your bash startup files, read my article here.

12 comments