B
    )`                 @   s  d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlmZ ddlZddl	Z	ddl
Z
ddlZddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ dZdZdZdZdZdZdZdZddgZdZdd ZG dd de Z!G dd dej"Z#dS )zCCurses-Based Command-Line Interface of TensorFlow Debugger (tfdbg).    )absolute_import)division)print_functionN)textpad)xrange)base_ui)
cli_shared)command_parser)curses_widgets)debugger_cli_common)tensor_formatrefreshZupZdownZ	up_a_lineZdown_a_linehomeendZscroll_to_line_indexzgnome-terminalzxfce4-terminalzxterm-256colorc             C   sr   xl|D ]d}|d |   kr&|d k rn qt |d tr@|d n|d g}x|D ]}t |tjrP|jS qPW qW dS )a=  Attempt to extract command from the attribute segments of a line.

  Args:
    mouse_x: (int) x coordinate of the mouse event.
    attr_segs: (list) The list of attribute segments of a line from a
      RichTextLines object.

  Returns:
    (str or None) If a command exists: the command as a str; otherwise, None.
  r         N)
isinstancelistr   MenuItemcontent)mouse_xZ	attr_segsseg
attributesattr r   T/home/dcms/DCMS/lib/python3.7/site-packages/tensorflow/python/debug/cli/curses_ui.py _get_command_from_line_attr_segs3   s    
  
r   c               @   sB   e Zd ZdZejd ej Zdd ZdddZ	dd	 Z
d
d ZdS )	ScrollBara  Vertical ScrollBar for Curses-based CLI.

  An object of this class has knowledge of the location of the scroll bar
  in the screen coordinates, the current scrolling position, and the total
  number of text lines in the screen text. By using this information, it
  can generate text rendering of the scroll bar, which consists of and UP
  button on the top and a DOWN button on the bottom, in addition to a scroll
  block in between, whose exact location is determined by the scrolling
  position. The object can also calculate the scrolling command (e.g.,
  _SCROLL_UP_A_LINE, _SCROLL_DOWN) from the coordinate of a mouse click
  event in the screen region it occupies.
  _on_c             C   s   || _ || _|| _|| _|| _|| _|| d | _| j| j k rVtd| j| j  d  | j| jd k r~td| j| j d  dS )a)  Constructor of ScrollBar.

    Args:
      min_x: (int) left index of the scroll bar on the screen (inclusive).
      min_y: (int) top index of the scroll bar on the screen (inclusive).
      max_x: (int) right index of the scroll bar on the screen (inclusive).
      max_y: (int) bottom index of the scroll bar on the screen (inclusive).
      scroll_position: (int) 0-based location of the screen output. For example,
        if the screen output is scrolled to the top, the value of
        scroll_position should be 0. If it is scrolled to the bottom, the value
        should be output_num_rows - 1.
      output_num_rows: (int) Total number of output rows.

    Raises:
      ValueError: If the width or height of the scroll bar, as determined
       by min_x, max_x, min_y and max_y, is too small.
    r   z%Insufficient width for ScrollBar (%d)   z&Insufficient height for ScrollBar (%d)N)_min_x_min_y_max_x_max_y_scroll_position_output_num_rows_scroll_bar_height
ValueError)selfZmin_xZmin_yZmax_xZmax_yscroll_positionZoutput_num_rowsr   r   r   __init__W   s    zScrollBar.__init__Fc             C   s8   t t| j| jd  | jd  d }|r4|| j S |S )a  Get the 0-based y coordinate of the scroll block.

    This y coordinate takes into account the presence of the UP and DN buttons
    present at the top and bottom of the ScrollBar. For example, at the home
    location, the return value will be 1; at the bottom location, the return
    value will be self._scroll_bar_height - 2.

    Args:
      screen_coord_sys: (`bool`) whether the return value will be in the
        screen coordinate system.

    Returns:
      (int) 0-based y coordinate of the scroll block, in the ScrollBar
        coordinate system by default. For example,
        when scroll position is at the top, this return value will be 1 (not 0,
        because of the presence of the UP button). When scroll position is at
        the bottom, this return value will be self._scroll_bar_height - 2
        (not self._scroll_bar_height - 1, because of the presence of the DOWN
        button).
    r   r   )intfloatr$   r%   r&   r!   )r(   screen_coord_sysZrel_block_yr   r   r   _block_y   s    zScrollBar._block_yc       
      C   s   | j | j d }d| }d|| jfg}| jdkr|  }|dkrJd}d}n,|dkr\d}d}n|d	krnd
}d}nd}d}tj|gdd|| jfgid}x6td| jd D ]"}||kr|nd}	|j	||	d qW |j	||d nt|g| j }|S )zGet the RichTextLines layout of the scroll bar.

    Returns:
      (debugger_cli_common.RichTextLines) The text layout of the scroll bar.
    r    r   UDr   UPZDNr   zUP zDN z UP DOWN)font_attr_segsN)
r"   r    	BASE_ATTRr%   r.   r   RichTextLinesr   r&   append)
r(   widthZ
empty_lineZforeground_font_attr_segsZblock_yZup_textZ	down_textlayoutir4   r   r   r   r9      s2    
zScrollBar.layoutc             C   sn   | j dkrd S || jkrtS || jkr*tS || jddkrH|| jk rHtS || jddk rf|| jkrftS d S d S )Nr   T)r-   )r%   r!   _SCROLL_UP_A_LINEr#   _SCROLL_DOWN_A_LINEr.   _SCROLL_DOWN
_SCROLL_UP)r(   mouse_yr   r   r   get_click_command   s    




zScrollBar.get_click_commandN)F)__name__
__module____qualname____doc__r   COLOR_BLACKCOLOR_WHITEr5   r*   r.   r9   r@   r   r   r   r   r   G   s   (
&r   c               @   s  e Zd ZdZdZedZedZdZdZ	dZ
dZd	Zed
eddgZdejejdiZejejejejejejejejejejejejejejejejiZddejejejejiZejd ej Zejd ej Zejd ej Zejd ej Z ejd ej Z!ejd ej Z"ejd ej Z#dZ$dZ%e&' Z(dddZ)dd Z*dd Z+dd Z,dd Z-dd  Z.d!d" Z/d#d$ Z0dd&d'Z1d(d) Z2d*d+ Z3d,d- Z4dd.d/Z5d0d1 Z6d2d3 Z7d4d5 Z8d6d7 Z9d8d9 Z:d:d; Z;d<d= Z<d>d? Z=d@dA Z>dBdC Z?dDdE Z@dFdG ZAddHdIZBddKdLZCdMdN ZDejEdfdOdPZFdQdR ZGdSdT ZHddUdVZIdWdX ZJdYdZ ZKd[d\ ZLd]d^ ZMdd_d`ZNdadb ZOddcddZPdedf ZQdgdh ZRdidj ZSdkdl ZTdmdn ZUdodp ZVdqdr ZWdsdt ZXddudvZYdwdx ZZdydz Z[d{d| Z\dd}d~Z]dd Z^dd Z_dS )CursesUIzCurses-based Command-line UI.

  In this class, the methods with the prefix "_screen_" are the methods that
  interact with the actual terminal using the curses library.
     	/@nextprev   
