B
    b7B                 @   s   d Z ddlZddlZddlZddlZddlZddlm	Z	m
Z
 ddgZddd	d
gZG dd dZeZdd ZG dd dZdd Zdd ZG dd de	ZdS )z"Dependency scanner for LaTeX code.    N   )ScannerBaseFindPathDirsz.epsz.psz.pngz.jpgz.gifz.tifc               @   s   e Zd ZdS )_NullN)__name__
__module____qualname__ r	   r	   2lib/python3.7/site-packages/SCons/Scanner/LaTeX.pyr   )   s   r   c             C   s   y| d | }W n t k
r(   t}Y nX | || yVtj| | rd| |dd | | D  n&| |dd t| | tj	D  W n t k
r   Y nX tj| d | rtj	
| d | | d |< | d | tj	 | d |< |S )NENVc             S   s   g | ]}t jt|qS r	   )ospathabspathstr).0pr	   r	   r
   
<listcomp>:   s    z"modify_env_var.<locals>.<listcomp>c             S   s   g | ]}t j|qS r	   )r   r   r   )r   r   r	   r	   r
   r   =   s    )KeyError_nullZPrependENVPathSConsUtilZis_Listr   splitr   pathsepjoin)envvarr   Zsaver	   r	   r
   modify_env_var2   s    
*r   c               @   s"   e Zd ZdZdd ZdddZdS )FindENVPathDirsz
    A class to bind a specific E{*}PATH variable name to a function that
    will return all of the E{*}path directories.
    c             C   s
   || _ d S )N)variable)selfr   r	   r	   r
   __init__Q   s    zFindENVPathDirs.__init__Nc             C   s`   dd l }y|d | j }W n tk
r.   dS X |p:|jj}|j||||}t||S )Nr   r   r	   )	ZSCons.PathListr   r   ZfsZ_cwdZPathListZ
subst_pathtupleZRfindalldirs)r   r   dirtargetsourceargumentr   r   r	   r	   r
   __call__T   s    zFindENVPathDirs.__call__)NNNN)r   r   r   __doc__r    r&   r	   r	   r	   r
   r   L   s   r   c              C   s   t ddtdd} | S )zh
    Return a prototype Scanner instance for scanning LaTeX source files
    when built with latex.
    LaTeXScannerz$LATEXSUFFIXESr   )namesuffixesgraphics_extensions	recursive)LaTeXTexGraphics)dsr	   r	   r
   r(   `   s
    r(   c              C   s   t ddtdd} | S )zk
    Return a prototype Scanner instance for scanning LaTeX source files
    when built with pdflatex.
    PDFLaTeXScannerz$LATEXSUFFIXESr   )r)   r*   r+   r,   )r-   LatexGraphics)r/   r	   r	   r
   r0   m   s
    r0   c                   s   e Zd ZdZddddddddddddZejee	 Z
ddd	d
ddgZ fddZdd Zdd Zdd Zdd ZdddZdddZ  ZS )r-   a  Class for scanning LaTeX files for included files.

    Unlike most scanners, which use regular expressions that just
    return the included file name, this returns a tuple consisting
    of the keyword for the inclusion ("include", "includegraphics",
    "input", or "bibliography"), and then the file name itself.
    Based on a quick look at LaTeX documentation, it seems that we
    should append .tex suffix for the "include" keywords, append .tex if
    there is no extension for the "input" keyword, and need to add .bib
    for the "bibliography" keyword that does not accept extensions by itself.

    Finally, if there is no extension for an "includegraphics" keyword
    latex will append .ps or .eps to find the file, while pdftex may use .pdf,
    .jpg, .tif, .mps, or .png.

    The actual subset and search order may be altered by
    DeclareGraphicsExtensions command. This complication is ignored.
    The default order corresponds to experimentation with teTeX::

        $ latex --version
        pdfeTeX 3.141592-1.21a-2.2 (Web2C 7.5.4)
        kpathsea version 3.5.4

    The order is:
        ['.eps', '.ps'] for latex
        ['.png', '.pdf', '.jpg', '.tif'].

    Another difference is that the search path is determined by the type
    of the file being searched:
    env['TEXINPUTS'] for "input" and "include" keywords
    env['TEXINPUTS'] for "includegraphics" keyword
    env['TEXINPUTS'] for "lstinputlisting" keyword
    env['BIBINPUTS'] for "bibliography" keyword
    env['BSTINPUTS'] for "bibliographystyle" keyword
    env['INDEXSTYLE'] for "makeindex" keyword, no scanning support needed just allows user to set it if needed.

    FIXME: also look for the class or style in document[class|style]{}
    FIXME: also look for the argument of bibliographystyle{}
    Z	TEXINPUTSZ	BIBINPUTSZ	BSTINPUTSZ
