commit e13c9e5eec3eca1670477033fa276e9b48e78f58
parent e95a7d9de8805d9264b1d7cdcf43f15d2ec6b49c
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Wed, 14 Jun 2017 20:33:16 +0200
align widechars, optimize space a bit for 80x25, fix mailto: link
Diffstat:
M | TODO | | | 3 | ++- |
M | stagit-index.c | | | 40 | +++++++++++++++++++++++++++++++++++----- |
M | stagit.c | | | 56 | ++++++++++++++++++++++++++++++++++++++++++-------------- |
3 files changed, 79 insertions(+), 20 deletions(-)
diff --git a/TODO b/TODO
@@ -1,6 +1,7 @@
gopher:
-- align UTF-8 characters (and wide?).
+- cleanup code: escaping.
+? printutf8pad: print '...' when truncated?
- update documentation:
- document new gopher-specific options.
diff --git a/stagit-index.c b/stagit-index.c
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <wchar.h>
#include <git2.h>
@@ -25,6 +26,31 @@ static char owner[255];
#define pledge(p1,p2) 0
#endif
+#define ISUTF8(c) (((c) & 0xc0) != 0x80)
+
+/* print `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)
+{
+ wchar_t w;
+ size_t n = 0, i;
+ int r;
+
+ for (i = 0; *s && n < len; i++, s++) {
+ if (ISUTF8(*s)) {
+ if ((r = mbtowc(&w, s, 4)) == -1)
+ break;
+ if ((r = wcwidth(w)) == -1)
+ r = 1;
+ n += (size_t)r;
+ }
+ putc(*s, fp);
+ }
+ for (; n < len; n++)
+ putc(pad, fp);
+}
+
void
trim(char *buf, size_t bufsiz, const char *src)
{
@@ -87,9 +113,9 @@ writeheader(FILE *fp)
trim(buf, sizeof(buf), description);
if (buf[0] == 't')
fputc('t', fp);
- fprintf(fp, "%s\n", buf);
+ fprintf(fp, "%s\n\n", buf);
- fprintf(fp, "%-25.25s ", "Name");
+ fprintf(fp, "%-20.20s ", "Name");
fprintf(fp, "%-50.50s ", "Description");
fprintf(fp, "%-25.25s ", "Owner");
fprintf(fp, "%-16.16s\n", "Last commit");
@@ -131,12 +157,16 @@ writelog(FILE *fp)
if (!strcmp(p, ".git"))
*p = '\0';
+ fputs("[1|", fp);
trim(buf, sizeof(buf), stripped_name);
- fprintf(fp, "[1|%-25.25s ", buf);
+ printutf8pad(fp, buf, 20, ' ');
+ fputs(" ", fp);
trim(buf, sizeof(buf), description);
- fprintf(fp, "%-50.50s ", buf);
+ printutf8pad(fp, buf, 50, ' ');
+ fputs(" ", fp);
trim(buf, sizeof(buf), owner);
- fprintf(fp, "%-25.25s ", buf);
+ printutf8pad(fp, buf, 25, ' ');
+ fputs(" ", fp);
if (author)
printtimeshort(fp, &(author->when));
trim(buf, sizeof(buf), stripped_name);
diff --git a/stagit.c b/stagit.c
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <wchar.h>
#include <git2.h>
@@ -67,6 +68,31 @@ static const char *cachefile;
#define pledge(p1,p2) 0
#endif
+#define ISUTF8(c) (((c) & 0xc0) != 0x80)
+
+/* print `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)
+{
+ wchar_t w;
+ size_t n = 0, i;
+ int r;
+
+ for (i = 0; *s && n < len; i++, s++) {
+ if (ISUTF8(*s)) {
+ if ((r = mbtowc(&w, s, 4)) == -1)
+ break;
+ if ((r = wcwidth(w)) == -1)
+ r = 1;
+ n += (size_t)r;
+ }
+ putc(*s, fp);
+ }
+ for (; n < len; n++)
+ putc(pad, fp);
+}
+
void
joinpath(char *buf, size_t bufsiz, const char *path, const char *path2)
{
@@ -420,7 +446,7 @@ writeheader(FILE *fp, const char *title)
fprintf(fp, "[1|README|%sfile/README.gph|server|port]\n", relpath);
if (haslicense)
fprintf(fp, "[1|LICENSE|%sfile/LICENSE.gph|server|port]\n", relpath);
- fputs("===\n", fp);
+ fputs("---\n", fp);
}
void
@@ -432,7 +458,7 @@ int
writeblobgph(FILE *fp, const git_blob *blob)
{
size_t n = 0, i, j, prev;
- const char *nfmt = "%8d ";
+ const char *nfmt = "%6d ";
const char *s = git_blob_rawcontent(blob);
git_off_t len = git_blob_rawsize(blob);
@@ -479,12 +505,11 @@ printcommit(FILE *fp, struct commitinfo *ci)
ci->parentoid, relpath, ci->parentoid);
if (ci->author) {
- /* TODO: fix author email link to redirect as mailto: */
- fputs("[1|Author: ", fp);
+ fputs("[h|Author: ", fp);
gphlink(fp, ci->author->name, strlen(ci->author->name));
fputs(" <", fp);
gphlink(fp, ci->author->email, strlen(ci->author->email));
- fputs(">|mailto:", fp);
+ fputs(">|URL:mailto:", fp);
gphlink(fp, ci->author->email, strlen(ci->author->email));
fputs("|server|port]\n", fp);
fputs("Date: ", fp);
@@ -556,7 +581,7 @@ printshowfile(FILE *fp, struct commitinfo *ci)
ci->addcount, ci->addcount == 1 ? "" : "s",
ci->delcount, ci->delcount == 1 ? "" : "s");
- fputs("===\n", fp);
+ fputs("---\n", fp);
for (i = 0; i < ci->ndeltas; i++) {
patch = ci->deltas[i]->patch;
@@ -605,12 +630,12 @@ writelogline(FILE *fp, struct commitinfo *ci)
fputs(" ", fp);
if (ci->summary) {
trim(buf, sizeof(buf), ci->summary);
- fprintf(fp, "%-50.50s", buf);
+ printutf8pad(fp, buf, 50, ' ');
}
fputs(" ", fp);
if (ci->author) {
trim(buf, sizeof(buf), ci->author->name);
- fprintf(fp, "%-25.25s", buf);
+ printutf8pad(fp, buf, 25, ' ');
}
fprintf(fp, " %5zu", ci->filecount);
fprintf(fp, " %5zu+", ci->addcount);
@@ -766,7 +791,7 @@ writeblob(git_object *obj, const char *fpath, const char *filename, git_off_t fi
writeheader(fp, filename);
gphtext(fp, filename, strlen(filename));
fprintf(fp, " (%juB)\n", (uintmax_t)filesize);
- fputs("===\n", fp);
+ fputs("---\n", fp);
if (git_blob_is_binary((git_blob *)obj)) {
fputs("Binary file.\n", fp);
@@ -872,7 +897,8 @@ writefilestree(FILE *fp, git_tree *tree, const char *path)
fputs(filemode(git_tree_entry_filemode(entry)), fp);
fputs(" ", fp);
trim(buf, sizeof(buf), entrypath);
- fprintf(fp, "%-50.50s ", buf);
+ printutf8pad(fp, buf, 50, ' ');
+ fputs(" ", fp);
if (lc > 0)
fprintf(fp, "%7dL", lc);
else
@@ -882,7 +908,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);
- gphlink(fp, entrypath, strlen(entrypath));
+ trim(buf, sizeof(buf), entrypath);
+ printutf8pad(fp, buf, 50, ' ');
fprintf(fp, "|%sfile/.gitmodules.gph|server|port]\n", relpath);
/* NOTE: linecount omitted */
git_submodule_free(module);
@@ -983,7 +1010,7 @@ writerefs(FILE *fp)
/* print header if it has an entry (first). */
if (++count == 1) {
fprintf(fp, "%s\n", titles[j]);
- fprintf(fp, " %-25.25s", "Name");
+ fprintf(fp, " %-20.20s", "Name");
fprintf(fp, " %-16.16s", "Last commit date");
fprintf(fp, " %-25.25s\n", "Author");
}
@@ -992,13 +1019,14 @@ writerefs(FILE *fp)
fputs(" ", fp);
trim(buf, sizeof(buf), name);
- fprintf(fp, "%-25.25s ", name);
+ printutf8pad(fp, buf, 20, ' ');
+ fputs(" ", fp);
if (ci->author)
printtimeshort(fp, &(ci->author->when));
fputs(" ", fp);
if (ci->author) {
trim(buf, sizeof(buf), ci->author->name);
- fprintf(fp, "%-25.25s\n", buf);
+ printutf8pad(fp, buf, 25, ' ');
}
fputs("\n", fp);