iW        transparentr   zProcessing...d   Nc             C   s   t jj| ||d |   |   |   t | _g | _	d| _
d| _d| _td| _d| _d| _d| _d| _d| _yttj| j W n tk
r   Y nX | jd| jdd	gd
 dS )zConstructor of CursesUI.

    Args:
      on_ui_exit: (Callable) Callback invoked when the UI exits.
      config: An instance of `cli_config.CLIConfig()` carrying user-facing
        configurations.
    )
on_ui_exitconfigr   rV    
   NZmousez/Get or set the mouse mode of this CLI: (on|off)m)Zprefix_aliases)r   BaseUIr*   _screen_init_screen_refresh_size_init_layoutr   ZCommandHistory_command_history_store_active_command_history_command_pointer_command_history_limit_pending_commandr
   ZCursesNavigationHistory_nav_history_output_pad_output_pad_row_output_array_pointer_indices_curr_unwrapped_output_curr_wrapped_outputsignalSIGINT_interrupt_handlerr'   Zregister_command_handler_mouse_mode_command_handler)r(   rW   rX   r   r   r   r*     s0    	
zCursesUI.__init__c             C   s   t dd| _d| _d| _d| _d| _| j| j | j d | _| jd | j | _	| j	d | _
| j	d | _t| jd | _d| _d| _g | _| jd | _| jd | _| j| jd| j| j | jd	| _dS )
zInitialize the layout of UI components.

    Initialize the location and size of UI components such as command textbox
    and output region according to the terminal size.
    	rectangleztop left bottom rightr   r   r   rS   i'  N)topleftbottomright)collections
namedtuplero   _command_textbox_height
_title_row_nav_bar_row_output_top_rowr#   r%   _output_scroll_row_candidates_top_row_candidates_bottom_rowr+   _candidates_max_linesmax_output_lines_curr_search_regex_unwrapped_regex_match_lines_output_pad_screen_heightr"   Z_output_pad_screen_width_output_pad_screen_location)r(   r   r   r   r_   P  s*    
zCursesUI._init_layoutc             C   s4   t dtkrtt jd< t | _d| _| 	  dS )zbScreen initialization.

    Creates curses stdscr and initialize the color pairs for display.
    Z	COLORTERMTERMN)
osgetenv_COLOR_READY_COLORTERMS_COLOR_ENABLED_TERMenvironcursesZinitscr_stdscr_command_window_screen_color_init)r(   r   r   r   r]     s
    

zCursesUI._screen_initc             C   s  t   t   i | _d}xh| jD ]^}xX| jD ]N}|d7 }t || j| | j|  |}|dkrl|d| 7 }t || j|< q.W q"W y,|d7 }t |dd t || jtj	< W n* t j
k
r   | jtj | jtj	< Y nX t j| jd< t j| jd< t j| jd	< | jtj | _d
S )z Initialization of screen colors.r   r   rT   r      rU   ZboldZblink	underlineN)r   Zstart_colorZuse_default_colors_color_pairs_FOREGROUND_COLORS_BACKGROUND_COLORSZ	init_pair
color_pairr   Z
COLOR_GRAYerrorCOLOR_GREENA_BOLDZA_BLINKA_UNDERLINErF   _default_color_pair)r(   Zcolor_indexZfg_colorZbg_colorZ
color_namer   r   r   r     s.    zCursesUI._screen_color_initc                sT   t   t    jd  jd _    j	d fdd  
  dS )zLaunch the curses screen.r   
