From b7d6d3a608e7eafa8ccb6b3ab9e2adb09fb7408e Mon Sep 17 00:00:00 2001 From: Jonathan Amponsah <82057176+mgalore@users.noreply.github.com> Date: Thu, 13 Aug 2026 22:06:11 +0000 Subject: [PATCH 1/2] docs: add AutoIt porting example --- README.md | 4 +- autoitx/examples/port_from_autoit.rs | 97 ++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 autoitx/examples/port_from_autoit.rs diff --git a/README.md b/README.md index 4aa3895..258f07a 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ A Windows machine is needed only to observe real behaviour — never to compile. ## Examples -Eight, in [`autoitx/examples`][examples]. Run any with +Nine, in [`autoitx/examples`][examples]. Run any with `cargo run --example `. | | | @@ -209,6 +209,7 @@ Eight, in [`autoitx/examples`][examples]. Run any with | [`wait_until_ready`][wait_until_ready] | One intent, two mechanisms, one call | | [`portable_selectors`][portable_selectors] | One selector table for both platforms | | [`port_from_csharp`][port_from_csharp] | The same flow in AutoItX.Dotnet and here, side by side | +| [`port_from_autoit`][port_from_autoit] | An AutoIt flow and its safe, compiled Rust port, side by side | [examples]: https://github.com/iagodpassos/autoitx/tree/main/autoitx/examples [diagnose]: https://github.com/iagodpassos/autoitx/blob/main/autoitx/examples/diagnose.rs @@ -219,6 +220,7 @@ Eight, in [`autoitx/examples`][examples]. Run any with [wait_until_ready]: https://github.com/iagodpassos/autoitx/blob/main/autoitx/examples/wait_until_ready.rs [portable_selectors]: https://github.com/iagodpassos/autoitx/blob/main/autoitx/examples/portable_selectors.rs [port_from_csharp]: https://github.com/iagodpassos/autoitx/blob/main/autoitx/examples/port_from_csharp.rs +[port_from_autoit]: https://github.com/iagodpassos/autoitx/blob/main/autoitx/examples/port_from_autoit.rs ## Status diff --git a/autoitx/examples/port_from_autoit.rs b/autoitx/examples/port_from_autoit.rs new file mode 100644 index 0000000..69263ff --- /dev/null +++ b/autoitx/examples/port_from_autoit.rs @@ -0,0 +1,97 @@ +//! The same automation flow in AutoIt and in this crate, side by side. +//! +//! The compiled Rust below deliberately does not drive an application: this +//! example prints the comparison and exits. Keeping the Rust half as code, +//! rather than only prose, prevents the porting guidance from drifting. +//! +//! ```text +//! cargo run --example port_from_autoit +//! ``` + +#[cfg(any(windows, target_os = "macos", feature = "mock-loader"))] +use autoitx::options::{KeyMap, Options}; +#[cfg(any(windows, target_os = "macos", feature = "mock-loader"))] +use autoitx::{AutoIt, Keys, Selector, keys, recipes}; +#[cfg(any(windows, target_os = "macos", feature = "mock-loader"))] +use std::time::Duration; + +fn main() -> Result<(), Box> { + println!("{COMPARISON}"); + compiled_port()?; + Ok(()) +} + +// The Rust side is compiled rather than quoted, but never invoked against a +// real application. The empty Linux version lets this documentation example +// compile and print everywhere. +#[cfg(any(windows, target_os = "macos", feature = "mock-loader"))] +fn compiled_port() -> Result<(), autoitx::Error> { + if false { + let ai = AutoIt::builder() + .options(Options::default().with_key_map(KeyMap::PortableShortcuts)) + .build()?; + let window = Selector::from("[TITLE:Order Selection]"); + let customer_name = "Ada {priority}+"; + + // 1. Dynamic text is data, not an AutoIt key sequence. + ai.send(Keys::text(customer_name))?; + + // 2. The shortcut is a literal sequence validated at compile time. + let copied = + recipes::read_screen_text(&ai, keys!("{CTRLDOWN}c{CTRLUP}"), Duration::from_secs(5))?; + println!("copied total: {copied}"); + + // 3. This offset follows the selected window rather than the screen. + recipes::click_in_window(&ai, &window, 420, 260)?; + + // 4. Unlike AutoIt's unbounded WinWaitActive call, the timeout is explicit. + let active = ai.win_wait_active(&window, Some(Duration::from_secs(10)))?; + println!("order selection active: {active}"); + } + Ok(()) +} + +#[cfg(not(any(windows, target_os = "macos", feature = "mock-loader")))] +fn compiled_port() -> Result<(), Box> { + Ok(()) +} + +const COMPARISON: &str = r#" +1. Waiting for the order-selection window +------------------------------------------------------------------ + AutoIt WinWaitActive("Order Selection") + ; waits forever when the application never appears + + Rust ai.win_wait_active(&window, Some(Duration::from_secs(10)))?; + // the deadline is explicit, so a missing window is observable + +2. Copying a total from the screen +------------------------------------------------------------------ + AutoIt Send("{CTRLDOWN}c{CTRLUP}") + $total = ClipGet() + ; a blind copy can read the previous clipboard value + + Rust let total = recipes::read_screen_text( + &ai, keys!("{CTRLDOWN}c{CTRLUP}"), timeout + )?; + // waits for the clipboard sequence number to change + +3. Typing a customer name +------------------------------------------------------------------ + AutoIt Send($customerName) + ; { } ! + ^ # in data are interpreted as key commands + + Rust ai.send(Keys::text(customer_name))?; + // text() escapes data; keys!() is for literal, checked sequences + +4. Clicking the selected order +------------------------------------------------------------------ + AutoIt MouseClick("left", 420, 260) + ; absolute coordinates break when the window moves or the display changes + + Rust recipes::click_in_window(&ai, &window, 420, 260)?; + // measures the window and clicks at an offset from its top-left corner + +The example prints this comparison only. Its Rust half is compiled to keep the +API names, shortcut syntax, and safe-porting guidance current. +"#; From 7c460e455b178ec1230d914c5b32c0f5b3346067 Mon Sep 17 00:00:00 2001 From: Jonathan Amponsah <82057176+mgalore@users.noreply.github.com> Date: Tue, 1 Sep 2026 06:05:33 +0000 Subject: [PATCH 2/2] docs: align porting example sequence --- autoitx/examples/port_from_autoit.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/autoitx/examples/port_from_autoit.rs b/autoitx/examples/port_from_autoit.rs index 69263ff..d99da84 100644 --- a/autoitx/examples/port_from_autoit.rs +++ b/autoitx/examples/port_from_autoit.rs @@ -33,20 +33,20 @@ fn compiled_port() -> Result<(), autoitx::Error> { let window = Selector::from("[TITLE:Order Selection]"); let customer_name = "Ada {priority}+"; - // 1. Dynamic text is data, not an AutoIt key sequence. - ai.send(Keys::text(customer_name))?; + // 1. Unlike AutoIt's unbounded WinWaitActive call, the timeout is explicit. + let active = ai.win_wait_active(&window, Some(Duration::from_secs(10)))?; + println!("order selection active: {active}"); // 2. The shortcut is a literal sequence validated at compile time. let copied = recipes::read_screen_text(&ai, keys!("{CTRLDOWN}c{CTRLUP}"), Duration::from_secs(5))?; println!("copied total: {copied}"); - // 3. This offset follows the selected window rather than the screen. - recipes::click_in_window(&ai, &window, 420, 260)?; + // 3. Dynamic text is data, not an AutoIt key sequence. + ai.send(Keys::text(customer_name))?; - // 4. Unlike AutoIt's unbounded WinWaitActive call, the timeout is explicit. - let active = ai.win_wait_active(&window, Some(Duration::from_secs(10)))?; - println!("order selection active: {active}"); + // 4. This offset follows the selected window rather than the screen. + recipes::click_in_window(&ai, &window, 420, 260)?; } Ok(()) }