diff --git a/src/commands.cc b/src/commands.cc index e6008b3d..49555f88 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -424,7 +424,7 @@ void define_command(const CommandParameters& params, Context& context) { const String& prefix = token_to_complete < params.size() ? params[token_to_complete] : String(); - return complete_filename(context, prefix, pos_in_token); + return complete_filename(context.options()["ignored_files"].get(), prefix, pos_in_token); }; } else if (parser.has_option("shell-completion")) @@ -790,7 +790,10 @@ void register_commands() cm.register_commands({"nop"}, [](const CommandParameters&, Context&){}); - PerArgumentCommandCompleter filename_completer({ complete_filename }); + PerArgumentCommandCompleter filename_completer({ + [](const Context& context, const String& prefix, ByteCount cursor_pos) + { return complete_filename(prefix, context.options()["ignored_files"].get(), cursor_pos); } + }); cm.register_commands({ "e", "edit" }, edit, filename_completer); cm.register_commands({ "e!", "edit!" }, edit, filename_completer); cm.register_commands({ "w", "write" }, write_buffer, filename_completer); diff --git a/src/completion.cc b/src/completion.cc deleted file mode 100644 index 99801cdc..00000000 --- a/src/completion.cc +++ /dev/null @@ -1,102 +0,0 @@ -#include "completion.hh" - -#include "buffer_manager.hh" -#include "utils.hh" -#include "file.hh" -#include "context.hh" -#include "debug.hh" - -#include -#include - -#include - -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& err) - { - write_debug(err.what()); - } - } - return result; -} - -CandidateList complete_filename(const Context& context, - const String& prefix, - ByteCount cursor_pos) -{ - String real_prefix = parse_filename(prefix.substr(0, cursor_pos)); - String dirname = "./"; - String dirprefix; - String fileprefix = real_prefix; - - boost::regex ignored_files = make_regex_ifp(context.options()["ignored_files"].get()); - - ByteCount dir_end = -1; - for (ByteCount i = 0; i < real_prefix.length(); ++i) - { - if (real_prefix[i] == '/') - dir_end = i; - } - if (dir_end != -1) - { - dirname = real_prefix.substr(0, dir_end + 1); - dirprefix = dirname; - fileprefix = real_prefix.substr(dir_end + 1); - } - - DIR* dir = opendir(dirname.c_str()); - 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); - - 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)) - continue; - - 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] != '.') - { - if (match_prefix) - result.push_back(escape(name)); - if (match_regex) - regex_result.push_back(escape(name)); - } - } - } - CandidateList& real_result = result.empty() ? regex_result : result; - std::sort(real_result.begin(), real_result.end()); - return real_result; -} - -} diff --git a/src/completion.hh b/src/completion.hh index 45c25149..06dd3a53 100644 --- a/src/completion.hh +++ b/src/completion.hh @@ -26,10 +26,6 @@ struct Completions : start(start), end(end) {} }; -CandidateList complete_filename(const Context& context, - const String& prefix, - ByteCount cursor_pos = -1); - typedef std::function Completer; diff --git a/src/file.cc b/src/file.cc index caa93127..2922a835 100644 --- a/src/file.cc +++ b/src/file.cc @@ -3,16 +3,16 @@ #include "buffer.hh" #include "buffer_manager.hh" #include "assert.hh" - #include "unicode.hh" +#include "debug.hh" +#include "completion.hh" #include #include #include #include #include -#include - +#include namespace Kakoune { @@ -199,4 +199,89 @@ String find_file(const String& filename, const memoryview& paths) return ""; } +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& err) + { + write_debug(err.what()); + } + } + return result; +} + +std::vector complete_filename(const String& prefix, + const String& ignored_regex, + ByteCount cursor_pos) +{ + String real_prefix = parse_filename(prefix.substr(0, cursor_pos)); + String dirname = "./"; + String dirprefix; + String fileprefix = real_prefix; + + boost::regex ignored_files = make_regex_ifp(ignored_regex); + + ByteCount dir_end = -1; + for (ByteCount i = 0; i < real_prefix.length(); ++i) + { + if (real_prefix[i] == '/') + dir_end = i; + } + if (dir_end != -1) + { + dirname = real_prefix.substr(0, dir_end + 1); + dirprefix = dirname; + fileprefix = real_prefix.substr(dir_end + 1); + } + + DIR* dir = opendir(dirname.c_str()); + auto closeDir = on_scope_end([=]{ closedir(dir); }); + + std::vector 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); + + boost::regex file_regex = make_regex_ifp(fileprefix); + std::vector 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)) + continue; + + 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] != '.') + { + if (match_prefix) + result.push_back(escape(name)); + if (match_regex) + regex_result.push_back(escape(name)); + } + } + } + auto& real_result = result.empty() ? regex_result : result; + std::sort(real_result.begin(), real_result.end()); + return real_result; +} + } diff --git a/src/file.hh b/src/file.hh index 82f2015c..eb2f79ba 100644 --- a/src/file.hh +++ b/src/file.hh @@ -32,6 +32,9 @@ Buffer* create_buffer_from_file(const String& filename); void write_buffer_to_file(const Buffer& buffer, const String& filename); String find_file(const String& filename, const memoryview& paths); +std::vector complete_filename(const String& prefix, + const String& ignore_regex, + ByteCount cursor_pos = -1); } #endif // file_hh_INCLUDED