Why I like Boo

Boo is a very simple programming language.

I am not sure that I would use it in a production application for fear of the maintenance problems (where do you get Boo programmers from?).

Things that I particularly like are:

Booish – being able to interactively play with practacally any .NET class without the need for a heavyweight IDE to be open.

The fact that you can post the source code to a blog like this without messing up the formatting!

I am planning a series of topics on Boo and the .NET 3 Pillars:

  • WF – windows workflow
  • WPF – windows presentation foundation
  • WCF – windows communication framework

At first I will be using Boo plus Nant but may need to stray into MSBuild.

Boo Generic Support

The following blog listed generic support details for boo: link

states that generic type definitions in Boo are handled thus:

 MyType of MyGenericParam

or for multiple generic parameters

MyType[of X,Y,Z]

I find Boo to be a great exerimentation language, ideal for turning a class into a commandline tool.

wmi in boo

# The following is a very simple example of using wmi from boo
import System
import System.Collections
import System.Data
import Boo.Lang
import System.Management
import System.Windows.Forms

class WmiApp:
    _tb as TextBox
    _dgv as DataGridView
    [STAThread]
    def Run():
        f = Form(Text: “Hello, boo!”)
        _tb = TextBox(Text: “SELECT * FROM Win32_Service”, Dock: DockStyle.Top)
        _dgv = DataGridView(Dock: DockStyle.Fill)
        b = Button(Text: “Click Me!”, Dock: DockStyle.Top)
        b.Click += ButtonClick
        f.Controls.Add(_dgv)
        f.Controls.Add(b)
        f.Controls.Add(_tb)

        Application.Run(f)
    def ButtonClick(args, sender):
        WMIQuery(_tb.Text)
    def WMIQuery(query as string):
        qry = SelectQuery(query)
        ds = DataSet()
        table = ds.Tables.Add(“WMI”)
        mos = ManagementObjectSearcher(qry)
        loaded = false
        moc as ManagementObjectCollection
        moc = mos.Get()
        for prop as PropertyData in (array(moc)[0] as ManagementObject).Properties:
            table.Columns.Add(prop.Name)
        moa = array(moc)
        mo as ManagementObject
        for i in range(0, moc.Count):
            mo = moa[i]
            row = table.NewRow()
            for prop as PropertyData in mo.Properties:
                row[prop.Name] = prop.Value
            table.Rows.Add(row)

        _dgv.DataSource = table

WmiApp().Run()

Using a class in an exe in Boo

Boo is great for lightweight experiments:

===  myclass.boo ===

namespace foo

class myclass:
    def foo():
        print(“Hello”)

c = myclass()
c.foo()

===============

=== myclass2.boo ===

import foo from “myclass.exe”

c = myclass()
c.foo()

=================

Create the two above files.

Compile both with the booc compiler. 

 run myclass2.exe

This shows how easy it is to extend a .net app in Boo. 

Boo Podcast Client

# Podcatcher.boo
#
# (C) Chris Eyre 2007

# This is released under the BSD licence.

#
# This is the start of a podcast download script.
# I have been unable to find a suitable podcast client to replace iPodder under Ubuntu 7.4
# so there was a need to write one.
#
# Required features:
# Download a podcast to a defined directory.
# Easy reload.
# No excessive configuration.
#
# Todo:
# Scheduler
# UI
# bitorrent support.
# Currently it is portable between Mono and .Net

import System.IO
import System.Net
import System.Xml

# This reads a file structured:
# podcastlist
# podcast
# name
# url
# output
#
def ProcessFeeds(target as string):
x = XmlDocument();
x.Load(target)
for xnode as XmlNode in x.FirstChild.ChildNodes:
url = xnode.SelectSingleNode(“url”).InnerText
name = xnode.SelectSingleNode(“output”).InnerText
ProcessFeed( url, name)

#Decodes the RSS feed.
def ProcessFeed(uri as string, output as string):
w = WebClient()
x = XmlDocument()
x.Load(w.OpenRead(uri))
xnode = x.SelectSingleNode(“//channel”)
for itemnode as XmlNode in xnode.ChildNodes:
if itemnode.Name == “item”:
url = itemnode.SelectSingleNode(“enclosure/@url”).InnerText
print(url)
GetPodcast(url, output)

// Grabs the podcast if not already got.
// If the downloaded file is corrupt then delete it and it will be replaced on the next run.
def GetPodcast(podcast as string, output as string):
filename = output + “/” + NameFromUrl(podcast)
if not File.Exists(filename):
WebClient().DownloadFile(FixUrl(podcast), filename)

# another hack for .NetRocks
def FixUrl(url as string) as string:
if Path.GetExtension(url) == “.torrent”:
return Path.ChangeExtension(url,null)
else:
return url

def NameFromUrl(url as string) as string:
#HACK: This may work for dotnet rocks, but I am still working on a torrent client
if Path.GetExtension(url) == “.torrent”:
return Path.ChangeExtension(Path.GetFileName(url),null)
else:
return Path.GetFileName(url)

ProcessFeeds(“/home/chris/Projects/PodCatcher/list.xml”)
print(“done”)

Boo and MSBuild

Msbuild is microsofts answer to Ant. This is a build tool for the .Net Platform.

It has the minor benfit of being the native file format of the Visual Studio 2005 project files.

You need the .Net Framework 2 installed and to add the Microsoft Framework to your path statement

Boo is a lightweight .Net language.

Here is a sample that gets a task written in Boo for msbuild:

=== MyTask.boo ===

import Microsoft.Build.Framework
import Microsoft.Build.Utilities
import Boo.Lang

class MyTask(Task):
public override def Execute():
Log.LogMessage(MyProperty)
return true

private _MyProperty as string

MyProperty as string:
get:
return _MyProperty
set:
_MyProperty = value

=== Test.proj ===

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
DefaultTargets="MyTarget"
InitialTargets="BuildMyTask"
>

<Target Name="BuildMyTask">
<Exec command="booc MyTask.boo -t:library"/>
</Target>

<UsingTask TaskName="MyTask" AssemblyFile="MyTask.dll"/>

<Target Name="MyTarget">
<MyTask MyProperty="Hello!"/>
</Target>
</Project>

===

You also need Boo installed (and on your path).
Copy Boo.Lang into the directory that you created these scripts in.

At the command line type: msbuild
This will build and run the minimal boo task.
I am planning to add a real msbuild task for boo.