From 871b559962bde4154eea2228fefd2394f89531cc Mon Sep 17 00:00:00 2001 From: Reimu NotMoe <34613827+ReimuNotMoe@users.noreply.github.com> Date: Sat, 24 Nov 2018 22:20:14 +0800 Subject: [PATCH] Initial commit --- CMakeLists.txt | 12 ++++ Commands.cpp | 20 ++++++ Commands.hpp | 26 ++++++++ Commands/Type.cpp | 163 +++++++++++++++++++++++++++++++++++++++++++++ CommonIncludes.hpp | 25 +++++++ LICENSE | 21 ++++++ README.md | 24 +++++++ ydotool.cpp | 55 +++++++++++++++ 8 files changed, 346 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 Commands.cpp create mode 100644 Commands.hpp create mode 100644 Commands/Type.cpp create mode 100644 CommonIncludes.hpp create mode 100644 LICENSE create mode 100644 README.md create mode 100644 ydotool.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1762c6f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.8) +project(ydotool) + +set(CMAKE_CXX_STANDARD 11) + +set(SOURCE_FILES + ydotool.cpp CommonIncludes.hpp Commands.hpp Commands.cpp + Commands/Type.cpp) + + +add_executable(ydotool ${SOURCE_FILES}) +target_link_libraries(ydotool boost_program_options uInputPlus) \ No newline at end of file diff --git a/Commands.cpp b/Commands.cpp new file mode 100644 index 0000000..9ed1a15 --- /dev/null +++ b/Commands.cpp @@ -0,0 +1,20 @@ +/* + This file is part of ydotool. + Copyright (C) 2018 ReimuNotMoe + + This program is free software: you can redistribute it and/or modify + it under the terms of the MIT License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#include "Commands.hpp" + +std::unordered_map CommandTable; + +void InitCommands() { + CommandTable["type"] = (void *)Command_Type; + +} \ No newline at end of file diff --git a/Commands.hpp b/Commands.hpp new file mode 100644 index 0000000..0233e11 --- /dev/null +++ b/Commands.hpp @@ -0,0 +1,26 @@ +/* + This file is part of ydotool. + Copyright (C) 2018 ReimuNotMoe + + This program is free software: you can redistribute it and/or modify + it under the terms of the MIT License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#ifndef YDOTOOL_COMMANDS_HPP +#define YDOTOOL_COMMANDS_HPP + +#include "CommonIncludes.hpp" + +extern std::unordered_map CommandTable; + +extern void InitCommands(); + +namespace po = boost::program_options; + +extern int Command_Type(int argc, const char *argv[]); + +#endif //YDOTOOL_COMMANDS_HPP diff --git a/Commands/Type.cpp b/Commands/Type.cpp new file mode 100644 index 0000000..a5a7448 --- /dev/null +++ b/Commands/Type.cpp @@ -0,0 +1,163 @@ +/* + This file is part of ydotool. + Copyright (C) 2018 ReimuNotMoe + + This program is free software: you can redistribute it and/or modify + it under the terms of the MIT License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#include "../Commands.hpp" + + +using namespace uInputPlus; + +static uInput *uInput1 = nullptr; +static int time_keydelay = 12; + +static void ShowHelp(){ + fprintf(stderr, "Usage: type [--delay milliseconds] [--key-delay milliseconds] [--args N] [--file ] \n" + " --help Show this help\n" + " --delay milliseconds Delay time before start typing\n" + " --key-delay milliseconds Delay time between keystrokes. Default 12ms\n" + " --args N How many arguments to expect in the exec command. This \n" + " is useful for ending an exec and continuing with more \n" + " ydotool commands\n" + " --file filepath Specify a file, the contents of which will be be typed \n" + " as if passed as an argument. The filepath may also be \n" + " '-' to read from stdin\n"); + +} + +static int TypeText(const std::string &text) { + int pos = 0; + + for (auto &c : text) { + + int isUpper = 0; + + int key_code; + + auto itk = KeyTextStringTable.find(c); + + if (itk != KeyTextStringTable.end()) { + key_code = itk->second; + } else { + auto itku = KeyTextStringTableUpper.find(c); + if (itku != KeyTextStringTableUpper.end()) { + isUpper = 1; + key_code = itku->second; + } else { + return -(pos+1); + } + } + + int sleep_time; + + if (isUpper) { + sleep_time = 250 * time_keydelay; + uInput1->SendKey(KEY_LEFTSHIFT, 1); + usleep(sleep_time); + } else { + sleep_time = 500 * time_keydelay; + } + + uInput1->SendKey(key_code, 1); + usleep(sleep_time); + uInput1->SendKey(key_code, 0); + usleep(sleep_time); + + + if (isUpper) { + uInput1->SendKey(KEY_LEFTSHIFT, 0); + usleep(sleep_time); + } + + } + + return pos; +} + +int Command_Type(int argc, const char *argv[]) { + + printf("argc = %d\n", argc); + + for (int i=1; i extra_args; + + try { + + po::options_description desc(""); + desc.add_options() + ("help", "Show this help") + ("delay", po::value()) + ("key-delay", po::value()) + ("args", po::value()) + ("file", po::value()) + ("extra-args", po::value(&extra_args)); + + + po::positional_options_description p; + p.add("extra-args", -1); + + + po::variables_map vm; + po::store(po::command_line_parser(argc, argv). + options(desc). + positional(p). + run(), vm); + po::notify(vm); + + + if (vm.count("help")) { + ShowHelp(); + return -1; + } + + if (vm.count("delay")) { + time_delay = vm["delay"].as(); + std::cerr << "Delay was set to " + << time_delay << " milliseconds.\n"; + } + + if (vm.count("key-delay")) { + time_keydelay = vm["key-delay"].as(); + std::cerr << "Key delay was set to " + << time_keydelay << " milliseconds.\n"; + } + + if (vm.count("args")) { + args_count = vm["args"].as(); + std::cerr << "Argument count was set to " + << args_count << ".\n"; + } + + + } catch (std::exception &e) { + fprintf(stderr, "ydotool: type: error: %s\n", e.what()); + return 2; + } + + uInput1 = new uInput(uInputSetup(uInputDeviceInfo("ydotool virtual device"))); + + if (time_delay) + usleep(time_delay * 1000); + + for (auto &txt : extra_args) { + TypeText(txt); + } + + return argc; + +} \ No newline at end of file diff --git a/CommonIncludes.hpp b/CommonIncludes.hpp new file mode 100644 index 0000000..1f6ccee --- /dev/null +++ b/CommonIncludes.hpp @@ -0,0 +1,25 @@ +/* + This file is part of ydotool. + Copyright (C) 2018 ReimuNotMoe + + This program is free software: you can redistribute it and/or modify + it under the terms of the MIT License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#ifndef YDOTOOL_COMMONINCLUDES_HPP +#define YDOTOOL_COMMONINCLUDES_HPP + + +#include +#include +#include + +#include + +#include + +#endif //YDOTOOL_COMMONINCLUDES_HPP diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7bd419e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Reimu NotMoe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..4ea2b92 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# ydotool +Generic Linux command-line automation tool (no X!) + +## Usage +Replace `x` with `y`. :P + +Currently implemented command(s): +- type + +## Compatibility +You can use it on anything as long as it accepts keyboard/mouse/whatever input. For example, wayland, text console, etc. + +## Build +### Dependencies +- [uInputPlus](https://github.com/YukiWorkshop/libuInputPlus) +- boost::program_options + +### Compile +Nearly all my projects use CMake. It's very simple: + + mkdir build + cd build + cmake .. + make -j `nproc` diff --git a/ydotool.cpp b/ydotool.cpp new file mode 100644 index 0000000..ba2331f --- /dev/null +++ b/ydotool.cpp @@ -0,0 +1,55 @@ +/* + This file is part of ydotool. + Copyright (C) 2018 ReimuNotMoe + + This program is free software: you can redistribute it and/or modify + it under the terms of the MIT License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#include "CommonIncludes.hpp" +#include "Commands.hpp" + +static void ShowHelp() { + fprintf(stderr, "Usage: ydotool \n" + "Available commands:\n"); + + for (auto &it : CommandTable) { + fprintf(stderr, " %s\n", it.first.c_str()); + } + +} + +int main(int argc, const char **argv) { + + InitCommands(); + + if (argc < 2) { + ShowHelp(); + exit(1); + } + + if (strncmp(argv[1], "-h", 2) == 0 || strncmp(argv[1], "--h", 3) == 0 || strcmp(argv[1], "help") == 0) { + ShowHelp(); + exit(1); + } + + auto it_cmd = CommandTable.find(argv[1]); + + if (it_cmd == CommandTable.end()) { + fprintf(stderr, "ydotool: Unknown command: %s\n" + "Run 'ydotool help' if you want a command list\n", argv[1]); + exit(1); + } + + auto command = (int (*)(int, const char *[]))it_cmd->second; + + fprintf(stderr, "ydotool: Executing `%s' at %p\n", argv[1], command); + + int rc = command(argc-1, &argv[1]); + + +} \ No newline at end of file