mouse_modec                s     | dS )Nr   )_set_mouse_enabledget)cfg)r(   r   r   <lambda>      z)CursesUI._screen_launch.<locals>.<lambda>N)r   ZnoechoZcbreakr   keypadrX   r   _mouse_enabled_screen_set_mousemaskZset_callback_screen_create_command_window)r(   enable_mouse_on_startr   )r(   r   _screen_launch  s    zCursesUI._screen_launchc             C   s<   | j r
| ` t| j| jt| j | j| j t| j| _ dS )z/Create command window according to screen size.N)r   r   Znewwinrv   r"   len
CLI_PROMPTr#   )r(   r   r   r   r     s
    z&CursesUI._screen_create_command_windowc             C   s   | j   d S )N)r   r   )r(   r   r   r   _screen_refresh  s    zCursesUI._screen_refreshc             C   sR   | j d t  t  t  yttjtj W n t	k
rL   Y nX dS )zTerminate the curses screen.r   N)
r   r   r   ZnocbreakZechoZendwinrk   rl   SIG_DFLr'   )r(   r   r   r   _screen_terminate  s    zCursesUI._screen_terminateTc             C   sj   | j   | j|d |dk	r(| | |dk	r>| j||d |  }| jrT|   |   | j   |S )zCRun the CLI: See the doc of base_ui.BaseUI.run_ui for more details.)r   N)title_color)	_single_instance_lockacquirer   _dispatch_command_title_ui_loop_on_ui_exitr   release)r(   Zinit_commandtitler   r   
exit_tokenr   r   r   run_ui  s    



zCursesUI.run_uic             C   s
   | j  S )N)_command_handler_registryget_help)r(   r   r   r   r     s    zCursesUI.get_helpc             G   s,   y| j j|  W n tjk
r&   Y nX d S )N)r   addstrr   r   )r(   argsr   r   r   _addstr  s    zCursesUI._addstrc             G   s*   y|j |  W n tjk
r$   Y nX d S )N)r   r   r   )r(   padr   r   r   r   _refresh_pad  s    zCursesUI._refresh_padc             C   sP   |  | j| j d| jtj | j  | j	  t
j| jdd| _| | dS )zCreate command textbox on screen.

    Args:
      existing_command: (str) A command string to put in the textbox right
        after its creation.
    r   T)Zinsert_modeN)r   r#   rv   r   r   r   r   r   r   clearr   ZTextbox_command_textbox_auto_key_in)r(   existing_commandr   r   r   _screen_create_command_textbox  s    	

z'CursesUI._screen_create_command_textboxc          
   C   s   x| j dkr| j| j   }n| j}| | y|  \}}}W n& tjk
rd } z|jS d}~X Y nX |sv|| jkrvq|| j	ks|t
jkr| |}|dk	r|S q|| jkr| |}|| _d| _q|r|| _qW dS )zfCommand-line UI loop.

    Returns:
      An exit token of arbitrary type. The token can be None.
    r   N)rb   ra   rd   r   _get_user_commandr   CommandLineExitr   CLI_TAB_KEYCLI_CR_KEYSr   	KEY_MOUSEr   _tab_completeZ_cmd_ptr)r(   r   command
terminatorZpending_command_changeder   Ztab_completedr   r   r   r   -  s,    





zCursesUI._ui_loopc             C   s,   d| _ d| _|  }| |}|| j | jfS )a  Get user command from UI.

    Returns:
      command: (str) The user-entered command.
      terminator: (str) Terminator type for the command.
        If command is a normal command entered with the Enter key, the value
        will be the key itself. If this is a tab completion call (using the
        Tab key), the value will reflect that as well.
      pending_command_changed:  (bool) If the pending command has changed.
        Used during command history navigation.
    NF)_textbox_curr_terminator _textbox_pending_command_changed_screen_get_user_command_strip_terminator)r(   r   r   r   r   r   Q  s    
zCursesUI._get_user_commandc             C   s   | j j| jdS )N)validate)r   Zedit_on_textbox_keypress)r(   r   r   r   r   g  s    z!CursesUI._screen_get_user_commandc             C   s8   |s|S x&| j D ]}|dk r|t|d}qW | S )N   rY   )r   replacechrstrip)r(   r   vr   r   r   r   j  s    zCursesUI._strip_terminatorc             C   s*   | j  \| _| _| j| jkr&| j| _d S )N)r   Zgetmaxyxr#   r"   _SCREEN_WIDTH_LIMIT)r(   r   r   r   r^   t  s    zCursesUI._screen_refresh_sizec             C   s   || j kr<| j r&| j }|j}ql| jd| jd dS n0| j rX| j }|j}n| jd| jd dS | 	|j
 |dkr| jt|d dS )zNavigate in screen output history.

    Args:
      command: (`str`) the navigation command, from
        {self._NAVIGATION_FORWARD_COMMAND, self._NAVIGATION_BACK_COMMAND}.
    z$At the LATEST in navigation history!)colorNz$At the OLDEST in navigation history!r   )
line_index)_NAVIGATION_FORWARD_COMMANDre   Zcan_go_forwardZ
go_forwardr)   _toast_NAVIGATION_WARNING_COLOR_PAIRZcan_go_backZgo_back_display_outputscreen_output_scroll_output_SCROLL_TO_LINE_INDEX)r(   r   itemr)   r   r   r   _navigate_screen_outputy  s     






z CursesUI._navigate_screen_outputc          
   C   s  | j r| j| j| jd || jkr(tjS || jks<|| jkrJ| 	| dS |rZ| j
| || jr| jrt|t| jkr|t| jd }|| _| j| j|d n| jr| j| jd| jd d| _d| _dS || jrr|dd  }|rdy8t|}t| j|\}}}}|s,| jt|d	 W n2 tk
r` } z| t | W dd}~X Y nX n
| d
 dS y| !|\}	}
}W n2 t"k
r } z| t | dS d}~X Y nX |	sdS d| j#d i}d}| j$%|	r*y| j$j&|	|
|d}W n, tj'k
r& } z
|j(}W dd}~X Y nX nt)| j*d|	  g}g | _+|dk	rT|S | j,-||d | | |ry|.| | /d|  W n$ tk
r   | d|  Y nX d| _d| _dS )zDispatch user command.

    Args:
      command: (str) Command to dispatch.

    Returns:
      An exit token object. None value means that the UI loop should not exit.
      A non-None value means the UI loop should exit.
    )r   N)highlight_regexT)
