Scripts collection

Discuss and announce AkelPad plugins
Post Reply
  • Author
  • Message
Offline
Posts: 63
Joined: Sun Jun 24, 2007 4:03 pm
Contact:

Evaluate.js

Post by wisgest »

Типа встроенный калькулятор. Выделяем какое-нибудь выражение, например, "13.34678+36777.89/8", вызываем скрипт, получаем результат "4610.58303" (кстати, я его таким образом и получил), если результат нравится, нажимаем "OK" - результат в буфере обмена (не нравится - "Отмена"), теперь можем, например, заменить им первоначальное выражение.

Code: Select all

// Применяет к выделенному тексту JavaScript-функцию eval(),
// сообщает вычисленное значение и при подтверждении пользователя
// запоминает его в буфере обмена.
// (Математические функции и константы доступны без префикса "Math.";
// при сложных вычислениях, использующих операторы JavaScript,
// можно использовать функцию Trace(<значение>[, <подсказка>]),
// возвращающую и показывающую промежуточное значение <значение>,
// которое тоже можно запоминать в буфере обмена.)

var
  AkelPad = new ActiveXObject("AkelPad.document"),
  WshShell = new ActiveXObject("WScript.Shell"),
  Err;
var
  Title = WScript.ScriptName,
  SelText = AkelPad.getSelText();

if (SelText == "") {
  WshShell.Popup("Отсутствует выделенный текст.", 0, Title, 0 + 48);
  WScript.Quit();
}
try {
  with (Math) Trace(eval(SelText), "Вычисленное значение");
} catch(Err) {
  WshShell.Popup(Err.description, 0, Title, 0 + 16);
}

function Trace(Value, Prompt) {
  Prompt = (Prompt? (Prompt + ":\n\n"): "") + Value;
  if (WshShell.Popup(Prompt, 0, Title, 1 + 64) == 1)
    AkelPad.SetClipboardText(Value);
  return Value;
}

Примеры использования:
56 * 13 - результат 728;
sin(PI/2) - синус пи на два (результат 1);
res=0; for (i=1; i<=500; i++) res=res+i*i - сумма квадратов первых пятиста целых чисел (41791750);
x=34+56; Trace(x,"Промежуточное значение"); x+26 - сумма трех чисел (34, 56 и 26) с выводом промежуточного результата;
Trace(34+56)+26 - предыдущий пример в другой записи.

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

Копирование даты в буфер обмена

Post by VladSh »

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1346#p1346
// Description(1033): Spell check using Microsoft Word
// Description(1049): Проверка орфографии используя MS Word
// Version: 1.4 (2015.01.20)
// Author: VladSh
// Initial code: © Instructor

var pSelText;
var hMainWnd = AkelPad.GetMainWnd();
var nCursor = -1;

if (hMainWnd) {
   var pScriptName = WScript.ScriptName;
   
   pSelText = AkelPad.GetSelText();
   if (!pSelText) {
      nCursor = AkelPad.GetSelStart();
      pSelText = AkelPad.GetTextRange(0, -1);
   }
   
   if (pSelText.charCodeAt(0) != 0)
   {
      var Word = new ActiveXObject("Word.application");
      if (Word)
      {
         var oSpellDoc;
         var pMessage;
         var pTextIn;
         var pTextOut;
         
         Word.Visible = false;
         Word.Options.SuggestSpellingCorrections = true;
   
         if (oSpellDoc = Word.Documents.Add())
         {
            oSpellDoc.Content.Text = pSelText;
            Word.ActiveWindow.WindowState = 2;  //wdWindowStateMinimize
				if (parseInt(Word.Version) >= 15)
				{
					//MS Word 2013 and higher
					Word.Visible = false;
					var oSys = AkelPad.SystemFunction();
					oSys.Call("user32::SetForegroundWindow", oSpellDoc.ActiveWindow.Hwnd);
				}
				
            pTextIn = oSpellDoc.Content.Text;
            if (Word.Options.CheckGrammarWithSpelling == true)
               oSpellDoc.CheckGrammar();
            else
               oSpellDoc.CheckSpelling();
            pTextOut = oSpellDoc.Content.Text;

            oSpellDoc.Close(false);

            if (pTextIn != pTextOut)
            {
               if (AkelPad.MessageBox(hMainWnd, GetLangString(3), pScriptName, 36 /*MB_ICONQUESTION|MB_YESNO*/) == 6 /*IDYES*/)
               {
                  if (nCursor != -1) AkelPad.SetSel(0, -1);
                  AkelPad.ReplaceSel(pTextOut.substr(0, pTextOut.length - 1), -2);
               }
            }
         }
	      Word.Quit(true);
	      Word = 0;
      }
      else
      {
         AkelPad.MessageBox(hMainWnd, GetLangString(0), pScriptName, 48 /*MB_ICONEXCLAMATION*/);
      }
   }
   else
   {
      AkelPad.MessageBox(hMainWnd, GetLangString(1), pScriptName, 64 /*MB_ICONINFORMATION*/);
   }
}

function GetLangString(nStringID)
{
   var nLangID = AkelPad.GetLangId(1 /*LANGID_PRIMARY*/);
   
   if (nLangID == 0x19)		//LANG_RUSSIAN
   {
      if (nStringID == 0)
         return "Необходимо сначала установить Microsoft Word 97 или выше.";
      if (nStringID == 1)
         return "Текст отсутствует.";
      if (nStringID == 3)
         return "Вставить исправленый текст?";
   }
   else
   {
      if (nStringID == 0)
         return "You must first install Microsoft Word 97 or higher.";
      if (nStringID == 1)
         return "The text is absent.";
      if (nStringID == 3)
         return "Insert corrected text?";
   }
   return "";
}
Данный скрипт является модификацией скрипта SpellCheck.js из дистрибутива Scripts-плагина.
Last edited by VladSh on Tue Jan 20, 2015 9:53 pm, edited 15 times in total.

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

СКРИПТ ДЛЯ ВСТАВКИ ФАЙЛА

Post by VladSh »

Code: Select all

// Description(1033): Inserts the selected text file into the current file
// Description(1049): Вставка выбранного текстового файла в текущий
// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1357#p1357
// Version: 1.12 (2015.01.15)
// Author: VladSh
// 
// Usage:
// 	-"Вставить\Файл..." Call("Scripts::Main", 1, "InsertFileEx.js", `"%f"`)

var fileName = WScript.Arguments(0);

if (fileName == AkelPad.GetEditFile(0)) {
   //Диалог открытия файла
   if (! AkelPad.Include("CommonFunctions.js")) WScript.Quit();
   fileName = fileDialogDefault(true, fileName, getFileExt(fileName));
}

if (fileName) {
   //Считывание содержимого файла
   var fso = new ActiveXObject("Scripting.FileSystemObject");
   if (fso.FileExists(fileName)) {
      //Считывание содержимого файла
      var Content = AkelPad.ReadFile(fileName);

      //Запись содержимого в окно редактирования Akel'а
      AkelPad.ReplaceSel(Content, -2);
   }
}


Реализовал вставку файла по своей же просьбе (п.2)

NB: Для работы данного кода обязателен CommonFunctions.js.

Скрипт работает в т.ч. из меню последних файлов; его нужно вызывать с парамертом "%f"!


Updated: скрипт отредактирован с учётом пожеланий уважаемого wisgest'а по открытию файла на JavaScript и по вставке в юникоде, а также добавлена проверка на наличие файла...
Last edited by VladSh on Thu Jan 15, 2015 4:34 pm, edited 22 times in total.

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

Скрипт копирует в буфер обмена полный путь ли дирректорию

Post by VladSh »

Code: Select all

///Copy to clipboard file name full (%f) or file directory (%d)
///Копирование полного имени файла (%f) или папки (%d) в буфер обмена
// Version: 1.1 (2010.07.30)
// 
// Usage:
//   -"FileName Full" Call("Scripts::Main", 1, "FilePathCopyToCB.js", `"%f"`)
//   -"FileDir" Call("Scripts::Main", 1, "FilePathCopyToCB.js", `"%d"`)

if (WScript.Arguments.length)
   AkelPad.SetClipboardText(WScript.Arguments(0));

Code: Select all

///Copy to clipboard file name short (%f)
///Копирование только имени файла (%f) в буфер обмена
// Version: 1.1 (2010.07.30)
// -"Только имя" Call("Scripts::Main", 1, "FileNameCopyToCB.js", `"%f"`)

if (WScript.Arguments.length)
	AkelPad.SetClipboardText(GetFileName(WScript.Arguments(0)));


function GetFileName(pFile)
{
	return pFile.slice(pFile.lastIndexOf('\\') + 1);
}
Чтобы не держать этот скрипт можно запускать скрипт переименования RenameFileDialog.js, из окошка InputBox копировать существующее имя файла и отменять переименование; совсем как в FS..


N.B.: Не поддерживается; я сам стал использовать copyPath.js из-за большей настраиваемости.
Last edited by VladSh on Wed Jul 30, 2014 6:52 pm, edited 12 times in total.

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

Post by VladSh »

InsertDate.js Instructor'а, преобразовал в функцию, возвращающую дату в опред. формате:

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1211#p1211
// Description(1033): Working with time and date; return it in specified format. Script implemented as the library for using in other scripts.
// Description(1049): Библиотека функций для работы с датами; возвращает дату/время в определённом формате.
// Version: 2.1 (2011.07.20)
// Author: VladSh
// Initial code: © Instructor
// 
// Time:
// h			Hours with no leading zero for single-digit hours; 12-hour clock.
// hh			Hours with leading zero for single-digit hours; 12-hour clock.
// H			Hours with no leading zero for single-digit hours; 24-hour clock.
// HH			Hours with leading zero for single-digit hours; 24-hour clock.
// m			Minutes with no leading zero for single-digit minutes.
// mm		Minutes with leading zero for single-digit minutes.
// s			Seconds with no leading zero for single-digit seconds.
// ss			Seconds with leading zero for single-digit seconds.
// t			One character time-marker string, such as A or P.
// tt			Multicharacter time-marker string, such as AM or PM.
//
// Date:
// d			Day of month as digits with no leading zero for single-digit days.
// dd			Day of month as digits with leading zero for single-digit days.
// ddd		Day of week as a three-letter abbreviation.
// dddd		Day of week as its full name.
// M			Month as digits with no leading zero for single-digit months.
// MM		Month as digits with leading zero for single-digit months.
// MMM		Month as a three-letter abbreviation.
// MMMM	Month as its full name.
// y			Year as last two digits, but with no leading zero for years less than 10.
// yy			Year as last two digits, but with leading zero for years less than 10.
// yyyy		Year represented by full four digits.
//
// Example:
// "H:mm:ss dd MMMM yyyy" -> "12:50:24 07 January 2008"

