Teach for-each-ref about a little language called Tcl.
PATCH 1/1 Teach for-each-ref about a little language called Tcl.
Love it or hate it, some people actually still program in Tcl. Some of those programs are meant for interfacing with Git. Programs such as gitk and git-gui. It may be useful to have Tcl-safe output available from for-each-ref, just like shell, Perl and Python already enjoy.
Thanks to Sergey Vlasov for pointing out the horrible flaws in the first version of this patch, and steering me in the right direction for Tcl value quoting.
---
This replaces my prior patch. As Sergey pointed out, it was horribly broken.
Documentation/git-for-each-ref.txt | 4 ++-- builtin-for-each-ref.c | 10 ++++++++++ quote.c | 36 ++++++++++++++++++++++++++++++++++++ quote.h | 1 + 4 files changed, 49 insertions(+), 2 deletions(-)
Documentation/git-for-each-ref.txt +2 -2
@@ -7,7 +7,7 @@ git-for-each-ref - Output information on each ref SYNOPSIS -------- -'git-for-each-ref' [--count=<count>]\* [--shell|--perl|--python] [--sort=<key>]\* [--format=<format>] [<pattern>] +'git-for-each-ref' [--count=<count>]\* [--shell|--perl|--python|--tcl] [--sort=<key>]\* [--format=<format>] [<pattern>] DESCRIPTION -----------
@@ -49,7 +49,7 @@ OPTIONS using fnmatch(3). Refs that do not match the pattern are not shown. ---shell, --perl, --python:: +--shell, --perl, --python, --tcl:: If given, strings that substitute `%(fieldname)` placeholders are quoted as string literals suitable for the specified host language. This is meant to produce
builtin-for-each-ref.c +10 -0
@@ -12,6 +12,7 @@#define QUOTE_SHELL 1#define QUOTE_PERL 2#define QUOTE_PYTHON 3 +#define QUOTE_TCL 4typedef enum {FIELD_STR ,FIELD_ULONG ,FIELD_TIME }cmp_type ;
@@ -723,6 +724,9 @@ static void print_value(struct refinfo *ref, int atom, int quote_style)case QUOTE_PYTHON :python_quote_print (stdout, v->s);break ; +case QUOTE_TCL : +tcl_quote_print (stdout, v->s); +break ; } }
@@ -834,6 +838,12 @@ int cmd_for_each_ref(int ac, const char **av, char *prefix) quote_style =QUOTE_PYTHON ;continue ; } +if (!strcmp (arg,"--tcl" ) ) { +if (0 <= quote_style) +die ("more than one quoting style?" ); + quote_style =QUOTE_TCL ; +continue ; + }if (!strncmp (arg,"--count=" ,8 )) {if (maxcount)die ("more than one --count?" );
quote.c +36 -0
@@ -387,3 +387,39 @@ void python_quote_print(FILE *stream, const char *src) }fputc (sq, stream); } + +void tcl_quote_print (FILE *stream,const char *src) +{ +char c; + +fputc ('"' , stream); +while ((c = *src++)) { +switch (c) { +case '[' : +case ']' : +case '$' : +case '\\' : +case '"' : +fputc ('\\' , stream); +default : +fputc (c, stream); +break ; +case '\f' : +fputs ("\\f" , stream); +break ; +case '\r' : +fputs ("\\r" , stream); +break ; +case '\n' : +fputs ("\\n" , stream); +break ; +case '\t' : +fputs ("\\t" , stream); +break ; +case '\v' : +fputs ("\\v" , stream); +break ; + } + } +fputc ('"' , stream); +}
quote.h +1 -0
@@ -55,5 +55,6 @@ extern void write_name_quoted(const char *prefix, int prefix_len,/* quoting as a string literal for other languages */ extern void perl_quote_print (FILE *stream,const char *src);extern void python_quote_print (FILE *stream,const char *src); +extern void tcl_quote_print (FILE *stream,const char *src);#endif
Signature · 1 line
1.5.0.rc2.gf127
Quoted 8 lines · Shawn O. Pearce
Love it or hate it, some people actually still program in Tcl. Some of those programs are meant for interfacing with Git. Programs such as gitk and git-gui. It may be useful to have Tcl-safe output available from for-each-ref, just like shell, Perl and Python already enjoy.
Thanks to Sergey Vlasov for pointing out the horrible flaws in the first version of this patch, and steering me in the right direction for Tcl value quoting.
[...]
Quoted 25 lines
quote.c +25
-0+void tcl_quote_print (FILE *stream,const char *src) +{ +char c; + +fputc ('"' , stream); +while ((c = *src++)) { +switch (c) { +case '[' : +case ']' : +case '$' : +case '\\' : +case '"' : +fputc ('\\' , stream); +default : +fputc (c, stream); +break ; +case '\f' : +fputs ("\\f" , stream); +break ; +case '\r' : +fputs ("\\r" , stream); +break ; +case '\n' : +fputs ("\\n" , stream); +break ;
quote.c void python_quote_print(FILE *stream, const char *src) · line 425
Quoted 10 lines
quote.c +10
-0+case '\t' : +fputs ("\\t" , stream); +break ; +case '\v' : +fputs ("\\v" , stream); +break ; + } + } +fputc ('"' , stream); +}
This is better; however, wrapping this format inside { ... } (which you may want to do in the template for some uses) won't work if the string contains unmatched braces. Quoting '{' and '}' characters with backslashes should fix this.
BTW, escaping newline characters as done here is not strictly required for a double-quoted string, but is very useful, because you may read the output line by line with "gets" and get fields from each line with "lindex"; without this escaping you will need to read the whole output before trying to parse it as a single huge list.
Quoted 4 lines · Sergey Vlasov
This is better; however, wrapping this format inside { ... } (which you may want to do in the template for some uses) won't work if the string contains unmatched braces. Quoting '{' and '}' characters with backslashes should fix this.
Then I'd commit after applying this on top of Shawn's. Ok?
quote.c +3 -5
@@ -395,11 +395,9 @@ void tcl_quote_print(FILE *stream, const char *src)fputc ('"' , stream);while ((c = *src++)) {switch (c) { -case '[' : -case ']' : -case '$' : -case '\\' : -case '"' : +case '[' :case ']' : +case '{' :case '}' : +case '$' :case '\\' :case '"' :fputc ('\\' , stream);default :fputc (c, stream);
Quoted 11 lines · Junio C Hamano
Then I'd commit after applying this on top of Shawn's. Ok?
quote.c +0
-1@@ -395,11 +395,9 @@ void tcl_quote_print(FILE *stream, const char *src)fputc ('"' , stream);while ((c = *src++)) {switch (c) { -case '[' :
quote.c void tcl_quote_print(FILE *stream, const char *src) · line 403
Quoted 10 lines
quote.c +3
-4-case ']' : -case '$' : -case '\\' : -case '"' : +case '[' :case ']' : +case '{' :case '}' : +case '$' :case '\\' :case '"' :fputc ('\\' , stream);default :fputc (c, stream);
Looks OK (still didn't have time to actually test this thing).