AkelPad Forum Index AkelPad
Support forum
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Format plugin
Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8  Next
 
Post new topic   Reply to topic    AkelPad Forum Index -> Plugins
View previous topic :: View next topic  
Author Message
KDJ



Joined: 06 Mar 2010
Posts: 1928
Location: Poland

PostPosted: Sat Dec 25, 2010 12:18 am    Post subject: Reply with quote

Andrey_A_A
To sort the file by line length, you can use the following code in JS:
Code:
if (! AkelPad.GetEditWnd()) WScript.Quit();

AkelPad.SetSel(0, -1);

var bDesc = 0;
var pTxt  = AkelPad.GetSelText(1 /*\r*/);
var aArr  = pTxt.split("\r");

ArrayTextSortByLength(aArr, bDesc);

pTxt = aArr.join("\r");

AkelPad.ReplaceSel(pTxt);

//////////////////////////////
function ArrayTextSortByLength(aArr, bDescending)
{
  if (bDescending)
  {
    aArr.sort(function(a, b) {
      if      (a.length < b.length) return 1;
      else if (a.length > b.length) return -1;
      else return 0; });
  }
  else
  {
    aArr.sort(function(a, b) {
      if      (a.length < b.length) return -1;
      else if (a.length > b.length) return 1;
      else return 0; });
  }
}
Back to top
View user's profile Send private message
Fr0sT



Joined: 24 Jul 2007
Posts: 876

PostPosted: Sat Dec 25, 2010 8:02 am    Post subject: Reply with quote

KDJ, simple and useful, but it'll take 2*charcount*sizeof(widechar) of RAM during execution if I get things right. May be found out too hard for the system Smile
Back to top
View user's profile Send private message
KDJ



Joined: 06 Mar 2010
Posts: 1928
Location: Poland

PostPosted: Sat Dec 25, 2010 4:09 pm    Post subject: Reply with quote

Fr0sT wrote:
...but it'll take 2*charcount*sizeof(widechar) of RAM during execution...

I did a test sort lines. On the file 35 MB, about 2.7 million lines.
Using Format plugin, script and UltraEdit.
Here are the results:
Code:
                  max. usage memory     sort time
AkelPad + plugin        600 MB             40 sec
AkelPad + script        600 MB            210 sec
UltraEdit               890 MB            110 min (6600 sec)

So if the script is not so bad.
Back to top
View user's profile Send private message
Fr0sT



Joined: 24 Jul 2007
Posts: 876

PostPosted: Sun Dec 26, 2010 9:37 pm    Post subject: Reply with quote

KDJ
nice, respect! Smile
Back to top
View user's profile Send private message
opk44



Joined: 16 Jan 2010
Posts: 596

PostPosted: Mon Dec 27, 2010 10:52 am    Post subject: Reply with quote

Andrey_A_A wrote:
В алелпаде большинство написано на js, а к нему привыкнуть и понять надо...

Прошу прощения, если дополнение покажется излишним (с учетом ответа от KDJ) но вдруг тема еще не исчерпана.
1) Отличия JS от VBS не так и велики - надо только точку с запятой в конце строки ставить (шутка). JS требует чуть больше внимательности, т.к. он регистрозависимый.
2) Оговорюсь, что мой "пример" пригоден для обработки НЕюникодных файлов. Но если это не проблема, то здесь можно обойтись вообще без AkelPad.

Я попробую показать, как "пользователь" "пользователю" (где "пользователь" = непрограммист с остаточными знаниями по школьной информатике и при наличии справки), как решить задачу путем "рассуждений":
Вариант 1. "наглядный".
Он вытекает из следующей посылки "а что если сделать все строки одинаковой длины и свести задачу сортировки к тривиальной?". Для этого нужно выровнять строки по длине, отсортировать, и затем вернуть строки к первоначальному виду (до выравнивания).
1) Исходный файл читается дважды. При первом чтении выясняется максимальная длина строки в файле.
2) Читаем файл повторно и генерируем выходной файл, в котором каждая строка (взятая из исходного файла) дополняется спереди пробелами до длины максимальной строки - получаем этакую огромную прямоугольную "простыню" с текстом выравненным по правому краю.
Внимание! Есть опасность того, что генерируемый файл окажется очень большого размера (если исходный файл содержит очень много коротких строк и очень длинную максимальную строку). Т.е. на входе имеем файл, размер которого - сумма длин его строк, а на выходе -файл, размер которого - произведение длины максимальной строки на количество строк.
3) Сортируем сгенерированный файл.
Получаем что-то вроде этого
(для наглядности пробелы заменены точками)
Code:

