Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

include file and indent every line

Tags:

m4

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?

like image 768
Lesmana Avatar asked Feb 21 '19 02:02

Lesmana


2 Answers

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.

like image 177
Lesmana Avatar answered Nov 01 '22 21:11

Lesmana


Why don't you use external commands?

esyscmd(`sed "s,^,    ," textcomma')
like image 3
uzsolt Avatar answered Nov 01 '22 20:11

uzsolt