Add support for options with embedded arguments without the '--' prefix.

e.g. "verbose=1"
This commit is contained in:
Juan Jose Comellas 2009-12-30 18:38:42 -03:00
parent 0329f560c4
commit a59893e9b9
2 changed files with 33 additions and 19 deletions

View File

@ -72,20 +72,20 @@ parse(OptSpecList, CmdLine) ->
-spec parse([option_spec()], [option()], [string()], integer(), [string()]) -> -spec parse([option_spec()], [option()], [string()], integer(), [string()]) ->
{ok, {[option()], [string()]}} | {error, {Reason :: atom(), Data:: any()}}. {ok, {[option()], [string()]}} | {error, {Reason :: atom(), Data:: any()}}.
%% Process long options. %% Process long options.
parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [[$-, $- | LongName] = OptStr | Tail]) -> parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [[$-, $- | Name] = OptStr | Tail]) ->
{Option, Tail1} = {Option, Tail1} =
case split_embedded_arg(LongName) of case split_embedded_arg(Name) of
{LongName1, Arg} -> {Name1, Arg} ->
%% Get option that has its argument within the same string %% Get option that has its argument within the same string
%% separated by an equal ('=') character. %% separated by an equal ('=') character.
{get_option_embedded_arg(OptSpecList, OptStr, LongName1, Arg), Tail}; {get_option_embedded_arg(OptSpecList, OptStr, ?OPT_LONG, Name1, Arg), Tail};
_LongName1 -> _Name1 ->
get_option(OptSpecList, OptStr, LongName, ?OPT_LONG, Tail) get_option(OptSpecList, OptStr, ?OPT_LONG, Name, Tail)
end, end,
parse(OptSpecList, [Option | OptAcc], ArgAcc, ArgPos, Tail1); parse(OptSpecList, [Option | OptAcc], ArgAcc, ArgPos, Tail1);
%% Process short options. %% Process short options.
parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [[$-, ShortName] = OptStr | Tail]) -> parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [[$-, ShortName] = OptStr | Tail]) ->
{Option, Tail1} = get_option(OptSpecList, OptStr, ShortName, ?OPT_SHORT, Tail), {Option, Tail1} = get_option(OptSpecList, OptStr, ?OPT_SHORT, ShortName, Tail),
parse(OptSpecList, [Option | OptAcc], ArgAcc, ArgPos, Tail1); parse(OptSpecList, [Option | OptAcc], ArgAcc, ArgPos, Tail1);
%% Process multiple short options with no argument. %% Process multiple short options with no argument.
parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [[$- | ShortNameList] = OptStr | Tail]) -> parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [[$- | ShortNameList] = OptStr | Tail]) ->
@ -96,12 +96,21 @@ parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [[$- | ShortNameList] = OptStr | Tail
end, OptAcc, ShortNameList), end, OptAcc, ShortNameList),
parse(OptSpecList, NewOptAcc, ArgAcc, ArgPos, Tail); parse(OptSpecList, NewOptAcc, ArgAcc, ArgPos, Tail);
%% Process non-option arguments. %% Process non-option arguments.
parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [Arg | Tail]) -> parse(OptSpecList, OptAcc, ArgAcc, ArgPos, [OptStr | Tail]) ->
case split_embedded_arg(OptStr) of
{Name, Arg} ->
%% Get option that has its argument within the same string
%% separated by an equal ('=') character.
parse(OptSpecList, [get_option_embedded_arg(OptSpecList, OptStr, ?OPT_LONG, Name, Arg) | OptAcc],
ArgAcc, ArgPos, Tail);
Arg ->
case find_non_option_arg(OptSpecList, ArgPos) of case find_non_option_arg(OptSpecList, ArgPos) of
{value, OptSpec} when ?IS_OPT_SPEC(OptSpec) -> {value, OptSpec} when ?IS_OPT_SPEC(OptSpec) ->
parse(OptSpecList, [convert_option_arg(OptSpec, Arg) | OptAcc], ArgAcc, ArgPos + 1, Tail); parse(OptSpecList, [convert_option_arg(OptSpec, Arg) | OptAcc],
ArgAcc, ArgPos + 1, Tail);
false -> false ->
parse(OptSpecList, OptAcc, [Arg | ArgAcc], ArgPos, Tail) parse(OptSpecList, OptAcc, [Arg | ArgAcc], ArgPos, Tail)
end
end; end;
parse(OptSpecList, OptAcc, ArgAcc, _ArgPos, []) -> parse(OptSpecList, OptAcc, ArgAcc, _ArgPos, []) ->
%% Once we have completed gathering the options we add the ones that were %% Once we have completed gathering the options we add the ones that were
@ -109,11 +118,11 @@ parse(OptSpecList, OptAcc, ArgAcc, _ArgPos, []) ->
{ok, {lists:reverse(append_default_args(OptSpecList, OptAcc)), lists:reverse(ArgAcc)}}. {ok, {lists:reverse(append_default_args(OptSpecList, OptAcc)), lists:reverse(ArgAcc)}}.
-spec get_option([option_spec()], string(), string() | char(), integer(), [string()]) -> -spec get_option([option_spec()], string(), integer(), string() | char(), [string()]) ->
{option(), [string()]}. {option(), [string()]}.
%% @doc Retrieve the specification corresponding to an option matching a string %% @doc Retrieve the specification corresponding to an option matching a string
%% received on the command line. %% received on the command line.
get_option(OptSpecList, OptStr, OptName, FieldPos, Tail) -> get_option(OptSpecList, OptStr, FieldPos, OptName, Tail) ->
case lists:keysearch(OptName, FieldPos, OptSpecList) of case lists:keysearch(OptName, FieldPos, OptSpecList) of
{value, {Name, _Short, _Long, ArgSpec, _Help} = OptSpec} -> {value, {Name, _Short, _Long, ArgSpec, _Help} = OptSpec} ->
case ArgSpec of case ArgSpec of
@ -132,12 +141,13 @@ get_option(OptSpecList, OptStr, OptName, FieldPos, Tail) ->
end. end.
-spec get_option_embedded_arg([option_spec()], string(), string(), string()) -> option(). -spec get_option_embedded_arg([option_spec()], string(), integer(), string(),
string()) -> option().
%% @doc Retrieve the specification corresponding to an option matching a string %% @doc Retrieve the specification corresponding to an option matching a string
%% received on the command line that had its argument assigned within the %% received on the command line that had its argument assigned within the
%% same string (e.g. "--verbose=true"). %% same string (e.g. "verbose=true").
get_option_embedded_arg(OptSpecList, OptStr, OptName, Arg) -> get_option_embedded_arg(OptSpecList, OptStr, FieldPos, OptName, Arg) ->
case lists:keysearch(OptName, ?OPT_LONG, OptSpecList) of case lists:keysearch(OptName, FieldPos, OptSpecList) of
{value, {_Name, _Short, _Long, ArgSpec, _Help} = OptSpec} -> {value, {_Name, _Short, _Long, ArgSpec, _Help} = OptSpec} ->
case ArgSpec of case ArgSpec of
undefined -> undefined ->

