Scripts collection

Discuss and announce AkelPad plugins
  • Author
  • Message
DV
Offline
Posts: 1251
Joined: Thu Nov 16, 2006 11:53 am
Location: Kyiv, Ukraine

Post by DV »

Поскольку под AkelPad такого ещё не было, выкладываю прототип GoToAnything (переход к файлу/строке в файле/поиск текста) для AkelPad. Вдохновлено угадайте каким редактором, в связи с чем предлагается горячая клавиша Ctrl+P.
Начиная с версии 0.4, скрипт поддерживает Избранное (Favourites) и Историю Открытия Файлов (Recent Files History).

GoToAnything.js
Скрипт уже увеличился настолько, что не влазит в сообщение. Поэтому скачайте его тут:
https://github.com/d0vgan/AkelPad-Scrip ... in/Scripts

Давайте обсуждать скрипт в соседней теме:
http://akelpad.sourceforge.net/forum/vi ... php?t=2151

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

Post by dothen »

Меню для цветовых тем.

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=35922#p35922
// Version: 1.5 (2023.05.07)
// Author: dothen
//
// *** Menu for color themes. ***
//
// Required to include: ShowMenu.js
//
// Usage:
// "ColorThemeMenu" Call("Scripts::Main", 1, "ColorThemeMenu.js") Icon("%a\AkelFiles\Plugs\Coder.dll", 5)
// "ColorThemeMenu" Call("Scripts::Main", 1, "ColorThemeMenu.js", `-posx=%bl -posy=%bb -mode=1`) Icon("%a\AkelFiles\Plugs\Coder.dll", 5)
//
// Аргументы:
//      -posx -posy     Координаты позиции меню (по умолчанию координаты курсора мыши),
//                      %bl и %bb  переменные плагина ToolBar, он вставит на их место координаты кнопки.
//      -mode           1 - Упрямое меню. 0 - Нормальное меню (по умолчанию 0).
//
// Описание:
// Выгружает на диск встроенные темы добавляя набор переменных от Infocatcher
// (https://github.com/Infocatcher/AkelPad_coder/blob/master/_colors.txt).
// Выгружает на диск пользовательские темы.
// Загружает с диска пользовательские темы.
// Выгрузка тем выполняется в папки \Coder\themes\user\ и \Coder\themes\internal\ с перезаписью файлов.
// Файлы с темами для загрузки в AkelPad надо сложить в папку \Coder\themes\
// Править и удалять темы можно через диалог настроек плагина Coder.
// Меню показывает пользовательские темы и файлы цветовых тем.
// Скрипт можно использовать как дополнение к PluginText.js от KDJ
// (http://akelpad.sourceforge.net/files/plugs/Scripts/KDJ.zip)
//
// Ctrl + Shift + LClick в меню удаляет выбранную тему из Coder.ini без подтверждения.
// Ctrl + LClick в подменю "Импорт" открывает выбранный файл для редактирования.

// Подсветка файлов с темами:
//
//Files:
//*.akel-theme
//
//QuotesRE:
//0 '^[^\s]+ "#([A-F\d]{6}|[A-F\d]{3})"$'   "\0=(0,\1,0)"   0   0


//Syntax
if (!GetSyntaxFile()) WScript.Quit();

//Include
if (!AkelPad.Include("ShowMenu.js")) WScript.Quit();

//HighLight
if (!AkelPad.IsPluginRunning("Coder::HighLight"))
    if (AkelPad.Call("Coder::HighLight") == -1 /*UD_FAILED*/) WScript.Quit();

//Variables
var oSys = AkelPad.SystemFunction();
var oSet = AkelPad.ScriptSettings();
var oFSO = new ActiveXObject("Scripting.FileSystemObject");
var sDirThemes = AkelPad.GetAkelDir(4) + "\\Coder\\themes\\";
var sDirThemesI = sDirThemes + "internal\\";
var sDirThemesU = sDirThemes + "user\\";
var sFileExt = ".akel-theme";
var sCurThemeName;
var aFileList = GetFileList();
var aThemeList = GetThemeList();
var nPosMenuX;
var nPosMenuY;
var nRunAgain;
var bUpdate = false;

var nPosMenuX = AkelPad.GetArgValue("posx", POS_CURSOR)
var nPosMenuY = AkelPad.GetArgValue("posy", POS_CURSOR)
var nRunAgain = AkelPad.GetArgValue("mode", 0)

 while (RunMenu())
{
    if (bUpdate)
    {
        aThemeList.splice(0,aThemeList.length);
        aThemeList = GetThemeList();
        bUpdate = false;
    }
    WScript.Sleep(100);
}

