Scripts discussion (3)

Discuss and announce AkelPad plugins
Locked
  • Author
  • Message
Offline
Posts: 1162
Joined: Sun Oct 20, 2013 11:44 am

Post by Skif_off »

InFive
У себя сделал простенько, с панелью вывода не стал возиться

после строки

Code: Select all

var extInfo = t.toLocaleTimeString() + " " + (AkelPad.GetEditFile(0) || "*") + " -> ";
добавил

Code: Select all

if (text.indexOf(">>") >= 0)
  output(extInfo + "\">>\" was found!", 48 /*MB_ICONEXCLAMATION*/);


А зачем вам tidy от гражданина Paehl? Он берёт те же исходники и компилит, забив на WinXP. К слову, в зависимостях msvcr120.dll, а у официалльных версий отсюда - msvcr100.dll: кб ~200 разница :)

Offline
Posts: 96
Joined: Tue Nov 10, 2015 4:56 am

Post by InFive »

Skif_off wrote: У себя сделал простенько, с панелью вывода не стал возиться

после строки

Code: Select all

var extInfo = t.toLocaleTimeString() + " " + (AkelPad.GetEditFile(0) || "*") + " -> ";
добавил

Code: Select all

if (text.indexOf(">>") >= 0)
  output(extInfo + "">>" was found!", 48 /*MB_ICONEXCLAMATION*/);
вариант, конечно, не практичный, но вариант... добавил себе, а там посмотрим... спасибо...
Skif_off wrote:А зачем вам tidy от гражданина Paehl?
мне не зачем... просто он был указан в сообщении со скриптом tidy.js, поэтому пробы с него и начинал...

Offline
Posts: 3234
Joined: Wed Nov 29, 2006 1:19 pm
Location: Киев, Русь
Contact:

Post by VladSh »

Skif_off
Идея хорошая (я тоже это буду добавлять, как раз над этим сейчас работаю), но не совсем верная. Здесь нужны регулярки. Поясню.
При таком варианте:
<тэг></тэг>><тэг></тэг>
это есть ошибка.
А вот при таком:
<тэг>></тэг>
нет.
Т.е. надо искать, чтобы после ">>" и любого последующего текста шло не "</".

Кстати, такой вариант MSXML-валидатор обрабатывает успешно:
<PRODUCTS>>
<PRODUCT>
...
Выводится сообщение об ошибке:
Согласно DTD и схеме в данном контексте текст не допускается.
Требуется: PRODUCT.
Ещё вопросы в тему:
1. Как определить номер строки, если известна позиция в файле? С перебросом туда курсора получилось, но может быть есть вариант без переброса курсора?
2. Как определить номер позиции в строке, если известены позиция в файле и номер строки?

Skif_off wrote:А зачем вам tidy от гражданина Paehl?
Изначально взял из скрипта камрада se7h. Спасибо за ссылку на оригинальные версии.

Offline
Posts: 3234
Joined: Wed Nov 29, 2006 1:19 pm
Location: Киев, Русь
Contact:

Post by VladSh »

Cuprum
По Punto.
Несмотря на то, что где-то с пол года назад добавляли функционал, который предотвращает срабатывание переключение в полях-паролях, у себя давно поставил язык ввода по умолчанию английский. С этим тоже есть некоторые неудобства, например первое слово, особенно если оно состоит из одной буквы, часто не переключается, приходится это помнить и, если не услышал звука переключения, использовать клавишу Break (Insert на ноуте).
Сейчас вышла 4.2.2, в которой заявлена переработка механизма переключения. Поглядим.

Offline
Posts: 1162
Joined: Sun Oct 20, 2013 11:44 am

Post by Skif_off »

VladSh
Если ошибка - на неё укажет валидатор. Так понимаю, схемы есть разные, вот для InFive обязательно, чтобы не было ">>", сам не сталкивался пока, но решил добавить на всякий случай предупреждение.
С регулярками не получится двойной как будто проверки: сначала скрипт проигнорирует, ведь в некоторых случаях допустимо, потом собственно валидатор проигнорирует?

