From 6a71b20d26f7940b0d6c5559b47221d02f4aca17 Mon Sep 17 00:00:00 2001 From: twanvl Date: Mon, 4 Aug 2008 21:01:40 +0000 Subject: [PATCH] Files can be written from command line interface git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1054 0fc631ac-6414-0410-93d0-97cfa31319b6 --- src/cli/cli_main.cpp | 48 ++++++++++++++++++++++++++------- src/cli/cli_main.hpp | 12 +++++++-- src/cli/text_io_handler.cpp | 10 ++++++- src/cli/text_io_handler.hpp | 2 ++ src/data/format/image.cpp | 1 + src/main.cpp | 17 ++++++++++-- src/script/context.hpp | 2 +- src/script/functions/export.cpp | 4 +-- 8 files changed, 78 insertions(+), 18 deletions(-) diff --git a/src/cli/cli_main.cpp b/src/cli/cli_main.cpp index 8ea5f75e..ba0df260 100644 --- a/src/cli/cli_main.cpp +++ b/src/cli/cli_main.cpp @@ -18,13 +18,15 @@ DECLARE_TYPEOF_COLLECTION(ScriptParseError); // ----------------------------------------------------------------------------- : Command line interface -CLISetInterface::CLISetInterface() - : quiet(false) +CLISetInterface::CLISetInterface(const SetP& set, bool quiet) + : quiet(quiet) , our_context(nullptr) { if (!cli.haveConsole()) { throw Error(_("Can not run command line interface without a console;\nstart MSE with \"mse.com --cli\"")); } + ei.directory_relative = ei.directory_absolute = wxGetCwd(); + setSet(set); run(); } @@ -33,13 +35,31 @@ CLISetInterface::~CLISetInterface() { } Context& CLISetInterface::getContext() { - if (!our_context) { - our_context = new Context(); - init_script_functions(*our_context); + if (set) { + return set->getContext(); + } else { + if (!our_context) { + our_context = new Context(); + init_script_functions(*our_context); + } + return *our_context; } - return *our_context; } +void CLISetInterface::onBeforeChangeSet() { + if (set || our_context) { + Context& ctx = getContext(); + ctx.closeScope(scope); + } +} + +void CLISetInterface::onChangeSet() { + Context& ctx = getContext(); + scope = ctx.openScope(); + ei.set = set; +} + + // ----------------------------------------------------------------------------- : Running void CLISetInterface::run() { @@ -48,6 +68,7 @@ void CLISetInterface::run() { // loop running = true; while (running) { + if (!cli.canGetLine()) break; // show prompt if (!quiet) { cli << GRAY << _("> ") << NORMAL; @@ -56,6 +77,7 @@ void CLISetInterface::run() { // read line from stdin String command = cli.getLine(); handleCommand(command); + cli.flush(); } } @@ -75,6 +97,7 @@ void CLISetInterface::showUsage() { cli << _(" :help Show this help page.\n"); cli << _(" :load Load a different set file.\n"); cli << _(" :quit Exit the MSE command line interface.\n"); + cli << _(" :reset Clear all local variable definitions.\n"); cli << _(" :! Perform a shell command.\n"); cli << _("\n Commands can be abreviated to their first letter if there is no ambiguity.\n\n"); } @@ -90,7 +113,7 @@ void CLISetInterface::handleCommand(const String& command) { String arg = space + 1 < command.size() ? command.substr(space+1) : wxEmptyString; if (before == _(":q") || before == _(":quit")) { if (!quiet) { - cli << _("Goodbye\n"); cli.flush(); + cli << _("Goodbye\n"); } running = false; } else if (before == _(":?") || before == _(":h") || before == _(":help")) { @@ -101,6 +124,10 @@ void CLISetInterface::handleCommand(const String& command) { } else { setSet(import_set(arg)); } + } else if (before == _(":r") || before == _(":reset")) { + Context& ctx = getContext(); + ctx.closeScope(scope); + scope = ctx.openScope(); } else if (before == _(":!")) { if (arg.empty()) { cli << _("Give a shell command to execute.\n"); @@ -124,13 +151,14 @@ void CLISetInterface::handleCommand(const String& command) { } else { // parse command vector errors; - ScriptP script = parse(command,set.get(),false,errors); + ScriptP script = parse(command,nullptr,false,errors); if (!errors.empty()) { FOR_EACH(error,errors) showError(error.what()); return; } // execute command - Context& ctx = set ? set->getContext() : getContext(); + WITH_DYNAMIC_ARG(export_info, &ei); + Context& ctx = getContext(); ScriptValueP result = ctx.eval(*script,false); // show result cli << result->toCode() << ENDL; @@ -141,5 +169,5 @@ void CLISetInterface::handleCommand(const String& command) { } void CLISetInterface::showError(const String& error) { - cli << RED << _("ERROR: ") << NORMAL << replace_all(error,_("\n"),_(" ")) << ENDL; + cli << RED << _("ERROR: ") << NORMAL << replace_all(error,_("\n"),_("\n ")) << ENDL; } diff --git a/src/cli/cli_main.hpp b/src/cli/cli_main.hpp index 0abad561..36462b7d 100644 --- a/src/cli/cli_main.hpp +++ b/src/cli/cli_main.hpp @@ -11,15 +11,19 @@ #include #include +#include // ----------------------------------------------------------------------------- : Command line interface class CLISetInterface : public SetView { public: - CLISetInterface(); + /// The set is optional + CLISetInterface(const SetP& set, bool quiet = false); ~CLISetInterface(); protected: - void onAction(const Action&, bool) {} + virtual void onAction(const Action&, bool) {} + virtual void onChangeSet(); + virtual void onBeforeChangeSet(); private: bool quiet; ///< Supress prompts and other non-vital stuff bool running; ///< Still running? @@ -33,6 +37,10 @@ class CLISetInterface : public SetView { /// our own context, when no set is loaded Context& getContext(); Context* our_context; + size_t scope; + + // export info, so we can write files + ExportInfo ei; }; // ----------------------------------------------------------------------------- : EOF diff --git a/src/cli/text_io_handler.cpp b/src/cli/text_io_handler.cpp index 306b48c3..06c35cee 100644 --- a/src/cli/text_io_handler.cpp +++ b/src/cli/text_io_handler.cpp @@ -54,6 +54,8 @@ bool TextIOHandler::haveConsole() const { } +// ----------------------------------------------------------------------------- : Output + void TextIOHandler::flush() { if (have_console) { fflush(stdout); @@ -86,10 +88,12 @@ TextIOHandler& TextIOHandler::operator << (const String& str) { return *this; } +// ----------------------------------------------------------------------------- : Input + String TextIOHandler::getLine() { String result; Char buffer[2048]; - while (true) { + while (!feof(stdin)) { if (!IF_UNICODE(fgetws,fgets)(buffer, 2048, stdin)) { return result; // error } @@ -100,4 +104,8 @@ String TextIOHandler::getLine() { return result; } } + return result; +} +bool TextIOHandler::canGetLine() { + return !feof(stdin); } diff --git a/src/cli/text_io_handler.hpp b/src/cli/text_io_handler.hpp index cbd50f95..10a4a912 100644 --- a/src/cli/text_io_handler.hpp +++ b/src/cli/text_io_handler.hpp @@ -30,6 +30,8 @@ class TextIOHandler { /// Read a line from stdin String getLine(); + /// Can another line be got? + bool canGetLine(); /// Flush output void flush(); diff --git a/src/data/format/image.cpp b/src/data/format/image.cpp index 0e37489e..8ca59aaf 100644 --- a/src/data/format/image.cpp +++ b/src/data/format/image.cpp @@ -40,6 +40,7 @@ Rotation UnzoomedDataViewer::getRotation() const { } Bitmap export_bitmap(const SetP& set, const CardP& card) { + if (!set) throw Error(_("no set")); // create viewer UnzoomedDataViewer viewer(!settings.stylesheetSettingsFor(set->stylesheetFor(card)).card_normal_export()); viewer.setSet(set); diff --git a/src/main.cpp b/src/main.cpp index a549a0cb..66dd0e80 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -190,8 +190,10 @@ int MSE::OnRun() { cli << _("\n \tExport the cards in a set to image files,"); cli << _("\n \tIMAGE is the same format as for 'export all card images'."); cli << _("\n\n ") << BRIGHT << _("--cli") << NORMAL << _(" [") - << PARAM << _("FILE") << NORMAL << _("]"); + << PARAM << _("FILE") << NORMAL << _("] [") + << BRIGHT << _("--quiet") << NORMAL << _("]"); cli << _("\n \tStart the command line interface for performing commands on the set file."); + cli << _("\n \tUse ") << BRIGHT << _("-q") << NORMAL << _(" or ") << BRIGHT << _("--quiet") << NORMAL << _(" to supress the startup banner and prompts."); cli << ENDL; cli.flush(); return EXIT_SUCCESS; @@ -203,7 +205,18 @@ int MSE::OnRun() { return EXIT_SUCCESS; } else if (arg == _("--cli")) { // command line interface - CLISetInterface cli_interface; + SetP set; + bool quiet = false; + for (int i = 2 ; i < argc ; ++i) { + String arg = argv[i]; + wxFileName f(argv[i]); + if (f.GetExt() == _("mse-set") || f.GetExt() == _("mse") || f.GetExt() == _("set")) { + set = import_set(arg); + } else if (arg == _("-q") || arg == _("--quiet")) { + quiet = true; + } + } + CLISetInterface cli_interface(set,quiet); return EXIT_SUCCESS; } else if (arg == _("--export")) { if (argc <= 2) { diff --git a/src/script/context.hpp b/src/script/context.hpp index 3cb82ad2..cc034eff 100644 --- a/src/script/context.hpp +++ b/src/script/context.hpp @@ -73,7 +73,7 @@ class Context { /// Make a closure of the function with the direct parameters of the current call ScriptValueP makeClosure(const ScriptValueP& fun); - private: + public: /// Open a new scope /** returns the number of shadowed binding before that scope */ diff --git a/src/script/functions/export.cpp b/src/script/functions/export.cpp index ae7e2553..8f0cd42e 100644 --- a/src/script/functions/export.cpp +++ b/src/script/functions/export.cpp @@ -26,8 +26,8 @@ DECLARE_TYPEOF_COLLECTION(SymbolFont::DrawableSymbol); // ----------------------------------------------------------------------------- : Utility // Make sure we can export files to a data directory -void guard_export_info(const String& fun) { - if (!export_info()) { +void guard_export_info(const String& fun, bool need_template = false) { + if (!export_info() && (!need_template || export_info()->export_template)) { throw ScriptError(_("Can only use ") + fun + _(" from export templates")); } else if (export_info()->directory_relative.empty()) { throw ScriptError(_("Can only use ") + fun + _(" when 'create directory' is set to true"));