o
    i=l                     @   s  d Z ddlZddlZddlmZmZmZmZmZm	Z	m
Z
mZmZ ddlmZ ddl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mZmZmZ ddlm Z m!Z! ddl"m#Z#m$Z$ ddl%m&Z& ddl'm(Z(m)Z) ddl*m+Z+ ddl,m-Z- ddl.m/Z/ ddl0m1Z1m2Z2 ddl3m4Z4 ddl5m6Z6 ddl7m8Z8 ddl9m:Z: ddl;m<Z< ddl=m>Z> ddl?m@Z@ ddlAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZI erddlJmKZK dgZLG dd de2ZMG dd de4ZNdS ) z3Module contains the class to create a fuzzy prompt.    N)	TYPE_CHECKINGAnyCallableDictListOptionalTupleUnioncast)fuzzy_match)
fzy_scorersubstr_scorer)	HAYSTACKS)Application)Buffer)IsDone)ConditionalContainerFloatContainerHSplitWindow)BufferControlDummyControl)	DimensionLayoutDimension)Layout)
AfterInputBeforeInput)SimpleLexer)ValidationError)Frame)FakeDocumentInquirerPyUIListControl)BaseListPrompt)InstructionWindow)MessageWindow)ValidationFloat)INQUIRERPY_POINTER_SEQUENCE)InvalidArgument)	Separator)InquirerPyDefaultInquirerPyKeybindingsInquirerPyListChoicesInquirerPyMessageInquirerPySessionResultInquirerPyStyleInquirerPyValidatecalculate_height)KeyPressEventFuzzyPromptc                       s   e Zd ZdZdedededeg ef dedee	 de
d	ed
e
ddf fddZdddZdeeeef  fddZdeeeef  fddZdeeeef  fddZdedeeeef  fddZedeeef fddZedefddZ  ZS )InquirerPyFuzzyControla(  An :class:`~prompt_toolkit.layout.UIControl` class that displays a list of choices.

    This only displays the chocies. The actual input buffer will be handled by a separate
    :class:`~prompt_toolkit.layout.BufferControl`.

    Reference the parameter definition in :class:`.FuzzyPrompt`.
    choicespointermarkercurrent_text	max_linessession_resultmultiselect	marker_plmatch_exactreturnNc
           
         sP   || _ || _|| _|| _|dkr|nd| _|	stnt| _t j	|d ||d d S )Nr      )r4   defaultr9   r:   )
_pointer_marker
_marker_pl_current_text
_max_linesr   r   _scorersuper__init__)
selfr4   r5   r6   r7   r8   r9   r:   r;   r<   	__class__ U/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/InquirerPy/prompts/fuzzy.pyrG   F   s   
zInquirerPyFuzzyControl.__init__c                 C   sj   t | jD ]\}}t|d trtd||d< g |d< q| j| _d| _t| j| j	| _
| j
| j | _d S )Nvaluez:fuzzy prompt argument choices should not contain Separatorindexindicesr   )	enumerater4   
isinstancer(   r'   _filtered_choices_first_lineminrD   choice_count
_last_line_height)rH   rN   choicerK   rK   rL   _format_choices_   s   
z&InquirerPyFuzzyControl._format_choicesc                 C   s   g }| d| jf | d| j|d  d r| jn| jf | d |d s2| d|d f |S t|d }t|d D ]\}}||v rN| d|f q>| d|f q>|S )	a  Get the current highlighted line of text.

        If in the middle of filtering, loop through the char and color
        indices matched char into style class `class:fuzzy_match`.

        Returns:
            FormattedText in list of tuple format.
        class:pointerclass:markerrN   enabled)z[SetCursorPosition] rO   nameclass:fuzzy_match)appendr@   r4   rA   rB   setrP   rH   rX   display_choicesrO   rN   charrK   rK   rL   _get_hover_textl   s&   	
