anchor.diff:                    lists:dropwhile(fun(C) -> lists:member(C, [$ , $\n]) end, S)
                 end,
     lists:reverse(StripLeft(lists:reverse(StripLeft(Str)))).
  -
  -strip_test_() ->
  -  [ ?_assertEqual(""       , strip(""))
  -  , ?_assertEqual("foo"    , strip("foo"))
  -  , ?_assertEqual("foo"    , strip("\n    \n  \nfoo"))
  -  , ?_assertEqual("foo"    , strip("    \n\n  \nfoo   \n \n  "))
  -  , ?_assertEqual("foo bar", strip("  \n  \n  \nfoo bar \n \n"))
  -  ].
   
   option_parse(Str) ->
     {Options, Desc} = partition(strip(Str), "  "),
  
positive.code: count(X, Patterns) ->
    length([P || P <- Patterns, X == P]).
  
  fix_list_arguments_test_() ->
    Fix = fun fix_list_arguments/1,
    [ ?_assertEqual(opt("-a"), Fix(opt("-a")))
    , ?_assertEqual(arg("N", undefined), Fix(arg("N", undefined)))
    , ?_assertEqual(req([arg("N", []), arg("N", [])]),
                    Fix(req([arg("N"), arg("N")])))
    , ?_assertEqual(either([arg("N", []), one_or_more([arg("N", [])])]),
                    Fix(either([arg("N"), one_or_more([arg("N")])])))
    ].
  
  do_fix_list_arguments(Pat, FixThese) ->
    case children(Pat) of
      undefined ->
  
negative.code:   ?assertEqual([2,3,a], replace(1, a, [2,3])),
    ?assertEqual([1,b,3], replace(2, b, [1,2,3])).
  
  single_match(Pat, Rest) ->
    case lists:filter(match_fun(Pat), Rest) of
      []        -> nomatch;
  