Копирование файла в панель другого Фара

Хотите предложить идею нового плагина или знаете, что улучшить в существующем? Пишите сюда.
Max Rusov
Posts: 3600
Joined: Wed 23 Nov, 2005 11:11
Location: Москва-Питер
Been thanked: 7 times

Копирование файла в панель другого Фара

Post by Max Rusov » Tue 13 Jan, 2015 08:50

Latest post of the previous page:

John Doe wrote:Тут основная задача в другом: грамотно реализовать межпроцессное взаимодействие (IPC)
Проще всего - через Shared Memory.

iva
Posts: 123
Joined: Sat 02 Nov, 2013 21:32
Been thanked: 3 times

Копирование файла в панель другого Фара

Post by iva » Tue 13 Jan, 2015 10:34

John Doe » Вт 13 янв, 2015 12:47
Тут основная задача в другом: грамотно реализовать межпроцессное взаимодействие (IPC)
Я понимаю, что реализовать такое копирование при помощи межпроцессного взаимодействия очень интересно. Но, если я не пропускаю какие-то подводные камни, мне видится другой путь.
А именно, каждый экземпляр FAR создаёт в определённом месте на диске файл, в который по событию FE_REDRAW записывает пути к директориям, отображаемым в панелях (про временные панели пока не думаем). При завершении работы FAR этот файл удаляет.
Теперь, если в каком-то экземпляре FAR пользователь вызывает диалог копирования в панели другого FAR, то нужно прочитать все файлы, созданные всеми экземплярами FAR, и дальше разбираться со списком директорий.
Может быть, пока FE_REDRAW недоступен, можно организовать такую запись информации о состоянии панелей по таймеру. Мне для этого умения не хватает.

User avatar
John Doe
Бюрократ
Posts: 11217
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 14 times
Been thanked: 80 times

Копирование файла в панель другого Фара

Post by John Doe » Tue 13 Jan, 2015 10:48

iva wrote: мне видится другой путь.
Выше по теме уже предлагалось. Да, это должно быть возможно, хоть и с ограничениями.
iva wrote: можно организовать такую запись информации о состоянии панелей по таймеру. Мне для этого умения не хватает.
У кого-то умения, а у кого-то желания.

iva
Posts: 123
Joined: Sat 02 Nov, 2013 21:32
Been thanked: 3 times

Копирование файла в панель другого Фара

Post by iva » Tue 13 Jan, 2015 16:04

Вот то, что я умею сходу. Не судите строго.
Чтобы работало нужно в %FARPROFILE% создать поддиректорию PanelInfo.
Пока я повесил запись состояния на Enter, а надо бы на событие смены папок или, хотя бы, на таймер .
Операцию получения данных от всех экземпляров FAR повесил на ShiftF7.
Как реализовать выбор из того списка, который получается, и собственно копирование я пока не знаю.
Attachments
CopyToOtherFar.lua.7z
(871 Bytes) Downloaded 30 times

User avatar
John Doe
Бюрократ
Posts: 11217
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 14 times
Been thanked: 80 times

Копирование файла в панель другого Фара

Post by John Doe » Tue 13 Jan, 2015 16:19

Всем было бы удобнее, если бы вы разместили код не вложением, а прямо в тексте, в теге [code]...[/code]

iva
Posts: 123
Joined: Sat 02 Nov, 2013 21:32
Been thanked: 3 times

Копирование файла в панель другого Фара

Post by iva » Tue 13 Jan, 2015 17:17

вот уже чуть исправленное

Code: Select all

local unit = {}
 local FILENAME

local function ExpandEnv (s)
  return s:gsub("%%(.-)%%", win.GetEnv) -- подставляет значение %FARPROFILE%
end

-- Парсинг имени файла, на входе имя_файла
-- на выходе {диск, путь, имя, расширение}
local function ParseFileName(str)
	local a, b, c, d
	if str == nil then str="" end

	a = string.match(str, "^%s*(.*:)")
	str=str:gsub("^%s*(.*:)","")

	b=string.match(str, "^(.*)[\\/]")
	str=str:gsub("^(.*)[\\/]","")

	d=string.match(str, "%.([^%.]*)$")
	c=str:gsub("%.([^%.]*)$","")

	if d == nil then d="" end
	if c == nil then c="" end
	if b == nil then b="" end
	if a == nil then a="" end
	
	return a, b, c, d
