home · contact · privacy
Refactor prompt geometry calculations.
authorChristian Heller <c.heller@plomlompom.de>
Wed, 11 Jun 2025 13:46:53 +0000 (15:46 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Wed, 11 Jun 2025 13:46:53 +0000 (15:46 +0200)
ircplom.py

index 228027699b07db40171f8c3303c5e63f5d37e6dd..50a916aedfa1c8711810cae54997f33f104297db 100755 (executable)
@@ -542,12 +542,12 @@ class PromptWidget(ScrollableWidget):
     _width: int
     _prompt: str = PROMPT_TEMPLATE
     _history_idx = 0
+    _input_buffer: str
     _cursor_x: int
 
     def __init__(self, *args, **kwargs) -> None:
         super().__init__(*args, **kwargs)
-        self._clear()
-        self._input_buffer = ''
+        self._reset_buffer('')
 
     def set_geometry(self, measurements: YX) -> None:
         self._y, self._width = measurements
@@ -558,27 +558,25 @@ class PromptWidget(ScrollableWidget):
 
     def append(self, to_append: str) -> None:
         self._cursor_x += len(to_append)
-        self._input_buffer = (self._input_buffer[:self._cursor_x - 2]
+        self._input_buffer = (self._input_buffer[:self._cursor_x - 1]
                               + to_append
-                              + self._input_buffer[self._cursor_x - 2:])
+                              + self._input_buffer[self._cursor_x - 1:])
         self._history_idx = 0
         self.draw()
 
     def draw(self) -> None:
         prefix = self._prompt[:]
         content = self._input_buffer[:]
-        if self._cursor_x > len(self._input_buffer):
+        if self._cursor_x == len(self._input_buffer):
             content += ' '
-        half_width = self._width // 2
+        half_width = (self._width - len(prefix)) // 2
         offset = 0
         if len(prefix) + len(content) > self._width\
                 and self._cursor_x > half_width:
             prefix += PROMPT_ELL_IN
-            if self._cursor_x > len(content) - half_width:
-                offset = len(content) - self._width + len(prefix)
-            else:
-                offset = self._cursor_x - half_width + (len(prefix) // 2)
-        cursor_x_to_write = len(prefix) - 1 + self._cursor_x - offset
+            offset = min(len(prefix) + len(content) - self._width,
+                         self._cursor_x - half_width + len(PROMPT_ELL_IN))
+        cursor_x_to_write = len(prefix) + self._cursor_x - offset
         to_write = f'{prefix}{content[offset:]}'
         if len(to_write) > self._width:
             to_write = (to_write[:self._width - len(PROMPT_ELL_OUT)]
@@ -589,41 +587,36 @@ class PromptWidget(ScrollableWidget):
         self._write(to_write[cursor_x_to_write + 1:])
 
     def _scroll(self, up: bool = True) -> None:
-
-        def set_to_record_at_idx() -> None:
-            self._input_buffer = self._history[self._history_idx][:]
-            self._cursor_x = len(self._input_buffer) + 1
-
         if up and -(self._history_idx) < len(self._history):
             if self._history_idx == 0 and self._input_buffer:
                 self._history += [self._input_buffer[:]]
-                self._clear()
+                self._reset_buffer('')
                 self._history_idx -= 1
             self._history_idx -= 1
-            set_to_record_at_idx()
+            self._reset_buffer(self._history[self._history_idx])
         elif not up:
             if self._history_idx < 0:
                 self._history_idx += 1
                 if self._history_idx == 0:
-                    self._clear()
+                    self._reset_buffer('')
                 else:
-                    set_to_record_at_idx()
+                    self._reset_buffer(self._history[self._history_idx])
             elif self._input_buffer:
                 self._history += [self._input_buffer[:]]
-                self._clear()
+                self._reset_buffer('')
 
     def cmd__backspace(self) -> None:
         'Truncate current content by one character, if possible.'
-        if self._cursor_x > 1:
+        if self._cursor_x > 0:
             self._cursor_x -= 1
-            self._input_buffer = (self._input_buffer[:self._cursor_x - 1]
-                                  + self._input_buffer[self._cursor_x:])
+            self._input_buffer = (self._input_buffer[:self._cursor_x]
+                                  + self._input_buffer[self._cursor_x + 1:])
             self._history_idx = 0
             self.draw()
 
     def cmd__move_cursor(self, direction: str) -> None:
         'Move cursor one space into direction ("left" or "right") if possible.'
-        if direction == 'left' and self._cursor_x > 1:
+        if direction == 'left' and self._cursor_x > 0:
             self._cursor_x -= 1
         elif direction == 'right'\
                 and self._cursor_x <= len(self._input_buffer):
@@ -632,16 +625,16 @@ class PromptWidget(ScrollableWidget):
             return
         self.draw()
 
-    def _clear(self) -> None:
-        self._input_buffer = ''
-        self._cursor_x = len(self._input_buffer) + 1
+    def _reset_buffer(self, content: str) -> None:
+        self._input_buffer = content
+        self._cursor_x = len(self._input_buffer)
 
     def enter(self) -> str:
         'Return current content while also clearing and then redrawing.'
         to_return = self._input_buffer[:]
         if to_return:
             self._history += [to_return]
-            self._clear()
+            self._reset_buffer('')
             self.draw()
         return to_return