#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(); }