end


do
 function unit.DefinePanelInfoFileName()
   local  Path = ExpandEnv([[%FARPROFILE%\PanelInfo\]])
   local List = far.GetDirList(Path)
   local no = 0
   if #List then
    for i = 1, #List do
     local a,b,c,d = ParseFileName(List[i].FileName)
     local n = tonumber(c)
     if no < n then no = n end
    end -- нашли максимум  
   end
   FILENAME = Path..(no+1) -- здесь надо брать номер на 1 больше, чем тот,
                                 -- который существует   
--   far.Message('FILENAME='..FILENAME) --
 end

 function unit.SavePanelInfo()
   if FILENAME == nil then unit.DefinePanelInfoFileName() end
   local f=io.output(FILENAME)
   local ADir = panel.GetPanelDirectory(nil,0)
   local BDir = panel.GetPanelDirectory(nil,1)
   f:write(ADir.Name.."\n")
   f:write(BDir.Name.."\n")
   f:close()
--   far.Message('WRITTEN: to '..FILENAME) --
 end

function unit.CopyToPanelsOfOtheFar()
   local  Path = ExpandEnv([[%FARPROFILE%\PanelInfo\]])
   local List = far.GetDirList(Path)
   local A = {}
   local B = {}
   for i = 1,#List do
     local name = List[i].FileName
     local f=io.input(name)
     A[i] = f:read()
     B[i] = f:read()
     f:close()
   end
   local s = 'LIST of directories'
   for i = 1,#List do
     s = s..'\nFAR<'..i..'>: \n'..A[i]..'\n'..B[i]
   end
   far.Message(s)
 end

 function unit.RemovePanelInfo()
   os.remove(FILENAME)
 end
end -- do
-----------------------------------------------------------------
Event { group = "ExitFAR", description = "Remove information file",
  action = function ()
    unit.RemovePanelInfo()
  end,
} -- Event "ExitFAR"

Macro { description="Save Panel Info to information file";
  area="Shell"; key="Enter";
  condition=function()
    unit.SavePanelInfo()
    return false
  end;
  action=function()
  end;
}

Macro { description="Get Panel Info from all Far's";
        area="Shell"; key="ShiftF7";
        action=function()
        unit.CopyToPanelsOfOtheFar()
        end;
}

iva
Posts: 123
Joined: Sat 02 Nov, 2013 21:32
Been thanked: 3 times

Копирование файла в панель другого Фара

Post by iva » Tue 13 Jan, 2015 23:16

Вроде такой вариант рабочий.
Напоминаю, что должна быть создана директория %FARPROFILE%\PanelInfo

Code: Select all

local unit = {}
 local FILENAME

local function ExpandEnv (s)
  return s:gsub("%%(.-)%%", win.GetEnv) -- подставляет значение %FARPROFILE%
end

do
 function unit.DefinePanelInfoFileName()
   local Path = ExpandEnv([[%FARPROFILE%\PanelInfo\]])
   FILENAME = Path..os.date("%d_%H_%M_%S") -- имя по дате
 end

 function unit.SavePanelInfo()
   if FILENAME == nil then unit.DefinePanelInfoFileName() end
   local f=io.output(FILENAME)
   local ADir = panel.GetPanelDirectory(nil,0)
   local BDir = panel.GetPanelDirectory(nil,1)
   f:write(ADir.Name.."\n")
   f:write(BDir.Name.."\n")
   f:close()
 end

