Commit 9608d74b authored by twanvl's avatar twanvl

Files can be written from command line interface

parent b0d34072
...@@ -18,13 +18,15 @@ DECLARE_TYPEOF_COLLECTION(ScriptParseError); ...@@ -18,13 +18,15 @@ DECLARE_TYPEOF_COLLECTION(ScriptParseError);
// ----------------------------------------------------------------------------- : Command line interface // ----------------------------------------------------------------------------- : Command line interface
CLISetInterface::CLISetInterface() CLISetInterface::CLISetInterface(const SetP& set, bool quiet)
: quiet(false) : quiet(quiet)
, our_context(nullptr) , 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\""));
} }
ei.directory_relative = ei.directory_absolute = wxGetCwd();
setSet(set);
run(); run();
} }
...@@ -33,13 +35,31 @@ CLISetInterface::~CLISetInterface() { ...@@ -33,13 +35,31 @@ CLISetInterface::~CLISetInterface() {
} }
Context& CLISetInterface::getContext() { Context& CLISetInterface::getContext() {
if (!our_context) { if (set) {
our_context = new Context(); return set->getContext();
init_script_functions(*our_context); } else {
if (!our_context) {
our_context = new Context();
init_script_functions(*our_context);
}
return *our_context;
}
}
void CLISetInterface::onBeforeChangeSet() {
if (set || our_context) {
Context& ctx = getContext();
ctx.closeScope(scope);
} }
return *our_context;
} }
void CLISetInterface::onChangeSet() {
Context& ctx = getContext();
scope = ctx.openScope();
ei.set = set;
}
// ----------------------------------------------------------------------------- : Running // ----------------------------------------------------------------------------- : Running
void CLISetInterface::run() { void CLISetInterface::run() {
...@@ -48,6 +68,7 @@ void CLISetInterface::run() { ...@@ -48,6 +68,7 @@ void CLISetInterface::run() {
// loop // loop
running = true; running = true;
while (running) { while (running) {
if (!cli.canGetLine()) break;
// show prompt // show prompt
if (!quiet) { if (!quiet) {
cli << GRAY << _("> ") << NORMAL; cli << GRAY << _("> ") << NORMAL;
...@@ -56,6 +77,7 @@ void CLISetInterface::run() { ...@@ -56,6 +77,7 @@ void CLISetInterface::run() {
// read line from stdin // read line from stdin
String command = cli.getLine(); String command = cli.getLine();
handleCommand(command); handleCommand(command);
cli.flush();
} }
} }
...@@ -75,6 +97,7 @@ void CLISetInterface::showUsage() { ...@@ -75,6 +97,7 @@ void CLISetInterface::showUsage() {
cli << _(" :help Show this help page.\n"); cli << _(" :help Show this help page.\n");
cli << _(" :load <setfile> Load a different set file.\n"); cli << _(" :load <setfile> Load a different set file.\n");
cli << _(" :quit Exit the MSE command line interface.\n"); cli << _(" :quit Exit the MSE command line interface.\n");
cli << _(" :reset Clear all local variable definitions.\n");
cli << _(" :! <command> Perform a shell command.\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"); 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) { ...@@ -90,7 +113,7 @@ void CLISetInterface::handleCommand(const String& command) {
String arg = space + 1 < command.size() ? command.substr(space+1) : wxEmptyString; String arg = space + 1 < command.size() ? command.substr(space+1) : wxEmptyString;
if (before == _(":q") || before == _(":quit")) { if (before == _(":q") || before == _(":quit")) {
if (!quiet) { if (!quiet) {
cli << _("Goodbye\n"); cli.flush(); cli << _("Goodbye\n");
} }
running = false; running = false;
} else if (before == _(":?") || before == _(":h") || before == _(":help")) { } else if (before == _(":?") || before == _(":h") || before == _(":help")) {
...@@ -101,6 +124,10 @@ void CLISetInterface::handleCommand(const String& command) { ...@@ -101,6 +124,10 @@ void CLISetInterface::handleCommand(const String& command) {
} else { } else {
setSet(import_set(arg)); setSet(import_set(arg));
} }
} else if (before == _(":r") || before == _(":reset")) {
Context& ctx = getContext();
ctx.closeScope(scope);
scope = ctx.openScope();
} else if (before == _(":!")) { } else if (before == _(":!")) {
if (arg.empty()) { if (arg.empty()) {
cli << _("Give a shell command to execute.\n"); cli << _("Give a shell command to execute.\n");
...@@ -124,13 +151,14 @@ void CLISetInterface::handleCommand(const String& command) { ...@@ -124,13 +151,14 @@ void CLISetInterface::handleCommand(const String& command) {
} else { } else {
// parse command // parse command
vector<ScriptParseError> errors; vector<ScriptParseError> errors;
ScriptP script = parse(command,set.get(),false,errors); ScriptP script = parse(command,nullptr,false,errors);
if (!errors.empty()) { if (!errors.empty()) {
FOR_EACH(error,errors) showError(error.what()); FOR_EACH(error,errors) showError(error.what());
return; return;
} }
// execute command // execute command
Context& ctx = set ? set->getContext() : getContext(); WITH_DYNAMIC_ARG(export_info, &ei);
Context& ctx = getContext();
ScriptValueP result = ctx.eval(*script,false); ScriptValueP result = ctx.eval(*script,false);
// show result // show result
cli << result->toCode() << ENDL; cli << result->toCode() << ENDL;
...@@ -141,5 +169,5 @@ void CLISetInterface::handleCommand(const String& command) { ...@@ -141,5 +169,5 @@ void CLISetInterface::handleCommand(const String& command) {
} }
void CLISetInterface::showError(const String& error) { 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;
} }
...@@ -11,15 +11,19 @@ ...@@ -11,15 +11,19 @@
#include <util/prec.hpp> #include <util/prec.hpp>
#include <data/set.hpp> #include <data/set.hpp>
#include <data/export_template.hpp>
// ----------------------------------------------------------------------------- : Command line interface // ----------------------------------------------------------------------------- : Command line interface
class CLISetInterface : public SetView { class CLISetInterface : public SetView {
public: public:
CLISetInterface(); /// The set is optional
CLISetInterface(const SetP& set, bool quiet = false);
~CLISetInterface(); ~CLISetInterface();
protected: protected:
void onAction(const Action&, bool) {} virtual void onAction(const Action&, bool) {}
virtual void onChangeSet();
virtual void onBeforeChangeSet();
private: private:
bool quiet; ///< Supress prompts and other non-vital stuff bool quiet; ///< Supress prompts and other non-vital stuff
bool running; ///< Still running? bool running; ///< Still running?
...@@ -33,6 +37,10 @@ class CLISetInterface : public SetView { ...@@ -33,6 +37,10 @@ class CLISetInterface : public SetView {
/// our own context, when no set is loaded /// our own context, when no set is loaded
Context& getContext(); Context& getContext();
Context* our_context; Context* our_context;
size_t scope;
// export info, so we can write files
ExportInfo ei;
}; };
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
......
...@@ -54,6 +54,8 @@ bool TextIOHandler::haveConsole() const { ...@@ -54,6 +54,8 @@ bool TextIOHandler::haveConsole() const {
} }
// ----------------------------------------------------------------------------- : Output
void TextIOHandler::flush() { void TextIOHandler::flush() {
if (have_console) { if (have_console) {
fflush(stdout); fflush(stdout);
...@@ -86,10 +88,12 @@ TextIOHandler& TextIOHandler::operator << (const String& str) { ...@@ -86,10 +88,12 @@ TextIOHandler& TextIOHandler::operator << (const String& str) {
return *this; return *this;
} }
// ----------------------------------------------------------------------------- : Input
String TextIOHandler::getLine() { String TextIOHandler::getLine() {
String result; String result;
Char buffer[2048]; Char buffer[2048];
while (true) { while (!feof(stdin)) {
if (!IF_UNICODE(fgetws,fgets)(buffer, 2048, stdin)) { if (!IF_UNICODE(fgetws,fgets)(buffer, 2048, stdin)) {
return result; // error return result; // error
} }
...@@ -100,4 +104,8 @@ String TextIOHandler::getLine() { ...@@ -100,4 +104,8 @@ String TextIOHandler::getLine() {
return result; return result;
} }
} }
return result;
}
bool TextIOHandler::canGetLine() {
return !feof(stdin);
} }
...@@ -30,6 +30,8 @@ class TextIOHandler { ...@@ -30,6 +30,8 @@ class TextIOHandler {
/// Read a line from stdin /// Read a line from stdin
String getLine(); String getLine();
/// Can another line be got?
bool canGetLine();
/// Flush output /// Flush output
void flush(); void flush();
......
...@@ -40,6 +40,7 @@ Rotation UnzoomedDataViewer::getRotation() const { ...@@ -40,6 +40,7 @@ Rotation UnzoomedDataViewer::getRotation() const {
} }
Bitmap export_bitmap(const SetP& set, const CardP& card) { Bitmap export_bitmap(const SetP& set, const CardP& card) {
if (!set) throw Error(_("no set"));
// create viewer // create viewer
UnzoomedDataViewer viewer(!settings.stylesheetSettingsFor(set->stylesheetFor(card)).card_normal_export()); UnzoomedDataViewer viewer(!settings.stylesheetSettingsFor(set->stylesheetFor(card)).card_normal_export());
viewer.setSet(set); viewer.setSet(set);
......
...@@ -190,8 +190,10 @@ int MSE::OnRun() { ...@@ -190,8 +190,10 @@ int MSE::OnRun() {
cli << _("\n \tExport the cards in a set to image files,"); 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 \tIMAGE is the same format as for 'export all card images'.");
cli << _("\n\n ") << BRIGHT << _("--cli") << NORMAL << _(" [") 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 \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 << ENDL;
cli.flush(); cli.flush();
return EXIT_SUCCESS; return EXIT_SUCCESS;
...@@ -203,7 +205,18 @@ int MSE::OnRun() { ...@@ -203,7 +205,18 @@ int MSE::OnRun() {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} else if (arg == _("--cli")) { } else if (arg == _("--cli")) {
// command line interface // 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; return EXIT_SUCCESS;
} else if (arg == _("--export")) { } else if (arg == _("--export")) {
if (argc <= 2) { if (argc <= 2) {
......
...@@ -73,7 +73,7 @@ class Context { ...@@ -73,7 +73,7 @@ class Context {
/// Make a closure of the function with the direct parameters of the current call /// Make a closure of the function with the direct parameters of the current call
ScriptValueP makeClosure(const ScriptValueP& fun); ScriptValueP makeClosure(const ScriptValueP& fun);
private: public:
/// Open a new scope /// Open a new scope
/** returns the number of shadowed binding before that scope */ /** returns the number of shadowed binding before that scope */
......
...@@ -26,8 +26,8 @@ DECLARE_TYPEOF_COLLECTION(SymbolFont::DrawableSymbol); ...@@ -26,8 +26,8 @@ DECLARE_TYPEOF_COLLECTION(SymbolFont::DrawableSymbol);
// ----------------------------------------------------------------------------- : Utility // ----------------------------------------------------------------------------- : Utility
// Make sure we can export files to a data directory // Make sure we can export files to a data directory
void guard_export_info(const String& fun) { void guard_export_info(const String& fun, bool need_template = false) {
if (!export_info()) { if (!export_info() && (!need_template || export_info()->export_template)) {
throw ScriptError(_("Can only use ") + fun + _(" from export templates")); throw ScriptError(_("Can only use ") + fun + _(" from export templates"));
} else if (export_info()->directory_relative.empty()) { } else if (export_info()->directory_relative.empty()) {
throw ScriptError(_("Can only use ") + fun + _(" when 'create directory' is set to true")); throw ScriptError(_("Can only use ") + fun + _(" when 'create directory' is set to 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