@@ -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 */
}