Skip to content

Add match: / match_first: kwargs to file.append and new file.before command#132

Draft
schneems wants to merge 6 commits into
mainfrom
schneems/match-kwarg-file-before
Draft

Add match: / match_first: kwargs to file.append and new file.before command#132
schneems wants to merge 6 commits into
mainfrom
schneems/match-kwarg-file-before

Conversation

@schneems

@schneems schneems commented Jun 5, 2026

Copy link
Copy Markdown
Member

Appending content at a specific line number (file.append Gemfile#5) breaks
when the target file changes unexpectedly -- the line number drifts and content
lands in the wrong place. This happened in practice with the Node.js Getting
Started tutorial (see heroku/nodejs-getting-started#403).

This adds match: and match_first: kwargs so the insertion point is located
by matching a placeholder comment or code pattern instead of a line number:

:::>> file.before("index.js", match: "// Cleanup after server close")
pool.end().then(() => { console.log('PG pool closed') })

:::>> file.append("Gemfile", match: "gem 'rails'")
gem 'pg'

match: raises if the target string is not unique in the file (safety check).
match_first: uses the first occurrence when duplicates are expected.

Also adds a new file.before command with the same kwargs.

Closes #121

@schneems schneems force-pushed the schneems/match-kwarg-file-before branch 3 times, most recently from 1096f8a to 2b27d51 Compare June 5, 2026 21:38
schneems added 3 commits June 5, 2026 16:40
Locating the insertion point by line number (file.append Gemfile#5) is
brittle -- the number drifts when the target file changes. These kwargs
locate the line by matching its content instead:

    :::>> file.append("Gemfile", match: "gem 'rails'")
    gem 'pg'

match: raises if the target is not unique (safety check).
match_first: uses the first occurrence when duplicates are expected.
New command that inserts content before a matched line. Supports the
same match: / match_first: kwargs as file.append:

    :::>> file.before("index.js", match: "// Cleanup after server close")
    pool.end().then(() => { console.log('PG pool closed') })
@schneems schneems force-pushed the schneems/match-kwarg-file-before branch from 2b27d51 to d907684 Compare June 5, 2026 21:40
schneems added 3 commits June 5, 2026 17:19
Pure class methods with explicit arguments -- no ivars, no implicit
state. resolve_match_line returns a 1-indexed line number from a match
string. insert_contents_at_line handles insertion at any line including
after the last line.
Both file.append and file.before now share one Args class that handles
filename#line_number parsing, match:/match_first: validation, and
mutual exclusivity checks. file.before now supports bare (prepend to
head) and #line_number modes in addition to match.
Both AppendRunner and BeforeRunner now delegate to
FileUtil.resolve_match_line and FileUtil.insert_contents_at_line
instead of duplicating match resolution and insertion logic.

Fixes file.append + match: to insert AFTER the matched line (was
inserting before, same as file.before). "append" now means append.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Idea: file.before command with match: kwarg

1 participant