View File

@ -127,10 +127,12 @@ parse_1_test_() ->
{?HELP(Long), ?_assertMatch({ok, {[long], []}}, parse([Long], ["--long"]))}, {?HELP(Long), ?_assertMatch({ok, {[long], []}}, parse([Long], ["--long"]))},
{?HELP(LongArg), ?_assertMatch({ok, {[{long_arg, "value"}], []}}, parse([LongArg], ["--long-arg", "value"]))}, {?HELP(LongArg), ?_assertMatch({ok, {[{long_arg, "value"}], []}}, parse([LongArg], ["--long-arg", "value"]))},
{?HELP(LongArg), ?_assertMatch({ok, {[{long_arg, "value"}], []}}, parse([LongArg], ["--long-arg=value"]))}, {?HELP(LongArg), ?_assertMatch({ok, {[{long_arg, "value"}], []}}, parse([LongArg], ["--long-arg=value"]))},
{?HELP(LongArg), ?_assertMatch({ok, {[{long_arg, "value"}], []}}, parse([LongArg], ["long-arg=value"]))},
{?HELP(LongArg), ?_assertMatch({ok, {[{long_arg, "value=1"}], []}}, parse([LongArg], ["--long-arg=value=1"]))}, {?HELP(LongArg), ?_assertMatch({ok, {[{long_arg, "value=1"}], []}}, parse([LongArg], ["--long-arg=value=1"]))},
{?HELP(LongDefArg), ?_assertMatch({ok, {[{long_def_arg, "default-long"}], []}}, parse([LongDefArg], []))}, {?HELP(LongDefArg), ?_assertMatch({ok, {[{long_def_arg, "default-long"}], []}}, parse([LongDefArg], []))},
{?HELP(LongInt), ?_assertMatch({ok, {[{long_int, 100}], []}}, parse([LongInt], ["--long-int", "100"]))}, {?HELP(LongInt), ?_assertMatch({ok, {[{long_int, 100}], []}}, parse([LongInt], ["--long-int", "100"]))},
{?HELP(LongInt), ?_assertMatch({ok, {[{long_int, 100}], []}}, parse([LongInt], ["--long-int=100"]))}, {?HELP(LongInt), ?_assertMatch({ok, {[{long_int, 100}], []}}, parse([LongInt], ["--long-int=100"]))},
{?HELP(LongInt), ?_assertMatch({ok, {[{long_int, 100}], []}}, parse([LongInt], ["long-int=100"]))},
{"Long form option and arguments", {"Long form option and arguments",
?_assertMatch({ok, {[long], ["arg1", "arg2"]}}, parse([Long], ["--long", "arg1", "arg2"]))}, ?_assertMatch({ok, {[long], ["arg1", "arg2"]}}, parse([Long], ["--long", "arg1", "arg2"]))},
{"Long form option and arguments (unsorted)", {"Long form option and arguments (unsorted)",
@ -141,10 +143,12 @@ parse_1_test_() ->
{?HELP(ShortLongArg), ?_assertEqual({ok, {[{short_long_arg, "value"}], []}}, parse([ShortLongArg], [[$-, ?SHORT(ShortLongArg)], "value"]))}, {?HELP(ShortLongArg), ?_assertEqual({ok, {[{short_long_arg, "value"}], []}}, parse([ShortLongArg], [[$-, ?SHORT(ShortLongArg)], "value"]))},
{?HELP(ShortLongArg), ?_assertMatch({ok, {[{short_long_arg, "value"}], []}}, parse([ShortLongArg], ["--short-long-arg", "value"]))}, {?HELP(ShortLongArg), ?_assertMatch({ok, {[{short_long_arg, "value"}], []}}, parse([ShortLongArg], ["--short-long-arg", "value"]))},
{?HELP(ShortLongArg), ?_assertMatch({ok, {[{short_long_arg, "value"}], []}}, parse([ShortLongArg], ["--short-long-arg=value"]))}, {?HELP(ShortLongArg), ?_assertMatch({ok, {[{short_long_arg, "value"}], []}}, parse([ShortLongArg], ["--short-long-arg=value"]))},
{?HELP(ShortLongArg), ?_assertMatch({ok, {[{short_long_arg, "value"}], []}}, parse([ShortLongArg], ["short-long-arg=value"]))},
{?HELP(ShortLongDefArg), ?_assertMatch({ok, {[{short_long_def_arg, "default-short-long"}], []}}, parse([ShortLongDefArg], []))}, {?HELP(ShortLongDefArg), ?_assertMatch({ok, {[{short_long_def_arg, "default-short-long"}], []}}, parse([ShortLongDefArg], []))},
{?HELP(ShortLongInt), ?_assertEqual({ok, {[{short_long_int, 1234}], []}}, parse([ShortLongInt], [[$-, ?SHORT(ShortLongInt)], "1234"]))}, {?HELP(ShortLongInt), ?_assertEqual({ok, {[{short_long_int, 1234}], []}}, parse([ShortLongInt], [[$-, ?SHORT(ShortLongInt)], "1234"]))},
{?HELP(ShortLongInt), ?_assertMatch({ok, {[{short_long_int, 1234}], []}}, parse([ShortLongInt], ["--short-long-int", "1234"]))}, {?HELP(ShortLongInt), ?_assertMatch({ok, {[{short_long_int, 1234}], []}}, parse([ShortLongInt], ["--short-long-int", "1234"]))},
{?HELP(ShortLongInt), ?_assertMatch({ok, {[{short_long_int, 1234}], []}}, parse([ShortLongInt], ["--short-long-int=1234"]))}, {?HELP(ShortLongInt), ?_assertMatch({ok, {[{short_long_int, 1234}], []}}, parse([ShortLongInt], ["--short-long-int=1234"]))},
{?HELP(ShortLongInt), ?_assertMatch({ok, {[{short_long_int, 1234}], []}}, parse([ShortLongInt], ["short-long-int=1234"]))},
%% Non-option arguments %% Non-option arguments
{?HELP(NonOptArg), ?_assertMatch({ok, {[{non_opt_arg, "value"}], []}}, parse([NonOptArg], ["value"]))}, {?HELP(NonOptArg), ?_assertMatch({ok, {[{non_opt_arg, "value"}], []}}, parse([NonOptArg], ["value"]))},
{?HELP(NonOptInt), ?_assertMatch({ok, {[{non_opt_int, 1234}], []}}, parse([NonOptInt], ["1234"]))}, {?HELP(NonOptInt), ?_assertMatch({ok, {[{non_opt_int, 1234}], []}}, parse([NonOptInt], ["1234"]))},