Skip to content

Commit ec0caee

Browse files
authored
Merge pull request #2961 from williamthome/feat/bash-completion-file-support
Add file completion support for bash completion
2 parents aca6b70 + c6e7e80 commit ec0caee

File tree

2 files changed

+48
-9
lines changed

2 files changed

+48
-9
lines changed

apps/rebar/src/rebar_completion_bash.erl

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,24 @@ main(Commands, #{shell:=bash, aliases:=Aliases}) ->
8282
" cmdsnvars=\"",lists:join(" \\\n", CmdNames),"\"\n",
8383
" ",[cmd_clause(Cmd) || Cmd <- Commands],
8484
" fi\n",
85-
" COMPREPLY=( $(compgen -W \"${sopts} ${lopts} ${cmdsnvars} \" -- ${cur}) )\n",
86-
" if [ -n \"$COMPREPLY\" ] ; then\n",
87-
" # append space if matched\n",
88-
" COMPREPLY=\"${COMPREPLY} \"\n",
89-
" # remove trailing space after equal sign\n",
90-
" COMPREPLY=${COMPREPLY/%= /=}\n",
85+
" \n",
86+
" # File completion for commands that accept file arguments\n",
87+
" if [[ (${prev1} == ct || ${prev1} == eunit) && \"$cur\" != -* ]]; then\n",
88+
" # Complete with .erl files and directories for test commands\n",
89+
" COMPREPLY=( $(compgen -f -X '!*.erl' -- ${cur}) $(compgen -d -- ${cur}) )\n",
90+
" elif [[ (${prev1} == completion || ${prev1} == shell || ${prev1} == tar) && \"$cur\" != -* ]]; then\n",
91+
" # Complete with files and directories for other file-accepting commands\n",
92+
" COMPREPLY=( $(compgen -f -- ${cur}) $(compgen -d -- ${cur}) )\n",
93+
" else\n",
94+
" COMPREPLY=( $(compgen -W \"${sopts} ${lopts} ${cmdsnvars} \" -- ${cur}) )\n",
9195
" fi\n",
96+
" \n",
97+
" # If no completions found, fall back to normal completion\n",
98+
" if [ ${#COMPREPLY[@]} -eq 0 ]; then\n",
99+
" COMPREPLY=( $(compgen -W \"${sopts} ${lopts} ${cmdsnvars} \" -- ${cur}) )\n",
100+
" fi\n",
101+
" \n",
102+
" # Let bash handle spacing naturally\n",
92103
" return 0\n",
93104
"}\n"].
94105

@@ -110,4 +121,4 @@ cmd_depth([_ | Rest],Depth,Max) ->
110121

111122
complete(#{shell:=bash, aliases:=Aliases}) ->
112123
Triggers = ["rebar3" | Aliases],
113-
[["complete -o nospace -F _rebar3 ", Trigger, "\n"] || Trigger <- Triggers].
124+
[["complete -o filenames -F _rebar3 ", Trigger, "\n"] || Trigger <- Triggers].

apps/rebar/test/rebar_completion_SUITE.erl

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ suite() ->
99
[].
1010

1111
all() ->
12-
[test_completion_gen, check_bash, check_zsh].
12+
[test_completion_gen, check_bash, check_zsh, check_bash_file_completion].
1313

1414
groups() ->
1515
[].
@@ -30,6 +30,13 @@ init_per_testcase(check_bash, Config) ->
3030
false ->
3131
{skip, "bash not found"}
3232
end;
33+
init_per_testcase(check_bash_file_completion, Config) ->
34+
case shell_available(bash) of
35+
true ->
36+
rebar_test_utils:init_rebar_state(Config, "completion_");
37+
false ->
38+
{skip, "bash not found"}
39+
end;
3340
init_per_testcase(check_zsh, Config) ->
3441
case shell_available(zsh) of
3542
true ->
@@ -69,7 +76,7 @@ check_bash(Config) ->
6976
%% function definition
7077
{match, _} = re:run(Completion, "_rebar3\\(\\)\\{"),
7178
%% aliases
72-
CompleteCmd = "complete -o nospace -F _rebar3 ",
79+
CompleteCmd = "complete -o filenames -F _rebar3 ",
7380
lists:foreach(fun(Alias) ->
7481
?assertMatch({Alias, {match, _}}, {Alias, re:run(Completion, CompleteCmd++Alias++"\n")})
7582
end,
@@ -91,6 +98,27 @@ check_zsh(Config) ->
9198
end,
9299
["rebar3" | Aliases]).
93100

101+
check_bash_file_completion(Config) ->
102+
ComplFile = ?config(compl_file, Config),
103+
Opts = #{shell => bash, file => ComplFile},
104+
completion_gen(Config, Opts),
105+
{ok, Completion} = file:read_file(ComplFile),
106+
107+
%% Check that file completion logic is present for ct and eunit
108+
{match, _} = re:run(Completion, "\\$\\{prev1\\} == ct \\|\\| \\$\\{prev1\\} == eunit"),
109+
110+
%% Check that .erl file completion is included
111+
{match, _} = re:run(Completion, "compgen -f -X '!\\*\\.erl'"),
112+
113+
%% Check that directory completion is included
114+
{match, _} = re:run(Completion, "compgen -d"),
115+
116+
%% Check that other file-accepting commands are handled
117+
{match, _} = re:run(Completion, "\\$\\{prev1\\} == completion \\|\\| \\$\\{prev1\\} == shell \\|\\| \\$\\{prev1\\} == tar"),
118+
119+
%% Check that fallback completion is present
120+
{match, _} = re:run(Completion, "If no completions found, fall back to normal completion").
121+
94122
%% helpers
95123

96124
completion_gen(Config, CmplOpts) ->

0 commit comments

Comments
 (0)