Scripts discussion (4)

Discuss and announce AkelPad plugins
  • Author
  • Message
Offline
Posts: 96
Joined: Tue Nov 10, 2015 4:56 am

Post by InFive »

проблемка в скрипте TextReplace.js

не любит он "-", ошибку выдает, хотя скрипт SearchReplace.js отрабатывает

например, нельзя [-+*/] и нельзя [-.\d] - ошибка синтаксиса регэкс
надо экранировать: можно вот так [\-+*/] и так [\-.\d]

интересно, как-то можно это выправить в скрипте TextReplace.js - он видимо расценивает тире как дипазон, например символов, но в JS если тире в начале скобочной группы, то это просто символ тире, если бы тире была в середине скобочной группы, то можно было ругаться на неверный синтаксис

мне не нравится SearchReplace.js потому и озабочен скриптом TextReplace.js - дело не в том, что SearchReplace.js плох, но не удобно в нем - нет такой истории, как во втором, нет шаблонов, нет переноса строк...

Offline
Posts: 1873
Joined: Mon Aug 06, 2007 1:07 pm
Contact:

Post by Infocatcher »

InFive wrote:например, нельзя [-+*/] и нельзя [-.\d] - ошибка синтаксиса регэкс
надо экранировать: можно вот так [\-+*/] и так [\-.\d]
Так ведь
TextReplace.js - GUI for TextReplace_function.js
It works similarly to "replace" method in JScript, but uses syntax of AkelPad regular expressions.
Со всеми вытекающими отличиями в синтаксисе.
Так что править нужно реализацию регулярных выражений в самом AkelPad.

Offline
Posts: 348
Joined: Mon Jun 03, 2019 2:33 am

Post by AZJIO »

InFive wrote:например, нельзя [-+*/] и нельзя [-.\d] - ошибка синтаксиса регэкс
В движке PCRE тоже так нельзя. Без экранирования можно только в конце, например так [+*/-] и [.\d-]
Всегда необходимо изучать движок используемого рег.выр.

Offline
Posts: 1873
Joined: Mon Aug 06, 2007 1:07 pm
Contact:

Post by Infocatcher »

tileTabs.js
[x] (Hopefully) fixed child windows resizing in case of scrollbar (dis)appearance inside MDI frame.

Offline
Posts: 17
Joined: Wed Feb 16, 2022 2:25 pm

Post by AlexeyB »

Infocatcher, в скрипте runScript.js есть ошибки в работе горячих клавиш.

1.

Code: Select all

//   F4, Ctrl+E                   - Edit
//   F2, Ctrl+S                   - Rewrite options (and remove arguments for removed files)
//   F1, Shift+F1                 - Next/previous script
Но редактирование скрипта запускается при нажатии просто E без Ctrl, даже если это E вводится в поле для аргументов. А при нажатии F1, так же, как и при Shift+F1, выделяет предыдущий сценарий.

Code: Select all

case 256: //WM_KEYDOWN
	var ctrl = oSys.Call("user32::GetAsyncKeyState", 162 /*VK_LCONTROL*/)
		|| oSys.Call("user32::GetAsyncKeyState", 163 /*VK_RCONTROL*/);
	var shift = oSys.Call("user32::GetAsyncKeyState", 160 /*VK_LSHIFT*/)
		|| oSys.Call("user32::GetAsyncKeyState", 161 /*VK_RSHIFT*/);
ctrl и shift здесь всегда или почти всегда не равны 0. В описании GetAsyncKeyState говорится, что эта функция возвращает 2-байтное число. При вызове из C так и есть, но oSyS.Call возвращает 4-байтные числа с каким-то мусором (например: 0x04820000, 0x0A618000...), которые маловероятно примут значение 0. Нужен только старший бит 2-байтного числа, т.е. 0x8000.

Проверять VK_LCONTROL || VK_RCONTROL и VK_LSHIFT || VK_RSHIFT излишне, т.к. VK_CONTROL и VK_SHIFT работают ничуть не хуже (таблица).

Code: Select all

var ctrl = oSys.Call("user32::GetAsyncKeyState", 17 /*VK_CONTROL*/) & 0x8000;
var shift = oSys.Call("user32::GetAsyncKeyState", 16 /*VK_SHIFT*/) & 0x8000;
//var alt = oSys.Call("user32::GetAsyncKeyState", 18 /*VK_MENU*/) & 0x8000;
2.
Нажимаю Ctrl+E, но для редактирования открывается не текущий скрипт, а "EvalCmd.js".

По умолчанию при нажатии клавиши, печатающей символ, ListBox запускает пошаговый поиск по элементам. Нажатие клавиши Ctrl его не отменяет: сначала выбирается элемент, начинающийся на введенную букву, а потом уже обрабатывается WM_KEYDOWN диалога. Запретить обработку по умолчанию можно, создав субкласс для обработки сообщений ListBox отдельно (нужно только WM_CHAR).
To trap keys that generate a char message and do special processing, the application must subclass the list box, trap both the WM_KEYDOWN and WM_CHAR messages, and process the messages appropriately in the subclass procedure.
(Источник)

В AkelPad можно написать так:

Code: Select all

var hListBoxSubClass;
...
hListBoxSubClass = AkelPad.WindowSubClass(hWndListBox, listBoxCallback, 258 /*WM_CHAR*/);
...
function listBoxCallback(hWnd, uMsg, wParam, lParam) {
	if (oSys.Call("user32::GetAsyncKeyState", 17 /*VK_CONTROL*/) & 0x8000)
		AkelPad.WindowNoNextProc(hListBoxSubClass);
}
Исправленный вариант скрипта:
runScript.js (0.2.8)
runScript.js (0.2.9pre2)

Примечание: Может быть, удобнее перенести переменную субкласса и callback ближе к месту создания ListBox:

Code: Select all

setWindowFont(hWndListBox, hGuiFont);
var hListBoxSubClass;
var listBoxCallback = function(hWnd, uMsg, wParam, lParam) {
	if (oSys.Call("user32::GetAsyncKeyState", 17 /*VK_CONTROL*/) & 0x8000)
		AkelPad.WindowNoNextProc(hListBoxSubClass);
}
hListBoxSubClass = AkelPad.WindowSubClass(hWndListBox, listBoxCallback, 258 /*WM_CHAR*/);

Offline
Posts: 1873
Joined: Mon Aug 06, 2007 1:07 pm
Contact:

Post by Infocatcher »

AlexeyB wrote:ctrl и shift здесь всегда или почти всегда не равны 0. В описании GetAsyncKeyState говорится, что эта функция возвращает 2-байтное число. При вызове из C так и есть, но oSyS.Call возвращает 4-байтные числа с каким-то мусором (например: 0x04820000, 0x0A618000...), которые маловероятно примут значение 0. Нужен только старший бит 2-байтного числа, т.е. 0x8000.
Интересно. У меня на Windows 7 x86 сочетания клавиш работают как и задумывалось.

Но, раз поведение не ломается, то почему бы и нет.

Обновил: https://github.com/Infocatcher/AkelPad_ ... ...9dfe231
Спасибо!

А еще интересно, чем чревато отсутствие вызова AkelPad.WindowUnsubClass().

Offline
Posts: 17
Joined: Wed Feb 16, 2022 2:25 pm

Post by AlexeyB »

Infocatcher wrote:Интересно. У меня на Windows 7 x86 сочетания клавиш работают как и задумывалось.
У меня Windows 7 x64 и соответственно AkelPad x64. Проверил в этой же ОС, но в AkelPad x86 - там возвращаемое значение двухбайтовое.

Offline
Posts: 40
Joined: Thu May 05, 2022 5:38 am

Post by dothen »

ColorThemeMenu.js v.1.04 (2022.05.18)

Обновил.
Last edited by dothen on Fri May 06, 2022 6:03 pm, edited 1 time in total.

Offline
Posts: 39
Joined: Thu Aug 20, 2020 11:19 am

Post by texter »

