1+ import sublime , sublime_plugin
2+ import os , shutil
3+
4+ class RefactorSafeCopyCommand (sublime_plugin .TextCommand ):
5+ def run (self , edit , ** args ):
6+ view = self .view
7+ window = view .window ()
8+ file_name = view .file_name ()
9+ inputs = args .get ("inputs" )
10+ view_id_caller = args .get ("view_id_caller" ) if "view_id_caller" in args else None
11+ new_path = inputs ["new_path" ].strip ()
12+ settings = get_project_settings ()
13+
14+ if not file_name :
15+ sublime .error_message ("Cannot copy this file. File name is empty." )
16+ return
17+
18+ if new_path == file_name :
19+ sublime .message_dialog ("The file path is the same as before." )
20+ return
21+
22+ if settings :
23+
24+ if not args .get ("preview" ):
25+
26+ if os .path .isfile (new_path ):
27+ if not sublime .ok_cancel_dialog (new_path + " already exists." , "Copy anyway" ):
28+ return
29+
30+ if not os .path .isdir (os .path .dirname (new_path )):
31+ os .makedirs (os .path .dirname (new_path ))
32+
33+ else :
34+ preview_view = None
35+ for v in window .views ():
36+ if v .name () == "Refactor - Copy Preview" :
37+ preview_view = v
38+ preview_view .erase (edit , sublime .Region (0 , preview_view .size ()))
39+ window .focus_view (preview_view )
40+ break
41+
42+ if not preview_view :
43+ preview_view = window .new_file ()
44+ preview_view .set_name ("Refactor - Copy Preview" )
45+ preview_view .set_syntax_file ('Packages/Default/Find Results.hidden-tmLanguage' )
46+ preview_view .set_scratch (True )
47+
48+ preview_view .run_command ("append_text_view" , args = {"text" : "Refactor - Copy Preview\n \n List of files that will be updated\n \n " })
49+
50+ imports = self .get_imports (settings , [file_name ])
51+
52+ if imports [file_name ]["requirements" ]:
53+ content = ""
54+
55+ with open (file_name , "r" ) as file :
56+ content = file .read ()
57+ preview_content = ""
58+
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
62+
63+ 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" ])
64+
65+ if os .path .dirname (new_path ) == os .path .dirname (req_new_path ):
66+ rel_new_path = "./" + os .path .basename (req_new_path )
67+ else :
68+ rel_new_path = os .path .relpath (req_new_path , start = os .path .dirname (new_path ))
69+ if not rel_new_path .startswith (".." ):
70+ rel_new_path = "./" + rel_new_path
71+ content = content [:start_offset ] + rel_new_path + content [end_offset :]
72+
73+ if args .get ("preview" ):
74+ splitted_content = content .splitlines ()
75+
76+ if not preview_content :
77+ preview_content = "- From:\n " + file_name + "\n \n "
78+ preview_content += "- To:\n " + new_path + "\n \n "
79+
80+ line = int (req ["line" ]) - 1
81+ range_start = max (0 , line - 2 )
82+ range_end = min (line + 2 , len (splitted_content ))
83+ while range_start <= range_end :
84+ preview_content += " " + str (range_start + 1 ) + (": " if line == range_start else " " ) + splitted_content [range_start ] + "\n "
85+ range_start += 1
86+ preview_content += "\n \n "
87+
88+ if args .get ("preview" ):
89+ preview_view .run_command ("append_text_view" , args = {"text" : preview_content })
90+
91+ if not args .get ("preview" ):
92+ with open (new_path , "w+" ) as file :
93+ file .seek (0 )
94+ file .write (content )
95+ file .truncate ()
96+
97+ if not args .get ("preview" ):
98+
99+ for v in window .views ():
100+ if v .name () == "Refactor - Copy Preview" :
101+ v .close ()
102+ break
103+
104+ if view_id_caller :
105+ windowViewManager .get (view_id_caller ).close ()
106+
107+ else :
108+ sublime .error_message ("Error: can't get project settings" )
109+
110+ def get_imports (self , settings , javascript_files ):
111+
112+ view = self .view
113+
114+ flow_cli = "flow"
115+ is_from_bin = True
116+ chdir = settings ["project_dir_name" ]
117+ use_node = True
118+ bin_path = ""
119+
120+ if settings and settings ["project_settings" ]["flow_cli_custom_path" ]:
121+ flow_cli = os .path .basename (settings ["project_settings" ]["flow_cli_custom_path" ])
122+ bin_path = os .path .dirname (settings ["project_settings" ]["flow_cli_custom_path" ])
123+ is_from_bin = False
124+ chdir = settings ["project_dir_name" ]
125+ use_node = False
126+
127+ deps = flow_parse_cli_dependencies (view )
128+
129+ node = NodeJS (check_local = True )
130+
131+ result = node .execute_check_output (
132+ flow_cli ,
133+ [
134+ 'get-imports' ,
135+ '--from' , 'sublime_text' ,
136+ '--root' , deps .project_root ,
137+ '--json'
138+ ] + javascript_files ,
139+ is_from_bin = is_from_bin ,
140+ use_fp_temp = True ,
141+ is_output_json = True ,
142+ chdir = chdir ,
143+ bin_path = bin_path ,
144+ use_node = use_node
145+ )
146+
147+ if result [0 ]:
148+ return result [1 ]
149+
150+ return {}
151+
152+ def is_enabled (self , ** args ) :
153+ view = self .view
154+ if not view .file_name ():
155+ return False
156+ settings = get_project_settings ()
157+ if not settings or not Util .selection_in_js_scope (view ):
158+ return False
159+ return True
160+
161+ def is_visible (self , ** args ) :
162+ view = self .view
163+ if not view .file_name ():
164+ return False
165+ settings = get_project_settings ()
166+ if not settings or not Util .selection_in_js_scope (view ):
167+ return False
168+ return True
169+
0 commit comments