§
    xÅjO5  ã                  ó"  — d Z ddlmZ ddlmZ ddlmZ ddlmZm	Z	m
Z
 ddgZdd	lmZ dd
lmZmZmZmZmZmZmZmZmZmZmZmZmZmZ erddlmZ dZ G d„ de¦  «        Z  ed¬¦  «        d1d„¦   «         Z! ed¬¦  «        d2d„¦   «         Z" ed¬¦  «        d2d„¦   «         Z# ed¬¦  «        d2d„¦   «         Z$ ed¬¦  «        d2d„¦   «         Z% G d„ de
¦  «        Z& ed¬¦  «        d3d„¦   «         Z'd4d$„Z(	 	 d5d6d+„Z)d7d-„Z*d8d.„Z+	 	 d5d9d0„Z,e)Z-d%S ):zú
Grapheme cluster segmentation following Unicode Standard Annex #29.

This module provides pure-Python implementation of the grapheme cluster boundary algorithm as
defined in UAX #29: Unicode Text Segmentation.

https://www.unicode.org/reports/tr29/
é    )Úannotations)ÚIntEnum)Ú	lru_cache)ÚTYPE_CHECKINGÚOptionalÚ
NamedTuplezwcwidth.bisearchzwcwidth.table_graphemeé   )Úbisearch)Ú
GRAPHEME_LÚ
GRAPHEME_TÚ
GRAPHEME_VÚGRAPHEME_LVÚINCB_EXTENDÚINCB_LINKERÚGRAPHEME_LVTÚINCB_CONSONANTÚGRAPHEME_EXTENDÚGRAPHEME_CONTROLÚGRAPHEME_PREPENDÚGRAPHEME_SPACINGMARKÚEXTENDED_PICTOGRAPHICÚGRAPHEME_REGIONAL_INDICATOR)ÚIteratoré    c                  óJ   — e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdS )ÚGCBz'Grapheme Cluster Break property values.r   r	   é   é   é   é   é   é   é   é	   é
   é   é   é   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚOTHERÚCRÚLFÚCONTROLÚEXTENDÚZWJÚREGIONAL_INDICATORÚPREPENDÚSPACING_MARKÚLÚVÚTÚLVÚLVT© ó    úAC:\Projects\Historical\venv\Lib\site-packages\wcwidth/grapheme.pyr   r   0   s[   € € € € € Ø1Ð1à€EØ	
€BØ	
€BØ€GØ€FØ
€CØÐØ€GØ€LØ	€AØ
€AØ
€AØ	€BØ
€C€C€Cr<   r   i   )ÚmaxsizeÚucsÚintÚreturnc                ó  — | dk    rt           j        S | dk    rt           j        S | dk    rt           j        S t	          | t
          ¦  «        rt           j        S t	          | t          ¦  «        rt           j        S t	          | t          ¦  «        rt           j
        S t	          | t          ¦  «        rt           j        S t	          | t          ¦  «        rt           j        S t	          | t          ¦  «        rt           j        S t	          | t"          ¦  «        rt           j        S t	          | t&          ¦  «        rt           j        S t	          | t*          ¦  «        rt           j        S t	          | t.          ¦  «        rt           j        S t           j        S )z;Return the Grapheme_Cluster_Break property for a codepoint.r(   r%   i   )r   r.   r/   r2   Ú	_bisearchr   r0   r   r1   r   r3   r   r4   r   r5   r   r6   r   r7   r   r8   r   r9   r   r:   r-   ©r?   s    r=   Ú_grapheme_cluster_breakrE   F   sA  € ð
 ˆf‚}€}ÝŒvˆØ
