Skip to content

Commit 988b8a5

Browse files
committed
Use enter to choose the completion candidate, and add fuzzy sort for completion list.
1 parent c6c13fd commit 988b8a5

10 files changed

+124
-14
lines changed

AdvancedNewFile.sublime-settings

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,5 +179,8 @@
179179
"empty_filename_action": false,
180180

181181
// When specifying initial input, this boolean will place the cursor prior to the .<content>
182-
"cursor_before_extension": false
182+
"cursor_before_extension": false,
183+
184+
// Ignore regex patters
185+
"filter_regex": ["\\.DS_Store", "\\.git"]
183186
}

Default (Linux).sublime-keymap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
{"keys": ["ctrl+l"],"command": "advanced_new_file_updir",
1919
"context": [{"key": "setting.anf_panel"}]
2020
},
21+
{"keys": ["enter"],"command": "advanced_new_file_confirm",
22+
"context": [{"key": "setting.anf_panel"}]
23+
},
2124
{"keys": ["ctrl+j"],"command": "insert", "args": {"characters": "\t"},
2225
"context": [{"key": "setting.anf_panel"}]
2326
},

Default (OSX).sublime-keymap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
{"keys": ["ctrl+l"],"command": "advanced_new_file_updir",
1919
"context": [{"key": "setting.anf_panel"}]
2020
},
21+
{"keys": ["enter"],"command": "advanced_new_file_confirm",
22+
"context": [{"key": "setting.anf_panel"}]
23+
},
2124
{"keys": ["ctrl+j"],"command": "insert", "args": {"characters": "\t"},
2225
"context": [{"key": "setting.anf_panel"}]
2326
},

Default (Windows).sublime-keymap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
{"keys": ["ctrl+l"],"command": "advanced_new_file_updir",
1919
"context": [{"key": "setting.anf_panel"}]
2020
},
21+
{"keys": ["enter"],"command": "advanced_new_file_confirm",
22+
"context": [{"key": "setting.anf_panel"}]
23+
},
2124
{"keys": ["ctrl+j"],"command": "insert", "args": {"characters": "\t"},
2225
"context": [{"key": "setting.anf_panel"}]
2326
},

advanced_new_file/anf_util.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
COPY_FILE_DEFAULT_ROOT_SETTING = "copy_file_default_root"
4141
DEFAULT_NEW_FILE = "empty_filename_action"
4242
CURSOR_BEFORE_EXTENSION_SETTING = "cursor_before_extension"
43+
FILTER_REGEX_SETTING = "filter_regex"
4344

4445

4546
SETTINGS = [
@@ -80,7 +81,8 @@
8081
RENAME_FILE_DEFAULT_ROOT_SETTING,
8182
COPY_FILE_DEFAULT_ROOT_SETTING,
8283
DEFAULT_NEW_FILE,
83-
CURSOR_BEFORE_EXTENSION_SETTING
84+
CURSOR_BEFORE_EXTENSION_SETTING,
85+
FILTER_REGEX_SETTING
8486
]
8587

8688
NIX_ROOT_REGEX = r"^/"

advanced_new_file/commands/command_base.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -296,12 +296,21 @@ def __update_filename_input(self, path_in):
296296
if self.view is not None:
297297
self.view.erase_status("AdvancedNewFile2")
298298

299+
input_view = AdvancedNewFileBase.static_input_panel_view
299300
if path_in.endswith("\t"):
300301
creation_path, candidate, completion_list = self.parse_status_line(self.get_status_line()) # type: ignore
301-
print("candidate", candidate, str(completion_list))
302-
new_content = self.completion_input(path_in.replace("\t", ""), candidate)
303-
print("new_content", new_content)
304-
# new_content = candidate
302+
new_content = self.completion_input(path_in.replace("\n", "").replace("\t", ""), candidate)
303+
elif path_in.endswith("\n"):
304+
path_in = path_in.replace("\n", "")
305+
if input_view:
306+
# print("visible", input_view.is_popup_visible())
307+
if input_view.is_popup_visible():
308+
input_view.run_command("insert", {"characters": "\t"})
309+
else:
310+
# print("end panel")
311+
self.on_done(path_in)
312+
self.window.run_command("hide_panel", {"cancel": True})
313+
return
305314
else:
306315
completion_list = self.completion.hint(path_in)
307316
if completion_list:
@@ -310,7 +319,7 @@ def __update_filename_input(self, path_in):
310319
else:
311320
candidate = ''
312321

313-
input_view = AdvancedNewFileBase.static_input_panel_view
322+
314323
if input_view:
315324
input_view.hide_popup()
316325
if input_view and new_content != path_in:

advanced_new_file/commands/new_file_command.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,13 @@ def updir(self, path_in):
180180
new_content = ''
181181
return new_content
182182

183+
class AdvancedNewFileConfirmCommand(AdvancedNewFileBase, sublime_plugin.WindowCommand):
184+
def __init__(self, window):
185+
super().__init__(window)
186+
187+
def run(self):
188+
pass
189+
183190
class AdvancedNewFileNewAtCommand(sublime_plugin.WindowCommand):
184191
def run(self, dirs):
185192
if len(dirs) != 1:

advanced_new_file/completions/completion_base.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from ..anf_util import *
55
from .pinyin_lib import *
66

7+
from .fuzzy_sort import sort_by_fuzzy
8+
79