function unit.CopyToPanelsOfOtherFar()
   local Path = ExpandEnv([[%FARPROFILE%\PanelInfo\]])
   local List = far.GetDirList(Path)
   local Items = {}
   local name = panel.GetCurrentPanelItem(nil,1) -- File to copy
   name = name.FileName
   local width = name:len() + 13
   for i = 1,#List do
     local name = List[i].FileName
     if name ~= FILENAME then                    -- Exclude itself
       local f=io.input(name)
       local A = f:read()
       local curw = A:len()
       if width < curw then width = curw end
       table.insert(Items,{ Flags = 0, Text = A })
       A = f:read()
       curw = A:len()
       if width < curw then width = curw end
       table.insert(Items,{ Flags = 0, Text = A })
       f:close()
     end
   end
  if #Items then                 
    local Form = {{"DI_LISTBOX", 0, 0, width+3, #Items+1, Items, 0, 0, 0, 
                   "Copy '"..name.."' to:"}}

    local function DlgProc (dlg, msg, param1, param2) end -- заглушка

    local hDlg = far.DialogInit("",5,5,8+width, 6+#Items, nil, Form, 0, DlgProc)
    local Index = far.DialogRun(hDlg) > 0 and
      far.SendDlgMessage(hDlg, far.Flags.DM_LISTGETCURPOS, 1).SelectPos or nil
    far.DialogFree(hDlg)
    if Index then
      local to = Items[Index].Text..[[\]]..name
      Keys("F5")
      print(to)
      Keys("Enter")
    end
  end
end

 function unit.RemovePanelInfo()
   os.remove(FILENAME)
 end
end -- do
-----------------------------------------------------------------
Event { group = "ExitFAR", description = "Remove information file",
  action = function ()
    unit.RemovePanelInfo()
  end,
} -- Event "ExitFAR"

Macro { description="Save Panel Info to information file";
  area="Shell"; key="Enter";
  condition=function()
    unit.SavePanelInfo()
    return false
  end;
  action=function()
  end;
}

Macro { description="Copy current file to other Far's";
        area="Shell"; key="ShiftF7";
        action=function()
          unit.CopyToPanelsOfOtherFar()
        end;
}

User avatar
John Doe
Бюрократ
Posts: 11217
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 14 times
Been thanked: 80 times

Копирование файла в панель другого Фара

Post by John Doe » Wed 14 Jan, 2015 08:51

iva, вы напрасно усложнили задачу: не надо ничего копировать.
Достаточно только подставлять путь в стандартный диалог копирования/перемещения.

Что касается имён файлов, то для уникальности проще всего использовать Far.PID

fml2
Posts: 490
Joined: Mon 09 Jul, 2012 22:10
Has thanked: 1 time
Been thanked: 5 times

Копирование файла в панель другого Фара

Post by fml2 » Wed 14 Jan, 2015 10:55

iva, я думал сделать что-то более общее и сложное, на основе чего можно было бы довольно легко реализовать и копирование (но и многое другое) -- подход математика-теоретика. А вы быстро сделали нечто более ограниченное, но именно то, что надо -- подход инженера! :-)

iva
Posts: 123
Joined: Sat 02 Nov, 2013 21:32
Been thanked: 3 times

Копирование файла в панель другого Фара

Post by iva » Wed 14 Jan, 2015 17:25

Я, к сожалению, исчерпал лимит свободного времени и в ближайшие дни не смогу дорабатывать код. Если кто-нибудь, доведёт до ума - было бы здорово.
Я планировал повесить запись в информационный файл, который сейчас повешен на Enter, на все кнопкосочетания, пробовал так

Code: Select all

  key=[[/[\w]/ Enter Tab Left Right Up Down Esc /F[1-9]/ F11 F12]]; 
Далее, надо было бы делать такую запись в режиме пост-обработки. Сходу, я не уверен, что правильно понял John Doe про Keys"Akey". Особенно меня смущает случай, когда нажата клавиша выхода из Far.
И, действительно, хорошо было бы встроится в стандартный диалог копирования, но я пока не умею.

fml2: Вы интересно расклассифицировали подходы.

P.S. A как оформляется "офтопик"?

User avatar
John Doe
Бюрократ
Posts: 11217
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 14 times
Been thanked: 80 times

Копирование файла в панель другого Фара

Post by John Doe » Wed 14 Jan, 2015 17:29

iva wrote: P.S. A как оформляется "офтопик"?
Никак. Просто его следует избегать.
iva wrote: И, действительно, хорошо было бы встроится в стандартный диалог копирования, но я пока не умею.
Ваш макрос мог бы вызываться прямо из диалога копирования, а не из панелей.

User avatar
John Doe
Бюрократ
Posts: 11217
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 14 times
Been thanked: 80 times

