From e9c351d109439ca27c472f0d8d5f8a530ce24033 Mon Sep 17 00:00:00 2001 From: BossCode45 Date: Sat, 4 Jan 2025 20:28:39 +1300 Subject: revert: Added the commands library back to the source --- YATwm.nix | 1 - flake.lock | 6 +- flake.nix | 5 - makefile | 3 +- src/IPC.h | 2 +- src/commands.cpp | 372 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/commands.h | 91 ++++++++++++++ src/config.cpp | 5 +- src/config.h | 2 +- src/keybinds.cpp | 5 +- src/keybinds.h | 2 +- 11 files changed, 475 insertions(+), 19 deletions(-) create mode 100644 src/commands.cpp create mode 100644 src/commands.h diff --git a/YATwm.nix b/YATwm.nix index 515fad5..be7cd2d 100644 --- a/YATwm.nix +++ b/YATwm.nix @@ -33,6 +33,5 @@ runHook postInstall xorg.libXrandr libnotify pkg-config - inputs.libCommands.packages.x86_64-linux.default ]; } diff --git a/flake.lock b/flake.lock index d22a24f..af0e49b 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1734323986, - "narHash": "sha256-m/lh6hYMIWDYHCAsn81CDAiXoT3gmxXI9J987W5tZrE=", + "lastModified": 1735141468, + "narHash": "sha256-VIAjBr1qGcEbmhLwQJD6TABppPMggzOvqFsqkDoMsAY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "394571358ce82dff7411395829aa6a3aad45b907", + "rev": "4005c3ff7505313cbc21081776ad0ce5dfd7a3ce", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index da92073..8d97f64 100644 --- a/flake.nix +++ b/flake.nix @@ -2,10 +2,6 @@ description = "YATwm"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; - libCommands = { - url = "github:BossCode45/commands"; - inputs.nixpkgs.follows = "nixpkgs"; - }; }; outputs = { self, nixpkgs, ... }@inputs: let pkgs = nixpkgs.legacyPackages.x86_64-linux; @@ -20,7 +16,6 @@ pkgs.libnotify pkgs.pkg-config pkgs.clang-tools - inputs.libCommands.packages.x86_64-linux.default ]; }; packages.x86_64-linux.YATwm = (pkgs.callPackage ./YATwm.nix {inherit inputs;}); diff --git a/makefile b/makefile index 3a12ea4..991a02a 100644 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ .PHONY: clean CXX := g++ CXXFLAGS := -std=c++17 `pkg-config --cflags --libs libnotify`# -g -fsanitize=address -fno-omit-frame-pointer -LINKFLAGS := -lX11 -lXrandr -lcommands +LINKFLAGS := -lX11 -lXrandr OBJS_DIR := ./build OUT_DIR := ./out SOURCE_DIR := ./src @@ -32,6 +32,7 @@ remove: r #Files to be compiled $(OBJS_DIR)/main.o: $(SOURCE_FILES) $(SOURCE_HEADERS) $(OBJS_DIR)/ewmh.o: $(SOURCE_DIR)/ewmh.cpp $(SOURCE_DIR)/ewmh.h +$(OBJS_DIR)/command.o: $(SOURCE_DIR)/commands.cpp $(SOURCE_DIR)/commands.h $(SOURCE_DIR)/util.h $(SOURCE_DIR)/error.h $(OBJS_DIR)/util.o: $(SOURCE_DIR)/util.cpp $(SOURCE_DIR)/util.h $(OBJS_DIR)/config.o: $(SOURCE_DIR)/config.cpp $(SOURCE_DIR)/config.h $(OBJS_DIR)/keybinds.o: $(SOURCE_DIR)/keybinds.cpp $(SOURCE_DIR)/keybinds.h diff --git a/src/IPC.h b/src/IPC.h index 0705c2b..e0bbcee 100644 --- a/src/IPC.h +++ b/src/IPC.h @@ -3,7 +3,7 @@ #include #include -#include +#include "commands.h" #include "config.h" #include "util.h" diff --git a/src/commands.cpp b/src/commands.cpp new file mode 100644 index 0000000..caa82eb --- /dev/null +++ b/src/commands.cpp @@ -0,0 +1,372 @@ +#include "commands.h" +#include "error.h" +#include "util.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::cout, std::endl, std::string, std::vector; + +const void CommandsModule::echo(const CommandArg* argv) +{ + cout << argv[0].str << endl; +} + +const void CommandsModule::loadFile(const CommandArg* argv) +{ + std::vector errs; + + string path = cwd + "/" + std::string(argv[0].str); + + std::ifstream file(path); + if(!file.good()) + throw Err(CMD_ERR_NON_FATAL, "File '" + std::string(argv[0].str) + "' doesn't exist"); + + string prevCWD = cwd; + cwd = std::filesystem::path(path).parent_path(); + + cout << "Loading file '" << argv[0].str << "'" << endl; + + int line = 0; + for(string cmd; std::getline(file, cmd);) + { + line++; + if(cmd.size() == 0) + continue; + if(cmd.at(0) == '#') + continue; + try + { + this->runCommand(cmd); + } + catch (Err e) + { + throw Err(e.code, "Error in file '" + std::string(argv[0].str) + "' (line " + std::to_string(line) + "): " + std::to_string(e.code) + "\n\tMessage: " + e.message); + } + } + + cwd = prevCWD; +} + +CommandsModule::CommandsModule() +{ + addCommand("echo", &CommandsModule::echo, 1, {STR_REST}, this); + addCommand("loadFile", &CommandsModule::loadFile, 1, {STR_REST}, this); + cwd = std::filesystem::current_path(); +} +CommandsModule::~CommandsModule() +{ + for(Command c : commandList) + { + if(c.argc > 0) + delete[] c.argTypes; + } +} + +void CommandsModule::addCommand(Command c) +{ + if(lookupCommand(c.name) != nullptr) + { + cout << "Duplicate command: " << c.name << endl; + } + commandList.push_back(c); +} +void CommandsModule::addCommand(std::string name, const void (*func)(const CommandArg *), const int argc, CommandArgType *argTypes) +{ + Command c = {name, nullptr, func, argc, argTypes, nullptr}; + addCommand(c); +} +void CommandsModule::addCommand(std::string name, const void(*func)(const CommandArg*), const int argc, std::vector argTypes) +{ + CommandArgType* argTypesArr = new CommandArgType[argc]; + for(int i = 0; i < argc; i++) + { + argTypesArr[i] = argTypes[i]; + } + addCommand(name, func, argc, argTypesArr); +} + +struct NameMatches +{ + NameMatches(string s): s_{s} {} + bool operator()(Command c) { return (c.name == s_); } + string s_; +}; + +Command* CommandsModule::lookupCommand(string name) +{ + auto elem = std::find_if(commandList.begin(), commandList.end(), NameMatches(name)); + if (elem != commandList.end()) + { + int i = elem - commandList.begin(); + return &(commandList[i]); + } + else + { + return nullptr; + } +} + +vector CommandsModule::splitCommand(string command) +{ + vector v; + string arg = ""; + bool inQuotes = false; + bool escapeNext = true; + char quoteType; + for(int i = 0; i < command.size(); i++) + { + if(escapeNext) + { + arg += command[i]; + escapeNext = false; + } + else if(command[i] == '\\') + { + escapeNext = true; + } + else if(inQuotes) + { + if(command[i] == quoteType) + { + if(arg != "") + { + v.push_back(arg); + arg = ""; + } + inQuotes = false; + } + else + { + arg += command[i]; + } + } + else + { + if(command[i] == ' ') + { + if(arg != "") + { + v.push_back(arg); + arg = ""; + } + } + else if(command[i] == '"' || command[i] == '\'') + { + inQuotes = true; + quoteType = command[i]; + } + else + { + arg += command[i]; + } + } + } + if(arg != "") + v.push_back(arg); + return v; +} + +CommandArg* CommandsModule::getCommandArgs(vector& split, const CommandArgType* argTypes, const int argc) +{ + CommandArg* args = new CommandArg[argc]; + for(int i = 1; i < argc + 1; i++) + { + switch(argTypes[i-1]) + { + case STR: args[i-1].str = (char*)split[i].c_str(); break; + case NUM: + { + try + { + args[i-1].num = std::stoi(split[i]); + break; + } + catch(std::invalid_argument e) + { + delete[] args; + throw Err(CMD_ERR_WRONG_ARGS, split[i] + " is not a number!"); + } + } + case MOVDIR: + { + if(lowercase(split[i]) == "up") + args[i-1].dir = UP; + else if(lowercase(split[i]) == "down") + args[i-1].dir = DOWN; + else if(lowercase(split[i]) == "left") + args[i-1].dir = LEFT; + else if(lowercase(split[i]) == "right") + args[i-1].dir = RIGHT; + else + { + delete[] args; + throw Err(CMD_ERR_WRONG_ARGS, split[i] + " is not a direction!"); + } + break; + } + case STR_REST: + { + string rest = ""; + for(int j = i; j < split.size(); j++) + { + rest += split[j]; + if(j != split.size() - 1) + rest += " "; + } + args[i-1].str = new char[rest.size()]; + strncpy(args[i-1].str, rest.c_str(), rest.size()); + return args; + } + case NUM_ARR_REST: + { + int* rest = new int[split.size() - i]; + for(int j = 0; j < split.size() - i; j++) + { + try + { + rest[j] = std::stoi(split[j + i]); + } + catch(std::invalid_argument e) + { + delete[] rest; + delete[] args; + throw Err(CMD_ERR_WRONG_ARGS, split[i] + " is not a number!"); + } + } + args[i-1].numArr = {rest, (int) split.size() - i}; + return args; + } + default: cout << "UH OH SOMETHING IS VERY WRONG" << endl; + } + } + return args; +} + +void CommandsModule::runCommand(string command) +{ + vector split = splitCommand(command); + vector::const_iterator start = split.begin(); + int count = 0; + for(string s : split) + { + if(s == ";") + { + vector::const_iterator end = start + count; + vector partialCmd(start, end); + runCommand(partialCmd); + count = 0; + start = end + 1; + } + else + { + count++; + } + } + if(start != split.end()) + { + vector partialCmd(start, (vector::const_iterator)split.end()); + runCommand(partialCmd); + } +} +void CommandsModule::runCommand(vector split) +{ + Command* cmd = lookupCommand(split[0]); + if(cmd == nullptr) + throw Err(CMD_ERR_NOT_FOUND, split[0] + " is not a valid command name"); + if(cmd->argc > split.size() - 1) + throw Err(CMD_ERR_WRONG_ARGS, "wrong number of arguments"); + CommandArg* args; + try + { + args = getCommandArgs(split, cmd->argTypes, cmd->argc); + } + catch(Err e) + { + throw e; + } + try + { + if(cmd->module == nullptr) + cmd->staticFunc(args); + else + cmd->func(*cmd->module, args); + } + catch (Err e) + { + for(int i = 0; i < cmd->argc; i++) + { + if(cmd->argTypes[i] == STR_REST) + delete[] args[i].str; + } + delete[] args; + throw e; + } + for(int i = 0; i < cmd->argc; i++) + { + if(cmd->argTypes[i] == STR_REST) + delete[] args[i].str; + } + delete[] args; +} + +vector CommandsModule::checkCommand(string command) +{ + vector errs; + vector split = splitCommand(command); + vector::const_iterator start = split.begin(); + int count = 0; + for(string s : split) + { + if(s == ";") + { + vector::const_iterator end = start + count; + vector partialCmd(start, end); + errs.push_back(checkCommand(partialCmd)); + count = 0; + start = end + 1; + } + else + { + count++; + } + } + if(start != split.end()) + { + vector partialCmd(start, (vector::const_iterator)split.end()); + errs.push_back(checkCommand(partialCmd)); + } + return errs; +} + +Err CommandsModule::checkCommand(vector split) +{ + Command* cmd = lookupCommand(split[0]); + if(cmd == nullptr) + return Err(CMD_ERR_NOT_FOUND, split[0] + " is not a valid command name"); + if(cmd->argc > split.size()) + return Err(CMD_ERR_WRONG_ARGS, "wrong number of arguments"); + CommandArg* args; + try + { + args = getCommandArgs(split, cmd->argTypes, cmd->argc); + } + catch(Err e) + { + return e; + } + for(int i = 0; i < cmd->argc; i++) + { + if(cmd->argTypes[i] == STR_REST || cmd->argTypes[i] == NUM_ARR_REST) + delete[] args[i].str; + } + delete[] args; + return Err(NOERR, ""); +} diff --git a/src/commands.h b/src/commands.h new file mode 100644 index 0000000..4825f1c --- /dev/null +++ b/src/commands.h @@ -0,0 +1,91 @@ +#pragma once + +#include "error.h" + +#include +#include +#include +#include + +enum MoveDir + { + UP, + RIGHT, + DOWN, + LEFT + }; +enum CommandArgType + { + STR, + NUM, + MOVDIR, + STR_REST, + NUM_ARR_REST + }; + +struct NumArr +{ + int* arr; + int size; +}; +typedef union +{ + char* str; + int num; + NumArr numArr; + MoveDir dir; +} CommandArg; + +struct Command +{ + const std::string name; + const std::function func; + const std::function staticFunc; + const int argc; + CommandArgType* argTypes; + std::any* module; +}; +class CommandsModule +{ +private: + std::vector commandList; + std::vector splitCommand(std::string command); + CommandArg* getCommandArgs(std::vector& args, const CommandArgType* argTypes, const int argc); + const void echo(const CommandArg* argv); + const void loadFile(const CommandArg* argv); + std::string cwd; +public: + CommandsModule(); + ~CommandsModule(); + template + void addCommand(std::string name, const void(T::*func)(const CommandArg*), const int argc, CommandArgType* argTypes, T* module); + void addCommand(std::string name, const void(*func)(const CommandArg*), const int argc, CommandArgType* argTypes); + template + void addCommand(std::string name, const void(T::*func)(const CommandArg*), const int argc, std::vector argTypes, T* module); + void addCommand(std::string name, const void(*func)(const CommandArg*), const int argc, std::vector argTypes); + void addCommand(Command c); + Command* lookupCommand(std::string name); + void runCommand(std::string command); + void runCommand(std::vector split); + std::vector checkCommand(std::string command); + Err checkCommand(std::vector split); +}; + +// YES I KNOW THIS IS BAD +// but it needs to be done this way +template +void CommandsModule::addCommand(std::string name, const void(T::*func)(const CommandArg*), const int argc, CommandArgType* argTypes, T* module) +{ + Command c = {name, (const void*(std::any::*)(const CommandArg* argv)) func, nullptr, argc, argTypes, (std::any*)module}; + addCommand(c); +} +template +void CommandsModule::addCommand(std::string name, const void(T::*func)(const CommandArg*), const int argc, std::vector argTypes, T* module) +{ + CommandArgType* argTypesArr = new CommandArgType[argc]; + for(int i = 0; i < argc; i++) + { + argTypesArr[i] = argTypes[i]; + } + addCommand(name, func, argc, argTypesArr, module); +} diff --git a/src/config.cpp b/src/config.cpp index df195aa..925e6ea 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1,7 +1,6 @@ #include "config.h" -#include -//TODO: FIX THIS -#include +#include "commands.h" +#include "error.h" #include diff --git a/src/config.h b/src/config.h index b04753f..55e4fd3 100644 --- a/src/config.h +++ b/src/config.h @@ -2,7 +2,7 @@ #include #include -#include +#include "commands.h" #include #include diff --git a/src/keybinds.cpp b/src/keybinds.cpp index 127a534..235f8c1 100644 --- a/src/keybinds.cpp +++ b/src/keybinds.cpp @@ -7,9 +7,8 @@ #include #include -#include -//TODO: FIX THIS -#include +#include "commands.h" +#include "error.h" #include "keybinds.h" #include "util.h" diff --git a/src/keybinds.h b/src/keybinds.h index 5fd4fba..a742240 100644 --- a/src/keybinds.h +++ b/src/keybinds.h @@ -8,7 +8,7 @@ #include #include -#include +#include "commands.h" #include "config.h" #include "util.h" -- cgit v1.2.3