Справка по изменениям в Macro API

Начиная с 30.09.2012 (Far 3.0.2851), в Far Manager вместо встроенного макроязыка используется скриптовый язык Lua 5.1.

Под макросом понимается Lua-скрипт и его мета-данные, такие как:

  • Область начала исполнения скрипта.
  • Клавиша, инициирующая исполнение скрипта из данной области.
  • Предварительные условия для исполнения скрипта.
  • Флаги времени исполнения: DisableOutput и NoSendKeysToPlugins.

Функциональность

  • Импорт и экспорт макросов.
  • Запись и воспроизведение макросов.
  • Библиотеки функций Lua.
  • Библиотеки функций LuaFAR (API плагинов).
  • Библиотеки функций макроязыка (API макросов).
  • API MacroControl для плагинов: все операции.


Библиотеки функций макроязыка

Описание API в данном документе не является самодостаточным, оно является дополняющим и уточняющим к описанию свойств и функций объектов Фара в разделе Макроязык Энциклопедии Фара.

В идеале, API должен совпадать с оригинальным API макроязыка, за исключением случаев, перечисленных в статье Изменения API в сравнении с макроязыком.


Изменения API в сравнении с макроязыком

  1. Все идентификаторы чувствительны к регистру символов.
  2. Вместо прямого указания клавиш используется функция Keys.
  3. $AKey -> Keys("AKey")
  4. $SelWord -> Keys("SelWord")
  5. $XLat -> Keys("XLat")
  6. $Exit -> exit()
  7. Логические свойства имеют тип boolean (поэтому нет смысла сравнивать их с числом 0).
  8. Функция prompt может возвращать либо стринг, либо false (но никогда не число 0).
  9. Многие функции помещены в таблицу mf (сокращение от macrofunctions), например: mf.abs, mf.fsplit и т.д.
  10. Функция mf.fexist возвращает булевое значение, а не число.
  11. Функции mload и msave изменились, см. их описание.
  12. Свойства, зависящие от контекста исполнения, находятся в таблице Object, например: Object.CurPos, Object.Empty.
  13. CheckHotkey -> Object.CheckHotkey
  14. GetHotkey -> Object.GetHotkey
  15. Логические свойства проверки области исполнения находятся в таблице Area, например: Area.Editor, Area.Shell.
  16. Macro.Area -> Area.Current.
  17. Dialog.AutoCompletion -> Area.DialogAutoCompletion
  18. Shell.AutoCompletion -> Area.ShellAutoCompletion
  19. CallPlugin -> Plugin.Call
  20. Dlg.Info.Id -> Dlg.Id
  21. Dlg.Info.Owner -> Dlg.Owner
  22. Far.Cfg.Get -> Far.Cfg_Get. Эта функция возвращает стринг в случае успеха или false в случае неудачи.
  23. Far.Cfg.Err больше не существует.
  24. FullScreen -> Far.FullScreen
  25. IsUserAdmin -> Far.IsUserAdmin
  26. History.Disable -> Far.DisableHistory
  27. KbdLayout -> Far.KbdLayout
  28. KeyBar.Show -> Far.KeyBar_Show
  29. Window.Scroll -> Far.Window_Scroll
  30. Menu.Info.Id -> Menu.Id
  31. MsX, MsY, MsButton, MsCtrlState, MsEventFlags — см. таблицу Mouse
  32. RCounter больше не существует.
  33. Macro.Const, Macro.Func, Macro.Keyword и Macro.Var больше не существуют.


Глобальные свойства и функции

Свойства: нет.

Функции:

  akey
  band, bnot, bor, bxor, lshift, rshift
  eval
  exit
  Keys
  mmode
  msgbox
  print
  printf
  prompt

Примечания:

1. Функции band, bnot, bor, bxor, lshift и rshift (операции с битами)
   - это глобальные ссылки на одноимённые функции из библиотеки bit64
   (см. LuaFAR manual).

2. Функции akey и mmode, будучи вызваны из функции condition макроса, возвращают false.

3. Для единообразия, все данные функции продублированы в таблице mf,
   например: eval и mf.eval - это одна и та же функция.


