Skip to content

Commit 9066872

Browse files
committed
A project files command is added, and improve the variable exchange method
1 parent 988b8a5 commit 9066872

File tree

7 files changed

+191
-60
lines changed

7 files changed

+191
-60
lines changed

advanced_new_file/commands/__init__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from .cut_to_file import AdvancedNewFileCutToFile
55
from .move_file_command import AdvancedNewFileMove, AdvancedNewFileMoveAtCommand
66
from .copy_file_command import AdvancedNewFileCopy, AdvancedNewFileCopyAtCommand
7+
from .project_file_command import AdvancedNewFileProjectFileCommand
78

89
__all__ = [
910
"AnfReplaceCommand",
@@ -21,5 +22,6 @@
2122
"AdvancedNewFileCopy",
2223
"AdvancedNewFileCopyAtCommand",
2324
"AnfRemoveRegionContentAndRegionCommand",
24-
"AdvancedNewFileCutToFile"
25+
"AdvancedNewFileCutToFile",
26+
"AdvancedNewFileProjectFileCommand"
2527
]

advanced_new_file/commands/command_base.py

+65-36
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323

2424

2525
class AdvancedNewFileBase(object):
26-
static_input_panel_view = None
27-
2826
def __init__(self, window):
2927
super()
3028
self.window = window
@@ -270,6 +268,38 @@ def __translate_alias(self, path):
270268
def input_panel_caption(self):
271269
return ""
272270

271+
def get_active_window_settings(self):
272+
return sublime.active_window().settings()
273+
274+
def set_input_view(self, input_view):
275+
self.get_active_window_settings().set("anf_input_view", input_view.id())
276+
277+
def get_input_view(self):
278+
return sublime.View(self.get_active_window_settings().get("anf_input_view"))
279+
280+
281+
def get_active_view_settings(self):
282+
view = self.get_input_view()
283+
if view:
284+
return view.settings()
285+
else:
286+
return self.get_active_window_settings()
287+
288+
def clear_input_view(self):
289+
self.get_active_view_settings().erase("anf_input_view")
290+
291+
def set_input_view_content(self, content):
292+
self.get_active_view_settings().set("anf_input_view_content", content)
293+
294+
def get_input_view_content(self):
295+
return self.get_active_view_settings().get("anf_input_view_content")
296+
297+
def clear_input_view_content(self):
298+
self.get_active_view_settings().erase("anf_input_view_content")
299+
300+
def clear_input_view_project_files(self):
301+
self.get_active_view_settings().erase("anf_input_view_project_files")
302+
273303
def show_filename_input(self, initial):
274304
caption = self.input_panel_caption()
275305

@@ -286,8 +316,8 @@ def show_filename_input(self, initial):
286316
self.input_panel_view.settings().set("anf_panel", True)
287317
if self.settings.get(CURSOR_BEFORE_EXTENSION_SETTING):
288318
self.__place_cursor_before_extension(self.input_panel_view)
289-
AdvancedNewFileBase.static_input_panel_view = self.input_panel_view
290-
self.__update_filename_input('')
319+
self.set_input_view(self.input_panel_view)
320+
self.__update_filename_input(initial)
291321

292322
def __update_filename_input(self, path_in):
293323
new_content = path_in
@@ -296,9 +326,9 @@ def __update_filename_input(self, path_in):
296326
if self.view is not None:
297327
self.view.erase_status("AdvancedNewFile2")
298328

299-
input_view = AdvancedNewFileBase.static_input_panel_view
329+
input_view = self.get_input_view()
300330
if path_in.endswith("\t"):
301-
creation_path, candidate, completion_list = self.parse_status_line(self.get_status_line()) # type: ignore
331+
creation_path, candidate, completion_list = self.get_input_view_content()
302332
new_content = self.completion_input(path_in.replace("\n", "").replace("\t", ""), candidate)
303333
elif path_in.endswith("\n"):
304334
path_in = path_in.replace("\n", "")
@@ -312,25 +342,41 @@ def __update_filename_input(self, path_in):
312342
self.window.run_command("hide_panel", {"cancel": True})
313343
return
314344
else:
315-
completion_list = self.completion.hint(path_in)
345+
completion_list = self.get_completion_list(path_in)
316346
if completion_list:
317347
candidate = completion_list[0]
318348
completion_list.remove(candidate)
319349
else:
320350
candidate = ''
321351

