Welcome to little lamb

Code » comain » commit 9252361

initrepo/initprj: Some refactoring, use templates

author Olivier Brunel
2023-05-17 07:24:14 UTC
committer Olivier Brunel
2023-06-20 07:07:15 UTC
parent 03457911575f6511a5cd3a78183ec741b9269620

initrepo/initprj: Some refactoring, use templates

initprj +40 -131
initrepo +2 -0
libcomain +16 -6
tpl/gitignore +2 -0
tpl/main.c +92 -0
tpl/main.md +44 -0
tpl/project.mk +1 -0

diff --git a/initprj b/initprj
index ddd4240..39b4ba1 100755
--- a/initprj
+++ b/initprj
@@ -1,12 +1,12 @@
 #!/bin/sh
 
 if ! test -d meta; then
-    echo "Directory 'meta' not found" >&2
+    echo "${0##*/}: fatal: directory 'meta' not found" >&2
     exit 2
 fi
 
 if ! test -d .git; then
-    echo "Repo (.git) not found -- use 'initrepo' first" >&2
+    echo "${0##*/}: fatal: repo (.git) not found -- use 'initrepo' first" >&2
     exit 2
 fi
 
@@ -15,159 +15,68 @@ name=$(cat meta/name)
 . "$(dirname $0)"/libcomain
 
 if test ! -d comain; then
-    error 2 "Directory 'comain' not found"
+    dief 2 "directory 'comain' not found"
 fi
 
