-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathindent-replace
executable file
·62 lines (52 loc) · 2.02 KB
/
indent-replace
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/usr/bin/env python
import os, sys, re, base64, pathlib as pl
def indent_replace(p_list, to_tabs, n, verbose):
p_tmp_rm, pre_src, pre_dst = None, ' '*n, '\t'
if not to_tabs: pre_src, pre_dst = pre_dst, pre_src
pre_sub = re.compile(fr'^({pre_src})+')
try:
for p in p_list:
src_old, src_new = p.read_text(), list()
for line in src_old.split('\n'):
if m := pre_sub.search(line):
line = m.group().replace(pre_src, pre_dst) + line[m.end():]
src_new.append(line)
src_new = '\n'.join(src_new)
if src_old == src_new: continue
if verbose: print(p)
p_tmp = p.parent / (p.name + '.tmp')
while p_tmp.exists():
suffix = base64.urlsafe_b64encode(os.urandom(3)).decode()
p_tmp = p.parent / (p.name + f'.tmp.{suffix}')
p_tmp_rm = p_tmp
p_tmp.touch(p.stat().st_mode)
p_tmp.write_text(src_new)
p_tmp.rename(p)
p_tmp_rm = None
finally:
if p_tmp_rm: p_tmp_rm.unlink(missing_ok=True)
def main(args=None):
import argparse
parser = argparse.ArgumentParser(
description='Replace tabs with spaces in all files and back.')
parser.add_argument('files', nargs='+', help='File(s) to process.')
parser.add_argument('-t', '--tabs',
action='store_true', help='Replace spaces with tabs (default).')
parser.add_argument('-s', '--spaces',
action='store_true', help='Replace tabs with spaces.')
parser.add_argument('-n', '--space-count',
type=int, metavar='n', default=4,
help='Number of spaces to replace in either direction (default: %(default)s)')
parser.add_argument('-q', '--quiet',
action='store_true', help='Do not print processed filenames to stdout.')
opts = parser.parse_args(sys.argv[1:] if args is None else args)
if opts.tabs and opts.spaces:
parser.error( 'Both -t/--tabs or -s/--spaces'
' options cannot be used at the same time' )
p_list = list(map(pl.Path, opts.files))
for p in p_list:
if not p.is_file(): parser.error(f'Not a file: {p}')
indent_replace( p_list,
to_tabs=not opts.spaces,
n=opts.space_count, verbose=not opts.quiet )
if __name__ == '__main__': sys.exit(main())