
    RiT                         d Z ddlZddlZddlZddlmZ ddlmZmZm	Z	  ej                  e      Zg dZ G d de      ZddZ	 dd	ed
edededef
dZd Zd Zd Zd Zd Zd ZddZd Zd Zd Zd Zd Zy)z
A set of functions useful for customizing bibtex fields.
You can find inspiration from these functions to design yours.
Each of them takes a record and return the modified record.
    N)str)latex_to_unicodestring_to_latexprotect_uppercase)	splitnamegetnamesauthoreditorjournalkeywordlinkpage_double_hyphendoitypeconvert_to_unicodehomogenize_latex_encodingadd_plaintext_fieldsc                       e Zd ZdZy)InvalidNamez[Exception raised by :py:func:`customization.splitname` when an invalid name is input.

    N)__name__
__module____qualname____doc__     R/home/agent/.friday_env/lib/python3.12/site-packages/bibtexparser/customization.pyr   r      s     	r   r   c                 j	   t        d      }g g}g g}g }d}d}d}d}	d}
t        |       }|D ]9  }|dk(  rt        |      }||v r|j                  |       |}nd|rd}|j	                         }	d}
n*|dk(  r%|j	                         r|j                         rd}nd}|j                  |       |j                  |       |d	k(  r|dz  }|j                  |       d}d}	d}
d}|d
k(  rM|r|dz  }n.|rt        dj                  |             |j                  dd	       d}	d}
|j                  |       |rT|	r|j	                         s/d}	n,|
r*|dk(  r%|j	                         r|j                         rd}nd}|j                  |       \|dk(  s||v r|r?|d   j                  dj                  |             g }|d   j                  |       d}d}	d}
|dk(  rMt        |      dk  r#|j                  g        |j                  g        n|rt        dj                  |             |j                  |       |dk(  s|j	                         s$|j                         rd}8d}< |r7|rt        dj                  |             |r|j                  d
       |dz  }|r|r7|d   j                  dj                  |             |d   j                  |       |d   sLt        |      dkD  r|rt        dj                  |             |j                  d       |j                  d       |rt        d |D              si S g g g g d}t        |      dk(  r|d   }t        |      dk(  r||d<   |S t        |      dk(  r|dd |d<   |dd |d<   |S |d   }d|v rb|j                  d      t        |      z
  }|ddd   j                  d       dz
  }|dk(  r|dz  }|d| |d<   |||dz    |d<   ||dz   d |d<   |S |dd |d<   |dd |d<   |S |d   }|r
|d   r||d<   t        |      dk(  r|d   }|r
|d   r||d<   |d   }t        |      dk(  r||d<   |S |d   }d|v rKt        |      |ddd   j                  d      z
  }|t        |      k(  rd}|d   d| |d<   |d   |d |d<   |S |d   |d<   |S )a  
    Break a name into its constituent parts: First, von, Last, and Jr.

    :param string name: a string containing a single name
    :param Boolean strict_mode: whether to use strict mode
    :returns: dictionary of constituent parts
    :raises `customization.InvalidName`: If an invalid name is given and
                                         ``strict_mode = True``.

    In BibTeX, a name can be represented in any of three forms:
        * First von Last
        * von Last, First
        * von Last, Jr, First

    This function attempts to split a given name into its four parts. The
    returned dictionary has keys of ``first``, ``last``, ``von`` and ``jr``.
    Each value is a list of the words making up that part; this may be an empty
    list.  If the input has no non-whitespace characters, a blank dictionary is
    returned.

    It is capable of detecting some errors with the input name. If the
    ``strict_mode`` parameter is ``True``, which is the default, this results in
    a :class:`customization.InvalidName` exception being raised. If it is
    ``False``, the function continues, working around the error as best it can.
    The errors that can be detected are listed below along with the handling
    for non-strict mode:

        * Name finishes with a trailing comma: delete the comma
        * Too many parts (e.g., von Last, Jr, First, Error): merge extra parts
          into First
        * Unterminated opening brace: add closing brace to end of input
        * Unmatched closing brace: add opening brace at start of word

    z ~
	r   FTN\   {}z(Unmatched closing brace in name {{{0}}}.,    z$Too many commas in the name {{{0}}}.z/Unterminated opening brace in the name {{{0}}}.z&Trailing comma at end of name {{{0}}}.c              3   2   K   | ]  }t        |        y wN)bool).0sections     r   	<genexpr>zsplitname.<locals>.<genexpr>   s     EtG}Es   )firstlastvonjrr-      r,   r.   r/   )setiternextappendisalphaisupperr   formatinsertjoinlenpopanyindex)namestrict_mode
