Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.239.90.61] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Прикр. сообщ.
#1
,
|
|
|
Far Manager
Windows. FreeWare. Многофункциональный файловый менеджер для работы с различными файлами, позволяет просматривать файлы и каталоги, редактировать, копировать и переименовывать файлы. Поддерживает Unicode имеет удобный и простой в использовании пользовательский интерфейс с многоязычной поддержкой. Позволяет работать с архивами, FTP-клиентами, и просматривать сеть с помощью реализованных в стандартную поставку плагинов. Кроме того есть возможность расширения функциональности за счет подключения дополнительных плагинов. Ну очень странно что его уже давным давно не включили в разделе "Полезного ПО" Подключаемые модули (плагины) Возможности FAR существенно расширяются благодаря плагинам различного назначения: Домашняя страничка: https://farmanager.com |
Сообщ.
#1
,
|
|
|
Lua-скрипт EditorTools
Позволяет подключать и исполнять в редакторе Far'а различные обработчики - фильтры, компиляторы, интерпретаторы. Исполнять их без отрытия дополнительных окон, отлавливать stdout и stdrr, загружать результаты обработки назад в редактор, выводить сообщения об ошибках и результатах обработки в виде диалогов. Возможно кому-то пригодится. Предыстория Для быстрого редактирования файлов - встроенный редактор Far'а просто прекрасен. Но, к сожалению, определенных функций в нем не хватает. Конечно можно, при наличии времени и сил, сесть и написать свой инструмент обработки в виде полноценного плагина, либо Lua-скрипта. Меня же заинтересовал чисто практический вопрос - найти способ подключения уже готовых инструментов не через подсистему ассоциаций файлов. Надоело сохраняться, обрабатывать файл, потом опять грузить файл в редактор. Ну и вот родилась идея создать более-менее универсальное средство. Прошу учесть - это моя первая программа на языке Lua, так что принимайте мой отказ от ответственности, еличе На момент написания скрипта мне нужно было подключить: Функионал Команды обработки прописываются в файл конфигурации EditorTools.conf, который лежит рядом с макросом. Программы могут работать в четырех режимах: 1) Filter Используется для запуска программ, которые могут непосредственно вносить изменения в файл. После выполнения содержимое редактора заменяется результатом обработки 2) Pipe Используется для запуска программ, которые могут читать и обрабатывать файл, но вывод умеют делать только в STDOUT После выполнения содержимое редактора заменяется результатом обработки 3) Compiler Используется для запуска компиляторов После выполнения выводится диалог об успешной компиляции, либо диалог, содержащий ошибки компилятора 4) Execute Используется для запуска как правило интерпретаторов После выполнения выводится диалог, в котором отображается результат обрабтки текста внешней программой Скрипт EditorTools.lua Скрытый текст ------------------------------------------------------------------------------------------------------------------------ -- Скрипт EditorTools v.1.1 -- подключение внешних инструментов в редакторе Far'а -- -- 2020 (C) Автор Majestio aka JoeUser -- -- http://majestio.info -- ------------------------------------------------------------------------------------------------------------------------ -- local inspect = require('inspect') local ScriptName = ... local EOPT_BOM = 0x00000200 local BTYPE_STREAM = 1 local SW_HIDE = 0 ------------------------------------------------------------------------------------------------------------------------ local EditorTools = function () local CurPath = mf.fsplit(ScriptName,3) local ConfigName = ScriptName:gsub("[^.]+$","conf") local Conf = io.open(ConfigName,"r") -- читаем файл конфигурации ------------------------------------------------------------------------------------------ if Conf == nil then far.Message('Файл конфигурации нельзя прочесть!', 'Ошибка', ';Ok', 'w') return else local Cmd = {} local Idx = 1 -- разбираем файл конфигурации на список "инструментов" ------------------------------------------------------------ for line in Conf:lines() do if regex.match(line,'^(F|P|C|E)') then for w1,w2,w3 in regex.gmatch(line, "^(F|P|C|E)\\s*,\\s*'\\s*([^']+?)\\s*'\\s*,\\s*'\\s*([^']+?)\\s*'\\s*$") do Cmd[Idx] = {w1,w2,w3} end Idx = Idx + 1 end end Conf:close() -- формируем и выводим диалог выбора "инструментов" ---------------------------------------------------------------- local Choice = '' for Idx = 1, #Cmd do Choice = Choice..Cmd[Idx][2]..'\n'; end local ChoiceIdx = Menu.Show(Choice, nil, 8+0x200) if ChoiceIdx == 0 then return end -- формируем имя временного файла для сброса содержимого редактора ------------------------------------------------- math.randomseed(os.time()) local RndNumber = math.random(1000) local EditorFullName = editor.GetFileName() local EditorFilePath = regex.match(EditorFullName,"^(.+\\\\).+$") local EditorFileName = regex.match(EditorFullName,"^.+\\\\([^\\.]+)\\.*.*$") local EditorFileExt = regex.match(EditorFullName,"^.+?\\.([^\\.]+)$") if EditorFileExt == nil then EditorFileExt = "" end local TmpName = EditorFilePath..EditorFileName..'-tmp-'..RndNumber..'.'..EditorFileExt local OutName = EditorFilePath..EditorFileName..'-tmp-'..RndNumber..'.'.."out" local ResName = EditorFilePath..EditorFileName..'-tmp-'..RndNumber..'.'.."res" local ErrName = EditorFilePath..EditorFileName..'-tmp-'..RndNumber..'.'.."err" -- в командной строке производим замены в плэйсхолдерах ------------------------------------------------------------ local CmdName = regex.gsub(Cmd[ChoiceIdx][3],"%p",EditorFilePath) -- %p на значение EditorFilePath CmdName = regex.gsub(CmdName,"%n",EditorFileName) -- %n на значение EditorFileName CmdName = regex.gsub(CmdName,"%e",EditorFileExt) -- %e на значение EditorFileExt CmdName = regex.gsub(CmdName,"%t",TmpName) -- %t на значение TmpName CmdName = regex.gsub(CmdName,"%o",OutName) -- %o на значение OutName CmdName = regex.gsub(CmdName,"%r",ResName) -- %r на значение ResName -- запускаем внешнюю обработку в зависимости от "режима" выбранного инструмента ------------------------------------ if WriteFile(TmpName) ~= nil then local Out, Err = ExecCommand(CmdName, TmpName, OutName, ResName, ErrName, Cmd[ChoiceIdx][1]) if Cmd[ChoiceIdx][1] == "C" then if Err == "" or Err == nil then far.Message("Компиляция прошла удачно", 'Результат компиляции', ';Ok', 'k') else far.Message(win.OemToUtf8(Err), 'Ошибка', ';Ok', 'w') end else if Out ~= "" and Out ~= nil then if Cmd[ChoiceIdx][1] == "E" then far.Message(win.WideCharToMultiByte(win.MultiByteToWideChar(Out,1251),65001), 'Результат выполнения', ';Ok', 'k') else LoadContent(Out) end else if Err == "" or Err == nil then far.Message('Обработчик вернул пустой вывод!', 'Ошибка', ';Ok', 'w') end end end else far.Message('Ошибка записи временного файла!!', 'Ошибка', ';Ok', 'w') end end end ------------------------------------------------------------------------------------------------------------------------ -- Загрузка файла в редактор ------------------------------------------------------------------------------------------------------------------------ function LoadContent(Content) local Ei = editor.GetInfo() local EId = Ei.EditorID local Flags = far.Flags editor.UndoRedo(EId, Flags.EUR_BEGIN) editor.Select(EId, BTYPE_STREAM, 1, 1, 1, Ei.TotalLines+1) editor.DeleteBlock(EId) Content = regex.gsub(Content,"^(\xef\xbb\xbf)","") editor.InsertText(EId,Content) editor.UndoRedo(EId,Flags.EUR_END) editor.SetPosition(EId, 1, 1) end ------------------------------------------------------------------------------------------------------------------------ -- Запуск процесса по обработке файла ------------------------------------------------------------------------------------------------------------------------ function ExecCommand(CmdName, TmpName, OutName, ResName, ErrName, Mode) local RetOut, RetErr local File = io.popen(('"%s >"%s" 2>"%s"'):format(CmdName, OutName, ErrName),"w") if File == nil then far.Message('Ошибка при запуске команды!', 'Ошибка', ';Ok', 'w') return nil, nil end File:close() local TheName = OutName if Mode ~= "P" and Mode ~= "E" then TheName = ResName end if win.GetFileInfo(TheName) ~= nil then OutFile = io.open(TheName) if OutFile~= nil then RetOut = OutFile:read("*a") OutFile:close() end end if win.GetFileInfo(ErrName) ~= nil then ErrFile = io.open(ErrName) if ErrFile~= nil then RetErr = ErrFile:read("*a") ErrFile:close() end end win.ShellExecute(nil,nil,win.GetEnv"COMSPEC",('/c "del "%s" "%s" "%s" "%s"'):format(TmpName, OutName, ResName, ErrName),nil,SW_HIDE) return RetOut, RetErr end ------------------------------------------------------------------------------------------------------------------------ -- Запись файла ------------------------------------------------------------------------------------------------------------------------ function WriteFile (FileName) local Info = editor.GetInfo() local File = io.open(FileName,"wb") if File == nil then far.Message('Ошибка записи временного файла!', 'Ошибка', ';Ok', 'w') return nil else if (bit.band(Info.Options, EOPT_BOM) == EOPT_BOM) then File:write(string.char(239,187,191)) end for Line = 1, Info.TotalLines do local Gs = editor.GetString(Info.EditorID, Line, 0) File:write(Gs.StringText, Gs.StringEOL) end File:close() return Info.TotalLines end end ------------------------------------------------------------------------------------------------------------------------ -- Macro ------------------------------------------------------------------------------------------------------------------------ Macro { area="Editor"; key="CtrlE"; flags=""; description="EditorTools"; action = function() EditorTools() end; } Пример конфига EditorTools.conf Скрытый текст ; Поля конфига следующие: ; ; Режим, "Название-инструмента", "командная строка" ; ; Режим: ; ; [F]ilter - записываем временный файл, обрабатываем его, потом загружаем в редактор ; [P]ipe - записываем временный файл, обрабатываем его, но загружаем STDOUT программы ; [C]ompiler - сохраняем файл, запускаем команду компилятора ; [E]xecute - сохраняем файл, запускаем команду интерпретатора, результат выводим в виде диалога ; ; Плейсхолдеры: ; ; %p - путь к файлу в редакторе ; %n - имя файла в редакторе (без расширения) ; %e - расширение имени файла в редакторе ; %t - полное имя временного файла ; %o - полное имя временного файла-результата (куда пишется из пайпа) ; %r - полное имя временного файла-результата (куда может писать сама программа) ; ; Пример: ; ; F,'Инструмент-1','comm-1.cmd' ; P,'Инструмент-2','comm-2.cmd' ; C,'Инструмент-3','comm-3.cmd' ; E,'Инструмент-4','comm-4.cmd' ; P,'AStyle (Space-P)','C:\Tools\AStyle\AStyle.exe --options=C:\Tools\AStyle\.astylerc-space --stdin=%t' F,'AStyle (Space-F)','C:\Tools\AStyle\AStyle.exe --options=C:\Tools\AStyle\.astylerc-space --stdin=%t --stdout=%r' P,'TidyP','C:\Tools\Tidy\tidy.exe -config c:\Tools\Tidy\tidy.conf "%t"' P,'Hello Ruby','ruby.exe C:\Tools\Far3-x64\Profile\Macros\scripts\EditorTools\hello.rb' P,'Test Perl-P','perl.exe C:\Tools\Far3-x64\Profile\Macros\scripts\EditorTools\test-p.pl "%p%n.%e"' F,'Test Perl-F','perl.exe C:\Tools\Far3-x64\Profile\Macros\scripts\EditorTools\test-f.pl "%t" "%r"' C,'Компилировать FASM программу','C:\Tools\Fasm\FASM.CMD "%t" "%p%n.exe"' E,'Исполнить Perl скрипт','perl.exe %t' E,'Исполнить SWI-Prolog скрипт','C:\Tools\Prolog\bin\swipl.exe -q -f %t' Мои конфиги форматеров Скрытый текст .astylerc-space align-pointer=type align-reference=type attach-classes attach-closing-while attach-extern-c attach-inlines attach-namespaces attach-return-type break-one-line-headers close-templates delete-empty-lines indent-cases indent-classes indent-col1-comments indent-modifiers indent-namespaces indent-preproc-block indent-preproc-define indent-switches indent=spaces=2 keep-one-line-blocks max-continuation-indent=40 min-conditional-indent=1 pad-comma pad-header pad-oper remove-brackets style=java unpad-paren .astylerc-tabs align-pointer=type align-reference=type attach-classes attach-closing-while attach-extern-c attach-inlines attach-namespaces attach-return-type break-one-line-headers close-templates delete-empty-lines indent-cases indent-classes indent-col1-comments indent-modifiers indent-namespaces indent-preproc-block indent-preproc-define indent-switches indent=force-tab=2 keep-one-line-blocks max-continuation-indent=40 min-conditional-indent=1 pad-comma pad-header pad-oper remove-brackets style=java unpad-paren tidy.conf // sample config file for HTML tidy indent: auto indent-spaces: 2 wrap: 0 markup: yes output-xml: no input-xml: no show-warnings: yes numeric-entities: yes quote-marks: yes quote-nbsp: yes quote-ampersand: no break-before-br: no uppercase-tags: no uppercase-attributes: no char-encoding: utf8 new-inline-tags: cfif, cfelse, math, mroot, mrow, mi, mn, mo, msqrt, mfrac, msubsup, munderover, munder, mover, mmultiscripts, msup, msub, mtext, mprescripts, mtable, mtr, mtd, mth new-blocklevel-tags: cfoutput, cfquery new-empty-tags: cfelse drop-empty-elements: no Установка Скрипт и его конфиг нужно переписать в каталог скриптов (в свой подкаталог). Перезапустить Far. Для себя я настроил Far так, чтобы каталог профилей лежал рядом, а не в домашнем каталоге. По итогу у меня макрос лежит в каталоге - C:\Tools\Far3-x64\Profile\Macros\scripts\EditorTools Если будут вопросы - прошу в личку. Чтобы не засорять тред про Far. |
Сообщ.
#2
,
|
|
|
А чем он лучше Total Commander-a ?
|
Сообщ.
#3
,
|
|
|
Цитата ... @ А чем он лучше Total Commander-a ? Три преимущества (ну на вкус и цвет): * удобная работа с консольными программами * встроенный быстрый редактор, который как и сам Фар можно обвесить плагинами * уже давно подключили поддержку Lua, с нативными плагинами можно не париться |
Сообщ.
#4
,
|
|
|
Цитата ... @ А чем он лучше Total Commander-a ? Total - это как DOS Navigator: швейцарский нож, уже не помещающийся в руку из-за неудобной толщины. А вот FAR - это классический Norton, быстро и легко. Мультитул, у которого можно отстегнуть всё лишнее. |
Сообщ.
#5
,
|
|
|
Цитата Mr.Delphist @ А вот FAR - это классический Norton, быстро и легко. Мультитул, у которого можно отстегнуть всё лишнее. Когда-то был более удачный вариант - Volkov Commander, типа Нортона - но гораздо шустрее и меньше хавал ресурсов. А на счет FAR'а - полностью согласен. А если его запускать под ConEmu, то еще добавляется мешок сахара. |
Сообщ.
#6
,
|
|
|
Я даже видел гика, что запускал FAR из-под вайна вместо MC в линухе.
|
Сообщ.
#7
,
|
|
|
Цитата Qraizer @ видел гика, что запускал FAR из-под вайна вместо MC в линухе. О, мсье знает толк в извращениях! |
Сообщ.
#8
,
|
|
|
Цитата Qraizer @ Я даже видел гика, что запускал FAR из-под вайна вместо MC в линухе. Мну сейчас запускает Far2 из под Wine 6.10 в рамках LiveCD Linux Puppy (пакет собранный взял из топика форума Puppy) P.S. После запуска Far2 через команду терминала: wine Far.exe дальше запускаю Total Commander, а через него повторно Far2 для получения графического вида гуи Fara Windows софт, запускаемый в рамках окружения Linux, зачастую показывает лучшую "рабочесть" чем в родной для него Windows! и это приятно удивляет и при этом не требует гигабайт дискового пространства для установки Windows системы нативно или в VM (виртуальные машины) |
Сообщ.
#9
,
|
|
|
Кто-то знает (может объяснить) отчего так:
1. Создаю 3 файла: a-.txt, a!.txt и a=.txt 2. Они сортируются в Far'е именно в таком порядке, но по коду символа должно быть: a!.txt, a-.txt, a=.txt т.к. : код(!)=$21, код(-)=$2D, код(=)=$3D. Т.е. почему знак '-' столь важен стал? Добавлено П.С. вот запустил в NDN (Necro... DOS Navigator), там всё правильно! И виндовый проводник сортирует как надо. |
Сообщ.
#10
,
|
|
|
По тыкайте Ctrl+F<3-11> и посмотрите разные варианты
|
Сообщ.
#11
,
|
|
|
Да, по Ctrl-F7 (Несорт) стало сортировать нормально. Но это ж не выход, т.к. у меня всегда установлена сортировка по расширению. Непонятна причина, увы.
|
Сообщ.
#12
,
|
|
|
Так он сортирует по одному указанному критерию. По другим критериям никаких гарантий какого-либо порядка. Тебе же нужно два критерия одновременно. Вроде было как-то у них на форуме обсуждение объединения нескольких критериев для создания своих правил, но к чему пришли, я не знаю. Мож плагин какой нарелизили.
|
Сообщ.
#13
,
|
|
|
Впрочем, чушь это. Даже если включить сортировку по имени, всё равно тот же результат.
Я порылся в FARовых сырцах, там всё упирается в CompareString() суть WinAPI. Проверил (основано на string_sort.cpp / compare_natural_base()): #include <windows.h> #include <iostream> #include <string> #include <map> std::string Str1 = "a!"; std::string Str2 = "a-"; int main() { auto Flags = LINGUISTIC_IGNORECASE | SORT_STRINGSORT; auto Result= CompareString(LOCALE_USER_DEFAULT, Flags, Str1.data(), static_cast<int>(Str1.size()), Str2.data(), static_cast<int>(Str2.size())); std::cout << [](int x){ return std::map<int, std::string>{{0, std::to_string(GetLastError())}, {CSTR_LESS_THAN, "Less" }, {CSTR_EQUAL, "Equal" }, {CSTR_GREATER_THAN, "Greater"}}[x]; }(Result); } Greater P.S. Если будет выдавать цифры, значит CompareString() вернула эррор, и это системный код ошибки last error |
Сообщ.
#14
,
|
|
|
Если интересно, то Calculate Linux 6.6.57 + wine (wine-9.20 (Staging) или wine-9.0 (Proton-9.0-2)) при установленной Windows 10 в префиксе выдают Greater.
|
Сообщ.
#15
,
|
|
|
В общем, разгадка на поверхности, хотя и не так уж очевидна. CompareString() же выполняет лексикографическое сравнение с учётом национальных предпочтений. Это очевидно. А вот что не так уж, так это то, что '-' ассоциируется с дефисами и тире, в частности переносами, как явными, так и мягкими. Ну и лексикографически они располагаются перед разделителями, типа там пробел, таб итп, т.к. по сравнению с ними должны иметь меньший вес.
Я заглянул в 7-ку, там такое же поведение. Даже поставил XPю на виртуалку и заморочился пакетом её поддержки в Студии, что собрать под неё. И в ней тоже Greater. Осталось только ради интереса чекнуть 98SE, но это VS6 расчехлять... ну так мы тут крутые парни или зумеры ленивые |