diff --git a/autoload/cpsm.py b/autoload/cpsm.py index 5da99df..1e7d1b4 100644 --- a/autoload/cpsm.py +++ b/autoload/cpsm.py @@ -36,6 +36,7 @@ def ctrlp_match(): match_crfile=int(vim.eval("s:match_crfile")), max_threads=int(vim.eval("g:cpsm_max_threads")), query_inverting_delimiter=vim.eval("g:cpsm_query_inverting_delimiter"), + regex_line_prefix=vim.eval("s:regex_line_prefix"), unicode=int(vim.eval("g:cpsm_unicode"))) # Escape backslashes and ". vim.command("let s:results = [%s]" % ",".join( diff --git a/autoload/cpsm.vim b/autoload/cpsm.vim index fdcfa18..7fca6ea 100644 --- a/autoload/cpsm.vim +++ b/autoload/cpsm.vim @@ -74,6 +74,10 @@ function cpsm#CtrlPMatch(items, str, limit, mmode, ispath, crfile, regex) elseif s:status == 1 return ['ERROR: cpsm built with version of Python not supported by Vim'] endif + let s:regex_line_prefix = '> ' + if exists('g:ctrlp_line_prefix') + let s:regex_line_prefix = g:ctrlp_line_prefix + endif if empty(a:str) && g:cpsm_match_empty_query == 0 let s:results = a:items[0:(a:limit)] let s:regexes = [] diff --git a/src/ctrlp_util.cc b/src/ctrlp_util.cc index 38840b9..dadd21b 100644 --- a/src/ctrlp_util.cc +++ b/src/ctrlp_util.cc @@ -86,38 +86,42 @@ CtrlPMatchMode parse_ctrlp_match_mode(boost::string_ref const mmode) { void get_highlight_regexes(boost::string_ref const mode, boost::string_ref const item, std::vector const& positions, - std::vector& regexes) { + std::vector& regexes, + boost::string_ref const line_prefix) { for (auto const group : group_positions(mode, positions)) { // Each match group's regex has the same structure: // - "\V": very nomagic (only "\" needs to be escaped) // - "\C": forces case sensitivity // - "\^": beginning of string - // - "> ": appears at the start of each line + // - the line prefix // - characters in the item before the match // - "\zs": starts the match // - characters in the match group // - "\ze": ends the match // - characters in the item after the match // - "\$": end of string - std::size_t i = 0; - std::string regex = R"(\V\C\^> )"; - auto const write_char = [&](std::size_t i) { - if (item[i] == '\\') { + std::string regex = R"(\V\C\^)"; + auto const write_char = [&](char c) { + if (c == '\\') { regex += R"(\\)"; } else { - regex += item[i]; + regex += c; } }; + for (char const c : line_prefix) { + write_char(c); + } + std::size_t i = 0; for (; i < group.first; i++) { - write_char(i); + write_char(item[i]); } regex += R"(\zs)"; for (; i < group.second; i++) { - write_char(i); + write_char(item[i]); } regex += R"(\ze)"; for (; i < item.size(); i++) { - write_char(i); + write_char(item[i]); } regex += R"(\$)"; regexes.emplace_back(std::move(regex)); diff --git a/src/ctrlp_util.h b/src/ctrlp_util.h index dc9bfc2..3ce68ff 100644 --- a/src/ctrlp_util.h +++ b/src/ctrlp_util.h @@ -98,7 +98,8 @@ struct CtrlPItem { // for the given highlight mode. `positions` must be sorted. void get_highlight_regexes(boost::string_ref mode, boost::string_ref item, std::vector const& positions, - std::vector& regexes); + std::vector& regexes, + boost::string_ref line_prefix); } // namespace cpsm diff --git a/src/python_extension.cc b/src/python_extension.cc index 070010f..9377536 100644 --- a/src/python_extension.cc +++ b/src/python_extension.cc @@ -267,6 +267,7 @@ constexpr char CTRLP_MATCH_DOC[] = "match_crfile -- if false, never match `crfile`\n" "max_threads -- if positive, limit on the number of matcher threads\n" "query_inverting_delimiter -- see README\n" +"regex_line_prefix -- prefix for each regex in `regexes`\n" "unicode -- if true, all items are UTF-8-encoded"; static PyObject* cpsm_ctrlp_match(PyObject* self, PyObject* args, @@ -274,7 +275,7 @@ static PyObject* cpsm_ctrlp_match(PyObject* self, PyObject* args, static char const* kwlist[] = {"items", "query", "limit", "mmode", "ispath", "crfile", "highlight_mode", "match_crfile", "max_threads", "query_inverting_delimiter", - "unicode", nullptr}; + "regex_line_prefix", "unicode", nullptr}; // Required parameters. PyObject* items_obj; char const* query_data; @@ -293,14 +294,17 @@ static PyObject* cpsm_ctrlp_match(PyObject* self, PyObject* args, int max_threads_int = 0; char const* query_inverting_delimiter_data = nullptr; Py_ssize_t query_inverting_delimiter_size = 0; + char const* regex_line_prefix_data = nullptr; + Py_ssize_t regex_line_prefix_size = 0; int unicode = 0; if (!PyArg_ParseTupleAndKeywords( - args, kwargs, "Os#|iz#iz#z#iiz#i", const_cast(kwlist), + args, kwargs, "Os#|iz#iz#z#iiz#z#i", const_cast(kwlist), &items_obj, &query_data, &query_size, &limit_int, &mmode_data, &mmode_size, &is_path, &crfile_data, &crfile_size, &highlight_mode_data, &highlight_mode_size, &match_crfile, &max_threads_int, &query_inverting_delimiter_data, - &query_inverting_delimiter_size, &unicode)) { + &query_inverting_delimiter_size, ®ex_line_prefix_data, + ®ex_line_prefix_size, &unicode)) { return nullptr; } @@ -357,8 +361,10 @@ static PyObject* cpsm_ctrlp_match(PyObject* self, PyObject* args, for (auto& pos : match_positions) { pos += delta; } - cpsm::get_highlight_regexes(highlight_mode, item, match_positions, - highlight_regexes); + cpsm::get_highlight_regexes( + highlight_mode, item, match_positions, highlight_regexes, + boost::string_ref(regex_line_prefix_data, + regex_line_prefix_size)); }); if (PyTuple_SetItem(output_tuple.get(), 0, matches_list.release())) { return nullptr;