diff --git a/src/file.cc b/src/file.cc index 5bab7304..0012d256 100644 --- a/src/file.cc +++ b/src/file.cc @@ -339,8 +339,6 @@ std::vector complete_filename(StringView prefix, std::vector complete_command(StringView prefix, ByteCount cursor_pos) { String real_prefix = parse_filename(prefix.substr(0, cursor_pos)); - String dirname; - String fileprefix = real_prefix; ByteCount dir_end = -1; for (ByteCount i = 0; i < real_prefix.length(); ++i) @@ -349,6 +347,27 @@ std::vector complete_command(StringView prefix, ByteCount cursor_pos) dir_end = i; } + if (dir_end != -1) + { + auto dirname = real_prefix.substr(0, dir_end + 1); + auto fileprefix = real_prefix.substr(dir_end + 1); + auto filter = [&](const dirent& entry) + { + struct stat st; + if (stat((dirname + entry.d_name).c_str(), &st)) + return false; + bool executable = (st.st_mode & S_IXUSR) + | (st.st_mode & S_IXGRP) + | (st.st_mode & S_IXOTH); + return S_ISDIR(st.st_mode) or (S_ISREG(st.st_mode) and executable); + }; + std::vector res = list_files(fileprefix, dirname, filter); + for (auto& file : res) + file = dirname + file; + std::sort(res.begin(), res.end()); + return res; + } + typedef decltype(stat::st_mtime) TimeSpec; struct CommandCache @@ -358,17 +377,8 @@ std::vector complete_command(StringView prefix, ByteCount cursor_pos) }; static UnorderedMap command_cache; - std::vector path; - if (dir_end != -1) - { - path.emplace_back(real_prefix.substr(0, dir_end + 1)); - fileprefix = real_prefix.substr(dir_end + 1); - } - else - path = split(getenv("PATH"), ':'); - std::vector res; - for (auto dir : path) + for (auto dir : split(getenv("PATH"), ':')) { String dirname = dir; if (not dirname.empty() and dirname.back() != '/') @@ -396,7 +406,7 @@ std::vector complete_command(StringView prefix, ByteCount cursor_pos) } for (auto& cmd : cache.commands) { - if (prefix_match(cmd, fileprefix)) + if (prefix_match(cmd, real_prefix)) res.push_back(cmd); } }