Compute prompt completion only from characters left of the cursor

If I type

	:echo -mx

I get no completions, even when I move the cursor on the x.
If I replace the x  with a k, I get a completion "-markup".
The odd thing is that if I accept the completion while the cursor is
on the k, then the commandline will be

	:echo markupk

Evidently, the characters under cursor (x/k) influence the completion
(actually all letters right of the cursor do), but they are not
incorporated in the final result, which is weird.

I think there are two consistent behaviors:
1. Compute completions only from characters left of the cursor. We already
   do this in insert mode completion, and when completing the command name
   in a prompt.
2. Compute completions from the whole token, and when accepting a completion,
   replace the whole token.

Most readline-style completion systems out there implement 1. A
notable exception is fish's tab-completion. I think we should stick
to 1 because it's more predictable and familiar. Do that.

This allows us to get rid of a special case for completing command
names, because the new behavior subsumes it.

In fact, I think this would allow us to get rid of most "pos_in_token"
or "cursor_pos" completer parameters. I believe the only place where we
it's actually different from the end of the query is in "shell-script"
completers, where we expose "$kak_pos_in_token". I think we can still
remove that parameter and just cut the commandline at the cursor
position before passing it to a "shell-script" completer. Then we
also don't need "$kak_token_to_complete" (but we can still keep
expose them for backwards compatibility).
This commit is contained in:
Johannes Altmanninger 2022-07-21 10:24:09 +02:00
parent 559af669c7
commit 19fccc1587

View File

@ -653,8 +653,9 @@ Completions CommandManager::complete(const Context& context,
StringView command_line, StringView command_line,
ByteCount cursor_pos) ByteCount cursor_pos)
{ {
CommandParser parser{command_line}; auto prefix = command_line.substr(0_byte, cursor_pos);
const char* cursor = command_line.begin() + (int)cursor_pos; CommandParser parser{prefix};
const char* cursor = prefix.begin() + (int)cursor_pos;
Vector<Token> tokens; Vector<Token> tokens;
bool is_last_token = true; bool is_last_token = true;
@ -675,7 +676,7 @@ Completions CommandManager::complete(const Context& context,
} }
if (is_last_token) if (is_last_token)
tokens.push_back({Token::Type::Raw, command_line.length(), {}}); tokens.push_back({Token::Type::Raw, prefix.length(), {}});
kak_assert(not tokens.empty()); kak_assert(not tokens.empty());
const auto& token = tokens.back(); const auto& token = tokens.back();
@ -712,8 +713,7 @@ Completions CommandManager::complete(const Context& context,
if (tokens.size() == 1 and (token.type == Token::Type::Raw or if (tokens.size() == 1 and (token.type == Token::Type::Raw or
token.type == Token::Type::RawQuoted)) token.type == Token::Type::RawQuoted))
{ {
StringView query = command_line.substr(start, pos_in_token); return offset_pos(requote(complete_command_name(context, prefix), token.type), start);
return offset_pos(requote(complete_command_name(context, query), token.type), start);
} }
switch (token.type) switch (token.type)