Skip to content

Commit

Permalink
Merge pull request #565 from asciinema/resize-events
Browse files Browse the repository at this point in the history
Terminal resize capture
  • Loading branch information
ku1ik committed Aug 17, 2023
2 parents 994a071 + a9dc2e5 commit a0cc9cb
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 7 deletions.
7 changes: 5 additions & 2 deletions asciinema/asciicast/raw.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import sys
from os import path
from typing import Any, Callable, Optional
from typing import Any, Callable, Optional, Tuple

from ..file_writer import file_writer

Expand Down Expand Up @@ -44,13 +44,16 @@ def __enter__(self) -> Any:
def write_stdout(self, _ts: float, data: Any) -> None:
self._write(data)

# pylint: disable=no-self-use
def write_stdin(self, ts: float, data: Any) -> None:
pass

def write_marker(self, ts: float) -> None:
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
def _open_file(self) -> None:
if self.path == "-":
Expand Down
5 changes: 5 additions & 0 deletions asciinema/asciicast/v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
List,
Optional,
TextIO,
Tuple,
Union,
)

Expand Down Expand Up @@ -148,6 +149,10 @@ def write_stdin(self, ts: float, data: Union[str, bytes]) -> None:
def write_marker(self, ts: float) -> None:
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
def _open_file(self) -> None:
if self.path == "-":
Expand Down
14 changes: 10 additions & 4 deletions asciinema/pty_.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,14 @@ def record(
add_marker_key = key_bindings.get("add_marker")
input_data = bytes()

def set_pty_size() -> None:
cols, rows = get_tty_size()
def handle_resize() -> None:
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])
fcntl.ioctl(pty_fd, termios.TIOCSWINSZ, buf)

Expand Down Expand Up @@ -149,7 +155,7 @@ def copy(signal_fd: int) -> None: # pylint: disable=too-many-branches
if sig in EXIT_SIGNALS:
crfds.remove(signal_fd)
if sig == signal.SIGWINCH:
set_pty_size()
handle_resize()

if pty_fd in wfds:
n = os.write(pty_fd, input_data)
Expand All @@ -164,7 +170,7 @@ def copy(signal_fd: int) -> None: # pylint: disable=too-many-branches
fcntl.fcntl(pty_fd, fcntl.F_SETFL, flags)

start_time = time.perf_counter()
set_pty_size()
set_pty_size(get_tty_size())

with SignalFD(EXIT_SIGNALS + [signal.SIGWINCH]) as sig_fd:
with raw(tty_stdin_fd):
Expand Down
5 changes: 5 additions & 0 deletions asciinema/recorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ def write_stdout(self, ts: float, data: Any) -> None:
def write_marker(self, ts: float) -> 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:
try:
with self.writer as w:
Expand All @@ -148,6 +151,8 @@ def run(self) -> None:
w.write_stdin(self.time_offset + ts, data)
elif etype == "m":
w.write_marker(self.time_offset + ts)
elif etype == "r":
w.write_resize(self.time_offset + ts, data)
except IOError:
for event in iter(self.queue.get, None):
pass
Expand Down
10 changes: 9 additions & 1 deletion doc/asciicast-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Example file:
[1.001376, "o", "That was ok\rThis is better."]
[1.500000, "m", ""]
[2.143733, "o", "Now... "]
[4.050000, "r", "80x24"]
[6.541828, "o", "Bye!"]
```

Expand Down Expand Up @@ -115,7 +116,7 @@ Where:

* `time` (float) - indicates when this event happened, represented as the number
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
type.

Expand Down Expand Up @@ -176,6 +177,13 @@ the user to resume.
`event-data` can be used to annotate a marker. Annotations may be used to e.g.
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

Version 2 of asciicast file format solves several problems which couldn't be
Expand Down

0 comments on commit a0cc9cb

Please sign in to comment.