From 777a79d37c675540052e0d4212800e877905e49e Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Wed, 12 Dec 2012 13:51:15 +0100 Subject: [PATCH] File completion: when no files match entered text as prefix, try as regex --- src/completion.cc | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/completion.cc b/src/completion.cc index 7f9325fe..8ee18aa2 100644 --- a/src/completion.cc +++ b/src/completion.cc @@ -13,6 +13,20 @@ namespace Kakoune { +static boost::regex make_regex_ifp(const String& ex) +{ + boost::regex result; + if (not ex.empty()) + { + try + { + result = boost::regex(ex.c_str()); + } + catch(boost::regex_error&) {} + } + return result; +} + CandidateList complete_filename(const Context& context, const String& prefix, ByteCount cursor_pos) @@ -22,10 +36,7 @@ CandidateList complete_filename(const Context& context, String dirprefix; String fileprefix = real_prefix; - String ignored_files = context.options()["ignored_files"].as_string(); - boost::regex ignored_files_regex; - if (not ignored_files.empty()) - ignored_files_regex = boost::regex(ignored_files.c_str()); + boost::regex ignored_files = make_regex_ifp(context.options()["ignored_files"].as_string()); ByteCount dir_end = -1; for (ByteCount i = 0; i < real_prefix.length(); ++i) @@ -41,36 +52,47 @@ CandidateList complete_filename(const Context& context, } DIR* dir = opendir(dirname.c_str()); - auto closeDir = on_scope_end([=](){ closedir(dir); }); + auto closeDir = on_scope_end([=]{ closedir(dir); }); CandidateList result; if (not dir) return result; const bool check_ignored_files = not ignored_files.empty() and - not boost::regex_match(fileprefix.c_str(), ignored_files_regex); + not boost::regex_match(fileprefix.c_str(), ignored_files); + boost::regex file_regex = make_regex_ifp(fileprefix); + CandidateList regex_result; while (dirent* entry = readdir(dir)) { String filename = entry->d_name; if (filename.empty()) continue; - if (check_ignored_files and - boost::regex_match(filename.c_str(), ignored_files_regex)) + if (check_ignored_files and boost::regex_match(filename.c_str(), ignored_files)) continue; - if (filename.substr(0, fileprefix.length()) == fileprefix) + const bool match_prefix = (filename.substr(0, fileprefix.length()) == fileprefix); + const bool match_regex = not file_regex.empty() and + boost::regex_match(filename.c_str(), file_regex); + + if (match_prefix or match_regex) { String name = dirprefix + filename; if (entry->d_type == DT_DIR) name += '/'; if (fileprefix.length() != 0 or filename[0] != '.') - result.push_back(escape(name)); + { + if (match_prefix) + result.push_back(escape(name)); + if (match_regex) + regex_result.push_back(escape(name)); + } } } - std::sort(result.begin(), result.end()); - return result; + CandidateList& real_result = result.empty() ? regex_result : result; + std::sort(real_result.begin(), real_result.end()); + return real_result; } }