From b9a2aa87e5ed3e2f3ba2701a9f6ea798e5077d5e Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Sat, 29 Aug 2015 17:52:20 -0700 Subject: `rebar3 path' provider prints requested paths to stdout based on current profile --- src/rebar.app.src | 1 + src/rebar_prv_path.erl | 123 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/rebar_prv_path.erl diff --git a/src/rebar.app.src b/src/rebar.app.src index 6b0f315..655506e 100644 --- a/src/rebar.app.src +++ b/src/rebar.app.src @@ -52,6 +52,7 @@ rebar_prv_lock, rebar_prv_new, rebar_prv_packages, + rebar_prv_path, rebar_prv_plugins, rebar_prv_plugins_upgrade, rebar_prv_release, diff --git a/src/rebar_prv_path.erl b/src/rebar_prv_path.erl new file mode 100644 index 0000000..2da41ea --- /dev/null +++ b/src/rebar_prv_path.erl @@ -0,0 +1,123 @@ +%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 et + +-module(rebar_prv_path). + +-behaviour(provider). + +-export([init/1, + do/1, + format_error/1]). + +-include("rebar.hrl"). + +-define(PROVIDER, path). +-define(DEPS, [app_discovery]). + +%% =================================================================== +%% Public API +%% =================================================================== + +-spec init(rebar_state:t()) -> {ok, rebar_state:t()}. +init(State) -> + State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER}, + {module, ?MODULE}, + {bare, true}, + {deps, ?DEPS}, + {example, "rebar3 path"}, + {short_desc, "Print paths to build dirs in current profile."}, + {desc, "Print paths to build dirs in current profile."}, + {opts, eunit_opts(State)}])), + + {ok, State1}. + +-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. +do(State) -> + {RawOpts, _} = rebar_state:command_parsed_args(State), + %% retrieve apps to filter by for other args + Apps = filter_apps(RawOpts, State), + %% remove apps opt from options + Paths = lists:filter(fun({app, _}) -> false; (_) -> true end, RawOpts), + %% if no paths requested in opts print the base_dir instead + P = case Paths of [] -> [{base, true}]; _ -> Paths end, + case paths(P, Apps, State, []) of + ok -> {ok, State}; + {error, Error} -> {error, Error} + end. + +-spec format_error(any()) -> iolist(). +format_error(Reason) -> + io_lib:format("~p", [Reason]). + +filter_apps(RawOpts, State) -> + RawApps = proplists:get_all_values(app, RawOpts), + Apps = lists:foldl(fun(String, Acc) -> string:tokens(String, ",") ++ Acc end, [], RawApps), + case Apps of + [] -> + ProjectDeps = project_deps(State), + ProjectApps = rebar_state:project_apps(State), + lists:map(fun(A) -> binary_to_list(rebar_app_info:name(A)) end, ProjectApps) ++ ProjectDeps; + _ -> Apps + end. + + +paths([], _, _, Acc) -> print_paths_if_exist(lists:reverse(Acc)); +paths([{base, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, [base_dir(State)|Acc]); +paths([{bin, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, [bin_dir(State)|Acc]); +paths([{ebin, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, ebin_dirs(Apps, State) ++ Acc); +paths([{lib, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, [lib_dir(State)|Acc]); +paths([{priv, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, priv_dirs(Apps, State) ++ Acc); +paths([{src, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, src_dirs(Apps, State) ++ Acc); +paths([{rel, true}|Rest], Apps, State, Acc) -> + paths(Rest, Apps, State, [rel_dir(State)|Acc]). + +base_dir(State) -> io_lib:format("~s", [rebar_dir:base_dir(State)]). +bin_dir(State) -> io_lib:format("~s/bin", [rebar_dir:base_dir(State)]). +lib_dir(State) -> io_lib:format("~s/lib", [rebar_dir:base_dir(State)]). +rel_dir(State) -> io_lib:format("~s/rel", [rebar_dir:base_dir(State)]). + +ebin_dirs(Apps, State) -> + lists:map(fun(App) -> io_lib:format("~s/lib/~s/ebin", [rebar_dir:base_dir(State), App]) end, Apps). +priv_dirs(Apps, State) -> + lists:map(fun(App) -> io_lib:format("~s/lib/~s/priv", [rebar_dir:base_dir(State), App]) end, Apps). +src_dirs(Apps, State) -> + lists:map(fun(App) -> io_lib:format("~s/lib/~s/src", [rebar_dir:base_dir(State), App]) end, Apps). + +print_paths_if_exist(Paths) -> + RealPaths = lists:filter(fun(P) -> ec_file:is_dir(P) end, Paths), + io:format("~s", [string:join(RealPaths, ",")]). + +project_deps(State) -> + Profiles = rebar_state:current_profiles(State), + List = lists:foldl(fun(Profile, Acc) -> rebar_state:get(State, {deps, Profile}, []) ++ Acc end, [], Profiles), + Deps = [normalize(Name) || {Name, _} <- List], + lists:usort(Deps). + +normalize(AppName) when is_list(AppName) -> AppName; +normalize(AppName) when is_atom(AppName) -> atom_to_list(AppName); +normalize(AppName) when is_binary(AppName) -> binary_to_list(AppName). + +eunit_opts(_State) -> + [{app, undefined, "app", string, help(app)}, + {base, undefined, "base", boolean, help(base)}, + {bin, undefined, "bin", boolean, help(bin)}, + {ebin, undefined, "ebin", boolean, help(ebin)}, + {lib, undefined, "lib", boolean, help(lib)}, + {priv, undefined, "priv", boolean, help(priv)}, + {src, undefined, "src", boolean, help(src)}, + {rel, undefined, "rel", boolean, help(rel)}]. + +help(app) -> "Comma seperated list of applications to return paths for."; +help(base) -> "Return the `base' path of the current profile."; +help(bin) -> "Return the `bin' path of the current profile."; +help(ebin) -> "Return all `ebin' paths of the current profile's applications."; +help(lib) -> "Return the `lib' path of the current profile."; +help(priv) -> "Return the `priv' path of the current profile's applications."; +help(src) -> "Return the `src' path of the current profile's applications."; +help(rel) -> "Return the `rel' path of the current profile.". \ No newline at end of file -- cgit v1.1 From 7e32efda63bbf3598eb1860933a10e19eb95653f Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Mon, 31 Aug 2015 17:13:02 -0700 Subject: default to `ebin' for `rebar3 path' command and use single space as default seperator --- src/rebar_prv_path.erl | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/rebar_prv_path.erl b/src/rebar_prv_path.erl index 2da41ea..8ee8b69 100644 --- a/src/rebar_prv_path.erl +++ b/src/rebar_prv_path.erl @@ -36,10 +36,10 @@ do(State) -> {RawOpts, _} = rebar_state:command_parsed_args(State), %% retrieve apps to filter by for other args Apps = filter_apps(RawOpts, State), - %% remove apps opt from options - Paths = lists:filter(fun({app, _}) -> false; (_) -> true end, RawOpts), + %% remove apps and seperator opts from options + Paths = lists:filter(fun({app, _}) -> false; ({seperator, _}) -> false; (_) -> true end, RawOpts), %% if no paths requested in opts print the base_dir instead - P = case Paths of [] -> [{base, true}]; _ -> Paths end, + P = case Paths of [] -> [{ebin, true}]; _ -> Paths end, case paths(P, Apps, State, []) of ok -> {ok, State}; {error, Error} -> {error, Error} @@ -61,7 +61,7 @@ filter_apps(RawOpts, State) -> end. -paths([], _, _, Acc) -> print_paths_if_exist(lists:reverse(Acc)); +paths([], _, State, Acc) -> print_paths_if_exist(lists:reverse(Acc), State); paths([{base, true}|Rest], Apps, State, Acc) -> paths(Rest, Apps, State, [base_dir(State)|Acc]); paths([{bin, true}|Rest], Apps, State, Acc) -> @@ -89,9 +89,11 @@ priv_dirs(Apps, State) -> src_dirs(Apps, State) -> lists:map(fun(App) -> io_lib:format("~s/lib/~s/src", [rebar_dir:base_dir(State), App]) end, Apps). -print_paths_if_exist(Paths) -> +print_paths_if_exist(Paths, State) -> + {RawOpts, _} = rebar_state:command_parsed_args(State), + Sep = proplists:get_value(seperator, RawOpts, " "), RealPaths = lists:filter(fun(P) -> ec_file:is_dir(P) end, Paths), - io:format("~s", [string:join(RealPaths, ",")]). + io:format("~s", [string:join(RealPaths, Sep)]). project_deps(State) -> Profiles = rebar_state:current_profiles(State), @@ -110,14 +112,16 @@ eunit_opts(_State) -> {ebin, undefined, "ebin", boolean, help(ebin)}, {lib, undefined, "lib", boolean, help(lib)}, {priv, undefined, "priv", boolean, help(priv)}, + {seperator, $s, "seperator", string, help(seperator)}, {src, undefined, "src", boolean, help(src)}, {rel, undefined, "rel", boolean, help(rel)}]. -help(app) -> "Comma seperated list of applications to return paths for."; -help(base) -> "Return the `base' path of the current profile."; -help(bin) -> "Return the `bin' path of the current profile."; -help(ebin) -> "Return all `ebin' paths of the current profile's applications."; -help(lib) -> "Return the `lib' path of the current profile."; -help(priv) -> "Return the `priv' path of the current profile's applications."; -help(src) -> "Return the `src' path of the current profile's applications."; -help(rel) -> "Return the `rel' path of the current profile.". \ No newline at end of file +help(app) -> "Comma seperated list of applications to return paths for."; +help(base) -> "Return the `base' path of the current profile."; +help(bin) -> "Return the `bin' path of the current profile."; +help(ebin) -> "Return all `ebin' paths of the current profile's applications."; +help(lib) -> "Return the `lib' path of the current profile."; +help(priv) -> "Return the `priv' path of the current profile's applications."; +help(seperator) -> "In case of multiple return paths, the seperator character to use to join them."; +help(src) -> "Return the `src' path of the current profile's applications."; +help(rel) -> "Return the `rel' path of the current profile.". \ No newline at end of file -- cgit v1.1 From 04da2ffd5e65895ff0beb6f8f3ffd0deb95328de Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Thu, 3 Sep 2015 01:41:13 -0700 Subject: shell completions for `rebar3 path' --- README.md | 1 + priv/shell-completion/bash/rebar3 | 12 ++++++++++++ priv/shell-completion/fish/rebar3.fish | 12 ++++++++++++ priv/shell-completion/zsh/_rebar3 | 11 +++++++++++ src/rebar_prv_path.erl | 10 +++++----- 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4054b8d..8d85934 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ locations ([hex.pm](http://hex.pm), git, hg, and so on). | eunit | Run eunit tests | | help | Print help for rebar or task | | new | Create new rebar project from templates | +| path | Print paths to build dirs in current profile | | pkgs | List available packages | | plugins | List or upgrade plugins | | release | Build release of project | diff --git a/priv/shell-completion/bash/rebar3 b/priv/shell-completion/bash/rebar3 index 40009b7..511d537 100644 --- a/priv/shell-completion/bash/rebar3 +++ b/priv/shell-completion/bash/rebar3 @@ -23,6 +23,7 @@ _rebar3() eunit \ help \ new \ + path \ pkgs \ plugins \ release \ @@ -98,6 +99,17 @@ _rebar3() elif [[ ${prev} == new ]] ; then sopts="-f" lopts="--force" + elif [[ ${prev} == path ]] ; then + sopts="-s" + lopts="--app \ + --base \ + --bin \ + --ebin \ + --lib \ + --priv \ + --separator \ + --src \ + --rel" elif [[ ${prev} == pkgs ]] ; then : elif [[ ${prev} == plugins ]] ; then diff --git a/priv/shell-completion/fish/rebar3.fish b/priv/shell-completion/fish/rebar3.fish index df1697e..f3b449e 100644 --- a/priv/shell-completion/fish/rebar3.fish +++ b/priv/shell-completion/fish/rebar3.fish @@ -44,6 +44,7 @@ end ## eunit Run EUnit Tests. ## help Display a list of tasks or help for a given task or subtask. ## new Create new project from templates. +## path Print paths to build dirs in current profile. ## pkgs List available packages. ## release Build release of project. ## relup Create relup of releases. @@ -118,6 +119,17 @@ complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a new -d "Create new p complete -f -c 'rebar3' -n '__fish_rebar3_using_command new' -s f -l force -d "Overwrite existing files" complete -f -c 'rebar3' -n '__fish_rebar3_using_command new' -a help -d "Display all variables and arguments for each template" +complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a paths -d "Print paths to build dirs in current profile." +complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l app -d "Comma seperated list of applications to return paths for." +complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l base -d "Return the `base' path of the current profile." +complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l bin -d Return the `bin' path of the current profile." +complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l ebin -d "Return all `ebin' paths of the current profile's applications." +complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l lib -d "Return the `lib' path of the current profile." +complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l priv -d "Return the `priv' path of the current profile's applications." +complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -s s -l separator -d "In case of multiple return paths, the separator character to use to join them." +complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l src -d "Return the `src' path of the current profile's applications." +complete -f -c 'rebar3' -n '__fish_rebar3_needs_command paths' -l rel -d "Return the `rel' path of the current profile." + complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a pkgs -d "List available packages." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a release -d "Build release of project." complete -f -c 'rebar3' -n '__fish_rebar3_needs_command' -a relup -d "Create relup of releases." diff --git a/priv/shell-completion/zsh/_rebar3 b/priv/shell-completion/zsh/_rebar3 index 04575bc..8855bdf 100644 --- a/priv/shell-completion/zsh/_rebar3 +++ b/priv/shell-completion/zsh/_rebar3 @@ -108,6 +108,17 @@ _rebar3 () { '(-f --force)'{-f,--force}'[ overwrite existing files]' \ && ret=0 ;; + (path) + _arguments \ + '(--app)--app[Comma seperated list of applications to return paths for.]:apps' \ + '(--base)--base[Return the `base' path of the current profile.]' \ + '(--bin)--bin[Return the `bin' path of the current profile.]' \ + '(--ebin)--ebin[Return all `ebin' paths of the current profile's applications.]' \ + '(--lib)--lib[Return the `lib' path of the current profile.]' \ + '(--priv)--priv[Return the `priv' path of the current profile's applications.]' \ + '(-s --separator)--separator[In case of multiple return paths, the separator character to use to join them.]' \ + && ret=0 + ;; (pkgs) _message 'List available packages.' && ret=0 ;; diff --git a/src/rebar_prv_path.erl b/src/rebar_prv_path.erl index 8ee8b69..2a59ae4 100644 --- a/src/rebar_prv_path.erl +++ b/src/rebar_prv_path.erl @@ -36,8 +36,8 @@ do(State) -> {RawOpts, _} = rebar_state:command_parsed_args(State), %% retrieve apps to filter by for other args Apps = filter_apps(RawOpts, State), - %% remove apps and seperator opts from options - Paths = lists:filter(fun({app, _}) -> false; ({seperator, _}) -> false; (_) -> true end, RawOpts), + %% remove apps and separator opts from options + Paths = lists:filter(fun({app, _}) -> false; ({separator, _}) -> false; (_) -> true end, RawOpts), %% if no paths requested in opts print the base_dir instead P = case Paths of [] -> [{ebin, true}]; _ -> Paths end, case paths(P, Apps, State, []) of @@ -91,7 +91,7 @@ src_dirs(Apps, State) -> print_paths_if_exist(Paths, State) -> {RawOpts, _} = rebar_state:command_parsed_args(State), - Sep = proplists:get_value(seperator, RawOpts, " "), + Sep = proplists:get_value(separator, RawOpts, " "), RealPaths = lists:filter(fun(P) -> ec_file:is_dir(P) end, Paths), io:format("~s", [string:join(RealPaths, Sep)]). @@ -112,7 +112,7 @@ eunit_opts(_State) -> {ebin, undefined, "ebin", boolean, help(ebin)}, {lib, undefined, "lib", boolean, help(lib)}, {priv, undefined, "priv", boolean, help(priv)}, - {seperator, $s, "seperator", string, help(seperator)}, + {separator, $s, "separator", string, help(separator)}, {src, undefined, "src", boolean, help(src)}, {rel, undefined, "rel", boolean, help(rel)}]. @@ -122,6 +122,6 @@ help(bin) -> "Return the `bin' path of the current profile."; help(ebin) -> "Return all `ebin' paths of the current profile's applications."; help(lib) -> "Return the `lib' path of the current profile."; help(priv) -> "Return the `priv' path of the current profile's applications."; -help(seperator) -> "In case of multiple return paths, the seperator character to use to join them."; +help(separator) -> "In case of multiple return paths, the separator character to use to join them."; help(src) -> "Return the `src' path of the current profile's applications."; help(rel) -> "Return the `rel' path of the current profile.". \ No newline at end of file -- cgit v1.1