-site=$(cat meta/site)
+desc="$(head -1 meta/desc)"
+site="$(cat meta/site)"
+code="$(cat meta/code)"
+git="$(cat meta/git)"
 sp=$((52 - ${#name} - ${#site}))
 sp="$(printf "%${sp}s")"
 prefix=$(sanitize $name)
 year=$(date +%Y)
 
-run cp -a comain/meta/deps.tpl/skalibs meta/deps
-run cp -a comain/meta/deps.tpl/limb meta/deps
-
-run mkdir src/$name
-run touch src/$name/+skalibs
-run touch src/$name/+limb
-run cat > src/$name/$name.c <<EOF
+run cat > h <<EOF
 /* This file is part of $name$sp$site
  * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
 /* SPDX-License-Identifier: GPL-2.0-only */
-#include <limb/autoopt.h>
-#include <limb/exitcode.h>
-#include <limb/loadopt.h>
-#include <limb/output.h>
-#include "config.h"
+EOF
+
+git checkout -b dev
+git checkout -b dev-wip
+git add h
+git commit -m 'wip: Add h'
 
-const char *PROG = "$name";
+run cp -a comain/meta/deps.tpl/skalibs meta/deps
+run cp -a comain/meta/deps.tpl/limb meta/deps
 
-enum {
-    OPTID_DEBUG = OPTID_FIRST,
-    OPTID_VERSION,
-};
+run mkdir src/$name
+run touch src/$name/+limb
 
-static void
-parse_cmdline(int argc, const char *argv[], const char *file, const char *section)
+sedesc()
 {
-    const char usage[] = "[-h] [OPTION..]";
-    const struct option options[] = {
-        OPTION_ARG_OPT(  0 , "debug",                   0, OPTID_DEBUG),
-        OPTION_ARG_NONE('h', "help",                    OPT_SKIP, OPTID_SHORTOPT),
-        OPTION_ARG_REQ( 'O', "log-file",                0, OPTID_SHORTOPT),
-        OPTION_ARG_NONE('q', "quiet",                   0, OPTID_SHORTOPT),
-        OPTION_ARG_NONE('v', "verbose",                 0, OPTID_SHORTOPT),
-        OPTION_ARG_NONE( 0 , "version",                 0, OPTID_VERSION),
-        LOADOPT_DONE
-    };
-    struct loadopt lo = { 0 };
-
-    int c;
-    while ((c = loadopt(argc, argv, options, file, section, 0, &lo))) switch (c) {
-        case OPTID_DEBUG:
-            if (!autoopt_debug(&options[lo.idx], lo.arg))
-                dieusage(EX_USAGE, usage);
-            break;
-        case 'h':
-            diehelp(0, usage,
-"     --debug [[@[level]:]+FD|FILE]     Enable debug output (to FD|FILE)\n"
-" -O, --output [@[level]:]+FD|FILE      Set output log to FD|FILE\n"
-"\n"
-" -q, --quiet                           Enable quiet mode\n"
-" -v, --verbose                         Enable verbose mode\n"
-"\n"
-" -h, --help                            Show this help screen and exit\n"
-"     --version                         Show version information and exit\n"
-);
-        case 'O':
-            if (!autoopt_log(&options[lo.idx], lo.arg))
-                dieusage(EX_USAGE, usage);
-            break;
-        case 'q':
-            autoopt_quiet(&options[lo.idx], lo.arg);
-            break;
-        case 'v':
-            autoopt_verbose(&options[lo.idx], lo.arg);
-            break;
-        case OPTID_VERSION:
-            dieversion(${prefix}_VERSION, "$year", ${prefix}_CURYEAR, ${prefix}_AUTHOR, ${prefix}_URL, NULL);
-        case -1:
-            dieusage(EX_USAGE, usage);
-        default:
-            die(EX_SOFTWARE, "unexpected return value ", PUTMSG_INT(c), " from loadopt");
-    };
+    printf %s "$*" | sed -e 's/\//\\\//g'
 }
 
-int
-main(int argc, const char *argv[])
+sed_site="$(sedesc $site)"
+sed_code="$(sedesc $code)"
+sed_git="$(sedesc $git)"
+sed_desc="$(sedesc $desc)"
+sedtpl()
 {
-    const char config[] = "/etc/$name.conf";
-    parse_cmdline(argc, argv, config, NULL);
-
-    out("done.");
-    return 0;
+    if test $# -ne 2; then dief 2 "wrong sedtpl invocation"; fi
+    run sed -e s/\$name/$name/g -e s/\$prefix/$prefix/g -e s/\$year/$year/g \
+        -e s/\$site/$sed_site/g -e s/\$code/$sed_code/g -e s/\$git/$sed_git/g \
+        -e s/\$desc/"$sed_desc"/g \
+        "comain/tpl/$1" >> "$2"
 }
-EOF
-
-run cat > project.mk <<EOF
-BINS = $name
-EOF
 
+cp h src/$name/$name.c
+sedtpl main.c src/$name/$name.c
+run rm project.mk
+sedtpl project.mk project.mk
 run mkdir src/doc
-run cat > src/doc/$name.1.md <<EOF
-% $name
-% $name(1)
-
-# NAME
-
-$name - $(head -1 meta/desc)
-
-# SYNOPSIS
+sedtpl main.md src/doc/$name.1.md
+sedtpl gitignore .gitignore
 
-*$name* [*-q*] [*-v*] [*--debug* [[@[\`level\`]:]+\`FD\`|\`FILE\`]] [*-O* [@[\`level\`]:]+\`FD\`|\`FILE\`]
-
-# OPTIONS
-
-: *--debug* [[@[\`level\`]:]+\`FD\`|\`FILE\`]
-<inc autoopt_debug.md>
-<inc autoopt_logdbg_level.md>
-
-<inc opt_help.md>
-
-: *-O*, *--log-file* [@[\`level\`]:]+\`FD\`|\`FILE\`
-<inc autoopt_log.md>
-<inc autoopt_logdbg_level.md>
-
-: *-q*, *--quiet*
-<inc autoopt_quiet.md>
-
-: *-v*, *--verbose*
-<inc autoopt_verbose.md>
-
-<inc opt_version.md>
-
-# DESCRIPTION
-
-*$name* is...
-
-<inc bugs.md>
-
-# REPOSITORY
-
-You can find the latest about *$name* from its official site at $(cat meta/site)
-Latest source code can be browsed online at $(cat meta/code); or you can close
-its [git](1) repo from $(cat meta/git)
-
-<inc author.md>
-EOF
-
-run cat >> .gitignore <<EOF
-/limb
-/$name
-EOF
 git add . .gitignore
 git commit --message="First commit"
 
+git checkout dev
+git cherry-pick dev-wip
+git rebase --onto dev dev-wip~2 dev-wip
+
 make
 ./configure
 
diff --git a/initrepo b/initrepo
index 08bab3d..817d795 100755
--- a/initrepo
+++ b/initrepo
@@ -24,6 +24,7 @@ run echo https://lila.oss/$name > meta/site
 run echo git://lila.oss/$name.git > meta/git
 run echo https://lila.oss/doc/$name > meta/doc
 run echo https://lila.oss/code/$name > meta/code
+run echo FIXME: desc here > meta/desc
 run cp -n comain/meta/COPYING meta
 run cp -n comain/meta/LICENSE meta
 run cp -n comain/meta/AUTHORS.tpl meta/AUTHORS
@@ -47,6 +48,7 @@ run cat > .gitignore <<EOF
 /common.mk
 /config.mk
 /src/include/config.h
+/deps
 /build
 EOF
 if test -e .git; then error 2 "Already a git repo (.git exist)"; fi
diff --git a/libcomain b/libcomain
index 2faac22..5268314 100644
--- a/libcomain
+++ b/libcomain
@@ -16,19 +16,29 @@ echon()
     printf %s "$*"
 }
 
-error()
+die()
 {
-    r=$1
+    local r=$1
     shift
-    m="$*"
-
-    echo "$0: fatal: $m" >&2
+    echo "${0##*/}: $*" >&2
     exit $r
 }
 
+dief()
+{
+    local r=$1
+    shift
+    die $r "fatal: $*"
+}
+
+error()
+{
+    dief "$@"
+}
+
 warn()
 {
-    echo "$0: warning: $@" >&2
+    echo "${0##*/}: warning: $*" >&2
 }
 
 upper()
diff --git a/tpl/gitignore b/tpl/gitignore
new file mode 100644
index 0000000..0ad2cb8
--- /dev/null
+++ b/tpl/gitignore
@@ -0,0 +1,2 @@
+/deps
+/$name
diff --git a/tpl/main.c b/tpl/main.c
new file mode 100644
index 0000000..b8884d7
--- /dev/null
+++ b/tpl/main.c
@@ -0,0 +1,92 @@
+#include <fcntl.h> /* AT_FDCWD */
+#include <limb/autoopt.h>
+#include <limb/exitcode.h>
+#include <limb/loadopt.h>
+#include <limb/output.h>
+#include <limb/stralloc.h>
+#include "config.h"
+
+const char *PROG = "$name";
+
+struct ctx {
+    stralloc sa;
+    size_t fileoff;
+};
+
+enum {
+    OPTID_VERSION = OPTID_FIRST,
+    OPTID_DEBUG,
+    /* arguments */
+    ARGID_FILE,
+};
+
+static void
+parse_cmdline(int argc, const char *argv[], int dirfd, const char *confdir, struct ctx *ctx)
+{
+    const char usage[] = "[-h] [OPTION..] FILE";
+    const struct option options[] = {
+        OPTION_ARG_OPT(  0 , "debug",                   OPT_SKIP,   OPTID_DEBUG),
+        OPTION_ARG_NONE('h', "help",                    OPT_SKIP,   OPTID_SHORTOPT),
+        OPTION_ARG_REQ( 'O', "log-file",                0,          OPTID_SHORTOPT),
+        OPTION_ARG_NONE('q', "quiet",                   0,          OPTID_SHORTOPT),
+        OPTION_ARG_NONE('v', "verbose",                 0,          OPTID_SHORTOPT),
+        OPTION_ARG_NONE( 0 , "version",                 OPT_SKIP,   OPTID_VERSION),
+        LOADOPT_ARGUMENTS,
+        ARGUMENT_REQ( "file",                           OPT_PATH,   ARGID_FILE),
+        LOADOPT_DONE
+    };
+    struct loadopt lo = LOADOPT_ZERO;
+
+    int c;
+    while ((c = loadopt(&ctx->sa, argc, argv, options, dirfd, confdir, 0, &lo))) switch (c) {
+        case OPTID_DEBUG:
+            if (!autoopt_debug(&options[LO_IDX(&lo)], LO_ARG(&lo)))
+                dieusage(EX_USAGE, usage);
+            break;
+        case 'h':
+            diehelp(0, usage,
+"     --debug [[@[level]:]+FD|FILE]     Enable debug output (to FD|FILE)\n"
+" -O, --output [@[level]:]+FD|FILE      Set output log to FD|FILE\n"
+"\n"
+" -q, --quiet                           Enable quiet mode\n"
+" -v, --verbose                         Enable verbose mode\n"
+"\n"
+" -h, --help                            Show this help screen and exit\n"
+"     --version                         Show version information and exit\n"
+);
+        case 'O':
+            if (!autoopt_log(&options[LO_IDX(&lo)], LO_ARG(&lo)))
+                dieusage(EX_USAGE, usage);
+            break;
+        case 'q':
+            autoopt_quiet(&options[LO_IDX(&lo)], LO_ARG(&lo));
+            break;
+        case 'v':
+            autoopt_verbose(&options[LO_IDX(&lo)], LO_ARG(&lo));
+            break;
+        case OPTID_VERSION:
+            dieversion($prefix_VERSION, "$year", $prefix_CURYEAR, $prefix_AUTHOR, $prefix_URL, NULL);
+
+        case ARGID_FILE:
+            ctx->fileoff = LO_OFF(&lo);
+            break;
+
+        case -1:
+            dieusage(EX_USAGE, usage);
+        default:
+            die(EX_SOFTWARE, "unexpected return value ", PMINT(c), " from loadopt");
+    };
+}
+
+int
+main(int argc, const char *argv[])
+{
+    struct ctx ctx = { STRALLOC_ZERO, 0 };
+    const char confdir[] = "/etc/$name/conf";
+    parse_cmdline(argc, argv, AT_FDCWD, confdir, &ctx);
+
+    out("file is ", ESC, ctx.sa.s + ctx.fileoff, ESC);
+
+    stralloc_free(&ctx.sa);
+    return 0;
+}
diff --git a/tpl/main.md b/tpl/main.md
new file mode 100644
index 0000000..1d10744
--- /dev/null
+++ b/tpl/main.md
@@ -0,0 +1,44 @@
+% $name
+% $name(1)
+
+# NAME
+
+$name - $desc
+
+# SYNOPSIS
+
+*$name* [*-q*] [*-v*] [*--debug* [[@[\`level\`]:]+\`FD\`|\`FILE\`]] [*-O* [@[\`level\`]:]+\`FD\`|\`FILE\`]
+
+# OPTIONS
+
+: *--debug* [[@[\`level\`]:]+\`FD\`|\`FILE\`]
+<inc autoopt_debug.md>
+<inc autoopt_logdbg_level.md>
+
+<inc opt_help.md>
+
+: *-O*, *--log-file* [@[\`level\`]:]+\`FD\`|\`FILE\`
+<inc autoopt_log.md>
+<inc autoopt_logdbg_level.md>
+
+: *-q*, *--quiet*
+<inc autoopt_quiet.md>
+
+: *-v*, *--verbose*
+<inc autoopt_verbose.md>
+
+<inc opt_version.md>
+
+# DESCRIPTION
+
+*$name* is...
+
+<inc bugs.md>
+
+# REPOSITORY
+
+You can find the latest about *$name* from its official site at $site
+Latest source code can be browsed online at $code; or you can clone its
+[git](1) repo from $git
+
+<inc author.md>
diff --git a/tpl/project.mk b/tpl/project.mk
new file mode 100644
index 0000000..3a1343b
--- /dev/null
+++ b/tpl/project.mk
@@ -0,0 +1 @@
+BINS = $name