function RunMenu()
{
    var aItems = [];
    var nChecked = 0;
    var nFileListLength = aFileList.length;
    var nThemeListLength = aThemeList.length;
    var nDisabled = (nFileListLength == 0) ? MF_DISABLED | MF_GRAYED : MF_NORMAL;
    var i = -1;
    var c = 0;

    sCurThemeName = GetCurTheme();

    for(c = 0; c < nThemeListLength; c++)       // Список тем
    {
        nChecked = (aThemeList[c] == sCurThemeName) ? MF_NORMAL | MF_CHECKED | MF_USECHECKBITMAPS : MF_NORMAL;
        aItems[++i] = [aThemeList[c], nChecked, i];
    }

    aItems[++i] = ["", MF_SEPARATOR];
    aItems[++i] = ["Экспорт", MF_SUBMENU];
        aItems[++i] = ["Выгрузить свои темы", MF_NORMAL, i];
        aItems[++i] = ["Выгрузить встроенные темы", MF_NORMAL | MF_LAST, i];

    aItems[++i] = ["Импорт", MF_SUBMENU];
        for(c = 0; c < nFileListLength; c++)    // Список файлов
            aItems[++i] = [aFileList[c], MF_NORMAL, i];
        aItems[++i] = ["", MF_SEPARATOR];
        aItems[++i] = ["Загрузить все темы", nDisabled | MF_LAST, i];

    aItems[++i] = ["", MF_SEPARATOR];
    aItems[++i] = ["Настроить...", MF_NORMAL, i];

    //Show menu
    var nItem = ShowMenu(aItems, nPosMenuX, nPosMenuY);
    if (nItem == -1)
        return false;               // Ничего не выбрано.

    if (nItem < nThemeListLength)
    {
        if (Ctrl() && Shift())
        {
            DeleteColorTheme(aThemeList[nItem]);    // Удалить выбранную из меню цветовую тему.
            bUpdate = true;
        }
        else if (!Ctrl() && !Shift())
            ActivateColorTheme(aThemeList[nItem]);  // Активировать выбранную из меню цветовую тему.
        return nRunAgain;
    }

    if (nItem == nThemeListLength + 2)
    {
        ExportUserThemes();         // Выгрузить пользовательские темы в папку \Coder\themes\user\
        return false;
    }

    if (nItem == nThemeListLength + 3)
    {
        ExportInternalThemes();     // Выгрузить встроенные темы в папку \Coder\themes\internal\
        return false;
    }

    if ((nItem > nThemeListLength + 3) && (nItem < i - 3) )
    {
        if (Ctrl() && !Shift())
        {
            AkelPad.OpenFile(sDirThemes + aItems[nItem][0]);    // Открыть выбранный файл для редактирования.
            return false;
        }
        if (!(Ctrl() || Shift()))
        {
            ImportUserThemes(aItems[nItem][0]);                 // Загрузить тему из выбранного файла и активировать.
            bUpdate = true;
            return nRunAgain;
        }
        return false;
    }

    if (nItem == i - 2)
    {
        ImportUserThemes("");       // Загрузить все цветовые темы из папки \Coder\themes.
        bUpdate = true;
        return nRunAgain;
    }

    if (nItem == i)
    {
        ColorThemeSettings();       // Открыть диалог настроек плагина Coder.
        return false;
    }

    WScript.Echo("RunMenu Error");
    return false;
}

function Ctrl()
{
    return Boolean(oSys.Call("User32::GetKeyState", 0x11 /*VK_CONTROL*/) & 0x8000);
}

function Shift()
{
    return Boolean(oSys.Call("User32::GetKeyState", 0x10 /*VK_SHIFT*/) & 0x8000);
}

function DeleteColorTheme(sThemeName)
{
    var sThemeList;
    var aThemeList;

    if (oSet.Begin("Coder", 0x21 /*POB_PLUGS|POB_READ*/))
    {
        sThemeList = oSet.Read("VarThemeList", 3 /*PO_STRING*/);
        oSet.End();
    }

    aThemeList = sThemeList.split("|").sort();

    for (i = 0; i < aThemeList.length; ++i)
    {
        if (aThemeList[i] == sThemeName)
        {
            aThemeList.splice(i, 1);
            break;
        }
    }

    sThemeList = aThemeList.join("|");

    if (oSet.Begin("Coder", 0x22 /*POB_PLUGS|POB_SAVE*/))
    {
        oSet.Delete("/" + sThemeName);
        oSet.Write("VarThemeList", 3 /*PO_STRING*/, sThemeList);

        if (sThemeName == sCurThemeName)
        {
            if (aThemeList.length == 0)
                sThemeName = "Default";
            else sThemeName = aThemeList[0];

            oSet.Write("VarThemeActive", 3 /*PO_STRING*/, sThemeName);
        }
        oSet.End();
    }
    RestartPlugin();
}

function ActivateColorTheme(sThemeName)
{
    AkelPad.Call("Coder::Settings", 5, sThemeName);
}

function ColorThemeSettings()
{
    AkelPad.Call("Coder::Settings");
}

function GetCurTheme()
{
    var sThemeName = "";
    var lpBuf;

    if (lpBuf = AkelPad.MemAlloc(256))
    {
        AkelPad.CallW("Coder::Settings", 20, 0, lpBuf, 256);
        sThemeName = AkelPad.MemRead(lpBuf, 1 /*DT_UNICODE*/);
        AkelPad.MemFree(lpBuf);
    }
    return sThemeName;
}

function RestartPlugin()
{
    var bHighLight    = AkelPad.IsPluginRunning("Coder::HighLight");
    var bCodeFold     = AkelPad.IsPluginRunning("Coder::CodeFold");
    var bAutoComplete = AkelPad.IsPluginRunning("Coder::AutoComplete");
    for(var i = 0; i < 2; i++)
    {
        if (bHighLight)
            AkelPad.Call("Coder::HighLight");
        if (bCodeFold)
            AkelPad.Call("Coder::CodeFold");
        if (bAutoComplete)
            AkelPad.Call("Coder::AutoComplete");
    }
}

function GetFileList()
{
    var aList = [];
    var sFileName;
    var sFile_Ext;

    if (ThemesFolderExists())
    {
        var Folder = oFSO.GetFolder(sDirThemes);
        var Files = new Enumerator(Folder.Files);

        for (; !Files.atEnd(); Files.moveNext())
        {
            sFileName = Files.item().Name;
            sFile_Ext = "." + AkelPad.GetFilePath(sFileName, 4 /*CPF_FILEEXT*/);
            if (sFile_Ext == sFileExt)
                aList.push(sFileName);
        }
    }
    return aList.sort();
}

