All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 6/6] pretty: support padding placeholders, %< %> and %<>
Date: Sat, 22 Sep 2012 11:22:19 +0700	[thread overview]
Message-ID: <1348287739-12128-7-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1348287739-12128-1-git-send-email-pclouds@gmail.com>

Either %<, %> or %<> standing before a placeholder specifies how many
columns (at least as the placeholder can exceed it) it takes. Each
differs on how spaces are padded:

  %< pads on the right (aka left alignment)
  %> pads on the left (aka right alignment)
  %<> pads both ways equally (aka centered)

The (<N>) follows them, e.g. `%<(100)', to specify the number of
columns the next placeholder takes.

However, if '|' stands before (<N>), e.g. `%>|(100)', then the number
of columns is calculated so that it reaches the Nth column on screen.

TODO: %>> allows the next placeholder to eat the trailing spaces in
resulting string if it exceeds its allocated space. Maybe useful in
combination with %<(100)%s%>(40)%d, where spaces are wasted sometimes.

TODO: maybe support modifier '!' in addition to '|' above to cut
exceeding part in the next placeholder.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/pretty-formats.txt |   4 ++
 pretty.c                         | 106 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 8304325..7710ea8 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -149,6 +149,10 @@ The placeholders are:
 - '%x00': print a byte from a hex code
 - '%w([<w>[,<i1>[,<i2>]]])': switch line wrapping, like the -w option of
   linkgit:git-shortlog[1].
+- '%<(<N>)': make the next placeholder take at least N columns, padding spaces on the right if necessary
+- '%<|(<N>)': make the next placeholder take at least until Nth columns, padding spaces on the right if necessary
+- '%>(<N>)', '%>|(<N>)': similar to '%<(<N<)', '%<|(<N<)' respectively, but padding spaces on the left
+- '%<>(<N>)', '%<>|(<N>)': similar to '%<(<N<)', '%<|(<N<)' respectively, but padding both sides (i.e. the text is centered)
 
 NOTE: Some placeholders may depend on other options given to the
 revision traversal engine. For example, the `%g*` reflog options will
diff --git a/pretty.c b/pretty.c
index 45fe878..6662f52 100644
--- a/pretty.c
+++ b/pretty.c
@@ -617,12 +617,20 @@ struct chunk {
 	size_t len;
 };
 
