Rename breakpoints to markers

This commit is contained in:
Marcin Kulik
2023-05-05 10:55:00 +02:00
parent 719bd9de55
commit 2902529a45
12 changed files with 62 additions and 65 deletions

View File

@@ -296,7 +296,7 @@ Available options:
- `-i, --idle-time-limit=<sec>` - Limit replayed terminal inactivity to max `<sec>` seconds - `-i, --idle-time-limit=<sec>` - Limit replayed terminal inactivity to max `<sec>` seconds
- `-s, --speed=<factor>` - Playback speed (can be fractional) - `-s, --speed=<factor>` - Playback speed (can be fractional)
- `-l, --loop` - Play in a loop - `-l, --loop` - Play in a loop
- `-b, --breakpoints` - Automatically pause on [breakpoints](#breakpoints) - `-m, --pause-on-markers` - Automatically pause on [markers](#markers)
- `--stream=<stream>` - Select stream to play (see below) - `--stream=<stream>` - Select stream to play (see below)
- `--out-fmt=<format>` - Select output format (see below) - `--out-fmt=<format>` - Select output format (see below)
@@ -362,31 +362,28 @@ happen in any order.
> asciinema versions prior to 2.0 confusingly referred to install ID as "API > asciinema versions prior to 2.0 confusingly referred to install ID as "API
> token". > token".
## Breakpoints ## Markers
Breakpoints are markers that you can set in a recording to pause the playback at Markers allow marking specific time locations in a recording, which can be used
a specific point. for navigation, as well as for automatic pausing of the playback.
When a breakpoint is reached, the playback automatically pauses and can be Markers can be added to a recording in several ways:
resumed by pressing space bar key. The playback continues until next breakpoint
is encountered.
To enable auto-pause-on-breakpoint behaviour when replaying with `asciinema - while you are recording, by pressing a configured hotkey, see [add_marker_key
play` use `-b`/`--breakpoints` option. It's off by default. config option](#configuration-file)
- for existing recording, by inserting marker events (`"m"`) in the asciicast
file, see [marker event](doc/asciicast-v2.md#m---marker)
Breakpoints can be added to a recording in several ways: When replaying a recording with `asciinema play` you can enable
auto-pause-on-marker behaviour with `-m`/`--pause-on-markers` option (it's off
by default). When a marker is encountered, the playback automatically pauses and
can be resumed by pressing space bar key. The playback continues until next
marker is encountered. You can also fast-forward to the next marker by pressing
`]` key (when paused).
- during recording session, by pressing a configured hotkey, see Markers can be useful in e.g. live demos: you can create a recording with
[add_breakpoint_key config option](#configuration-file) markers, then play it back during presentation, and have it stop wherever you
- for existing recording, by inserting breakpoint events (`"b"`) in the want to explain terminal contents in more detail.
asciicast file, see [breakpoint event](doc/asciicast-v2.md#b---breakpoint)
When replaying a recording with `asciinema play` you can fast-forward to the
next breakpoint by pressing `]` key (when paused).
Breakpoints can be useful in e.g. live demos: you can create a recording with
breakpoints, then play it back during presentation, and have it stop wherever
you want to explain terminal contents in more detail.
## Hosting the recordings on the web ## Hosting the recordings on the web
@@ -446,8 +443,8 @@ quiet = true
; default: C-\ (control + backslash) ; default: C-\ (control + backslash)
pause_key = C-p pause_key = C-p
; Define hotkey for adding a breakpoint, default: none ; Define hotkey for adding a marker, default: none
add_breakpoint_key = C-b add_marker_key = C-x
; Define hotkey prefix key - when defined other recording hotkeys must ; Define hotkey prefix key - when defined other recording hotkeys must
; be preceeded by it, default: no prefix ; be preceeded by it, default: no prefix
@@ -469,9 +466,9 @@ pause_key = p
; default: . (dot) ; default: . (dot)
step_key = s step_key = s
; Define hotkey for jumping to the next breakpoint, ; Define hotkey for jumping to the next marker,
; default: ] ; default: ]
next_breakpoint_key = b next_marker_key = m
[notifications] [notifications]
; Desktop notifications are displayed on certain occasions, e.g. when ; Desktop notifications are displayed on certain occasions, e.g. when

View File

@@ -197,9 +197,9 @@ For help on a specific command run:
default=False, default=False,
) )
parser_play.add_argument( parser_play.add_argument(
"-b", "-m",
"--breakpoints", "--pause-on-markers",
help="automatically pause on breakpoints", help="automatically pause on markers",
action="store_true", action="store_true",
default=False, default=False,
) )

