#include #include #include #include #include #include #include #include #include #include "tecla_oo.h" #include #undef protected #include "input.h" #include "map.h" #define KBLIB_DEF_MACROS 1 #include "kblib/convert.h" extern const char* vnum; // HelpStr, iHelpStr #include "strings.h" using std::cerr; using std::cin; using std::cout; using std::endl; using std::string; using std::vector; using namespace std::string_literals; // main interface, generates 1024x1024 map with all default settings // void genMap(vector inList); static bool Continue = true; std::map vars; std::map settings; static input_trie commands; bool& verbose() { return settings["verbose"]; } void createInitTrie(); std::vector> initTrie1(); std::vector> initTrie2(); void runCommand(string in); // Since every lambda has the same signature, and it's quite verbose #define INPUT_TRIE_DECL(X) std::pair(std::string(X), new functdata(\ [](std::vector inList) -> std::vector // This one is pretty much useless, but otherwise the parentheses end up // unmatched #define CPARENS )) void drawMap(vector inList) { std::string file{inList[2]}; unsigned cmapID{lookupMap(inList[1])}, size{pFromStr(unsigned short, inList[6])}; float x{pFromStr(float, inList[3])}, y{pFromStr(float, inList[4])}, width{pFromStr(float, inList[5])}; spiral mode = parse_spiral(inList[0][1]); if (current_cmap[cmapID].second.size() > 256) { auto image = genMap_impl(cmapID, mode, x, y, width, size); image.write(file); } else { auto image = genMap_impl(cmapID, mode, x, y, width, size); image.write(file); } } int main(int argc, char** argv) { // Add built-in functions to trie createInitTrie(); // Aliases and saved commands: commands.execute(std::vector{"save", "esc", "u"}); commands.execute(std::vector{"save", ":", "= ec"}); commands.execute(std::vector{"save", "ls", "= p p-"}); commands.execute(std::vector{"..", "long", "off"}); commands.execute(std::vector{"..", "prompt", "on"}); commands.execute(std::vector{"..", "s_prompt", "off"}); commands.execute(std::vector{"..", "verbose", "off"}); commands.execute(std::vector{".", "prompt", "$>"}); string in; commands.insert(vector>({{ std::pair( "m", new functdata( [](vector inList) { bool archimedian{true}; unsigned cmapID{1}; auto split = inList[0].find_first_of("0123456789abcdef"); if (split == string::npos) { split = inList[0].size(); } string fname{inList[0].substr(0, split)}, cmapnum{inList[0].substr(split)}; if (fname.find_first_of('l') != string::npos) { archimedian = false; } inList.insert(inList.begin() + 1, cmapnum); inList[0] = "d"s + fname; drawMap(inList); return vector{}; }, 5, 5, "Draw map (filename left upper width resolution)", functdata::FSingle)), std::pair( "d", new functdata( [](vector inList) { drawMap(std::move(inList)); return vector{}; }, 6, 6, "Draw map ", functdata::FSingle)), std::pair( "c", new functdata( [](vector inList) { int maxlen{0}; for (auto& m : current_cmap) { (m.second.size() > maxlen) ? maxlen = m.second.size() : false; } png::image image(maxlen, current_cmap.size()); for (int i = 0; i < (signed)current_cmap.size(); ++i) { auto cmap = current_cmap[i].second; for (int x = 0; x < maxlen; ++x) { auto v = x * cmap.size() / maxlen; image[i][x] = {cmap[v].red, cmap[v].green, cmap[v].blue}; } } image.write(inList[1]); return vector{}; }, 1, 1, "Print colormaps ()", functdata::FSingle)), std::pair( "cr", new functdata( [](vector inList) { auto cmaps = read_cmap(inList[1]); int maxlen{0}; for (auto& m : cmaps) { (m.second.size() > maxlen) ? maxlen = m.second.size() : false; } png::image image(maxlen, cmaps.size()); for (int i = 0; i < (signed)cmaps.size(); ++i) { auto& cmap = cmaps[i].second; for (int x = 0; x < maxlen; ++x) { auto v = x * cmap.size() / maxlen; image[i][x] = {cmap[v].red, cmap[v].green, cmap[v].blue}; } } image.write(inList[2]); return vector{}; }, 2, 2, "Print colormaps from file ", functdata::FSingle)), std::pair( "pc", new functdata( []([[maybe_unused]] vector inList) { vector out; for (int i = 0; i < (signed)current_cmap.size(); ++i) { std::string name; png::palette cmap; std::tie(name, cmap) = current_cmap[i]; out.emplace_back( kblib::concat(':', name, ':', cmap.size())); // cout << ":" << name << ":" << std::dec // << cmap.size() << std::hex; for (int x = 0; x < (signed)cmap.size(); ++x) { if (x % 8 == 0) { out.emplace_back("\t"); // cout << endl // << "\t"; } std::ostringstream sout; sout << std::hex << std::setw(2) << std::setfill('0') << +cmap[x].red << std::setw(2) << std::setfill('0') << +cmap[x].green << std::setw(2) << std::setfill('0') << +cmap[x].blue << " "; out.back() += sout.str(); } // cout << endl; } // cout << std::dec; return out; }, 0, 0, "Formats colormaps", functdata::Single)), std::pair( "pcr", new functdata( []([[maybe_unused]] vector inList) { vector out(1); auto cmaps = read_cmap(inList[1]); for (int i = 0; i < (signed)cmaps.size(); ++i) { std::string name; png::palette cmap; std::tie(name, cmap) = cmaps[i]; for (int c = 0; c != (signed)name.size(); ++c) { if (name[c] == ':' || name[c] == '\\') { name.insert(c, "\\"); ++c; } } out.back() += kblib::concat(':', name, ':', cmap.size()); // cout << ":" << name << ":" << std::dec // << cmap.size() << std::hex; for (int x = 0; x < (signed)cmap.size(); ++x) { if (x % 8 == 0) { cout << endl << "\t"; } std::ostringstream sout; sout << std::hex << std::setw(2) << std::setfill('0') << +cmap[x].red << std::setw(2) << std::setfill('0') << +cmap[x].green << std::setw(2) << std::setfill('0') << +cmap[x].blue << " "; out.back() += sout.str(); } // cout << endl; } // cout << std::dec; return out; }, 0, 0, "Formats colormaps", functdata::FSingle)), std::pair( "rc", new functdata( [](vector inList) { vector out; try { current_cmap = read_cmap(inList[1]); out.emplace_back(kblib::concat( "Read ", current_cmap.size(), " cmaps")); // cout << "Read " << current_cmap.size() << " cmaps" // << endl; for (auto& map : current_cmap) { out.emplace_back(kblib::concat(map.first, ": ", map.second.size(), " colors")); // cout << map.first << ": " << map.second.size() // << " colors" << endl; } } catch (malformed_file_error& e) { out.emplace_back(e.what()); // cout << e.what() << endl; } return out; }, 1, 1, "Read colormap ", functdata::FSingle)), }})); std::vector scriptedCommands; bool cont_after = false; for (int i = 1; i < argc; i++) { // cout<<"["< inList = tokenizeInput(in); vector out = commands.execute(inList); for (auto i : out) { cout << i << endl; } } inline void createInitTrie() { auto a = initTrie1(); commands.insert(a); // Commands that require the trie to already be initialized/reference it auto b = initTrie2(); commands.insert(b); } inline std::vector> initTrie1() { return std::vector>({ std::pair( "h", new functdata( [](vector inList) -> vector { if (inList.size() > 1) { int len = 0; functdata* found = commands.longestPrefix( kblib::toLower(inList[1]), &len); if (found) { if (found->mode != functdata::Composite) return {found->help}; else return {"Alias of \"" + found->help + "\""}; } else { return {string("Nothing found for \"") + kblib::toLower(inList[1]) + "\""}; } } else { // from strings.h return iHelpStr; } }, 0, 1, std::string("Get help"), functdata::Single)), std::pair( "q", new functdata( [](vector inList) -> vector { Continue = false; return {}; }, 0, std::string("Quit"))), std::pair( "..", new functdata( [](vector inList) -> vector { inList[1].resize(inList[1].size()); if (inList.size() > 2) settings[kblib::toLower(inList[1])] = truthy(inList[2]); else settings[kblib::toLower(inList[1])] = !settings[kblib::toLower(inList[1])]; return {}; }, 1, 2, std::string("Change setting (toggle if no argument)"), functdata::Single)), std::pair( "..-", new functdata( [](vector inList) -> vector { inList[1].resize(inList[1].size()); settings.erase(kblib::toLower(inList[1])); return {}; }, 1, 1, std::string("Clear setting"), functdata::Single)), std::pair( "??", new functdata( [](vector inList) -> vector { if (inList.size() == 2) { inList[1].resize(inList[1].size()); return {settings[kblib::toLower(inList[1])] ? std::string("on") : std::string("off")}; } else { std::vector ret; for (auto i : settings) { ret.push_back(std::string("\"") + i.first + "\": " + (i.second ? std::string("on") : std::string("off"))); } return ret; } }, 0, 1, std::string("Query setting"), functdata::Single)), std::pair( ".", new functdata( [](vector inList) -> vector { inList[1].resize(inList[1].size()); if (inList.size() == 2) vars.erase(kblib::toLower(inList[1])); else vars[kblib::toLower(inList[1])] = inList[2]; return {}; }, 1, 2, std::string("Save/Clear variable"), functdata::Single)), std::pair( "?", new functdata( [](vector inList) -> vector { if (inList.size() == 2) { inList[1].resize(inList[1].size()); return {vars[kblib::toLower(inList[1])]}; } else { std::vector ret; for (auto i : vars) { ret.push_back(std::string("\"") + i.first + "\": \"" + i.second + "\""); } return ret; } }, 0, 1, std::string("Query variable"), functdata::Single)), std::pair("e", new functdata( [](vector inList) { std::vector ret; string tmp = "["; for (auto i : inList) { (tmp += i) += ':'; } tmp += ']'; ret.push_back(tmp); return ret; }, 0, std::string("Echo inputs"))), std::pair( "el", new functdata( [](vector inList) { // std::vector ret; inList.erase(inList.begin()); return inList; // for (auto i : inList) { // ret.push_back(i); //} // return ret; }, 0, std::string("Echo inputs (1/line)"))), std::pair( "es", new functdata([](vector inList) -> vector { return {inList[1]}; }, 1, 1, std::string("Echo input (Single)"), functdata::Single)), std::pair( "ec", new functdata( [](vector inList) -> vector { std::string ret{inList[1]}; inList.erase(inList.begin()); inList.erase(inList.begin()); for (auto i : inList) { ret += ' ' + i; } return {ret}; }, 1, -1, std::string("Echo inputs (Collating)"), functdata::Batch)), std::pair( "#", new functdata( [](vector inList) -> vector { return {}; }, 0, std::string("Echo inputs (1/line)"))), std::pair( "dup", new functdata( [](vector inList) -> vector { return {inList[1], inList[1]}; }, 1, 1, std::string("Duplicate"), functdata::Single)), std::pair( "r", new functdata( [](vector inList) -> vector { return {inList[2], inList[1]}; }, 2, 2, std::string("Reverse"), functdata::Single)), std::pair( "k", new functdata( [](vector inList) { std::vector ret; inList.erase(inList.begin()); std::vector a; for (auto i : inList) { a = tokenizeInput(i); ret.insert(ret.end(), a.begin(), a.end()); } return ret; }, 0, std::string("Tokenize input (again)"))), std::pair( "u", new functdata( [](vector inList) { inList.erase(inList.begin()); return std::vector{deTokenize(inList)}; }, 0, std::string("Detokenize/escape input"))), std::pair( "l", new functdata( [](vector inList) { std::size_t c = 2, cons = 0; std::vector ret; while (c < inList.size()) { auto b = std::vector(inList.begin() + c, inList.end()); b.insert(b.begin(), inList[1]); auto a = commands.execute(b, &cons); ret.insert(ret.end(), a.begin(), a.end()); if (cons) c += cons; else return ret; } return ret; }, 2, -1, std::string("Loop Command"), functdata::Batch)), std::pair( "la", new functdata( [](vector inList) -> vector { std::size_t c = 3, cons = 0; std::string r = inList[2]; while (c < inList.size()) { r = commands.execute({inList[1], r, inList[c]}, &cons)[0]; if (cons) c += cons - 1; else return {r}; } return {r}; }, 2, -1, std::string("Loop-accumulate left"), functdata::Batch)), std::pair( "lar", new functdata( [](vector inList) -> vector { std::size_t c = 3, cons = 0; std::reverse(inList.begin() + 2, inList.end()); std::string r = inList[2]; while (c < inList.size()) { r = commands.execute({inList[1], inList[c], r}, &cons)[0]; if (cons) c += cons - 1; else return {r}; } return {r}; }, 2, -1, std::string("Loop-accumulate right"), functdata::Batch)), std::pair( "=", new functdata( [](vector inList) { auto a = commands.execute(std::vector( inList.begin() + 2, inList.end())); return commands.execute( kblib::arraycat(vector{inList[1]}, a)); }, 2, -1, std::string("Apply function"), functdata::Batch)), std::pair( "|", new functdata( [](vector inList) -> vector { std::string f(inList[0], 1); // f is all of inList[0] except '|' if (f.empty()) { return {"Please specify a funtion for \"|\""}; } auto a = commands.execute(std::vector( inList.begin() + 1, inList.end())); return commands.execute( kblib::arraycat(vector{f}, a)); }, 1, -1, std::string("Apply (fixed) function"), functdata::Batch)), std::pair( "=p", new functdata( [](vector inList) { auto a = commands.execute(std::vector( inList.begin() + 2, inList.end())); return kblib::arraycat(vector{inList[1]}, a); }, 2, -1, std::string("Pretend to apply function"), functdata::Batch)), std::pair( "p", new functdata( [](vector inList) -> vector { if (inList.size() == 1) { auto dump = commands.getIndex(); std::vector ret; string tmp; for (unsigned i = 0; i != dump.size(); i++) { (tmp += std::to_string(i)) += ": "; for (unsigned char j = 0; j != 128; j++) { if (dump[i][j].first || dump[i][j].second) { tmp += (char)(j ? j : '/') + std::to_string(dump[i][j].first) + (dump[i][j].second ? '*' : ' ') + ' '; } } ret.push_back(tmp); tmp.clear(); if (inList[0][1] == 'l') { for (unsigned char j = 0; j != 128; j++) { tmp += (dump[i][j].first ? std::to_string(dump[i][j].first) : string(" ")) + (dump[i][j].second ? '*' : ' ') + ' '; // print 16 to a line if (j % 16 == 15) { ret.push_back(tmp); tmp.clear(); } } ret.push_back(tmp); tmp.clear(); } } return ret; } else { int len = 0; functdata* found = commands.longestPrefix( kblib::toLower(inList[1]), &len); if (found) { if (found->mode == functdata::Composite) return {string("\"") + inList[1].substr(0, len) + "\": Aliases \"" + found->help + "\"" + (found->call ? " " : "[!]")}; else return {string("\"") + inList[1].substr(0, len) + "\": " + found->help + " [takes " + std::to_string(found->argN) + ((found->argX != unsigned(-1)) ? '-' + std::to_string(found->argX) : std::string("+")) + "; " + functdata::modeS(found->mode) + ']' + (found->call ? ' ' : '!')}; } else return {std::to_string(len) + "; Nothing found for \"" + kblib::toLower(inList[1]) + "\""}; } }, 0, 1, std::string("Print/Probe input trie (Long)"), functdata::Single)), std::pair( "p-", new functdata( [](vector inList) { return commands.allWithPrefix( inList.size() > 1 ? inList[1] : ""); }, 0, 1, std::string("List input trie"), functdata::Single)), }); } inline std::vector> initTrie2() { return std::vector>({ INPUT_TRIE_DECL("x") { return commands.execute( std::vector(inList.begin()+1, inList.end()) ); } , 1, std::string("Execute Command") CPARENS, INPUT_TRIE_DECL("save") { int len = 0; commands.longestPrefix(inList[1], &len); if (static_cast(len) == inList[1].length()) { return {std::string("\"") + inList[1] + "\" is already a command."}; } else { commands.insert( std::string(inList[1]), new functdata( [inList](std::vector inList2) -> std::vector { return commands.execute(tokenizeInput( inList[2] + " " //+ // commands.execute(arraycat(std::vector(1,"ec"), // std::vector(inList2.begin()+1, // inList2.end())))[0] + deTokenize(std::vector(inList2.begin() + 1, inList2.end())))); }, 0, -1, inList[2], functdata::Composite)); return {"Warning: This feature is highly experimental."}; } } , 2, 2, std::string("Save Command (Simple, EXP)"), functdata::Single CPARENS, INPUT_TRIE_DECL("del") { auto f = commands.longestPrefix(inList[1], nullptr); if (f != nullptr && f->mode == functdata::Composite) { commands.remove(inList[1]); return {"Deleted " + inList[1]}; } else { return {"Did not delete built-in command " + inList[1]}; } } , 1, 1, std::string("Delete saved Command"), functdata::Single CPARENS, INPUT_TRIE_DECL("x-") { auto f = commands.longestPrefix(inList[1], nullptr); if (f != nullptr) { if (f->mode == functdata::Composite) { // return tokenizeInput(f->help); return kblib::arraycat( tokenizeInput(f->help), std::vector(inList.begin() + 2, inList.end())); } else { return {inList[1]}; } } else { return {"Nothing found for \"" + inList[1] + "\""}; } } , 1, 1, std::string("Expand Alias"), functdata::Single CPARENS, INPUT_TRIE_DECL("x=") { auto f = commands.longestPrefix(inList[1], nullptr); // auto allnames = commands.allWithPrefix(inList.size()>1?inList[1]:""); if (f != nullptr) { if (f->mode == functdata::Composite) { return kblib::arraycat( tokenizeInput(f->help), std::vector(inList.begin() + 2, inList.end())); } else { // return {inList[1]}; if (inList[1] == "=" && inList.size() > 3) { /*std::vector a, b; a = arraycat(std::vector({inList[1]}), commands.execute({"x=", inList[2]})); b = commands.execute(arraycat(std::vector({"x="}), std::vector(inList.begin()+3, inList.end()))); return arraycat(a,b);//*/ return kblib::arraycat( kblib::arraycat(std::vector({inList[1]}), commands.execute({"x=", inList[2]})), commands.execute( kblib::arraycat(std::vector({"x="}), std::vector(inList.begin() + 3, inList.end())))); } return std::vector(inList.begin() + 1, inList.end()); } } else { return {"Nothing found for \"" + inList[1] + "\""}; } } , 1, std::string("Expand Alias (smart)") CPARENS, INPUT_TRIE_DECL("pa") { auto allnames = commands.allWithPrefix(inList.size() > 1 ? inList[1] : ""); // std::vector> aliases; std::vector ret; for (auto i : allnames) { auto j = commands.longestPrefix(i, nullptr); // No need to test for null because all results are guaranteed to exist if (j->mode == functdata::Composite) { // aliases.push_back(std::make_pair(i,j->help); if (inList[0] == "pa") { ret.push_back(std::string("\"") + i + "\": " + j->help); } else { ret.push_back(i); } } } return ret; } , 0, 1, std::string("Print all aliases"), functdata::Single CPARENS, }); }