+enum flush_type {
+	no_flush,
+	flush_right,
+	flush_left,
+	flush_both
+};
+
 struct format_commit_context {
 	const struct commit *commit;
 	const struct pretty_print_context *pretty_ctx;
 	unsigned commit_header_parsed:1;
 	unsigned commit_message_parsed:1;
 	unsigned commit_signature_parsed:1;
+	enum flush_type flush_type;
 	struct {
 		char *gpg_output;
 		char good_bad;
@@ -631,6 +639,7 @@ struct format_commit_context {
 	char *message;
 	size_t width, indent1, indent2;
 	unsigned use_color;
+	int padding;
 
 	/* These offsets are relative to the start of the commit message. */
 	struct chunk author;
@@ -916,6 +925,52 @@ static size_t parse_color_placeholder(struct strbuf *sb,
 	return 0;
 }
 
+static size_t parse_padding_placeholder(struct strbuf *sb,
+					const char *placeholder,
+					struct format_commit_context *c)
+{
+	const char *ch = placeholder;
+	enum flush_type flush_type;
+	int to_column = 0;
+
+	switch (*ch++) {
+	case '<':
+		if (*ch == '>') {
+			flush_type = flush_both;
+			ch++;
+		} else
+			flush_type = flush_right;
+		break;
+	case '>':
+		flush_type = flush_left;
+		break;
+	default:
+		return 0;
+	}
+
+	/* the next value means "wide enough to that column" */
+	if (*ch == '|') {
+		to_column = 1;
+		ch++;
+	}
+
+	if (*ch == '(') {
+		const char *start = ch + 1;
+		const char *end = strchr(start, ')');
+		char *next;
+		int width;
+		if (!end || end == start)
+			return 0;
+		width = strtoul(start, &next, 10);
+		if (next == start || width == 0)
+			return 0;
+		c->padding = to_column ? -width : width;
+		c->flush_type = flush_type;
+		return end - placeholder + 1;
+	}
+	return 0;
+}
+
 static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 				void *context)
 {
@@ -966,6 +1021,10 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
 			return end - placeholder + 1;
 		} else
 			return 0;
+
+	case '<':
+	case '>':
+		return parse_padding_placeholder(sb, placeholder, c);
 	}
 
 	/* these depend on the commit */
@@ -1125,6 +1184,7 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 				 void *context)
 {
 	struct format_commit_context *c = context;
+	struct strbuf local_sb = STRBUF_INIT;
 	int consumed;
 	size_t orig_len;
 	enum {
@@ -1151,7 +1211,51 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 		placeholder++;
 
 	orig_len = sb->len;
-	consumed = format_commit_one(sb, placeholder, context);
+	if (c->flush_type != no_flush) {
+		int len, padding = c->padding;
+		if (padding < 0) {
+			const char *start = strrchr(sb->buf, '\n');
+			int occupied;
+			if (!start)
+				start = sb->buf;
+			occupied = utf8_strnwidth(start, -1, 1);
+			padding = (-padding) - occupied;
+		}
+		consumed = format_commit_one(&local_sb, placeholder, context);
+		len = utf8_strnwidth(local_sb.buf, -1, 1);
+		if (len >= padding)
+			/* Maybe we can trim the exceeded part */
+			strbuf_addstr(sb, local_sb.buf);
+		else {
+			int sb_len = sb->len, offset;
+			switch (c->flush_type) {
+			case flush_left:
+				offset = padding - len;
+				break;
+			case flush_right:
+				offset = 0;
+				break;
+			case flush_both:
+				offset = (padding - len) / 2;
+				break;
+			case no_flush: /* to make gcc happy */
+				break;
+			}
+			/*
+			 * we calculate padding in columns, now
+			 * convert it back to chars
+			 */
+			padding = padding - len + local_sb.len;
+			strbuf_grow(sb, padding);
+			strbuf_setlen(sb, sb_len + padding);
+			memset(sb->buf + sb_len, ' ', sb->len - sb_len);
+			memcpy(sb->buf + sb_len + offset, local_sb.buf,
+			       local_sb.len);
+		}
+		strbuf_release(&local_sb);
+		c->flush_type = no_flush;
+	} else
+		consumed = format_commit_one(sb, placeholder, context);
 	if (c->use_color)
 		c->use_color--;
 	if (magic == NO_MAGIC)
-- 
1.7.12.1.384.g7b808e7

  parent reply	other threads:[~2012-09-22  4:23 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-22  4:22 [PATCH 0/6] Advanced --oneline layout Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` [PATCH 1/6] pretty: share code between format_decoration and show_decorations Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` [PATCH 2/6] pretty: split parsing %C into a separate function Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` [PATCH 3/6] pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s) Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` [PATCH 4/6] utf8.c: move display_mode_esc_sequence_len() for use by other functions Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` [PATCH 5/6] utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences Nguyễn Thái Ngọc Duy
2012-09-22  4:22 ` Nguyễn Thái Ngọc Duy [this message]
2012-09-22  4:26 ` [PATCH 7/6] pretty: trim trailing spaces due to padding Nguyễn Thái Ngọc Duy
2012-09-23  9:10 ` [PATCH v2 0/9] Advanced --oneline layout Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 1/9] pretty: share code between format_decoration and show_decorations Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 2/9] pretty: split parsing %C into a separate function Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 3/9] pretty: support %C(auto[,N]) to turn on coloring on next placeholder(s) Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 4/9] utf8.c: move display_mode_esc_sequence_len() for use by other functions Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 5/9] utf8.c: add utf8_strnwidth() with the ability to skip ansi sequences Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 6/9] pretty: two phase conversion for non utf-8 commits Nguyễn Thái Ngọc Duy
2012-09-23 13:54     ` Robin Rosenberg
2012-09-24  1:21       ` Nguyen Thai Ngoc Duy
2012-09-23  9:10   ` [PATCH 7/9] pretty: support padding placeholders, %< %> and %>< Nguyễn Thái Ngọc Duy
2012-10-24  8:25     ` Jeff King
2012-09-23  9:10   ` [PATCH 8/9] pretty: support truncating in %>, %< " Nguyễn Thái Ngọc Duy
2012-09-23  9:10   ` [PATCH 9/9] pretty: support %>> that steal trailing spaces Nguyễn Thái Ngọc Duy

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=1348287739-12128-7-git-send-email-pclouds@gmail.com \
    --to=pclouds@gmail.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.