322-
323352
if input_view:
324-
input_view.hide_popup()
353+
try:
354+
input_view.hide_popup()
355+
except Exception as e:
356+
print("hide_popup", e)
325357
if input_view and new_content != path_in:
326358
input_view.run_command("anf_replace", {"content": new_content})
327359
else:
328360
base, path = self.split_path(path_in)
329-
status_line = generate_creation_path(self.settings, base, path, True) + '|' + candidate + str(completion_list)
361+
creation_path = generate_creation_path(self.settings, base, path, True)
362+
status_line = self.create_status_line(creation_path, candidate, completion_list)
363+
self.set_input_view_content((creation_path, candidate, completion_list))
364+
330365
if self.settings.get(SHOW_PATH_SETTING, False):
331366
self.update_status_message(status_line)
332-
if input_view and candidate and not new_content.endswith(candidate):
333-
input_view.show_popup('<strong>' + candidate + '</strong><br/>' + '<br/>'.join(completion_list))
367+
if not new_content.endswith(candidate):
368+
self.show_input_popup(candidate, completion_list)
369+
370+
def show_input_popup(self, candidate, completion_list):
371+
try:
372+
input_view = self.get_input_view()
373+
if input_view and candidate:
374+
input_view.show_popup('<strong>' + candidate + '</strong><br/>' + '<br/>'.join(completion_list), max_width=1024)
375+
except Exception as e:
376+
print("show_popup", e)
377+
378+
def get_completion_list(self, path_in):
379+
return self.completion.complete_for_folder(path_in)
334380

335381
def completion_input(self, path_in, candidate):
336382
pattern = r"(.*[/\\:])(.*)"
@@ -403,7 +449,9 @@ def clear(self):
403449
if self.view is not None:
404450
self.view.erase_status("AdvancedNewFile")
405451
self.view.erase_status("AdvancedNewFile2")
406-
AdvancedNewFileBase.static_input_panel_view = None
452+
self.clear_input_view()
453+
self.clear_input_view_content()
454+
self.clear_input_view_project_files()
407455

408456
def create(self, filename):
409457
base, filename = os.path.split(filename)
@@ -455,7 +503,10 @@ def get_cursor_path(self):
455503
break
456504
if (re.match(".*string.quoted.double", syntax) or
457505
re.match(".*string.quoted.single", syntax)):
458-
path = view.substr(view.extract_scope(region.begin()))
506+
point = region.begin()
507+
if (re.match(".*punctuation.definition.string.end", syntax)):
508+
point -= 1
509+
path = view.substr(view.extract_scope(point))
459510
path = re.sub('^"|\'', '', re.sub('"|\'$', '', path.strip()))
460511
break
461512

@@ -507,9 +558,6 @@ def __place_cursor_before_extension(self, view):
507558
cursors.clear()
508559
cursors.add(sublime.Region(initial_position, initial_position))
509560

510-
def get_status_line(self):
511-
return self.view.get_status("AdvancedNewFile")
512-
513561
def update_status_message(self, creation_path):
514562
if self.view is not None:
515563
self.view.set_status("AdvancedNewFile", creation_path)
@@ -522,25 +570,6 @@ def get_status_prefix(self):
522570
def create_status_line(self, creation_path, candidate, completion_list):
523571
return creation_path + '|' + candidate + str(completion_list)
524572

525-
def parse_status_line(self, status_line):
526-
# Creating file at AdvancedNewFile/advanced_new_file/commands/|__init__.py['command_base.py']
527-
if status_line:
528-
status_line = status_line.strip()
529-
index1 = status_line.rindex('[')
530-
completion_list = status_line[index1:]
531-
try:
532-
completion_list = json.loads(completion_list.replace("'", '"'))
533-
except Exception as e:
534-
print("completion_list", completion_list, e)
535-
raise e
536-
index2 = status_line.rindex('|')
537-
candidate = status_line[index2 + 1:index1]
538-
# TODO: prefix_len = len(self.get_status_prefix())
539-
creation_path = status_line[0:index2]
540-
return (creation_path, candidate, completion_list)
541-
else:
542-
return ('', '', [])
543-
544573
def next_candidate(self, candidate, completion_list):
545574
if candidate and completion_list:
546575
# replace the candidate with the first, and append the old candidate to the last

