@@ -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
@@ -604,7 +602,7 @@ def insert_text_at_cursor(self, text: str) -> None:
604
602
text: New text to insert.
605
603
"""
606
604
607
- new_value = self ._template .insert_text_at_cursor (text )
605
+ new_value = self ._template .insert_text_at_cursor (text , self . value , self . cursor_position )
608
606
if new_value is not None :
609
607
self .value , self .cursor_position = new_value
610
608
else :
@@ -619,16 +617,33 @@ def replace(self, text: str, start: int, end: int):
619
617
end: End index to replace (inclusive).
620
618
"""
621
619
622
- old_cursor_position = self .cursor_position
623
- self .cursor_position = start
624
- new_value = self ._template .insert_text_at_cursor (text )
625
- if new_value is not None :
626
- value , cursor_position = new_value
627
- self .value = value [:cursor_position ] + value [end :]
628
- self .cursor_position = cursor_position
629
- else :
630
- self .cursor_position = old_cursor_position
631
- self .restricted ()
620
+ previous_cursor_position = self .cursor_position
621
+ value = self .value
622
+ cursor_position = start
623
+ for char in text :
624
+ new_value_cursor_position = self ._template .insert_text_at_cursor (char , value , cursor_position )
625
+ if new_value_cursor_position is None :
626
+ self .value = value
627
+ self .cursor_position = previous_cursor_position
628
+ self .restricted ()
629
+ return
630
+
631
+ new_value , new_cursor_position = new_value_cursor_position
632
+ if new_cursor_position >= end :
633
+ self .value = new_value [:end ] + value [end :]
634
+ self .cursor_position = new_cursor_position
635
+ return
636
+
637
+ value = new_value
638
+ cursor_position = new_cursor_position
639
+
640
+ self .value = value
641
+ self .cursor_position = end
642
+ while self .cursor_position > cursor_position :
643
+ self ._template .move_cursor (- 1 )
644
+ self ._template .delete_at_position ()
645
+
646
+ self .cursor_position = cursor_position
632
647
633
648
def clear (self ) -> None :
634
649
"""Clear the masked input."""
0 commit comments