Skip to content

Commit

Permalink
feat: Support top.
Browse files Browse the repository at this point in the history
1. Implemented `CSI d` (set cursor vertical absolute) command,
2. Correctly deals with `CSI m` with no arguments (means reset all styles),
3. Correctly recognizes `ESC ( <rest>` (select G0 charset) and discard it.

I don't think G0 charset selection will be needed in modern cases.

Fixed #26.
  • Loading branch information
TerryGeng committed Feb 5, 2024
1 parent 150d2af commit 8b11a1d
Showing 1 changed file with 45 additions and 0 deletions.
45 changes: 45 additions & 0 deletions termqt/terminal_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class State(Enum):
WAIT_FOR_BRAC_OR_CHAR = 1
# if receive a [, transfer to CSI_WAIT_FOR_MARKS
# if receive a ], transfer to OSC_WAIT_FOR_NEXT_ARG
# if receive a (, transfer to OSC_WAIT_FOR_ARG
# if receive a letter/digit, save to cmd buffer, transfer to ESC_COMPLETE
# otherwise return to WAIT_FOR_ESC

Expand Down Expand Up @@ -128,6 +129,13 @@ class State(Enum):
# otherwise return to WAIT_FOR_ESC

OSC_COMPLETE = 9
# once entered, process the input and return to WAIT_FOR_ESC

G0_WAIT_FOR_ARG = 10
# if receive a letter/number, save to cmd buffer, transfer to G0_COMPLETE

G0_COMPLETE = 11
# once entered, process the input and return to WAIT_FOR_ESC

def __init__(self, logger):
self.logger = logger
Expand All @@ -143,6 +151,7 @@ def __init__(self, logger):
}

self._csi_func = {
'd': self._csi_d,
'n': self._csi_n,
'n?': self._csi_n,
'm': self._csi_m,
Expand Down Expand Up @@ -193,6 +202,11 @@ def __init__(self, logger):
# pos_c: column
self.set_cursor_abs_position_cb = lambda pos_r, pos_c: None

# Cursor Vertical Position Absolute (VPA)
# Move cursor to row `pos_r` (begin from 0).
self.set_cursor_y_position_cb = lambda pos_r: None


# Cursor Position(relative position)
# set the position of the cursor
# offset_r: row (begin from 0)
Expand Down Expand Up @@ -273,6 +287,8 @@ def input(self, c: int):
self._enter_state(self.State.CSI_WAIT_FOR_MARKS)
elif c == 93: # ord(']')
self._enter_state(self.State.OSC_WAIT_FOR_NEXT_ARG)
elif c == 40: # ord('(')
self._enter_state(self.State.G0_WAIT_FOR_ARG)
elif 48 <= c <= 57 or \
65 <= c <= 90 or 97 <= c <= 122: # 0-9, A-Z, a-z
self._cmd = chr(c)
Expand Down Expand Up @@ -354,6 +370,16 @@ def input(self, c: int):
# this branch should never be reached
self.fail()

# === G0 ===
elif self._state == self.State.G0_WAIT_FOR_ARG:
self._args.append(chr(c))
self._enter_state(self.State.G0_COMPLETE)
return 1

elif self._state == self.State.G0_COMPLETE:
# this branch should never be reached
self.fail()

else:
raise ValueError(f"Unhandle state {self._state}")

Expand All @@ -372,6 +398,10 @@ def _enter_state(self, _state):
self._state = self.State.OSC_COMPLETE
self._process_osc_command()
self.reset()
elif _state == self.State.G0_COMPLETE:
self._state = self.State.G0_COMPLETE
pass # Not implemented
self.reset()
else:
self._state = _state

Expand Down Expand Up @@ -435,6 +465,9 @@ def _esc_m(self):

self.reverse_index_cb()

def _csi_d(self):
self.set_cursor_y_position_cb(self._get_args(0, default=1) - 1)

def _csi_n(self):
# DSR – Device Status Report
arg = self._get_args(0, default=0)
Expand Down Expand Up @@ -492,6 +525,12 @@ def _csi_m(self):
bold, underline, reverse = -1, -1, -1

i = 0

if len(self._args) == 0:
bold, underline, reverse = 0, 0, 0
color = DEFAULT_FG_COLOR
bg_color = DEFAULT_BG_COLOR

while i < len(self._args):
arg = self._get_args(i, default=0)
if 0 <= arg <= 29:
Expand Down Expand Up @@ -759,6 +798,7 @@ def _register_escape_callbacks(self):
ep.erase_line_cb = self.erase_line
ep.delete_line_cb = self.delete_line
ep.reverse_index_cb = lambda: self.set_cursor_rel_pos(0, -1, False)
ep.set_cursor_y_position_cb = self.set_cursor_y_pos
ep.set_cursor_abs_position_cb = self.set_cursor_on_screen_position
ep.set_cursor_rel_position_cb = self.set_cursor_rel_pos
ep.set_cursor_x_position_cb = self.set_cursor_x_pos
Expand Down Expand Up @@ -1324,6 +1364,11 @@ def set_cursor_x_pos(self, x: int):

self.set_cursor_position(x, y)

def set_cursor_y_pos(self, y):
pos_y = self._buffer_display_offset + y

self.set_cursor_position(self._cursor_position.x, pos_y)

def report_cursor_pos(self):
x = self._cursor_position.x + 1
y = self._cursor_position.y - self._buffer_display_offset + 1
Expand Down

0 comments on commit 8b11a1d

Please sign in to comment.