diff options
author | Adrián Oliva <adrian.oliva@cimat.mx> | 2023-05-08 21:31:09 -0600 |
---|---|---|
committer | Adrián Oliva <adrian.oliva@cimat.mx> | 2023-05-08 21:31:09 -0600 |
commit | ca65b3836eaa5b026b3f13afdd7ad3b8b192e9a4 (patch) | |
tree | 86e55759380d38c92b47f124bd051c3ecfccd089 /utils/acc_regex.py | |
parent | 269eee248d24acbb12f13ab519dfbe1c881d3bb8 (diff) | |
download | Ledger.py-ca65b3836eaa5b026b3f13afdd7ad3b8b192e9a4.tar.gz Ledger.py-ca65b3836eaa5b026b3f13afdd7ad3b8b192e9a4.zip |
First attempt at sorting accounts.
I DID IT!! I'm really happy with the result. :')
Diffstat (limited to '')
-rw-r--r-- | utils/acc_regex.py | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/utils/acc_regex.py b/utils/acc_regex.py new file mode 100644 index 0000000..1c85def --- /dev/null +++ b/utils/acc_regex.py @@ -0,0 +1,105 @@ +from typing import List +from utils.read_file import entry +from utils.register import complete_prices +import re + +RE_NOT = r'not ((?:[^()\s]+)|(?:\(.+\)))' +RE_AND = r'((?:[^()\s]+)|(?:\(.+\))) and ((?:[^()\s]+)|(?:\(.+\)))' +RE_OR = r'((?:[^()\s]+)|(?:\(.+\))) or ((?:[^()\s]+)|(?:\(.+\)))' + + +def clean_pattern(pattern: str): + pattern = pattern.strip() + + if pattern[0] == '(' and pattern[-1] == ')': + pattern = pattern[1:-1] + + return pattern + + +def create_ors(string: str): + splitted = string.split() + result = '' + + for left, right in zip(splitted[:-1], splitted[1:]): + if left not in ['not', 'and', 'or'] and right not in ['and', 'or']: + result += f'{left} or ' + else: + result += f'{left} ' + + result += splitted[-1] + + return result + + +def find_logic_patt(pattern: str): + # First search for the pattern "not {text}" + patt = re.findall(RE_NOT, pattern) + if patt: + return ('not', patt[0]) + + # If there wasn't a "not" pattern, try searching for "{text 1} or {text 2}" + patt = re.findall(RE_OR, pattern) + if patt: + return ('or', patt[0]) + + # Lastly, try searching for "{text 1} and {text 2}" pattern. + patt = re.findall(RE_AND, pattern) + if patt: + return ('and', patt[0]) + + # If there wasn't any pattern, return None. + return (None, None) + + +def re_ledger(pattern: str, account_name: str): + pattern = clean_pattern(pattern) + + if ' ' not in pattern: + if pattern == '{False}': + return False + elif pattern == '{True}': + return True + elif re.search(pattern, account_name) is None: + return False + else: + return True + + pattern = create_ors(pattern) + key, patt = find_logic_patt(pattern) + + while key is not None: + if key == 'not': + meets_criteria = not re_ledger(patt, account_name) + pattern = pattern.replace(f'not {patt}', f'{{{meets_criteria}}}') + + elif key == 'or': + meets_criteria = re_ledger(patt[0], account_name) or re_ledger(patt[1], account_name) + pattern = pattern.replace(f'{patt[0]} or {patt[1]}', f'{{{meets_criteria}}}') + + elif key == 'and': + meets_criteria = re_ledger(patt[0], account_name) and re_ledger(patt[1], account_name) + pattern = pattern.replace(f'{patt[0]} and {patt[1]}', f'{{{meets_criteria}}}') + + + key, patt = find_logic_patt(pattern) + + return re_ledger(pattern, account_name) + + +def filter_accounts(arguments: List[str], my_entries: List[entry]): + pattern = ' '.join(arguments) + result = [] + + for ent in my_entries: + complete_prices(ent) + + for trans in ent.transactions: + if re_ledger(pattern, trans[0]): + result.append(entry( + date=ent.date.strftime('%Y-%m-%d'), + comment=ent.comment, + transactions=[[trans[0], str(trans[1])]] + )) + + return result |