I want to include a file and have all the lines indented. I want it to be a code block in a markdown document.
Basically I want something like this:
text
include(somefile)
text
to have this output:
text
content
from
somefile
text
I looked through the manual and found patsubst
. I also found this question and answer: How to indent a block of text in an m4 macro
That works for files containing no commas:
$ cat textnocomma
some text.
with sentences.
and no commas.
$ cat patsubstincludenocomma
text
patsubst(include(textnocomma), `^', ` ')
text
$ m4 patsubstincludenocomma
text
some text.
with sentences.
and no commas.
text
But when I include
a file that contains a comma:
$ cat textcomma
some text.
with sentences.
and, commas.
$ cat patsubstincludecomma
text
patsubst(include(textcomma), `^', ` ')
text
$ m4 patsubstincludecomma
text
m4:patsubstincludecommanoquote:3: Warning: excess arguments to builtin `patsubst' ignored
some text.
with sentences.
and
text
The problem seems to be the naive way m4 does macro expansion. The comma from the included text is interpreted as syntax of the patsubst
macro. The solution (should be) simple: quote the included text.
But if I quote the include
then just the first line is indented:
$ cat patsubstincludecommaquote
text
patsubst(`include(textcomma)', `^', ` ')
text
$ m4 patsubstincludecommaquote
text
some text.
with sentences.
and, commas.
text
I have tried different combinations of quoting and literal newlines instead of regex newlines. But all I got so far is either the excess arguments
error message or just the first line indented.
How can I include text with comma, and maybe other m4 syntax, and have it indented in m4?
i have done some research and can conclude that quoting the include
makes patsubst
no longer recognize ^
(beginning of line) in the text apart from the first line. at least on my system.
$ m4 --version
m4 (GNU M4) 1.4.18
...
observe:
$ cat textnocomma
some text.
with sentences.
and no commas.
$ cat includenocomma
foo
patsubst(include(textnocomma), `^', ` ')
bar
patsubst(`include(textnocomma)', `^', ` ')
baz
$ m4 includenocomma
foo
some text.
with sentences.
and no commas.
bar
some text.
with sentences.
and no commas.
baz
this also happens when defining the text as "string literals" instead of include
:
$ cat definestringliterals
define(`sometext', `first line
second line
third line')dnl
foo
patsubst(sometext, `^', ` ')
bar
patsubst(`sometext', `^', ` ')
baz
$ m4 definestringliterals
foo
first line
second line
third line
bar
first line
second line
third line
baz
here is a question and answer that supports this observation: How to match newlines in GNU M4 _properly_
strangely this does not happen if putting the string literals directly inside patsubst
:
$ cat patsubststringliterals
foo
patsubst(first line
second line
third line, `^', ` ')
bar
patsubst(`first line
second line
third line', `^', ` ')
baz
$ m4 patsubststringliterals
foo
first line
second line
third line
bar
first line
second line
third line
baz
using parens to "quote" the text does not have this problem. but now my text has parens around it:
$ cat textcomma
some text.
with sentences.
and, commas.
$ cat includecomma
foo
patsubst(include(textcomma), `^', ` ')
bar
patsubst(`include(textcomma)', `^', ` ')
baz
patsubst((include(textcomma)), `^', ` ')
qux
$ m4 includecomma
foo
m4:includecomma:2: Warning: excess arguments to builtin `patsubst' ignored
some text.
with sentences.
and
bar
some text.
with sentences.
and, commas.
baz
(some text.
with sentences.
and, commas.
)
qux
so i guess this is a bug. if quoting include
then patsubst
will no longer recognize ^
apart from the first line. But quoting include
is necessary to prevent a comma in the text to be interpreted as syntax.
Why don't you use external commands?
esyscmd(`sed "s,^, ," textcomma')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With