Add support for explicit completion in prompt mode
This commit is contained in:
parent
600be827b3
commit
f549190a98
|
@ -794,6 +794,15 @@ The following keys are recognized by this mode to help with editing
|
||||||
*<c-v>*::
|
*<c-v>*::
|
||||||
insert next keystroke without interpreting it
|
insert next keystroke without interpreting it
|
||||||
|
|
||||||
|
*<c-x>*::
|
||||||
|
explicit completion query, followed by:
|
||||||
|
|
||||||
|
*f*:::
|
||||||
|
explicit file completion
|
||||||
|
|
||||||
|
*w*:::
|
||||||
|
explicit word completion (from current buffer)
|
||||||
|
|
||||||
*<c-o>*::
|
*<c-o>*::
|
||||||
toggle automatic completion
|
toggle automatic completion
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "user_interface.hh"
|
#include "user_interface.hh"
|
||||||
#include "utf8.hh"
|
#include "utf8.hh"
|
||||||
#include "window.hh"
|
#include "window.hh"
|
||||||
|
#include "word_db.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -929,9 +930,40 @@ public:
|
||||||
m_refresh_completion_pending = true;
|
m_refresh_completion_pending = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (key == ctrl('x'))
|
||||||
|
{
|
||||||
|
on_next_key_with_autoinfo(context(), "explicit-completion", KeymapMode::None,
|
||||||
|
[this](Key key, Context&) {
|
||||||
|
m_explicit_completer = PromptCompleter{};
|
||||||
|
|
||||||
|
if (key.key == 'f')
|
||||||
|
use_explicit_completer([](const Context& context, StringView token) {
|
||||||
|
return complete_filename(token, context.options()["ignored_files"].get<Regex>(),
|
||||||
|
token.length(), FilenameFlags::Expand);
|
||||||
|
});
|
||||||
|
else if (key.key == 'w')
|
||||||
|
use_explicit_completer([](const Context& context, StringView token) {
|
||||||
|
CandidateList candidates;
|
||||||
|
for_n_best(get_word_db(context.buffer()).find_matching(token),
|
||||||
|
100, [](auto& lhs, auto& rhs){ return rhs < lhs; },
|
||||||
|
[&](RankedMatch& m) {
|
||||||
|
candidates.push_back(m.candidate().str());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return candidates;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (m_explicit_completer)
|
||||||
|
refresh_completions(CompletionFlags::None);
|
||||||
|
}, "enter completion type",
|
||||||
|
"f: filename\n"
|
||||||
|
"w: buffer word\n");
|
||||||
|
}
|
||||||
else if (key == ctrl('o'))
|
else if (key == ctrl('o'))
|
||||||
{
|
{
|
||||||
|
m_explicit_completer = PromptCompleter{};
|
||||||
m_auto_complete = not m_auto_complete;
|
m_auto_complete = not m_auto_complete;
|
||||||
|
|
||||||
if (m_auto_complete)
|
if (m_auto_complete)
|
||||||
refresh_completions(CompletionFlags::Fast);
|
refresh_completions(CompletionFlags::Fast);
|
||||||
else if (context().has_client())
|
else if (context().has_client())
|
||||||
|
@ -995,16 +1027,36 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template<typename Completer>
|
||||||
|
void use_explicit_completer(Completer&& completer)
|
||||||
|
{
|
||||||
|
m_explicit_completer = [completer](const Context& context, CompletionFlags flags, StringView content, ByteCount cursor_pos) {
|
||||||
|
Optional<Token> last_token;
|
||||||
|
CommandParser parser{content.substr(0_byte, cursor_pos)};
|
||||||
|
while (auto token = parser.read_token(false))
|
||||||
|
last_token = std::move(token);
|
||||||
|
|
||||||
|
if (last_token and (last_token->pos + last_token->content.length() < cursor_pos))
|
||||||
|
last_token.reset();
|
||||||
|
|
||||||
|
auto token_start = last_token.map([&](auto&& t) { return t.pos; }).value_or(cursor_pos);
|
||||||
|
auto token_content = last_token.map([](auto&& t) -> StringView { return t.content; }).value_or(StringView{});
|
||||||
|
|
||||||
|
return Completions{token_start, cursor_pos, completer(context, token_content)};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void refresh_completions(CompletionFlags flags)
|
void refresh_completions(CompletionFlags flags)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_refresh_completion_pending = false;
|
m_refresh_completion_pending = false;
|
||||||
if (not m_completer)
|
auto& completer = m_explicit_completer ? m_explicit_completer : m_completer;
|
||||||
|
if (not completer)
|
||||||
return;
|
return;
|
||||||
m_current_completion = -1;
|
m_current_completion = -1;
|
||||||
const String& line = m_line_editor.line();
|
const String& line = m_line_editor.line();
|
||||||
m_completions = m_completer(context(), flags, line,
|
m_completions = completer(context(), flags, line,
|
||||||
line.byte_count_to(m_line_editor.cursor_pos()));
|
line.byte_count_to(m_line_editor.cursor_pos()));
|
||||||
const bool menu = (bool)(m_completions.flags & Completions::Flags::Menu);
|
const bool menu = (bool)(m_completions.flags & Completions::Flags::Menu);
|
||||||
if (context().has_client())
|
if (context().has_client())
|
||||||
|
@ -1075,6 +1127,7 @@ private:
|
||||||
|
|
||||||
PromptCallback m_callback;
|
PromptCallback m_callback;
|
||||||
PromptCompleter m_completer;
|
PromptCompleter m_completer;
|
||||||
|
PromptCompleter m_explicit_completer;
|
||||||
const String m_prompt;
|
const String m_prompt;
|
||||||
Face m_prompt_face;
|
Face m_prompt_face;
|
||||||
Completions m_completions;
|
Completions m_completions;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user