Commit b0d34072 authored by twanvl's avatar twanvl

command line interface can now execute scripts

parent c7e3a98d
...@@ -10,11 +10,17 @@ ...@@ -10,11 +10,17 @@
#include <util/error.hpp> #include <util/error.hpp>
#include <cli/cli_main.hpp> #include <cli/cli_main.hpp>
#include <cli/text_io_handler.hpp> #include <cli/text_io_handler.hpp>
#include <script/functions/functions.hpp>
#include <data/format/formats.hpp>
#include <wx/process.h>
DECLARE_TYPEOF_COLLECTION(ScriptParseError);
// ----------------------------------------------------------------------------- : Command line interface // ----------------------------------------------------------------------------- : Command line interface
CLISetInterface::CLISetInterface() CLISetInterface::CLISetInterface()
: quiet(false) : quiet(false)
, our_context(nullptr)
{ {
if (!cli.haveConsole()) { if (!cli.haveConsole()) {
throw Error(_("Can not run command line interface without a console;\nstart MSE with \"mse.com --cli\"")); throw Error(_("Can not run command line interface without a console;\nstart MSE with \"mse.com --cli\""));
...@@ -22,6 +28,20 @@ CLISetInterface::CLISetInterface() ...@@ -22,6 +28,20 @@ CLISetInterface::CLISetInterface()
run(); run();
} }
CLISetInterface::~CLISetInterface() {
delete our_context;
}
Context& CLISetInterface::getContext() {
if (!our_context) {
our_context = new Context();
init_script_functions(*our_context);
}
return *our_context;
}
// ----------------------------------------------------------------------------- : Running
void CLISetInterface::run() { void CLISetInterface::run() {
// show welcome logo // show welcome logo
if (!quiet) showWelcome(); if (!quiet) showWelcome();
...@@ -49,23 +69,77 @@ void CLISetInterface::showWelcome() { ...@@ -49,23 +69,77 @@ void CLISetInterface::showWelcome() {
cli.flush(); cli.flush();
} }
void CLISetInterface::showUsage() {
cli << _(" Commands available from the prompt:\n\n");
cli << _(" <expression> Execute a script expression, display the result\n");
cli << _(" :help Show this help page.\n");
cli << _(" :load <setfile> Load a different set file.\n");
cli << _(" :quit Exit the MSE command line interface.\n");
cli << _(" :! <command> Perform a shell command.\n");
cli << _("\n Commands can be abreviated to their first letter if there is no ambiguity.\n\n");
}
void CLISetInterface::handleCommand(const String& command) { void CLISetInterface::handleCommand(const String& command) {
if (command.empty()) { try {
// empty, ignore if (command.empty()) {
} else if (command == _(":q") || command == _(":quit")) { // empty, ignore
if (!quiet) { } else if (command.GetChar(0) == _(':')) {
cli << _("Goodbye\n"); cli.flush(); // :something
size_t space = min(command.find_first_of(_(' ')), command.size());
String before = command.substr(0,space);
String arg = space + 1 < command.size() ? command.substr(space+1) : wxEmptyString;
if (before == _(":q") || before == _(":quit")) {
if (!quiet) {
cli << _("Goodbye\n"); cli.flush();
}
running = false;
} else if (before == _(":?") || before == _(":h") || before == _(":help")) {
showUsage();
} else if (before == _(":l") || before == _(":load")) {
if (arg.empty()) {
cli << _("Give a filename to open.\n");
} else {
setSet(import_set(arg));
}
} else if (before == _(":!")) {
if (arg.empty()) {
cli << _("Give a shell command to execute.\n");
} else {
#ifdef __WXMSW__
_wsystem(arg.c_str());
#elif UNICODE
wxCharBuffer buf = arg.fn_str();
system(buf);
#else
system(arg.c_str());
#endif
}
} else {
cli << _("Unknown command, type :help for help.\n");
}
} else if (command == _("exit") || command == _("quit")) {
cli << _("Use :quit to quit\n");
} else if (command == _("help")) {
cli << _("Use :help for help\n");
} else {
// parse command
vector<ScriptParseError> errors;
ScriptP script = parse(command,set.get(),false,errors);
if (!errors.empty()) {
FOR_EACH(error,errors) showError(error.what());
return;
}
// execute command
Context& ctx = set ? set->getContext() : getContext();
ScriptValueP result = ctx.eval(*script,false);
// show result
cli << result->toCode() << ENDL;
} }
running = false; } catch (const Error& e) {
} else if (command == _(":?") || command == _(":help")) { showError(e.what());
// TODO show help
} else if (command == _("exit") || command == _("quit")) {
cli << _("Use :quit to quit\n"); cli.flush();
} else if (command.GetChar(0) == _(':')) {
cli << _("Unknown command, type :help for help.\n"); cli.flush();
} else {
// execute command
// TODO
cli << _("You said:\n") << command << ENDL; cli.flush();
} }
} }
void CLISetInterface::showError(const String& error) {
cli << RED << _("ERROR: ") << NORMAL << replace_all(error,_("\n"),_(" ")) << ENDL;
}
...@@ -10,19 +10,29 @@ ...@@ -10,19 +10,29 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp> #include <util/prec.hpp>
#include <data/set.hpp>
// ----------------------------------------------------------------------------- : Command line interface // ----------------------------------------------------------------------------- : Command line interface
class CLISetInterface { class CLISetInterface : public SetView {
public: public:
CLISetInterface(); CLISetInterface();
~CLISetInterface();
protected:
void onAction(const Action&, bool) {}
private: private:
bool quiet; bool quiet; ///< Supress prompts and other non-vital stuff
bool running; bool running; ///< Still running?
void run(); void run();
void showWelcome(); void showWelcome();
void showUsage();
void handleCommand(const String& command); void handleCommand(const String& command);
void showError(const String& error);
/// our own context, when no set is loaded
Context& getContext();
Context* our_context;
}; };
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
......
...@@ -41,6 +41,7 @@ struct Transfer { ...@@ -41,6 +41,7 @@ struct Transfer {
DWORD WINAPI TransferThread(Transfer*); DWORD WINAPI TransferThread(Transfer*);
BOOL WINAPI HandleCtrlEvent(DWORD type); BOOL WINAPI HandleCtrlEvent(DWORD type);
void CopyFileBuffer(HANDLE output, char* buffer, DWORD size);
void InitEscapeTranslation(HANDLE console); void InitEscapeTranslation(HANDLE console);
void PerformEscapeCode(HANDLE console, char command, int argc, int argv[]); void PerformEscapeCode(HANDLE console, char command, int argc, int argv[]);
...@@ -158,12 +159,13 @@ BOOL WINAPI HandleCtrlEvent(DWORD type) { ...@@ -158,12 +159,13 @@ BOOL WINAPI HandleCtrlEvent(DWORD type) {
DWORD exit_code = 1; DWORD exit_code = 1;
// try to exit child process cleanly // try to exit child process cleanly
// TODO: don't exit child on Ctrl+C // TODO: don't exit child on Ctrl+C
/*CopyFileBuffer(TODO,":quit\n",6); CopyFileBuffer(in_mine,":quit\n",6);
CopyFileBuffer(out_real,":quit\n",6);
if (WaitForSingleObject(child_process_info.hProcess,100) == WAIT_OBJECT_0) { if (WaitForSingleObject(child_process_info.hProcess,100) == WAIT_OBJECT_0) {
GetExitCodeProcess(child_process_info.hProcess, &exit_code); GetExitCodeProcess(child_process_info.hProcess, &exit_code);
} else {*/ } else {
TerminateProcess(child_process_info.hProcess,1); TerminateProcess(child_process_info.hProcess,1);
//} }
// exit this process // exit this process
ExitProcess(exit_code); ExitProcess(exit_code);
return TRUE; return TRUE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment