git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jeff King <peff@peff.net>
To: Robert Dailey <rcdailey.lists@gmail.com>
Cc: Git <git@vger.kernel.org>
Subject: Re: Conditional newline in pretty format
Date: Tue, 17 Mar 2020 13:55:58 -0400	[thread overview]
Message-ID: <20200317175558.GA16061@coredump.intra.peff.net> (raw)
In-Reply-To: <CAHd499AfYZth1oFii66iUMDJTKVaa-S1K37jt2V027EmYsGPkA@mail.gmail.com>

On Tue, Mar 17, 2020 at 12:27:00PM -0500, Robert Dailey wrote:

> > I wonder in the meantime if it would be possible to introduce a block
> > syntax to the pretty formats, like:
> >
> >   git log --format='* %s%n%+{%w(100,2,2)%b}'
> >
> > or something. I don't know the conditional code well enough to say
> > whether that would be a trivial patch or a horribly complicated one. :)
> 
> Thanks for the information. It could also be that for something this
> complex, expecting Git to do it internally might be unreasonable. I'll
> try to come up with a bash script to replace the alias. It'll be a lot
> more verbose but I can take more of a "string builder" approach in an
> actual script which might be more intuitive. I just wanted to check
> for any bugs/built-in behavior before I go that route.

Yeah, I think it would be easy to do something like this with perl
(possibly using Git's --format directives to make it easier to parse the
individual pieces). Once upon a time I had a hacky patch to let you
format with lua inside Git, which would have made this trivial. But it
needed quite a bit of polishing.

At any rate, here's a patch for %{}. It seems to work but I think it may
be too hacky within the current system. One thing in particular is that
%w takes effect for the rest of the string, and we apply it
retroactively at the end of the string. I think we'd want to "push" a
new context onto a stack and pop it at the end of the block. But the
current format_commit_context is a bit muddled; some of the things we'd
want to do this with (wrapping, padding, etc) but not others (parsed
elements of the commit we've parsed).

I didn't pursue it further because I think the right solution is doing
an up-front parse of the format string into a true recursive parse tree,
and then walking that tree to format each commit.

But in the meantime, you can hack around it by "popping" the wrap
parameters manually at the end of the block:

  git log --format='* %s%n%+{%w(100,2,2)%b%w(0,0,0)}'

---
diff --git a/pretty.c b/pretty.c
index 28afc701b6..659fc4f3e9 100644
--- a/pretty.c
+++ b/pretty.c
@@ -1146,6 +1146,9 @@ static int format_trailer_match_cb(const struct strbuf *key, void *ud)
 	return 0;
 }
 
+static size_t format_commit_item(struct strbuf *, const char *placeholder,
+				 void *context);
+
 static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
 				const char *placeholder,
 				void *context)
@@ -1209,6 +1212,29 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
 	case '<':
 	case '>':
 		return parse_padding_placeholder(placeholder, c);
+
+	case '{':
+		{
+			/*
+			 * A real recursive descent parser would allow embedded
+			 * braces, or blocks within blocks. This hacky solution
+			 * just finds a plausible ending brace, but it's
+			 * probably the best we can do using strbuf_expand().
+			 *
+			 * The copy is also ugly and inefficient, since we do
+			 * it for every commit. This would all be much nicer if
+			 * we pre-parsed the format into a tree.
+			 */
+			const char *beg = placeholder + 1;
+			const char *end = strchrnul(beg, '}');
+			char *inner = xmemdupz(beg, end - beg);
+
+			strbuf_expand(sb, inner, format_commit_item, context);
+			free(inner);
+
+			/* consumed whole inner string plus maybe closing brace */
+			return end - placeholder + !!*end;
+		  }
 	}
 
 	/* these depend on the commit */

      reply	other threads:[~2020-03-17 17:56 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-17 15:28 Conditional newline in pretty format Robert Dailey
2020-03-17 15:37 ` Robert Dailey
2020-03-17 17:18   ` Jeff King
2020-03-17 17:27     ` Robert Dailey
2020-03-17 17:55       ` Jeff King [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

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200317175558.GA16061@coredump.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=rcdailey.lists@gmail.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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).