Offline
Posts: 3234
Joined: Wed Nov 29, 2006 1:19 pm
Location: Киев, Русь
Contact:

Post by VladSh »

Skif_off
Я уже опустил это "предупреждение" ниже валидатора - если он не сработал, тогда выполняется наша "ручная" проверка.

От регулярок мне всего лишь нужно чтобы вместо text.indexOf(">>") выполнился более сложный поиск (например text.search(/???/)), который также возвращал бы позицию найденного элемента. Логику описывал:
надо искать, чтобы после ">>" и любого последующего текста шло не "</".
т.е. выбирать случаи:

Code: Select all

>>текст<любой_символ_кроме_слэша
исключая:

Code: Select all

>>текст</

Добавлено:
Предварительная версия (может кто ещё с регуляркой всё-таки поможет):

Code: Select all

///Validates selected XML fragment or whole document, pointing potential error place
// http://akelpad.sourceforge.net/forum/viewtopic.php?p=15256#p15256
// https://github.com/FeyFre/akelpad-customisations/blob/scripts/XMLValidator.js
// Version: ???
// Version: 2.0 (2016.02.28) by VladSh
// Version: 1.9 (2016.02.24) by Skif_off
// Version: 1.8 (2015.04.10) by VladSh
// Version: 1.7 (2014.12.01) by VladSh
// Version: 1.6 (2012.10.24) by VladSh
// Version: 1.0 (2011.10.25) (c) Panych Y.W. aka FeyFre
//
// Arguments:
//   validate:
//      • [true | без параметра] - производить проверку синтаксиса xml и валидацию согласно схеме;
//      • false - только проверку правильности структуры xml
//   parse2gt:
//      • [false | без параметра] - не производить проверку удвоенного символа '>'
//      • true - производить
//   keep:
//      • [0 | без параметра] - не сохранять исходное выделение, устанавливая курсор в место ошибки
//      • 1 - сохранять исходное выделение; если выделения нет, то курсор также будет установлен в место ошибки
//   msgOpts - параметры вывода сообщений:
//      • [0 | без параметра] - в диалоговое окно;
//      • перечень кодов сообщений через запятую, которые выводить в панели вывода Log-плагина:
//         1 - все сообщения/ошибки;
//         16 - критическая ошибка xml-парсера;
//         48 - ошибка xml-синтаксиса (можно выводить только её, т.к. можно переходить на место ошибки);
//         64 - сообщение об успешно пройденной валидации
//   append - параметры вывода в панель Log-плагина:
//      • [0 | без параметра] - очищать содержимое панели перед записью
//      • 1, 2 - не очищать (см. Log-Rus.txt -> вызов с кодом 4 -> параметр "APPEND")
//   lClose - параметры закрытия панели Log-плагина (при msgOpts=1 игнорируется):
//      • [0 | без параметра] - не закрывать (в панели может остаться нужный текст, в т.ч. и от других вкладок программы);
//      • 1 - закрывать только при успешно пройденной валидации;
//      • 2 - закрывать всегда (только при msgOpts=0)
//
// Examples:
//    Call("Scripts::Main", 1, "XMLValidator.js")               - вывод в обычное диалоговое сообщение
//    Call("Scripts::Main", 1, "XMLValidator.js", `-msgOpts=1`) - вывод всех сообщений в панель Log-плагина
//    Call("Scripts::Main", 1, "XMLValidator.js", `-msgOpts=48 -lClose=1`) - вывод в панель Log-плагина только сообщений об ошибках xml-синтаксиса с закрытием панели при успешно пройденной валидации
//    Call("Scripts::Main", 1, "XMLValidator.js", `-msgOpts=48 -append=1`) - вывод в панель Log-плагина только сообщений об ошибках xml-синтаксиса с добавлением их к уже существующим в панели сообщениям

