commit e46c746c435114ae3e7541ca93ffa7aacf4aaff3
parent daa814e5c59ef7dcadfe779b46bd305e0d93f7a1
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Fri, 17 Nov 2017 16:06:51 +0100
fixes for escaping and printing
- if the index or project description is empty don't print an empty line.
- escape | in gph links.
- when a column is not set / empty print it aligned.
- pad text, then print it escaped.
- print left-aligned headers of last column in a simpler way.
Diffstat:
M | stagit-gopher-index.c | | | 107 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
M | stagit-gopher.c | | | 130 | ++++++++++++++++++++++++++++++++++++------------------------------------------- |
2 files changed, 127 insertions(+), 110 deletions(-)
diff --git a/stagit-gopher-index.c b/stagit-gopher-index.c
@@ -25,17 +25,17 @@ static char *name = "";
#define pledge(p1,p2) 0
#endif
-/* print `len' columns of characters. If string is shorter pad the rest
+/* format `len' columns of characters. If string is shorter pad the rest
* with characters `pad`. */
-void
-printutf8pad(FILE *fp, const char *s, size_t len, int pad)
+int
+utf8pad(char *buf, size_t bufsiz, const char *s, size_t len, int pad)
{
wchar_t w;
- size_t col = 0, i, slen;
+ size_t col = 0, i, slen, siz = 0;
int rl, wc;
if (!len)
- return;
+ return -1;
slen = strlen(s);
for (i = 0; i < slen && col < len + 1; i += rl) {
@@ -43,43 +43,74 @@ printutf8pad(FILE *fp, const char *s, size_t len, int pad)
break;
if ((wc = wcwidth(w)) == -1)
wc = 1;
- col += (size_t)wc;
+ col += wc;
if (col >= len && s[i + rl]) {
- fputs("\xe2\x80\xa6", fp);
+ if (siz + 4 >= bufsiz)
+ return -1;
+ memcpy(&buf[siz], "\xe2\x80\xa6", 4);
+ return 0;
+ }
+ if (siz + rl + 1 >= bufsiz)
+ return -1;
+ memcpy(&buf[siz], &s[i], rl);
+ siz += rl;
+ buf[siz] = '\0';
+ }
+
+ len -= col;
+ if (siz + len + 1 >= bufsiz)
+ return -1;
+ memset(&buf[siz], pad, len);
+ siz += len;
+ buf[siz] = '\0';
+
+ return 0;
+}
+
+/* Escape characters in text in geomyidae .gph format,
+ newlines are ignored */
+void
+gphtext(FILE *fp, const char *s, size_t len)
+{
+ size_t i;
+
+ for (i = 0; *s && i < len; i++) {
+ switch (s[i]) {
+ case '\r': /* ignore CR */
+ case '\n': /* ignore LF */
+ break;
+ case '\t':
+ fputs(" ", fp);
+ break;
+ default:
+ fputc(s[i], fp);
break;
}
- fwrite(&s[i], 1, rl, fp);
}
- for (; col < len; col++)
- putc(pad, fp);
}
+/* Escape characters in links in geomyidae .gph format */
void
-trim(char *buf, size_t bufsiz, const char *src)
+gphlink(FILE *fp, const char *s, size_t len)
{
- size_t d = 0, i, len, s;
+ size_t i;
- len = strlen(src);
- for (s = 0; s < len && d < bufsiz - 1; s++) {
- switch (src[s]) {
+ for (i = 0; *s && i < len; i++) {
+ switch (s[i]) {
+ case '\r': /* ignore CR */
+ case '\n': /* ignore LF */
+ break;
case '\t':
- if (d + 8 >= bufsiz - 1)
- goto end;
- for (i = 0; i < 8; i++)
- buf[d++] = ' ';
+ fputs(" ", fp);
break;
- case '|':
- case '\n':
- case '\r':
- buf[d++] = ' ';
+ case '|': /* escape separators */
+ fputs("\\|", fp);
break;
default:
- buf[d++] = src[s];
+ fputc(s[i], fp);
break;
}
}
-end:
- buf[d] = '\0';
}
void
@@ -111,16 +142,15 @@ printtimeshort(FILE *fp, const git_time *intime)
void
writeheader(FILE *fp)
{
- char buf[256];
-
- trim(buf, sizeof(buf), description);
- if (buf[0] == 't' || buf[0] == '[')
- fputc('t', fp);
- fprintf(fp, "%s\n\n", buf);
+ if (description[0]) {
+ putchar('t');
+ gphtext(fp, description, strlen(description));
+ fputs("\n\n", fp);
+ }
fprintf(fp, "%-20.20s ", "Name");
fprintf(fp, "%-50.50s ", "Description");
- fprintf(fp, "%-16.16s\n", "Last commit");
+ fprintf(fp, "%s\n", "Last commit");
}
int
@@ -155,16 +185,15 @@ writelog(FILE *fp)
*p = '\0';
fputs("[1|", fp);
- trim(buf, sizeof(buf), stripped_name);
- printutf8pad(fp, buf, 20, ' ');
+ utf8pad(buf, sizeof(buf), stripped_name, 20, ' ');
+ gphlink(fp, buf, strlen(buf));
fputs(" ", fp);
- trim(buf, sizeof(buf), description);
- printutf8pad(fp, buf, 50, ' ');
+ utf8pad(buf, sizeof(buf), description, 50, ' ');
+ gphlink(fp, buf, strlen(buf));
fputs(" ", fp);
if (author)
printtimeshort(fp, &(author->when));
- trim(buf, sizeof(buf), stripped_name);
- fprintf(fp, "|%s/%s/log.gph|server|port]\n", relpath, buf);
+ fprintf(fp, "|%s/%s/log.gph|server|port]\n", relpath, stripped_name);
git_commit_free(commit);
err:
diff --git a/stagit-gopher.c b/stagit-gopher.c
@@ -69,17 +69,17 @@ static const char *cachefile;
#define pledge(p1,p2) 0
#endif
-/* print `len' columns of characters. If string is shorter pad the rest
+/* format `len' columns of characters. If string is shorter pad the rest
* with characters `pad`. */
-void
-printutf8pad(FILE *fp, const char *s, size_t len, int pad)
+int
+utf8pad(char *buf, size_t bufsiz, const char *s, size_t len, int pad)
{
wchar_t w;
- size_t col = 0, i, slen;
+ size_t col = 0, i, slen, siz = 0;
int rl, wc;
if (!len)
- return;
+ return -1;
slen = strlen(s);
for (i = 0; i < slen && col < len + 1; i += rl) {
@@ -87,15 +87,28 @@ printutf8pad(FILE *fp, const char *s, size_t len, int pad)
break;
if ((wc = wcwidth(w)) == -1)
wc = 1;
- col += (size_t)wc;
+ col += wc;
if (col >= len && s[i + rl]) {
- fputs("\xe2\x80\xa6", fp);
- break;
+ if (siz + 4 >= bufsiz)
+ return -1;
+ memcpy(&buf[siz], "\xe2\x80\xa6", 4);
+ return 0;
}
- fwrite(&s[i], 1, rl, fp);
+ if (siz + rl + 1 >= bufsiz)
+ return -1;
+ memcpy(&buf[siz], &s[i], rl);
+ siz += rl;
+ buf[siz] = '\0';
}
- for (; col < len; col++)
- putc(pad, fp);
+
+ len -= col;
+ if (siz + len + 1 >= bufsiz)
+ return -1;
+ memset(&buf[siz], pad, len);
+ siz += len;
+ buf[siz] = '\0';
+
+ return 0;
}
void
@@ -277,35 +290,6 @@ xmlencode(FILE *fp, const char *s, size_t len)
}
}
-void
-trim(char *buf, size_t bufsiz, const char *src)
-{
- size_t d = 0, i, len, s;
-
- len = strlen(src);
- for (s = 0; s < len && d < bufsiz - 1; s++) {
- switch (src[s]) {
- case '\t':
- if (d + 8 >= bufsiz - 1)
- goto end;
- for (i = 0; i < 8; i++)
- buf[d++] = ' ';
- break;
- case '\r': /* ignore CR */
- case '|': /* ignore separators here */
- break;
- case '\n':
- buf[d++] = ' ';
- break;
- default:
- buf[d++] = src[s];
- break;
- }
- }
-end:
- buf[d] = '\0';
-}
-
/* Escape characters in text in geomyidae .gph format, with newlines */
void
gphtextnl(FILE *fp, const char *s, size_t len)
@@ -316,7 +300,7 @@ gphtextnl(FILE *fp, const char *s, size_t len)
if (s[i] == '\n')
n = 0;
- /* escape 't' at the start of a line */
+ /* escape with 't' at the start of a line */
if (!n && (s[i] == 't' || s[i] == '[')) {
fputc('t', fp);
n = 1;
@@ -340,10 +324,15 @@ gphtext(FILE *fp, const char *s, size_t len)
for (i = 0; *s && i < len; i++) {
switch (s[i]) {
- case '\r':
- case '\n': break;
- case '\t': fputs(" ", fp); break;
- default: fputc(s[i], fp);
+ case '\r': /* ignore CR */
+ case '\n': /* ignore LF */
+ break;
+ case '\t':
+ fputs(" ", fp);
+ break;
+ default:
+ fputc(s[i], fp);
+ break;
}
}
}
@@ -356,16 +345,15 @@ gphlink(FILE *fp, const char *s, size_t len)
for (i = 0; *s && i < len; i++) {
switch (s[i]) {
- case '\n':
- /* in this context replace newline with space */
- fputc(' ', fp);
- break;
case '\r': /* ignore CR */
- case '|': /* ignore separators here */
+ case '\n': /* ignore LF */
break;
case '\t':
fputs(" ", fp);
break;
+ case '|': /* escape separators */
+ fputs("\\|", fp);
+ break;
default:
fputc(s[i], fp);
break;
@@ -575,12 +563,12 @@ printshowfile(FILE *fp, struct commitinfo *ci)
if (strcmp(delta->old_file.path, delta->new_file.path)) {
snprintf(filename, sizeof(filename), "%s -> %s",
delta->old_file.path, delta->new_file.path);
- trim(buf, sizeof(buf), filename);
+ utf8pad(buf, sizeof(buf), filename, 35, ' ');
} else {
- trim(buf, sizeof(buf), delta->old_file.path);
+ utf8pad(buf, sizeof(buf), delta->old_file.path, 35, ' ');
}
fputs(" ", fp);
- printutf8pad(fp, buf, 35, ' ');
+ gphtext(fp, buf, strlen(buf));
add = ci->deltas[i]->addcount;
del = ci->deltas[i]->delcount;
@@ -655,16 +643,14 @@ writelogline(FILE *fp, struct commitinfo *ci)
fputs("[1|", fp);
if (ci->author)
printtimeshort(fp, &(ci->author->when));
+ else
+ fputs(" ", fp);
fputs(" ", fp);
- if (ci->summary) {
- trim(buf, sizeof(buf), ci->summary);
- printutf8pad(fp, buf, 50, ' ');
- }
+ utf8pad(buf, sizeof(buf), ci->summary ? ci->summary : "", 50, ' ');
+ gphlink(fp, buf, strlen(buf));
fputs(" ", fp);
- if (ci->author) {
- trim(buf, sizeof(buf), ci->author->name);
- printutf8pad(fp, buf, 25, ' ');
- }
+ utf8pad(buf, sizeof(buf), ci->author ? ci->author->name : "", 25, ' ');
+ gphlink(fp, buf, strlen(buf));
fprintf(fp, "|%s/commit/%s.gph", relpath, ci->oid);
fputs("|server|port]\n", fp);
}
@@ -926,8 +912,8 @@ writefilestree(FILE *fp, git_tree *tree, const char *path)
fputs("[1|", fp);
fputs(filemode(git_tree_entry_filemode(entry)), fp);
fputs(" ", fp);
- trim(buf, sizeof(buf), entrypath);
- printutf8pad(fp, buf, 50, ' ');
+ utf8pad(buf, sizeof(buf), entrypath, 50, ' ');
+ gphlink(fp, buf, strlen(buf));
fputs(" ", fp);
if (lc > 0)
fprintf(fp, "%7dL", lc);
@@ -938,8 +924,8 @@ writefilestree(FILE *fp, git_tree *tree, const char *path)
git_object_free(obj);
} else if (!git_submodule_lookup(&module, repo, entryname)) {
fputs("[1|m--------- ", fp);
- trim(buf, sizeof(buf), entrypath);
- printutf8pad(fp, buf, 50, ' ');
+ utf8pad(buf, sizeof(buf), entrypath, 50, ' ');
+ gphlink(fp, buf, strlen(buf));
fprintf(fp, "|%s/file/.gitmodules.gph|server|port]\n", relpath);
/* NOTE: linecount omitted */
git_submodule_free(module);
@@ -1042,21 +1028,23 @@ writerefs(FILE *fp)
fprintf(fp, "%s\n", titles[j]);
fprintf(fp, " %-20.20s", "Name");
fprintf(fp, " %-16.16s", "Last commit date");
- fprintf(fp, " %-25.25s\n", "Author");
+ fprintf(fp, " %s\n", "Author");
}
name = git_reference_shorthand(r);
fputs(" ", fp);
- trim(buf, sizeof(buf), name);
- printutf8pad(fp, buf, 20, ' ');
+ utf8pad(buf, sizeof(buf), name, 20, ' ');
+ gphlink(fp, buf, strlen(buf));
fputs(" ", fp);
if (ci->author)
printtimeshort(fp, &(ci->author->when));
+ else
+ fputs(" ", fp);
fputs(" ", fp);
if (ci->author) {
- trim(buf, sizeof(buf), ci->author->name);
- printutf8pad(fp, buf, 25, ' ');
+ utf8pad(buf, sizeof(buf), ci->author->name, 25, ' ');
+ gphlink(fp, buf, strlen(buf));
}
fputs("\n", fp);
@@ -1204,7 +1192,7 @@ main(int argc, char *argv[])
fprintf(fp, "%-16.16s ", "Date");
fprintf(fp, "%-50.50s ", "Commit message");
- fprintf(fp, "%-25.25s\n", "Author");
+ fprintf(fp, "%s\n", "Author");
if (cachefile) {
/* read from cache file (does not need to exist) */