2
2
import os
3
3
import sys
4
4
import time
5
+ import re
5
6
6
7
import sublime
7
8
import sublime_plugin
@@ -94,7 +95,7 @@ def __init__(self, filename):
94
95
'syntacticDiag' : [],
95
96
'semanticDiag' : [],
96
97
}
97
-
98
+ self . loadHandler = None
98
99
99
100
# a reference to a source file, line, column; next and prev refer to the
100
101
# next and previous reference in a view containing references
@@ -277,7 +278,6 @@ def __init__(self, filename, cc):
277
278
self .lastModChangeCount = cc
278
279
self .modCount = 0
279
280
280
-
281
281
# region that will not change as buffer is modified
282
282
class StaticRegion :
283
283
def __init__ (self , b , e ):
@@ -290,6 +290,9 @@ def toRegion(self):
290
290
def begin (self ):
291
291
return self .b
292
292
293
+ def empty (self ):
294
+ return self .b == self .e
295
+
293
296
294
297
# convert a list of static regions to ordinary regions
295
298
def staticRegionsToRegions (staticRegions ):
@@ -334,13 +337,16 @@ def decrLocsToRegions(locs, amt):
334
337
rr .append (sublime .Region (loc - amt , loc - amt ))
335
338
return rr
336
339
337
- # right now, we must have this setting because no way to guess how to translate
338
- # tabs on the server side; so burn it in
340
+ # right now, we have this setting because there is no way to know how to translate
341
+ # tabs on the server side
339
342
# TODO: see if we can tolerate tabs by having the editor tell the server how
340
343
# to interpret them
341
344
def setFilePrefs (view ):
342
345
settings = view .settings ()
343
- settings .set ('translateTabsToSpaces' , True )
346
+ settings .set ('translate_tabs_to_spaces' , True )
347
+ settings .set ('tab_size' , 4 )
348
+ settings .set ('detect_indentation' , False )
349
+ settings .set ('use_tab_stops' , False )
344
350
345
351
# given a list of regions and a (possibly zero-length) string to insert,
346
352
# send the appropriate change information to the server
@@ -474,12 +480,10 @@ def showErrorMsgs(self, diagEvtBody, syntactic):
474
480
filename = diagEvtBody .file
475
481
if os .name == 'nt' :
476
482
filename = filename .replace ('/' , '\\ ' )
477
- print ("SEM!!! " + filename )
478
483
diags = diagEvtBody .diagnostics
479
484
info = self .fileMap .get (filename )
480
485
if info :
481
486
view = info .view
482
- print ("sem: " + str (info .changeCountErrReq ) + " " + str (self .change_count (view )))
483
487
if info .changeCountErrReq == self .change_count (view ):
484
488
if syntactic :
485
489
regionKey = 'syntacticDiag'
@@ -512,7 +516,6 @@ def showErrorMsgs(self, diagEvtBody, syntactic):
512
516
513
517
# event arrived from the server; call appropriate handler
514
518
def dispatchEvent (self , ev ):
515
- print ("dispatch event" )
516
519
evtype = ev .event
517
520
if evtype == 'syntaxDiag' :
518
521
self .showErrorMsgs (ev .body , syntactic = True )
@@ -553,7 +556,6 @@ def onIdle(self):
553
556
view = active_view ()
554
557
ev = cli .service .getEvent ()
555
558
if ev is not None :
556
- print ("idle got event" )
557
559
self .dispatchEvent (ev )
558
560
self .errRefreshRequested = False
559
561
# reset the timer in case more events are on the queue
@@ -567,6 +569,12 @@ def onIdle(self):
567
569
# request errors
568
570
self .refreshErrors (view , 500 )
569
571
572
+ def on_load (self , view ):
573
+ clientInfo = cli .getOrAddFile (view .file_name ())
574
+ if clientInfo and clientInfo .loadHandler :
575
+ clientInfo .loadHandler (view )
576
+ clientInfo .loadHandler = None
577
+
570
578
# ST3 only
571
579
# for certain text commands, learn what changed and notify the
572
580
# server, to avoid sending the whole buffer during completion
@@ -654,15 +662,7 @@ def on_modified(self, view):
654
662
# change handled in on_text_command
655
663
info .clientInfo .changeCount = self .change_count (view )
656
664
info .preChangeSent = False
657
- elif (lastCommand == "insert" ) and (not "\n " in args ['characters' ]):
658
- # single-line insert, use saved cursor information to determine
659
- # what was inserted
660
- # REVIEW: consider using this only if there is a single cursor,
661
- # and only if that
662
- # cursor is an empty region; right now, the code tries to
663
- # handle multiple cursors
664
- # and non-empty selections (which will be replaced by the
665
- # string inserted)
665
+ elif (lastCommand == "insert" ) and (not "\n " in args ['characters' ]) and (len (info .prevSel ) == 1 ) and (info .prevSel [0 ].empty ()):
666
666
info .clientInfo .changeCount = self .change_count (view )
667
667
prevCursor = info .prevSel [0 ].begin ()
668
668
cursor = view .sel ()[0 ].begin ()
@@ -905,6 +905,12 @@ def on_done(newName):
905
905
on_done , None , on_cancel )
906
906
907
907
908
+ def locsToValue (locs ):
909
+ locsValue = []
910
+ for loc in locs :
911
+ locsValue .append (loc .toDict ())
912
+ return locsValue
913
+
908
914
# called from on_done handler in finish_rename command
909
915
# on_done is called by input panel for new name
910
916
class TypescriptFinishRenameCommand (sublime_plugin .TextCommand ):
@@ -916,15 +922,52 @@ def run(self, text, argsJson=""):
916
922
for outerLoc in outerLocs :
917
923
file = outerLoc .file
918
924
innerLocs = outerLoc .locs
919
- for innerLoc in innerLocs :
920
- startlc = innerLoc .start
921
- (startl , startc ) = extractLineCol (startlc )
922
- endlc = innerLoc .end
923
- (endl , endc ) = extractLineCol (endlc )
924
- applyEdit (text , self .view , startl , startc , endl ,
925
- endc , ntext = newName )
925
+ activeWindow = sublime .active_window ()
926
+ renameView = activeWindow .find_open_file (file )
927
+ if not renameView :
928
+ renameView = activeWindow .open_file (file )
929
+ if renameView .is_loading ():
930
+ clientInfo = cli .getOrAddFile (file )
931
+ innerLocsValue = locsToValue (innerLocs )
932
+ def applyLocs (v ):
933
+ v .run_command ('typescript_delayed_rename_file' ,
934
+ { "locs" : innerLocsValue , "name" : newName })
935
+ clientInfo .loadHandler = applyLocs
936
+ elif renameView != self .view :
937
+ print (" got to " + renameView .file_name ())
938
+ innerLocsValue = locsToValue (innerLocs )
939
+ print (innerLocsValue )
940
+ renameView .run_command ('typescript_delayed_rename_file' ,
941
+ { "locs" : innerLocsValue , "name" : newName })
942
+ else :
943
+ for innerLoc in innerLocs :
944
+ startlc = innerLoc .start
945
+ (startl , startc ) = extractLineCol (startlc )
946
+ endlc = innerLoc .end
947
+ (endl , endc ) = extractLineCol (endlc )
948
+ applyEdit (text , self .view , startl , startc , endl ,
949
+ endc , ntext = newName )
926
950
927
951
952
+ def extractLineColFromDict (lc ):
953
+ line = lc ['line' ] - 1
954
+ col = lc ['col' ] - 1
955
+ return (line , col )
956
+
957
+ class TypescriptDelayedRenameFile (sublime_plugin .TextCommand ):
958
+ def run (self , text , locs = None , name = "" ):
959
+ if locs and (len (name ) > 0 ):
960
+ print (name )
961
+ print (locs )
962
+ for innerLoc in locs :
963
+ startlc = innerLoc ['start' ]
964
+ (startl , startc ) = extractLineColFromDict (startlc )
965
+ endlc = innerLoc ['end' ]
966
+ (endl , endc ) = extractLineColFromDict (endlc )
967
+ applyEdit (text , self .view , startl , startc , endl ,
968
+ endc , ntext = name )
969
+
970
+
928
971
# if the FindReferences view is active, get it
929
972
# TODO: generalize this so that we can find any scratch view
930
973
# containing references to other files
@@ -1136,16 +1179,17 @@ def applyFormattingChanges(text, view, codeEdits):
1136
1179
# format on ";", "}", or "\n"; called by typing these keys in a ts file
1137
1180
# in the case of "\n", this is only called when no completion dialogue visible
1138
1181
class TypescriptFormatOnKey (sublime_plugin .TextCommand ):
1139
- def run (self , text , key = "" ):
1182
+ def run (self , text , key = "" , insertKey = True ):
1140
1183
if 0 == len (key ):
1141
1184
return
1142
1185
loc = self .view .sel ()[0 ].begin ()
1143
- self .view .insert (text , loc , key )
1144
- sendReplaceChangesForRegions (self .view , [sublime .Region (loc , loc )], key )
1145
- if not cli .ST2 ():
1146
- clientInfo = cli .getOrAddFile (self .view .file_name ())
1147
- clientInfo .changeCount = self .view .change_count ()
1148
- checkUpdateView (self .view )
1186
+ if insertKey :
1187
+ self .view .insert (text , loc , key )
1188
+ sendReplaceChangesForRegions (self .view , [sublime .Region (loc , loc )], key )
1189
+ if not cli .ST2 ():
1190
+ clientInfo = cli .getOrAddFile (self .view .file_name ())
1191
+ clientInfo .changeCount = self .view .change_count ()
1192
+ checkUpdateView (self .view )
1149
1193
formatResp = cli .service .formatOnKey (self .view .file_name (), getLocationFromView (self .view ), key )
1150
1194
if formatResp .success :
1151
1195
codeEdits = formatResp .body
@@ -1176,14 +1220,38 @@ class TypescriptFormatDocument(sublime_plugin.TextCommand):
1176
1220
def run (self , text ):
1177
1221
formatRange (text , self .view , 0 , self .view .size ())
1178
1222
1223
+ nonBlankLinePattern = re .compile ("[\S]+" )
1179
1224
1180
1225
# command to format the current line
1181
1226
class TypescriptFormatLine (sublime_plugin .TextCommand ):
1182
1227
def run (self , text ):
1183
1228
lineRegion = self .view .line (self .view .sel ()[0 ])
1184
- formatRange (text , self .view , lineRegion .begin (), lineRegion .end ())
1185
-
1229
+ lineText = self .view .substr (lineRegion )
1230
+ if (nonBlankLinePattern .search (lineText )):
1231
+ formatRange (text , self .view , lineRegion .begin (), lineRegion .end ())
1232
+ else :
1233
+ position = self .view .sel ()[0 ].begin ()
1234
+ cursor = self .view .rowcol (position )
1235
+ line = cursor [0 ]
1236
+ if line > 0 :
1237
+ self .view .run_command ('typescript_format_on_key' , { "key" : "\n " , "insertKey" : False });
1186
1238
1239
+ class TypescriptFormatBrackets (sublime_plugin .TextCommand ):
1240
+ def run (self , text ):
1241
+ sel = self .view .sel ()
1242
+ if (len (sel ) == 1 ):
1243
+ print ('format brackets' )
1244
+ originalPos = sel [0 ].begin ()
1245
+ bracketChar = self .view .substr (originalPos )
1246
+ if bracketChar != "}" :
1247
+ self .view .run_command ('move_to' , { "to" : "brackets" });
1248
+ bracketPos = self .view .sel ()[0 ].begin ()
1249
+ bracketChar = self .view .substr (bracketPos )
1250
+ if bracketChar == "}" :
1251
+ self .view .run_command ('move' , { "by" : "characters" , "forward" : True })
1252
+ self .view .run_command ('typescript_format_on_key' , { "key" : "}" , "insertKey" : False });
1253
+ self .view .run_command ('move' , { "by" : "characters" , "forward" : True })
1254
+
1187
1255
# this is not always called on startup by Sublime, so we call it
1188
1256
# from on_activated or on_close if necessary
1189
1257
# TODO: get abbrev message and set up dictionary
0 commit comments