Changed code to support older Python versions
This commit is contained in:
parent
eb92d2d36f
commit
582458cdd0
5027 changed files with 794942 additions and 4 deletions
132
venv/lib/python3.11/site-packages/rich_toolkit/_input_handler.py
Normal file
132
venv/lib/python3.11/site-packages/rich_toolkit/_input_handler.py
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
"""Unified input handler for all platforms."""
|
||||
|
||||
import sys
|
||||
import unicodedata
|
||||
|
||||
|
||||
class TextInputHandler:
|
||||
"""Input handler with platform-specific key code support."""
|
||||
|
||||
# Platform-specific key codes
|
||||
if sys.platform == "win32":
|
||||
# Windows uses \xe0 prefix for special keys when using msvcrt.getwch
|
||||
DOWN_KEY = "\xe0P" # Down arrow
|
||||
UP_KEY = "\xe0H" # Up arrow
|
||||
LEFT_KEY = "\xe0K" # Left arrow
|
||||
RIGHT_KEY = "\xe0M" # Right arrow
|
||||
DELETE_KEY = "\xe0S" # Delete key
|
||||
BACKSPACE_KEY = "\x08" # Backspace
|
||||
TAB_KEY = "\t"
|
||||
SHIFT_TAB_KEY = "\x00\x0f" # Shift+Tab
|
||||
ENTER_KEY = "\r"
|
||||
|
||||
# Alternative codes that might be sent
|
||||
ALT_BACKSPACE = "\x7f"
|
||||
ALT_DELETE = "\x00S"
|
||||
else:
|
||||
# Unix/Linux key codes (ANSI escape sequences)
|
||||
DOWN_KEY = "\x1b[B"
|
||||
UP_KEY = "\x1b[A"
|
||||
LEFT_KEY = "\x1b[D"
|
||||
RIGHT_KEY = "\x1b[C"
|
||||
BACKSPACE_KEY = "\x7f"
|
||||
DELETE_KEY = "\x1b[3~"
|
||||
TAB_KEY = "\t"
|
||||
SHIFT_TAB_KEY = "\x1b[Z"
|
||||
ENTER_KEY = "\r"
|
||||
|
||||
# Alternative codes
|
||||
ALT_BACKSPACE = "\x08"
|
||||
ALT_DELETE = None
|
||||
|
||||
def __init__(self):
|
||||
self.text = ""
|
||||
self._cursor_index = 0 # Character index in the text string
|
||||
|
||||
@property
|
||||
def cursor_left(self) -> int:
|
||||
"""Visual cursor position in display columns."""
|
||||
return self._get_text_width(self.text[: self._cursor_index])
|
||||
|
||||
@staticmethod
|
||||
def _get_char_width(char: str) -> int:
|
||||
"""Get the display width of a character (1 for normal, 2 for CJK/fullwidth)."""
|
||||
if not char:
|
||||
return 0
|
||||
|
||||
# Check East Asian Width property
|
||||
east_asian_width = unicodedata.east_asian_width(char)
|
||||
# F (Fullwidth) and W (Wide) characters take 2 columns
|
||||
if east_asian_width in ("F", "W"):
|
||||
return 2
|
||||
# A (Ambiguous) characters are typically 2 columns in CJK contexts
|
||||
# but for simplicity we'll treat them as 1 (can be made configurable)
|
||||
return 1
|
||||
|
||||
def _get_text_width(self, text: str) -> int:
|
||||
"""Get the total display width of a text string."""
|
||||
return sum(self._get_char_width(char) for char in text)
|
||||
|
||||
def _move_cursor_left(self) -> None:
|
||||
self._cursor_index = max(0, self._cursor_index - 1)
|
||||
|
||||
def _move_cursor_right(self) -> None:
|
||||
self._cursor_index = min(len(self.text), self._cursor_index + 1)
|
||||
|
||||
def _insert_char(self, char: str) -> None:
|
||||
self.text = (
|
||||
self.text[: self._cursor_index] + char + self.text[self._cursor_index :]
|
||||
)
|
||||
self._cursor_index += 1
|
||||
|
||||
def _delete_char(self) -> None:
|
||||
"""Delete character before cursor (backspace)."""
|
||||
if self._cursor_index == 0:
|
||||
return
|
||||
|
||||
self.text = (
|
||||
self.text[: self._cursor_index - 1] + self.text[self._cursor_index :]
|
||||
)
|
||||
self._cursor_index -= 1
|
||||
|
||||
def _delete_forward(self) -> None:
|
||||
"""Delete character at cursor (delete key)."""
|
||||
if self._cursor_index >= len(self.text):
|
||||
return
|
||||
|
||||
self.text = (
|
||||
self.text[: self._cursor_index] + self.text[self._cursor_index + 1 :]
|
||||
)
|
||||
|
||||
def handle_key(self, key: str) -> None:
|
||||
# Handle backspace (both possible codes)
|
||||
if key == self.BACKSPACE_KEY or (
|
||||
self.ALT_BACKSPACE and key == self.ALT_BACKSPACE
|
||||
):
|
||||
self._delete_char()
|
||||
# Handle delete key
|
||||
elif key == self.DELETE_KEY or (self.ALT_DELETE and key == self.ALT_DELETE):
|
||||
self._delete_forward()
|
||||
elif key == self.LEFT_KEY:
|
||||
self._move_cursor_left()
|
||||
elif key == self.RIGHT_KEY:
|
||||
self._move_cursor_right()
|
||||
elif key in (
|
||||
self.UP_KEY,
|
||||
self.DOWN_KEY,
|
||||
self.ENTER_KEY,
|
||||
self.SHIFT_TAB_KEY,
|
||||
self.TAB_KEY,
|
||||
):
|
||||
pass
|
||||
else:
|
||||
# Handle regular text input
|
||||
# Special keys on Windows start with \x00 or \xe0
|
||||
if sys.platform == "win32" and key and key[0] in ("\x00", "\xe0"):
|
||||
# Skip special key sequences
|
||||
return
|
||||
|
||||
# Even if we call this handle_key, in some cases we might receive
|
||||
# multiple keys at once (e.g., during paste operations)
|
||||
for char in key:
|
||||
self._insert_char(char)
|
||||
Loading…
Add table
Add a link
Reference in a new issue