is_refreshr   r   rY   r   )r   zEmpty indices.colsr   )screen_infozInvalid command prefix "%s"zWrote output to %szFailed to write output to %s)0rf   r   _UI_WAIT_MESSAGE_UI_WAIT_COLOR_PAIRZCLI_EXIT_COMMANDSr   ZEXPLICIT_USER_EXITr   _NAVIGATION_BACK_COMMANDr   r`   Zadd_command
startswithREGEX_SEARCH_PREFIXri   r   r   r   r   rb   rd    TENSOR_INDICES_NAVIGATION_PREFIXr   r	   Zparse_indicesr   Zlocate_tensor_elementrj   r   r   	Exception_error_toaststrZ_parse_commandSyntaxErrorr"   r   Zis_registeredZdispatch_commandr   r   r6   ERROR_MESSAGE_PREFIXra   re   Zadd_itemZwrite_to_file_info_toast)r(   r   regexZindices_strindicesZomittedr   _r   prefixr   Zoutput_file_pathr   r   r   r   r   r   r     s    





"



zCursesUI._dispatch_commandc             C   s   | j  }| S )zGather the text string in the command text box.

    Returns:
      (str) the current text string in the command textbox, excluding any
      return keys.
    )r   gatherr   )r(   txtr   r   r   _screen_gather_textbox_str  s    
z#CursesUI._screen_gather_textbox_strc       
      C   s  t |tstdt| || jkr0|| _| jS || jkrH| j| _| jS |tj	kr`| 
