0
# Text Editing
1
2
Multi-line text editing capabilities with syntax highlighting, line numbers, and advanced text manipulation features.
3
4
## Capabilities
5
6
### Text Edit Widget
7
8
TTkTextEdit provides comprehensive multi-line text editing functionality.
9
10
```python { .api }
11
class TTkTextEdit(TTkAbstractScrollArea):
12
def __init__(self, parent=None, **kwargs):
13
"""
14
Initialize a text edit widget.
15
16
Parameters:
17
- text (str): Initial text content
18
- readOnly (bool): Whether the editor is read-only
19
- lineWrapMode (int): Line wrapping mode
20
- wordWrapMode (int): Word wrapping mode
21
"""
22
23
def setText(self, text):
24
"""Set the text content."""
25
26
def text(self):
27
"""Get the text content."""
28
29
def append(self, text):
30
"""Append text to the end."""
31
32
def prepend(self, text):
33
"""Prepend text to the beginning."""
34
35
def insertText(self, text):
36
"""Insert text at cursor position."""
37
38
def clear(self):
39
"""Clear all text."""
40
41
def copy(self):
42
"""Copy selected text to clipboard."""
43
44
def cut(self):
45
"""Cut selected text to clipboard."""
46
47
def paste(self):
48
"""Paste text from clipboard."""
49
50
def undo(self):
51
"""Undo last operation."""
52
53
def redo(self):
54
"""Redo last undone operation."""
55
56
def selectAll(self):
57
"""Select all text."""
58
59
def setReadOnly(self, readOnly):
60
"""Set read-only mode."""
61
62
def isReadOnly(self):
63
"""Check if in read-only mode."""
64
65
def setLineWrapMode(self, mode):
66
"""Set line wrapping mode."""
67
68
def lineWrapMode(self):
69
"""Get line wrapping mode."""
70
71
def setWordWrapMode(self, mode):
72
"""Set word wrapping mode."""
73
74
def wordWrapMode(self):
75
"""Get word wrapping mode."""
76
77
def textCursor(self):
78
"""Get the text cursor."""
79
80
def setTextCursor(self, cursor):
81
"""Set the text cursor."""
82
83
def cursorPosition(self):
84
"""Get cursor position."""
85
86
def setCursorPosition(self, position):
87
"""Set cursor position."""
88
89
def hasSelectedText(self):
90
"""Check if text is selected."""
91
92
def selectedText(self):
93
"""Get selected text."""
94
95
def find(self, text, options=0):
96
"""Find text in the document."""
97
98
def replace(self, text):
99
"""Replace selected text."""
100
101
def setDocument(self, document):
102
"""Set the text document."""
103
104
def document(self):
105
"""Get the text document."""
106
107
def setTabStopWidth(self, width):
108
"""Set tab stop width."""
109
110
def tabStopWidth(self):
111
"""Get tab stop width."""
112
113
def isUndoRedoEnabled(self):
114
"""Check if undo/redo is enabled."""
115
116
def setUndoRedoEnabled(self, enabled):
117
"""Enable/disable undo/redo."""
118
119
# Signals
120
textChanged: pyTTkSignal # Emitted when text changes
121
cursorPositionChanged: pyTTkSignal # Emitted when cursor moves
122
selectionChanged: pyTTkSignal # Emitted when selection changes
123
undoAvailable: pyTTkSignal # Emitted when undo becomes available
124
redoAvailable: pyTTkSignal # Emitted when redo becomes available
125
```
126
127
### Text Edit View
128
129
TTkTextEditView provides the visual component of the text editor.
130
131
```python { .api }
132
class TTkTextEditView(TTkWidget):
133
def __init__(self, parent=None, **kwargs):
134
"""Initialize a text edit view."""
135
136
def setDocument(self, document):
137
"""Set the text document to display."""
138
139
def document(self):
140
"""Get the current document."""
141
142
def setTextCursor(self, cursor):
143
"""Set the text cursor."""
144
145
def textCursor(self):
146
"""Get the text cursor."""
147
148
def setLineNumberEnabled(self, enabled):
149
"""Enable/disable line numbers."""
150
151
def isLineNumberEnabled(self):
152
"""Check if line numbers are enabled."""
153
154
def setSyntaxHighlighter(self, highlighter):
155
"""Set syntax highlighter."""
156
157
def syntaxHighlighter(self):
158
"""Get syntax highlighter."""
159
```
160
161
### Text Edit Ruler
162
163
TTkTextEditRuler provides line numbers and editor annotations.
164
165
```python { .api }
166
class TTkTextEditRuler(TTkWidget):
167
def __init__(self, parent=None, **kwargs):
168
"""Initialize a text edit ruler."""
169
170
def setTextEdit(self, textEdit):
171
"""Set the associated text edit widget."""
172
173
def textEdit(self):
174
"""Get the associated text edit widget."""
175
176
def setLineNumbersVisible(self, visible):
177
"""Show/hide line numbers."""
178
179
def lineNumbersVisible(self):
180
"""Check if line numbers are visible."""
181
182
def setBookmarksEnabled(self, enabled):
183
"""Enable/disable bookmark support."""
184
185
def bookmarksEnabled(self):
186
"""Check if bookmarks are enabled."""
187
188
def addBookmark(self, line):
189
"""Add bookmark at line."""
190
191
def removeBookmark(self, line):
192
"""Remove bookmark from line."""
193
194
def hasBookmark(self, line):
195
"""Check if line has bookmark."""
196
197
def bookmarks(self):
198
"""Get list of bookmarked lines."""
199
```
200
201
### Text Cursor
202
203
TTkTextCursor provides navigation and text manipulation within documents.
204
205
```python { .api }
206
class TTkTextCursor:
207
def __init__(self, document=None):
208
"""
209
Initialize a text cursor.
210
211
Parameters:
212
- document: Text document to operate on
213
"""
214
215
def position(self):
216
"""Get cursor position."""
217
218
def setPosition(self, position, mode=None):
219
"""
220
Set cursor position.
221
222
Parameters:
223
- position (int): Character position
224
- mode: Selection mode (MoveAnchor, KeepAnchor)
225
"""
226
227
def movePosition(self, operation, mode=None, n=1):
228
"""
229
Move cursor by operation.
230
231
Parameters:
232
- operation: Move operation (Start, End, Up, Down, etc.)
233
- mode: Selection mode
234
- n: Number of operations
235
"""
236
237
def hasSelection(self):
238
"""Check if cursor has selection."""
239
240
def selectedText(self):
241
"""Get selected text."""
242
243
def selectionStart(self):
244
"""Get selection start position."""
245
246
def selectionEnd(self):
247
"""Get selection end position."""
248
249
def clearSelection(self):
250
"""Clear current selection."""
251
252
def select(self, selection):
253
"""Select text by selection type."""
254
255
def insertText(self, text):
256
"""Insert text at cursor position."""
257
258
def deleteChar(self):
259
"""Delete character at cursor."""
260
261
def deletePreviousChar(self):
262
"""Delete character before cursor."""
263
264
def beginEditBlock(self):
265
"""Begin an edit block for undo/redo."""
266
267
def endEditBlock(self):
268
"""End an edit block."""
269
270
def atStart(self):
271
"""Check if cursor is at document start."""
272
273
def atEnd(self):
274
"""Check if cursor is at document end."""
275
276
def atBlockStart(self):
277
"""Check if cursor is at block start."""
278
279
def atBlockEnd(self):
280
"""Check if cursor is at block end."""
281
```
282
283
### Text Document
284
285
TTkTextDocument represents the document model for text editing.
286
287
```python { .api }
288
class TTkTextDocument:
289
def __init__(self, parent=None):
290
"""Initialize a text document."""
291
292
def setPlainText(self, text):
293
"""Set document content as plain text."""
294
295
def toPlainText(self):
296
"""Get document content as plain text."""
297
298
def isEmpty(self):
299
"""Check if document is empty."""
300
301
def blockCount(self):
302
"""Get number of text blocks."""
303
304
def characterCount(self):
305
"""Get total character count."""
306
307
def lineCount(self):
308
"""Get number of lines."""
309
310
def findBlock(self, position):
311
"""Find text block at position."""
312
313
def findBlockByLineNumber(self, lineNumber):
314
"""Find text block by line number."""
315
316
def isModified(self):
317
"""Check if document is modified."""
318
319
def setModified(self, modified=True):
320
"""Set document modified state."""
321
322
def undo(self):
323
"""Undo last operation."""
324
325
def redo(self):
326
"""Redo last undone operation."""
327
328
def isUndoAvailable(self):
329
"""Check if undo is available."""
330
331
def isRedoAvailable(self):
332
"""Check if redo is available."""
333
334
def setUndoRedoEnabled(self, enabled):
335
"""Enable/disable undo/redo."""
336
337
def isUndoRedoEnabled(self):
338
"""Check if undo/redo is enabled."""
339
340
def clear(self):
341
"""Clear document content."""
342
343
# Signals
344
contentsChanged: pyTTkSignal # Emitted when content changes
345
modificationChanged: pyTTkSignal # Emitted when modification state changes
346
undoAvailable: pyTTkSignal # Emitted when undo availability changes
347
redoAvailable: pyTTkSignal # Emitted when redo availability changes
348
```
349
350
### Syntax Highlighting
351
352
TextDocumentHighlight provides syntax highlighting capabilities.
353
354
```python { .api }
355
class TextDocumentHighlight:
356
def __init__(self, parent=None):
357
"""Initialize syntax highlighter."""
358
359
def setDocument(self, document):
360
"""Set document to highlight."""
361
362
def document(self):
363
"""Get highlighted document."""
364
365
def highlightBlock(self, text):
366
"""Override to implement custom highlighting."""
367
368
def setFormat(self, start, count, format):
369
"""Set formatting for text range."""
370
371
def format(self, position):
372
"""Get format at position."""
373
374
def setDefaultColor(self, color):
375
"""Set default text color."""
376
377
def defaultColor(self):
378
"""Get default text color."""
379
380
def addKeyword(self, keyword, color):
381
"""Add keyword with color."""
382
383
def addPattern(self, pattern, color):
384
"""Add regex pattern with color."""
385
386
def setCommentColor(self, color):
387
"""Set comment color."""
388
389
def setStringColor(self, color):
390
"""Set string literal color."""
391
392
def setNumberColor(self, color):
393
"""Set number literal color."""
394
```
395
396
## Usage Examples
397
398
### Basic Text Editor
399
400
```python
401
import TermTk as ttk
402
403
root = ttk.TTk()
404
container = ttk.TTkContainer(parent=root)
405
layout = ttk.TTkVBoxLayout()
406
407
# Create text editor
408
text_edit = ttk.TTkTextEdit()
409
initial_text = """# Welcome to pyTermTk Text Editor
410
411
This is a multi-line text editor with the following features:
412
- Syntax highlighting
413
- Line numbers
414
- Undo/Redo support
415
- Find and replace
416
- Cut, copy, paste operations
417
418
Type your text here..."""
419
420
text_edit.setText(initial_text)
421
422
# Create toolbar
423
toolbar_layout = ttk.TTkHBoxLayout()
424
425
save_btn = ttk.TTkButton(text="Save")
426
load_btn = ttk.TTkButton(text="Load")
427
undo_btn = ttk.TTkButton(text="Undo")
428
redo_btn = ttk.TTkButton(text="Redo")
429
find_btn = ttk.TTkButton(text="Find")
430
431
toolbar_layout.addWidget(save_btn)
432
toolbar_layout.addWidget(load_btn)
433
toolbar_layout.addWidget(undo_btn)
434
toolbar_layout.addWidget(redo_btn)
435
toolbar_layout.addWidget(find_btn)
436
toolbar_layout.addStretch(1)
437
438
# Status bar
439
status = ttk.TTkLabel(text="Ready")
440
441
# Button handlers
442
@ttk.pyTTkSlot()
443
def save_file():
444
text = text_edit.text()
445
# Save logic here
446
status.setText("File saved")
447
448
@ttk.pyTTkSlot()
449
def undo_action():
450
text_edit.undo()
451
452
@ttk.pyTTkSlot()
453
def redo_action():
454
text_edit.redo()
455
456
# Connect buttons
457
save_btn.clicked.connect(save_file)
458
undo_btn.clicked.connect(undo_action)
459
redo_btn.clicked.connect(redo_action)
460
461
# Text change handler
462
@ttk.pyTTkSlot()
463
def text_changed():
464
status.setText("Modified")
465
466
text_edit.textChanged.connect(text_changed)
467
468
# Add to layout
469
layout.addLayout(toolbar_layout)
470
layout.addWidget(text_edit)
471
layout.addWidget(status)
472
473
container.setLayout(layout)
474
root.mainloop()
475
```
476
477
### Text Editor with Line Numbers
478
479
```python
480
import TermTk as ttk
481
482
root = ttk.TTk()
483
container = ttk.TTkContainer(parent=root)
484
layout = ttk.TTkHBoxLayout()
485
486
# Create text editor with ruler
487
text_edit = ttk.TTkTextEdit()
488
ruler = ttk.TTkTextEditRuler()
489
490
# Associate ruler with text editor
491
ruler.setTextEdit(text_edit)
492
ruler.setLineNumbersVisible(True)
493
ruler.setBookmarksEnabled(True)
494
495
# Sample code content
496
code_content = """#!/usr/bin/env python3
497
import TermTk as ttk
498
499
def main():
500
root = ttk.TTk()
501
502
# Create main window
503
window = ttk.TTkWindow(
504
parent=root,
505
title="My App",
506
size=(60, 20)
507
)
508
509
# Add widgets
510
label = ttk.TTkLabel(
511
parent=window,
512
text="Hello World!"
513
)
514
515
root.mainloop()
516
517
if __name__ == "__main__":
518
main()"""
519
520
text_edit.setText(code_content)
521
522
# Add bookmarks to some lines
523
ruler.addBookmark(1) # Bookmark shebang line
524
ruler.addBookmark(8) # Bookmark main window creation
525
526
layout.addWidget(ruler)
527
layout.addWidget(text_edit, stretch=1)
528
529
container.setLayout(layout)
530
root.mainloop()
531
```
532
533
### Find and Replace Dialog
534
535
```python
536
import TermTk as ttk
537
538
class FindReplaceDialog(ttk.TTkWindow):
539
def __init__(self, parent=None, text_edit=None):
540
super().__init__(parent=parent, title="Find & Replace", size=(40, 15))
541
self.text_edit = text_edit
542
543
layout = ttk.TTkVBoxLayout()
544
545
# Find section
546
find_layout = ttk.TTkHBoxLayout()
547
find_layout.addWidget(ttk.TTkLabel(text="Find:"))
548
self.find_edit = ttk.TTkLineEdit()
549
find_layout.addWidget(self.find_edit)
550
551
# Replace section
552
replace_layout = ttk.TTkHBoxLayout()
553
replace_layout.addWidget(ttk.TTkLabel(text="Replace:"))
554
self.replace_edit = ttk.TTkLineEdit()
555
replace_layout.addWidget(self.replace_edit)
556
557
# Options
558
self.case_sensitive = ttk.TTkCheckbox(text="Case sensitive")
559
self.whole_words = ttk.TTkCheckbox(text="Whole words only")
560
561
# Buttons
562
btn_layout = ttk.TTkHBoxLayout()
563
find_btn = ttk.TTkButton(text="Find Next")
564
replace_btn = ttk.TTkButton(text="Replace")
565
replace_all_btn = ttk.TTkButton(text="Replace All")
566
close_btn = ttk.TTkButton(text="Close")
567
568
btn_layout.addWidget(find_btn)
569
btn_layout.addWidget(replace_btn)
570
btn_layout.addWidget(replace_all_btn)
571
btn_layout.addWidget(close_btn)
572
573
# Add to layout
574
layout.addLayout(find_layout)
575
layout.addLayout(replace_layout)
576
layout.addWidget(self.case_sensitive)
577
layout.addWidget(self.whole_words)
578
layout.addLayout(btn_layout)
579
580
self.setLayout(layout)
581
582
# Connect buttons
583
find_btn.clicked.connect(self.find_next)
584
replace_btn.clicked.connect(self.replace_current)
585
replace_all_btn.clicked.connect(self.replace_all)
586
close_btn.clicked.connect(self.close)
587
588
@ttk.pyTTkSlot()
589
def find_next(self):
590
if self.text_edit:
591
find_text = self.find_edit.text()
592
options = 0
593
if self.case_sensitive.isChecked():
594
options |= ttk.TTkConstant.FindCaseSensitively
595
if self.whole_words.isChecked():
596
options |= ttk.TTkConstant.FindWholeWords
597
598
found = self.text_edit.find(find_text, options)
599
if not found:
600
print("Text not found")
601
602
@ttk.pyTTkSlot()
603
def replace_current(self):
604
if self.text_edit and self.text_edit.hasSelectedText():
605
replace_text = self.replace_edit.text()
606
self.text_edit.replace(replace_text)
607
608
@ttk.pyTTkSlot()
609
def replace_all(self):
610
if self.text_edit:
611
find_text = self.find_edit.text()
612
replace_text = self.replace_edit.text()
613
614
# Simple replace all implementation
615
content = self.text_edit.text()
616
if not self.case_sensitive.isChecked():
617
# Case insensitive replace
618
content = content.replace(find_text.lower(), replace_text)
619
else:
620
content = content.replace(find_text, replace_text)
621
622
self.text_edit.setText(content)
623
624
# Usage example
625
root = ttk.TTk()
626
container = ttk.TTkContainer(parent=root)
627
layout = ttk.TTkVBoxLayout()
628
629
text_edit = ttk.TTkTextEdit()
630
text_edit.setText("This is sample text. Find and replace this text.")
631
632
find_replace_btn = ttk.TTkButton(text="Find & Replace")
633
634
@ttk.pyTTkSlot()
635
def open_find_replace():
636
dialog = FindReplaceDialog(parent=root, text_edit=text_edit)
637
dialog.show()
638
639
find_replace_btn.clicked.connect(open_find_replace)
640
641
layout.addWidget(find_replace_btn)
642
layout.addWidget(text_edit)
643
644
container.setLayout(layout)
645
root.mainloop()
646
```
647
648
### Syntax Highlighted Code Editor
649
650
```python
651
import TermTk as ttk
652
653
class PythonSyntaxHighlighter(ttk.TextDocumentHighlight):
654
def __init__(self, parent=None):
655
super().__init__(parent=parent)
656
657
# Define colors
658
self.keyword_color = ttk.TTkColor(fg="#0066CC")
659
self.comment_color = ttk.TTkColor(fg="#008000")
660
self.string_color = ttk.TTkColor(fg="#AA0000")
661
self.number_color = ttk.TTkColor(fg="#FF6600")
662
663
# Python keywords
664
self.keywords = [
665
'def', 'class', 'import', 'from', 'if', 'else', 'elif',
666
'for', 'while', 'try', 'except', 'finally', 'with',
667
'return', 'yield', 'pass', 'break', 'continue',
668
'and', 'or', 'not', 'in', 'is', 'None', 'True', 'False'
669
]
670
671
def highlightBlock(self, text):
672
# Highlight keywords
673
for keyword in self.keywords:
674
index = text.find(keyword)
675
while index >= 0:
676
# Check if it's a whole word
677
if (index == 0 or not text[index-1].isalnum()) and \
678
(index + len(keyword) >= len(text) or not text[index + len(keyword)].isalnum()):
679
self.setFormat(index, len(keyword), self.keyword_color)
680
index = text.find(keyword, index + 1)
681
682
# Highlight comments
683
comment_index = text.find('#')
684
if comment_index >= 0:
685
self.setFormat(comment_index, len(text) - comment_index, self.comment_color)
686
687
# Highlight strings
688
for quote in ['"', "'"]:
689
start = 0
690
while True:
691
start = text.find(quote, start)
692
if start == -1:
693
break
694
end = text.find(quote, start + 1)
695
if end == -1:
696
end = len(text)
697
else:
698
end += 1
699
self.setFormat(start, end - start, self.string_color)
700
start = end
701
702
# Create code editor with syntax highlighting
703
root = ttk.TTk()
704
container = ttk.TTkContainer(parent=root)
705
706
text_edit = ttk.TTkTextEdit()
707
highlighter = PythonSyntaxHighlighter()
708
text_edit.setSyntaxHighlighter(highlighter)
709
710
sample_code = '''def factorial(n):
711
"""Calculate factorial of n"""
712
if n <= 1:
713
return 1
714
else:
715
return n * factorial(n - 1)
716
717
# Test the function
718
result = factorial(5)
719
print(f"Factorial of 5 is {result}")'''
720
721
text_edit.setText(sample_code)
722
723
container.addWidget(text_edit)
724
root.mainloop()
725
```