From 04780b235b359daeb780ebf2ea15ae23006f598f Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Thu, 4 May 2023 12:49:50 +1000 Subject: [PATCH] Add support for recursive expansions with %exp{...} %exp{...} just expands its content the same way double quoted strings do, but using a named expansion type makes it possible to use the more quoting mechanism to avoid quoting hell. --- doc/pages/expansions.asciidoc | 5 +++++ src/command_manager.cc | 18 ++++++++++-------- src/command_manager.hh | 2 +- src/main.cc | 5 +++++ 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/doc/pages/expansions.asciidoc b/doc/pages/expansions.asciidoc index 191e588b..6d935a3f 100644 --- a/doc/pages/expansions.asciidoc +++ b/doc/pages/expansions.asciidoc @@ -427,3 +427,8 @@ everywhere. A value described as a "quoted list" will follow the rules of Kakoune string quoting (See <>). An "unquoted list" cannot contain any special characters that would require quoting. + +== Recursive Expansions + +Expansions with the type `exp` expand their content, the same way doubly +quoted strings do. diff --git a/src/command_manager.cc b/src/command_manager.cc index 22b365ea..e1b44888 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -220,6 +220,8 @@ Token::Type token_type(StringView type_name, bool throw_on_invalid) return Token::Type::ArgExpand; else if (type_name == "file") return Token::Type::FileExpand; + else if (type_name == "exp") + return Token::Type::Expand; else if (throw_on_invalid) throw parse_error{format("unknown expand '{}'", type_name)}; else @@ -396,7 +398,7 @@ void expand_token(Token&& token, const Context& context, const ShellContext& she } case Token::Type::FileExpand: return set_target(read_file(content)); - case Token::Type::RawEval: + case Token::Type::Expand: return set_target(expand(content, context, shell_context)); case Token::Type::Raw: case Token::Type::RawQuoted: @@ -425,7 +427,7 @@ Optional CommandParser::read_token(bool throw_on_unterminated) ParseResult quoted = parse_quoted(m_state, c); if (throw_on_unterminated and not quoted.terminated) throw parse_error{format("unterminated string {0}...{0}", c)}; - return Token{c == '"' ? Token::Type::RawEval + return Token{c == '"' ? Token::Type::Expand : Token::Type::RawQuoted, start - line.begin(), std::move(quoted.content), quoted.terminated}; @@ -613,7 +615,7 @@ Optional CommandManager::command_info(const Context& context, Strin { if (it->type == Token::Type::Raw or it->type == Token::Type::RawQuoted or - it->type == Token::Type::RawEval) + it->type == Token::Type::Expand) params.push_back(it->content); } String helpstr = cmd->value.helper(context, params); @@ -692,9 +694,9 @@ static Completions complete_expansion(const Context& context, CompletionFlags fl } } -static Completions complete_raw_eval(const Context& context, CompletionFlags flags, - StringView prefix, ByteCount start, - ByteCount cursor_pos, ByteCount pos_in_token) +static Completions complete_expand(const Context& context, CompletionFlags flags, + StringView prefix, ByteCount start, + ByteCount cursor_pos, ByteCount pos_in_token) { ParseState state{prefix, prefix.begin()}; while (state) @@ -849,8 +851,8 @@ Completions CommandManager::complete(const Context& context, return offset_pos(requote(command.completer(context, flags, params, index, pos_in_token), token.type), start); } - case Token::Type::RawEval: - return complete_raw_eval(context, flags, token.content, start, cursor_pos, pos_in_token); + case Token::Type::Expand: + return complete_expand(context, flags, token.content, start, cursor_pos, pos_in_token); default: break; } diff --git a/src/command_manager.hh b/src/command_manager.hh index 503e1977..8804b5b2 100644 --- a/src/command_manager.hh +++ b/src/command_manager.hh @@ -45,7 +45,7 @@ struct Token { Raw, RawQuoted, - RawEval, + Expand, ShellExpand, RegisterExpand, OptionExpand, diff --git a/src/main.cc b/src/main.cc index fef83090..b64b14d6 100644 --- a/src/main.cc +++ b/src/main.cc @@ -44,6 +44,11 @@ struct { unsigned int version; StringView notes; } constexpr version_notes[] = { { + 0, + "» History is now stored linearly instead of in a tree\n" + "» {+u}%exp\\{...}{} expansions provide flexible quoting for expanded " + "strings (as double quoted strings)\n" + }, { 20221031, "» {+b}{} does not end macro recording anymore, use {+b}Q{}\n" "» pipe commands do not append final end-of-lines anymore\n"