summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2014-12-21 17:08:33 +0000
committerMaxime Coste <frrrwww@gmail.com>2014-12-21 17:08:33 +0000
commit7a7ad57871dc23882c482a52fbd258923b59cdf0 (patch)
treec5791cff87240ea8343123deacb7f976d415ecc1 /src
parent5b94b7315223bb30709700f886c8de9771f5657a (diff)
Support absolute paths when completing commands
Diffstat (limited to 'src')
-rw-r--r--src/file.cc36
1 files changed, 23 insertions, 13 deletions
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<String> complete_filename(StringView prefix,
std::vector<String> 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<String> 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<String> 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<String> complete_command(StringView prefix, ByteCount cursor_pos)
};
static UnorderedMap<String, CommandCache> command_cache;
- std::vector<StringView> 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<String> 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<String> 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);
}
}