[hackers] [sbase] nl: add -d -p -f -h options || Quentin Rameau

From: <git_AT_suckless.org>
Date: Tue, 24 Mar 2015 23:54:21 +0100 (CET)

commit 787d99d896e06b2383da763df695b9e9496bdff5
Author: Quentin Rameau <quinq_AT_quinq.eu.org>
Date: Wed Mar 18 17:58:09 2015 +0100

    nl: add -d -p -f -h options

diff --git a/LICENSE b/LICENSE
index 3633fda..f4c6cc8 100644
--- a/LICENSE
+++ b/LICENSE
_AT_@ -56,3 +56,4 @@ Authors/contributors include:
 © 2014 Adria Garriga <rhaps0dy_AT_installgentoo.com>
 © 2014 Greg Reagle <greg.reagle_AT_umbc.edu>
 © 2015 Tai Chi Minh Ralph Eastwood <tcmreastwood_AT_gmail.com>
+© 2015 Quentin Rameau <quinq_AT_quinq.eu.org>
diff --git a/README b/README
index 4c832ff..0d9c3a2 100644
--- a/README
+++ b/README
_AT_@ -49,7 +49,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support,
 =*| mktemp non-posix none
 =*| mv yes none (-i)
 =*| nice yes none
-= nl no -d, -f, -h, -p
+=* nl yes none
 =*| nohup yes none
 #*| paste yes none
 =*| printenv non-posix none
diff --git a/nl.1 b/nl.1
index 3f9cd81..0817421 100644
--- a/nl.1
+++ b/nl.1
_AT_@ -1,4 +1,4 @@
-.Dd February 20, 2015
+.Dd March 18, 2015
 .Dt NL 1
 .Os sbase
 .Sh NAME
_AT_@ -6,7 +6,11 @@
 .Nd line numbering filter
 .Sh SYNOPSIS
 .Nm
+.Op Fl p
 .Op Fl b Ar type
+.Op Fl d Ar delim
+.Op Fl f Ar type
+.Op Fl h Ar type
 .Op Fl i Ar incr
 .Op Fl l Ar num
 .Op Fl n Ar format
_AT_@ -25,8 +29,10 @@ is given
 reads from stdin.
 .Sh OPTIONS
 .Bl -tag -width Ds
+.It Fl p
+Do not reset number for logical pages
 .It Fl b Ar type
-Defines which lines will be numbered:
+Defines which lines will be numbered for body sections:
 .Bl -tag -width pstringXX
 .It a
 All lines.
_AT_@ -40,6 +46,16 @@ Only lines which match
 a regular expression as defined in
 .Xr regex 7 .
 .El
+.It Fl d Ar delim
+Specify the two characters delimiter (default is "\\:"). If only one character is specified, the second remains ':'.
+.It Fl f Ar type
+Same as
+.Fl b
+except for footer sections.
+.It Fl h Ar type
+Same as
+.Fl b
+except for header sections.
 .It Fl i Ar incr
 Defines the increment between numbered lines.
 .It Fl l Ar num
_AT_@ -76,3 +92,9 @@ The default is 6.
 .El
 .Sh SEE ALSO
 .Xr pr 1
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification.
diff --git a/nl.c b/nl.c
index d756f60..46b3c0b 100644
--- a/nl.c
+++ b/nl.c
_AT_@ -13,29 +13,64 @@
 #define FORMAT_RN "%*ld%s"
 #define FORMAT_RZ "%0*ld%s"
 
-static char mode = 't';
-static int blines = 1;
+static char type[] = { 'n', 't', 'n' }; /* footer, body, header */
+static char delim[] = { '\\', ':' };
 static const char *format = FORMAT_RN;
 static const char *sep = "\t";
 static int width = 6;
+static int pflag = 0;
 static size_t startnum = 1;
 static size_t incr = 1;
