October 31, 2009

A Truly Modal UIAlertView

I don't know why it took me so long to realize this, but UIAlertViews are not modal. Yes, they are modal as far as the UI is concerned, but your code continues running after you call the show method.
I discovered this while making a callback in my TableFormEditor package. In the callback, the form is asking the delegate "is it ok to save this data?". My delegate takes a quick look, sees something wrong, and fires up a UIAlertView to get the users input if it is ok or not. However, the [alert show] call came back immediately and the form was given a bogus answer, while the dialog was still waiting for user input. Dang.
After a bit of research, it seems that Mac UI frameworks do not embrace the concept of pure modal dialogs. I've read both sides of the argument, but it really shouldn't be an argument at all. You *should* design your code to not rely on modal behavior and instead make use of the delegate concept, but you *should* also have the ability to do modal if your code warrants it.
Sure, I could rewrite my code to move the logic from the location it belongs over to the delegate, but this creates an unmaintainable mess in my code. This is one case where a modal would really keep things neat and tidy. To address this in a general way, I created a wrapper class around UIAlertView that shows a modal dialog. The class is called JESAlert. The show method will not return until the user selects a button, and it will return the selected button index.
- (int) show;
To simplify things, this class does not allow a delegate, so the init method is similar to the original UIAlertView init but without the delegate parameter.
- (id) initWithTitle:(NSString*) title
             message:(NSString*) message
   cancelButtonTitle:(NSString*) cancelButtonTitle
   otherButtonTitles:(NSString*) otherButtonTitles, ...;

Simply call this init, then call the show method. What it returns is the selected button index.
I also enhanced the UIAlertView interface to allow for an array of otherButtonTitles, instead of just the varargs that is currently supported. I needed this feature once upon a time, so I added it.
- (id) initWithTitle:(NSString*) title
             message:(NSString*) message
   cancelButtonTitle:(NSString*) cancelButtonTitle
otherButtonTitleArray:(NSArray*) otherButtonTitles;
And lastly, since I am on a JESON kick, I have created a JESON-aware interface. You can define your UIAlertView properties in a JESON file and deploy that as a resource with your application. This removes the typical static text settings from your code and moves it into a JESON file.
To use it this way, simply use the plain init method (or combine alloc and init with a new), and call the showWithJeson: method. The filename is expected to be a resource bundle stored in your application. This will also return the button index.
JESAlert* alert = [JESAlert new];
int button = [alert showWithFile:@"alert.jes"];
The JESON file contents look like this:
alert {
    title = "Your alert title" 
    message = "More details of your message" 
    cancelButtonTitle = "cancel button title or null"
    otherButtonTitles = ["button 1", "button 2"]
}

The JESON portion of JESAlert is a bit more feature rich than the init approach. You can also run the normal, non-modal version of UIAlertView, but build the properties in a JESON file. Just add the modal = false property. You can also specify a delegate by setting the delegate property.
For example, the old-fashioned way:
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"An error"
  message:@"Something really bad happened"
  delegate:self
cancelButtonTitle:@"Stop doing it"
otherButtonTitles:@"try again", @"try harder", nil];

[alert show];
And here is how it could be set up in a JESON file:
alert {
    title = "An error" 
    message = "Something really bad happened" 
    cancelButtonTitle = "Stop doing it"
    otherButtonTitles = ["try again", "try harder"]
    delegate = self
    modal = false
}
And accessed in the code like this:
JESAlert* alert = [JESAlert new];
alert.jesonContext = self;
[alert showWithFile:@"jeson_alert.jes"];
The jesonContext property is needed to handle variable references in your JESON text, like the "self" used above on the delegate property.
The JESON support can be easily disabled if you are not so inclined, as it requires the JESON library available here. To disable JESON support, simply comment out the define at the top of the JESAlert.h file.
//#define USE_JESON
I have not yet taken the time to create an Xcode project for this, so for now I offer this class as a .h/.m pair of files. The code is available on the Osmorphis group: JESAlert-1.0.zip.

