From d1b685aa359f13e2a4e1de50355f668e1549b9bd Mon Sep 17 00:00:00 2001 From: William Erik Baxter Date: Tue, 13 Aug 2024 12:06:47 -0500 Subject: [PATCH 1/2] Implement echo -quoting json Format each argument as a json string and join on newline Split out quoting.hh from string_utils.hh. Also split options_strings.hh from string_utils.hh. This seemed less awkward than keeping the material in quoting.hh. Added `#include ` to strings.hh. Without this compile failed on FreeBSD 14.1, clang version 18.1.5. --- doc/pages/commands.asciidoc | 3 ++ src/command_manager.cc | 1 + src/commands.cc | 11 +++++-- src/normal.cc | 2 ++ src/option_manager.hh | 2 ++ src/option_strings.hh | 19 ++++++++++++ src/option_types.hh | 2 ++ src/quoting.hh | 60 +++++++++++++++++++++++++++++++++++++ src/regex.cc | 3 ++ src/shell_manager.cc | 1 + src/string.hh | 1 + src/string_utils.hh | 43 -------------------------- 12 files changed, 102 insertions(+), 46 deletions(-) create mode 100644 src/option_strings.hh create mode 100644 src/quoting.hh diff --git a/doc/pages/commands.asciidoc b/doc/pages/commands.asciidoc index 6b5a48e57c..b9dd6fa1f0 100644 --- a/doc/pages/commands.asciidoc +++ b/doc/pages/commands.asciidoc @@ -278,6 +278,9 @@ of the file onto the filesystem also wrap each arguments in single quotes and escape embedded quotes in a shell compatible way. + - *json*:::: + convert each argument to a json string and join on newline. + *set-face* :: *alias* face + define a face in *scope* diff --git a/src/command_manager.cc b/src/command_manager.cc index 3e44ab1ebb..7a6ac159cd 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -10,6 +10,7 @@ #include "optional.hh" #include "option_types.hh" #include "profile.hh" +#include "quoting.hh" #include "ranges.hh" #include "regex.hh" #include "register_manager.hh" diff --git a/src/commands.cc b/src/commands.cc index 8446edf59d..81c88b1e75 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -19,9 +19,11 @@ #include "insert_completer.hh" #include "normal.hh" #include "option_manager.hh" +#include "option_strings.hh" #include "option_types.hh" #include "parameters_parser.hh" #include "profile.hh" +#include "quoting.hh" #include "ranges.hh" #include "ranked_match.hh" #include "regex.hh" @@ -1524,7 +1526,7 @@ const CommandDesc echo_cmd = { "echo ...: display given parameters in the status line", ParameterDesc{ { { "markup", { {}, "parse markup" } }, - { "quoting", { {arg_completer(Array{"raw", "kakoune", "shell"})}, "quote each argument separately using the given style (raw|kakoune|shell)" } }, + { "quoting", { {arg_completer(Array{"raw", "kakoune", "shell","json"})}, "quote each argument separately using the given style (raw|kakoune|shell|json)" } }, { "end-of-line", { {}, "add trailing end-of-line" } }, { "to-file", { {filename_arg_completer}, "echo contents to given filename" } }, { "to-shell-script", { ArgCompleter{}, "pipe contents to given shell script" } }, @@ -1538,8 +1540,11 @@ const CommandDesc echo_cmd = { { String message; if (auto quoting = parser.get_switch("quoting")) - message = join(parser | transform(quoter(option_from_string(Meta::Type{}, *quoting))), - ' ', false); + { + auto quoting_type = option_from_string(Meta::Type{}, *quoting); + message = join(parser | transform(quoter(quoting_type)), + (quoting_type == Quoting::Json ? '\n' : ' '), false); + } else message = join(parser, ' ', false); diff --git a/src/normal.cc b/src/normal.cc index 5a7c4e58fc..2bca00140c 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -14,7 +14,9 @@ #include "file.hh" #include "flags.hh" #include "option_manager.hh" +#include "option_strings.hh" #include "option_types.hh" +#include "quoting.hh" #include "ranges.hh" #include "regex.hh" #include "register_manager.hh" diff --git a/src/option_manager.hh b/src/option_manager.hh index 480b589be8..a4ce73eea3 100644 --- a/src/option_manager.hh +++ b/src/option_manager.hh @@ -5,6 +5,8 @@ #include "exception.hh" #include "hash_map.hh" #include "option.hh" +#include "option_strings.hh" +#include "quoting.hh" #include "ranges.hh" #include "utils.hh" #include "vector.hh" diff --git a/src/option_strings.hh b/src/option_strings.hh new file mode 100644 index 0000000000..d2bb716cb0 --- /dev/null +++ b/src/option_strings.hh @@ -0,0 +1,19 @@ +#ifndef option_strings_hh_INCLUDED +#define option_strings_hh_INCLUDED + +#include "quoting.hh" +#include "string.hh" +#include "string_utils.hh" +#include "vector.hh" + +namespace Kakoune +{ + +inline String option_to_string(StringView opt, Quoting quoting) { return quoter(quoting)(opt); } +inline Vector option_to_strings(StringView opt) { return {opt.str()}; } +inline String option_from_string(Meta::Type, StringView str) { return str.str(); } +inline bool option_add(String& opt, StringView val) { opt += val; return not val.empty(); } + +} + +#endif // option_strings_hh_INCLUDED diff --git a/src/option_types.hh b/src/option_types.hh index fedc476f09..6f56f4006c 100644 --- a/src/option_types.hh +++ b/src/option_types.hh @@ -7,6 +7,8 @@ #include "flags.hh" #include "hash_map.hh" #include "option.hh" +#include "option_strings.hh" +#include "quoting.hh" #include "string.hh" #include "string_utils.hh" #include "format.hh" diff --git a/src/quoting.hh b/src/quoting.hh new file mode 100644 index 0000000000..73c3ee0006 --- /dev/null +++ b/src/quoting.hh @@ -0,0 +1,60 @@ +#ifndef quoting_hh_INCLUDED +#define quoting_hh_INCLUDED + +#include "format.hh" +#include "json.hh" +#include "meta.hh" +#include "string.hh" +#include "string_utils.hh" + +namespace Kakoune +{ + +inline String quote(StringView s) +{ + return format("'{}'", double_up(s, "'")); +} + +inline String shell_quote(StringView s) +{ + return format("'{}'", replace(s, "'", R"('\'')")); +} + +inline String json_quote(StringView s) +{ + return format("{}", to_json(s)); +} + +enum class Quoting +{ + Raw, + Kakoune, + Shell, + Json +}; + +constexpr auto enum_desc(Meta::Type) +{ + return make_array>({ + { Quoting::Raw, "raw" }, + { Quoting::Kakoune, "kakoune" }, + { Quoting::Shell, "shell" }, + { Quoting::Json, "json" } + }); +} + +inline auto quoter(Quoting quoting) +{ + switch (quoting) + { + case Quoting::Kakoune: return "e; + case Quoting::Shell: return &shell_quote; + case Quoting::Json: return &json_quote; + case Quoting::Raw: + default: + return +[](StringView s) { return s.str(); }; + } +} + +} +#endif // quoting_hh_INCLUDED diff --git a/src/regex.cc b/src/regex.cc index b62bdddf63..07e963979c 100644 --- a/src/regex.cc +++ b/src/regex.cc @@ -1,4 +1,7 @@ #include "regex.hh" + +#include "option_strings.hh" +#include "quoting.hh" #include "ranges.hh" #include "string_utils.hh" diff --git a/src/shell_manager.cc b/src/shell_manager.cc index d08c4dbd26..37333f44ab 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -12,6 +12,7 @@ #include "flags.hh" #include "option.hh" #include "option_types.hh" +#include "quoting.hh" #include "regex.hh" #include diff --git a/src/string.hh b/src/string.hh index 0ed1dc7514..130c1c1a36 100644 --- a/src/string.hh +++ b/src/string.hh @@ -3,6 +3,7 @@ #include #include +#include #include "memory.hh" #include "hash.hh" #include "units.hh" diff --git a/src/string_utils.hh b/src/string_utils.hh index 24da011134..601d882e46 100644 --- a/src/string_utils.hh +++ b/src/string_utils.hh @@ -110,49 +110,6 @@ Optional str_to_int_ifp(StringView str); String double_up(StringView s, StringView characters); -inline String quote(StringView s) -{ - return format("'{}'", double_up(s, "'")); -} - -inline String shell_quote(StringView s) -{ - return format("'{}'", replace(s, "'", R"('\'')")); -} - -enum class Quoting -{ - Raw, - Kakoune, - Shell -}; - -constexpr auto enum_desc(Meta::Type) -{ - return make_array>({ - { Quoting::Raw, "raw" }, - { Quoting::Kakoune, "kakoune" }, - { Quoting::Shell, "shell" } - }); -} - -inline auto quoter(Quoting quoting) -{ - switch (quoting) - { - case Quoting::Kakoune: return "e; - case Quoting::Shell: return &shell_quote; - case Quoting::Raw: - default: - return +[](StringView s) { return s.str(); }; - } -} - -inline String option_to_string(StringView opt, Quoting quoting) { return quoter(quoting)(opt); } -inline Vector option_to_strings(StringView opt) { return {opt.str()}; } -inline String option_from_string(Meta::Type, StringView str) { return str.str(); } -inline bool option_add(String& opt, StringView val) { opt += val; return not val.empty(); } - } #endif // string_utils_hh_INCLUDED From d7a7d0faa25699885134424cc168491de07c780f Mon Sep 17 00:00:00 2001 From: William Erik Baxter Date: Tue, 13 Aug 2024 18:41:26 -0500 Subject: [PATCH 2/2] William Baxter Copyright Waiver I dedicate any and all copyright interest in this software to the public domain. I make this dedication for the benefit of the public at large and to the detriment of my heirs and successors. I intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.