
    sjma                    Z    d Z ddlmZ dZddZdd	ZddZddZddZddZ	ddZ
ddZdS )u  Augmentations to prompt_toolkit's input-parsing tables.

Imported once at CLI startup. Each helper installs a small mapping into
prompt_toolkit's `ANSI_SEQUENCES` so byte sequences emitted by modern
keyboard protocols (Kitty / xterm `modifyOtherKeys`) decode to existing
key tuples Hermes already binds.

Kept in a standalone module — separate from `cli.py` — so the registrations
can be unit-tested without importing the whole CLI runtime.
    )annotations)r   @         modifierintreturntuple[int, ...]c                D     t           fdt          D                       S )z9Return ``modifier`` plus its CapsLock/NumLock/both twins.c              3  "   K   | ]	}|z   V  
d S N .0offr   s     >/home/agent/.hermes/hermes-agent/hermes_cli/pt_input_extras.py	<genexpr>z!_lock_variants.<locals>.<genexpr>   s'      ==CC======    tuple_LOCK_BIT_OFFSETSr   s   `r   _lock_variantsr      s'    ====+<======r   c                T     t           fdt          dd         D                       S )zBReturn only the lock twins of ``modifier`` (never the base value).c              3  "   K   | ]	}|z   V  
d S r   r   r   s     r   r   z_lock_twins.<locals>.<genexpr>   s'      AACCAAAAAAr      Nr   r   s   `r   _lock_twinsr      s0    AAAA+<QRR+@AAAAAAr   Nonec                 ^    	 ddl m}  |                                  dS # t          $ r Y dS w xY w)a  Drop prompt_toolkit's memoized "is this a prefix of a longer match?"
    answers after mutating ``ANSI_SEQUENCES``.

    The cache is module-global and populated lazily per distinct prefix, so
    parsers created before an install (or primed by earlier tests) would
    otherwise keep stale ``False`` answers and misparse newly registered
    sequences. Call after any install that changed the table.
    r    _IS_PREFIX_OF_LONGER_MATCH_CACHEN)!prompt_toolkit.input.vt100_parserr!   clear	Exceptionr    s    r   _clear_vt100_prefix_cacher%   !   sa    	
 	
 	
 	
 	
 	
 	)..00000   s    