t |S |tjkrx| 
t |S |tjkr| 
t |S |tjkr| 
t |S |tjtjgkrJ| js|  }| j|| j| _| jr8|tjkr| jt| jk r6|  jd7  _n&|tjkr>| jdkr>|  jd8  _nd| _|| _| jS |tjkr||   |   |   |   | jS |tj kr| j!ry| " \}}}}}W n tj#k
r   d}Y nX |tj$kr||| j%d kr| j&'d x||tj$krht(| j) | j*+|}|ttfkr*| 
| | j&,  y| " \}}}}}W n tj#k
rb   Y nX qW | j&'d |S nz|tj-kr|| j%d kr| j*+|}|dk	r| 
| |S | .||}|r| /  | 0|}	|	dk	rt1j2|	dn d| _3d| _g | _| j45||S dS )	a  Text box key validator: Callback of key strokes.

    Handles a user's keypress in the input text box. Translates certain keys to
    terminator keys for the textbox to allow its edit() method to return.
    Also handles special key-triggered events such as PgUp/PgDown scrolling of
    the screen output.

    Args:
      x: (int) Key code.

    Returns:
      (int) A translated key code. In most cases, this is identical to the
        input x. However, if x is a Return key, the return value will be
        CLI_TERMINATOR_KEY, so that the text box's edit() method can return.

    Raises:
      TypeError: If the input x is not of type int.
      debugger_cli_common.CommandLineExit: If a mouse-triggered command returns
        an exit token when dispatched.
    z1Key validator expected type int, received type %sr   r   Nr   TF)r   )6r   r+   	TypeErrortyper   r   CLI_TERMINATOR_KEYr   r   Z	KEY_PPAGEr   r;   Z	KEY_NPAGEr<   ZKEY_HOME_SCROLL_HOMEZKEY_END_SCROLL_ENDZKEY_UPZKEY_DOWNra   r   r`   Zlookup_prefixrc   rb   r   Z
KEY_RESIZEr^   r_   r   _redraw_outputr   r   _screen_getmouser   BUTTON1_PRESSEDr"   r   ZnodelayZnapms_MOUSE_SCROLL_DELAY_MS_scroll_barr@   ZgetchBUTTON1_RELEASED_fetch_hyperlink_commandr   r   r   r   r   _KEY_MAPr   )
r(   xZhist_prefixr   r   r?   Zmouse_event_typeZscroll_commandr   r   r   r   r   r   	  s    

















zCursesUI._on_textbox_keypressc             C   s   t  S )N)r   Zgetmouse)r(   r   r   r   r     s    zCursesUI._screen_getmousec             C   s2   | j d k	r.|   | | j  | j| j dd d S )NT)r   )ri   _display_nav_bar_display_main_menur   )r(   r   r   r   r     s    
zCursesUI._redraw_outputc             C   s   | j }| jr|d7 }|| jkr6| jr6t|| jjd S || j krX| jrXt|| jjd S || j | }|| jjkrt|| jj| S d S )Nr   r   )	ry   _main_menu_padrx   _nav_barr   r4   
_main_menurg   rj   )r(   r   r?   
output_topZabsolute_mouse_yr   r   r   r    s    z!CursesUI._fetch_hyperlink_commandc             C   sP   d| | _ t| j | jk r8|  j d| jt| j   7  _ | j| j| j |d dS )zDisplay title.

    Args:
      title: (str) The title to display.
      title_color: (str) Color of the title, e.g., "yellow".
    z--- %s -)r   N)Z_title_liner   r"   _screen_draw_text_linerw   )r(   r   r   r   r   r   r     s
    	
zCursesUI._titleFc             C   s6   |r|    |pd}x|D ]}| jt| qW dS )zAutomatically key in a command to the command Textbox.

    Args:
      command: The command, as a string or None.
      erase_existing: (bool) whether existing text (if any) is to be erased
          first.
    rY   N)_erase_existing_commandr   
do_commandord)r(   r   Zerase_existingcr   r   r   r     s
    
zCursesUI._auto_key_inc             C   s2   t | j }xt|D ]}| j| j qW dS )z'Erase existing text in command textpad.N)r   r   r   r   r  BACKSPACE_KEY)r(   Zexisting_lenr   r   r   r   r    s    z CursesUI._erase_existing_commandc             C   sf   t |tstdt|| jkr.|d| j }|dkr<| jn| j| }| |d|||B  |   dS )zRender a line of text on the screen.

    Args:
      row: (int) Row index.
      line: (str) The line content.
      attr: curses font attribute.
      color: (str) font foreground color name.

    Raises:
      TypeError: If row is not of type int.
    zInvalid type in rowNr   )	r   r+   r   r   r"   r   r   r   r   )r(   rowliner   r   r   r   r   r   r    s    

zCursesUI._screen_draw_text_linec             C   s   t ||S )a	  Generate a new pad on the screen.

    Args:
      rows: (int) Number of rows the pad will have: not limited to screen size.
      cols: (int) Number of columns the pad will have: not limited to screen
        size.

    Returns:
      A curses textpad object.
    )r   Znewpad)r(   rowsr   r   r   r   _screen_new_output_pad  s    zCursesUI._screen_new_output_padc                s   t || jd \| _ | jjdg| jd   | j | jkr| j	d| j| _| jj
d| j  dt|jd tjfg| jj| j< |   | | j | | j| j\| _| _| _ fdd| jD S )	ac  Actually render text output on the screen.

    Wraps the lines according to screen width. Pad lines below according to
    screen height so that the user can scroll the output to a state where
    the last non-empty line is on the top of the screen. Then renders the
    lines on the screen.

    Args:
      output: (RichTextLines) text lines to display on the screen. These lines
        may have widths exceeding the screen width. This method will take care
        of the wrapping.

    Returns:
      (List of int) A list of line indices, in the wrapped output, where there
        are regex matches.
    r   rY   r   r   zOutput cut off at %d lines!rU   c                s   g | ]} | qS r   r   ).0r  )wrapped_line_indicesr   r   
<listcomp>   s   z3CursesUI._screen_display_output.<locals>.<listcomp>)r   wrap_rich_text_linesr"   rj   linesextendr%   Z	num_linesr~   slicer7   r   r   COLOR_MAGENTAr4   r  r  _display_linesrf   _output_pad_heightZ_output_pad_widthr   )r(   outputr   )r  r   _screen_display_output  s    

"
zCursesUI._screen_display_outputc       	   
   C   s,  |sdS |rxyt j||| jd}W n0 tk
rR } z| t| dS d}~X Y nX |sh|jt j | _q|  j	d7  _	n|| _
g | _| |}|rd}x|D ]}|| j	kr|}P qW |dkr| jt|d n| jd| jd nJ|r| t n:t j|jkr|jt j }| jt|d nd| _	| t dS )	a  Display text output in a scrollable text pad.

    This method does some preprocessing on the text lines, render them on the
    screen and scroll to the appropriate line. These are done according to regex
    highlighting requests (if any), scroll-to-next-match requests (if any),
    and screen refresh requests (if any).

    TODO(cais): Separate these unrelated request to increase clarity and
      maintainability.

    Args:
      output: A RichTextLines object that is the screen output text.
      is_refresh: (bool) Is this a refreshing display with existing output.
      highlight_regex: (str) Optional string representing the regex used to
        search and highlight in the current screen output.
    N)Z	font_attrr   rU   r   )r   zPattern not found)r   )r   Z
regex_find_SEARCH_HIGHLIGHT_FONT_ATTRr'   r   r   annotationsZREGEX_MATCH_LINES_KEYr   rg   ri   r!  r   r   r   _ERROR_TOAST_COLOR_PAIR_SCROLL_REFRESHZINIT_SCROLL_POS_KEYr   )	r(   r   r   r   r   Zwrapped_regex_match_linesZnext_match_lineZ
match_liner   r   r   r   r   $  sB    


zCursesUI._display_outputc             C   s   t |tjstd|   t|t|j}| jd }| 	||}xTt
t|jD ]B}||jkr| j|||j| |j| d qR| |||j|  qRW |||fS )a  Display RichTextLines object on screen.

    Args:
      output: A RichTextLines object.
      min_num_rows: (int) Minimum number of output rows.

    Returns:
      1) The text pad object used to display the main text body.
      2) (int) number of rows of the text pad, which may exceed screen size.
      3) (int) number of columns of the text pad.

    Raises:
      ValueError: If input argument "output" is invalid.
    zBOutput is required to be an instance of RichTextLines, but is not.r   )color_segments)r   r   r6   r'   r   maxr   r  r"   r  r   r4   _screen_add_line_to_output_pad)r(   r   Zmin_num_rowsr  r   r   r:   r   r   r   r  j  s    

zCursesUI._display_linesc             C   sr   | j d }| d|| _| j|| j| j| _| j| jd| jj	d d |d  d| jj
krf| jj
d nd d d S )Nr   r   r   )r&  )r"   r  _nav_bar_padre   renderr   r   r  r(  r  r4   )r(   Znav_bar_widthr   r   r   r    s    

zCursesUI._display_nav_barc             C   s   t j|jkr|jt j jdddgd| _| d| jd | _t | j| jd \}}| j	| jd|j
d d|jkrz|jd nd	d
 nd	| _d	| _d	S )a  Display main menu associated with screen output, if the menu exists.

    Args:
      output: (debugger_cli_common.RichTextLines) The RichTextLines output from
        the annotations field of which the menu will be extracted and used (if
        the menu exists).
    z| z | r   )r   dividerZenabled_item_attrsr   r   r   r   N)r&  )r   ZMAIN_MENU_KEYr#  Zformat_as_single_liner	  r  r"   r  r  r(  r  r4   )r(   r   Zwrapped_menur   r   r   r   r    s    	zCursesUI._display_main_menuc             C   s2   || j d k r.|||d| j d |  | j dS )ap  Pad the whitespace at the end of a line with the default color pair.

    Prevents spurious color pairs from appearing at the end of the lines in
    certain text terminals.

    Args:
      pad: The curses pad object to operate on.
      row: (`int`) row index.
      line_end_x: (`int`) column index of the end of the line (beginning of
        the whitespace).
    r   r/   r   N)r"   r   r   )r(   r   r  Z
line_end_xr   r   r   _pad_line_end_with_whitespace  s    z&CursesUI._pad_line_end_with_whitespacec          	   C   s  |s,| |d|| j | ||t| dS t|ts>tdg }g }|d d dkrXn"|d|d d f || j xt||dd t|ddfg D ]\\}}}	\}
}}|||f t|	ts|	g}	t	j
}x>|	D ]6}| jrt|tjr|t	jO }q|| j|| jO }qW || ||
k r|||
f || j qW xLt||D ]>\}}|d | jk rR| ||d ||d |d  | qRW |r| |||d d  dS )a  Render a line in a text pad.

    Assumes: segments in color_segments are sorted in ascending order of the
    beginning index.
    Note: Gaps between the segments are allowed and will be fixed in with a
    default color.

    Args:
      pad: The text pad to render the line in.
      row: Row index, as an int.
      txt: The text to be displayed on the specified row, as a str.
      color_segments: A list of 3-tuples. Each tuple represents the beginning
        and the end of a color segment, in the form of a right-open interval:
        [start, end). The last element of the tuple is a color string, e.g.,
        "red".

    Raisee:
      TypeError: If color_segments is not of type list.
    r   Nz4Input color_segments needs to be a list, but is not.r   rU   )r   r   r,  r   r   r   r   r7   zipr   A_NORMALr   r   r   r   r   r   r"   )r(   r   r  r   r&  Zall_segmentsZall_color_pairsZ
curr_startZcurr_endZ
curr_attrsZ
next_startr   Zcurses_attrr   segmentr   r   r   r   r(    s@    
4


*z'CursesUI._screen_add_line_to_output_padc       
   
   C   s   |  ||||||| t| jd d| jd | jd | j| j| j | _| | j	 | jd \}}	}	|  |dd| j
d | jd | jd | jd  d S )Nr   r   r   r   )r   r   r"   r%   rg   r  r   r   r  r9   ry   )
r(   r   Zviewport_topZviewport_leftZscreen_location_topZscreen_location_leftZscreen_location_bottomZscreen_location_rightZ
scroll_padr   r   r   r   _screen_scroll_output_pad  s    z"CursesUI._screen_scroll_output_padc          	   C   s  | j s
dS |tkrn>|tkrJ|  jt| jd 8  _| jdk rFd| _n
|tkr|  jt| jd 7  _| j| j| j d kr| j| j d | _n|t	kr| jd dkr|  jd8  _n|t
kr| jd | j| j k r|  jd7  _nl|tkrd| _n\|tkr| j| j d | _n>|tkrHt|ts@tdt|tf || _ntd| | j| j | jj}| jrz|d7 }| | j | jd|| jj| jj| jj |   |   |  | _| j| j | j| j!d dS )a  Scroll the output pad.

    Args:
      direction: _SCROLL_REFRESH, _SCROLL_UP, _SCROLL_DOWN, _SCROLL_UP_A_LINE,
        _SCROLL_DOWN_A_LINE, _SCROLL_HOME, _SCROLL_END, _SCROLL_TO_LINE_INDEX
      line_index: (int) Specifies the zero-based line index to scroll to.
        Applicable only if direction is _SCROLL_TO_LINE_INDEX.

    Raises:
      ValueError: On invalid scroll direction.
      TypeError: If line_index is not int and direction is
        _SCROLL_TO_LINE_INDEX.
    Nr   r   r   z*Invalid line_index type (%s) under mode %szUnsupported scroll mode: %s)r   )"rf   r%  r>   rg   r+   r%   r=   r  r   r;   r<   r   r   r   r   r   r   r'   re   Zupdate_scroll_positionr   rp   r  r0  rq   rr   rs   _screen_render_nav_bar_screen_render_menu_pad_compile_ui_status_summaryZ_scroll_infor  rz   _STATUS_BAR_COLOR_PAIR)r(   	directionr   Zoutput_pad_topr   r   r   r   $  s\    





zCursesUI._scroll_outputc          	   C   s*   | j r&| | j dd| jd| jj| j d S )Nr   )r)  r   rx   r   rp   r"   )r(   r   r   r   r1  q  s    zCursesUI._screen_render_nav_barc          	   C   s,   | j r(| | j dd| jjd| jj| j d S )Nr   )r  r   r   rp   r"   )r(   r   r   r   r2  v  s    z CursesUI._screen_render_menu_padc             C   s\  d}| j | jd krxdtdt| j| j | j d   }| jdkrHd}n | j| j | j d krdd}nd}|d	||f 7 }|  | _| jr| jd r|| | jd 7 }|d
7 }| jd r|| | jd 7 }|d7 }d}|| jrdnd7 }t	|t	| d | j
k rB|d
| j
t	| t	| d  7 }|d7 }||7 }|d7 }n|d
| j
t	|  7 }|S )zCompile status summary about this Curses UI instance.

    The information includes: scroll status and mouse ON/OFF status.

    Returns:
      (str) A single text line summarizing the UI status, adapted to the
        current screen width.
    rY   r   g      Y@g      ?r   z (PgDn)z (PgUp)z (PgDn/PgUp)z--- Scroll%s: %.2f%% r  rU   r/   zMouse: ONZOFF   rS   z ---)r  r   minr,   rg   _show_array_indicesrh   _format_indicesr   r   r"   )r(   infoZscroll_percentageZscroll_directionsZmouse_mode_strr   r   r   r3  |  s<    




"
z#CursesUI._compile_ui_status_summaryc             C   s   t |ddS )Nr/   rY   )reprr   )r(   r   r   r   r   r:    s    zCursesUI._format_indicesc             C   sR   |  d}| j}| jr|d7 }| jj| d }|  |}|s@|rJ||dS dS dS )a  Show array indices for the lines at the top and bottom of the output.

    For the top line and bottom line of the output display area, show the
    element indices of the array being displayed.

    Returns:
      If either the top of the bottom row has any matching array indices,
      a dict from line index (0 being the top of the display area, -1
      being the bottom of the display area) to array element indices. For
      example:
        {0: [0, 0], -1: [10, 0]}
      Otherwise, None.
    r   r   )r   rU   N)_show_array_index_at_linery   r  r   rr   )r(   Zindices_topr
  Zbottom_line_indexZindices_bottomr   r   r   r9    s    


zCursesUI._show_array_indicesc             C   s~   | j | }|| jjkrvd| jj| krv| jj| d }| |}d| }| j}| jr\|d7 }| j|| j|| d |S dS dS )ax  Show array indices for the specified line in the display area.

    Uses the line number to array indices map in the annotations field of the
    RichTextLines object being displayed.
    If the displayed RichTextLines object does not contain such a mapping,
    will do nothing.

    Args:
      line_index: (int) 0-based line index from the top of the display area.
        For example,if line_index == 0, this method will display the array
        indices for the line currently at the top of the display area.

    Returns:
      (list) The array indices at the specified line, if available. None, if
        not available.
    Zi0rL   r   )r   r   N)rg   rj   r#  r:  ry   r  r   _ARRAY_INDICES_COLOR_PAIR)r(   r   pointerr   Zarray_indices_strZarray_indices_infor
  r   r   r   r=    s    

z"CursesUI._show_array_index_at_linec             C   s`   |  |\}}}| j||\}}|r>t|dkr>| | n
| g  |rT|| S || S dS )a[  Perform tab completion.

    Obtains tab completion candidates.
    If there are no candidates, return command_str and take no other actions.
    If there are candidates, display the candidates on screen and return
    command_str + (common prefix of the candidates).

    Args:
      command_str: (str) The str in the command input textbox when Tab key is
        hit.

    Returns:
      (str) Completed string. Could be the same as command_str if no completion
      candidate is available. If candidate(s) are available, return command_str
      appended by the common prefix of the candidates.
    r   N)Z_analyze_tab_complete_inputZ_tab_completion_registryZget_completionsr   _display_candidates)r(   Zcommand_strcontextr   Zexcept_last_word
candidatescommon_prefixr   r   r   r     s    
zCursesUI._tab_completec          
   C   s   | j r| t |sdS d}|d| }tj|dt|t|dfgid}t|| jd \}}t	t|j
