I have the definition of a variable, it's name and an associated comment in a YAML file and am trying to use Jinja2 to create an appropriate target file; in this case a proprietary config file
...
- comment: >
This is a comment which will almost certainly end up longer than standard eighty characters or at least on the occasion on which it does.
name: my_useful_variable
value: /a/long/example/path/to/my/file.txt
I would like this text to be rendered as follows:
# This is a comment which will almost certainly end up
# longer than standard eighty characters or at least on
# the occasion on which it does.
my_useful_variable = "/a/long/example/path/to/my/file.txt"
Does Jinja2 have any way of wrapping text so that the long comment line is limited in length and split over however many lines is necessary?
So far I have:
# {{item.comment}}
{{item.name}} = "{{item.value}}"
But this of course does not deal with the length of the comment.
Solution
Following on from the answer provided by @blhsing below, I came up with the following macro, which works fine for basic variables and simple lists (i.e. not dictionaries or more complex hierarchical data structures:
{% macro set_params(param_list, ind=4, wid=80) -%}
{% for item in param_list %}
{% if item.comment is defined %}{{item.comment|wordwrap(wid - ind - 2)|replace('', ' ' * ind +'# ', 1)|replace('\n', '\n' + ' ' * ind + '# ')}}
{% endif %}
{% if item.value is iterable and item.value is not string %}{{item.name|indent(ind, True)}} = [ {% for item_2 in item.value %}{{item_2}}{{ ", " if not loop.last else " " }}{% endfor %}{% else %}{{item.name|indent(ind, True)}} = {{item.value}}{% endif %}
{% endfor %}
{%- endmacro %}
To use this, simply pass a list of items similar to the spec given at the top together with the indentation and the page width.
A bit of explanation:
name = value
or name = [ value1, value2, value3 ]
Of course, it is not fool-proof but it meets my basic requirements.
You can prepend the given string with a newline character, then use the wordwrap
filter to wrap the text into multiple lines first, and use the replace
filter to replace newline characters with newline plus '# '
:
{{ ('\n' ~ item.comment) | wordwrap(78) | replace('\n', '\n# ') }}
The above assumes you want each line to be no more than 80 characters. Change 78
to your desired line width minus 2 to leave room for '# '
.