Add print and usage APIs for CLI (#2893)

This commit is contained in:
Shawn 2019-09-12 09:35:05 +08:00 committed by GitHub
parent 80621ec9be
commit 59309e6c11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 68 additions and 5 deletions

View File

@ -34,6 +34,19 @@
, lookup_command/1
]).
-export([ print/1
, print/2
, usage/1
, usage/2
]).
%% format/1,2 and format_usage/1,2 are exported mainly for test cases
-export([ format/1
, format/2
, format_usage/1
, format_usage/2
]).
%% gen_server callbacks
-export([ init/1
, handle_call/3
@ -46,6 +59,8 @@
-record(state, {seq = 0}).
-type(cmd() :: atom()).
-type(cmd_descr() :: string()).
-type(cmd_usage() :: {cmd(), cmd_descr()}).
-define(SERVER, ?MODULE).
-define(TAB, emqx_command).
@ -75,7 +90,7 @@ run_command([Cmd | Args]) ->
-spec(run_command(cmd(), [string()]) -> ok | {error, term()}).
run_command(help, []) ->
usage();
help();
run_command(Cmd, Args) when is_atom(Cmd) ->
case lookup_command(Cmd) of
[{Mod, Fun}] ->
@ -87,7 +102,7 @@ run_command(Cmd, Args) when is_atom(Cmd) ->
{error, Reason}
end;
[] ->
usage(), {error, cmd_not_found}
help(), {error, cmd_not_found}
end.
-spec(lookup_command(cmd()) -> [{module(), atom()}]).
@ -97,11 +112,51 @@ lookup_command(Cmd) when is_atom(Cmd) ->
[] -> []
end.
usage() ->
io:format("Usage: ~s~n", [?MODULE]),
[begin io:format("~80..-s~n", [""]), Mod:Cmd(usage) end
help() ->
print("Usage: ~s~n", [?MODULE]),
[begin print("~80..-s~n", [""]), Mod:Cmd(usage) end
|| {_, {Mod, Cmd}, _} <- ets:tab2list(?TAB)].
-spec(print(io:format()) -> ok).
print(Msg) ->
io:format(format(Msg)).
-spec(print(io:format(), [term()]) -> ok).
print(Format, Args) ->
io:format(format(Format, Args)).
-spec(usage([cmd_usage()]) -> ok).
usage(UsageList) ->
io:format(format_usage(UsageList)).
-spec(usage(cmd(), cmd_descr()) -> ok).
usage(Cmd, Desc) ->
io:format(format_usage(Cmd, Desc)).
-spec(format(io:format()) -> string()).
format(Msg) ->
lists:flatten(io_lib:format("~p", [Msg])).
-spec(format(io:format(), [term()]) -> string()).
format(Format, Args) ->
lists:flatten(io_lib:format(Format, Args)).
-spec(format_usage([cmd_usage()]) -> ok).
format_usage(UsageList) ->
lists:map(
fun({Cmd, Desc}) ->
format_usage(Cmd, Desc)
end, UsageList).
-spec(format_usage(cmd(), cmd_descr()) -> string()).
format_usage(Cmd, Desc) ->
CmdLines = split_cmd(Cmd),
DescLines = split_cmd(Desc),
lists:foldl(
fun({CmdStr, DescStr}, Usage) ->
Usage ++ format("~-48s# ~s~n", [CmdStr, DescStr])
end, "", zip_cmd(CmdLines, DescLines)).
%%------------------------------------------------------------------------------
%% gen_server callbacks
%%------------------------------------------------------------------------------
@ -151,3 +206,11 @@ noreply(State) ->
next_seq(State = #state{seq = Seq}) ->
State#state{seq = Seq + 1}.
split_cmd(CmdStr) ->
Lines = string:split(CmdStr, "\n", all),
[L || L <- Lines, L =/= []].
zip_cmd([X | Xs], [Y | Ys]) -> [{X, Y} | zip_cmd(Xs, Ys)];
zip_cmd([X | Xs], []) -> [{X, ""} | zip_cmd(Xs, [])];
zip_cmd([], [Y | Ys]) -> [{"", Y} | zip_cmd([], Ys)];
zip_cmd([], []) -> [].