From bb9194d06a422efa24ea320c683054a19c8b0997 Mon Sep 17 00:00:00 2001 From: ville rantanen Date: Fri, 9 Jun 2017 10:51:28 +0300 Subject: [PATCH] gcd now has string similarity metrics --- files/gcd-findmatch.py | 49 +++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/files/gcd-findmatch.py b/files/gcd-findmatch.py index 0dcd77c..0676396 100755 --- a/files/gcd-findmatch.py +++ b/files/gcd-findmatch.py @@ -1,11 +1,15 @@ #!/usr/bin/env python import sys,os,re +import difflib as dl +# Define color codes Green="\033[32;1m" Red="\033[31;1m" Reset="\033[0m" +# Available shortcut keys key_list="1234567890qwertyuiop" + class getch: def get(self): fd = sys.stdin.fileno() @@ -16,13 +20,30 @@ class getch: finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) return ch + def printerr(s): sys.stderr.write(s+"\n") sys.stderr.flush() + +def colorize_matches(directories,repl): + return [repl.sub("%s\g<1>%s"%(Green,Reset),d) for d in directories] + +def search_close_match(directories, key): + """ Return a list of Components whose name closely matches key """ + match=[] + key=key.lower() + for name in directories: + s=dl.SequenceMatcher(None, name.lower(), key) + s_ratio=s.ratio() + if s_ratio > 0: + match.append(( s_ratio, name )) + match.sort(key=lambda x:x[0], reverse=True) + best_matches=[x[1] for x in match[0:10]] + return best_matches + # Print help if len(sys.argv)==1 or sys.argv[-1]=="-h": printerr("Guess cd: Find first match in folder, interactive if multiple matches\n Arguments: [dir/]pattern_to_match_folders") -if sys.argv[-1]=="-h": sys.exit(0) pattern=".".join(sys.argv[1:]) @@ -35,34 +56,46 @@ if pat_dir=="": if not os.path.exists(pat_dir): printerr("%s: %sNo such folder%s"%(pat_dir,Red,Reset)) sys.exit(1) + # list sub-folders in the folder -current_folders=[d for d in os.listdir(pat_dir) if os.path.isdir(d)] +current_folders=[d for d in os.listdir(pat_dir) if os.path.isdir(os.path.join(pat_dir,d))] current_folders=[d for d in current_folders if not d.startswith(".")] current_folders.sort() +# no sub-folders +if len(current_folders)==0: + printerr("There are no subfolders in %s"%(pat_dir,)) + sys.exit(0) + # find matches match_case=re.compile(".*"+pat_base+".*") repl_case=re.compile("("+pat_base+")") matching_folders=[d for d in current_folders if match_case.match(d)] -matches=[repl_case.sub("%s\g<1>%s"%(Green,Reset),d) for d in matching_folders] +matches=colorize_matches(matching_folders, repl_case) +#[repl_case.sub("%s\g<1>%s"%(Green,Reset),d) for d in matching_folders] # no matches, try case insensitive if len(matching_folders)==0: match_nocase=re.compile(".*"+pat_base+".*",re.I) repl_nocase=re.compile("("+pat_base+")",re.I) matching_folders=[d for d in current_folders if match_nocase.match(d)] - matches=[repl_nocase.sub("%s\g<1>%s"%(Green,Reset),d) for d in matching_folders] + matches=colorize_matches(matching_folders, repl_nocase) + #matches=[repl_nocase.sub("%s\g<1>%s"%(Green,Reset),d) for d in matching_folders] + +# No matches, try close match +if len(matching_folders)==0: + matching_folders=search_close_match(current_folders, pat_base) + matches=[d for d in matching_folders] + print("close") + print(matches) # One match, print and return if len(matching_folders)==1: printerr(matches[0]) print(os.path.join(pat_dir,matching_folders[0])) sys.exit(0) -# No matches -if len(matching_folders)==0: - printerr("%sno matches%s"%(Red,Reset)) - sys.exit(1) + # Many matches, ask the user for folder index for i,m in enumerate(matches[0:len(key_list)]): printerr(key_list[i]+": "+m)