From 72cf85a98bb1b2a6ef04b580cfa7c6a0d5ae1b24 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Mon, 22 Jul 2019 03:21:49 +0000 Subject: 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. --- man_term.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) (limited to 'man_term.c') diff --git a/man_term.c b/man_term.c index bb4851e9..b051b2ec 100644 --- a/man_term.c +++ b/man_term.c @@ -1,4 +1,4 @@ -/* $Id: man_term.c,v 1.230 2019/07/01 22:56:24 schwarze Exp $ */ +/* $Id: man_term.c,v 1.231 2019/07/22 03:21:49 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze @@ -27,10 +27,12 @@ #include #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; @@ -1148,3 +1154,60 @@ print_man_head(struct termp *p, const struct roff_meta *meta) } 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; + } + } +} -- cgit v1.2.3-56-ge451