,,c                    	 ddl m}  ddlm} n# t          $ r Y dS w xY w|j        |j        f}d}d t          d          D             }|ddgz  }|D ]%}|                     |          |k    r
|| |<   |dz  }&|rt                       |S )	u	  Map Shift+Enter byte sequences to the (Escape, ControlM) key tuple
    that Alt+Enter produces, so the existing Alt+Enter newline handler
    fires for terminals that emit a distinct Shift+Enter.

    Sequences mapped:
      - "\x1b[13;2u"     — Kitty keyboard protocol / CSI-u, modifier=2 (Shift)
        (plus its CapsLock/NumLock lock twins via ``_lock_variants``)
      - "\x1b[27;2;13~"  — xterm modifyOtherKeys=2, modifier=2 (Shift)
      - "\x1b[27;2;13u"  — alternate ordering some emitters use

    The CSI-u sequence is not in stock prompt_toolkit. The modifyOtherKeys
    variant `\x1b[27;2;13~` IS in stock prompt_toolkit but mapped to plain
    `Keys.ControlM` — i.e. Shift+Enter behaves identically to Enter, which
    is the very bug this helper exists to fix. We therefore overwrite
    those two specific keys (and `\x1b[27;2;13u`) unconditionally; other
    `\x1b[27;...;13~` sequences (Ctrl+Enter, Alt+Enter via modifyOtherKeys
    variants 5/6/etc.) are left untouched.

    Default macOS Terminal and stock Windows Terminal still send the same
    byte for Enter and Shift+Enter, so there is no fix for those terminals
    at the application layer — the sequences above never reach Hermes.

    Returns the number of sequences whose mapping was changed.
    r   ANSI_SEQUENCESKeysc                    g | ]}d | d	S z[13;ur   r   ms     r   
<listcomp>z-install_shift_enter_alias.<locals>.<listcomp>T        777OqOOO777r      z
[27;2;13~z
[27;2;13ur   
*prompt_toolkit.input.ansi_escape_sequencesr(   prompt_toolkit.keysr*   r$   EscapeControlMr   getr%   r(   r*   	alt_enterchangedseqsseqs         r   install_shift_enter_aliasr>   3   s    2MMMMMM,,,,,,,   qq dm,IG77^A%6%6777D_o..D  c""i//"+N3qLG $!###N    
c                    	 ddl m}  ddlm} n# t          $ r Y dS w xY w|j        |j        f}d}d t          d          D             }|ddgz  }|D ]%}|                     |          |k    r
|| |<   |dz  }&|rt                       |S )	u  Map Ctrl+Enter byte sequences to the (Escape, ControlM) key tuple
    that Alt+Enter produces, so the existing Alt+Enter newline handler
    fires for terminals that emit a distinct Ctrl+Enter.

    Sequences mapped:
      - "\x1b[13;5u"     — Kitty keyboard protocol / CSI-u, modifier=5 (Ctrl)
        (plus its CapsLock/NumLock lock twins via ``_lock_variants``)
      - "\x1b[27;5;13~"  — xterm modifyOtherKeys=2, modifier=5 (Ctrl)
      - "\x1b[27;5;13u"  — alternate ordering some emitters use

    Stock prompt_toolkit maps only the tilde form ``\x1b[27;5;13~`` (to
    plain ``Keys.ControlM``, which this deliberately overwrites — same
    bug-fix rationale as install_shift_enter_alias). Without this alias,
    Kitty/mintty/xterm-with-modifyOtherKeys users over SSH never get a
    Ctrl+Enter newline — the keystroke arrives as a raw CSI sequence that
    falls through to the default character-insert handler. See #22379.

    Returns the number of sequences whose mapping was changed.
    r   r'   r)   c                    g | ]}d | d	S r,   r   r.   s     r   r0   z,install_ctrl_enter_alias.<locals>.<listcomp>{   r1   r      z
[27;5;13~z
[27;5;13ur   r3   r9   s         r   install_ctrl_enter_aliasrC   _   s    (MMMMMM,,,,,,,   qq dm,IG77^A%6%6777D_o..D  c""i//"+N3qLG $!###Nr?   c                 `   	 ddl m}  ddlm} n# t          $ r Y dS w xY wi }dD ]0}t          |          D ]}|j        |d| d<   |j        |d| d<   1|j        |d	<   d}|                                D ](\  }}| 	                    |          |k    r
|| |<   |d
z  })|rt                       |S )uP  Map Cmd+Backspace / Cmd+ForwardDelete to the readline kill bindings
    prompt_toolkit already ships (``unix-line-discard`` / ``kill-line``).

    Terminals that rewrite Cmd+Backspace to Ctrl+U (``\x15``) already work.
    Kitty keyboard protocol and xterm modifyOtherKeys terminals instead
    report Cmd as the *super* modifier bit (8), producing sequences
    prompt_toolkit does not map — the raw bytes then fall through to
    literal insertion.

    Cmd+Backspace → ``Keys.ControlU`` (kill backward to start of line).
    Codepoint 127 with modifier 9 (super) / 10 (super+shift), each with
    its CapsLock/NumLock lock twins via ``_lock_variants``:
      - ``\x1b[127;9u`` / ``\x1b[127;10u``  — Kitty CSI-u
      - ``\x1b[27;9;127~``                   — xterm modifyOtherKeys

    Cmd+ForwardDelete → ``Keys.ControlK`` (kill to end of line). The
    forward-delete key is a CSI *tilde* key, not a CSI-u codepoint, so the
    modifier rides in the standard ``CSI 3 ; mod ~`` form:
      - ``\x1b[3;9~`` / ``\x1b[3;10~``

    Returns the number of sequences whose mapping was changed.
    r   r'   r)   )	   
   z[127;r-   z[3;~z[27;9;127~r   )r4   r(   r5   r*   r$   r   ControlUControlKitemsr8   r%   )r(   r*   aliasesbasemodr;   r=   keys           r   install_cmd_backspace_aliasrO      s*   .MMMMMM,,,,,,,   qq "$G 6 6!$'' 	6 	6C*.-G&&&&'(,G$c$$$%%	6 !%GGMMOO  Sc""c))"%N3qLG $!###Nr?   c                    	 ddl m ddlm}  n# t          $ r Y dS w xY wi }t          t          d          t          d          dz             D ]0}t          |dz            }                    |          }||||<   1t          d	          D ](}t          | d
|           |t          d          |z   <   )dD ]0}t          |dz            }                    |          }||||<   1dd@fd} |d|           i }t          t          d          t          d          dz             D ]>}t          |          }	t          |dz
            }
