Implement terminal resize capture ("r" event)

This commit is contained in:
Marcin Kulik
2023-08-14 16:38:10 +02:00
parent ff14e5b5be
commit a9dc2e5396
5 changed files with 34 additions and 7 deletions

View File

@@ -1,7 +1,7 @@
import os import os
import sys import sys
from os import path from os import path
from typing import Any, Callable, Optional from typing import Any, Callable, Optional, Tuple
from ..file_writer import file_writer from ..file_writer import file_writer
@@ -44,13 +44,16 @@ class writer(file_writer):
def write_stdout(self, _ts: float, data: Any) -> None: def write_stdout(self, _ts: float, data: Any) -> None:
self._write(data) self._write(data)
# pylint: disable=no-self-use
def write_stdin(self, ts: float, data: Any) -> None: def write_stdin(self, ts: float, data: Any) -> None:
pass pass
def write_marker(self, ts: float) -> None: def write_marker(self, ts: float) -> None:
pass pass
def write_resize(self, ts: float, size: Tuple[int, int]) -> None:
cols, rows = size
self._write(f"\x1b[8;{rows};{cols}t".encode("utf-8"))
# pylint: disable=consider-using-with # pylint: disable=consider-using-with
def _open_file(self) -> None: def _open_file(self) -> None:
if self.path == "-": if self.path == "-":

View File

@@ -12,6 +12,7 @@ from typing import (
List, List,
Optional, Optional,
TextIO, TextIO,
Tuple,
Union, Union,
) )
@@ -148,6 +149,10 @@ class writer(file_writer):
def write_marker(self, ts: float) -> None: def write_marker(self, ts: float) -> None:
self.__write_event(ts, "m", "") self.__write_event(ts, "m", "")
def write_resize(self, ts: float, size: Tuple[int, int]) -> None:
cols, rows = size
self.__write_event(ts, "r", f"{cols}x{rows}")
# pylint: disable=consider-using-with # pylint: disable=consider-using-with
def _open_file(self) -> None: def _open_file(self) -> None:
if self.path == "-": if self.path == "-":

View File

@@ -41,8 +41,14 @@ def record(
add_marker_key = key_bindings.get("add_marker") add_marker_key = key_bindings.get("add_marker")
input_data = bytes() input_data = bytes()
def set_pty_size() -> None: def handle_resize() -> None:
cols, rows = get_tty_size() size = get_tty_size()
set_pty_size(size)
assert start_time is not None
writer.write_resize(time.perf_counter() - start_time, size)
def set_pty_size(size: Tuple[int, int]) -> None:
cols, rows = size
buf = array.array("h", [rows, cols, 0, 0]) buf = array.array("h", [rows, cols, 0, 0])
fcntl.ioctl(pty_fd, termios.TIOCSWINSZ, buf) fcntl.ioctl(pty_fd, termios.TIOCSWINSZ, buf)
@@ -149,7 +155,7 @@ def record(
if sig in EXIT_SIGNALS: if sig in EXIT_SIGNALS:
crfds.remove(signal_fd) crfds.remove(signal_fd)
if sig == signal.SIGWINCH: if sig == signal.SIGWINCH:
set_pty_size() handle_resize()
if pty_fd in wfds: if pty_fd in wfds:
n = os.write(pty_fd, input_data) n = os.write(pty_fd, input_data)
@@ -164,7 +170,7 @@ def record(
fcntl.fcntl(pty_fd, fcntl.F_SETFL, flags) fcntl.fcntl(pty_fd, fcntl.F_SETFL, flags)
start_time = time.perf_counter() start_time = time.perf_counter()
set_pty_size() set_pty_size(get_tty_size())
with SignalFD(EXIT_SIGNALS + [signal.SIGWINCH]) as sig_fd: with SignalFD(EXIT_SIGNALS + [signal.SIGWINCH]) as sig_fd:
with raw(tty_stdin_fd): with raw(tty_stdin_fd):

View File

@@ -134,6 +134,9 @@ class async_writer(async_worker):
def write_marker(self, ts: float) -> None: def write_marker(self, ts: float) -> None:
self.enqueue([ts, "m", None]) self.enqueue([ts, "m", None])
def write_resize(self, ts: float, size: Tuple[int, int]) -> None:
self.enqueue([ts, "r", size])
def run(self) -> None: def run(self) -> None:
try: try:
with self.writer as w: with self.writer as w:
@@ -148,6 +151,8 @@ class async_writer(async_worker):
w.write_stdin(self.time_offset + ts, data) w.write_stdin(self.time_offset + ts, data)
elif etype == "m": elif etype == "m":
w.write_marker(self.time_offset + ts) w.write_marker(self.time_offset + ts)
elif etype == "r":
w.write_resize(self.time_offset + ts, data)
except IOError: except IOError:
for event in iter(self.queue.get, None): for event in iter(self.queue.get, None):
pass pass

View File

@@ -15,6 +15,7 @@ Example file:
[1.001376, "o", "That was ok\rThis is better."] [1.001376, "o", "That was ok\rThis is better."]
[1.500000, "m", ""] [1.500000, "m", ""]
[2.143733, "o", "Now... "] [2.143733, "o", "Now... "]
[4.050000, "r", "80x24"]
[6.541828, "o", "Bye!"] [6.541828, "o", "Bye!"]
``` ```
@@ -115,7 +116,7 @@ Where:
* `time` (float) - indicates when this event happened, represented as the number * `time` (float) - indicates when this event happened, represented as the number
of seconds since the beginning of the recording session, of seconds since the beginning of the recording session,
* `event-type` (string) - one of: `"o"`, `"i"`, `"m"` * `event-type` (string) - one of: `"o"`, `"i"`, `"m"`, `"r"`
* `event-data` (any) - event specific data, described separately for each event * `event-data` (any) - event specific data, described separately for each event
type. type.
@@ -176,6 +177,13 @@ the user to resume.
`event-data` can be used to annotate a marker. Annotations may be used to e.g. `event-data` can be used to annotate a marker. Annotations may be used to e.g.
show a list of named "chapters". show a list of named "chapters".
#### "r" - resize
Event of type `"r"` represents terminal resize.
`event-data` contains new terminal size (columns + rows) formatted as
`"{COLS}x{ROWS}"`, e.g. `"80x24"`.
## Notes on compatibility ## Notes on compatibility
Version 2 of asciicast file format solves several problems which couldn't be Version 2 of asciicast file format solves several problems which couldn't be