exit

exit ()

Параметры:
  нет

Возвращает:
  ничего

Описание:
  Завершить работу макроса.


Keys

Keys (...)

Параметры:
  Один или больше аргументов типа string.
  Каждый аргумент может содержать несколько ключей, разделённых пробельными символами.
  Аргументы регистронезависимы.

Возвращает:
  ничего

Описание:
  Послать один или более ключей Far Manager'у.

Примечания:

  1. Специальные ключи:
     "AKey"    - послать Far Manager'у клавишу, вызвавшую данный макрос.
     "SelWord" - выделить слово под курсором.
     "XLat"    - преобразовать слово под курсором.

Пример:
  mykeys = "CtrlF5 Esc"
  Keys("AKey A b CtrlC ShiftEnter", mykeys)


printf

printf (fmt, ...)

Параметры:
  fmt :  string
  ... :  0 или более параметров, в соответствии с форматом,
         заданным аргументом fmt.

Возвращает:
  ничего

Описание:
  Работает аналогично функции макроязыка print, но с дополнительной
  возможностью форматирования. Правила форматирования описаны в мануале Lua.


mf

Свойства: нет.

Функции:

  abs              len
  akey             lshift
  asc              max
  atoi             mdelete
  band             min
  beep             mload
  bnot             mmode
  bor              mod
  bxor             msave
  chr              msgbox
  clip             print
  date             printf
  env              prompt
  eval             replace
  exit             rindex
  fattr            rshift
  fexist           size2str
  float            sleep
  flock            string
  fmatch           strpad
  fsplit           strwrap
  iif              substr
  index            testfolder
  int              trim
  itoa             ucase
  key              usermenu
  Keys             waitkey
  lcase            xlat


mdelete

mf.mdelete (key, name)

Параметры:
  key:  string
  name: string

Возвращает:
  ничего

Описание:
  Функция mdelete удаляет значение или ключ из базы данных.
  Для удаления ключа следует указать параметр name == "*" (звёздочку).


mload

ret = mf.mload (key, name)

Параметры:
  key:   string
  name:  string

Возвращает:
  ret:   number, string, boolean, table или nil.

Описание:
  Функция mload читает значение из базы данных.


msave

mf.msave (key, name, value)

Параметры:
  key:         string
  name:        string
  value:       number, string, boolean или table

Возвращает:
  ничего

Описание:
  Функция msave сохраняет переданное значение в базу данных.
  При сохранении таблиц будут сохраняться только:
     ключи типов:    number, string, boolean.
     значения типов: number, string, boolean, table.
  Сохраняются и вложенные таблицы, при этом рекурсивные вложения пропускаются.


usermenu

mf.usermenu (mode, filename)

Параметры:
  mode:     number (0 по умолчанию)
  filename: string или nil

Возвращает:
  ничего

Описание:
  Открывает или создаёт пользовательское меню.

  - mode может содержать бит 0x100, в этом случае функция возвращается
    только по закрытии пользовательского меню (синхронный вызов). Если
    данный бит равен нулю, то функция возвращается немедленно по открытии
    меню (асинхронный вызов).

  Поведение функции в зависимости от величины младшего байта mode:

    0: равносильно нажатию F2 в панелях; filename игнорируется.
    1: выводится диалог выбора пользовательского меню; filename игнорируется.
    2: файл открывается "как есть", т.е. по заданному filename.
    3: файл filename открывается в %farprofile%\Menus (папка создаётся
       автоматически).


Area

Area - таблица со следующими полями:

Свойства:

  Current:               string
  Other:                 boolean
  Shell:                 boolean
  Viewer:                boolean
  Editor:                boolean
  Dialog:                boolean
  Search:                boolean
  Disks:                 boolean
  MainMenu:              boolean
  Menu:                  boolean
  Help:                  boolean
  Info:                  boolean
  QView:                 boolean
  Tree:                  boolean
  FindFolder:            boolean
  UserMenu:              boolean
  ShellAutoCompletion:   boolean
  DialogAutoCompletion:  boolean

Функции:

  Нет.


APanel, PPanel