whitespacesectionscaseswordcaselevel
bracestart
controlseqspecialcharnameitercharescapedpartsp0firstllastlr,   r/   r-   lcasessplits                          r   r   r      s   P ZJ
 tHDEDDEJJK DzH i4<8nG *$D! !&J!(!2J"&K bjgoo&7(   D!G$ 3;QJEKKJJK 
 3;
%&P&W&WX\&]^^As# JKKK ||~!&J BJDLLN||~   KK 3;$*,##BGGDM2b	  &"
# s{x=1$OOB'LL$ %&L&S&STX&YZZ 	DBJDLLN||~SiX OVVW[\]]KKQJE 
 BGGDM*b	 B<MA;FMMdSTTR		" 3EHEE	 "Rr:E 8}a[ r7a<E&MP LK W\VE'NqrFE&MF L !HE EzQ#e*4tt**1--1B;QJE "$GVg!&3e "519:fZ LS "$CRg "23fP LG U1X"E'N x=A"Bbe d {t9> E&M* L# 1XF
 F{FfTrTl&8&8&;;CK'E'{6E2e (EF 3f L !)f Lr   textopeningclosingignore_escapedreturnc                    g }g }|r
d|z   }d|z   }t        j                  ||       D ]$  }|j                  |j                         d          & t        j                  ||       D ]'  }|j                  d|j                         d   z         ) t	        |      dk(  rt	        |      dk(  ri S t	        |      t	        |      k7  rt        d| d| d      t        ||z   d       }i }g }	|D ]Q  }|dk\  r|	j                  |       t	        |	      dk(  rt        d	| d
|d      |	j                         }
d|z  ||
<   S t	        |	      dkD  r t        d| d|	j                         d      |S )af  
    Find matching 'brackets'.

    :param text: The string to consider.
    :param opening: The opening bracket (e.g. "(", "[", "{").
    :param closing: The closing bracket (e.g. ")", "]", "}").
    :param ignore_escaped: Ignore escaped bracket (e.g. "\(", "\[", "\{", "\)", "\]", "\}").
    :return: Dictionary with ``{index_opening: index_closing}``
    z(?<!\\)r   r   zUnmatching z...z foundc                     t        |       S r'   )abs)is    r   <lambda>zfind_matching.<locals>.<lambda>Q  s
    3q6 r   )keyzNo closing z at: dzNo opening z at )refinditerr5   spanr;   
IndexErrorsortedr<   )rS   rT   rU   rV   abr[   bracketsretstackjs              r   find_matchingrj   .  s}     	A
Aw&w&[[$' 	! [[$' #	affhqk!"# 1v{s1v{	
1vQ;wis7)6BCCa!e!12H
CE 6LLO5zQ ;wiuQqE!BCC		A!VCF 5zA~;witEIIK?CDDJr   c                    g }| D ]  }|j                         }t        |      dk  r#d|v rT|j                  dd      }|d   j                         }|d   j                         D cg c]  }|j                          }}nd|v rd|v r{	 t        |dd      }g }d}d}	 ||v r||   }n|dz  }|t        |      k\  rnX||   dk(  r|j                  |||        |dz   }n%|t        |      dz
  k(  r|j                  ||d        f|j                         }|j                         }|D cg c]"  }|j                  dd	      j                         $ }}|d
