U
    eR                     @   s   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
eZddddd	d
dddddddgZG dd deZd&ddZd'eeeeedddZdd Zdd Zdd Zdd Zdd Zdd	 Zd(d d
Zd!d Zd"d Zd#d Zd$d Zd%d ZdS ))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                   @   s   e Zd ZdZdS )InvalidNamez[Exception raised by :py:func:`customization.splitname` when an invalid name is input.

    N)__name__
__module____qualname____doc__ r   r   x/mounts/lovelace/software/anaconda3/envs/qiime2-shotgun-2023.9/lib/python3.8/site-packages/bibtexparser/customization.pyr      s   r   Tc                 C   s  t d}g g}g g}g }d}d}d}d}	d}
t| }|D ]}|dkrt|}||krf|| |}nN|r|d}| }	d}
n"|dkr| r| rd}nd}|| || q8|d	kr|d7 }|| d}d}	d}
q8d}|d
kr,|r|d8 }n |rtd| |dd	 d}	d}
|| q8|r|	rH| svd}	n.|
rv|dkrv| rv| rrd}nd}|| q8|dks||kr|r|d d	| g }|d | d}d}	d}
|dkr8t
|dk r|g  |g  q8|r8td| q8|| |dkr8| r8| r8d}q8d}q8|rt|rXtd| |rt|d
 |d8 }qX|r|d d	| |d | |d st
|dkr|rtd| |d |d |rtdd |D si S g g g g d}t
|dkr|d }t
|dkr6||d< nt
|dkrf|dd |d< |dd |d< n|d }d|kr|dt
| }|ddd d d }|dkr|d8 }|d| |d< |||d  |d< ||d d |d< n |dd |d< |dd |d< n|d }|r2|d r2||d< t
|dkr`|d }|r`|d r`||d< |d }t
|dkr||d< nv|d }d|krt
||ddd d }|t
|krd}|d d| |d< |d |d |d< n|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                 s   s   | ]}t |V  qd S N)bool).0sectionr   r   r   	<genexpr>   s     zsplitname.<locals>.<genexpr>)firstlastvonjrr(      r'   r)   r*   )setiternextappendisalphaisupperr   formatinsertjoinlenpopanyindex)namestrict_mode
whitespacesectionsZcaseswordcaselevelZ
bracestartZ
controlseqZspecialcharZnameitercharescapedpartsZp0ZfirstlZlastlr'   r*   r(   Zlcasessplitr   r   r   r      s   (






















)textopeningclosingignore_escapedreturnc                 C   sH  g }g }|rd| }d| }t || D ]}|| d  q(t || D ]}|d| d   qLt|dkrt|dkri S t|t|krtd| d| dt|| dd d	}i }g }	|D ]P}|dkr|	| qt|	dkrtd
| d|d|	 }
d| ||
< qt|	dkrDtd| d|	 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                 S   s   t | S r"   )abs)ir   r   r   <lambda>Q      zfind_matching.<locals>.<lambda>)keyzNo closing z at: dzNo opening z at )refinditerr0   spanr6   
IndexErrorsortedr7   )rE   rF   rG   rH   abrK   bracketsretstackjr   r   r   find_matching.  s4    r[   c           
   	   C   s  g }| D ]}|  }t|dk r$qd|kr\|dd}|d   }dd |d  D }nd|kr*d|kr*zt|dd}W n" tk
r   || Y qY nX g }d}d}||kr|| }n|d7 }|t|krڐq2|| dkr||||  |d }q|t|d kr|||d	  qn| }| }d
d |D }|dkrZ| }|D ] }	|	dkr^| d | }q^||d d|  q|S )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   c                 S   s   g | ]}|  qS r   stripr$   rK   r   r   r   
<listcomp>z  s     zgetnames.<locals>.<listcomp>r   r    Nc                 S   s   g | ]}| d d qS ).z. )replacer]   r^   r   r   r   r_     s     )Zjnrr*   Zjunior)Zbenvanderdelalez, )r]   r6   rD   r[   rS   r0   r7   r5   )
namesZ	tidynamesZ
namestringZ	namesplitr(   ZfirstsrW   startrK   itemr   r   r   r   e  sL    






c                 C   sL   d| krH| d rBt dd tjd| d ddtjdD | d< n| d= | S )z
    Split author field into a list of "Name, Surname".

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

    r   c                 S   s   g | ]}|  qS r   r\   r^   r   r   r   r_     s     zauthor.<locals>.<listcomp>z\ and\ 
r`   )flags)r   rP   rD   rb   
IGNORECASErecordr   r   r   r     s    	c                 C   sZ   d| krV| d rPt dd | d dddD | d< dd | d D | d< n| d= | S )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	   c                 S   s   g | ]}|  qS r   r\   r^   r   r   r   r_     s     zeditor.<locals>.<listcomp>rk   r`   z and c                 S   s.   g | ]&}|| d d dd dddqS )r   r    r`   ra   r:   IDrb   r^   r   r   r   r_     s     )r   rb   rD   rn   r   r   r   r	     s    
(c                    sf   d| krbddddddg}|D ]D  | d kr fdd	| d   D }|d
 d |d  | d< q| S )z
    Separate pages by a double hyphen (--).

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

    Zpagesu   ‐u   ‑u   –u   —-u   −c                    s   g | ]}|    qS r   r\   r^   	separatorr   r   r_     s     z&page_double_hyphen.<locals>.<listcomp>r   z--r   )rD   )ro   
