From 2baa73fb0d3999d541b2122b853b56e2bfdea56b Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 27 Oct 2013 02:50:55 -0500 Subject: Promote nl from pending to posix, and add tests. --- scripts/test/nl.test | 50 ++++++++++++++++++++++++++++ toys/pending/nl.c | 94 ---------------------------------------------------- toys/posix/nl.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 94 deletions(-) create mode 100644 scripts/test/nl.test delete mode 100644 toys/pending/nl.c create mode 100644 toys/posix/nl.c diff --git a/scripts/test/nl.test b/scripts/test/nl.test new file mode 100644 index 00000000..958cb41e --- /dev/null +++ b/scripts/test/nl.test @@ -0,0 +1,50 @@ +#!/bin/bash + +[ -f testing.sh ] && . testing.sh + +#testing "name" "command" "result" "infile" "stdin" + +testing "nl" "nl" " 1\tone\n 2\ttwo\n 3\tthree\n" \ + "" "one\ntwo\nthree\n" + +testing "nl explicit defaults" "nl -nrn -b a" \ + " 1\tone\n 2\ttwo\n 3\tthree\n" "" "one\ntwo\nthree\n" + +# -n ln rn rz + +testing "nl -nln" "nl -nln" "1 \tone\n2 \ttwo\n3 \tthree\n" \ + "" "one\ntwo\nthree\n" +testing "nl -nln -w" "nl -nln -w 8" \ + "1 \tone\n2 \ttwo\n3 \tthree\n" "" "one\ntwo\nthree\n" + +testing "nl -nrz" "nl -nrz" "000001\tone\n000002\ttwo\n000003\tthree\n" \ + "" "one\ntwo\nthree\n" + +testing "nl -nrz -w" "nl -w3 -nrz" "001\tone\n002\ttwo\n003\tthree\n" \ + "" "one\ntwo\nthree\n" + + +# For non-matching lines the separator is "suppressed" meaning it... +# turns into spaces! And the tab turns into one space, and -d boom turns +# into 4 spaces, but these: +# nl -s"$(echo -e 'bo\tom')" -bpand README +# nl -w 3 -bpthe README +# Yeah. And I doubt utf8 fontmetrics are used either. + +testing "nl -b t" "nl -b t" " \n 1\tone\n \n 2\ttwo\n" \ + "" "\none\n\ntwo\n" +testing "nl -b n" "nl -b n" " one\n two\n three\n" \ + "" "one\ntwo\nthree\n" +testing "nl -sook -b p" "nl -sook -bpoing" \ + " one\n 1ookboing\n 2ooksproingy\n" \ + "" "one\nboing\nsproingy\n" + +testing "nl -v" "nl -v 42" " 42\tone\n 43\ttwo\n 44\tthree\n" \ + "" "one\ntwo\nthree\n" +testing "nl -l" "nl -ba -l2 -w2 - input" \ + " 1\tone\n \n 2\t\n 3\ttwo\n \n 4\t\n \n 5\tthree\n 6\tfour\n \n 7\t\n \n 8\tbang\n \n" \ + "\n\nbang\n\n" "one\n\n\ntwo\n\n\n\nthree\nfour\n\n" +testing "nl no space" "nl -w 1 -v 42" "42\tline\n" "" "line\n" + +# Should test for -E but no other implementation seems to have it? +#testing "nl -E" "nl -w2 -sx -Ebp'(one|two)'" " 1x" "one\nand\ntwo\n" diff --git a/toys/pending/nl.c b/toys/pending/nl.c deleted file mode 100644 index 2adac246..00000000 --- a/toys/pending/nl.c +++ /dev/null @@ -1,94 +0,0 @@ -/* nl.c - print line numbers - * - * Copyright 2013 CE Strake - * - * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/nl.html - * - * This implements a subset: only one logical page (-ip), no sections (-dfh). - * todo: -lv - -USE_NL(NEWTOY(nl, "v#<1=1l#b:n:s:w#<0=6E", TOYFLAG_BIN)) - -config NL - bool "nl" - default n - help - usage: nl [-E] [-l #] [-b MODE] [-n STYLE] [-s SEPARATOR] [-w WIDTH] [FILE...] - - Number lines of input. - - -E Use extended regex syntax (when doing -b pREGEX) - -b which lines to number: a (all) t (non-empty, default) pREGEX (pattern) - -l Only count last of this many consecutive blank lines - -n number STYLE: ln (left justified) rn (right justified) rz (zero pad) - -s Separator to use between number and line (instead of TAB) - -w Width of line numbers (default 6) -*/ - -#define FOR_nl -#include "toys.h" -#include "lib/xregcomp.h" - -GLOBALS( - long w; - char *s; - char *n; - char *b; - long l; - long v; - - // Count of consecutive blank lines for -l has to persist between files - long lcount; -) - -void do_nl(int fd, char *name) -{ - FILE *f = xfdopen(fd, "r"); - int w = TT.w, slen = strlen(TT.s); - - for (;;) { - char *line = 0; - size_t temp; - int match = *TT.b != 'n'; - - if (getline(&line, &temp, f) < 1) { - if (ferror(f)) perror_msg("%s", name); - break; - } - - if (*TT.b == 'p') match = !regexec((void *)(toybuf+16), line, 0, 0, 0); - if (TT.l || *TT.b == 't') - if (*line == '\n') match = TT.l && ++TT.lcount >= TT.l; - if (match) { - TT.lcount = 0; - printf(toybuf, w, TT.v++, TT.s); - } else printf("%*c", (int)w+slen, ' '); - xprintf("%s", line); - - free(line); - } - - fclose(f); -} - -void nl_main(void) -{ - char *clip = ""; - - if (!TT.s) TT.s = "\t"; - - if (!TT.n || !strcmp(TT.n, "rn")); // default - else if (!strcmp(TT.n, "ln")) clip = "-"; - else if (!strcmp(TT.n, "rz")) clip = "0"; - else error_exit("bad -n '%s'", TT.n); - - sprintf(toybuf, "%%%s%s", clip, "*ld%s"); - - if (!TT.b) TT.b = "t"; - if (*TT.b == 'p' && TT.b[1]) - xregcomp((void *)(toybuf+16), TT.b+1, - REG_NOSUB | (toys.optflags&FLAG_E)*REG_EXTENDED); - else if (!strchr("atn", *TT.b)) error_exit("bad -b '%s'", TT.b); - - loopfiles (toys.optargs, do_nl); -} diff --git a/toys/posix/nl.c b/toys/posix/nl.c new file mode 100644 index 00000000..b462cddd --- /dev/null +++ b/toys/posix/nl.c @@ -0,0 +1,94 @@ +/* nl.c - print line numbers + * + * Copyright 2013 CE Strake + * + * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/nl.html + * + * This implements a subset: only one logical page (-ip), no sections (-dfh). + * todo: -lv + +USE_NL(NEWTOY(nl, "v#<1=1l#b:n:s:w#<0=6E", TOYFLAG_BIN)) + +config NL + bool "nl" + default y + help + usage: nl [-E] [-l #] [-b MODE] [-n STYLE] [-s SEPARATOR] [-w WIDTH] [FILE...] + + Number lines of input. + + -E Use extended regex syntax (when doing -b pREGEX) + -b which lines to number: a (all) t (non-empty, default) pREGEX (pattern) + -l Only count last of this many consecutive blank lines + -n number STYLE: ln (left justified) rn (right justified) rz (zero pad) + -s Separator to use between number and line (instead of TAB) + -w Width of line numbers (default 6) +*/ + +#define FOR_nl +#include "toys.h" +#include "lib/xregcomp.h" + +GLOBALS( + long w; + char *s; + char *n; + char *b; + long l; + long v; + + // Count of consecutive blank lines for -l has to persist between files + long lcount; +) + +void do_nl(int fd, char *name) +{ + FILE *f = xfdopen(fd, "r"); + int w = TT.w, slen = strlen(TT.s); + + for (;;) { + char *line = 0; + size_t temp; + int match = *TT.b != 'n'; + + if (getline(&line, &temp, f) < 1) { + if (ferror(f)) perror_msg("%s", name); + break; + } + + if (*TT.b == 'p') match = !regexec((void *)(toybuf+16), line, 0, 0, 0); + if (TT.l || *TT.b == 't') + if (*line == '\n') match = TT.l && ++TT.lcount >= TT.l; + if (match) { + TT.lcount = 0; + printf(toybuf, w, TT.v++, TT.s); + } else printf("%*c", (int)w+slen, ' '); + xprintf("%s", line); + + free(line); + } + + fclose(f); +} + +void nl_main(void) +{ + char *clip = ""; + + if (!TT.s) TT.s = "\t"; + + if (!TT.n || !strcmp(TT.n, "rn")); // default + else if (!strcmp(TT.n, "ln")) clip = "-"; + else if (!strcmp(TT.n, "rz")) clip = "0"; + else error_exit("bad -n '%s'", TT.n); + + sprintf(toybuf, "%%%s%s", clip, "*ld%s"); + + if (!TT.b) TT.b = "t"; + if (*TT.b == 'p' && TT.b[1]) + xregcomp((void *)(toybuf+16), TT.b+1, + REG_NOSUB | (toys.optflags&FLAG_E)*REG_EXTENDED); + else if (!strchr("atn", *TT.b)) error_exit("bad -b '%s'", TT.b); + + loopfiles (toys.optargs, do_nl); +} -- cgit v1.2.3