simpler comandline application context/configs

October 21, 2006

A couple of days ago i stumbled upon the SimpleConsole. Really a nice piece of software, pretty close to what i was pondering about already for some time. And just two weeks before i did put up (try: gem install app-ctx) my own take on that. App-ctx shares some of the design decisions of SimpleConsole like

  • ruby classes as controllers
  • automatic method invokation from arguments
  • parameter parsing and conversion

still though, app-ctx has some differences, and tries to be just a little simpler(and add some more). You might use classes, similar to SimpleConsole:


class Simple
def add context
a, b = context.argv
puts "#{a} + #{b} = #{a + b}"
end
end

App::run :class => Simple

Argument type conversions are build in, no declarations: "foo
bar"
becomes a string, 23 a int and 3.14 a Float. Same with options: --int=23 --text="some text here" --float=3.14.

But I did not want to force this inheritance thing upon the humble user so she can use her own baseclasses(SimpleConsole::Controller maybe?). Next, i wanted to support blocks, just being more ruby like:


class Simple
# $ ./examples/run_with_block.rb add 1 5
# 1 + 5 = 6
# $
def add a, b
puts "#{a} + #{b} = #{a + b}"
end

# $ ./examples/run_with_block.rb sub 1 5
# 1 - 5 = 6
# $
def sub a, b
puts "#{a} - #{b} = #{a - b}"
end
end

App::run do |context|
puts context
Simple.new.send(context.argv.shift, *context.argv)
end

The general setup of the comand line i wanted to stay good old unix style: <comand> [options] [arguments...] only. I don't like these: <comand> --foo --bar=1 action --help where there are more options after the last argument.

And than there is the problem with resonable default values. You need configuration and app-ctx defines some clear rules on where to put them. On default, app-ctx pulls a YAML default values file from next to where your application script lives, e.g:

$ ~/bin/my-script.rb

preloads its default values from

~/bin/my-script.yml

Values from the command line then will simply overload setting from your config file and your app can't distinguish from where the values are actually coming. Thisway you can extract default values from your code an put them in a separate file.

But if you prefer to keep things together instead, you may also set defaults directly from the code:


class Simple
def initialize(context)
context.set_default_values({
:desc => "programatically setting default values",
:port => 1234,
})
end

def show context
puts context
end
end

App::run :class => Simple

app-ctx tries calling a c'tor of your class with a context argument and you can set your default values there. Last but not least, you can define from where to load the config file with a command line option:

~/bin/my-script --config=/tmp/bogus-setup-here show

will not load the ~/bin/my-script.rb but the one you supplied.

Thats most of the stuff i could recall right now and if you like it, go ahead use it. In case you do, i might feel challenged to put up some concise online documentation and a little tutorial. 'till then

have fun

share this: