qBFjcUdZddlmZddlZddlZddlZddlZddlmZm Z m Z m Z m Z m Z mZddlmZddlmZddlmZmZmZd gZejd Zejd Zejd Zejd ZejdZejdZee edfej Z!de"d<Gdde eZ#GddZ$Gdd Z%dS)zB The `Document` that implements all the text operations/querying. ) annotationsN)CallableDictIterableListNoReturnPatterncast) ClipboardData)vi_mode) PasteModeSelectionState SelectionTypeDocumentz ([a-zA-Z0-9_]+|[^a-zA-Z0-9_\s]+)z!^([a-zA-Z0-9_]+|[^a-zA-Z0-9_\s]+)z&^(([a-zA-Z0-9_]+|[^a-zA-Z0-9_\s]+)\s*)z([^\s]+)z ^([^\s]+)z ^([^\s]+\s*)_DocumentCachezdict[str, _DocumentCache]_text_to_document_cachec>eZdZdZd dZeZeZeZeZeZ eZ eZ eZ eZ dS) _ImmutableLineListz Some protection for our 'lines' list, which is assumed to be immutable in the cache. (Useful for detecting obvious bugs.) aobjectkwreturnrc td)Nz$Attempt to modify an immutable list.)NotImplementedError)selfrrs EC:\PYTHON\_runtimes\venv\Lib\site-packages\prompt_toolkit/document.py_errorz_ImmutableLineList._error6s!"HIIIN)rrrrrr)__name__ __module__ __qualname____doc__r __setitem__appendclearextendinsertpopremovereversesortrrrr0s_ JJJJK F E F F C FG DDDrrceZdZddZdS)rrNonec"d|_d|_dSN)lines line_indexesrs r__init__z_DocumentCache.__init__Es04 /3rN)rr/)r r!r"r5r-rrrrDs(333333rceZdZdZdZ dydzd Zd{dZd|dZed{dZ ed}dZ ed~dZ ed{dZ ed{dZ ed{dZed{dZed{dZed{dZeddZedd Zedd!Zed}d"Zed{d#Zed{d$Zddd'Zedd(Zedd)Zed}d*Zed}d+Zdd.Zdd/Zdd2Zedd3Z edd4Z!dd6Z" ddd=Z#ddd>Z$ ddd?Z% dddCZ& dddDZ' dddEZ( dddHZ)dddIZ* dddJZ+ dddKZ, dddLZ- dddMZ. dddPZ/ dddQZ0dddRZ1dddSZ2 dddUZ3 dddVZ4 dddZZ5 ddd\Z6 ddd]Z7d}d^Z8d}d_Z9dddaZ:d}dbZ;d}dcZddhZ?ddjZ@ddlZAeBjCd8fddqZDd}drZEdddtZFdddvZGddwZHddxZIdS)ra This is a immutable class around the text and cursor position, and contains methods for querying this data, e.g. to give the text before the cursor. This class is usually instantiated by a :class:`~prompt_toolkit.buffer.Buffer` object, and accessed as the `document` property of that class. :param text: string :param cursor_position: int :param selection: :class:`.SelectionState` )_text_cursor_position _selection_cacheNtextstrcursor_position int | None selectionSelectionState | Nonerr/c p|=|t|ks*Jtd|dt||t|}||_||_||_ t |j|_dS#t$r+t|_|jt |j<YdSwxYw)Nzcursor_position=z , len_text=) lenAssertionErrorr7r8r9rr<r:KeyErrorr)rr<r>r@s rr5zDocument.__init__\s&/SYY*F*F*F J J JSYY J JI I *F*FF  "!$iiO  /# =1$)r4s r__repr__zDocument.__repr__s+.)TTDITT4;OTTTTrotherrboolct|tsdS|j|jko|j|jko|j|jkS)NF) isinstancerr<r>r@)rrKs r__eq__zDocument.__eq__sP%** 5 I # 2$(== 2%/1 rc|jS)zThe document text.)r7r4s rr<z Document.texts zrintc|jS)zThe document cursor position.)r8r4s rr>zDocument.cursor_positions $$rc|jS)z :class:`.SelectionState` object.)r9r4s rr@zDocument.selections rc0|dpdS)z1Return character under cursor or an empty string.rr;_get_char_relative_to_cursorr4s r current_charzDocument.current_chars00339r9rc0|dpdS)z6Return character before the cursor or an empty string.r;rUr4s rchar_before_cursorzDocument.char_before_cursors0044::rc*|jd|jSr1r<r>r4s rtext_before_cursorzDocument.text_before_cursorsy14/122rc*|j|jdSr1r\r4s rtext_after_cursorzDocument.text_after_cursorsy-//00rcB|jd\}}}|S)z1Text from the start of the line until the cursor. )r] rpartition)r_r<s rcurrent_line_before_cursorz#Document.current_line_before_cursors%,77== 1d rcB|jd\}}}|S)z/Text from the cursor until the end of the line.ra)r_ partition)rr<rcs rcurrent_line_after_cursorz"Document.current_line_after_cursors%+55d;; a r list[str]c|jj1t|jd|j_|jjS)z) Array of all the lines. Nra)r:r2rr<splitr4s rr2zDocument.liness: ;  $ 249??43H3H I IDK {  r list[int]c|jjqtt|j}dg}|j}d}|D]}||dzz }||t|dkr|||j_|jjS)zG Array pointing to the start indexes of all the lines. Nrr )r:r3maprCr2r%r))r line_lengthsindexesr%pos line_lengths r_line_start_indexeszDocument._line_start_indexess ; # +sDJ//LcG^FC+   {Q&s 7||a '.DK ${''rc*|j|jdS)zY Array of the lines starting from the current line, until the last line. N)r2cursor_position_rowr4s rlines_from_currentzDocument.lines_from_currents z$24455rc*t|jS)zReturn the number of lines in this document. If the document ends with a trailing \n, that counts as the beginning of a new line.)rCr2r4s r line_countzDocument.line_counts4:rc |j|jzS)zuReturn the text on the line where the cursor is. (when the input consists of just one line, it equals `text`.)rdrgr4s r current_linezDocument.current_lines.1OOOrc|j}t|t|z }|d|S)z>The leading whitespace in the left margin of the current line.N)ryrClstrip)rrylengths r"leading_whitespace_in_current_linez+Document.leading_whitespace_in_current_linesA( \""S)<)<)>)>%?%??GVG$$rroffsetcP |j|j|zS#t$rYdSwxYw)zO Return character relative to cursor position, or empty string r;)r<r> IndexError)rr~s rrVz%Document._get_char_relative_to_cursors> 9T1F:; ;   22 s  %%c|jdkS)z5 True when we are at the first line. r)rtr4s r on_first_linezDocument.on_first_lines '1,,rc(|j|jdz kS)z4 True when we are at the last line. r )rtrwr4s r on_last_linezDocument.on_last_lines '4?Q+>>>rc@||j\}}|S)z) Current row. (0-based.) _find_line_start_indexr>)rrowrcs rrtzDocument.cursor_position_rows# ,,T-ABBQ rcP||j\}}|j|z S)z, Current column. (0-based.) r)rrcline_start_indexs rcursor_position_colzDocument.cursor_position_cols/#99$:NOO #&666rindextuple[int, int]cT|j}tj||dz }|||fS)z For the index of a character at a certain line, calculate the index of the first character on that line. Return (row, index) tuple. r )rrbisect bisect_right)rrrorps rrzDocument._find_line_start_index(s2*!'511A5GCL  rcD||\}}||z }||fS)z Given an index for the text, return the corresponding (row, col) tuple. (0-based. Returns (0, 0) for index=0.) )r)rrr row_indexcols rtranslate_index_to_positionz$Document.translate_index_to_position4s. 44U;;YiCxrrrc  |j|}|j|}nK#t$r>|dkr|jd}|jd}n|jd}|jd}YnwxYw|tdt |t |z }tdt |t |j}|S)z Given a (row, col) tuple, return the corresponding index. (Row and col params are 0-based.) Negative row/col values are turned into zero. rrY)rrr2rmaxminrCr<)rrrresultlines rtranslate_row_col_to_indexz#Document.translate_row_col_to_index?s &-c2F:c?DD & & &Qww1!4z!}1"5z"~  & #aS#d)),,---QFC NN3344 sAA%$A%c<|jt|jkS)z/True when the cursor is at the end of the text.)r>rCr<r4s ris_cursor_at_the_endzDocument.is_cursor_at_the_endXs#s49~~55rc|jdvS)z0True when the cursor is at the end of this line.)rar;)rWr4s ris_cursor_at_the_end_of_linez%Document.is_cursor_at_the_end_of_line]s J..rsubcT|j||j|jkS)zM `True` when this substring is found at the cursor position. )r<findr>)rrs rhas_match_at_current_positionz&Document.has_match_at_current_positionbs%y~~c4#788D>/2${{1~~---${{1~~1111 " 2     D ts5C9CC C"!C"c|r tjnd}dtjtj||j|DS)zu Find all occurrences of the substring. Return a list of absolute positions in the document. rc6g|]}|Sr-)r).0rs r z%Document.find_all..s QQQa QQQr)rrrrr<)rrrrs rfind_allzDocument.find_alls@ "-3 !QQ2;ry~~ty%#P#PQQQQrc~|r|jddd}n|jddd}|r tjnd}tjtj|ddd||} t |D]6\}} |dz|kr(| d t|z cS7n#t$rYnwxYwdS)z Find `text` before the cursor, return position relative to the cursor position. Return `None` if nothing was found. :param count: Find the n-th occurrence. NrYrr ) rdr]rrrrrrrCr) rrrrr before_cursorrrrrs rfind_backwardszDocument.find_backwardss  : ;DDbDAMM 3DDbD9M!,3 !;ryTTrT33]EJJ %h// 6 65q5E>>!KKNN?SXX5555" 6    D ts&AB-+B-- B:9B:WORDpatternPattern[str] | Nonec|||rdS|j}|||pd}|t||zdS)z Give the word before the cursor. If we have whitespace before the cursor this returns an empty string. :param pattern: (None or compiled regex). When given, use this regex pattern. rrr;rN)_is_word_before_cursor_completer]find_start_of_previous_wordrC)rrrr]rs rget_word_before_cursorzDocument.get_word_before_cursorsj  / /T7 / K K 2!400dG0LLQPQ!#&8"9"9E"A"C"CDDrc|r|||duS|jdkp |jddS)Nrr;rY)rr]isspace)rrrs rrz(Document._is_word_before_cursor_completesZ  33w3OOSWW W'2-W1H1M1U1U1W1W rc|r|rJ|jddd}|r|}n|rt}nt}||} t |D]&\}}|dz|kr|d cS'n#t $rYnwxYwdS)z Return an index relative to the cursor position pointing to the start of the previous word. Return `None` if nothing was found. :param pattern: (None or compiled regex). When given, use this regex pattern. NrYr r)r]_FIND_BIG_WORD_RE _FIND_WORD_RErrendr) rrrrr]regexrrrs rrz$Document.find_start_of_previous_words%W%%%"4TTrT:  "EE  "%EE!E>>"455 %h// ) )5q5E>>!IIaLL=(((" )    D ts4A:8A:: BBinclude_leading_whitespaceinclude_trailing_whitespacec|jddd}|j}d fd }|||}|||}sF|rD|rB|j|jdz } |j|j} t jd z} | | v| | vkrd}|r|d nd |r|dnd fS) a Return the relative boundaries (startpos, endpos) of the current word under the cursor. (This is at the current line, because line boundaries obviously don't belong to any word.) If not on a word, this returns (0,0) NrYinclude_whitespacerLr Pattern[str]cJttttd|fS)N))FF)FT)TF)TT)_FIND_CURRENT_WORD_RE1_FIND_CURRENT_WORD_INCLUDE_TRAILING_WHITESPACE_RE_FIND_CURRENT_BIG_WORD_RE5_FIND_CURRENT_BIG_WORD_INCLUDE_TRAILING_WHITESPACE_RE)rrs r get_regexz;Document.find_boundaries_of_current_word..get_regexs. 5P8S  '( * *rr 0123456789_r)rrLrr)rdrgsearchr<r>string ascii_lettersr) rrrrr]r_r match_before match_afterc1c2alphabets ` rfind_boundaries_of_current_wordz(Document.find_boundaries_of_current_words#")rrrrs rget_word_under_cursorzDocument.get_word_under_cursors@ 99t9DD sy-58Ls8RRSSrcl|dkr|| |S|rtnt}||j} t |D]I\}}|dkr|ddkr|dz }|dz|kr|dcSJn#t$rYnwxYwdS)z Return an index relative to the cursor position pointing to the start of the next word. Return `None` if nothing was found. rrrr N)find_previous_word_beginningrrrr_rrrrrrrrrrs rfind_next_word_beginningz!Document.find_next_word_beginning's 19944E64MM M%)<!!}>>$"899 %h// * *566ekk!nn11QJEq5E>> ;;q>>)))"  *    D ts AB$"B$$ B10B1cb|dkr|| |S|r|j}n|jdd}|rtnt}||} t |D]0\}}|dz|kr"|d} |r| cS| dzcS1n#t$rYnwxYwdS)z Return an index relative to the cursor position pointing to the end of the next word. Return `None` if nothing was found. rrr N)find_previous_word_endingr_rrrrrr) rrrrr<riterablerrvalues rfind_next_word_endingzDocument.find_next_word_ending@s 19911T1JJ J # .)DD)!""-D%)<!!}>>$'' %h// ) )5q5E>>!IIaLLE/)$ $qy((( " )    D ts7BBB B,+B,c8|dkr|| |S|rtnt}||jddd} t |D]&\}}|dz|kr|d cS'n#t$rYnwxYwdS)z Return an index relative to the cursor position pointing to the start of the previous word. Return `None` if nothing was found. rrNrYr )rrrrr]rrrrs rrz%Document.find_previous_word_beginning`s 19900vD0II I%)<!!}>>$"9$$B$"?@@ %h// ) )5q5E>>!IIaLL=(((" )    D ts4B B BBc|dkr|| |S|jdd|jdddz}|rtnt}||} t |D]M\}}|dkr|ddkr|dz }|dz|kr|d dzcSNn#t$rYnwxYwdS)z Return an index relative to the cursor position pointing to the end of the previous word. Return `None` if nothing was found. rrNr rY) rr_r]rrrrrr)rrrr]rrrrs rrz"Document.find_previous_word_endingus 199--UF-FF F!3BQB7$:QRVRVTVRV:WW%)<!!}>>"455 %h// / /566ekk!nn11QJEq5E>>!KKNN?Q...."  /    D ts%ACC CC match_funcCallable[[str], bool]cd}t|j|jdzdD]"\}}||r d|z}|dz}|dkrn#|S)zn Look downwards for empty lines. Return the line index, relative to the current line. Nr rrr2rtrrrrrrs rfind_next_matching_linez Document.find_next_matching_linesw$TZ0H10L0N0N%OPP  KE4z$ U zz rcd}t|jd|jdddD]"\}}||r d|z }|dz}|dkrn#|S)zl Look upwards for empty lines. Return the line index, relative to the current line. NrYr rrrs rfind_previous_matching_linez$Document.find_previous_matching_lines}$TZ0J$2J0J%KDDbD%QRR  KE4z$ e zz rcf|dkr|| St|j| S)z4 Relative position for cursor left. r)get_cursor_right_positionrrrrs rget_cursor_left_positionz!Document.get_cursor_left_positions9 199115&99 9D,e4444rc~|dkr|| St|t|jS)z5 Relative position for cursor_right. r)rrrCrgrs rrz"Document.get_cursor_right_positions> 19900%88 85#d<==>>>rpreferred_columnc|dksJ||jn|}|td|j|z ||jz S)a Return the relative cursor position (character index) where we would be if the user pressed the arrow-up button. :param preferred_column: When given, go to this column instead of staying at the current column. r Nr)rrrrtr>rrrcolumns rget_cursor_up_positionzDocument.get_cursor_up_positionsezzzz(8(@D $ $FV   + +At/%788&  " # rct|dksJ||jn|}||j|z||jz S)a Return the relative cursor position (character index) where we would be if the user pressed the arrow-down button. :param preferred_column: When given, go to this column instead of staying at the current column. r )rrrtr>rs rget_cursor_down_positionz!Document.get_cursor_down_positionsTzzzz(8(@D $ $FV   + +D,Du,Lf U U" # rleft_chright_chend_posc8|j|krdS|t|j}n"tt|j|}d}t |jdz|D]8}|j|}||kr|dz }n ||kr|dz}|dkr ||jz cS9dS)z Find the right bracket enclosing current position. Return the relative position to the cursor position. When `end_pos` is given, don't look past the position. rNr )rWrCr<rranger>)rrrrstackrcs rfind_enclosing_bracket_rightz%Document.find_enclosing_bracket_rights   ( (1 ?$)nnGG#di..'22Gt+a/99 0 0A ! AG|| h zz4/////tr start_posc|j|krdS|d}ntd|}d}t|jdz |dz dD]8}|j|}||kr|dz }n ||kr|dz}|dkr ||jz cS9dS)z Find the left bracket enclosing current position. Return the relative position to the cursor position. When `start_pos` is given, don't look past the position. rNr rY)rWrrr>r<)rrrr rrrs rfind_enclosing_bracket_leftz$Document.find_enclosing_bracket_lefts   ' '1  IIAy))It+a/QCC 0 0A ! AH}} g zz4/////trcdD]`}|d}|d}|j|kr||||pdcS|j|kr||||pdcSadS)z Return relative cursor position of matching [, (, { or < bracket. When `start_pos` or `end_pos` are given. Don't look past the positions. )z()z[]z{}z<>rr )r)r )rWrr )rr rpairABs rfind_matching_bracket_positionz'Document.find_matching_bracket_position4s+ X XDQAQA A%%88Aw8OOTSTTTT"a''771 7RRWVWWWW(qrc|j S)z0Relative position for the start of the document.)r>r4s rget_start_of_document_positionz'Document.get_start_of_document_positionHs$$$rc:t|j|jz S)z.Relative position for the end of the document.)rCr<r>r4s rget_end_of_document_positionz%Document.get_end_of_document_positionLs49~~ 444rafter_whitespacec|r@|j}t|t|z |jz St|j S)z-Relative position for the start of this line.)ryrCr{rrd)rrrys rget_start_of_line_positionz#Document.get_start_of_line_positionPs_  9,LL!!l))++,,-*+  7888 8rc*t|jS)z+Relative position for the end of this line.)rCrgr4s rget_end_of_line_positionz!Document.get_end_of_line_position\s41222rcdt|j|jz dz S)zR Relative position for the last non blank character of this line. r )rCryrstriprr4s r'last_non_blank_of_current_line_positionz0Document.last_non_blank_of_current_line_position`s.4$++--..1IIAMMrrc~t|j}|j}tdt ||}||z S)z Return the relative cursor position for this column at the current line. (It will stay between the boundaries of the line in case of a larger number.) r)rCryrrr)rrrqcurrent_columns rget_column_cursor_positionz#Document.get_column_cursor_positionfs@ $+,, 1QK0011&&rc||jr$t|j|jjg\}}n|j|j}}||fS)z Return (from, to) tuple of the selection. start and end position are included. This doesn't take the selection type into account. Use `selection_ranges` instead. )r@sortedr>original_cursor_position)rfrom_tos rselection_rangezDocument.selection_rangersO > C%t~'NOIE22,d.B2EbyrIterable[tuple[int, int]]c #K|jrt|j|jjg\}}|jjt jkr||\}}||\}}t||g\}}|j}tr|dz }t||dzD]Y}t||} || kr<| ||| |t| |fVZdS|jjt jkrtd|jdd|dz}|jd|dkr|jd|}nt|jdz }tr|dz }||fVdSdS)aE Return a list of `(from, to)` tuples for the selection or none if nothing was selected. The upper boundary is not included. This will yield several (from, to) tuples in case of a BLOCK selection. This will return zero ranges, like (8,8) for empty lines in a block selection. r rraN)r@r!r>r"typerBLOCKrr2r rrCrrLINESrr<rfindr) rr#r$ from_line from_columnto_line to_columnr2lrqs rselection_rangeszDocument.selection_rangess >' %t~'NOIE2~"m&999)-)I)I%)P)P& ;%)%E%Eb%I%I")/i0H)I)I& Y 99#NIy'A+66  A"%eAh--K"k11 ;;A{KK ;; !3{I#>#>  >&-*===49??4E#B#BQ#FGGEy~~dB//144!Y^^D"55 ^^a/99!GBRiO' ' rtuple[int, int] | Nonec@|jr|j|}||d}||t|}t |j|jjg\}}t||}t||}||kr|jj tj kr|}|}n|jj tj kr| |\} } | |\} } t | | g\} } | t|krdS||| }||| }| |\} } | |\} } tr| dz } | | fSdS)aB If the selection spans a portion of the given line, return a (from, to) tuple. The returned upper boundary is not included in the selection, so `(0, 0)` is an empty selection. `(0, 1)`, is a one character selection. Returns None if the selection doesn't cover this line at all. rNr )r@r2rrCr!r>r"rrr(rr*r)rr )rrr row_startrow_endr#r$intersection_startintersection_endrccol1col2r-r/s rselection_range_at_linez Document.selection_range_at_lines >& .:c?D77Q??I55c3t99EEG%t~'NOIE2 "%Y!6!6 "7B// !%555>&-*===)2&'.$$^(M,???">>uEEGAt">>rBBGAt!'t !5!5JD$c$ii''#t)-)H)Hd)S)S&'+'F'FsD'Q'Q$!%!A!ABT!U!U;#??@PQQ 999#NI"I--trtuple[Document, ClipboardData]c~|jr%g}g}|j}d}|D]S\}}|dkr|}||j||||j|||}T||j|dd|}d|}|jjtjkr| dr |dd}t||t||jjfS|tdfS)z Return a (:class:`.Document`, :class:`.ClipboardData`) tuple, where the document represents the new document when the selection is cut, and the clipboard data, represents whatever has to be put on the clipboard. rNrar;rYr\) r@r>r1r%r<joinr(rr*endswithrr ) r cut_partsremaining_partsnew_cursor_positionlast_tor#r$cut_textremaining_texts r cut_selectionzDocument.cut_selectionsT > +I O"&"6 G!2244   ra<<*/'&&ty'?@@@  58!4555  " "49WXX#6 7 7 7yy++HWW_55N~"m&999h>O>OPT>U>U9#CRC=n>QRRRh(;<<  r*** *rdatar paste_moderc|tjk}|tjk}|jtjkr|r;|jd|jdz|j|zz|j|jdzdz}n|j|j|zz|j z}|jt|j|zz}|r|dz}n|jtj kr|j }|rt|j d||jg|zz|j |dz} d| }td|j d||z}n}|j d|dz|jg|zz|j |dzdz} td|j d|dz|zdz}d| }n|jtjkr|j dd} |j } |j|rdndz} t#|jdD]z\} } | | z}|t| kr| d| || | |<| |d| | |zz| || dz| |<{d| }|j|rdndz}t+||S)a Return a new :class:`.Document` instance which contains the result if we would paste this data at the current cursor position. :param paste_mode: Where to paste. (Before/after/emacs.) :param count: When >1, Paste multiple times. Nr rar;rr\)r VI_BEFOREVI_AFTERr(r CHARACTERSr<r>r]r_rCr*rtr2r=r)rrrjr%ljustr)rrFrGrbeforeafternew_textrAr0r2 start_line start_columnrrrs rpaste_clipboard_datazDocument.paste_clipboard_datasy22i00 9 0 0 0 I8 4q 889i%'(i 4q 8 : :;<+di%.??$BXX#'"6TY%9O"O  )#q(# Y-- - -(A , 2A2$)u)<>   rrMcd d}|||}|r.|rdnd}td|| |zS|j S) zX Return the start of the current paragraph. (Relative cursor position.) r<r=rrLc0| p|Sr1rr<s rrz/Document.start_of_paragraph..match_funcb8-t||~~ -rrrrr rNr<r=rrL)rrrr>)rrrMr line_indexadds rstart_of_paragraphzDocument.start_of_paragraph]s  . . . .55!6    )$!!1Cq$55ZK5HH3NOO O(( (rrNcd d}|||}|r-|rdnd}td|| |z St|jS) zV Return the end of the current paragraph. (Relative cursor position.) r<r=rrLc0| p|Sr1rWrXs rrz-Document.end_of_paragraph..match_functrYrrZrr r[Nr\)rrrrCr_)rrrNrr]r^s rend_of_paragraphzDocument.end_of_paragraphos}  . . . .11Zu1UU  /#!!!Cq$77j7IICOPP Pt-.. .rcJt|j|z|j|jS)z Create a new document, with this text inserted after the buffer. It keeps selection ranges and cursor position in sync. r<r>r@)rr<r>r@)rr<s r insert_afterzDocument.insert_afters0 T! 0n    rc|j}|r+t|jt|z|j}t ||jz|jt|z|S)z Create a new document, with this text inserted before the buffer. It keeps selection ranges and cursor position in sync. )r"r(rd)r@rr"rCr(rr<r>)rr<selection_states r insert_beforezDocument.insert_beforesx .  ,)8)Qd))*$)O  ! 03t99<%    r)r;NN)r<r=r>r?r@rArr/)rr=)rKrrrL)rrQ)rrA)rrh)rrk)r)r~rQrr=)rrL)rrQrr)rrQrrQrrQ)rr=rrL)FFFr ) rr=rrLrrLrrLrrQrr?)F)rr=rrLrrk)FFr ) rr=rrLrrLrrQrr?)FN)rrLrrrr=)rrLrrrrL)r FN)rrQrrLrrrr?)FFF)rrLrrLrrLrr)rrLrr=)r F)rrQrrLrr?)Fr F)rrLrrQrrLrr?)r )rrrrQrr?)rrQrrQ)r N)rrQrr?rrQr1)rr=rr=rr?rr?)rr=rr=r r?rr?)NN)r r?rr?rrQ)rrLrrQ)rrQrrQ)rr)rr&)rrQrr2)rr;)rFr rGrrrQrr)rrQrMrLrrQ)rrQrNrLrrQ)r<r=rr)Jr r!r"r# __slots__r5rJrOpropertyr<r>r@rWrZr]r_rdrgr2rrrurwryr}rVrrrtrrrrrrrrrrrrrrrrrrrrrrrrrrr rrrrrrrr%r1r:rErEMACSrRrTr_rbrerhr-rrrrMs  FI&*+/ =====NUUUU    X%%%X%X:::X:;;;X;333X3111X1X X !!!X!(((X(6666X6 X PPPXP %%%X% ---X- ???X? X777X7 ! ! ! !    2666X6///X/QQQQ!&).! '''''RRRRRR!&! <BFEEEEE(BFRVF+0,1 ) ) ) ) ) VTTTTT,14TYB,1,,18?@(?@&55555?????>B     .>B     *BFDDHDCG(%%%%5555 9 9 9 9 93333NNNN ' ' ' '*0 0 0 0 d0000d"+"+"+"+N!* ?L?L?L?L?LB    )))))$/////$           r)&r# __future__rrrrweakreftypingrrrrrr r clipboardr filtersr r@rrr__all__compilerrrrrrr=WeakValueDictionaryr__annotations__rrrr-rrrus#""""" JJJJJJJJJJJJJJJJJJ$$$$$$??????????  >?? " #GHH4>BJ-551 BJ{++&BJ|448B ?8S8S5 6:T G!!66 c(33333333Q Q Q Q Q Q Q Q Q Q r