View File

@@ -33,7 +33,7 @@ class writer(file_writer):
def write_stdin(self, ts: float, data: Any) -> None: def write_stdin(self, ts: float, data: Any) -> None:
pass pass
def write_breakpoint(self, ts: float) -> None: def write_marker(self, ts: float) -> None:
pass pass
# pylint: disable=consider-using-with # pylint: disable=consider-using-with

View File

@@ -145,8 +145,8 @@ class writer(file_writer):
data = self.stdin_decoder.decode(data) data = self.stdin_decoder.decode(data)
self.__write_event(ts, "i", data) self.__write_event(ts, "i", data)
def write_breakpoint(self, ts: float) -> None: def write_marker(self, ts: float) -> None:
self.__write_event(ts, "b", "") self.__write_event(ts, "m", "")
# pylint: disable=consider-using-with # pylint: disable=consider-using-with
def _open_file(self) -> None: def _open_file(self) -> None:

View File

@@ -21,12 +21,12 @@ class PlayCommand(Command):
self.loop = args.loop self.loop = args.loop
self.out_fmt = args.out_fmt self.out_fmt = args.out_fmt
self.stream = args.stream self.stream = args.stream
self.breakpoints = args.breakpoints self.pause_on_markers = args.pause_on_markers
self.player = player if player is not None else Player() self.player = player if player is not None else Player()
self.key_bindings = { self.key_bindings = {
"pause": config.play_pause_key, "pause": config.play_pause_key,
"step": config.play_step_key, "step": config.play_step_key,
"next_breakpoint": config.play_next_breakpoint_key, "next_marker": config.play_next_marker_key,
} }
def execute(self) -> int: def execute(self) -> int:
@@ -48,7 +48,7 @@ class PlayCommand(Command):
key_bindings=self.key_bindings, key_bindings=self.key_bindings,
out_fmt=self.out_fmt, out_fmt=self.out_fmt,
stream=self.stream, stream=self.stream,
pause_on_breakpoints=self.breakpoints, pause_on_markers=self.pause_on_markers,
) )
except asciicast.LoadError as e: except asciicast.LoadError as e:

View File

@@ -34,7 +34,7 @@ class RecordCommand(Command): # pylint: disable=too-many-instance-attributes
self.key_bindings = { self.key_bindings = {
"prefix": config.record_prefix_key, "prefix": config.record_prefix_key,
"pause": config.record_pause_key, "pause": config.record_pause_key,
"add_breakpoint": config.record_add_breakpoint_key, "add_marker": config.record_add_marker_key,
} }
# pylint: disable=too-many-branches # pylint: disable=too-many-branches

View File

@@ -137,8 +137,8 @@ class Config:
return self.__get_key("record", "pause", "C-\\") return self.__get_key("record", "pause", "C-\\")
@property @property
def record_add_breakpoint_key(self) -> Any: def record_add_marker_key(self) -> Any:
return self.__get_key("record", "add_breakpoint") return self.__get_key("record", "add_marker")
@property @property
def play_idle_time_limit(self) -> Optional[float]: def play_idle_time_limit(self) -> Optional[float]:
@@ -162,8 +162,8 @@ class Config:
return self.__get_key("play", "step", ".") return self.__get_key("play", "step", ".")
@property @property
def play_next_breakpoint_key(self) -> Any: def play_next_marker_key(self) -> Any:
return self.__get_key("play", "next_breakpoint", "]") return self.__get_key("play", "next_marker", "]")
@property @property
def notifications_enabled(self) -> bool: def notifications_enabled(self) -> bool:

View File

@@ -56,7 +56,7 @@ class Player: # pylint: disable=too-few-public-methods
key_bindings: Optional[Dict[str, Any]] = None, key_bindings: Optional[Dict[str, Any]] = None,
out_fmt: str = "raw", out_fmt: str = "raw",
stream: Optional[str] = None, stream: Optional[str] = None,
pause_on_breakpoints: bool = False, pause_on_markers: bool = False,
) -> None: ) -> None:
if key_bindings is None: if key_bindings is None:
key_bindings = {} key_bindings = {}
@@ -75,7 +75,7 @@ class Player: # pylint: disable=too-few-public-methods
stdin, stdin,
key_bindings, key_bindings,
output, output,
pause_on_breakpoints, pause_on_markers,
) )
except IOError: except IOError:
self._play( self._play(
@@ -96,12 +96,12 @@ class Player: # pylint: disable=too-few-public-methods
stdin: Optional[TextIO], stdin: Optional[TextIO],
key_bindings: Dict[str, Any], key_bindings: Dict[str, Any],
output: Output, output: Output,
pause_on_breakpoints: bool, pause_on_markers: bool,
) -> None: ) -> None:
idle_time_limit = idle_time_limit or asciicast.idle_time_limit idle_time_limit = idle_time_limit or asciicast.idle_time_limit
pause_key = key_bindings.get("pause") pause_key = key_bindings.get("pause")
step_key = key_bindings.get("step") step_key = key_bindings.get("step")
next_breakpoint_key = key_bindings.get("next_breakpoint") next_marker_key = key_bindings.get("next_marker")
events = asciicast.events() events = asciicast.events()
events = ev.to_relative_time(events) events = ev.to_relative_time(events)
@@ -150,8 +150,8 @@ class Player: # pylint: disable=too-few-public-methods
output.write(time_, event_type, text) output.write(time_, event_type, text)
time_, event_type, text = next_event() time_, event_type, text = next_event()
elif key == next_breakpoint_key: elif key == next_marker_key:
while time_ is not None and event_type != "b": while time_ is not None and event_type != "m":
output.write(time_, event_type, text) output.write(time_, event_type, text)
time_, event_type, text = next_event() time_, event_type, text = next_event()
@@ -179,7 +179,7 @@ class Player: # pylint: disable=too-few-public-methods
else: else:
output.write(time_, event_type, text) output.write(time_, event_type, text)
if event_type == "b" and pause_on_breakpoints: if event_type == "m" and pause_on_markers:
pause_elapsed_time = time_ pause_elapsed_time = time_
time_, event_type, text = next_event() time_, event_type, text = next_event()
break break

View File

