Skip to content

Commit ac620a9

Browse files
Forced 'auto_complete_delay' option to 0 when showing JavaScript auto-completions, added extract field refactor command
1 parent 81a342f commit ac620a9

File tree

7 files changed

+627
-6
lines changed

7 files changed

+627
-6
lines changed

Context.sublime-menu

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@
104104
"case": "extract_variable"
105105
}
106106
},
107+
{
108+
"caption": "Field",
109+
"command": "refactor",
110+
"args": {
111+
"case": "extract_field"
112+
}
113+
},
107114
{
108115
"caption": "Parameter",
109116
"command": "refactor",

_generated_2018_02_04_at_04_47_41.py renamed to _generated_2018_02_04_at_18_22_03.py

Lines changed: 308 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,15 @@ def add_whitespace_indentation(view, region, string, replace="\t", add_whitespac
822822
string = re.sub("(["+replace+"]+)", whitespace+r"\1", string)
823823
return string
824824

825+
@staticmethod
826+
def convert_tabs_using_tab_size(view, string):
827+
tab_size = view.settings().get("tab_size")
828+
829+
if tab_size:
830+
return string.replace("\t", " "*tab_size)
831+
832+
return string.replace("\t", " ")
833+
825834
@staticmethod
826835
def go_to_centered(view, row, col):
827836
while view.is_loading() :
@@ -3827,7 +3836,8 @@ def run_auto_complete(self):
38273836
'disable_auto_insert': True,
38283837
'api_completions_only': False,
38293838
'next_completion_if_showing': False,
3830-
'auto_complete_commit_on_tab': True
3839+
'auto_complete_commit_on_tab': True,
3840+
'auto_complete_delay': 0
38313841
})
38323842

38333843
def on_query_completions(self, view, prefix, locations):
@@ -6027,7 +6037,7 @@ def run(self, edit, **args):
60276037
if view.sel()[0].begin() == view.sel()[0].end():
60286038
return
60296039

6030-
select_options = ['Global scope', 'Current Scope', 'Class method']
6040+
select_options = ['Global scope', 'Current scope', 'Class method']
60316041
if not view.match_selector(view.sel()[0].begin(), 'meta.class.js'):
60326042
select_options.remove('Class method')
60336043
if len(scope.split(" ")) < 2:
@@ -6059,6 +6069,24 @@ def run(self, edit, **args):
60596069

60606070
self.view.run_command("refactor_extract_variable")
60616071

6072+
elif case == "extract_field" :
6073+
if view.sel()[0].begin() == view.sel()[0].end() or not view.match_selector(view.sel()[0].begin(), 'meta.class.js'):
6074+
return
6075+
6076+
select_options = ["Current method", "Field declaration", "Class constructor"]
6077+
6078+
windowView = WindowView(title="Refactor - Extract Field", use_compare_layout=True)
6079+
windowView.addTitle(text="Refactor - Extract Field")
6080+
windowView.add(text="\n\n")
6081+
windowView.addInput(value="new_field", label="Field Name: ", region_id="field_name")
6082+
windowView.add(text="\n")
6083+
windowView.addSelect(default_option=0, options=select_options, label="Scope: ", region_id="scope")
6084+
windowView.add(text="\n\n")
6085+
windowView.addCloseButton(text="OK", scope="javascriptenhancements.button_ok", callback=lambda view: self.view.run_command("refactor_extract_field", args={"inputs": windowView.getInputs()}))
6086+
windowView.add(text=" ")
6087+
windowView.addCloseButton(text="CANCEL", scope="javascriptenhancements.button_cancel")
6088+
windowView.add(text=" \n")
6089+
60626090
def is_enabled(self, **args) :
60636091

60646092
view = self.view
@@ -6963,6 +6991,284 @@ def is_visible(self, **args) :
69636991
return selection.begin() != selection.end()
69646992

69656993

