Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang-getopt
getopt-1.0.1-git.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File getopt-1.0.1-git.patch of Package erlang-getopt
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a485625 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/_build diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a953aae --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: erlang + +otp_release: + - R13B04 + - R14B04 + - R15B03 + - R16B03 + - 17.5 + - 18.3 + - 19.3 + - 20.0 diff --git a/README.md b/README.md index dd5f5b6..377fcf8 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ The `parse/2` function receives a list of tuples with the command line option specifications. The type specification for the tuple is: ```erlang --type arg_type() :: 'atom' | 'binary' | 'boolean' | 'float' | 'integer' | 'string'. +-type arg_type() :: 'atom' | 'binary' | 'utf8_binary' | 'boolean' | 'float' | 'integer' | 'string'. -type arg_value() :: atom() | binary() | boolean() | float() | integer() | string(). @@ -244,7 +244,8 @@ A long option can have the following syntax: Argument Types -------------- -The arguments allowed for options are: *atom*; *binary*; *boolean*; *float*; *integer*; *string*. +The arguments allowed for options are: *atom*; *binary*; *utf8_binary*; *boolean*; +*float*; *integer*; *string*. The `getopt` module checks every argument to see if it can be converted to its correct type. @@ -256,6 +257,17 @@ Numeric arguments can only be negative when passed as part of an assignment expr e.g. `--increment=-100` is a valid expression; whereas `--increment -100` is invalid +Arguments of `utf8_binary` type allow proper binary encoding of arguments containing +code points greater than 255. The resulting value is a normalized UTF-8 binary. + +As of Erlang/20, `standard_error` device has `unicode` option set to `false`. +It prevents correct printing of usage for arguments containing unicode +binaries/strings as default values. To fix this, one needs to enable unicode: + +```erlang +io:setopts(standard_error, [{unicode, true}]). +``` + Implicit Arguments ------------------ diff --git a/src/getopt.erl b/src/getopt.erl index b5ee7b4..8e9ea1b 100644 --- a/src/getopt.erl +++ b/src/getopt.erl @@ -13,7 +13,7 @@ -export([parse/2, check/2, parse_and_check/2, format_error/2, usage/2, usage/3, usage/4, usage/6, tokenize/1]). --export([usage_cmd_line/2]). +-export([usage_cmd_line/2, usage_options/1]). -define(LINE_LENGTH, 75). -define(MIN_USAGE_COMMAND_LINE_OPTION_LENGTH, 25). @@ -30,7 +30,7 @@ (Char) =:= $\n orelse (Char) =:= $\r)). %% Atom indicating the data type that an argument can be converted to. --type arg_type() :: 'atom' | 'binary' | 'boolean' | 'float' | 'integer' | 'string'. +-type arg_type() :: 'atom' | 'binary' | 'utf8_binary' | 'boolean' | 'float' | 'integer' | 'string'. %% Data type that an argument can be converted to. -type arg_value() :: atom() | binary() | boolean() | float() | integer() | string(). %% Argument specification. @@ -149,12 +149,7 @@ parse(OptSpecList, OptAcc, ArgAcc, _ArgPos, []) -> format_error(OptSpecList, {error, Reason}) -> format_error(OptSpecList, Reason); format_error(OptSpecList, {missing_required_option, Name}) -> - OptStr = case lists:keyfind(Name, 1, OptSpecList) of - {Name, undefined, undefined, _Type, _Help} -> ["<", to_string(Name), ">"]; - {_Name, undefined, Long, _Type, _Help} -> ["--", Long]; - {_Name, Short, undefined, _Type, _Help} -> ["-", Short]; - {_Name, Short, Long, _Type, _Help} -> ["-", Short, " (", Long, ")"] - end, + OptStr = opt_to_list(lists:keyfind(Name, 1, OptSpecList)), lists:flatten(["missing required option: ", OptStr]); format_error(_OptSpecList, {invalid_option, OptStr}) -> lists:flatten(["invalid option: ", to_string(OptStr)]); @@ -162,9 +157,21 @@ format_error(_OptSpecList, {invalid_option_arg, {Name, Arg}}) -> lists:flatten(["option \'", to_string(Name) ++ "\' has invalid argument: ", to_string(Arg)]); format_error(_OptSpecList, {invalid_option_arg, OptStr}) -> lists:flatten(["invalid option argument: ", to_string(OptStr)]); +format_error(OptSpecList, {missing_option_arg, Name}) -> + OptStr = opt_to_list(lists:keyfind(Name, 1, OptSpecList)), + lists:flatten(["missing option argument: ", OptStr, " <", to_string(Name), $>]); format_error(_OptSpecList, {Reason, Data}) -> lists:flatten([to_string(Reason), " ", to_string(Data)]). +opt_to_list({Name, undefined, undefined, _Type, _Help}) -> + [$<, to_string(Name), $>]; +opt_to_list({_Name, undefined, Long, _Type, _Help}) -> + [$-, $-, Long]; +opt_to_list({_Name, Short, undefined, _Type, _Help}) -> + [$-, Short]; +opt_to_list({_Name, Short, Long, _Type, _Help}) -> + [$-, Short, $\s, $(, Long, $)]. + %% @doc Parse a long option, add it to the option accumulator and continue %% parsing the rest of the arguments recursively. @@ -435,6 +442,8 @@ to_type({Type, _DefaultArg}, Arg) -> to_type(Type, Arg); to_type(binary, Arg) -> list_to_binary(Arg); +to_type(utf8_binary, Arg) -> + unicode:characters_to_binary(Arg); to_type(atom, Arg) -> list_to_atom(Arg); to_type(integer, Arg) -> @@ -730,8 +739,8 @@ usage_option_text({_Name, Short, Long, _ArgSpec, _Help}) -> -spec usage_help_text(option_spec()) -> string(). -usage_help_text({_Name, _Short, _Long, {_ArgType, ArgValue}, [_ | _] = Help}) -> - Help ++ " [default: " ++ default_arg_value_to_string(ArgValue) ++ "]"; +usage_help_text({_Name, _Short, _Long, {ArgType, ArgValue}, [_ | _] = Help}) -> + Help ++ " [default: " ++ default_arg_value_to_string(ArgType, ArgValue) ++ "]"; usage_help_text({_Name, _Short, _Long, _ArgSpec, Help}) -> Help. @@ -804,15 +813,17 @@ wrap_text_line(_Length, [], Acc, _Count, _CurrentLineAcc) -> lists:reverse(Acc). -default_arg_value_to_string(Value) when is_atom(Value) -> +default_arg_value_to_string(_, Value) when is_atom(Value) -> atom_to_list(Value); -default_arg_value_to_string(Value) when is_binary(Value) -> +default_arg_value_to_string(binary, Value) when is_binary(Value) -> binary_to_list(Value); -default_arg_value_to_string(Value) when is_integer(Value) -> +default_arg_value_to_string(utf8_binary, Value) when is_binary(Value) -> + unicode:characters_to_list(Value); +default_arg_value_to_string(_, Value) when is_integer(Value) -> integer_to_list(Value); -default_arg_value_to_string(Value) when is_float(Value) -> +default_arg_value_to_string(_, Value) when is_float(Value) -> lists:flatten(io_lib:format("~w", [Value])); -default_arg_value_to_string(Value) -> +default_arg_value_to_string(_, Value) -> Value. diff --git a/test/getopt_test.erl b/test/getopt_test.erl index 7ec0f35..4c7108f 100644 --- a/test/getopt_test.erl +++ b/test/getopt_test.erl @@ -298,6 +298,19 @@ check_test_() -> ?_assertEqual({error, {missing_required_option, arg}}, check(OptSpecList, Opts))}, {"Parse arguments and check required options", ?_assertEqual({error, {missing_required_option, arg}}, parse_and_check(OptSpecList, ""))}, + {"Parse arguments and check required option args", + ?_assertEqual({error, {missing_option_arg, arg}}, + parse_and_check(OptSpecList, "-a"))}]. + +format_error_test_() -> + OptSpecList = + [ + { arg, $a, "arg", string, "Required arg"}, + { short, $s, undefined, string, "short option"}, + { long, undefined, "long", string, "long option"}, + { other, undefined, undefined, string, "task"} + ], + [ {"Format missing option error test 1", ?_assertEqual("missing required option: -a (arg)", format_error(OptSpecList, {error, {missing_required_option, arg}}))}, @@ -321,5 +334,34 @@ check_test_() -> format_error(OptSpecList, {error, {invalid_option_arg, "arg_value"}}))}, {"Format invalid option argument error test 2", ?_assertEqual("option 'verbose' has invalid argument: 100", - format_error(OptSpecList, {error, {invalid_option_arg, {verbose, "100"}}}))} + format_error(OptSpecList, {error, {invalid_option_arg, {verbose, "100"}}}))}, + {"Format missing option argument error test 1", + ?_assertEqual("missing option argument: -a (arg) <arg>", + format_error(OptSpecList, {error, {missing_option_arg, arg}}))}, + {"Format missing option argument error test 2", + ?_assertEqual("missing option argument: -a (arg) <arg>", + format_error(OptSpecList, {missing_option_arg, arg}))}, + {"Format missing option argument error test 3", + ?_assertEqual("missing option argument: -s <short>", + format_error(OptSpecList, {missing_option_arg, short}))}, + {"Format missing option argument error test 4", + ?_assertEqual("missing option argument: --long <long>", + format_error(OptSpecList, {missing_option_arg, long}))}, + {"Format missing option argument error test 5", + ?_assertError(_, format_error(OptSpecList, {missing_option_arg, unknown}))} ]. + +utf8_binary_test_() -> + OptSpecList = [{utf8, undefined, "utf8", utf8_binary, "UTF-8 arg"}], + Unicode = [228, 220, 223, 1455], + Utf8 = unicode:characters_to_binary(Unicode), + io:setopts(standard_error, [{encoding, utf8}]), + OptSpecsWithDefault = [{utf8, undefined, "utf8", {utf8_binary, Utf8}, "UTF-8 arg"}], + [{"Empty utf8_binary argument", + ?_assertEqual({ok, {[{utf8, <<>>}], []}}, parse(OptSpecList, ["--utf8", ""]))}, + {"Non empty utf8_binary argument", + ?_assertEqual({ok, {[{utf8, Utf8}], []}}, parse(OptSpecList, ["--utf8", Unicode]))}, + {"Default utf8_binary argument", + ?_assertEqual({ok, {[{utf8, Utf8}], []}}, parse(OptSpecsWithDefault, []))}, + {"Default utf8_binary argument usage", + ?_assert(is_list(string:find(getopt:usage_options(OptSpecsWithDefault), Unicode)))}].
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor