Saturday, April 23, 2011

HTML5 Canvas - Bouncing Balls

I've been taking a closer look at HTML5 recently and have been playing with the canvas feature which allows you to draw graphics on a webpage using JavaScript. I wrote a quick example showing a few balls bouncing around.

Click on the box below, to activate:

Canvas not supported.

Source Code:

<script type="text/javascript">
var width = 100;
var height = 200;

function Ball(){
    // random radius
    this.radius = Math.floor(Math.random()*(10-5+1))+5;

    // random x and y
    this.x = Math.floor(Math.random()*(width-this.radius+1))+this.radius;
    this.y = Math.floor(Math.random()*(width-this.radius+1))+this.radius;

    // random direction, +1 or -1
    this.dx = Math.floor(Math.random()*2) * 2 - 1;
    this.dy = Math.floor(Math.random()*2) * 2 - 1;

    //random colour, r, g or b
    var rcol = Math.floor(Math.random()*3);
    this.col = rcol==0 ? "red" :
               rcol==1 ? "blue" : "green";
}

// create an array of balls
numBalls = 10;
var balls = new Array(numBalls);
for(i= 0 ; i < numBalls ; i++){
   balls[i] = new Ball();
}

// draw the balls on the canvas
function draw(){
  var canvas = document.getElementById("myCanvas");

  // check if supported
  if(canvas.getContext){

    var ctx=canvas.getContext("2d");

    //clear canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    ctx.globalAlpha = 0.5;
    ctx.strokeStyle="black";

    // draw each ball
    for(i = 0; i < numBalls ; i++){
      var ball = balls[i];
      ctx.fillStyle=ball.col;
      ctx.beginPath();

      // check bounds
      // change direction if hitting border
      if(ball.x<=ball.radius ||
         ball.x >= (width-ball.radius)){
        ball.dx *= -1;
      }
      if(ball.y<=ball.radius ||
         ball.y >= (height-ball.radius)){
        ball.dy *= -1;
      }

      // move ball
      ball.x += ball.dx;
      ball.y += ball.dy;

      // draw it
      ctx.arc(ball.x, ball.y, ball.radius, 0, 2*Math.PI, false);
      ctx.stroke();
      ctx.fill();
    }
  }
  else{
    //canvas not supported
  }
}

// calls draw every 10 millis
function bounce(){
    setInterval(draw, 10);
}
</script>
<canvas id="myCanvas" width="100" height="200" style="border-style:solid;border-width:1px" onclick="bounce()">
Canvas not supported.</canvas>

Further Reading:
Canvas Tutorial [developer.mozilla.org]

Sunday, April 17, 2011

Highlighting Command Output with Generic Colouriser

I recently started using Generic Colouriser, which is a tool that has the ability to colour the output from different programs based on regular expressions. It comes with config files for colouring output from commands such as diff, traceroute, ping, netstat and cvs, but it is also very easy to colour your own commands.

I wrote a config for ps which greys out the processes being run by root and highlights in green, the processes being run by me:

# configuration file for ps
# grey everything out
regexp=^[a-zA-Z]+ .*$
colours=bold black
======
# highlight my processes in green
regexp=^sharfah.*$
colours=green
You can then alias ps to use grc:
alias ps='grc ps'
I've also changed the log config, so that it greys out debug statements, colours warnings yellow and errors red. Most of my logs are produced by log4j. Here is my config:
# this configuration file is suitable for displaying log files
#errors
regexp=^.*(ERROR|Error|Exception).*$
colours=bold red
======
#stack trace
regexp=^\s+at [^:]*:\d*\)$
colours=red
======
regexp=^.*(FATAL|Fatal).*$
colours=on_red
======
regexp=^.*(WARNING|Warning).*$
colours=bold yellow
======
regexp=^.*(DEBUG|Debug).*$
colours=bold black
======
# this is a time
regexp=[^\d]*\d\d:\d\d:\d\d[\.,]{0,1}\d{0,1}\d{0,1}\d{0,1}
colours=bold blue
count=once
======
# ip number
regexp=\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
colours=bold magenta
count=more
I then created a bash function called cless which I use instead of less, to view my logs. I've also aliased tail.
cless ()
{
    if [ $# -eq 0 ]; then
        echo Usage: cless FILE;
        return 1;
    fi;
    grc cat $1 | less -iMF -R
}
alias tail='grc tail'
If you are getting bored of your bland terminal, try this out!

Saturday, April 16, 2011

Writing your own Bash Completion Function

Bash programmable completion is a powerful feature which allows you to specify how arguments to commands should be completed. You do this using the complete command. For example, you can set completion up so that when you type the unzip command and hit the TAB key, it only shows completions for files ending with the .zip extension. Similarly, the completion for the ssh command would display hosts taken from your known_hosts file.

In this post, I will describe how you can write a custom completion function for a command foo. Bash will execute this function when foo [TAB][TAB] is typed at the prompt and will display possible completions.

Bash uses the following variables for completion:

  • COMPREPLY: an array containing possible completions as a result of your function
  • COMP_WORDS: an array containing individual command arguments typed so far
  • COMP_CWORD: the index of the command argument containing the current cursor position
  • COMP_LINE: the current command line
Therefore, if you want the current argument that you are trying to complete, you would index into the words array using: ${COMP_WORDS[COMP_CWORD]}.

So, how do you build the result array COMPREPLY? The easiest way is to use the compgen command. You can supply a list of words to compgen and a partial word, and it will show you all words that match it. Let's try it out:

sharfah@starship:~> compgen -W "mars twix twirl" tw
twix
twirl

Now we have everything we need to write our completion function:

_foo()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $(compgen -W "alpha beta bar baz" -- $cur) )
}
complete -F _foo foo
Save this. Mine is in ~/.bash_completion.d/foo

