Remove at from mouse instructions in Ice syntax

This commit is contained in:
Héctor Ramón Jiménez 2025-09-20 17:33:57 +02:00
parent 364b68f030
commit 79d501f9a5
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
5 changed files with 89 additions and 52 deletions

View file

@ -1,4 +1,5 @@
use iced::keyboard; use iced::keyboard;
use iced::time::milliseconds;
use iced::widget::{ use iced::widget::{
self, Text, button, center, center_x, checkbox, column, keyed_column, self, Text, button, center, center_x, checkbox, column, keyed_column,
operation, row, scrollable, text, text_input, operation, row, scrollable, text, text_input,
@ -544,8 +545,8 @@ impl SavedState {
.map_err(|_| SaveError::Write)?; .map_err(|_| SaveError::Write)?;
} }
// This is a simple way to save at most once every couple seconds // This is a simple way to save at most twice every second
tokio::time::sleep(std::time::Duration::from_secs(2)).await; tokio::time::sleep(milliseconds(500)).await;
Ok(()) Ok(())
} }

View file

@ -2,13 +2,13 @@ viewport: 500x800
mode: Immediate mode: Immediate
preset: Empty preset: Empty
----- -----
click at "What needs to be done?" click "What needs to be done?"
type "Create the universe" type "Create the universe"
type enter type enter
type "Make an apple pie" type "Make an apple pie"
type enter type enter
expect "2 tasks left" expect "2 tasks left"
click at "Create the universe" click "Create the universe"
expect "1 task left" expect "1 task left"
click at "Make an apple pie" click "Make an apple pie"
expect "0 tasks left" expect "0 tasks left"

View file

