Add support for line completion in all buffers

- via completers option with line=all vs line=buffer
- via <c-x> L mapping
This commit is contained in:
Delapouite 2017-10-26 13:04:28 +02:00
parent 9bd9fecb53
commit 0568836943
4 changed files with 61 additions and 21 deletions

View File

@ -718,6 +718,7 @@ using `<c-x>`, followed, by:
* *w* : word completion (current buffer) * *w* : word completion (current buffer)
* *W* : word completion (all buffers) * *W* : word completion (all buffers)
* *l* : line completion (current buffer) * *l* : line completion (current buffer)
* *L* : line completion (all buffers)
Completion candidates can be selected using `<c-n>` and `<c-p>`. Completion candidates can be selected using `<c-n>` and `<c-p>`.

View File

@ -1223,12 +1223,15 @@ public:
if (key.key == 'W') if (key.key == 'W')
m_completer.explicit_word_all_complete(); m_completer.explicit_word_all_complete();
if (key.key == 'l') if (key.key == 'l')
m_completer.explicit_line_complete(); m_completer.explicit_line_buffer_complete();
if (key.key == 'L')
m_completer.explicit_line_all_complete();
}, "enter completion type", }, "enter completion type",
"f: filename\n" "f: filename\n"
"w: word (current buffer)\n" "w: word (current buffer)\n"
"W: word (all buffers)\n" "W: word (all buffers)\n"
"l: line\n"); "l: line (current buffer)\n"
"L: line (all buffers)\n");
update_completions = false; update_completions = false;
} }
else if (key == ctrl('o')) else if (key == ctrl('o'))

View File

@ -33,7 +33,7 @@ String option_to_string(const InsertCompleterDesc& opt)
case InsertCompleterDesc::Option: case InsertCompleterDesc::Option:
return "option=" + (opt.param ? *opt.param : ""); return "option=" + (opt.param ? *opt.param : "");
case InsertCompleterDesc::Line: case InsertCompleterDesc::Line:
return "line"; return "line=" + (opt.param ? *opt.param : "");
} }
kak_assert(false); kak_assert(false);
return ""; return "";
@ -63,12 +63,16 @@ void option_from_string(StringView str, InsertCompleterDesc& opt)
opt.param = Optional<String>{}; opt.param = Optional<String>{};
return; return;
} }
else if (str == "line") else if (str.substr(0_byte, 5_byte) == "line=")
{
auto param = str.substr(5_byte);
if (param == "all" or param == "buffer")
{ {
opt.mode = InsertCompleterDesc::Line; opt.mode = InsertCompleterDesc::Line;
opt.param = Optional<String>{}; opt.param = param.str();
return; return;
} }
}
throw runtime_error(format("invalid completer description: '{}'", str)); throw runtime_error(format("invalid completer description: '{}'", str));
} }
@ -342,6 +346,7 @@ InsertCompletion complete_option(const SelectionList& sels,
return {}; return {};
} }
template<bool other_buffers>
InsertCompletion complete_line(const SelectionList& sels, const OptionManager& options) InsertCompletion complete_line(const SelectionList& sels, const OptionManager& options)
{ {
const Buffer& buffer = sels.buffer(); const Buffer& buffer = sels.buffer();
@ -352,18 +357,37 @@ InsertCompletion complete_line(const SelectionList& sels, const OptionManager& o
StringView prefix = buffer[cursor_pos.line].substr(0_byte, cursor_pos.column); StringView prefix = buffer[cursor_pos.line].substr(0_byte, cursor_pos.column);
InsertCompletion::CandidateList candidates; InsertCompletion::CandidateList candidates;
for (LineCount l = 0_line; l < buffer.line_count(); ++l)
auto add_candidates = [&](const Buffer& buf) {
for (LineCount l = 0_line; l < buf.line_count(); ++l)
{ {
if (l == cursor_pos.line) // perf: it's unlikely the user intends to search among >10 candidates anyway
if (candidates.size() == 100)
break;
if (buf.name() == buffer.name() && l == cursor_pos.line)
continue; continue;
ByteCount len = buffer[l].length(); ByteCount len = buf[l].length();
if (len > cursor_pos.column and std::equal(prefix.begin(), prefix.end(), buffer[l].begin())) if (len > cursor_pos.column and std::equal(prefix.begin(), prefix.end(), buf[l].begin()))
{ {
StringView candidate = buffer[l].substr(0_byte, len-1); StringView candidate = buf[l].substr(0_byte, len-1);
candidates.push_back({candidate.str(), "", candidates.push_back({candidate.str(), "",
expand_tabs(candidate, tabstop, column)}); expand_tabs(candidate, tabstop, column)});
} }
} }
};
add_candidates(buffer);
if (other_buffers)
{
for (const auto& buf : BufferManager::instance())
{
if (buf.get() == &buffer or buf->flags() & Buffer::Flags::Debug)
continue;
add_candidates(*buf);
}
}
if (candidates.empty()) if (candidates.empty())
return {}; return {};
std::sort(candidates.begin(), candidates.end()); std::sort(candidates.begin(), candidates.end());
@ -500,7 +524,12 @@ bool InsertCompleter::setup_ifn()
try_complete(complete_word<true>)) try_complete(complete_word<true>))
return true; return true;
if (completer.mode == InsertCompleterDesc::Line and if (completer.mode == InsertCompleterDesc::Line and
try_complete(complete_line)) *completer.param == "buffer" and
try_complete(complete_line<false>))
return true;
if (completer.mode == InsertCompleterDesc::Line and
*completer.param == "all" and
try_complete(complete_line<true>))
return true; return true;
} }
return false; return false;
@ -584,10 +613,16 @@ void InsertCompleter::explicit_word_all_complete()
m_explicit_completer = complete_word<true>; m_explicit_completer = complete_word<true>;
} }
void InsertCompleter::explicit_line_complete() void InsertCompleter::explicit_line_buffer_complete()
{ {
try_complete(complete_line); try_complete(complete_line<false>);
m_explicit_completer = complete_line; m_explicit_completer = complete_line<false>;
}
void InsertCompleter::explicit_line_all_complete()
{
try_complete(complete_line<true>);
m_explicit_completer = complete_line<true>;
} }
} }

View File

@ -88,7 +88,8 @@ public:
void explicit_file_complete(); void explicit_file_complete();
void explicit_word_buffer_complete(); void explicit_word_buffer_complete();
void explicit_word_all_complete(); void explicit_word_all_complete();
void explicit_line_complete(); void explicit_line_buffer_complete();
void explicit_line_all_complete();
private: private:
bool setup_ifn(); bool setup_ifn();