local Info = package.loaded.regscript or function(...) return ... end local nfo = Info {_filename or ..., name = "EditorToCmdLine"; description = "BAX: Переключение на область Shell с погашенными панелями для доступа к командной строке"; version = "1.0.5"; --http://semver.org/lang/ru/ author = "BAX"; url = [[https://forum.farmanager.com/viewtopic.php?f=15&t=12501]]; id = "97C4C4E9-E729-466A-B8EC-F3B836C608A4"; idea = 'ujos (https://forum.farmanager.com/memberlist.php?mode=viewprofile&u=14042)'; history = [[ 1.0.1 от 26.06.2021: стартовая версия 1.0.2 от 27.06.2021: восстановлена реакция на закрытие редактора 1.0.3 от 28.06.2021: 1. Реализован "диалоговый" режим: по Ctrl+Shift+O внизу окна редактора открывается однострочный диалог с полем ввода и кнопкой { Run! }. Введённая строка передаётся в командную строку и выполняется. 2. Исправлены некоторые неточности (клавиша копирования Alt+V) 1.0.4 от 30.06.2021: 1. Слегка изменён интерфейс "диалогового" режима ввода командной строки (рамка, цвета) 1.0.5 от 02.07.2021: 1. Для раскраски неизменённого текста использована "прозрачность" :-) Посмотрим, как народ отреагирует… 2. Исправлена ошибка, из-за которой в команду помещался заголовок диалога. ]]; --parent_id = ""; --minfarversion = {3,0,0,4744,0}; --files = "*.cfg;*.ru.lng"; --config = function(nfo,name) end; help = function(nfo,name) far.Message( ' Макрос работает в немодальном редакторе. По Ctrl+O не просто показывает экран консоли, ' .. 'а переключает в среду панелей и гасит последние. Это даёт возможность вводить команды ' .. 'в командную строку.\n\n' .. ' Возврат в редактор осуществляется по повторному Ctrl+O или по Esc.\n\n' .. ' Если в исходном редакторе есть отмеченный текст, то по клавише Alt+V отмеченный текст '.. 'вставляется в командную строку.', 'EditorToCmdLine', nil, 'l' ) end; --execute = function(nfo,name) end; --disabled = false; --options = {}; } if not nfo then return end --local O = nfo.options local F = far.Flags local EdiStack = {} local h_Dlg = nil local prio,CtrlO = 50,"CtrlO" ----------------- Утилиты -------------------------------- local function SwitchToPan(sCmd) local wi = far.AdvControl(F.ACTL_GETWINDOWINFO) EdiStack[#EdiStack+1] = {Type=wi.Type; Id=wi.Id} for i=1,far.AdvControl(F.ACTL_GETWINDOWCOUNT) do wi = far.AdvControl(F.ACTL_GETWINDOWINFO, i) if wi.Type == F.WTYPE_PANELS then far.AdvControl(F.ACTL_SETCURRENTWINDOW, wi.Pos) EdiStack[#EdiStack].NeedOnOff = APanel.Visible or PPanel.Visible if EdiStack[#EdiStack].NeedOnOff then Keys(CtrlO) end if sCmd then if type(sCmd) == 'string' then sCmd = {sCmd} end for _,v in ipairs(sCmd) do panel.SetCmdLine(nil, v) panel.SetCmdLinePos(nil, v:len()+1) Keys"Enter" end end return true end end end -- SwitchToPan ----------------- Переключение на панели ------------------ Macro{ id="FD02076B-828F-475A-A19E-95B99199DE5D"; area="Editor"; key=CtrlO; description="Командная строка в редакторе по "..CtrlO; flags=""; priority=prio; condition = function(key, data) return not next(EdiStack) and band(far.AdvControl(F.ACTL_GETWINDOWINFO).Flags, F.WIF_MODAL) == 0 end; action=function(data) SwitchToPan() end; } ------------------ Восстановление в редактор ------------------ local function RestEdit() -- 1. Восстановление видимости панелей if EdiStack[#EdiStack].NeedOnOff then Keys(CtrlO) end -- 2. Возврат к редактору local wi for i=1,far.AdvControl(F.ACTL_GETWINDOWCOUNT) do wi = far.AdvControl(F.ACTL_GETWINDOWINFO, i) if wi.Type == EdiStack[#EdiStack].Type and wi.Id == EdiStack[#EdiStack].Id then far.AdvControl(F.ACTL_SETCURRENTWINDOW, wi.Pos) break end end table.remove(EdiStack) end -- RestEdit Macro{ id="4AF3D4C8-5A89-40ED-8407-F7EBFAA3C416"; area="Shell"; key=CtrlO; description="Восстановление редактора по "..CtrlO; priority=prio; condition=function(key, data) return not not next(EdiStack) end; action=function(data) RestEdit() end; } --------------------- Macro{ id="379D0E92-9830-4C03-A22D-483CCD042C36"; area="Shell"; key="Esc"; description="Восстановление редактора по Esc"; flags="EmptyCommandLine"; priority=99; condition=function(key, data) return not not next(EdiStack) end; action=function(data) RestEdit() end; } ----------------- Обработка закрытия редактора -------------------------- Event { id = "AA556FB4-5DF7-42D4-8CD6-DD177A725A7F"; group = "EditorEvent"; description = "Закрытие редактора"; condition = function(EditorID, Event, Param) return Event==F.EE_CLOSE end; action = function(EditorID, Event, Param) for i,v in ipairs(EdiStack) do if v.Type == F.WTYPE_EDITOR and v.Id == EditorID then table.remove(EdiStack, i) break end end end; } ------------- Вставка отмеченного в комстроку ------------- -- Функция получения строки отмеченного local function GetSel(EdId) local aSel = editor.GetSelection(EdId) if not aSel then return end if aSel.BlockType == F.BTYPE_COLUMN then local asSel = {} for i=aSel.StartLine, aSel.EndLine do asSel[#asSel+1] = editor.GetString(EdId, i, 3):sub(aSel.StartPos, aSel.EndPos) end return table.concat(asSel, '\n') .. '\n' elseif aSel.BlockType == F.BTYPE_STREAM then if aSel.EndLine == aSel.StartLine then return editor.GetString(EdId, aSel.StartLine, 3):sub(aSel.StartPos, aSel.EndPos) else local asSel = {editor.GetString(EdId, aSel.StartLine, 3):sub(aSel.StartPos)} for i=aSel.StartLine+1, aSel.EndLine-1 do asSel[#asSel+1] = editor.GetString(EdId, i, 3) end asSel[#asSel+1] = editor.GetString(EdId, aSel.EndLine, 3):sub(1,aSel.EndPos) return table.concat(asSel, '\n') end else return end end -- GetSel Macro{ id="5D5C23EA-097D-4416-A8F6-B448AD491111"; area="Shell"; key="AltV"; description="Вставка отмеченного из редактора в комстроку"; flags=""; priority=prio; condition=function(key, data) if next(EdiStack) then local SelStr = GetSel(EdiStack[#EdiStack].Id) if SelStr then data.SelStr = SelStr return true end end end; action=function(data) print(data.SelStr) end; } ------------------ То же самое, но через диалог ---------------------- --local DialogTools = require"BAX.DialogTools" --local DialogItem = DialogTools.DialogItem Macro{ id="A0BC0F20-85BF-4698-8D63-2AC3AEFCE772"; area="Editor"; -- Other Search Dialog Help FindFolder UserMenu ShellAutoCompletion Menu Grabber Editor Viewer Tree QView Desktop DialogAutoCompletion Info MainMenu Disks Shell key="CtrlShiftO"; description="КомСтрока из редактора"; flags=""; -- EnableOutput RunAfterFARStart EmptyCommandLine NotEmptyCommandLine NoFilePanels NoFilePPanels NoPluginPanels NoPluginPPanels NoFolders NoPFolders NoFiles NoPFiles Selection PSelection NoSelection NoPSelection EVSelection NoEVSelection NoSendKeysToPlugins priority=prio; condition = function() return not not Far.GetConfig('Editor.ShowKeybar') and not next(EdiStack) end; action=function(data) local EdId = far.AdvControl(F.ACTL_GETWINDOWINFO).Id if h_Dlg == nil then local aDlg = { --DialogItem{'DI_EDIT', x1=2, x2=Far.Width-12, y1=0, y2=0; Flags='DIF_HISTORY|DIF_USELASTHISTORY'; History='Editor.CmdLine'}; --DialogItem{'DI_BUTTON', x1=Far.Width-10, y1=0, Text='Run!'; Flags='DIF_DEFAULTBUTTON'}; --, Flags='DIF_NOBRACKETS'}; {'DI_DOUBLEBOX', 0, 0, Far.Width-1, 2, 0,0,0,0,'Командная строка'}; {"DI_EDIT", 2, 1, Far.Width-13, 1, 0, "Editor.CmdLine", 0, bor(F.DIF_HISTORY, F.DIF_USELASTHISTORY)}; {"DI_BUTTON", Far.Width-10, 1, 0, 1, 0, 0, 0, F.DIF_DEFAULTBUTTON, "Run!"}; } local iBox, iEdit, iRun = 1,2,3 --*D* { --do -- local TabUtils=require"Bax.TabUtils" -- local TabToStr=TabUtils.TableToString -- local hf=io.open([[C:\Users\PC\AppData\Roaming\Far Manager\Profile\Macros\scripts\Bax\EditorToCmdLine\aDlg.lua]], 'w') -- if hf then -- hf:write(TabToStr(aDlg[1], ', ')..';\n') -- hf:write(TabToStr(aDlg[2], ', ')..';\n') -- hf:close() -- end --end --*D* } local function fDlg(hDlg, Msg, Param1, Param2) if Msg == F.DN_CTLCOLORDIALOG then Param2.BackgroundColor = 0 Param2.ForegroundColor = 7 return Param2 elseif Msg == F.DN_CTLCOLORDLGITEM then if Param1 == iBox then -- Title Param2[1].BackgroundColor = 0xFF000000 + 0 Param2[1].ForegroundColor = 0xFF000000 + 0x7 Param2[1].Flags = bor(F.FCF_FG_4BIT, F.FCF_BG_4BIT) -- HiText Param2[2].BackgroundColor = 0xFF000000 + 0 Param2[2].ForegroundColor = 0xFF000000 + 0x7 Param2[2].Flags = bor(F.FCF_FG_4BIT, F.FCF_BG_4BIT) -- Box Param2[3].BackgroundColor = 0xFF000000 + 0 Param2[3].ForegroundColor = 0xFF000000 + 0x2 Param2[3].Flags = bor(F.FCF_FG_4BIT, F.FCF_BG_4BIT) return Param2 elseif Param1 == iEdit then -- Изменённый текст Param2[1].BackgroundColor = 0xFF000000 + 0 Param2[1].ForegroundColor = 0xFF000000 + 0x7 Param2[1].Flags = bor(F.FCF_FG_4BIT, F.FCF_BG_4BIT) -- Отмеченный текст. Param2[2].BackgroundColor = 0xFF000000 + 0x7 Param2[2].ForegroundColor = 0xFF000000 + 0 Param2[2].Flags = bor(F.FCF_FG_4BIT, F.FCF_BG_4BIT) -- Неизменённый текст Param2[3].BackgroundColor = 0x20000000 + 0x7 Param2[3].ForegroundColor = 0xFF000000 + 0x7 Param2[3].Flags = bor(F.FCF_FG_4BIT, F.FCF_BG_4BIT) -- Стрелка для вызова истории Param2[4].BackgroundColor = 0xFF000000 + 0 Param2[4].ForegroundColor = 0xFF000000 + 0xF Param2[4].Flags = bor(F.FCF_FG_4BIT, F.FCF_BG_4BIT) return Param2 elseif Param1 == iRun then if hDlg:send(F.DM_GETFOCUS) == iRun then Param2[1].BackgroundColor = 0xFF000000 + 0x2 Param2[1].ForegroundColor = 0xFF000000 + 0xe Param2[1].Flags = bor(F.FCF_FG_4BIT, F.FCF_BG_4BIT) Param2[2].BackgroundColor = 0xFF000000 + 0xe Param2[2].ForegroundColor = 0xFF000000 + 0x2 Param2[2].Flags = bor(F.FCF_FG_4BIT, F.FCF_BG_4BIT) else Param2[1].BackgroundColor = 0xFF000000 + 0x7 Param2[1].ForegroundColor = 0xFF000000 + 0x0 Param2[1].Flags = bor(F.FCF_FG_4BIT, F.FCF_BG_4BIT) Param2[2].BackgroundColor = 0xFF000000 + 0x0 Param2[2].ForegroundColor = 0xFF000000 + 0x7 Param2[2].Flags = bor(F.FCF_FG_4BIT, F.FCF_BG_4BIT) end --Param2[2] = Param2[1] return Param2 end elseif Msg == F.DN_CONTROLINPUT then if Param1 == -1 then local wc = far.AdvControl(F.ACTL_GETWINDOWCOUNT) if wc > 1 then far.AdvControl(F.ACTL_SETCURRENTWINDOW, wc-1) end return true elseif Param1 == iEdit and Param2.EventType == F.KEY_EVENT then local key = far.InputRecordToName(Param2) if key == 'AltV' then local Sel = GetSel(EdId) if Sel then local EdSel = hDlg:send(F.DM_GETSELECTION, iEdit) if EdSel.BlockType ~= F.BTYPE_NONE then local Sel1,Sel2, txt = EdSel.BlockStartPos, EdSel.BlockWidth, hDlg:send(F.DM_GETTEXT, iEdit) hDlg:send(F.DM_SETTEXT, iEdit,txt:sub(1,Sel1-1) .. Sel .. txt:sub(Sel1+Sel2) ) hDlg:send(F.DM_SETEDITPOSITION, iEdit, {CurPos=Sel1 + Sel:len()}) else local ePos, txt = hDlg:send(F.DM_GETEDITPOSITION, iEdit).CurPos, hDlg:send(F.DM_GETTEXT, iEdit) hDlg:send(F.DM_SETTEXT, iEdit, txt:sub(1,ePos-1) .. Sel .. txt:sub(ePos)) hDlg:send(F.DM_SETEDITPOSITION, iEdit, {CurPos=ePos+Sel:len()}) end end end end elseif Msg == F.DN_CLOSE then h_Dlg = nil if Param1 == iRun then local sCmd = hDlg:send(F.DM_GETTEXT, iEdit) if sCmd:find"%S" then mf.postmacro(SwitchToPan, {sCmd}) end end end -- Switch on Msg end -- fDlg h_Dlg = far.DialogInit(win.Uuid'D317FCE6-0718-41A1-B2B0-4A08E40757D2', 0, Far.Height-3, Far.Width, Far.Height-1, nil, aDlg, bor(F.FDLG_NONMODAL,F.FDLG_NODRAWSHADOW), fDlg) else for i=1, far.AdvControl(F.ACTL_GETWINDOWCOUNT) do local wi = far.AdvControl(F.ACTL_GETWINDOWINFO, i) if wi.Type == F.WTYPE_DIALOG and wi.Id == h_Dlg then far.AdvControl(F.ACTL_SETCURRENTWINDOW, wi.Pos) break end end end end; } |