summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2015-02-11 14:31:15 -0500
committerFred Hebert <mononcqc@ferd.ca>2015-02-11 14:31:15 -0500
commit2fd6f43c020555435c758ffe84ffe56a632387d8 (patch)
treef55f6b642913bc00750288da1bf49efa7f1e41d9
parent7298c9f77483dd3e9f35b7a8fe3dcfd04d3a2b5e (diff)
parentc79d13f5e854ff84b4fe61a45ce666ee1c8479da (diff)
Merge pull request #138 from talentdeficit/args_to_tasks
factor out task/args parsing from `do` for use in other meta commands
-rw-r--r--src/rebar_prv_do.erl8
-rw-r--r--src/rebar_utils.erl55
-rw-r--r--test/rebar_utils_SUITE.erl120
3 files changed, 176 insertions, 7 deletions
diff --git a/src/rebar_prv_do.erl b/src/rebar_prv_do.erl
index 5dec7d8..83e57a1 100644
--- a/src/rebar_prv_do.erl
+++ b/src/rebar_prv_do.erl
@@ -32,13 +32,12 @@ init(State) ->
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->
- Tasks = args_to_tasks(rebar_state:command_args(State)),
+ Tasks = rebar_utils:args_to_tasks(rebar_state:command_args(State)),
do_tasks(Tasks, State).
do_tasks([], State) ->
{ok, State};
-do_tasks([TaskArgs | Tail], State) ->
- [TaskStr | Args] = string:tokens(TaskArgs, " "),
+do_tasks([{TaskStr, Args}|Tail], State) ->
Task = list_to_atom(TaskStr),
State1 = rebar_state:set(State, task, Task),
State2 = rebar_state:command_args(State1, Args),
@@ -52,6 +51,3 @@ do_tasks([TaskArgs | Tail], State) ->
-spec format_error(any()) -> iolist().
format_error(Reason) ->
io_lib:format("~p", [Reason]).
-
-args_to_tasks(Args) ->
- [string:strip(T) || T <- string:tokens(string:join(Args, " "), ",")].
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index d899dc5..85f59d6 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -47,7 +47,8 @@
deprecated/4,
erl_opts/1,
indent/1,
- cleanup_code_path/1]).
+ cleanup_code_path/1,
+ args_to_tasks/1]).
%% for internal use only
-export([otp_release/0]).
@@ -218,6 +219,12 @@ erl_opts(Config) ->
[debug_info|Opts]
end.
+%% for use by `do` task
+
+%% note: this does not handle the case where you have an argument that
+%% was enclosed in quotes and might have commas but should not be split.
+args_to_tasks(Args) -> new_task(Args, []).
+
%% ====================================================================
%% Internal functions
%% ====================================================================
@@ -467,3 +474,49 @@ cleanup_code_path(OrigPath) ->
_ ->
code:set_path(OrigPath)
end.
+
+new_task([], Acc) -> lists:reverse(Acc);
+new_task([TaskList|Rest], Acc) ->
+ case re:split(TaskList, ",", [{return, list}, {parts, 2}]) of
+ %% `do` consumes all remaining args
+ ["do" = Task|RestArgs] ->
+ lists:reverse([{Task, RestArgs ++ Rest}|Acc]);
+ %% single task terminated by a comma
+ [Task, ""] -> new_task(Rest, [{Task, []}|Acc]);
+ %% sequence of two or more tasks
+ [Task, More] -> new_task([More|Rest], [{Task, []}|Acc]);
+ %% single task not terminated by a comma
+ [Task] -> arg_or_flag(Rest, [{Task, []}|Acc])
+ end.
+
+arg_or_flag([], [{Task, Args}|Acc]) ->
+ lists:reverse([{Task, lists:reverse(Args)}|Acc]);
+%% case where you have `foo , bar`
+arg_or_flag([","|Rest], Acc) -> new_task(Rest, Acc);
+%% case where you have `foo ,bar`
+arg_or_flag(["," ++ Task|Rest], Acc) -> new_task([Task|Rest], Acc);
+%% a flag
+arg_or_flag(["-" ++ _ = Flag|Rest], [{Task, Args}|Acc]) ->
+ case maybe_ends_in_comma(Flag) of
+ false -> arg_or_flag(Rest, [{Task, [Flag|Args]}|Acc]);
+ NewFlag -> new_task(Rest, [{Task,
+ lists:reverse([NewFlag|Args])}|Acc])
+ end;
+%% an argument or a sequence of arguments
+arg_or_flag([ArgList|Rest], [{Task, Args}|Acc]) ->
+ case re:split(ArgList, ",", [{return, list}, {parts, 2}]) of
+ %% single arg terminated by a comma
+ [Arg, ""] -> new_task(Rest, [{Task,
+ lists:reverse([Arg|Args])}|Acc]);
+ %% sequence of two or more args/tasks
+ [Arg, More] -> new_task([More|Rest], [{Task,
+ lists:reverse([Arg|Args])}|Acc]);
+ %% single arg not terminated by a comma
+ [Arg] -> arg_or_flag(Rest, [{Task, [Arg|Args]}|Acc])
+ end.
+
+maybe_ends_in_comma(H) ->
+ case lists:reverse(H) of
+ "," ++ Flag -> lists:reverse(Flag);
+ _ -> false
+ end.
diff --git a/test/rebar_utils_SUITE.erl b/test/rebar_utils_SUITE.erl
new file mode 100644
index 0000000..e9b32e2
--- /dev/null
+++ b/test/rebar_utils_SUITE.erl
@@ -0,0 +1,120 @@
+-module(rebar_utils_SUITE).
+
+-export([all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+ empty_arglist/1,
+ single_task/1,
+ single_task_with_immediate_comma/1,
+ single_task_with_trailing_comma/1,
+ multiple_task/1,
+ multiple_task_no_spaces/1,
+ multiple_task_with_immediate_comma/1,
+ multiple_task_with_trailing_comma/1,
+ task_with_arg/1,
+ task_with_arg_with_immediate_comma/1,
+ task_with_arg_with_trailing_comma/1,
+ task_with_multiple_args/1,
+ task_with_flag/1,
+ task_with_flag_with_immediate_comma/1,
+ task_with_flag_with_trailing_comma/1,
+ task_with_flag_with_commas/1,
+ task_with_multiple_flags/1,
+ special_task_do/1]).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("eunit/include/eunit.hrl").
+-include_lib("kernel/include/file.hrl").
+
+
+all() ->
+ [{group, args_to_tasks}].
+
+groups() ->
+ [{args_to_tasks, [], [empty_arglist,
+ single_task,
+ single_task_with_immediate_comma,
+ single_task_with_trailing_comma,
+ multiple_task,
+ multiple_task_no_spaces,
+ multiple_task_with_immediate_comma,
+ multiple_task_with_trailing_comma,
+ task_with_arg,
+ task_with_arg_with_immediate_comma,
+ task_with_arg_with_trailing_comma,
+ task_with_multiple_args,
+ task_with_flag,
+ task_with_flag_with_immediate_comma,
+ task_with_flag_with_trailing_comma,
+ task_with_flag_with_commas,
+ task_with_multiple_flags,
+ special_task_do]}].
+
+init_per_group(_, Config) -> Config.
+end_per_group(_, Config) -> Config.
+
+empty_arglist(_Config) ->
+ [] = rebar_utils:args_to_tasks([]).
+
+single_task(_Config) ->
+ [{"foo", []}] = rebar_utils:args_to_tasks(["foo"]).
+
+single_task_with_immediate_comma(_Config) ->
+ [{"foo", []}] = rebar_utils:args_to_tasks(["foo,"]).
+
+single_task_with_trailing_comma(_Config) ->
+ [{"foo", []}] = rebar_utils:args_to_tasks(["foo", ","]).
+
+multiple_task(_Config) ->
+ [{"foo", []}, {"bar", []}, {"baz", []}] = rebar_utils:args_to_tasks(["foo,",
+ "bar,",
+ "baz"]).
+
+multiple_task_no_spaces(_Config) ->
+ [{"foo", []}, {"bar", []}, {"baz", []}] = rebar_utils:args_to_tasks(["foo,bar,baz"]).
+
+multiple_task_with_immediate_comma(_Config) ->
+ [{"foo", []}, {"bar", []}, {"baz", []}] = rebar_utils:args_to_tasks(["foo,",
+ "bar,",
+ "baz,"]).
+
+multiple_task_with_trailing_comma(_Config) ->
+ [{"foo", []}, {"bar", []}, {"baz", []}] = rebar_utils:args_to_tasks(["foo",
+ ",",
+ "bar",
+ ",",
+ "baz",
+ ","]).
+task_with_arg(_Config) ->
+ [{"foo", ["bar"]}] = rebar_utils:args_to_tasks(["foo", "bar"]).
+
+task_with_arg_with_immediate_comma(_Config) ->
+ [{"foo", ["bar"]}, {"baz", []}] = rebar_utils:args_to_tasks(["foo", "bar,", "baz"]).
+
+task_with_arg_with_trailing_comma(_Config) ->
+ [{"foo", ["bar"]}, {"baz", []}] = rebar_utils:args_to_tasks(["foo", "bar", ",", "baz"]).
+
+task_with_multiple_args(_Config) ->
+ [{"foo", ["bar", "baz"]}] = rebar_utils:args_to_tasks(["foo", "bar", "baz"]).
+
+task_with_flag(_Config) ->
+ [{"foo", ["--bar"]}] = rebar_utils:args_to_tasks(["foo", "--bar"]).
+
+task_with_flag_with_immediate_comma(_Config) ->
+ [{"foo", ["--bar"]}, {"baz", []}] = rebar_utils:args_to_tasks(["foo", "--bar,", "baz"]).
+
+task_with_flag_with_trailing_comma(_Config) ->
+ [{"foo", ["--bar"]}, {"baz", []}] = rebar_utils:args_to_tasks(["foo", "--bar", ",", "baz"]).
+
+task_with_flag_with_commas(_Config) ->
+ [{"foo", ["--bar=baz,qux"]}] = rebar_utils:args_to_tasks(["foo", "--bar=baz,qux"]).
+
+task_with_multiple_flags(_Config) ->
+ [{"foo", ["--bar", "--baz"]}] = rebar_utils:args_to_tasks(["foo", "--bar", "--baz"]).
+
+special_task_do(_Config) ->
+ [{"foo", []}, {"do", ["bar,", "baz"]}] = rebar_utils:args_to_tasks(["foo,",
+ "do",
+ "bar,",
+ "baz"]).