Demo

sharfah@starship:~> . ~/.bash_completion.d/foo
sharfah@starship:~> foo ba[TAB][TAB]
bar
baz

A Bigger Example
Here is a meatier example of Bash completion. It shows how to complete Autosys commands such as sendevent and autorep. It completes command options, events which can be sent to jobs and job names which are obtained from a file. In some cases, the completions depend on the previous argument e.g. if the previous argument is -J then we know that we have to complete job names.

# a file containing job names
export AUTOSYS_JOBFILE=~/.autosysjobs

# complete autosys jobs using the job file
_autosysjobs()
{
  local cur=${COMP_WORDS[COMP_CWORD]}
  [ ! -z ${AUTOSERV} ] && \
    COMPREPLY=( $( compgen -W "$(cat ${AUTOSYS_JOBFILE}_${AUTOSERV})" -- $cur ) )
  return 0
}

# complete sendevent
_sendevent()
{
  local cur=${COMP_WORDS[COMP_CWORD]}
  local prev=${COMP_WORDS[COMP_CWORD-1]}

  case "$prev" in
   -S)
     COMPREPLY=( $( compgen -W "$(cat $AUTOSYS_HOSTFILE)" -- $cur ) )
     return 0
     ;;
   -E)
     COMPREPLY=( $( compgen -W "STARTJOB KILLJOB DELETEJOB \
                    FORCE_STARTJOB JOB_ON_ICE JOB_OFF_ICE \
                    JOB_ON_HOLD JOB_OFF_HOLD CHANGE_STATUS \
                    STOP_DEMON CHANGE_PRIORITY COMMENT \
                    ALARM SET_GLOBAL SEND_SIGNAL" -- $cur ) )
     return 0
     ;;
   -s)
     COMPREPLY=( $( compgen -W "RUNNING STARTING SUCCESS \
                    FAILURE INACTIVE TERMINATED" -- $cur ) )
     return 0
     ;;
   -J)
     _autosysjobs
     ;;
  esac

  # completing an option
  if [[ "$cur" == -* ]]; then
          COMPREPLY=( $( compgen -W "-E -S -A -J -s -P \
                       -M -q -G -C -U -T -K" -- $cur ) )
  fi
}
complete -F _sendevent sendevent

# complete autorep
_autorep()
{
  local cur=${COMP_WORDS[COMP_CWORD]}
  local prev=${COMP_WORDS[COMP_CWORD-1]}

  case "$prev" in
   -J)
      _autosysjobs
     ;;
  esac

  # completing an option
  if [[ "$cur" == -* ]]; then
          COMPREPLY=( $( compgen -W "-J -d -s -q -o \
                    -w -r -L -z -G -M -D" -- $cur ) )
  fi
}
complete -F _autorep autorep
Related Posts:
My Bash Profile - Part III: Completions

Saturday, April 02, 2011

My vimrc

.vimrc is file used to configure Vim.

Update: My dotfiles are now in Git. For the latest version, please visit my GitHub dotfiles repository.

Here is a dump of mine:

set nocompatible        " vim, not vi
set history=50          " keep 50 lines of command line history
set ruler               " show the cursor position all the time
set noerrorbells        " don't make noise
set cursorline          " highlight current line
set laststatus=2        " always show the status line
set expandtab           " no real tabs please!
set number              " Display line numbers on the left
set showcmd             " Show partial commands in the last line of the screen
set ignorecase          " Use case insensitive search, except when using capital letters
set smartcase           " case insensitive patterns - when only lowercase is used
set smarttab            " smart tabulation and backspace
set autoindent
set showmode            " Show the current mode
set showmatch           " show matching braces
set hlsearch            " highlight searches
set incsearch           " find as you type
set title               " show title
set pastetoggle=<F11>   " F11 toggles indenting when pasting
set wildmenu            " make command-line completion bash like + menu
set wildmode=longest:full
set showcmd             " show the cmd being typed
set shiftwidth=4        " No 8 character tabs
set softtabstop=4
set undolevels=1000     " 1000 undos

" Allow backspacing over autoindent, line breaks and start of insert action
set backspace=indent,eol,start

"F10 toggles line numbers
map <silent> <F10> :set invnumber<cr>

syntax on
For a complete list of vim options check out the Vim documentation.

Friday, April 01, 2011

Add Colour to Ant Output

You can add pretty colours to your ant output really easily by simply setting the following in your profile:
export ANT_ARGS='-logger org.apache.tools.ant.listener.AnsiColorLogger'
The AnsiColorLogger adds color to the standard Ant output by prefixing and suffixing ANSI color code escape sequences to it.

Read more about it here: Apache Ant | AnsiColorLogger