Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion AdvancedNewFile.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -179,5 +179,8 @@
"empty_filename_action": false,

// When specifying initial input, this boolean will place the cursor prior to the .<content>
"cursor_before_extension": false
"cursor_before_extension": false,

// Ignore regex patters
"filter_regex": ["\\.DS_Store", "\\.git"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This setting needs more context. I'd guess it is for filtering out the completions, but guessing is all I can do from reading this.

}
3 changes: 3 additions & 0 deletions Default (Linux).sublime-keymap
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
{"keys": ["ctrl+l"],"command": "advanced_new_file_updir",
Copy link
Member

@FichteFoll FichteFoll Jun 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why L? Is that how emacs does it? Please add some comments above the binding to explain their inspiration because I (for example) wouldn't know otherwise. Probably to the readme as well.

"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["enter"],"command": "advanced_new_file_confirm",
"context": [{"key": "setting.anf_panel"}]
},
Comment on lines +21 to +23
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this prevent submitting the inserted new file name when the completion list is not visible? It would also not match the native completions UX if "auto_complete_commit_on_tab": true.

{"keys": ["ctrl+j"],"command": "insert", "args": {"characters": "\t"},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose this is how tab completion works currently, but I find that questionable when you could instead bind the tab key to a proper command instead.

"context": [{"key": "setting.anf_panel"}]
},
Expand Down
3 changes: 3 additions & 0 deletions Default (OSX).sublime-keymap
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
{"keys": ["ctrl+l"],"command": "advanced_new_file_updir",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["enter"],"command": "advanced_new_file_confirm",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["ctrl+j"],"command": "insert", "args": {"characters": "\t"},
"context": [{"key": "setting.anf_panel"}]
},
Expand Down
3 changes: 3 additions & 0 deletions Default (Windows).sublime-keymap
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
{"keys": ["ctrl+l"],"command": "advanced_new_file_updir",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["enter"],"command": "advanced_new_file_confirm",
"context": [{"key": "setting.anf_panel"}]
},
{"keys": ["ctrl+j"],"command": "insert", "args": {"characters": "\t"},
"context": [{"key": "setting.anf_panel"}]
},
Expand Down
4 changes: 3 additions & 1 deletion advanced_new_file/anf_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
COPY_FILE_DEFAULT_ROOT_SETTING = "copy_file_default_root"
DEFAULT_NEW_FILE = "empty_filename_action"
CURSOR_BEFORE_EXTENSION_SETTING = "cursor_before_extension"
FILTER_REGEX_SETTING = "filter_regex"


SETTINGS = [
Expand Down Expand Up @@ -80,7 +81,8 @@
RENAME_FILE_DEFAULT_ROOT_SETTING,
COPY_FILE_DEFAULT_ROOT_SETTING,
DEFAULT_NEW_FILE,
CURSOR_BEFORE_EXTENSION_SETTING
CURSOR_BEFORE_EXTENSION_SETTING,
FILTER_REGEX_SETTING
]

NIX_ROOT_REGEX = r"^/"
Expand Down
19 changes: 14 additions & 5 deletions advanced_new_file/commands/command_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,12 +296,21 @@ def __update_filename_input(self, path_in):
if self.view is not None:
self.view.erase_status("AdvancedNewFile2")

input_view = AdvancedNewFileBase.static_input_panel_view
if path_in.endswith("\t"):
creation_path, candidate, completion_list = self.parse_status_line(self.get_status_line()) # type: ignore
print("candidate", candidate, str(completion_list))
new_content = self.completion_input(path_in.replace("\t", ""), candidate)
print("new_content", new_content)
# new_content = candidate
new_content = self.completion_input(path_in.replace("\n", "").replace("\t", ""), candidate)
elif path_in.endswith("\n"):
path_in = path_in.replace("\n", "")
if input_view:
# print("visible", input_view.is_popup_visible())
if input_view.is_popup_visible():
input_view.run_command("insert", {"characters": "\t"})
else:
# print("end panel")
self.on_done(path_in)
self.window.run_command("hide_panel", {"cancel": True})
return
else:
completion_list = self.completion.hint(path_in)
if completion_list:
Expand All @@ -310,7 +319,7 @@ def __update_filename_input(self, path_in):
else:
candidate = ''

input_view = AdvancedNewFileBase.static_input_panel_view

if input_view:
input_view.hide_popup()
if input_view and new_content != path_in:
Expand Down
7 changes: 7 additions & 0 deletions advanced_new_file/commands/new_file_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,13 @@ def updir(self, path_in):
new_content = ''
return new_content

class AdvancedNewFileConfirmCommand(AdvancedNewFileBase, sublime_plugin.WindowCommand):
def __init__(self, window):
super().__init__(window)

def run(self):
pass

