возможность из Lua писать в консольный буфер FARа

Здесь обсуждается всё, что касается макросов.
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

возможность из Lua писать в консольный буфер FARа

Post by John Doe »

Latest post of the previous page:

Воот.
Был плагин. И в код его вы вероятно не заглядывали.
Ответ я уже дал выше: http://forum.farmanager.com/viewtopic.p ... 03#p125203
AleXH
Posts: 1000
Joined: Sun 12 Apr, 2009 05:21
Been thanked: 1 time

возможность из Lua писать в консольный буфер FARа

Post by AleXH »

О! Понял :) Спасибо, проверил - арбайтен :)
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

возможность из Lua писать в консольный буфер FARа

Post by John Doe »

Shmuel wrote: Раз пошла такая пьянка, вот модификация, которая позволяет (у меня по крайней мере) выводить и русский текст, если на входе UTF-8. "Чисто юникодные" символы, естественно, таким путём не выведешь.

Code: Select all

function printToFARConsole(...)
  local OemCp = win.GetOEMCP()
  panel.GetUserScreen()
  for k=1, select("#",...) do
    local s = select(k,...)
    s = win.WideCharToMultiByte(win.Utf8ToUtf16(s),OemCp)
    io.write(s)
  end
  io.write("\n")
  panel.SetUserScreen()
end
С использованием win.Utf8ToOEM получается так:

Code: Select all

function printToFARConsole(...)
  panel.GetUserScreen()
  for k=1, select("#",...) do
    io.write(win.Utf8ToOEM(select(k,...)))
  end
  io.write("\n")
  panel.SetUserScreen()
end
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

возможность из Lua писать в консольный буфер FARа

Post by John Doe »

gotar wrote: Tue 26 Aug, 2014 17:26Многие ли пользуются функцией print? Предлагаю сделать поведение функции print более похожим на print в обычном lua, т.е. print мог бы выводить информацию на Descktop (ConsoleOutput) [...]
Вот функция, по поведению максимально приближённая к стандартной Lua

Code: Select all

local function _tostr(arg)
  return win.Utf8ToOem(tostring(arg))
end
local function printToFARConsole(...)
  local n = select("#",...)
  panel.GetUserScreen()
  if n>0 then
    io.write(_tostr(...))
    for i=2,n do
      io.write("\t",_tostr(select(i,...)))
    end
  end
  --io.write("\n")
  panel.SetUserScreen()
end
--io.write("\n") закомментирован, потому что panel.SetUserScreen() сам по себе вставляет пустую строку (что нежелательно, и будет предметом очередного тикета на мантисе: 3525)
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

возможность из Lua писать в консольный буфер FARа

Post by John Doe »

Вероятно, вместо того чтобы закладываться на OemCP, лучше определять CP динамически.

Code: Select all

local ffi = require"ffi"
local C = ffi.C

ffi.cdef[[
//https://docs.microsoft.com/en-us/windows/console/getconsoleoutputcp
UINT GetConsoleOutputCP(void); //WINAPI
]]

local OutputCP
local function _tostr(arg)
  return win.WideCharToMultiByte(win.Utf8ToUtf16(tostring(arg)),OutputCP)
end
local function printToFARConsole(...)
  local n = select("#",...)
  panel.GetUserScreen()
  if n>0 then
    OutputCP = C.GetConsoleOutputCP()
    io.write(_tostr(...))
    for i=2,n do
      io.write("\t",_tostr(select(i,...)))
    end
  end
  --io.write("\n")
  panel.SetUserScreen()
end
User avatar
DrKnS
Posts: 6114
Joined: Thu 04 Aug, 2005 06:44
Location: Kyiv
Has thanked: 12 times
Been thanked: 426 times

возможность из Lua писать в консольный буфер FARа

Post by DrKnS »

Если вы все равно используете ффи, почему бы не протащить WriteConsoleW и не портить данные?
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

возможность из Lua писать в консольный буфер FARа

Post by John Doe »

Действительно

Code: Select all