advanced_new_file/commands/new_file_command.py

+25-17
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def entered_file_action(self, path):
3232

3333
def multi_file_action(self, paths):
3434
for path in paths:
35-
self.single_file_action(path, False)
35+
self.single_file_action(path)
3636

3737
def single_file_action(self, path, apply_template=True):
3838
attempt_open = True
@@ -127,29 +127,37 @@ def __init__(self, window):
127127

128128
def run(self):
129129
self.run_setup()
130-
# Creating file at AdvancedNewFile/advanced_new_file/commands/|__init__.py['__init__.py', 'command_base.py']
131-
status_line = self.get_status_line()
132-
creation_path, candidate, completion_list = self.parse_status_line(status_line) # type: ignore
130+
try:
131+
creation_path, candidate, completion_list = self.get_input_view_content()
132+
except Exception:
133+
# if the content is not init, then simulate the new input
134+
input_view = self.get_input_view()
135+
input_view.run_command("anf_replace", {"content": ""})
136+
creation_path, candidate, completion_list = self.get_input_view_content()
137+
133138
candidate, completion_list = self.next_candidate(candidate, completion_list)
139+
self.set_input_view_content((creation_path, candidate, completion_list))
134140
self.update_status_message(self.create_status_line(creation_path, candidate, completion_list))
135-
input_view = AdvancedNewFileBase.static_input_panel_view
136-
if input_view:
137-
input_view.show_popup('<strong>' + candidate + '</strong><br/>' + '<br/>'.join(completion_list))
141+
self.show_input_popup(candidate, completion_list)
138142

139143
class AdvancedNewFilePrevCommand(AdvancedNewFileBase, sublime_plugin.WindowCommand):
140144
def __init__(self, window):
141145
super().__init__(window)
142146

143147
def run(self):
144148
self.run_setup()
145-
# Creating file at AdvancedNewFile/advanced_new_file/commands/|__init__.py['__init__.py', 'command_base.py']
146-
status_line = self.get_status_line()
147-
creation_path, candidate, completion_list = self.parse_status_line(status_line) # type: ignore
149+
try:
150+
creation_path, candidate, completion_list = self.get_input_view_content()
151+
except Exception:
152+
# if the content is not init, then simulate the new input
153+
input_view = self.get_input_view()
154+
input_view.run_command("anf_replace", {"content": ""})
155+
creation_path, candidate, completion_list = self.get_input_view_content()
156+
148157
candidate, completion_list = self.prev_candidate(candidate, completion_list)
158+
self.set_input_view_content((creation_path, candidate, completion_list))
149159
self.update_status_message(self.create_status_line(creation_path, candidate, completion_list))
150-
input_view = AdvancedNewFileBase.static_input_panel_view
151-
if input_view and candidate and completion_list:
152-
input_view.show_popup('<strong>' + candidate + '</strong><br/>' + '<br/>'.join(completion_list))
160+
self.show_input_popup(candidate, completion_list)
153161

154162

155163
class AdvancedNewFileUpdirCommand(AdvancedNewFileBase, sublime_plugin.WindowCommand):
@@ -158,11 +166,11 @@ def __init__(self, window):
158166

159167
def run(self):
160168
self.run_setup()
161-
view = AdvancedNewFileBase.static_input_panel_view
162-
if view:
163-
path_in = view.substr(sublime.Region(0, view.size()))
169+
input_view = self.get_input_view()
170+
if input_view:
171+
path_in = input_view.substr(sublime.Region(0, input_view.size()))
164172
new_content = self.updir(path_in)
165-
view.run_command("anf_replace", {"content": new_content})
173+
input_view.run_command("anf_replace", {"content": new_content})
166174