@ -54,11 +54,11 @@ impl Interaction {
} }
mouse::Event::ButtonPressed(button) => Mouse::Press { mouse::Event::ButtonPressed(button) => Mouse::Press {
button: *button, button: *button,
at: None, target: None,
}, },
mouse::Event::ButtonReleased(button) => Mouse::Release { mouse::Event::ButtonReleased(button) => Mouse::Release {
button: *button, button: *button,
at: None, target: None,
}, },
_ => None?, _ => None?,
}), }),
@ -117,28 +117,40 @@ impl Interaction {
(Mouse::Move(_), Mouse::Move(to)) => { (Mouse::Move(_), Mouse::Move(to)) => {
(Self::Mouse(Mouse::Move(to)), None) (Self::Mouse(Mouse::Move(to)), None)
} }
(Mouse::Move(to), Mouse::Press { button, at: None }) => ( (
Mouse::Move(to),
Mouse::Press {
button,
target: None,
},
) => (
Self::Mouse(Mouse::Press { Self::Mouse(Mouse::Press {
button, button,
at: Some(to), target: Some(to),
}), }),
None, None,
), ),
(Mouse::Move(to), Mouse::Release { button, at: None }) => ( (
Mouse::Move(to),
Mouse::Release {
button,
target: None,
},
) => (
Self::Mouse(Mouse::Release { Self::Mouse(Mouse::Release {
button, button,
at: Some(to), target: Some(to),
}), }),
None, None,
), ),
( (
Mouse::Press { Mouse::Press {
button: press, button: press,
at: press_at, target: press_at,
}, },
Mouse::Release { Mouse::Release {
button: release, button: release,
at: release_at, target: release_at,
}, },
) if press == release ) if press == release
&& release_at.as_ref().is_none_or(|release_at| { && release_at.as_ref().is_none_or(|release_at| {
@ -148,7 +160,7 @@ impl Interaction {
( (
Self::Mouse(Mouse::Click { Self::Mouse(Mouse::Click {
button: press, button: press,
at: press_at, target: press_at,
}), }),
None, None,
) )
@ -156,26 +168,26 @@ impl Interaction {
( (
Mouse::Press { Mouse::Press {
button, button,
at: Some(press_at), target: Some(press_at),
}, },
Mouse::Move(move_at), Mouse::Move(move_at),
) if press_at == move_at => ( ) if press_at == move_at => (
Self::Mouse(Mouse::Press { Self::Mouse(Mouse::Press {
button, button,
at: Some(press_at), target: Some(press_at),
}), }),
None, None,
), ),
( (
Mouse::Click { Mouse::Click {
button, button,
at: Some(click_at), target: Some(click_at),
}, },
Mouse::Move(move_at), Mouse::Move(move_at),
) if click_at == move_at => ( ) if click_at == move_at => (
Self::Mouse(Mouse::Click { Self::Mouse(Mouse::Click {
button, button,
at: Some(click_at), target: Some(click_at),
}), }),
None, None,
), ),
@ -235,23 +247,29 @@ impl Interaction {
Mouse::Move(to) => vec![mouse_move_(find_target(to)?)], Mouse::Move(to) => vec![mouse_move_(find_target(to)?)],
Mouse::Press { Mouse::Press {
button, button,
at: Some(at), target: Some(at),
} => vec![mouse_move_(find_target(at)?), mouse_press(*button)], } => vec![mouse_move_(find_target(at)?), mouse_press(*button)],
Mouse::Press { button, at: None } => { Mouse::Press {
button,
target: None,
} => {
vec![mouse_press(*button)] vec![mouse_press(*button)]
} }
Mouse::Release { Mouse::Release {
button, button,
at: Some(at), target: Some(at),
} => { } => {
vec![mouse_move_(find_target(at)?), mouse_release(*button)] vec![mouse_move_(find_target(at)?), mouse_release(*button)]
} }
Mouse::Release { button, at: None } => { Mouse::Release {
button,
target: None,
} => {
vec![mouse_release(*button)] vec![mouse_release(*button)]
} }
Mouse::Click { Mouse::Click {
button, button,
at: Some(at), target: Some(at),
} => { } => {
vec![ vec![
mouse_move_(find_target(at)?), mouse_move_(find_target(at)?),
@ -259,7 +277,10 @@ impl Interaction {
mouse_release(*button), mouse_release(*button),
] ]
} }
Mouse::Click { button, at: None } => { Mouse::Click {
button,
target: None,
} => {
vec![mouse_press(*button), mouse_release(*button)] vec![mouse_press(*button), mouse_release(*button)]
} }
}, },
@ -294,21 +315,21 @@ pub enum Mouse {
/// The button. /// The button.
button: mouse::Button, button: mouse::Button,
/// The location of the press. /// The location of the press.
at: Option<Target>, target: Option<Target>,
}, },
/// A button was released. /// A button was released.
Release { Release {
/// The button. /// The button.
button: mouse::Button, button: mouse::Button,
/// The location of the release. /// The location of the release.
at: Option<Target>, target: Option<Target>,
}, },
/// A button was clicked. /// A button was clicked.
Click { Click {
/// The button. /// The button.
button: mouse::Button, button: mouse::Button,
/// The location of the click. /// The location of the click.
at: Option<Target>, target: Option<Target>,
}, },
} }
@ -318,14 +339,26 @@ impl fmt::Display for Mouse {
Mouse::Move(target) => { Mouse::Move(target) => {
write!(f, "move cursor to {}", target) write!(f, "move cursor to {}", target)
} }
Mouse::Press { button, at } => { Mouse::Press { button, target } => {
write!(f, "press {}", format::button_at(*button, at.as_ref())) write!(
f,
"press {}",
format::button_at(*button, target.as_ref())
)
} }
Mouse::Release { button, at } => { Mouse::Release { button, target } => {
write!(f, "release {}", format::button_at(*button, at.as_ref())) write!(
f,
"release {}",
format::button_at(*button, target.as_ref())
)
} }
Mouse::Click { button, at } => { Mouse::Click { button, target } => {
write!(f, "click {}", format::button_at(*button, at.as_ref())) write!(
f,
"click {}",
format::button_at(*button, target.as_ref())
)
} }
} }
} }
@ -412,9 +445,9 @@ mod format {
if let Some(at) = at { if let Some(at) = at {
if button.is_empty() { if button.is_empty() {
format!("at {}", at) at.to_string()
} else { } else {
format!("{} at {}", button, at) format!("{} {}", button, at)
} }
} else { } else {
button.to_owned() button.to_owned()
@ -479,9 +512,7 @@ mod parser {
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::bytes::{is_not, take_while_m_n}; use nom::bytes::{is_not, take_while_m_n};
use nom::character::complete::{char, multispace0, multispace1}; use nom::character::complete::{char, multispace0, multispace1};
use nom::combinator::{ use nom::combinator::{map, map_opt, map_res, opt, success, value, verify};
cut, map, map_opt, map_res, opt, success, value, verify,
};
use nom::error::ParseError; use nom::error::ParseError;
use nom::multi::fold; use nom::multi::fold;
use nom::number::float; use nom::number::float;
@ -526,9 +557,9 @@ mod parser {
fn mouse_click(input: &str) -> IResult<&str, Mouse> { fn mouse_click(input: &str) -> IResult<&str, Mouse> {
let (input, _) = tag("click ")(input)?; let (input, _) = tag("click ")(input)?;
let (input, (button, at)) = mouse_button_at(input)?; let (input, (button, target)) = mouse_button_at(input)?;
Ok((input, Mouse::Click { button, at })) Ok((input, Mouse::Click { button, target }))
} }
fn mouse_button_at( fn mouse_button_at(
@ -541,11 +572,7 @@ mod parser {
} }
fn target(input: &str) -> IResult<&str, Target> { fn target(input: &str) -> IResult<&str, Target> {
preceded( alt((string.map(Target::Text), point.map(Target::Point))).parse(input)
whitespace(tag("at ")),
cut(alt((string.map(Target::Text), point.map(Target::Point)))),
)
.parse(input)
} }
fn mouse_button(input: &str) -> IResult<&str, mouse::Button> { fn mouse_button(input: &str) -> IResult<&str, mouse::Button> {

View file

@ -502,7 +502,7 @@ impl<P: Program + 'static> Tester<P> {
let instruction::Interaction::Mouse( let instruction::Interaction::Mouse(
instruction::Mouse::Click { instruction::Mouse::Click {
button: mouse::Button::Left, button: mouse::Button::Left,
at: Some(instruction::Target::Text(text)), target: Some(instruction::Target::Text(text)),
}, },
) = interaction ) = interaction
else { else {

View file

@ -415,17 +415,26 @@ fn record<Message>(
}; };
let Interaction::Mouse( let Interaction::Mouse(
Mouse::Move(at) Mouse::Move(target)
| Mouse::Press { at: Some(at), .. } | Mouse::Press {
| Mouse::Release { at: Some(at), .. } target: Some(target),
| Mouse::Click { at: Some(at), .. }, ..
}
| Mouse::Release {
target: Some(target),
..
}
| Mouse::Click {
target: Some(target),
..
},
) = &mut interaction ) = &mut interaction
else { else {
shell.publish(on_record(interaction)); shell.publish(on_record(interaction));
return; return;
}; };
let Target::Point(position) = *at else { let Target::Point(position) = *target else {
shell.publish(on_record(interaction)); shell.publish(on_record(interaction));
return; return;
}; };
@ -433,7 +442,7 @@ fn record<Message>(
if let Some((content, visible_bounds)) = if let Some((content, visible_bounds)) =
find_text(position + (bounds.position() - Point::ORIGIN), operate) find_text(position + (bounds.position() - Point::ORIGIN), operate)
{ {
*at = Target::Text(content); *target = Target::Text(content);
*last_hovered = visible_bounds; *last_hovered = visible_bounds;
} else { } else {
*last_hovered = None; *last_hovered = None;