mirror of
https://github.com/asciinema/asciinema.git
synced 2025-12-16 11:48:13 +01:00
Implement terminal resize capture ("r" event)
This commit is contained in:
@@ -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 == "-":
|
||||||
|
|||||||
@@ -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 == "-":
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user