Insert mode completion execute completers in order, and supports multiple option
The 'completions' option is gone, just add option=completion_option_name in the completers list.
This commit is contained in:
parent
19f5eb65e8
commit
36b016226c
|
@ -523,15 +523,18 @@ Some options are built in Kakoune, and can be used to control it's behaviour:
|
||||||
* +filetype+ _str_: arbitrary string defining the type of the file
|
* +filetype+ _str_: arbitrary string defining the type of the file
|
||||||
filetype dependant actions should hook on this option changing for
|
filetype dependant actions should hook on this option changing for
|
||||||
activation/deactivation.
|
activation/deactivation.
|
||||||
* +completions+ _str-list_: option used for external completion, the
|
|
||||||
first string should follow the format
|
|
||||||
_<line>.<column>[+<length>]@<timestamp>_ to define where the completion
|
|
||||||
apply in the buffer, and the other strings are the candidates.
|
|
||||||
* +path+ _str-list_: directories to search for gf command.
|
* +path+ _str-list_: directories to search for gf command.
|
||||||
* +completers+ _str-list_: completion systems to use for insert mode
|
* +completers+ _str-list_: completion systems to use for insert mode
|
||||||
completion. Support +option+ which use the +completions+ option, and
|
completion. given completers are tried in order until one generate some
|
||||||
+word=all+ or +word=buffer+ which complete using words in all buffers
|
completion candidates. Existing completers are:
|
||||||
(+word=all+) or only the current one (+word=buffer+)
|
- +word=all+ or +word=buffer+ which complete using words in all buffers
|
||||||
|
(+word=all+) or only the current one (+word=buffer+)
|
||||||
|
- +filename+ which tries to detect when a filename is being entered and
|
||||||
|
provides completion based on local filesystem.
|
||||||
|
- +option=<opt-name>+ where <opt-name> is a _str-list_ option. The first
|
||||||
|
element of the list should follow the format:
|
||||||
|
_<line>.<column>[+<length>]@<timestamp>_ to define where the completion
|
||||||
|
apply in the buffer, and the other strings are the candidates.
|
||||||
* +autoreload+ _yesnoask_: auto reload the buffers when an external
|
* +autoreload+ _yesnoask_: auto reload the buffers when an external
|
||||||
modification is detected.
|
modification is detected.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
decl -hidden str clang_filename
|
decl -hidden str clang_filename
|
||||||
decl str clang_options
|
decl str clang_options
|
||||||
|
decl str-list clang_completions
|
||||||
|
|
||||||
def clang-complete %{
|
def clang-complete %{
|
||||||
%sh{
|
%sh{
|
||||||
|
@ -23,12 +24,13 @@ def clang-complete %{
|
||||||
for cmp in ${output}; do
|
for cmp in ${output}; do
|
||||||
completions="${completions}:${cmp}"
|
completions="${completions}:${cmp}"
|
||||||
done
|
done
|
||||||
echo "eval -client $kak_client %[ echo completed; set buffer completions '${completions}' ]" | kak -p ${kak_session}
|
echo "eval -client $kak_client %[ echo completed; set buffer clang_completions '${completions}' ]" | kak -p ${kak_session}
|
||||||
) > /dev/null 2>&1 < /dev/null &
|
) > /dev/null 2>&1 < /dev/null &
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def clang-enable-autocomplete %{
|
def clang-enable-autocomplete %{
|
||||||
|
set window completers %sh{ echo "'option=clang_completions:${kak_opt_completers}'" }
|
||||||
hook window -id clang-autocomplete InsertIdle .* %{ try %{
|
hook window -id clang-autocomplete InsertIdle .* %{ try %{
|
||||||
exec -draft <a-h><a-k>(\.|->|::).$<ret>
|
exec -draft <a-h><a-k>(\.|->|::).$<ret>
|
||||||
echo 'completing...'
|
echo 'completing...'
|
||||||
|
@ -36,4 +38,7 @@ def clang-enable-autocomplete %{
|
||||||
} }
|
} }
|
||||||
}
|
}
|
||||||
|
|
||||||
def clang-disable-autocomplete %{ rmhooks window clang-autocomplete }
|
def clang-disable-autocomplete %{
|
||||||
|
set window completers %sh{ echo "'${kak_opt_completers}'" | sed -e 's/option=clang_completions://g' }
|
||||||
|
rmhooks window clang-autocomplete
|
||||||
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ def tag-complete %{ eval -draft %{
|
||||||
%sh{ (
|
%sh{ (
|
||||||
compl=$(readtags -p "$kak_selection" | cut -f 1 | sort | uniq | sed -e 's/:/\\:/g' | sed -e 's/\n/:/g' )
|
compl=$(readtags -p "$kak_selection" | cut -f 1 | sort | uniq | sed -e 's/:/\\:/g' | sed -e 's/\n/:/g' )
|
||||||
compl="${kak_cursor_line}.${kak_cursor_column}+${#kak_selection}@${kak_timestamp}:${compl}"
|
compl="${kak_cursor_line}.${kak_cursor_column}+${#kak_selection}@${kak_timestamp}:${compl}"
|
||||||
echo "set buffer=$kak_bufname completions '${compl}'" | kak -p ${kak_session}
|
echo "set buffer=$kak_bufname ctags_completions '${compl}'" | kak -p ${kak_session}
|
||||||
) > /dev/null 2>&1 < /dev/null & }
|
) > /dev/null 2>&1 < /dev/null & }
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "color_registry.hh"
|
#include "color_registry.hh"
|
||||||
#include "file.hh"
|
#include "file.hh"
|
||||||
#include "word_db.hh"
|
#include "word_db.hh"
|
||||||
|
#include "debug.hh"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
@ -711,12 +712,20 @@ public:
|
||||||
m_context.ui().menu_hide();
|
m_context.ui().menu_hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<BufferCompletion (BufferCompleter::*complete_func)(const Buffer&, BufferCoord)>
|
template<typename CompleteFunc>
|
||||||
bool try_complete()
|
bool try_complete(CompleteFunc complete_func)
|
||||||
{
|
{
|
||||||
auto& buffer = m_context.buffer();
|
auto& buffer = m_context.buffer();
|
||||||
BufferCoord cursor_pos = m_context.selections().main().cursor();
|
BufferCoord cursor_pos = m_context.selections().main().cursor();
|
||||||
m_completions = (this->*complete_func)(buffer, cursor_pos);
|
try
|
||||||
|
{
|
||||||
|
m_completions = complete_func(buffer, cursor_pos);
|
||||||
|
}
|
||||||
|
catch (runtime_error& e)
|
||||||
|
{
|
||||||
|
write_debug("error while trying to run completer: "_str + e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (not m_completions.is_valid())
|
if (not m_completions.is_valid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -812,9 +821,9 @@ public:
|
||||||
return { begin.coord(), pos.coord(), std::move(res), buffer.timestamp() };
|
return { begin.coord(), pos.coord(), std::move(res), buffer.timestamp() };
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferCompletion complete_option(const Buffer& buffer, BufferCoord cursor_pos)
|
BufferCompletion complete_option(const Buffer& buffer, BufferCoord cursor_pos, const String& option_name)
|
||||||
{
|
{
|
||||||
const StringList& opt = options()["completions"].get<StringList>();
|
const StringList& opt = options()[option_name].get<StringList>();;
|
||||||
if (opt.empty())
|
if (opt.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
@ -868,7 +877,14 @@ public:
|
||||||
private:
|
private:
|
||||||
void on_option_changed(const Option& opt) override
|
void on_option_changed(const Option& opt) override
|
||||||
{
|
{
|
||||||
if (opt.name() == "completions")
|
auto& completers = options()["completers"].get<StringList>();
|
||||||
|
StringList option_names;
|
||||||
|
for (auto& completer : completers)
|
||||||
|
{
|
||||||
|
if (completer.substr(0_byte, 7_byte) == "option=")
|
||||||
|
option_names.emplace_back(completer.substr(7_byte));
|
||||||
|
}
|
||||||
|
if (contains(option_names, opt.name()))
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
setup_ifn();
|
setup_ifn();
|
||||||
|
@ -889,18 +905,29 @@ private:
|
||||||
|
|
||||||
bool setup_ifn()
|
bool setup_ifn()
|
||||||
{
|
{
|
||||||
|
using namespace std::placeholders;
|
||||||
if (not m_completions.is_valid())
|
if (not m_completions.is_valid())
|
||||||
{
|
{
|
||||||
auto& completers = options()["completers"].get<StringList>();
|
auto& completers = options()["completers"].get<StringList>();
|
||||||
if (contains(completers, "option") and try_complete<&BufferCompleter::complete_option>())
|
for (auto& completer : completers)
|
||||||
return true;
|
{
|
||||||
if (contains(completers, "word=buffer") and try_complete<&BufferCompleter::complete_word<false>>())
|
if (completer == "filename" and
|
||||||
return true;
|
try_complete([this](const Buffer& buffer, BufferCoord cursor_pos)
|
||||||
if (contains(completers, "word=all") and try_complete<&BufferCompleter::complete_word<true>>())
|
{ return complete_filename(buffer, cursor_pos); }))
|
||||||
return true;
|
return true;
|
||||||
if (contains(completers, "filename") and try_complete<&BufferCompleter::complete_filename>())
|
if (completer.substr(0_byte, 7_byte) == "option=" and
|
||||||
return true;
|
try_complete([&, this](const Buffer& buffer, BufferCoord cursor_pos)
|
||||||
|
{ return complete_option(buffer, cursor_pos, completer.substr(7_byte)); }))
|
||||||
|
return true;
|
||||||
|
if (completer == "word=buffer" and
|
||||||
|
try_complete([this](const Buffer& buffer, BufferCoord cursor_pos)
|
||||||
|
{ return complete_word<false>(buffer, cursor_pos); }))
|
||||||
|
return true;
|
||||||
|
if (completer == "word=all" and
|
||||||
|
try_complete([this](const Buffer& buffer, BufferCoord cursor_pos)
|
||||||
|
{ return complete_word<true>(buffer, cursor_pos); }))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -946,13 +973,14 @@ public:
|
||||||
if (m_mode == Mode::Complete)
|
if (m_mode == Mode::Complete)
|
||||||
{
|
{
|
||||||
if (key.key == 'f')
|
if (key.key == 'f')
|
||||||
m_completer.try_complete<&BufferCompleter::complete_filename>();
|
m_completer.try_complete([this](const Buffer& buffer, BufferCoord cursor_pos)
|
||||||
|
{ return m_completer.complete_filename(buffer, cursor_pos); });
|
||||||
if (key.key == 'w')
|
if (key.key == 'w')
|
||||||
m_completer.try_complete<&BufferCompleter::complete_word<true>>();
|
m_completer.try_complete([this](const Buffer& buffer, BufferCoord cursor_pos)
|
||||||
if (key.key == 'o')
|
{ return m_completer.complete_word<true>(buffer, cursor_pos); });
|
||||||
m_completer.try_complete<&BufferCompleter::complete_option>();
|
|
||||||
if (key.key == 'l')
|
if (key.key == 'l')
|
||||||
m_completer.try_complete<&BufferCompleter::complete_line>();
|
m_completer.try_complete([this](const Buffer& buffer, BufferCoord cursor_pos)
|
||||||
|
{ return m_completer.complete_line(buffer, cursor_pos); });
|
||||||
m_mode = Mode::Default;
|
m_mode = Mode::Default;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,15 +133,18 @@ GlobalOptions::GlobalOptions()
|
||||||
declare_option<bool>("aligntab", false);
|
declare_option<bool>("aligntab", false);
|
||||||
declare_option<Regex>("ignored_files", Regex{R"(^(\..*|.*\.(o|so|a))$)"});
|
declare_option<Regex>("ignored_files", Regex{R"(^(\..*|.*\.(o|so|a))$)"});
|
||||||
declare_option<String>("filetype", "");
|
declare_option<String>("filetype", "");
|
||||||
declare_option<std::vector<String>>("completions", {});
|
|
||||||
declare_option<std::vector<String>>("path", { "./", "/usr/include" });
|
declare_option<std::vector<String>>("path", { "./", "/usr/include" });
|
||||||
declare_option<std::vector<String>>("completers", {"option", "filename", "word=buffer"},
|
declare_option<std::vector<String>>("completers", {"filename", "word=buffer"},
|
||||||
Option::Flags::None,
|
Option::Flags::None,
|
||||||
[](const std::vector<String>& s) {
|
[](const std::vector<String>& s) {
|
||||||
static const auto values = {"option", "word=buffer", "word=all", "filename" };
|
static const auto values = {"word=buffer", "word=all", "filename" };
|
||||||
for (auto& v : s)
|
for (auto& v : s)
|
||||||
|
{
|
||||||
|
if (v.substr(0_byte, 7_byte) == "option=")
|
||||||
|
continue;
|
||||||
if (not contains(values, v))
|
if (not contains(values, v))
|
||||||
throw runtime_error(v + " is not a recognised value for completers");
|
throw runtime_error(v + " is not a recognised value for completers");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
declare_option<YesNoAsk>("autoreload", Ask);
|
declare_option<YesNoAsk>("autoreload", Ask);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user