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,
|
single_name_param,
|
||||||
CommandFlags::None,
|
CommandFlags::None,
|
||||||
CommandHelper{},
|
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&)
|
[](const ParametersParser& parser, Context&, const ShellContext&)
|
||||||
{
|
{
|
||||||
if (chdir(parse_filename(parser[0]).c_str()) != 0)
|
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))
|
while (dirent* entry = readdir(dir))
|
||||||
{
|
{
|
||||||
StringView filename = entry->d_name;
|
StringView filename = entry->d_name;
|
||||||
if (filename.empty() or not filter(*entry))
|
if (filename.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
auto fmt_str = (dirname.empty() or dirname.back() == '/') ? "{}{}" : "{}/{}";
|
auto fmt_str = (dirname.empty() or dirname.back() == '/') ? "{}{}" : "{}/{}";
|
||||||
format_to(buffer, fmt_str, dirname, filename);
|
format_to(buffer, fmt_str, dirname, filename);
|
||||||
if (stat(buffer, &st) != 0)
|
if (stat(buffer, &st) != 0 or not filter(*entry, st))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (S_ISDIR(st.st_mode))
|
if (S_ISDIR(st.st_mode))
|
||||||
|
@ -366,7 +366,7 @@ Vector<String> list_files(StringView dirname, Filter filter)
|
||||||
|
|
||||||
Vector<String> list_files(StringView directory)
|
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) != ".";
|
return StringView{entry.d_name}.substr(0_byte, 1_byte) != ".";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -380,9 +380,8 @@ static CandidateList candidates(ConstArrayView<RankedMatch> matches, StringView
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
CandidateList complete_filename(StringView prefix,
|
CandidateList complete_filename(StringView prefix, const Regex& ignored_regex,
|
||||||
const Regex& ignored_regex,
|
ByteCount cursor_pos, bool only_dir)
|
||||||
ByteCount cursor_pos)
|
|
||||||
{
|
{
|
||||||
String real_prefix = parse_filename(prefix.substr(0, cursor_pos));
|
String real_prefix = parse_filename(prefix.substr(0, cursor_pos));
|
||||||
StringView dirname, fileprefix;
|
StringView dirname, fileprefix;
|
||||||
|
@ -392,10 +391,11 @@ CandidateList complete_filename(StringView prefix,
|
||||||
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) == ".";
|
||||||
|
|
||||||
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
|
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);
|
auto files = list_files(dirname, filter);
|
||||||
Vector<RankedMatch> matches;
|
Vector<RankedMatch> matches;
|
||||||
|
@ -416,13 +416,8 @@ Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
||||||
|
|
||||||
if (not dirname.empty())
|
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)
|
bool executable = (st.st_mode & S_IXUSR)
|
||||||
| (st.st_mode & S_IXGRP)
|
| (st.st_mode & S_IXGRP)
|
||||||
| (st.st_mode & S_IXOTH);
|
| (st.st_mode & S_IXOTH);
|
||||||
|
@ -460,12 +455,7 @@ Vector<String> complete_command(StringView prefix, ByteCount cursor_pos)
|
||||||
auto& cache = command_cache[dirname];
|
auto& cache = command_cache[dirname];
|
||||||
if (memcmp(&cache.mtim, &st.st_mtim, sizeof(TimeSpec)) != 0)
|
if (memcmp(&cache.mtim, &st.st_mtim, sizeof(TimeSpec)) != 0)
|
||||||
{
|
{
|
||||||
auto filter = [&dirname](const dirent& entry) {
|
auto filter = [&dirname](const dirent& entry, const struct stat& st) {
|
||||||
struct stat st;
|
|
||||||
char buffer[PATH_MAX+1];
|
|
||||||
format_to(buffer, "{}/{}", dirname, entry.d_name);
|
|
||||||
if (stat(buffer, &st))
|
|
||||||
return false;
|
|
||||||
bool executable = (st.st_mode & S_IXUSR)
|
bool executable = (st.st_mode & S_IXUSR)
|
||||||
| (st.st_mode & S_IXGRP)
|
| (st.st_mode & S_IXGRP)
|
||||||
| (st.st_mode & S_IXOTH);
|
| (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,
|
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);
|
CandidateList complete_command(StringView prefix, ByteCount cursor_pos = -1);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user