Do not expand filenames when doing insert filename completion

Fixes #855
This commit is contained in:
Maxime Coste 2016-10-13 19:46:09 +01:00
parent ee5c246861
commit 1f3e424047
3 changed files with 27 additions and 12 deletions

View File

@ -111,7 +111,7 @@ auto filename_completer = make_completer(
{ return Completions{ 0_byte, cursor_pos, { return Completions{ 0_byte, cursor_pos,
complete_filename(prefix, complete_filename(prefix,
context.options()["ignored_files"].get<Regex>(), context.options()["ignored_files"].get<Regex>(),
cursor_pos) }; }); cursor_pos, FilenameFlags::Expand) }; });
static Completions complete_buffer_name(const Context& context, CompletionFlags flags, static Completions complete_buffer_name(const Context& context, CompletionFlags flags,
StringView prefix, ByteCount cursor_pos) StringView prefix, ByteCount cursor_pos)
@ -873,7 +873,7 @@ void define_command(const ParametersParser& parser, Context& context, const Shel
auto& ignored_files = context.options()["ignored_files"].get<Regex>(); auto& ignored_files = context.options()["ignored_files"].get<Regex>();
return Completions{ 0_byte, pos_in_token, return Completions{ 0_byte, pos_in_token,
complete_filename(prefix, ignored_files, complete_filename(prefix, ignored_files,
pos_in_token) }; pos_in_token, FilenameFlags::Expand) };
}; };
} }
else if (parser.get_switch("client-completion")) else if (parser.get_switch("client-completion"))
@ -1678,7 +1678,8 @@ const CommandDesc prompt_cmd = {
StringView prefix, ByteCount cursor_pos) -> Completions { StringView prefix, ByteCount cursor_pos) -> Completions {
auto& ignored_files = context.options()["ignored_files"].get<Regex>(); auto& ignored_files = context.options()["ignored_files"].get<Regex>();
return { 0_byte, cursor_pos, return { 0_byte, cursor_pos,
complete_filename(prefix, ignored_files, cursor_pos) }; complete_filename(prefix, ignored_files, cursor_pos,
FilenameFlags::Expand) };
}; };
else if (parser.get_switch("client-completion")) else if (parser.get_switch("client-completion"))
completer = [](const Context& context, CompletionFlags, completer = [](const Context& context, CompletionFlags,
@ -1968,7 +1969,7 @@ const CommandDesc change_working_directory_cmd = {
return { 0_byte, cursor_pos, return { 0_byte, cursor_pos,
complete_filename(prefix, complete_filename(prefix,
context.options()["ignored_files"].get<Regex>(), context.options()["ignored_files"].get<Regex>(),
cursor_pos, true) }; cursor_pos, FilenameFlags::OnlyDirectories) };
}), }),
[](const ParametersParser& parser, Context&, const ShellContext&) [](const ParametersParser& parser, Context&, const ShellContext&)
{ {

View File

@ -392,24 +392,26 @@ static CandidateList candidates(ConstArrayView<RankedMatch> matches, StringView
} }
CandidateList complete_filename(StringView prefix, const Regex& ignored_regex, CandidateList complete_filename(StringView prefix, const Regex& ignored_regex,
ByteCount cursor_pos, bool only_dir) ByteCount cursor_pos, FilenameFlags flags)
{ {
String real_prefix = parse_filename(prefix.substr(0, cursor_pos)); prefix = prefix.substr(0, cursor_pos);
StringView dirname, fileprefix; StringView dirname, fileprefix;
std::tie(dirname, fileprefix) = split_path(real_prefix); std::tie(dirname, fileprefix) = split_path(prefix);
auto parsed_dirname = parse_filename(dirname);
const bool check_ignored_regex = not ignored_regex.empty() and const bool check_ignored_regex = not ignored_regex.empty() and
not regex_match(fileprefix.begin(), fileprefix.end(), ignored_regex); not regex_match(fileprefix.begin(), fileprefix.end(), ignored_regex);
const bool include_hidden = fileprefix.substr(0_byte, 1_byte) == "."; const bool include_hidden = fileprefix.substr(0_byte, 1_byte) == ".";
const bool only_dirs = (flags & FilenameFlags::OnlyDirectories);
auto filter = [&ignored_regex, check_ignored_regex, include_hidden, only_dir](const dirent& entry, struct stat& st) auto filter = [&ignored_regex, check_ignored_regex, include_hidden, only_dirs](const dirent& entry, struct stat& st)
{ {
StringView name{entry.d_name}; StringView name{entry.d_name};
return (include_hidden or name.substr(0_byte, 1_byte) != ".") and return (include_hidden or name.substr(0_byte, 1_byte) != ".") and
(not check_ignored_regex or not regex_match(name.begin(), name.end(), ignored_regex)) and (not check_ignored_regex or not regex_match(name.begin(), name.end(), ignored_regex)) and
(not only_dir or S_ISDIR(st.st_mode)); (not only_dirs or S_ISDIR(st.st_mode));
}; };
auto files = list_files(dirname, filter); auto files = list_files(parsed_dirname, filter);
Vector<RankedMatch> matches; Vector<RankedMatch> matches;
for (auto& file : files) for (auto& file : files)
{ {
@ -417,7 +419,8 @@ CandidateList complete_filename(StringView prefix, const Regex& ignored_regex,
matches.push_back(match); matches.push_back(match);
} }
std::sort(matches.begin(), matches.end()); std::sort(matches.begin(), matches.end());
return candidates(matches, dirname); const bool expand = (flags & FilenameFlags::Expand);
return candidates(matches, expand ? parsed_dirname : dirname);
} }
Vector<String> complete_command(StringView prefix, ByteCount cursor_pos) Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)

View File

@ -5,6 +5,7 @@
#include "completion.hh" #include "completion.hh"
#include "exception.hh" #include "exception.hh"
#include "regex.hh" #include "regex.hh"
#include "flags.hh"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -83,8 +84,18 @@ constexpr bool operator!=(const timespec& lhs, const timespec& rhs)
return not (lhs == rhs); return not (lhs == rhs);
} }
enum class FilenameFlags
{
None = 0,
OnlyDirectories = 1 << 0,
Expand = 1 << 1
};
template<> struct WithBitOps<FilenameFlags> : std::true_type {};
CandidateList complete_filename(StringView prefix, const Regex& ignore_regex, CandidateList complete_filename(StringView prefix, const Regex& ignore_regex,
ByteCount cursor_pos = -1, bool only_dir = false); ByteCount cursor_pos = -1,
FilenameFlags flags = FilenameFlags::None);
CandidateList complete_command(StringView prefix, ByteCount cursor_pos = -1); CandidateList complete_command(StringView prefix, ByteCount cursor_pos = -1);