var hWndEdit = AkelPad.GetEditWnd();
var parserName = "msxml2.DOMDocument";
var xml = new ActiveXObject(parserName);
try {
   xml.async = false;
   xml.validateOnParse = AkelPad.GetArgValue("validate", true);
   xml.resolveExternals = false;
} catch (e) {
   output("Internal parser " + parserName + " error: " + e.description, 16 /*MB_ICONSTOP*/);
}

var text = AkelPad.GetSelText();
var selection;
var bKeep = false;
if (!text) {
   text = AkelPad.GetTextRange(0, -1);
   selection = false;
} else {
   selection = true;
   var npStart = AkelPad.GetSelStart();
   var npEnd = AkelPad.GetSelEnd();
   bKeep = AkelPad.GetArgValue("keep", 0);
   var npMin = Math.min(AkelPad.GetSelStart(), AkelPad.GetSelEnd());
}
var filepos, linepos, oLine;
var linenum = 0;

var t = new Date();
var extInfo = t.toLocaleTimeString() + " " + (AkelPad.GetEditFile(0) || "*") + " -> ";

xml.loadXML(text);
if (xml.parseError.errorCode !== 0) {
   var err = xml.parseError;
   linepos = err.linepos;
   if (selection) {
      filepos = npMin + err.filepos;
      oLine = getLogLine(filepos);
      linenum = oLine.linenum;
   }
   else {
		linenum = err.line;
		filepos = err.filepos;
   }
   if (!bKeep)
   	AkelPad.SetSel(filepos, filepos);
   output(extInfo + "XML validation error:\r(" + linenum + "," + linepos + ")\t\t" + err.reason, 48 /*MB_ICONEXCLAMATION*/);
   
} else {
   if (AkelPad.GetArgValue("parse2gt", false)) {
//      filepos = text.search(/>>.*<[^\/]/);
		filepos = AkelPad.TextFind(0, "<([^>\\s]++)\\s*\\K>>++(?![^<]*+</\\1)", 0x00280001);
      if (filepos >= 0) {
         filepos += 1;
//         if (selection)
//            filepos = npMin + filepos;
         oLine = getLogLine(filepos);
         linenum = oLine.linenum;
         linepos = filepos - oLine.startpos;
         if (!bKeep)
         	AkelPad.SetSel(filepos, filepos);
         output(extInfo + "XML parsing error:\r(" + linenum + "," + linepos + ")\t\t'>>' was found.", 48 /*MB_ICONEXCLAMATION*/);
      }
   }
   output(extInfo + "XML fragment is valid.\r", 64 /*MB_ICONINFORMATION*/);
}

function output(msg, nIcon /*MB_ICON...*/) {
   var slog = AkelPad.GetArgValue("msgOpts", "0");
   if (slog == "1" || (slog != "0" && slog.indexOf(nIcon.toString()) != -1)) {
      var fLogOutput = "Log::Output";
      if (AkelPad.Call(fLogOutput, 1, "", "", "^\\((\\d+),(\\d+)\\)", "/GOTOLINE=\\1:\\2") != -1) {
         var nAppend = AkelPad.GetArgValue("append", 0);
         AkelPad.Call(fLogOutput, 4, msg, -1, nAppend);
      }
   } else {
      var lClose = AkelPad.GetArgValue("lClose", 0);
      if ((lClose == 1 && nIcon == 64) || lClose == 2)
         AkelPad.Call("Log::Output", 6);
      AkelPad.MessageBox(hWndEdit, msg, WScript.ScriptName, nIcon);
   }
   WScript.Quit();
}

