8 Feb 2012

Running interactive programs uninteractively in Bash scripts

Bash scripts are great for automating tasks. Some challenges arise though when you want to automate a process that involves programs that ask for user input by keyboard. You know, the kind of program that keeps asking things like: "Are you sure you want to do this (y/n)?". Most programs accept arguments that enable some kind of "non-interactive mode" for that. For example,


rm -i somefile
asks for confirmation before deleting somefile, while

rm -f somefile
does not. This of course makes the latter a lot more suitable for use in automated scripts. Unfortunately, not all programs provide these kind of arguments. What to do with them?

One option is to use redirection and echo the input into them, like so:


echo "yes" | rm -i somefile
or, if you want to remove a lot of files (and for some reason don't want to replace the -i argument with -f), with the brilliant command yes:

yes | rm -i somefile*

Things start to look ugly though when you have to provide a lot of different input texts. Say you have a program generate_random_files which, well, generates random files after asking in sequence:

  1. How many files?
  2. Size of files?
  3. Are you sure (y/n)?
Suppose our answer to the first question is 2, to the second question 4, and the third one y. Providing the input could be accomplished by:

/bin/echo -e "2\n4\ny" | generate_random_files
but it doesn't look particularly readable. Another option would be to create a text file input.txt with contents:
2
4
y
and then invoke the program with redirected input from this file:

generate_random_files < input.txt

This gives you one more file to manage though. Also, it makes it clumsy to use Bash variables in the input. For example, if you want a file size not of 4, but of some variable $calculatedSize, then you would have to manipulate the text file from within your script before calling generate_random_files.

An elegant way to do it is to use what is called "here documents", which allows you to basically put the literal contents of input.txt right in your script, eliminating the need for a separate file and allowing use of variables, while keeping things reasonably human-readable. The syntax is: program name followed by << followed by a unique delimiter of your own choosing, then on a new line the text that serves as input for the program, and then on a new line (and not preceded by any spaces or tabs!) the delimiter again. Like in this little script:


#!/bin/bash
echo "Starting generate_random_files..."
generate_random_files <<TextForInput
2
4
y
TextForInput
echo "Finished!"
And here's the same example, but using a variable which holds the size in bytes, calculated based on the argument $1 that provides the size in kilobytes:

#!/bin/bash
sizeInKb=$1
calculatedSize=$((1024*$sizeInKb))
echo "Starting generate_random_files..."
generate_random_files <<TextForInput
2
$calculatedSize
y
TextForInput
echo "Finished!"

24 Jan 2012

Dynamically hiding and showing columns in a Dojo DataGrid

Still having fun with my DataGrid. (See my previous post for more DataGrid joy.)

Now I had a big DataGrid with lots of columns and rows. It got so big that I decided it might be a good idea to hide some rarely needed columns when the user clicks a button. As I found out, the JavaScript code to show or hide a DataGrid's column is:


grid.layout.setColumnVisibility(i, visible);
in which grid is the DataGrid, i is the column number and visible is true (visible) or false (invisible). This worked, but with lots of columns and rows, it took forever to show or hide the columns. The API mentions the methods beginUpdate() and endUpdate(), which should speed things up when you "make multiple changes to rows". Although I'm not actually changing the rows (just the columns), I decided to give it a try:

grid.beginUpdate();
grid.layout.setColumnVisibility(i, visible);
...
grid.layout.setColumnVisibility(j, visible2);
grid.endUpdate();
This made the hiding/showing at least ten times faster!

23 Jan 2012

Firing an event after updating a DataGrid's data store in Dojo

Currently I find myself struggling with Dojo. It's rather sparsely documented and I regularly have to plow through the web to find out how to get something done. I might as well document some of my findings here, so other people (and myself because I might forget) can benefit from it.

In this case the issue was that I had a Dojo DataGrid, and I wanted to do something after every (re)load of its datastore. For the example's sake, suppose I wanted to run the following JavaScript function:


function doThisAfterLoadingDataStore()
{
  alert('DataStore has been (re)loaded!');
}
Of course the data store's fetch() method has an onComplete event, but to fire that event, I would have to explicitly call fetch(). This would be a waste of bandwidth, because the data store's data has already been fetched since I declaratively specified the store in the DataGrid, which causes an automatic fetch (without a specifyable onComplete event). It would have been great if there were an event onFetchComplete for the DataGrid, but unfortunately in the version of Dojo that I'm using (1.6), this is not the case. It does have an event _onFetchComplete, but this is a private event, and can't be specified declaratively in HTML (which is what I wanted to do). Luckily it can be specified in JavaScript with the dojo.connect method, so I managed to do it in the following way:
  1. I declaratively specified a postCreate method for my datagrid:
    
    <table ... dojoType="dojox.grid.DataGrid" ... postCreate="gridPostCreate">...</table>
    
  2. This postCreate method calls dojo.connect to specify the _onFetchComplete event (and also makes sure the base postCreate is called):
    
    function gridPostCreate()
    {
      dojo.connect(this, "_onFetchComplete", doThisAfterLoadingDataStore );
      this.inherited("postCreate", arguments);
    }
    
This did the trick. Now let's hope the _onFetchComplete event will continue to work like this in future Dojo versions...

19 Jan 2012

Syntax highlighting for source code on Blogger

This being a software development blog, I wanted to show some source code. This code should of course be shown in a nicely syntax highlighted way. I searched around on the web a bit, and found some articles that explain how to use the excellent SyntaxHighlighter by Alex Gorbatchev on Blogger, but they're rather old. Here are updated instructions for the new Blogger interface:

  1.  On your blog's dashboard, click Template and then Edit HTML. You'll get a warning that says that you may mess up your blog, but since you're an ace programmer anyway, you don't mind much and you click Proceed.
  2. Find the closing </head> tag and right above it, paste the following:
    
    <!--SYNTAX HIGHLIGHTER BEGINS-->
    <link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
    <link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js' type='text/javascript'/>
    <script language='javascript'>
    SyntaxHighlighter.config.bloggerMode = true;
    SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf';
    SyntaxHighlighter.all();
    </script>
    <!--SYNTAX HIGHLIGHTER ENDS-->
    
  3. Click Save.
  4. Now, to use the syntax hightlighting in your Blogger post, click HTML in the Edit Post window, and write code like this (the example is for HTML code - notice the &lt; instead of < to prevent issues, see Alex's website for more explanation):
    
    <pre class="brush:html">
    &lt;input type="Submit" value="Submit" />
    </pre>
    
    to get this in the resulting post:
    
    <input type="Submit" value="Submit" />
    

That's all!

Update 21 January 2014: This blog now uses highlight.js for syntax highlighting. See also this post.