yozhic, спасибо за замечания. Когда будет время займусь улучшениями. Пока что времени нет :(


Не знаю если будет кому-то полезно, но заметил такую особенность:

Пропустил этот код через babeljs.io, чтобы функция генератор заработала в AkelPad

Code: Select all

function* add(x) {
    let y = yield(x*5)
    return x + y
}

let iterator = add(2)

console.log(iterator.next())
console.log(iterator.next(3))

1. Babel пресет, который использовал для IE 6 браузера: https://babeljs.io/repl/#?browsers=ie%2 ... ons=%7B%7D


2. Исправил всего одну ошибку, как мне кажется, связанную с зарезервированными словами JScript языка, которые не должны находиться в ключах литеральных объектов. Если такое слово будет найдено, то можно обернуть его в кавычки "". В моём случае это было слово "catch" - обернул его в кавычки на 929 строке и функция генератор сработала. Если это единственная проблема транспиляции Babel, то возможно если подправить исходный код в babel для Targets IE 6 браузера - теоретически может расширить возможности написания кода для JScript'a, используя некоторые современные возможности стандарта ECMAScript, что также позволит расширить возможности для написания AkelPad скриптов.

Сгенерированный код из babeljs.io начинается с 436 строки в test_generator_function.js


3. В самое начало добавил несколько ES5 полифилов и json2.js https://github.com/douglascrockford/JSO ... r/json2.js , чтобы красиво выводить объекты в попап, в виде JSON.



То что получилось запустил как скрипт AkelPad:

Code: Select all

/*
//https://babeljs.io/repl/#?browsers=ie%206&build=&builtIns=false&corejs=3.21&spec=false&loose=false&code_lz=Q&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env&prettier=true&targets=&version=7.18.8&externalPlugins=&assumptions=%7B%7D

function* add(x) {
    let y = yield(x*5)
    return x + y
}

let iterator = add(2)

console.log(iterator.next())
console.log(iterator.next(3))
*/

////////////////////////////////////////////////////////////////////////// some AkelPad code

//Arguments
var bLocal = AkelPad.GetArgValue("Local", false);

//Variables
var hMainWnd = AkelPad.GetMainWnd();
var hWndEdit = AkelPad.GetEditWnd();
var oSys = AkelPad.SystemFunction();
var dwOptions;

////////////////////////////////////////////////////////////////////////// polyfills

if (!Object.create) {
  Object.create = function (proto) {
    function F() {}
    F.prototype = proto;
    return new F;
  };
}

if (!Array.prototype.forEach) {
  Array.prototype.forEach = function (callback, thisArg) {
    for (var i = 0; i < this.length; i++) {
      callback.call(thisArg, this[i], i, this);
    }
  };
}

var console = {
  log: function () {
    for (var i = 0; i < arguments.length; i++) {
      if (typeof arguments[i] === "object")
        WScript.echo(JSON.stringify(arguments[i], null, 4));
      else
        WScript.echo(arguments[i]);
    }
  }
};

////////////////////////////////////////////////////////////////////////// json2.js

if (typeof JSON !== "object") {
  JSON = {};
}

(function () {
  "use strict";

  var rx_one = /^[\],:{}\s]*$/;
  var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
  var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
  var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
  var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
  var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;

  function f(n) {
    // Format integers to have at least two digits.
    return (n < 10) ?
      "0" + n :
      n;
  }

  function this_value() {
    return this.valueOf();
  }

  if (typeof Date.prototype.toJSON !== "function") {

    Date.prototype.toJSON = function () {

      return isFinite(this.valueOf()) ?
        (
          this.getUTCFullYear() +
          "-" +
          f(this.getUTCMonth() + 1) +
          "-" +
          f(this.getUTCDate()) +
          "T" +
          f(this.getUTCHours()) +
          ":" +
          f(this.getUTCMinutes()) +
          ":" +
          f(this.getUTCSeconds()) +
          "Z"
        ) :
        null;
    };

    Boolean.prototype.toJSON = this_value;
    Number.prototype.toJSON = this_value;
    String.prototype.toJSON = this_value;
  }

  var gap;
  var indent;
  var meta;
  var rep;

  function quote(string) {

    // If the string contains no control characters, no quote characters, and no
    // backslash characters, then we can safely slap some quotes around it.
    // Otherwise we must also replace the offending characters with safe escape
    // sequences.

    rx_escapable.lastIndex = 0;
    return rx_escapable.test(string) ?
      "\"" + string.replace(rx_escapable, function (a) {
        var c = meta[a];
        return typeof c === "string" ?
          c :
          "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
      }) + "\"" :
      "\"" + string + "\"";
  }

  function str(key, holder) {

    // Produce a string from holder[key].

    var i; // The loop counter.
    var k; // The member key.
    var v; // The member value.
    var length;
    var mind = gap;
    var partial;
    var value = holder[key];

    // If the value has a toJSON method, call it to obtain a replacement value.

    if (
      value &&
      typeof value === "object" &&
      typeof value.toJSON === "function"
    ) {
      value = value.toJSON(key);
    }

    // If we were called with a replacer function, then call the replacer to
    // obtain a replacement value.

    if (typeof rep === "function") {
      value = rep.call(holder, key, value);
    }

    // What happens next depends on the value's type.

    switch (typeof value) {
    case "string":
      return quote(value);

    case "number":

      // JSON numbers must be finite. Encode non-finite numbers as null.

      return (isFinite(value)) ?
        String(value) :
        "null";

    case "boolean":
    case "null":

      // If the value is a boolean or null, convert it to a string. Note:
      // typeof null does not produce "null". The case is included here in
      // the remote chance that this gets fixed someday.

      return String(value);

      // If the type is "object", we might be dealing with an object or an array or
      // null.

    case "object":

      // Due to a specification blunder in ECMAScript, typeof null is "object",
      // so watch out for that case.

      if (!value) {
        return "null";
      }

      // Make an array to hold the partial results of stringifying this object value.

      gap += indent;
      partial = [];

      // Is the value an array?

      if (Object.prototype.toString.apply(value) === "[object Array]") {

        // The value is an array. Stringify every element. Use null as a placeholder
        // for non-JSON values.

        length = value.length;
        for (i = 0; i < length; i += 1) {
          partial[i] = str(i, value) || "null";
        }

        // Join all of the elements together, separated with commas, and wrap them in
        // brackets.

        v = partial.length === 0 ?
          "[]" :
          gap ?
          (
            "[\n" +
            gap +
            partial.join(",\n" + gap) +
            "\n" +
            mind +
            "]"
          ) :
          "[" + partial.join(",") + "]";
        gap = mind;
        return v;
      }

      // If the replacer is an array, use it to select the members to be stringified.

      if (rep && typeof rep === "object") {
        length = rep.length;
        for (i = 0; i < length; i += 1) {
          if (typeof rep[i] === "string") {
            k = rep[i];
            v = str(k, value);
            if (v) {
              partial.push(quote(k) + (
                (gap) ?
                ": " :
                ":"
              ) + v);
            }
          }
        }
      }
      else {

        // Otherwise, iterate through all of the keys in the object.

        for (k in value) {
          if (Object.prototype.hasOwnProperty.call(value, k)) {
            v = str(k, value);
            if (v) {
              partial.push(quote(k) + (
                (gap) ?
                ": " :
                ":"
              ) + v);
            }
          }
        }
      }

      // Join all of the member texts together, separated with commas,
      // and wrap them in braces.

      v = partial.length === 0 ?
        "{}" :
        gap ?
        "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" :
        "{" + partial.join(",") + "}";
      gap = mind;
      return v;
    }
  }

  // If the JSON object does not yet have a stringify method, give it one.

  if (typeof JSON.stringify !== "function") {
    meta = { // table of character substitutions
      "\b": "\\b",
      "\t": "\\t",
      "\n": "\\n",
      "\f": "\\f",
      "\r": "\\r",
      "\"": "\\\"",
      "\\": "\\\\"
    };
    JSON.stringify = function (value, replacer, space) {

      // The stringify method takes a value and an optional replacer, and an optional
      // space parameter, and returns a JSON text. The replacer can be a function
      // that can replace values, or an array of strings that will select the keys.
      // A default replacer method can be provided. Use of the space parameter can
      // produce text that is more easily readable.

      var i;
      gap = "";
      indent = "";

      // If the space parameter is a number, make an indent string containing that
      // many spaces.

      if (typeof space === "number") {
        for (i = 0; i < space; i += 1) {
          indent += " ";
        }

        // If the space parameter is a string, it will be used as the indent string.

      }
      else if (typeof space === "string") {
        indent = space;
      }

      // If there is a replacer, it must be a function or an array.
      // Otherwise, throw an error.

      rep = replacer;
      if (replacer && typeof replacer !== "function" && (
          typeof replacer !== "object" ||
          typeof replacer.length !== "number"
        )) {
        throw new Error("JSON.stringify");
      }

      // Make a fake root object containing our value under the key of "".
      // Return the result of stringifying the value.

      return str("", {
        "": value
      });
    };
  }

  // If the JSON object does not yet have a parse method, give it one.

  if (typeof JSON.parse !== "function") {
    JSON.parse = function (text, reviver) {

      // The parse method takes a text and an optional reviver function, and returns
      // a JavaScript value if the text is a valid JSON text.

      var j;

      function walk(holder, key) {

        // The walk method is used to recursively walk the resulting structure so
        // that modifications can be made.

        var k;
        var v;
        var value = holder[key];
        if (value && typeof value === "object") {
          for (k in value) {
            if (Object.prototype.hasOwnProperty.call(value, k)) {
              v = walk(value, k);
              if (v !== undefined) {
                value[k] = v;
              }
              else {
                delete value[k];
              }
            }
          }
        }
        return reviver.call(holder, key, value);
      }

      // Parsing happens in four stages. In the first stage, we replace certain
      // Unicode characters with escape sequences. JavaScript handles many characters
      // incorrectly, either silently deleting them, or treating them as line endings.

      text = String(text);
      rx_dangerous.lastIndex = 0;
      if (rx_dangerous.test(text)) {
        text = text.replace(rx_dangerous, function (a) {
          return (
            "\\u" +
            ("0000" + a.charCodeAt(0).toString(16)).slice(-4)
          );
        });
      }

      // In the second stage, we run the text against regular expressions that look
      // for non-JSON patterns. We are especially concerned with "()" and "new"
      // because they can cause invocation, and "=" because it can cause mutation.
      // But just to be safe, we want to reject all unexpected forms.

      // We split the second stage into 4 regexp operations in order to work around
      // crippling inefficiencies in IE's and Safari's regexp engines. First we
      // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
      // replace all simple value tokens with "]" characters. Third, we delete all
      // open brackets that follow a colon or comma or that begin the text. Finally,
      // we look to see that the remaining characters are only whitespace or "]" or
      // "," or ":" or "{" or "}". If that is so, then the text is safe for eval.

      if (
        rx_one.test(
          text
          .replace(rx_two, "@")
          .replace(rx_three, "]")
          .replace(rx_four, "")
        )
      ) {

        // In the third stage we use the eval function to compile the text into a
        // JavaScript structure. The "{" operator is subject to a syntactic ambiguity
        // in JavaScript: it can begin a block or an object literal. We wrap the text
        // in parens to eliminate the ambiguity.

        j = eval("(" + text + ")");

        // In the optional fourth stage, we recursively walk the new structure, passing
        // each name/value pair to a reviver function for possible transformation.

        return (typeof reviver === "function") ?
          walk({
            "": j
          }, "") :
          j;
      }

      // If the text is not JSON parseable, then a SyntaxError is thrown.

      throw new SyntaxError("JSON.parse");
    };
  }
}());

