aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/man.test196
-rw-r--r--toys/pending/man.c112
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);
+}