local printToFARConsole do
  local ffi = require"ffi"
  local C = ffi.C

  ffi.cdef[[
  //https://docs.microsoft.com/en-us/windows/console/getstdhandle
  HANDLE GetStdHandle(                    //WINAPI
    DWORD nStdHandle                      //_In_
  );
  //https://docs.microsoft.com/en-us/windows/console/writeconsole
  BOOL WriteConsoleW(                     //WINAPI
          HANDLE  hConsoleOutput,         //_In_
    const VOID    *lpBuffer,              //_In_
          DWORD   nNumberOfCharsToWrite,  //_In_
          LPDWORD lpNumberOfCharsWritten, //_Out_
          LPVOID  lpReserved              //_Reserved_
  );
  ]]
  local STD_OUTPUT_HANDLE = ffi.new("DWORD",-11)
  local INVALID_HANDLE_VALUE = ffi.cast("HANDLE",-1)

  local hConsoleOutput
  local function GetOutputHandle()
    hConsoleOutput = C.GetStdHandle(STD_OUTPUT_HANDLE)
    if hConsoleOutput==INVALID_HANDLE_VALUE then
      far.Message("GetStdHandle failed","Error",nil,"ew")
      error("GetStdHandle",2)
    end
  end
  local lpNumberOfCharsWritten = ffi.new"DWORD[1]"
  local function WriteConsole(str)
    local len = str:len()
    local wstr = win.Utf8ToUtf16(str.."\0")
    if 0==C.WriteConsoleW(hConsoleOutput,ffi.cast("const VOID*",wstr),len,lpNumberOfCharsWritten,nil) then
      far.Message("WriteConsoleW failed","Error",nil,"ew")
      error("WriteConsole",2)
    end
  end
  function printToFARConsole(...)
    GetOutputHandle()
    local n = select("#",...)
    panel.GetUserScreen()
    if n>0 then
      WriteConsole(tostring(...))
      for i=2,n do
        WriteConsole("\t")
        WriteConsole(tostring(select(i,...)))
      end
    end
    --WriteConsole("\n") --https://bugs.farmanager.com/view.php?id=3525
    panel.SetUserScreen()
  end
end

Надо только учитывать, что в этом варианте не будет работать перенаправление в файл (но в фаре такого быть не может).
Last edited by John Doe on Mon 06 Nov, 2017 14:03, edited 1 time in total.
User avatar
zg
zero-gravity
Posts: 6035
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 185 times
Contact:

возможность из Lua писать в консольный буфер FARа

Post by zg »

а что не так:

Code: Select all

local ffi=require("ffi")
local C=ffi.C
ffi.cdef[[int wprintf(const wchar_t*,...);]]
panel.GetUserScreen()
C.wprintf(ffi.cast("const wchar_t*",win.Utf8ToUtf16("превед медвед\0")))
panel.SetUserScreen()
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

возможность из Lua писать в консольный буфер FARа

Post by John Doe »

У меня не заработало.
Возвращает -1

Edit: проблема именно с кириллицей
Last edited by John Doe on Mon 06 Nov, 2017 13:10, edited 1 time in total.
User avatar
zg
zero-gravity
Posts: 6035
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 185 times
Contact:

возможность из Lua писать в консольный буфер FARа

Post by zg »

файл в какой кодировке?
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

возможность из Lua писать в консольный буфер FARа

Post by John Doe »

В utf8. Но пробовал и 1251/866

Windows XP
User avatar
zg
zero-gravity
Posts: 6035
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 185 times
Contact:

возможность из Lua писать в консольный буфер FARа

Post by zg »

в 10-ке всё окей. в w2k3 выводит в 1251. видимо от версии msvcrt зависит.
Last edited by zg on Mon 06 Nov, 2017 15:31, edited 1 time in total.
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

возможность из Lua писать в консольный буфер FARа

Post by John Doe »

В 8.1 тоже кириллицу не выводит, хотя и возвращает 13
Post Reply

Return to “Обсуждение макросов”