summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2013-11-04 21:53:10 +0000
committerMaxime Coste <frrrwww@gmail.com>2013-11-04 21:59:28 +0000
commit3e1bb777ce9c8de3dbe55dee4e454241eddc98d1 (patch)
tree0b6635de8461910e2a6d90e3a14f48c2e5091e36
parent70e94cb00a577c53b77f7349f138d3a563745793 (diff)
Add automatic completion display in prompt mode
Controlled by the autoshowcompl option Completers now take a CompletionFlag parameter, used to specify we want fast completion (tag completion can be slow, we do not want to run it if not explicitely wanted by the user).
-rw-r--r--README.asciidoc2
-rw-r--r--src/client.cc25
-rw-r--r--src/command_manager.cc9
-rw-r--r--src/command_manager.hh5
-rw-r--r--src/commands.cc24
-rw-r--r--src/completion.hh11
-rw-r--r--src/normal.cc2
-rw-r--r--src/option_manager.cc1
8 files changed, 55 insertions, 24 deletions
diff --git a/README.asciidoc b/README.asciidoc
index 6ee322c6..8d477610 100644
--- a/README.asciidoc
+++ b/README.asciidoc
@@ -394,6 +394,8 @@ Some options are built in kakoune, and can be used to control it's behaviour:
candidates exist, enable completion with common prefix.
* +incsearch+ _bool_: execute search as it is typed
* +autoinfo+ _bool_: display automatic information box for certain commands.
+ * +autoshowcompl+ _bool_: automatically display possible completions when
+ editing a prompt.
* +ignored_files+ _regex_: filenames matching this regex wont be considered
as candidates on filename completion (except if the text being completed
already matches it).
diff --git a/src/client.cc b/src/client.cc
index a596a961..d999816f 100644
--- a/src/client.cc
+++ b/src/client.cc
@@ -267,7 +267,7 @@ public:
display_line.insert(display_line.begin(), { "filter:"_str, get_color("Prompt") });
context().print_status(display_line);
}
- }
+ }
String description() const override
{
@@ -410,9 +410,9 @@ public:
const bool reverse = (key == Key::BackTab);
CandidateList& candidates = m_completions.candidates;
// first try, we need to ask our completer for completions
- if (m_current_completion == -1)
+ if (candidates.empty())
{
- m_completions = m_completer(context(), line,
+ m_completions = m_completer(context(), CompletionFlags::None, line,
line.byte_count_to(m_line_editor.cursor_pos()));
if (candidates.empty())
return;
@@ -451,13 +451,26 @@ public:
// when we have only one completion candidate, make next tab complete
// from the new content.
if (candidates.size() == 1)
- m_current_completion = -1;
+ candidates.clear();
}
else
{
- context().ui().menu_hide();
- m_current_completion = -1;
m_line_editor.handle_key(key);
+ m_current_completion = -1;
+ context().ui().menu_hide();
+
+ if (context().options()["autoshowcompl"].get<bool>()) try
+ {
+ m_completions = m_completer(context(), CompletionFlags::Fast, line,
+ line.byte_count_to(m_line_editor.cursor_pos()));
+ CandidateList& candidates = m_completions.candidates;
+ if (not candidates.empty())
+ {
+ DisplayCoord menu_pos{ context().ui().dimensions().line, 0_char };
+ context().ui().menu_show(candidates, menu_pos, get_color("MenuForeground"),
+ get_color("MenuBackground"), MenuStyle::Prompt);
+ }
+ } catch (runtime_error&) {}
}
display();
m_callback(line, PromptEvent::Change, context());
diff --git a/src/command_manager.cc b/src/command_manager.cc
index c62d75fa..165a58f3 100644
--- a/src/command_manager.cc
+++ b/src/command_manager.cc
@@ -312,7 +312,7 @@ void CommandManager::execute(const String& command_line,
execute_single_command(params, context);
}
-Completions CommandManager::complete(const Context& context,
+Completions CommandManager::complete(const Context& context, CompletionFlags flags,
const String& command_line, ByteCount cursor_pos)
{
TokenPosList pos_info;
@@ -356,20 +356,21 @@ Completions CommandManager::complete(const Context& context,
return Completions();
ByteCount start = token_to_complete < tokens.size() ?
- pos_info[token_to_complete].first : cursor_pos;
+ pos_info[token_to_complete].first : cursor_pos;
Completions result(start , cursor_pos);
ByteCount cursor_pos_in_token = cursor_pos - start;
std::vector<String> params;
for (auto token_it = tokens.begin()+1; token_it != tokens.end(); ++token_it)
params.push_back(token_it->content());
- result.candidates = command_it->second.completer(context, params,
+ result.candidates = command_it->second.completer(context, flags, params,
token_to_complete - 1,
cursor_pos_in_token);
return result;
}
CandidateList PerArgumentCommandCompleter::operator()(const Context& context,
+ CompletionFlags flags,
CommandParameters params,
size_t token_to_complete,
ByteCount pos_in_token) const
@@ -382,7 +383,7 @@ CandidateList PerArgumentCommandCompleter::operator()(const Context& context,
const String& argument = token_to_complete < params.size() ?
params[token_to_complete] : String();
- return m_completers[token_to_complete](context, argument, pos_in_token);
+ return m_completers[token_to_complete](context, flags, argument, pos_in_token);
}
}
diff --git a/src/command_manager.hh b/src/command_manager.hh
index 9aee1e0c..849ea3a7 100644
--- a/src/command_manager.hh
+++ b/src/command_manager.hh
@@ -18,6 +18,7 @@ struct Context;
using CommandParameters = memoryview<String>;
using Command = std::function<void (CommandParameters, Context& context)>;
using CommandCompleter = std::function<CandidateList (const Context& context,
+ CompletionFlags,
CommandParameters,
size_t, ByteCount)>;
@@ -25,6 +26,7 @@ class PerArgumentCommandCompleter
{
public:
using ArgumentCompleter = std::function<CandidateList (const Context&,
+ CompletionFlags flags,
const String&, ByteCount)>;
using ArgumentCompleterList = memoryview<ArgumentCompleter>;
@@ -32,6 +34,7 @@ public:
: m_completers(completers.begin(), completers.end()) {}
CandidateList operator()(const Context& context,
+ CompletionFlags flags,
CommandParameters params,
size_t token_to_complete,
ByteCount pos_in_token) const;
@@ -47,7 +50,7 @@ public:
memoryview<String> shell_params = {},
const EnvVarMap& env_vars = EnvVarMap{});
- Completions complete(const Context& context,
+ Completions complete(const Context& context, CompletionFlags flags,
const String& command_line, ByteCount cursor_pos);
bool command_defined(const String& command_name) const;
diff --git a/src/commands.cc b/src/commands.cc
index ce973b22..87743ef8 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -405,7 +405,8 @@ void define_command(CommandParameters params, Context& context)
CommandCompleter completer;
if (parser.has_option("file-completion"))
{
- completer = [](const Context& context, CommandParameters params,
+ completer = [](const Context& context, CompletionFlags flags,
+ CommandParameters params,
size_t token_to_complete, ByteCount pos_in_token)
{
const String& prefix = token_to_complete < params.size() ?
@@ -416,9 +417,12 @@ void define_command(CommandParameters params, Context& context)
else if (parser.has_option("shell-completion"))
{
String shell_cmd = parser.option_value("shell-completion");
- completer = [=](const Context& context, CommandParameters params,
+ completer = [=](const Context& context, CompletionFlags flags,
+ CommandParameters params,
size_t token_to_complete, ByteCount pos_in_token)
{
+ if (flags == CompletionFlags::Fast) // no shell on fast completion
+ return CandidateList{};
EnvVarMap vars = {
{ "token_to_complete", to_string(token_to_complete) },
{ "pos_in_token", to_string(pos_in_token) }
@@ -743,8 +747,9 @@ void change_working_directory(CommandParameters params, Context&)
template<typename GetRootGroup>
CommandCompleter group_rm_completer(GetRootGroup get_root_group)
{
- return [=](const Context& context, CommandParameters params,
- size_t token_to_complete, ByteCount pos_in_token) {
+ return [=](const Context& context, CompletionFlags flags,
+ CommandParameters params, size_t token_to_complete,
+ ByteCount pos_in_token) {
auto& root_group = get_root_group(context);
const String& arg = token_to_complete < params.size() ?
params[token_to_complete] : String();
@@ -759,8 +764,9 @@ CommandCompleter group_rm_completer(GetRootGroup get_root_group)
template<typename FactoryRegistry, typename GetRootGroup>
CommandCompleter group_add_completer(GetRootGroup get_root_group)
{
- return [=](const Context& context, CommandParameters params,
- size_t token_to_complete, ByteCount pos_in_token) {
+ return [=](const Context& context, CompletionFlags flags,
+ CommandParameters params, size_t token_to_complete,
+ ByteCount pos_in_token) {
auto& root_group = get_root_group(context);
const String& arg = token_to_complete < params.size() ?
params[token_to_complete] : String();
@@ -810,7 +816,7 @@ void register_commands()
cm.register_commands({"nop"}, [](CommandParameters, Context&){});
PerArgumentCommandCompleter filename_completer({
- [](const Context& context, const String& prefix, ByteCount cursor_pos)
+ [](const Context& context, CompletionFlags flags, const String& prefix, ByteCount cursor_pos)
{ return complete_filename(prefix, context.options()["ignored_files"].get<Regex>(), cursor_pos); }
});
cm.register_commands({ "e", "edit" }, edit<false>, filename_completer);
@@ -823,7 +829,7 @@ void register_commands()
cm.register_command("wq!", write_and_quit<true>);
PerArgumentCommandCompleter buffer_completer({
- [](const Context& context, const String& prefix, ByteCount cursor_pos)
+ [](const Context& context, CompletionFlags flags, const String& prefix, ByteCount cursor_pos)
{ return BufferManager::instance().complete_buffername(prefix, cursor_pos); }
});
cm.register_commands({ "b", "buffer" }, show_buffer, buffer_completer);
@@ -857,7 +863,7 @@ void register_commands()
cm.register_command("debug", write_debug_message);
cm.register_command("set", set_option,
- [](const Context& context, CommandParameters params, size_t token_to_complete, ByteCount pos_in_token)
+ [](const Context& context, CompletionFlags, CommandParameters params, size_t token_to_complete, ByteCount pos_in_token)
{
if (token_to_complete == 0)
{
diff --git a/src/completion.hh b/src/completion.hh
index c833e2b4..bd89ea4c 100644
--- a/src/completion.hh
+++ b/src/completion.hh
@@ -26,10 +26,15 @@ struct Completions
: start(start), end(end) {}
};
-typedef std::function<Completions (const Context&,
- const String&, ByteCount)> Completer;
+enum class CompletionFlags
+{
+ None,
+ Fast
+};
+using Completer = std::function<Completions (const Context&, CompletionFlags,
+ const String&, ByteCount)>;
-inline Completions complete_nothing(const Context& context,
+inline Completions complete_nothing(const Context& context, CompletionFlags,
const String&, ByteCount cursor_pos)
{
return Completions(cursor_pos, cursor_pos);
diff --git a/src/normal.cc b/src/normal.cc
index 2ff1e0b0..226f554b 100644
--- a/src/normal.cc
+++ b/src/normal.cc
@@ -249,7 +249,7 @@ void command(Context& context, int)
{
context.client().prompt(
":", get_color("Prompt"),
- std::bind(&CommandManager::complete, &CommandManager::instance(), _1, _2, _3),
+ std::bind(&CommandManager::complete, &CommandManager::instance(), _1, _2, _3, _4),
[](const String& cmdline, PromptEvent event, Context& context) {
if (event == PromptEvent::Validate)
CommandManager::instance().execute(cmdline, context);
diff --git a/src/option_manager.cc b/src/option_manager.cc
index 65943061..f472d3fa 100644
--- a/src/option_manager.cc
+++ b/src/option_manager.cc
@@ -116,6 +116,7 @@ GlobalOptions::GlobalOptions()
declare_option<bool>("complete_prefix", true);
declare_option<bool>("incsearch", true);
declare_option<bool>("autoinfo", true);
+ declare_option<bool>("autoshowcompl", true);
declare_option<Regex>("ignored_files", Regex{R"(^(\..*|.*\.(o|so|a))$)"});
declare_option<String>("filetype", "");
declare_option<std::vector<String>>("completions", {});