class AdvancedNewFileNewAtCommand(sublime_plugin.WindowCommand):
def run(self, dirs):
if len(dirs) != 1:
Expand Down
32 changes: 26 additions & 6 deletions advanced_new_file/completions/completion_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from ..anf_util import *
from .pinyin_lib import *

from .fuzzy_sort import sort_by_fuzzy


class GenerateCompletionListBase(object):
"""docstring for GenerateCompletionListBase"""
Expand Down Expand Up @@ -38,6 +40,8 @@ def generate_completion_list(self, path_in):
directory, filename = os.path.split(full_path)
if os.path.isdir(directory):
for d in os.listdir(directory):
if not self.filter_file(d):
continue
full_path = os.path.join(directory, d)
if os.path.isdir(full_path):
is_file = False
Expand All @@ -54,7 +58,20 @@ def generate_completion_list(self, path_in):

completion_list = alias_list + dir_list + file_list

return sorted(completion_list), alias_list, dir_list, file_list
return sort_by_fuzzy(filename, completion_list), alias_list, dir_list, file_list

def filter_file(self, fname):
"""
Returns False if a file should be ignored: If the file matched any of the regular expressions
on the settings file
"""
fname = os.path.basename(fname)
for regex in self.settings.get('filter_regex', list()):
regex = regex.replace('\\\\', '\\') # Fix backslash escaping on json
p = re.compile(regex)
if p.match(fname) is not None:
return False
return True

def generate_project_auto_complete(self, base):
folder_data = get_project_folder_data(
Expand Down Expand Up @@ -94,9 +111,12 @@ def compare_entries(self, compare_entry, compare_base):
def hint(self, path_in):
(completion_list, alias_list,
dir_list, file_list) = self.generate_completion_list(path_in)
new_completion_list = []
if len(completion_list) > 0:
dir_list = map(lambda s: s + "/", dir_list)
alias_list = map(lambda s: s + ":", alias_list)
completion_list = sorted(list(dir_list) +
list(alias_list) + file_list)
return completion_list
for path in completion_list:
if path in dir_list:
path += "/"
elif path in alias_list:
path += ":"
new_completion_list.append(path)
return new_completion_list
60 changes: 60 additions & 0 deletions advanced_new_file/completions/fuzzy_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from operator import itemgetter
# import numpy as np

def sort_by_fuzzy(query, choices):
if not query or not choices:
return choices
choices_ratio = {}
for choice in choices:
choices_ratio[choice] = levenshtein_ratio(query, choice)

# print(choices_ratio)
return [key[0] for key in sorted(choices_ratio.items(), key=itemgetter(1), reverse=True)]

def levenshtein_ratio(s, t):
""" levenshtein_ratio_and_distance:
Calculates levenshtein distance between two strings.
If ratio_calc = True, the function computes the
levenshtein distance ratio of similarity between two strings
For all i and j, distance[i,j] will contain the Levenshtein
distance between the first i characters of s and the
first j characters of t
"""
# Initialize matrix of zeros
rows = len(s)+1
cols = len(t)+1
distance = [[0 for i in range(cols)] for j in range(rows)]
# distance = np.zeros((rows, cols),dtype=int)

# Populate matrix of zeros with the indeces of each character of both strings
for i in range(1, rows):
for k in range(1,cols):
distance[i][0] = i
distance[0][k] = k

# Iterate over the matrix to compute the cost of deletions,insertions and/or substitutions
for col in range(1, cols):
for row in range(1, rows):
if s[row-1].lower() == t[col-1].lower():
cost = 0 # If the characters are the same in the two strings in a given position [i,j] then the cost is 0
else:
# In order to align the results with those of the Python Levenshtein package, if we choose to calculate the ratio
# the cost of a substitution is 2.
cost = 1
distance[row][col] = min(distance[row-1][col] + 1, # Cost of deletions
distance[row][col-1] + 1, # Cost of insertions
distance[row-1][col-1] + cost) # Cost of substitutions

# Computation of the Levenshtein Distance Ratio
ratio = ((len(s)+len(t)) - distance[row][col]) / (len(s)+len(t))
if rows < cols:
ratio = max(ratio, ((len(s)+len(t)) - distance[row][row]) / (len(s)+len(t)))
return ratio

# if __name__ == '__main__':
# print(levenshtein_ratio('test', 'test'))
# print(levenshtein_ratio('test', 'test tt'))
# print(levenshtein_ratio('test', 'taebsct'))
# print(levenshtein_ratio('test', 'tabtest'))
# print(levenshtein_ratio('test', 'tst tt'))
# 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']))
2 changes: 1 addition & 1 deletion advanced_new_file/reloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
mods_load_order = [
'',
'.anf_util',
'.completion_base',

".lib",
".lib.package_resources",
".lib.ushlex",

".completions",
'.completions.fuzzy_sort',
'.completions.pinyin_lib',
'.completions.completion_base',
'.completions.nix_completion',
Expand Down