October 13, 2009

Variable References in JESON

JESON
This is a continuation of my series on JESON, an enhanced replacement for JSON. The previous articles were:
  1. An introduction to JESON
  2. A quick overview of where to get JESON and how to use it
In this part I describe an additional enhancement to JESON. I have been developing and redefining JESON as I go along, so a few things have changed and will continue to change as this specification evolves. These changes, of course, drift farther and farther away from the original JSON syntax, but all for the better. The following enhancement is variable support in values. In JSON and JESON, you can assign constant values to keys:
x = 23
y = 'hello'
z = [1, 2, 3]

and so on. But now in JESON, you can assign a variable to a key. This is done by simply giving the name of the variable:
x = 23
y = x
This will assign 23 to y. You can also use variable references in array elements:
x = 23
y = x
z = [x, y]
Basically, anywhere a value is allowed (in dictionary key assignments and elements of an array), a variable reference can be used.

Valid key/variable names

In order for this to work, your variables and dictionary keys cannot look like a constant, meaning:
  • names cannot be true or false or null or start with a number
  • names cannot have spaces in them
Variable/key names can be alpha-numerics (a-z, A-Z, 0-9), but can also include "." and "_". The need for "." will be apparent later. Note that the old JSON key name rules can still be applied, like putting spaces or weird character in key names. But if you do, you cannot reference that key in a value. For example, you can still do the first line, but there is no way to do the second line:
"my key" = true
x = my key // syntax error

Name scoping

Variables have scope, just like in any programming language. Each nested dictionary forms a context. When trying to resolve a variable, JESON will search upwards through the nested dictionaries. In the following example, x will be assigned 72 because that is the nearest scope for y:
outer {
    y = 23
    inner {
        y = 72
        x = y
    }
}
If you comment out the inner y, then x is assigned 23. JESON will continue up the nested contexts until it finds it. If it doesn't, it uses null for the value.

Exposing Host Scope

Scope is not limited to the JESON file itself; context searches can spill out into your host application. In the above example, if there are no y's at any level, then JESON can ask the host application for the variable. To support this, the host application needs to set the hostContext property on the JESON parser object. The value to this property is an object that supports Key-Value coding. You could use self, or even construct a context via JESON, as in this example:

// create a parser object
JESON* parser = [JESON new];

// create a dictionary 
id context = [parser parseString:@"y='hello'"];

// set that dictionary as our external context
parser.hostContext = context;

// and parse something that references a variable
id root = [parser parseString:@"x = y"];
This code will assign to root a dictionary with the key "x" set to the value "hello". The extension to the NSString class has also been extended to support this:
NSString* jeson = @"x = y";
id root = [jeson parseAsJESON:jeson usingContext:context];

The beauty of this is a host application can provide himself as the context, and then the JESON has access to all its properties.
// set some properties
self.myProperty = somevalue;
self.anotherProperty = anothervalue;

// parse some JESON
parser.hostContext = self;
id root = [parser parseString:@"x = myProperty, y = anotherProperty"];
As a practical application of this technique, I am using the new TableFormEditor which can have the form described in JESON. I want to edit a form that can have a title that varies depending on the situation. The host application determines the title and puts it in a property for the JESON to reference:
if(editing) {
    self.formTitle = @"Edit data";
} else {
    self.formTitle = @"Add data";
}



id root = [parser parseString:myJESON];
And the JESON text could have something like this:
showLabels = true
title = formTitle

Variable Paths

To be consistent with Key/Value Coding, the variable name can also be a path in order to traverse nested contexts and to dig into dictionaries:
globals {
    y = "Hi"
}

