diff --git a/include/cmd/args/arg_generic.hpp b/include/cmd/args/arg_generic.hpp index fabfd09..2bbf324 100644 --- a/include/cmd/args/arg_generic.hpp +++ b/include/cmd/args/arg_generic.hpp @@ -1,10 +1,16 @@ #pragma once #include +#include +#include +#include #include "cmd/args/arg_base.hpp" #include "ast/ast_component.hpp" +#include "lexer.hpp" +#include "util/stringliteral.hpp" + namespace fsh { template @@ -15,22 +21,33 @@ namespace fsh { Argument() {} virtual void svalue(const std::string& val, const Lexer::TokenType& type) override; + virtual T& gvalue() { return value; } - private: + bool gis_string_literal() { return is_string_literal; } + + protected: bool is_string_literal; // Currently no getter T value; }; template void Argument::svalue(const std::string& val, const Lexer::TokenType& type) { - if constexpr (std::is_same_v) { - value = val; - } else { + + is_string_literal = type == Lexer::TokenType::STRING_LITERAL; + + if constexpr (std::is_same_v) { + if(type != Lexer::TokenType::STRING_LITERAL) { + throw std::invalid_argument("Incorrect type"); + } + } + + if constexpr (!std::is_same_v && !std::is_base_of_v) { std::stringstream ss_val(val); if (!(ss_val >> value)) { throw std::invalid_argument("Incorrect type"); } + } else { + value = val; } - is_string_literal = type == Lexer::TokenType::STRING_LITERAL; } } \ No newline at end of file diff --git a/include/cmd/args/arg_input.hpp b/include/cmd/args/arg_input.hpp index 346b2cb..3aee7ff 100644 --- a/include/cmd/args/arg_input.hpp +++ b/include/cmd/args/arg_input.hpp @@ -4,19 +4,20 @@ #include #include "cmd/args/arg_base.hpp" +#include "cmd/args/arg_generic.hpp" namespace fsh { - class ArgInput : public _Argument { + class ArgInput : public Argument { public: static std::istream& get(std::shared_ptr<_Argument> a) { - return std::dynamic_pointer_cast(a)->gvalue(); + return std::dynamic_pointer_cast(a)->gstream(); } ArgInput() {} virtual void svalue(const std::string& val, const Lexer::TokenType& type) override; - virtual std::istream& gvalue(); + virtual std::istream& gstream(); private: std::optional str; diff --git a/include/cmd/args/arg_manager.hpp b/include/cmd/args/arg_manager.hpp index 99d344f..a631f4f 100644 --- a/include/cmd/args/arg_manager.hpp +++ b/include/cmd/args/arg_manager.hpp @@ -30,11 +30,16 @@ namespace fsh { if (flags.find(id) != flags.end()) return Argument::get(flags[id]); return std::make_optional(); } + bool get(const std::string& id) { return flags.find(id) != flags.end(); } void push_arg(std::shared_ptr<_Argument> arg) { pos_argument.push_back(arg); } void push_flag(const std::string& id, std::shared_ptr<_Argument> arg = nullptr) { flags[id] = arg; } + unsigned int size() { + return pos_argument.size(); + } + private: PosArgs pos_argument; FlagOpts flags; diff --git a/include/cmd/cmd.hpp b/include/cmd/cmd.hpp index 2af8a17..5c70eb7 100644 --- a/include/cmd/cmd.hpp +++ b/include/cmd/cmd.hpp @@ -8,6 +8,10 @@ #include "cmd/cmd_misc.hpp" #include "cmd/cmd_time.hpp" #include "cmd/cmd_touch.hpp" +#include "cmd/cmd_truncate.hpp" +#include "cmd/cmd_tr.hpp" +#include "cmd/cmd_prompt.hpp" +#include "cmd/cmd_rm.hpp" #include "cmd/cmd_wc.hpp" namespace fsh { @@ -21,7 +25,7 @@ namespace fsh { } Command& get(const std::string n) { - if (cmds.find(n) == cmds.end()) { throw std::runtime_error("Command not found"); } + if (cmds.find(n) == cmds.end()) { throw std::runtime_error("Command not found " + n); } return *(cmds[n]); } @@ -30,13 +34,17 @@ namespace fsh { private: // Nove komande bi registrovali ovde: CommandRegistry() { - cmds["wc"] = Command::register_cmd(); - cmds["date"] = Command::register_cmd(); - cmds["time"] = Command::register_cmd(); - cmds["echo"] = Command::register_cmd(); - cmds["exit"] = Command::register_cmd(); - cmds["touch"] = Command::register_cmd(); - cmds["debug"] = Command::register_cmd(); + cmds["tr"] = Command::register_cmd(); + cmds["rm"] = Command::register_cmd(); + cmds["wc"] = Command::register_cmd(); + cmds["date"] = Command::register_cmd(); + cmds["time"] = Command::register_cmd(); + cmds["echo"] = Command::register_cmd(); + cmds["exit"] = Command::register_cmd(); + cmds["touch"] = Command::register_cmd(); + cmds["debug"] = Command::register_cmd(); + cmds["prompt"] = Command::register_cmd(); + cmds["truncate"] = Command::register_cmd(); } std::unordered_map > cmds; diff --git a/include/cmd/cmd_base.hpp b/include/cmd/cmd_base.hpp index aa7de5b..796ef10 100644 --- a/include/cmd/cmd_base.hpp +++ b/include/cmd/cmd_base.hpp @@ -12,12 +12,12 @@ namespace fsh { class Command { - + public: using FlagNode = std::optional&; using ArgNodes = std::vector >; - public: - void execute(FlagNode flag, ArgNodes& vec, std::istream& in, std::ostream& out); + virtual void execute(FlagNode flag, ArgNodes& vec, std::istream& in, std::ostream& out, ArgFactory &arg_factory); + virtual void execute(FlagNode flag, ArgNodes& vec, std::istream& in, std::ostream& out); template static std::unique_ptr register_cmd() { diff --git a/include/cmd/cmd_echo.hpp b/include/cmd/cmd_echo.hpp index 93e8742..88b77e2 100644 --- a/include/cmd/cmd_echo.hpp +++ b/include/cmd/cmd_echo.hpp @@ -15,7 +15,7 @@ namespace fsh { virtual void run(std::istream& in, std::ostream& out, ArgManager& args) override { std::string s; std::string o; - while (getline(in, s)) { o += s + "\n"; } + while (std::getline(in, s)) { o += s + "\n"; } out << o; } }; diff --git a/include/cmd/cmd_prompt.hpp b/include/cmd/cmd_prompt.hpp new file mode 100644 index 0000000..70557df --- /dev/null +++ b/include/cmd/cmd_prompt.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "cmd/cmd_base.hpp" +#include "util/stringliteral.hpp" +#include "fsh.hpp" +#include + +namespace fsh { + + class CmdPrompt : public Command { + + protected: + virtual void register_flags() override { + ArgFactory& factory = get_factory(); + factory.add_rule(1); + } + + virtual void run(std::istream& in, std::ostream& out, ArgManager& args) override { + + std::string n_prompt = args.get(0).value(); + + fsh::instance().environment["PROMPT"] = n_prompt; + } + }; + +} \ No newline at end of file diff --git a/include/cmd/cmd_rm.hpp b/include/cmd/cmd_rm.hpp new file mode 100644 index 0000000..4b5c424 --- /dev/null +++ b/include/cmd/cmd_rm.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "cmd/cmd_base.hpp" +#include +#include + +namespace fsh { + + class CmdRM : public Command { + + protected: + virtual void register_flags() override { + ArgFactory& factory = get_factory(); + factory.add_rule(1); + } + + virtual void run(std::istream& in, std::ostream& out, ArgManager& args) override { + + if(std::remove(args.get(0).value().c_str())) { + throw std::runtime_error("Could not delete file"); + } + + } + }; + +} \ No newline at end of file diff --git a/include/cmd/cmd_tr.hpp b/include/cmd/cmd_tr.hpp new file mode 100644 index 0000000..3da59ea --- /dev/null +++ b/include/cmd/cmd_tr.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include "cmd/args/arg.hpp" +#include "cmd/args/arg_generic.hpp" +#include "cmd/args/arg_input.hpp" +#include "cmd/args/arg_manager.hpp" +#include "cmd/cmd_base.hpp" +#include "util/input.hpp" +#include "util/stringliteral.hpp" +#include +#include +#include +#include +#include + +namespace fsh { + + class CmdTr : public Command { + public: + virtual void execute(FlagNode flag, ArgNodes& vec, std::istream& in, std::ostream& out) override { + ArgFactory af; + switch (vec.size()) { + case 2: + af.add_rule(1); + case 1: + af.add_rule(1); + break; + + default: + af.add_input_rule(); + af.add_rule(1); + af.add_rule(1); + break; + } + Command::execute(flag, vec, in,out, af); + } + + protected: + + std::string replace_all(std::string str,const std::string &what,const std::string &with) { + if(what == "") throw std::runtime_error("\"\" cannot be used as what"); + + unsigned long long pos = str.find(what); + + while(pos != std::string::npos) { + str.replace(pos,what.size(),with) ; + pos = str.find(what,pos+with.size()); + } + return str; + } + + virtual void run(std::istream& in, std::ostream& out, ArgManager& args) override { + std::string s; + std::string o; + std::string what = ""; + std::string with = ""; + while (std::getline(in, s)) { o += s + "\n"; } + + switch (args.size()) { + case 2: + with = args.get(1).value(); + case 1: + what = args.get(0).value(); + break; + case 3: + what = args.get(1).value(); + with = args.get(2).value(); + } + + out << replace_all(o,what,with); + } + }; + +} \ No newline at end of file diff --git a/include/cmd/cmd_truncate.hpp b/include/cmd/cmd_truncate.hpp new file mode 100644 index 0000000..39bc925 --- /dev/null +++ b/include/cmd/cmd_truncate.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "cmd/cmd_base.hpp" +#include +#include +#include +#include + +namespace fsh { + + class CmdTruncate : public Command { + + protected: + virtual void register_flags() override { + ArgFactory& factory = get_factory(); + factory.add_rule(1); + } + + virtual void run(std::istream& in, std::ostream& out, ArgManager& args) override { + + std::string filename = args.get(0).value(); + + if(!std::ifstream(filename, std::ios_base::in)) { + throw std::runtime_error("File does not exist"); + } + + if(!std::ofstream(filename, std::ios_base::out)) { + throw std::runtime_error("Failed to truncate"); + } + + } + }; + +} \ No newline at end of file diff --git a/include/util/stringliteral.hpp b/include/util/stringliteral.hpp new file mode 100644 index 0000000..31d48b3 --- /dev/null +++ b/include/util/stringliteral.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace fsh { + + class StringLiteral : public std::string { + public: + StringLiteral() : std::string() {} + StringLiteral(const std::string& str) : std::string(str) {} + }; + +} \ No newline at end of file