function ExportUserThemes()
{
    var sThemeList = "";
    var sThemeText = "";

    if (MsgBox(sDirThemesU) == 2 /*IDCANCEL*/) return;

    if (oFSO.FolderExists(sDirThemes) == false)
        oFSO.CreateFolder(sDirThemes);
    if (oFSO.FolderExists(sDirThemesU) == false)
        oFSO.CreateFolder(sDirThemesU);

    if (oSet.Begin("Coder", 0x21 /*POB_PLUGS|POB_READ*/))
    {
        sThemeList = oSet.Read("VarThemeList", 3 /*PO_STRING*/);
        if (sThemeList != "")
        {
            var aList = sThemeList.split("|");
            var nLen = aList.length;

            for(var i = 0; i < nLen; i++)
            {
                sThemeText = oSet.Read("/" + aList[i], 20 /*PO_BINARYSTRING*/);
                if (sThemeText != "")
                    AkelPad.WriteFile(sDirThemesU + aList[i] + sFileExt, sThemeText, -1, 1251, false);
            }
            MsgBoxOk(sDirThemesU);
        }
        oSet.End();
    }
}

function ThemesFolderExists()
{
    return oFSO.FolderExists(sDirThemes);
}

function ImportUserThemes(sFile)
{
    if (ThemesFolderExists())
    {
        if (sFile == "")    // Загрузить все файлы.
        {
            var nLen = aFileList.length;
            for(var i = 0; i < nLen; i++)
                WriteThemeToIniFile(aFileList[i]);
            RestartPlugin();
        }
        else                // Загрузить файл.
        {
            WriteThemeToIniFile(sFile);
            RestartPlugin();
            AkelPad.Call("Coder::Settings", 5 /*DLLA_CODER_SETVARTHEME*/, sFile.replace(sFileExt,""));
        }
    }
}

function ReadThemeFile(sFullFileName)
{
    var sText = AkelPad.ReadFile(sFullFileName);

    sText = sText.replace(/\x0A/g, "\r");       // Newline format - CR (Macintosh)
    sText = sText.replace(/\x0D{2,}/g, "\r");   // Удалить пустые строки.
    sText = sText + String.fromCharCode(0);     // Дописать в конец нули.
    return sText;
}

function WriteThemeToIniFile(sFileName)
{
    var sThemeText = ReadThemeFile(sDirThemes + sFileName);
    var sThemeName = sFileName.replace(sFileExt,"");

    if (oSet.Begin("Coder", 0x21 /*POB_PLUGS|POB_READ*/))
    {
        var sThemeList = oSet.Read("VarThemeList", 3 /*PO_STRING*/);
        oSet.End();
    }

    if (oSet.Begin("Coder", 0x22 /*POB_PLUGS|POB_SAVE*/))
    {
        if (sThemeList == "")
           sThemeList = sThemeName;

        else if (sThemeList.search(sThemeName) == -1)
           sThemeList = sThemeList + "|" + sThemeName;

        oSet.Write("VarThemeList", 3 /*PO_STRING*/, sThemeList);      //  VarThemeList=Active4DEx|BespinEx|...|ZenburnEx
        oSet.Write("/" + sThemeName, 2 /*PO_BINARY*/, sThemeText);    //  /BespinEx=4F004B00...22000D0000000000
        oSet.End();
    }
}

function MsgBox(sDir)
{
    var nChoice = AkelPad.MessageBox(
        AkelPad.GetMainWnd(),
        "\nФайлы в папке\n" + sDir + "\nбудут перезаписаны.\n\nПродолжить?",
        "Экспорт цветовых тем", 65 /*MB_ICONASTERISK | MB_OKCANCEL*/);
    return nChoice;
}

function MsgBoxOk(sDir)
{
    AkelPad.MessageBox(
        AkelPad.GetMainWnd(),
        "\nТемы экспортированы в папку\n" + sDir,
        "Экспорт цветовых тем", 64 /*MB_ICONASTERISK | MB_OK*/);
}

function GetThemeList()
{
    return GetThemeData(1);
}

function ExportInternalThemes()
{
    GetThemeData(2);
    MsgBoxOk(sDirThemesI);
}