outer {
    y = 23
    inner {
        y = 72
        x = globals.y
    }
}
Instead of using one of the "local" y values, we pull y out of a different dictionary. You can use this syntax to dive into any dictionary:
stats {
    records {
        years {
            y2008 {
                july { income = 5, expenses = 3 }
                august {
                    income = 4
                    // expenses are the same as in July
                    expenses = july.expenses
                }
            }
        }
    }
}

income = stats.records.years.y2008.august.income

Note that the path is relative to where the reference is. JESON will still search up through the nested contexts, but instead of looking for a single key, it is looking for a path. This variable "path" is also supported when accessing host application data.
There is one caveat to what is supported, due to the way the nested dictionaries are parsed. You cannot reference a dictionary by name if you are a descendent of it. For example, the key "expenses" above could not reference "y2008.july.expenses" because expenses is a grandchild of y2008. This limitation is because the y2008 dictionary has not been created fully yet, as it is recursively getting built. In most cases, this is not a problem, as the contexts are searched upwards through the ancestors, so there is little reason to name your ancestor. Many people don't realize that key/value coding also works with arrays. But the key is not applied directly to the array. Instead it is applied to every element in the array and returns an array of those results. For example:
fields [
    { id = 1 }
    { id = 2 }
    { id = 55 }
]

ids = fields.id
// ids => [1, 2, 55]
An updated JESON parser has been made available with the features described here. Get it off the Osmorphis group: jeson.zip.

October 8, 2009

kaLua

For years I have been searching for the "perfect" scripting language. I started with Unix shells and Tcl, migrated to Python, toyed with Javascript and Groovy, and lately I have ventured into the world of Lua. To me Javascript is one of the more elegant syntaxes. It is fairly simple with a good balance of words vs. puctuation. However, Javascript is designed for web pages and the various runtimes that are available are rather large and cumbersome. Lua's size is extremely attractive, and I like Lua's simple syntax and no-nonsense approach.
But I felt the language is too wordy. This is one of the turnoffs Ruby has as well. There is a good balance that can be reached between wordy, verbose languages (like Objective-C) and terse, cryptic languages (like Unix shell). I am constantly looking for that balance. Python is close, but I really dislike the "blocking via indent", even after programming in it for years; it never found a place in my heart.
So what's wrong with Lua? Not much, really, as long as you're not looking for a true OO language. But it's not perfect. For starters, Lua denotes blocks via do/end, function/end, and if/then/end keywords. To me, this makes the code too wordy. The density of words over punctuation is too great. I wanted to shift that balance, plus make the syntax a little closer to existing languages. There are some other constructs in Lua that strike me as odd or "old-fashioned". For example, the [[/]] pair to create multiline strings. I find the Python/Groovy approach of using triple quotes (""" or ''') much more appealing.
So I looked at the Lua parser code and it seemed simple enough. I started tweaking and adding things. Before I knew it, I had changed a great deal of the syntax.
Once I realized I had a new language on my hands, I needed a name. I have come up with "kaLua", which could stand for "Kick Ass" Lua, but it really is just the best I could come up with and still retain the "Lua". I'm all for changing this name. One alternative that stands out is Superscript.
kaLua is a derivative of Lua and is still very much Lua-like. It would be nice if it did not change existing syntax and merely added to it, but some things had to change. I'll describe these incompatible changes below. This document summarizes those changes made to Lua to create the kaLua almost-superset. Mind you, these changes come from a syntax snob, and many will dislike these changes. Syntax is a matter of taste; this is my taste. If it's not yours, then move along. I won't be offended.

Function Blocking

Functions can be declared like this in Lua:
function hello() print('hello world') end
and they can be declared anonymously (inline) like this:
if something then return function () print('hi') end end
kaLua adds curly brace blocking to function definitions. The above two could be written as:
function hello() { print('hello world') }
and
if something { return function () { print('hi') } }
It does not matter what line the {} characters are on; Lua is fairly insensitive to line breaks as opposed to some scripting languages.

If/then/elseif/else Blocking

