align widechars, optimize space a bit for 80x25, fix mailto: link - stagit-gopher - A git gopher frontend. (mirror)
 (HTM) git clone git://bitreich.org/stagit-gopher/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/stagit-gopher/
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit e13c9e5eec3eca1670477033fa276e9b48e78f58
 (DIR) parent e95a7d9de8805d9264b1d7cdcf43f15d2ec6b49c
 (HTM) 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(-)
       ---
 (DIR) 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.
        
 (DIR) 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);
 (DIR) 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);