{"thread":{"id":"41759","subject":"[PATCH/GSoC] parse-options: Add a new nousage opt","startedAt":"2016-03-20T06:46:45Z","lastAt":"2016-03-24T17:34:27Z","messageCount":5,"participants":["Chirayu Desai","Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"281259","messageId":"1458456405-3519-1-git-send-email-chirayudesai1@gmail.com","threadId":"41759","inReplyTo":null,"subject":"[PATCH/GSoC] parse-options: Add a new nousage opt","fromName":"Chirayu Desai","fromEmail":"chirayudesai1@gmail.com","sentAt":"2016-03-20T06:46:45Z","receivedAt":"2016-03-20T06:46:45Z","isPatch":true,"sender":{"key":"chirayudesai1@gmail.com","avatar":"https://gravatar.com/avatar/c2d0bd062b197c940eaaf3ac349f63fdbe0df58a2421c140ee8c9b4f52af95e3?d=mp&s=160"},"body":"* To show only error text on an error instead of the full usage\n* Currently used only by commands with options \"--with\" or \"--contains\",\n  such as 'tag', 'branch', 'for-each-ref'.\n\nIt now prints only\n  $ git tag --contains qq\n  error: malformed object name qq\ninstead of the full usage text after the error text.\n\nTODO: Add tests\n---\n parse-options-cb.c | 12 ++++++++----\n parse-options.c    |  5 +++++\n parse-options.h    |  6 ++++--\n 3 files changed, 17 insertions(+), 6 deletions(-)\n\ndiff --git a/parse-options-cb.c b/parse-options-cb.c\nindex 239898d946..ac2ea4d674 100644\n--- a/parse-options-cb.c\n+++ b/parse-options-cb.c\n@@ -85,11 +85,15 @@ int parse_opt_commits(const struct option *opt, const char *arg, int unset)\n \n \tif (!arg)\n \t\treturn -1;\n-\tif (get_sha1(arg, sha1))\n-\t\treturn error(\"malformed object name %s\", arg);\n+\tif (get_sha1(arg, sha1)) {\n+\t\terror(\"malformed object name %s\", arg);\n+\t\treturn -3;\n+\t}\n \tcommit = lookup_commit_reference(sha1);\n-\tif (!commit)\n-\t\treturn error(\"no such commit %s\", arg);\n+\tif (!commit) {\n+\t\terror(\"no such commit %s\", arg);\n+\t\treturn -3;\n+\t}\n \tcommit_list_insert(commit, opt->value);\n \treturn 0;\n }\ndiff --git a/parse-options.c b/parse-options.c\nindex 47a9192060..d136c1afd0 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -158,6 +158,9 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\t\treturn (*opt->callback)(opt, NULL, 0) ? (-1) : 0;\n \t\tif (get_arg(p, opt, flags, &arg))\n \t\t\treturn -1;\n+\t\tif (opt->flags & PARSE_OPT_NOUSAGE) {\n+\t\t\treturn (*opt->callback)(opt, arg, 0);\n+\t\t}\n \t\treturn (*opt->callback)(opt, arg, 0) ? (-1) : 0;\n \n \tcase OPTION_INTEGER:\n@@ -504,6 +507,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n \t\t\tgoto show_usage_error;\n \t\tcase -2:\n \t\t\tgoto unknown;\n+\t\tcase -3:\n+\t\t\treturn PARSE_OPT_DONE;\n \t\t}\n \t\tcontinue;\n unknown:\ndiff --git a/parse-options.h b/parse-options.h\nindex ea4af92a51..628e34c5af 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -38,7 +38,8 @@ enum parse_opt_option_flags {\n \tPARSE_OPT_LASTARG_DEFAULT = 16,\n \tPARSE_OPT_NODASH = 32,\n \tPARSE_OPT_LITERAL_ARGHELP = 64,\n-\tPARSE_OPT_SHELL_EVAL = 256\n+\tPARSE_OPT_SHELL_EVAL = 256,\n+\tPARSE_OPT_NOUSAGE = 512\n };\n \n struct option;\n@@ -89,6 +90,7 @@ typedef int parse_opt_ll_cb(struct parse_opt_ctx_t *ctx,\n  *   PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets\n  *\t\t\t\t(i.e. '<argh>') in the help message.\n  *\t\t\t\tUseful for options with multiple parameters.\n+ *   PARSE_OPT_NOUSAGE: do not print usage / help on error.\n  *\n  * `callback`::\n  *   pointer to the callback to use for OPTION_CALLBACK or\n@@ -254,7 +256,7 @@ extern int parse_opt_passthru_argv(const struct option *, const char *, int);\n \t{ OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), parse_opt_passthru_argv }\n #define _OPT_CONTAINS_OR_WITH(name, variable, help, flag) \\\n \t{ OPTION_CALLBACK, 0, name, (variable), N_(\"commit\"), (help), \\\n-\t  PARSE_OPT_LASTARG_DEFAULT | flag, \\\n+\t  PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOUSAGE | flag, \\\n \t  parse_opt_commits, (intptr_t) \"HEAD\" \\\n \t}\n #define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH(\"contains\", v, h, 0)\n-- \n2.7.4\n"},{"id":"281261","messageId":"CAJj6+1ExK2wftTvtWEW4=RAvrYeKynSmyviqWfk1jrF-UpqmCw@mail.gmail.com","threadId":"41759","inReplyTo":"1458456405-3519-1-git-send-email-chirayudesai1@gmail.com","subject":"Re: [PATCH/GSoC] parse-options: Add a new nousage opt","fromName":"Chirayu Desai","fromEmail":"chirayudesai1@gmail.com","sentAt":"2016-03-20T06:52:18Z","receivedAt":"2016-03-20T06:52:18Z","isPatch":true,"sender":{"key":"chirayudesai1@gmail.com","avatar":"https://gravatar.com/avatar/c2d0bd062b197c940eaaf3ac349f63fdbe0df58a2421c140ee8c9b4f52af95e3?d=mp&s=160"},"body":"This is being discussed in the \"Re: \"git tag --contains <id>\" is too\nchatty, if <id> is invalid\" thread.\n$gmane/289312\n\nOn Sun, Mar 20, 2016 at 12:16 PM, Chirayu Desai <chirayudesai1@gmail.com> wrote:\n> * To show only error text on an error instead of the full usage\n> * Currently used only by commands with options \"--with\" or \"--contains\",\n>   such as 'tag', 'branch', 'for-each-ref'.\n>\n> It now prints only\n>   $ git tag --contains qq\n>   error: malformed object name qq\n> instead of the full usage text after the error text.\n>\n> TODO: Add tests\n> ---\n>  parse-options-cb.c | 12 ++++++++----\n>  parse-options.c    |  5 +++++\n>  parse-options.h    |  6 ++++--\n>  3 files changed, 17 insertions(+), 6 deletions(-)\n>\n> diff --git a/parse-options-cb.c b/parse-options-cb.c\n> index 239898d946..ac2ea4d674 100644\n> --- a/parse-options-cb.c\n> +++ b/parse-options-cb.c\n> @@ -85,11 +85,15 @@ int parse_opt_commits(const struct option *opt, const char *arg, int unset)\n>\n>         if (!arg)\n>                 return -1;\n> -       if (get_sha1(arg, sha1))\n> -               return error(\"malformed object name %s\", arg);\n> +       if (get_sha1(arg, sha1)) {\n> +               error(\"malformed object name %s\", arg);\n> +               return -3;\n> +       }\n>         commit = lookup_commit_reference(sha1);\n> -       if (!commit)\n> -               return error(\"no such commit %s\", arg);\n> +       if (!commit) {\n> +               error(\"no such commit %s\", arg);\n> +               return -3;\n> +       }\n>         commit_list_insert(commit, opt->value);\n>         return 0;\n>  }\n> diff --git a/parse-options.c b/parse-options.c\n> index 47a9192060..d136c1afd0 100644\n> --- a/parse-options.c\n> +++ b/parse-options.c\n> @@ -158,6 +158,9 @@ static int get_value(struct parse_opt_ctx_t *p,\n>                         return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;\n>                 if (get_arg(p, opt, flags, &arg))\n>                         return -1;\n> +               if (opt->flags & PARSE_OPT_NOUSAGE) {\n> +                       return (*opt->callback)(opt, arg, 0);\n> +               }\n>                 return (*opt->callback)(opt, arg, 0) ? (-1) : 0;\n>\n>         case OPTION_INTEGER:\n> @@ -504,6 +507,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n>                         goto show_usage_error;\n>                 case -2:\n>                         goto unknown;\n> +               case -3:\n> +                       return PARSE_OPT_DONE;\n>                 }\n>                 continue;\n>  unknown:\n> diff --git a/parse-options.h b/parse-options.h\n> index ea4af92a51..628e34c5af 100644\n> --- a/parse-options.h\n> +++ b/parse-options.h\n> @@ -38,7 +38,8 @@ enum parse_opt_option_flags {\n>         PARSE_OPT_LASTARG_DEFAULT = 16,\n>         PARSE_OPT_NODASH = 32,\n>         PARSE_OPT_LITERAL_ARGHELP = 64,\n> -       PARSE_OPT_SHELL_EVAL = 256\n> +       PARSE_OPT_SHELL_EVAL = 256,\n> +       PARSE_OPT_NOUSAGE = 512\nPerhaps a _ON_ERR should be appended at the end to make it clearer?\n>  };\n>\n>  struct option;\n> @@ -89,6 +90,7 @@ typedef int parse_opt_ll_cb(struct parse_opt_ctx_t *ctx,\n>   *   PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets\n>   *                             (i.e. '<argh>') in the help message.\n>   *                             Useful for options with multiple parameters.\n> + *   PARSE_OPT_NOUSAGE: do not print usage / help on error.\n>   *\n>   * `callback`::\n>   *   pointer to the callback to use for OPTION_CALLBACK or\n> @@ -254,7 +256,7 @@ extern int parse_opt_passthru_argv(const struct option *, const char *, int);\n>         { OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), parse_opt_passthru_argv }\n>  #define _OPT_CONTAINS_OR_WITH(name, variable, help, flag) \\\n>         { OPTION_CALLBACK, 0, name, (variable), N_(\"commit\"), (help), \\\n> -         PARSE_OPT_LASTARG_DEFAULT | flag, \\\n> +         PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOUSAGE | flag, \\\n>           parse_opt_commits, (intptr_t) \"HEAD\" \\\n>         }\n>  #define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH(\"contains\", v, h, 0)\n> --\n> 2.7.4\n>\n"},{"id":"281611","messageId":"20160323223157.GA12531@sigill.intra.peff.net","threadId":"41759","inReplyTo":"1458456405-3519-1-git-send-email-chirayudesai1@gmail.com","subject":"Re: [PATCH/GSoC] parse-options: Add a new nousage opt","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-03-23T22:31:57Z","receivedAt":"2016-03-23T22:31:57Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Mar 20, 2016 at 12:16:45PM +0530, Chirayu Desai wrote:\n\n> diff --git a/parse-options-cb.c b/parse-options-cb.c\n> index 239898d946..ac2ea4d674 100644\n> --- a/parse-options-cb.c\n> +++ b/parse-options-cb.c\n> @@ -85,11 +85,15 @@ int parse_opt_commits(const struct option *opt, const char *arg, int unset)\n>  \n>  \tif (!arg)\n>  \t\treturn -1;\n> -\tif (get_sha1(arg, sha1))\n> -\t\treturn error(\"malformed object name %s\", arg);\n> +\tif (get_sha1(arg, sha1)) {\n> +\t\terror(\"malformed object name %s\", arg);\n> +\t\treturn -3;\n> +\t}\n\nNow that we have a few meaningful return values, should we have some\nenum that gives them human-readable names?\n\nE.g., why don't we allow \"-2\" here? I think it is because\nparse_options_step internally uses it for \"I don't know about that\noption\". But maybe we should have something like:\n\n  enum PARSE_OPT_ERROR {\n          PARSE_OPT_ERR_USAGE = -1,\n\t  PARSE_OPT_ERR_UNKNOWN_OPTION = -2,\n\t  PARSE_OPT_ERR_FAIL_QUIETLY = -3,\n  }\n\n(I don't quite like the final name, but I couldn't think of anything\nbetter).\n\n> diff --git a/parse-options.c b/parse-options.c\n> index 47a9192060..d136c1afd0 100644\n> --- a/parse-options.c\n> +++ b/parse-options.c\n> @@ -158,6 +158,9 @@ static int get_value(struct parse_opt_ctx_t *p,\n>  \t\t\treturn (*opt->callback)(opt, NULL, 0) ? (-1) : 0;\n>  \t\tif (get_arg(p, opt, flags, &arg))\n>  \t\t\treturn -1;\n> +\t\tif (opt->flags & PARSE_OPT_NOUSAGE) {\n> +\t\t\treturn (*opt->callback)(opt, arg, 0);\n> +\t\t}\n>  \t\treturn (*opt->callback)(opt, arg, 0) ? (-1) : 0;\n\nHere you use PARSE_OPT_NOUSAGE to pass the callback's value directly\nback to the rest of the option-parsing code. But can't we just intercept\n\"-3\" always? It's possible that another callback is using it to\ngenerically return an error, but it seems like a rather low risk, and\nthe resulting code is much simpler.\n\nOr we could go the opposite direction. If a callback is annotated with\nPARSE_OPT_NOUSAGE, why do we even need to care about its return value?\nThe callback could continue to return -1, and we would simply suppress\nthe usage message.\n\n>  \tcase OPTION_INTEGER:\n> @@ -504,6 +507,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n>  \t\t\tgoto show_usage_error;\n>  \t\tcase -2:\n>  \t\t\tgoto unknown;\n> +\t\tcase -3:\n> +\t\t\treturn PARSE_OPT_DONE;\n>  \t\t}\n>  \t\tcontinue;\n>  unknown:\n\nIf I understand correctly, this is now getting the value from the\ncallback directly. What happens if a callback returns \"-4\" or \"4\"?\n\nAlso, this covers the parse_long_opt() call, but there are two\nparse_short_opt() calls earlier. Wouldn't they need to learn the same\nlogic?\n\n-Peff\n"},{"id":"281689","messageId":"CAJj6+1EYYiK3qjOpZLBZG1d0FfW2r67759dCcLjxEy=+vFN0Dg@mail.gmail.com","threadId":"41759","inReplyTo":"20160323223157.GA12531@sigill.intra.peff.net","subject":"Re: [PATCH/GSoC] parse-options: Add a new nousage opt","fromName":"Chirayu Desai","fromEmail":"chirayudesai1@gmail.com","sentAt":"2016-03-24T17:21:05Z","receivedAt":"2016-03-24T17:21:05Z","isPatch":true,"sender":{"key":"chirayudesai1@gmail.com","avatar":"https://gravatar.com/avatar/c2d0bd062b197c940eaaf3ac349f63fdbe0df58a2421c140ee8c9b4f52af95e3?d=mp&s=160"},"body":"Note Before: I have decided not to apply for GSoC with Git this year,\nas I was already late, and all the remaining time got taken by the\nproposal I wrote for Debian, and college studies / exams.\n\nI definitely want to work with Git in the future too, it has always\npiqued my interest being something that I use daily.\nI want to get this change done as well, if that is okay.\n\nOn Thu, Mar 24, 2016 at 4:01 AM, Jeff King <peff@peff.net> wrote:\n> On Sun, Mar 20, 2016 at 12:16:45PM +0530, Chirayu Desai wrote:\n>\n>> diff --git a/parse-options-cb.c b/parse-options-cb.c\n>> index 239898d946..ac2ea4d674 100644\n>> --- a/parse-options-cb.c\n>> +++ b/parse-options-cb.c\n>> @@ -85,11 +85,15 @@ int parse_opt_commits(const struct option *opt, const char *arg, int unset)\n>>\n>>       if (!arg)\n>>               return -1;\n>> -     if (get_sha1(arg, sha1))\n>> -             return error(\"malformed object name %s\", arg);\n>> +     if (get_sha1(arg, sha1)) {\n>> +             error(\"malformed object name %s\", arg);\n>> +             return -3;\n>> +     }\n>\n> Now that we have a few meaningful return values, should we have some\n> enum that gives them human-readable names?\n>\n> E.g., why don't we allow \"-2\" here? I think it is because\n> parse_options_step internally uses it for \"I don't know about that\n> option\". But maybe we should have something like:\n>\n>   enum PARSE_OPT_ERROR {\n>           PARSE_OPT_ERR_USAGE = -1,\n>           PARSE_OPT_ERR_UNKNOWN_OPTION = -2,\n>           PARSE_OPT_ERR_FAIL_QUIETLY = -3,\n>   }\n>\n> (I don't quite like the final name, but I couldn't think of anything\n> better).\nI agree, this would be much better and clearer than using hard coded values.\n>\n>> diff --git a/parse-options.c b/parse-options.c\n>> index 47a9192060..d136c1afd0 100644\n>> --- a/parse-options.c\n>> +++ b/parse-options.c\n>> @@ -158,6 +158,9 @@ static int get_value(struct parse_opt_ctx_t *p,\n>>                       return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;\n>>               if (get_arg(p, opt, flags, &arg))\n>>                       return -1;\n>> +             if (opt->flags & PARSE_OPT_NOUSAGE) {\n>> +                     return (*opt->callback)(opt, arg, 0);\n>> +             }\n>>               return (*opt->callback)(opt, arg, 0) ? (-1) : 0;\n>\n> Here you use PARSE_OPT_NOUSAGE to pass the callback's value directly\n> back to the rest of the option-parsing code. But can't we just intercept\n> \"-3\" always? It's possible that another callback is using it to\n> generically return an error, but it seems like a rather low risk, and\n> the resulting code is much simpler.\nI don't get what you mean by intercepting '-3'.\nThe idea was that other options could use it in the future to return\narbitary values.\n>\n> Or we could go the opposite direction. If a callback is annotated with\n> PARSE_OPT_NOUSAGE, why do we even need to care about its return value?\n> The callback could continue to return -1, and we would simply suppress\n> the usage message.\nThat would also work, but I feel that this is cleaner.\n>\n>>       case OPTION_INTEGER:\n>> @@ -504,6 +507,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n>>                       goto show_usage_error;\n>>               case -2:\n>>                       goto unknown;\n>> +             case -3:\n>> +                     return PARSE_OPT_DONE;\n>>               }\n>>               continue;\n>>  unknown:\n>\n> If I understand correctly, this is now getting the value from the\n> callback directly. What happens if a callback returns \"-4\" or \"4\"?\nThat could be handled in the future if somebody decides to use that.\nNow this makes using the above \"return -1 always but don't print usage if flags\ncontain PARSE_OPT_NOUSAGE\" option look much better.\n>\n> Also, this covers the parse_long_opt() call, but there are two\n> parse_short_opt() calls earlier. Wouldn't they need to learn the same\n> logic?\nI didn't add it right now as both \"--contains\" and \"--with\" are long opts.\n>\n> -Peff\n\nThanks,\nChirayu\n"},{"id":"281692","messageId":"20160324173427.GC6341@sigill.intra.peff.net","threadId":"41759","inReplyTo":"CAJj6+1EYYiK3qjOpZLBZG1d0FfW2r67759dCcLjxEy=+vFN0Dg@mail.gmail.com","subject":"Re: [PATCH/GSoC] parse-options: Add a new nousage opt","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-03-24T17:34:27Z","receivedAt":"2016-03-24T17:34:27Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 24, 2016 at 10:51:05PM +0530, Chirayu Desai wrote:\n\n> I definitely want to work with Git in the future too, it has always\n> piqued my interest being something that I use daily.\n> I want to get this change done as well, if that is okay.\n\nSure, that's great. Part of the point of microprojects is that they're\nuseful changes on their own, outside of GSoC.\n\n> >> diff --git a/parse-options.c b/parse-options.c\n> >> index 47a9192060..d136c1afd0 100644\n> >> --- a/parse-options.c\n> >> +++ b/parse-options.c\n> >> @@ -158,6 +158,9 @@ static int get_value(struct parse_opt_ctx_t *p,\n> >>                       return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;\n> >>               if (get_arg(p, opt, flags, &arg))\n> >>                       return -1;\n> >> +             if (opt->flags & PARSE_OPT_NOUSAGE) {\n> >> +                     return (*opt->callback)(opt, arg, 0);\n> >> +             }\n> >>               return (*opt->callback)(opt, arg, 0) ? (-1) : 0;\n> >\n> > Here you use PARSE_OPT_NOUSAGE to pass the callback's value directly\n> > back to the rest of the option-parsing code. But can't we just intercept\n> > \"-3\" always? It's possible that another callback is using it to\n> > generically return an error, but it seems like a rather low risk, and\n> > the resulting code is much simpler.\n> I don't get what you mean by intercepting '-3'.\n> The idea was that other options could use it in the future to return\n> arbitary values.\n\nI mean could this code just be:\n\n  switch (opt->callback(opt, arg, 0)) {\n  case 0: /* ok, no error */\n\treturn 0;\n  case -3: /* error, but we were asked not to show usage; relay it */\n\treturn -3;\n  default: /* anything else is a normal error */\n\treturn -1;\n  }\n\nDo we need PARSE_OPT_NOUSAGE at all?\n\n> > Or we could go the opposite direction. If a callback is annotated with\n> > PARSE_OPT_NOUSAGE, why do we even need to care about its return value?\n> > The callback could continue to return -1, and we would simply suppress\n> > the usage message.\n> That would also work, but I feel that this is cleaner.\n\nYeah, I think it comes down to where the decision for \"don't show usage\"\nshould be made. Is it something that the options-list (that is using the\ncallback) knows, or is it something that the callback knows?\n\n> >>       case OPTION_INTEGER:\n> >> @@ -504,6 +507,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,\n> >>                       goto show_usage_error;\n> >>               case -2:\n> >>                       goto unknown;\n> >> +             case -3:\n> >> +                     return PARSE_OPT_DONE;\n> >>               }\n> >>               continue;\n> >>  unknown:\n> >\n> > If I understand correctly, this is now getting the value from the\n> > callback directly. What happens if a callback returns \"-4\" or \"4\"?\n> That could be handled in the future if somebody decides to use that.\n> Now this makes using the above \"return -1 always but don't print usage if flags\n> contain PARSE_OPT_NOUSAGE\" option look much better.\n\nWhat I meant specifically was that I think a callback returning \"-4\" is\nan error (with usage) in the current code, but is silently ignored with\nyour patch (if PARSE_OPT_NOUSAGE is set, of course), making it a\npotential hazard.\n\n> > Also, this covers the parse_long_opt() call, but there are two\n> > parse_short_opt() calls earlier. Wouldn't they need to learn the same\n> > logic?\n> I didn't add it right now as both \"--contains\" and \"--with\" are long opts.\n\nYeah, I agree it is not necessary for those long opts, but it seems like\na maintenance hazard for it to work in one case, but not another. IOW,\nit would be a big surprise for somebody who later adds a short option\nfor \"--contains\", or who adds PARSE_OPT_NOUSAGE to an existing short\noption.\n\n-Peff\n"}]}