.........ff
.........ff
.......ffff
.......ffff
......ffffa
......fffff
......fffff
.....aaaaaa
.....aaaaab
.....ffffff
.....ffffff
fffffffffff

4) Отсекаем лидирующие пробелы (прижимаем текст к левой границе).
Внимание! Если исходный файл содержит значимые пробелы в начале строк, то они также будут потеряны. Чтобы этого не происходило, можно предварительно добавлять в начало каждой строки некий символ-маркер (например '#') и только затем пробелы. При отсечке же удалять пробелы до маркера и сам маркер.
Подход примитивный и затратный. Много минусов. Один плюс - наглядный (как мне кажется). Собственно, только ради этого он и приведен.
Взгляните на картинку с "отсортированным файлом". Начальные пробелы являются просто частью ключа сортировки. Очевидное неудобство - эта часть разной длины. ЭТО плюс слово "ключ" и подводит нас к варианту номер два.
Вариант 2.
Можно улучшить предыдущий вариант и избавиться от его недостатков, сделав его не только менее ресурсоемким но и более простым в кодировании, если совместить с использованным ранее (при сортировке по длине строк) методом (универсальность). Для этого нужно доработать фрагмент кода
Code:
   TXT_SIZE = TXT.length;   // получить длину строки

А именно, преобразовывать числа в строки ФИКСИРОВАННОЙ ширины (1 -> '00000001', 2654 -> '00002654', ...). Тогда Вы получите возможность сортировки такой, какой хотели.

фрагмент измененного js скрипта

Code:

while (!file_in.atEndOfStream)
{
   TXT = file_in.ReadLine();
   TXT_SIZE = TXT.length;   // получить длину строки
   TXT_SIZE = TXT_SIZE.toString(10);   // получить строковое представление числа в 10-тичной системе
//   дополнить нулями слева до восьми** символов ('123' --> '00000123').
   while (TXT_SIZE.length < 8)
   {
      TXT_SIZE = '0' + TXT_SIZE;
   }
//   записать в генерируемый файл
   file_out.WriteLine(TXT_SIZE + '\t' + TXT);
}
// **Примечание: 8 выбрано для удобства, как число, обычно равное, либо кратное размеру табуляции,
//   а не для обработки строк до 100 миллионов символов ;)


Здесь уже можно остановиться и подумать "а можно ли не загружать файл в AkelPad для сортировки?".
Чтобы избавиться от необходимости загружать полученный файл в редактор, сортировать его и затем выделять и отрезАть левый блок с ключами, Вы можете передоверить и всю эту работу скрипту.
Так, сортировку НЕюникодного файла можно поручить системной утилите SORT (см. справку по командной строке в Windows).
Если предполагается наличие в файле строк длиннее 4096, то с параметром "/rec символы" примерно так:
SORT /rec 65535 d:\WORK\notes_NUM.txt /o d:\WORK\notes_NUM_SORT.txt
для обратного порядка, с ключом "/r":
SORT /r /rec 65535 d:\WORK\notes_NUM.txt /o d:\WORK\notes_NUM_SORT.txt

Запуск же самой команды, см. справку Windows Script Host по методам RUN или EXEC.

Например так
Code:

var WshShell = WScript.CreateObject ("WScript.shell");
// запуск в скрытом окне командной строки, и выполнение сортировки с ожиданием завершения ее работы.
WshShell.run ('cmd.exe /c "SORT /rec 65535 d:\\WORK\\notes_NUM.txt /o d:\\WORK\\notes_NUM_SORT.txt"', 0, "TRUE");
// собщение о выполнении сортировки (само закроется через 5 секунд)
WshShell.Popup ("Сортировка завершена. Создан отсортированный файл.", 5,"Сообщение от скрипта",0);

