class _ScrollableWidget(_Widget):
- _history_idx: int
+ _history_idx_neg: int
def __init__(self, write: Callable[..., None], **kwargs) -> None:
super().__init__(**kwargs)
def __init__(self, wrap: Callable[[str], list[str]], **kwargs) -> None:
super().__init__(**kwargs)
self._wrap = wrap
- self._wrapped_idx = self._history_idx = -1
+ self._wrapped_idx_neg = self._history_idx_neg = -1
self._wrapped: list[tuple[Optional[int], str]] = []
- def _add_wrapped(self, idx_original, line) -> int:
+ def _add_wrapped(self, idx_pos_original, line) -> int:
wrapped_lines = self._wrap(line)
- self._wrapped += [(idx_original, line) for line in wrapped_lines]
+ self._wrapped += [(idx_pos_original, line) for line in wrapped_lines]
return len(wrapped_lines)
def set_geometry(self, sizes: _YX) -> None:
self._wrapped.clear()
self._wrapped += [(None, '')] * self._sizes.y
if self._history:
- for idx_history, line in enumerate(self._history):
- self._add_wrapped(idx_history, line)
+ for idx_pos_history, line in enumerate(self._history):
+ self._add_wrapped(idx_pos_history, line)
wrapped_lines_for_history_idx = [
t for t in self._wrapped
- if t[0] == len(self._history) + self._history_idx]
- idx_their_last = self._wrapped.index(
+ if t[0] == len(self._history) + self._history_idx_neg]
+ # ensure that of the full line identified by ._history_idx_neg,
+ # ._wrapped_idx_neg point to the lowest of its wrap parts
+ idx_pos_their_last = self._wrapped.index(
wrapped_lines_for_history_idx[-1])
- self._wrapped_idx = idx_their_last - len(self._wrapped)
+ self._wrapped_idx_neg = idx_pos_their_last - len(self._wrapped)
def append(self, to_append: str) -> None:
super().append(to_append)
self.taint()
- if self._history_idx < -1:
- self._history_idx -= 1
+ if self._history_idx_neg < -1:
+ self._history_idx_neg -= 1
if self._drawable:
n_wrapped_lines = self._add_wrapped(len(self._history)
- 1, to_append)
- if self._wrapped_idx < -1:
- self._wrapped_idx -= n_wrapped_lines
+ if self._wrapped_idx_neg < -1:
+ self._wrapped_idx_neg -= n_wrapped_lines
def _draw(self) -> None:
- start_idx = self._wrapped_idx - self._sizes.y + 1
- end_idx = self._wrapped_idx
- idx_bookmark = ([idx for idx, t in enumerate(self._wrapped)
- if t[0] == self._bookmark]+[0])[0]
- wrapped = (self._wrapped[:idx_bookmark+1]
+ start_idx_neg = self._wrapped_idx_neg - self._sizes.y + 1
+ end_idx_neg = self._wrapped_idx_neg
+ idx_pos_bookmark = ([idx_pos for idx_pos, t in enumerate(self._wrapped)
+ if t[0] == self._bookmark]+[0])[0]
+ wrapped = (self._wrapped[:idx_pos_bookmark+1]
+ [(0, '-'*self._sizes.x)]
- + self._wrapped[idx_bookmark+1:])
- to_write = [t[1] for t in wrapped[start_idx:end_idx]]
- if self._wrapped_idx < -1:
- scroll_info = f'vvv [{(-1) * self._wrapped_idx}] '
+ + self._wrapped[idx_pos_bookmark+1:])
+ to_write = [t[1] for t in wrapped[start_idx_neg:end_idx_neg]]
+ if self._wrapped_idx_neg < -1:
+ scroll_info = f'vvv [{(-1) * self._wrapped_idx_neg}] '
scroll_info += 'v' * (self._sizes.x - len(scroll_info))
to_write += [scroll_info]
else:
- to_write += [wrapped[self._wrapped_idx][1]]
+ to_write += [wrapped[self._wrapped_idx_neg][1]]
for i, line in enumerate(to_write):
self._write(line, i)
- hist_idx = self._wrapped[end_idx][0]
- self._last_read = max(self._last_read, hist_idx or 0)
+ hist_idx_pos = self._wrapped[end_idx_neg][0]
+ self._last_read = max(self._last_read, hist_idx_pos or 0)
def bookmark(self) -> None:
'Store to what most recent line we have (been) scrolled.'
super()._scroll(up)
if self._drawable:
if up:
- self._wrapped_idx = max(
+ self._wrapped_idx_neg = max(
self._sizes.y + 1 - len(self._wrapped),
- self._wrapped_idx - self._y_pgscroll)
+ self._wrapped_idx_neg - self._y_pgscroll)
else:
- self._wrapped_idx = min(
- -1, self._wrapped_idx + self._y_pgscroll)
- history_idx_to_wrapped_idx = self._wrapped[self._wrapped_idx][0]
- if history_idx_to_wrapped_idx is not None:
- self._history_idx = history_idx_to_wrapped_idx\
+ self._wrapped_idx_neg = min(
+ -1, self._wrapped_idx_neg + self._y_pgscroll)
+ hist_idx_to_wrapped_idx = self._wrapped[self._wrapped_idx_neg][0]
+ if hist_idx_to_wrapped_idx is not None:
+ self._history_idx_neg = hist_idx_to_wrapped_idx\
- len(self._history)
class PromptWidget(_ScrollableWidget):
'Manages/displays keyboard input field.'
- _history_idx: int = 0
+ _history_idx_neg: int = 0
_input_buffer_unsafe: str
_cursor_x: int
def _scroll(self, up: bool = True) -> None:
super()._scroll(up)
- if up and -(self._history_idx) < len(self._history):
- if self._history_idx == 0 and self._input_buffer:
+ if up and -(self._history_idx_neg) < len(self._history):
+ if self._history_idx_neg == 0 and self._input_buffer:
self._archive_prompt()
- self._history_idx -= 1
- self._history_idx -= 1
- self._reset_buffer(self._history[self._history_idx])
+ self._history_idx_neg -= 1
+ self._history_idx_neg -= 1
+ self._reset_buffer(self._history[self._history_idx_neg])
elif not up:
- if self._history_idx < 0:
- self._history_idx += 1
- if self._history_idx == 0:
+ if self._history_idx_neg < 0:
+ self._history_idx_neg += 1
+ if self._history_idx_neg == 0:
self._reset_buffer('')
else:
- self._reset_buffer(self._history[self._history_idx])
+ self._reset_buffer(self._history[self._history_idx_neg])
elif self._input_buffer:
self._archive_prompt()
self._input_buffer = (self._input_buffer[:self._cursor_x - 1]
+ to_insert
+ self._input_buffer[self._cursor_x - 1:])
- self._history_idx = 0
+ self._history_idx_neg = 0
def cmd__backspace(self) -> None:
'Truncate current content by one character, if possible.'
self._cursor_x -= 1
self._input_buffer = (self._input_buffer[:self._cursor_x]
+ self._input_buffer[self._cursor_x + 1:])
- self._history_idx = 0
+ self._history_idx_neg = 0
def cmd__move_cursor(self, direction: str) -> None:
'Move cursor one space into direction ("left" or "right") if possible.'