11
11
'''
12
12
13
13
import binaryninjaui
14
- from binaryninja import log_warn
14
+ from binaryninja import log_warn , bncompleter
15
15
if "qt_major_version" in binaryninjaui .__dict__ and binaryninjaui .qt_major_version == 6 :
16
16
from PySide6 .QtCore import Qt , QRect , QRegularExpression
17
17
from PySide6 .QtWidgets import QWidget , QTextEdit , QPlainTextEdit
18
- from PySide6 .QtGui import (QPainter , QFont , QSyntaxHighlighter , QTextFormat , QTextCharFormat , QColor )
18
+ from PySide6 .QtGui import (QPainter , QFont , QSyntaxHighlighter , QTextFormat , QTextCharFormat , QColor , QTextCursor )
19
19
else :
20
20
from PySide2 .QtCore import Qt , QRect , QRegularExpression
21
21
from PySide2 .QtWidgets import QWidget , QTextEdit , QPlainTextEdit
22
- from PySide2 .QtGui import (QPainter , QFont , QSyntaxHighlighter , QTextFormat , QTextCharFormat , QColor )
22
+ from PySide2 .QtGui import (QPainter , QFont , QSyntaxHighlighter , QTextFormat , QTextCharFormat , QColor , QTextCursor )
23
23
from binaryninjaui import (getMonospaceFont , getThemeColor , ThemeColor )
24
24
from pygments import highlight , token
25
25
from pygments .lexers import *
@@ -216,13 +216,18 @@ def updateContents(self, rect, scroll):
216
216
217
217
218
218
def __init__ (self , DISPLAY_LINE_NUMBERS = True , HIGHLIGHT_CURRENT_LINE = True ,
219
- SyntaxHighlighter = Pylighter , lang = "python" , font_size = 11 , * args ):
219
+ SyntaxHighlighter = Pylighter , lang = "python" , font_size = 11 , delimeter = " " , * args ):
220
220
super (QCodeEditor , self ).__init__ ()
221
221
222
222
font = getMonospaceFont (self )
223
223
font .setPointSize (font_size )
224
224
self .setFont (font )
225
225
self .setLineWrapMode (QPlainTextEdit .NoWrap )
226
+ self .completionState = 0
227
+ self .completing = False
228
+ self .delimeter = delimeter
229
+ self .completer = bncompleter .Completer ()
230
+ self .cursorPositionChanged .connect (self .resetCompletion )
226
231
227
232
self .DISPLAY_LINE_NUMBERS = DISPLAY_LINE_NUMBERS
228
233
@@ -232,6 +237,111 @@ def __init__(self, DISPLAY_LINE_NUMBERS=True, HIGHLIGHT_CURRENT_LINE=True,
232
237
if SyntaxHighlighter is not None : # add highlighter to textdocument
233
238
self .highlighter = SyntaxHighlighter (self .document (), lang )
234
239
240
+ def resetCompletion (self ):
241
+ if not self .completing :
242
+ self .completionState = 0
243
+
244
+ def isStart (self ):
245
+ tempCursor = self .textCursor ()
246
+ if tempCursor .positionInBlock () == 0 :
247
+ return True
248
+ startText = tempCursor .block ().text ()[0 :tempCursor .positionInBlock ()]
249
+ delim = set (self .delimeter )
250
+ if set (startText ) - delim == set ():
251
+ #only delimeters before cursor, not worrying about varying lengths of spaces for now
252
+ return True
253
+ return False
254
+
255
+ def keyPressEvent (self , event ):
256
+ if event .key () == Qt .Key_Backtab and self .textCursor ().hasSelection ():
257
+ startCursor = self .textCursor ()
258
+ startCursor .beginEditBlock ()
259
+ startPos = startCursor .selectionStart ()
260
+ startCursor .setPosition (startPos )
261
+ startCursor .movePosition (QTextCursor .StartOfLine , QTextCursor .MoveAnchor )
262
+ startCursor .clearSelection ()
263
+
264
+ endCursor = self .textCursor ()
265
+ endPos = endCursor .selectionEnd ()
266
+ endCursor .setPosition (endPos )
267
+ endCursor .movePosition (QTextCursor .StartOfLine )
268
+
269
+ while startCursor .anchor () != endCursor .position ():
270
+ startCursor .movePosition (QTextCursor .NextCharacter , QTextCursor .KeepAnchor , len (self .delimeter ))
271
+ if startCursor .selectedText () == self .delimeter :
272
+ startCursor .removeSelectedText ()
273
+ startCursor .movePosition (QTextCursor .NextBlock , QTextCursor .MoveAnchor )
274
+ startCursor .movePosition (QTextCursor .NextCharacter , QTextCursor .KeepAnchor , len (self .delimeter ))
275
+ if startCursor .selectedText () == self .delimeter :
276
+ startCursor .removeSelectedText ()
277
+ startCursor .endEditBlock ()
278
+ return
279
+
280
+ if event .key () == Qt .Key_Tab and self .textCursor ().hasSelection ():
281
+ startCursor = self .textCursor ()
282
+ startCursor .beginEditBlock ()
283
+ startPos = startCursor .selectionStart ()
284
+ startCursor .setPosition (startPos )
285
+ startCursor .movePosition (QTextCursor .StartOfLine )
286
+
287
+ endCursor = self .textCursor ()
288
+ endPos = endCursor .selectionEnd ()
289
+ endCursor .setPosition (endPos )
290
+ endCursor .movePosition (QTextCursor .StartOfLine )
291
+
292
+ while startCursor .position () != endCursor .position ():
293
+ startCursor .insertText (self .delimeter )
294
+ startCursor .movePosition (QTextCursor .NextBlock )
295
+
296
+ startCursor .insertText (self .delimeter )
297
+ startCursor .endEditBlock ()
298
+ return
299
+
300
+ if event .key () == Qt .Key_Escape and self .completionState > 0 :
301
+ self .completionState = 0
302
+ cursor = self .textCursor ()
303
+ cursor .beginEditBlock ()
304
+ cursor .select (QTextCursor .BlockUnderCursor )
305
+ cursor .removeSelectedText ()
306
+ cursor .insertText ("\n " + self .origText )
307
+ cursor .endEditBlock ()
308
+ self .origText == None
309
+ return
310
+
311
+ if event .key () == Qt .Key_Tab :
312
+ if self .isStart ():
313
+ self .textCursor ().insertText (self .delimeter )
314
+ else :
315
+ cursor = self .textCursor ()
316
+ cursor .beginEditBlock ()
317
+ self .completing = True
318
+ if self .completionState == 0 :
319
+ self .origText = self .textCursor ().block ().text ()
320
+ if self .completionState > 0 :
321
+ cursor .select (QTextCursor .BlockUnderCursor )
322
+ cursor .removeSelectedText ()
323
+ cursor .insertText ("\n " + self .origText )
324
+ newText = self .completer .complete (self .origText , self .completionState )
325
+ if newText :
326
+ if newText .find ("(" ) > 0 :
327
+ newText = newText [0 :newText .find ("(" ) + 1 ]
328
+ self .completionState += 1
329
+ cursor .select (QTextCursor .BlockUnderCursor )
330
+ cursor .removeSelectedText ()
331
+ cursor .insertText ("\n " + newText )
332
+ else :
333
+ self .completionState = 0
334
+ cursor .select (QTextCursor .BlockUnderCursor )
335
+ cursor .removeSelectedText ()
336
+ cursor .insertText ("\n " + self .origText )
337
+ self .origText == None
338
+ cursor .endEditBlock ()
339
+ self .completing = False
340
+ return
341
+
342
+ return super ().keyPressEvent (event )
343
+
344
+
235
345
def resizeEvent (self , * e ):
236
346
'''overload resizeEvent handler'''
237
347
0 commit comments