Blocking for the if/... set of statements is a bit more complex, mainly because the current Lua syntax is somewhat inconsistent. You can have numerous "then" portions but only one "end":
if something then do_something() elseif something_else then do_another_thing() elseif something_else_yet then do_that_again() else last_ditch_effort() end
The blocks for each condition are separate contexts. To make this cleaner and clearer, kaLua adds support for braces and removes the useless "then" keyword:
if something { do_something() } elseif something_else { do_another_thing() } elseif something_else_yet { do_that_again() } else { last_ditch_effort() }
The braces do not have to appear on the same line or on a different line. Although you can continue to use the old style blocking, you have to be consistent within one if compound statement. In other words, you can't use braces in the if block and use the old style blocking in the else portion.

While Blocking

The while loop blocks via a do/end pair:
while something_is_true do something() end
kaLua adds an addition to support braces:
while something_is_true { something() }

Repeat/Until Blocking

Lua creates yet another form of blocking with the repeat/until pair:
x = 3 repeat print('repeat') x = x - 1 until x == 0
kaLua simply adds braces to form the block for consistency. The block creates a new context, and the condition in the until clause does have visibility to that context, even though it is physically outside the block.
x = 3 repeat { print('repeat') x = x - 1 } until x == 0

Standalone Blocks

Lua uses do/end blocks to create a nested context:
x = 'hello' do local x = 23 end
kaLua replaces the do/end pair with {}:
x = 'hello' { local x = 23 }

Function Calls

Lua supports 3 different syntaxes for making function calls:
x = callme("23") x = callme{f="23"} x = callme"23"
Of these, only the first one makes sense. The other two muddle up the language syntax and offer little advantage. I guess they are syntactic sugar, but they don't seem very "sweet" to me. The second two examples above are no longer supported. Only the following is allowed:
x = callme("23")
Because of the additional support for braces in the syntax, the second one conflicts with the updated grammar. The third function call form is just loopy; I hope no one really uses that.
If you need to pass a table as an argument, surround with parens like you would expect. In other words, function calls always involve parens. To me this is consistent and clean:
x = callme({f="23"})

Multiline Strings

Lua supports multiline strings with the [[/]] pair, and also supports nested multiline strings with [=[/]=], [==[/]==], etc pairs:
print([[this is a multiline string]]) print([=[ this is a [==[nested string]==] so there you have it]=])
The use of [[/]] is pretty ugly and uses the bracket characters where they would be best used for indexing. kaLua changes the multiline string to use the triple quote concept from Python and other languages:
print("""this is a multiline string""") print('''this is also a multi- line string''')
kaLua gets rid of the nested string format altogether. Its value is very dubious and it is extremely ugly. For an embedded language that prides itself on simplicity, this feature seems unnecessary.

Comments

Lua uses the -- characters to denote a single line comment, and --[[/]] for multiline comments:
-- this is a comment --[[ print("this code is commented out") ]]
kaLua changes these to more common comment sequences:
// this is a comment /* print("this code is commented out") */

Operators

Lua uses ~= for "not equals". kaLua adds a more common operator sequence !=

Summary

That sums up the additions and changes made to the Lua syntax. I have these changes implemented in a version of the library. I really haven't used it much and the code needs some more tweaking. I would like to make kaLua be a true superset of Lua and put back some of the things I removed. The only thing kaLua cannot support is the function call syntax that uses curly braces instead of parens. This is one feature of Lua that won't survive in kaLua.
There are a few other quirks of Lua I don't like, but will require a lot more thought and code mangling. The biggest offender to me is the "method call" syntax:
object:method(parms)
It's really not that bad, but I find it a little hokey. How else to do it? No idea. This is still better than:
object.method(object, parms)
It would be preferable that I can call it with a dot instead of the colon and have it just figure it out, and pass object as the self parameter:
object.method(parms)
If anyone is interested in getting a copy of kaLua, let me know via a comment or an email. If there is enough demand (which I don't expect), then I can post the code.