Commit 4c527278 authored by twanvl's avatar twanvl

Allow writing files anywhere from the command lines interface, not just in the working directory

parent 4f13ac9f
...@@ -26,6 +26,7 @@ CLISetInterface::CLISetInterface(const SetP& set, bool quiet) ...@@ -26,6 +26,7 @@ CLISetInterface::CLISetInterface(const SetP& set, bool quiet)
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(); ei.directory_relative = ei.directory_absolute = wxGetCwd();
ei.allow_writes_outside = true;
setSet(set); setSet(set);
run(); run();
} }
...@@ -100,6 +101,8 @@ void CLISetInterface::showUsage() { ...@@ -100,6 +101,8 @@ void CLISetInterface::showUsage() {
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 << _(" :reset Clear all local variable definitions.\n");
cli << _(" :pwd Print the current working directory.\n");
cli << _(" :cd Change working directory.\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");
} }
...@@ -122,17 +125,30 @@ void CLISetInterface::handleCommand(const String& command) { ...@@ -122,17 +125,30 @@ void CLISetInterface::handleCommand(const String& command) {
showUsage(); showUsage();
} else if (before == _(":l") || before == _(":load")) { } else if (before == _(":l") || before == _(":load")) {
if (arg.empty()) { if (arg.empty()) {
cli << _("Give a filename to open.\n"); cli.showError(_("Give a filename to open."));
} else { } else {
setSet(import_set(arg)); setSet(import_set(arg));
} }
} else if (before == _(":r") || before == _(":reset")) { } else if (before == _(":r") || before == _(":reset")) {
Context& ctx = getContext(); Context& ctx = getContext();
ei.exported_images.clear();
ctx.closeScope(scope); ctx.closeScope(scope);
scope = ctx.openScope(); scope = ctx.openScope();
} else if (before == _(":c") || before == _(":cd")) {
if (arg.empty()) {
cli.showError(_("Give a new working directory."));
} else {
if (!wxSetWorkingDirectory(arg)) {
cli.showError(_("Can't change working directory to ")+arg);
} else {
ei.directory_relative = ei.directory_absolute = wxGetCwd();
}
}
} else if (before == _(":pwd") || before == _(":p")) {
cli << ei.directory_absolute << ENDL;
} else if (before == _(":!")) { } else if (before == _(":!")) {
if (arg.empty()) { if (arg.empty()) {
cli << _("Give a shell command to execute.\n"); cli.showError(_("Give a shell command to execute."));
} else { } else {
#ifdef __WXMSW__ #ifdef __WXMSW__
_wsystem(arg.c_str()); _wsystem(arg.c_str());
...@@ -144,7 +160,7 @@ void CLISetInterface::handleCommand(const String& command) { ...@@ -144,7 +160,7 @@ void CLISetInterface::handleCommand(const String& command) {
#endif #endif
} }
} else { } else {
cli << _("Unknown command, type :help for help.\n"); cli.showError(_("Unknown command, type :help for help."));
} }
} else if (command == _("exit") || command == _("quit")) { } else if (command == _("exit") || command == _("quit")) {
cli << _("Use :quit to quit\n"); cli << _("Use :quit to quit\n");
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <util/prec.hpp> #include <util/prec.hpp>
#include <data/export_template.hpp> #include <data/export_template.hpp>
#include <data/game.hpp> #include <data/game.hpp>
#include <data/set.hpp>
#include <data/field.hpp> #include <data/field.hpp>
// ----------------------------------------------------------------------------- : Export template, basics // ----------------------------------------------------------------------------- : Export template, basics
...@@ -45,3 +46,5 @@ IMPLEMENT_REFLECTION(ExportTemplate) { ...@@ -45,3 +46,5 @@ IMPLEMENT_REFLECTION(ExportTemplate) {
// ----------------------------------------------------------------------------- : ExportInfo // ----------------------------------------------------------------------------- : ExportInfo
IMPLEMENT_DYNAMIC_ARG(ExportInfo*, export_info, nullptr); IMPLEMENT_DYNAMIC_ARG(ExportInfo*, export_info, nullptr);
ExportInfo::ExportInfo() : allow_writes_outside(false) {}
...@@ -45,12 +45,15 @@ class ExportTemplate : public Packaged { ...@@ -45,12 +45,15 @@ class ExportTemplate : public Packaged {
/// Information that can be used by export functions /// Information that can be used by export functions
struct ExportInfo { struct ExportInfo {
ExportInfo();
SetP set; ///< The set that is being exported SetP set; ///< The set that is being exported
ExportTemplateP export_template; ///< The export template used ExportTemplateP export_template; ///< The export template used
String directory_relative; ///< The directory for storing extra files (or "" if !export->create_directory) String directory_relative; ///< The directory for storing extra files (or "" if !export->create_directory)
/// This is just the directory name /// This is just the directory name
String directory_absolute; ///< The absolute path of the directory String directory_absolute; ///< The absolute path of the directory
map<String,wxSize> exported_images; ///< Images (from symbol font) already exported, and their size map<String,wxSize> exported_images; ///< Images (from symbol font) already exported, and their size
bool allow_writes_outside; ///< Can files outside the directory be written to?
}; };
DECLARE_DYNAMIC_ARG(ExportInfo*, export_info); DECLARE_DYNAMIC_ARG(ExportInfo*, export_info);
......
...@@ -34,6 +34,29 @@ void guard_export_info(const String& fun, bool need_template = false) { ...@@ -34,6 +34,29 @@ void guard_export_info(const String& fun, bool need_template = false) {
} }
} }
/// Find an absolute filename for a relative filename from an export template,
/// Returns the absolute filename, and may modify the relative name.
String get_export_full_path(String& rel_name) {
ExportInfo& ei = *export_info();
// the absolute path
wxFileName fn(rel_name);
fn.Normalize(wxPATH_NORM_ALL, ei.directory_absolute);
if (!ei.allow_writes_outside) {
// check if path is okay
wxFileName fn2(_("x"));
fn2.SetPath(ei.directory_absolute);
fn2.Normalize(wxPATH_NORM_ALL, ei.directory_absolute);
String p1 = fn.GetFullPath();
String p2 = fn2.GetFullPath();
p2.resize(p2.size() - 1); // drop the x
if (p2.empty() || p1.size() < p2.size() || p1.substr(0,p2.size()-1) != p2.substr(0,p2.size()-1)) {
throw ScriptError(_("Not a relative filename: ") + rel_name);
}
}
rel_name = fn.GetFullName();
return fn.GetFullPath();
}
// ----------------------------------------------------------------------------- : HTML // ----------------------------------------------------------------------------- : HTML
// An HTML tag // An HTML tag
...@@ -351,15 +374,16 @@ SCRIPT_FUNCTION(to_text) { ...@@ -351,15 +374,16 @@ SCRIPT_FUNCTION(to_text) {
SCRIPT_FUNCTION(copy_file) { SCRIPT_FUNCTION(copy_file) {
guard_export_info(_("copy_file")); guard_export_info(_("copy_file"));
SCRIPT_PARAM_C(String, input); // file to copy SCRIPT_PARAM_C(String, input); // file to copy
ExportInfo& ei = *export_info(); // output path
wxFileName fn(input); String out_name = input;
fn.SetPath(ei.directory_absolute); String out_path = get_export_full_path(out_name);
// copy // copy
ExportInfo& ei = *export_info();
InputStreamP in = ei.export_template->openIn(input); InputStreamP in = ei.export_template->openIn(input);
wxFileOutputStream out(fn.GetFullPath()); wxFileOutputStream out(out_path);
if (!out.Ok()) throw Error(_("Unable to open file '") + fn.GetFullPath() + _("' for output")); if (!out.Ok()) throw Error(_("Unable to open file '") + out_path + _("' for output"));
out.Write(*in); out.Write(*in);
SCRIPT_RETURN(fn.GetFullName()); SCRIPT_RETURN(out_name);
} }
// write a file to the destination directory // write a file to the destination directory
...@@ -367,29 +391,26 @@ SCRIPT_FUNCTION(write_text_file) { ...@@ -367,29 +391,26 @@ SCRIPT_FUNCTION(write_text_file) {
guard_export_info(_("write_text_file")); guard_export_info(_("write_text_file"));
SCRIPT_PARAM_C(String, input); // text to write SCRIPT_PARAM_C(String, input); // text to write
SCRIPT_PARAM(String, file); // file to write to SCRIPT_PARAM(String, file); // file to write to
// filename // output path
wxFileName fn; String out_path = get_export_full_path(file);
fn.SetPath(export_info()->directory_absolute);
fn.SetFullName(file);
// write // write
wxFileOutputStream out(fn.GetFullPath()); wxFileOutputStream out(out_path);
if (!out.Ok()) throw Error(_("Unable to open file '") + fn.GetFullPath() + _("' for output")); if (!out.Ok()) throw Error(_("Unable to open file '") + out_path + _("' for output"));
wxTextOutputStream tout(out); wxTextOutputStream tout(out);
tout.WriteString(BYTE_ORDER_MARK); tout.WriteString(BYTE_ORDER_MARK);
tout.WriteString(input); tout.WriteString(input);
SCRIPT_RETURN(fn.GetFullName()); SCRIPT_RETURN(file);
} }
SCRIPT_FUNCTION(write_image_file) { SCRIPT_FUNCTION(write_image_file) {
guard_export_info(_("write_image_file")); guard_export_info(_("write_image_file"));
ExportInfo& ei = *export_info(); // output path
// filename
SCRIPT_PARAM(String, file); // file to write to SCRIPT_PARAM(String, file); // file to write to
wxFileName fn; String out_path = get_export_full_path(file);
fn.SetPath(ei.directory_absolute); // duplicates?
fn.SetFullName(file); ExportInfo& ei = *export_info();
if (ei.exported_images.find(fn.GetFullName()) != ei.exported_images.end()) { if (ei.exported_images.find(file) != ei.exported_images.end()) {
SCRIPT_RETURN(fn.GetFullName()); // already written an image with this name SCRIPT_RETURN(file); // already written an image with this name
} }
// get image // get image
SCRIPT_PARAM_C(ScriptValueP, input); SCRIPT_PARAM_C(ScriptValueP, input);
...@@ -405,9 +426,9 @@ SCRIPT_FUNCTION(write_image_file) { ...@@ -405,9 +426,9 @@ SCRIPT_FUNCTION(write_image_file) {
} }
if (!image.Ok()) throw Error(_("Unable to generate image for file ") + file); if (!image.Ok()) throw Error(_("Unable to generate image for file ") + file);
// write // write
image.SaveFile(fn.GetFullPath()); image.SaveFile(out_path);
ei.exported_images.insert(make_pair(fn.GetFullName(), wxSize(image.GetWidth(), image.GetHeight()))); ei.exported_images.insert(make_pair(file, wxSize(image.GetWidth(), image.GetHeight())));
SCRIPT_RETURN(fn.GetFullName()); SCRIPT_RETURN(file);
} }
// ----------------------------------------------------------------------------- : Init // ----------------------------------------------------------------------------- : Init
......
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