o
    ˷eD                     @   s   d Z ddlZddlmZmZ ddlmZ ddlmZm	Z	m
Z
mZmZmZ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mZ erZddlmZ ddlmZ g dZ G dd dZ!	 e!dddZ"G dd dZ#G dd dZ$dS )a%  
An :class:`~.KeyProcessor` receives callbacks for the keystrokes parsed from
the input in the :class:`~prompt_toolkit.inputstream.InputStream` instance.

The `KeyProcessor` will according to the implemented keybindings call the
correct callbacks when new key presses are feed through `feed`.
    N)Tasksleep)deque)TYPE_CHECKINGAnyDeque	GeneratorListOptionalUnion)get_app)EditingMode)vi_navigation_mode)Keys)Event   )BindingKeyBindingsBase)Application)Buffer)KeyProcessorKeyPressKeyPressEventc                   @   sT   e Zd ZdZddeeef dee ddfddZdefdd	Z	d
e
defddZdS )r   z
    :param key: A `Keys` instance or text (one character).
    :param data: The received string on stdin. (Often vt100 escape codes.)
    Nkeydatareturnc                 C   sH   t |tst|dksJ |d u rt |tr|j}n|}|| _|| _d S )Nr   )
isinstancer   lenvaluer   r   )selfr   r    r    _/var/www/ideatree/venv/lib/python3.10/site-packages/prompt_toolkit/key_binding/key_processor.py__init__'   s   

zKeyPress.__init__c                 C   s   | j j d| jd| jdS )Nz(key=z, data=))	__class____name__r   r   r   r    r    r!   __repr__3   s   zKeyPress.__repr__otherc                 C   s&   t |tsdS | j|jko| j|jkS )NF)r   r   r   r   )r   r(   r    r    r!   __eq__6   s   
zKeyPress.__eq__N)r%   
__module____qualname____doc__r   r   strr
   r"   r'   objectboolr)   r    r    r    r!   r   !   s
    $r   ?_Flush)r   c                   @   s  e Zd ZdZdeddfddZd)ddZd	ee dee	 fd
dZ
d	ee defddZdededf fddZd*dededdfddZd*d	ee deddfddZd)ddZdee fddZde	dee ddfddZd+d!d"Zd+d#d$Zd)d%d&Zd)d'd(ZdS ),r   aP  
    Statemachine that receives :class:`KeyPress` instances and according to the
    key bindings in the given :class:`KeyBindings`, calls the matching handlers.

    ::

        p = KeyProcessor(key_bindings)

        # Send keys into the processor.
        p.feed(KeyPress(Keys.ControlX, ''))
        p.feed(KeyPress(Keys.ControlC, '')

        # Process all the keys in the queue.
        p.process_keys()

        # Now the ControlX-ControlC callback will be called if this sequence is
        # registered in the key bindings.

    :param key_bindings: `KeyBindingsBase` instance.
    key_bindingsr   Nc                 C   s,   || _ t| | _t| | _d | _|   d S r*   )	_bindingsr   before_key_pressafter_key_press_flush_wait_taskreset)r   r3   r    r    r!   r"   Y   s
   

zKeyProcessor.__init__c                 C   s:   g | _ d | _t | _g | _d | _|  | _| jd  d S r*   )	_previous_key_sequence_previous_handlerr   input_queue
key_bufferarg_process_process_coroutinesendr&   r    r    r!   r8   c   s   
zKeyProcessor.resetkey_pressesc                 C   s(   t dd |D }dd | j|D S )zw
        For a list of :class:`KeyPress` instances. Give the matching handlers
        that would handle this.
        c                 s       | ]}|j V  qd S r*   r   .0kr    r    r!   	<genexpr>{       z,KeyProcessor._get_matches.<locals>.<genexpr>c                 S      g | ]}|  r|qS r    filterrE   br    r    r!   
<listcomp>~       z-KeyProcessor._get_matches.<locals>.<listcomp>)tupler4   get_bindings_for_keys)r   rA   keysr    r    r!   _get_matchesv   s   zKeyProcessor._get_matchesc                 C   s:   t dd |D }dd | j|D }tdd |D S )z
        For a list of :class:`KeyPress` instances. Return True if there is any
        handler that is bound to a suffix of this keys.
        c                 s   rB   r*   rC   rD   r    r    r!   rG      rH   z:KeyProcessor._is_prefix_of_longer_match.<locals>.<genexpr>c                 S   s   h | ]}|j qS r    rJ   rL   r    r    r!   	<setcomp>   s    z:KeyProcessor._is_prefix_of_longer_match.<locals>.<setcomp>c                 s   s    | ]}| V  qd S r*   r    )rE   fr    r    r!   rG      rH   )rP   r4   get_bindings_starting_with_keysany)r   rA   rR   filtersr    r    r!   _is_prefix_of_longer_match   s
   