z&InquirerPyFuzzyControl._get_hover_textc                 C   s   g }| dt| jd f | d| j|d  d r| jn| jf |d s1| d|d f |S t|d }t|d D ]\}}||v rM| d	|f q=| d|f q=|S )
a<  Get the line of text in `FormattedText`.

        If in the middle of filtering, loop through the char and color
        indices matched char into `class:fuzzy_match`.

        Calculate spaces of pointer to make the choice equally align.

        Returns:
            FormattedText in list of tuple format.
        rZ    r[   rN   r\   rO   r]   r^   r_   )r`   lenr@   r4   rA   rB   ra   rP   rb   rK   rK   rL   _get_normal_text   s$   z'InquirerPyFuzzyControl._get_normal_textc                 C   s  g }| j dkrd| _|S | jdk rd| _n| j| j kr!| j d | _| j| j t| j | jk rAt| j | j| _| jt| j | j | _| j| jkrW| j| _| jt| j| j  | _n| j| jkrn| jd | _| jt| j| j  | _| j| j kr| j | _| jt| j| j  | _| jdk rd| _| jt| j| j  | _t| j| jD ]!}|| jkr|| | j	| 7 }n
|| 
| j	| 7 }|d q|r|  |S )a1  Get all available choices in formatted text format.

        Overriding this method because `self.choice` will be the
        full choice list. Using `self.filtered_choice` to get
        a list of choice based on current_text.

        Returns:
            FormattedText in list of tuple format.
        r   r>   )r]   
)rU   _selected_choice_indexrV   rS   rT   rW   rangeselected_choice_indexre   rR   rh   r`   pop)rH   rc   rN   rK   rK   rL   _get_formatted_choices   s>   




