jwlodek / py_cui

A python library for intuitively creating CUI/TUI interfaces with widgets, inspired by gocui.
https://jwlodek.github.io/py_cui-docs
BSD 3-Clause "New" or "Revised" License
752 stars 42 forks source link

HOME and END in TextBoxPopup places cursor outside of popup box #180

Closed pkazmier closed 1 year ago

pkazmier commented 2 years ago

Describe the bug show_text_box_popup does not properly position cursor when HOME and END keys are pressed. Instead of positioning at the start of the popup input box, HOME sends the cursor to the start of the line (left edge of terminal). END positions the cursor offset from the start of the line instead of the start of the popup box.

To Reproduce Steps to reproduce the behavior:

  1. Open a popup text box.
  2. Enter text.
  3. Press HOME key and press END key.

Expected behavior HOME and END should position the cursor within the bounding box of the popup.

Root Cause Root cause is that _initial_cursor position of the TextBoxImplementation is always set to 0.

https://github.com/jwlodek/py_cui/blob/f1173ca3ad93683dcbbed886260940375272fc8a/py_cui/ui.py#L485

As a workaround, I have to use this hack:

# TODO Workaround until upstream py_cui fixes bug
root._popup._initial_cursor = root._popup.get_start_position()[0] + root._popup.get_padding()[0] + 2

I believe the fix for this is modifying update_height_width of TextBoxPopup:

    def update_height_width(self) -> None:
        """Need to update all cursor positions on resize
        """

        Popup.update_height_width(self)
        padx, pady              = self.get_padding()
        start_x, start_y        = self.get_start_position()
        height, width           = self.get_absolute_dimensions()
        self._cursor_text_pos   = 0
        self._cursor_x          = start_x + 2 + padx
        ###################################
        self._initial_cursor = self._cursor_x
        ###################################
        self._cursor_max_left   = self._cursor_x
        self._cursor_max_right  = start_x + width - 1 - pady
        self._cursor_y          = start_y + int(height / 2) + 1
        self._viewport_width    = self._cursor_max_right - self._cursor_max_left

Because the _jump_to_start and _jump_to_end methods in TextBoxImplemenation use the _initial_cursor position to place the cursor, which is currently always set to 0 thus causing the issue.

https://github.com/jwlodek/py_cui/blob/f1173ca3ad93683dcbbed886260940375272fc8a/py_cui/ui.py#L625-L638

*Environment:*

jwlodek commented 1 year ago

Good catch! Reproduced the issue with the popups example. Applied your fix and it is now working:

https://github.com/jwlodek/py_cui/pull/178/commits/d5534cbaa7c1687bd5effafdd6cd13ebd2620175