@@ -36,7 +36,7 @@ def record(
prefix_mode: bool = False prefix_mode: bool = False
prefix_key = key_bindings.get("prefix") prefix_key = key_bindings.get("prefix")
pause_key = key_bindings.get("pause") pause_key = key_bindings.get("pause")
add_breakpoint_key = key_bindings.get("add_breakpoint") add_marker_key = key_bindings.get("add_marker")
def set_pty_size() -> None: def set_pty_size() -> None:
cols, rows = get_tty_size() cols, rows = get_tty_size()
@@ -60,7 +60,7 @@ def record(
return return
if prefix_mode or ( if prefix_mode or (
not prefix_key and data in [pause_key, add_breakpoint_key] not prefix_key and data in [pause_key, add_marker_key]
): ):
prefix_mode = False prefix_mode = False
@@ -74,10 +74,10 @@ def record(
pause_time = time.time() pause_time = time.time()
notify("Paused recording") notify("Paused recording")
elif data == add_breakpoint_key: elif data == add_marker_key:
assert start_time is not None assert start_time is not None
writer.write_breakpoint(time.time() - start_time) writer.write_marker(time.time() - start_time)
notify("Breakpoint added") notify("Marker added")
return return

View File

@@ -131,8 +131,8 @@ class async_writer(async_worker):
def write_stdout(self, ts: float, data: Any) -> None: def write_stdout(self, ts: float, data: Any) -> None:
self.enqueue([ts, "o", data]) self.enqueue([ts, "o", data])
def write_breakpoint(self, ts: float) -> None: def write_marker(self, ts: float) -> None:
self.enqueue([ts, "b", None]) self.enqueue([ts, "m", None])
def run(self) -> None: def run(self) -> None:
try: try:
@@ -146,8 +146,8 @@ class async_writer(async_worker):
w.write_stdout(self.time_offset + ts, data) w.write_stdout(self.time_offset + ts, data)
elif etype == "i": elif etype == "i":
w.write_stdin(self.time_offset + ts, data) w.write_stdin(self.time_offset + ts, data)
elif etype == "b": elif etype == "m":
w.write_breakpoint(self.time_offset + ts) w.write_marker(self.time_offset + ts)
except IOError: except IOError:
for event in iter(self.queue.get, None): for event in iter(self.queue.get, None):
pass pass

View File

@@ -13,7 +13,7 @@ Example file:
{"version": 2, "width": 80, "height": 24, "timestamp": 1504467315, "title": "Demo", "env": {"TERM": "xterm-256color", "SHELL": "/bin/zsh"}} {"version": 2, "width": 80, "height": 24, "timestamp": 1504467315, "title": "Demo", "env": {"TERM": "xterm-256color", "SHELL": "/bin/zsh"}}
[0.248848, "o", "\u001b[1;31mHello \u001b[32mWorld!\u001b[0m\n"] [0.248848, "o", "\u001b[1;31mHello \u001b[32mWorld!\u001b[0m\n"]
[1.001376, "o", "That was ok\rThis is better."] [1.001376, "o", "That was ok\rThis is better."]
[1.500000, "b", ""] [1.500000, "m", ""]
[2.143733, "o", "Now... "] [2.143733, "o", "Now... "]
[6.541828, "o", "Bye!"] [6.541828, "o", "Bye!"]
``` ```
@@ -115,7 +115,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"`, `"b"` * `event-type` (string) - one of: `"o"`, `"i"`, `"m"`
* `event-data` (any) - event specific data, described separately for each event * `event-data` (any) - event specific data, described separately for each event
type. type.
@@ -165,16 +165,16 @@ non-printable Unicode codepoints encoded as `\uXXXX`.
> implementations of asciicast-compatible terminal recorder should not capture > implementations of asciicast-compatible terminal recorder should not capture
> it either unless explicitly permitted by the user. > it either unless explicitly permitted by the user.
#### "b" - breakpoint #### "m" - marker
Event of type `"b"` represents a breakpoint. Event of type `"m"` represents a marker.
When breakpoint is encountered in the event stream and "pause on breakpoint" When marker is encountered in the event stream and "pause on markers"
functionality of the player is enabled, the playback should pause, and wait for functionality of the player is enabled, the playback should pause, and wait for
the user to resume. the user to resume.
`event-data` can be used to annotate a breakpoint. Annotations may be used to `event-data` can be used to annotate a marker. Annotations may be used to e.g.
e.g. show a list of named "chapters". show a list of named "chapters".
## Notes on compatibility ## Notes on compatibility

View File

@@ -98,7 +98,7 @@ asciinema rec --raw -c 'bash -c "echo t3st; sleep 1; echo ok"' "${TMP_DATA_DIR}/
asciinema rec -c 'echo allright!; sleep 0.1' "${TMP_DATA_DIR}/7.cast" asciinema rec -c 'echo allright!; sleep 0.1' "${TMP_DATA_DIR}/7.cast"
asciinema rec --append -c uptime "${TMP_DATA_DIR}/7.cast" asciinema rec --append -c uptime "${TMP_DATA_DIR}/7.cast"
# adding a breakpoint # adding a marker
printf "[record]\nadd_breakpoint_key = C-b\n" >> "${ASCIINEMA_CONFIG_HOME}/config" printf "[record]\nadd_marker_key = C-b\n" >> "${ASCIINEMA_CONFIG_HOME}/config"
(bash -c "sleep 1; printf '.'; sleep 0.5; printf '\x08'; sleep 0.5; printf '\x02'; sleep 0.5; printf '\x04'") | asciinema rec -c /bin/bash "${TMP_DATA_DIR}/8.cast" (bash -c "sleep 1; printf '.'; sleep 0.5; printf '\x08'; sleep 0.5; printf '\x02'; sleep 0.5; printf '\x04'") | asciinema rec -c /bin/bash "${TMP_DATA_DIR}/8.cast"
grep '"b",' "${TMP_DATA_DIR}/8.cast" grep '"m",' "${TMP_DATA_DIR}/8.cast"