@@ -200,7 +200,7 @@ def insert_separators(self, value: str, cursor_position: int) -> tuple[str, int]
200
200
cursor_position += 1
201
201
return value , cursor_position
202
202
203
- def insert_text_at_cursor (self , text : str ) -> tuple [str , int ] | None :
203
+ def insert_text_at_cursor (self , text : str , value : str , cursor_position : int ) -> tuple [str , int ] | None :
204
204
"""Inserts `text` at current cursor position. If not present in `text`, any expected separator is automatically
205
205
inserted at the correct position.
206
206
@@ -211,8 +211,6 @@ def insert_text_at_cursor(self, text: str) -> tuple[str, int] | None:
211
211
A tuple in the form `(value, cursor_position)` with the new control value and current cursor position if
212
212
`text` matches the template, None otherwise.
213
213
"""
214
- value = self .input .value
215
- cursor_position = self .input .cursor_position
216
214
separators = set (
217
215
[
218
216
char_definition .char
@@ -612,7 +610,7 @@ def insert_text_at_cursor(self, text: str) -> None:
612
610
text: New text to insert.
613
611
"""
614
612
615
- new_value = self ._template .insert_text_at_cursor (text )
613
+ new_value = self ._template .insert_text_at_cursor (text , self . value , self . cursor_position )
616
614
if new_value is not None :
617
615
self .value , self .cursor_position = new_value
618
616
else :
@@ -627,16 +625,33 @@ def replace(self, text: str, start: int, end: int):
627
625
end: End index to replace (inclusive).
628
626
"""
629
627
630
- old_cursor_position = self .cursor_position
631
- self .cursor_position = start
632
- new_value = self ._template .insert_text_at_cursor (text )
633
- if new_value is not None :
634
- value , cursor_position = new_value
635
- self .value = value [:cursor_position ] + value [end :]
636
- self .cursor_position = cursor_position
637
- else :
638
- self .cursor_position = old_cursor_position
639
- self .restricted ()
628
+ previous_cursor_position = self .cursor_position
629
+ value = self .value
630
+ cursor_position = start
631
+ for char in text :
632
+ new_value_cursor_position = self ._template .insert_text_at_cursor (char , value , cursor_position )
633
+ if new_value_cursor_position is None :
634
+ self .value = value
635
+ self .cursor_position = previous_cursor_position
636
+ self .restricted ()
637
+ return
638
+
639
+ new_value , new_cursor_position = new_value_cursor_position
640
+ if new_cursor_position >= end :
641
+ self .value = new_value [:end ] + value [end :]
642
+ self .cursor_position = new_cursor_position
643
+ return
644
+
645
+ value = new_value
646
+ cursor_position = new_cursor_position
647
+
648
+ self .value = value
649
+ self .cursor_position = end
650
+ while self .cursor_position > cursor_position :
651
+ self ._template .move_cursor (- 1 )
652
+ self ._template .delete_at_position ()
653
+
654
+ self .cursor_position = cursor_position
640
655
641
656
def clear (self ) -> None :
642
657
"""Clear the masked input."""
0 commit comments