Support repeat counts in #slow, and change command order.

This commit is contained in:
Condorra 2025-04-21 11:39:00 +10:00
parent 44a9b89844
commit 62583e7cdf
2 changed files with 28 additions and 9 deletions

View File

@ -18,7 +18,7 @@
"panel_merge": "Use #panel_merge followed by the frame path to merge panels. For example, #panel_merge {} will merge the current panel with the top-level split.", "panel_merge": "Use #panel_merge followed by the frame path to merge panels. For example, #panel_merge {} will merge the current panel with the top-level split.",
"send_multiple_commands": "To send several commands in quick succession, separate them with a semicolon. For example, use 'n;e' to go north and then east.", "send_multiple_commands": "To send several commands in quick succession, separate them with a semicolon. For example, use 'n;e' to go north and then east.",
"tick": "Use #tick to set a recurring command to run at a specified time interval (in seconds).\r\nFor example, #tick 60 {#echo Cockadoodledoo!} will repeat every 60 seconds.\r\nOptionally give it a name with a third argument.\r\nUse #tick by itself to list active ticks.\r\nSee also: #untick", "tick": "Use #tick to set a recurring command to run at a specified time interval (in seconds).\r\nFor example, #tick 60 {#echo Cockadoodledoo!} will repeat every 60 seconds.\r\nOptionally give it a name with a third argument.\r\nUse #tick by itself to list active ticks.\r\nSee also: #untick",
"slow": "To send commands at a controlled rate, try #slow {command;command;command} 0.5, where 0.5 is replaced with the time between commands in seconds" "slow": "Use #slow to send commands at a controlled rate.\r\nExample: #slow 0.5 {command1;#2 command2}\r\n0.5 is time between commands in seconds.\r\nTop level repeat counts are also rate controlled, while deeply nested commands are not; the above example would run command1, then 0.5 seconds later command2, then another 0.5 seconds later command2 again.",
"unact": "Use #unact followed by the trigger pattern to delete a trigger. Example: #unact {^The (.*) attacks you.}.", "unact": "Use #unact followed by the trigger pattern to delete a trigger. Example: #unact {^The (.*) attacks you.}.",
"unalias": "Use #unalias followed by the alias pattern to delete it. For example, #unalias {^hi}.", "unalias": "Use #unalias followed by the alias pattern to delete it. For example, #unalias {^hi}.",
"undelay": "Use #undelay followed by the delay name to cancel it. Example: #undelay ding to cancel a delay named 'ding'.", "undelay": "Use #undelay followed by the delay name to cancel it. Example: #undelay ding to cancel a delay named 'ding'.",

View File

@ -2,7 +2,7 @@ use crate::{
echo_to_term_frame, echo_to_term_frame,
id_intern::intern_id, id_intern::intern_id,
match_table::{create_match_table, match_table_add, match_table_remove}, match_table::{create_match_table, match_table_add, match_table_remove},
parsing::parse_commands, parsing::{parse_commands, ParsedCommand},
timer_host::TimerHostAccessContext, timer_host::TimerHostAccessContext,
FrameId, FrameViewType, GlobalLayoutCell, GlobalLayoutState, GlobalMemoCell, FrameId, FrameViewType, GlobalLayoutCell, GlobalLayoutState, GlobalMemoCell,
}; };
@ -888,6 +888,12 @@ pub(super) fn slow<'gc>(
&ctx.get_global::<Table>("info")? &ctx.get_global::<Table>("info")?
.get(ctx, ctx.intern_static(b"current_frame"))?, .get(ctx, ctx.intern_static(b"current_frame"))?,
)?; )?;
let delay: f64 = f64::from_value(
ctx,
stack
.pop_front()
.ok_or_else(|| anyhow::Error::msg("Missing slow delay time"))?,
)?;
let cmds = piccolo::String::from_value( let cmds = piccolo::String::from_value(
ctx, ctx,
stack stack
@ -895,12 +901,7 @@ pub(super) fn slow<'gc>(
.ok_or_else(|| anyhow::Error::msg("Missing commands to slowly queue"))?, .ok_or_else(|| anyhow::Error::msg("Missing commands to slowly queue"))?,
)? )?
.to_str()?; .to_str()?;
let delay: f64 = f64::from_value(
ctx,
stack
.pop_front()
.ok_or_else(|| anyhow::Error::msg("Missing slow delay time"))?,
)?;
if !stack.is_empty() { if !stack.is_empty() {
Err(anyhow::Error::msg( Err(anyhow::Error::msg(
"Extra arguments to slow command. Try wrapping the action in {}", "Extra arguments to slow command. Try wrapping the action in {}",
@ -908,13 +909,31 @@ pub(super) fn slow<'gc>(
} }
let cmds = parse_commands(cmds).commands; let cmds = parse_commands(cmds).commands;
let mut expanded_cmds: Vec<ParsedCommand> = vec![];
for cmdline in cmds {
match cmdline.split_out_command() {
None => {}
Some((cmd, rest)) => {
if let ("#", command_rest) = cmd.split_at(1) {
if let Ok(repeat_count) = command_rest.parse::<u16>() {
for _ in 0..repeat_count {
expanded_cmds.push(rest.clone());
}
continue;
}
}
expanded_cmds.push(cmdline);
}
}
}
let delay_fn: Function = ctx.get_global::<Table>("commands")?.get(ctx, "delay")?; let delay_fn: Function = ctx.get_global::<Table>("commands")?.get(ctx, "delay")?;
let seq = async_sequence(&ctx, |locals, mut seq| { let seq = async_sequence(&ctx, |locals, mut seq| {
let global_memo = global_memo.clone(); let global_memo = global_memo.clone();
let delay_fn = locals.stash(&ctx, delay_fn); let delay_fn = locals.stash(&ctx, delay_fn);
async move { async move {
for (idx, cmd) in cmds.iter().enumerate() { for (idx, cmd) in expanded_cmds.iter().enumerate() {
if idx == 0 { if idx == 0 {
global_memo global_memo
.command_queue .command_queue