aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2017-06-02 20:30:20 +1200
committerTom Ryder <tom@sanctum.geek.nz>2017-06-02 20:30:20 +1200
commitcde3c255ff7024181a54b19e5ec1dac3ab892836 (patch)
tree8b4b8ab889bb4d28223ff510ff7e6188d1641aa5
parentSimplify some awk (diff)
downloaddotfiles-cde3c255ff7024181a54b19e5ec1dac3ab892836.tar.gz
dotfiles-cde3c255ff7024181a54b19e5ec1dac3ab892836.zip
Add mi5(1df)
-rw-r--r--.gitignore1
-rw-r--r--IDEAS.markdown2
-rw-r--r--Makefile1
-rw-r--r--README.markdown2
-rw-r--r--bin/mi5.awk50
-rw-r--r--man/man1/mi5.1df63
6 files changed, 119 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index a539a8f8..68ac0a0a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,7 @@ bin/jfc
bin/jfcd
bin/jfp
bin/loc
+bin/mi5
bin/max
bin/maybe
bin/mean
diff --git a/IDEAS.markdown b/IDEAS.markdown
index 3b0f1c75..61f1049d 100644
--- a/IDEAS.markdown
+++ b/IDEAS.markdown
@@ -12,3 +12,5 @@ Ideas
processes and mkfifo(1).
* Write something like hcat(1df) or tcat(1df) that includes filename headings
for each concatenated file.
+* mi5(1df) could be made to handle comment delimiters and $1 $2 expansions
+ without too much pain (substr/index counting)
diff --git a/Makefile b/Makefile
index f35e1917..a562b0b1 100644
--- a/Makefile
+++ b/Makefile
@@ -119,6 +119,7 @@ BINS = bin/ap \
bin/jfcd \
bin/jfp \
bin/loc \
+ bin/mi5 \
bin/max \
bin/maybe \
bin/mean \
diff --git a/README.markdown b/README.markdown
index c35d3790..bd0b6682 100644
--- a/README.markdown
+++ b/README.markdown
@@ -498,6 +498,8 @@ Installed by the `install-bin` target:
success,
it exits with success or failure. Good for quick tests.
* `mex(1df)` makes given filenames in `$PATH` executable.
+* `mi5(1df)` pre-processes a crude but less painful macro expansion file
+ format into m4.
* `mftl(1df)` finds usable-looking targets in Makefiles.
* `mkcp(1df)` creates a directory and copies preceding arguments into it.
* `mkmv(1df)` creates a directory and moves preceding arguments into it.
diff --git a/bin/mi5.awk b/bin/mi5.awk
new file mode 100644
index 00000000..c05955ff
--- /dev/null
+++ b/bin/mi5.awk
@@ -0,0 +1,50 @@
+# Crude m4 preprocessor
+BEGIN { mac = 0 }
+
+# Print an m4 opener as the first byte
+NR == 1 { printf "`" }
+
+# Blocks
+NF == 1 && $1 == "<%" && !mac {
+ mac = 1
+ printf "'"
+ next
+}
+NF == 1 && $1 == "%>" && mac {
+ mac = 0
+ printf "`"
+ next
+}
+
+# If processing macros, strip leading and trailing whitespace and skip blank
+# lines
+mac {
+ sub(/^ */, "")
+ sub(/ *$/, "")
+}
+mac && !NF { next }
+
+# Inlines
+mac {
+ print $0 "dnl"
+}
+!mac {
+
+ # Don't let apostrophes close the comment
+ gsub(/'/, "''`")
+
+ # Don't let $ signs confound expansion
+ gsub(/\$/, "$'`")
+
+ # Replace m5 opener with m4 closer
+ gsub(/<% */, "'")
+
+ # Replace m5 closer with m4 opener
+ gsub(/ *%>/, "`")
+ print
+}
+
+# Print an m4 closer and newline deleter as the last bytes
+END {
+ print "'dnl"
+}
diff --git a/man/man1/mi5.1df b/man/man1/mi5.1df
new file mode 100644
index 00000000..dd215d0c
--- /dev/null
+++ b/man/man1/mi5.1df
@@ -0,0 +1,63 @@
+.TH MI5 1df "June 2017" "Manual page for mi5"
+.SH NAME
+.B mi5
+\- m4 inverted preprocessor
+.SH SYNOPSIS
+.B mi5
+FILE > out.m4
+.br
+.B mi5
+FILE1 FILE2 > out.m4
+.br
+prog |
+.B mi5 > out.m4
+.br
+.SH DESCRIPTION
+.B mi5
+is a simple and crude m4 preprocessor to make using m4 slightly more bearable
+and predictable for its author, who wants badly to like m4 but doesn't. It's
+primarily intended for situations where the majority of a file is simple static
+text, and only a few simple macros need to be defined and expanded, which
+covers almost every usage case for the author. It's written to work with any
+POSIX m4.
+.P
+mi5 inverts m4's usual approach by approaching most of the file as if it were
+part of an m4 comment, with <% and %> as the delimiters to specify markers in
+which macro expansion should occur. This makes m4 work in a way reminiscent of
+templating libraries or languages like PHP.
+.P
+Macros can be expanded as blocks:
+.P
+ <%
+ define(`FOO', `bar')
+ define(`BAZ', include(`include/quux.inc')
+ ?>
+.P
+For this format, "dnl" macros to delete newlines for each declaration are
+inserted for you. Blank lines are skipped, and leading and trailing spaces are
+ignored. The above code therefore produces no actual output, as it only has two
+define calls.
+.P
+For inline expansion, the syntax is similar, but the behaviour slightly different:
+.P
+ The value of the FOO macro is <% FOO %>.
+.P
+Spaces immediately after the opening delimiter and before the closing delimiter
+are ignored, but spaces produced within the macro are preserved.
+.P
+Ideally, you do macro definition in an mi5 block at the top of your file, and
+very simple macro expansion in an mi5 inline.
+.SH CAVEATS
+Only very simple macro expansions work in inline calls at the moment. This can
+be fixed by the author tokenizing the line properly, which he'll do Real Soon
+Now (TM). Specifically, neither comment delimiters nor macro parameters work.
+The latter is because of a nasty corner-case in m4 where parameter expansions
+$1, $2, $*, etc are expanded
+.B even within comments,
+one of m4's darkest corners. The workaround is to do as much logic as you can
+in a block, defining your result as a single simple macros, and then expanding
+that inline.
+.SH SEE ALSO
+bp(1df), xargs(1)
+.SH AUTHOR
+Tom Ryder <tom@sanctum.geek.nz>