| j}| j| d | _| |d\}}}| |dd| jd| j| d | jd	  dS )
zShow candidates (e.g., tab-completion candidates) on multiple lines.

    Args:
      candidates: (list of str) candidates.
    NzCandidates: r/   r   Zyellow)r4   r   r   r   )ri   r   r%  joinr   r6   r   r  r"   r8  r  r}   r|   r{   r  r0  )r(   rB  Zcandidates_prefixZcandidates_lineZcandidates_outputr   Zcandidates_num_rowsr   r   r   r   r@  "  s$    
zCursesUI._display_candidatesc          	   C   sr   |  tj|ddt||ptjfgidd\}}}tt|| jd }|dkrX| jd }| 	|dd|d|| dS )a\  Display a one-line message on the screen.

    By default, the toast is displayed in the line right above the scroll bar.
    But the line location can be overridden with the line_index arg.

    Args:
      message: (str) the message to display.
      color: (str) optional color attribute for the message.
      line_index: (int) line index.
    r   )r4   r   Nr   )
r  r   r6   r   r   rF   r8  r"   rz   r0  )r(   messager   r   r   r   Z	right_endr   r   r   r   H  s    
zCursesUI._toastc             C   s   | j | j| | jd dS )zDisplay a one-line error message on screen.

    Args:
      message: The error message, without the preceding "ERROR: " substring.
    )r   N)r   r   r$  )r(   rE  r   r   r   r   b  s    zCursesUI._error_toastc             C   s   | j | j| | jd dS )zmDisplay a one-line informational message on screen.

    Args:
      message: The informational message.
    )r   N)r   ZINFO_MESSAGE_PREFIX_INFO_TOAST_COLOR_PAIR)r(   rE  r   r   r   r   l  s    zCursesUI._info_toastc             C   s6   ~~| j r|    |   tdtjd td d S )Nz+
