import vim, re import heapq _escape = dict((c , "\\" + c) for c in ['^','$','.','{','}','(',')','[',']','\\','/','+']) def CtrlPPyMatch(): items = vim.eval('a:items') astr = vim.eval('a:str') lowAstr = astr.lower() limit = int(vim.eval('a:limit')) mmode = vim.eval('a:mmode') aregex = int(vim.eval('a:regex')) spath = vim.eval('a:ispath') crfile = vim.eval('a:crfile') if not vim.eval('exists("g:ctrlp_match_current_file")') and ispath and crfile: items.remove(crfile) rez = vim.eval('s:rez') regex = '' if aregex == 1: regex = astr else: # Escape all of the characters as necessary escaped = [_escape.get(c, c) for c in lowAstr] # If the string is longer that one character, append a mismatch # expression to each character (except the last). if len(lowAstr) > 1: mismatch = ["[^" + c + "]*" for c in escaped[:-1]] regex = ''.join([c for pair in zip(escaped[:-1], mismatch) for c in pair]) # Append the last character in the string to the regex regex += escaped[-1] # because this IGNORECASE flag is extremely expensive we are converting everything to lower case # see https://github.com/FelikZ/ctrlp-py-matcher/issues/29 regex = regex.lower() res = [] prog = re.compile(regex) def filename_score(line): # get filename via reverse find to improve performance slashPos = line.rfind('/') if slashPos != -1: line = line[slashPos + 1:] lineLower = line.lower() result = prog.search(lineLower) if result: score = result.end() - result.start() + 1 score = score + ( len(lineLower) + 1 ) / 100.0 score = score + ( len(line) + 1 ) / 1000.0 return 1000.0 / score return 0 def path_score(line): lineLower = line.lower() result = prog.search(lineLower) if result: score = result.end() - result.start() + 1 score = score + ( len(lineLower) + 1 ) / 100.0 return 1000.0 / score return 0 if mmode == 'filename-only': res = [(filename_score(line), line) for line in items] elif mmode == 'first-non-tab': res = [(path_score(line.split('\t')[0]), line) for line in items] elif mmode == 'until-last-tab': res = [(path_score(line.rsplit('\t')[0]), line) for line in items] else: res = [(path_score(line), line) for line in items] rez.extend([line for score, line in heapq.nlargest(limit, res) if score != 0]) # Use double quoted vim strings and escape \ vimrez = ['"' + line.replace('\\', '\\\\').replace('"', '\\"') + '"' for line in rez] vim.command("let s:regex = '%s'" % regex) vim.command('let s:rez = [%s]' % ','.join(vimrez))