////////////////////////////////////////////////////////////////////////// transpiled by the https://babeljs.io with TARGETS `ie 6`

"use strict";

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 _regeneratorRuntime() {
  "use strict";
  /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
  _regeneratorRuntime =
    function _regeneratorRuntime() {
      return exports;
    };
  var exports = {},
    Op = Object.prototype,
    hasOwn = Op.hasOwnProperty,
    $Symbol = "function" == typeof Symbol ? Symbol : {},
    iteratorSymbol = $Symbol.iterator || "@@iterator",
    asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
    toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";

  function define(obj, key, value) {
    return (
      Object.defineProperty(obj, key, {
        value: value,
        enumerable: !0,
        configurable: !0,
        writable: !0
      }),
      obj[key]
    );
  }
  try {
    define({}, "");
  }
  catch (err) {
    define = function define(obj, key, value) {
      return (obj[key] = value);
    };
  }

  function wrap(innerFn, outerFn, self, tryLocsList) {
    var protoGenerator =
      outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
      generator = Object.create(protoGenerator.prototype),
      context = new Context(tryLocsList || []);
    return (
      (generator._invoke = (function (innerFn, self, context) {
        var state = "suspendedStart";
        return function (method, arg) {
          if ("executing" === state)
            throw new Error("Generator is already running");
          if ("completed" === state) {
            if ("throw" === method) throw arg;
            return doneResult();
          }
          for (context.method = method, context.arg = arg;;) {
            var delegate = context.delegate;
            if (delegate) {
              var delegateResult = maybeInvokeDelegate(delegate, context);
              if (delegateResult) {
                if (delegateResult === ContinueSentinel) continue;
                return delegateResult;
              }
            }
            if ("next" === context.method)
              context.sent = context._sent = context.arg;
            else if ("throw" === context.method) {
              if ("suspendedStart" === state)
                throw ((state = "completed"), context.arg);
              context.dispatchException(context.arg);
            }
            else
              "return" === context.method &&
              context.abrupt("return", context.arg);
            state = "executing";
            var record = tryCatch(innerFn, self, context);
            if ("normal" === record.type) {
              if (
                ((state = context.done ? "completed" : "suspendedYield"),
                  record.arg === ContinueSentinel)
              )
                continue;
              return {
                value: record.arg,
                done: context.done
              };
            }
            "throw" === record.type &&
              ((state = "completed"),
                (context.method = "throw"),
                (context.arg = record.arg));
          }
        };
      })(innerFn, self, context)),
      generator
    );
  }

  function tryCatch(fn, obj, arg) {
    try {
      return {
        type: "normal",
        arg: fn.call(obj, arg)
      };
    }
    catch (err) {
      return {
        type: "throw",
        arg: err
      };
    }
  }
  exports.wrap = wrap;
  var ContinueSentinel = {};

  function Generator() {}

  function GeneratorFunction() {}

  function GeneratorFunctionPrototype() {}
  var IteratorPrototype = {};
  define(IteratorPrototype, iteratorSymbol, function () {
    return this;
  });
  var getProto = Object.getPrototypeOf,
    NativeIteratorPrototype = getProto && getProto(getProto(values([])));
  NativeIteratorPrototype &&
    NativeIteratorPrototype !== Op &&
    hasOwn.call(NativeIteratorPrototype, iteratorSymbol) &&
    (IteratorPrototype = NativeIteratorPrototype);
  var Gp =
    (GeneratorFunctionPrototype.prototype =
      Generator.prototype =
      Object.create(IteratorPrototype));

  function defineIteratorMethods(prototype) {
    ["next", "throw", "return"].forEach(function (method) {
      define(prototype, method, function (arg) {
        return this._invoke(method, arg);
      });
    });
  }

  function AsyncIterator(generator, PromiseImpl) {
    function invoke(method, arg, resolve, reject) {
      var record = tryCatch(generator[method], generator, arg);
      if ("throw" !== record.type) {
        var result = record.arg,
          value = result.value;
        return value &&
          "object" == _typeof(value) &&
          hasOwn.call(value, "__await") ?
          PromiseImpl.resolve(value.__await).then(
            function (value) {
              invoke("next", value, resolve, reject);
            },
            function (err) {
              invoke("throw", err, resolve, reject);
            }
          ) :
          PromiseImpl.resolve(value).then(
            function (unwrapped) {
              (result.value = unwrapped), resolve(result);
            },
            function (error) {
              return invoke("throw", error, resolve, reject);
            }
          );
      }
      reject(record.arg);
    }
    var previousPromise;
    this._invoke = function (method, arg) {
      function callInvokeWithMethodAndArg() {
        return new PromiseImpl(function (resolve, reject) {
          invoke(method, arg, resolve, reject);
        });
      }
      return (previousPromise = previousPromise ?
        previousPromise.then(
          callInvokeWithMethodAndArg,
          callInvokeWithMethodAndArg
        ) :
        callInvokeWithMethodAndArg());
    };
  }

  function maybeInvokeDelegate(delegate, context) {
    var method = delegate.iterator[context.method];
    if (undefined === method) {
      if (((context.delegate = null), "throw" === context.method)) {
        if (
          delegate.iterator["return"] &&
          ((context.method = "return"),
            (context.arg = undefined),
            maybeInvokeDelegate(delegate, context),
            "throw" === context.method)
        )
          return ContinueSentinel;
        (context.method = "throw"),
        (context.arg = new TypeError(
          "The iterator does not provide a 'throw' method"
        ));
      }
      return ContinueSentinel;
    }
    var record = tryCatch(method, delegate.iterator, context.arg);
    if ("throw" === record.type)
      return (
        (context.method = "throw"),
        (context.arg = record.arg),
        (context.delegate = null),
        ContinueSentinel
      );
    var info = record.arg;
    return info ?
      info.done ?
      ((context[delegate.resultName] = info.value),
        (context.next = delegate.nextLoc),
        "return" !== context.method &&
        ((context.method = "next"), (context.arg = undefined)),
        (context.delegate = null),
        ContinueSentinel) :
      info :
      ((context.method = "throw"),
        (context.arg = new TypeError("iterator result is not an object")),
        (context.delegate = null),
        ContinueSentinel);
  }

  function pushTryEntry(locs) {
    var entry = {
      tryLoc: locs[0]
    };
    1 in locs && (entry.catchLoc = locs[1]),
      2 in locs && ((entry.finallyLoc = locs[2]), (entry.afterLoc = locs[3])),
      this.tryEntries.push(entry);
  }

  function resetTryEntry(entry) {
    var record = entry.completion || {};
    (record.type = "normal"), delete record.arg, (entry.completion = record);
  }

  function Context(tryLocsList) {
    (this.tryEntries = [{
      tryLoc: "root"
    }]),
    tryLocsList.forEach(pushTryEntry, this),
      this.reset(!0);
  }

  function values(iterable) {
    if (iterable) {
      var iteratorMethod = iterable[iteratorSymbol];
      if (iteratorMethod) return iteratorMethod.call(iterable);
      if ("function" == typeof iterable.next) return iterable;
      if (!isNaN(iterable.length)) {
        var i = -1,
          next = function next() {
            for (; ++i < iterable.length;) {
              if (hasOwn.call(iterable, i))
                return (next.value = iterable[i]), (next.done = !1), next;
            }
            return (next.value = undefined), (next.done = !0), next;
          };
        return (next.next = next);
      }
    }
    return {
      next: doneResult
    };
  }

  function doneResult() {
    return {
      value: undefined,
      done: !0
    };
  }
  return (
    (GeneratorFunction.prototype = GeneratorFunctionPrototype),
    define(Gp, "constructor", GeneratorFunctionPrototype),
    define(GeneratorFunctionPrototype, "constructor", GeneratorFunction),
    (GeneratorFunction.displayName = define(
      GeneratorFunctionPrototype,
      toStringTagSymbol,
      "GeneratorFunction"
    )),
    (exports.isGeneratorFunction = function (genFun) {
      var ctor = "function" == typeof genFun && genFun.constructor;
      return (
        !!ctor &&
        (ctor === GeneratorFunction ||
          "GeneratorFunction" === (ctor.displayName || ctor.name))
      );
    }),
    (exports.mark = function (genFun) {
      return (
        Object.setPrototypeOf ?
        Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) :
        ((genFun.__proto__ = GeneratorFunctionPrototype),
          define(genFun, toStringTagSymbol, "GeneratorFunction")),
        (genFun.prototype = Object.create(Gp)),
        genFun
      );
    }),
    (exports.awrap = function (arg) {
      return {
        __await: arg
      };
    }),
    defineIteratorMethods(AsyncIterator.prototype),
    define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
      return this;
    }),
    (exports.AsyncIterator = AsyncIterator),
    (exports.async = function (
      innerFn,
      outerFn,
      self,
      tryLocsList,
      PromiseImpl
    ) {
      void 0 === PromiseImpl && (PromiseImpl = Promise);
      var iter = new AsyncIterator(
        wrap(innerFn, outerFn, self, tryLocsList),
        PromiseImpl
      );
      return exports.isGeneratorFunction(outerFn) ?
        iter :
        iter.next().then(function (result) {
          return result.done ? result.value : iter.next();
        });
    }),
    defineIteratorMethods(Gp),
    define(Gp, toStringTagSymbol, "Generator"),
    define(Gp, iteratorSymbol, function () {
      return this;
    }),
    define(Gp, "toString", function () {
      return "[object Generator]";
    }),
    (exports.keys = function (object) {
      var keys = [];
      for (var key in object) {
        keys.push(key);
      }
      return (
        keys.reverse(),
        function next() {
          for (; keys.length;) {
            var key = keys.pop();
            if (key in object)
              return (next.value = key), (next.done = !1), next;
          }
          return (next.done = !0), next;
        }
      );
    }),
    (exports.values = values),
    (Context.prototype = {
      constructor: Context,
      reset: function reset(skipTempReset) {
        if (
          ((this.prev = 0),
            (this.next = 0),
            (this.sent = this._sent = undefined),
            (this.done = !1),
            (this.delegate = null),
            (this.method = "next"),
            (this.arg = undefined),
            this.tryEntries.forEach(resetTryEntry),
            !skipTempReset)
        )
          for (var name in this) {
            "t" === name.charAt(0) &&
              hasOwn.call(this, name) &&
              !isNaN(+name.slice(1)) &&
              (this[name] = undefined);
          }
      },
      stop: function stop() {
        this.done = !0;
        var rootRecord = this.tryEntries[0].completion;
        if ("throw" === rootRecord.type) throw rootRecord.arg;
        return this.rval;
      },
      dispatchException: function dispatchException(exception) {
        if (this.done) throw exception;
        var context = this;

        function handle(loc, caught) {
          return (
            (record.type = "throw"),
            (record.arg = exception),
            (context.next = loc),
            caught && ((context.method = "next"), (context.arg = undefined)),
            !!caught
          );
        }
        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
          var entry = this.tryEntries[i],
            record = entry.completion;
          if ("root" === entry.tryLoc) return handle("end");
          if (entry.tryLoc <= this.prev) {
            var hasCatch = hasOwn.call(entry, "catchLoc"),
              hasFinally = hasOwn.call(entry, "finallyLoc");
            if (hasCatch && hasFinally) {
              if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
              if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
            }
            else if (hasCatch) {
              if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
            }
            else {
              if (!hasFinally)
                throw new Error("try statement without catch or finally");
              if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
            }
          }
        }
      },
      abrupt: function abrupt(type, arg) {
        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
          var entry = this.tryEntries[i];
          if (
            entry.tryLoc <= this.prev &&
            hasOwn.call(entry, "finallyLoc") &&
            this.prev < entry.finallyLoc
          ) {
            var finallyEntry = entry;
            break;
          }
        }
        finallyEntry &&
          ("break" === type || "continue" === type) &&
          finallyEntry.tryLoc <= arg &&
          arg <= finallyEntry.finallyLoc &&
          (finallyEntry = null);
        var record = finallyEntry ? finallyEntry.completion : {};
        return (
          (record.type = type),
          (record.arg = arg),
          finallyEntry ?
          ((this.method = "next"),
            (this.next = finallyEntry.finallyLoc),
            ContinueSentinel) :
          this.complete(record)
        );
      },
      complete: function complete(record, afterLoc) {
        if ("throw" === record.type) throw record.arg;
        return (
          "break" === record.type || "continue" === record.type ?
          (this.next = record.arg) :
          "return" === record.type ?
          ((this.rval = this.arg = record.arg),
            (this.method = "return"),
            (this.next = "end")) :
          "normal" === record.type && afterLoc && (this.next = afterLoc),
          ContinueSentinel
        );
      },
      finish: function finish(finallyLoc) {
        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
          var entry = this.tryEntries[i];
          if (entry.finallyLoc === finallyLoc)
            return (
              this.complete(entry.completion, entry.afterLoc),
              resetTryEntry(entry),
              ContinueSentinel
            );
        }
      },
      "catch": function _catch(tryLoc) {
        for (var i = this.tryEntries.length - 1; i >= 0; --i) {
          var entry = this.tryEntries[i];
          if (entry.tryLoc === tryLoc) {
            var record = entry.completion;
            if ("throw" === record.type) {
              var thrown = record.arg;
              resetTryEntry(entry);
            }
            return thrown;
          }
        }
        throw new Error("illegal catch attempt");
      },
      delegateYield: function delegateYield(iterable, resultName, nextLoc) {
        return (
          (this.delegate = {
            iterator: values(iterable),
            resultName: resultName,
            nextLoc: nextLoc
          }),
          "next" === this.method && (this.arg = undefined),
          ContinueSentinel
        );
      }
    }),
    exports
  );
}