// Function returns a LineObject for Log-panel
function getLogLine(filepos) {
   var wrpLine = AkelPad.SendMessage(hWndEdit, 1078 /*EM_EXLINEFROMCHAR*/, 0, filepos);
   var start = AkelPad.SendMessage(hWndEdit, 187 /*EM_LINEINDEX*/, wrpLine, 0);
	var unwrpLine = AkelPad.SendMessage(hWndEdit, 3143 /*AEM_GETUNWRAPLINE*/, wrpLine, 0);
	return {
		linenum: unwrpLine + 1,
		startpos: start - 1
	};
}
Last edited by VladSh on Thu Mar 03, 2016 1:29 pm, edited 7 times in total.

KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

InFive wrote:

Code: Select all

Usage in menu or toolbar: 
   Call("Scripts::Main", 1, "EvalCmd.js", `if (AkelPad.Include("TextReplace_function.js")) TextReplace(sFindIt, ReplaceWith[, sFlags[, nRangeStart[, nRangeEnd]]]);`)
а что собственно должно происходить? вываливается ошибка и бросает в скрипт EvalCmd.js на строку 84 eval(pArgLine);
It seems to me that you forgot to specify the function arguments, eg:

Code: Select all

Call("Scripts::Main", 1, "EvalCmd.js", `if (AkelPad.Include("TextReplace_function.js")) TextReplace("a", "b", "g");`)

Offline
Posts: 96
Joined: Tue Nov 10, 2015 4:56 am

Post by InFive »

KDJ wrote:It seems to me that you forgot to specify the function arguments, eg:

Code: Select all

Call("Scripts::Main", 1, "EvalCmd.js", `if (AkelPad.Include("TextReplace_function.js")) TextReplace("a", "b", "g");`)
спасибо, надо запомнить решение...

но я давно пользуюсь другим решением... по моему заказу на другом форуме был сделан скрипт ScriptTemplate.vbs... в нем я создаю любое количество "Case" с любой комбинацией текстовых замен, хоть простые замены, хоть с помощью регулярок... в одном "Case" может быть хоть одна подобная вашей команда, хоть сотни... вызывается любой "Case" просто

Code: Select all

Call("Scripts::Main", 1, "ScriptTemplate.vbs", `"2"`)
мой этот файл весит 40 мегов с огромным количеством шаблонов замен... уже решил дублировать файлы данного скрипта чтобы они не были столь большими...

ваш вариант запуска комбинации замены из меню лично для меня может быть полезен, но пока не могу понять для чего, но запомню...

я же предлагаю другой вариант, которым я пользуюсь...

правда, то, что я предложил, касается вызова команд замен из меню, а не использования в других скриптах...

Offline
Posts: 3234
Joined: Wed Nov 29, 2006 1:19 pm
Location: Киев, Русь
Contact:

Post by VladSh »

InFive wrote:мой этот файл весит 40 мегов с огромным количеством шаблонов замен...
Зачем 40 "мегов"??? Ну пусть даже 100 шаблонов = 100 килобайт, но не 40 метров же...
InFive wrote:уже решил дублировать файлы данного скрипта чтобы они не были столь большими...
Зачем дублировать файлы скрипта? Чтобы ещё больше объём был?

Но замена по указанному сохранённому шаблону без поднятия GUI конечно же очень удобна.
Last edited by VladSh on Wed Mar 02, 2016 3:38 pm, edited 1 time in total.

Offline
Posts: 96
Joined: Tue Nov 10, 2015 4:56 am

Post by InFive »

VladSh wrote:Зачем 40 "мегов"??? Ну пусть даже 100 шаблонов = 100 килобайт, но не 40 метров же....
к сожалению, столько много я делаю замен в текстах, поэтому много готовых шаблонов у меня...
VladSh wrote:Зачем дублировать файлы скрипта?
чем меньше файл скрипта с шаблонами тем быстрее запускается выполнение команды и меньше ест оперативку... под словом дублировать я имел ввиду что новые шаблоны свои прописывать в новую копию данного скрипта, и не доводить каждую копию до бльших размеров, лучше создавать новую копию... и каждая новая копия скрипта запускается независимо от другой копии, это просто будут самостоятельные скрипты...

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