ˆf‚}€}ÝŒvˆØ
ˆf‚}€}ÝŒwˆå�Õ&Ñ'Ô'ð ÝŒ{ÐÝ�•oÑ&Ô&ð ÝŒzÐÝ�Õ1Ñ2Ô2ð &ÝÔ%Ð%Ý�Õ&Ñ'Ô'ð ÝŒ{ÐÝ�Õ*Ñ+Ô+ð  ÝÔÐÝ�•jÑ!Ô!ð ÝŒuˆÝ�•jÑ!Ô!ð ÝŒuˆÝ�•jÑ!Ô!ð ÝŒuˆÝ�•kÑ"Ô"ð ÝŒvˆÝ�•lÑ#Ô#ð ÝŒwˆÝŒ9Ðr<   Úboolc                óF   — t          t          | t          ¦  «        ¦  «        S )z6Check if codepoint has Extended_Pictographic property.)rF   rC   r   rD   s    r=   Ú_is_extended_pictographicrH   i   s   € õ •	˜#Õ4Ñ5Ô5Ñ6Ô6Ð6r<   c                óF   — t          t          | t          ¦  «        ¦  «        S )z,Check if codepoint has InCB=Linker property.)rF   rC   r   rD   s    r=   Ú_is_incb_linkerrJ   o   ó   € õ •	˜#�{Ñ+Ô+Ñ,Ô,Ð,r<   c                óF   — t          t          | t          ¦  «        ¦  «        S )z/Check if codepoint has InCB=Consonant property.)rF   rC   r   rD   s    r=   Ú_is_incb_consonantrM   u   s   € õ •	˜#�~Ñ.Ô.Ñ/Ô/Ð/r<   c                óF   — t          t          | t          ¦  «        ¦  «        S )z,Check if codepoint has InCB=Extend property.)rF   rC   r   rD   s    r=   Ú_is_incb_extendrO   {   rK   r<   c                  ó(   — e Zd ZU dZded<   ded<   dS )ÚBreakResultz*Result of grapheme cluster break decision.rF   Úshould_breakr@   Úri_countN)r)   r*   r+   r,   Ú__annotations__r;   r<   r=   rQ   rQ   �   s+   € € € € € € Ø4Ð4àÐÐÑØ€M€M�M€M€Mr<   rQ   Úprev_gcbÚcurr_gcbúOptional[BreakResult]c                ó¨  — | t           j        k    r!|t           j        k    rt          dd¬¦  «        S | t           j        t           j        t           j        fv rt          dd¬¦  «        S |t           j        t           j        t           j        fv rt          dd¬¦  «        S | t           j        k    rA|t           j        t           j        t           j        t           j        fv rt          dd¬¦  «        S | t           j        t           j        fv r+|t           j        t           j	        fv rt          dd¬¦  «        S | t           j        t           j	        fv r!|t           j	        k    rt          dd¬¦  «        S |t           j
        k    rt          dd¬¦  «        S |t           j        k    rt          dd¬¦  «        S | t           j        k    rt          dd¬¦  «        S dS )zÚ
    Check simple GCB-pair-based break rules (cacheable).

    Returns BreakResult for rules that can be determined from GCB properties alone, or None if
    complex lookback rules (GB9c, GB11) need to be checked.
    Fr   ©rR   rS   TN)r   r.   r/   rQ   r0   r6   r7   r9   r:   r8   r1   r5   r4   )rU   rV   s     r=   Ú_simple_break_checkrZ   ˆ   s¤  € ð •3”6ÒÐ˜h­#¬&Ò0Ð0Ý¨¸Ð:Ñ:Ô:Ð:ð •C”K¥¤­¬Ð0Ð0Ð0Ý¨°qÐ9Ñ9Ô9Ð9ð •C”K¥¤­¬Ð0Ð0Ð0Ý¨°qÐ9Ñ9Ô9Ð9ð •3”5ÒÐ˜X­#¬%µ´½¼ÅÄÐ)HÐHÐHÝ¨¸Ð:Ñ:Ô:Ð:ð •C”F�CœE�?Ð"Ð" xµC´E½3¼5°>Ð'AÐ'AÝ¨¸Ð:Ñ:Ô:Ð:ð •C”G�SœUÐ#Ð#Ð#¨µC´EÒ(9Ð(9Ý¨¸Ð:Ñ:Ô:Ð:ð •3”:ÒÐÝ¨¸Ð:Ñ:Ô:Ð:ð •3Ô#Ò#Ð#Ý¨¸Ð:Ñ:Ô:Ð:ð •3”;ÒÐÝ¨¸Ð:Ñ:Ô:Ð:ð ˆ4r<   ÚtextÚstrÚcurr_idxrS   c                óÖ  — t          | |¦  «        }|�|S |t          j        k    rt          dd¬¦  «        S t	          ||         ¦  «        }t          |¦  «        r“|dz
  }|dk    rOt          t	          ||         ¦  «        ¦  «        r-|dz  }|dk    r"t          t	          ||         ¦  «        ¦  «        °-|dk    r3t          t	          ||         ¦  «        ¦  «        rt          dd¬¦  «        S | t          j        k    r{t          |¦  «        rl|dz
  }|dk    rat	          ||         ¦  «        }t          |¦  «        }	|	t          j
        k    r|dz  }n!t          |¦  «        rt          dd¬¦  «        S n|dk    °a| t          j        k    r>|t          j        k    r.|dz  dk    rt          d|dz   ¬¦  «        S t          dd¬¦  «        S |t          j        k    rdnd}t          d|¬¦  «        S )z�
    Determine if there should be a grapheme cluster break between prev and curr.

    Implements UAX #29 grapheme cluster boundary rules.
    NFr   rY   r	   r   T)rZ   r   r2   rQ   ÚordrM   rO   rJ   rH   rE   r1   r3   )