var _marked = /*#__PURE__*/ _regeneratorRuntime().mark(add);

function add(x) {
  var y;
  return _regeneratorRuntime().wrap(function add$(_context) {
    while (1) {
      switch ((_context.prev = _context.next)) {
      case 0:
        _context.next = 2;
        return x * 5;

      case 2:
        y = _context.sent;
        return _context.abrupt("return", x + y);

      case 4:
      case "end":
        return _context.stop();
      }
    }
  }, _marked);
}

var iterator = add(2);
console.log(iterator.next());
console.log(iterator.next(3));








1. Есть ли у вас где-нибудь на форуме тема, касающаяся стандартов написания кода и вообще какие-нибудь материалы по WSH для AkelPad?
Например, непонятно какой ECMAScript стандарт у меня локально выполняется.

Скрипт у меня сработал с такой версией:
Microsoft (R) Windows Script Host Version 5.812


2. Возможно ли запускать в JScript background процесс, некие воркеры, чтобы не блокировать выполнение скрипта и было меньше крашов? Если такое есть, то можно ли пример?


3. Если нет стандартов по стилю написания кода, то буду использовать такую настройку:

Code: Select all

Call("Scripts::Main", 1, "jsBeautifier.js", "-restoreCaretPos=true -indentSize=2 -keepArrayIndentation=true -braceStyle='end-expand' -breakChainedMethods=false -jsLintHappy=true -spaceBeforeConditional=true -newlineBetweenRules=true -unformattedTags=['a','h1','h2','h3','h4','h5'] ")
Она без использования Allman style, потому что в дальнейшем может быть очень много кода и может быть некомпактно...


P.s.: Мира всем и долгой жизни!
Last edited by texter on Wed Jul 13, 2022 4:11 pm, edited 8 times in total.

Offline
Posts: 39
Joined: Thu Aug 20, 2020 11:19 am

Post by texter »

yozhic wrote:Эх, похоже, я немного поторопился радоваться новому SearchReplace_extended.js: подсветка совпадений в консоли после нескольких запусков перестала работать по непонятной причине, а в интерфейсе окошка стали периодически исчезать radio-переключатели...
Image
Да вы не расстраивайтесь, и даже наоборот изучайте AkelPad, если нравится идея - форкайте, исправляйте ошибки :) потому что я старался писать код быстро, так как времени было мало) мне хотелось убить 2 с чем-то месяца на AkelPad, чтобы в нём разобраться, при том что я вообще пишу на php :D

Помню, когда читал код кажется FindReplaceEx.js - почти ничего не мог понять и мне вообще очень далеко до уровня например KDJ и других разработчиков, так как не шарю в WSH интерфейсах :) просто на какой-то момент захотелось поэкспериментировать и рискнул, так как понравился редактор и идеи скриптов :roll:



В общем уже запутался, где что добавлял, так как делал давно. Помню что делал что-то в SearchReplace_extended.js и FindReplaceFiles_extended.js :?

Существует множество бесплатных сервисов, куда можно присобачить таск менеджмент типа Kanban c todo листами и статусами разработки + какой-нибудь discord чат или прикрутить своё решение используя бесплатные сервисы AWS. Без понятия как сейчас обстоят дела в странах СНГ. Привет из Молдовы.



Мне очень не хватало Log вывода с найденными результатами строк поиска в указанной директории, как хотя бы в Notepad++ и нигде не видел реализации на форуме, и просто решил запилить, лишь бы работало. Там конечно есть что улучшать, потому что по логике приложения собирается очень большой массив, особенно если поиск очень глубокий, то приложение не выдерживает и крашится. Там нужен хороший рефакторинг и кое что переделать под функции генераторы/итераторы, чтобы память освобождалась, а не переполнялась в процессе поиска. Возможно ещё алгоритм поиска нужно разработать. Там всё тупо через обычные массивы и простые итерации сделано + помню что были методы, которые возвращают копию того большого массива и нужно переделать в более императивный стиль, то есть работать с исходным массивом в памяти. У меня поиск нормально по одному проекту работал и я забросил с усовершенствованием скрипта. Времени уже не было :)


Что касается улучшений вывода результатов поиска - нужно ещё нормально вычислить ширину открытого Log'а, чтобы при помощи этой ширины можно было адаптивно слайдить результаты видимой области очень длинных строк по горизонтали, иначе если выводить полностью строки, то краш неизбежен и не заставит себя долго ждать. Особенно, если в указанной директории поиска например лежит какой-нибудь app.js с минифицированным кодом на несколько мегабайт, то это всё будет рендериться прямо в Log.

Иначе говоря, очень длинные строки должны быть разбиты на "слайды", которые состоят из видимой области ширины открытого Log'а. Эту фитчу можно было бы выделить в компонент, но то что код неразделён на модули и не по SOLID принципам это 100%. Думаю что, если разделять прямо всё на модули, то нужно делать это с расчётом на то, что SOLID может ударить по производительности алгоритмов :?


Повторюсь, что добавил туда фильтры по .gitignore (VCS paths, VCS files, VCS - Version Control System - Система контроля версий), чтобы фильтровать ненужное и не теряться в результатах поиска, чтобы было как в IDE - поиск по проекту. Большенство современных разработчиков используют Git. SVN не знаю, но где-то замечал похожий стандарт на .gitignore . VCS nested фильтр фильтрует по вложенным .gitignore , которые находятся в различных зависимостях проекта и VCS nested работает неточно, так как многое выруливается регулярными выражениями и их нужно как-то заточить.



P.s.: Разрабатывал в x86 сборке Андрея Аверина, в которой много тулбаров (там где есть ToolBar_16.dll, ToolBarExtra.dll), под звуки радио TCIMG 8)

Offline
Posts: 39
Joined: Thu Aug 20, 2020 11:19 am

Post by texter »

Поэкспериментировал с браузерными полифилами до 2017 года


Чуть изменил timer.js, чтобы через setTimeout() передавались аргументы, как в браузере
https://github.com/CoreText/AkelPad-Ext ... xtended.js


Есть полифилы для Promise + адаптировал underscore.js библиотеку (2015 год, потому что был конфликт с Promise)


underscore.js https://github.com/CoreText/AkelPad-Ext ... erscore.js
документация https://underscorejs.org/




Всё что в этой папке https://github.com/CoreText/AkelPad-Ext ... Include/ES

нужно для этого скрипта:

Code: Select all

/*



*/
if (!(
    AkelPad.Include("ES\\polyfills\\es5.min.js")

        && AkelPad.Include("ES\\underscore.min.js")

    && AkelPad.Include("ES\\json2.min.js")
    && AkelPad.Include("ES\\console.js")
    && AkelPad.Include("ES\\my_polyfills.js")
    && AkelPad.Include("ES\\symbol.min.js")
    && AkelPad.Include("ES\\polyfills\\es2016.min.js")
    && AkelPad.Include("timer_extended.js")
    && AkelPad.Include("ES\\promise.min.js")
    && AkelPad.Include("ES\\reflect.js")
    && AkelPad.Include("ES\\polyfills\\es6.min.js")
    && AkelPad.Include("ES\\polyfills\\es2017.min.js")
    //&& AkelPad.Include("ES\\object.js")
    && AkelPad.Include("ES\\iterate-iterator.js")
  )) {
  WScript.Quit();
}


var und = _.filter([1, 2, 3, 4, 5, 6], function (num) { return num % 2 == 0 });
console.log(und);



['test', 'one', 'two'].forEach(function (item) { console.log(item) });



setTimeout(function (arg1, arg2) {
  console.log(arg1, arg2)
}, 5, null, 'wat1', 'wat2');



//////////////////////////////////////////////////////////////////////////

var arr = [1, 2, 3, 4];

var aFlatMap = arr.flatMap(function (x) {
    return [x, x * 2];
});
console.log(aFlatMap);



//////////////////////////////////////////////////////////////////////////

function M() {
    this.add = 2;
}

// test Functor
M.prototype.testMap = function (arr) {
    return arr.map(function (x, index, a) {
       return [x, x * this.add];
    }, this);
};

// test Monad
M.prototype.testFlatMap = function (arr) {
    return arr.flatMap(function (x, index, a) {
       return [x, x * this.add];
    }, this);
};

var oM = new M;

console.log(oM.testMap(arr));
console.log(oM.testFlatMap(arr));



//////////////////////////////////////////////////////////////////////////

console.log('Breaded Mushrooms'.padEnd(25, '.'));