INDEXSTYLE)includeinputincludegraphicsbibliographyZbibliographystyleZaddbibresourceZaddglobalbibZaddsectionbibZ	makeindex
usepackageZlstinputlistingimport	subimportincludefromsubincludefrom	inputfromsubinputfromc       
         s   d}t |t jt jB | _t dt j| _|| _d| fdd}G dd d}G dd	 d	}	||d
< |tj|d< d|d< ||d< |	||d< ||d< t	 j
|| d S )NaW  
            \\(
                include
              | includegraphics(?:\s*\[[^\]]+\])?
              | lstinputlisting(?:\[[^\]]+\])?
              | input
              | import
              | subimport
              | includefrom
              | subincludefrom
              | inputfrom
              | subinputfrom
              | bibliography
              | addbibresource
              | addglobalbib
              | addsectionbib
              | usepackage
              )
                  \s*{([^}]*)}       # first arg
              (?: \s*{([^}]*)} )?    # maybe another arg
        z^((?:(?:\\%)|[^%\n])*)(.*)$r	   c             S   s    |   } |  sg S || |S )N)Zrfileexistsscan_recurse)noder   r   r   r	   r	   r
   _scan   s    zLaTeX.__init__.<locals>._scanc               @   s"   e Zd ZdZdd ZdddZdS )z)LaTeX.__init__.<locals>.FindMultiPathDirsay  The stock FindPathDirs function has the wrong granularity:
            it is called once per target, while we need the path that depends
            on what kind of included files is being searched. This wrapper
            hides multiple instances of FindPathDirs, one per the LaTeX path
            variable in the environment. When invoked, the function calculates
            and returns all the required paths as a dictionary (converted into
            a tuple to become hashable). Then the scan function converts it
            back and uses a dictionary of tuples rather than a single tuple
            of paths.
            c             S   s6   i | _ x*| D ]\}}t|t|f| j |< qW d S )N)
dictionaryitemsr   r   )r   rA   knr	   r	   r
   r       s    z2LaTeX.__init__.<locals>.FindMultiPathDirs.__init__Nc       
   	   S   sT   i }xB| j  D ]4\}\}}	||d d d d d|	|d d d d df||< qW t| S )N)r"   r#   r$   r%   )rA   rB   r!   )
r   r   r"   r#   r$   r%   ZdirC   cZcENVr	   r	   r
   r&      s    

