commit e9eb24defb885d3aa11a81b12f074bdc0d776a23 Author: UnrealDragon Date: Wed Sep 10 18:54:44 2025 +0530 goto v0.0.1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a007fea --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9eb069f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.16) + +project(helloworld VERSION 1.0.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(Qt6_DIR "/home/ud/Qt/6.9.2/gcc_64/lib/cmake/Qt6") + +find_package(Boost CONFIG) +find_package(Qt6 REQUIRED COMPONENTS Core) + +qt_add_executable(goto main.cpp) + +target_link_libraries(goto PRIVATE Qt6::Core) diff --git a/README.md b/README.md new file mode 100644 index 0000000..422b8dc --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +### Simple Goto script written in cpp. +Usage: goto [OPTION|LINK_NAME] +Options: + -h --help : Show this info + -c --create_link : Create a new link e.g: goto --create_link [LINK_NAME] [FROM_PATH] + -l --list : List all the existing links + -d --delete_link : Delete an exisiting link e.g: goto -d [LINK_NAME] + -rf --delete_file : Delete the existing link file completely. + [LINK_NAME] : Goes to an exisiting link e.g: goto [LINK_NAME] + [LINK_NAME] : Rules for creating [LINK_NAME] name must be BASH variable and must not start with "-" + [LINK_NAME] : [LINK_NAME] cannot be "last" + +### To use add a function in bash like: +```bash +function goto() { + if [[ "$#" -eq 1 ]] && [[ "$1" != -* ]]; then + out=$(/home/ud/Scripts/goto $1 2>&1) + if [[ "$?" -eq "0" ]]; then + cd "$out" + else + echo $out + fi + else + /home/ud/Scripts/goto $@ + fi +} +``` + + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..286aacc --- /dev/null +++ b/main.cpp @@ -0,0 +1,304 @@ +#include +#include +# include +# include +# include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +# include +#include +#include +# include +#include +# include + +namespace globals { + static std::filesystem::path config_path; + + std::expected read_config() { + if (std::filesystem::exists(globals::config_path)) { + std::fstream file_input(globals::config_path, std::fstream::in); + std::string data; + std::string temp; + while(std::getline(file_input, temp)) { + data += temp; + } + file_input.close(); + return QJsonDocument::fromJson(QByteArray::fromStdString(data)).object(); + } else { + return std::unexpected(false); + } + } + + void overwrite_config(QJsonObject& obj) { + QJsonDocument doc; + doc.setObject(obj); + std::string data = doc.toJson().toStdString(); + std::fstream file_input(globals::config_path, std::fstream::out); + file_input << data; + file_input.flush(); + file_input.close(); + } + +} + +std::string get_current_time() { + const auto now = std::chrono::system_clock::now(); + std::time_t ctime_now = std::chrono::system_clock::to_time_t(now); + std::stringstream ss; + ss << "[" << std::put_time(std::localtime(&ctime_now), "%d-%m-%y %H:%M:%S") << "] "; + return ss.str(); +} + +int get_parent_id() { + std::stringstream ss; + int var; + ss << getppid(); + ss >> var; + return var; +} + +void show_help() { + std::stringstream ss; + ss << "Usage: goto [OPTION|LINK_NAME]" << std::endl; + ss << "Options:" << std::endl; + ss << " -h --help : Show this info" << std::endl; + ss << " -c --create_link : Create a new link e.g: goto --create_link [LINK_NAME] [FROM_PATH]" << std::endl; + ss << " -l --list : List all the existing links" << std::endl; + ss << " -d --delete_link : Delete an exisiting link e.g: goto -d [LINK_NAME]" << std::endl; + ss << " -rf --delete_file : Delete the existing link file completely." << std::endl; + ss << " [LINK_NAME] : Goes to an exisiting link e.g: goto [LINK_NAME]" << std::endl; + ss << " [LINK_NAME] : Rules for creating [LINK_NAME] name must be BASH variable and must not start with \"-\"" << std::endl; + ss << " [LINK_NAME] : [LINK_NAME] cannot be \"last\"" << std::endl; + std::cout << ss.str(); +} + +void show_invalid() { + std::stringstream ss; + ss << "[goto] Invalid arguments use -h or --help for help" << std::endl; + std::cout << ss.str(); +} + + +void print_links() { + QJsonObject links = globals::read_config().or_else([](bool err){ + std::cout << "Could not read config file." << std::endl; + exit(-1); + return std::expected {QJsonObject()}; + }).value(); + std::unordered_map link_list; + for(auto i = links.begin(); i != links.end(); i++) { + link_list[i.key().toStdString()] = i.value().toString().toStdString(); + } + int iter = 1; + std::cout << "Links from file: " << globals::config_path << std::endl; + for(auto &[key, value]: link_list) { + if(key != "last") + std::cout << iter++ << ". " << key << " --> " << value << std::endl; + } + if(link_list.find("last") != link_list.end()) { + std::cout << iter << ". Last place --> " << link_list["last"] << std::endl; + } +} + +void delete_link(std::string link_name) { + QJsonObject obj = globals::read_config().or_else([](bool err){ + std::cout << "Could not read config file." << std::endl; + exit(-1); + return std::expected {QJsonObject()}; + }).value(); + obj.remove(QString::fromStdString(link_name)); + globals::overwrite_config(obj); + std::cout << "Link: " << link_name << " deleted." << std::endl; +} + +void create_link(std::string link_name, std::string dir) { + if(dir == ".") { + dir = std::filesystem::current_path().string(); + } + if(std::filesystem::exists(globals::config_path)) { + QJsonObject links = globals::read_config().or_else([](bool err){ + std::cout << "Could not read config file." << std::endl; + exit(-1); + return std::expected {QJsonObject()}; + }).value(); + if(links.find(QString::fromStdString(link_name)) == links.end()) + links[QString::fromStdString(link_name)] = QString::fromStdString(dir); + else { + std::string char_in; + std::cout << "Warning: Link name: " << link_name << " already exists. Do you want to overwrite it?"; + std::cout.flush(); + std::getline(std::cin, char_in); + if(char_in.size() >= 1 && (char_in[0] == 'Y' || char_in[0] == 'y')) { + std::string prev_value = links[QString::fromStdString(link_name)].toString().toStdString(); + links[QString::fromStdString(link_name)] = QString::fromStdString(dir); + globals::overwrite_config(links); + std::cout << "Overwritten link: " << link_name << " -> " << dir << " from: " << prev_value << " in: " << globals::config_path << std::endl; + exit(0); + } + else { + exit(-1); + } + } + globals::overwrite_config(links); + std::cout << "Written new link: " << link_name << " -> " << dir << " in: " << globals::config_path << std::endl; + exit(0); + } + else { + QJsonObject new_link; + new_link[QString::fromStdString(link_name)] = QString::fromStdString(dir); + globals::overwrite_config(new_link); + std::cout << "Written new link: " << link_name << " -> " << dir << " in: " << globals::config_path << std::endl; + exit(0); + } +} + +void goto_link(std::string link_name) { + QJsonObject config = globals::read_config().or_else([](bool err){ + std::cout << "Could not read config file." << std::endl; + exit(-1); + return std::expected {QJsonObject()}; + }).value(); + std::string place = config[QString::fromStdString(link_name)].toString("-_- Place Does not exist.").toStdString(); + if(place == "-_- Place Does not exist.") { + std::cout << "Specified link: " << link_name << " does not exist in links file." << std::endl; + exit(-1); + } + config["last"] = QString::fromStdString(place); + globals::overwrite_config(config); + // int parent_id = get_parent_id(); + // std::ostringstream std_out, std_err, std_log; + // + // auto prev_cout_buffer = std::cout.rdbuf(); + // auto prev_clog_buffer = std::clog.rdbuf(); + // auto prev_cerr_buffer = std::cerr.rdbuf(); + + // std::cout.rdbuf(std_out.rdbuf()); + // std::cerr.rdbuf(std_err.rdbuf()); + // std::clog.rdbuf(std_log.rdbuf()); + + std::cout << place << std::endl; + // system(std::format("sh -c cd {}", place).c_str()); + // system(std::format("kill -9 {}", parent_id).c_str()); + // QProcess *proc = new QProcess(); + // proc->setProgram("/usr/bin/bash"); + // proc->setWorkingDirectory(QString::fromStdString(place)); + // proc->startDetached(); + + // std::cout.rdbuf(prev_cout_buffer); + // std::cerr.rdbuf(prev_cerr_buffer); + // std::clog.rdbuf(prev_clog_buffer); +} + +void delete_file() { + std::string in; + std::cout << "Are you sure you want to completely remove the links.json file?"; + std::cout.flush(); + std::getline(std::cin, in); + if(in.size() >= 1 && (in[0] == 'y' || in[0] == 'Y')) { + std::filesystem::remove(globals::config_path); + std::cout << "Removed config file from: " < command_list = {{"help", 1}, {"h", 1}, {"create_link", 2}, {"c", 2}, {"l", 3}, {"list", 3}, {"d", 4}, {"delete_link", 4}, {"rf", 5}, {"delete_file", 5}}; + + + int command_size = argc - 1; + if(command_size == 0) { + show_invalid(); + exit(0); + } else { + bool arg = false; + if(std::string(argv[1]).starts_with("--") || std::string(argv[1]).starts_with("-")) { + while(argv[1][0] == '-') { + ++argv[1]; + } + arg = true; + } + if(arg) { + if(command_list.find(argv[1]) == command_list.end()) { + show_invalid(); + exit(-1); + } + else { + switch (command_list[argv[1]]) { + case 1: { + show_help(); + exit(0); + } + case 2: { + if(command_size != 3) { + show_invalid(); + exit(-1); + } + std::string link_name, directory; + link_name = argv[2]; + directory = argv[3]; + create_link(link_name, directory); + exit(0); + } + case 3: { + if(command_size != 1) { + show_invalid(); + exit(-1); + } + print_links(); + exit(0); + } + case 4: { + if(command_size != 2) { + show_invalid(); + exit(-1); + } + std::string link_name; + link_name = argv[2]; + delete_link(link_name); + exit(0); + } + case 5: { + if(command_size != 1) { + show_invalid(); + exit(-1); + } + delete_file(); + exit(0); + } + + } + } + } + else { + std::string link_name = argv[1]; + goto_link(link_name); + exit(0); + } + exit(0); + } + + + + return app.exec(); +} +