add command history in repl

This commit is contained in:
ValKmjolnir 2023-09-19 00:24:45 +08:00
parent d0d9ce3b80
commit 85bc699905
4 changed files with 43 additions and 25 deletions

View File

@ -51,7 +51,7 @@ public:
return 1; return 1;
} }
int flag = fcntl(0, F_GETFL); int flag = fcntl(0, F_GETFL);
fcntl(0, F_SETFL,flag|O_NONBLOCK); fcntl(0, F_SETFL, flag|O_NONBLOCK);
nread = read(0, &ch, 1); nread = read(0, &ch, 1);
fcntl(0, F_SETFL, flag); fcntl(0, F_SETFL, flag);
if (nread==1) { if (nread==1) {
@ -83,25 +83,25 @@ public:
noecho_input this_window; noecho_input this_window;
var nas_getch(var* args, usize size, gc* ngc) { var nas_getch(var* args, usize size, gc* ngc) {
return var::num((double)this_window.noecho_getch()); return var::num(static_cast<double>(this_window.noecho_getch()));
} }
var nas_kbhit(var* args, usize size, gc* ngc) { var nas_kbhit(var* args, usize size, gc* ngc) {
return var::num((double)this_window.noecho_kbhit()); return var::num(static_cast<double>(this_window.noecho_kbhit()));
} }
var nas_noblock(var* args, usize size, gc* ngc) { var nas_noblock(var* args, usize size, gc* ngc) {
if (this_window.noecho_kbhit()) { if (this_window.noecho_kbhit()) {
return var::num((double)this_window.noecho_getch()); return var::num(static_cast<double>(this_window.noecho_getch()));
} }
return nil; return nil;
} }
module_func_info func_tbl[] = { module_func_info func_tbl[] = {
{"nas_getch",nas_getch}, {"nas_getch", nas_getch},
{"nas_kbhit",nas_kbhit}, {"nas_kbhit", nas_kbhit},
{"nas_noblock",nas_noblock}, {"nas_noblock", nas_noblock},
{nullptr,nullptr} {nullptr, nullptr}
}; };
extern "C" module_func_info* get() { extern "C" module_func_info* get() {

View File

@ -34,16 +34,16 @@ var nas_socket(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num) if (args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num)
return nas_err("socket", "\"af\", \"type\", \"protocol\" should be number"); return nas_err("socket", "\"af\", \"type\", \"protocol\" should be number");
int sd = socket(args[0].num(), args[1].num(), args[2].num()); int sd = socket(args[0].num(), args[1].num(), args[2].num());
return var::num((double)sd); return var::num(static_cast<double>(sd));
} }
var nas_closesocket(var* args, usize size, gc* ngc) { var nas_closesocket(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("closesocket", "\"sd\" should be number"); return nas_err("closesocket", "\"sd\" should be number");
#ifdef _WIN32 #ifdef _WIN32
return var::num((double)closesocket(args[0].num())); return var::num(static_cast<double>(closesocket(args[0].num())));
#else #else
return var::num((double)close(args[0].num())); return var::num(static_cast<double>(close(args[0].num())));
#endif #endif
} }
@ -52,7 +52,7 @@ var nas_shutdown(var* args, usize size, gc* ngc) {
return nas_err("shutdown", "\"sd\" must be a number"); return nas_err("shutdown", "\"sd\" must be a number");
if (args[1].type!=vm_num) if (args[1].type!=vm_num)
return nas_err("shutdown", "\"how\" must be a number"); return nas_err("shutdown", "\"how\" must be a number");
return var::num((double)shutdown(args[0].num(), args[1].num())); return var::num(static_cast<double>(shutdown(args[0].num(), args[1].num())));
} }
var nas_bind(var* args, usize size, gc* ngc) { var nas_bind(var* args, usize size, gc* ngc) {
@ -67,7 +67,11 @@ var nas_bind(var* args, usize size, gc* ngc) {
server.sin_family = AF_INET; server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(args[1].str().c_str()); server.sin_addr.s_addr = inet_addr(args[1].str().c_str());
server.sin_port = htons(args[2].num()); server.sin_port = htons(args[2].num());
return var::num((double)bind(args[0].num(), (sockaddr*)&server, sizeof(server))); return var::num(static_cast<double>(bind(
args[0].num(),
(sockaddr*)&server,
sizeof(server)
)));
} }
var nas_listen(var* args, usize size, gc* ngc) { var nas_listen(var* args, usize size, gc* ngc) {
@ -75,7 +79,7 @@ var nas_listen(var* args, usize size, gc* ngc) {
return nas_err("listen", "\"sd\" must be a number"); return nas_err("listen", "\"sd\" must be a number");
if (args[1].type!=vm_num) if (args[1].type!=vm_num)
return nas_err("listen", "\"backlog\" must be a number"); return nas_err("listen", "\"backlog\" must be a number");
return var::num((double)listen(args[0].num(), args[1].num())); return var::num(static_cast<double>(listen(args[0].num(), args[1].num())));
} }
var nas_connect(var* args, usize size, gc* ngc) { var nas_connect(var* args, usize size, gc* ngc) {
@ -91,11 +95,11 @@ var nas_connect(var* args, usize size, gc* ngc) {
addr.sin_port = htons(args[2].num()); addr.sin_port = htons(args[2].num());
hostent* entry = gethostbyname(args[1].str().c_str()); hostent* entry = gethostbyname(args[1].str().c_str());
memcpy(&addr.sin_addr, entry->h_addr, entry->h_length); memcpy(&addr.sin_addr, entry->h_addr, entry->h_length);
return var::num((double)connect( return var::num(static_cast<double>(connect(
args[0].num(), args[0].num(),
(sockaddr*)&addr, (sockaddr*)&addr,
sizeof(sockaddr_in) sizeof(sockaddr_in)
)); )));
} }
var nas_accept(var* args, usize size, gc* ngc) { var nas_accept(var* args, usize size, gc* ngc) {
@ -110,7 +114,7 @@ var nas_accept(var* args, usize size, gc* ngc) {
#endif #endif
var res=ngc->temp = ngc->alloc(vm_hash); var res=ngc->temp = ngc->alloc(vm_hash);
auto& hash = res.hash().elems; auto& hash = res.hash().elems;
hash["sd"] = var::num((double)client_sd); hash["sd"] = var::num(static_cast<double>(client_sd));
hash["ip"] = ngc->newstr(inet_ntoa(client.sin_addr)); hash["ip"] = ngc->newstr(inet_ntoa(client.sin_addr));
ngc->temp = nil; ngc->temp = nil;
return res; return res;
@ -123,12 +127,12 @@ var nas_send(var* args, usize size, gc* ngc) {
return nas_err("send", "\"buff\" must be a string"); return nas_err("send", "\"buff\" must be a string");
if (args[2].type!=vm_num) if (args[2].type!=vm_num)
return nas_err("send", "\"flags\" muse be a number"); return nas_err("send", "\"flags\" muse be a number");
return var::num((double)send( return var::num(static_cast<double>(send(
args[0].num(), args[0].num(),
args[1].str().c_str(), args[1].str().c_str(),
args[1].str().length(), args[1].str().length(),
args[2].num() args[2].num()
)); )));
} }
var nas_sendto(var* args, usize size, gc* ngc) { var nas_sendto(var* args, usize size, gc* ngc) {
@ -148,14 +152,14 @@ var nas_sendto(var* args, usize size, gc* ngc) {
addr.sin_port = htons(args[2].num()); addr.sin_port = htons(args[2].num());
hostent* entry = gethostbyname(args[1].str().c_str()); hostent* entry = gethostbyname(args[1].str().c_str());
memcpy(&addr.sin_addr, entry->h_addr, entry->h_length); memcpy(&addr.sin_addr, entry->h_addr, entry->h_length);
return var::num((double)sendto( return var::num(static_cast<double>(sendto(
args[0].num(), args[0].num(),
args[3].str().c_str(), args[3].str().c_str(),
args[3].str().length(), args[3].str().length(),
args[4].num(), args[4].num(),
(sockaddr*)&addr, (sockaddr*)&addr,
sizeof(sockaddr_in) sizeof(sockaddr_in)
)); )));
} }
var nas_recv(var* args, usize size, gc* ngc) { var nas_recv(var* args, usize size, gc* ngc) {
@ -169,9 +173,9 @@ var nas_recv(var* args, usize size, gc* ngc) {
return nas_err("recv", "\"flags\" muse be a number"); return nas_err("recv", "\"flags\" muse be a number");
var res = ngc->temp = ngc->alloc(vm_hash); var res = ngc->temp = ngc->alloc(vm_hash);
auto& hash = res.hash().elems; auto& hash = res.hash().elems;
char* buf = new char[(int)args[1].num()]; char* buf = new char[static_cast<int>(args[1].num())];
auto recvsize = recv(args[0].num(), buf,args[1].num(), args[2].num()); auto recvsize = recv(args[0].num(), buf,args[1].num(), args[2].num());
hash["size"] = var::num((double)recvsize); hash["size"] = var::num(static_cast<double>(recvsize));
buf[recvsize>=0? recvsize:0] = 0; buf[recvsize>=0? recvsize:0] = 0;
hash["str"] = ngc->newstr(buf); hash["str"] = ngc->newstr(buf);
delete[] buf; delete[] buf;
@ -192,7 +196,7 @@ var nas_recvfrom(var* args, usize size, gc* ngc) {
int socklen = sizeof(sockaddr_in); int socklen = sizeof(sockaddr_in);
var res = ngc->temp = ngc->alloc(vm_hash); var res = ngc->temp = ngc->alloc(vm_hash);
auto& hash = res.hash().elems; auto& hash = res.hash().elems;
char* buf = new char[(int)args[1].num()+1]; char* buf = new char[static_cast<int>(args[1].num()+1)];
#ifdef _WIN32 #ifdef _WIN32
auto recvsize = recvfrom( auto recvsize = recvfrom(
args[0].num(), args[0].num(),
@ -212,7 +216,7 @@ var nas_recvfrom(var* args, usize size, gc* ngc) {
(socklen_t*)&socklen (socklen_t*)&socklen
); );
#endif #endif
hash["size"] = var::num((double)recvsize); hash["size"] = var::num(static_cast<double>(recvsize));
buf[recvsize>=0? recvsize:0] = 0; buf[recvsize>=0? recvsize:0] = 0;
hash["str"] = ngc->newstr(buf); hash["str"] = ngc->newstr(buf);
delete[] buf; delete[] buf;

View File

@ -9,6 +9,13 @@
namespace nasal { namespace nasal {
namespace repl { namespace repl {
void repl::add_command_history(const std::string& history) {
command_history.push_back(history);
if (command_history.size()>1000) {
command_history.pop_front();
}
}
std::string repl::readline(std::string prompt = ">>> ") { std::string repl::readline(std::string prompt = ">>> ") {
auto line = std::string(""); auto line = std::string("");
std::cout << prompt; std::cout << prompt;
@ -51,6 +58,7 @@ bool repl::check_need_more_input() {
} }
auto line = readline("... "); auto line = readline("... ");
add_command_history(line);
source.back() += "\n" + line; source.back() += "\n" + line;
} }
return true; return true;
@ -117,6 +125,7 @@ void repl::execute() {
if (!line.length()) { if (!line.length()) {
continue; continue;
} }
add_command_history(line);
if (line == ".e" || line == ".exit") { if (line == ".e" || line == ".exit") {
break; break;

View File

@ -8,6 +8,7 @@
#include <vector> #include <vector>
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
#include <deque>
namespace nasal { namespace nasal {
namespace repl { namespace repl {
@ -27,9 +28,11 @@ struct info {
class repl { class repl {
private: private:
std::vector<std::string> source; std::vector<std::string> source;
std::deque<std::string> command_history;
vm runtime; vm runtime;
private: private:
void add_command_history(const std::string&);
std::string readline(std::string); std::string readline(std::string);
bool check_need_more_input(); bool check_need_more_input();
void update_temp_file(); void update_temp_file();
@ -42,6 +45,8 @@ public:
runtime.set_repl_mode_flag(true); runtime.set_repl_mode_flag(true);
// no detail report info // no detail report info
runtime.set_detail_report_info(false); runtime.set_detail_report_info(false);
// set empty history
command_history = {""};
} }
void execute(); void execute();
}; };