finish tab completion

pull/241/head
William Ting 11 years ago
parent 71861c4402
commit 0422d23a86

@ -45,12 +45,16 @@ from data import save
from utils import decode from utils import decode
from utils import encode_local from utils import encode_local
from utils import first from utils import first
from utils import get_needle_and_index
from utils import get_pwd from utils import get_pwd
from utils import has_uppercase from utils import has_uppercase
from utils import is_osx from utils import is_osx
from utils import is_tab_entry
from utils import is_tab_partial_match
from utils import last from utils import last
from utils import print_entry from utils import print_entry
from utils import print_tab_completion_menu from utils import print_tab_menu
from utils import sanitize
from utils import second from utils import second
from utils import surround_quotes from utils import surround_quotes
from utils import take from utils import take
@ -58,11 +62,11 @@ from utils import take
VERSION = 'release-v21.8.0' VERSION = 'release-v21.8.0'
FUZZY_MATCH_THRESHOLD = 0.6 FUZZY_MATCH_THRESHOLD = 0.6
TAB_COMPLETION_COUNT = 9 TAB_COMPLETION_COUNT = 9
TAB_SEPARATOR = '__'
def set_defaults(): def set_defaults():
config = {} config = {}
config['tab_menu_separator'] = '__'
if is_osx(): if is_osx():
data_home = os.path.join( data_home = os.path.join(
@ -170,8 +174,6 @@ def find_matches(entries, needles):
if not needles: if not needles:
return first(data).path return first(data).path
sanitize = lambda x: decode(x).rstrip(os.sep)
needles = map(sanitize, needles)
ignore_case = detect_smartcase(needles) ignore_case = detect_smartcase(needles)
exists = lambda entry: os.path.exists(entry.path) exists = lambda entry: os.path.exists(entry.path)
@ -318,11 +320,11 @@ def main():
if args.add: if args.add:
save(config, first(add_path(load(config), args.add))) save(config, first(add_path(load(config), args.add)))
elif args.complete: elif args.complete:
print_tab_completion_menu( needle = first(sanitize(args.directory))
separator=config['tab_menu_separator'], tab_entries = take(
entries=take( TAB_COMPLETION_COUNT,
TAB_COMPLETION_COUNT, find_matches(entriefy(load(config)), needle))
find_matches(entriefy(load(config)), args.directory))) print_tab_menu(needle, tab_entries, TAB_SEPARATOR)
elif args.decrease: elif args.decrease:
data, entry = decrease_path(load(config), get_pwd(), args.decrease) data, entry = decrease_path(load(config), get_pwd(), args.decrease)
save(config, data) save(config, data)
@ -340,14 +342,31 @@ def main():
print_stats(load(config), config['data_path']) print_stats(load(config), config['data_path'])
else: else:
# default behavior, no optional arguments # default behavior, no optional arguments
result = first(find_matches(entriefy(load(config)), args.directory)) entries = entriefy(load(config))
needles = sanitize(args.directory)
needle = first(needles)
if is_tab_entry(needle, TAB_SEPARATOR):
# the needle is actually a tab entry here
needle, tab_index = get_needle_and_index(needle, TAB_SEPARATOR)
tab_entries = take(
TAB_COMPLETION_COUNT,
find_matches(entries, needle))
if result: get_ith_path = lambda i, iterable: last(take(i, iterable)).path
print(encode_local(surround_quotes(result.path))) print(encode_local(surround_quotes(
get_ith_path(tab_index, tab_entries))))
elif is_tab_partial_match(needle, TAB_SEPARATOR):
print("tab_partial_match")
else: else:
# always return something so the calling shell function has an result = first(find_matches(entries, needles))
# argument to `cd` to
print(encode_local('.')) if result:
print(encode_local(surround_quotes(result.path)))
else:
# always return something so the calling shell function has an
# argument to `cd` to
print(encode_local('.'))
return 0 return 0

@ -8,6 +8,7 @@ import errno
from itertools import islice from itertools import islice
import os import os
import platform import platform
import re
import shutil import shutil
import sys import sys
import unicodedata import unicodedata
@ -51,6 +52,21 @@ def first(xs):
return None return None
def get_needle_and_index(tab_entry, separator):
"""
Given a tab entry in the following format return the needle and index:
[needle]__[index]__[possible_match]
"""
matches = re.search(
r'(.*)' + \
separator + \
r'([0-9]{1})' + \
separator, tab_entry)
return matches.group(1), int(matches.group(2))
def get_pwd(): def get_pwd():
try: try:
return os.getcwdu() return os.getcwdu()
@ -79,6 +95,24 @@ def is_osx():
return platform.system() == 'Darwin' return platform.system() == 'Darwin'
def is_tab_entry(needle, separator):
"""
Valid tab entry:
[needle]__[index]__[possible_match]
"""
pattern = re.compile(
'.*' + \
separator + \
'[0-9]{1}' + \
separator)
return re.search(pattern, needle)
def is_tab_partial_match(needle, separator):
return re.match(r'(.*)'+separator, needle)
def is_windows(): def is_windows():
return platform.system() == 'Windows' return platform.system() == 'Windows'
@ -110,16 +144,30 @@ def print_entry(entry):
print(encode_local("%.1f:\t%s" % (entry.weight, entry.path))) print(encode_local("%.1f:\t%s" % (entry.weight, entry.path)))
def print_tab_completion_menu(separator, entries): def print_tab_menu(needle, tab_entries, separator):
for i, entry in enumerate(entries): """
Prints the tab completion menu according to the following format:
[needle]__[index]__[possible_match]
The needle (search pattern) and index are necessary to recreate the results
on subsequent calls.
"""
for i, entry in enumerate(tab_entries):
print(encode_local(surround_quotes( print(encode_local(surround_quotes(
'%s%d%s%s' % ( '%s%s%d%s%s' % (
needle,
separator, separator,
i, i+1,
separator, separator,
entry.path)))) entry.path))))
def sanitize(directories):
clean = lambda x: decode(x).rstrip(os.sep)
return map(clean, directories)
def second(xs): def second(xs):
it = iter(xs) it = iter(xs)
try: try:

Loading…
Cancel
Save