Hi Theo,

Theo de Raadt wrote on Sun, Jul 21, 2019 at 02:00:20PM -0600:

> Nice rant.  Now get back to work.  :)

As you wish, Your Grace.  =;c)
  Ingo


Log Message:
-----------
Slowly start implementing tagging support for man(7) pages, even 
though it is obvious that this can never become as good as for
mdoc(7) pages.  As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.

Modified Files:
--------------
    mandoc:
        Makefile.depend
        man_term.c
        tag.c

Revision Data
-------------
Index: tag.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/tag.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -Ltag.c -Ltag.c -u -p -r1.23 -r1.24
--- tag.c
+++ tag.c
@@ -151,11 +151,11 @@ tag_put(const char *s, int prio, size_t 
                s += 2;
 
        /*
-        * Skip whitespace and whatever follows it,
+        * Skip whitespace and escapes and whatever follows,
         * and if there is any, downgrade the priority.
         */
 
-       len = strcspn(s, " \t");
+       len = strcspn(s, " \t\\");
        if (len == 0)
                return;
 
Index: Makefile.depend
===================================================================
RCS file: /home/cvs/mandoc/mandoc/Makefile.depend,v
retrieving revision 1.44
retrieving revision 1.45
diff -LMakefile.depend -LMakefile.depend -u -p -r1.44 -r1.45
--- Makefile.depend
+++ Makefile.depend
@@ -37,7 +37,7 @@ main.o: main.c config.h mandoc_aux.h man
 man.o: man.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h 
roff_int.h libman.h
 man_html.o: man_html.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h 
html.h main.h
 man_macro.o: man_macro.c config.h mandoc.h roff.h man.h libmandoc.h roff_int.h 
libman.h
-man_term.o: man_term.c config.h mandoc_aux.h roff.h man.h out.h term.h main.h
+man_term.o: man_term.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h 
term.h tag.h main.h
 man_validate.o: man_validate.c config.h mandoc_aux.h mandoc.h roff.h man.h 
libmandoc.h roff_int.h libman.h
 mandoc.o: mandoc.c config.h mandoc_aux.h mandoc.h roff.h libmandoc.h roff_int.h
 mandoc_aux.o: mandoc_aux.c config.h mandoc.h mandoc_aux.h
Index: man_term.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/man_term.c,v
retrieving revision 1.230
retrieving revision 1.231
diff -Lman_term.c -Lman_term.c -u -p -r1.230 -r1.231
--- man_term.c
+++ man_term.c
@@ -27,10 +27,12 @@
 #include <string.h>
 
 #include "mandoc_aux.h"
+#include "mandoc.h"
 #include "roff.h"
 #include "man.h"
 #include "out.h"
 #include "term.h"
+#include "tag.h"
 #include "main.h"
 
 #define        MAXMARGINS        64 /* maximum number of indented scopes */
@@ -92,6 +94,8 @@ static        void              post_SY(DECL_ARGS);
 static void              post_TP(DECL_ARGS);
 static void              post_UR(DECL_ARGS);
 
+static void              tag_man(struct termp *, struct roff_node *);
+
 static const struct man_term_act man_term_acts[MAN_MAX - MAN_TH] = {
        { NULL, NULL, 0 }, /* TH */
        { pre_SH, post_SH, 0 }, /* SH */
@@ -534,8 +538,10 @@ pre_IP(DECL_ARGS)
        case ROFFT_HEAD:
                p->tcol->offset = mt->offset;
                p->tcol->rmargin = mt->offset + len;
-               if (n->child != NULL)
+               if (n->child != NULL) {
                        print_man_node(p, mt, n->child, meta);
+                       tag_man(p, n->child);
+               }
                return 0;
        case ROFFT_BODY:
                p->tcol->offset = mt->offset + len;
@@ -1147,4 +1153,61 @@ print_man_head(struct termp *p, const st
                term_vspace(p);
        }
        free(title);
+}
+
+/*
+ * Skip leading whitespace, dashes, backslashes, and font escapes,
+ * then create a tag if the first following byte is a letter.
+ * Priority is high unless whitespace is present.
+ */
+static void
+tag_man(struct termp *p, struct roff_node *n)
+{
+       const char      *cp, *arg;
+       int              prio, sz;
+
+       assert(n->type == ROFFT_TEXT);
+       cp = n->string;
+       prio = 1;
+       for (;;) {
+               switch (*cp) {
+               case ' ':
+               case '\t':
+                       prio = INT_MAX;
+                       /* FALLTHROUGH */
+               case '-':
+                       cp++;
+                       break;
+               case '\\':
+                       cp++;
+                       switch (mandoc_escape(&cp, &arg, &sz)) {
+                       case ESCAPE_FONT:
+                       case ESCAPE_FONTROMAN:
+                       case ESCAPE_FONTITALIC:
+                       case ESCAPE_FONTBOLD:
+                       case ESCAPE_FONTPREV:
+                       case ESCAPE_FONTBI:
+                               break;
+                       case ESCAPE_SPECIAL:
+                               if (sz != 1)
+                                       return;
+                               switch (*arg) {
+                               case '&':
+                               case '-':
+                               case 'e':
+                                       break;
+                               default:
+                                       return;
+                               }
+                               break;
+                       default:
+                               return;
+                       }
+                       break;
+               default:
+                       if (isalpha((unsigned char)*cp))
+                               tag_put(cp, prio, p->line);
+                       return;
+               }
+       }
 }

Reply via email to