810
class GenerateCompletionListBase(object):
911
"""docstring for GenerateCompletionListBase"""
@@ -38,6 +40,8 @@ def generate_completion_list(self, path_in):
3840
directory, filename = os.path.split(full_path)
3941
if os.path.isdir(directory):
4042
for d in os.listdir(directory):
43+
if not self.filter_file(d):
44+
continue
4145
full_path = os.path.join(directory, d)
4246
if os.path.isdir(full_path):
4347
is_file = False
@@ -54,7 +58,20 @@ def generate_completion_list(self, path_in):
5458

5559
completion_list = alias_list + dir_list + file_list
5660

57-
return sorted(completion_list), alias_list, dir_list, file_list
61+
return sort_by_fuzzy(filename, completion_list), alias_list, dir_list, file_list
62+
63+
def filter_file(self, fname):
64+
"""
65+
Returns False if a file should be ignored: If the file matched any of the regular expressions
66+
on the settings file
67+
"""
68+
fname = os.path.basename(fname)
69+
for regex in self.settings.get('filter_regex', list()):
70+
regex = regex.replace('\\\\', '\\') # Fix backslash escaping on json
71+
p = re.compile(regex)
72+
if p.match(fname) is not None:
73+
return False
74+
return True
5875

5976
def generate_project_auto_complete(self, base):
6077
folder_data = get_project_folder_data(
@@ -94,9 +111,12 @@ def compare_entries(self, compare_entry, compare_base):
94111
def hint(self, path_in):
95112
(completion_list, alias_list,
96113
dir_list, file_list) = self.generate_completion_list(path_in)
114+
new_completion_list = []
97115
if len(completion_list) > 0:
98-
dir_list = map(lambda s: s + "/", dir_list)
99-
alias_list = map(lambda s: s + ":", alias_list)
100-
completion_list = sorted(list(dir_list) +
101-
list(alias_list) + file_list)
102-
return completion_list
116+
for path in completion_list:
117+
if path in dir_list:
118+
path += "/"
119+
elif path in alias_list:
120+
path += ":"
121+
new_completion_list.append(path)
122+
return new_completion_list
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from operator import itemgetter
2+
# import numpy as np
3+
4+
def sort_by_fuzzy(query, choices):
5+
if not query or not choices:
6+
return choices
7+
choices_ratio = {}
8+
for choice in choices:
9+
choices_ratio[choice] = levenshtein_ratio(query, choice)
10+
11+
# print(choices_ratio)
12+
return [key[0] for key in sorted(choices_ratio.items(), key=itemgetter(1), reverse=True)]
13+
14+
def levenshtein_ratio(s, t):
15+
""" levenshtein_ratio_and_distance:
16+
Calculates levenshtein distance between two strings.
17+
If ratio_calc = True, the function computes the
18+
levenshtein distance ratio of similarity between two strings
19+
For all i and j, distance[i,j] will contain the Levenshtein
20+
distance between the first i characters of s and the
21+
first j characters of t
22+
"""
23+
# Initialize matrix of zeros
24+
rows = len(s)+1
25+
cols = len(t)+1
26+
distance = [[0 for i in range(cols)] for j in range(rows)]
27+
# distance = np.zeros((rows, cols),dtype=int)
28+
29+
# Populate matrix of zeros with the indeces of each character of both strings
30+
for i in range(1, rows):
31+
for k in range(1,cols):
32+
distance[i][0] = i
33+
distance[0][k] = k
34+
35+
# Iterate over the matrix to compute the cost of deletions,insertions and/or substitutions
36+
for col in range(1, cols):
37+
for row in range(1, rows):
38+
if s[row-1].lower() == t[col-1].lower():
39+
cost = 0 # If the characters are the same in the two strings in a given position [i,j] then the cost is 0
40+
else:
41+
# In order to align the results with those of the Python Levenshtein package, if we choose to calculate the ratio
42+
# the cost of a substitution is 2.
43+
cost = 1
44+
distance[row][col] = min(distance[row-1][col] + 1, # Cost of deletions
45+
distance[row][col-1] + 1, # Cost of insertions
46+
distance[row-1][col-1] + cost) # Cost of substitutions
47+
48+
# Computation of the Levenshtein Distance Ratio
49+
ratio = ((len(s)+len(t)) - distance[row][col]) / (len(s)+len(t))
50+
if rows < cols:
51+
ratio = max(ratio, ((len(s)+len(t)) - distance[row][row]) / (len(s)+len(t)))
52+
return ratio
53+
54+
# if __name__ == '__main__':
55+
# print(levenshtein_ratio('test', 'test'))
56+
# print(levenshtein_ratio('test', 'test tt'))
57+
# print(levenshtein_ratio('test', 'taebsct'))
58+
# print(levenshtein_ratio('test', 'tabtest'))
59+
# print(levenshtein_ratio('test', 'tst tt'))
60+
# print(sort_by_fuzzy('def', ['advanced_new_file', 'AdvancedNewFile.py', 'AdvancedNewFile.sublime-settings', 'Default (Linux).sublime-keymap', 'Default (OSX).sublime-keymap', 'Default (Windows).sublime-keymap', 'Default.sublime-commands']))

advanced_new_file/reloader.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@
2323
mods_load_order = [
2424
'',
2525
'.anf_util',
26-
'.completion_base',
2726

2827
".lib",
2928
".lib.package_resources",
3029
".lib.ushlex",
3130

3231
".completions",
32+
'.completions.fuzzy_sort',
3333
'.completions.pinyin_lib',
3434
'.completions.completion_base',
3535
'.completions.nix_completion',

0 commit comments

Comments
 (0)