console.log(Symbol('foo'));

// [Symbol.iterator]() - NOT WORKING :(


//////////////////////////////////////////////////////////////////////////

var arr = [
   ['mark johansson', 'waffle iron', '80' , '2'],
   ['mark johansson', 'blender'    , '200', '1'],
   ['mark johansson', 'knife'      , '10' , '4'],
   ['Nikita Smith'  , 'waffle iron', '80' , '1'],
   ['Nikita Smith'  , 'knife'      , '10' , '2'],
   ['Nikita Smith'  , 'pot'        , '20' , '3']
];

var structure = arr.reduce(function (customers, line) {
  customers[line[0]] = customers[line[0]] || [];
  customers[line[0]].push({
    name: line[1],
    price: line[2],
    quantity: line[3]
  });
  return customers;
}, {})

console.log(JSON.stringify(structure, null, 4))

//////////////////////////////////////////////////////////////////////////

var inventory = [
  {name: 'apples', quantity: 2},
  {name: 'bananas', quantity: 0},
  {name: 'cherries', quantity: 5}
];

function isCherries(fruit) {
  return fruit.name === 'cherries';
}

console.log(inventory.find(isCherries));

//////////////////////////////////////////////////////////////////////////

var johnDoe = {
  firstName: "John",
  lastName: "Doe",
  sayName: function () {
    return "My name is " + this.firstName + " " + this.lastName;
  }
};

var janeDoe = Object.create(johnDoe, {
  firstName: {
    value: "Jane"
  },
  greet: {
    value: function (person) {
      return "Hello, " + person.firstName;
    }
  }
});

var jimSmith = Object.create(janeDoe, {
  firstName: {
    value: "Jim"
  },
  lastName: {
    value: "Smith"
  }
});

console.log(janeDoe.sayName() + " " + janeDoe.greet(johnDoe));
console.log(jimSmith.sayName() + " " + jimSmith.greet(janeDoe));
console.log(JSON.stringify(jimSmith, null, 4));



//////////////////////////////////////////////////////////////////////////
var createPeroson = function (firstName, lastName) {
    var person = {};

    Object.defineProperties( person, {
        firstName: {
            value: firstName,
            enumerable: true, // by default is false
            writable  : true
        },
        lastName : {
            value: lastName,
            enumerable: true,
            writable  : true
        },
        getFullName : {
            value : function () {
                return this.firstName + " " + this.lastName;
            }
        },
        setFullName : {
            value : function (value) {
                var val = value.split(" ");
                this.firstName = val[0];
                this.lastName  = val[1];
            },
            enumerable  : true,
            configurable: true
        },
        sayHi: {
            value: function () {
                return "Hello!";
            }
        }
    });

    return person;
};

var person = createPeroson("John", "Doe");
console.log(person)
console.log(person.getFullName())
console.log(person.sayHi())


/**
 * Parasitic Inheritance
 */
var createEmployee = function (firstName, lastName, position) {
    var person = createPeroson(firstName, lastName);

    person.position = position || "no position";

    // var fullName = person.fullName; /* won't redefine this property */
    // gets property descriptor and we can redefine property
    var getFullName = Object.getOwnPropertyDescriptor( person, "getFullName");

    // it will execute func as it was person's obj
    var fullNameFunction = getFullName.value.bind(person);

    // так можно перегружать функции
    var sayHiFunction = person.sayHi.bind(person);

    person.sayHiFunction = function () {
        return sayHiFunction() + ". My name is " + this.getFullName();
    };

    Object.defineProperty(person, "fullPosition", {
        value : function () {
            return fullNameFunction() + " (" + this.position + ")";
        },
        enumerable: true,
        configurable: true
    });

    return person;
};

var newEmployee = createEmployee("Snoop", "Dogg", "Web Developer");

console.log(newEmployee.fullPosition());
console.log(newEmployee.sayHiFunction());



//////////////////////////////////////////////////////////////////////////

/**
 * A - object literal
 */
var A = {
  name: 'A',
  special: 'from A',
  specialMethod: function () {
    return this.name + ' ' + this.special
  }
};

var newA = Object.create(A)
B.prototype = newA
B.constructor = A

/**
 * B - function
 */
function B() {
  this.name = 'B'
}

/**
 * C - function
 */
function C() {
  this.name = 'C'
}

var newB = new B()
console.log(newB.specialMethod())        // B from A

C.prototype = newB
C.constructor = B

var newC = new C()
console.log(newC.specialMethod())        // C from A



//////////////////////////////////////////////////////////////////////////

// Shape - superclass
function Shape() {
  this.x = 0;
  this.y = 0;
}

// superclass method
Shape.prototype.move = function (x, y) {
  this.x += x;
  this.y += y;
  console.log('Shape moved.');
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);

//If you don't set Rectangle.prototype.constructor to Rectangle,
//it will take the prototype.constructor of Shape (parent).
//To avoid that, we set the prototype.constructor to Rectangle (child).
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?', rect instanceof Shape); // true
rect.move(1, 1); // Outputs, 'Shape moved.'



//////////////////////////////////////////////////////////////////////////
function SuperClass() {
  this.name = 'SuperClass'
}

function OtherSuperClass() {
  SuperClass.call(this);
}

function MyClass() {
  SuperClass.call(this);
  OtherSuperClass.call(this);
}

// inherit one class
MyClass.prototype = Object.create(SuperClass.prototype);

// mixin another
Object.assign(Object.getPrototypeOf(MyClass.prototype), OtherSuperClass.prototype);

// re-assign constructor
MyClass.prototype.constructor = MyClass;

MyClass.prototype.myMethod = function () {
  return this.name;
};

console.log(new MyClass().name);



//////////////////////////////////////////////////////////////////////////

var duck = {
  name: 'Maurice',
  color: 'white',
  greeting: function () {
    console.log('Quaaaack! My name is ' + this.name);
  }
}

console.log(Reflect.has(duck, 'color'));
// true
console.log(Reflect.has(duck, 'haircut'));
// false

console.log(Reflect.ownKeys(duck))
console.log(Reflect.set(duck, 'eyes', 'black'))

console.log(JSON.stringify(Object.entries(duck), null, 4));



//////////////////////////////////////////////////////////////////////////

var promiseA = new Promise(function (resolutionFunc, rejectionFunc) {
  return resolutionFunc(777);
});

// At this point, "promiseA" is already settled.
promiseA.then(function (val) {
  console.log("asynchronous logging has val:" + val)
});
console.log("immediate logging");



//////////////////////////////////////////////////////////////////////////

var promise = new Promise(function (resolve, reject) {
  setTimeout(resolve, 0, null, 101);
}).then(function (value) {
  console.log(value);
  return Promise.resolve(102);
}).then(function (value) {
  console.log(value);
  return {
    then: function (resolve, reject) {
      setTimeout(resolve, 0, null, 103);
    }
  }
}).then(function (value) {
  console.log(value);
  return Promise.all(["Bar", new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 106)
  }), Promise.resolve(104)]);
}).then(function (value) {
  console.log(value);
  return Promise.race([Promise.reject("Error"), Promise.resolve(108)]);
}).then(function (value) {
  console.log(value);
  return 109;
}).error(function (error) {
  console.log(error);
});

// true
// 101
// 102
// 103
// [ 'Bar', 106, 104 ]
// Error

console.log(promise)



//////////////////////////////////////////////////////////////////////////

var pAllSettled = Promise.allSettled([
  Promise.resolve(33),
  new Promise(function (resolve) {
      return setTimeout(function () {
        return resolve(66)
      })
    }),
  99,
  Promise.reject(new Error('an error'))
])
  .then(function (values) {
    console.log(values)
  });

console.log(pAllSettled)

//////////////////////////////////////////////////////////////////////////

var promise1 = new Promise(function (resolve, reject) {
  setTimeout(resolve, 500, null, 'one');
});

var promise2 = new Promise(function (resolve, reject) {
  setTimeout(resolve, 100, null, 'two');
});

var pRace = Promise.race([promise1, promise2]).then(function (value) {
  console.log(value);
  // Both resolve, but promise2 is faster
});

console.log(pRace)
// expected output: "two"


//////////////////////////////////////////////////////////////////////////
// we are passing as argument an array of promises that are already resolved,
// to trigger Promise.race as soon as possible
var resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];

var pRace = Promise.race(resolvedPromisesArray);
// immediately logging the value of p
console.log(pRace);

