Skip to content

Commit 068c9b9

Browse files
release 0.15.0, fix #35, fix #24, fix #28, fix #29, fix #32, improved some refactor commands and folder_explorer
1 parent be03aed commit 068c9b9

14 files changed

+367
-201
lines changed

Diff for: README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ This plugin uses **[Flow](https://github.com/facebook/flow)** (javascript static
1111

1212
This is in **BETA** version for **testing**.
1313

14-
It offers better **javascript autocomplete** and also a lot of features about creating, developing and managing **javascript projects**, such as:
14+
It offers better **JavaScript autocomplete** and also a lot of features about creating, developing and managing [**JavaScript projects**](https://github.com/pichillilorenzo/JavaScriptEnhancements/wiki/Creating-a-JavaScript-Project), such as:
1515

1616
- Cordova projects (run cordova emulate, build, compile, serve, etc. directly from Sublime Text!)
1717
- Ionic v1 and v2 (it includes also v3) projects (same as Cordova projects!)
@@ -20,8 +20,9 @@ It offers better **javascript autocomplete** and also a lot of features about cr
2020
- React Native projects (only about the creation at this moment. I will add also **NativeScript** support)
2121
- Express projects (only about the creation at this moment)
2222
- Yeoman generators
23-
- Local bookmarks project
24-
- JavaScript real-time errors
23+
- [Local bookmarks project](https://github.com/pichillilorenzo/JavaScriptEnhancements/wiki/Features#bookmarks-project)
24+
- [JavaScript real-time errors](https://github.com/pichillilorenzo/JavaScriptEnhancements/wiki/Errors-and-linting)
25+
- [Code Refactoring](https://github.com/pichillilorenzo/JavaScriptEnhancements/wiki/Code-Refactoring)
2526
- etc.
2627

2728
You could use it also in **existing projects** (see the [Wiki](https://github.com/pichillilorenzo/JavaScriptEnhancements/wiki/Using-it-with-an-existing-project))!

Diff for: _generated_2018_02_11_at_03_11_05.py renamed to _generated_2018_02_11_at_19_44_22.py

+180-98
Large diffs are not rendered by default.

Diff for: changelog/0.15.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ v0.15.0
77
- Fixed "Create React App - Could not create a project called 'myApp' because of npm naming restrictions" #29, 'myApp' changed to 'my-app'
88
- Fixed an issue caused by "echo" command in .bash_profile and similar when loading the system PATH variable of an user
99
- Fixed Evaluate Javascript feature not working in Windows - "The filename, directory name, or volume label syntax is incorrect." error #32
10+
- Fixed ascii conversion of json.dumps call on Windows command arguments #35
1011

1112
## Improvements
1213

Diff for: src/_init.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,17 @@ def sublime_executable_path():
6666
def subl(args):
6767

6868
executable_path = sublime_executable_path()
69-
69+
args = [executable_path] + args
7070
args_list = list()
7171

7272
if sublime.platform() == 'windows' :
73-
args = [executable_path] + args
7473
for arg in args :
75-
args_list.append(json.dumps(arg))
76-
json.dumps(executable_path)
74+
args_list.append(json.dumps(arg, ensure_ascii=False))
7775
else :
7876
for arg in args :
7977
args_list.append(shlex.quote(arg))
80-
shlex.quote(executable_path)
8178

82-
args = executable_path + " " + " ".join(args_list)
79+
args = " ".join(args_list)
8380

8481
return subprocess.Popen(args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
8582

Diff for: src/can_i_use/can_i_use_data.json

+1-1
Large diffs are not rendered by default.

Diff for: src/create_class_from_object_literal_command.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ def run(self, edit, **args):
1515
object_literal_region = item_object_literal.get("region")
1616
selection = item_object_literal.get("selection")
1717
object_literal = item_object_literal.get("region_string_stripped")
18-
node = NodeJS()
18+
19+
node = NodeJS(check_local=True)
1920
object_literal = re.sub(r'[\n\r\t]', ' ', object_literal)
20-
object_literal = json.loads(node.eval("JSON.stringify("+object_literal+")", "print"))
21-
object_literal = [(key, json.dumps(value)) for key, value in object_literal.items()]
21+
object_literal = json.loads(node.eval("JSON.stringify("+object_literal+")", "print"), encoding="utf-8")
22+
object_literal = [(key, json.dumps(value, ensure_ascii=False)) for key, value in object_literal.items()]
2223

2324
list_ordered = ("keyword.operator.assignment.js", "variable.other.readwrite.js", "storage.type.js")
2425
items = Util.find_regions_on_same_depth_level(view, scope, selection, list_ordered, depth_level, False)
26+
2527
if items :
2628
last_selection = items[-1:][0].get("selection")
2729
class_name = items[1].get("region_string_stripped")

Diff for: src/folder_explorer/FolderExplorer.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ def open(self, path=""):
4848
self.current_path = path if path else self.current_path
4949

5050
if not os.path.isdir(self.current_path):
51-
self.current_path = os.path.dirname(self.current_path)
51+
prev_path = ""
52+
while not os.path.isdir(self.current_path) and prev_path != self.current_path:
53+
prev_path = self.current_path
54+
self.current_path = os.path.dirname(self.current_path)
5255

5356
try:
5457
for item in os.listdir(self.current_path):

Diff for: src/node/main.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,14 @@ def execute_check_output(self, command, command_args, is_from_bin=False, use_fp_
8282
for command_arg in command_args :
8383
if command_arg == ":temp_file":
8484
command_arg = fp.name
85-
command_args_list.append( (shlex.quote(command_arg) if sublime.platform() != 'windows' else json.dumps(command_arg)) if command_arg_escape else command_arg )
85+
command_args_list.append( (shlex.quote(command_arg) if sublime.platform() != 'windows' else json.dumps(command_arg, ensure_ascii=False)) if command_arg_escape else command_arg )
8686
command_args = " ".join(command_args_list)
8787

8888
if sublime.platform() == 'windows':
8989
if is_from_bin :
90-
args = json.dumps(os.path.join((bin_path or NODE_MODULES_BIN_PATH), command)+'.cmd')+' '+command_args+(' < '+json.dumps(fp.name) if fp and not use_only_filename_view_flow else "")
90+
args = json.dumps(os.path.join((bin_path or NODE_MODULES_BIN_PATH), command)+'.cmd', ensure_ascii=False)+' '+command_args+(' < '+json.dumps(fp.name, ensure_ascii=False) if fp and not use_only_filename_view_flow else "")
9191
else :
92-
args = ( json.dumps(self.node_js_path)+" " if use_node else "")+json.dumps(os.path.join((bin_path or NODE_MODULES_BIN_PATH), command))+" "+command_args+(" < "+json.dumps(fp.name) if fp and not use_only_filename_view_flow else "")
92+
args = ( json.dumps(self.node_js_path, ensure_ascii=False)+" " if use_node else "")+json.dumps(os.path.join((bin_path or NODE_MODULES_BIN_PATH), command), ensure_ascii=False)+" "+command_args+(" < "+json.dumps(fp.name, ensure_ascii=False) if fp and not use_only_filename_view_flow else "")
9393
else:
9494
args = ( shlex.quote(self.node_js_path)+" " if use_node else "")+shlex.quote(os.path.join((bin_path or NODE_MODULES_BIN_PATH), command))+" "+command_args+(" < "+shlex.quote(fp.name) if fp and not use_only_filename_view_flow else "")
9595

Diff for: src/project/npm/Main_disabled.sublime-menu

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
[{"id": "tools", "children": [{"id": "npm_scripts", "children": [], "caption": "Npm/Yarn Scripts"}], "caption": "Tools"}]
1+
[{"id": "tools", "caption": "Tools", "children": [{"id": "npm_scripts", "caption": "Npm/Yarn Scripts", "children": []}]}]

Diff for: src/refactor/refactor_extract_method_command.py

+80-26
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,59 @@ def run(self, edit, **args):
2020

2121
if inputs["scope"] == "Class method":
2222

23-
view.replace(edit, selection, "this."+function_name+parameters)
24-
region_class = Util.get_region_scope_first_match(view, scope, selection, 'meta.class.js')["region"]
25-
new_text = Util.replace_with_tab(view, selection, ("\t\n" if not Util.prev_line_is_empty(view, sublime.Region(region_class.end(), region_class.end())) else "")+"\t"+function_name+" "+parameters+" {\n\t", "\n\t}\n")
23+
flow_cli = "flow"
24+
is_from_bin = True
25+
chdir = ""
26+
use_node = True
27+
bin_path = ""
28+
29+
settings = get_project_settings()
30+
if settings and settings["project_settings"]["flow_cli_custom_path"]:
31+
flow_cli = os.path.basename(settings["project_settings"]["flow_cli_custom_path"])
32+
bin_path = os.path.dirname(settings["project_settings"]["flow_cli_custom_path"])
33+
is_from_bin = False
34+
chdir = settings["project_dir_name"]
35+
use_node = False
36+
37+
node = NodeJS(check_local=True)
38+
39+
result = node.execute_check_output(
40+
flow_cli,
41+
[
42+
'ast',
43+
'--from', 'sublime_text'
44+
],
45+
is_from_bin=is_from_bin,
46+
use_fp_temp=True,
47+
fp_temp_contents=view.substr(sublime.Region(0, view.size())),
48+
is_output_json=True,
49+
chdir=chdir,
50+
bin_path=bin_path,
51+
use_node=use_node
52+
)
53+
54+
if result[0]:
55+
if "body" in result[1]:
56+
body = result[1]["body"]
57+
items = Util.nested_lookup("type", ["ClassBody"], body)
58+
last_block_statement = None
59+
last_item = None
60+
region = None
61+
62+
for item in items:
63+
region = sublime.Region(int(item["range"][0]), int(item["range"][1]))
64+
if region.contains(selection):
65+
prev_line_is_empty = Util.prev_line_is_empty(view, sublime.Region(region.end(), region.end()))
66+
space = Util.get_whitespace_from_line_begin(view, selection)
67+
space_before = ("\n\t" if not prev_line_is_empty else "\t")
68+
space_after = "\n\n"
69+
new_text = Util.replace_with_tab(view, selection, space_before+function_name+" "+parameters+" {\n", "\n\t}" + space_after, add_to_each_line_before="\t", lstrip=True)
70+
71+
view.insert(edit, region.end() - 1, new_text)
72+
view.erase(edit, selection)
73+
view.insert(edit, selection.begin(), "this." + function_name + parameters)
2674

27-
view.insert(edit, region_class.end()-1, new_text)
75+
break
2876

2977
elif inputs["scope"] == "Current scope":
3078

@@ -68,9 +116,9 @@ def run(self, edit, **args):
68116
region = None
69117

70118
for item in items:
71-
region = sublime.Region(int(item["range"][0]), int(item["range"][1]))
72-
if region.contains(selection):
73-
last_block_statement = region
119+
r = sublime.Region(int(item["range"][0]), int(item["range"][1]))
120+
if r.contains(selection):
121+
last_block_statement = r
74122
last_item = item
75123

76124
if last_block_statement:
@@ -79,6 +127,10 @@ def run(self, edit, **args):
79127
if r.contains(selection):
80128
region = r
81129
break
130+
131+
if not region:
132+
region = last_block_statement
133+
82134
else:
83135
for item in body:
84136
r = sublime.Region(int(item["range"][0]), int(item["range"][1]))
@@ -88,18 +140,18 @@ def run(self, edit, **args):
88140

89141
if region:
90142
prev_line_is_empty = Util.prev_line_is_empty(view, selection)
91-
next_line_is_empty = Util.next_line_is_empty(view, selection)
92143
space = Util.get_whitespace_from_line_begin(view, selection)
93-
space_before = ("\n" + space if not prev_line_is_empty else "")
94-
space_after = "\n" + space
144+
space_before = ("\n" + space if not prev_line_is_empty else ( space if view.substr(region).startswith("{") else ""))
145+
space_after = (( "\n" + space if not view.substr(region).startswith("{") else "\n") if not prev_line_is_empty else "\n" + space)
95146
new_text = Util.replace_with_tab(view, selection, space_before+"function "+function_name+" "+parameters+" {\n"+space, "\n"+space+"}" + space_after)
147+
contains_this = Util.region_contains_scope(view, selection, "variable.language.this.js")
96148

97149
view.erase(edit, selection)
98-
if Util.region_contains_scope(view, selection, "variable.language.this.js"):
150+
if contains_this:
99151
view.insert(edit, selection.begin(), function_name+".call(this"+(", "+parameters[1:-1] if parameters[1:-1].strip() else "")+")" )
100152
else:
101153
view.insert(edit, selection.begin(), function_name+parameters)
102-
view.insert(edit, region.begin() + (1 if view.substr(region.begin()) == "{" else 0), new_text)
154+
view.insert(edit, (view.full_line(region.begin()).end() if view.substr(region).startswith("{") else region.begin()), new_text)
103155

104156
elif inputs["scope"] == "Global scope":
105157

@@ -137,15 +189,18 @@ def run(self, edit, **args):
137189
if result[0]:
138190
if "body" in result[1]:
139191
body = result[1]["body"]
140-
items = Util.nested_lookup("type", ["BlockStatement"], body, return_parent=True)[::-1]
192+
items = Util.nested_lookup("type", ["ClassBody", "BlockStatement"], body, return_parent=True)
141193
region = None
142194

143-
for item in items:
144-
r = sublime.Region(int(item["range"][0]), int(item["range"][1]))
145-
if r.contains(selection):
146-
region = r
147-
break
148-
else:
195+
if items:
196+
items_sorted = sorted(items, key=lambda item: int(item["range"][0]))
197+
for item in items_sorted:
198+
r = sublime.Region(int(item["range"][0]), int(item["range"][1]))
199+
if r.contains(selection):
200+
region = r
201+
break
202+
203+
if not region:
149204
for item in body:
150205
r = sublime.Region(int(item["range"][0]), int(item["range"][1]))
151206
if r.contains(selection) or r.intersects(selection):
@@ -155,17 +210,16 @@ def run(self, edit, **args):
155210
if region:
156211

157212
prev_line_is_empty = Util.prev_line_is_empty(view, region)
158-
next_line_is_empty = Util.next_line_is_empty(view, region)
159213
space_before = ("\n" if not prev_line_is_empty else "")
160-
161214
new_text = Util.replace_with_tab(view, selection, space_before+"function "+function_name+" "+parameters+" {\n", "\n}\n\n", lstrip=True)
215+
contains_this = Util.region_contains_scope(view, selection, "variable.language.this.js")
162216

163-
view.erase(edit, selection)
164-
view.insert(edit, region.begin(), new_text)
165-
if Util.region_contains_scope(view, selection, "variable.language.this.js"):
166-
view.insert(edit, selection.begin() + len(Util.convert_tabs_using_tab_size(view, new_text)), function_name+".call(this"+(", "+parameters[1:-1] if parameters[1:-1].strip() else "")+")" )
217+
view.erase(edit, selection)
218+
if contains_this:
219+
view.insert(edit, selection.begin(), function_name+".call(this"+(", "+parameters[1:-1] if parameters[1:-1].strip() else "")+")" )
167220
else:
168-
view.insert(edit, selection.begin() + len(Util.convert_tabs_using_tab_size(view, new_text)), function_name+parameters)
221+
view.insert(edit, selection.begin(), function_name+parameters)
222+
view.insert(edit, region.begin(), new_text)
169223

170224
windowViewManager.close(view.id())
171225

Diff for: src/refactor/refactor_safe_copy_command.py

+37-23
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ def run(self, edit, **args):
1111
settings = get_project_settings()
1212
preview_view = None
1313

14+
if view.is_dirty():
15+
sublime.error_message("Cannot copy this file. There are unsaved modifications to the buffer. Save the file before use this.")
16+
return
17+
1418
if not file_name:
1519
sublime.error_message("Cannot copy this file. File name is empty.")
1620
return
@@ -55,10 +59,14 @@ def run(self, edit, **args):
5559
with open(file_name, "r", encoding="utf-8") as file:
5660
content = file.read()
5761
preview_content = ""
62+
delta = 0
63+
lines_updated = []
64+
65+
requirements_sorted = sorted(imports[file_name]["requirements"], key=lambda req: int(req["loc"]["start"]["offset"]))
5866

59-
for req in imports[file_name]["requirements"]:
60-
start_offset = int(req["loc"]["start"]["offset"]) + 1
61-
end_offset = int(req["loc"]["end"]["offset"]) - 1
67+
for req in requirements_sorted:
68+
start_offset = int(req["loc"]["start"]["offset"]) + 1 + delta if sublime.platform() != "windows" else view.text_point(int(req["line"]) - 1, int(req["start"])) + delta
69+
end_offset = int(req["loc"]["end"]["offset"]) - 1 + delta if sublime.platform() != "windows" else view.text_point(int(req["endline"]) - 1, int(req["end"]) - 1) + delta
6270

6371
req_new_path = req["import"] if os.path.isabs(req["import"]) else os.path.abspath(os.path.dirname(file_name) + os.path.sep + req["import"])
6472

@@ -73,27 +81,33 @@ def run(self, edit, **args):
7381
if not rel_new_path.startswith(".."):
7482
rel_new_path = "./" + rel_new_path
7583

76-
77-
content = content [:start_offset] + rel_new_path + content[end_offset:]
84+
delta += len(rel_new_path) - len(content[start_offset:end_offset])
85+
content = content[:start_offset] + rel_new_path + content[end_offset:]
7886

7987
if args.get("preview"):
80-
splitted_content = content.splitlines()
81-
82-
if not preview_content:
83-
preview_content = "- From:\n" + file_name + "\n\n"
84-
preview_content += "- To:\n" + new_path + "\n\n"
85-
8688
line = int(req["line"]) - 1
87-
range_start = max(0, line - 2)
88-
range_end = min(line + 2, len(splitted_content) - 1)
89-
while range_start <= range_end:
90-
line_number = str(range_start + 1)
91-
space_before_line_number = " " * ( 5 - len(line_number) )
92-
preview_content += space_before_line_number + line_number + (": " if line == range_start else " ") + splitted_content[range_start] + "\n"
93-
range_start += 1
94-
preview_content += "\n\n"
89+
lines_updated.append(line)
9590

9691
if args.get("preview"):
92+
splitted_content = content.splitlines()
93+
94+
preview_content = "- Copy From:\n" + file_name + "\n\n"
95+
preview_content += "- To:\n" + new_path + "\n\n"
96+
97+
range_start_before = -1
98+
is_first_range_start = True
99+
100+
for range_start in lines_updated:
101+
line_number = str(range_start + 1)
102+
space_before_line_number = " " * ( 5 - len(line_number) )
103+
if range_start - 1 != range_start_before and not is_first_range_start:
104+
space_before_line_number = space_before_line_number + ("." * len(line_number) ) + "\n" + space_before_line_number
105+
is_first_range_start = False
106+
preview_content += space_before_line_number + line_number + (": " if range_start in lines_updated else " ") + splitted_content[range_start] + "\n"
107+
range_start_before = range_start
108+
range_start += 1
109+
110+
preview_content += "\n\n"
97111
preview_view.append_text(preview_content)
98112

99113
if not args.get("preview"):
@@ -136,12 +150,12 @@ def get_imports(self, settings, javascript_files):
136150
index = 0
137151
for i in range(0, len(javascript_files)):
138152

139-
if len(javascript_files_temp + " " + json.dumps(javascript_files[i])) <= 7500 :
153+
if len(javascript_files_temp + " " + json.dumps(javascript_files[i], ensure_ascii=False)) <= 7500 :
140154

141155
if not javascript_files_temp:
142-
javascript_files_temp = json.dumps(javascript_files[i])
156+
javascript_files_temp = json.dumps(javascript_files[i], ensure_ascii=False)
143157
else:
144-
javascript_files_temp += " " + json.dumps(javascript_files[i])
158+
javascript_files_temp += " " + json.dumps(javascript_files[i], ensure_ascii=False)
145159

146160
if i < len(javascript_files) - 1:
147161
continue
@@ -169,7 +183,7 @@ def get_imports(self, settings, javascript_files):
169183
return {}
170184

171185
index = i
172-
javascript_files_temp = json.dumps(javascript_files[i])
186+
javascript_files_temp = json.dumps(javascript_files[i], ensure_ascii=False)
173187

174188
return imports
175189
else:

0 commit comments

Comments
 (0)