APanel, PPanel - таблицы со следующими полями:

Свойства:

  Bof:          boolean
  ColumnCount:  number
  CurPos:       number
  Current:      string
  DriveType:    number
  Empty:        boolean
  Eof:          boolean
  FilePanel:    boolean
  Filter:       boolean
  Folder:       boolean
  Format:       string
  Height:       number
  HostFile:     string
  ItemCount:    number
  Left:         boolean
  LFN:          boolean
  OPIFlags:     number
  Path:         string
  Path0:        string
  Plugin:       boolean
  Prefix:       string
  Root:         boolean
  SelCount:     number
  Selected:     boolean
  Type:         number
  UNCPath:      string
  Visible:      boolean
  Width:        number

Функции:

  Нет.


Panel

Panel - таблица со следующими полями:

Свойства:

  Нет.

Функции:

  FAttr
  FExist
  Item
  Select
  SetPath
  SetPos
  SetPosIdx


BM

BM - таблица со следующими полями:

Свойства:

  Нет.

Функции:

  Add
  Back
  Clear
  Del
  Get
  Goto
  Next
  Pop
  Prev
  Push
  Stat


CmdLine

CmdLine - таблица со следующими полями:

Свойства:

  Bof:        boolean
  Empty:      boolean
  Eof:        boolean
  Selected:   boolean
  CurPos:     number
  ItemCount:  number
  Value:      string

Функции:

  Нет.


Dlg

Dlg - таблица со следующими полями:

Свойства:

  CurPos:     number
  Id:         string (GUID)
  Owner:      string (GUID)
  ItemCount:  number
  ItemType:   number
  PrevPos:    number

Функции:

  GetValue
  SetFocus


Drv

Drv - таблица со следующими полями:

Свойства:

  ShowMode:  number
  ShowPos:   number

Функции:

  Нет.


Editor

Editor - таблица со следующими полями:

Свойства:

  CurLine:   number
  CurPos:    number
  FileName:  string
  Lines:     number
  RealPos:   number
  SelValue:  string
  State:     number
  Value:     string

Функции:

  DelLine
  GetStr
  InsStr
  Pos
  Sel
  Set
  SetStr
  SetTitle
  Undo


Far

Far - таблица со следующими полями:

Свойства:

  FullScreen:      boolean
  Height:          number
  IsUserAdmin:     boolean
  PID:             number
  Title:           string
  UpTime:          number
  Width:           number

Функции:

  Cfg_Get
  DisableHistory
  KbdLayout
  KeyBar_Show
  Window_Scroll


Help

Help - таблица со следующими полями:

Свойства:

  FileName:  string
  SelTopic:  string
  Topic:     string

Функции:

  Нет.


Menu

Menu - таблица со следующими полями:

Свойства:

  Id:     string (GUID)
  Value:  string

Функции:

  Filter
  FilterStr
  GetValue
  ItemStatus
  Select
  Show


Mouse

Mouse - таблица со следующими полями:

Свойства:

  X:              number
  Y:              number
  Button:         number
  CtrlState:      number
  EventFlags:     number
  LastCtrlState:  number

Функции:

  Нет.

Примечание:

  Mouse.LastCtrlState отличается от Mouse.CtrlState тем, что обновляется
  как по событиям от мыши, так и по клавиатурным событиям.


Object

Свойства, зависящие от контекста исполнения.

Object: таблица со следующими полями:

Свойства:

  Bof:         boolean
  CurPos:      number
  Empty:       boolean
  Eof:         boolean
  Height:      number
  ItemCount:   number
  Selected:    boolean
  Title:       string
  Width:       number

Функции:

  CheckHotkey
  GetHotkey


Plugin

Plugin - таблица со следующими полями:

Свойства:

  Нет.

Функции:

  Call
  Command
  Config
  Exist
  Load
  Menu
  Unload


Plugin.Call

... = Plugin.Call (PluginId, ...)

Параметры:
  PluginId: string (GUID плагина в текстовом представлении)
  ...     : ноль или более дополнительных параметров

Возвращает:
  ...     : ноль или более возвращаемых значений