// using setTimeout we can execute code after the stack is empty
setTimeout(function () {
  console.log('the stack is now empty');
  console.log(pRace);
}, 0);


//////////////////////////////////////////////////////////////////////////
var foreverPendingPromise = Promise.race([]);
var alreadyFulfilledProm = Promise.resolve(100);

var arr = [foreverPendingPromise, alreadyFulfilledProm, "non-Promise value"];
var arr2 = [foreverPendingPromise, "non-Promise value", Promise.resolve(100)];
var p = Promise.race(arr);
var p2 = Promise.race(arr2);

console.log(p);
console.log(p2);

setTimeout(function () {
  console.log('the stack is now empty');
  console.log(p);
  console.log(p2);
}, 0);


//////////////////////////////////////////////////////////////////////////
var promise1 = new Promise(function (resolve, reject) {
  setTimeout(resolve, 500, null, 'one');
});

var promise2 = new Promise(function (resolve, reject) {
  setTimeout(reject, 100, null, 'two');
});


var pRace = Promise.race([promise1, promise2]).then(function (value) {
  console.log('succeeded with value:', value);
}).error(function (reason) {
  // Only promise1 is fulfilled, but promise2 is faster
  console.log('failed with reason:', reason);
});

console.log(pRace)
// expected output: "failed with reason: two"


var pAny = Promise.any([promise1, promise2]).then(function (value) {
  // Only promise1 is fulfilled, even though promise2 settled sooner
  console.log('succeeded with value:', value);
}).error(function (reason) {
  console.log('failed with reason:', reason);
});

console.log(pAny)
// expected output: "succeeded with value: one"



////////////////////////////////////////////////////////////////////////// Iterator

function makeIterator(array) {
    var nextIndex = 0;
    return {
        next: function () {
            return (
            (nextIndex < array.length)
                ? {value: array[nextIndex++], done: false}
                : {done: true}
            );
        }
    };
}

var iterate = makeIterator;
var some = iterate(["yo", "ya", "hoo"]);

/*
console.log(some.next().value)
console.log(some.next().value)
console.log(some.next().value)
console.log(some.next().value)
console.log(some.next().done)
*/


while (true) {
  var result = some.next();
  if (result.done)
    break;

  console.log(result.value);
}


var wtf = iterate("WTF".split(''));
iterateIterator(wtf, function (item) {
    return WScript.echo(item);
})



//////////////////////////////////////////////////////////////////////////
// ES3-5 version

/*
function gen(obj) {
  var keys = [];
  var index = 0;
  for (keys[index++] in obj);
  var total = index;
  index = 0;
  return {
    next: function () {
      if (index < total) {
        var key = keys[index++];
        return {
          done: false,
          value: [key, obj[key]]
        }
      }
      return {
        done: true
      };
    }
  };
}

var www = gen(["one", "two", "three"]);
iterateIterator(www, function (item) {
  return WScript.echo(item);
})
*/


//////////////////////////////////////////////////////////////////////////

console.equals(true, 'abc'.startsWith('a'));
console.equals(false, 'abc'.endsWith('a'));
console.equals(true, 'john alice'.includes('john'));
console.equals('123'.repeat(2), '123123');
console.equals(false, NaN === NaN);
console.equals(true, Object.is(NaN, NaN));
console.equals(true, -0 === 0);
console.equals(false, Object.is(-0, 0));






Можно лучше адаптировать эти полифилы к AkelPad, особенно если знать чем наполнить переменные global, window, self - не знаю если есть похожая переменная, которая отвечает за глобальный контекст.

В AkelEmmet.js заметил такой код, который описывает global:

Code: Select all

// define `global` object variable for AkelPad Scripts engine
// install Log plugin to see possible Emmet logs
var global = {
	console: {
		log: function()
		{
			// we can not use arguments.join here
			var i;
			for(i = 0; i < arguments.length; i++)
		 		if(AkelPad.Call('Log::Output', 4, arguments[i] + '\n') < 0)
		 			break;
		}
	}
}
Пока что не знаю как используется эта переменная в скриптах, но в console.js сделал похожим образом https://github.com/CoreText/AkelPad-Ext ... console.js

Code: Select all

var global = (global) ? global : {};

// code...

// export to global variable
if (!global.console) {
    global.console = console;
}
В дальнейшем, так как эта переменная global используется в полифилах, можно будет подправить код в полифилах и возможно полифилы будут лучше интегрированны для AkelPad. На данный момент, в некоторых полифилах убрал self-invoking function expression обёртку с параметром global, чтобы полифилы сработали, из-за чего ненужные переменные из полифилов стали доступны и теоретически в дальнейшем могут конфликтовать.




Минифицировал скрипты с помощью jsMin.js, так как другие минификаторы создавали ошибки.

Из недостатков заметил что:
- get set не работают в объектах
- Symbol.iterator не работает, который очень хотелось. Возможно позже найду специфичное решение для итераторов
- Proxy не удалось адаптировать, также Set, Map, WeakSet, WeakMap. Если они где-то определены, то скорее всего служат в качестве заглушки




P.s.: то что выше писал про catch, который мол нужно обернуть в кавычки - не канает такой вариант. Когда полифилил Promise, то пришлось переименовать catch в error, чтобы сработало
Last edited by texter on Sun Jul 17, 2022 5:23 pm, edited 12 times in total.

Offline
Posts: 1873
Joined: Mon Aug 06, 2007 1:07 pm
Contact:

Post by Infocatcher »

texter wrote:Чуть изменил timer.js, чтобы через setTimeout() передавались аргументы, как в браузере
https://github.com/CoreText/AkelPad-Ext ... xtended.js
Тогда надо убрать аргумент id, чтобы он не оказался использован в качестве идентификатора таймера:

Code: Select all

function setTimeout(fn, delay/*, id*/) {
	var delay = delay || 0;
	var args = Array.prototype.slice.call(arguments, 3);
	return timers.set(fn, delay, true, undefined/*id*/, args);
}

Offline
Posts: 39
Joined: Thu Aug 20, 2020 11:19 am

Post by texter »

Infocatcher wrote:
texter wrote:Чуть изменил timer.js, чтобы через setTimeout() передавались аргументы, как в браузере
https://github.com/CoreText/AkelPad-Ext ... xtended.js
Тогда надо убрать аргумент id, чтобы он не оказался использован в качестве идентификатора таймера:

Code: Select all

function setTimeout(fn, delay/*, id*/) {
	var delay = delay || 0;
	var args = Array.prototype.slice.call(arguments, 3);
	return timers.set(fn, delay, true, undefined/*id*/, args);
}
Там было написано:

Code: Select all

// Be careful: 3rd argument is an ID of already created timer!
и я не трогал этот аргумент и просто можно добавить null таким образом

Code: Select all

var promise1 = new Promise(function (resolve, reject) {
  setTimeout(resolve, 500, null, 'one');
});

Offline
Posts: 39
Joined: Thu Aug 20, 2020 11:19 am

Post by texter »

Чтобы работал timer_extended.js нужно перед инклюдом ES5 полифил.

Code: Select all

if (!(
    AkelPad.Include("ES\\polyfills\\es5.min.js")
    && AkelPad.Include("timer_extended.js")
  )) {
  WScript.Quit();
}

// ваш код...

var timeoutID = setTimeout(function (arg1, arg2) {
  WScript.echo(arg1 + ' ' + arg2);
}, 5, null, 'wat1', 'wat2');

WScript.echo(timeoutID);



Сделал console.js, чтобы было легче дебажить.
https://github.com/CoreText/AkelPad-Ext ... console.js

Чтобы без проблем работал console.js нужны эти зависимости:

Code: Select all

if (!(
    AkelPad.Include("ES\\polyfills\\es5.min.js")
    && AkelPad.Include("ES\\json2.min.js")
    && AkelPad.Include("ES\\console.js")
  )) {
  WScript.Quit();
}

// ваш код...

console.log('wat');


Если Log плагин будет открыт, то в него будут выводиться console.log(), но если console.log() в setTimeout коллбеке, то в Log не выводит.
Если же закрыть Log, то всё будет выводиться в попапы, в том числе из setTimeout коллбека.

console.assert() - сделал для заглушки в некоторых полифилах.


Тема для console.log() вывода Json.coder , который можно найти здесь: https://github.com/CoreText/AkelPad-Ext ... Json.coder

Code: Select all