или так:
Code:
//var WshShell = new ActiveXObject("WScript.Shell");
//var oExec = WshShell.Exec("SORT /rec 65535 d:\\WORK\\notes_NUM.txt /o d:\\WORK\\notes_NUM_SORT.txt");
//
//while (oExec.Status == 0)
//{
//     WScript.Sleep(1000);
//}
//WshShell.Popup ("Сортировка завершена. Создан отсортированный файл.", 5,"Сообщение от скрипта",0);

(для JS не забывайте "удваивать слеши" в путях и "закавычивать строки").
Для удаления в отсортированном файле колонки с ключами подойдет метод substr (для JScript, а для VBScript функция Right)
stringvar.substr(start [, length ])
"Выкусываем" 8 символов ключа + 1 символ табулятора.
Поскольку отсчет индексов ведется с нуля, то стартовая позиция (одна и та же) = 9, а раз нужен весь "хвост" строки, то второй параметр опускаем.
Таким образом TXT.substr(9) даст то, что нужно.
Кусок кода записи в файл:
TXT = file_in.ReadLine();
file_out.WriteLine(TXT.substr(9));

Это все. Осталось только собрать все вместе и добавить, если хотите, интерактивности (чтобы не модифицировать скрипт всякий раз, когда меняется имя файла или потребуется изменить порядок сортировки). А также предусмотреть обработку промежуточных файлов. Итоговый скрипт будет никак не привязан к AkelPad, что тоже неплохо.
P.S.
Не за чем "невротизировать себя недостижимой целью". Стремление к изучению хороших скриптов похвально - я от этих слов не отказываюсь и не вкладываю в них никакого сарказма, только это не годится для "первых шагов". Стремясь сделать с первого раза "идеально", можно вообще никогда не начать (всегда будет казаться, что нужно "еще что-нибудь почитать"). Начните с примитивных и корявых решений. Это лучше чем ничего.
Оценивая же итоговые затраты, берусь утверждать, что для самостоятельного написания первого СВОЕГО скрипта ТАКОГО уровня, Вам потребуется не более 2-3 дней на ознакомление с JS либо VBS и еще пол-дня на собственно работу по "программированию" и тестированию. Для скриптов уровня KDJ трех недель не достаточно.
Back to top
View user's profile Send private message
KDJ



Joined: 06 Mar 2010
Posts: 1928
Location: Poland

PostPosted: Mon Dec 27, 2010 7:55 pm    Post subject: Reply with quote

Maybe this script will solve the problem.
Code:
// Lines sort by length and string
// Call("Scripts::Main", 1, "LinesSortByLengthAndString.js")
// The script sorts all lines by two keys:
// key 1 - line length
// key 2 - string containing entire line

if (! AkelPad.GetEditWnd()) WScript.Quit();

AkelPad.SetSel(0, -1);

var bDesc1 = 0; // = 1 if key 1 descending
var bDesc2 = 0; // = 1 if key 2 descending
var pTxt   = AkelPad.GetSelText(1 /*\r*/);
var lpArr  = pTxt.split("\r");

lpArr.sort(function(a, b) {
  if      (a.length < b.length) return (bDesc1 ?  1 : -1);
  else if (a.length > b.length) return (bDesc1 ? -1 :  1);
  else if (a < b) return (bDesc2 ?  1 : -1);
  else if (a > b) return (bDesc2 ? -1 :  1);
  else return 0; });

pTxt = lpArr.join("\r");

AkelPad.ReplaceSel(pTxt);
Back to top
View user's profile Send private message
Andrey_A_A



Joined: 03 Jun 2010
Posts: 665
Location: Сочи, Хоста

PostPosted: Wed Dec 29, 2010 4:50 pm    Post subject: Reply with quote

Спасибо, всё шикарно работает, добавил
var nResult=AkelPad.Call("Format::LineRemoveDuplicates");
перед AkelPad.SetSel(0, -1);
теперь сразу удаляет дубликаты и сортирует!!!
Back to top
View user's profile Send private message Send e-mail Visit poster's website
KDJ