z2LaTeX.__init__.<locals>.FindMultiPathDirs.__call__)NNNN)r   r   r   r'   r    r&   r	   r	   r	   r
   FindMultiPathDirs   s   
 rF   c               @   s    e Zd ZdZdd Zdd ZdS )z&LaTeX.__init__.<locals>.LaTeXScanCheckz`Skip all but LaTeX source files.

            Do not scan *.eps, *.pdf, *.jpg, etc.
            c             S   s
   || _ d S )N)r*   )r   r*   r	   r	   r
   r       s    z/LaTeX.__init__.<locals>.LaTeXScanCheck.__init__c             S   s2   |   p| }| || jd k}|o0|S )Nr   )Zhas_builderZis_up_to_dateZ
get_suffixZ
subst_listr*   )r   r?   r   ZcurrentZ	scannabler	   r	   r
   r&      s    z/LaTeX.__init__.<locals>.LaTeXScanCheck.__call__N)r   r   r   r'   r    r&   r	   r	   r	   r
   LaTeXScanCheck   s   rG   ZfunctionZpath_functionr   r,   ZskeysZ
scan_checkr)   )recompileMXcre
comment_rer+   r-   keyword_pathssuperr    )
r   r)   r*   r+   argskwargsZregexr@   rF   rG   )	__class__r	   r
   r       s    zLaTeX.__init__c                s   |dkr*t j \}}|dkr* d gS |dkrTt j \}}|dkrT d gS |dkr~t j \}}|dkr~ d gS |dkrt j \}}|dkr d gS |d	krt j \}}|dkr܇ fd
d| jD S  gS )Nr3    z.tex)r2   r7   r8   r9   r:   r;   r<   r5   z.bibr6   z.styr4   c                s   g | ]} | qS r	   r	   )r   e)filenamer	   r
   r   !  s    z&LaTeX._latex_names.<locals>.<listcomp>)r   r   splitextr+   )r   Zinclude_typerU   baseZextr	   )rU   r
   _latex_names  s*    



zLaTeX._latex_namesc             C   s   t jjt|S )N)r   NodeFSZ_my_normcaser   )r   r2   r	   r	   r
   sort_key$  s    zLaTeX.sort_keyc          	      s   |\} }y|| }W n t tfk
r2   d}Y nX | ||}|fgt| }xL|D ]D}	x>|D ]6}
t fdd|
D }tjj|	|}|r`||fS q`W qVW d |fS )N)r	   r	   c                s   g | ]}|  qS r	   )ZDir)r   d)
inc_subdirr	   r
   r   7  s    z&LaTeX.find_include.<locals>.<listcomp>)	
IndexErrorr   rX   listr!   r   rY   rZ   Z	find_file)r   r2   
source_dirr   inc_typeinc_filenameZ	sub_pathsZ	try_namesZsearch_pathsrD   search_pathpathsir	   )r]   r
   find_include'  s    



zLaTeX.find_includec             C   sp   g }d}xT|  D ]H}| j|d \}}|rD|d |  |d< n
|| t|dk}qW d| d S )zStandardize an input TeX-file contents.

        Currently:
          * removes comments, unwrapping comment-wrapped lines.
        Fr   
)
splitlinesrM   findalllstripappendlenr   rstrip)r   textoutZline_continues_a_commentlinecommentr	   r	   r
   canonical_text=  s    
zLaTeX.canonical_text.c             C   s   t d}|jd k	r|j}n| | }| j|}g }xx|D ]p}|d|d }|}	|| jkrt	j
||d }	|d d}
n|d d}
x|
D ]}|||	|f qW q@W |}||_|S )Nz\s*\[.*$rS   r   r      ,)rH   rI   includesrs   Zget_text_contentsrL   rj   subtwo_arg_commandsr   r   r   r   rl   )r   r?   ZsubdirZ	noopt_crerw   ro   Zsplit_includesr2   ra   r]   Zinc_listZincr	   r	   r
   scanN  s$    





z
LaTeX.scanr	   c             C   s   t t|}g }|| | i }g }| }x|r| }|\}	}
}y|| rTw2W n tk
rr   d||< Y nX | |||\}}|dkr|	dkrtj	
tj	jd||f  q2| |}|||f || ||
 q2W dd t|D S )z do a recursive scan of the top level target file
        This lets us search for included files based on the
        directory of the main file just as latex doesTNr6   zJNo dependency generated for file: %s (included from: %s) -- file not foundc             S   s   g | ]}|d  qS )r   r	   )r   Zpairr	   r	   r
   r     s    z&LaTeX.scan_recurse.<locals>.<listcomp>)dictr_   extendrz   Zget_dirpopr   rf   r   ZWarningswarnZDependencyWarningr[   rl   sorted)r   r?   r   Z	path_dictZqueueseenZnodesr`   r2   ra   r]   rb   rD   re   Zsortkeyr	   r	   r
   r>   v  s2    	

zLaTeX.scan_recurse)rt   )r	   )r   r   r   r'   rN   r   r   uniquer_   valuesZenv_variablesry   r    rX   r[   rf   rs   rz   r>   __classcell__r	   r	   )rR   r
   r-   z   s.   'T
(r-   )r'   os.pathr   rH   ZSCons.Node.FSr   Z
SCons.UtilZSCons.WarningsrS   r   r   r.   r1   r   r   r   r   r(   r0   r-   r	   r	   r	   r
   <module>   s   