6994+
import sublime, sublime_plugin
6995+
6996+
class RefactorExtractFieldCommand(sublime_plugin.TextCommand):
6997+
def run(self, edit, **args):
6998+
view = self.view
6999+
selection = view.sel()[0]
7000+
inputs = args.get("inputs")
7001+
content = view.substr(selection).strip()
7002+
content = content[:-1] if content[-1] == ";" else content
7003+
field_name = inputs["field_name"]
7004+
7005+
flow_cli = "flow"
7006+
is_from_bin = True
7007+
chdir = ""
7008+
use_node = True
7009+
bin_path = ""
7010+
7011+
settings = get_project_settings()
7012+
if settings and settings["project_settings"]["flow_cli_custom_path"]:
7013+
flow_cli = os.path.basename(settings["project_settings"]["flow_cli_custom_path"])
7014+
bin_path = os.path.dirname(settings["project_settings"]["flow_cli_custom_path"])
7015+
is_from_bin = False
7016+
chdir = settings["project_dir_name"]
7017+
use_node = False
7018+
7019+
node = NodeJS(check_local=True)
7020+
7021+
result = node.execute_check_output(
7022+
flow_cli,
7023+
[
7024+
'ast',
7025+
'--from', 'sublime_text'
7026+
],
7027+
is_from_bin=is_from_bin,
7028+
use_fp_temp=True,
7029+
fp_temp_contents=content,
7030+
is_output_json=True,
7031+
chdir=chdir,
7032+
bin_path=bin_path,
7033+
use_node=use_node
7034+
)
7035+
7036+
if result[0] and not result[1]["errors"] and result[1]["body"] and "type" in result[1]["body"][0] and result[1]["body"][0]["type"] == "ExpressionStatement":
7037+
7038+
result = node.execute_check_output(
7039+
flow_cli,
7040+
[
7041+
'ast',
7042+
'--from', 'sublime_text'
7043+
],
7044+
is_from_bin=is_from_bin,
7045+
use_fp_temp=True,
7046+
fp_temp_contents=view.substr(sublime.Region(0, view.size())),
7047+
is_output_json=True,
7048+
chdir=chdir,
7049+
bin_path=bin_path,
7050+
use_node=use_node
7051+
)
7052+
7053+
if result[0]:
7054+
if "body" in result[1]:
7055+
body = result[1]["body"]
7056+
classes = Util.nested_lookup("type", ["ClassDeclaration"], body)
7057+
_class = None
7058+
class_region = None
7059+
7060+
for c in classes:
7061+
r = sublime.Region(int(c["range"][0]), int(c["range"][1]))
7062+
if r.contains(selection):
7063+
_class = c
7064+
class_region = r
7065+
break
7066+
7067+
if class_region:
7068+
7069+
items = Util.nested_lookup("type", ["BlockStatement"], _class)
7070+
last_block_statement = None
7071+
last_item = None
7072+
region = None
7073+
constructor_region = None
7074+
constructor_method = None
7075+
7076+
method_definitions = Util.nested_lookup("type", ["MethodDefinition"], _class)
7077+
7078+
for method in method_definitions:
7079+
if method["kind"] == "constructor":
7080+
constructor_method = method
7081+
constructor_region = sublime.Region(int(method["value"]["body"]["range"][0]), int(method["value"]["body"]["range"][1]))
7082+
break
7083+
7084+
for item in items:
7085+
r = sublime.Region(int(item["range"][0]), int(item["range"][1]))
7086+
if r.contains(selection):
7087+
last_block_statement = r
7088+
last_item = item
7089+
7090+
if last_block_statement:
7091+
for item in last_item["body"]:
7092+
r = sublime.Region(int(item["range"][0]), int(item["range"][1]))
7093+
if r.contains(selection):
7094+
region = r
7095+
break
7096+
7097+
if region:
7098+
7099+
class_properties = Util.nested_lookup("type", ["ClassProperty"], _class)
7100+
last_class_property = None
7101+
region_last_class_property = None
7102+
if len(class_properties) > 0:
7103+
last_class_property = class_properties[-1]
7104+
region_last_class_property = sublime.Region(int(last_class_property["range"][0]), int(last_class_property["range"][1]))
7105+
7106+
if not constructor_region and inputs["scope"] == "Class constructor":
7107+
if region_last_class_property:
7108+
view.insert(edit, region_last_class_property.end(), "\n\n\tconstructor () {\n\t}")
7109+
else:
7110+
view.insert(edit, int(_class["body"]["range"][0]) + 1, "\n\n\tconstructor () {\n\t}")
7111+
7112+
# create the constructor method and then execute this command again
7113+
view.run_command("refactor_extract_field", args={"inputs": inputs})
7114+
return
7115+
7116+
prev_line_is_empty = Util.prev_line_is_empty(view, region)
7117+
7118+
space = ""
7119+
if inputs["scope"] == "Current method" or inputs["scope"] == "Class constructor":
7120+
space = Util.get_whitespace_from_line_begin(
7121+
view,
7122+
(
7123+
region
7124+
if inputs["scope"] == "Current method"
7125+
else sublime.Region(int(constructor_method["range"][0]), int(constructor_method["range"][1]))
7126+
)
7127+
)
7128+
if inputs["scope"] == "Class constructor":
7129+
space += Util.convert_tabs_using_tab_size(view, "\t")
7130+
7131+
str_assignement = "this." + (field_name + " = " + content if inputs["scope"] == "Current method" or inputs["scope"] == "Class constructor" else field_name)
7132+
7133+
is_line_empty = view.substr(view.line(selection)).strip().replace(view.substr(selection), "") == ""
7134+
7135+
view.erase(edit, selection)
7136+
7137+
if not is_line_empty:
7138+
view.insert(edit, selection.begin(), "this." + field_name)
7139+
if inputs["scope"] == "Current method":
7140+
str_assignement = ("\n" + space if not prev_line_is_empty else "") + "this." + field_name + " = " + content + "\n" + space
7141+
view.insert(edit, region.begin(), str_assignement)
7142+
else:
7143+
str_assignement = ""
7144+
else:
7145+
if inputs["scope"] == "Class constructor":
7146+
view.insert(edit, selection.begin(), "this." + field_name)
7147+
else:
7148+
view.insert(edit, selection.begin(), str_assignement)
7149+
7150+
if inputs["scope"] == "Class constructor":
7151+
str_assignement = "\n" + space + "this." + field_name + " = " + content + ("\n" + space if view.substr(constructor_region).splitlines()[0].strip().replace("{", "") != "" else "")
7152+
view.insert(edit, constructor_region.begin() + 1, str_assignement)
7153+
7154+
str_class_property = ""
7155+
if region_last_class_property:
7156+
str_class_property = "\n\t" + (field_name if inputs["scope"] == "Current method" or inputs["scope"] == "Class constructor" else field_name + " = " + content) + ";"
7157+
view.insert(edit, region_last_class_property.end(), str_class_property)
7158+
else:
7159+
str_class_property = "\n\n\t" + (field_name if inputs["scope"] == "Current method" or inputs["scope"] == "Class constructor" else field_name + " = " + content) + ";"
7160+
view.insert(edit, int(_class["body"]["range"][0])+1, str_class_property)
7161+
7162+
str_class_property = Util.convert_tabs_using_tab_size(view, str_class_property)
7163+
7164+
view.sel().clear()
7165+
7166+
if not is_line_empty:
7167+
7168+
view.sel().add(
7169+
sublime.Region(
7170+
selection.begin()+len("this.")+len(str_assignement)+len(str_class_property),
7171+
selection.begin()+len("this.")+len(str_assignement)+len(field_name)+len(str_class_property)
7172+
)
7173+
)
7174+
7175+
if inputs["scope"] == "Current method" or inputs["scope"] == "Class constructor":
7176+
7177+
view.sel().add(
7178+
sublime.Region(
7179+
(
7180+
region.begin()
7181+
if inputs["scope"] == "Current method"
7182+
else constructor_region.begin() + 1
7183+
) +
7184+
len(("\n" + space if not prev_line_is_empty else "") + "this.") +
7185+
len(str_class_property)
7186+
7187+
,
7188+
7189+
(
7190+
region.begin()
7191+
if inputs["scope"] == "Current method"
7192+
else constructor_region.begin() + 1
7193+
) +
7194+
len(("\n" + space if not prev_line_is_empty else "") + "this.") +
7195+
len(field_name) +
7196+
len(str_class_property)
7197+
)
7198+
)
7199+
7200+
else:
7201+
view.sel().add(
7202+
sublime.Region(
7203+
selection.begin() +
7204+
len("this.") +
7205+
len(str_class_property) +
7206+
(len(str_assignement) if inputs["scope"] == "Class constructor" else 0)
7207+
7208+
,
7209+
7210+
selection.begin() +
7211+
len("this.") +
7212+
len(field_name) +
7213+
len(str_class_property) +
7214+
(len(str_assignement) if inputs["scope"] == "Class constructor" else 0)
7215+
)
7216+
)
7217+
7218+
if inputs["scope"] == "Class constructor":
7219+
view.sel().add(
7220+
sublime.Region(
7221+
constructor_region.begin() + 1 +
7222+
len(("\n" + space if not prev_line_is_empty else "") + "this.") +
7223+
len(str_class_property)
7224+
7225+
,
7226+
7227+
constructor_region.begin() + 1 +
7228+
len(("\n" + space if not prev_line_is_empty else "") + "this.") +
7229+
len(field_name) +
7230+
len(str_class_property)
7231+
)
7232+
)
7233+
7234+
tab_to_string = Util.convert_tabs_using_tab_size(view, "\t")
7235+
7236+
if region_last_class_property:
7237+
view.sel().add(
7238+
sublime.Region(
7239+
region_last_class_property.end()+len("\n" + tab_to_string),
7240+
region_last_class_property.end()+len("\n" + tab_to_string)+len(field_name)
7241+
)
7242+
)
7243+
else:
7244+
view.sel().add(
7245+
sublime.Region(
7246+
int(_class["body"]["range"][0])+1+len("\n\n" + tab_to_string),
7247+
int(_class["body"]["range"][0])+1+len("\n\n" + tab_to_string)+len(field_name)
7248+
)
7249+
)
7250+
7251+
else:
7252+
sublime.error_message("Cannot introduce property. Some problems occured.")
7253+
7254+
else:
7255+
sublime.error_message("Cannot introduce property. Selection does not form an ExpressionStatement.")
7256+
7257+
def is_enabled(self, **args) :
7258+
view = self.view
7259+
if not Util.selection_in_js_scope(view) :
7260+
return False
7261+
selection = view.sel()[0]
7262+
return selection.begin() != selection.end()
7263+
7264+
def is_visible(self, **args) :
7265+
view = self.view
7266+
if not Util.selection_in_js_scope(view) :
7267+
return False
7268+
selection = view.sel()[0]
7269+
return selection.begin() != selection.end()
7270+
7271+
69667272
import sublime, sublime_plugin
69677273
import os
69687274

changelog/0.14.0.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ v0.14.0
1111
## Improvements
1212

1313
- Show hint_parameters tooltip on commit_completion and on insert_snippet "()"
14-
- Added JavaScript Refactor command:
14+
- Added JavaScript Refactor commands (added to Context and Side Bar menus):
1515
* Safe Copy
1616
* Safe Move
1717
* Safe Delete
1818
* Extract Method (global scope, current scope, class method)
1919
* Extract Parameter
2020
* Extract Variable
21+
* Extract Field
2122
- Added "Open TerminalView Here…" command to Context Menu and Side Bar Menu
23+
- Forced "auto_complete_delay" option to 0 when showing JavaScript auto-completions
2224

2325

2426
=================================================================

helper/javascript_completions/on_query_completions_event_listener.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ def run_auto_complete(self):
5555
'disable_auto_insert': True,
5656
'api_completions_only': False,
5757
'next_completion_if_showing': False,
58-
'auto_complete_commit_on_tab': True
58+
'auto_complete_commit_on_tab': True,
59+
'auto_complete_delay': 0
5960
})
6061

6162
def on_query_completions(self, view, prefix, locations):

0 commit comments

Comments
 (0)