Auto-insert best completion on space for menu completions
The menu flag signifies that only the completions are valid arguments, hence it makes sense to auto insert the best one on space. Because full match is always considered the best match in completion ranking, this should always have a reasonable behaviour. This makes it harder to enter a hidden command, but completion can always be disabled via <c-o> or by quoting in those rare cases.
This commit is contained in:
parent
2cd323b314
commit
65587d1eee
|
@ -7,6 +7,9 @@ released versions.
|
|||
|
||||
* `set-option -remove` support for substracting/removing from option values
|
||||
|
||||
* Menu completions such as command name completion are now auto-inserted on
|
||||
space
|
||||
|
||||
== Kakoune 2020.09.01
|
||||
|
||||
* The `repl` and `send-text` aliases have been renamed respectively into
|
||||
|
|
|
@ -628,10 +628,9 @@ Completions CommandManager::complete_command_name(const Context& context, String
|
|||
| transform(&CommandMap::Item::key);
|
||||
|
||||
auto aliases = context.aliases().flatten_aliases()
|
||||
| transform(&HashItem<String, String>::key)
|
||||
| filter([](auto& alias) { return alias.length() > 3; });
|
||||
| transform(&HashItem<String, String>::key);
|
||||
|
||||
return {0, query.length(), Kakoune::complete(query, query.length(), concatenated(commands, aliases))};
|
||||
return {0, query.length(), Kakoune::complete(query, query.length(), concatenated(commands, aliases)), Completions::Flags::Menu};
|
||||
}
|
||||
|
||||
Completions CommandManager::complete_module_name(StringView query) const
|
||||
|
@ -672,18 +671,43 @@ Completions CommandManager::complete(const Context& context,
|
|||
kak_assert(not tokens.empty());
|
||||
const auto& token = tokens.back();
|
||||
|
||||
auto requote = [](Completions completions, Token::Type token_type) {
|
||||
if (completions.flags & Completions::Flags::Quoted)
|
||||
return completions;
|
||||
|
||||
if (token_type == Token::Type::Raw)
|
||||
{
|
||||
for (auto& c : completions.candidates)
|
||||
{
|
||||
if (c.substr(0_byte, 1_byte) == "%" or any_of(c, [](auto i) { return contains("; \t'\"", i); }))
|
||||
c = quote(c);
|
||||
}
|
||||
}
|
||||
else if (token_type == Token::Type::RawQuoted)
|
||||
{
|
||||
kak_assert(completions.start > 0);
|
||||
--completions.start;
|
||||
completions.flags |= Completions::Flags::Quoted;
|
||||
for (auto& c : completions.candidates)
|
||||
c = quote(c);
|
||||
}
|
||||
else
|
||||
kak_assert(false);
|
||||
|
||||
return completions;
|
||||
};
|
||||
|
||||
const ByteCount start = token.pos;
|
||||
const ByteCount cursor_pos_in_token = cursor_pos - start;
|
||||
|
||||
// command name completion
|
||||
if (tokens.size() == 1 and (token.type == Token::Type::Raw or
|
||||
token.type == Token::Type::RawQuoted))
|
||||
{
|
||||
auto cmd_start = token.pos;
|
||||
StringView query = command_line.substr(cmd_start, cursor_pos - cmd_start);
|
||||
return offset_pos(complete_command_name(context, query), cmd_start);
|
||||
StringView query = command_line.substr(start, cursor_pos_in_token);
|
||||
return requote(offset_pos(complete_command_name(context, query), start), token.type);
|
||||
}
|
||||
|
||||
const ByteCount start = token.pos;
|
||||
const ByteCount cursor_pos_in_token = cursor_pos - start;
|
||||
|
||||
switch (token.type)
|
||||
{
|
||||
case Token::Type::RegisterExpand:
|
||||
|
@ -714,11 +738,7 @@ Completions CommandManager::complete(const Context& context,
|
|||
|
||||
case Token::Type::Raw:
|
||||
case Token::Type::RawQuoted:
|
||||
case Token::Type::RawEval:
|
||||
{
|
||||
if (token.type != Token::Type::Raw and token.type != Token::Type::RawQuoted)
|
||||
return Completions{};
|
||||
|
||||
StringView command_name = tokens.front().content;
|
||||
if (command_name != m_last_complete_command)
|
||||
{
|
||||
|
@ -744,20 +764,11 @@ Completions CommandManager::complete(const Context& context,
|
|||
Vector<String> params;
|
||||
for (auto it = tokens.begin() + 1; it != tokens.end(); ++it)
|
||||
params.push_back(it->content);
|
||||
Completions completions = offset_pos(command_it->value.completer(
|
||||
return requote(offset_pos(command_it->value.completer(
|
||||
context, flags, params, tokens.size() - 2,
|
||||
cursor_pos_in_token), start);
|
||||
|
||||
if (not (completions.flags & Completions::Flags::Quoted) and token.type == Token::Type::Raw)
|
||||
{
|
||||
for (auto& c : completions.candidates)
|
||||
c = (not c.empty() and c[0] == '%') or
|
||||
any_of(c, [](auto i) { return contains("; \t'\"", i); }) ?
|
||||
format("'{}'", replace(c, "'", "''")) : c;
|
||||
}
|
||||
|
||||
return completions;
|
||||
cursor_pos_in_token), start), token.type);
|
||||
}
|
||||
case Token::Type::RawEval:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -991,6 +991,15 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
if (key == ' ' and
|
||||
(m_completions.flags & Completions::Flags::Menu) and
|
||||
not (m_completions.flags & Completions::Flags::Quoted) and
|
||||
m_current_completion == -1 and not m_completions.candidates.empty())
|
||||
{
|
||||
m_line_editor.insert_from(line.char_count_to(m_completions.start),
|
||||
m_completions.candidates.front());
|
||||
}
|
||||
|
||||
m_line_editor.handle_key(key);
|
||||
clear_completions();
|
||||
m_refresh_completion_pending = true;
|
||||
|
|
Loading…
Reference in New Issue
Block a user