я просто не помню случаи когда ">>" были ошибкой, может ">>" были в комбинации с такими символами, с которыми такое недопустимо, ибо я раньше проверял xml в программе XML Copy Editor... ваши примеры попробовал проверить в XML Copy Editor - так он не посчитал это ошибкой...

еще раз приношу извинения, просто я считал что ">>" - это ошибка... но если подойти логически, то лучше такое из текста убирать, особенно когда я компилирую много текстовых модулей под Андроид, он вообще копризен в правильности xml и чуть что сразу плюётся...

но это если подойти логически, а так, может быть оно и не стоит ваших усилий!? другие как думают?

Offline
Posts: 3234
Joined: Wed Nov 29, 2006 1:19 pm
Location: Киев, Русь
Contact:

Post by VladSh »

InFive wrote:чем меньше файл скрипта с шаблонами тем быстрее запускается выполнение команды и меньше ест оперативку... под словом дублировать я имел ввиду что новые шаблоны свои прописывать в новую копию данного скрипта, и не доводить каждую копию до бльших размеров, лучше создавать новую копию... и каждая новая копия скрипта запускается независимо от другой копии, это просто будут самостоятельные скрипты...
Вы извините, но, по моему, это какое-то извращение...
По нормальному настройки и данные должны быть отделены от программного кода. Т.е. шаблоны не должны быть в скрипте, а желательно или в отдельных файлах или в одном отдельном файле. Для этого достаточно обычного ini-файла:
<название шаблона> = параметры
Тогда пользователю вообще ненужно видеть скрипт.
InFive wrote:касательно ">>"
Почти всё уже готово. Осталось правильную регулярку запилить.
Большая часть времени у меня ушла как раз не на это, а на восстановление возможности проверки выделения с правильным выводом сообщений об ошибках в консоль (получение номера строки и номера позиции места ошибки в строке).
Так что не стоит переживать, это всё равно нужно было сделать.

Offline
Posts: 3234
Joined: Wed Nov 29, 2006 1:19 pm
Location: Киев, Русь
Contact:

Post by VladSh »

Интересный момент обнаружился.

Строка

Code: Select all

var line = AkelPad.SendMessage(hWndEdit, 1078 /*EM_EXLINEFROMCHAR*/, 0, filepos);
возвращает номер не абзаца, а строки. Это ведёт к тому, что при коротких строках их номера вычисляются корректно, и переход в панели лога происходит правильно, а если же абзац занимает 2 и более строки, то переход осуществляется в неверное место.

Может кто знает, как в Акеле по номеру позиции в файле получить не номер "линии", а соответствующего абзаца?

Offline
Posts: 2248
Joined: Tue Aug 07, 2007 2:03 pm
Location: Vinnitsa, Ukraine

Post by FeyFre »

AEM_GETLINENUMBER + AEGI_UNWRAPLINEFROMRICHOFFSET ???

Offline
Posts: 3234
Joined: Wed Nov 29, 2006 1:19 pm
Location: Киев, Русь
Contact:

Post by VladSh »

У Infocatcher'а в openFileIn.js выкопал :) :

Code: Select all

function getLine() {
	var hWndEdit = AkelPad.GetEditWnd();
	var wrpLine = AkelPad.SendMessage(hWndEdit, 1078 /*EM_EXLINEFROMCHAR*/, 0, AkelPad.GetSelStart());
	var unwrpLine = AkelPad.SendMessage(hWndEdit, 3143 /*AEM_GETUNWRAPLINE*/, wrpLine, 0);
	return unwrpLine + 1;
}
8)

KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

TextReplace_function.js
Added: ability to use predefined variables _s0, _s1, ..., _n0, _n1 in ReplaceWith function passed as string.
Fixed: bug in count of changes.
Locked