Welcome to little lamb

Code » limb » release » tree

[release] / src / liblimb / output.h / lila_dieversion.c

/* This file is part of limb                           https://lila.oss/limb
 * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
/* SPDX-License-Identifier: GPL-2.0-only */
#include <unistd.h> /* isatty() */
#include <sys/ioctl.h>
#include <limb/output.h>

#define ANSI_BOLD                   "\x1B[1m"
#define ANSI_BOLD_YELLOW            "\x1B[1;33m"
#define ANSI_YELLOW                 "\x1B[0;33m"
#define ANSI_BLUE                   "\x1B[0;36m"
#define ANSI_OFF                    "\x1B[0m"

static void
putline(const char *line, size_t len, size_t sp, const char *suffix, size_t slen,
        size_t col, int tty)
{
    sp += col - len - 11;
    char buf[sp];
    memset(buf, ' ', sp);

    obuffer_put(obuffer_1, OLVL_NORMAL, line, len);
    obuffer_put(obuffer_1, OLVL_NORMAL, buf, sp);
    if (tty) obuffer_put(obuffer_1, OLVL_NORMAL, ANSI_BLUE, strlen(ANSI_BLUE));
    obuffer_put(obuffer_1, OLVL_NORMAL, suffix, slen);
    if (tty) obuffer_put(obuffer_1, OLVL_NORMAL, ANSI_OFF, strlen(ANSI_OFF));
    obuffer_put(obuffer_1, OLVL_NORMAL, "\n", 1);
}

void
lila_dieversion(const char *version, const char *yearbeg, const char *yearend,
                const char *author, const char *url,  const char *license, int is_lila)
{
    int tty = isatty(buffer_1->fd);
    size_t l;

    struct winsize ws = { 0 };
    ioctl(buffer_1->fd, TIOCGWINSZ, &ws);
    /* some default */
    if (!ws.ws_col) ws.ws_col = 80;
    /* just a visual thing */
    if (ws.ws_col > 60) ws.ws_col -= 4;

    size_t vlen = strlen(version);
    size_t yblen = strlen(yearbeg);
    size_t yelen = strlen(yearend);
    int has_ye = yblen != yelen || strcmp(yearbeg, yearend);

#define VERSION     " version "
#define COPYRIGHT   "Copyright (C) "
#define LICENSE \
    "License GPL-2.0. This is free software:\n" \
    "you are free to change and redistribute it.\n" \
    "There is NO WARRANTY, to the extent permitted by law."

    l = strlen(PROG);
    /* we need at least 56 cols, otherwise don't bother */
    if (!is_lila || ws.ws_col < 56 || l + strlen(" version ") + vlen >= ws.ws_col)
        outdie(0, PROG, " version ", version, "\n",
               "Copyright (C) ", yearbeg,
               (has_ye) ? "-" : "", (has_ye) ? yearend : "", " ", author, "\n",
               url, "\n",
               (!license) ? "\n" LICENSE : license);

    char line[ws.ws_col];
    size_t len = 0;

    if (tty) obuffer_put(obuffer_1, OLVL_NORMAL, ANSI_BOLD_YELLOW, strlen(ANSI_BOLD_YELLOW));
    memcpy(line, PROG, l); len += l;
    l = strlen(VERSION); memcpy(line + len, VERSION, l); len += l;
    memcpy(line + len, version, vlen); len += vlen;

    putline(line, len, 7, "*", 1, ws.ws_col, tty);
    if (tty) obuffer_put(obuffer_1, OLVL_NORMAL, ANSI_BLUE, strlen(ANSI_BLUE));
    putline(url, strlen(url), 5, "*", 1, ws.ws_col, tty);
    putline("", 0, 3, "*", 1, ws.ws_col, tty);

    len = 0;
    l = strlen(COPYRIGHT); memcpy(line + len, COPYRIGHT, l); len += l;
    memcpy(line + len, yearbeg, yblen); len += yblen;
    if (has_ye) {
        line[len++] = '-';
        memcpy(line + len, yearend, yelen); len += yelen;
    }
    line[len++] = ' ';
    l = strlen(author); memcpy(line + len, author, l); len += l;

    if (tty) obuffer_put(obuffer_1, OLVL_NORMAL, ANSI_YELLOW, strlen(ANSI_YELLOW));
    putline(line,len, 5, "*", 1, ws.ws_col, tty);
    putline("", 0, 1, "*     *  *", 10, ws.ws_col, tty);
    if (tty) obuffer_put(obuffer_1, OLVL_NORMAL, ANSI_BOLD, strlen(ANSI_BOLD));
    obuffer_put(obuffer_1, OLVL_NORMAL, LICENSE, 16);
    if (tty) obuffer_put(obuffer_1, OLVL_NORMAL, ANSI_OFF, strlen(ANSI_OFF));
    putline(LICENSE + 16, 23, 5, "*", 1, ws.ws_col - 16, tty);
    putline(LICENSE + 16 + 23 + 1, 43, 3, "*", 1, ws.ws_col, tty);
    putline(LICENSE + 16 + 23 + 1 + 43 + 1, 45, 5, "*", 1, ws.ws_col, tty);
    putline(LICENSE + 16 + 23 + 1 + 43 + 1 + 45 + 1, 7, 7, "*", 1, ws.ws_col, tty);

    obuffer_putmsgdie(obuffer_1, OLVL_NORMAL, (const char * const []) { PUTMSG_FLUSH }, 1, 0);
}