Added support for {DELAY=<delay>} to allow for custom delay in command execution instead of using dedicated UI and settings for this

This commit is contained in:
Michael Starke 2019-06-17 15:38:12 +02:00
parent 3ef2c01859
commit 8d66621803
5 changed files with 62 additions and 17 deletions

View File

@ -26,6 +26,7 @@
#import "MPAutotypeCommand.h"
#import "MPAutotypeContext.h"
#import "MPAutotypePaste.h"
#import "MPAutotypeDelay.h"
#import "MPPasteBoardController.h"
#import "MPSettingsHelper.h"
#import "MPAutotypeCandidateSelectionViewController.h"
@ -319,18 +320,24 @@ static MPAutotypeDaemon *_sharedInstance;
usleep(1 * NSEC_PER_MSEC);
}
useconds_t delay = 0;
if(nil != [NSUserDefaults.standardUserDefaults objectForKey:kMPSettingsKeyGlobalAutotypeDelay]) {
/* limit the delay to 1000 ms */
delay = (useconds_t)MIN([NSUserDefaults.standardUserDefaults integerForKey:kMPSettingsKeyGlobalAutotypeDelay], 1000);
}
useconds_t globalDelay = 0;
for(MPAutotypeCommand *command in [MPAutotypeCommand commandsForContext:context]) {
/*
FIXME: Introduce a global state for execution to allow command to set state value
e.g. [command executeWithContext:(MPCommandExectionContext *)context]
and inside the command set the sate e.g. context.delay = myDelay
then use this state in the command scheduling to set the global delay
*/
if([command isKindOfClass:MPAutotypeDelay.class]) {
MPAutotypeDelay *delayCommand = (MPAutotypeDelay *)command;
if(delayCommand.isGlobal) {
globalDelay = (useconds_t)delayCommand.delay;
}
}
/* dispatch commands to main thread since most of them translate key events which is disallowed on background thread */
dispatch_async(dispatch_get_main_queue(), ^{
if(delay > 0) {
usleep(delay * NSEC_PER_MSEC);
if(globalDelay > 0) {
usleep(globalDelay*NSEC_PER_USEC);
}
[command execute];
});

View File

@ -25,6 +25,7 @@
@interface MPAutotypeDelay : MPAutotypeCommand
@property (readonly) NSUInteger delay;
@property (readonly) BOOL isGlobal;
/**
* Creates an DelayCommand that delays the execution for n milliseconds
*
@ -33,5 +34,6 @@
* @return <#return value description#>
*/
- (instancetype)initWithDelay:(NSUInteger)delay;
- (instancetype)initWithGlobalDelay:(NSUInteger)delay;
@end

View File

@ -29,7 +29,7 @@
@implementation MPAutotypeDelay
- (id)init {
self = [self initWithDelay:0];
self = [self _initWithDelay:0 global:NO];
return self;
}
@ -38,17 +38,32 @@
}
- (instancetype)initWithDelay:(NSUInteger)delay {
self = [self _initWithDelay:delay global:NO];
return self;
}
- (instancetype)initWithGlobalDelay:(NSUInteger)delay {
self = [self _initWithDelay:delay global:YES];
return self;
}
- (instancetype)_initWithDelay:(NSUInteger)delay global:(BOOL)global {
self = [super init];
if(self) {
_isGlobal = global;
/* Delays longer than a minute are a bit long */
_delay = MIN(60*1000,delay);
_delay = MIN(60*NSEC_PER_USEC,delay);
}
return self;
}
- (void)execute {
/* milliseconds * 10000 = microseconds */
usleep((useconds_t)(self.delay*1000));
if(self.isGlobal) {
return; // global delays should not be executed locally
}
usleep((useconds_t)(self.delay*NSEC_PER_USEC));
}
@end

View File

@ -281,7 +281,7 @@ static CGKeyCode kMPNumpadKeyCodes[] = {
static NSRegularExpression *delayRegExp;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *delayPattern = [[NSString alloc] initWithFormat:@"\\{(%@|%@)[ |=]+([0-9]+)\\}",
NSString *delayPattern = [[NSString alloc] initWithFormat:@"\\{(%@|%@)([ |=])+([0-9]+)\\}",
kKPKAutotypeDelay,
kKPKAutotypeVirtualKey/*,
kKPKAutotypeVirtualExtendedKey,
@ -327,9 +327,10 @@ static CGKeyCode kMPNumpadKeyCodes[] = {
// TODO: add {APPLICATION <appname>}
/* Delay */
NSTextCheckingResult *result = [delayRegExp firstMatchInString:commandString options:0 range:NSMakeRange(0, commandString.length)];
if(result && (result.numberOfRanges == 3)) {
if(result && (result.numberOfRanges == 4)) {
NSString *uppercaseCommand = [[commandString substringWithRange:[result rangeAtIndex:1]] uppercaseString];
NSString *valueString = [commandString substringWithRange:[result rangeAtIndex:2]];
NSString *assignOrNot = [commandString substringWithRange:[result rangeAtIndex:2]];
NSString *valueString = [commandString substringWithRange:[result rangeAtIndex:3]];
NSScanner *numberScanner = [[NSScanner alloc] initWithString:valueString];
NSInteger value;
if([numberScanner scanInteger:&value]) {
@ -337,7 +338,12 @@ static CGKeyCode kMPNumpadKeyCodes[] = {
if(MAX(0, value) <= 0) {
return; // Value too low, just skipp
}
[self.mutableCommands addObject:[[MPAutotypeDelay alloc] initWithDelay:value]];
if([assignOrNot isEqualToString:@"="]) {
[self.mutableCommands addObject:[[MPAutotypeDelay alloc] initWithGlobalDelay:value]];
}
else {
[self.mutableCommands addObject:[[MPAutotypeDelay alloc] initWithDelay:value]];
}
return; // Done
}
else if([kKPKAutotypeVirtualKey isEqualToString:uppercaseCommand]) {

View File

@ -31,7 +31,7 @@
[super tearDown];
}
- (void)testValidDelayCommands {
- (void)testLocalDelayCommands {
/* Command 1 */
MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"{DELAY 200}"];
NSArray *commands = [MPAutotypeCommand commandsForContext:context];
@ -41,8 +41,23 @@
XCTAssertTrue([commands.firstObject isKindOfClass:[MPAutotypeDelay class]], @"Command is Delay command");
MPAutotypeDelay *delay = commands.firstObject;
XCTAssertEqual(delay.delay, 200, @"Delay is 200 ms");
XCTAssertFalse(delay.isGlobal, @"Delay is no global delay");
}
- (void)testGlobalDelayCommands {
/* Command 1 */
MPAutotypeContext *context = [[MPAutotypeContext alloc] initWithEntry:self.entry andSequence:@"{DELAY=200}"];
NSArray *commands = [MPAutotypeCommand commandsForContext:context];
XCTAssertEqual(commands.count, 1);
/* {DELAY=200} */
XCTAssertTrue([commands.firstObject isKindOfClass:MPAutotypeDelay.class], @"Command is Delay command");
MPAutotypeDelay *delay = commands.firstObject;
XCTAssertEqual(delay.delay, 200, @"Delay is 200 ms");
XCTAssertTrue(delay.isGlobal, @"Delay is global delay");
}
- (void)testDelayExecution {
MPAutotypeDelay *delay = [[MPAutotypeDelay alloc] initWithDelay:200];
XCTestExpectation *expectation = [self expectationWithDescription:delay.description];