
    LT                         d Z ddlmZ ddlmZ ddlmZ ddlZddlmZ ddlm	Z	 ddl
mZ  G d	 d
e	j                        Zy)a{  Cloud SDK markdown document token renderer.

This is different from the other renderers:

(1) The output is a list of (token, text) tuples returned by
    TokenRenderer.Finish().
(2) A token is an empty object that conveys font style and embellishment by
    convention using the token name. Callers set up a style sheet indexed by
    tokens to control how the embellishments are rendered, e.g. color.
(3) The rendering is constrained by width and height.

Tokens generated by this module:

  Token.Markdown.Bold: bold text
  Token.Markdown.BoldItalic: bold+italic text
  Token.Markdown.Code: code text for command line examples
  Token.Markdown.Definition: definition list item (flag or subcommand or choice)
  Token.Markdown.Italic: italic text
  Token.Markdown.Normal: normal text
  Token.Markdown.Section: section header
  Token.Markdown.Truncated: the last token => indicates truncation
  Token.Markdown.Value: definition list item value (flag value)

The Token objects self-define on first usage. Don't champion this pattern in the
Cloud SDK.

Usage:

  from six.moves import StringIO

  from googlecloudsdk.core.document_renderers import token_renderer
  from googlecloudsdk.core.document_renderers import render_document

  markdown = <markdown document string>
  tokens = render_document.MarkdownRenderer(
      token_renderer.TokenRenderer(width=W, height=H),
      StringIO(markdown)).Run()
    )absolute_import)division)unicode_literalsN)console_attr)renderer)Tokenc                       e Zd ZdZdZej                  j                  ej                  j                  ej                  j                  ej                  j                  ej                  j                  dZdZdZdZdZ G d d	e      Zd  fd
	Zd Zd!dZd Zd!dZd Zd Zd Zd"dZd Zd Zd Zd!dZd Z d Z!d#dZ"d Z#d Z$d$dZ%d Z&d%dZ'd&dZ( xZ)S )'TokenRenderera\  Renders markdown to a list of lines where each line is a list of Tokens.

  Attributes:
    _attr: console_attr.ConsoleAttr object.
    _bullet: List of bullet characters indexed by list level modulo #bullets.
    _compact: Compact representation if True. Saves rendering real estate.
    _csi: The control sequence indicator character. Token does not have control
      sequences. This renderer uses them internally to manage font styles and
      attributes (bold, code, italic).
    _current_token_type: current default Token.Markdown.* type
    _fill: The number of characters in the current output line.
    _height: The height of the output window, 0 to disable height checks.
    _ignore_paragraph: Ignore paragraph markdown until the next non-space
      _AddToken.
    _ignore_width: True if the next output word should ignore _width.
    _indent: List of left indentations in characters indexed by _level.
    _level: The section or list level counting from 0.
    _tokens: The list of output tokens
    _truncated: The number of output lines exceeded the output height.
    _rows: current rows in table
   )BCINZ      r      c                       e Zd ZdZddZy)TokenRenderer.IndentzSecond line indent stack.c                 X    |rdnt         j                  | _        | j                  | _        y )Nr   )r
   INDENTindentsecond_line_indent)selfcompacts     <lib/googlecloudsdk/core/document_renderers/token_renderer.py__init__zTokenRenderer.Indent.__init__l   s     Am&:&:dk $d    N)T)__name__
__module____qualname____doc__r    r   r   Indentr   i   s
    #,r   r$   c                    t        t        | 
  di | t        j                  |      | _        | j                  | _        | j                  | j
                  _        | j
                  j                         | _	        || _
        d| _        t        j                  j                  | _        || _        d| _        d| _        | j'                  |      g| _        d| _        g | _        g | _        d| _        g | _        y )N)encodingr   Fr#   )superr
   r   r   GetConsoleAttr_attrCSI_csi
GetBullets_bullet_compact_fillr   MarkdownNormal_current_token_type_height_ignore_paragraph_ignore_widthr$   _indent_level_lines_tokens
_truncated_rows)r   heightr&   r   kwargs	__class__s        r   r   zTokenRenderer.__init__p   s    	-'1&1,,h?DJDIiiDJJO::((*DLDMDJ$~~44DDL"DDKK()DLDKDKDLDODJr   c                 B   d| _         d}t        |      }t        j                  j                  |f}|r|r|\  }}||k(  rn|dz   |k  r;d| j                  |      d||z
  dz
   z   }|j                  | j                  |f       ng }| j                  }|D ]v  }	|	| j                     }| j                  j                  |      }
