def print_field(t, field, matches=None, extras=None): if not extras: extras = {} pad_width = 12 fieldname = extras.get(field, ' ' + field.title()) line = TERM.clear_eol + '%s: %s' % (TERM.ljust( fieldname, pad_width, '.'), colorize_match(t, field.lower(), matches) or TERM.red('<none>')) print(line)
def print_field(t, field, matches=None, extras=None): if not extras: extras = {} pad_width = 12 fieldname = extras.get(field, ' ' + field.title()) line = TERM.clear_eol + '%s: %s' % ( TERM.ljust(fieldname, pad_width, '.'), colorize_match(t, field.lower(), matches) or TERM.red('<none>') ) print(line)
def print_field(t, field, matches=None, extras=None): if not extras: extras = {} pad_width = 12 fieldname = extras.get(field, " " + field.title()) line = TERM.clear_eol + "%s: %s" % ( TERM.ljust(fieldname, pad_width, "."), colorize_match(t, field.lower(), matches) or TERM.red("<none>"), ) print(line)
def check_ruler(ruler, t): """Build fields status dict obtained by applying ruler to transaction.""" extras = {} match, match_info = tags.match(ruler, t) for (key, val) in match_info.items(): if not val: extras[key] = TERM.red("%s %s" % (TERM.KO, key.title())) else: extras[key] = TERM.green("%s %s" % (TERM.OK, key.title())) if not match: extras["category"] = TERM.red("%s Category" % TERM.KO) else: extras["category"] = TERM.green("%s Category" % TERM.OK) return match, extras
def check_ruler(ruler, t): """Build fields status dict obtained by applying ruler to transaction. """ extras = {} match, match_info = tags.match(ruler, t) if not match: for (key, val) in match_info.iteritems(): if not val: extras[key] = TERM.red('✖ %s' % key.title()) extras['category'] = TERM.red('✖ Category') else: for field in ruler: extras[field] = TERM.green('✔ %s' % field.title()) extras['category'] = TERM.green('✔ Category') return match, extras
def check_ruler(ruler, t): """Build fields status dict obtained by applying ruler to transaction. """ extras = {} match, match_info = tags.match(ruler, t) for (key, val) in match_info.iteritems(): if not val: extras[key] = TERM.red(u'%s %s' % (TERM.KO, key.title())) else: extras[key] = TERM.green(u'%s %s' % (TERM.OK, key.title())) if not match: extras['category'] = TERM.red(u'%s Category' % TERM.KO) else: extras['category'] = TERM.green(u'%s Category' % TERM.OK) return match, extras
def query_guru_ruler(t): """Define rules on a combination of fields. All rules must match corresponding fields for the ruler to be valid. """ extras = sorted([k for (k, v) in t.items() if (v and not k.isdigit())]) matchable_fields = sorted( set([x for x in t if t[x] and not x.isdigit()]) - {"category", "number"}) guru_ruler = {} extras = {} field = True while field: # Enter field while True: # Update fields match indicators print(TERM.move_y(0)) print_transaction(t, short=False, extras=extras) field = quick_input("\nMatch on field", sugg=matchable_fields, clear=True).lower() regex = "*" in field field = field.strip("*") if not field or field in matchable_fields: break # Enter match while field: print(TERM.move_y(0)) print_transaction(t, short=False, extras=extras) existing_match = guru_ruler.get(field, "") ruler = quick_input( "\n%s match (%s)%s" % ( field.title(), "regex" if regex else "chars", " [%s]" % existing_match if existing_match else "", ), clear=True, ) if ruler.isspace(): # remove field rule from ruler extras.pop(field, None) guru_ruler.pop(field, None) elif ruler: guru_ruler[field] = r"%s" % ruler if regex else re.escape( ruler) match, extras = check_ruler(guru_ruler, t) if match: break return guru_ruler
def process_transaction(t, options): """Assign a category to a transaction. """ cat, ruler = t['category'], None extras = {} if not t['category']: # Grab category from json cache cat, ruler, _ = tags.find_tag_for(t) if cat: t['category'] = cat extras = {'category': '+ Category'} print('---\n' + TERM.clear_eol, end='') print_transaction(t, extras=extras) edit = False audit = options.get('audit', False) if t['category']: if audit: msg = "\nEdit '%s' category" % TERM.green(t['category']) edit = quick_input(msg, 'yN', vanish=True) == 'Y' if not edit: return t['category'], ruler # Query for category and overwrite category on screen if (not cat or edit) and not options.get('batch', False): t['category'] = query_cat(cat) extras = {'category': '✔ Category'} if not t['category'] else {} print(TERM.clear_last, end='') print_field(t, 'category', extras=extras) # Query ruler if category entered or edit if t['category']: ruler = query_ruler(t) return t['category'], ruler
def process_transaction(t, options): """Assign a category to a transaction. """ cat, ruler = t['category'], None extras = {} if not t['category']: # Grab category from json cache cat, ruler, _ = tags.find_tag_for(t) if cat: t['category'] = cat extras = {'category': '+ Category'} print('---\n' + TERM.clear_eol, end='') print_transaction(t, extras=extras) edit = options['force'] > 1 or (options['force'] and t['category'] not in tags.TAGS) audit = options['audit'] if t['category']: if audit: msg = "\nEdit '%s' category" % TERM.green(t['category']) edit = quick_input(msg, 'yN', vanish=True) == 'Y' if not edit: return t['category'], ruler # Query for category and overwrite category on screen if (not cat or edit) and not options['batch']: t['category'] = query_cat(cat) # Query ruler if category entered or edit if t['category']: ruler = query_ruler(t) extras = {'category': TERM.OK + ' Category'} if t['category'] else {} print(TERM.clear_last, end='') print_field(t, 'category', extras=extras) return t['category'], ruler
def process_transaction(t, options): """Assign a category to a transaction. """ cat, ruler = t["category"], None extras = {} if not t["category"]: # Grab category from json cache cat, ruler, _ = tags.find_tag_for(t) if cat: t["category"] = cat extras = {"category": "+ Category"} print("---\n" + TERM.clear_eol, end="") print_transaction(t, extras=extras) edit = options["force"] > 1 or (options["force"] and t["category"] not in tags.TAGS) audit = options["audit"] if t["category"]: if audit: msg = "\nEdit '%s' category" % TERM.green(t["category"]) edit = quick_input(msg, "yN", clear=True) == "Y" if not edit: return t["category"], ruler # Query for category and overwrite category on screen if (not cat or edit) and not options["batch"]: t["category"] = query_cat(cat) # Query ruler if category entered or edit if t["category"]: ruler = query_ruler(t) extras = {"category": TERM.OK + " Category"} if t["category"] else {} print(TERM.clear_last, end="") print_field(t, "category", extras=extras) return t["category"], ruler
def colorize_match(t, field, matches=None): field_val = t[field] if not field_val: return None match = matches.get(field, '') if matches else '' seqmatch = SequenceMatcher(None, field_val, match) a, b, size = seqmatch.find_longest_match(0, len(field_val), 0, len(match)) return (field_val[:a] + TERM.green(field_val[a:a + size]) + field_val[a + size:])
def query_ruler(t): """Prompt user to enter a valid matching ruler for transaction. First prompt is used to enter a basic ruler aka successive words to look for on payee line. This prompt can be skipped by pressing <Enter> to have access to guru ruler prompt, where ruler is a list of field/match to validate. """ with TERM.fullscreen(): extras = {'category': '? Category'} ok = False ruler = {} while True: print(TERM.move_y(0)) print_transaction(t, extras=extras) if ok: break ruler = query_basic_ruler(t, tags.unrulify(ruler)) or \ query_guru_ruler(t) ok, extras = check_ruler(ruler, t) return ruler
def query_ruler(t): """Prompt user to enter a valid matching ruler for transaction. First prompt is used to enter a basic ruler aka successive words to look for on payee line. This prompt can be skipped by pressing <Enter> to have access to guru ruler prompt, where ruler is a list of field/match to validate. """ with TERM.fullscreen(): extras = {} ok = False ruler = {} while True: print(TERM.move_y(0)) print_transaction(t, extras=extras) if ok: break ruler = query_basic_ruler(t, tags.unrulify(ruler)) or query_guru_ruler(t) ok, extras = check_ruler(ruler, t) return ruler
def query_guru_ruler(t): """Define rules on a combination of fields. All rules must match corresponding fields for the ruler to be valid. """ extras = sorted([k for (k, v) in t.iteritems() if ( v and not k.isdigit())]) set_completer(extras) guru_ruler = {} extras = {} field = True while field: # Enter field while True: # Update fields match indicators print(TERM.move_y(0)) print_transaction(t, short=False, extras=extras) field = quick_input('\nMatch on field', vanish=True).lower() regex = '*' in field field = field.strip('*') if not field or field in set(FIELDS_FULL.values()) - {'category'}: break # Enter match while field: print(TERM.move_y(0)) print_transaction(t, short=False, extras=extras) existing_match = guru_ruler.get(field, '') ruler = quick_input('\n%s match (%s)%s' % (field.title(), 'regex' if regex else 'chars', ' [%s]' % existing_match if existing_match else ''), vanish=True) if ruler.isspace(): # remove field rule from ruler extras.pop(field, None) guru_ruler.pop(field, None) # break elif ruler: guru_ruler[field] = r'%s' % ruler if regex else re.escape( ruler) match, extras = check_ruler(guru_ruler, t) if match: break return guru_ruler
def query_guru_ruler(t): """Define rules on a combination of fields. All rules must match corresponding fields for the ruler to be valid. """ extras = sorted([k for (k, v) in t.items() if (v and not k.isdigit())]) set_completer(extras) guru_ruler = {} extras = {} field = True while field: # Enter field while True: # Update fields match indicators print(TERM.move_y(0)) print_transaction(t, short=False, extras=extras) field = quick_input('\nMatch on field', vanish=True).lower() regex = '*' in field field = field.strip('*') if not field or field in set( config.FIELDS_FULL.values()) - {'category'}: break # Enter match while field: print(TERM.move_y(0)) print_transaction(t, short=False, extras=extras) existing_match = guru_ruler.get(field, '') ruler = quick_input( '\n%s match (%s)%s' % (field.title(), 'regex' if regex else 'chars', ' [%s]' % existing_match if existing_match else ''), vanish=True) if ruler.isspace(): # remove field rule from ruler extras.pop(field, None) guru_ruler.pop(field, None) elif ruler: guru_ruler[field] = r'%s' % ruler if regex else re.escape( ruler) match, extras = check_ruler(guru_ruler, t) if match: break return guru_ruler