Code: Select all
// AZJIO 14.10.2019 Обновил 6 раз
//
// Description(1033): Selects the text between operators () [] {} "" ', and the re-call extends the selection until the next nesting level.
// Description(1049): Выделяет текст между операторами ( ) [ ] { } " " ' ', причём повторный вызов расширяет выделение до следующего уровня вложения.
//
// Usage:
// Call("Scripts::Main", 1, "SelectLevel.js")
var hEditWnd = AkelPad.GetEditWnd();
var hMainWnd = AkelPad.GetMainWnd();
var oSys = AkelPad.SystemFunction();
var nSelStart = AkelPad.GetSelStart();
var nSelEnd = AkelPad.GetSelEnd();
if (nSelStart == 0) {
WScript.Quit();
}
// Установи "nearestbr.selto_flags=1" в файле XBrackets.ini, чтобы начинать захват сразу со скобками/кавычками
if (nSelStart == nSelEnd) {
AkelPad.Call("XBrackets::SelToNearestBrackets");
WScript.Quit();
}
var sEditFile = AkelPad.GetEditFile(0);
var sFileExt = AkelPad.GetFilePath(sEditFile, 4 /*CPF_FILEEXT*/ );
// var pStartText=AkelPad.GetTextRange(0, nSelStart);
// var pEndText=AkelPad.GetTextRange(nSelEnd, -1);
switch (sFileExt.toLowerCase()) {
// эти (xml, html) практически не работают, надо писать индивидуальный алгоритьм
case "xml":
case "htm":
case "html":
/*
aStart = ["<"];
aStart = [">"];
*/
aStart = ["<", ">", '"', "'"]; // выделяет не тексты, а теги
aStart = [">", "<", '"', "'"];
break;
default:
/*
aStart = '(,{,[,"'.split(',')
aEnd = '),},],"'.split(',')
*/
aStart = ["(", "{", "[", '"', "'"];
aEnd = [")", "}", "]", '"', "'"];
break;
}
var nPosAll = [[0, 0, nSelStart],
[0, 0, nSelStart],
[0, 0, nSelStart],
[0, 0, nSelStart],
[0, 0, nSelStart],
[0, 0, nSelStart]];
var nStartPos2 = 0;
var nEndPos2 = 0;
var nEndPos = 0
var nStartPosTmp = 0;
var nStartPos = 0;
var idx = -1;
SetRedraw(hEditWnd, false);
var nFirstLine = saveLineScroll(hEditWnd);
Search()
function Search() {
for (var j = 0; j <= 7; j++) { // сколько раз ищем скобки выше и выше. Ведь выше стоящие скобки могут быть одноуровневые и скрипт никогда не захватит выше.
for (var i = 0; i <= aStart.length; i++) {
// WScript.Echo(i);
if (nPosAll[i][2] == -1) { // если
continue;
}
AkelPad.SetSel(nPosAll[i][2], nSelEnd); // возвращаем выделение
nStartPos = AkelPad.TextFind(hEditWnd, aStart[i], 0x00100000 + 0x80000000); // FRF_UP + FRF_TEST - ищем вверх парный оператор
nPosAll[i][2] = nStartPos;
// WScript.Echo(nStartPos);
if (nStartPos == -1) { // если
continue;
}
nEndPos = GetPos(nStartPos); // ищем парный оператор
// WScript.Echo('шаг = ' + i + '\n' + nStartPos + '\n' + nEndPos);
if (nEndPos < nSelEnd || nEndPos == -1) { // если закрывающий оператор-скобка не вышла за пределы выделенного, то игнор
continue;
} else {
// nStartPos2 = nStartPos; // кэшируем валидные операторы
// nEndPos2 = nEndPos;
nPosAll[i][0] = nStartPos; // кэшируем валидные операторы
nPosAll[i][1] = nEndPos;
// WScript.Echo('валидные = ' + nStartPos + '\n' + nEndPos);
// WScript.Echo('валидные = ' + nPosAll[i][0] + '\n' + nPosAll[i][1]);
// WScript.Echo(nPosAll[i][0] + '\n' + nPosAll[i][1]);
}
if (nStartPosTmp < nStartPos) {
nStartPosTmp = nStartPos
idx = i;
}
};
if (idx > -1) {
return
}
};
};
// WScript.Echo('idx = ' + idx);
if (idx > -1) { // nStartPos не подразумевает 0, так как это выделить всё
if (nPosAll[idx][0] !== -1 && nPosAll[idx][1] !== -1) {
// WScript.Echo(nPosAll[idx][0] + '\n' + nPosAll[idx][1]);
// AkelPad.SetSel(nPosAll[i][0] + 1, nPosAll[i][1]); // без захвата разделителя
AkelPad.SetSel(nPosAll[idx][0], nPosAll[idx][1] + 1); // с захватом разделителя
}
} else {
AkelPad.SetSel(nSelStart, nSelEnd);
}
restoreLineScroll(hEditWnd, nFirstLine);
SetRedraw(hEditWnd, true);
function GetPos(Pos) {
var lpBuffer;
var a;
var s = "";
AkelPad.SetSel(Pos, Pos); // курсор в начало скобки/кавычки, чтобы найти пару
if (lpBuffer = AkelPad.MemAlloc(64 * _TSIZE)) {
var res;
res = AkelPad.Call("XBrackets::SelToMatchingBracket", 1, lpBuffer);
if (res > 0) {
s = AkelPad.MemRead(lpBuffer, _TSTR);
}
AkelPad.MemFree(lpBuffer);
}
a = s.split(" ");
if (a.length == 3) {
// WScript.Echo("pos1 = " + a[0] + "\npos2 = " + a[1] + "\nbrackets = " + a[2]);
return parseInt(a[1])
}
return -1
}
function SendMessage(hWnd, uMsg, wParam, lParam) {
return oSys.Call("User32::SendMessage" + _TCHAR, hWnd, uMsg, wParam, lParam);
}
function SetRedraw(hWnd, bRedraw)
{
SendMessage(hWnd, 11 /*WM_SETREDRAW*/, bRedraw, 0);
bRedraw && oSys.Call("User32::InvalidateRect", hWnd, 0, true);
}
// From Instructor's SearchReplace.js
function saveLineScroll(hWnd)
{
AkelPad.SendMessage(hWnd, 11 /*WM_SETREDRAW*/, false, 0);
return AkelPad.SendMessage(hWnd, 3129 /*AEM_GETLINENUMBER*/, 4 /*AEGL_FIRSTVISIBLELINE*/, 0);
}
function restoreLineScroll(hWnd, nBeforeLine)
{
if (AkelPad.SendMessage(hWnd, 3129 /*AEM_GETLINENUMBER*/, 4 /*AEGL_FIRSTVISIBLELINE*/, 0) != nBeforeLine)
{
var lpScrollPos;
var nPosY=AkelPad.SendMessage(hWnd, 3198 /*AEM_VPOSFROMLINE*/, 0 /*AECT_GLOBAL*/, nBeforeLine);
if (lpScrollPos=AkelPad.MemAlloc(_X64?16:8 /*sizeof(POINT64)*/))
{
AkelPad.MemCopy(lpScrollPos + 0 /*offsetof(POINT64, x)*/, -1, 2 /*DT_QWORD*/);
AkelPad.MemCopy(lpScrollPos + (_X64?8:4) /*offsetof(POINT64, y)*/, nPosY, 2 /*DT_QWORD*/);
AkelPad.SendMessage(hWnd, 3180 /*AEM_SETSCROLLPOS*/, 0, lpScrollPos);
AkelPad.MemFree(lpScrollPos);
}
}
AkelPad.SendMessage(hWnd, 3377 /*AEM_UPDATECARET*/, 0, 0);
AkelPad.SendMessage(hWnd, 11 /*WM_SETREDRAW*/, true, 0);
oSys.Call("user32::InvalidateRect", hWnd, 0, true);
}