function DateFormat(pFormat) {
	if (AkelPad.GetMainWnd()) {
		if (!pFormat)
			pFormat = AkelPad.GetArgLine() || "dd.MM.yyyy HH:mm";		//default value
		return TimeFormat(pFormat);
	}
}

function TimeFormat(pFormat) {
	var _TCHAR;
	var _TSTR;
	var _TSIZE;

	if (AkelPad.IsOldWindows()) {
		_TCHAR = "A";
		_TSTR = 0		/*DT_ANSI*/;
		_TSIZE = 1	/*sizeof(char)*/;
	}
	else {
		_TCHAR = "W";
		_TSTR = 1		/*DT_UNICODE*/;
		_TSIZE = 2	/*sizeof(wchar_t)*/;
	}

	var lpFormatBuffer;
	var lpTimeBuffer;
	var pTime = "";

	if (lpFormatBuffer = AkelPad.MemAlloc(256 * _TSIZE)) {
		AkelPad.MemCopy(lpFormatBuffer, pFormat.substr(0, 255), _TSTR);

		if (lpTimeBuffer = AkelPad.MemAlloc(256 * _TSIZE)) {
			var oSys = AkelPad.SystemFunction();
			
			oSys.AddParameter(1024);	//LOCALE_USER_DEFAULT
			oSys.AddParameter(0);
			oSys.AddParameter(0);
			oSys.AddParameter(lpFormatBuffer);
			oSys.AddParameter(lpTimeBuffer);
			oSys.AddParameter(256);
			oSys.Call("kernel32::GetTimeFormat" + _TCHAR);

			oSys.AddParameter(1024);	//LOCALE_USER_DEFAULT
			oSys.AddParameter(0);
			oSys.AddParameter(0);
			oSys.AddParameter(lpTimeBuffer);
			oSys.AddParameter(lpFormatBuffer);
			oSys.AddParameter(256);
			oSys.Call("kernel32::GetDateFormat" + _TCHAR);

			pTime = AkelPad.MemRead(lpFormatBuffer, _TSTR);

			AkelPad.MemFree(lpTimeBuffer);
		}
		AkelPad.MemFree(lpFormatBuffer);
	}
	return pTime;
}



Примеры использования:
  • вставка в окно редактирования:

    Code: Select all

    // http://akelpad.sourceforge.net/forum/viewtopic.php?p=1387#p1387
    // Description(1033): Insert DateTime in specified format
    // Description(1049): Вставка даты-времени в определённом в аргументах формате
    // Version: 1.3 (2011.07.20)
    // Author: VladSh
    
    if (! AkelPad.Include("DateFormat.js")) WScript.Quit();
    
    AkelPad.ReplaceSel(DateFormat(""));
    Внешние вызовы из ContextMenu:

    Code: Select all

    "Insert"
    {
      ;...
      -"Date" Call("Scripts::Main", 1, "DateInsert.js", `"dd.MM.yyyy"`, 0)
      -"Date Turn" Call("Scripts::Main", 1, "DateInsert.js", `"yyyy.MM.dd"`, 0)
      -"Date-Time Turn" Call("Scripts::Main", 1, "DateInsert.js", `"yyyy.MM.dd HH:mm:ss"`, 0)
    }
  • копирование в буфер обмена:

    Code: Select all

    // http://akelpad.sourceforge.net/forum/viewtopic.php?p=1387#p1387
    // Description(1033): Copy to clipboard DateTime in specified format
    // Description(1049): Копирование в буфер обмена даты-времени в определённом в аргументах формате
    // Version: 1.3 (2011.07.20)
    // Author: VladSh
    
    if (! AkelPad.Include("DateFormat.js")) WScript.Quit();
    
    AkelPad.SetClipboardText(DateFormat(""));
    Внешние вызовы из ContextMenu:

    Code: Select all

    "Copy to Clipboard"
    {
      ;...
      -"Date" Call("Scripts::Main", 1, "DateCopyToCB.js", `""`)
      -"Date Turn" Call("Scripts::Main", 1, "DateCopyToCB.js", `"yyyyMMdd"`)
      -"Date Turn (.)" Call("Scripts::Main", 1, "DateCopyToCB.js", `"yyyy.MM.dd"`)
      -"Date Turn Full" Call("Scripts::Main", 1, "DateCopyToCB.js", `"yyyyMMdd_HHmmss"`)
    }
Last edited by VladSh on Thu May 07, 2015 8:58 pm, edited 23 times in total.

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

?????????????????? -> normal text

Post by VladSh »