rU   rV   r[   r]   rS   ÚresultÚcurr_ucsÚiÚprev_ucsÚ	prev_props
             r=   Ú_should_breakre   ¹   sü  € õ ! ¨8Ñ4Ô4€FØÐØˆð •3”7ÒÐÝ¨¸Ð:Ñ:Ô:Ð:õ �4˜”>Ñ"Ô"€HÝ˜(Ñ#Ô#ð ?Ø�q‰LˆØ�1Šfˆf�­¨T°!¬W©¬Ñ6Ô6ˆfØ�‰FˆAð �1Šfˆf�­¨T°!¬W©¬Ñ6Ô6ˆfà�Š6ˆ6•o¥c¨$¨q¬'¡l¤lÑ3Ô3ˆ6Ý¨E¸AÐ>Ñ>Ô>Ð>ð •3”7ÒÐÕ8¸ÑBÔBÐØ�q‰LˆØ�1ŠfˆfÝ˜4 œ7‘|”|ˆHÝ/°Ñ9Ô9ˆIØ�CœJÒ&Ð&Ø�Q‘��Ý*¨8Ñ4Ô4ð Ý"°ÀÐBÑBÔBÐBàð �1Šfˆfð •3Ô)Ò)Ð)¨h½#Ô:PÒ.PÐ.PØ�a‰<˜1ÒÐÝ¨E¸HÀq¹LÐIÑIÔIÐIÝ¨°qÐ9Ñ9Ô9Ð9ð ¥Ô 6Ò6Ð6ˆqˆq¸A€HÝ D°8Ð<Ñ<Ô<Ð<r<   NÚunistrÚstartÚendú
int | NoneúIterator[str]c              #  óÎ  K  — | sdS t          | ¦  «        }|€|}||k    s||k    rdS t          ||¦  «        }|}d}t          t          | |         ¦  «        ¦  «        }|t          j        k    rd}t          |dz   |¦  «        D ]U}t          t          | |         ¦  «        ¦  «        }t          ||| ||¦  «        }	|	j        }|	j	        r| ||…         V — |}|}ŒV| ||…         V — dS )uI  
    Iterate over grapheme clusters by UAX #29 extended grapheme cluster rules.

    Grapheme clusters are "user-perceived characters" - what a user would
    consider a single character, which may consist of multiple Unicode
    codepoints (e.g., a base character with combining marks, emoji sequences).

    :param unistr: The Unicode string to segment.
    :param start: Starting index (default 0).
    :param end: Ending index (default len(unistr)).
    :yields: Grapheme cluster substrings.

    Example::

        >>> list(iter_graphemes('cafe\u0301'))
        ['c', 'a', 'f', 'eÌ�']
        >>> list(iter_graphemes('ok\U0001F468\u200D\U0001F469\u200D\U0001F467'))
        ['o', 'k', 'ðŸ‘¨\u200dðŸ‘©\u200dðŸ‘§']
        >>> list(iter_graphemes('ok\U0001F1FA\U0001F1F8'))
        ['o', 'k', 'ðŸ‡ºðŸ‡¸']

    .. versionadded:: 0.3.0
    Nr   r	   )