167175
def updir(self, path_in):
168176
if not(path_in):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import sublime
2+
import sublime_plugin
3+
import os
4+
import re
5+
import xml.etree.ElementTree as ET
6+
7+
from .new_file_command import AdvancedNewFileNew
8+
from ..lib.package_resources import get_resource
9+
from ..anf_util import *
10+
11+
12+
class AdvancedNewFileProjectFileCommand(AdvancedNewFileNew, sublime_plugin.WindowCommand):
13+
def __init__(self, window):
14+
super().__init__(window)
15+
16+
def run(self, is_python=False, initial_path=None):
17+
self.is_python = is_python
18+
self.run_setup()
19+
self.show_filename_input(self.generate_initial_path(initial_path))
20+
21+
def get_project_folder(self):
22+
return sublime.active_window().folders()[0]
23+
24+
def split_path(self, path_in):
25+
return (self.get_project_folder(), path_in)
26+
27+
def entered_file_action(self, path):
28+
if self.settings.get(SHELL_INPUT_SETTING, False):
29+
self.multi_file_action(self.curly_brace_expansion(path))
30+
else:
31+
self.single_file_action(path)
32+
33+
def input_panel_caption(self):
34+
caption = 'Enter a path for a project file'
35+
return caption
36+
37+
def update_status_message(self, creation_path):
38+
if self.view is not None:
39+
self.view.set_status("AdvancedNewFile", "Project file at %s" % creation_path)
40+
else:
41+
sublime.status_message("Project file at %s" % creation_path)
42+
43+
def get_completion_list(self, path_in):
44+
return self.completion.complete_for_project(path_in)
45+
46+
def set_input_view_project_files(self, project_files):
47+
self.get_active_view_settings().set("anf_input_view_project_files", project_files)
48+
49+
def get_input_view_project_files(self):
50+
return self.get_active_view_settings().get("anf_input_view_project_files")
51+
52+

advanced_new_file/completions/completion_base.py

+37-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def generate_completion_list(self, path_in):
3434
alias_list += self.generate_alias_auto_complete(filename)
3535
alias_list += self.generate_project_auto_complete(filename)
3636
base, path = self.command.split_path(path_in)
37-
print("base,path", path_in, base, path)
37+
# print("base,path", path_in, base, path)
3838
full_path = generate_creation_path(self.settings, base, path)
3939

4040
directory, filename = os.path.split(full_path)
@@ -58,7 +58,7 @@ def generate_completion_list(self, path_in):
5858

5959
completion_list = alias_list + dir_list + file_list
6060

61-
return sort_by_fuzzy(filename, completion_list), alias_list, dir_list, file_list
61+
return sort_by_fuzzy(filename, completion_list, 20), alias_list, dir_list, file_list
6262

6363
def filter_file(self, fname):
6464
"""
@@ -108,7 +108,7 @@ def compare_entries(self, compare_entry, compare_base):
108108
pattern = get_str_pattern(compare_base, self.settings.get(IGNORE_CASE_SETTING, True))
109109
return re.match(pattern, compare_entry) is not None
110110

111-
def hint(self, path_in):
111+
def complete_for_folder(self, path_in):
112112
(completion_list, alias_list,
113113
dir_list, file_list) = self.generate_completion_list(path_in)
114114
new_completion_list = []
@@ -120,3 +120,37 @@ def hint(self, path_in):
120120
path += ":"
121121
new_completion_list.append(path)
122122
return new_completion_list
123+
124+
125+
def complete_for_project(self, path_in):
126+
directory = self.command.get_project_folder()
127+
128+
completion_list = []
129+
if os.path.isdir(directory):
130+
files = self.command.get_input_view_project_files()
131+
if not files:
132+
files = self.get_files_recursively(directory, self.filter_file)
133+
self.command.set_input_view_project_files(files)
134+
else:
135+
print("use the old files", str(len(files)))
136+
for file in files:
137+
if self.compare_entries(os.path.basename(file), path_in):
138+
completion_list.append(file)
139+
140+
return sort_by_fuzzy(path_in, completion_list, 20)
141+
142+
def get_files_recursively(self, dir, filter_func=None):
143+
if not os.path.isdir(dir):
144+
return list(dir)
145+
dirlist = os.walk(dir)
146+
result = []
147+
for root, _, files in dirlist:
148+
rel_path = os.path.relpath(root, dir)
149+
for file in files:
150+
rel_file = os.path.join(rel_path, file)
151+
if filter_func:
152+
if filter_func(rel_file):
153+
result.append(rel_file)
154+
else:
155+
result.append(rel_file)
156+
return result

0 commit comments

Comments
 (0)