||
z  }||k  r/||z
  }|r|d|  }|j                  |	| j                     |f        n|j                  |	       x |}|j                  |       |S )ag  Injects a truncation indicator token and rejects subsequent tokens.

    Args:
      tokens: The last line of tokens at the output height. The part of the line
        within the output width will be visible, modulo the trailing truncation
        marker token added here.
      overflow: If not None then this is a (word, available) tuple from Fill()
        where word caused the line width overflow and available is the number of
        characters available in the current line before ' '+word would be
        appended.

    Returns:
      A possibly altered list of tokens that form the last output line.
    Tz...r    N)r:   lenr   r0   	Truncated	_UnFormatappendr2   _widthTOKEN_TEXT_INDEXr)   DisplayWidthTOKEN_TYPE_INDEX)r   tokensoverflowmarker_stringmarker_widthmarker_tokenword	availabletruncated_tokenstokenwidthtrims               r   	_TruncatezTokenRenderer._Truncate   sB    DOM}%LNN,,m<L( odI		"1*T^^D)*HI,Dq,HIIt//67 KK	Et,,-$**))$/%
u
),&)+D&D5\d##U4+@+@%A4$HI

!
!%
(  "
MM,Mr   c                    | j                   }g | _         | j                  s|s| j                  ry| j                  r| j                  d   r| j                  d   d   | j                     j                         r\| j                  d   dd | j                  d<   | j                  d   r.| j                  d   d   | j                     j                         r\| j                  rIt        | j                        t        t        |            z   | j                  k\  r| j                  ||      }| j                  j                  |       y)a9  Adds the current token list to the line list.

    Args:
      overflow: If not None then this is a (word, available) tuple from Fill()
        where word caused the line width overflow and available is the number of
        characters available in the current line before ' '+word would be
        appended.
    N)r9   r:   r.   r8   rF   isspacer3   rA   intboolrT   rD   )r   rJ   rI   s      r   _NewLinezTokenRenderer._NewLine   s     \\FDLf{{ ++b/kk"ob!$"7"78@@B++b/#2.B ++b/kk"ob!$"7"78@@B ||T[[)CV,==$,,N~~fh/fKKvr   c                    |sy| j                   r| j                   d   | j                     |k7  r| j                   j                  ||f       y| j                   d   | j                     t        j                  j
                  k(  r| j                   d   | j                     }t        j                  d|      j                  d      }t        j                  d|      j                  d      }||k(  r||f| j                   d<   y| j                          | j                   j                  ||f       y|| j                   d   | j                     |z   f| j                   d<   y)zFMerges text if the previous token_type matches or appends a new token.NrV   z( *)r   )r9   rH   rD   r   r0   SectionrF   rematchgrouprZ   )r   text
token_typeprv_text
prv_indent
new_indents         r   _MergeOrAddTokenzTokenRenderer._MergeOrAddToken   s%   LL<<D112j@
ll:t,-	b	$//	0ENN4J4J	Jb!$"7"78h88FH-33A6j88FD)//2j	z	!&-R 	Z./ 
,,r
400
1D
8dll2r   c                 t   |r|j                         sd| _        |s| j                  }| j                  |vr| j	                  ||       yd}	 |j                  | j                  |      }|dk  r| j	                  ||d |       y| j	                  ||| |       | j                  ||dz         }|| _        |dz   }n)z7Appends a (token_type, text) tuple to the current line.Fr   Nr   r   )rW   r4   r2   r+   re   findEMBELLISHMENTS)r   r`   ra   ijs        r   	_AddTokenzTokenRenderer._AddToken   s    DLLN$d++jyy
D*-
aIIdii#q5


QR*
5
d1Qi4((a!e5
#- E r   c                 $   | j                   |vr|S g }d}|t        |      k  r^|j                  | j                   |      }|dk  r|j                  ||d        n(|j                  |||        |dz   }|t        |      k  r^dj	                  |      S )z1Returns text with all inline formatting stripped.r   Nr    )r+   rA   rg   rD   join)r   r`   strippedri   rj   s        r   rC   zTokenRenderer._UnFormat   s    yykH	A
c$i-
))DIIq
!a	
QQR!ood1Qi 
a%a c$i- 778r   c                    | j                  |      }|j                  dd      }| j                  |d   t        j                  j
                         t        |      dkD  rW| j                  dt        j                  j                         | j                  |d   t        j                  j                         | j                          y)z>Appends a definition list definition item to the current line.=r   r   N)
