diff options
| author | Maxime Coste <frrrwww@gmail.com> | 2016-04-07 22:47:41 +0100 |
|---|---|---|
| committer | Maxime Coste <frrrwww@gmail.com> | 2016-04-07 22:47:41 +0100 |
| commit | 3eca90f2b142e4b4b4430fa17534f137e0a89ec0 (patch) | |
| tree | 801f5e811583f6471945b60da93d2277ddd0af8b /src | |
| parent | a8b2834d56d03777b219f62829cbf09c47e7603f (diff) | |
Only offer directories when completing :cd arguments
Refactor code in file.cc, avoid many double stat when searching
commands
Fixes #646
Diffstat (limited to 'src')
| -rw-r--r-- | src/commands.cc | 10 | ||||
| -rw-r--r-- | src/file.cc | 30 | ||||
| -rw-r--r-- | src/file.hh | 2 |
3 files changed, 20 insertions, 22 deletions
diff --git a/src/commands.cc b/src/commands.cc index e0dbef07..43cfa850 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -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) diff --git a/src/file.cc b/src/file.cc index a558dc29..21e06836 100644 --- a/src/file.cc +++ b/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); diff --git a/src/file.hh b/src/file.hh index 9a17c2b1..29d979e3 100644 --- a/src/file.hh +++ b/src/file.hh @@ -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); |