Описание:
  1. Параметры передаются плагину в соответствии с их Lua-типами:
       number   -> FMVT_DOUBLE
       boolean  -> FMVT_BOOLEAN
       string   -> FMVT_STRING  (автоматически преобразуется из UTF-8 в UTF-16LE)
       int64    -> FMVT_INTEGER (int64 - тип userdata, создаваемый библиотекой bit64)
       {string} -> FMVT_BINARY  (для того, чтобы передать произвольный стринг без
                                 преобразования UTF-8 -> UTF16LE, его нужно передавать,
                                 помещённым в таблицу как элемент с ключом 1)

  2. Если плагин не найден или вернул 0, макросу возвращается false.
     Если плагин вернул 1 или INVALID_HANDLE_VALUE, макросу возвращается true.

  3. Величины, возвращаемые плагином через структуру FarMacroCall, передаются макросу
     следующим образом:
       FMVT_DOUBLE  -> number
       FMVT_BOOLEAN -> boolean
       FMVT_STRING  -> string (автоматически преобразуется из UTF-16LE в UTF-8)
       FMVT_INTEGER -> number, если "укладывается" в 53 бита, иначе int64
       FMVT_BINARY  -> {string} (передаётся в таблице, как элемент с ключом 1,
                                как есть, без преобразования)

  4. При "асинхронном" вызове плагина, т.е. после вызова mmode(3,1), возвращается true,
     но только в случае, если вызов в действительности оказался "асинхронным", например,
     если плагин вывел диалог на экран. Иначе возвращается то, что вернул плагин.


Viewer

Viewer - таблица со следующими полями:

Свойства:

  FileName:  string
  State:     number

Функции:

  Нет.


Формат макросов


Спецификации ключей


Плагин Luamacro

Данный плагин необходим для работы макросов, поэтому должен быть установлен. То же касается и рантайма (файлы lua5.1.dll и luafar3.dll), необходимого для работы плагина.

Работа с командной строки (префикс LM)

    lm: load
    lm: save
    lm: post  <sequence>|@<filename>
    lm: check <sequence>|@<filename>
    lm: unload

Эти операции аналогичны операциям macro: плагина FarCmds, со следующими отличиями:

  1. Имя файла должно указываться сразу после символа @; символ < не поддерживается.
  2. lm:unload выгружает все макросы.


Разное


Макросы, начинающиеся с @

Если макропоследовательность начинается с символа @, то последующая её часть интерпретируется как имя файла, содержащего скрипт.

Переменные окружения расширяются.

Такие макросы легче отлаживать и модифицировать, так как не требуется их перезагрузка.

Пример: @%FARHOME%\macros\editor\shift.lua


Переменные

Окружение

Макросы, загружаемые из одного файла, имеют общее окружение (environment). Переменные, объявляемые без ключевого слова local, принадлежат этому окружению.

  Пример: var = 15

Переменные окружения макрофайла сохраняют свои значения между вызовами макросов. Их значения сбрасываются в исходные при выполнении любой операции загрузки макросов: старт Far Manager, macro:load, lm:load, far.MacroLoadAll, MacroControl(MCTL_LOADALL).

Глобальные переменные

Для установки глобальных переменных, значения которых будут сохраняться в течение всей сессии Far Manager и будут доступны всем скриптам, нужно использовать таблицу _G.

  Пример: _G.var = 15

Глобальные переменные не меняют своего значения даже при операциях перезагрузки макросов, за исключением рестарта Far Manager или перезагрузки плагина LuaMacro.

При чтении несуществующей переменной окружения, прочтётся одноимённая глобальная переменная (наследование в некотором смысле).

  Пример:
    var = 5
    _G.var = 10
    far.Message(var) --> 5
    var = nil
    far.Message(var) --> 10

Upvalues

Локальные переменные, доступные из функций одного или нескольких макросов (upvalues), являются общими для этих функций и сохраняют свои значения между вызовами макросов. Их значения сбрасываются в исходные при выполнении любой операции загрузки макросов.

  Пример:
    local var = 15
    function inc_var() var = var+1 end
    function dec_var() var = var-1 end


