diff --git a/TODO b/TODO new file mode 100644 index 0000000..f921ce0 --- /dev/null +++ b/TODO @@ -0,0 +1,2 @@ +* write documentation +* ZSH completion script diff --git a/priv/shell-completion/bash/rebar b/priv/shell-completion/bash/rebar index a7a1426..ba87bdd 100644 --- a/priv/shell-completion/bash/rebar +++ b/priv/shell-completion/bash/rebar @@ -6,12 +6,12 @@ _rebar() COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" - sopts="-h -v -f -j" - lopts=" --help --verbose --force --jobs=" + sopts="-h -c -v -f -j" + lopts=" --help --commands --verbose --force --jobs=" cmdsnvars="analyze build_plt check_plt clean compile \ create-app create-node eunit generate \ install int_test perf_test test \ - case= force=1 jobs= suite= verbose=1 appid= target=" + case= force=1 jobs= suite= verbose=1 appid= target= template=" if [[ ${cur} == --* ]] ; then COMPREPLY=( $(compgen -W "${lopts}" -- ${cur}) ) diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 3f8c2ba..0279971 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -85,32 +85,25 @@ parse_args(Args) -> %% Parse getopt options OptSpecList = option_spec_list(), case getopt:parse(OptSpecList, Args) of - {ok, {_Options, []}} -> - %% no command to run specified - help(), - halt(1); {ok, {Options, NonOptArgs}} -> - case proplists:get_bool(help, Options) of - true -> - %% display help - help(), - halt(0); - false -> - %% Set global variables based on getopt options - set_global_flag(Options, verbose), - set_global_flag(Options, force), - DefJobs = rebar_config:get_jobs(), - case proplists:get_value(jobs, Options, DefJobs) of - DefJobs -> - ok; - Jobs -> - rebar_config:set_global(jobs, Jobs) - end, + %% Check options and maybe halt execution + {ok, continue} = print_help_maybe_halt(Options, NonOptArgs), + + %% Set global variables based on getopt options + set_global_flag(Options, verbose), + set_global_flag(Options, force), + DefJobs = rebar_config:get_jobs(), + case proplists:get_value(jobs, Options, DefJobs) of + DefJobs -> + ok; + Jobs -> + rebar_config:set_global(jobs, Jobs) + end, + + %% Filter all the flags (i.e. strings of form key=value) from the + %% command line arguments. What's left will be the commands to run. + filter_flags(NonOptArgs, []); - %% Filter all the flags (i.e. strings of form key=value) from the - %% command line arguments. What's left will be the commands to run. - filter_flags(NonOptArgs, []) - end; {error, {Reason, Data}} -> ?ERROR("Error: ~s ~p~n~n", [Reason, Data]), help(), @@ -129,6 +122,31 @@ set_global_flag(Options, Flag) -> end, rebar_config:set_global(Flag, Value). +%% +%% print help +%% +print_help_maybe_halt(Options, NonOptArgs) -> + case proplists:get_bool(help, Options) of + true -> + help(), + halt(0); + false -> + case proplists:get_bool(commands, Options) of + true -> + commands(), + halt(0); + false -> + case NonOptArgs of + [] -> + io:format("No command to run specified!~n"), + help(), + halt(1); + _ -> + {ok, continue} + end + end + end. + %% %% print help/usage string %% @@ -139,6 +157,32 @@ help() -> [{"var=value", "rebar global variables (e.g. force=1)"}, {"command", "Command to run (e.g. compile)"}]). +%% +%% print known commands +%% +commands() -> + io:format(<< +"analyze Analyze with Dialyzer~n" +"build_plt Build Dialyzer PLT~n" +"check_plt Check Dialyzer PLT~n" +"~n" +"clean Clean~n" +"compile Compile sources~n" +"~n" +"create template= [var=foo,...] Create skel based on template and vars~n" +"create-app Create simple app skel~n" +"create-node Create simple node skel~n" +"~n" +"generate [dump_spec=0/1] Build release with reltool~n" +"install [target=] Install build into target~n" +"~n" +"eunit [suite=foo] Run eunit [test/foo_tests.erl] tests~n" +"~n" +"int_test [suite=] [case=] Run ct suites in ./int_test~n" +"perf_test [suite=] [case=] Run ct suites in ./perf_test~n" +"test [suite=] [case=] Run ct suites in ./test~n" +>>). + %% %% options accepted via getopt %% @@ -149,10 +193,11 @@ option_spec_list() -> [Jobs]), [ %% {Name, ShortOpt, LongOpt, ArgSpec, HelpMsg} - {help, $h, "help", undefined, "Show the program options"}, - {verbose, $v, "verbose", undefined, "Be verbose about what gets done"}, - {force, $f, "force", undefined, "Force"}, - {jobs, $j, "jobs", integer, JobsHelp} + {help, $h, "help", undefined, "Show the program options"}, + {commands, $c, "commands", undefined, "Show available commands"}, + {verbose, $v, "verbose", undefined, "Be verbose about what gets done"}, + {force, $f, "force", undefined, "Force"}, + {jobs, $j, "jobs", integer, JobsHelp} ]. %% diff --git a/src/rebar_templater.erl b/src/rebar_templater.erl index c4217cd..fd1d813 100644 --- a/src/rebar_templater.erl +++ b/src/rebar_templater.erl @@ -110,8 +110,11 @@ create(_Config, _) -> %% Scan the current escript for available files and cache in pdict. %% cache_escript_files() -> - {ok, Files} = escript:foldl(fun(Name, _, GetBin, Acc) -> [{Name, GetBin()} | Acc] end, - [], rebar_config:get_global(escript, undefined)), + {ok, Files} = rebar_utils:escript_foldl( + fun(Name, _, GetBin, Acc) -> + [{Name, GetBin()} | Acc] + end, + [], rebar_config:get_global(escript, undefined)), erlang:put(escript_files, Files). diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index bfe7bce..e7d22fa 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -36,7 +36,8 @@ now_str/0, ensure_dir/1, beam_to_mod/2, beams/1, - abort/2]). + abort/2, + escript_foldl/3]). -include("rebar.hrl"). @@ -111,6 +112,18 @@ abort(String, Args) -> ?ERROR(String, Args), halt(1). +%% TODO: Rename emulate_escript_foldl to escript_foldl and remove +%% this function when the time is right. escript:foldl/3 was an +%% undocumented exported fun and is going to be removed post-R13B04. +escript_foldl(Fun, Acc, File) -> + {module, zip} = code:ensure_loaded(zip), + case erlang:function_exported(zip, foldl, 3) of + true -> + emulate_escript_foldl(Fun, Acc, File); + false -> + escript:foldl(Fun, Acc, File) + end. + %% ==================================================================== %% Internal functions %% ==================================================================== @@ -144,3 +157,21 @@ beams(Dir) -> filelib:fold_files(Dir, ".*\.beam\$", true, fun(F, Acc) -> [F | Acc] end, []). +emulate_escript_foldl(Fun, Acc, File) -> + case escript:extract(File, [compile_source]) of + {ok, [_Shebang, _Comment, _EmuArgs, Body]} -> + case Body of + {source, BeamCode} -> + GetInfo = fun() -> file:read_file_info(File) end, + GetBin = fun() -> BeamCode end, + {ok, Fun(".", GetInfo, GetBin, Acc)}; + {beam, BeamCode} -> + GetInfo = fun() -> file:read_file_info(File) end, + GetBin = fun() -> BeamCode end, + {ok, Fun(".", GetInfo, GetBin, Acc)}; + {archive, ArchiveBin} -> + zip:foldl(Fun, Acc, {File, ArchiveBin}) + end; + {error, Reason} -> + {error, Reason} + end.