diff --git a/src/buffer_manager.cc b/src/buffer_manager.cc index 37bef1bb..c830d011 100644 --- a/src/buffer_manager.cc +++ b/src/buffer_manager.cc @@ -103,7 +103,7 @@ CandidateList BufferManager::complete_buffername(const String& prefix, for (auto& buffer : m_buffers) { String name = buffer->display_name(); - if (name.substr(0, real_prefix.length()) == real_prefix) + if (prefix_match(name, real_prefix)) result.push_back(escape(name)); } // no prefix completion found, check regex matching diff --git a/src/client.cc b/src/client.cc index ca6f047c..f43203bb 100644 --- a/src/client.cc +++ b/src/client.cc @@ -350,11 +350,10 @@ public: m_prefix = line; auto it = m_history_it; // search for the previous history entry matching typed prefix - ByteCount prefix_length = m_prefix.length(); do { --it; - if (it->substr(0, prefix_length) == m_prefix) + if (prefix_match(*it, m_prefix)) { m_history_it = it; m_line_editor.reset(*it); @@ -368,11 +367,10 @@ public: { if (m_history_it != history.end()) { - ByteCount prefix_length = m_prefix.length(); // search for the next history entry matching typed prefix ++m_history_it; while (m_history_it != history.end() and - m_history_it->substr(0, prefix_length) != m_prefix) + prefix_match(*m_history_it, m_prefix)) ++m_history_it; if (m_history_it != history.end()) diff --git a/src/command_manager.cc b/src/command_manager.cc index c8e5d05a..c62d75fa 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -337,7 +337,7 @@ Completions CommandManager::complete(const Context& context, for (auto& command : m_commands) { - if (command.first.substr(0, prefix.length()) == prefix) + if (prefix_match(command.first, prefix)) result.candidates.push_back(command.first); } std::sort(result.candidates.begin(), result.candidates.end()); diff --git a/src/file.cc b/src/file.cc index ed4a8276..e8aa87b7 100644 --- a/src/file.cc +++ b/src/file.cc @@ -74,7 +74,7 @@ String compact_path(const String& filename) char cwd[1024]; getcwd(cwd, 1024); String real_cwd = real_path(cwd) + '/'; - if (real_filename.substr(0, real_cwd.length()) == real_cwd) + if (prefix_match(real_filename, real_cwd)) return real_filename.substr(real_cwd.length()); const char* home = getenv("HOME"); @@ -302,7 +302,7 @@ std::vector complete_filename(const String& prefix, if (check_ignored_regex and boost::regex_match(filename.c_str(), ignored_regex)) continue; - const bool match_prefix = (filename.substr(0, fileprefix.length()) == fileprefix); + const bool match_prefix = prefix_match(filename, fileprefix); const bool match_regex = not file_regex.empty() and boost::regex_match(filename.c_str(), file_regex); diff --git a/src/idvaluemap.hh b/src/idvaluemap.hh index 3a263c6e..9efbdd68 100644 --- a/src/idvaluemap.hh +++ b/src/idvaluemap.hh @@ -78,7 +78,7 @@ public: continue; String id_str = value.first; - if (id_str.substr(0, real_prefix.length()) == real_prefix) + if (prefix_match(id_str, real_prefix)) result.push_back(std::move(id_str)); } return result; diff --git a/src/option_manager.cc b/src/option_manager.cc index 5bca3323..daef90bb 100644 --- a/src/option_manager.cc +++ b/src/option_manager.cc @@ -73,8 +73,7 @@ CandidateList OptionManager::complete_option_name(const String& prefix, for (auto& option : m_options) { const auto& name = option->name(); - if (name.substr(0, real_prefix.length()) == real_prefix and - not contains(result, name)) + if (prefix_match(name, real_prefix) and not contains(result, name)) result.push_back(name); } return result; diff --git a/src/string.cc b/src/string.cc index dcfc1037..870cdf9e 100644 --- a/src/string.cc +++ b/src/string.cc @@ -83,4 +83,15 @@ void option_from_string(const String& str, Regex& re) } } +bool prefix_match(const String& str, const String& prefix) +{ + auto it = str.begin(); + for (auto& c : prefix) + { + if (it ==str.end() or *it++ != c) + return false; + } + return true; +} + } diff --git a/src/string.hh b/src/string.hh index f4a93309..25e051dc 100644 --- a/src/string.hh +++ b/src/string.hh @@ -112,6 +112,8 @@ String to_string(const StronglyTypedNumber& val) return to_string((ValueType)val); } +bool prefix_match(const String& str, const String& prefix); + } namespace std diff --git a/src/unit_tests.cc b/src/unit_tests.cc index c0d8a15b..589a83fe 100644 --- a/src/unit_tests.cc +++ b/src/unit_tests.cc @@ -136,6 +136,11 @@ void test_string() String escaped = escape("youpi:matin:tchou:", ':', '\\'); kak_assert(escaped == "youpi\\:matin\\:tchou\\:"); + + kak_assert(prefix_match("tchou kanaky", "tchou")); + kak_assert(prefix_match("tchou kanaky", "tchou kanaky")); + kak_assert(prefix_match("tchou kanaky", "t")); + kak_assert(not prefix_match("tchou kanaky", "c")); } void test_keys()