| j
        |	f||<   | j
        |
f||dz
  <   ? |d|           i }t          t          d          t          d          dz             D ]!}t          |dz
            }|||<   |||dz
  <   " |d|           i }i }i }t          t          d          t          d          dz             D ]R}t          |dz
            }|                    |          }||dz
  fD ]!}| j
        |f||<   ||||<   | j
        |f||<   "S |d|            |d|            |d|            |d|           dgd t          dd          D             z   D ]}|vr| j
        |<   dz   |d| j        | j        dd             |d| j
        | j        f| j
        | j        f| j
        dfd!            |d| j        | j
        | j        fd"            |d| j        | j        d| j        d#           t          dd          D ]}d$D ]s}|dk    rd%| | nd&| }                    |          }||dk    r                    d'|           }|Lt          |          D ]}d%| | }|vr
||<   dz  td(D ]X}|dk    r	d&| d)| d*nd&| d*}                    |          }|/t          |          D ]}d&| d)| d*}|vr
||<   dz  Yi }t          d	          D ]}t!          |          |d+|z   <   |                    d,d-d.d/d0| j        d1d2d3           |                    | j        | j        | j        | j        | j        | j        | j        | j        | j        | j        d4
           t          d5d6          D ]}t          | d7|           |d8|d5z
  z   <   t9          t          d9d:                    t9          t          d;d+                    z   d<gz   t9          t          d=d>                    z   D ]}|                    || j                   |                                D ]B\  }}d&| d?}|vr