separatorspr   rt   r   r     s    	c                 C   s   d| kr| d   | d< | S )z
    Put the type into lower case.

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

    r   )lowerrn   r   r   r   r     s    	c                 C   sB   d| kr>| d r>| d | d  dd dd 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    r`   ra   rp   rr   rn   r   r   r   r
     s    

,|;c                 C   s2   d| kr.dd t || d ddD | d< | S )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   c                 S   s   g | ]}|  qS r   r\   r^   r   r   r   r_     s     zkeyword.<locals>.<listcomp>rk   r    )rP   rD   rb   )ro   sepr   r   r   r     s    &c                 C   s   d| krdd | d  dD }g | d< |D ]h}| d}d|d i}t|dkr^|d |d	< t|d
krv|d
 |d< t|d dkr,| d | q,| S )h

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

    r   c                 S   s   g | ]}|  d dqS )z  r`   )r]   rb   r^   r   r   r   r_     s     zlink.<locals>.<listcomp>rk   r`   urlr   r   anchorr+   r3   )rD   r6   r0   )ro   linksr   rC   Zlinkobjr   r   r   r   
  s    
c                 C   sl   d| krhd| krg | d< d}| d D ]}d|kr$d}q$|rh| d }| drTd| }| d |dd | S )r{   r   r   TF10zhttps://doi.org/)r|   r}   )
startswithr0   )ro   Znodoirj   r   r   r   r   r   "  s    
c                 C   sn   | D ]d}t | | tr.dd | | D | |< qt | | trXdd | |  D | |< qt| | | |< q| S )z
    Convert accent from latex to unicode style.

    :param record: the record.
    :type record: dict
    :returns: dict -- the modified record.
    c                 S   s   g | ]}t |qS r   r   r$   xr   r   r   r_   C  s    z&convert_to_unicode.<locals>.<listcomp>c                 S   s   i | ]\}}|t |qS r   r   )r$   kvr   r   r   
<dictcomp>G  s     z&convert_to_unicode.<locals>.<dictcomp>)
isinstancelistdictitemsr   ro   valr   r   r   r   9  s    
c                 C   s   t | } | D ]}|dkrtd| t| | trJdd | | D | |< n0t| | trjt| | | |< ntd| t	 |dkrtd td| |  t
| | | |< td	| |  q| S )
z
    Homogenize the latex enconding style for bibtex

    This function is experimental.

    :param record: the record.
    :type record: dict
    :returns: dict -- the modified record.
    )rq   zApply string_to_latex to: %sc                 S   s   g | ]}t |qS r   )r   r   r   r   r   r_   `  s    z-homogenize_latex_encoding.<locals>.<listcomp>zDUnable 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   r   r   O  s&    

c                    s   dd  t |  D ]}d|}| | | |< t| | trN | | | |< qt| | tr| fdd| |  D | |< qt| | t r fdd| | D | |< q| S )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                 S   s   dD ]}|  |d} q| S )N)r   r   r    rr   )stringstrippedr   r   r   _strip_string{  s    z+add_plaintext_fields.<locals>._strip_stringzplain_{}c                    s   i | ]\}}| |qS r   r   )r$   subkeyvaluer   r   r   r     s    z(add_plaintext_fields.<locals>.<dictcomp>c                    s   g | ]} |qS r   r   )r$   r   r   r   r   r_     s   z(add_plaintext_fields.<locals>.<listcomp>)r   keysr3   r   r   r   r   )ro   rN   Z	plain_keyr   r   r   r   p  s    



)T)T)ry   ) r   loggingrP   r   builtinsr   Zbibtexparser.latexencr   r   r   	getLoggerr   r   __all__
ValueErrorr   r   r#   r   r[   r   r   r	   r   r   r
   r   r   r   r   r   r   r   r   r   r   <module>   sN   
     
   79
!