Only offer directories when completing :cd arguments
Refactor code in file.cc, avoid many double stat when searching commands Fixes #646
This commit is contained in:
parent
a8b2834d56
commit
3eca90f2b1
|
@ -1826,7 +1826,15 @@ const CommandDesc change_working_directory_cmd = {
|
|||
single_name_param,
|
||||
CommandFlags::None,
|
||||
CommandHelper{},
|
||||
filename_completer,
|
||||
PerArgumentCommandCompleter{{
|
||||
[](const Context& context, CompletionFlags flags,
|
||||
const String& prefix, ByteCount cursor_pos) -> Completions {
|
||||
return { 0_byte, cursor_pos,
|
||||
complete_filename(prefix,
|
||||
context.options()["ignored_files"].get<Regex>(),
|
||||
cursor_pos, true) };
|
||||
}
|
||||
}},
|
||||
[](const ParametersParser& parser, Context&, const ShellContext&)
|
||||
{
|
||||
if (chdir(parse_filename(parser[0]).c_str()) != 0)
|
||||
|
|
30
src/file.cc
30
src/file.cc
|
@ -348,13 +348,13 @@ Vector<String> list_files(StringView dirname, Filter filter)
|
|||
while (dirent* entry = readdir(dir))
|
||||
{
|
||||
StringView filename = entry->d_name;
|
||||
if (filename.empty() or not filter(*entry))
|
||||
if (filename.empty())
|
||||
continue;
|
||||
|
||||
struct stat st;
|
||||
auto fmt_str = (dirname.empty() or dirname.back() == '/') ? "{}{}" : "{}/{}";
|
||||
format_to(buffer, fmt_str, dirname, filename);
|
||||
if (stat(buffer, &st) != 0)
|
||||
if (stat(buffer, &st) != 0 or not filter(*entry, st))
|
||||
continue;
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
|
@ -366,7 +366,7 @@ Vector<String> list_files(StringView dirname, Filter filter)
|
|||
|
||||
Vector<String> list_files(StringView directory)
|
||||
{
|
||||
return list_files(directory, [](const dirent& entry) {
|
||||
return list_files(directory, [](const dirent& entry, const struct stat&) {
|
||||
return StringView{entry.d_name}.substr(0_byte, 1_byte) != ".";
|
||||
});
|
||||
}
|
||||
|
@ -380,9 +380,8 @@ static CandidateList candidates(ConstArrayView<RankedMatch> matches, StringView
|
|||
return res;
|
||||
}
|
||||
|
||||
CandidateList complete_filename(StringView prefix,
|
||||
const Regex& ignored_regex,
|
||||
ByteCount cursor_pos)
|
||||
CandidateList complete_filename(StringView prefix, const Regex& ignored_regex,
|
||||
ByteCount cursor_pos, bool only_dir)
|
||||
{
|
||||
String real_prefix = parse_filename(prefix.substr(0, cursor_pos));
|
||||
StringView dirname, fileprefix;
|
||||
|
@ -392,10 +391,11 @@ CandidateList complete_filename(StringView prefix,
|
|||
not regex_match(fileprefix.begin(), fileprefix.end(), ignored_regex);
|
||||
const bool include_hidden = fileprefix.substr(0_byte, 1_byte) == ".";
|
||||
|
||||
auto filter = [&ignored_regex, check_ignored_regex, include_hidden](const dirent& entry)
|
||||
auto filter = [&ignored_regex, check_ignored_regex, include_hidden, only_dir](const dirent& entry, struct stat& st)
|
||||
{
|
||||
return (include_hidden or StringView{entry.d_name}.substr(0_byte, 1_byte) != ".") and
|
||||
(not check_ignored_regex or not regex_match(entry.d_name, ignored_regex));
|
||||
(not check_ignored_regex or not regex_match(entry.d_name, ignored_regex)) and
|
||||
(not only_dir or S_ISDIR(st.st_mode));
|
||||
};
|
||||
auto files = list_files(dirname, filter);
|
||||
Vector<RankedMatch> matches;
|
||||
|
@ -416,13 +416,8 @@ Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
|||
|
||||
if (not dirname.empty())
|
||||
{
|
||||
auto filter = [&dirname](const dirent& entry)
|
||||
auto filter = [&dirname](const dirent& entry, const struct stat& st)
|
||||
{
|
||||
char buffer[PATH_MAX+1];
|
||||
format_to(buffer, "{}{}", dirname, entry.d_name);
|
||||
struct stat st;
|
||||
if (stat(buffer, &st) != 0)
|
||||
return false;
|
||||
bool executable = (st.st_mode & S_IXUSR)
|
||||
| (st.st_mode & S_IXGRP)
|
||||
| (st.st_mode & S_IXOTH);
|
||||
|
@ -460,12 +455,7 @@ Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
|||
auto& cache = command_cache[dirname];
|
||||
if (memcmp(&cache.mtim, &st.st_mtim, sizeof(TimeSpec)) != 0)
|
||||
{
|
||||
auto filter = [&dirname](const dirent& entry) {
|
||||
struct stat st;
|
||||
char buffer[PATH_MAX+1];
|
||||
format_to(buffer, "{}/{}", dirname, entry.d_name);
|
||||
if (stat(buffer, &st))
|
||||
return false;
|
||||
auto filter = [&dirname](const dirent& entry, const struct stat& st) {
|
||||
bool executable = (st.st_mode & S_IXUSR)
|
||||
| (st.st_mode & S_IXGRP)
|
||||
| (st.st_mode & S_IXOTH);
|
||||
|
|
|
@ -83,7 +83,7 @@ constexpr bool operator!=(const timespec& lhs, const timespec& rhs)
|
|||
}
|
||||
|
||||
CandidateList complete_filename(StringView prefix, const Regex& ignore_regex,
|
||||
ByteCount cursor_pos = -1);
|
||||
ByteCount cursor_pos = -1, bool only_dir = false);
|
||||
|
||||
CandidateList complete_command(StringView prefix, ByteCount cursor_pos = -1);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user