v r|j                         }|D ]  }	|	dv s|j                         dz   |z   } |j                  |dz   dj                  |      z           |S c c}w # t        $ r |j                  |       Y w xY wc c}w )a^  Convert people names as surname, firstnames
    or surname, initials.

    :param names: a list of names
    :type names: list
    :returns: list -- Correctly formated names

    .. Note::
        This function is known to be too simple to handle properly
        the complex rules. We would like to enhance this in forthcoming
        releases.
    r    r#   r   r!   r"    N.z. )jnrr/   junior)benvanderdelalez, )	stripr;   rR   rj   rb   r5   r<   replacer:   )
names	tidynames
namestring	namesplitr-   r[   firstsrf   startitems
             r   r   r   e  s    I '9
%%'
z?Q*"((a0IQ<%%'D)21););)=>Aaggi>F>j SJ%6,ZcBH 	H}$QKQC
O+!!}+!((E!)<= !Ac*o11!((EF);<  ',,.	==?D<EFqaiiT*002FFF**::<D 	1D>>zz|c)D0	1 	sxx'778O'9P C ?
 " $$Z0* Gs   &F1	F6''G6GGc           	          d| v rk| d   rct        t        j                  d| d   j                  dd      t        j                        D cg c]  }|j                          c}      | d<   | S | d= | S c c}w )z
    Split author field into a list of "Name, Surname".

    :param record: the record.
    :type record: dict
    :returns: dict -- the modified record.

    r	   z\ and\ 
rl   )flags)r   r_   rR   rw   
IGNORECASErv   recordr[   s     r   r	   r	     s     6('BHHZQWX`QaQiQijnpsQtKM===Z )[q )[  \F8 M x M	)[s   
A2c                 `   d| v r| d   rt        | d   j                  dd      j                  d      D cg c]  }|j                          c}      | d<   | d   D cg c]7  }||j                  dd      j                  dd      j                  dd      d9 c}| d<   | S | d= | S c c}w c c}w )	z
    Turn the editor field into a dict composed of the original editor name
    and a editor id (without coma or blank).

    :param record: the record.
    :type record: dict
    :returns: dict -- the modified record.

    r
   r   rl   z and r#   r$   rm   r?   ID)r   rw   rR   rv   r   s     r   r
   r
     s     6('F8<L<T<TUY[^<_<e<efm<n(oq(opF8 !'x 0 2lm!))C2D2L2LSRT2U2]2]^ace2f g  2F8 M x M )p 2s   B&<B+c                     d| v rbg d}|D ]Y  }|| d   v s| d   j                  |      D cg c]!  }|j                         j                  |      # }}|d   dz   |d   z   | d<   [ | S c c}w )z
    Separate pages by a double hyphen (--).

    :param record: the record.
    :type record: dict
    :returns: dict -- the modified record.

    pages)u   ‐u   ‑u   –u   —-u   −r   z--r   )rR   rv   )r   
separators	separatorr[   ps        r   r   r     s     &C
# 	6IF7O+9?9N9Ny9YZAQWWY__Y/ZZ"#A$+""5w	6 M [s   &A)c                 :    d| v r| d   j                         | d<   | S )z
    Put the type into lower case.

    :param record: the record.
    :type record: dict
    :returns: dict -- the modified record.

    r   )lowerr   s    r   r   r     s'     --/vMr   c                     d| v rC| d   r>| d   | d   j                  dd      j                  dd      j                  dd      d| d<   | S )z
    Turn the journal field into a dict composed of the original journal name
    and a journal id (without coma or blank).

    :param record: the record.
    :type record: dict
    :returns: dict -- the modified record.

    r   r#   r$   rl   rm   r   rw   r   s    r   r   r     sc     F))/	):'-i'8'@'@b'I'Q'QRUWY'Z'b'bcfhj'k!mF9 Mr   c                     d| v rHt        j                  || d   j                  dd            D cg c]  }|j                          c}| d<   | S c c}w )z
    Split keyword field into a list.

    :param record: the record.
    :type record: dict
    :param sep: pattern used for the splitting regexp.
    :type record: string, optional
    :returns: dict -- the modified record.

    r   r   r$   )r_   rR   rw   rv   )r   sepr[   s      r   r   r     sQ     F02fY>O>W>WX\^`>a0bc1QWWYcyM ds   Ac                    d| v r| d   j                  d      D cg c]"  }|j                         j                  dd      $ }}g | d<   |D ]l  }|j                  d      }d|d   i}t        |      dkD  r|d   |d<   t        |      d	kD  r|d	   |d
<   t        |d         dkD  sY| d   j	                  |       n | S c c}w )h

    :param record: the record.
    :type record: dict
    :returns: dict -- the modified record.

    r   r   z  rl   urlr   r    anchorr0   r8   )rR   rv   rw   r;   r5   )r   r[   linksr   rM   linkobjs         r   r   r   
  s     7=f~7K7KD7QR!""4-RRv 	/DJJsOEeAh'G5zA~$)!H!5zA~$)!H!75>"Q&v%%g.	/ M Ss   'B<c                     d| v rPd| vrg | d<   d}| d   D ]	  }d|v sd} |r2| d   }|j                  d      rd|z   }| d   j                  |dd       | S )r   r   r   TF10zhttps://doi.org/)r   r   )
