diff options
-rw-r--r-- | tests/man.test | 196 | ||||
-rw-r--r-- | toys/pending/man.c | 112 |
2 files changed, 308 insertions, 0 deletions
diff --git a/tests/man.test b/tests/man.test new file mode 100644 index 00000000..51c492a2 --- /dev/null +++ b/tests/man.test @@ -0,0 +1,196 @@ +#!/bin/bash +# Copyright 2019 makepost <makepost@firemail.cc> + +[ -f testing.sh ] && . testing.sh + +#testing "name" "command" "result" "infile" "stdin" + +x=$((RANDOM)) +echo $x | bzip2 >/usr/share/man/man1/toybox.1.bz2 +testing "curl_strequal" "man toybox" " $x\n\n" "" "" + +x=$((RANDOM)) +echo $x | bzip2 >/usr/share/man/man1/toybox.1.bz2 +testing "curl_strequal.3" "man toybox.1" " $x\n\n" "" "" + +rm /usr/share/man/man1/toybox.1.bz2 + +x=$((RANDOM)) +echo $x >/usr/share/man/man1/toybox.1 +testing "curl_strnequal" "man toybox" " $x\n\n" "" "" + +x=$((RANDOM)) +echo $x >/usr/share/man/man1/toybox.1 +testing "curl_strnequal.3" "man toybox.1" " $x\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +.TP +.PD 0 +.B \\-F +.TP +.PD +.B \\-\\^\\-foo\\-bar +Does something. +.TP +.PD 0 +.B \\-\\^\\-no\\-alias +Has no alias. +EOF +testing "gawk alias" "man toybox" " -F\n --foo-bar Does something.\n\n --no-alias Has no alias.\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +\\fBsh\\fR-compatible +\\fIKorn\\fP +EOF +testing "bash bold,ita" "man toybox" " sh-compatible Korn\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +quoted \\(aqstring\\(aq +\\(dqserver\\(dq +Don\\(cq\\&t +EOF +testing "bash,rsync quote" "man toybox" " quoted 'string' \"server\" Don't\n\n" "" "" + +echo "\\*(lq\\-\\^\\-\\*(rq" >/usr/share/man/man1/toybox.1 +testing "gawk quote" "man toybox" " \"--\"\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +.IP \\(bu +[\\fB|\\fP\\(bv\\fB|&\\fP] +EOF +testing "bash symbol" "man toybox" " * [|||&]\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +\\&\\fBfflush(...)\\fR +\\f(CW$ ssh ...\\fP +EOF +testing "gawk,rsync fancy" "man toybox" " fflush(...) $ ssh ...\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +"\\eC\\-x\\eC\\-r": re\\-read +must be \\(>= 1 +EOF +testing "bash escape" "man toybox" " \"\C-x\C-r\": re-read must be >= 1\n\n" "" "" + +echo "\\*(AK language. The \\*(PX standard" >/usr/share/man/man1/toybox.1 +testing "gawk var" "man toybox" " #AK language. The #PX standard\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +If set to +.BR On , +(...) +EOF +testing "bash boldpunct" "man toybox" " If set to On, (...)\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +.IP \\fB\$endif\\fP +(...) +.IP \\fB\$else\\fP +(...) +.IP \\fB\$include\\fP +EOF +testing "bash list" "man toybox" " \$endif (...)\n\n \$else (...)\n\n \$include\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +asynchronously (in the +.IR background ), +it prints +EOF +testing "bash itapunct" "man toybox" " asynchronously (in the background), it prints\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +(...) +.B Bash +is +EOF +testing "bash bold" "man toybox" " (...) Bash is\n\n" "" "" + +# TODO: Unquote. +cat >/usr/share/man/man1/toybox.1 <<EOF +.PD 0 +.BI \\-f " program-file" +.TP +EOF +testing "gawk boldita" "man toybox" " -f \" program-file\"\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +same format as +.FN /etc/hosts +(...) +EOF +testing "bash filename" "man toybox" " same format as /etc/hosts (...)\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +The +.I Internal Field Separator +that is used +EOF +testing "bash ita" "man toybox" " The Internal Field Separator that is used\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +.if n Copyright (C) 2019 +.if t Copyright \\(co 2019 +EOF +testing "bash nroff" "man toybox" " Copyright (C) 2019\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +(...) +.PP +(...) +EOF +testing "bash paragraph" "man toybox" " (...)\n\n (...)\n\n" "" "" + +# TODO: Find some command I saw that has a different see below. +cat >/usr/share/man/man1/toybox.1 <<EOF +(see +.SM +.B INVOCATION +below) +EOF +testing "bash small" "man toybox" " (see INVOCATION below)\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +(...) +.SH "SHELL GRAMMAR" +.SS Simple Commands +.PP +(...) +EOF +testing "bash section" "man toybox" " (...)\n\n\"SHELL GRAMMAR\"\n\nSimple Commands\n\n (...)\n\n" "" "" + +echo ".so man1/last.1" >/usr/share/man/man1/toybox.1 +testing "lastb" "man toybox" "See last.1\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +.TH TOYBOX 1 "Apr 13 2019" "Project Organization" "Document Name" +.PP +.TH "TOYBOX" "1" "04/13/2019" "Toybox 0\\&.8\\&.0" "Toybox Manual" +EOF +testing "gawk,git head" "man toybox" "TOYBOX 1 Apr 13 2019 Project Organization Document Name \n\n TOYBOX 1 04/13/2019 Toybox 0.8.0 Toybox Manual \n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +(...) +.PP +.PD 0 +.TP 10 +.B \\-c +If the +.B \\-c +option is present +EOF +testing "bash table" "man toybox" " (...)\n\n -c If the -c option is present\n\n" "" "" + +cat >/usr/share/man/man1/toybox.1 <<EOF +.de FN +.sp +.RE +'\" t +EOF +testing "bash,git garbage" "man toybox" "" "" "" + +# TODO: -k +# TODO: emerge section header newline +# TODO: fdm not roff +# TODO: git-pull consecutive escaped slashes + +rm /usr/share/man/man1/toybox.1 diff --git a/toys/pending/man.c b/toys/pending/man.c new file mode 100644 index 00000000..57f77c61 --- /dev/null +++ b/toys/pending/man.c @@ -0,0 +1,112 @@ +/* man.c - Read system documentation + * + * Copyright 2019 makepost <makepost@firemail.cc> + * + * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/man.html + +USE_MAN(NEWTOY(man, "<1>1", TOYFLAG_USR|TOYFLAG_BIN)) + +config MAN + bool "man" + default n + help + usage: man COMMAND + + Read manual for system command. +*/ + +#define FOR_man +#include <toys.h> +#include <glob.h> + +GLOBALS( + char any, cell, *f, *line; +) + +static void newln() +{ + if (TT.any) putchar('\n'); + if (TT.any && TT.cell != 2) putchar('\n'); // gawk alias + TT.any = TT.cell = 0; +} +static void put(char *x) { while (*x && *x != '\n') TT.any = putchar(*x++); } + +static void s(char *x, char *y) { // Substitute with same length or shorter. + int i = strlen(x), j = strlen(y), k, l; + for (k = 0; TT.line[k]; k++) if (!strncmp(x, &TT.line[k], i)) { + memmove(&TT.line[k], y, j); + for (l = k += j; TT.line[l]; l++) TT.line[l] = TT.line[l + i - j]; + } +} + +static char start(char *x) { return !strncmp(x, TT.line, strlen(x)); } +static void trim(char *x) { if (start(x)) while (*x++) TT.line++; } + +static void do_man(FILE *fp) +{ + size_t len = 0; + char *line = 0; + while (getline(&line, &len, fp) > 0) { + TT.line = line; + s("\\fB", ""), s("\\fI", ""), s("\\fP", ""), s("\\fR", ""); // bash bold,ita + s("\\(aq", "'"), s("\\(cq", "'"), s("\\(dq", "\""); // bash,rsync quote + s("\\*(lq", "\""), s("\\*(rq", "\""); // gawk quote + s("\\(bu", "*"), s("\\(bv", "|"); // bash symbol + s("\\&", ""), s("\\f(CW", ""); // gawk,rsync fancy + s("\\-", "-"), s("\\(", ""), s("\\^", ""), s("\\e", "\\"); // bash escape + s("\\*(", "#"); // gawk var + if (start(".BR")) trim(".BR "), s(" ", ""); // bash boldpunct + if (start(".IP")) newln(), trim(".IP "); // bash list + if (start(".IR")) trim(".IR "), s(" ", ""); // bash itapunct + trim(".B "); // bash bold + trim(".BI "); // gawk boldita + trim(".FN "); // bash filename + trim(".I "); // bash ita + trim(".if n "); // bash nroff + if (start(".PP")) newln(); // bash paragraph + else if (start(".SM")); // bash small + else if (start(".S")) newln(), put(TT.line + 4), newln(); // bash section + else if (start(".so")) put("See "), put(basename(TT.line + 4)); // lastb + else if (start(".TH")) s("\"", " "), put(TT.line + 4); // gawk,git head + else if (start(".TP")) newln(), TT.cell = 1; // bash table + else if (start(".") || start("\'")); // bash,git garbage + else if (!*TT.line); // emerge + else ((TT.cell != 0) && TT.cell++), put(" "), put(TT.line); + } + newln(); + free(line); + fclose(fp); +} + +static FILE *bzcat() +{ + char cmd[FILENAME_MAX]; + snprintf(cmd, sizeof(cmd), "bzcat %s", TT.f); + return popen(cmd, "r"); +} + +static char *find(char *path, int suf) +{ + glob_t g; + int i; + size_t len = strlen(*toys.optargs); + char *name; + glob(path, 0, 0, &g); + for (i = 0; !TT.f && i < g.gl_pathc; i++) { + name = basename(g.gl_pathv[i]); + if (strlen(name) == len + suf && !strncmp(name, *toys.optargs, len)) + TT.f = strdup(g.gl_pathv[i]); + } + globfree(&g); + return TT.f; +} + +void man_main(void) +{ + chdir("/usr/share/man"); + if (find("man?/*.?.bz2", 6)) do_man(bzcat()); // curl_strequal + else if (find("man?/*.bz2", 4)) do_man(bzcat()); // curl_strequal.3 + else if (find("man?/*.?", 2)) do_man(fopen(TT.f, "r")); // curl_strnequal + else if (find("man?/*", 0)) do_man(fopen(TT.f, "r")); // curl_strnequal.3 + if (TT.f) free(TT.f); +} |