Improve command completion by taking into account quoting of arguments
This commit is contained in:
parent
f59108072f
commit
574e337132
|
@ -48,6 +48,7 @@ struct Token
|
||||||
enum class Type
|
enum class Type
|
||||||
{
|
{
|
||||||
Raw,
|
Raw,
|
||||||
|
RawQuoted,
|
||||||
RawEval,
|
RawEval,
|
||||||
ShellExpand,
|
ShellExpand,
|
||||||
RegisterExpand,
|
RegisterExpand,
|
||||||
|
@ -188,7 +189,7 @@ template<bool throw_on_invalid>
|
||||||
Token::Type token_type(StringView type_name)
|
Token::Type token_type(StringView type_name)
|
||||||
{
|
{
|
||||||
if (type_name == "")
|
if (type_name == "")
|
||||||
return Token::Type::Raw;
|
return Token::Type::RawQuoted;
|
||||||
else if (type_name == "sh")
|
else if (type_name == "sh")
|
||||||
return Token::Type::ShellExpand;
|
return Token::Type::ShellExpand;
|
||||||
else if (type_name == "reg")
|
else if (type_name == "reg")
|
||||||
|
@ -200,7 +201,7 @@ Token::Type token_type(StringView type_name)
|
||||||
else if (throw_on_invalid)
|
else if (throw_on_invalid)
|
||||||
throw unknown_expand{type_name};
|
throw unknown_expand{type_name};
|
||||||
else
|
else
|
||||||
return Token::Type::Raw;
|
return Token::Type::RawQuoted;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skip_blanks_and_comments(Reader& reader)
|
void skip_blanks_and_comments(Reader& reader)
|
||||||
|
@ -295,7 +296,7 @@ TokenList parse(StringView line)
|
||||||
if (throw_on_unterminated and not reader)
|
if (throw_on_unterminated and not reader)
|
||||||
throw parse_error{format("unterminated string {0}...{0}", c)};
|
throw parse_error{format("unterminated string {0}...{0}", c)};
|
||||||
result.emplace_back(c == '"' ? Token::Type::RawEval
|
result.emplace_back(c == '"' ? Token::Type::RawEval
|
||||||
: Token::Type::Raw,
|
: Token::Type::RawQuoted,
|
||||||
start, reader.pos, coord, std::move(token));
|
start, reader.pos, coord, std::move(token));
|
||||||
}
|
}
|
||||||
else if (c == '%')
|
else if (c == '%')
|
||||||
|
@ -346,6 +347,7 @@ String expand_token(const Token& token, const Context& context,
|
||||||
case Token::Type::RawEval:
|
case Token::Type::RawEval:
|
||||||
return expand(content, context, shell_params, env_vars);
|
return expand(content, context, shell_params, env_vars);
|
||||||
case Token::Type::Raw:
|
case Token::Type::Raw:
|
||||||
|
case Token::Type::RawQuoted:
|
||||||
return content;
|
return content;
|
||||||
default: kak_assert(false);
|
default: kak_assert(false);
|
||||||
}
|
}
|
||||||
|
@ -483,7 +485,8 @@ CommandInfo CommandManager::command_info(const Context& context, StringView comm
|
||||||
|
|
||||||
CommandInfo res;
|
CommandInfo res;
|
||||||
if (cmd_idx == tokens.size() or
|
if (cmd_idx == tokens.size() or
|
||||||
tokens[cmd_idx].type() != Token::Type::Raw)
|
(tokens[cmd_idx].type() != Token::Type::Raw and
|
||||||
|
tokens[cmd_idx].type() != Token::Type::RawQuoted))
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
auto cmd = find_command(context, tokens[cmd_idx].content());
|
auto cmd = find_command(context, tokens[cmd_idx].content());
|
||||||
|
@ -501,7 +504,9 @@ CommandInfo CommandManager::command_info(const Context& context, StringView comm
|
||||||
it != tokens.end() and it->type() != Token::Type::CommandSeparator;
|
it != tokens.end() and it->type() != Token::Type::CommandSeparator;
|
||||||
++it)
|
++it)
|
||||||
{
|
{
|
||||||
if (it->type() == Token::Type::Raw or it->type() == Token::Type::RawEval)
|
if (it->type() == Token::Type::Raw or
|
||||||
|
it->type() == Token::Type::RawQuoted or
|
||||||
|
it->type() == Token::Type::RawEval)
|
||||||
params.push_back(it->content());
|
params.push_back(it->content());
|
||||||
}
|
}
|
||||||
String helpstr = cmd->second.helper(context, params);
|
String helpstr = cmd->second.helper(context, params);
|
||||||
|
@ -554,7 +559,8 @@ Completions CommandManager::complete(const Context& context,
|
||||||
// command name completion
|
// command name completion
|
||||||
if (tokens.empty() or
|
if (tokens.empty() or
|
||||||
(tok_idx == cmd_idx and (tok_idx == tokens.size() or
|
(tok_idx == cmd_idx and (tok_idx == tokens.size() or
|
||||||
tokens[tok_idx].type() == Token::Type::Raw)))
|
tokens[tok_idx].type() == Token::Type::Raw or
|
||||||
|
tokens[tok_idx].type() == Token::Type::RawQuoted)))
|
||||||
{
|
{
|
||||||
const bool is_end_token = tok_idx == tokens.size();
|
const bool is_end_token = tok_idx == tokens.size();
|
||||||
ByteCount cmd_start = is_end_token ? cursor_pos
|
ByteCount cmd_start = is_end_token ? cursor_pos
|
||||||
|
@ -586,7 +592,7 @@ Completions CommandManager::complete(const Context& context,
|
||||||
ByteCount cursor_pos_in_token = cursor_pos - start;
|
ByteCount cursor_pos_in_token = cursor_pos - start;
|
||||||
|
|
||||||
const Token::Type type = tok_idx < tokens.size() ?
|
const Token::Type type = tok_idx < tokens.size() ?
|
||||||
tokens[tok_idx].type() : Token::Type::Raw;
|
tokens[tok_idx].type() : Token::Type::Raw;
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case Token::Type::OptionExpand:
|
case Token::Type::OptionExpand:
|
||||||
|
@ -599,6 +605,8 @@ Completions CommandManager::complete(const Context& context,
|
||||||
cursor_pos_in_token), start);
|
cursor_pos_in_token), start);
|
||||||
|
|
||||||
case Token::Type::Raw:
|
case Token::Type::Raw:
|
||||||
|
case Token::Type::RawQuoted:
|
||||||
|
case Token::Type::RawEval:
|
||||||
{
|
{
|
||||||
if (tokens[cmd_idx].type() != Token::Type::Raw)
|
if (tokens[cmd_idx].type() != Token::Type::Raw)
|
||||||
return Completions{};
|
return Completions{};
|
||||||
|
@ -615,14 +623,16 @@ Completions CommandManager::complete(const Context& context,
|
||||||
params.push_back(it->content());
|
params.push_back(it->content());
|
||||||
if (tok_idx == tokens.size())
|
if (tok_idx == tokens.size())
|
||||||
params.push_back("");
|
params.push_back("");
|
||||||
Completions completions = command_it->second.completer(
|
Completions completions = offset_pos(command_it->second.completer(
|
||||||
context, flags, params, tok_idx - cmd_idx - 1,
|
context, flags, params, tok_idx - cmd_idx - 1,
|
||||||
cursor_pos_in_token);
|
cursor_pos_in_token), start);
|
||||||
completions.start += start;
|
|
||||||
completions.end += start;
|
|
||||||
|
|
||||||
for (auto& candidate : completions.candidates)
|
if (type != Token::Type::RawQuoted)
|
||||||
candidate = escape(candidate, " \t;", '\\');
|
{
|
||||||
|
StringView to_escape = type == Token::Type::Raw ? "% \t;" : "%";
|
||||||
|
for (auto& candidate : completions.candidates)
|
||||||
|
candidate = escape(candidate, to_escape, '\\');
|
||||||
|
}
|
||||||
|
|
||||||
return completions;
|
return completions;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user