diff --git a/.gitignore b/.gitignore index 0b7bda4..8b186c9 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ /DerivedData /build cliclick +.DS_Store ActionClassesMacro.h diff --git a/Actions/ScheduleAction.h b/Actions/ScheduleAction.h new file mode 100644 index 0000000..1ed8572 --- /dev/null +++ b/Actions/ScheduleAction.h @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2007-2021, Carsten Blüm + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * - Neither the name of Carsten Blüm nor the names of his contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import "ActionProtocol.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ScheduleAction : NSObject { + +} + ++ (NSString *)commandShortcut; + +- (void)performActionWithData:(NSString *)data + withOptions:(struct ExecutionOptions)options; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Actions/ScheduleAction.m b/Actions/ScheduleAction.m new file mode 100644 index 0000000..7af76ae --- /dev/null +++ b/Actions/ScheduleAction.m @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2007-2021, Carsten Blüm + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * - Neither the name of Carsten Blüm nor the names of his contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ScheduleAction.h" + +@implementation ScheduleAction + +#pragma mark - ActionProtocol + ++ (NSString *)commandShortcut { + return @"s"; +} + ++ (NSString *)commandDescription { + return @" s:UTC(s) Will WAIT/PAUSE until reach the giving UTC(s) time.\n" + " Example: “s:1668172060” will pause command execution until 2022-11-11 21:07:40"; +} + +- (void)performActionWithData:(NSString *)data + withOptions:(struct ExecutionOptions)options { + + NSTimeInterval targetUTC = [data doubleValue]; + NSString *shortcut = [[self class] commandShortcut]; + + if ([data isEqualToString:@""] || + !targetUTC) { + [NSException raise:@"InvalidCommandException" + format:@"Invalid or missing argument to command “%@”: Expected number of milliseconds. Example: “%@:50”", shortcut, shortcut]; + } + + if (MODE_REGULAR != options.mode) { + [options.verbosityOutputHandler write:[NSString stringWithFormat:@"schedule UTC :%.3f", targetUTC]]; + } + + if (MODE_TEST == options.mode) { + return; + } + + NSDate *target = [NSDate dateWithTimeIntervalSince1970:targetUTC]; + NSTimeInterval waitTime = [target timeIntervalSinceNow]; + if (waitTime < 0.1) { + waitTime = 0.1; + } + unsigned milliseconds = waitTime * 1000; + + struct timespec waitingtime; + if (milliseconds > 999) { + waitingtime.tv_sec = (int)floor(milliseconds / 1000); + waitingtime.tv_nsec = (milliseconds - waitingtime.tv_sec * 1000) * 1000000; + } else { + waitingtime.tv_sec = 0; + waitingtime.tv_nsec = milliseconds * 1000000; + } + + nanosleep(&waitingtime, NULL); +} + +@end diff --git a/Makefile b/Makefile index 4e0ff7e..9029821 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ cliclick: Actions/ClickAction.o \ Actions/TripleclickAction.o \ Actions/TypeAction.o \ Actions/WaitAction.o \ + Actions/ScheduleAction.o \ ActionExecutor.o \ KeycodeInformer.o \ OutputHandler.o \ diff --git a/cliclick.xcodeproj/project.pbxproj b/cliclick.xcodeproj/project.pbxproj index 38dce5e..6704816 100644 --- a/cliclick.xcodeproj/project.pbxproj +++ b/cliclick.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 5B9FEE9A1DDF5E6F0020F6F6 /* RightClickAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B9FEE991DDF5E6F0020F6F6 /* RightClickAction.m */; }; 8DD76F9A0486AA7600D96B5E /* cliclick.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* cliclick.m */; settings = {ATTRIBUTES = (); }; }; 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; }; + 9B5B99E7291E7C6700C0B243 /* ScheduleAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5B99E6291E7C6700C0B243 /* ScheduleAction.m */; }; F0A674F818EE2D0C0062FD29 /* DragDownAction.m in Sources */ = {isa = PBXBuildFile; fileRef = F0A674F718EE2D0C0062FD29 /* DragDownAction.m */; }; F0A674FB18EE3F220062FD29 /* DragUpAction.m in Sources */ = {isa = PBXBuildFile; fileRef = F0A674FA18EE3F220062FD29 /* DragUpAction.m */; }; /* End PBXBuildFile section */ @@ -98,6 +99,8 @@ 5B9FEE981DDF5E6F0020F6F6 /* RightClickAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RightClickAction.h; path = Actions/RightClickAction.h; sourceTree = ""; }; 5B9FEE991DDF5E6F0020F6F6 /* RightClickAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RightClickAction.m; path = Actions/RightClickAction.m; sourceTree = ""; }; 8DD76FA10486AA7600D96B5E /* cliclick */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cliclick; sourceTree = BUILT_PRODUCTS_DIR; }; + 9B5B99E5291E7C6700C0B243 /* ScheduleAction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ScheduleAction.h; path = Actions/ScheduleAction.h; sourceTree = ""; }; + 9B5B99E6291E7C6700C0B243 /* ScheduleAction.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ScheduleAction.m; path = Actions/ScheduleAction.m; sourceTree = ""; }; F0A674F618EE2D0C0062FD29 /* DragDownAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DragDownAction.h; path = Actions/DragDownAction.h; sourceTree = ""; }; F0A674F718EE2D0C0062FD29 /* DragDownAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DragDownAction.m; path = Actions/DragDownAction.m; sourceTree = ""; }; F0A674F918EE3F220062FD29 /* DragUpAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DragUpAction.h; path = Actions/DragUpAction.h; sourceTree = ""; }; @@ -233,6 +236,8 @@ 22E5626616BA589200CD5D86 /* PrintAction.m */, 22E5626916BA589200CD5D86 /* WaitAction.h */, 22E5626A16BA589200CD5D86 /* WaitAction.m */, + 9B5B99E5291E7C6700C0B243 /* ScheduleAction.h */, + 9B5B99E6291E7C6700C0B243 /* ScheduleAction.m */, ); name = OtherActions; sourceTree = ""; @@ -322,7 +327,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "KEYWORDS=\"TODO:|FIXME:\"\nfind \"${SRCROOT}\" \\( -name \"*.h\" -or -name \"*.m\" \\) -print0 | \\\n xargs -0 egrep --with-filename --line-number --only-matching \"($KEYWORDS).*\\$\" | \\\n perl -p -e \"s/($KEYWORDS)/ warning: \\$1/\""; + shellScript = "KEYWORDS=\"TODO:|FIXME:\"\nfind \"${SRCROOT}\" \\( -name \"*.h\" -or -name \"*.m\" \\) -print0 | \\\n xargs -0 egrep --with-filename --line-number --only-matching \"($KEYWORDS).*\\$\" | \\\n perl -p -e \"s/($KEYWORDS)/ warning: \\$1/\"\n"; }; 22D9A7B019A46A00004F4CEE /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -335,7 +340,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "./generate-action-classes-macro.sh"; + shellScript = "./generate-action-classes-macro.sh\n"; }; 22F0E20215D9AAC600158334 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -377,6 +382,7 @@ 5B9FEE9A1DDF5E6F0020F6F6 /* RightClickAction.m in Sources */, 226347791B998B80003C5D71 /* ColorPickerAction.m in Sources */, 22C0ECEE16BAFD9800E3A46C /* KeyBaseAction.m in Sources */, + 9B5B99E7291E7C6700C0B243 /* ScheduleAction.m in Sources */, F0A674F818EE2D0C0062FD29 /* DragDownAction.m in Sources */, F0A674FB18EE3F220062FD29 /* DragUpAction.m in Sources */, );