-static regex_t preg;
+static size_t blines = 1;
+static regex_t preg[3];
+
+static int
+getsection(char *buf, int *section)
+{
+ int sectionchanged = 0;
+ int newsection = *section;
+
+ while (!strncmp(buf, delim, 2)) {
+ if (!sectionchanged) {
+ sectionchanged = 1;
+ newsection = 0;
+ } else {
+ ++newsection;
+ newsection %= 3;
+ }
+ buf += 2;
+ }
+
+ if (buf && buf[0] == '\n')
+ *section = newsection;
+ else
+ sectionchanged = 0;
+
+ return sectionchanged;
+}
 
 static void
 nl(const char *name, FILE *fp)
 {
         char *buf = NULL;
- int donumber, bl = 1;
- size_t size = 0;
+ int donumber, oldsection, section = 1, bl = 1;
+ size_t number = startnum, size = 0;
 
         while (getline(&buf, &size, fp) != -1) {
                 donumber = 0;
+ oldsection = section;
+
+ if (getsection(buf, &section)) {
+ if ((section >= oldsection) && !pflag)
+ number = startnum;
+ continue;
+ }
 
- if ((mode == 't' && buf[0] != '\n')
- || (mode == 'p' && !regexec(&preg, buf, 0, NULL, 0))) {
+ if ((type[section] == 't' && buf[0] != '\n')
+ || (type[section] == 'p' &&
+ !regexec(&preg[section], buf, 0, NULL, 0))) {
                         donumber = 1;
- } else if (mode == 'a') {
+ } else if (type[section] == 'a') {
                         if (buf[0] == '\n' && bl < blines) {
                                 ++bl;
                         } else {
_AT_@ -45,8 +80,8 @@ nl(const char *name, FILE *fp)
                 }
 
                 if (donumber) {
- printf(format, width, startnum, sep);
- startnum += incr;
+ printf(format, width, number, sep);
+ number += incr;
                 } else {
                         printf("%*s", width, "");
                 }
_AT_@ -60,23 +95,46 @@ nl(const char *name, FILE *fp)
 static void
 usage(void)
 {
- eprintf("usage: %s [-b type] [-i incr] [-l num] [-n format] [-s sep] [-v startnum] [-w width] [file]\n", argv0);
+ eprintf("usage: %s [-p] [-b type] [-d delim] [-f type] "
+ "[-h type] [-i incr] [-l num]\n[-n format] [-s sep] "
+ "[-v startnum] [-w width] [file]\n", argv0);
+}
+static char
+getlinetype(char *type, regex_t *preg)
+{
+ if (type[0] == 'p')
+ eregcomp(preg, &type[1], REG_NOSUB);
+ else if (!strchr("ant", type[0]))
+ usage();
+
+ return type[0];
 }
 
 int
 main(int argc, char *argv[])
 {
         FILE *fp;
- char *r;
+ char *d;
 
         ARGBEGIN {
         case 'b':
- r = EARGF(usage());
- mode = r[0];
- if (r[0] == 'p')
- eregcomp(&preg, &r[1], REG_NOSUB);
- else if (!strchr("ant", mode))
+ type[1] = getlinetype(EARGF(usage()), &preg[1]);
+ break;
+ case 'd':
+ d = EARGF(usage());
+ if (strlen(d) > 2) {
                         usage();
+ } else if (d[0] != '\0') {
+ delim[0] = d[0];
+ if (d[1])
+ delim[1] = d[1];
+ }
+ break;
+ case 'f':
+ type[0] = getlinetype(EARGF(usage()), &preg[0]);
+ break;
+ case 'h':
+ type[2] = getlinetype(EARGF(usage()), &preg[2]);
                 break;
         case 'i':
                 incr = estrtonum(EARGF(usage()), 0, MIN(LLONG_MAX, SIZE_MAX));
_AT_@ -95,6 +153,9 @@ main(int argc, char *argv[])
                 else
                         eprintf("%s: bad format\n", format);
                 break;
+ case 'p':
+ pflag = 1;
+ break;
         case 's':
                 sep = EARGF(usage());
                 break;
Received on Tue Mar 24 2015 - 23:54:21 CET

This archive was generated by hypermail 2.3.0 : Wed Mar 25 2015 - 00:12:11 CET