From: "René Scharfe" <rene.scharfe@lsrfire.ath.cx>
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH 0/3] Generalized "string function" syntax
Date: Sun, 08 Nov 2009 02:02:20 +0100 [thread overview]
Message-ID: <4AF6189C.9050500@lsrfire.ath.cx> (raw)
In-Reply-To: <7vd44jx9at.fsf@alter.siamese.dyndns.org>
Junio C Hamano schrieb:
> René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:
>> I'm more in favour of adding ways to customize the shape of the elements
>> rather than adding string functions. %S(width=76,indent=4) over
>> %[wrap(76,4)%s%].
>
> Yeah, %X(some modifier) that can apply to any 'X' looks much simpler and
> easier to look at. The way the code is structured currently it might be
> more work and risk to break things, though.
Here's something along this line. It's an experiment that tries to
explore named parameters and extending individual place holders instead of
adding a generic modifier (%w).
The patch implements a way to pass named parameters to %s and %b. Those
parameters are width, indent1 and indent2, which are then passed to
strbuf_add_wrapped_text() to indent and wrap the subject or body text,
respectively.
Handling wrapping for the individual place holders avoids having to deal
with terminal colour codes. The patch that implements %w() currently in
next ignores this issue.
It also allows to avoid copying the results around -- no temporary strbuf
is needed for %b(). However, quick tests showed no measurable performance
improvement.
While indent1 and indent2 are numerical parameters in this patch, they
really should be strings, in order to allow indenting using tabs etc..
For that to work, strbuf_add_wrapped_text() would need to be changed
first, though.
The parser parse_params() supports strings and numerical values, but only
the latter are used in this patch. String parameters are intended to be
fed to unquote_c_style(). It never complains about syntax errors. It
aborts if the string ends prematurely, but otherwise ignores invalid input
and just keeps going. That's how the % place holder parser has always
worked, but perhaps the introduction of named parameters justifies a more
strict approach?
My main motivation for this experiment was to avoid extra copies in the
hope to speed things up. However, my basic timing tests show that it's
not that much of an improvement.
The remaining reason is the handling of colour codes. I think we can keep
ignoring this issue -- the only impact is that lines with colour codes and
wrapping combined (e.g. "%w(72)%Cred%s") shorter than they should be,
because the colour code is considered (incorrectly) to have a non-zero
width. I think we can get away with mentioning that fact in the docs.
After all, one can simple use "%Cred%w(72)%s".
Anyway, here's the patch.
pretty.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 150 insertions(+), 4 deletions(-)
diff --git a/pretty.c b/pretty.c
index da15cf2..09272ec 100644
--- a/pretty.c
+++ b/pretty.c
@@ -596,6 +596,117 @@ static void format_decoration(struct strbuf *sb, const struct commit *commit)
strbuf_addch(sb, ')');
}
+struct param {
+ const char *name;
+ long *numeric_value;
+ const char *value;
+ size_t value_len;
+};
+
+static size_t prefixlen(const char *s, const char *prefix)
+{
+ size_t len = 0;
+
+ while (*prefix) {
+ if (*s != *prefix)
+ return 0;
+ s++;
+ prefix++;
+ len++;
+ }
+ return len;
+}
+
+static size_t parse_params(const char *s, struct param *params, int count,
+ int end)
+{
+ const char *start = s;
+ int i;
+
+ for (;;) {
+ while (isspace(*s))
+ s++;
+again:
+ if (*s == end)
+ return s - start + 1;
+ if (*s == '\0')
+ return 0;
+
+ for (i = 0; i < count; i++) {
+ size_t len = prefixlen(s, params[i].name);
+ if (len) {
+ if (s[len] == end)
+ return s - start + 1;
+ if (s[len] == '\0')
+ return 0;
+ if (isspace(s[len])) {
+ s += len + 1;
+ while (isspace(*s))
+ s++;
+ if (*s != '=')
+ goto again;
+ s++;
+ break;
+ } else if (s[len] == '=') {
+ s += len + 1;
+ break;
+ }
+ }
+ }
+
+ if (i < count) {
+ while (isspace(*s))
+ s++;
+ if (*s == end)
+ return s - start + 1;
+ if (*s == '\0')
+ return 0;
+
+ params[i].value = s;
+ if (*s == '"') {
+ for (;;) {
+ int quoted = 0;
+ const char *q;
+
+ s = strchr(s + 1, '"');
+ if (!s)
+ return 0;
+
+ for (q = s - 1; *q == '\\'; q--)
+ quoted = !quoted;
+ if (!quoted)
+ break;
+ }
+ s++;
+ } else {
+ char *endp;
+ long num = strtol(s, &endp, 10);
+
+ s = endp;
+ if (isspace(*s) || *s == end) {
+ if (params[i].numeric_value)
+ *params[i].numeric_value = num;
+ } else {
+ while (!isspace(*s) && *s != end) {
+ if (*s == '\0')
+ return 0;
+ s++;
+ }
+ }
+ }
+ params[i].value_len = s - params[i].value;
+ } else {
+ while (!isspace(*s)) {
+ if (*s == end)
+ return s - start + 1;
+ if (*s == '\0')
+ return 0;
+ s++;
+ }
+ }
+ }
+}
+
static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
void *context)
{
@@ -744,14 +855,49 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
switch (placeholder[0]) {
case 's': /* subject */
- format_subject(sb, msg + c->subject_off, " ");
- return 1;
+ if (placeholder[1] == '(') {
+ struct strbuf subject = STRBUF_INIT;
+ long indent1 = 0, indent2 = 0, width = 0;
+ struct param params[] = {
+ { "indent1", &indent1 },
+ { "indent2", &indent2 },
+ { "width", &width },
+ };
+ size_t consumed = parse_params(placeholder + 2, params,
+ ARRAY_SIZE(params), ')');
+ if (!consumed)
+ return 0;
+ format_subject(&subject, msg + c->subject_off, " ");
+ strbuf_add_wrapped_text(sb, subject.buf, indent1,
+ indent2, width);
+ strbuf_release(&subject);
+ return consumed + 2;
+ } else {
+ format_subject(sb, msg + c->subject_off, " ");
+ return 1;
+ }
case 'f': /* sanitized subject */
format_sanitized_subject(sb, msg + c->subject_off);
return 1;
case 'b': /* body */
- strbuf_addstr(sb, msg + c->body_off);
- return 1;
+ if (placeholder[1] == '(') {
+ long indent1 = 0, indent2 = 0, width = 0;
+ struct param params[] = {
+ { "indent1", &indent1 },
+ { "indent2", &indent2 },
+ { "width", &width },
+ };
+ size_t consumed = parse_params(placeholder + 2, params,
+ ARRAY_SIZE(params), ')');
+ if (!consumed)
+ return 0;
+ strbuf_add_wrapped_text(sb, msg + c->body_off, indent1,
+ indent2, width);
+ return consumed + 2;
+ } else {
+ strbuf_addstr(sb, msg + c->body_off);
+ return 1;
+ }
}
return 0; /* unknown placeholder */
}
prev parent reply other threads:[~2009-11-08 1:02 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 ` [PATCH 3/3] Add proof-of-concept %[w(width,in1,in2)<<any-string>>%] implementation Junio C Hamano
2009-10-16 11:32 ` 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 [this message]
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=4AF6189C.9050500@lsrfire.ath.cx \
--to=rene.scharfe@lsrfire.ath.cx \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).