module

Krikri::PluginHelpers::LineEditor

LineEditor - pure line-matching/insertion logic for the lineinfile plugin, factored out so it can be unit tested without touching the filesystem or going through the plugin's stdin/stdout protocol.

Class methods

ensure_present(lines : Array(String), line : String, regexp : String | Nil, backrefs : Bool, insertafter : String | Nil, insertbefore : String | Nil, firstmatch : Bool = false, search_string : String | Nil = nil) : Tuple(Array(String), Bool)

state: present - ensure line (or a regexp-matched line, optionally rewritten via backrefs) exists, inserting at insertafter/insertbefore if it's missing. Returns {new_lines, changed}.

search_string is the literal-substring alternative to regexp (real Ansible's own argument_spec marks them mutually exclusive, so this only ever sees one of the two). firstmatch switches the replacement/insertion target from real Ansible's default LAST match to the FIRST (live-verified against ansible-core 2.19.4: both the regexp/search_string replacement target and the insertafter/insertbefore anchor honor it, state=absent does not - there it removes every matching line regardless).

Source
insertion_index(lines : Array(String), insertafter : String | Nil, insertbefore : String | Nil, firstmatch : Bool = false) : Int32

Shared with BlockEditor, so this is public rather than private.

Real Ansible anchors the insertion at the LAST line matching the insertafter/insertbefore pattern (its own loop keeps scanning and only stops early under firstmatch), not the first - live-verified against ansible-core 2.19.4 for both lineinfile and blockinfile (blockinfile's marker-placement loop also has no break). The previous first-match-always behavior diverged on any file where the anchor pattern occurs more than once.

Source
lines_equal?(a : String, b : String) : Bool
Source
match_index(lines : Array(String), pattern : String, firstmatch : Bool, literal : Bool = false) : Int32 | Nil

Position of the line matching pattern: the LAST match by default (real Ansible's lineinfile/blockinfile both scan the whole file without breaking), or the FIRST when firstmatch is set. With literal: true the pattern is a plain substring to CONTAIN (real Ansible's search_string), not a regex.

Source
matches_regexp?(line : String, pattern : String | Nil) : Bool
Source
remove_matching(lines : Array(String), line : String | Nil, regexp : String | Nil, search_string : String | Nil = nil) : Tuple(Array(String), Bool)

state: absent - drop every line matching regexp, containing search_string (literal substring - real Ansible's own matcher for state=absent), or - failing both - an exact match against line. firstmatch does NOT apply here: real Ansible removes ALL matching lines regardless (live-verified against ansible-core 2.19.4). Returns {new_lines, changed}.

Source