In Specman, how can I tell if a reference to a unit has the do-not-generate modifier in front of it? - verification

In Specman, how can I tell if a reference to a unit has the do-not-generate modifier, '!', at the reference's definition?
e.g.
unit foo_u {
};
extend sys {
foo : foo_u is instance;
foo_ptr_generated : foo_u;
keep foo_ptr_generated == foo;
!foo_ptr_notgenerated : foo_u;
connect_pointers() is also {
foo_ptr_notgenerated = foo;
};
};
Without inspecting the code or relying on a naming convention, how can I tell that foo_ptr_generated went through Specman's constraint solver and foo_ptr_notgenerated was procedurally set?

Finally figured this out. This code will determine which references are generated and which aren't in Specman 6 via the reflection interface:
<'
type my_t : [ A,B,C];
unit foo_u {
sub_typiness : my_t;
other_sub_typiness : my_t;
when A'sub_typiness foo_u {
!bar_ptr : bar_u;
};
when B'other_sub_typiness foo_u {
in_b_sub_type : int;
};
when A'sub_typiness B'other_sub_typiness foo_u {
in_a_b_subtype :int;
};
b : bah_u is instance;
};
unit bar_u {
sub_typiness : my_t;
other_sub_typiness :my_t;
when B'sub_typiness bar_u {
!foo_ptr : foo_u;
};
when C'other_sub_typiness bar_u {
inc_sub_type : int;
};
when A'other_sub_typiness bar_u {
!you_shouldnt_see_this_field : bah_u;
};
when B'sub_typiness C'other_sub_typiness bar_u{
in_b_c_subtype :int;
};
!b : bah_u;
b2 : bah_u;
};
unit bah_u {
};
extend any_unit {
!path_to_parent :string;
!my_e_path : string;
post_generate() is also {
if not me is a sys {
path_to_parent = get_parent_unit().e_path();
};
my_e_path = e_path();
};
print_pointers() is {
for each ( wf ) in rf_manager.get_struct_of_instance(me).as_a(rf_like_struct).sd_.all_when_fields {
if not str_match(wf.name,"/___/"){
};
};
for each (sub_unit) in get_all_units(any_unit) {
sub_unit.print_pointers();
};
};
};
struct wank_s {
oh_joy: int;
};
extend sys {
foo : A'sub_typiness B'other_sub_typiness foo_u is instance;
bar : B'sub_typiness C'other_sub_typiness bar_u is instance;
keep bar.b2 == foo.b;
wank : wank_s;
connect_pointers() is also {
foo.bar_ptr = bar;
bar.foo_ptr = foo;
bar.b = foo.b;
};
!possible_ptr : any_unit;
!is_a_unit : bool;
!an_e_path : string;
!a_unit : any_unit;
!a_field : field;
--
-- rf_manager.get_all_unit_instances
my_specman( cmd : string ) : bool is {
try {
--out(cmd);
specman(cmd);
} else {
return FALSE;
};
return TRUE;
};
check_generation() is also {
out("PRINT OUT FIELDS");
var all_units : list of any_unit;
for each any_unit(u) in get_all_units(any_unit) {
for each ( wf ) in rf_manager.get_struct_of_instance(u).as_a(rf_like_struct).sd_.all_when_fields {
--print wf.source_ref;
--print wf.source_ref.to_string().as_a(uint);
--if wf.source_ref.to_string().as_a(uint) > 1000 and not str_match(wf.name,"/___/"){
if not str_match(wf.name,"/___|driver_trans/"){
an_e_path = append(u.e_path(),".",wf.name);
an_e_path = append(an_e_path, " - marked_as_reachable=",wf.fgi.marked_as_reachable);
if wf.base_type is a struct_descriptor (s){
an_e_path = append(an_e_path, " - instantiated == ", s.instantiated);
};
if wf.base_type is a struct_descriptor (s) and not s is a list_descriptor and not s is a long_descriptor {
sys.is_a_unit = FALSE;
if not my_specman(append("sys.is_a_unit = ( ",u.e_path(),".",wf.name,
" != NULL)")) {
sys.is_a_unit = FALSE;
};
if sys.is_a_unit {
if not my_specman(append(" sys.is_a_unit = (",u.e_path(),".",wf.name,
".as_a(any_struct) == ",u.e_path(),".",wf.name,".get_enclosing_unit(any_unit).as_a(any_struct))")) {
sys.is_a_unit = FALSE;
};
};
if sys.is_a_unit and str_match(wf.name,"/([\w_]+'+[\w_']*)[\w_]+/") {
if not my_specman( append( "sys.is_a_unit = ( ",u.e_path(),
" is a ", $1, " ",
rf_manager.get_struct_of_instance(u).as_a(rf_like_struct).sd_.name,
")")) {
sys.is_a_unit = FALSE;
};
};
if is_a_unit {
sys.a_unit = NULL;
if not my_specman(append("sys.a_unit = (",u.e_path(),".",wf.name,
".as_a(any_unit))")) {
sys.a_unit = NULL;
};
if sys.a_unit != NULL {
sys.an_e_path = NULL;
var printout := append(":: ",u.e_path(), ".", wf.name);
compute my_specman(append( "sys.an_e_path = ",u.e_path(),".",wf.name,
".my_e_path"));
if append(u.e_path(),".",wf.name) != sys.an_e_path {
printout = append(printout, " -> ");
printout = append(printout, sys.an_e_path);
if wf.fgi != NULL and wf.fgi.gcs.size() > 0 and (
wf.fgi.gcs[0].last_reduction != UNDEF or
wf.fgi.gcs[0].gcois.size() > 0 ) {
printout = append(printout, " GENERATED POINTER");
};
};
out(printout);
};
};
};
--out( " ",an_e_path);
--specman(append("print ",u.e_path(),".",wf.name));
};
};
--for each ( m ) in rf_manager.get_struct_of_instance(u).as_a(rf_like_struct).sd_.methods {
-- if m != NULL {
-- out(m.md.name);
-- };
--};
--print u.get_all_attribute_names();
--print u.get_attribute("agent");
--print u.agent_kind();
-- for each (m) in rf_manager.get_struct_of_instance(u).get_declared_methods() {
-- print m;
-- };
-- out("fields at '",u.e_path(),"'s struct level:");
-- for each (f) in rf_manager.get_struct_of_instance(u).get_declared_fields() {
-- out( " ",u.e_path()," -> ",f.f_.short_name);
-- };
-- out("fields at '",u.e_path(),"'s exact sub-type level:");
-- for each (f) in rf_manager.get_exact_subtype_of_instance(u).get_declared_fields() {
-- out( " ",u.e_path()," -> ",f.f_.short_name);
-- };
-- out("");
};
-- out("\nPRINT OUT UNIT INSTANCES");
-- for each any_unit(u) in {sys;foo;bar} {
-- for each (i) in rf_manager.get_all_unit_instances(u) {
-- if i != u {
-- out(u.e_path(), " has unit ", i.e_path());
-- };
-- };
-- };
};
};
'>
Running with:
specman -c 'load rf_test.e; gen'
Produces:
Generating the test using seed 1...
PRINT OUT FIELDS
:: sys.bar.B'sub_typiness'foo_ptr -> sys.foo
:: sys.bar.b -> sys.foo.b
:: sys.bar.b2 -> sys.foo.b GENERATED POINTER
:: sys.foo.A'sub_typiness'bar_ptr -> sys.bar
:: sys.foo.b
:: sys.logger.base_unit -> sys
:: sys.logger
:: sys.foo
:: sys.bar
Starting the test ...
Running the test ...

Related

Typewriter is not working when loaded via npm import (compiled with Babel)

I set up Typewriter on a site, it works fine when loaded via the direct src.
<script src="https://unpkg.com/typewriter-effect#2.3.1/dist/core.js"></script>
<script>
window.addEventListener('DOMContentLoaded', () => {document.getElementById('typewriter-container');
const typewriter = new Typewriter(whatever, { ... });
...
But when I do it with npm, it doesn't work.
What does "doing it with npm" mean?
Well, since loading stuff the traditional way seems to be outdated... I'm doing the same thing with npm and using the import into a file:
src/typewriter.js
import Typewriter from 'typewriter-effect/dist/core';
And then compiling this file with webpack and babel, and loading that file instead.
<script src="/my_site_stuff/dist/typewriter.js"></script>
This is the compiled file:
dist/typewriter.js
/******/ (function() { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/typewriter-effect/dist/core.js":
/*!*****************************************************!*\
!*** ./node_modules/typewriter-effect/dist/core.js ***!
\*****************************************************/
/***/ (function(module, exports, __webpack_require__) {
/* module decorator */ module = __webpack_require__.nmd(module);
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;function _typeof(obj) { "#babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
!function (e, t) {
"object" == ( false ? 0 : _typeof(exports)) && "object" == ( false ? 0 : _typeof(module)) ? module.exports = t() : true ? !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (t),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) : 0;
}("undefined" != typeof self ? self : this, function () {
return function () {
var e = {
75: function _(e) {
(function () {
var t, n, r, o, a, s;
"undefined" != typeof performance && null !== performance && performance.now ? e.exports = function () {
return performance.now();
} : "undefined" != typeof process && null !== process && process.hrtime ? (e.exports = function () {
return (t() - a) / 1e6;
}, n = process.hrtime, o = (t = function t() {
var e;
return 1e9 * (e = n())[0] + e[1];
})(), s = 1e9 * process.uptime(), a = o - s) : Date.now ? (e.exports = function () {
return Date.now() - r;
}, r = Date.now()) : (e.exports = function () {
return new Date().getTime() - r;
}, r = new Date().getTime());
}).call(this);
},
4087: function _(e, t, n) {
for (var r = n(75), o = "undefined" == typeof window ? n.g : window, a = ["moz", "webkit"], s = "AnimationFrame", i = o["request" + s], u = o["cancel" + s] || o["cancelRequest" + s], l = 0; !i && l < a.length; l++) {
i = o[a[l] + "Request" + s], u = o[a[l] + "Cancel" + s] || o[a[l] + "CancelRequest" + s];
}
if (!i || !u) {
var c = 0,
p = 0,
d = [];
i = function i(e) {
if (0 === d.length) {
var t = r(),
n = Math.max(0, 16.666666666666668 - (t - c));
c = n + t, setTimeout(function () {
var e = d.slice(0);
d.length = 0;
for (var t = 0; t < e.length; t++) {
if (!e[t].cancelled) try {
e[t].callback(c);
} catch (e) {
setTimeout(function () {
throw e;
}, 0);
}
}
}, Math.round(n));
}
return d.push({
handle: ++p,
callback: e,
cancelled: !1
}), p;
}, u = function u(e) {
for (var t = 0; t < d.length; t++) {
d[t].handle === e && (d[t].cancelled = !0);
}
};
}
e.exports = function (e) {
return i.call(o, e);
}, e.exports.cancel = function () {
u.apply(o, arguments);
}, e.exports.polyfill = function (e) {
e || (e = o), e.requestAnimationFrame = i, e.cancelAnimationFrame = u;
};
}
},
t = {};
function n(r) {
var o = t[r];
if (void 0 !== o) return o.exports;
var a = t[r] = {
exports: {}
};
return e[r].call(a.exports, a, a.exports, n), a.exports;
}
n.n = function (e) {
var t = e && e.__esModule ? function () {
return e.default;
} : function () {
return e;
};
return n.d(t, {
a: t
}), t;
}, n.d = function (e, t) {
for (var r in t) {
n.o(t, r) && !n.o(e, r) && Object.defineProperty(e, r, {
enumerable: !0,
get: t[r]
});
}
}, n.g = function () {
if ("object" == (typeof globalThis === "undefined" ? "undefined" : _typeof(globalThis))) return globalThis;
try {
return this || new Function("return this")();
} catch (e) {
if ("object" == (typeof window === "undefined" ? "undefined" : _typeof(window))) return window;
}
}(), n.o = function (e, t) {
return Object.prototype.hasOwnProperty.call(e, t);
};
var r = {};
return function () {
"use strict";
n.d(r, {
default: function _default() {
return S;
}
});
var e = n(4087),
t = n.n(e);
var o = function o(e) {
return new RegExp(/<[a-z][\s\S]*>/i).test(e);
},
a = function a(e) {
var t = document.createElement("div");
return t.innerHTML = e, t.childNodes;
},
s = function s(e, t) {
return Math.floor(Math.random() * (t - e + 1)) + e;
};
var i = "TYPE_CHARACTER",
u = "REMOVE_CHARACTER",
l = "REMOVE_ALL",
c = "REMOVE_LAST_VISIBLE_NODE",
p = "PAUSE_FOR",
d = "CALL_FUNCTION",
f = "ADD_HTML_TAG_ELEMENT",
v = "CHANGE_DELETE_SPEED",
h = "CHANGE_DELAY",
m = "CHANGE_CURSOR",
y = "PASTE_STRING",
g = "HTML_TAG";
function E(e, t) {
var n = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var r = Object.getOwnPropertySymbols(e);
t && (r = r.filter(function (t) {
return Object.getOwnPropertyDescriptor(e, t).enumerable;
})), n.push.apply(n, r);
}
return n;
}
function w(e) {
for (var t = 1; t < arguments.length; t++) {
var n = null != arguments[t] ? arguments[t] : {};
t % 2 ? E(Object(n), !0).forEach(function (t) {
N(e, t, n[t]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : E(Object(n)).forEach(function (t) {
Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(n, t));
});
}
return e;
}
function T(e) {
return function (e) {
if (Array.isArray(e)) return b(e);
}(e) || function (e) {
if ("undefined" != typeof Symbol && null != e[Symbol.iterator] || null != e["##iterator"]) return Array.from(e);
}(e) || function (e, t) {
if (e) {
if ("string" == typeof e) return b(e, t);
var n = Object.prototype.toString.call(e).slice(8, -1);
return "Object" === n && e.constructor && (n = e.constructor.name), "Map" === n || "Set" === n ? Array.from(e) : "Arguments" === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n) ? b(e, t) : void 0;
}
}(e) || function () {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}();
}
function b(e, t) {
(null == t || t > e.length) && (t = e.length);
for (var n = 0, r = new Array(t); n < t; n++) {
r[n] = e[n];
}
return r;
}
function A(e, t) {
for (var n = 0; n < t.length; n++) {
var r = t[n];
r.enumerable = r.enumerable || !1, r.configurable = !0, "value" in r && (r.writable = !0), Object.defineProperty(e, r.key, r);
}
}
function N(e, t, n) {
return t in e ? Object.defineProperty(e, t, {
value: n,
enumerable: !0,
configurable: !0,
writable: !0
}) : e[t] = n, e;
}
var S = function () {
function n(r, E) {
var b = this;
if (function (e, t) {
if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function");
}(this, n), N(this, "state", {
cursorAnimation: null,
lastFrameTime: null,
pauseUntil: null,
eventQueue: [],
eventLoop: null,
eventLoopPaused: !1,
reverseCalledEvents: [],
calledEvents: [],
visibleNodes: [],
initialOptions: null,
elements: {
container: null,
wrapper: document.createElement("span"),
cursor: document.createElement("span")
}
}), N(this, "options", {
strings: null,
cursor: "|",
delay: "natural",
pauseFor: 1500,
deleteSpeed: "natural",
loop: !1,
autoStart: !1,
devMode: !1,
skipAddStyles: !1,
wrapperClassName: "Typewriter__wrapper",
cursorClassName: "Typewriter__cursor",
stringSplitter: null,
onCreateTextNode: null,
onRemoveNode: null
}), N(this, "setupWrapperElement", function () {
b.state.elements.container && (b.state.elements.wrapper.className = b.options.wrapperClassName, b.state.elements.cursor.className = b.options.cursorClassName, b.state.elements.cursor.innerHTML = b.options.cursor, b.state.elements.container.innerHTML = "", b.state.elements.container.appendChild(b.state.elements.wrapper), b.state.elements.container.appendChild(b.state.elements.cursor));
}), N(this, "start", function () {
return b.state.eventLoopPaused = !1, b.runEventLoop(), b;
}), N(this, "pause", function () {
return b.state.eventLoopPaused = !0, b;
}), N(this, "stop", function () {
return b.state.eventLoop && ((0, e.cancel)(b.state.eventLoop), b.state.eventLoop = null), b;
}), N(this, "pauseFor", function (e) {
return b.addEventToQueue(p, {
ms: e
}), b;
}), N(this, "typeOutAllStrings", function () {
return "string" == typeof b.options.strings ? (b.typeString(b.options.strings).pauseFor(b.options.pauseFor), b) : (b.options.strings.forEach(function (e) {
b.typeString(e).pauseFor(b.options.pauseFor).deleteAll(b.options.deleteSpeed);
}), b);
}), N(this, "typeString", function (e) {
var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : null;
if (o(e)) return b.typeOutHTMLString(e, t);
if (e) {
var n = b.options || {},
r = n.stringSplitter,
a = "function" == typeof r ? r(e) : e.split("");
b.typeCharacters(a, t);
}
return b;
}), N(this, "pasteString", function (e) {
var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : null;
return o(e) ? b.typeOutHTMLString(e, t, !0) : (e && b.addEventToQueue(y, {
character: e,
node: t
}), b);
}), N(this, "typeOutHTMLString", function (e) {
var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : null,
n = arguments.length > 2 ? arguments[2] : void 0,
r = a(e);
if (r.length > 0) for (var o = 0; o < r.length; o++) {
var s = r[o],
i = s.innerHTML;
s && 3 !== s.nodeType ? (s.innerHTML = "", b.addEventToQueue(f, {
node: s,
parentNode: t
}), n ? b.pasteString(i, s) : b.typeString(i, s)) : s.textContent && (n ? b.pasteString(s.textContent, t) : b.typeString(s.textContent, t));
}
return b;
}), n;
}();
}(), r.default;
}();
});
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ id: moduleId,
/******/ loaded: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ !function() {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function() { return module['default']; } :
/******/ function() { return module; };
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ !function() {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = function(exports, definition) {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ !function() {
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ }();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ !function() {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/node module decorator */
/******/ !function() {
/******/ __webpack_require__.nmd = function(module) {
/******/ module.paths = [];
/******/ if (!module.children) module.children = [];
/******/ return module;
/******/ };
/******/ }();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be in strict mode.
!function() {
"use strict";
/*!*************************************!*\
!*** ./src/js/typewriter-effect.js ***!
\*************************************/
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var typewriter_effect_dist_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! typewriter-effect/dist/core */ "./node_modules/typewriter-effect/dist/core.js");
/* harmony import */ var typewriter_effect_dist_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(typewriter_effect_dist_core__WEBPACK_IMPORTED_MODULE_0__);
}();
/******/ })()
;
//# sourceMappingURL=typeWriter.js.map
How do I know what the problem is?
Webpack encloses everything in the compiled file so nothing leaks into the global scope.
You'd have to change your src file and do:
import Typewriter from 'typewriter-effect/dist/core';
window.Typewriter = Typewriter;
Then, when using it, instead of:
const typewriter = new Typewriter(...);
Just do:
const typewriter = new window.Typewriter(...);
What we are doing here is, making it available to the global scope.

Segmentation fault in the below program

The below code is being called from a simple script like this.
$test.line-validation();
method line-validation is rw {
my $file-data = slurp($!FileName, enc => "iso-8859-1");
my #lines = $file-data.lines;
my $start = now;
for #lines -> $line {
state $i = 1;
my #splitLine = split('|', $line);
if ($line.starts-with("H|") || $line.starts-with("T|")) {
next;
}
my $lnObject = LineValidation.new( line => $line, FileType => $.FileType );
$lnObject.ColumnIds = %.ColumnIds;
my #promises;
my #validationIds;
for %.ValidationRules.keys -> $validationId {
if (%.ValidationRules{$validationId}<ValidationType> eq 'COLUMN') {
push #promises, start {$lnObject.ColumnValidationFunction(%.ValidationRules{$validationId}<ValidationFunction>, %.ValidationRules{$validationId}<Arguments>, $.ValidationRules{$validationId}<Description>); 1};
push #validationIds, $validationId;
}
}
my #promise-output = await #promises;
for #validationIds -> $valId {
state $j = 0;
my $result = #promise-output[$j];
if ($result.Bool == True) {
if (%.ResultSet{$valId}<count> :!exists) {
%.ResultSet{$valId}<count> = 1;
} else {
%.ResultSet{$valId}<count> = %.ResultSet{$valId}<count> + 1;
}
my #prCol = (%.ValidationRules{$valId}<Arguments><column>, #.printColumns);
if (%.ResultSet{$valId}<count> <= 10) {
%.ResultSet{$valId}.push: (sample => join('|', #splitLine[#prCol[*;*]].map: { if ($_.Bool == False ) { $_ = ''} else {$_ = $_;} }));
}
%.ResultSet{$valId}<ColumnList> = #prCol[*;*];
}
$j++;
}
$i++;
}
say "Line validation completed in {now - $start } time for $.lineCount lines";
}
The code was working fine earlier but when run using larger files, it just arbitrarily throws the error Segmentation fault and exists. I cannot determine where it is failing either.

CKEditor5 Custom Plugin changes the Model but not the View

I have create a custom build of CKEditor5 and created a plugin BorderColor. The Plugin isn't working good. The problem is that the model is changing, but the view isn't changed.
border-color.js
import Plugin from '#ckeditor/ckeditor5-core/src/plugin';
import BorderColorEditing from './border-color-editing';
import BorderColorUi from './border-color-ui';
export default class BorderColor extends Plugin {
/**
* #inheritDoc
*/
static get requires() {
return [ BorderColorEditing, BorderColorUi ];
}
/**
* #inheritDoc
*/
static get pluginName() {
return 'BorderColor';
}
}
border-color-ui.js
import ColorUI from '#ckeditor/ckeditor5-font/src/ui/colorui';
export default class BorderColorUi extends ColorUI {
/**
* #inheritDoc
*/
constructor( editor ) {
const t = editor.locale.t;
super( editor, {
commandName: 'borderColor',
componentName: 'borderColor',
dropdownLabel: t( 'Rahmenfarbe' )
} );
}
/**
* #inheritDoc
*/
static get pluginName() {
return 'BorderColorUI';
}
}
border-color-editing.js
import Plugin from '#ckeditor/ckeditor5-core/src/plugin';
import BorderColorCommand from './border-color-command';
import { isDefault, isSupported, supportedOptions } from './utils';
export default class BorderColorEditing extends Plugin {
/**
* #inheritDoc
*/
constructor( editor ) {
super( editor );
editor.config.define( 'borderColor', supportedOptions );
}
/**
* #inheritDoc
*/
init() {
const editor = this.editor;
const schema = editor.model.schema;
// Filter out unsupported options.
const enabledOptions = editor.config.get( 'borderColor.colors' );
// Allow alignment attribute on all blocks.
schema.extend( '$block', { allowAttributes: 'borderColor' } );
editor.model.schema.setAttributeProperties( 'borderColor', { isFormatting: true } );
editor.model.schema.addAttributeCheck( ( context, attributeName ) => {
if ( context.endsWith( 'table' ) || context.endsWith( 'tableRow' ) || context.endsWith( 'tableCell' )) {
return true;
}
} );
const definition = _buildDefinition( enabledOptions.filter( option => !isDefault( option ) ) );
editor.conversion.attributeToAttribute( definition );
editor.commands.add( 'borderColor', new BorderColorCommand( editor ) );
}
}
// Utility function responsible for building converter definition.
// #private
function _buildDefinition( options ) {
const definition = {
model: {
key: 'borderColor',
values: options.slice()
},
view: {}
};
for ( const option of options ) {
const _def = { key: 'style', value: {} };
_def.value[ 'border-color' ] = option.color;
definition.view[ option ] = _def;
}
return definition;
}
border-color-command.js
import Command from '#ckeditor/ckeditor5-core/src/command';
import first from '#ckeditor/ckeditor5-utils/src/first';
import { isDefault } from './utils';
const BORDER_COLOR = 'borderColor';
export default class BorderColorCommand extends Command {
/**
* #inheritDoc
*/
refresh() {
let childBlocks;
if ( this.editor.model.document.selection.getSelectedElement() != null )
childBlocks = this.getSelectedBlocks( this.editor.model.document, 'all-tablerow' );
const firstBlock = this.editor.model.document.selection.getSelectedElement() != null
? this.editor.model.document.selection.getSelectedElement()
: first( this.editor.model.document.selection.getSelectedBlocks() );
// As first check whether to enable or disable the command as the value will always be false if the command cannot be enabled.
this.isEnabled = !!firstBlock && this._canBeAligned( firstBlock );
/**
* A value of the current block's alignment.
*
* #observable
* #readonly
* #member {String} #value
*/
if ( this.isEnabled && firstBlock.hasAttribute( BORDER_COLOR ) )
this.value = firstBlock.getAttribute( BORDER_COLOR );
else if ( this.isEnabled && childBlocks && childBlocks[ 0 ].hasAttribute( BORDER_COLOR ) )
this.value = childBlocks[ 0 ].getAttribute( BORDER_COLOR );
else
this.value = '';
}
/**
* Executes the command. Applies the alignment `value` to the selected blocks.
* If no `value` is passed, the `value` is the default one or it is equal to the currently selected block's alignment attribute,
* the command will remove the attribute from the selected blocks.
*
* #param {Object} [options] Options for the executed command.
* #param {String} [options.value] The value to apply.
* #fires execute
*/
execute( options = {} ) {
const editor = this.editor;
const model = editor.model;
const doc = model.document;
const value = options.value;
model.change( writer => {
let childBlocks;
if ( this.editor.model.document.selection.getSelectedElement() != null )
childBlocks = this.getSelectedBlocks( this.editor.model.document, 'all-tablerow' );
const firstBlock = this.editor.model.document.selection.getSelectedElement() != null
? this.editor.model.document.selection.getSelectedElement()
: first( this.editor.model.document.selection.getSelectedBlocks() );
let currentAlignment;
if ( firstBlock.hasAttribute( BORDER_COLOR ) )
currentAlignment = firstBlock.getAttribute( BORDER_COLOR );
else if ( childBlocks && childBlocks[ 0 ].hasAttribute( BORDER_COLOR ) )
currentAlignment = childBlocks[ 0 ].getAttribute( BORDER_COLOR );
// Remove alignment attribute if current alignment is:
// - default (should not be stored in model as it will bloat model data)
// - equal to currently set
// - or no value is passed - denotes default alignment.
const removeAlignment = isDefault( value ) || currentAlignment === value || !value;
console.log( 'childBlocks / firstBlock', childBlocks, firstBlock, currentAlignment);
const blocks = childBlocks ? Array.from( childBlocks ) : [];
blocks.push( firstBlock );
if ( removeAlignment ) {
removeAlignmentFromSelection( blocks, writer );
} else {
setAlignmentOnSelection( blocks, writer, value );
}
} );
}
getSelectedBlocks( doc, value ) {
let blocks;
if ( doc.selection.getSelectedElement() == null )
blocks = Array.from( doc.selection.getSelectedBlocks() ).filter( block => this._canBeAligned( block ) )
else {
blocks = [ doc.selection.getSelectedElement() ];
if ( value.indexOf( 'tablerow' ) > -1 ) {
var children = doc.selection.getSelectedElement().getChildren();
console.log( 'Selected Element Children', children );
var out = [];
let _next = children.next();
while ( !_next.done ) {
console.log( _next );
if ( _next.value.getChildren ) {
const children2 = _next.value.getChildren();
let _next2 = children2.next();
while ( !_next2.done ) {
console.log( _next2 );
out[ out.length ] = _next2.value;
_next2 = children2.next();
}
}
else {
out[ out.length ] = _next.value;
}
_next = children.next();
}
blocks = out;
}
}
return blocks;
}
/**
* Checks whether a block can have alignment set.
*
* #private
* #param {module:engine/model/element~Element} block The block to be checked.
* #returns {Boolean}
*/
_canBeAligned( block ) {
return this.editor.model.schema.checkAttribute( block, BORDER_COLOR );
}
}
// Removes the alignment attribute from blocks.
// #private
function removeAlignmentFromSelection( blocks, writer ) {
for ( const block of blocks ) {
writer.removeAttribute( BORDER_COLOR, block );
}
}
// Sets the alignment attribute on blocks.
// #private
function setAlignmentOnSelection( blocks, writer, border ) {
for ( const block of blocks ) {
writer.setAttribute( BORDER_COLOR, border, block );
}
}
The code can also be seen at Github: CKEditor Custom Build Github.
I have found a solution.
I edited border-color-editing.js:
I replaced following code:
editor.conversion.attributeToAttribute( definition );
with:
editor.conversion.for( 'downcast' ).attributeToAttribute( {
model: 'borderColor',
view: function( option ) {
const allSelectedBlocks = getAllSelectedBlocks( this.editor );
const borderAttribute = allSelectedBlocks[ 0 ].getAttribute( BORDER );
if ( !borderAttribute || !option )
return { key: 'style', value: '' };
const _value = {};
const styleOption = borderAttribute.replace( '-tablerow', '' );
_value[ 'border' + ( styleOption == 'all' ? '' : '-' + styleOption ) + '-color' ] = option ? option : 'black';
return { key: 'style', value: _value };
}.bind( this )
} );

Ripple exchanges websocket equivalent for ripple data apiv2

I'm trying to get the exchanges in ripple and I found this data API and its working. But I want to use the ripple websocket tool for some reasons. Is there any websocket equivalent for this data API?
I think there is equivalent if you use "tx_history" command in the socket but Sorry to tell you that the json result are not equal to your specific data result.
ripple data apiv2 is being played by ajax. see the result json formatter in ripple for exchange:
} else if (resp.rows.length) {
resp.rows[0] = {
base_currency: resp.rows[0].base_currency,
base_issuer: resp.rows[0].base_issuer,
base_amount: resp.rows[0].base_amount,
counter_amount: resp.rows[0].counter_amount,
counter_currency: resp.rows[0].counter_currency,
counter_issuer: resp.rows[0].counter_issuer,
rate: resp.rows[0].rate,
executed_time: resp.rows[0].executed_time,
ledger_index: resp.rows[0].ledger_index,
buyer: resp.rows[0].buyer,
seller: resp.rows[0].seller,
taker: resp.rows[0].taker,
provider: resp.rows[0].provider,
autobridged_currency: resp.rows[0].autobridged_currency,
autobridged_issuer: resp.rows[0].autobridged_issuer,
offer_sequence: resp.rows[0].offer_sequence,
tx_type: resp.rows[0].tx_type,
tx_index: resp.rows[0].tx_index,
node_index: resp.rows[0].node_index,
tx_hash: resp.rows[0].tx_hash
};
}
res.csv(resp.rows, filename);
} else {
res.json({
result: 'success',
count: resp.rows.length,
marker: resp.marker,
exchanges: resp.rows
});
} }
and it can be only access by get url :
route: '/v2/exchanges/{:base}/{:counter}'
that is bind in there server.js:
app.get('/v2/exchanges/:base/:counter', routes.getExchanges);
and last hint this is their database query using hbase:
HbaseClient.getExchanges = function (options, callback) {
var base = options.base.currency + '|' + (options.base.issuer || '');
var counter = options.counter.currency + '|' + (options.counter.issuer
||''); var table;
var keyBase;
var startRow;
var endRow;
var descending;
var columns;
if (counter.toLowerCase() > base.toLowerCase()) {
keyBase = base + '|' + counter;
} else {
keyBase = counter + '|' + base;
options.invert = true; }
if (!options.interval) {
table = 'exchanges';
descending = options.descending ? true : false;
options.unreduced = true;
//only need certain columns
if (options.reduce) {
columns = [
'd:base_amount',
'd:counter_amount',
'd:rate',
'f:executed_time',
'f:buyer',
'f:seller',
'f:taker'
];
}
} else if (exchangeIntervals.indexOf(options.interval) !== -1) {
keyBase = options.interval + '|' + keyBase;
descending = options.descending ? true : false;
table = 'agg_exchanges';
} else {
callback('invalid interval: ' + options.interval);
return; }
startRow = keyBase + '|' + options.start.hbaseFormatStartRow();
endRow = keyBase + '|' + options.end.hbaseFormatStopRow();
if (options.autobridged) {
options.filterstring = "DependentColumnFilter('f', 'autobridged_currency')";
if (columns) {
columns.push('f:autobridged_currency');
} }
this.getScanWithMarker(this, {
table: table,
startRow: startRow,
stopRow: endRow,
marker: options.marker,
limit: options.limit,
descending: descending,
columns: columns,
filterString: options.filterstring }, function (err, resp) {
if (!resp) {
resp = {rows: []};
}
if (!resp.rows) {
resp.rows = [];
}
if (options.reduce && options.unreduced) {
if (descending) {
resp.rows.reverse();
}
resp.reduced = reduce(resp.rows);
} else if (table === 'exchanges') {
resp.rows = formatExchanges(resp.rows);
} else {
resp.rows = formatAggregates(resp.rows);
}
callback(err, resp); });
/** * formatExchanges */
function formatExchanges (rows) {
rows.forEach(function(row) {
var key = row.rowkey.split('|');
delete row.base_issuer;
delete row.base_currency;
delete row.counter_issuer;
delete row.counter_currency;
row.base_amount = parseFloat(row.base_amount);
row.counter_amount = parseFloat(row.counter_amount);
row.rate = parseFloat(row.rate);
row.offer_sequence = Number(row.offer_sequence || 0);
row.ledger_index = Number(row.ledger_index);
row.tx_index = Number(key[6]);
row.node_index = Number(key[7]);
row.time = utils.unformatTime(key[4]).unix();
});
if (options.invert) {
rows = invertPair(rows);
}
return rows; }
/** * formatAggregates */
function formatAggregates (rows) {
rows.forEach(function(row) {
var key = row.rowkey.split('|');
row.base_volume = parseFloat(row.base_volume),
row.counter_volume = parseFloat(row.counter_volume),
row.buy_volume = parseFloat(row.buy_volume),
row.count = Number(row.count);
row.open = parseFloat(row.open);
row.high = parseFloat(row.high);
row.low = parseFloat(row.low);
row.close = parseFloat(row.close);
row.vwap = parseFloat(row.vwap);
row.close_time = Number(row.close_time);
row.open_time = Number(row.open_time);
});
if (options.invert) {
rows = invertPair(rows);
}
return rows; }
/** * if the base/counter key was inverted, we need to swap * some of the values in the results */
function invertPair (rows) {
var swap;
var i;
if (options.unreduced) {
for (i=0; i<rows.length; i++) {
rows[i].rate = 1/rows[i].rate;
//swap base and counter vol
swap = rows[i].base_amount;
rows[i].base_amount = rows[i].counter_amount;
rows[i].counter_amount = swap;
//swap buyer and seller
swap = rows[i].buyer;
rows[i].buyer = rows[i].seller;
rows[i].seller = swap;
}
} else {
for (i=0; i<rows.length; i++) {
//swap base and counter vol
swap = rows[i].base_volume;
rows[i].base_volume = rows[i].counter_volume;
rows[i].counter_volume = swap;
//swap high and low
swap = 1/rows[i].high;
rows[i].high = 1/rows[i].low;
rows[i].low = swap;
//invert open, close, vwap
rows[i].open = 1/rows[i].open;
rows[i].close = 1/rows[i].close;
rows[i].vwap = 1/rows[i].vwap;
//invert buy_volume
rows[i].buy_volume /= rows[i].vwap;
}
}
return rows; }
/** * reduce * reduce all rows */
function reduce (rows) {
var buyVolume = 0;
var reduced = {
open: 0,
high: 0,
low: Infinity,
close: 0,
base_volume: 0,
counter_volume: 0,
buy_volume: 0,
count: 0,
open_time: 0,
close_time: 0
};
rows = formatExchanges(rows);
// filter out small XRP amounts
rows = rows.filter(function(row) {
if (options.base.currency === 'XRP' && row.base_amount < 0.0005) {
return false;
} else if (options.counter.currency === 'XRP' && row.counter_amount < 0.0005) {
return false;
} else {
return true;
}
});
if (rows.length) {
reduced.open_time = moment.unix(rows[0].time).utc().format();
reduced.close_time = moment.unix(rows[rows.length-1].time).utc().format();
reduced.open = rows[0].rate;
reduced.close = rows[rows.length -1].rate;
reduced.count = rows.length;
} else {
reduced.low = 0;
return reduced;
}
rows.forEach(function(row) {
reduced.base_volume += row.base_amount;
reduced.counter_volume += row.counter_amount;
if (row.rate < reduced.low) reduced.low = row.rate;
if (row.rate > reduced.high) reduced.high = row.rate;
if (row.buyer === row.taker) {
reduced.buy_volume += row.base_amount;
}
});
reduced.vwap = reduced.counter_volume / reduced.base_volume;
return reduced; } };
Maybe you should make a custom websocket that make your RPC call upgrade to 1.1 http protocol (ws).
In nodejs you can simply
// for http
var http = require('http');
// for websocket
var ws = require("nodejs-websocket")
var options = {
host: 'URL-RPC-HERE',
port: '80',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': post_data.length
}
};
var req = http.request(options, function(res) {
// after getting the response wich is the <res>
// we can upgrade it to ws
upToWebsocket(res);
});
//Upgrade to websocket
var upToWebsocket = function(json) {
var server = ws.createServer(function (conn) {
conn.on("json", function (str) {
conn.sendText(str.toUpperCase()+"!!!")
})
conn.on("close", function (code, reason) {
console.log("Connection closed")
})
}).listen(8001)
}
And also if you have Rippled running on a server this does not help because there's no RPC or WS that supports exchange API.

Rename & Copy Multiple Files (Different names) to One Name With Numbers

how can I rename or copy multiple files (with different name without numbers like "jhf.mp4" "JJHGF.flv" ..) to one name with numbers like (input_01.mp4 input_02 ....) (order by case) by batch file by giving just path of (folder files) to batch file or dropping the files to it (patch file).
-- MEAN USING VARIABLE OR (dropping with %*) .
Note 1: I need this technique for encoding animes with X264 if any other good ideas I'll be happy to hear it.
Note 2: I'm using Windows 10.
I think you can solve this problem using WSHost-scripts. WSHost-system should be preinstalled on any modern Windows computer.
I designed a system of utilities to tackle your problem:
build-mapping-to-normalized-filenames.js
map-filenames.js
cleanup.cmd
before.cmd
after.cmd
You can find source code for 3-4-5 at the bottom of this answer, and for 1-2 - in separate answers (there is a limit of characters per answer).
1 and 2 are workhorses of this system. Powerful but not user-friendly. Yes you can use them as stand-alone utilities if you understand what input they use.
3-4-5 - are glue that bind this system and expose user-friendly controls.
This system is dependent on absolute paths. But all absolute paths are set as variables at the start of 3-4-5 - so if you want to reorganize system - you need change things there and only there.
This is how it should be deployed at filesystem:
folders:
C:\1\ <- this is the root of system
C:\1\aOrig <- folder for original files
C:\1\norm\ <- folder with files that are part of this system + temp folders
C:\1\norm\backend <- place for non-user-friendly utilities
files:
C:\1\norm\backend\build-mapping-to-normalized-filenames.js
C:\1\norm\backend\map-filenames.js
C:\1\norm\after.cmd
C:\1\norm\before.cmd
C:\1\norm\cleanup.cmd
+files: (these are example international filesnames that you can use for playground to check how system works to make yourserf familiar with it)
C:\1\aOrig\English.txt <- test files, you could add unique content to each
C:\1\aOrig\Русский.txt
C:\1\aOrig\العربية.txt
C:\1\aOrig\ܐܪܡܝܐ.txt
C:\1\aOrig\中文.txt
C:\1\aOrig\日本語.txt
How to use it:
You open your console and go to dir **C:\1\norm**
You call programs in this order:
cleanup.cmd
before.cmd
What happened now is that two interesting temp folders are created:
C:\1\norm\bTemp <- here are normalized files.
C:\1\norm\mappingTemp <- it contains a file with mapping between original and normalized names.
What you must do now - is to process files in C:\1\norm\bTemp - that special processing you mentioned before. Right now for the purposes of learning, you can manually change extensions and contents.
after.cmd
cleanup.cmd
And that's it.
So, if we condence it that's your typical session here, plain and simple -
cleanup.cmd
before.cmd
..do your stuff with files at "C:\1\norm\bTemp"...
after.cmd
cleanup.cmd
Also, you don't need command line to use those - you can open **C:\1\norm** in Explorer and double click those utilities in the order that I explained above - cleanup-before-(..manually do your work with bTemp..)-after-cleanup
Listing for program cleanup.cmd :
#ECHO OFF
:: name of this script...
:: useful for debugging...
SET me=%~nx0
:: aOrig - directory that contains source files...
:: bTemp - temporary working directory...
:: mTemp - temporary directory for mapping.txt...
SET aOrig=C:\1\aOrig
SET bTemp=C:\1\norm\bTemp
SET mTemp=C:\1\norm\mappingTemp
:: Removing temporary folders...
:: Be warned - this RD is working
:: in quiet mode /Q - so it wouldn't ask you politely
:: about del y/n - thus, please make shure that
:: %aOrig% doesn't point to anything
:: important for your personal data or system...
IF EXIST "%bTemp%" RD /S /Q "%bTemp%"
IF EXIST "%mTemp%" RD /S /Q "%mTemp%"
IF %ERRORLEVEL% NEQ 0 (
ECHO Script %me% failed on step cleanup-1: [Removing temporary folders]...
ECHO Error: %ERRORLEVEL%
EXIT /B 1
)
:: Successfully finished
ECHO.
ECHO Script %me% successfully finished!
Listing for program before.cmd :
#ECHO OFF
:: name of this script...
:: useful for debugging...
SET me=%~nx0
:: aOrig - directory that contains original files...
:: bTemp - temporary working directory...
:: mTemp - temporary directory for mapping.txt...
SET aOrig=C:\1\aOrig
SET bTemp=C:\1\norm\bTemp
SET mTemp=C:\1\norm\mappingTemp
:: scriptBuild - name of .js-script for building a map
:: from original to normalized filenames...
:: scriptMapFi - name of .js-script interpreting
:: mapping file that was build by scriptBuild...
:: mappingFile - path for file that will contain mapping between
:: original filenames and normalized filenames...
SET scriptBuild=C:\1\norm\backend\build-mapping-to-normalized-filenames.js
SET scriptMapFi=C:\1\norm\backend\map-filenames.js
SET mappingFile=C:\1\norm\mappingTemp\mapping.txt
:: creating temporary folders...
IF NOT EXIST "%bTemp%" MKDIR "%bTemp%"
IF NOT EXIST "%mTemp%" MKDIR "%mTemp%"
IF %ERRORLEVEL% NEQ 0 (
ECHO Script %me% failed on step before-1: [Creating temporary folders]...
ECHO Error: %ERRORLEVEL%
EXIT /B 1
)
:: now we run build-mapping-to-normalized-filenames.js ...
:: that //U thing is important...
CSCRIPT //U //NoLogo "%scriptBuild%" "%aOrig%" 0 1 > "%mappingFile%"
IF %ERRORLEVEL% NEQ 0 (
ECHO Script %me% failed on step before-2: [Building a list of normalized filenames]...
ECHO Error: %ERRORLEVEL%
EXIT /B 1
)
:: now we run map-filenames.js ...
:: that //U thing is important...
CSCRIPT //U //NoLogo "%scriptMapFi%" "%aOrig%" "%bTemp%" /NotTraining < "%mappingFile%"
IF %ERRORLEVEL% NEQ 0 (
ECHO Script %me% failed on step before-3: [Copy files while simultaneously changing their names to normalised form]...
ECHO Error: %ERRORLEVEL%
EXIT /B 1
)
:: Successfully finished
ECHO.
ECHO Script %me% successfully finished!
Listing for program after.cmd :
#ECHO OFF
:: name of this script...
:: useful for debugging...
SET me=%~nx0
:: aOrig - directory that contains original files...
:: bTemp - temporary working directory...
:: mTemp - temporary directory for mapping.txt...
SET aOrig=C:\1\aOrig
SET bTemp=C:\1\norm\bTemp
SET mTemp=C:\1\norm\mappingTemp
:: scriptBuild - name of .js-script for building a map
:: from original to normalized filenames...
:: scriptMapFi - name of .js-script interpreting
:: mapping file that was build by scriptBuild...
:: mappingFile - path for file that will contain mapping between
:: original filenames and normalized filenames...
SET scriptBuild=C:\1\norm\backend\build-mapping-to-normalized-filenames.js
SET scriptMapFi=C:\1\norm\backend\map-filenames.js
SET mappingFile=C:\1\norm\mappingTemp\mapping.txt
:: Removing files in original folder...
:: Not recursive
:: Be warned - this DEL is working
:: in quiet mode /Q - so it wouldn't ask you politely
:: about del y/n - thus, please make shure that
:: %aOrig% doesn't point to anything
:: important for your personal data or system...
IF EXIST "%aOrig%" DEL /Q "%aOrig%"
IF %ERRORLEVEL% NEQ 0 (
ECHO Script %me% failed on step after-1: [Removing files from original folder]...
ECHO Error: %ERRORLEVEL%
EXIT /B 1
)
:: now we run map-filenames.js ...
:: that //U thing is important...
CSCRIPT //U //NoLogo "%scriptMapFi%" "%bTemp%" "%aOrig%" /NotTraining /MapFrom2To1 /ResultExtension:2 /FuzzyExtensionsFrom < "%mappingFile%"
IF %ERRORLEVEL% NEQ 0 (
ECHO Script %me% failed on step after-2: [Copy files while simultaneously changing their names to normalised form]...
ECHO Error: %ERRORLEVEL%
EXIT /B 1
)
:: Successfully finished
ECHO.
ECHO Script %me% successfully finished!
Listing for program build-mapping-to-normalized-filenames.js :
// - - - - -
// #magicVars #config
// Purpose of basicOptions: organize set of most basic settings
// into a compact object package
var basicOptions = {
// Fist things first -
// "scriptName" will be important for error messages.
// Because when you debug a pipeline of scripts, it is always
// crucial to know - which program in pipeline of 10 utilities
// throws that cryptic stderr message "error: not enough arguments".
// I mean huh? Was that calc-tool.js? Or sort-tool.js? Go figure...
scriptName: WScript.ScriptName.toString(),
// What kind of End Of Line sequence
// (they call it New Line sometimes too)
// you prefer when using outputToolbox?
eolStdOut: '\r\n',
eolStdErr: '\r\n',
// Those are all possible errorCodes that this script
// was designed to fail with.
// You can define other error codes.
// Those SHOULD be integer (not strings).
// Code noErrors = 0 is indication that script finished without errors.
errorCodes: {
noErrors: 0,
badArguments: 1,
badGettingFileList: 2
}
};
// - - - - -
// thisOptions
// Purpose of thisOptions: organize set of hard-coded
// normalisation settings
// into a compact object package
var thisOptions = {
normNameBefore: 'input_',
normNameAfter: ''
}
// - - - - -
// outputToolbox depends on
// basicOptions && WScript
// Purpose of outputToolbox: organize in one group
// functions that are used to
// output chars or messages to stdout or stderr
var outputToolbox = {
// Syntactic sugar for printing exact set of chars to stdout.
print: function( data ) {
// For this script to output UTF characters correctly, program must
// run under /U switch - like
// cscript /U //NoLogo program-name-here.js arg1 arg2
WScript.StdOut.Write( data );
},
// Syntactic sugar for printing one line to stdout.
// terminated with your preferred line-terminator.
printLine: function( data ) {
outputToolbox.print( data );
outputToolbox.print( basicOptions.eolStdOut );
},
// Syntactic sugar for printing exact set of chars to stderr.
printErr: function( data ) {
WScript.StdErr.Write( data );
},
// Syntactic sugar for printing one line to stderr
// terminated with your preferred line-terminator.
printErrLine: function( data ) {
outputToolbox.printErr( data );
outputToolbox.printErr( basicOptions.eolStdErr );
},
// Syntactic sugar for printing one line to stderr
// prepended with meaningful script name (that is useful for debug)
// terminated with your preferred line-terminator.
printErrMessage: function( data ) {
outputToolbox.printErr( basicOptions.scriptName + ' failed' );
outputToolbox.printErr( data );
outputToolbox.printErr( basicOptions.eolStdErr );
},
// Syntactic sugar for printing one line to stderr
// prepended with meaningful script name (that is useful for debug)
// terminated with your preferred line-terminator.
printErrWarning: function( data ) {
outputToolbox.printErr( 'Warning for ' + basicOptions.scriptName + ': ' );
outputToolbox.printErr( data );
outputToolbox.printErr( basicOptions.eolStdErr );
},
// Syntactic sugar for printing Error objects
// catched by throw...catch construction
printErrCatchedErr: function( e ) {
outputToolbox.printErrMessage(
' - catched error details - ' + e.name + ': ' + e.message
);
}
};
// - - - - -
// flowToolbox depends on
// WScript
// Purpose of flowToolbox: organize in one group
// functions that are used to
// control general flow of program
var flowToolbox = {
// Shortcut to kill this script.
// When invoked it stops execution.
die: function ( code ) {
if ( typeof code === 'undefined' ) {
code = 0;
}
WScript.Quit(code);
}
};
// - - - - -
// Here is a cleaner alternative: we pollute only name $b.
// Not so easy to type but later, you can easily find all code calls
// dependant on functions from 'basis'.
// '$b' stands for 'library-b' or more exactly - "library named 'basis'"
var $b = {};
$b.print = outputToolbox.print;
$b.printLine = outputToolbox.printLine;
$b.printErr = outputToolbox.printErr;
$b.printErrLine = outputToolbox.printErrLine;
$b.printErrMessage = outputToolbox.printErrMessage;
$b.printErrWarning = outputToolbox.printErrWarning;
$b.die = flowToolbox.die;
// ^ You can use those as functions now
// - - - - -
// $fileListToolbox
// depends on WScript && ActiveXObject( "Scripting.FileSystemObject" ) && $b
var $fileListToolbox = {
/*
* Input:
* any gibberish that is acceptable
* for your local version of
* Scripting.FileSystemObject
* - like
* getFileListForFolder( 'C:\' );
* getFileListForFolder( 'C:\abc' );
* getFileListForFolder( './' );
* getFileListForFolder( './abc/../abc/..' );
*
* Output:
* aFileList with format:
* empty array
* or
* array of oFileData
* oFileData has format:
* {
* fileNameBase: ...[string],
* fileNameExtension: ...[string],
* parentAbsolutePath: ...[string]
* }
*/
getFileListForFolder: function( folderSpec )
{
var aResult = [];
var fso = new ActiveXObject( "Scripting.FileSystemObject" );
if ( !fso.FolderExists( folderSpec ) ) {
$b.printErrMessage(' folder="' + folderSpec + '" doesn\'t exist');
$b.die( basicOptions.errorCodes.badGettingFileList );
}
var folder = fso.GetFolder( folderSpec );
var files = new Enumerator( folder.files );
for ( ; !files.atEnd(); files.moveNext() ) {
var thisFileItem = files.item();
aResult.push({
fileNameBase: fso.GetBaseName( thisFileItem ),
fileNameExtension: fso.GetExtensionName( thisFileItem ),
parentAbsolutePath: (
fso.GetParentFolderName(
fso.GetAbsolutePathName( thisFileItem )
)
)
});
}
return( aResult );
},
/*
* Purpose:
* Sort files by fileNameBase
*
* Input:
* aFileList
* - format is the same
* as for function $fileListToolbox.getFileListForFolder
*
* Output:
* - format is the same
* as for function $fileListToolbox.getFileListForFolder
*/
sortFileListByFileNameBaseAsc: function( aFileList ) {
var fSort = function( a, b ) {
if ( a.fileNameBase > b.fileNameBase ) {
return 1;
}
if ( a.fileNameBase < b.fileNameBase ) {
return -1;
}
return 0;
}
return aFileList.sort( fSort );
},
/*
* Purpose:
* Tool for displaying contents of fileList
*
* Input:
* aFileList
* - format is the same
* as for function $fileListToolbox.getFileListForFolder
*
* Sideeffects:
* Prints aFileList to the stdout stream
*/
printFileList: function( aFileList, callbackPrintLine ) {
if ( typeof callbackPrintLine === 'undefined' ) {
return;
}
var i;
var L = aFileList.length;
var elem;
for ( i = 0; i < L; i++ ) {
elem = aFileList[i];
callbackPrintLine();
callbackPrintLine( 'i: ' + i );
callbackPrintLine( 'fileNameBase: ' + elem.fileNameBase );
callbackPrintLine( 'fileNameExtension: ' + elem.fileNameExtension );
callbackPrintLine( 'parentAbsolutePath: ' + elem.parentAbsolutePath );
}
}
};
/*
// basic test:
$fileListToolbox.printFileList(
$fileListToolbox.sortFileListByFileNameBaseAsc(
$fileListToolbox.getFileListForFolder( 'bTmp' )
),
$b.printLine
);
*/
// - - - - -
// $mappingEngine
var $mappingEngine = {
// this is a relic from a more complex fileformat...
printHeader: function(
functionPrintChars
) {
},
printBasicFilePair: function(
functionPrintChars,
aFileNameBase, aFileNameExtension,
bFileNameBase, bFileNameExtension
) {
var eol = '\r\n';
if ( aFileNameBase.match( /[\r\n]/ ) !== null ) {
throw new Error(
'error: bad input: aFileNameBase contains end of line symbols'
);
}
if ( bFileNameBase.match( /[\r\n]/ ) !== null ) {
throw new Error(
'error: bad input: bFileNameBase contains end of line symbols'
);
}
if ( aFileNameExtension.match( /[\r\n]/ ) !== null ) {
throw new Error(
'error: bad input: aFileNameExtension contains end of line symbols'
);
}
if ( bFileNameExtension.match( /[\r\n]/ ) !== null ) {
throw new Error(
'error: bad input: bFileNameExtension contains end of line symbols'
);
}
var ar = [
'id:1',
'baseName:' + aFileNameBase,
'extensionName:' + aFileNameExtension,
'id:2',
'baseName:' + bFileNameBase,
'extensionName:' + bFileNameExtension,
':',
''
];
functionPrintChars( ar.join( eol ) );
}
};
/*
//basic test:
$mappingEngine.printHeader( $b.print );
$mappingEngine.printBasicFilePair( $b.print, 'abcdef', 'ext', 'input_001', 'txt' );
$mappingEngine.printBasicFilePair( $b.print, 'ghijkl', 'jpg', 'input_002', 'png' );
*/
// it should print to output:
/*
id:1
baseName:abcdef
extensionName:ext
id:2
baseName:input_001
extensionName:txt
:
id:1
baseName:ghijkl
extensionName:jpg
id:2
baseName:input_002
extensionName:png
:
*/
// - - - - -
function generateFAddLeadingZeroes( minimumLength, startFrom ) {
if ( typeof minimumLength === 'undefined' ) {
minimumLength = 0;
}
if ( typeof startFrom === 'undefined' ) {
startFrom = 0;
}
minimumLength = parseInt( minimumLength ) - 1;
startFrom = parseInt( startFrom );
var fAddLeadingZeroes = function( i, L ) {
i += startFrom;
L += startFrom - 1;
var sResult = i.toString();
if ( minimumLength > 0 ) {
var level = 0;
var tmpL = L;
while (
( tmpL = parseInt( tmpL / 10 ) ) >= 1
) {
++level;
}
level = Math.max( level, minimumLength );
var iLength = sResult.length;
while ( iLength <= level-- ) {
sResult = '0' + sResult;
}
}
return sResult;
}
return fAddLeadingZeroes;
}
// - - - - -
var $thisArguments = {
getArgumentsObj: function() {
return WScript.Arguments;
// mockup for tests in browser
/*
var testArr = [1,2,3,4,5];
var mockupArguments = function( i ) {
return testArr[i];
};
mockupArguments.length = testArr.length;
return mockupArguments;
*/
},
printErrorMessageAndDie: function( meaningfulPart ) {
$b.printErrMessage(
' - problem when ' +
'parsing command-line arguments (options): ' +
''
);
$b.die( basicOptions.errorCodes.badArguments );
},
getArgumentsDummy: function() {
return {
folder: 'C:\abc',
minNOfDigits: 0,
countStart: 1
};
},
print: function( argumentsObject ) {
$b.printErrLine( 'folder: ' + argumentsObject.folder );
$b.printErrLine( 'minNOfDigits: ' + argumentsObject.minNOfDigits );
$b.printErrLine( 'countStart: ' + argumentsObject.countStart );
},
// We don't use any flags it this script...
/*
isThereAFlagInArguments: function( inString ) {
var normalizedEthalon = inString.toString().toLowerCase();
var objArgs = $thisArguments.getArgumentsObj();
var i;
var L = objArgs.length;
for ( i = 2; i < L; i++ ) {
var normalizedArgument = objArgs( i ).toString().toLowerCase();
if ( normalizedEthalon === normalizedArgument ) {
return true;
}
}
return false;
},
*/
getArguments: {
folder: function() {
var rR = '';
var objArgs = $thisArguments.getArgumentsObj();
if ( objArgs.length < 1 ) {
$b.printErrMessage(
' - reason: not enough arguments, ' +
'you MUST to provide at least 1 argument, ' +
'but ammount of arguments you provided ' +
'only: ' + objArgs.length
);
$b.die( basicOptions.errorCodes.badArguments );
}
rR = objArgs(0);
var fso = new ActiveXObject("Scripting.FileSystemObject");
rR = fso.GetAbsolutePathName( rR );
return rR;
},
minNOfDigits: function() {
var rR = '0';
var objArgs = $thisArguments.getArgumentsObj();
if ( objArgs.length >= 2 ) {
rR = objArgs(1);
}
var intRR = parseInt( rR );
// test for NaN
if ( intRR !== intRR ) {
$b.printErrMessage(
' - reason: bad argument 2, ' +
'you MUST to provide non-negative integer, ' +
'but you provided non-integer: ' +
'[' + ( typeof rR ) + ']' +
' "' + rR + '"' +
''
);
$b.die( basicOptions.errorCodes.badArguments );
}
// test for negative
if ( intRR < 0 ) {
$b.printErrMessage(
' - reason: bad argument 2, ' +
'you MUST to provide non-negative integer, ' +
'but you provided negtive integer: ' +
'[' + ( typeof rR ) + ']' +
' "' + rR + '"' +
''
);
$b.die( basicOptions.errorCodes.badArguments );
}
rR = intRR;
return rR;
},
countStart: function() {
var rR = '1';
var objArgs = $thisArguments.getArgumentsObj();
if ( objArgs.length >= 3 ) {
rR = objArgs(2);
}
var intRR = parseInt( rR );
// test for NaN
if ( intRR !== intRR ) {
$b.printErrMessage(
' - reason: bad argument 3, ' +
'you MUST to provide non-negative integer, ' +
'but you provided non-integer: ' +
'[' + ( typeof rR ) + ']' +
' "' + rR + '"' +
''
);
$b.die( basicOptions.errorCodes.badArguments );
}
// test for negative
if ( intRR < 0 ) {
$b.printErrMessage(
' - reason: bad argument 3, ' +
'you MUST to provide non-negative integer, ' +
'but you provided negtive integer: ' +
'[' + ( typeof rR ) + ']' +
' "' + rR + '"' +
''
);
$b.die( basicOptions.errorCodes.badArguments );
}
rR = intRR;
return rR;
}
},
getArgumentsAll: function() {
var $get = $thisArguments.getArguments;
var rR = {
folder: $get.folder(),
minNOfDigits: $get.minNOfDigits(),
countStart: $get.countStart()
};
return rR;
}
};
var $a = $thisArguments;
// - - - - -
function main() {
var $inputOptions = $a.getArgumentsAll();
$b.printErrLine();
$b.printErrLine(
'Arguments for ' + basicOptions.scriptName +
' are interpreted this way:'
);
$a.print( $inputOptions );
$b.printErrLine();
try {
var aFileList = $fileListToolbox.getFileListForFolder( $inputOptions.folder );
} catch (e) {
$b.printErrMessage(
' - problems while trying ' +
'to get list of files from folder: ' +
$inputOptions.folder
);
$b.die( basicOptions.errorCodes.badGettingFileList );
return;
}
aFileList = $fileListToolbox.sortFileListByFileNameBaseAsc( aFileList );
// addLeadingZeroes
// is a function now.
// You can see what arguments it requires
// and output it produces in source for
// generateFAddLeadingZeroes
// function.
var addLeadingZeroes = generateFAddLeadingZeroes(
$inputOptions.minNOfDigits,
$inputOptions.countStart
);
var normNameBefore = thisOptions.normNameBefore;
var normNameAfter = thisOptions.normNameAfter;
var i;
var L = aFileList.length;
for ( i = 0; i < L; i++ ) {
var elem = aFileList[i];
var aBase = elem.fileNameBase;
var aExtension = elem.fileNameExtension;
var count = addLeadingZeroes( i, L );
var bBase = normNameBefore + count + normNameAfter;
var bExtension = aExtension;
$mappingEngine.printBasicFilePair(
$b.print,
aBase, aExtension,
bBase, bExtension
);
}
$b.printErr( 'Script ' + basicOptions.scriptName + ' - finished!' );
};
main();
Listing for program map-filenames.js :
// - - - - -
// #magicVars #config
// Purpose of basicOptions: organize set of most basic settings
// into a compact object package
var basicOptions = {
// Fist things first -
// "scriptName" will be important for error messages.
// Because when you debug a pipeline of scripts, it is always
// crucial to know - which program in pipeline of 10 utilities
// throws that cryptic stderr message "error: not enough arguments".
// I mean huh? Was that calc-tool.js? Or sort-tool.js? Go figure...
scriptName: WScript.ScriptName.toString(),
// What kind of End Of Line sequence
// (they call it New Line sometimes too)
// you prefer when using outputToolbox?
eolStdOut: '\r\n',
eolStdErr: '\r\n',
// Those are all possible errorCodes that this script
// was designed to fail with.
// You can define other error codes.
// Those SHOULD be integer (not strings).
// Code noErrors = 0 is indication that script finished without errors.
errorCodes: {
noErrors: 0,
badArguments: 1,
badCopy: 2,
badParsing: 3,
badGettingFileList: 4
}
};
// - - - - -
// - - - - -
// outputToolbox depends on
// basicOptions && WScript
// Purpose of outputToolbox: organize in one group
// functions that are used to
// output chars or messages to stdout or stderr
var outputToolbox = {
// Syntactic sugar for printing exact set of chars to stdout.
print: function( data ) {
// For this script to output UTF characters correctly, program must
// run under /U switch - like
// cscript /U //NoLogo program-name-here.js arg1 arg2
WScript.StdOut.Write( data );
},
// Syntactic sugar for printing one line to stdout.
// terminated with your preferred line-terminator.
printLine: function( data ) {
outputToolbox.print( data );
outputToolbox.print( basicOptions.eolStdOut );
},
// Syntactic sugar for printing exact set of chars to stderr.
printErr: function( data ) {
WScript.StdErr.Write( data );
},
// Syntactic sugar for printing one line to stderr
// terminated with your preferred line-terminator.
printErrLine: function( data ) {
outputToolbox.printErr( data );
outputToolbox.printErr( basicOptions.eolStdErr );
},
// Syntactic sugar for printing one line to stderr
// prepended with meaningful script name (that is useful for debug)
// terminated with your preferred line-terminator.
printErrMessage: function( data ) {
outputToolbox.printErr( basicOptions.scriptName + ' failed' );
outputToolbox.printErr( data );
outputToolbox.printErr( basicOptions.eolStdErr );
},
// Syntactic sugar for printing one line to stderr
// prepended with meaningful script name (that is useful for debug)
// terminated with your preferred line-terminator.
printErrWarning: function( data ) {
outputToolbox.printErr( 'Warning for ' + basicOptions.scriptName + ': ' );
outputToolbox.printErr( data );
outputToolbox.printErr( basicOptions.eolStdErr );
},
// Syntactic sugar for printing Error objects
// catched by throw...catch construction
printErrCatchedErr: function( e ) {
outputToolbox.printErrMessage(
' - catched error details - ' + e.name + ': ' + e.message
);
}
};
// - - - - -
// flowToolbox depends on
// WScript
// Purpose of flowToolbox: organize in one group
// functions that are used to
// control general flow of program
var flowToolbox = {
// Shortcut to kill this script.
// When invoked it stops execution.
die: function ( code ) {
if ( typeof code === 'undefined' ) {
code = 0;
}
WScript.Quit(code);
}
};
// - - - - -
// Here is a cleaner alternative: we pollute only name $b.
// Not so easy to type but later, you can easily find all code calls
// dependant on functions from 'basis'.
// '$b' stands for 'library-b' or more exactly - "library named 'basis'"
var $b = {};
$b.print = outputToolbox.print;
$b.printLine = outputToolbox.printLine;
$b.printErr = outputToolbox.printErr;
$b.printErrLine = outputToolbox.printErrLine;
$b.printErrMessage = outputToolbox.printErrMessage;
$b.printErrWarning = outputToolbox.printErrWarning;
$b.die = flowToolbox.die;
// ^ You can use those as functions now
// - - - - -
// $fileListToolbox
// depends on WScript && ActiveXObject( "Scripting.FileSystemObject" ) && $b
var $fileListToolbox = {
/*
* Input:
* any gibberish that is acceptable
* for your local version of
* Scripting.FileSystemObject
* - like
* getFileListForFolder( 'C:\' );
* getFileListForFolder( 'C:\abc' );
* getFileListForFolder( './' );
* getFileListForFolder( './abc/../abc/..' );
*
* Output:
* aFileList with format:
* empty array
* or
* array of oFileData
* oFileData has format:
* {
* fileNameBase: ...[string],
* fileNameExtension: ...[string],
* parentAbsolutePath: ...[string]
* }
*/
getFileListForFolder: function( folderSpec )
{
var aResult = [];
var fso = new ActiveXObject( "Scripting.FileSystemObject" );
if ( !fso.FolderExists( folderSpec ) ) {
$b.printErrMessage(' folder="' + folderSpec + '" doesn\'t exist');
$b.die( basicOptions.errorCodes.badGettingFileList );
}
var folder = fso.GetFolder( folderSpec );
var files = new Enumerator( folder.files );
for ( ; !files.atEnd(); files.moveNext() ) {
var thisFileItem = files.item();
aResult.push({
fileNameBase: fso.GetBaseName( thisFileItem ),
fileNameExtension: fso.GetExtensionName( thisFileItem ),
parentAbsolutePath: (
fso.GetParentFolderName(
fso.GetAbsolutePathName( thisFileItem )
)
)
});
}
return( aResult );
},
/*
* Purpose:
* Sort files by fileNameBase
*
* Input:
* aFileList
* - format is the same
* as for function $fileListToolbox.getFileListForFolder
*
* Output:
* - format is the same
* as for function $fileListToolbox.getFileListForFolder
*/
sortFileListByFileNameBaseAsc: function( aFileList ) {
var fSort = function( a, b ) {
if ( a.fileNameBase > b.fileNameBase ) {
return 1;
}
if ( a.fileNameBase < b.fileNameBase ) {
return -1;
}
return 0;
}
return aFileList.sort( fSort );
},
/*
Output:
false
when no results
oFileData
when result found
*/
getAnyFileWithBaseName: function( baseName, aFileList ) {
var i;
var L = aFileList.length;
for ( i = 0; i < L; i++ ) {
var a = aFileList[i];
if ( a.fileNameBase === baseName ) {
return a;
}
}
return false;
},
/*
* Purpose:
* Tool for displaying contents of fileList
*
* Input:
* aFileList
* - format is the same
* as for function $fileListToolbox.getFileListForFolder
*
* Sideeffects:
* Prints aFileList to the stdout stream
*/
printFileList: function( aFileList, callbackPrintLine ) {
if ( typeof callbackPrintLine === 'undefined' ) {
return;
}
var i;
var L = aFileList.length;
var elem;
for ( i = 0; i < L; i++ ) {
elem = aFileList[i];
callbackPrintLine();
callbackPrintLine( 'i: ' + i );
callbackPrintLine( 'fileNameBase: ' + elem.fileNameBase );
callbackPrintLine( 'fileNameExtension: ' + elem.fileNameExtension );
callbackPrintLine( 'parentAbsolutePath: ' + elem.parentAbsolutePath );
}
}
};
/*
// basic test:
$fileListToolbox.printFileList(
$fileListToolbox.sortFileListByFileNameBaseAsc(
$fileListToolbox.getFileListForFolder( 'bTmp' )
),
$b.printLine
);
*/
/*
// test for fuzzy search only by file base name:
$fileListToolbox.printFileList(
$fileListToolbox.sortFileListByFileNameBaseAsc(
$fileListToolbox.getFileListForFolder( 'bTmp' )
),
$b.printLine
);
var fuzzy = $fileListToolbox.getAnyFileWithBaseName(
'input_1',
$fileListToolbox.getFileListForFolder( 'bTmp' )
);
$b.printLine( 'fuzzy.fileNameBase: ' + fuzzy.fileNameBase );
$b.printLine( 'fuzzy.fileNameExtension: ' + fuzzy.fileNameExtension );
*/
// $streamToolbox
var $streamToolbox = {
// when end of line returns '' (aka empty string)
getChar: function() {
if ( WScript.StdIn.AtEndOfStream ) {
return '';
}
return WScript.StdIn.Read(1);
},
// tests show that for Windows 7 it understands terminators
// CRLF or LF-only
// when end of line returns '' (aka empty string)
getLine: function() {
if ( WScript.StdIn.AtEndOfStream ) {
return '';
}
return WScript.StdIn.ReadLine();
}
}
var $s = $streamToolbox;
// it could be used like that:
/*
var piece;
while ( ( piece = $s.getLine() ) !== '' ) {
$b.printLine( 'piece: ' + '>' + piece + '<' );
}
*/
// $thisArguments
var $thisArguments = {
getArgumentsObj: function() {
return WScript.Arguments;
// mockup for tests in browser
/*
var testArr = [1,2,3,4,5];
var mockupArguments = function( i ) {
return testArr[i];
};
mockupArguments.length = testArr.length;
return mockupArguments;
*/
},
printErrorMessageAndDie: function( meaningfulPart ) {
$b.printErrMessage(
' - problem when ' +
'parsing command-line arguments (options): ' +
''
);
$b.die( basicOptions.errorCodes.badArguments );
},
getArgumentsDummy: function() {
return {
direction: 'from-id-2-to-id-1',
resultExtension: 'auto',
folderFrom: 'C:\abc',
folderTo: 'D:\abc',
mode: 'training',
modeForExtensionFrom: 'strict'
};
},
print: function( argumentsObject ) {
$b.printErrLine( 'folderFrom: ' + argumentsObject.folderFrom );
$b.printErrLine( 'folderTo: ' + argumentsObject.folderTo );
$b.printErrLine( 'direction: ' + argumentsObject.direction );
$b.printErrLine( 'resultExtension: ' + argumentsObject.resultExtension );
$b.printErrLine( 'mode: ' + argumentsObject.mode );
$b.printErrLine( 'modeForExtensionFrom: ' + argumentsObject.modeForExtensionFrom );
},
isThereAFlagInArguments: function( inString ) {
var normalizedEthalon = inString.toString().toLowerCase();
var objArgs = $thisArguments.getArgumentsObj();
var i;
var L = objArgs.length;
for ( i = 2; i < L; i++ ) {
var normalizedArgument = objArgs( i ).toString().toLowerCase();
if ( normalizedEthalon === normalizedArgument ) {
return true;
}
}
return false;
},
getArguments: {
folderFrom: function() {
var rR = '';
var objArgs = $thisArguments.getArgumentsObj();
if ( objArgs.length < 2 ) {
$b.printErrMessage(
' - reason: not enough arguments, ' +
'you MUST to provide at least 2 arguments, ' +
'but ammount of arguments you provided ' +
'is only: ' + objArgs.length
);
$b.die( basicOptions.errorCodes.badArguments );
}
rR = objArgs(0);
var fso = new ActiveXObject("Scripting.FileSystemObject");
rR = fso.GetAbsolutePathName( rR );
return rR;
},
folderTo: function() {
var rR = '';
var objArgs = $thisArguments.getArgumentsObj();
if ( objArgs.length < 2 ) {
$b.printErrMessage(
' - reason: not enough arguments, ' +
'you MUST to provide at least 2 arguments, ' +
'but ammount of arguments you provided ' +
'is only: ' + objArgs.length
);
$b.die( basicOptions.errorCodes.badArguments );
}
rR = objArgs(1);
var fso = new ActiveXObject("Scripting.FileSystemObject");
rR = fso.GetAbsolutePathName( rR );
return rR;
},
direction: function() {
var rR = 'from-id-1-to-id-2';
var hasFlag = $thisArguments.isThereAFlagInArguments;
if ( hasFlag( '/MapFrom2To1' ) ) {
rR = 'from-id-2-to-id-1';
}
return rR;
},
resultExtension: function() {
var rR = 'auto';
var hasFlag = $thisArguments.isThereAFlagInArguments;
if ( hasFlag( '/ResultExtension:none' ) ) {
rR = 'none';
}
if ( hasFlag( '/ResultExtension:21' ) ) {
rR = '21';
}
if ( hasFlag( '/ResultExtension:12' ) ) {
rR = '12';
}
if ( hasFlag( '/ResultExtension:2' ) ) {
rR = '2';
}
if ( hasFlag( '/ResultExtension:1' ) ) {
rR = '1';
}
return rR;
},
mode: function() {
var rR = 'training';
var hasFlag = $thisArguments.isThereAFlagInArguments;
if ( hasFlag( '/NotTraining' ) ) {
rR = 'not-training';
}
return rR;
},
modeForExtensionFrom: function() {
var rR = 'strict';
var hasFlag = $thisArguments.isThereAFlagInArguments;
if ( hasFlag( '/FuzzyExtensionsFrom' ) ) {
rR = 'fuzzy';
}
return rR;
}
},
getArgumentsAll: function() {
var $get = $thisArguments.getArguments;
var rR = {
folderFrom: $get.folderFrom(),
folderTo: $get.folderTo(),
direction: $get.direction(),
resultExtension: $get.resultExtension(),
mode: $get.mode(),
modeForExtensionFrom: $get.modeForExtensionFrom()
};
return rR;
}
};
var $a = $thisArguments;
//you can use it like this:
/*
var $inputOptions = $a.getArgumentsAll()
$a.print( $inputOptions );
*/
// $parser
// mockup options for separate testing
/*
var basicOptions = {
errorCodes: {
badParsing: 3
}
};
var $b = {
printErrMessage: function( a ) { console.log(a); },
die: function() { throw new Error(); }
};
*/
var $parser = {};
$parser.generateDummyLineReader = function( textBlock ) {
var lines = textBlock.split( '\r\n' );
var i = -1;
var L = lines.length;
var f = function() {
i++;
if ( i >= L ) {
return '';
}
return lines[i];
}
return f;
}
$parser.generateDummyInputOptions = function() {
return {
direction: '1-to-2',
resultExtension: '12',
folderFrom: 'C:\abc',
folderTo: 'D:\abc'
}
}
$parser.generateDummyMappingLineReader = function() {
return $parser.generateDummyLineReader(
[
'id:1',
'baseName:abcdef',
'extensionName:ext',
'id:2',
'baseName:input_001',
'extensionName:txt',
':',
'id:1',
'baseName:ghijkl',
'extensionName:jpg',
'id:2',
'baseName:input_002',
'extensionName:png',
':'
].join('\r\n')
);
}
/*
Remark:
functionReadNextLine
must be iterator that returns '' (aka empty string)
when stream of lines ends
functionForEachBlockDo must have
those arguments:
- id1Base
- id1Ext
- id2Base
- id2Ext
- $inputOptions
- functionCopyFile
$inputOptions must have properties
(wherever it mentioned in this block of comments):
- direction
- resultExtension
- folderFrom
- folderTo
functionCopyFile must have these arguments
- folderFrom
- fileFrom
- folderTo
- fileTo
*/
$parser.parseLinesAndForEachBlockDo = function(
functionReadNextLine,
functionForEachBlockDo,
$inputOptions,
functionCopyFile
) {
var buffer = null;
var nOfLine = 0;
var states = [
'waitingForId1',
'waitingForId2',
'waitingForBase',
'waitingForExtension',
'waitingForEndOfGroup'
];
function printErrorMessageAndDie( meaningfulPart ) {
$b.printErrMessage(
' - problem when parsing line ' + nOfLine + ': ' +
'[' + typeof line + ']' +
'"' + line + '"' +
meaningfulPart +
''
);
$b.die( basicOptions.errorCodes.badParsing );
}
var state = 'waitingForId1';
var line;
while (
( line = functionReadNextLine() ) !== ''
) {
++nOfLine;
var arOrNull = line.match( /^([a-zA-Z0-9-]*):(.*)$/ );
if (
( arOrNull === null )
) {
printErrorMessageAndDie(
'every line in mapping must be either' +
'"key:value" or ":"'
);
}
var key = arOrNull[1];
var value = arOrNull[2];
if (
( value.match( '\r' ) !== null )
) {
printErrorMessageAndDie(
'if line is ' +
'"key:value" ' +
'then it MUST NOT contain \r (CR) symbols ' +
'exept in terminator'
);
}
if ( state === 'waitingForId1' ) {
if (
( key === 'id' )
&&
( value === '1' )
) {
buffer = {};
buffer.nowGroup = {
id: 1
};
state = 'waitingForBase';
continue;
} else {
printErrorMessageAndDie(
'but this line must be "id:1"'
);
}
}
if ( state === 'waitingForBase' ) {
if (
( key === 'baseName' )
) {
buffer.nowGroup.base = value;
state = 'waitingForExtension';
continue;
} else {
printErrorMessageAndDie(
'but this line must be "baseName:...anything-here..."'
);
}
}
if ( state === 'waitingForExtension' ) {
if (
( key === 'extensionName' )
) {
buffer.nowGroup.ext = value;
if ( buffer.nowGroup.id === 1 ) {
state = 'waitingForId2';
} else {
state = 'waitingForEndOfGroup';
}
continue;
} else {
printErrorMessageAndDie(
'but this line must be "extensionName:...anything-here..."'
);
}
}
if ( state === 'waitingForId2' ) {
if (
( key === 'id' )
&&
( value === '2' )
) {
buffer.group1 = {
base: buffer.nowGroup.base,
ext: buffer.nowGroup.ext
}
buffer.nowGroup = {
id: 2
};
state = 'waitingForBase';
continue;
} else {
printErrorMessageAndDie(
'but this line must be "id:2"'
);
}
}
if ( state === 'waitingForEndOfGroup' ) {
if (
( key === '' )
&&
( value === '' )
) {
buffer.group2 = {
base: buffer.nowGroup.base,
ext: buffer.nowGroup.ext
}
functionForEachBlockDo(
buffer.group1.base,
buffer.group1.ext,
buffer.group2.base,
buffer.group2.ext,
$inputOptions,
functionCopyFile
);
buffer = null;
state = 'waitingForId1';
continue;
} else {
printErrorMessageAndDie(
'but this line must be ":"'
);
}
}
}
if ( buffer !== null ) {
printErrorMessageAndDie(
'dangling state (not all properties group are defined) - ' + state
);
}
}
/*
// test
// can be tested in for browser with only $parser object
$parser.parseLinesAndForEachBlockDo(
$parser.generateDummyMappingLineReader(),
function( a, b, c, d ) {
console.log( 'a:', a, 'b:', b, 'c:', c, 'd:', d );
}
);
*/
/*
Remark:
$inputOptions must have properties:
- direction
- resultExtension
- folderFrom
- folderTo
*/
$parser.reactionOnGoodParsedBlock = function(
id1Base, id1Ext,
id2Base, id2Ext,
$inputOptions,
functionCopyFile
) {
function glueExtensionToFileName(
fileName, extension
) {
fileName = fileName.toString();
extension = extension.toString();
if ( extension.length > 0 ) {
extension = '.' + extension;
}
return fileName + extension;
}
var folderFrom = $inputOptions.folderFrom;
var folderTo = $inputOptions.folderTo;
if ( $inputOptions.modeForExtensionFrom === 'fuzzy' ) {
var tmpFromBase = id1Base;
if ( $inputOptions.direction == 'from-id-2-to-id-1' ) {
tmpFromBase = id2Base;
}
var fuzzyFile = $fileListToolbox.getAnyFileWithBaseName(
tmpFromBase,
$fileListToolbox.getFileListForFolder( folderFrom )
);
if ( fuzzyFile !== false ) {
if ( $inputOptions.direction == 'from-id-2-to-id-1' ) {
id2Ext = fuzzyFile.fileNameExtension;
} else {
id1Ext = fuzzyFile.fileNameExtension;
}
}
}
var fromSet = { base: id1Base, ext: id1Ext };
var toSet = { base: id2Base, ext: id2Ext };
if ( $inputOptions.direction == 'from-id-2-to-id-1' ) {
fromSet = { base: id2Base, ext: id2Ext };
toSet = { base: id1Base, ext: id1Ext };
}
if ( $inputOptions.resultExtension === '21' ) {
toSet.ext = glueExtensionToFileName( id2Ext, id1Ext );
}
if ( $inputOptions.resultExtension === '12' ) {
toSet.ext = glueExtensionToFileName( id1Ext, id2Ext );
}
if ( $inputOptions.resultExtension === '2' ) {
toSet.ext = id2Ext;
}
if ( $inputOptions.resultExtension === '1' ) {
toSet.ext = id1Ext;
}
if ( $inputOptions.resultExtension === 'none' ) {
toSet.ext = '';
}
var fileFrom = glueExtensionToFileName( fromSet.base, fromSet.ext );
var fileTo = glueExtensionToFileName( toSet.base, toSet.ext );
functionCopyFile(
folderFrom, fileFrom,
folderTo, fileTo
);
}
/*
// test
// can be tested in for browser with only $parser object
$parser.reactionOnGoodParsedBlock(
'originalA', 'extA',
'originalB', 'extB',
{
direction: 'from-id-2-to-id-1',
resultExtension: 'auto',
folderFrom: 'C:\abc',
folderTo: 'D:\abc'
},
function(
folderFrom, fileFrom,
folderTo, fileTo
) {
console.log(
'folderFrom:', folderFrom,
'fileFrom:', fileFrom,
'folderTo:', folderTo,
'fileTo:', fileTo
);
}
);
// expected result:
// folderFrom: C:abc fileFrom: originalA.extA folderTo: D:abc fileTo: originalB.extB
*/
var $copyFileToolbox = {
copyFileTraining: function(
folderFrom, fileFrom,
folderTo, fileTo
) {
var fso = new ActiveXObject( "Scripting.FileSystemObject" );
if ( !fso.FolderExists( folderFrom ) ) {
$b.printErrWarning('folderFrom="' + folderFrom + '" doesn\'t exist');
}
if ( !fso.FolderExists( folderTo ) ) {
$b.printErrWarning('folderTo="' + folderTo + '" doesn\'t exist');
}
var pathFrom = fso.BuildPath( folderFrom, fileFrom );
var pathTo = fso.BuildPath( folderTo, fileTo );
if ( !fso.FileExists( pathFrom ) ) {
$b.printErrLine();
$b.printErrWarning('no source file found, script looking for it at pathFrom="' + pathFrom + '" - this file doesn\'t exist');
}
if ( fso.FileExists( pathTo ) ) {
$b.printErrLine();
$b.printErrWarning('be advised - there was found a file at destination for copy command, and in "NotTraining" mode you will overwrite file at pathTo="' + pathTo + '"');
}
$b.printLine( '' );
$b.printLine( 'Training mode: you ask to copy file' );
$b.printLine( 'from: ' + pathFrom );
$b.printLine( '\\/' );
$b.printLine( 'to: ' + pathTo );
},
copyFile: function(
folderFrom, fileFrom,
folderTo, fileTo
) {
var fso = new ActiveXObject( "Scripting.FileSystemObject" );
if ( !fso.FolderExists( folderFrom ) ) {
$b.printErrMessage(' folderFrom="' + folderFrom + '" doesn\'t exist');
$b.die( basicOptions.errorCodes.badCopy );
}
if ( !fso.FolderExists( folderTo ) ) {
$b.printErrMessage (' folderTo="' + folderTo + '" doesn\'t exist');
$b.die( basicOptions.errorCodes.badCopy );
}
var pathFrom = fso.BuildPath( folderFrom, fileFrom );
var pathTo = fso.BuildPath( folderTo, fileTo );
if ( !fso.FileExists( pathFrom ) ) {
$b.printErrMessage(' no source file found, script looking for it at pathFrom="' + pathFrom + '" doesn\'t exist');
$b.die( basicOptions.errorCodes.badCopy );
}
fso.copyFile( pathFrom, pathTo, true );
}
}
var $c = $copyFileToolbox;
// you can use it as:
/*
$c.copyFileTraining(
'./', '123.txt',
'b', '345.txt'
);
*/
// you will have a lot of problems testing if filename is unicode
// only way that I found for Windows 7 is to pass filename as stdin
// from some file (perhaps any streaming from file works ok here...)
// and yes, test shows that it works...
function main() {
var $inputOptions = $a.getArgumentsAll();
$b.printErrLine();
$b.printErrLine(
'Arguments for ' + basicOptions.scriptName +
' are interpreted this way:'
);
$a.print( $inputOptions );
$b.printErrLine();
var fCopyFile = $c.copyFileTraining;
if ( $inputOptions.mode === 'not-training' ) {
fCopyFile = $c.copyFile;
}
/*
var fuzzy = $fileListToolbox.getAnyFileWithBaseName(
'input_1',
$fileListToolbox.getFileListForFolder( 'bTmp' )
);
*/
$parser.parseLinesAndForEachBlockDo(
$s.getLine,
$parser.reactionOnGoodParsedBlock,
$inputOptions,
fCopyFile
);
$b.printErr( 'Script ' + basicOptions.scriptName + ' - finished!' );
};
main();