5
5
from os import environ
6
6
from subprocess import Popen , PIPE
7
7
8
- PLUGIN_VERSION = "0.14 .0"
8
+ PLUGIN_VERSION = "0.15 .0"
9
9
10
10
PACKAGE_PATH = os .path .abspath (os .path .dirname (__file__ ))
11
11
PACKAGE_NAME = os .path .basename (PACKAGE_PATH )
@@ -994,10 +994,11 @@ def selection_in_js_scope(view, point = -1, except_for = ""):
994
994
return False
995
995
996
996
@staticmethod
997
- def replace_with_tab (view , region , pre = "" , after = "" , add_to_each_line_before = "" , add_to_each_line_after = "" ) :
998
- lines = view .substr (region ).split ( " \n " )
997
+ def replace_with_tab (view , region , pre = "" , after = "" , add_to_each_line_before = "" , add_to_each_line_after = "" , lstrip = False ) :
998
+ lines = view .substr (region ).splitlines ( )
999
999
body = list ()
1000
1000
empty_line = 0
1001
+ first_line = False
1001
1002
for line in lines :
1002
1003
if line .strip () == "" :
1003
1004
empty_line = empty_line + 1
@@ -1006,15 +1007,17 @@ def replace_with_tab(view, region, pre="", after="", add_to_each_line_before="",
1006
1007
continue
1007
1008
else :
1008
1009
empty_line = 0
1009
- line = "\t " + add_to_each_line_before + line + add_to_each_line_after
1010
+ line = ("\t " if (line and line [0 ] == " " ) or not first_line else "" ) + add_to_each_line_before + (line .lstrip () if lstrip else line ) + add_to_each_line_after
1011
+ if not first_line :
1012
+ first_line = True
1010
1013
body .append (line )
1011
1014
if body [len (body )- 1 ].strip () == "" :
1012
1015
del body [len (body )- 1 ]
1013
1016
body = "\n " .join (body )
1014
1017
return pre + body + after
1015
1018
1016
1019
@staticmethod
1017
- def replace_without_tab (view , region , pre = "" , after = "" , add_to_each_line_before = "" , add_to_each_line_after = "" ) :
1020
+ def replace_without_tab (view , region , pre = "" , after = "" , add_to_each_line_before = "" , add_to_each_line_after = "" , lstrip = False ) :
1018
1021
lines = view .substr (region ).split ("\n " )
1019
1022
body = list ()
1020
1023
empty_line = 0
@@ -1026,15 +1029,16 @@ def replace_without_tab(view, region, pre="", after="", add_to_each_line_before=
1026
1029
continue
1027
1030
else :
1028
1031
empty_line = 0
1029
- body .append (add_to_each_line_before + line + add_to_each_line_after )
1032
+ body .append (add_to_each_line_before + ( line . lstrip () if lstrip else line ) + add_to_each_line_after )
1030
1033
if body [len (body )- 1 ].strip () == "" :
1031
1034
del body [len (body )- 1 ]
1032
1035
body = "\n " .join (body )
1033
1036
return pre + body + after
1034
1037
1035
1038
@staticmethod
1036
1039
def get_whitespace_from_line_begin (view , region ) :
1037
- return " " * ( region .begin () - view .line (region ).begin () )
1040
+ n_space = len (view .substr (view .line (region ))) - len (view .substr (view .line (region )).lstrip ())
1041
+ return " " * n_space
1038
1042
1039
1043
@staticmethod
1040
1044
def add_whitespace_indentation (view , region , string , replace = "\t " , add_whitespace_end = True ) :
@@ -1262,30 +1266,30 @@ def _wrapper_func_stdout_listen_error(process, func_stdout=None, args_func_stdou
1262
1266
char = b""
1263
1267
1264
1268
@staticmethod
1265
- def nested_lookup (key , values , document , wild = False ):
1269
+ def nested_lookup (key , values , document , wild = False , return_parent = False ):
1266
1270
"""Lookup a key in a nested document, return a list of values"""
1267
- return list (Util ._nested_lookup (key , values , document , wild = wild ))
1271
+ return list (Util ._nested_lookup (key , values , document , wild = wild , return_parent = return_parent ))
1268
1272
1269
1273
@staticmethod
1270
- def _nested_lookup (key , values , document , wild = False ):
1274
+ def _nested_lookup (key , values , document , wild = False , return_parent = False ):
1271
1275
"""Lookup a key in a nested document, yield a value"""
1272
1276
if isinstance (document , list ):
1273
1277
for d in document :
1274
- for result in Util ._nested_lookup (key , values , d , wild = wild ):
1278
+ for result in Util ._nested_lookup (key , values , d , wild = wild , return_parent = ( document if return_parent else False ) ):
1275
1279
yield result
1276
1280
1277
1281
if isinstance (document , dict ):
1278
1282
for k , v in document .items ():
1279
1283
if values and v in values and (key == k or (wild and key .lower () in k .lower ())):
1280
- yield document
1284
+ yield ( document if not return_parent else return_parent )
1281
1285
elif not values and key == k or (wild and key .lower () in k .lower ()):
1282
- yield document
1286
+ yield ( document if not return_parent else return_parent )
1283
1287
elif isinstance (v , dict ):
1284
- for result in Util ._nested_lookup (key , values , v , wild = wild ):
1288
+ for result in Util ._nested_lookup (key , values , v , wild = wild , return_parent = ( document if return_parent else False ) ):
1285
1289
yield result
1286
1290
elif isinstance (v , list ):
1287
1291
for d in v :
1288
- for result in Util ._nested_lookup (key , values , d , wild = wild ):
1292
+ for result in Util ._nested_lookup (key , values , d , wild = wild , return_parent = ( document if return_parent else False ) ):
1289
1293
yield result
1290
1294
1291
1295
import time , os , re , threading , socket , traceback , sys , struct
@@ -6522,7 +6526,7 @@ def run(self, edit, **args):
6522
6526
windowView = WindowView (title = "Refactor - Safe Move" , use_compare_layout = True )
6523
6527
windowView .addTitle (text = "Refactor - Safe Move" )
6524
6528
windowView .add (text = "\n \n " )
6525
- windowView .add (text = "NOTE: If you want this command checks all files and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
6529
+ windowView .add (text = "NOTE: If you want this command checks all the imported/exported JavaScript dependencies and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
6526
6530
windowView .addLink (text = "here" , link = "https://flow.org/en/docs/config/options/#toc-all-boolean" , scope = "flow-toc-all-boolean" )
6527
6531
windowView .add (text = ".\n \n " )
6528
6532
windowView .addInput (value = view .file_name (), label = "Move to: " , region_id = "new_path" )
@@ -6539,7 +6543,7 @@ def run(self, edit, **args):
6539
6543
windowView = WindowView (title = "Refactor - Safe Copy" , use_compare_layout = True )
6540
6544
windowView .addTitle (text = "Refactor - Safe Copy" )
6541
6545
windowView .add (text = "\n \n " )
6542
- windowView .add (text = "NOTE: If you want this command checks all files and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
6546
+ windowView .add (text = "NOTE: If you want this command checks all the imported/exported JavaScript dependencies and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
6543
6547
windowView .addLink (text = "here" , link = "https://flow.org/en/docs/config/options/#toc-all-boolean" , scope = "flow-toc-all-boolean" )
6544
6548
windowView .add (text = ".\n \n " )
6545
6549
windowView .addInput (value = view .file_name (), label = "Copy to: " , region_id = "new_path" )
@@ -6556,7 +6560,7 @@ def run(self, edit, **args):
6556
6560
windowView = WindowView (title = "Refactor - Safe Delete" , use_compare_layout = True )
6557
6561
windowView .addTitle (text = "Refactor - Safe Delete" )
6558
6562
windowView .add (text = "\n \n " )
6559
- windowView .add (text = "NOTE: If you want this command checks all files and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
6563
+ windowView .add (text = "NOTE: If you want this command checks all the imported/exported JavaScript dependencies and not just those with @flow, you need to add \" all=true\" into the .flowconfig [options]. See " )
6560
6564
windowView .addLink (text = "here" , link = "https://flow.org/en/docs/config/options/#toc-all-boolean" , scope = "flow-toc-all-boolean" )
6561
6565
windowView .add (text = ".\n \n " )
6562
6566
windowView .add (text = "File to delete: " + view .file_name ())
@@ -6575,9 +6579,6 @@ def run(self, edit, **args):
6575
6579
select_options = ['Global scope' , 'Current scope' , 'Class method' ]
6576
6580
if not view .match_selector (view .sel ()[0 ].begin (), 'meta.class.js' ):
6577
6581
select_options .remove ('Class method' )
6578
- print (scope , len (scope .split (" " )))
6579
- if len (scope .split (" " )) <= 2 :
6580
- select_options .remove ('Global scope' )
6581
6582
6582
6583
windowView = WindowView (title = "Refactor - Extract Method" , use_compare_layout = True )
6583
6584
windowView .addTitle (text = "Refactor - Extract Method" )
@@ -7362,8 +7363,8 @@ class RefactorExtractMethodCommand(sublime_plugin.TextCommand):
7362
7363
def run (self , edit , ** args ):
7363
7364
view = self .view
7364
7365
selection = view .sel ()[0 ]
7366
+ selection = Util .trim_Region (view , selection )
7365
7367
inputs = args .get ("inputs" )
7366
- view_id_caller = args .get ("view_id_caller" ) if "view_id_caller" in args else None
7367
7368
scope = view .scope_name (selection .begin ()).strip ()
7368
7369
function_name = inputs ["function_name" ].strip ()
7369
7370
parameters = inputs ["parameters" ].strip ()
@@ -7440,34 +7441,92 @@ def run(self, edit, **args):
7440
7441
else :
7441
7442
for item in body :
7442
7443
r = sublime .Region (int (item ["range" ][0 ]), int (item ["range" ][1 ]))
7443
- if r .contains (selection ):
7444
+ if r .contains (selection ) or r . intersects ( selection ) :
7444
7445
region = r
7445
7446
break
7446
7447
7447
7448
if region :
7449
+ prev_line_is_empty = Util .prev_line_is_empty (view , selection )
7450
+ next_line_is_empty = Util .next_line_is_empty (view , selection )
7451
+ space = Util .get_whitespace_from_line_begin (view , selection )
7452
+ space_before = ("\n " + space if not prev_line_is_empty else "" )
7453
+ space_after = "\n " + space
7454
+ new_text = Util .replace_with_tab (view , selection , space_before + "function " + function_name + " " + parameters + " {\n " + space , "\n " + space + "}" + space_after )
7448
7455
7449
- space = Util .get_whitespace_from_line_begin (view , region )
7450
- new_text = Util .replace_with_tab (view , selection , "function " + function_name + " " + parameters + " {\n " + space , "\n " + space + "}\n " + space )
7456
+ view .erase (edit , selection )
7451
7457
if Util .region_contains_scope (view , selection , "variable.language.this.js" ):
7452
- view .replace (edit , selection , function_name + ".call(this" + (", " + parameters [1 :- 1 ] if parameters [1 :- 1 ].strip () else "" )+ ")" )
7458
+ view .insert (edit , selection . begin () , function_name + ".call(this" + (", " + parameters [1 :- 1 ] if parameters [1 :- 1 ].strip () else "" )+ ")" )
7453
7459
else :
7454
- view .replace (edit , selection , function_name + parameters )
7455
- view .insert (edit , region .begin (), new_text )
7460
+ view .insert (edit , selection . begin () , function_name + parameters )
7461
+ view .insert (edit , region .begin () + ( 1 if view . substr ( region . begin ()) == "{" else 0 ) , new_text )
7456
7462
7457
7463
elif inputs ["scope" ] == "Global scope" :
7458
7464
7459
- region_class = Util .get_region_scope_first_match (view , scope , selection , scope .split (" " )[1 ])["region" ]
7460
- space = Util .get_whitespace_from_line_begin (view , region_class )
7461
- new_text = Util .replace_with_tab (view , selection , "function " + function_name + " " + parameters + " {\n " + space , "\n " + space + "}\n \n " + space )
7465
+ flow_cli = "flow"
7466
+ is_from_bin = True
7467
+ chdir = ""
7468
+ use_node = True
7469
+ bin_path = ""
7462
7470
7463
- if Util .region_contains_scope (view , selection , "variable.language.this.js" ):
7464
- view .replace (edit , selection , function_name + ".call(this" + (", " + parameters [1 :- 1 ] if parameters [1 :- 1 ].strip () else "" )+ ")" )
7465
- else :
7466
- view .replace (edit , selection , function_name + parameters )
7467
- view .insert (edit , region_class .begin (), new_text )
7471
+ settings = get_project_settings ()
7472
+ if settings and settings ["project_settings" ]["flow_cli_custom_path" ]:
7473
+ flow_cli = os .path .basename (settings ["project_settings" ]["flow_cli_custom_path" ])
7474
+ bin_path = os .path .dirname (settings ["project_settings" ]["flow_cli_custom_path" ])
7475
+ is_from_bin = False
7476
+ chdir = settings ["project_dir_name" ]
7477
+ use_node = False
7478
+
7479
+ node = NodeJS (check_local = True )
7480
+
7481
+ result = node .execute_check_output (
7482
+ flow_cli ,
7483
+ [
7484
+ 'ast' ,
7485
+ '--from' , 'sublime_text'
7486
+ ],
7487
+ is_from_bin = is_from_bin ,
7488
+ use_fp_temp = True ,
7489
+ fp_temp_contents = view .substr (sublime .Region (0 , view .size ())),
7490
+ is_output_json = True ,
7491
+ chdir = chdir ,
7492
+ bin_path = bin_path ,
7493
+ use_node = use_node
7494
+ )
7468
7495
7469
- if view_id_caller :
7470
- windowViewManager .get (view_id_caller ).close ()
7496
+ if result [0 ]:
7497
+ if "body" in result [1 ]:
7498
+ body = result [1 ]["body" ]
7499
+ items = Util .nested_lookup ("type" , ["BlockStatement" ], body , return_parent = True )[::- 1 ]
7500
+ region = None
7501
+
7502
+ for item in items :
7503
+ r = sublime .Region (int (item ["range" ][0 ]), int (item ["range" ][1 ]))
7504
+ if r .contains (selection ):
7505
+ region = r
7506
+ break
7507
+ else :
7508
+ for item in body :
7509
+ r = sublime .Region (int (item ["range" ][0 ]), int (item ["range" ][1 ]))
7510
+ if r .contains (selection ) or r .intersects (selection ):
7511
+ region = r
7512
+ break
7513
+
7514
+ if region :
7515
+
7516
+ prev_line_is_empty = Util .prev_line_is_empty (view , region )
7517
+ next_line_is_empty = Util .next_line_is_empty (view , region )
7518
+ space_before = ("\n " if not prev_line_is_empty else "" )
7519
+
7520
+ new_text = Util .replace_with_tab (view , selection , space_before + "function " + function_name + " " + parameters + " {\n " , "\n }\n \n " , lstrip = True )
7521
+
7522
+ view .erase (edit , selection )
7523
+ view .insert (edit , region .begin (), new_text )
7524
+ if Util .region_contains_scope (view , selection , "variable.language.this.js" ):
7525
+ 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 "" )+ ")" )
7526
+ else :
7527
+ view .insert (edit , selection .begin () + len (Util .convert_tabs_using_tab_size (view , new_text )), function_name + parameters )
7528
+
7529
+ windowViewManager .close (view .id ())
7471
7530
7472
7531
def is_enabled (self , ** args ) :
7473
7532
view = self .view
@@ -8438,8 +8497,8 @@ def run(self, edit, **args):
8438
8497
if need_to_import :
8439
8498
last_import_region = ( import_regions [- 1 ] if import_regions else (sublime .Region (0 , 0 ) if not view .match_selector (0 , 'comment' ) else view .extract_scope (0 )) )
8440
8499
8441
- text = "\n import " + ( "{ " + export_name + " }" if file_already_exists or export_to_search == "VariableDeclaration" else export_name ) + " from '" + rel_new_path + "'\n "
8442
-
8500
+ text = "\n import " + ( "{ " + export_name + " }" if file_already_exists or export_to_search == "VariableDeclaration" else export_name ) + " from '" + rel_new_path + "'\n " + ( " \n " if not Util . next_line_is_empty ( view , last_import_region ) else "" )
8501
+
8443
8502
if not args .get ("preview" ):
8444
8503
view .insert (edit , last_import_region .end (), text )
8445
8504
else :
0 commit comments