From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH 3/3] Add proof-of-concept %[w(width,in1,in2)<<any-string>>%] implementation
Date: Fri, 16 Oct 2009 01:28:22 -0700 [thread overview]
Message-ID: <1255681702-5215-4-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1255681702-5215-1-git-send-email-gitster@pobox.com>
This uses the strbuf_nested_expand() mechanism introduced earlier
to demonstrate how to implement a nested string function. It does
not "wrap" using the line-wrap code, but lifting the change by Dscho
and plugging it in should be a trivial exercise.
The overall idea is to parse something like "%[w(72,4,8)%an %ae %s%]" in
these steps:
#1 "%[" introduces the nested string function.
#2 After that, a name identifies what function to call.
#3 The function parses its parameters ("(72,4,8)" in the above example),
and makes a nested expansion on the remainder of the format string.
#4 The nested expansion is terminated at "%]" and returned to the
function.
#5 The function massages the string returned from #4, and the result
becomes the expansion of the whole thing.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
pretty.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 84 insertions(+), 0 deletions(-)
diff --git a/pretty.c b/pretty.c
index 587101f..a8a38c3 100644
--- a/pretty.c
+++ b/pretty.c
@@ -595,6 +595,80 @@ static void format_decoration(struct strbuf *sb, const struct commit *commit)
strbuf_addch(sb, ')');
}
+typedef int (*string_fmt_fn)(struct strbuf *sb, const char *placeholder, void *context);
+static size_t format_commit_item(struct strbuf *, const char *, void *);
+
+static int wrap_fn(struct strbuf *sb, const char *placeholder, void *context)
+{
+ const char *template = placeholder;
+ char *endptr;
+ long width = 0, indent1 = 0, indent2 = 0;
+
+ width = strtol(template, &endptr, 10);
+ if (*endptr == ',') {
+ template = endptr + 1;
+ indent1 = strtol(template, &endptr, 10);
+ if (*endptr == ',') {
+ template = endptr + 1;
+ indent2 = strtol(template, &endptr, 10);
+ }
+ }
+ if (*endptr++ != ')')
+ return 0;
+
+ template = endptr;
+ strbuf_nested_expand(sb, &template, format_commit_item, context);
+ if (*template++ != ']')
+ return 0;
+
+ /*
+ * NEEDSWORK: here you wrap the contents of substr with
+ * strbuf_wrap(&substr, width, indent1, indent2);
+ *
+ * ... but I am too lazy to do that here, and I just demonstrate
+ * how it should work by just upcasing the result ;-)
+ */
+ {
+ int i;
+ for (i = 0; i < sb->len; i++)
+ sb->buf[i] = toupper(sb->buf[i]);
+ }
+ return template - placeholder;
+}
+
+static struct {
+ const char *name;
+ string_fmt_fn fn;
+} format_fn_list[] = {
+ { "w(", wrap_fn }
+};
+
+static size_t format_fn(struct strbuf *sb, const char *placeholder,
+ void *context)
+{
+ const char *template = placeholder;
+ size_t consumed;
+ struct strbuf substr = STRBUF_INIT;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(format_fn_list); i++)
+ if (!prefixcmp(template, format_fn_list[i].name))
+ break;
+ if (ARRAY_SIZE(format_fn_list) <= i)
+ return 0;
+ template += strlen(format_fn_list[i].name);
+ consumed = format_fn_list[i].fn(&substr, template, context);
+ if (!consumed) {
+ strbuf_release(&substr);
+ return 0;
+ }
+
+ strbuf_add(sb, substr.buf, substr.len);
+ template += consumed;
+ strbuf_release(&substr);
+ return template - placeholder;
+}
+
static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
void *context)
{
@@ -603,9 +677,19 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
const char *msg = commit->buffer;
struct commit_list *p;
int h1, h2;
+ size_t nested;
/* these are independent of the commit */
switch (placeholder[0]) {
+ case ']':
+ return -1;
+ case '[':
+ /*
+ * %[func(arg...) string %]: we consumed the opening '['
+ * and the callee consumed up to the closing '%]'.
+ */
+ nested = format_fn(sb, placeholder + 1, context);
+ return nested ? 1 + nested : 0;
case 'C':
if (placeholder[1] == '(') {
const char *end = strchr(placeholder + 2, ')');
--
1.6.5.99.g9ed7e
next prev parent reply other threads:[~2009-10-16 8:33 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-16 8:28 [PATCH 0/3] Generalized "string function" syntax Junio C Hamano
2009-10-16 8:28 ` [PATCH 1/3] format_commit_message(): fix function signature Junio C Hamano
2009-10-17 21:04 ` René Scharfe
2009-10-16 8:28 ` [PATCH 2/3] strbuf_nested_expand(): allow expansion to interrupt in the middle Junio C Hamano
2009-10-16 11:30 ` Johannes Schindelin
2009-10-16 17:22 ` Junio C Hamano
2009-10-16 8:28 ` Junio C Hamano [this message]
2009-10-16 11:32 ` [PATCH 3/3] Add proof-of-concept %[w(width,in1,in2)<<any-string>>%] implementation Johannes Schindelin
2009-10-16 17:25 ` Junio C Hamano
2009-10-16 18:02 ` Jakub Narebski
2009-10-16 19:01 ` Junio C Hamano
2009-10-16 22:19 ` Jakub Narebski
2009-10-16 23:23 ` Junio C Hamano
2009-10-17 0:00 ` Jakub Narebski
2009-10-17 0:18 ` Junio C Hamano
2009-10-17 21:04 ` [PATCH 0/3] Generalized "string function" syntax René Scharfe
2009-10-18 4:18 ` Junio C Hamano
2009-10-18 8:24 ` René Scharfe
2009-10-18 22:47 ` Junio C Hamano
2009-10-19 23:07 ` René Scharfe
2009-10-19 23:18 ` Junio C Hamano
2009-11-08 1:02 ` René Scharfe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1255681702-5215-4-git-send-email-gitster@pobox.com \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.