startswithr5   )r   nodoir~   r   s       r   r   r   "  s     F6N6N 	D}	 %=Dt$)D06N!!$%"@AMr   c           	      @   | D ]  }t        | |   t              r | |   D cg c]  }t        |       c}| |<   6t        | |   t              r4| |   j	                         D ci c]  \  }}|t        |       c}}| |<   }t        | |         | |<    | S c c}w c c}}w )z
    Convert accent from latex to unicode style.

    :param record: the record.
    :type record: dict
    :returns: dict -- the modified record.
    )
isinstancelistr   dictitems)r   valxkvs        r   r   r   9  s      
8fSk4(-3C[() #F3K sT*39#;3D3D3F+/1a#A&&F3K +6#;7F3K
8 Ms   B"Bc                    t        |       } | D ]  }|dvst        j                  d|       t        | |   t              r | |   D cg c]  }t        |       c}| |<   nBt        | |   t              rt        | |         | |<   nt        j                  d|z  t               |dk(  st        j                  d       t        j                  d| |          t        | |         | |<   t        j                  d| |           | S c c}w )z
    Homogenize the latex enconding style for bibtex

    This function is experimental.

    :param record: the record.
    :type record: dict
    :returns: dict -- the modified record.
    )r   zApply string_to_latex to: %szDUnable to homogenize latex encoding for %s: Expected string or list,titlezProtect uppercase in titlez
Before: %sz	After: %s)r   loggerdebugr   r   r   r   warningswarnRuntimeWarningr   )r   r   r   s      r   r   r   O  s      'F 7gLL7=&+t,06s+,OA&s F3K--fSk:sdgjj,.g~9:\6#;7/s<s[&+6!7" Ms   Dc           	         d }t        | j                               D ]  }dj                  |      }| |   | |<   t        | |   t              r || |         | |<   >t        | |   t
              r1| |   j                         D ci c]  \  }}| ||       c}}| |<   t        | |   t               s| |   D cg c]
  } ||       c}| |<    | S c c}}w c c}w )a%  
    For each field in the record, add a `plain_` field containing the
    plaintext, stripped from braces and similar. See
    https://github.com/sciunto-org/python-bibtexparser/issues/116.

    :param record: the record.
    :type record: dict
    :returns: dict -- the modified record.
    c                 8    dD ]  }| j                  |d      }  | S )N)r!   r"   r$   r   )stringstrippeds     r   _strip_stringz+add_plaintext_fields.<locals>._strip_string{  s&    " 	2H^^Hb1F	2r   zplain_{})r   keysr8   r   r   r   r   )r   r   r]   	plain_keysubkeyvalues         r   r   r   p  s    
 FKKM" %%c*	"3KyfY'- -fY.? @F9y)40 &,I%6%<%<%>!!FE e,,!F9 y)40 $I.! e$!F9" M!
!s   C:C)T)z,|;) r   loggingr_   r   builtinsr   bibtexparser.latexencr   r   r   	getLoggerr   r   __all__
ValueErrorr   r   r(   r   rj   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   <module>r      s     	   V V			8	$@
	* 	Mh  	4
44 4 	4
 
4n6r$*&&"0.,B!r   