z'KeyProcessor._is_prefix_of_longer_matchc           
      c   s   | j }d}	 d}|rd}ndV }|tu rd}n|| |r| |}|r)d}n| |}dd |D }|r;|}d}|sR|rR| j|d |dd d |dd= n;|s|sd}d}tt|ddD ]#}	| |d|	 }|r| j|d |d|	 d |d|	= d} nqb|s|dd	= q)
z
        Coroutine implementing the key match algorithm. Key strokes are sent
        into this generator, and it calls the appropriate handlers.
        FTNc                 S   rI   r    )eager)rE   mr    r    r!   rN      rO   z)KeyProcessor._process.<locals>.<listcomp>)key_sequencer   r   )r<   r2   appendrS   rY   _call_handlerranger   )
r   bufferretryflushr   matchesis_prefix_of_longer_matcheager_matchesfoundir    r    r!   r>      sJ   




zKeyProcessor._processF	key_pressfirstc                 C   s$   |r
| j | dS | j | dS )z
        Add a new :class:`KeyPress` to the input queue.
        (Don't forget to call `process_keys` in order to process the queue.)

        :param first: If true, insert before everything else.
        N)r;   
appendleftr^   )r   ri   rj   r    r    r!   feed   s   zKeyProcessor.feedc                 C   s(   |r| j t| dS | j | dS )zG
        :param first: If true, insert before everything else.
        N)r;   
extendleftreversedextend)r   rA   rj   r    r    r!   feed_multiple   s   zKeyProcessor.feed_multiplec                    s   t   dtf fdd}dtf fdd}d}| rW| }|tu }|jtjk}|s2|s2j  zj	
| W n tyJ        w |sT|sTj  | s|s_  dS dS )a,  
        Process all the keys in the `input_queue`.
        (To be called after `feed`.)

        Note: because of the `feed`/`process_keys` separation, it is
              possible to call `feed` from inside a key binding.
              This function keeps looping until the queue is empty.
        r   c                      s$    j rtdd jD S tjS )Nc                 s   s     | ]}|j tjkr|V  qd S r*   r   r   CPRResponserD   r    r    r!   rG      s    z?KeyProcessor.process_keys.<locals>.not_empty.<locals>.<genexpr>)is_donerW   r;   r0   r    appr   r    r!   	not_empty   s   
z,KeyProcessor.process_keys.<locals>.not_emptyc                     s4    j rdd jD d } j|  | S j S )Nc                 S   s   g | ]
}|j tjkr|qS r    rq   rD   r    r    r!   rN          z?KeyProcessor.process_keys.<locals>.get_next.<locals>.<listcomp>r   )rs   r;   removepopleft)cprrt   r    r!   get_next   s
   
z+KeyProcessor.process_keys.<locals>.get_nextFN)r   r0   r   r2   r   r   rr   r5   firer?   r@   	Exceptionr8   empty_queuer6   _start_timeout)r   rv   r{   is_flushri   is_cprr    rt   r!   process_keys   s.   		

zKeyProcessor.process_keysc                 C   s&   t | j}| j  dd |D }|S )zF
        Empty the input queue. Return the unprocessed input.
        c                 S   s   g | ]
}|j tjkr|qS r    rq   rD   r    r    r!   rN   %  rw   z,KeyProcessor.empty_queue.<locals>.<listcomp>)listr;   clear)r   rA   r    r    r!   r~     s   

zKeyProcessor.empty_queuehandlerr]   c                 C   s&  t  }|jj}t|jj}|jj}| j}d | _tt	
| ||| j|| jkd}||r2|jj  ddlm}	 z|| | | W n |	yR   |j  Y nw |rZ| | || _|| _| r|jjrw|rw|jj}
|
d urw|
| |jjr|r|D ]}|j j|j7  _qd S d S d S d S )N)r=   r]   previous_key_sequence	is_repeatr   )EditReadOnlyBuffer)r   emacs_stateis_recordingr0   vi_staterecording_registertemporary_navigation_moder=   r   weakrefrefr9   r:   save_beforeru   current_buffersave_to_undo_stackprompt_toolkit.bufferr   call_fix_vi_cursor_positionoutputbell_leave_vi_temp_navigation_moderecord_in_macrocurrent_recordingro   r   )r   r   r]   ru   was_recording_emacswas_recording_viwas_temporary_navigation_moder=   eventr   	recordingrF   r    r    r!   r_   (  sJ   
	


zKeyProcessor._call_handlerr   r   c                 C   sT   |j }|j}|j}t r$|jjr&t|jjdkr(| jd8  _||_dS dS dS dS )z
        After every command, make sure that if we are in Vi navigation mode, we
        never put the cursor after the last character of a line. (Unless it's
        an empty line.)
        r   r   N)	ru   r   preferred_columnr   documentis_cursor_at_the_end_of_liner   current_linecursor_position)r   r   ru   buffr   r    r    r!   r   [  s   
z$KeyProcessor._fix_vi_cursor_positionc                 C   s@   |j }|jtjkr|jjdu r| jdu rd|j_dS dS dS dS )z
        If we're in Vi temporary navigation (normal) mode, return to
        insert/replace mode after executing one action.
        NF)ru   editing_moder   VIr   operator_funcr=   r   )r   r   ru   r    r    r!   r   p  s   z+KeyProcessor._leave_vi_temp_navigation_modec                    sZ   t  }|jdu rdS d fdd}dfdd jr$j  || _dS )a%  
        Start auto flush timeout. Similar to Vim's `timeoutlen` option.

        Start a background coroutine with a timer. When this timeout expires
        and no key was pressed in the meantime, we flush all data in the queue
        and call the appropriate key binding handlers.
        Nr   c                      s,   t I dH  tjdkr   dS dS )zWait for timeout.Nr   )r   r   r<   r    
