Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add more examples of line wrapping #95

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 120 additions & 4 deletions coding_style/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,16 @@ example_list:
+
[%collapsible]
====
Rationale:: long lines are difficult to read, many teams even ask for a line length limit around 120-150 characters.
Examples:: there are multiple ways to avoid long lines but the most generic one is to use the YAML folding sign (`>`):
Rationale:: Long lines are difficult to read, and many teams even ask for a line length limit around 120-150 characters.
ansible-lint defaults to 82 characters per line - see (https://ansible-lint.readthedocs.io/rules/yaml/[Ansible Lint YAML rules]).
You don't want to have to skip `yaml[line-length]` in your `.ansible-lint`, or litter your code with `# noqa yaml[line-length]`.
Examples:: there are multiple ways to avoid long lines but the most generic one is to use the YAML folding sign (`>-`):
+
.Usage of the YAML folding sign
[source,yaml]
----
- name: call a very long command line
command: >
command: >-
echo Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas mollis, ante in cursus congue, mauris orci tincidunt nulla,
non gravida tortor mi non nunc.
Expand All @@ -82,7 +84,10 @@ Examples:: there are multiple ways to avoid long lines but the most generic one
Duis a neque fermentum nulla imperdiet blandit.
----
+
TIP: use the sign `>-` if it is important that the last line return code doesn't become part of the string (e.g. when defining a string variable).
TIP: Always use the sign `>-` instead of `>` unless you are absolutely sure the trailing newline is not significant.
richm marked this conversation as resolved.
Show resolved Hide resolved
The sign `>` adds a newline character to the last line, effectively turning `non nunc.` at the end of the example string above into `"non nunc.\n"`, and `>-` doesn't add the newline character.
It is really easy to introduce an error by using `>` and silently add a newline to a variable, like a filename, which leads to strange, hard to decipher errors.
See below for "How To Wrap Lines"
====

* If the `when:` condition results in a line that is too long, and is an `and` expression, then break it into a list of conditions.
Expand Down Expand Up @@ -353,3 +358,114 @@ localhost | SUCCESS => {

```
====

== How To Wrap Lines

ansible-lint has a pretty short line length, which causes problems if you are trying to use good programming practices by having descriptive variable names, which usually end up being quite long.
Here are some examples of how to deal with line wrapping in common scenarios:

* Jinja expressions can be wrapped

Within the Jinja expression, whitespace and newline characters aren't significant, so take advantage of this to wrap lines into as readable a form as possible:

.Do this:
[source,yaml]
----
foo: "{{ a_very.long_variable.name |
somefilter('with', 'many', 'arguments') |
another_filter | list }}"
----

.Don't do this:
[source,yaml]
----
foo: "{{ a_very.long_variable.name | somefilter('with', 'many', 'arguments') | another_filter | list }}"
----

Remember, in a `when`, `that`, `failed_when`, or other such keywords, you can just write Jinja code - you do not need the `"{{ ... }}"`

.Do this:
[source,yaml]
----
when: a_very.long_variable.name |
somefilter('with', 'many', 'arguments') |
another_filter | list
----

* Start an expression with '{{' followed by newline

But what if the code is already indented a lot, and the variable I'm assigning to is already very long, and I can't put anything else on the line?
Just start the assignment on the next line:

.Do this:
[source,yaml]
----
foo: "{{
a_very.long_variable.name |
somefilter('with', 'many', 'arguments') |
another_filter | list }}"
----

You can do the same thing in a `when`, `that`, etc., with a backslash:

.Do this:
[source,yaml]
----
when: \
a_very.long_variable.name |
somefilter('with', 'many', 'arguments') |
another_filter | list | length > 0
----

* Use `vars` for locally scoped intermediate values

But what if my variable name is very long, and/or I use it in several places?
Use a `vars` in the task to assign a locally scoped variable with a short name, or pre-digest some of the work. This is very useful in a `block` where you have a value used in several places:

.Do this:
[source,yaml]
----
- name: Set some test variables
set_fact:
my_very_long_variable_1: "{{ __pre_digest | filter1 }}"
my_very_long_variable_2: "{{ __pre_digest | filter2 }}"
vars:
__pre_digest: "{{ a_very.long_variable.name | some_filter }}"
----

.Don't do this:
[source,yaml]
----
- name: Set some test variables
set_fact:
my_very_long_variable_1: "{{ a_very.long_variable.name | some_filter | filter1 }}"
my_very_long_variable_2: "{{ a_very.long_variable.name | some_filter | filter2 }}"
----

Notice that both assignments have `a_very.long_variable.name | some_filter` in common, so we can "pre-digest" that with a local variable.
You can use a `vars` on *any* task - even `include_role`, `include_tasks`, etc.
You can also use `vars` in a `block` to create variables used by multiple tasks in the `block` that are locally scoped to the `block`.

* Use backslash escapes in double quoted strings

But what if I have a very long string that I cannot use `>-` to wrap because I cannot have extra spaces in the value e.g. like a url value?
Use a backslash escape in a double quoted string:

.Do this:
[source,yaml]
----
uri:
url: "https://{{ my_very_long_value_for_hostname }}:\
{{ my_very_long_value_for_port }}\
{{ my_very_long_value_for_uri }}?\
{{ my_very_long_value_for_query }}"
----
YAML will concatenate the values with no spaces:
`https://myhost:myport/myuri?myquery`

.Don't do this:
[source,yaml]
----
uri:
url: "https://{{ my_very_long_value_for_hostname }}:{{ my_very_long_value_for_port }}{{ my_very_long_value_for_uri }}{{ my_very_long_value_for_query }}"
----