Correct relative shell command parsing

This also makes some changes to identifier parsing. It replaces the A-z
pattern match with a more specific one that does not implicitly match characters
in between Z and a in the ASCII table. Also adds some necessary explicit
matches for underscores and such. Improves variable and identifier parsing
specs.
Mimic sh(1) when handling unset variables.

If an unset variable is used as an argument, it is dropped from the argument
list.

For example:

    & commit -m $foo
    error: switch `m' requires a value
    ...
    & :set foo "This is a commit"
    & commit -m $foo
    (a commit is created)