diff options
Diffstat (limited to '')
-rw-r--r-- | bin/.gitignore | 1 | ||||
-rw-r--r-- | bin/Makefile | 4 | ||||
-rw-r--r-- | bin/README.7 | 4 | ||||
-rw-r--r-- | bin/man1/mtags.1 | 68 | ||||
-rw-r--r-- | bin/mtags.c | 86 |
5 files changed, 161 insertions, 2 deletions
diff --git a/bin/.gitignore b/bin/.gitignore index d2b46a7f..a52982b3 100644 --- a/bin/.gitignore +++ b/bin/.gitignore @@ -16,6 +16,7 @@ hnel htagml htmltags modem +mtags nudge open order diff --git a/bin/Makefile b/bin/Makefile index 13dfb2f2..b133232f 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -29,6 +29,7 @@ BINS += hilex BINS += hnel BINS += htagml BINS += modem +BINS += mtags BINS += nudge BINS += order BINS += pbd @@ -132,9 +133,10 @@ html: ${HTMLS} ${HTMLS}: html.sh scheme hilex htagml htmltags -htmltags: *.[chly] +htmltags: *.[chly] mtags Makefile rm -f $@ for f in *.[chly]; do ctags -aw -f $@ $$f; done + ./mtags -a -f $@ Makefile .SUFFIXES: .html diff --git a/bin/README.7 b/bin/README.7 index aded212e..723845e2 100644 --- a/bin/README.7 +++ b/bin/README.7 @@ -1,4 +1,4 @@ -.Dd January 13, 2021 +.Dd January 19, 2021 .Dt BIN 7 .Os "Causal Agency" . @@ -44,6 +44,8 @@ PTY input remapper tags HTMLizer .It Xr modem 1 fixed baud rate wrapper +.It Xr mtags 1 +miscellaneous tags .It Xr nudge 1 terminal vibrator .It Xr order 1 diff --git a/bin/man1/mtags.1 b/bin/man1/mtags.1 new file mode 100644 index 00000000..bb4b50b4 --- /dev/null +++ b/bin/man1/mtags.1 @@ -0,0 +1,68 @@ +.Dd January 19, 2021 +.Dt MTAGS 1 +.Os +. +.Sh NAME +.Nm mtags +.Nd miscellaneous tags +. +.Sh SYNOPSIS +.Nm +.Op Fl a +.Op Fl f Ar tagsfile +.Ar +. +.Sh DESCRIPTION +The +.Nm +utility +makes a +.Pa tags +file for +.Xr ex 1 +from the specified +.Xr make 1 +and +.Xr mdoc 7 +sources. +. +.Pp +The arguments are as follows: +.Bl -tag -width Ds +.It Fl a +Append to +.Pa tags +file. +.It Fl f Ar tagsfile +Place the tag descriptions +in a file called +.Ar tagsfile . +The default behaviour is +to place them in a file called +.Pa tags . +.El +. +.Pp +Files whose names are +.Pa Makefile +or end in +.Pa .mk +are assumed to be +.Xr make 1 +files. +Files whose names end in +.Pa .[1-9] +are assumed to be +.Xr mdoc 7 +files. +. +.Sh FILES +.Bl -tag -width Ds +.It Pa tags +default output tags file +.El +. +.Sh SEE ALSO +.Xr ctags 1 , +.Xr ex 1 , +.Xr vi 1 diff --git a/bin/mtags.c b/bin/mtags.c new file mode 100644 index 00000000..3ff72c19 --- /dev/null +++ b/bin/mtags.c @@ -0,0 +1,86 @@ +/* Copyright (C) 2021 C. McEnroe <june@causal.agency> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <err.h> +#include <regex.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sysexits.h> +#include <unistd.h> + +int main(int argc, char *argv[]) { + bool append = false; + const char *path = "tags"; + for (int opt; 0 < (opt = getopt(argc, argv, "af:"));) { + switch (opt) { + break; case 'a': append = true; + break; case 'f': path = optarg; + break; default: return EX_USAGE; + } + } + + FILE *tags = fopen(path, (append ? "a" : "w")); + if (!tags) err(EX_CANTCREAT, "%s", path); + + regex_t makeFile, makeLine; + regex_t mdocFile, mdocLine; + int error = 0 + || regcomp(&makeFile, "(^|/)Makefile|[.]mk$", REG_EXTENDED | REG_NOSUB) + || regcomp( + &makeLine, + "^([.][^$A-Z][^$[:space:]]*|[^.$][^$[:space:]]*):", + REG_EXTENDED + ) + || regcomp(&mdocFile, "[.][1-9]$", REG_EXTENDED | REG_NOSUB) + || regcomp(&mdocLine, "^[.]S[hs] ([^\t\n]+)", REG_EXTENDED); + assert(!error); + + size_t cap = 0; + char *buf = NULL; + for (int i = optind; i < argc; ++i) { + const regex_t *regex; + if (!regexec(&makeFile, argv[i], 0, NULL, 0)) { + regex = &makeLine; + } else if (!regexec(&mdocFile, argv[i], 0, NULL, 0)) { + regex = &mdocLine; + } else { + warnx("skipping unknown file type %s", argv[i]); + continue; + } + + FILE *file = fopen(argv[i], "r"); + if (!file) err(EX_NOINPUT, "%s", argv[i]); + + while (0 < getline(&buf, &cap, file)) { + regmatch_t match[2]; + if (regexec(regex, buf, 2, match, 0)) continue; + int n = fprintf( + tags, "%.*s\t%s\t/^%.*s/\n", + (int)(match[1].rm_eo - match[1].rm_so), &buf[match[1].rm_so], + argv[i], + (int)(match[0].rm_eo - match[0].rm_so), &buf[match[0].rm_so] + ); + if (n < 0) err(EX_IOERR, "%s", path); + } + fclose(file); + } + + error = fclose(tags); + if (error) err(EX_IOERR, "%s", path); +} |