Rules on using !include in configuration files

It seems that I can only use !include after a colon and it needs to complete that context. It cannot be a partial snippet. It’s almost like the parser is fed the !include directly rather than inserting the external file and then parsing the end result.

I have a bunch of input_text entries like:

  name: "Duration: Vanity 2 Motion (HH:MM:SS)"
  icon: mdi:motion-sensor-off
  pattern: "[0-9]{2}:[0-9]{2}:[0-9]{2}"

The last 2 lines are always the same. I could simplify a tiny bit with 2 includes:

  name: "Duration: Vanity 2 Motion (HH:MM:SS)"
  icon: !include foo.yaml
  pattern: !include bar.yaml

But what I really want is something like:

  name: "Duration: Vanity 2 Motion (HH:MM:SS)"
!include foobar.yaml

Is there some clever way to accomplish my goal?

There are obviously other ways to eliminate the redundancy. I could write a script to generate the config or just rely on copy/search/replace.

Use anchors: Misc tricks · thomasloven/hass-config Wiki · GitHub

So this is a yaml parser thing. HA is oblivious. You can’t just insert new key/value pairs that HA doesn’t already expect. Instead, you’ll either need to create dummy objects to define your anchors or annotate as you go. Here’s what I came up with:

bath1_vanity_md042g_manual: {name: "Duration: Vanity 1 Manual (HH:MM:SS)", <<: &manual {icon: mdi:timer-sand, pattern: &timer_regex "[0-9]{2}:[0-9]{2}:[0-9]{2}"}}
bath1_vanity_md042g_motion: {name: "Duration: Vanity 1 Motion (HH:MM:SS)", <<: &motion {icon: mdi:motion-sensor-off, pattern: *timer_regex}}

bath2_shower_md064g_manual: {name: "Duration: Shower 2 Manual (HH:MM:SS)", <<: *manual}
bath2_shower_md064g_motion: {name: "Duration: Shower 2 Motion (HH:MM:SS)", <<: *motion}

bath2_toilet_md065g_manual: {name: "Duration: Toilet 2 Manual (HH:MM:SS)", <<: *manual}
bath2_toilet_md065g_motion: {name: "Duration: Toilet 2 Motion (HH:MM:SS)", <<: *motion}


I’ve since used this technique on multiple config and automation files. Note that the HA ‘visual editor’ will expand all your anchors. It’s best to make these files external (i.e. read-only).

There are different kind of include parameters.
Open this video and jump to around 11:00.

I watched the entire video. Maybe some good ideas for the future.

I was surprised that he failed to mention dictionary format with { }, since that’s what I ended up using.

As I mentioned in the OP, every example places the include after a colon. There are different kinds of includes, but none allow arbitrary placement.

I’ve since learned that some platforms (e.g. docker) intentionally ignore properties with a certain prefix (e.g. x-) to foster yaml anchor usage.

Apparently, nobody wants to code a generic include-- probably because of complexity and memory considerations.

I think it might be included in livelace_gen, but I am not using it, because it require YAML_only mode and I like to use some GUI now and then.

Why using this “{ … }” notation?

Yaml-anchors may work as was said already:

  name: some_name_1
  icon: icon_1
  pattern: &ref_pattern some_pattern

  name: some_name_2
  <<: &ref_package
    icon: icon_2
    pattern: *ref_pattern

  name: some_name_3
  <<: *ref_package

And this is nice.

The { } is more compact and no indentation worries. The anchors will work either way.

I realized later that my inline yaml may not format as nicely on the forum-- especially mobile. On a monitor, the forum wastes 1/3 of the screen width. The line length is not a problem for local editing.

The task from the 1st post can be easily solved:

  test_text_pattern_1: !include /config/shared/helpers/input_text_hh_mm_ss.yaml
  test_text_pattern_2: !include /config/shared/helpers/input_text_hh_mm_ss.yaml
    name: abc text
    name: xyz text


This method may be used in cases when similar “input_text” entities are initially defined in different packages.
Ofc, if they are defined in the same package - yaml-anchors are sufficient.