ÚlenÚminrE   r_   r   r3   Úrangere   rS   rR   )
rf   rg   rh   ÚlengthÚcluster_startrS   rU   ÚidxrV   r`   s
             r=   Ú_iter_graphemes_pythonrr   ñ   s(  è è € ð8 ð Øˆå�‰[Œ[€Fà
€{Øˆà�‚|€|�u ’�Øˆå
ˆc�6Ñ
Ô
€Cð €MØ€Hõ '¥s¨6°%¬=Ñ'9Ô'9Ñ:Ô:€Hð •3Ô)Ò)Ð)Øˆå�U˜Q‘Y Ñ$Ô$ð 
ð 
ˆÝ*­3¨v°c¬{Ñ+;Ô+;Ñ<Ô<ˆå˜x¨°6¸3ÀÑIÔIˆØ”?ˆàÔð 	 Ø˜ sÐ*Ô+Ð+Ð+Ð+ØˆMàˆˆð �˜sÐ"Ô
#Ð#Ð#Ð#Ð#Ð#r<   Úposc                óV  — t          | |dz
           ¦  «        }|dk    r|dk    r| |dz
           dk    r|dz
  S |dk     r_|dk    rT|dk    rNt          | |dz
           ¦  «        }|dk    r0t          |¦  «        t          j        k    rt	          | |dz
  ¦  «        S |dz
  S |dz
  }|dk    rk||z
  t
          k     r]t          | |         ¦  «        }d|cxk    rdk     rn nn7t          |¦  «        t          j        k    rn|dz  }|dk    r||z
  t
          k     °]|}t          t          | |         ¦  «        ¦  «        }|t          j        k    rdnd}t          |dz   |¦  «        D ]I}	t          t          | |	         ¦  «        ¦  «        }
t          ||
| |	|¦  «        }|j
        }|j        r|	}|
}ŒJ|S )a  
    Find the start of the grapheme cluster containing the character before pos.

    Scans backwards from pos to find a safe starting point, then iterates forward using standard
    break rules to find the actual cluster boundary.

    :param text: The Unicode string.
    :param pos: Position to search before (exclusive).
    :returns: Start position of the grapheme cluster.
    r	   r%   r   úé€   r   r   )r_   rE   r   r4   Ú_find_cluster_startÚMAX_GRAPHEME_SCANr0   r3   rn   re   rS   rR   )r[   rs   Ú	target_cpÚprev_cpÚ
safe_startÚcprp   Úleft_gcbrS   rb   Ú	right_gcbr`   s               r=   rw   rw   5  sô  € õ �D˜˜q™”MÑ"Ô"€Ið �DÒÐ˜S AšX˜X¨$¨s°Q©w¬-¸4Ò*?Ð*?Ø�Q‰wˆð �4ÒÐà�!Š8ˆ8˜	 TÒ)Ð)Ý˜$˜s Q™wœ-Ñ(Ô(ˆGØ˜$ŠˆÕ#:¸7Ñ#CÔ#CÅsÄ{Ò#RÐ#RÝ*¨4°°q±Ñ9Ô9Ð9Ø�Q‰wˆð �q‘€JØ
�qŠ.ˆ.˜c JÑ.Õ2CÒCÐCÝ��jÔ!Ñ"Ô"ˆØ�2ÐÐÒÐ˜ÒÐÐÐÐØÝ" 2Ñ&Ô&­#¬+Ò5Ð5ØØ�a‰ˆ
ð �qŠ.ˆ.˜c JÑ.Õ2CÒCÐCð €MÝ&¥s¨4°
Ô+;Ñ'<Ô'<Ñ=Ô=€HØ¥Ô 6Ò6Ð6ˆqˆq¸A€Hå�: ‘> 3Ñ'Ô'ð ð ˆÝ+­C°°Q´©L¬LÑ9Ô9ˆ	Ý˜x¨°D¸!¸XÑFÔFˆØ”?ˆØÔð 	ØˆMØˆˆàÐr<   c           	     óh   — |dk    rdS t          | t          |t          | ¦  «        ¦  «        ¦  «        S )aÌ  
    Find the grapheme cluster boundary immediately before a position.

    :param unistr: The Unicode string to search.
    :param pos: Position in the string (0 < pos <= len(unistr)).
    :returns: Start index of the grapheme cluster containing the character at pos-1.

    Example::

        >>> grapheme_boundary_before('Hello \U0001F44B\U0001F3FB', 8)
        6
        >>> grapheme_boundary_before('a\r\nb', 3)
        1

    .. versionadded:: 0.3.6
    r   )rw   rm   rl   )rf   rs   s     r=   Úgrapheme_boundary_beforer€   i  s2   € ð" ˆa‚x€xØˆqÝ˜v¥s¨3µ°F±´Ñ'<Ô'<Ñ=Ô=Ð=r<   úOptional[int]c              #  ó   K  — | sdS t          | ¦  «        }|€|nt          ||¦  «        }t          |d¦  «        }||k    s||k    rdS |}||k    r.t          | |¦  «        }||k     rdS | ||…         V — |}||k    °,dS dS )a¡  
    Iterate over grapheme clusters in reverse order (last to first).

    :param unistr: The Unicode string to segment.
    :param start: Starting index (default 0).
    :param end: Ending index (default len(unistr)).
    :yields: Grapheme cluster substrings in reverse order.

    Example::

        >>> list(iter_graphemes_reverse('cafe\u0301'))
        ['e\u0301', 'f', 'a', 'c']

    .. versionadded:: 0.3.6
    Nr   )rl   rm   Úmaxrw   )rf   rg   rh   ro   rs   rp   s         r=   Úiter_graphemes_reverser„     sµ   è è € ð( ð Øˆå�‰[Œ[€Fà�Kˆ&ˆ&¥S¨¨fÑ%5Ô%5€CÝ��q‰MŒM€Eà�‚|€|�u ’�Øˆà
€CØ
�Š+ˆ+Ý+¨F°CÑ8Ô8ˆà˜5Ò Ð ØˆEØ�] 3Ð&Ô'Ð'Ð'Ð'Øˆð �Š+ˆ+ˆ+ˆ+ˆ+ˆ+r<   )r?   r@   rA   r   )r?   r@   rA   rF   )rU   r   rV   r   rA   rW   )rU   r   rV   r   r[   r\   r]   r@   rS   r@   rA   rQ   )r   N)rf   r\   rg   r@   rh   ri   rA   rj   )r[   r\   rs   r@   rA   r@   )rf   r\   rs   r@   rA   r@   )rf   r\   rg   r@   rh   r�   rA   rj   ).r,   Ú
__future__r   Úenumr   Ú	functoolsr   Útypingr   r   r   Ú__lazy_modules__r
   rC   Útable_graphemer   r   r   r   r   r   r   r   r   r   r   r   r   r   Úcollections.abcr   rx   r   rE   rH   rJ   rM   rO   rQ   rZ   re   rr   rw   r€   r„   Úiter_graphemesr;   r<   r=   ú<module>r�      sK  ððð ð #Ð "Ð "Ð "Ð "Ð "ð Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð à 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6ð ØðÐ ð
 ,Ð +Ð +Ð +Ð +Ð +ð:ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð ð )à(Ð(Ð(Ð(Ð(Ð(ð Ð ðð ð ð ð ˆ'ñ ô ð ð, €�4ÐÑÔðð ð ñ ÔððD €�4ÐÑÔð7ð 7ð 7ñ Ôð7ð
 €�4ÐÑÔð-ð -ð -ñ Ôð-ð
 €�4ÐÑÔð0ð 0ð 0ñ Ôð0ð
 €�4ÐÑÔð-ð -ð -ñ Ôð-ð
ð ð ð ð �*ñ ô ð ð €�4ÐÑÔð-ð -ð -ñ Ôð-ð`5=ð 5=ð 5=ð 5=ðt ØðA$ð A$ð A$ð A$ð A$ðH1ð 1ð 1ð 1ðh>ð >ð >ð >ð0 Øð&ð &ð &ð &ð &ðT (€€€r<   