||<   dz  t          d          D ]}d&| d)| d?}|vr
||<   dz  CrtA                       S )Au  Map Ctrl+key and Alt+key sequences emitted under ``modifyOtherKeys`` level 2
    and Kitty CSI-u to the same ``Keys``.* values that the raw control bytes
    already map to.

    When the terminal is in ``modifyOtherKeys=2`` mode (pushed by
    ``_enable_extended_enter_keys`` so Shift+Enter is distinguishable from
    Enter), the terminal re-encodes *every* Ctrl+key combo as
    ``ESC[27;5;<codepoint>~`` instead of the raw control byte (``\x01`` etc.).
    Kitty keyboard protocol emits ``ESC[<codepoint>;5u``.

    Stock prompt_toolkit 3.x only maps ``ESC[27;5;13~`` (Ctrl+Enter = Ctrl+M);
    all other Ctrl+letter combos are unmapped and leak as literal text or get
    swallowed — breaking Ctrl+A, Ctrl+C, Ctrl+D, Ctrl+E, Ctrl+K, Ctrl+R,
    Ctrl+U, Ctrl+W, Ctrl+Z, etc. (#56684, #86866, #87390).

    This function populates ``ANSI_SEQUENCES`` for the full set:

    * **Ctrl+letter** (a–z): ``ESC[27;5;<codepoint>~`` and ``ESC[<codepoint>;5u``
      → ``Keys.ControlA`` .. ``Keys.ControlZ``
    * **Ctrl+digit** (0–9): same formats → ``Keys.Control0`` .. ``Keys.Control9``
    * **Ctrl+symbol** (``[`` ``\`` ``]`` ``^`` ``_`` `` `` ``@``):
      same formats → the same ``Keys`` value the raw control byte maps to.
    * **Alt+letter** (a–z, A–Z): ``ESC[27;3;<codepoint>~`` and
      ``ESC[<codepoint>;3u`` → ``(Keys.Escape, <letter>)`` — matching how
      prompt_toolkit handles a bare ``ESC`` followed by a character.
    * **Shift+letter** (a–z): → the uppercase character.
    * **Multi-modifier letters** (Shift+Alt=4, Ctrl+Shift=6, Ctrl+Alt=7,
      Ctrl+Alt+Shift=8): normalized onto the same targets — Ctrl-bearing
      combos behave as the Ctrl key (Alt adds an ``Escape`` prefix),
      matching how dte/kakoune normalize these protocols.
    * **Lock-bit variants**: every CSI-u mapping above is also installed
      with the CapsLock (64) and NumLock (128) bits ORed into the modifier
      parameter — kitty/ghostty include them while a lock is on, and
      without the variants every key combo dies with the lock enabled
      (``ESC[99;133u`` instead of ``ESC[99;5u``, #89651).
    * **Esc key**: ``ESC[27u`` / ``ESC[27;<mod>u`` (Kitty disambiguate mode
      reports Esc this way, #56684) → ``Keys.Escape``.
    * **Modified Enter/Tab/Backspace/Space**: Alt+Enter → the Alt+Enter
      newline tuple; Shift+Tab → ``BackTab``; Ctrl+Tab → plain Tab;
      Ctrl/Alt+Backspace → ``(Escape, ControlH)`` (backward-kill-word,
      matching the Ink TUI and Desktop, #78285); Shift+Backspace → plain
      backspace; Shift+Space → a plain space (#86866); Alt+Space →
      ``(Escape, " ")``.
    * **Kitty functional keys** (Private Use Area codepoints): keypad keys
      → their non-keypad equivalents (KP_ENTER → Enter, KP_4 → '4',
      KP_LEFT → Left, …); F13–F24 → ``Keys.F13``..``F24``; lock/media/
      modifier-event keys → ``Keys.Ignore`` so they are consumed instead of
      leaking as literal text. kitty emits these CSI-u forms even in legacy
      mode for keys that have no legacy encoding.

    Existing mappings (including those installed by
    ``install_shift_enter_alias`` / ``install_ctrl_enter_alias``) are never
    overwritten — ``setdefault`` semantics.

    Returns the number of sequences whose mapping was newly installed.
    r   r'   r)   azr      NrF   Control0)r   [   \   ]   ^   _       r   r   mappingdictr	   r   c           	         |                                 D ]X\  }}| dk    rg n	d|  d| dg}t          |           D ]}|                    d| d| d           |D ]}|vr
||<   dz  YdS )u  Install both modifyOtherKeys (ESC[27;N;CP~) and CSI-u (ESC[CP;Nu)
        mappings for the given modifier and codepoint→key mapping.

        The tilde form is skipped for modifier 1 ("no modifier") — xterm
        never emits modifier-1 tilde sequences.
        r   [27;;rG   [r-   N)rJ   r   append)	r   r\   	codepointkey_valr<   rM   r=   r(   r;   s	          r   _install_pairedz:install_modify_other_keys_aliases.<locals>._install_paired  s     #*--// 	! 	!Iw!Q22-O-O-O9-O-O-O,PD%h// 8 86I666667777 ! !n,,*1N3'qLG!		! 	!r   rB   r[      r2               z[27uc                >    g | ]}t          |          D ]}d | d	S )r_   r-   )r   )r   r/   rM   s      r   r0   z5install_modify_other_keys_aliases.<locals>.<listcomp>q  sR       !!$$   	3   r       )rE      r[   )   rn   r[   )rE   rn   )rE   ro   r[   rn   
ABCDFHPQRSz[1;ra   zO)r   r2   rf   rg   rB   rh   ri   rj   r`   rG   i7  ./*-+=,)iA  iB  iC  iD  iE  iF  iG  iH  )
iI  iJ  iK  iL  iM  iN  iO  iP  iQ  iR  ro      Fi   i  i  i,  iS  iT  io  r-   )r   r   r\   r]   r	   r   )!r4   r(   r5   r*   r$   rangeordchrr8   getattrr6   BackTabControlHr7   ControlIr   strupdateLeftRightUpDownPageUpPageDownHomeEndInsertDeletelist
setdefaultIgnorerJ   r%   )r*   ctrl_key_mapchrawexistingdrc   re   alt_mapletterupper	shift_map
upper_charshift_alt_mapctrl_shift_mapctrl_alt_mapctrl_keycpr=   r/   trailerbase_seqrN   rM   numfunctional_mapncoderd   r(   r;   s                                @@r   !install_modify_other_keys_aliasesr      sX   rMMMMMM,,,,,,,   qq ')L CHHc#hhl++ ( ("t)nn!%%c**'L
 2YY B B%,T=Q==%A%ASXX\"" 2 / /	)d"##!%%c**&.L#G! ! ! ! ! ! !$ OA|$$$ !#GCHHc#hhl++ 0 0RBG{F+ K/ROAw !#ICHHc#hhl++ ( (b\\
"	"'	"r'OAy!!! ')M(*N%'LCHHc#hhl++ ; ;b\\
##B''rBw- 	; 	;B!%j 9M"#%-r"$(K#:R 		;
 OA}%%%OA~&&&OA|$$$OA|$$$ |  q"     
 n$$"&+N3qLG
 OA<]    
 OA[$-(k4=)[#    
 OA=k4=)     OA=M]	    " 1b\\ ! !# 	! 	!G12Q--G---<MG<M<MH $$X..C{qAvv$(():):):;;{"1~~ ! !..W..n,,*-N3'qLG	! , 		! 		!C-.UU)s))Q))))H $$X..C{"1~~ ! !*c**C***n,,*-N3'qLG	!		! )+N2YY + +$'FFuqy!!3s34=S     yDGyT]y$+{	     2r]] B B+24Q+A+AuB'((
 	U5%  !!
uUE""
#
#	$'	 uUE""
#
#	$5 5 	!!$4444'--// 
 
gdooon$$")N3qLGq>> 	 	C'$'''''C.((&-s#1		  $!###Ns    
c                     	 ddl m}  ddlm} n# t          $ r Y dS w xY wd}dD ]}|| vr|j        | |<   |dz  }|rt                       |S )u  Map terminal-emitted noise sequences to ``Keys.Ignore`` so they
    are consumed by the VT100 parser before they reach key bindings or
    the input buffer.

    Currently covers focus reports:
      - ``\x1b[I`` — terminal regained focus (focus in)
      - ``\x1b[O`` — terminal lost focus (focus out)

    Ghostty, iTerm2, and some xterm builds can emit these sequences when
    the user switches tabs / windows or when a multiplexer toggles focus
    tracking upstream. prompt_toolkit does not map these by default, so
    its parser falls back to literal key presses (ESC, ``[``, ``I``/``O``)
    and inserts ``[I``/``[O`` into the prompt buffer after the ESC byte
    is handled.

    Registering them as ``Keys.Ignore`` is parser-level — strictly
    cleaner than post-hoc regex stripping in the input sanitizer because
    the bytes never reach the buffer. ``setdefault`` is used so any user
    or downstream registration wins.

    Returns the number of sequences whose mapping was changed.
    r   r'   r)   )z[Iz[Or   )r4   r(   r5   r*   r$   r   r%   )r(   r*   r;   r=   s       r   "install_ignored_terminal_sequencesr     s    .MMMMMM,,,,,,,   qq G#  n$$"&+N3qLG $!###Nr?   N)r   r   r	   r
   )r	   r   )r	   r   )__doc__
__future__r   r   r   r   r%   r>   rC   rO   r   r   r   r   r   <module>r      s   	 	 # " " " " " & > > > >
B B B B
   $) ) ) )X$ $ $ $N* * * *Z| | | |~	$ $ $ $ $ $r   