rC   splitrk   r   r0   
DefinitionrA   r1   ValuerZ   )r   r`   partss      r   _AddDefinitionzTokenRenderer._AddDefinition  s    >>$DJJsAENN58U^^667
5zA~
nnS%..//0
nnU1Xu~~334MMOr   c                 z    d| _         | j                  r(| j                          | j                          d| _        yy)z/Flushes the current collection of Fill() lines.Fr   N)r5   r/   rZ   Contentr   s    r   _FlushzTokenRenderer._Flush  s/    Dzz
mmo
llndj r   c                    | j                   |k  r| j                   |k  r| j                   }| xj                   dz  c_         | j                   t        | j                        k\  r)| j                  j                  | j	                                | j                  |   j
                  |z   | j                  | j                      _        | j                   dkD  r_| j                  |   j                  | j                  |   j
                  k(  r,| j                  | j                      xj
                  dz  c_        | j                  | j                      j
                  }|| j                  | j                      _        |,| j                  | j                      xj                  |z  c_        | j                   |k  ryy|| _         |C| j                  | j                      j                  |z   | j                  | j                      _        yy)a  Sets the markdown list level and indentations.

    Args:
      level: int, The desired markdown list level.
      indent: int, The new indentation.
      second_line_indent: int, The second line indentation. This is subtracted
        from the prevailing indent to decrease the indentation of the next input
        line for this effect: SECOND LINE INDENT ON THE NEXT LINE PREVAILING
        INDENT ON SUBSEQUENT LINES
    r   N)r7   rA   r6   rD   r$   r   r   )r   levelr   r   
prev_levelvalues         r   
_SetIndentzTokenRenderer._SetIndent  s    {{U KK%[[
q;;#dll++
,,

dkkm
,LL$++f4 	T[[!( KK!OZ(;;||J'../
 ,,t{{
#
*
*a
/
*T[[)007<T[[!4)
,,t{{
#
6
6:L
L
6+ KK%0 dk		' LL%88;MM 	T[[!( 
(r   c                 0   | j                   | j                     j                  | j                  z   | _        | j                  d| j                  z  |z   t        j                  j                         | j                          | j                          d| _        y)zXDisplays line as an indented example.

    Args:
      line: The example line text.
    r@   r   N)r6   r7   r   r   r/   rk   r   r0   r1   rZ   rx   )r   lines     r   ExamplezTokenRenderer.ExampleG  sf     dkk*11DKK?DJNN3#d*ENN,A,ABMMOLLNDJr   c                 @   | j                          |j                         D ]z  }| j                  si| j                  s| j                  s,| j
                  | j                     j                  dz
  | _        nd| _        | j                  d| j                  z         | j                  j                  |      }| j                  | j                  z
  }|dz   |k\  rg| j                  s[| j                  ||f       | j
                  | j                     j                  | _        | j                  d| j                  z         n9d| _        | j                  r&| xj                  dz  c_        | j                  d       | xj                  |z  c_        | j                  |       } y)zAdds a line to the output, splitting to stay within the output width.

    This is close to textwrap.wrap() except that control sequence characters
    don't count in the width computation.

    Args:
      line: The text line.
    r   r   r@   )rJ   FN)Blankrr   r/   r7   r.   r6   r   rk   r)   rG   rE   r5   rZ   )r   r   rN   rR   rO   s        r   FillzTokenRenderer.FillS  s*    	JJL

ZZ;;dmm||DKK077!;$*$+sTZZ'(jj%%d+e++

*i
!)		!$*<*<i01\\$++.55
sTZZ'("::
**/*
..

jjEj
nnT' r   c                 Z    | j                          | j                          | j                  S )z'Finishes all output document rendering.)rz   Fontr8   ry   s    r   FinishzTokenRenderer.Finishr  s    KKMIIK;;r   c                    |d| _         nd|z  }| xj                   |z  c_         | j                   dt        j                  z  dt        j                  z  z  dt        j                  z  z  z  }|dt        j                  z  z  rd}na|dt        j                  z  dt        j                  z  z  k(  rd}n4|dt        j                  z  k(  rd}n|dt        j                  z  k(  rd}nd}| j
                  |z   S )a   Returns the font embellishment control sequence for attr.

    Args:
      attr: None to reset to the default font, otherwise one of renderer.BOLD,
        renderer.ITALIC, or renderer.CODE.

    Returns:
      The font embellishment control sequence.
    r   r   r   r   r   r   r   )_fontr   BOLDCODEITALICr+   )r   attrmaskfontembellishments        r   r   zTokenRenderer.Fontx  s     |dj$Yd
jjDj::	
hmm	X]] 23qHOO7KLD qHMM!"m	1%!x*>?	@m	!x}}$	%m	!x&	'mm99}$$r   c                 d   |dk(  r|j                  d      ry| j                          | j                          | j                          |dkD  rJd|dz
  z  }| j	                  |       | j
                  r%d| _        | xj                  t        |      z  c_        | j	                  |t        j                  j                         | j
                  r6d| _        | xj                  | j                  j                  |      z  c_        n| j                          | j                          d| _        g | _        y)zsRenders a heading.

    Args:
      level: The heading level counting from 1.
      heading: The heading text.
    r   z(1)Nr   z  Tr   )endswithrz   Liner   rk   r.   r4   r/   rA   r   r0   r\   r)   rG   rZ   r   r7   r;   )r   r|   headingr   s       r   HeadingzTokenRenderer.Heading  s     zg&&u-KKMIIKIIKqyuqy!f
nnV	!%

c&k!
NN7ENN223}}#d
jjDJJ++G44j
mmoJJLDKDJr   c                     | j                   ry| j                          | j                         s!| j                          | j	                          yy)z$Renders a paragraph separating line.N)r4   rz   	HaveBlankr   rZ   ry   s    r   r   zTokenRenderer.Line  s8    KKM>>
jjl
mmo r   c                    | j                          |s|| _        y|r| j                  |       y|x|rQ| j                  |dd       | j                  d| j                  |   j
                  z         | j                  |       y| j                  |dd       | j                          y|dkD  rdnd}| j                  ||d       | j                  d| j                  |   j
                  z  | j                  |dz
  t        | j                        z     z          | j                  |   j                  dz   | _        d	| _        y)
zRenders a bullet or definition list item.

    Args:
      level: The list nesting level, 0 if not currently in a list.
      definition: Bullet list if None, definition list item otherwise.
      end: End of list if True.
    Nr      )r   r   r@   r   r   r   T)rz   r7   r   rk   r6   r   rv   r   r-   rA   r   r/   r5   )r   r|   
definitionendr   s        r   ListzTokenRenderer.List  s    	KKMdk	
ooe			aA>sT\\%0CCCDJ'aA>		 AIq1f
ooeFqoA
nn
U#66
6LL%!)s4<<'889: <<&--1djdr   c                 d    |t        |      k  r!||   }|dk7  r	 |S |dz  }|t        |      k  r!|S )zSkip space characters starting at line[index].

    Args:
      line: The string.
      index: The starting index in string.

    Returns:
      The index in line after spaces or len(line) at end of string.
    r@   r   )rA   )r   r   indexcs       r   
_SkipSpacezTokenRenderer._SkipSpace  sH     #d)

u+a	
cL qje	 #d)

 Lr   c                 P    | j                   j                  ||d       }|sd}||z   S )zSkip the control sequence at line[index].

    Args:
      line: The string.
      index: The starting index in string.

    Returns:
      The index in line after the control sequence or len(line) at end of
      string.
    Nr   )r)   GetControlSequenceLen)r   r   r   ns       r   _SkipControlSequencez"TokenRenderer._SkipControlSequence  s0     	

((ef6A
a19r   c                     d}|t        |      k  rU||   }|dz  }||v r|dz  }n2||v r|dz  }|dk  r$	 |S || j                  k(  r| j                  ||      }|t        |      k  rU|S )aJ  Skip a [...] nested bracket group starting at line[index].

    Args:
      line: The string.
      index: The starting index in string.
      open_chars: The open nesting characters.
      close_chars: The close nesting characters.

    Returns:
      The index in line after the nesting group or len(line) at end of string.
    r   r   )rA   r+   r   )r   r   r   
open_charsclose_charsnestr   s          r   	_SkipNestzTokenRenderer._SkipNest  s     D
#d)

u+aqje	
j		19
 L 		>))$6 #d)
 Lr   c                 .   d}|rdD ]  }|j                  |      \  }}}| j                  j                  |      }	|t        |      z   |	z   | j                  k\  s
|dk7  r|dk(  r|dk7  r,|| j
                  z   t        |      z   |	z   | j                  k\  r|dk(  r| j                  |       d}||k7  r3|| j
                  z   }| j                          | j                  d|z         | j                  ||z          |t        |      |	z   z  }|}|} n |r|S )a"  Splits a wide SYNOPSIS section group string._out.

    Args:
      group: The wide group string to split.
      indent: The prevailing left indent.
      running_width: The width of the line in progress.

    Returns:
      The running_width after the group has been split and written.
    r@   )z | z : r@   ,r   )	partitionr)   rG   rA   rE   SPLIT_INDENTrk   rZ   )
r   r_   r   running_widthprev_delimiter	delimiterpart_	remainderws
             r   _SplitWideSynopsisGroupz%TokenRenderer._SplitWideSynopsisGroup  s,    N
/)"__Y7aJJ##D)S0014D$S  3D---N0CCaG s"NN>* Nf$"T%6%66MMMONN3./~,-^,q00"5 0 : r   c                    g }| j                  |d      }|}|t        |      k  r||   }|dk(  re|}| j                  ||      }|t        |      dz
  k  r)||   dk(  r!||dz      dk(  r| j                  ||dz         }nU|j                  |||        |}n>|dv r| j                  ||      }n'|| j                  k(  r| j                  ||      }n|dz  }|t        |      k  r|t        |      k  r|j                  ||d        | j                  d   j                  dz
  }|}	| j                  d|	z         || j                  z  }|D ]  }
| j                  j                  |
      dz   }|	|z   | j                  k\  rL|}	| j                          | j                  d|	z         |	|z   | j                  k\  r| j                  |
||	      }	| j                  d|
z          |	|z  }	 | j                          | j                          y)ac  Renders NAME and SYNOPSIS lines as a second line indent.

    Collapses adjacent spaces to one space, deletes trailing space, and doesn't
    split top-level nested [...] or (...) groups. Also detects and does not
    count terminal control sequences.

    Args:
      line: The NAME or SYNOPSIS text.
      is_synopsis: if it is the synopsis section
    r   r@   r   |[(N)r   rA   rD   r   r+   r   r6   r   rk   r   r)   rG   rE   rZ   r   )r   r   is_synopsisgroupsri   begr   r   r   r   r_   r   s               r   SynopsiszTokenRenderer.SynopsisD  s    Fa A
C
c$i-
q'a	
cOOD!$TQDGsNtAE{c7IoodAE*!
--S
&#9NN4#		>%%dA.	Q c$i-  SYmmDJ \\!_##a'FMNN3&'
dkkF
**
!
!%
(1
,a
!
	+s]*+A$++-66V]- 
nnS5[!qm  	MMOMMOr   c                 R    | j                  |dz  |z          | j                          y)zAdds an indented table line to the output.

    Args:
      line: The line to add. A newline will be added.
      indent: The number of characters to indent the table.
    r@   N)rk   rZ   )r   r   r   s      r   	TableLinezTokenRenderer.TableLine|  s"     	NN6C<$&'MMOr   )r   zutf-8T)N)r   N)NF)r   z)])F)r   )*r   r    r!   r"   r*   r   r0   BoldCodeItalicr1   
BoldItalicrh   r   r   rH   rF   objectr$   r   rT   rZ   re   rk   rC   rv   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__)r>   s   @r   r
   r
   B   s    2 	#>>>>>>  >>  >>$$. &,,v ,&-^06(+
Z
>%<:  D" 4)V6pr   r
   )r"   
__future__r   r   r   r]   googlecloudsdk.core.consoler   &googlecloudsdk.core.document_renderersr   prompt_toolkit.tokenr   Rendererr
   r#   r   r   <module>r      s6    %N '  ' 	 4 ; &B	H%% B	r   