#!/usr/bin/env python3 """Set keys in the [ddraw] section of a cnc-ddraw ddraw.ini. Usage: patch-ddraw-ini.py [--check] DDRAW_INI KEY=VALUE [KEY=VALUE ...] Only the global [ddraw] section is touched; the hundreds of per-game preset sections further down the file are left alone. CRLF line endings are preserved, because cnc-ddraw writes the file back out as a Windows INI. Exit status: 0 if the file already matches (or was updated), 1 under --check if it does not match. """ import re import sys def main(argv): check = False if argv and argv[0] == '--check': check, argv = True, argv[1:] if len(argv) < 2: sys.exit(__doc__) path, assignments = argv[0], argv[1:] wanted = {} for a in assignments: if '=' not in a: sys.exit('not a KEY=VALUE pair: %s' % a) k, v = a.split('=', 1) wanted[k.strip().lower()] = v with open(path, 'rb') as fh: raw = fh.read().decode('utf-8', 'surrogateescape') newline = '\r\n' if '\r\n' in raw else '\n' lines = raw.split(newline) out, in_ddraw, pending, changes = [], False, dict(wanted), [] for line in lines: stripped = line.strip() if stripped.startswith('['): # leaving [ddraw]: append any keys the section never had if in_ddraw and pending: for k, v in pending.items(): out.append('%s=%s' % (k, v)) changes.append('added %s=%s' % (k, v)) pending = {} in_ddraw = stripped.lower() == '[ddraw]' elif in_ddraw: m = re.match(r'^(\s*)([A-Za-z_][A-Za-z0-9_]*)(\s*)=(.*)$', line) if m and m.group(2).lower() in pending: key = m.group(2).lower() want = pending.pop(key) if m.group(4) != want: changes.append('%s=%s -> %s=%s' % (m.group(2), m.group(4), m.group(2), want)) line = '%s=%s' % (m.group(2), want) out.append(line) if in_ddraw and pending: for k, v in pending.items(): out.append('%s=%s' % (k, v)) changes.append('added %s=%s' % (k, v)) if not changes: print('already set: %s' % ', '.join('%s=%s' % kv for kv in wanted.items())) return 0 if check: for c in changes: print('would change: %s' % c) return 1 with open(path, 'wb') as fh: fh.write(newline.join(out).encode('utf-8', 'surrogateescape')) for c in changes: print(c) return 0 if __name__ == '__main__': sys.exit(main(sys.argv[1:]))