Minor BufferCompleter refactoring
This commit is contained in:
parent
417682883e
commit
96b017f76e
|
@ -450,10 +450,19 @@ private:
|
||||||
KeyCallback m_callback;
|
KeyCallback m_callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::pair<CandidateList, BufferIterator> complete_word(const BufferIterator& pos)
|
struct BufferCompletion
|
||||||
|
{
|
||||||
|
BufferIterator begin;
|
||||||
|
BufferIterator end;
|
||||||
|
CandidateList candidates;
|
||||||
|
|
||||||
|
bool is_valid() const { return begin.is_valid() and not candidates.empty(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
static BufferCompletion complete_word(const BufferIterator& pos)
|
||||||
{
|
{
|
||||||
if (pos.is_begin() or not is_word(*utf8::previous(pos)))
|
if (pos.is_begin() or not is_word(*utf8::previous(pos)))
|
||||||
return { {}, pos };
|
return {};
|
||||||
|
|
||||||
BufferIterator end = pos;
|
BufferIterator end = pos;
|
||||||
BufferIterator begin = end-1;
|
BufferIterator begin = end-1;
|
||||||
|
@ -479,15 +488,15 @@ static std::pair<CandidateList, BufferIterator> complete_word(const BufferIterat
|
||||||
result.emplace_back(std::move(content));
|
result.emplace_back(std::move(content));
|
||||||
}
|
}
|
||||||
std::sort(result.begin(), result.end());
|
std::sort(result.begin(), result.end());
|
||||||
return { std::move(result), begin };
|
return { begin, end, std::move(result) };
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::pair<CandidateList, BufferIterator> complete_opt(const BufferIterator& pos, OptionManager& options)
|
static BufferCompletion complete_opt(const BufferIterator& pos, OptionManager& options)
|
||||||
{
|
{
|
||||||
using StringList = std::vector<String>;
|
using StringList = std::vector<String>;
|
||||||
const StringList& opt = options["completions"].get<StringList>();
|
const StringList& opt = options["completions"].get<StringList>();
|
||||||
if (opt.empty())
|
if (opt.empty())
|
||||||
return { {}, pos };
|
return {};
|
||||||
|
|
||||||
auto& desc = opt[0];
|
auto& desc = opt[0];
|
||||||
Regex re(R"((\d+):(\d+)@(\d+))");
|
Regex re(R"((\d+):(\d+)@(\d+))");
|
||||||
|
@ -499,9 +508,9 @@ static std::pair<CandidateList, BufferIterator> complete_opt(const BufferIterato
|
||||||
int timestamp = str_to_int(String(match[3].first, match[3].second));
|
int timestamp = str_to_int(String(match[3].first, match[3].second));
|
||||||
|
|
||||||
if (timestamp == pos.buffer().timestamp() and line == pos.line() and column == pos.column())
|
if (timestamp == pos.buffer().timestamp() and line == pos.line() and column == pos.column())
|
||||||
return { { opt.begin() + 1, opt.end() }, pos };
|
return { pos, pos, { opt.begin() + 1, opt.end() } };
|
||||||
}
|
}
|
||||||
return { {}, pos };
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
class BufferCompleter : public OptionManagerWatcher
|
class BufferCompleter : public OptionManagerWatcher
|
||||||
|
@ -524,39 +533,44 @@ public:
|
||||||
if (not setup_ifn())
|
if (not setup_ifn())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_context.buffer().erase(m_position, m_position + m_matching_completions[m_current_completion].length());
|
m_current_candidate = (m_current_candidate + offset) % (int)m_matching_candidates.size();
|
||||||
m_current_completion = (m_current_completion + offset) % (int)m_matching_completions.size();
|
if (m_current_candidate < 0)
|
||||||
if (m_current_completion < 0)
|
m_current_candidate += m_matching_candidates.size();
|
||||||
m_current_completion += m_matching_completions.size();
|
const String& candidate = m_matching_candidates[m_current_candidate];
|
||||||
m_context.buffer().insert(m_position, m_matching_completions[m_current_completion]);
|
|
||||||
m_context.ui().menu_select(m_current_completion);
|
m_context.buffer().erase(m_completions.begin, m_completions.end);
|
||||||
|
m_context.buffer().insert(m_completions.begin, candidate);
|
||||||
|
m_completions.end = m_completions.begin + candidate.length();
|
||||||
|
m_context.ui().menu_select(m_current_candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
{
|
{
|
||||||
if (m_position.is_valid())
|
if (m_completions.is_valid())
|
||||||
{
|
{
|
||||||
|
ByteCount longest_completion = 0;
|
||||||
|
for (auto& candidate : m_completions.candidates)
|
||||||
|
longest_completion = std::max(longest_completion, candidate.length());
|
||||||
|
|
||||||
BufferIterator cursor = m_context.editor().main_selection().last();
|
BufferIterator cursor = m_context.editor().main_selection().last();
|
||||||
ByteCount longest_completion = std::max_element(m_all_completions.begin(), m_all_completions.end(),
|
if (cursor > m_completions.begin and ByteCount{(int)(cursor - m_completions.begin)} < longest_completion)
|
||||||
[](const String& lhs, const String& rhs)
|
|
||||||
{ return lhs.length() < rhs.length(); })->length();
|
|
||||||
if (cursor > m_position and ByteCount{(int)(cursor - m_position)} < longest_completion)
|
|
||||||
{
|
{
|
||||||
String prefix = m_context.buffer().string(m_position, cursor);
|
String prefix = m_context.buffer().string(m_completions.begin, cursor);
|
||||||
m_matching_completions.clear();
|
m_matching_candidates.clear();
|
||||||
for (auto& candidate : m_all_completions)
|
for (auto& candidate : m_completions.candidates)
|
||||||
{
|
{
|
||||||
if (candidate.substr(0, prefix.length()) == prefix)
|
if (candidate.substr(0, prefix.length()) == prefix)
|
||||||
m_matching_completions.push_back(candidate);
|
m_matching_candidates.push_back(candidate);
|
||||||
}
|
}
|
||||||
if (not m_matching_completions.empty())
|
if (not m_matching_candidates.empty())
|
||||||
{
|
{
|
||||||
m_context.ui().menu_hide();
|
m_context.ui().menu_hide();
|
||||||
m_current_completion = m_matching_completions.size();
|
m_current_candidate = m_matching_candidates.size();
|
||||||
DisplayCoord menu_pos = m_context.window().display_position(m_position);
|
DisplayCoord menu_pos = m_context.window().display_position(m_completions.begin);
|
||||||
m_context.ui().menu_show(m_matching_completions, menu_pos, MenuStyle::Inline);
|
m_context.ui().menu_show(m_matching_candidates, menu_pos, MenuStyle::Inline);
|
||||||
m_context.ui().menu_select(m_current_completion);
|
m_context.ui().menu_select(m_current_candidate);
|
||||||
m_matching_completions.push_back(prefix);
|
m_completions.end = cursor;
|
||||||
|
m_matching_candidates.push_back(prefix);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -567,7 +581,7 @@ public:
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
m_position = BufferIterator();
|
m_completions = BufferCompletion{};
|
||||||
m_context.ui().menu_hide();
|
m_context.ui().menu_hide();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
@ -582,33 +596,30 @@ private:
|
||||||
|
|
||||||
bool setup_ifn()
|
bool setup_ifn()
|
||||||
{
|
{
|
||||||
if (not m_position.is_valid())
|
if (not m_completions.is_valid())
|
||||||
{
|
{
|
||||||
BufferIterator cursor = m_context.editor().main_selection().last();
|
BufferIterator cursor = m_context.editor().main_selection().last();
|
||||||
auto completions = complete_opt(cursor, m_context.options());
|
m_completions = complete_opt(cursor, m_context.options());
|
||||||
if (completions.first.empty())
|
if (not m_completions.is_valid())
|
||||||
completions = complete_word(cursor);
|
m_completions = complete_word(cursor);
|
||||||
m_all_completions = std::move(completions.first);
|
if (not m_completions.is_valid())
|
||||||
if (m_all_completions.empty())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
assert(cursor >= completions.second);
|
assert(cursor >= m_completions.begin);
|
||||||
m_position = completions.second;
|
|
||||||
|
|
||||||
m_matching_completions = m_all_completions;
|
m_matching_candidates = m_completions.candidates;
|
||||||
DisplayCoord menu_pos = m_context.window().display_position(m_position);
|
DisplayCoord menu_pos = m_context.window().display_position(m_completions.begin);
|
||||||
m_context.ui().menu_show(m_matching_completions, menu_pos, MenuStyle::Inline);
|
m_context.ui().menu_show(m_matching_candidates, menu_pos, MenuStyle::Inline);
|
||||||
m_matching_completions.push_back(m_context.buffer().string(m_position, cursor));
|
m_matching_candidates.push_back(m_context.buffer().string(m_completions.begin, m_completions.end));
|
||||||
m_current_completion = m_matching_completions.size() - 1;
|
m_current_candidate = m_matching_candidates.size() - 1;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Context& m_context;
|
const Context& m_context;
|
||||||
BufferIterator m_position;
|
BufferCompletion m_completions;
|
||||||
CandidateList m_all_completions;
|
CandidateList m_matching_candidates;
|
||||||
CandidateList m_matching_completions;
|
int m_current_candidate = -1;
|
||||||
int m_current_completion = -1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Insert : public InputMode
|
class Insert : public InputMode
|
||||||
|
|
Loading…
Reference in New Issue
Block a user