Skip to content

Commit

Permalink
GH-266 fix key_wait
Browse files Browse the repository at this point in the history
  • Loading branch information
spyoungtech committed Feb 28, 2024
1 parent 8ab9a98 commit 0612ecd
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 34 deletions.
20 changes: 11 additions & 9 deletions ahk/_async/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,9 @@ async def get_coord_mode(self, target: CoordModeTargets) -> str:
return resp

async def set_send_mode(self, mode: SendMode) -> None:
"""
Analog for `SendMode <https://www.autohotkey.com/docs/v1/lib/SendMode.htm>`_
"""
args = [str(mode)]
await self._transport.function_call('AHKSetSendMode', args)
return None
Expand Down Expand Up @@ -1126,13 +1129,13 @@ async def key_up(self, key: Union[str, Key], blocking: bool = True) -> Union[Non

# fmt: off
@overload
async def key_wait(self, key_name: str, *, timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> int: ...
async def key_wait(self, key_name: str, *, timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> bool: ...
@overload
async def key_wait(self, key_name: str, *, blocking: Literal[True], timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> int: ...
async def key_wait(self, key_name: str, *, blocking: Literal[True], timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> bool: ...
@overload
async def key_wait(self, key_name: str, *, blocking: Literal[False], timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> AsyncFutureResult[int]: ...
async def key_wait(self, key_name: str, *, blocking: Literal[False], timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> AsyncFutureResult[bool]: ...
@overload
async def key_wait(self, key_name: str, *, timeout: Optional[int] = None, logical_state: bool = False, released: bool = False, blocking: bool = True) -> Union[int, AsyncFutureResult[int]]: ...
async def key_wait(self, key_name: str, *, timeout: Optional[int] = None, logical_state: bool = False, released: bool = False, blocking: bool = True) -> Union[bool, AsyncFutureResult[bool]]: ...
# fmt: on
async def key_wait(
self,
Expand All @@ -1142,7 +1145,7 @@ async def key_wait(
logical_state: bool = False,
released: bool = False,
blocking: bool = True,
) -> Union[int, AsyncFutureResult[int]]:
) -> Union[bool, AsyncFutureResult[bool]]:
"""
Analog for `KeyWait <https://www.autohotkey.com/docs/commands/KeyWait.htm>`_
"""
Expand All @@ -1151,11 +1154,10 @@ async def key_wait(
options += 'D'
if logical_state:
options += 'L'
if timeout:
if timeout is not None:
assert timeout >= 0, 'Timeout value must be non-negative'
options += f'T{timeout}'
args = [key_name]
if options:
args.append(options)
args = [key_name, options]

resp = await self._transport.function_call('AHKKeyWait', args, blocking=blocking)
return resp
Expand Down
2 changes: 1 addition & 1 deletion ahk/_async/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ async def function_call(self, function_name: Literal['AHKClick'], args: Optional
@overload
async def function_call(self, function_name: Literal['AHKMouseClickDrag'], args: Optional[List[str]] = None, *, blocking: bool = True, engine: Optional[AsyncAHK[Any]] = None) -> Union[None, AsyncFutureResult[None]]: ...
@overload
async def function_call(self, function_name: Literal['AHKKeyWait'], args: Optional[List[str]] = None, *, blocking: bool = True, engine: Optional[AsyncAHK[Any]] = None) -> Union[int, AsyncFutureResult[int]]: ...
async def function_call(self, function_name: Literal['AHKKeyWait'], args: Optional[List[str]] = None, *, blocking: bool = True, engine: Optional[AsyncAHK[Any]] = None) -> Union[bool, AsyncFutureResult[bool]]: ...
@overload
async def function_call(self, function_name: Literal['SetKeyDelay'], args: Optional[List[str]] = None, *, blocking: bool = True, engine: Optional[AsyncAHK[Any]] = None) -> Union[None, AsyncFutureResult[None]]: ...
@overload
Expand Down
29 changes: 23 additions & 6 deletions ahk/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -1891,13 +1891,24 @@
{% block AHKKeyWait %}
keyname := args[1]
if (args.Length() = 2) {
options := args[2]
if (options = "") {
KeyWait,% keyname
} else {
options := args[2]
KeyWait,% keyname,% options
}
return FormatResponse("ahk.message.IntegerResponseMessage", ErrorLevel)
ret := ErrorLevel
if (ret = 1) {
return FormatResponse("ahk.message.BooleanResponseMessage", 0)
} else if (ret = 0) {
return FormatResponse("ahk.message.BooleanResponseMessage", 1)
} else {
; Unclear if this is even reachable
return FormatResponse("ahk.message.ExceptionResponseMessage", Format("There was a problem. ErrorLevel: {}", ret))
}
{% endblock AHKKeyWait %}
}
Expand Down Expand Up @@ -4981,13 +4992,19 @@
{% block AHKKeyWait %}
keyname := args[1]
if (args.Length = 2) {
options := args[2]
if (options = "") {
ret := KeyWait(keyname)
} else {
options := args[2]
ret := KeyWait(keyname, options)
}
return FormatResponse("ahk.message.IntegerResponseMessage", ret)
if (ret = 0) {
return FormatResponse("ahk.message.BooleanResponseMessage", 0)
} else {
return FormatResponse("ahk.message.BooleanResponseMessage", 1)
}
{% endblock AHKKeyWait %}
}
Expand Down
20 changes: 11 additions & 9 deletions ahk/_sync/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,9 @@ def get_coord_mode(self, target: CoordModeTargets) -> str:
return resp

def set_send_mode(self, mode: SendMode) -> None:
"""
Analog for `SendMode <https://www.autohotkey.com/docs/v1/lib/SendMode.htm>`_
"""
args = [str(mode)]
self._transport.function_call('AHKSetSendMode', args)
return None
Expand Down Expand Up @@ -1114,13 +1117,13 @@ def key_up(self, key: Union[str, Key], blocking: bool = True) -> Union[None, Fut

# fmt: off
@overload
def key_wait(self, key_name: str, *, timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> int: ...
def key_wait(self, key_name: str, *, timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> bool: ...
@overload
def key_wait(self, key_name: str, *, blocking: Literal[True], timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> int: ...
def key_wait(self, key_name: str, *, blocking: Literal[True], timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> bool: ...
@overload
def key_wait(self, key_name: str, *, blocking: Literal[False], timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> FutureResult[int]: ...
def key_wait(self, key_name: str, *, blocking: Literal[False], timeout: Optional[int] = None, logical_state: bool = False, released: bool = False) -> FutureResult[bool]: ...
@overload
def key_wait(self, key_name: str, *, timeout: Optional[int] = None, logical_state: bool = False, released: bool = False, blocking: bool = True) -> Union[int, FutureResult[int]]: ...
def key_wait(self, key_name: str, *, timeout: Optional[int] = None, logical_state: bool = False, released: bool = False, blocking: bool = True) -> Union[bool, FutureResult[bool]]: ...
# fmt: on
def key_wait(
self,
Expand All @@ -1130,7 +1133,7 @@ def key_wait(
logical_state: bool = False,
released: bool = False,
blocking: bool = True,
) -> Union[int, FutureResult[int]]:
) -> Union[bool, FutureResult[bool]]:
"""
Analog for `KeyWait <https://www.autohotkey.com/docs/commands/KeyWait.htm>`_
"""
Expand All @@ -1139,11 +1142,10 @@ def key_wait(
options += 'D'
if logical_state:
options += 'L'
if timeout:
if timeout is not None:
assert timeout >= 0, 'Timeout value must be non-negative'
options += f'T{timeout}'
args = [key_name]
if options:
args.append(options)
args = [key_name, options]

resp = self._transport.function_call('AHKKeyWait', args, blocking=blocking)
return resp
Expand Down
2 changes: 1 addition & 1 deletion ahk/_sync/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ def function_call(self, function_name: Literal['AHKClick'], args: Optional[List[
@overload
def function_call(self, function_name: Literal['AHKMouseClickDrag'], args: Optional[List[str]] = None, *, blocking: bool = True, engine: Optional[AHK[Any]] = None) -> Union[None, FutureResult[None]]: ...
@overload
def function_call(self, function_name: Literal['AHKKeyWait'], args: Optional[List[str]] = None, *, blocking: bool = True, engine: Optional[AHK[Any]] = None) -> Union[int, FutureResult[int]]: ...
def function_call(self, function_name: Literal['AHKKeyWait'], args: Optional[List[str]] = None, *, blocking: bool = True, engine: Optional[AHK[Any]] = None) -> Union[bool, FutureResult[bool]]: ...
@overload
def function_call(self, function_name: Literal['SetKeyDelay'], args: Optional[List[str]] = None, *, blocking: bool = True, engine: Optional[AHK[Any]] = None) -> Union[None, FutureResult[None]]: ...
@overload
Expand Down
12 changes: 9 additions & 3 deletions ahk/templates/daemon-v2.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -2007,13 +2007,19 @@ AHKKeyWait(args*) {
{% block AHKKeyWait %}

keyname := args[1]
if (args.Length = 2) {
options := args[2]

if (options = "") {
ret := KeyWait(keyname)
} else {
options := args[2]
ret := KeyWait(keyname, options)
}
return FormatResponse("ahk.message.IntegerResponseMessage", ret)

if (ret = 0) {
return FormatResponse("ahk.message.BooleanResponseMessage", 0)
} else {
return FormatResponse("ahk.message.BooleanResponseMessage", 1)
}
{% endblock AHKKeyWait %}
}

Expand Down
17 changes: 14 additions & 3 deletions ahk/templates/daemon.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -1888,13 +1888,24 @@ AHKKeyWait(args*) {
{% block AHKKeyWait %}

keyname := args[1]
if (args.Length() = 2) {
options := args[2]

if (options = "") {
KeyWait,% keyname
} else {
options := args[2]
KeyWait,% keyname,% options
}
return FormatResponse("ahk.message.IntegerResponseMessage", ErrorLevel)
ret := ErrorLevel

if (ret = 1) {
return FormatResponse("ahk.message.BooleanResponseMessage", 0)
} else if (ret = 0) {
return FormatResponse("ahk.message.BooleanResponseMessage", 1)
} else {
; Unclear if this is even reachable
return FormatResponse("ahk.message.ExceptionResponseMessage", Format("There was a problem. ErrorLevel: {}", ret))
}

{% endblock AHKKeyWait %}
}

Expand Down
6 changes: 4 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,10 @@ ahk.key_press('a') # Press and release a key
ahk.key_down('Control') # Press down (but do not release) Control key
ahk.key_up('Control') # Release the key
ahk.set_capslock_state("On") # Turn CapsLock on
ahk.key_wait('a', timeout=3) # Wait up to 3 seconds for the "a" key to be pressed. NOTE: This throws
# a TimeoutError if the key isn't pressed within the timeout window
if ahk.key_wait('x', timeout=3): # wait for a key to be pressed; returns a boolean
print('X was pressed within 3 seconds')
else:
print('X was not pressed within 3 seconds')
```

## Windows
Expand Down
16 changes: 16 additions & 0 deletions tests/_async/test_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import time
import unittest.mock

import pytest

from ahk import AsyncAHK
from ahk import AsyncWindow

Expand Down Expand Up @@ -78,6 +80,20 @@ async def test_hotstring_callback(self):
await async_sleep(1)
m.assert_called()

async def test_key_wait(self):
res = await self.ahk.key_wait('x', timeout=3, blocking=False)
await self.ahk.set_send_level(1)
await async_sleep(1)
await self.ahk.key_down('x')
await async_sleep(1)
await self.ahk.key_up('x')
result = await res.result()
assert result is True

async def test_key_wait_timeout(self):
res = await self.ahk.key_wait('x', timeout=1)
assert res is False


class TestKeysAsyncV2(TestKeysAsync):
async def asyncSetUp(self) -> None:
Expand Down
16 changes: 16 additions & 0 deletions tests/_sync/test_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import time
import unittest.mock

import pytest

from ahk import AHK
from ahk import Window

Expand Down Expand Up @@ -77,6 +79,20 @@ def test_hotstring_callback(self):
sleep(1)
m.assert_called()

def test_key_wait(self):
res = self.ahk.key_wait('x', timeout=3, blocking=False)
self.ahk.set_send_level(1)
sleep(1)
self.ahk.key_down('x')
sleep(1)
self.ahk.key_up('x')
result = res.result()
assert result is True

def test_key_wait_timeout(self):
res = self.ahk.key_wait('x', timeout=1)
assert res is False


class TestKeysAsyncV2(TestKeysAsync):
def setUp(self) -> None:
Expand Down

0 comments on commit 0612ecd

Please sign in to comment.