Ограничения в использовании некоторых функций

Следующие функции имеют особенности реализации, которые накладывают определённые ограничения на их использование в макросах:

  • exit
  • mf.usermenu (в “асинхронном” режиме вызова)
  • Keys
  • Plugin.Call
  • Plugin.Command
  • Plugin.Config
  • Plugin.Menu
  • print
  • printf

  1. Если макрос создаёт корутины с помощью coroutine.wrap(f), то вышеперечисленные функции не будут работать, будучи вызванными из тела функции f.
    Данного ограничения нет, если корутины создаются с помощью coroutine.create(f).

  2. Вышеперечисленные функции, будучи вызванными прямо или косвенно посредством функции pcall, приведут к немедленному возврату pcall с результатом false.
    Данного ограничения нет при использовании LuaJIT 2.0.

  3. Вышеперечисленные функции не будут работать, будучи вызванными из диалоговой процедуры. Однако их можно вызывать из диалоговой процедуры посредством far.MacroPost.

  4. Вышеперечисленные функции не будут работать, будучи вызванными из функции condition макроса.


Интроспекция

Содержимое глобальных таблиц API макроязыка можно просмотреть с помощью функции pairs, отдельно для функций и “свойств” таблицы.

На примере таблицы Editor:

    for k,v in pairs(Editor) do .... end -- для функций

    for k,v in pairs(Editor.properties) do .... end -- для свойств


unicode.utf8.cfind

Эта функция аналогична unicode.utf8.find, кроме того, что она принимает входное смещение и возвращает выходные смещения в символах, а не в байтах. (Исключением являются “position captures”, которые всё же возвращаются в байтах).


Примеры


Выделить слово под курсором

Macro {
  description="Выделить/снять выделение слова под курсором";
  area="Editor"; key="CtrlM";
  action=function()
    Keys"RCtrl9 CtrlRight CtrlLeft"
    Keys(Object.Selected and "CtrlU" or "CtrlShiftRight")
    Keys"Ctrl9"
  end;
}


Переход в меню выбора дисков

-- Переход в меню выбора дисков на противоположной панели,
-- включение видимости панели, в которой будет происходить
-- смена диска, если её не было.
Macro {
  description="Переход в меню выбора дисков на противоположной панели";
  area="Disks"; key="CtrlM";
  action=function()
    Keys"Esc"
    if not PPanel.Visible then
      Keys(APanel.Left and "CtrlF2" or "CtrlF1")
    end
    Keys"Tab F9 Enter End Enter"
  end;
}


Выделить файлы новее текущего

-- Выделить в активной панели все файлы/папки новее текущего,
-- используя API плагинов (LuaFAR).
Macro {
  description="Выделить в активной панели все файлы/папки новее текущего";
  area="Shell"; key="CtrlM";
  action=function()
    local info = panel.GetPanelInfo(nil,1)
    local curItem = panel.GetCurrentPanelItem(nil,1)
    for i=1,info.ItemsNumber do
      local item = panel.GetPanelItem(nil,1,i)
      if item.LastWriteTime > curItem.LastWriteTime then
        panel.SetSelection(nil,1,i,true)
      end
    end
    panel.RedrawPanel(nil,1)
  end;
}

-- Выделить в активной панели все файлы/папки новее текущего,
-- используя API макросов (LuaFAR + LuaMacro).
Macro {
  description="Выделить в активной панели все файлы/папки новее текущего";
  area="Shell"; key="CtrlM";
  action=function()
    d = Panel.Item(0,0,17)
    for i=1,APanel.ItemCount do
      if Panel.Item(0,i,17) > d then
        Panel.Select(0,1,1,i)
      end
    end
  end;
}


Cоздание папки с именем = текущей дате

Macro {
  description="создание папки с именем = текущей дате";
  area="Shell"; key="CtrlShiftF7"; flags="DisableOutput|NoPluginPanels";
  action=function()
    folder = mf.date("%d.%m0.%Y")
    if Panel.FExist(0,folder)==0 then
      Keys"F7 CtrlY"
      print(folder)
      Keys"Enter"
    end
  end;
}