Копирование файла в панель другого Фара

Post by John Doe » Wed 14 Jan, 2015 20:50

Вот набросал что-то.

При вызове опрашивает прочие запущенные экземпляры фара, и предоставляет выбор из списка путей на их панелях.

Вызывается так:
— комбинацией CtrlUp (в предопредёлённых диалогах)
— из меню плагинов (во всех диалогах, а также в редакторе и командной строке)
Attachments
PickPathFromOtherFAR.lua.7z
(1.75 KiB) Downloaded 79 times

fml2
Posts: 490
Joined: Mon 09 Jul, 2012 22:10
Has thanked: 1 time
Been thanked: 5 times

Копирование файла в панель другого Фара

Post by fml2 » Wed 14 Jan, 2015 22:58

Работает! Здорово, спасибо!

Есть еще следующие предложения. Я сам не уверен, стоит ли их реализовывать, но обдумать, по-моему, неплохо бы. Может, сделать опции?

1. Сортировать все пункты по алфавиту. Если других экземпляров Фара много, то уже не помнишь, где там что, и поэтому, наверное, будет легче найти искомый элемент, если элементы отсортированы по алфавиту.

2. Включать в список и пути из "собственного" экземпляра. Бывает, надо скопировать куда-то, и я точно знаю, что путь назначения где-то открыт. Но уже не помню где, т.к. внимание сконцентрировано только на одной (активной) панели -- настолько, что даже не помню, какой путь на неактивной.

3. Включать в список каждое значение только один раз, если один и тот же путь открыт в нескольких экземплярах Фара (т.е., иными словами, исключать дубликаты)

4. Сделать вызов скрипта возможным и из диалога перемещения файлов (а не только копирования)

Спасибо iva и вам за скрипт!

iva
Posts: 123
Joined: Sat 02 Nov, 2013 21:32
Been thanked: 3 times

Копирование файла в панель другого Фара

Post by iva » Sat 17 Jan, 2015 15:36

Postby John Doe » Wed 14 Jan, 2015 20:50
Вот набросал что-то:
Заглянул на форум и обрадовался, что мои каракули подвигли Вас, John Doe, написать такой макрос. Как я понял, Вы посчитали, что выгоднее привязать создание файлов с данными о директориях с запросом на копирование, а не со сменой каталога, как пытался сделать я.
Ваш код меня многому научил, остался только один вопрос: почему Вы использовали mf.postmacro(print, item.text), а не просто print(item.text)? Надеюсь, не для того чтобы у меня на 3.0.3525 не работало (шутка).

User avatar
John Doe
Бюрократ
Posts: 11217
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 14 times
Been thanked: 80 times

Копирование файла в панель другого Фара

Post by John Doe » Sat 17 Jan, 2015 22:48

fml2, ok.
iva wrote: почему Вы использовали mf.postmacro(print, item.text)
Иначе не будет работать из меню плагинов.

fml2
Posts: 490
Joined: Mon 09 Jul, 2012 22:10
Has thanked: 1 time
Been thanked: 5 times

Копирование файла в панель другого Фара

Post by fml2 » Sun 18 Jan, 2015 10:50

Я тоже пытаюсь учиться по вашим скриптам. Если я правильно понял, работа скрипта основана на том, что каждый экземпляр Фара 20 раз в секунду (poll_delay = 50) опрашивает, существует ли определенный файл. Есть ли это хорошо? Не слишком ли большая нагрузка на систему?

User avatar
John Doe
Бюрократ
Posts: 11217
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 14 times
Been thanked: 80 times

Копирование файла в панель другого Фара

Post by John Doe » Sun 18 Jan, 2015 12:28

fml2 wrote: Не слишком ли большая нагрузка на систему?
Думаю мизерная.

Давайте рассмотрим альтернативный подход: каждый экземпляр должен следить за изменениями пути. Допустим, это можно делать в 20 раз реже, 1 раз в секунду.
Но зато вместо простого вызова одной системной функции понадобиться следить за состоянием базы sqlite, что (не исключено) может получится и затратнее по ресурсам.

Без реальных измерений я затрудняюсь делать выводы.

Post Reply

Return to “Предложения и идеи”