subprompt/subprompt

117 lines
2.9 KiB
Python
Executable File

#!/bin/python3.9
import re
import hashlib
import os
from sys import argv, stderr
from os.path import basename
from colorama import init, Fore, Back, Style
init(autoreset=True)
if len(argv) <= 3:
print('usage: {0} [REGEX] [SUB] [FILES...]'.format(basename(__file__)), file=stderr)
exit(1)
regex = argv[1]
sub = argv[2]
files = argv[3:]
replace_all = False
quit_loop = False
sub_count = 0
match_count = 0
def prompt(matchobj, line, line_n, file):
global replace_all
global quit_loop
global sub_count
global match_count
if quit_loop:
return matchobj.group(0)
replaced_match = re.sub(regex, sub, matchobj.group(0))
if replaced_match == matchobj.group(0):
return replaced_match
match_count += 1
if replace_all:
sub_count += 1
return replaced_match
highlighted = line.replace(matchobj.group(0),
Back.RED + matchobj.group(0) + Back.RESET)
replaced = line.replace(matchobj.group(0),
Back.YELLOW + Fore.BLACK + replaced_match + Back.RESET + Fore.RESET)
print(Fore.GREEN + Style.BRIGHT + file)
print(Fore.YELLOW + Style.BRIGHT + str(line_n), end='')
print(':{0}'.format(highlighted))
print('Becomes the following:')
print(Fore.YELLOW + Style.BRIGHT + str(line_n), end='')
print(':{0}'.format(replaced))
print()
while True:
answer = input('Confirm the change? [Y/n/a/q] ').lower()
if answer in ['y', 'yes', '']:
sub_count += 1
print()
return replaced_match
elif answer in ['n', 'no']:
print()
return matchobj.group(0)
elif answer in ['a', 'all']:
sub_count += 1
replace_all = True
return replaced_match
elif answer in ['q', 'quit']:
quit_loop = True
return matchobj.group(0)
print('Invalid answer. Please type again.')
def filter_file(fname):
with open(fname, 'r') as file:
contents = file.read()
lines = contents.splitlines()
lines = [
re.sub(regex,
lambda matchobj: prompt(matchobj, line, line_n, fname),
line)
for (line_n, line) in enumerate(lines)
]
new_contents = '\n'.join(lines)
hash_old = hashlib.md5(contents.encode())
hash_new = hashlib.md5(new_contents.encode())
if hash_old.digest() != hash_new.digest():
with open(fname, 'w') as file:
file.write(new_contents)
file.write('\n')
for file in files:
if os.access(file, os.W_OK):
filter_file(file)
if quit_loop:
break
if match_count == 0:
print(Fore.RED + Style.BRIGHT + 'No matches found.')
else:
print(Fore.YELLOW + Style.BRIGHT + 'Made {0} of {1} substitutions.'.
format(Fore.WHITE + str(sub_count) + Fore.YELLOW,
Fore.WHITE + str(match_count) + Fore.YELLOW))