mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
Added break_text function
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@857 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
//+----------------------------------------------------------------------------+
|
||||
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||
//| Copyright: (C) 2001 - 2008 Twan van Laarhoven and "coppro" |
|
||||
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||
//+----------------------------------------------------------------------------+
|
||||
|
||||
#ifndef HEADER_DATA_ACTION_GENERIC
|
||||
#define HEADER_DATA_ACTION_GENERIC
|
||||
|
||||
/** @file data/action/generic.hpp
|
||||
*
|
||||
* Generic action stuff
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <util/prec.hpp>
|
||||
#include <util/action_stack.hpp>
|
||||
|
||||
// ----------------------------------------------------------------------------- : Generic add/remove action
|
||||
|
||||
enum AddingOrRemoving {ADD, REMOVE};
|
||||
|
||||
/// Adding or removing some objects from a vector
|
||||
template <typename T>
|
||||
class GenericAddAction {
|
||||
public:
|
||||
GenericAddAction(AddingOrRemoving, const T& item, const vector<T>& container);
|
||||
GenericAddAction(AddingOrRemoving, const vector<T>& items, const vector<T>& container);
|
||||
|
||||
String getName() const;
|
||||
void perform(vector<T>& container, bool to_undo) const;
|
||||
|
||||
/// A step of removing/adding
|
||||
struct Step {
|
||||
inline Step(size_t pos, const T& item) : pos(pos), item(item) {}
|
||||
size_t pos;
|
||||
T item;
|
||||
};
|
||||
bool adding; ///< Were objects added? (as opposed to removed)
|
||||
vector<Step> steps; ///< Added/removed objects, sorted by ascending pos
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Implementation
|
||||
|
||||
template <typename T>
|
||||
bool contains(const vector<T>& items, const T& item) {
|
||||
return find(items.begin(), items.end(), item) != items.end();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
GenericAddAction<T>::GenericAddAction(AddingOrRemoving ar, const T& item, const vector<T>& container)
|
||||
: adding(ar == ADD)
|
||||
{
|
||||
if (ar == ADD) {
|
||||
size_t pos = container.size();
|
||||
steps.push_back(Step(pos, item));
|
||||
} else {
|
||||
for (size_t pos = 0 ; pos < container.size() ; ++pos) {
|
||||
if (container[pos] == item) {
|
||||
steps.push_back(Step(pos, item));
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw InternalError(_("Item to remove not found in container"));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
GenericAddAction<T>::GenericAddAction(AddingOrRemoving ar, const vector<T>& items, const vector<T>& container)
|
||||
: adding(ar == ADD)
|
||||
{
|
||||
if (ar == ADD) {
|
||||
size_t pos = container.size();
|
||||
for (vector<T>::const_iterator it = items.begin() ; it != items.end() ; ++it) {
|
||||
steps.push_back(Step(pos++, *it));
|
||||
}
|
||||
} else {
|
||||
for (size_t pos = 0 ; pos < container.size() ; ++pos) {
|
||||
if (contains(items, container[pos])) {
|
||||
steps.push_back(Step(pos, container[pos]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (steps.size() != items.size()) {
|
||||
throw InternalError(_("Item to remove not found in container"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
String GenericAddAction<T>::getName() const {
|
||||
String type = type_name(steps.front().item) + (steps.size() == 1 ? _("") : _("s"));
|
||||
return adding ? _ACTION_1_("add object", type) : _ACTION_1_("remove object", type);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void GenericAddAction<T>::perform(vector<T>& container, bool to_undo) const {
|
||||
if (adding != to_undo) {
|
||||
// (re)insert the items
|
||||
// ascending order, this is the reverse of removal
|
||||
FOR_EACH_CONST(s, steps) {
|
||||
assert(s.pos <= container.size());
|
||||
container.insert(container.begin() + s.pos, s.item);
|
||||
}
|
||||
} else {
|
||||
// remove the items
|
||||
// descending order, because earlier removals shift the rest of the vector
|
||||
FOR_EACH_CONST_REVERSE(s, steps) {
|
||||
assert(s.pos < container.size());
|
||||
container.erase(container.begin() + s.pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
#endif
|
||||
@@ -447,7 +447,7 @@ ScriptValueP replace_rule(Context& ctx) {
|
||||
ret->replacement = replace->toString();
|
||||
}
|
||||
// in_context
|
||||
SCRIPT_OPTIONAL_PARAM_N(String, _("in context"), in_context) {
|
||||
SCRIPT_OPTIONAL_PARAM_C(String, in_context) {
|
||||
if (!ret->context.Compile(in_context, wxRE_ADVANCED)) {
|
||||
throw ScriptError(_("Error while compiling regular expression: '")+in_context+_("'"));
|
||||
}
|
||||
@@ -479,7 +479,7 @@ class ScriptFilterRule : public ScriptValue {
|
||||
bool ok = regex.GetMatch(&start, &len, 0);
|
||||
assert(ok);
|
||||
String inside = input.substr(start, len); // the match
|
||||
String next_input = input.substr(start + len); // everything after the match
|
||||
String next_input = input.substr(start + len); // everything after the match
|
||||
if (!context.IsValid() || context.Matches(input.substr(0,start) + _("<match>") + next_input)) {
|
||||
// no context or context match
|
||||
ret += inside;
|
||||
@@ -497,7 +497,7 @@ class ScriptFilterRule : public ScriptValue {
|
||||
ScriptValueP filter_rule(Context& ctx) {
|
||||
// cached?
|
||||
SCRIPT_PARAM_C(String, match);
|
||||
SCRIPT_PARAM_DEFAULT_N(String, _("in context"), in_context, String());
|
||||
SCRIPT_PARAM_DEFAULT_C(String, in_context, String());
|
||||
|
||||
// cache
|
||||
const int CACHE_SIZE = 6;
|
||||
@@ -540,6 +540,59 @@ SCRIPT_FUNCTION(filter_text) {
|
||||
return filter_rule(ctx)->eval(ctx);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rules : regex filter/break
|
||||
|
||||
class ScriptBreakRule : public ScriptValue {
|
||||
public:
|
||||
virtual ScriptType type() const { return SCRIPT_FUNCTION; }
|
||||
virtual String typeName() const { return _("break_rule"); }
|
||||
virtual ScriptValueP eval(Context& ctx) const {
|
||||
SCRIPT_PARAM_C(String, input);
|
||||
intrusive_ptr<ScriptCustomCollection> ret(new ScriptCustomCollection);
|
||||
while (regex.Matches(input)) {
|
||||
// match, append to result
|
||||
size_t start, len;
|
||||
bool ok = regex.GetMatch(&start, &len, 0);
|
||||
assert(ok);
|
||||
String inside = input.substr(start, len); // the match
|
||||
String next_input = input.substr(start + len); // everything after the match
|
||||
if (!context.IsValid() || context.Matches(input.substr(0,start) + _("<match>") + next_input)) {
|
||||
// no context or context match
|
||||
ret->value.push_back(to_script(inside));
|
||||
}
|
||||
input = next_input;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
wxRegEx regex; ///< Regex to match
|
||||
wxRegEx context; ///< Match only in a given context, optional
|
||||
};
|
||||
|
||||
// Create a regular expression rule for breaking strings
|
||||
ScriptValueP break_rule(Context& ctx) {
|
||||
intrusive_ptr<ScriptBreakRule> ret(new ScriptBreakRule);
|
||||
// match
|
||||
SCRIPT_PARAM_C(String, match);
|
||||
if (!ret->regex.Compile(match, wxRE_ADVANCED)) {
|
||||
throw ScriptError(_("Error while compiling regular expression: '")+match+_("'"));
|
||||
}
|
||||
// in_context
|
||||
SCRIPT_OPTIONAL_PARAM_C(String, in_context) {
|
||||
if (!ret->context.Compile(in_context, wxRE_ADVANCED)) {
|
||||
throw ScriptError(_("Error while compiling regular expression: '")+in_context+_("'"));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(break_rule) {
|
||||
return break_rule(ctx);
|
||||
}
|
||||
SCRIPT_FUNCTION(break_text) {
|
||||
return break_rule(ctx)->eval(ctx);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rules : regex match
|
||||
|
||||
class ScriptMatchRule : public ScriptValue {
|
||||
@@ -657,10 +710,12 @@ void init_script_basic_functions(Context& ctx) {
|
||||
// advanced string rules/functions
|
||||
ctx.setVariable(_("replace"), script_replace);
|
||||
ctx.setVariable(_("filter text"), script_filter_text);
|
||||
ctx.setVariable(_("break text"), script_break_text);
|
||||
ctx.setVariable(_("match"), script_match);
|
||||
ctx.setVariable(_("sort text"), script_sort_text);
|
||||
ctx.setVariable(_("replace rule"), script_replace_rule);
|
||||
ctx.setVariable(_("filter rule"), script_filter_rule);
|
||||
ctx.setVariable(_("break rule"), script_break_rule);
|
||||
ctx.setVariable(_("match rule"), script_match_rule);
|
||||
ctx.setVariable(_("sort rule"), script_sort_rule);
|
||||
}
|
||||
|
||||
@@ -136,6 +136,8 @@ inline Type from_script(const ScriptValueP& v, Variable var) {
|
||||
#define SCRIPT_PARAM_DEFAULT_N(Type, str, name, def) \
|
||||
ScriptValueP name##_ = ctx.getVariableOpt(str); \
|
||||
Type name = name##_ ? from_script<Type>(name##_, str) : def
|
||||
#define SCRIPT_PARAM_DEFAULT_C(Type, name, def) \
|
||||
SCRIPT_PARAM_DEFAULT_N(Type, SCRIPT_VAR_ ## name, name, name)
|
||||
|
||||
// ----------------------------------------------------------------------------- : Rules
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ enum Variable
|
||||
, SCRIPT_VAR_in
|
||||
, SCRIPT_VAR_match
|
||||
, SCRIPT_VAR_replace
|
||||
, SCRIPT_VAR_in_context
|
||||
, SCRIPT_VAR_order
|
||||
, SCRIPT_VAR_filter
|
||||
, SCRIPT_VAR_choice
|
||||
|
||||
Reference in New Issue
Block a user