Joined: 06 Mar 2010
Posts: 1928
Location: Poland

PostPosted: Wed Dec 29, 2010 6:39 pm    Post subject: Reply with quote

Andrey_A_A wrote:
...добавил
var nResult=AkelPad.Call("Format::LineRemoveDuplicates");
перед AkelPad.SetSel(0, -1);

AkelPad.Call(Format::LineRemoveDuplicates") should be placed after AkelPad.SetSel(0, -1);
This will ensure, that the removal of duplicates and sorting is performed on the same range. In this case, the entire text.
Back to top
View user's profile Send private message
Infocatcher



Joined: 06 Aug 2007
Posts: 1765

PostPosted: Sat Jan 01, 2011 10:13 pm    Post subject: Reply with quote

Для функций, работающих со строками, напрашивается обобщающий диалог с кнопками и галочкой «Учитывать регистр символов». Что-то вроде вот такого:
Code:
 - Сортировать ---------------------------------------------------------
| ([Иконка] По возрастанию          )  ([Иконка] По убыванию          ) |
| ([Иконка] По числовому возрастанию)  ([Иконка] По числовому убыванию) |
| ([Иконка] Инвертировать порядок   )                                   |
 -----------------------------------------------------------------------
 - Дублирующиеся строки ------------------------------------------------
| ([Иконка] Получить дублирующиеся  )  ([Иконка] Удалить дублирующиеся) |
| ([Иконка] Получить уникальные     )                                   |
 -----------------------------------------------------------------------
[+] С учётом регистра


А скрипт делать лень. Razz
Тем более, что сейчас одновременно может быть запущен только один скрипт.
Back to top
View user's profile Send private message Visit poster's website
KDJ



Joined: 06 Mar 2010
Posts: 1928
Location: Poland

PostPosted: Sun Jan 02, 2011 12:41 pm    Post subject: Reply with quote

I have a question.
How do I sort of regard for local alphabet, in a script?
For example, normal sort gives the result: ć > z.
And it should be: c < ć < d < z
Back to top
View user's profile Send private message
KDJ



Joined: 06 Mar 2010
Posts: 1928
Location: Poland

PostPosted: Sun Jan 02, 2011 9:06 pm    Post subject: Reply with quote

I already found the answer to above question.
Can use the system function "kernel32::lstrcmp" to compare strings.
Back to top
View user's profile Send private message
KDJ



Joined: 06 Mar 2010
Posts: 1928
Location: Poland

PostPosted: Mon Jan 10, 2011 8:45 pm    Post subject: Reply with quote

Infocatcher wrote:
Для функций, работающих со строками, напрашивается обобщающий диалог с кнопками и галочкой «Учитывать регистр символов».
...
А скрипт делать лень.

But it's all in Format plugin.
You can do it yourself in ContexMenu plugin.
Back to top
View user's profile Send private message
Infocatcher



Joined: 06 Aug 2007
Posts: 1765

PostPosted: Mon Jan 10, 2011 9:08 pm    Post subject: Reply with quote

KDJ wrote:
You can do it yourself in ContexMenu plugin.
It's very huge because of combinations with «case sensitive» option on and off.
Back to top
View user's profile Send private message Visit poster's website
KDJ



Joined: 06 Mar 2010
Posts: 1928
Location: Poland

PostPosted: Mon Jan 10, 2011 9:29 pm    Post subject: Reply with quote

Infocatcher wrote:
It's very huge because of combinations with «case sensitive» option on and off.

Well, actually in Format plugin is not option "case sensitive".
May partially solve the problem ColumnsSort.js script.
Back to top
View user's profile Send private message
KDJ



Joined: 06 Mar 2010
Posts: 1928
Location: Poland

PostPosted: Sat Jan 15, 2011 8:25 pm    Post subject: Reply with quote

Infocatcher
Maybe something like this:

Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AkelPad Forum Index -> Plugins All times are GMT
Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8  Next
Page 3 of 8

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


SourceForge.net Logo Powered by phpBB © 2001, 2005 phpBB Group