Skip to content

Instantly share code, notes, and snippets.

@erenon
Created July 19, 2022 09:39
Show Gist options
  • Save erenon/a2cd3d04d2db5cb842954a1ee2c03a05 to your computer and use it in GitHub Desktop.
Save erenon/a2cd3d04d2db5cb842954a1ee2c03a05 to your computer and use it in GitHub Desktop.
Replace matching patterns at the specified locations
#!/bin/python
# Replace matching patterns at the specified locations
#
# On stdin it expects locations (as reported by the rustc compiler):
#
# --> path/to/file.rs:line:col
#
# Lines not matching this pattern are ignored:
marker = '^\s+--> (.+?):(\d+)'
# This program opens each file specified on the input.
# Lines not specified on the input are kept as-is.
# Each specified line is tested against the given regular expressions,
# and gets replaced by them as specified.
# Each entry in replacements is a tuple of (pattern, replacement).
# replacement can be a function, see python re::sub.
replacements = [
('bad', 'good'),
('spoiled (.+)', 'fresh \\1'),
]
# Only the first matching expression gets applied.
# The matching lines with replacement applied get written back to the input file.
# Non-matching lines are kept verbatim, with an optional warning:
warn_non_matching_line = True
# Files with multiple locations are supported.
import collections
import io
import re
import shutil
import sys
def main():
locations = collections.defaultdict(set)
markerex = re.compile(marker)
for fl in sys.stdin:
m = markerex.match(fl)
if m:
path, line = m[1], int(m[2])
locations[path].add(line)
for path, lines in locations.items():
with open(path) as f:
output = rewrite_file(f, lines)
with open(path, 'w') as f:
output.seek(0)
shutil.copyfileobj(output, f)
output.close()
def rewrite_file(f, lines):
output = io.StringIO()
for i,line in enumerate(f):
if i+1 in lines:
output.write(apply_replacements(line))
else:
output.write(line)
return output
def apply_replacements(s):
for pattern,repl in replacements:
new,matched = re.subn(pattern, repl, s)
if matched:
return new
if warn_non_matching_line:
print(f'NOMATCH {s.rstrip()}')
return s
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment