+
    Rj                         R t ^ RIt^ RItR t]! 4       tR tRR.RR.RR.RR.R	R	.R
R
.RR.RR.RR.RR.RR.RR./tRtR tR t	Rs
R tR tR tR tR tR tR tR# )!uk  sshj.config — user settings: default sort mode + keymap bindings.

Lives in the XDG config home (``~/.config/sshj/config.json``), NOT the state
dir (state is runtime data; config is user intent). Optional — every field
has a default, so a missing/invalid file degrades to the defaults.

Shape::

    {
      "sort": "last",                 # "last" | "last_success" | "alpha"
      "keymap": { "down": ["down", "j"], "up": ["up", "k"] }
    }

The config's ``keymap`` keys are **symbols** (``"up"``, ``"right"``,
``"tab"``, ``"ctrl+r"``, …) for readability; single letters are their own
symbol. Symbols resolve to the REAL terminal keys the dispatch compares
against (``ui.KEYMAP``'s constants) via ``resolve_key`` / ``resolved_keymap``
— so the config layer and the dispatch layer can never drift.

``keymap`` merges with the default (the default keys are kept; your entries
are ADDED, so binding ``"j"`` to ``down`` keeps the down arrow too — that is
the "alternate key" mechanism). **No single letter is bound by default**:
every printable character is free for the search filter. Opting a single
letter into a binding is explicit and yours alone ("if someone does that they
know what they did") — and the input-mode rule in run.py makes a bound
single-char key *type* while the input field has content.

``SSHJ_CONFIG_FILE`` overrides the path (tests / exotic installs).
Nc                     \         P                  P                  R 4      ;'       gf    \         P                  P	                  \         P                  P                  R4      ;'       g     \         P                  P                  R4      RR4      # )SSHJ_CONFIG_FILEXDG_CONFIG_HOMEz	~/.configsshjzconfig.json)osenvirongetpathjoin
expanduser     src/sshj/config.py_config_pathr   "   s`     ::>>,-  


()LLRWW-?-?-L2 r   updownpage_uppguppage_dnpgdnhomeendconnectenterstage_aliasrightstage_addresstableftquitescsortzctrl+rbsc                      \        4       p \        P                  4        F  w  rV P                  V4       K  	  V P	                  \
        4       V # N)setDEFAULT_KEYMAPitemsupdateaddBACK_KEY)symsakss      r   _known_symbolsr.   G   s:    5D%%'B (HHXKr   c                N    \        V 4      ^8H  ;'       d    V P                  4       # )u   A config symbol / key is a "single-char binding" iff it is exactly
one printable character (j, k, a, space, /, …). Such bindings are what
the input-mode rule suppresses while the field has content.)lenisprintable)keys   &r   is_single_charr3   O   s!     s8q=..S__..r   c                     \         fm   ^RIHp  / p\        P	                  4        F7  w  r#V^ ,          pV P
                   F  w  rVrxWr8X  g   K  Vf   K  WQV&    K5  	  K9  	  V P                  V\        &   Vs \         # )u  symbol -> REAL key, built ONCE from ui.KEYMAP (the single source of
truth) so a default-key spelling always resolves to the exact constant
the dispatch compares against — robust no matter what bytes K_UP /
K_TAB / … actually are. ``"bs"`` maps to the term's backspace key.)ui)_SYMBOL_REAL r5   r&   r'   KEYMAPK_BSr*   )	r5   mactr+   symk_aliasr,   _lbls	            r   _symbol_realr@   Y   sp     '--/ICq'C&(ii"18cF '0 0 gg(r   c                  a  \        4       pS V9   d
   VS ,          # \        S 4      '       d   S # \        ;QJ d-    V 3R lVP                  4        4       F  '       g   K   RM"	  RM! V 3R lVP                  4        4       4      '       d   S # R# )u  A config symbol (or a single-char literal) -> the REAL key the
dispatch compares against. Single chars resolve to themselves (they are
their own key). Anything that is neither a known default-key spelling
nor a single printable char resolves to None — a typo in the config is
then DROPPED (a dead binding is worse than a missing one), not honored.
A REAL key that happens to be passed in is returned as-is (idempotent
for keys already in the symbol map's values).c              3   .   <"   T F
  pSV8H  x  K  	  R # 5ir$   r   ).0vr<   s   & r   	<genexpr>resolve_key.<locals>.<genexpr>z   s     
(Z3!8Zs   TFN)r@   r3   anyvalues)r<   r:   s   f r   resolve_keyrI   m   sa     	A
axvc

s
(QXXZ
(sss
(QXXZ
(((
r   c                 r    \         P                  4        U Uu/ uF  w  rV \        V4      bK  	  upp # u upp i )u   The default keymap as SYMBOLS (action -> [symbols]) — a copy, so a
caller can mutate it (tests) without touching the module global.)r&   r'   list)r,   r-   s     r   default_keymaprL      s1     &4%9%9%;<%;EAAtBxK%;<<<s   3c                    / pV P                  4        F6  w  r#. pV F%  p\        V4      pVf   K  VP                  V4       K'  	  WAV&   K8  	  V# )zaction -> [REAL keys], over a (symbol) keymap, every key resolved via
``resolve_key``. Unresolvable (typo) symbols are dropped; single chars
pass through as the literal the dispatch will match.)r'   rI   append)kmapoutr,   r-   realr=   rs   &      r   resolved_keymaprS      sS     CAAA}A  A  Jr   c                V    / pV P                  4        F  w  r#V F  pW!V&   K	  	  K  	  V# )u   key -> action over a (REAL) keymap. On a conflicting binding the
action that appears LATER wins (deterministic; a single letter the user
bound to two actions loses to the later action — document in help).)r'   )rO   r:   r,   r-   r=   s   &    r   key_action_maprU      s3     	AAaD   Hr   c                       \        \        4       4      ;_uu_ 4       p \        P                  ! V 4      uuR R R 4       #   + '       g   i     R # ; i  \         d    / u # i ; ir$   )openr   jsonload	Exception)fs    r   _loadr\      sC    ,.!!Q99Q< "!!! 	s+   A >
A A		A A A"!A"c            
        \        4       p V P                  RR4      pV\        9  d   Rp\        4       pV P                  R4      ;'       g    / P	                  4        F  w  r4V\
        9  d   K  \        V\        4      '       d   V.p\        V\        4      '       g   KC  \        W#,          4      pY#;;,          V Uu. uF/  pWe9  g   K  V\        4       9   g   \        V4      '       g   K-  VNK1  	  up,          uu&   K  	  RVRV/# u upi )u   Return {'sort': <mode>, 'keymap': {action: [symbol-keys]}} — the
defaults merged with any user config (symbols; resolve with
resolved_keymap before dispatch).r!   lastkeymap)r\   r   
SORT_MODESrL   r'   r&   
isinstancestrrK   r%   r.   r3   )rawr!   r_   r,   r-   seenr=   s          r   load_configre      s     'C7766"D:F''(#))r002N"b#B"d##69~	 CA ,-1A,A/=a/@ a C 	C	 3 D(F++Cs   >D	D	-D	)r^   last_successalpha)__doc__rX   r   r   CONFIG_FILEr`   r&   r*   r.   r3   r6   r@   rI   rL   rS   rU   r\   re   r   r   r   <module>rj      s   :  	 n.
 	dV
fXfXfX
fX	eWgYgYeW
fX
eW
hZ  
/ ($=,r   