tfdbg: caught SIGINT; calling sys.exit(1).)filer   )r   r   printsysstderrexit)r(   Z
signal_numframer   r   r   rm   v  s    zCursesUI._interrupt_handlerc             C   s   ~|rt |dkr|rb|d  dkr,d}n,|d  dkrBd}n| d|d   dS | | | jrldnd}| d	|  n
| d
 dS )a<  Handler for the command prefix 'mouse'.

    Args:
      args: (list of str) Arguments to the command prefix 'mouse'.
      screen_info: (dict) Information about the screen, unused by this handler.

    Returns:
      None, as this command handler does not generate any screen outputs other
        than toasts.
    r   r   onToffFzInvalid mouse mode: %sNzMouse mode: %szmouse_mode: syntax error)r   lowerr   r   r   r   )r(   r   r   enabledZmode_strr   r   r   rn     s    

z$CursesUI._mouse_mode_command_handlerc             C   s$   | j |kr || _ |   |   d S )N)r   r   r   )r(   rP  r   r   r   r     s    
zCursesUI._set_mouse_enabledc             C   s(   | j rttjtjB  n
td d S )Nr   )r   r   Z	mousemaskr  r   )r(   r   r   r   r     s    zCursesUI._screen_set_mousemask)NN)NNNT)N)N)F)FN)N)N)NN)N)`rA   rB   rC   rD   r   r  r   r  r   r   r   r   r   r   r   ZKEY_BACKSPACEZKEY_DCr  r   rF   Z	COLOR_REDr   ZCOLOR_YELLOWZ
COLOR_BLUEZ
COLOR_CYANr  rE   r   r   r"  r>  r$  rF  r4  r   r   r   r   	threadingLockr   r*   r_   r]   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r^   r   r   r   r   r   r   r  r   r   r  r.  r  r  r!  r   r  r  r  r,  r(  r0  r   r1  r2  r3  r:  r9  r=  r   r@  r   r   r   rm   rn   r   r   r   r   r   r   rG      s   

::'	   

$
i 

2
F)
C
M4+&&



!rG   )$rD   
__future__r   r   r   rt   r   r   r   rk   rI  rQ  Z	six.movesr   Ztensorflow.python.debug.clir   r   r	   r
   r   r   r%  r>   r=   r;   r<   r   r   r   r   r   r   objectr   r\   rG   r   r   r   r   <module>   s>    