summaryrefslogtreecommitdiff
path: root/src/input_handler.cc
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2020-10-19 19:36:58 +1100
committerMaxime Coste <mawww@kakoune.org>2020-10-19 19:36:58 +1100
commitf549190a988bb91f5d4a79b3f9bba5eac029da73 (patch)
tree094a5d2838bd4eddcfc383b7c96d85974f0350ae /src/input_handler.cc
parent600be827b378444ed548492328a041a0b5154a70 (diff)
Add support for explicit completion in prompt mode
Diffstat (limited to 'src/input_handler.cc')
-rw-r--r--src/input_handler.cc59
1 files changed, 56 insertions, 3 deletions
diff --git a/src/input_handler.cc b/src/input_handler.cc
index 36425eff..c8333dda 100644
--- a/src/input_handler.cc
+++ b/src/input_handler.cc
@@ -17,6 +17,7 @@
#include "user_interface.hh"
#include "utf8.hh"
#include "window.hh"
+#include "word_db.hh"
namespace Kakoune
{
@@ -929,9 +930,40 @@ public:
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'))
{
+ m_explicit_completer = PromptCompleter{};
m_auto_complete = not m_auto_complete;
+
if (m_auto_complete)
refresh_completions(CompletionFlags::Fast);
else if (context().has_client())
@@ -995,17 +1027,37 @@ public:
}
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)
{
try
{
m_refresh_completion_pending = false;
- if (not m_completer)
+ auto& completer = m_explicit_completer ? m_explicit_completer : m_completer;
+ if (not completer)
return;
m_current_completion = -1;
const String& line = m_line_editor.line();
- m_completions = m_completer(context(), flags, line,
- line.byte_count_to(m_line_editor.cursor_pos()));
+ m_completions = completer(context(), flags, line,
+ line.byte_count_to(m_line_editor.cursor_pos()));
const bool menu = (bool)(m_completions.flags & Completions::Flags::Menu);
if (context().has_client())
{
@@ -1075,6 +1127,7 @@ private:
PromptCallback m_callback;
PromptCompleter m_completer;
+ PromptCompleter m_explicit_completer;
const String m_prompt;
Face m_prompt_face;
Completions m_completions;