]> ToastFreeware Gitweb - philipp/winterrodeln/wrpylib.git/blob - wrpylib/cli_tools.py
VAO is missing important streets in Switzerland.
[philipp/winterrodeln/wrpylib.git] / wrpylib / cli_tools.py
1 from difflib import SequenceMatcher
2 from enum import Enum, auto
3 from typing import Optional
4
5 from termcolor import cprint  # python3-termcolor
6
7
8 def _format_range_unified(start: int, stop: int) -> str:
9     """Copied from difflib._format_range_unified"""
10     beginning = start + 1  # lines start numbering with one
11     length = stop - start
12     if length == 1:
13         return str(beginning)
14     if not length:
15         beginning -= 1  # empty ranges begin at line just before the range
16     return f'{beginning},{length}'
17
18
19 def unified_diff(a: str, b: str, context: int = 3):
20     a_lines = a.splitlines()
21     b_lines = b.splitlines()
22     for group in SequenceMatcher(None, a_lines, b_lines).get_grouped_opcodes(context):
23         first, last = group[0], group[-1]
24         file1_range = _format_range_unified(first[1], last[2])
25         file2_range = _format_range_unified(first[3], last[4])
26         cprint(f'@@ -{file1_range} +{file2_range} @@', 'magenta')
27
28         for tag, i1, i2, j1, j2 in group:
29             if tag == 'equal':
30                 for line in a_lines[i1:i2]:
31                     print(f'  {line}')
32                 continue
33             if tag in {'replace', 'delete'}:
34                 for line in a_lines[i1:i2]:
35                     cprint(f'- {line}', 'red')
36             if tag in {'replace', 'insert'}:
37                 for line in b_lines[j1:j2]:
38                     cprint(f'+ {line}', 'green')
39
40
41 class Choice(Enum):
42     yes = auto()
43     no = auto()
44     quit = auto()
45
46
47 def input_yes_no_quit(text: str, default: Optional[Choice]) -> Choice:
48     while True:
49         result = input(text)
50         if result in ['Y', 'y', 'yes']:
51             return Choice.yes
52         elif result in ['N', 'n', 'no']:
53             return Choice.no
54         elif result in ['Q', 'q', 'quit']:
55             return Choice.quit
56         elif result == '' and default is not None:
57             return default
58         cprint(f'Unrecognized input: "{result}"', 'red')