/*



*/
if (!(
    AkelPad.Include("ES\\polyfills\\es5.min.js")
    && AkelPad.Include("ES\\json2.min.js")
    && AkelPad.Include("ES\\console.js")
    && AkelPad.Include("timer_extended.js")
  )) {
  WScript.Quit();
}


setTimeout(function (arg1, arg2) {
  WScript.echo(arg1 + ' ' + arg2);
}, 5, null, 'wat1', 'wat2');


//////////////////////////////////////////////////////////////////////////
console.equals(false, NaN === NaN);
console.equals(true, -0 === 0);


//////////////////////////////////////////////////////////////////////////
var test = function () {alert(1);}
console.log(test);

var entire = test.toString(); // this part may fail!
var body = entire.substring(entire.indexOf("{") + 1, entire.lastIndexOf("}"));

console.log(body); // "alert(1);"


//////////////////////////////////////////////////////////////////////////
if (console.assert(true)) {
    console.log('ok');
}

if (console.assert(false, {reason: 'not true'})) {
    console.log('not ok');
}


//////////////////////////////////////////////////////////////////////////
/*
In algebra,

    a
    = 0+a
    = 0+0+a
    = 0+0+0+a

or

    a
    = 1*a
    = 1*1*a
    = 1*1*1*a

is called identity element.


0 in +(addition) operation,

    a + 0 = a  //right identity
    0 + a = a  //left identity


1 in *(multiplication) operation,

    a * 1 = a  //right identity
    1 * a = a  //left identity



In algebra is called associative property

    1 + 2 + 3 = 1 + 2 + 3
    (1+2) + 3 = 1 + (2+3)
        3 + 3 = 1 + 5
            6 = 6

*/

var compose = function (f, g) {
    return (function (x) { return g(f(x)) })
};

var isMonad = function (m) { return !(typeof m.val === "undefined") };

// M is a highly composable unit in functional programming.
var M = function (m) {
  var m = m || [];

  var f = function (m1) {
    //check type error
    try {
      return M(M(m1).val(m));
    } catch (e) {
      return M(compose(m, M(m1).val)); // f-f compose
    };
  };

  f.val = m;

  return (
    isMonad(m)
      ? m
      : f
  );
};

M.val = function (m) { return m };


//////////////////////////////////////////////////////////////////////////
var log = function (m) {
    return (
      (typeof m !== 'function')
        ? (function () {
            console.log(m);
            return m;
          })()
        : err()
    );
};

var err = function () {
  throw new TypeError();
};

////////////////////////////////////////////////////////////////////////// Test code

var loglog = M(log)(log);
M("test")(loglog);


M("------")(log);
M([1])(log);
M(M(M(5)))(log)
M(99)(M)(log)


M("------")(log);
//M([1, 2, 3])(([a, b, c]) => [a + 1, b + 1, c + 1])(log)
M([1, 2, 3])(function (args) {
  var a = args[0];
  var b = args[1];
  var c = args[2];
  return [a + 1, b + 1, c + 1]
})(log)


M("------")(log);
var add1 = function (a) {
  return (
    (typeof a == 'number')
      ? a + 1
      : err()
  );
};

M(10)(add1)(log);             //11
M(10)(add1)(add1)(log);       //12
M(10)(add1)(add1)(add1)(log); //13

var add2 = M(add1)(add1);
M(10)(add2)(log);             //12

var add3 = M(add2)(add1);
M(10)(add3)(log);             //13


M("------")(log);
var plus = function (x) {
  return function (y) {
    return (x + y)
  };
};

M(plus(1)(5))(log);           //6
M(5)(M(1)(plus))(log);        //6

var plus1 = M(1)(plus);
M(5)(plus1)(log);             //6


M("------")(log);
var map = function (f) {
  return function (array) {
    return array.map(f);
  };
};

var map1 = M(add1)(map);
M([1, 2, 3])(log)(map1)(log);


//////////////////////////////////////////////////////////////////////////

M("left identity   M(a)(f) = f(a)")(log);
M(7)(add1)(log)               //8

M("right identity  M = M(M)")(log);
console.log(M)                //{ [Function: M] val: [Function] }
console.log(M(M))             //{ [Function: M] val: [Function] }


M("identity")(log);
M(9)(M(function (x) { return x }))(log);         //9
M(9)(function (x) { return x })(log);            //9


M("homomorphism")(log);
M(100)(M(add1))(log);         //101
M(add1(100))(log);            //101


M("interchange")(log);
M(3)(add1)(log);                                //4
M(add1)(function (f) {return f(3) })(log);      //4


M("associativity")(log);
M(10)(add1)(add1)(log);       //12
M(10)(M(add1)(add1))(log);    //12


// left identity M(a)(f) = f(a)
M(7)(add1)                    //8
M(add1(7))                    //8

// right identity M = M(M)
console.log(M)                //{ [Function: M] val: [Function] }
console.log(M(M))             //{ [Function: M] val: [Function] }



/* Applicative

A value that implements the Applicative specification must also implement the Apply specification.
    1. v.ap(A.of(x => x)) is equivalent to v (identity)
    2. A.of(x).ap(A.of(f)) is equivalent to A.of(f(x)) (homomorphism)
    3. A.of(y).ap(u) is equivalent to u.ap(A.of(f => f(y))) (interchange)
*/

// identity
M(9)(M(function (x) { return x }))               //9


// homomorphism
M(100)(M(add1))               //101
M(add1(100))                  //101


// interchange
M(3)(add1)                                      //4
M(add1)(function (f) { return f(3) })           //4



/* Chain

A value that implements the Chain specification must also implement the Apply specification.
    1. m.chain(f).chain(g) is equivalent to m.chain(x => f(x).chain(g)) (associativity)
*/

// associativity
M(10)(add1)(add1)             //12
M(10)(M(add1)(add1))          //12




Offline
Posts: 39
Joined: Thu Aug 20, 2020 11:19 am

Post by texter »

Нашёл способ, как компилировать ES6 стандарт в ScriptHost, чтоб работало на AkelPad.


Для начала нужно установить Node js, затем TypeScript:

Code: Select all

npm install -g typescript
Код который написан на современном стандарте в script.ts:

Code: Select all

function* add(x) {
    let y = yield(x*5)
    return x + y
}

let iterator = add(2)

console.log(iterator.next())
console.log(iterator.next(3))


и затем скомпилировать script.ts используя эту команду и сгенерированный код появится в script.js:

Code: Select all

tsc --target es5 --lib DOM,ES6,ScriptHost script.ts

Code: Select all

/*

function* add(x) {
    let y = yield(x*5)
    return x + y
}

let iterator = add(2)

console.log(iterator.next())
console.log(iterator.next(3))

*/

if (!(
    AkelPad.Include("ES\\polyfills\\es5.min.js")
    && AkelPad.Include("ES\\json2.min.js")
    && AkelPad.Include("ES\\console.js")
  )) {
  WScript.Quit();
}

////////////////////////////////////////////////////////////////////////// tsc --target es5 --lib DOM,ES6,ScriptHost script.ts

var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};

function add(x) {
    var y;
    return __generator(this, function (_a) {
        switch (_a.label) {
            case 0: return [4 /*yield*/, (x * 5)];
            case 1:
                y = _a.sent();
                return [2 /*return*/, x + y];
        }
    });
}
var iterator = add(2);
console.log(iterator.next());
console.log(iterator.next(3));




Однако, если писать скрипт, в котором есть фунции AkelPad - будут такие ошибки:

Code: Select all

test_generator_function_typescript.ts:16:5 - error TS2304: Cannot find name 'AkelPad'.

16     AkelPad.Include("ES\\polyfills\\es5.min.js")
       ~~~~~~~

test_generator_function_typescript.ts:17:8 - error TS2304: Cannot find name 'AkelPad'.

17     && AkelPad.Include("ES\\json2.min.js")
          ~~~~~~~

test_generator_function_typescript.ts:18:8 - error TS2304: Cannot find name 'AkelPad'.

18     && AkelPad.Include("ES\\console.js")
          ~~~~~~~

test_generator_function_typescript.ts:19:8 - error TS2304: Cannot find name 'AkelPad'.

19     && AkelPad.Include("timer_extended.js")
          ~~~~~~~


Found 4 errors in the same file, starting at: test_generator_function_typescript.ts:16

P.s.: TypeScript транспилирует, но не полифиллит :lol:
Post Reply