flush_keysr   timeoutr    r!   wait  s
   
z)KeyProcessor._start_timeout.<locals>.waitc                      s     t    dS )zFlush keys.N)rl   r2   r   r    r&   r    r!   r     s   
z/KeyProcessor._start_timeout.<locals>.flush_keysr   N)r   
timeoutlenr7   cancelcreate_background_task)r   ru   r   r    r   r!   r   |  s   	
zKeyProcessor._start_timeoutc                 C   s"   | j ttjddd |   dS )zG
        Send SIGINT. Immediately call the SIGINT key handler.
        rC   T)rj   N)rl   r   r   SIGINTr   r&   r    r    r!   send_sigint  s   zKeyProcessor.send_sigintr   )F)r   r   r   N)r%   r+   r,   r-   r   r"   r8   r	   r   r   rS   r0   rY   r   r>   rl   rp   r   r~   r_   r   r   r   r   r    r    r    r!   r   C   s     


;
	;
3

!r   c                   @   s   e Zd ZdZdddee dee dee dedd	fd
dZ	defddZ
edefddZedefddZed!ddZed"ddZedefddZedefddZdedd	fddZed!dd Zd	S )#r   at  
    Key press event, delivered to key bindings.

    :param key_processor_ref: Weak reference to the `KeyProcessor`.
    :param arg: Repetition argument.
    :param key_sequence: List of `KeyPress` instances.
    :param previouskey_sequence: Previous list of `KeyPress` instances.
    :param is_repeat: True when the previous event was delivered to the same handler.
    key_processor_refz#weakref.ReferenceType[KeyProcessor]r=   r]   r   r   r   Nc                 C   s*   || _ || _|| _|| _|| _t | _d S r*   )_key_processor_refr]   r   r   _argr   _app)r   r   r=   r]   r   r   r    r    r!   r"     s   	zKeyPressEvent.__init__c                 C   s   d | j| j| jS )Nz:KeyPressEvent(arg={!r}, key_sequence={!r}, is_repeat={!r}))formatr=   r]   r   r&   r    r    r!   r'     s
   zKeyPressEvent.__repr__c                 C   s   | j d jS )Nr\   )r]   r   r&   r    r    r!   r     s   zKeyPressEvent.datac                 C   s   |   }|d u rtd|S )Nz.KeyProcessor was lost. This should not happen.)r   r}   )r   	processorr    r    r!   key_processor  s   zKeyPressEvent.key_processorApplication[Any]c                 C      | j S )z3
        The current `Application` object.
        )r   r&   r    r    r!   ru     s   zKeyPressEvent.appr   c                 C   s   | j jS )z%
        The current buffer.
        )ru   r   r&   r    r    r!   r     s   zKeyPressEvent.current_bufferc                 C   s0   | j dkrdS t| j pd}t|dkrd}|S )z&
        Repetition argument.
        -r\   r   i@B )r   int)r   resultr    r    r!   r=     s   
zKeyPressEvent.argc                 C   s
   | j duS )zF
        True if repetition argument was explicitly provided.
        N)r   r&   r    r    r!   arg_present  s   
zKeyPressEvent.arg_presentr   c                 C   sZ   |dv sJ | j }|dkr|du s|dksJ |}n|du r!|}n| | }|| j_dS )zb
        Add digit to the input argument.

        :param data: the typed digit as string
        z-0123456789r   N)r   r   r=   )r   r   currentr   r    r    r!   append_to_arg_count  s   z!KeyPressEvent.append_to_arg_countc                 C   r   )zFor backward-compatibility.)ru   r&   r    r    r!   cli  s   zKeyPressEvent.cli)r   r   )r   r   )r%   r+   r,   r-   r
   r.   r	   r   r0   r"   r'   propertyr   r   r   ru   r   r   r=   r   r   r   r    r    r    r!   r     s>    

r   )%r-   r   asyncior   r   collectionsr   typingr   r   r   r   r	   r
   r   "prompt_toolkit.application.currentr   prompt_toolkit.enumsr   prompt_toolkit.filters.appr   prompt_toolkit.keysr   prompt_toolkit.utilsr   r3   r   r   prompt_toolkit.applicationr   r   r   __all__r   r2   r   r   r    r    r    r!   <module>   s,    $  d