Иногда текст, вставляемый из буфера обмена, имеет нечитаемый вид, типа того: ?????? ????????? ????????????????
Такое встречается при копировании текста из старых (часто - из DOS'овских) доков или прог.

Для этого написал такой скриптик. Алгоритм прост до безобразия: создаётся новая вкладка, вставляется текст из буфера обмена, выделяется всё и копируется обратно в буфер обмена, вкладка закрывается. Если вставить текст из буфера снова, то он будет в нормальной, читаемой кодировке.

Чуть переделал скрипт на исправление текста в виде "умляутов", подробнее см. комменты в скрипте.

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1413#p1413
// Description(1033): Correction of Cyrillic characters of Clipboard
// Description(1049): Корректировка кириллических символов буфера обмена
// Version: 2.3 (2015.07.14)
// Author: VladSh

//Создание (закладки) нового файла
AkelPad.SendMessage(AkelPad.GetMainWnd(), 273 /*WM_COMMAND*/, 4101 /*wParam=MAKEWAPARAM(0,IDM_FILE_NEW)*/, 1 /*lParam=TRUE*/);

//это работало при вставке текста в виде вопросиков; добавил следующую строку, когда попадётся такая строка, то надо проверить, работает ли это при ней, и если нет, тогда думать, как заставить скрипт работать в 2-х вариантах
//AkelPad.ReplaceSel(AkelPad.GetClipboardText());

//корректировка текста в виде "умляутов" (такой текст гораздо чаще бывает); см. http://akelpad.sourceforge.net/forum/viewtopic.php?p=1306#p1306
AkelPad.Command(4191);

AkelPad.SetSel(0, -2);

AkelPad.SetClipboardText(AkelPad.GetSelText());

AkelPad.SendMessage(AkelPad.GetMainWnd(), 1229 /*AKD_SETMODIFY*/, 0, false);		//помечаем как неизменявшийся, чтобы не спрашивало, сохранить или нет
AkelPad.Command(4318);		//закрываем текущую вкладку
Last edited by VladSh on Tue Jul 14, 2015 6:03 pm, edited 19 times in total.

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

Ещё несколько скриптов

Post by VladSh »

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1420#p1420
// Description(1033): Convert selected lines to predefine structure
// Description(1049): Преобразовывает выделенный текст в блок определённой стрктуры
// Version: 5.4 (2016.01.09)
// Author: VladSh
// 
// Arguments:
//    -shift - lines shift to the right:
//        without this parameter - shift from program settings;
//        "" / "\t" or other value
//    -delEmptyLines:
//        without this parameter or 0 - won't delete empty lines;
//        1 - will delete empty lines;
//        [2] - will delete lines which contains tabs or/and spaces
//    -rootOpen, -rootClose, -lineOpen, -lineClose - see Usage section
// 
// Usage:
//     HTML (ul, ol, dt):
// -"<ul>...</ul>" Call("Scripts::Main", 1, "insertStructure.js", `-rootOpen="<ul>" -lineOpen="<li>" -lineClose="</li>" -rootClose="</ul>"`)
//     fb2 (stanza);
//     BbCode (list):
// -"[list]...[/list]" Call("Scripts::Main", 1, "insertStructure.js", `-rootOpen="[list]" -lineOpen="[*]" -rootClose="[/list]" -shift=""`)

if (AkelPad.IsAkelEdit()) {
	if (WScript.Arguments.length == 0) WScript.Quit();
	
	if (! AkelPad.Include("selCompleteLine.js")) WScript.Quit();
	
	oCh.runWithRedraw();
}

function process() {
	var rootOpen = AkelPad.GetArgValue("rootOpen", "");
	var lineOpen = AkelPad.GetArgValue("lineOpen", "");
	var lineClose = AkelPad.GetArgValue("lineClose", "");
	var rootClose = AkelPad.GetArgValue("rootClose", "");
	
	if (AkelPad.GetArgLine().indexOf("-shift") != -1) {
		sShift = escSequencesProcessing(AkelPad.GetArgValue("shift", ""));
	}
	else
		getShift();
	lineOpen = sShift + lineOpen;
	
	oCh.setCompleteLineText();
	
	var pBreak = (AkelPad.GetEditNewLine(0) != 2) ? "\r" : "\n";
	
	var lines = oCh.Text;
	
	var delEmptyLines = AkelPad.GetArgValue("delEmptyLines", 2);
	
	//убираем хвостовые пробелы и табуляции
	lines = lines.replace(/(\S)([ \t])+$/gm, "$1");
	
	if (delEmptyLines > 0) {
		if (delEmptyLines == 2) {
			//удаляем строки, состоящие только из табуляций и/или пробелов
			lines = lines.replace(/^[ \t]*$/gm, "");
		}
		//убираем пустые строки (2 и более переводов строк)
		lines = lines.replace(/\r{2,}/g, pBreak);
		lines = oStr.trim(lines, pBreak);		//убираем переводы строк по краям
	}
	
	var spaces = lines.match(/^[ \t]*/)[0];
	if (rootOpen) rootOpen = spaces + rootOpen + pBreak;
	if (rootClose) rootClose = pBreak + spaces + rootClose;
	
	if (lineOpen || lineClose) {
		lines = lines.replace(/^([ \t]*)/gm, "$1" + lineOpen);   //открывающий тэг
		lines = lines.replace(/([ \t]*$)/gm, "$1" + lineClose);  //закрывающий тэг
	}
	
	oCh.Text = rootOpen + lines + rootClose;
}
Благодарности: Infocatcher, FeyFre, Cuprum, opk44, yozhic, YuS


NB: This script used selCompleteLine.js.
Last edited by VladSh on Sat Jan 09, 2016 10:07 am, edited 36 times in total.

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

Post by VladSh »

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1505#p1505
// Description(1033): Creation of a new file on the basis of the contained allocated file in the list of the fresh
// Description(1049): Универсальное создание нового файла на основе имеющегося в окне редактирования или в списке свежих
// Version: 2.10 (2015.07.14)
// Author: VladSh
// 
// Usage:
// 	-"Новый на основе выбранного" Call("Scripts::Main", 1, "NewFilebyRecent.js", `"%f"`)  Icon("%a\AkelFiles\Plugs\ToolBar.dll", 1) - из меню свежих файлов (параметр `"%f"` обязателен!)
// 	-"Новый на основе текущего" Call("Scripts::Main", 1, "NewFilebyRecent.js")  Icon("%a\AkelFiles\Plugs\ToolBar.dll", 1) - меню вкладок, окна редактирования или тулбара

var fileName = "";
var ext = "";
var fso = new ActiveXObject("Scripting.FileSystemObject");
var pContent = "";

if (WScript.Arguments.length) {
	if (WScript.Arguments(0) != AkelPad.GetEditFile(0))
		fileName = WScript.Arguments(0);			//стартовали из меню списка свежих!
}

if (fileName) {
	//Создание на основе выделенного в списке свежих
	if (fso.FileExists(fileName)) {
		//Считывание содержимого файла
		pContent = AkelPad.ReadFile(fileName)
	}
	ext = fso.GetExtensionName(fileName);
}
else {
	//Стартовали из меню вкладок или окна редактирования
	//Пытаемся сначала взять выделенный текст и на основе его создать док, иначе создаём на основе всего текста файла текущей вкладки
	pContent = AkelPad.GetSelText() || AkelPad.GetTextRange(0, -1);
}

if (AkelPad.Include("CommonFunctions.js"))
	createFile(getFileFormat(0), ext);		//создаём со всеми параметрами исходного файла
else {
	AkelPad.SendMessage(AkelPad.GetMainWnd(), 273 /*WM_COMMAND*/, 4101 /*wParam=MAKEWAPARAM(0,IDM_FILE_NEW)*/, 1 /*lParam=TRUE*/);
}

//Запись содержимого в окно редактирования Akel'а
AkelPad.ReplaceSel(pContent);

//Установка курсора в начало нового файла
AkelPad.SetSel(0, 0);
This script used CommonFunctions.js.
Last edited by VladSh on Tue Jul 14, 2015 6:08 pm, edited 27 times in total.

Offline
Posts: 21
Joined: Sun May 06, 2007 10:14 am

Post by Idjo »

ShiftRight.js & ShiftLeft.js
Shifts selected rows.
The shift string can be defined, and if you define it as "//" it can be used to turn rows into comments.
JS is preety new for me so I'd like to have comments.

Update: Fixed by Instructor's suggestion.

Code: Select all

var sShift="  ";	//Shift definition (\t for tab)

//var AkelPad=new ActiveXObject("AkelPad.document");

var nSelStart=AkelPad.GetSelStart();
var nSelEnd=  AkelPad.GetSelEnd();
var sSelText= AkelPad.GetSelText();


//Find row start
var hEditWnd=AkelPad.GetEditWnd();
var nMinLine=AkelPad.SendMessage(hEditWnd, 1078 /*EM_EXLINEFROMCHAR*/, 0, nSelStart);
var nMinLineIndex=AkelPad.SendMessage(hEditWnd, 187 /*EM_LINEINDEX*/, nMinLine, 0);
AkelPad.SetSel(nMinLineIndex,nSelEnd);


//First row's shifting
var sContent=AkelPad.GetSelText();
var sNewContent=sShift;
nSelStart+=sShift.length;


//Other rows' shifting
while (sContent.length > 1)
{
  if (sContent.charAt(0)=="\r")
    sNewContent+="\r"+sShift;
  else
    sNewContent+=sContent.charAt(0);
  sContent=sContent.slice(1);
}
sNewContent+=sContent.charAt(0);

AkelPad.ReplaceSel(sNewContent);
AkelPad.SetSel(nSelStart,AkelPad.GetSelEnd());


Code: Select all

var sShift="  ";	//Shift definition (\t for tab)

//var AkelPad=new ActiveXObject("AkelPad.document");

var nSelStart=AkelPad.GetSelStart();
var nSelEnd=  AkelPad.GetSelEnd();
var sSelText= AkelPad.GetSelText();


//Find row start
var hEditWnd=AkelPad.GetEditWnd();
var nMinLine=AkelPad.SendMessage(hEditWnd, 1078 /*EM_EXLINEFROMCHAR*/, 0, nSelStart);
var nMinLineIndex=AkelPad.SendMessage(hEditWnd, 187 /*EM_LINEINDEX*/, nMinLine, 0);
AkelPad.SetSel(nMinLineIndex,nSelEnd);


//First row's shifting
var sContent=AkelPad.GetSelText();
var sNewContent="";
if (sContent.slice(0,sShift.length)==sShift)
{
  sContent=sContent.slice(sShift.length);
  nSelStart=Math.max(nSelStart-sShift.length,nMinLineIndex);
}


//Other rows' shifting
while (sContent.length > 0)
{
  if (sContent.slice(0,1+sShift.length)=="\r"+sShift)
  {
    sNewContent+="\r";
    sContent=sContent.slice(1+sShift.length);
  }
  else
  {
    sNewContent+=sContent.charAt(0);
    sContent=sContent.slice(1);
  }
}


AkelPad.ReplaceSel(sNewContent);
AkelPad.SetSel(nSelStart,AkelPad.GetSelEnd());
Last edited by Idjo on Sun Aug 05, 2007 10:41 pm, edited 2 times in total.

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

CommonFunctions

Post by VladSh »

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1582#p1582
// Description(1033): Works with for WinFS. Script implemented as the library for using in other scripts.
// Description(1049): Библиотека функций для работы с диалогами, файловой системой и т.п.
// Version: 2.19 (2015.10.08)
// Author: VladSh

//Default variables
var pSlash = "\\";
var pExtTXT = "txt";
var pDefaultExt;			//можно задать извне, это будет приоритетнее, т.е. не заменится при вызове функции

//FUNCTIONS

//определение расширения по умолчанию
function getDefaultExt() {
	if (!pDefaultExt) {
		var lParam;
		if (lParam = AkelPad.MemAlloc(256)) {
			AkelPad.SendMessage(AkelPad.GetMainWnd(), 1222 /*AKD_GETMAININFO*/, 224 /*MI_DEFAULTSAVEEXT*/, lParam);
			pDefaultExt = AkelPad.MemRead(lParam, 1 /*DT_UNICODE*/);
			AkelPad.MemFree(lParam);
		}
	}
	return pDefaultExt || pExtTXT;
}

//Вызов диалога Открытия/Сохранения файла (WinAPI) с предварительной обработкой и инициализацией всех необходимых параметров
function fileDialogDefault(bOpenTrueSaveFalse, pInitialDir, pInitialFile, pInitialExt) {
	if (pInitialDir == "\\") pInitialDir = "";
	pInitialFile = getFileName(pInitialFile);
	
	//<определение фильтров>
	var nFilterIndex = 0;		//номер по порядку (не индекс!) для arrFilterLines; по умолчанию считаем, что расширение пока не найдено..
	var arrFilters;
	var arrFilterLines = [];
	var arrFTypeInfo;
	var arrExts = [];
	arrFilters = getFileContent(AkelPad.GetAkelDir(5) + "\\Params\\" + "FileDialogExtentions.ini", false, -1, /\r\n|\n|\r/);
	if (arrFilters) {
		for (var i = 0, l = arrFilters.length; i < l; i++) {
			arrFTypeInfo = arrFilters[i].split("=");
			arrExts[i] = arrFTypeInfo[1];
			arrFilters[i] = getFilter(arrFTypeInfo[0], arrFTypeInfo[1]);
		   if ((";" + arrFTypeInfo[1] + ";").split(";" + pInitialExt + ";").length == 2) {
		   	//нашли точное совпадение расширения
		   	nFilterIndex = i + 1;
		   }
		}
		//полный список
		arrFilterLines = arrFilters;
	}
	else {
		//если файл со списком типов не существует или пуст
		arrExts[0] = "*";
		arrExts[1] = pExtTXT;
		arrFilterLines[0] = getFilter("All Files",        arrExts[0]);
		arrFilterLines[1] = getFilter("Plain Text files", arrExts[1]);
		if (pInitialExt == pExtTXT) nFilterIndex = 2;
	}
	if (nFilterIndex == 0) {
		//если это расширение отсутствует в списке, значит вручную добавляем его как неустановленное..
		if (pInitialExt) {
			arrExts[arrExts.length] = pInitialExt;
			arrFilterLines[arrFilterLines.length] = getFilter("Unspecified file type", pInitialExt);
			nFilterIndex = arrFilterLines.length + 1;
		}
		else
			pInitialExt = getDefaultExt();	//для того, чтобы при неопределении расширения файла он не сохранился без расширения
	}
	var pFilter = arrFilterLines.join("");
	//</определение фильтров>
	
//	if (!bOpenTrueSaveFalse)
//		pInitialFile = pInitialFile || "filename";
	
	var result = fileDialog(bOpenTrueSaveFalse, AkelPad.GetMainWnd(), pInitialDir, pInitialFile, pInitialExt, pFilter, nFilterIndex);
	if (!bOpenTrueSaveFalse) {
		if (result.file && result.filterIndex != null) {
			arrFTypeInfo = arrExts[result.filterIndex].split(";");
			sExtTmp = arrFTypeInfo[0];
			if (sExtTmp != "*") {
				result.file = separateFile(result.file);
				//если расширение в ComboBox'е с расширениями не было изменено 
				if (sExtTmp == pInitialExt) {
					//пробуем взять его из имени файла (возможно вписали туда вручную)
					sExtTmp = result.file.ext;
				}
				return result.file.path + result.file.name + "." + sExtTmp;
			}
		}
	}
	return result.file;
}

//Сборка фильтра
function getFilter(sFTypeInfo, sExts /* расширения ч/з ";" */) {
	var sMask = "*." + (sExts).replace(/;/g, ";*.");		//маска для всех расширений этого типа, без пробелов
	return sFTypeInfo + " (" + sMask.replace(/;/g, "; ") + ")\0" + sMask + "\0";		//фильтр в полном виде
}

//Стандартный диалог Открытия/Сохранения файла (WinAPI)
function fileDialog(bOpenTrueSaveFalse, hWnd, pInitialDir, pInitialFile, pInitialExt, pFilter, nFilterIndex) {
	var nFlags = 0x880804; //OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_EXPLORER|OFN_ENABLESIZING
	var lpStructure;
	var lpFilterBuffer;
	var lpFileBuffer;
	var lpExtBuffer;
	var lpDirBuffer;
	var oSys;
	var pResultFile = "";
	var nCallResult;
	
	var lFilterBuffer = pFilter.length;		//передаём не 256, а реальный размер pFilter
	if (lpFilterBuffer = AkelPad.MemAlloc((lFilterBuffer+1) * _TSIZE)) {
		AkelPad.MemCopy(lpFilterBuffer, pFilter.substr(0, lFilterBuffer), _TSTR);

		if (lpFileBuffer = AkelPad.MemAlloc(256 * _TSIZE)) {
			AkelPad.MemCopy(lpFileBuffer, pInitialFile.substr(0, 255), _TSTR);

			if (lpExtBuffer = AkelPad.MemAlloc(256 * _TSIZE)) {
				AkelPad.MemCopy(lpExtBuffer, pInitialExt.substr(0, 255), _TSTR);
				
				if (lpDirBuffer = AkelPad.MemAlloc(256 * _TSIZE)) { 
					AkelPad.MemCopy(lpDirBuffer, pInitialDir.substr(0, 255), _TSTR);
					
					if (lpStructure = AkelPad.MemAlloc(_X64?136:76)) {
						//Fill structure
						AkelPad.MemCopy(lpStructure, _X64?136:76, 3 /*DT_DWORD*/);										 //lStructSize
						AkelPad.MemCopy(lpStructure + (_X64?8:4), hWnd, 2 /*DT_QWORD*/);							 //hwndOwner
						AkelPad.MemCopy(lpStructure + (_X64?24:12), lpFilterBuffer, 2 /*DT_QWORD*/);	 //lpstrFilter
						AkelPad.MemCopy(lpStructure + (_X64?44:24), nFilterIndex, 3 /*DT_DWORD*/);		 //nFilterIndex
						nFilterIndex = -1;
						AkelPad.MemCopy(lpStructure + (_X64?48:28), lpFileBuffer, 2 /*DT_QWORD*/);		 //lpstrFile
						AkelPad.MemCopy(lpStructure + (_X64?56:32), 256, 3 /*DT_DWORD*/);							//nMaxFile
						AkelPad.MemCopy(lpStructure + (_X64?68:44), lpDirBuffer, 2 /*DT_QWORD*/);       //lpstrInitialDir
						AkelPad.MemCopy(lpStructure + (_X64?96:52), nFlags, 3 /*DT_DWORD*/);					 //Flags
						AkelPad.MemCopy(lpStructure + (_X64?104:60), lpExtBuffer, 2 /*DT_QWORD*/);		 //lpstrDefExt
						
						if (oSys = AkelPad.SystemFunction()) {
							//Call dialog
							if (bOpenTrueSaveFalse == true)
								nCallResult = oSys.Call("comdlg32::GetOpenFileName" + _TCHAR, lpStructure);
							else
								nCallResult = oSys.Call("comdlg32::GetSaveFileName" + _TCHAR, lpStructure);
	
							//Result file
							if (nCallResult) {
								pResultFile = AkelPad.MemRead(lpFileBuffer, _TSTR);
								nFilterIndex = AkelPad.MemRead(lpStructure + (_X64?44:24), 3 /*DT_DWORD*/) - 1;
							}
						}
						AkelPad.MemFree(lpStructure);
					}
					AkelPad.MemFree(lpDirBuffer);
				}
				AkelPad.MemFree(lpExtBuffer);
			}
			AkelPad.MemFree(lpFileBuffer);
		}
		AkelPad.MemFree(lpFilterBuffer);
	}
	return {
		file: pResultFile,
		filterIndex: nFilterIndex
	};
}

// Определение основных характеристик формата файла
function getFileFormat(hWnd /*hWndEdit*/) {
	return {
		cp: AkelPad.GetEditCodePage(hWnd),	// CodePage
		BOM: AkelPad.GetEditBOM(hWnd),
		nl: AkelPad.GetEditNewLine(hWnd)		// NewLine
	};
}

///Создание вкладки нового файла с передаваемыми параметрами
function createFile(fileFormat /*объект, полученный ранее с помощью getFileFormat*/,
                    pExt       /*расширение, для установки подстветки; если "", будет пытаться определить автоматически*/) {
	// пытаемся определить расширение для установки нужной подсветки
	var bCoderInclude = AkelPad.Include("CoderFunctions.js");
	if (!pExt && bCoderInclude)
		pExt = GetSyntaxAliasExtension();
	createNew();		//создание (закладки) для сохранения текста отдельным файлом
	AkelPad.SaveFile(0, "", fileFormat.cp, fileFormat.BOM);		//выставление кодировки
	AkelPad.SendMessage(AkelPad.GetMainWnd(), 1230 /*AKD_SETNEWLINE*/, 0, fileFormat.nl);		//выставление "формата новой строки"
	// пытаемся выставить нужную подсветку
	if (pExt && bCoderInclude) SetSyntax(pExt);
}

//Создание вкладки нового файла с отключением появления диалога Templates-плагина
function createNew() {
	AkelPad.SendMessage(AkelPad.GetMainWnd(), 273 /*WM_COMMAND*/, 4101 /*wParam=MAKEWAPARAM(0,IDM_FILE_NEW)*/, 1 /*lParam=TRUE*/);
}

//Закрытие файла и его вкладки
function closeFile() {
	AkelPad.Command(4324 /*IDM_WINDOW_FILECLOSE*/);
	AkelPad.Command(4318 /*IDM_WINDOW_FRAMECLOSE*/);
}

//Разбивает полный путь в массив [Папка, Имя_файла, Расширение]
function separateFile(pFile) {
	var pPath = "";
	var pFileName = "";
	var pFileExt = "";
	
	var pos = pFile.lastIndexOf(pSlash);
	if (pos != -1)
		pPath = pFile.slice(0, pos + 1);
	
	pFileName = pFile.slice(pos + 1);
	if (pFileName) {
		pos = pFileName.lastIndexOf(".");
		if (pos != -1)
		{
			pFileExt = pFileName.slice(pos + 1);
			pFileName = pFileName.slice(0, pos);
		}
	}
	
	return {
		path: pPath,
		name: pFileName,
		ext: pFileExt
	};
}

//Собирает полное имя файла из объекта, полученного с помощью separateFile()
function joinFile(oFile) {
	return oFile.path + oFile.name + "." + oFile.ext;
}

//Возвращает полное имя папки БЕЗ закрывающего \
function getParent(pFile) {
	var pDir = "";
	var pozLastSep = pFile.lastIndexOf(pSlash);
	if (pozLastSep != -1)
		pDir = pFile.slice(0, pozLastSep);
	return pDir;
}

//Возвращает полное имя папки С закрывающим \
function getParentClosed(pFile) {
	var pDir = getParent(pFile);
	if (pDir) pDir = pDir + pSlash;
	return pDir;
}

//Возвращает имя файла С расширением
function getFileName(pFile) {
	return pFile.slice(pFile.lastIndexOf(pSlash) + 1);
}

//Возвращает имя файла БЕЗ расширения
function getFileNameOnly(pFile) {
	var pFileName = getFileName(pFile);
	var pos = pFileName.lastIndexOf(".");
	if (pos != -1)
		pFileName = pFileName.slice(0, pos);
	return pFileName;
}

//Возвращает расширение файла
function getFileExt(pFile) {
	var ext = "";
	var pos = pFile.lastIndexOf(".");
	if (pos != -1) ext = pFile.substr(pos + 1);
	return ext;
}

function getEnvironmentPath(pPath) {
	var result = "";
	var WshShell = new ActiveXObject("WScript.shell");
	var path = WshShell.ExpandEnvironmentStrings(pPath);
	var fso = new ActiveXObject("Scripting.FileSystemObject");
	if (fso.FileExists(path)) result = path;
	return result;
}

//Remove inadmissible symbols (from wisgest)
function correctFileName(pFileNameOnly) {
	pFileNameOnly = pFileNameOnly.replace(/\t/g, " ");		//валим табуляции, т.к. диалог с ними иногда просто не отображается
	pFileNameOnly = pFileNameOnly.replace(/  /g, " ");		//убираем повторяющиеся пробелы
	return pFileNameOnly.replace(/[\\\/:\*\?"{}<>\|]/g, "");
}

function correctFileNameFull(pFile) {
	pFileNameOnly = getFileName(pFile);
	pFileNameOnly = correctFileName(pFileNameOnly);
	return getParent(pFile) + pSlash + pFileNameOnly;
}

//Получает содержимое файла из файловой системы; возвращает:
//если файла нет - undefined; если pSepRow не передан - возвращает содержимое в виде строки; если передан - возвращает массив, разбитый через pSepRow
//bCurrent = true - если переданный файл является текущим открытым, то его текст берётся сразу, если нет - из файловой системы с помощью FSO
//nSmb - количество возвращаемых символов; 0 или -1 - вернуть содержимое всего файла
function getFileContent(pFile, bCurrent, nBytesMax, pSepRow) {
	var result;
	if (nBytesMax == 0) {
		nBytesMax = -1;
	}
	if (bCurrent) {
		if (pFile == AkelPad.GetEditFile(0)) {
			result = AkelPad.GetTextRange(0, nBytesMax);
		}
	}
	if (!result) {
		var fso = new ActiveXObject("Scripting.FileSystemObject");
		if (fso.FileExists(pFile) == true) {
			result = AkelPad.ReadFile(pFile, 0xD, 0, 0, nBytesMax);
		}
	}
	if (result) {
		if (pSepRow.length != 0) {
			result = result.split(pSepRow);
		}
	}
	return result;
}

//by MSDN
function getDrivesList() {
	var e = new Enumerator(fso.Drives);
	var x;
	var i = 0;
	var disks = [];
	for (; !e.atEnd(); e.moveNext()) {
		x = e.item();
		if (x.DriveType == 3 && x.IsReady) {
			disks[i] = x.DriveLetter;
			i += 1;
		}
	}
	return disks;
}
Для вывода типов файлов в диалогах открытия/сохранения файла можно пользоваться файлом параметров, который должен находиться в ..\Scripts\Params\:

Code: Select all

All Files=*
Plain Text files=txt
AkelPad Coder files=coder
AkelPad Param=param
AkelPad SpellCheck files=spck
ASM files=asm;inc
Bash files=sh;csh;bsh
Basic files=bas;frm;cls
BbCode files=bbc
Config files [ini]=ini;inf;cfg
Config files [xml]=config
C files=c;inl;h
C# files=cs
C++ files=c;cpp;cxx;hpp;hxx;inl;h
CSS files=css
DOS/NT Batch files=bat;cmd
FictionBook files=fb2
Haskell files=hs;lhs
HE Java Script files=hejs
HE VB Script files=hevbs
HTML files=html;htm
Info files=log;nfo
IDL files=idl
Java files=java;jav
Java Script files=js
Lisp files=lsp;lisp
Lotus Script files=lss
Lotus @-formula files=l@
Lotus XML files=dxl
Menu files=mnu
Pascal files=pas;inc;def;dfm
Perl files=cgi;pl;pm;plx
PHP files=php;php3
PL/SQL files=sql
Python files=py;pyw
Resource Script files=rc;rc2
Ruby files=rb;rbw
T/SQL files=sql;tql
Visual Basic files=vb
Visual Basic Script files=vbs
Windows Registry files=reg
XML files=xml;xhtml
XSL files=xsl;xslt

Обязательное условие: первым должен идти "All Files", 2-м - txt.
Хоть размер фильтра теперь в скрипте и вычисляется, но я не советую мучать животное этим монструозным списком, лучше уж выбрать то, чем реально пользуешься.

Для наполнения этого списка (чтобы "всё было" :)) присылайте варианты в личку.


Common "lib" for used in other scripts.
Has edited it is a little, it is final on the basis of scripts Instructors - a convenient piece as it has appeared :) Now I use in many scripts thanks to what their size has considerably decreased.

Благодарности:
- wisgest'у за предложение по функции CorrectFileName;
- Instructor'у за InsertFile.js из диструбутива Scripts-плагина, на основе которого были написаны FileDialogDefault и FileDialog и за замечания;
- FeyFre за помощь по lpstrInitialDir.
Last edited by VladSh on Thu Oct 08, 2015 2:37 pm, edited 67 times in total.

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

My variant Rename file with dialog

Post by VladSh »

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1584#p1584
// Description(1033): Rename current editing file with dialog
// Description(1049): Переименование текущего файла
// Version: 2.11 (2015.10.22)
// Author: VladSh
// 
// Arguments:
// 	-ext ([1]/0) - отображает/не отображает в окошке расширение
// for -ext=1:
//		Если необходимо заменить имя файла с расширением, то необходимо в окошке дописать к имени файла новое расширение;
//		Если необходимо удалить расширение, то после имени файла достаточно поставить точку.
// 	
// Usage:
//		-"RenameFile..." Call("Scripts::Main", 1, "RenameFileDialog.js", `"-ext=0"`)		- меняет только имя файла

var hMainWnd = AkelPad.GetMainWnd();

var fileNameFull = AkelPad.GetEditFile(0);
if (fileNameFull)	{	//File already exist
	if (! AkelPad.Include("CommonFunctions.js")) WScript.Quit();
	
	var useExt = AkelPad.GetArgValue("ext", 1);
	
	var File = separateFile(fileNameFull);
	var extInfo = "";
	
	var fileSelect;
	if (useExt == true && File.ext)
		fileSelect = File.name + "." + File.ext;
	else {
		fileSelect = File.name;
		if (File.ext) extInfo = " for *." + File.ext;
	}
	
	var pScriptName = WScript.ScriptName;
	var Prompt = "New name" + extInfo + ":";
	var fileSelectNew = "";
	var fileNameNew = "";
	var fso;
	var fileExist;
	
	if (hMainWnd) {
		fso = new ActiveXObject("Scripting.FileSystemObject");
		
		do {
			fileSelectNew = AkelPad.InputBox(hMainWnd, pScriptName, Prompt, fileSelect);
			if (fileSelectNew) {
				fileSelectNew = correctFileName(fileSelectNew);			//Remove special symbols
				if (useExt == 1 || File.ext == "") {
					//играться с расширениями оставляем возможность только при useExt=1, чтобы при обычном переименовании не съедались точки в имени файла
					fileNameNew = fileSelectNew;
				}
				else {
					fileNameNew = fileSelectNew + "." + File.ext;
				}
				
				var fileNameFullNew = File.path + fileNameNew;
				
				if (fileSelectNew != "" & (fileNameFullNew != fileNameFull)) {
					fileExist = fso.FileExists(fileNameFullNew);
					if (fileExist == false)	{						//Check already newFileName existent
						var nSelStart = AkelPad.GetSelStart();
						var nSelEnd = AkelPad.GetSelEnd();
						var curFileFormat = getFileFormat(AkelPad.GetEditWnd());
						
						AkelPad.Command(4324);			//Close editing file
						
						if (AkelPad.GetEditFile(0) != fileNameFull) {		//Check noCANCEL click for changed document!
							var Err;
							//Rename file
							try {fso.MoveFile(fileNameFull, fileNameFullNew);}
							catch(e) {
								Err = e;
								fileNameFullNew = fileNameFull;
							}
							
							if (fso.FileExists(fileNameFullNew) == true) {
								//Open file
								AkelPad.OpenFile(fileNameFullNew, 0, curFileFormat.cp, curFileFormat.BOM);
								
								//Recovery selection
								AkelPad.SetSel(nSelStart, nSelEnd);
							}
							if (Err) {
								if (0x100000000 + Err.number == 0x800a0046)
									AkelPad.MessageBox(hMainWnd, "Insufficient rights, or file is locked by another application!", "AkelPad -> " + WScript.ScriptName, 48);
								else
									throw Err;
							}
						}
					}
					else {
						Prompt = "File '" + fileNameNew + "' already exist!  Input other filename" + extInfo + ":";
					}
				}
			}
			else {
				break;
			}
		}
		while (fileExist);
	}
}
else					//File is new - try new document save
	AkelPad.Command(4106)
Примеры использования:

В контекстном меню окна редактирования поставил новый вызов:

Code: Select all

-"Rename File..." Call("Scripts::Main", 1, "RenameFileDialog.js", `"-ext=0"`)
А в контекстном меню вкладок оставил старый:

Code: Select all

-"Rename File..." Call("Scripts::Main", 1, "RenameFileDialog.js")


Реализована логика, которую я собственно и хотел с самого начала.

N.B.: Для работы данного кода обязателен CommonFunctions.js.
Last edited by VladSh on Wed Oct 21, 2015 9:40 pm, edited 28 times in total.

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

FileOpenDialog

Post by VladSh »

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1585#p1585
// Description(1033): Opening a file with a choice of extensions from the list
// Description(1049): Открытие файла с возможностью выбора расширения из списка файла параметров
// Version: 4.0 (2015.04.29)
// Author: VladSh
// 
// Usage:
// 	-"Открыть..." Call("Scripts::Main", 1, "OpenEx.js")                                - открывает файл из последнего места открытия без установки фильтра по расширению  (обычный диалог открытия)
// 	-"Открыть из папки..." Call("Scripts::Main", 1, "OpenEx.js", `-dir="%d\"`)         - открывает из папки файла без установки фильтра по расширению
// 	-"Открыть по файлу..." Call("Scripts::Main", 1, "OpenEx.js", `-file="%f"`)         - открывает из папки файла; расширение для фильтра определяется по файлу
// 	-"Открыть [ini]..." Call("Scripts::Main", 1, "OpenEx.js", `-file="%f" -ext="ini"`) - открывает из папки файла с фильтром по указанному расширению

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

var pInitialFile = AkelPad.GetArgValue("file", "");
var pInitialDir = AkelPad.GetArgValue("dir", "") || getParentClosed(pInitialFile);
var pInitialExt = AkelPad.GetArgValue("ext", "") || getFileExt(pInitialFile);
pInitialFile = "";

pInitialFile = fileDialogDefault(true, pInitialDir, pInitialFile, pInitialExt);
if (pInitialFile) {
	//Проверка на существование файла с введенным в диалоге именем
	var fso = new ActiveXObject("Scripting.FileSystemObject");
	if (fso.FileExists(pInitialFile) == true)
		AkelPad.OpenFile(pInitialFile);
	else
		AkelPad.MessageBox(AkelPad.GetMainWnd(), "File '" + pInitialFile + "' not found.", "AkelPad", 64);
}
N.B.: Для работы данного кода обязателен CommonFunctions.js.

Моделирование своей кнопки тулбара "Открыть...":

Code: Select all

-"Открыть..." Call("Scripts::Main", 1, "OpenEx.js", `-dir="%d\"`) Menu("OPEN") Icon(2)
Вызываемое подменю:

Code: Select all

"OPEN"
{
  RECENTFILES
  SEPARATOR
 "Удалить несуществующие" Call("RecentFiles::DeleteNonExistent")
}
Last edited by VladSh on Fri Jun 19, 2015 6:46 pm, edited 25 times in total.

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

общий функционал для работы с выделением и текстом

Post by VladSh »

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1607#p1607
// Description(1033): Works with text. Script implemented as the library for using in other scripts.
// Description(1049): Библиотека функций для работы с текстом
// Version: 4.11 (2015.01.16)
// Author: VladSh

//GLOBAL VARIABLES
var pBreak = "\r";		//by default
var pTab = "\t";
var sShift;					//shift definition (\t for Tab or Spaces)
var sbOpen = "{";
var sbClose = "}";
var nEndLineOfFile = -1;		//индекс доступа к последней строке файла; (на -2 с наскока не удалось переделать, т.к. в correctRangebyBorders сложные условия)
var pContent = "";		//содержимое всего изменяемого файла; определяется и используется внутри данного скрипта, извне вручную не менять!


//"Класс"-объект модификации текста
var oCh =
{
	rBegin: [],					//Границы выделения при запуске скрипта - позиции символов в файле для начала и окончания выделения
	Text: "",						//Обработанная строка - результат работы скрипта
	rResult: [],				//Границы выделения изменяемого текста
	rCaret: [],					//Границы для установки выделения после работы скрипта
	
	saveSelRange: function()						//Запоминает границы выделения при запуске скрипта (вспомогательный Private-метод)
	{
		if (typeof(rBegin) == "undefined")
		{
			this.rBegin[0] = AkelPad.GetSelStart();
			this.rBegin[1] = AkelPad.GetSelEnd();
			this.rCaret = [this.rBegin[0], this.rBegin[0]];			//по умолчанию по окончании работы ставим каретку в начало выделения, которое в начале сделал пользователь
		}
	},
	
	getSelTextEmpty: function()				//Если текст не выделен, возвращает пустую строку
	{
		this.rResult = this.rBegin;
		
		if (this.rBegin[0] == this.rBegin[1])
			return "";
		else
			return getTextbyRange(this.rBegin);
	},
	
	getSelTextAll: function()						//Если текст не выделен, возвращает всё содержимое файла
	{
		if (this.rBegin[0] == this.rBegin[1])
		{
			this.rResult = getTextAll();
			return pContent;
		}
		else
		{
			this.rResult = this.rBegin;
			return getTextbyRange(this.rResult);
		}
	},
	
	getTextAll: function()						//Возвращает всё содержимое файла вне зависимости, выделено что-то или нет
	{
		this.rResult = getTextAll();
		return pContent;
	},
	
	setCompleteLineText: function()		//Работает автоматически по выделению
	{
		this.rResult = getRangeCompleteLine(this.rBegin[0], this.rBegin[1]);
		this.Text = getTextbyRange(this.rResult);
	},
	
	setCompleteLineRange: function(nPosStart, nPosEnd)			//Используется в сложних случаях, когда необходимо самому просчитать и передать границы
	{
		this.rResult = getRangeCompleteLine(nPosStart, nPosEnd);
		this.Text = getTextbyRange(this.rResult);
	},
	
	run: function()											//Основной метод запуска (без отключения прорисовки)
	{
		this.start();
		this.modify();
	},
	
	runWithRedraw: function()					//Основной метод запуска (с отключением прорисовки)
	{
		this.start();
		
		var hWndEdit = AkelPad.GetEditWnd();
		AutoRedrawOff(hWndEdit);
		this.modify();
		AutoRedrawOn(hWndEdit);
	},
	
	start: function()										//Вспомогательный "Private"-метод
	{
		this.saveSelRange();
		process();								//Определяется внутри вызывающего скрипта!
	},
	
	setSelCaret: function(nCaretStart, nCaretEnd)				//Установка параметров выделения; 2-й параметр необязателен
	{
		if (nCaretStart != null)												//Если в nCaretStart передан null - оставляем выделение в ReplaceSel (см. метод modify)
		{
			this.rCaret[0] = nCaretStart;
			this.rCaret[1] = nCaretEnd || nCaretStart;		//Если nCaretEnd не задан - устанавливаем курсор в позицию nCaretStart
		}
		else
			this.rCaret = null;
	},
	
	modify: function()									//Окончание работы скрипта: установка и замена выделения + установка курсора (вспомогательный Private-метод)
	{
		if (this.rResult != null)
		{
			AkelPad.SetSel(this.rResult[0], this.rResult[1]);
			var nSelect = (this.rCaret == null) ? -1 : 0;
			AkelPad.ReplaceSel(this.Text, nSelect);
			if (!nSelect)
				AkelPad.SetSel(this.rCaret[0], this.rCaret[1]);
		}
	},
	
	testSetSelResult: function()				//Тестирование установки выделения заменяемого текста
	{
		if (this.rResult != null)
			AkelPad.SetSel(this.rResult[0], this.rResult[1]);
		else
			AkelPad.MessageBox(AkelPad.GetEditWnd(), " this.rResult = null", "oCh.testSetSelResult() function", 0 /*MB_OK*/);
		AutoRedrawOn(AkelPad.GetEditWnd());		//если вдруг работу начинали с вызова runWithRedraw
		WScript.Quit();
	}
};

//FUNCTIONS

//Берёт текст чисто по указанным границам; вынесена, чтобы сделать "класс" более абстрактным
function getTextbyRange(Range)
{
	return AkelPad.GetTextRange(Range[0], Range[1]);
}

//Нужно для простых случаев, когда надо сразу выделить захваченые строки; иначе пользуемся алгоритмами с GetTextRange
function selCompleteLine(nCaretPosStart, nCaretPosEnd)
{
	var Range = getRangeCompleteLine(nCaretPosStart, nCaretPosEnd);
	AkelPad.SetSel(Range[0], Range[1]);
}

//Возвращает границы выделенных полных строк с учётом ограничивающих переводов строк; также поддерживаются значения -1 и -2.
function getRangeCompleteLine(nCaretPosStart, nCaretPosEnd)
{
	var hWndEdit = AkelPad.GetEditWnd();
	var Range = [];
	Range[0] = getOffset(hWndEdit, 18 /*AEGI_WRAPLINEBEGIN*/, nCaretPosStart);
	Range[1] = getOffset(hWndEdit, 19 /*AEGI_WRAPLINEEND*/, nCaretPosEnd);
	return Range;
	//return getRangebyBorders(nCaretPosStart, nCaretPosEnd, pBreak, pBreak, false);		//старая рабочая; закоментил на всякий случай, вдруг придётся открывать...
}

//Возвращает смещение объекта, определяемого nType (см. ScriptConsts.js в папке документации).
//by Instructor function: http://akelpad.sourceforge.net/forum/viewtopic.php?p=11382#p11382
function getOffset(hWndEdit, nType /*AEGI_*/, nOffset)
{
	var lpIndex;
	if (lpIndex = AkelPad.MemAlloc(_X64 ? 24 : 12 /*sizeof(AECHARINDEX)*/))
	{
		if (nOffset != -1)
			AkelPad.SendMessage(hWndEdit, 3137 /*AEM_RICHOFFSETTOINDEX*/, nOffset, lpIndex);
		
		AkelPad.SendMessage(hWndEdit, 3130 /*AEM_GETINDEX*/, nType, lpIndex);
		nOffset = AkelPad.SendMessage(hWndEdit, 3136 /*AEM_INDEXTORICHOFFSET*/, 0, lpIndex);
		AkelPad.MemFree(lpIndex);
	}
	return nOffset;
}

//Получает весь текст; при работе с "классом" перед её вызовом желателен вызов saveSelRange, чтобы запомнить границы выделения
function getTextAll()
{
	var rResult = [0, nEndLineOfFile];
	pContent = pContent || getTextbyRange(rResult);			//берём весь текст в бэкграунде в глобальную переменную
	if (pContent)
		return rResult;
}

//Простое определение границ по открывающему и закрывающему тэгу
function getRangebyBorders(nMinSel, nMaxSel, pBOpen, pBClose, bIncludeBorders)
{
	var Range = [];
	if (getTextAll())
	{
		Range[1] = pContent.indexOf(pBClose, nMaxSel);							//Ищем вниз
		Range[0] = pContent.lastIndexOf(pBOpen, nMinSel);					//Ищем вверх
		
		Range = correctRangebyBorders(nMinSel, pBOpen, pBClose, bIncludeBorders, Range);
	}
	return Range;
}

//Определение границ по открывающему и закрывающему тэгу с учётом возможности их вложенности
function getRangebyBordersEx(iCursor, pBOpen, pBClose, bIncludeBorders)
{
	var Range = [];
	var iStart;
	var cBOpen;
	var cBClose;
	if (!getTextAll())
		return null;
	
	var iBOpen = pContent.lastIndexOf(pBOpen, iCursor);					//ищем вверх индекс открывающего тэга
	var iBClose = pContent.lastIndexOf(pBClose, iCursor);					//ищем вверх индекс закрывающего тэга
	
	if (iBOpen < iBClose)		//если закрывающий тэг ниже открывающего, значит продолжаем искать открывающий тэг выше
	{
		do
		{
			iStart = iBOpen - 1;
			iBOpen = pContent.lastIndexOf(pBOpen, iStart);		//индекс открывающего тэга
			if (iBOpen == -1)
				return null;			//защита от зацикливания при передаче неправильных или несуществующих в файле тэгов
			
			cBOpen = substringCount(pContent, iBOpen, iCursor, pBOpen);		//количество открывающих тэгов
			cBClose = substringCount(pContent, iBOpen, iCursor, pBClose);		//количество закрывающих тэгов
		}
		while (cBOpen - 1 != cBClose);
		iBClose = iBOpen - 1;		//чтобы зайти в следующее условие (поиск последнего закрывающего тэга)
	}
	
	if (iBOpen > iBClose)		//если закрывающий тэг выше открывающего, значит ищем закрывающий тэг ниже курсора
	{
		iStart = iCursor;
		do
		{
			iBClose = pContent.indexOf(pBClose, iStart);		//индекс закрывающего тэга
			if (iBClose == -1)
				return null;			//защита от зацикливания при передаче неправильных или несуществующих в файле тэгов
			
			cBOpen = substringCount(pContent, iBOpen, iBClose, pBOpen);
			cBClose = substringCount(pContent, iBOpen, iBClose, pBClose);
			
			iStart = iBClose + 1;
		}
		while (cBOpen - 1 != cBClose);
	}
	
	Range[0] = iBOpen;
	Range[1] = iBClose;
	
	Range = correctRangebyBorders(iCursor, pBOpen, pBClose, bIncludeBorders, Range);
	
	return Range;
}

function correctRangebyBorders(nMinSel, pBOpen, pBClose, bIncludeBorders, Range)
{
	if ((Range[0] == -1 && pBOpen != pBreak) || (Range[1] == -1 && pBClose != pBreak))
		return null;
	else if (Range[0] == Range[1])			//Конец строки
	{
		if (Range[0] != 0)
			Range[0] = pContent.lastIndexOf(pBOpen, nMinSel - 1);		//Повторно ищем вверх
		else
			bIncludeBorders = null;
	}
	
	if (bIncludeBorders != null)
	{
		if (bIncludeBorders)
			Range[1] += (pBClose.length);
		else
			Range[0] += pBOpen.length;
	}
	return Range;
}

//Возвращает границы блока текста ограниченный разделителями
//поиск производится снизу вверх
//nMaxSel - позиция в файле, с которой будет начинаться поиск;
//	для внешнего цикла будет быстрее; по умолчанию передавать длину строки
function getRangebyBordersBack(pContent, pBOpen, pBClose, nMaxSel)
{
	var Range = [];
	var nMaxSelTmp = pContent.lastIndexOf(pBClose, nMaxSel);
	if ( !(nMaxSelTmp == -1 && pBClose == pBreak) )
		nMaxSel = nMaxSelTmp;
	if (nMaxSel != -1)
	{
		Range[1] = nMaxSel + pBClose.length;
		Range[0] = pContent.lastIndexOf(pBOpen, nMaxSel);
		var nMaxSel = Range[0];
		if (nMaxSel != -1)
			return Range;
	}
	return null;
}

//Возвращает границы строки, в которой находится искомое вхождение
//3-й элемент результирующего массива - nMaxSel для следующей итерации
function getTextLineRange(pContent, pText, nMaxSel)
{
	var Range = [];
	// находим вхождение строки
	nMaxSel = pContent.lastIndexOf(pText, nMaxSel);
	if (nMaxSel != -1)
	{
		// ищем её окончание
		Range[1] = pContent.indexOf(pBreak, nMaxSel);
		if (Range[1] == -1)
			Range[1] = pContent.length;
		// ищем её начало
		Range[0] = pContent.lastIndexOf(pBreak, nMaxSel);
		if (Range[0] == -1)
			Range[0] = 0;
		var nMaxSel = Range[0];
		return Range;
	}
	return null;
}

//Удаляет строку, в которой находится искомое вхождение;
//Возвращает массив:
//		- 1-й элемент - содержимое строки;
//		- 2-й - nMaxSel, т.е. точка отсчёта, откуда начинать поиск в следующей итерации
function removeTextLine(pContent, pText, nMaxSel)
{
	var iRange = getTextLineRange(pContent, pText, nMaxSel)
	if (iRange != null)
	{
		var sRange = splitbyBorders(pContent, iRange[0], iRange[1]);
		sRange[0] = sRange[0] + sRange[1];
		sRange[1] = iRange[0];
		return sRange;
	}
	return null;
}

//Удаляет все строки, в которых находится искомое вхождение
function removeTextLineAll(pContent, pTextRemove)
{
	var nMaxSel = pContent.length;
	do
	{
		var Range = removeTextLine(pContent, pTextRemove, nMaxSel);
		if (Range == null)
			return pContent;
		pContent = Range[0];
		nMaxSel = Range[1];
	}
	while (true);
}

//Разбивка строки: слева "пустые" символы начала строки, справа все остальные значащие
//by Infocatcher code
function separateRow(line)
{
	var sNull = line.match(/^\s*/)[0];
	return {
		left: sNull,			//начальные "пустые" символы текущей строки
		right: line.substr(sNull.length) 		//все символы текущей строки, идущие после "пустых"
    };
}

//Количество вхождений в определённом диапазоне
function substringCount(pContent, nStart, nEnd, pTextSearch)
{
	var pTextSource = pContent.substring(nStart, nEnd);
	return pTextSource.split(pTextSearch).length - 1;
}

//Разбивка строки в массив исключая участок, ограниченный номерами позиций;
//массив будет содержать 2 элемента
function splitbyBorders(pText, nStart, nEnd)
{
	var arrTmp = [];
	arrTmp[0] = pText.substring(0, nStart);
	arrTmp[1] = pText.substr(nEnd);
	return arrTmp;
}

//Замена участка, ограниченного номерами позиций, на подстроку;
//при nStart = nEnd будет, естественно, производиться вставка
function replacebyBorders(pText, nStart, nEnd, pTextIns)
{
	return splitbyBorders(pText, nStart, nEnd).join(pTextIns);
}


//STOP redraw window (by code of the Instructor)
function AutoRedrawOff(hWndEdit)
{
	AkelPad.SendMessage(hWndEdit, 11 /*WM_SETREDRAW*/, false, 0);
}

//START redraw window (by code of the Instructor)
function AutoRedrawOn(hWndEdit)
{
	AkelPad.SendMessage(hWndEdit, 11 /*WM_SETREDRAW*/, true, 0);
	var oFunction = AkelPad.SystemFunction();
	oFunction.Call("user32::InvalidateRect", hWndEdit, 0, true);
}


//Определение символа(-ов) сдвига из настроек
function getShift()
{
	if (sShift == undefined)
	{
		var bTabStopAsSpaces = AkelPad.SendMessage(AkelPad.GetMainWnd(), 1223 /*AKD_GETFRAMEINFO*/, 53 /*FI_TABSTOPASSPACES*/, 0);
		if (bTabStopAsSpaces)
		{
			var nTabStop = AkelPad.SendMessage(AkelPad.GetEditWnd(), 3239 /*AEM_GETTABSTOP*/, 0, 0);		//Number of Spaces in Tabs (take from the program settings)
			sShift = oStr.repeat(" ", nTabStop);
		}
		else
			sShift = pTab;
	}
	return sShift;
}

function shiftRightText(pText)
{
	getShift();
	return sShift + pText.replace(/\r/g, pBreak + sShift);
}


//"Класс"-объект расширенного функционала по работе со строками
var oStr =
{
	flags: "g",		//by default
	
	ltrim: function(pText, chars)
	{
		chars = chars || "\\s";
		return pText.replace(new RegExp("^[" + chars + "]+", this.flags), "");
	},
	
	rtrim: function(pText, chars)
	{
		chars = chars || "\\s";
		return pText.replace(new RegExp("[" + chars + "]+$", this.flags), "");
	},
	
	trim: function(pText, chars)
	{
		return this.ltrim(this.rtrim(pText, chars), chars);
	},
	
	left: function(pText, pSep)
	{
		var poz = pText.indexOf(pSep);
		if (poz > 0)
			return pText.slice(0, poz);
		else
			return "";
	},
	
	right: function(pText, pSep)
	{
		var poz = pText.indexOf(pSep);
		if (poz > 0)
			return pText.slice(poz + 1, pText.length);
		else
			return "";
	},
	
	leftback: function(pText, pSep)
	{
		var poz = pText.lastIndexOf(pSep);
		if (poz > 0)
			return pText.slice(0, poz);
		else
			return "";
	},
	
	rightback: function(pText, pSep)
	{
		var poz = pText.lastIndexOf(pSep);
		if (poz > 0)
			return pText.slice(poz + 1);
		else
			return "";
	},
	
	cleanbyBorders: function(pText, pBStart, pBEnd)
	{
		return replacebyBorders(pText, pBStart, pBEnd, "");
	},
	
	replacebyBorders: function(pText, pBStart, pBEnd, pNewText)
	{
		//При создании объекта RegExp в паттерне все слэши д.б. экранированы! Передавать тоже экранированные!
		return pText.replace(new RegExp(pBStart + "*?[\\s\\S]*?" + pBEnd, this.flags), pNewText);
	},
	
	repeat: function(pText, nCount)
	{
		return (new Array(nCount + 1)).join(pText);
	}
};

//Обработка Esc-последовательностей
function escSequencesProcessing(pText)
{
	if (pText)
	{
		pText = pText.replace(/\\\\/g, "\0");
	//	if (pText.search(/\\[^rnt]/g) != -1)
	//	{
			pText = pText.replace(/\\r\\n|\\r|\\n/g, "\r");
			pText = pText.replace(/\\t/g, pTab);
			pText = pText.replace(/\0/g, "\\");
	//	}
	}
	return pText;
}

// ------------------------------------------------------

// Functions for working with each row of selected text.
// Функции для организации обработки каждой строки текста
// 	(бывший ProcessRowText.js)
function processRowText(pSelText, pBreakLine, pJoinLine) {
	var arrOutput = [];											// output array of strings
	
	if (pSelText.length > 0) {
		var arrInput = pSelText.split(pBreakLine);		// input array of strings; универсальный "символ разрыва" для внутренних и внешних файлов: /\r\n|\n|\r/, но в виде "\r\n|\n|\r" в split это не работает
		var vResult;											// the result of processing row
		
		var index = -1;
		for (index = 0; index < arrInput.length; index++) {
			vResult = processString(arrInput[index]); // process each string
			addToResult(arrOutput, vResult);
		}
	}
	
	if (!pJoinLine)
		pJoinLine = pBreakLine;
	pSelText = arrOutput.join(pJoinLine);
	return pSelText;
}

// User-defined function; copy into your script, decomment and modify it

//function processString(s) {
//	var pResult;
//	//code modify the string s...
//	return pResult;
//}

//function addToResult(arrOutput, vResult) {
//	//condition and code added value in the resulting array
//	arrOutput[arrOutput.length] = vResult;		//by default return all values (with empty)
//}

Code: Select all

//Возвращает основную информацию о строке (отображаемой редактором) по переданной позиции в окне редактирования; поддерживаются значения -1 и -2 /оставлено для истории/
function getLineInfo(hWndEdit, nPos)
{
	if (!hWndEdit) hWndEdit = AkelPad.GetEditWnd();
	var nLine = AkelPad.SendMessage(hWndEdit, 1078 /*EM_EXLINEFROMCHAR*/, 0, nPos);
	var nLineIndex = AkelPad.SendMessage(hWndEdit, 187 /*EM_LINEINDEX*/, nLine, 0);
	var nLineLength = AkelPad.SendMessage(hWndEdit, 193 /*EM_LINELENGTH*/, nLineIndex, 0);
	
	return {
		number: nLine,
		start: nLineIndex,
		len: nLineLength
	};
}
Last edited by VladSh on Fri Jan 16, 2015 2:31 pm, edited 47 times in total.

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

Формирование, перенос и раскрытие символов блока {}

Post by VladSh »

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1608#p1608
// Description(1033): Formation, carrying over and disclosing of symbols of the block {}
// Description(1049): Проставка символов скрипт-блока {}
// Version: 4.0 (2020.01.06)
// Author: VladSh
//
// Arguments:
// 	-style:
// 		[0] - allman (old c-style)
// 		1 - java
// 
// A preferred combination of keys: Ctrl+Down

if (AkelPad.GetMainWnd() && AkelPad.IsAkelEdit()) {
	if (! AkelPad.Include("selCompleteLine.js")) WScript.Quit();
	oCh.runWithRedraw();
}

function process() {
	var existentShift = "";
	var existentLeft = "";
	var existentRight = "";
	var smbNull = " \t";
	getShift();
	var nStyle = AkelPad.GetArgValue("style", 0);
	var leftPartEndStyle = (nStyle) ? " " : pBreak;
	
	oCh.setCompleteLineText();
	
	if (oCh.Text)
		existentShift = oCh.Text.slice(0, oCh.Text.lastIndexOf(oStr.trim(oCh.Text, smbNull)));   //Определяем существующий отступ 1-го значащего символа от начала строки
	
	if (oCh.rBegin[0] == oCh.rBegin[1]) {                                                       //Если нет выделения
		pozOpen = oCh.Text.lastIndexOf(" " + sbOpen);
		if (pozOpen == -1)
			pozOpen = oCh.Text.lastIndexOf(pTab + sbOpen);
		if (pozOpen > 0) {                                                                       //Действия, выполняемые, если в текущей строке есть открывающая скобка
			existentLeft = oStr.rtrim(oCh.Text.slice(0, pozOpen), smbNull);                       //Остающиеся символы выделения перед открывающей скобкой
			if (existentLeft) {
				existentLeft += leftPartEndStyle;
			}
			
			existentRight = oStr.trim(oCh.Text.slice(pozOpen + 2), smbNull);                      //Кусок выделения после открывающей скобки, т.е. который должен быть внутри блока; 2 - размер искомого блока: " " + sbOpen
		}
		else {
			existentLeft = oStr.trim(AkelPad.GetTextRange(oCh.rResult[0], oCh.rBegin[0]), smbNull);
			if (existentLeft) {
					existentLeft = existentShift + existentLeft + leftPartEndStyle;
			}
			
			existentRight = oStr.trim(AkelPad.GetTextRange(oCh.rBegin[0], oCh.rResult[1]), smbNull);
		}
		
		if (existentRight.charAt(existentRight.length - 1) == sbClose)                           //Если закрывающая скобка есть - удаляем, так проще, - потом всё равно проставляем
			existentRight = existentRight.substr(0, existentRight.length - 1);
		
		existentRight = existentShift + sShift + existentRight;
	}
	else {
		existentRight = sShift + oCh.Text.replace(/\r/g, pBreak + sShift);
	}
	
	oCh.Text = existentLeft + existentShift + sbOpen + pBreak + existentRight + pBreak + existentShift + sbClose;
	
	oCh.setSelCaret(oCh.rResult[0] + oCh.Text.length - (existentShift.length + 2));             //Устанавливаем каретку в конец блока
}


NB: This script used selCompleteLine.js.
Old name of this script - CtrlDown.js.


| - simbol of cursor

Var 1 - In line there is no symbol of the beginning of the block (в строке нет символа начала блока):
1.1.
not left symbols

Code: Select all

|
or

Code: Select all

<condition>|
Result:

Code: Select all

<condition>
{
   |
}
1.2.

Code: Select all

condition |expression
Result:

Code: Select all

condition 
{
   expression|
}
1.3:

Code: Select all

condition
|
Result:

Code: Select all

condition
{
   |
}
1.4:

Code: Select all

|condition
Result:

Code: Select all

{
   |condition
}
Var 2 - In line there is a symbols of the block (в строке есть символы блока)
2.1.

Code: Select all

condition {|
or

Code: Select all

condition| {
or

Code: Select all

condition {|}
Result:

Code: Select all

condition 
{
   |
}
2.2.

Code: Select all

condition| {expression
or

Code: Select all

condition {|expression}
Result:

Code: Select all

condition 
{
   |expression
}
NB: The condition should not contain block symbols { }. (условие не должно содержать символов блока)

Var 3 - Some lines are selected (выделено несколько строк):

Code: Select all

code line 1;
code line 2 (selected);
code line 3 (selected);
code line 4;
Result:

Code: Select all

code line 1;
{
   code line 2;
   code line 3;|
}
code line 4;
P.S.
EN: I wish to allocate algorithm of shift in single function and to place it in SelCompleteLine.js which could be caused both from ShiftRight.js, and from CtrlDown.js.
RU: Хочу выделить алгоритм сдвига в отдельную функцию и поместить её в SelCompleteLine.js, которую можно было бы вызывать как из ShiftRight.js, так и из CtrlDown.js.
Last edited by VladSh on Mon Jan 06, 2020 12:19 pm, edited 29 times in total.

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

Скрипты для комментирования/раскомментирования текстблоков

Post by VladSh »

Code: Select all

// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1653#p1653
// Description(1033): Commented text or block of text
// 	variants comments see included CommentsExt.js
// Description(1049): Комментирование строки или текстового блока
// Version: 3.11 (2015.04.22)
// Author: VladSh
// 
// Arguments:
// 	-forceSingle = [true]/false
// 
// Proposed to use a keyboard shortcut in Scripts-plugin box: Ctrl + /

if (! AkelPad.Include("CommentsExt.js")) WScript.Quit();
if (! AkelPad.Include("selCompleteLine.js")) WScript.Quit();
if (! AkelPad.Include("CoderFunctions.js")) WScript.Quit();

setComments(GetSyntaxAliasExtension());
oCh.run();

function process() {
	var nCaretPos = 0;
	
	oCh.Text = oCh.getSelTextEmpty();
	
	if (!oCh.Text.length && !cSimple) {
		//если простые комменты не поддерживаются - пытаемся выделить строку целиком и заключить в блочные
		oCh.setCompleteLineText();
	}
	if (oCh.Text.length) {
		nCaretPos = setMultylineComment();
	}
	if (!nCaretPos) {
		nCaretPos = setSinglelineComment();
	}
	
	oCh.setSelCaret(nCaretPos);		//в этом скрипте восстанавливаем первоначальное положение каретки
}

function setMultylineComment() {
	if (cBlockOpen && !(AkelPad.GetArgValue("forceSingle", true) && cSimple)) {
		var tmpText = oStr.rtrim(oCh.Text, pBreak);
		var nDiff = oCh.Text.length - tmpText.length;
		if (nDiff) {		//если перевод строки в конце выделения захвачен
			oCh.Text = tmpText;
			oCh.rBegin[1] -= nDiff;		//для возможного дальнейшего полного выделения строк (если их выбрано несколько) с помощью setCompleteLineText
		}
		
		var pBreakValue = "";
		if (oCh.Text.indexOf(pBreak) !== -1) {		//если выделенный текст в несколько строк
			oCh.setCompleteLineText();
			if (!nDiff) pBreakValue = pBreak;		//специфика при отключенном NoSelEOL - переводы строк вокруг текста не вставляются
		}
		
		oCh.Text = cBlockOpen + pBreakValue + oCh.Text + pBreakValue + cBlockClose;
		return oCh.rBegin[0] + (pBreakValue + cBlockOpen).length;
	}
}

function setSinglelineComment() {
	if (!cSimple) WScript.Quit();
	
	oCh.setCompleteLineText();
	
	var lines = oCh.Text.split(pBreak);
	for (var i = 0; i < lines.length; i++) {
		lines[i] = cSimple + lines[i];
	}
	oCh.Text = lines.join(pBreak);
	return oCh.rBegin[0] + cSimple.length;
}
1. Назначить комбинацию клавиш Ctrl + /
2. Выделить блок текста программы и нажать вышеуказанную комбинацию.

1. To appoint a combination of keys Ctrl + /
2. To select the block of the text of the program and to press the above-stated combination.


Code: Select all

// Description(1033): Decommented text or block of text
// Description(1049): Раскомментирование строки или текстового блока
// 	variants comments see included CommentsExt.js
// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1653#p1653
// Version: 3.9 (2014.12.06)
// Author: VladSh
// 
// Usage:
// 	1. By Hotkeys-plugin: proposed to use a keyboard shortcut in Scripts-plugin box: Ctrl + \
// 	2. With arguments:
// 		• smbStart - start symbols for declose
// 		• smbEnd - end symbols for declose
// 		Example: -"Убрать кавычки «_|_»" Call("Scripts::Main", 1, "CommentsDel.js", `-smbStart="«" -smbEnd="»"`)

if (! AkelPad.Include("CommentsExt.js")) WScript.Quit();
if (! AkelPad.Include("selCompleteLine.js")) WScript.Quit();

if (WScript.Arguments.length) {
	cBlockOpen = AkelPad.GetArgValue("smbStart", "");
	cBlockClose = AkelPad.GetArgValue("smbEnd", "");
}
else {
	if (! AkelPad.Include("CoderFunctions.js")) WScript.Quit();
	setComments(GetSyntaxAliasExtension());
}

oCh.run();

function process() {
	var bSimple = false;
	var nCaretPos = AkelPad.GetSelEnd();
	var pSelText = "";
	
	if (cSimple != null) {
		//Проверка: строчный или блочный комментарий
		oCh.setCompleteLineText();
		
		if (oCh.Text.indexOf(cSimple) != -1)			//работа со СТРОЧНЫМИ комментариями
		{
			pSelText = oCh.Text;		//запоминаем для корректировки позиции курсора на количество убранных комментариев
			
			var arrText = oCh.Text.split(pBreak);
			for (var nLine = 0; nLine < arrText.length; nLine++)
				arrText[nLine] = arrText[nLine].replace(cSimple, "");
			oCh.Text = arrText.join(pBreak);
			
			nCaretPos -= (pSelText.length - oCh.Text.length);
			if (nCaretPos < oCh.rResult[0]) nCaretPos = oCh.rResult[0];	//когда каретка изначально стоит прямо на комментарии вводим коррективы..
			bSimple = true;
		}
	}
	
	if (!bSimple && cBlockOpen) {			//работа с БЛОЧНЫМ комментарием
		oCh.rResult = getRangebyBorders(nCaretPos, nCaretPos, cBlockOpen, cBlockClose, true);
		if (oCh.rResult == null)
			quitIsNotComment();		//если хоть какая-то часть коммента не найдена, значит неверно установлена каретка
		
		oCh.Text = getTextbyRange(oCh.rResult);
		
		oCh.Text = oCh.Text.substr(cBlockOpen.length, oCh.Text.length - cBlockOpen.length - cBlockClose.length - (oCh.Text.charAt(oCh.Text.length) == pBreak));		//берём строку без переднего и заднего комментов; последняя часть в скобках - захват перевода строки в многострочных комментариях
		
		if (oCh.Text.indexOf(cBlockOpen) != -1 || (oCh.Text.indexOf(cBlockClose) != -1))
			quitIsNotComment();		//если внутри текста найден противоположный коммент, считаем что неверно установлена каретка
		
		pSelText = oCh.Text;		//запоминаем для корректировки позиции курсора на количество съедаемых вначале переводов строк
		//продолжение корректировки текста: гасим ненужные переводы строк
		oCh.Text = oStr.ltrim(oCh.Text, pBreak);
		nCaretPos -= (cBlockOpen.length + (pSelText.length - oCh.Text.length));		//вычисляем здесь, т.к. для сдвига каретки нужна только верхняя часть: размер открывающего коммента и возможный перевод строки
		oCh.Text = oStr.rtrim(oCh.Text, pBreak);
	}
	
	oCh.setSelCaret(nCaretPos);
}

function quitIsNotComment() {
	AkelPad.MessageBox(AkelPad.GetEditWnd(), "Курсор установлен не в строке, где есть комментарий, либо за пределами блока комментария.", WScript.ScriptName, 64 /*MB_INFORMATION*/);
	WScript.Quit();
}
1. Назначить комбинацию клавиш Ctrl + \
2. Установить курсор внутрь закомментированного блока текста программы и нажать вышеуказанную комбинацию.

1. To appoint a combination of keys Ctrl + \
2. To set the cursor inside commented block of the text of the program and to press the above-stated combination.


Используемый обоими скрипт

Code: Select all

///Auxiliary script; needed to determine the type of commentary for the current file.
// must be placed in ...\Scripts\Include\
// http://akelpad.sourceforge.net/forum/viewtopic.php?p=1653#p1653
// Version: 3.13 (2014.12.19)

var cBlockOpen;
var cBlockClose;
var cSimple;

var commentsSets = {
// (c) Infocatcher
	//= extension: [
	//=     [blockCmmStart0, blockCmmStart1],
	//=     [blockCmmEnd0, blockCmmEnd1],
	//=     [lineCmm]
	//= ]
	// Or
	//= otherExtension: "extension"
	//= "extension" must be already defined!
	// Use 'null' (without commas) for unavailable comments type.
	// First string will be used for comments adding (blockCmmStart0 and blockCmmEnd0 in example).
	c: ["/*", "*/", "//"],
	cpp: "c",
	h: "c",
	js: "c",
	jsm: "c",
	java: "c",
	php: "c",
	dpr: ["{", "}", "//"],
	pas: "dpr",
	html: ["<!--", "-->", "//"],		//добавил возможность коментить js-код внутри html
	xhtml: "html",
	shtml: "html",
	htm: "html",
	xml: "html",
	xsl: "html",
	xul: "html",
	xbl: "html",
	rdf: "html",
	dtd: "html",
	css: ["/*", "*/", null],
	sql: ["/*", "*/", "--"],
	tpl: ["{*", "*}", "//"],
	ini: [null, null, ";"],
	asm: "ini",
	ahk: "ini",
	mnu: "ini",		//AkelPad menu file
	highlight: "ini",
	coder: "ini",
	spck: "ini",
	au3: ["#cs", "#ce", ";"],
	bat: [null, null, "rem "],
	vbs: [null, null, "'"],
	lss: ["%REM", "%END REM", "'"],
	manifest: [null, null, "#"],
	properties: "manifest",
	htaccess: "manifest",
	py: [null, null, "#"],
	pyw: "py"
};

function setComments(ext) {
	if (ext == "")
		ext = "c";		//by default
	
	var cmmSet = commentsSets[ext];
	if (typeof(cmmSet) == "string")
		cmmSet = commentsSets[cmmSet];
	
	if (cmmSet == undefined) {
		AkelPad.MessageBox(AkelPad.GetEditWnd(), 'Для расширения "' + ext + '" комментарии не заданы!', WScript.ScriptName, 48 /*MB_EXCLAMATION*/);
		WScript.Quit();
	}
	
	cBlockOpen = cmmSet[0];
	cBlockClose = cmmSet[1];
	cSimple = cmmSet[2];
}


P.S.: Instructor, Fr0sT, Infocatcher, Yustas.NeO, se7h, Lenchik thanks!
Last edited by VladSh on Fri Jun 19, 2015 8:42 pm, edited 38 times in total.
Post Reply