function WriteFileTheme(sThemeName, sThemeText)
{
    sThemeText = ExtraVars() + sThemeText;
    sThemeText = sThemeText.replace(/ ([^"]+?)$/gm, ' "$1"');     // Значения переменных взять в кавычки.
    AkelPad.WriteFile(sDirThemesI + sThemeName + "Ex" + sFileExt, sThemeText, -1, 1251, true);
}

function GetThemeData(nMode)
{
    var sThemeName;
    var sThemeText;
    var lpThemeCur;
    var lpThemePrev;
    var lpThemeData;
    var aThemeList = [];
    var CELL = _X64?8:4;

    if (nMode == 2)
    {
        if (MsgBox(sDirThemesI) == 2 /*IDCANCEL*/) return;

        if (oFSO.FolderExists(sDirThemes) == false)
            oFSO.CreateFolder(sDirThemes);
        if (oFSO.FolderExists(sDirThemesI) == false)
            oFSO.CreateFolder(sDirThemesI);
    }

    var lpVTG = AkelPad.MemAlloc(CELL); // **lppVarThemeGlobal
    var lpVTA = AkelPad.MemAlloc(CELL); // **lppVarThemeActive

    AkelPad.CallW("Coder::Settings", 24 /*DLLA_CODER_GETVARTHEMEDATA*/, 0, 0, lpVTG, lpVTA);
    lpThemeCur = AkelPad.MemRead(lpVTA, 2 /*DT_QWORD*/);
    AkelPad.MemFree(lpVTG);
    AkelPad.MemFree(lpVTA);

    while(lpThemeCur != 0) // Находим первую структуру VARTHEME.
    {
        lpThemePrev = lpThemeCur;
        lpThemeCur = AkelPad.MemRead(lpThemeCur + CELL, 2 /*DT_QWORD*/);      // *prev
    }

    lpThemeCur = lpThemePrev

    while(lpThemeCur != 0)
    {
        sThemeName = AkelPad.MemRead(lpThemeCur + CELL * 5, 1 /*DT_UNICODE*/);            // (4+4+12)/4=5          (8+8+24)/8=5          wszVarThemeName[MAX_PATH]
        lpThemeData = AkelPad.MemRead(lpThemeCur + CELL * (_X64?71:136), 2 /*DT_QWORD*/); // (4+4+12+520+4)/4=136  (8+8+24+520+8)/8=71   *wpTextData
        sThemeText = AkelPad.MemRead(lpThemeData, 1 /*DT_UNICODE*/);

        if ((nMode == 1) & (sThemeText == "")) // В пользовательской теме *wpTextData указывает на пустую строку.
            aThemeList.push(sThemeName);

        if ((nMode == 2) & (sThemeText != ""))
            WriteFileTheme(sThemeName, sThemeText);

        lpThemeCur = AkelPad.MemRead(lpThemeCur, 2 /*DT_QWORD*/);
    }
    if (nMode == 1) return aThemeList.sort();
}

/*
AkelPad-4.9.8-src.zip\AkelFiles\Plugs\Coder\Source\Coder.h
typedef struct _VARTHEME {
  struct _VARTHEME *next;             4(8)
  struct _VARTHEME *prev;             4(8)
  STACKVAR hVarStack;                 12(24)
  wchar_t wszVarThemeName[MAX_PATH];  520(520)     #define MAX_PATH 260   stdlib.h
  int nVarThemeNameLen;               4(8)
  const wchar_t *wpTextData;
} VARTHEME;
*/

function GetSyntaxFile()
{
    var pSyntaxFile = "";
    var lpSyntaxFile;
    if (lpSyntaxFile = AkelPad.MemAlloc(256 * 2))
    {
        AkelPad.CallW("Coder::Settings", 16, 0, lpSyntaxFile, 256);
        pSyntaxFile = AkelPad.MemRead(lpSyntaxFile, 1 /*DT_UNICODE*/);
        AkelPad.MemFree(lpSyntaxFile);
    }
    return (pSyntaxFile != "");
}

function ExtraVars()
{
    var sExtraVars =
    "LABEL #64E986\r" +
    "OK #339933\r" +
    "ERR #CC3333\r" +
    "IMPORTANT #CC3333\r" +
    "WARN #BB6622\r" +
    "DBG #9932CC\r" +
    "INFO #3333CC\r" +
    "COMM_C #668000\r" +
    "KEYWORD #9932CC\r" +
    "KEYWORD_ALT #3399CC\r" +
    "KEYWORD_SPECIAL #33CC99\r" +
    "KEYWORD_NOTSTD #800000\r" +
    "GLOBAL_VAR #9932CC\r" +
    "GLOBAL_VAR_NOTSTD #800000\r" +
    "REGEXP #8000FF\r" +
    "PROPERTY #3399CC\r" +
    "PROPERTY_ALT #3333CC\r" +
    "PROPERTY_NOTSTD #CC3333\r" +
    "EVENT #33CC99\r" +
    "EVENT_NOTSTD #CC3333\r" +
    "BLOCK #8B0000\r" +
    "BLOCK_NOTSTD #CC3333\r" +
    "OP_ALT #3399CC\r" +
    "OP_NOTSTD #8B0000\r" +
    "CMD #339933\r" +
    "TAG_NS #3399CC\r" +
    "TAG_ALT #3399CC\r" +
    "TAG_DEPRECATED #992266\r" +
    "TAG_NOTSTD #8B0000\r" +
    "ATTR_ALT #9932CC\r" +
    "ATTR_NS #33CC99\r" +
    "ATTR_NOTSTD #800000\r" +
    "ENTITY #3399CC\r" +
    "IF_NOTSTD #8B0000\r" +
    "NUM_ALT #0000FF\r";
    return sExtraVars;
}

Last edited by dothen on Sun May 07, 2023 6:56 pm, edited 1 time in total.

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

Post by Infocatcher »

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=36081#p36081
// http://infocatcher.ucoz.net/js/akelpad_scripts/toggleToolbarRows.js
// https://github.com/Infocatcher/AkelPad_scripts/blob/master/toggleToolbarRows.js

// (c) Infocatcher 2022
// Version: 0.1.0 - 2022-08-07
// Author: Infocatcher

//// Toggle multiline toolbar from ToolBar plugin (convert BREAK <-> #BREAK)

// Arguments:
//   -toolBarName="ToolBar2"  - specify file name of ToolBar plugin

// Usage:
//   Call("Scripts::Main", 1, "toggleToolbarRows.js")
//   Call("Scripts::Main", 1, "toggleToolbarRows.js", '-toolBarName="ToolBar2"')

var tbPlugName = AkelPad.GetArgValue("toolBarName", "ToolBar");

function _localize(s) {
	var strings = {
		"ToolBarText data in %P plugin is empty!": {
			ru: "Содержимое ToolBarText плагина %P пустое!"
		},
		"ToolBarText data in %P plugin not recognized:\n%S": {
			ru: "Содержимое ToolBarText плагина %P не распознано:\n%S"
		},
		"Failed to read settings of %P plugin": {
			ru: "Не удалось прочитать настройки плагина %P"
		},
		"Failed to write settings of %P plugin": {
			ru: "Не удалось записать настройки плагина %P"
		},
		"Failed to toggle multiline toolbar from %P plugin: BREAK item not found": {
			ru: "Не удалось переключить многострочность панели инструментов плагина %P: элемент BREAK не найден"
		}
	};
	var lng = "en";
	switch(AkelPad.GetLangId(1 /*LANGID_PRIMARY*/)) {
		case 0x19: lng = "ru";
	}
	_localize = function(s) {
		return strings[s] && strings[s][lng] || s;
	};
	return _localize(s);
}
function _str(s) {
	return _localize(s).replace("%P", tbPlugName);
}

var oSet = AkelPad.ScriptSettings();
var hMainWnd = AkelPad.GetMainWnd();
var isHex = AkelPad.SendMessage(hMainWnd, 1222 /*AKD_GETMAININFO*/, 5 /*MI_SAVESETTINGS*/, 0) == 2 /*SS_INI*/;

if(oSet.Begin(tbPlugName, 0x21 /*POB_READ|POB_PLUGS*/)) {
	var tbData = oSet.Read("ToolBarText", 3 /*PO_STRING*/);
	oSet.End();
	if(
		!tbData
		|| isHex && (tbData.length % 4 || /[^\dA-F]/i.test(tbData))
	) {
		error(
			tbData
				? _str("ToolBarText data in %P plugin not recognized:\n%S")
					.replace("%S", tbData.substr(0, 100))
				: _str("ToolBarText data in %P plugin is empty!")
		);
		WScript.Quit();
	}
}
else {
	error(_str("Failed to read settings of %P plugin"));
}

if(tbData && oSet.Begin(tbPlugName, 0x22 /*POB_SAVE|POB_PLUGS*/)) {
	var tbText = isHex ? hexToStr(tbData) : tbData;
	var changed;
	tbText = tbText.replace(/\r(#?)BREAK\r/g, function(s, commented) {
		changed = true;
		return "\r" + (commented ? "" : "#") + "BREAK\r";
	});
	if(changed) {
		tbData = isHex ? strToHex(tbText) : tbText;
		oSet.Write("ToolBarText", 3 /*PO_STRING*/, tbData);
	}
	else {
		error(_str("Failed to toggle multiline toolbar from %P plugin: BREAK item not found"), 48 /*MB_ICONEXCLAMATION*/);
	}
	oSet.End();

	if(changed && AkelPad.IsPluginRunning(tbPlugName + "::Main")) {
		AkelPad.Call(tbPlugName + "::Main");
		AkelPad.Call(tbPlugName + "::Main");
	}
}
else {
	tbData && error(_str("Failed to write settings of %P plugin"));
}

function hexToStr(h) {
	return h.replace(/[\dA-F]{4}/ig, function(h) {
		var n = parseInt(reorder(h), 16);
		return String.fromCharCode(n);
	});
}
function strToHex(s) {
	return s.replace(/[\s\S]/g, function(c) {
		var h = c.charCodeAt(0).toString(16).toUpperCase();
		h = "0000".substr(h.length) + h;
		return reorder(h);
	});
}
function reorder(h) { // LE <-> BE
	var b1 = h.substr(0, 2);
	var b2 = h.substr(2);
	return b2 + b1;
}

function error(msg, icon) {
	AkelPad.MessageBox(hMainWnd, msg, WScript.ScriptName, icon || 16 /*MB_ICONERROR*/);
}
<download | development version>
Toggle multiline toolbar from ToolBar plugin (convert BREAK <-> #BREAK).


Image

Image

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

Post by AlexeyB »

В сценарий PluginText.js (автор KDJ) добавил поддержку работы с различными кодировками (сохранение - только UTF-16 или UTF-8 ) и форматами новой строки (сохранение - только в CR или CRLF) файлов .akelmenu.

В оригинальном сценарии сохранять и загружать файлы можно только в UTF-16 LE, CR.

Прежде всего это полезно при работе с Git или Mercurial, которые не поддерживают UTF-16 (сравнивают как бинарные файлы, и с ними потом неудобно работать) и переводы строк в стиле Mac (CR, \r).

Поскольку KDJ перестал посещать этот форум, просто выкладываю модифицированный вариант сценария.

PluginTextEx.js

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

Re: Scripts collection

Post by AZJIO »

Иногда хочется посмотреть скрипт, но лень искать его в списке скриптов, скопировал имя скрипта (двойной клик -> Ctrl+C), кликаем пункт и скрипт уже открыт.

Code: Select all

// "Открыть скрипт" Call("Scripts::Main", 1, "OpenScript.js")
var pHelp = "Удерживая Ctrl нажмите пункт меню или кнопку, далее в открытом окне выделите имя скрипта двойным кликом (без .js), скопируйте и только потом используйте этот пункт, чтобы отрыть скрипт в AkelPad"
var pName = AkelPad.GetClipboardText(true);
// if (pName.indexOf("\n") = -1) {
// разрешил относительный путь folder/name в регвыре
if ((pName == "") || (pName.lengt > 150) || (pName.search(/[\n:*?"<>|]/) > -1)) {
	WScript.Echo('Буфер обмена не содержит имени файла. ' + pHelp);
	WScript.Quit();
}
var path = 'AkelFiles\\Plugs\\Scripts\\' + pName;
if (path.slice(-3) != '.js') {path += '.js';}
var fso = new ActiveXObject("Scripting.FileSystemObject");
if (fso.FileExists(path)) {
	AkelPad.OpenFile(path);
} else {
	WScript.Echo(path + '\n\nФайл не существует. ' + pHelp);
}

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

Re: Scripts collection

Post by AZJIO »

Stemming (RU) - удаляет окончания слов для генерации списка слов поискового запроса. Например я сделал поле ввода для поиска слов по справке. Мне нужно иметь только слова имеющиеся в справке. Я получаю список всех слов, но там есть такие как "мяч, мячу, мячом, мячами, мячи" и т.д. при этом для поискового запроса требуется только "мяч" чтобы найти все его вхождения в справке.
Обновил, добавил поддержку "ё", точнее восстановление "ё" из оригинального слова.
Обновил, оптимизировал вариант с "ё".
Обновил, добавил перевод в нижний регистр и сообщение о завершении обработки.
Проверка на отсутствие гласных в слове исключает абревиатуры.
70 тыс. строк очень медленно обрабатывает, 1 минута 10 сек. (онлайн-сервисы обрабатывают мгновенно).

Code: Select all

// Стеминг он же Стиммер (удаляет окончания слов оставляя базу), предназначен для генерации списка слов поискового запроса.
// модернизация для AkelPad от AZJIO (14.02.2024)
// алгоритм использовал по ссылке: https://popsul.ru/blog/2012/06/post-10.html
// но он работает с одним словом, пришлось дополнить его захватом русских слов из текста циклом обработки каждого слова,
// и добавить удаление дубликатов и сортировку.

var pAllText=AkelPad.GetTextRange(0, -1);
pAllText=pAllText.toLowerCase()
pAllText = Stemmer(pAllText)
pAllText = RemoveDuplicates(pAllText) // удаление дубликатов и сортировка
pAllText = pAllText.replace(/^[^\n]{0,3}\n/gm, ""); // удаление строк длинной меньше 4-х символов
AkelPad.SetClipboardText(pAllText);
WScript.Echo("готово, результат в буфере обмена");


function RemoveDuplicates(text) {
	oDict = new ActiveXObject("Scripting.Dictionary");
	oDict.CompareMode = 1;
	var ares = [];
	var result = "";
	var i;
	var size;
	var arr = text.split('\n'); // получаем массив слов

	for (i in arr) {
		if (oDict.Exists(arr[i]))
			oDict.Item(arr[i]) += 1;
		else
			oDict.Item(arr[i]) = 1;
		};

	ares = (new VBArray(oDict.Keys())).toArray();
	ares = ares.sort();
	result = ares.join("\n")
	return result;
};


function Stemmer(pAllText) {

	var RVRE= /^(.*?[аеиоуыэюя])(.*)$/i;
	var PERFECTIVEGROUND_1= /([ая])(в|вши|вшись)$/gi;
	var PERFECTIVEGROUND_2= /(ив|ивши|ившись|ыв|ывши|ывшись)$/i;
	var REFLEXIVE= /(с[яь])$/i;
	var ADJECTIVE= /(ее|ие|ые|ое|ими|ыми|ей|ий|ый|ой|ем|им|ым|ом|его|ого|ему|ому|их|ых|ую|юю|ая|яя|ою|ею)$/i;
	var PARTICIPLE_1= /([ая])(ем|нн|вш|ющ|щ)$/gi;
	var PARTICIPLE_2= /(ивш|ывш|ующ)$/i;
	var VERB_1= /([ая])(ла|на|ете|йте|ли|й|л|ем|н|ло|но|ет|ют|ны|ть|ешь|нно)$/gi;
	var VERB_2= /(ила|ыла|ена|ейте|уйте|ите|или|ыли|ей|уй|ил|ыл|им|ым|ен|ило|ыло|ено|ят|ует|уют|ит|ыт|ены|ить|ыть|ишь|ую|ю)$/i;
	var NOUN= /(а|ев|ов|ие|ье|е|иями|ями|ами|еи|ии|и|ией|ей|ой|ий|й|иям|ям|ием|ем|ам|ом|о|у|ах|иях|ях|ы|ь|ию|ью|ю|ия|ья|я)$/i;
	var DERIVATIONAL= /.*[^аеиоуыэюя]+[аеиоуыэюя].*ость?$/i;
	var DER= /ость?$/i;
	var SUPERLATIVE= /(ейше|ейш)$/i;
	var I= /и$/i;
	var P= /ь$/i;
	var NN= /нн$/i;

	var start;
	var rv;
	var wParts;
	var temp;
	var rure = /[а-яё]+/gi;
	var myArray;
	var result = "";

while ((myArray = rure.exec(pAllText)) != null) // цикл перечисления всех русских слов
{
	myArray[0] =  myArray[0].replace(/ё/gi, "е");
	wParts =  myArray[0].match(RVRE); // проверяем совпадение гласных в тексте
	if (!wParts) {
		// return word; // если нет гласных, возвращаем текст как есть назад
		continue
	}
	start = wParts[1];
	rv = wParts[2];
		temp = rv.replace(PERFECTIVEGROUND_2, "");
		if (temp == rv) {
			temp = rv.replace(PERFECTIVEGROUND_1, '$1');
		}
		if (temp == rv) {
			rv = rv.replace(REFLEXIVE, "");
			temp = rv.replace(ADJECTIVE, "");
			if (temp != rv) {
				rv = temp;
				temp = rv.replace(PARTICIPLE_2, "");
				if (temp == rv) {
					rv = rv.replace(PARTICIPLE_1, '$1');
				}
			} else {
				temp = rv.replace(VERB_2, "");
				if (temp == rv) {
					temp = rv.replace(VERB_1, '$1');
				}
				if (temp == rv) {
					rv = rv.replace(NOUN, "");
				} else {
					rv = temp;
				}
			}
		} else {
			rv = temp;
		}
		rv = rv.replace(I, "");
		if (rv.match(DERIVATIONAL)) {
			rv = rv.replace(DER, "");
		}
		temp = rv.replace(P, "");
		if (temp == rv) {
			rv = rv.replace(SUPERLATIVE, "");
			rv = rv.replace(NN, 'н');
		} else {
			rv = temp;
		}
		result += start + rv + "\n";
	};
		return result;
};



Code: Select all

// Стеминг он же Стиммер (удаляет окончания слов оставляя базу), предназначен для генерации списка слов поискового запроса.
// модернизация для AkelPad от AZJIO (14.02.2024)
// алгоритм использовал по ссылке: https://popsul.ru/blog/2012/06/post-10.html
// но он работает с одним словом, пришлось дополнить его захватом русских слов из текста циклом обработки каждого слова,
// и добавить удаление дубликатов и сортировку.

// Восстанавливает "ё" - если строка содержит ё (включаем флаг restore и перед тем как добавить слово в результат берём из оргинала
// число символов по результату и получаем обрезанное но с "ё").

var pAllText=AkelPad.GetTextRange(0, -1);
pAllText=pAllText.toLowerCase()
pAllText = Stemmer(pAllText)
pAllText = pAllText.replace(/^[^\n]{0,3}\n/gm, ""); // удаление строк длинной меньше 4-х символов
AkelPad.SetClipboardText(pAllText); // возвращаем результат в буфер обмена
WScript.Echo("готово, результат в буфере обмена");

function Stemmer(pAllText) {

	var RVRE= /^(.*?[аеиоуыэюя])(.*)$/i;
	var PERFECTIVEGROUND_1= /([ая])(в|вши|вшись)$/gi;
	var PERFECTIVEGROUND_2= /(ив|ивши|ившись|ыв|ывши|ывшись)$/i;
	var REFLEXIVE= /(с[яь])$/i;
	var ADJECTIVE= /(ее|ие|ые|ое|ими|ыми|ей|ий|ый|ой|ем|им|ым|ом|его|ого|ему|ому|их|ых|ую|юю|ая|яя|ою|ею)$/i;
	var PARTICIPLE_1= /([ая])(ем|нн|вш|ющ|щ)$/gi;
	var PARTICIPLE_2= /(ивш|ывш|ующ)$/i;
	var VERB_1= /([ая])(ла|на|ете|йте|ли|й|л|ем|н|ло|но|ет|ют|ны|ть|ешь|нно)$/gi;
	var VERB_2= /(ила|ыла|ена|ейте|уйте|ите|или|ыли|ей|уй|ил|ыл|им|ым|ен|ило|ыло|ено|ят|ует|уют|ит|ыт|ены|ить|ыть|ишь|ую|ю)$/i;
	var NOUN= /(а|ев|ов|ие|ье|е|иями|ями|ами|еи|ии|и|ией|ей|ой|ий|й|иям|ям|ием|ем|ам|ом|о|у|ах|иях|ях|ы|ь|ию|ью|ю|ия|ья|я)$/i;
	var DERIVATIONAL= /.*[^аеиоуыэюя]+[аеиоуыэюя].*ость?$/i;
	var DER= /ость?$/i;
	var SUPERLATIVE= /(ейше|ейш)$/i;
	var I= /и$/i;
	var P= /ь$/i;
	var NN= /нн$/i;

	var start;
	var rv;
	var wParts;
	var temp;
	// var rure = /[а-яё]+/gi;
	var rure = /[а-яё]{4,}/gi;
	var myArray;
	var result = "";
	var orig = "";
	var restoreIO = 0;
	var lenw;
	
	
	oDict = new ActiveXObject("Scripting.Dictionary");
	oDict.CompareMode = 1;
	var ares = [];

while ((myArray = rure.exec(pAllText)) != null) // цикл перечисления всех русских слов
{
	if (/ё/i.test(myArray[0])) {
		orig = myArray[0]
		myArray[0] =  myArray[0].replace(/ё/gi, "е");
		restoreIO=1
	}
	wParts =  myArray[0].match(RVRE); // проверяем совпадение гласных в тексте
	if (!wParts) {
		// return word; // если нет гласных, возвращаем текст как есть назад
		continue
	}
	start = wParts[1];
	rv = wParts[2];
		temp = rv.replace(PERFECTIVEGROUND_2, "");
		if (temp == rv) {
			temp = rv.replace(PERFECTIVEGROUND_1, '$1');
		}
		if (temp == rv) {
			rv = rv.replace(REFLEXIVE, "");
			temp = rv.replace(ADJECTIVE, "");
			if (temp != rv) {
				rv = temp;
				temp = rv.replace(PARTICIPLE_2, "");
				if (temp == rv) {
					rv = rv.replace(PARTICIPLE_1, '$1');
				}
			} else {
				temp = rv.replace(VERB_2, "");
				if (temp == rv) {
					temp = rv.replace(VERB_1, '$1');
				}
				if (temp == rv) {
					rv = rv.replace(NOUN, "");
				} else {
					rv = temp;
				}
			}
		} else {
			rv = temp;
		}
		rv = rv.replace(I, "");
		if (rv.match(DERIVATIONAL)) {
			rv = rv.replace(DER, "");
		}
		temp = rv.replace(P, "");
		if (temp == rv) {
			rv = rv.replace(SUPERLATIVE, "");
			rv = rv.replace(NN, 'н');
		} else {
			rv = temp;
		}
		
		temp = start + rv
		if (restoreIO) {
			lenw = temp.length
			temp = orig.substring(0, lenw)
			restoreIO=0
		}
		
		if (oDict.Exists(temp)) {
			oDict.Item(temp) += 1;
		} else {
			oDict.Item(temp) = 1;
		}
	};
	ares = (new VBArray(oDict.Keys())).toArray();
	ares = ares.sort();
	result = ares.join("\n");
	return result;
};

Offline
Posts: 23
Joined: Sat Jul 05, 2008 11:30 am
Location: Odesa, Ukraine

Re: Scripts collection

Post by ewild »

Code: Select all

// https://akelpad.sourceforge.net/forum/viewtopic.php?t=204&p=36478#p36478
// description: Pass selected text to the default browser
// version: 2024-09-14
// author: ewild
//// based on: InternetRequest.js (v2.2, 2015.04.01) by VladSh
//// https://akelpad.sourceforge.net/forum/viewtopic.php?t=204&p=7303#p7303
// Examples ("$text" is a selected text placeholder):
//// predefined url:
// "Translate: Google: Auto > Ua" Call("Scripts::Main",1,"InternetRequestFix.js","https://translate.google.com/sl=auto&tl=uk&text=$text")
// "Translate: DeepL : Auto > Ua" Call("Scripts::Main",1,"InternetRequestFix.js","https://www.deepl.com/translator#auto/uk/$text")
//// just a text*:
// "Google Search for selected text in default browser" Call("Scripts::Main",1,"InternetRequestFix.js","$text")
// *note: if a valid URL is recognized within the selected text at the beginning it will be opened in the default browser instead

pArgLine=AkelPad.GetArgLine();
if (pArgLine) {
pSelText=AkelPad.GetSelText();
pSelText=pSelText.replace(/ +/g," ");
pSelText=pSelText.replace(/^\s+|\s+$/gm,"");
if (pArgLine.indexOf('deepl') > -1) {
pSelText=pSelText.replace(/[\x2f\x7c]/g,"");}
pSelText=encodeURIComponent(pSelText);
if (pSelText) {
pLink = WScript.Arguments(0).replace('$text',pSelText);
objShell = new ActiveXObject("WScript.Shell");
if (pLink.search('^(http:|https:|www.|ftp:|notes:)') == -1)
pLink = 'https://www.google.com/search?q=' + pLink;
objShell.Run('"'+pLink+'"');}
}


The script is purposed to pass a selected text to the default browser.
  • If there's a predefined URL, the selected text will be processed by the receiving service, e.g. Google Translate, DeepL, etc.
  • If a valid URL is recognized within the selected text at the beginning, it will be opened in the default browser as such.
  • If the selected text is just a text it will be passed as a search query to Google Search.
Basically, this is a customized version of the original InternetRequest.js script by VladSh.
The main difference between the two is the way they handle selected text that a. contains double quotes ["], b. contains multiple lines, c. is simply a text and cannot be recognized as a [part of] valid URI.
  • if the selected text contains double quotes ["]:
    - The original script drops off everything after the very first double quote it meets.
    + The customized script will replace double quotes ["] with single quotes ['] to pass the selected text as a whole.
  • if the selected text contains multiple lines:
    - The original script glues the lines together without any separation which makes it difficult to properly process it further by the receiving services (translators, search engines, etc).
    + The customized script will join the lines via blank space(s) to pass the selected text as a whole readable line.
  • if the selected text is just a text (and cannot be recognized as a [part of] valid URI):
    - The original script adds 'http:\\' prefix to the selected text and then your browser tries to process all that as a URL, which makes no sense and fails.
    + The customized script will wrap the selected text into a valid request, for instance, as a Google Search request for the selected text as a whole.
Changes in version 2024-09-14

  1. The selected text is now being preprocessed with the encodeURIComponent() function within the script itself that brings the following positive effects:
    • multi-line text is now being passed as such (with line breaks); the receiving service would now process that properly (including keeping the multi-line structure intact, both within the input and output*); separate preprocessing of the line breaks in the script is no longer required.
    • double quotes are being passed as such; the receiving service would now process that properly (keeping the double quotes intact); separate preprocessing of the double quotes in the script is no longer required.
  2. If the receiving service is DeepL, slash and pipe characters ("/", \x2f; "|", \x7c, respectively) have to be removed from the text since the service cannot digest them within the externally passed URI (the service would drop off everything starting from the first "/" on; and would hang on when meets "|").
Notes:
* For Google Translate it may look as though the line breaks are gone within the translated text section, however, if you copy-paste the text from there back to AkelPad, the line breaks would be kept in place.**
** This might somehow not always be the case. For instance, if the target language is Russian, the line breaks are actually gone.

Offline
Posts: 23
Joined: Sat Jul 05, 2008 11:30 am
Location: Odesa, Ukraine

Re: Scripts collection

Post by ewild »

Code: Select all

// https://akelpad.sourceforge.net/forum/viewtopic.php?t=240&p=36486#p36486
// version:     2024-09-15
// author:      ewild
// Description: URL download with wget into the Downloads folder
// Usage    (in URL menu): "URL download : wget" Call("Scripts::Main",1,"downloadWget.js","%u")

WshShell   =  new ActiveXObject("WScript.Shell");
$key       = 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders';
$name      = '{374DE290-123F-4565-9164-39C4925E467B}';
$downloads =  WshShell.RegRead($key+'\\'+$name);
$url       =  AkelPad.GetArgLine();
$a         =  AkelPad.GetAkelDir();
$bin       = $a+'\\..\\Get\\wget.exe'; // See: Note
$command   = '-S -N --no-if-modified-since --no-hsts -U=Mozilla --referer="'+$url+'" "'+$url+'" -P '+$downloads;
WshShell.Exec($bin+' '+$command);

// Note:
// Put there the actual path to the wget executable:
// - relative path to the AkepPad directory as in the script :: $bin = $a+'\\..\\Get\\wget.exe';
// - or literal path, something like                         :: $bin = 'd:\\Tools\\wget.exe';


The script uses wget.exe tool to download a URL into the Downloads folder.

Notes:
The script's intended use is from the URL menu.
The Downloads folder location is being retrieved from the Windows* registry.
A user has to put their actual path to the wget executable there in the script:
  • relative to the AkepPad directory like in the script :: $bin = $a + '\\..\\Get\\wget.exe';
  • or a literal one, something like :: $bin = 'd:\\Tools\\wget.exe'
The wget.exe command in the script is essentially, as follows:
wget.exe -S -N --no-if-modified-since --no-hsts -U=Mozilla --referer="$url" "$url" -P $downloads
This is pretty suitable for most user cases, but, of course, is not universal.
So feel free to modify it according to your specific needs, if any.

* This is a thing for more or less modern Windows.
Windows XP does not have a designated "Downloads" folder by default.
In such a case, a user might prefer to set a destination folder manually, for instance, putting a literal path for the $downloads variable, something of a kind:
  • $downloads = 'd:\\Path\\to\\My\\Custom\\Downloads\\Location\\';
  • $downloads = "%USERPROFILE%\\Downloads";
Post Reply