z-InquirerPyFuzzyControl._get_formatted_choices	wait_timec                    s`   |   s| jD ]}g |d< q| j}|S t|I dH  t|   tt| jd| jdI dH }|S )zCall to filter choices using fzy fuzzy match.

        Args:
            wait_time: Additional time to wait before filtering the choice.

        Returns:
            Filtered choices.
        rO   Nr^   )keyscorer)rC   r4   asynciosleepr   r
   r   rE   )rH   ro   rX   r4   rK   rK   rL   _filter_choices   s   	

	
z&InquirerPyFuzzyControl._filter_choicesc                 C   s   | j | j S )zOverride this value since `self.choice` does not indicate the choice displayed.

        `self.filtered_choice` is the up to date choice displayed.

        Returns:
            A dictionary of name and value for the current pointed choice.
        )rR   rl   rH   rK   rK   rL   	selection   s   	z InquirerPyFuzzyControl.selectionc                 C   s
   t | jS )zint: Filtered choice count.)rg   rR   ru   rK   rK   rL   rU      s   
z#InquirerPyFuzzyControl.choice_countr=   N)__name__
__module____qualname____doc__r+   strr   intr   r-   boolrG   rY   r   r   re   rh   rn   floatr   r   rt   propertyrv   rU   __classcell__rK   rK   rI   rL   r3   =   s@    
	

 0
r3   c                A       s   e Zd ZdZdedddddddddeeddddddddd	dddddd
dfdedededede	e
 dededede	eegef  de	eegef  dedededededededededede	eeef  d e	eeef  d!e	e d"ed#e	e d$ed%ed&ed'ed(ed)e	e d*df@ fd+d,ZdId-e	e d*dfd.d/ZdJd0d1ZdId-e	e d*dfd2d3Zd*eeeef  fd4d5Zd*eeeef  fd6d7Zd8d9 Zd*efd:d;ZdJd<d=ZdJd>d?ZdKdBdCZ e!d*e"f fdDdEZ#e#j$d-e"d*dfdFdEZ#d*efdGdHZ%  Z&S )Lr2   uf  Create a prompt that lists choices while also allowing fuzzy search like fzf.

    A wrapper class around :class:`~prompt_toolkit.application.Application`.

    Fuzzy search using :func:`pfzy.match.fuzzy_match` function.

    Override the default keybindings for up/down as j/k cannot be bind even if `editing_mode` is vim
    due to the input buffer.

    Args:
        message: The question to ask the user.
            Refer to :ref:`pages/dynamic:message` documentation for more details.
        choices: List of choices to display and select.
            Refer to :ref:`pages/dynamic:choices` documentation for more details.
        style: An :class:`InquirerPyStyle` instance.
            Refer to :ref:`Style <pages/style:Alternate Syntax>` documentation for more details.
        vi_mode: Use vim keybinding for the prompt.
            Refer to :ref:`pages/kb:Keybindings` documentation for more details.
        default: Set the default value in the search buffer.
            Different than other list type prompts, the `default` parameter tries to replicate what fzf does and
            add the value in `default` to search buffer so it starts searching immediatelly.
            Refer to :ref:`pages/dynamic:default` documentation for more details.
        qmark: Question mark symbol. Custom symbol that will be displayed infront of the question before its answered.
        amark: Answer mark symbol. Custom symbol that will be displayed infront of the question after its answered.
        pointer: Pointer symbol. Customer symbol that will be used to indicate the current choice selection.
        instruction: Short instruction to display next to the question.
        long_instruction: Long instructions to display at the bottom of the prompt.
        validate: Add validation to user input.
            The main use case for this prompt would be when `multiselect` is True, you can enforce a min/max selection.
            Refer to :ref:`pages/validator:Validator` documentation for more details.
        invalid_message: Error message to display when user input is invalid.
            Refer to :ref:`pages/validator:Validator` documentation for more details.
        transformer: A function which performs additional transformation on the value that gets printed to the terminal.
            Different than `filter` parameter, this is only visual effect and won’t affect the actual value returned by :meth:`~InquirerPy.base.simple.BaseSimplePrompt.execute`.
            Refer to :ref:`pages/dynamic:transformer` documentation for more details.
        filter: A function which performs additional transformation on the result.
            This affects the actual value returned by :meth:`~InquirerPy.base.simple.BaseSimplePrompt.execute`.
            Refer to :ref:`pages/dynamic:filter` documentation for more details.
        height: Preferred height of the prompt.
            Refer to :ref:`pages/height:Height` documentation for more details.
        max_height: Max height of the prompt.
            Refer to :ref:`pages/height:Height` documentation for more details.
        multiselect: Enable multi-selection on choices.
            You can use `validate` parameter to control min/max selections.
            Setting to True will also change the result from a single value to a list of values.
        prompt: Input prompt symbol. Custom symbol to display infront of the input buffer to indicate for input.
        border: Create border around the choice window.
        info: Display choice information similar to fzf --info=inline next to the prompt.
        match_exact: Use exact sub-string match instead of using fzy fuzzy match algorithm.
        exact_symbol: Custom symbol to display in the info section when `info=True`.
        marker: Marker Symbol. Custom symbol to indicate if a choice is selected.
            This will take effects when `multiselect` is True.
        marker_pl: Marker place holder when the choice is not selected.
            This is empty space by default.
        keybindings: Customise the builtin keybindings.
            Refer to :ref:`pages/kb:Keybindings` for more details.
        cycle: Return to top item if hit bottom during navigation or vice versa.
        wrap_lines: Soft wrap question lines when question exceeds the terminal width.
        raise_keyboard_interrupt: Raise the :class:`KeyboardInterrupt` exception when `ctrl-c` is pressed. If false, the result
            will be `None` and the question is skiped.
        mandatory: Indicate if the prompt is mandatory. If True, then the question cannot be skipped.
        mandatory_message: Error message to show when user attempts to skip mandatory prompt.
        session_result: Used internally for :ref:`index:Classic Syntax (PyInquirer)`.

    Examples:
        >>> from InquirerPy import inquirer
        >>> result = inquirer.fuzzy(message="Select one:", choices=[1, 2, 3]).execute()
        >>> print(result)
        1
    r]   NF?rf   Tz EzInvalid inputzMandatory promptmessager4   r?   r5   stylevi_modeqmarkamarktransformerfilterinstructionlong_instructionr:   promptr6   r;   borderinfor<   exact_symbolheight
max_heightvalidateinvalid_messagekeybindingscycle
wrap_linesraise_keyboard_interrupt	mandatorymandatory_messager9   r=   c            #         s  |si }| _ | _d  _d _| _ddiddigddiddigg g d|}t jd1i d|d	|d
|d|d|d|d|	d|
d|d|d|d|d|d|d|d|d|d|d|d| dd jigi _t	|t
s{|ntt
| j _  jd7  _t|| jd\ _ _t||| j j||||d 	 _t jd! _ttdt jt jt j gt!d"d#d$}  fd%d&}!t j"|!d'd( _#t$|  j#g}" j%rt&|"}"t't(t$t) j*d' j+d'd)t,|"t-  d*t,tt. d+t-   j/@ d*t0 j1t-   j/@  j+d,gt2 j3 j4t-  @  j+d- j5d.gd/ _6 j67|  t8 j6 j9 j: j; j<d0 _=d S )2NFrp   upzc-pdownzc-n)r   r   toggletoggle-exactr   r   r   r   r   r   r   r   r   r   r:   r   r   r   r   r   r   r   r   r9   r   funcr>   )height_offset)	r4   r5   r6   r7   r8   r9   r:   r;   r<   )on_text_changedzclass:input)lexer)r   contentc                      s*   t  j j jjdkr jjdS ddS )Nr   r>   )max	preferredrT   )r   _dimmension_max_height_dimmension_heightcontent_controlrW   rK   ru   rK   rL   <lambda>  s    z&FuzzyPrompt.__init__.<locals>.<lambda>T)r   r   dont_extend_height)r   r   r   show_cursor)r   )r   )r   r   r   r   )r   r   r   leftbottom)r   floats)layoutr   key_bindingsediting_modeafter_renderrK   )>_prompt_info_task	_rendered_exact_symbolrF   rG   _toggle_exactkb_func_lookuprQ   r   r
   _result_default_height_offsetr0   r   r   r   r3   _get_current_text_content_controlr   _on_text_changed_bufferr   r   exactr   r   _generate_after_inputr   _generate_before_inputr   r   choice_windowr   _borderr   r   r   r$   _get_prompt_message_wrap_linesr   r   r   _is_displaying_long_instructionr#   _long_instructionr%   _get_error_message_is_invalid _validation_window_bottom_offset_layoutfocusr   _style_kb_editing_mode_after_render_application)#rH   r   r4   r?   r5   r   r   r   r   r   r   r   r   r:   r   r6   r;   r   r   r<   r   r   r   r   r   r   r   r   r   r   r   r9   input_windowchoice_height_dimmensionmain_content_windowrI   ru   rL   rG   K  s  "	

$zFuzzyPrompt.__init__rM   c                 C   s8   |dur|st nt| j_dS | jjtkrt nt| j_dS )zToggle matching algorithm.

        Switch between fzy fuzzy match or sub-string exact match.

        Args:
            value: Specify the value to toggle.
        N)r   r   r   rE   )rH   _rM   rK   rK   rL   r     s   
zFuzzyPrompt._toggle_exactc                 C   s,   | j rt| j }|| j_t|| j_dS dS )zRender callable choices and set the buffer default text.

        Setting buffer default text has to be after application is rendered and choice are loaded,
        because `self._filter_choices` will use the event loop from `Application`.
        N)r   r|   r   textrg   cursor_position)rH   r   default_textrK   rK   rL   _on_rendered  s
   
zFuzzyPrompt._on_renderedc                 C   sR   | j sdS | jjD ]}| jj|d  }t|d trq	|r|n|d  |d< q	dS )zkToggle all choice `enabled` status.

        Args:
            value: Specify the value to toggle.
        NrN   rM   r\   )_multiselectr   rR   r4   rQ   r(   )rH   r   rM   rX   
raw_choicerK   rK   rL   _handle_toggle_all  s   zFuzzyPrompt._handle_toggle_allc                 C   sz   g }| j r;|d |d| jj dt| jj f | jr-|ddt| j df | jjt	kr;|d| j
f |S )z,Virtual text displayed after the user input.)r]   z  zclass:fuzzy_info/z ())r   r`   r   rU   rg   r4   r   selected_choicesrE   r   r   rH   display_messagerK   rK   rL   r     s   
z!FuzzyPrompt._generate_after_inputc                 C   s   g }| dd| j f |S )z8Display prompt symbol as virtual text before user input.zclass:fuzzy_promptz%s )r`   r   r   rK   rK   rL   r   /  s   z"FuzzyPrompt._generate_before_inputc                 C   s&   |  rdS | | j_| j  dS )z<Redraw `self._application` when the filter task is finished.N)	cancelledresultr   rR   r   
invalidate)rH   taskrK   rK   rL   _filter_callback5  s   zFuzzyPrompt._filter_callbackc                 C   sl   ddddd}d}t | jjdkrttt | jjd }|dk r$d	S ||v r,|| S |d
 d|d
   S )a1  Calculate wait time to smoother the application on big data set.

        Using digit of the choices lengeth to get wait time.
        For digit greater than 6, using formula 2^(digit - 5) * 0.3 to increase the wait_time.

        Returns:
            Desired wait time before running the filter.
        g?g?g?g333333?)            r>   r   r   g        r   )rg   r   r4   r}   mathlog10)rH   
wait_tabledigitrK   rK   rL   _calculate_wait_time<  s   
z FuzzyPrompt._calculate_wait_timec                 C   sT   | j rd| _ |  }| jr| j s| j  t| j|| _| j	| j
 dS )a  Handle buffer text change event.

        1. Check if there is current task running.
        2. Cancel if already has task, increase wait_time
        3. Create a filtered_choice task in asyncio event loop
        4. Add callback

        1. Run a new filter on all choices.
        2. Re-calculate current selected_choice_index
            if it exceeds the total filtered_choice.
        3. Avoid selected_choice_index less than zero,
            this fix the issue of cursor lose when:
            choice -> empty choice -> choice

        Don't need to create or check asyncio event loop, `prompt_toolkit`
        application already has a event loop running.
        FN)_invalidr   r   donecancelrr   create_taskr   rt   add_done_callbackr   )rH   r   ro   rK   rK   rL   r   U  s   

zFuzzyPrompt._on_text_changedc                 C   s8   | j sdS | jjd }| jj| d  | jj| d< dS )z;Handle tab event, alter the `selected` state of the choice.NrN   r\   )r   r   rv   r4   )rH   r   current_selected_indexrK   rK   rL   _handle_toggle_choiceq  s   
z!FuzzyPrompt._handle_toggle_choiceeventr1   c              
   C   s6  z\t | j}| j| | jrAd| jd< | js0| jjd g| jd< |j	j
| jjd gd W dS | j| jd< |j	j
| jd W dS d| jd< | jjd | jd< |j	j
| jjd d W dS  tyv } z| t| W Y d}~dS d}~w ty   d| jd< | jsdng | jd< |j	j
| jsdng d Y dS w )a  Handle enter event.

        Validate the result first.

        In multiselect scenario, if no TAB is entered, then capture the current
        highlighted choice and return the value in a list.
        Otherwise, return all TAB choices as a list.

        In normal scenario, reutrn the current highlighted choice.

        If current UI contains no choice due to filter, return None.
        Tansweredr^   r   rM   )r   N)r    result_value
_validatorr   r   statusr   r   rv   appexitresult_namer   
_set_errorr|   
IndexError)rH   r   fake_documenterK   rK   rL   _handle_enterz  s*   



zFuzzyPrompt._handle_enterc                    s   t tt jS )z2InquirerPyFuzzyControl: Override for type-hinting.)r
   r3   rF   r   ru   rI   rK   rL   r     s   zFuzzyPrompt.content_controlc                 C   s
   || _ d S N)r   )rH   rM   rK   rK   rL   r     s   
c                 C   s   | j jS )zGet current input buffer text.)r   r   ru   rK   rK   rL   r     s   zFuzzyPrompt._get_current_textr  rw   )r   r1   r=   N)'rx   ry   rz   r{   r&   r,   r+   r)   r|   r   r.   r~   r   r   r	   r}   r/   r*   r-   rG   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r3   r   setterr   r   rK   rK   rI   rL   r2     s    K	
 ! (



	#)Or{   rr   r   typingr   r   r   r   r   r   r   r	   r
   pfzyr   
pfzy.scorer   r   
pfzy.typesr   &prompt_toolkit.application.applicationr   prompt_toolkit.bufferr   prompt_toolkit.filters.clir    prompt_toolkit.layout.containersr   r   r   r   prompt_toolkit.layout.controlsr   r   prompt_toolkit.layout.dimensionr   r   prompt_toolkit.layout.layoutr    prompt_toolkit.layout.processorsr   r   prompt_toolkit.lexers.baser   prompt_toolkit.validationr   prompt_toolkit.widgets.baser   InquirerPy.baser    r!   InquirerPy.base.listr"   !InquirerPy.containers.instructionr#   InquirerPy.containers.messager$    InquirerPy.containers.validationr%   InquirerPy.enumr&   InquirerPy.exceptionsr'   InquirerPy.separatorr(   InquirerPy.utilsr)   r*   r+   r,   r-   r.   r/   r0   (prompt_toolkit.key_binding.key_processorr1   __all__r3   r2   rK   rK   rK   rL   <module>   sB    ,( G